4.4BSD snapshot (revision 8.1); add 1993 to copyright
[unix-history] / usr / src / sys / netccitt / pk_output.c
CommitLineData
51386eb2
KS
1/*
2 * Copyright (c) University of British Columbia, 1984
a130a8be
KS
3 * Copyright (C) Computer Science Department IV,
4 * University of Erlangen-Nuremberg, Germany, 1992
e7a3707f
KB
5 * Copyright (c) 1991, 1992, 1993
6 * The Regents of the University of California. All rights reserved.
51386eb2 7 *
a130a8be
KS
8 * This code is derived from software contributed to Berkeley by the
9 * Laboratory for Computation Vision and the Computer Science Department
10 * of the the University of British Columbia and the Computer Science
11 * Department (IV) of the University of Erlangen-Nuremberg, Germany.
51386eb2
KS
12 *
13 * %sccs.include.redist.c%
14 *
e7a3707f 15 * @(#)pk_output.c 8.1 (Berkeley) %G%
51386eb2 16 */
0164bb81 17
5548a02f
KB
18#include <sys/param.h>
19#include <sys/systm.h>
20#include <sys/mbuf.h>
21#include <sys/socket.h>
22#include <sys/socketvar.h>
23#include <sys/protosw.h>
24#include <sys/errno.h>
0164bb81 25
5548a02f 26#include <net/if.h>
0164bb81 27
5548a02f
KB
28#include <netccitt/x25.h>
29#include <netccitt/pk.h>
30#include <netccitt/pk_var.h>
0164bb81 31
94c03198 32struct mbuf_cache pk_output_cache = {0 }, pk_input_cache;
0164bb81
KS
33struct mbuf *nextpk ();
34
35pk_output (lcp)
36register struct pklcd *lcp;
37{
38 register struct x25_packet *xp;
39 register struct mbuf *m;
40 register struct pkcb *pkp = lcp -> lcd_pkp;
41
42 if (lcp == 0 || pkp == 0) {
43 printf ("pk_output: zero arg\n");
44 return;
45 }
46
47 while ((m = nextpk (lcp)) != NULL) {
48 xp = mtod (m, struct x25_packet *);
49
50 switch (pk_decode (xp) + lcp -> lcd_state) {
51 /*
52 * All the work is already done - just set the state and
53 * pass to peer.
54 */
55 case CALL + READY:
56 lcp -> lcd_state = SENT_CALL;
57 lcp -> lcd_timer = pk_t21;
58 break;
59
60 /*
61 * Just set the state to allow packet to flow and send the
62 * confirmation.
63 */
64 case CALL_ACCEPTED + RECEIVED_CALL:
65 lcp -> lcd_state = DATA_TRANSFER;
66 break;
67
68 /*
69 * Just set the state. Keep the LCD around till the clear
70 * confirmation is returned.
71 */
72 case CLEAR + RECEIVED_CALL:
73 case CLEAR + SENT_CALL:
74 case CLEAR + DATA_TRANSFER:
75 lcp -> lcd_state = SENT_CLEAR;
76 lcp -> lcd_retry = 0;
77 /* fall through */
78
79 case CLEAR + SENT_CLEAR:
80 lcp -> lcd_timer = pk_t23;
81 lcp -> lcd_retry++;
82 break;
83
84 case CLEAR_CONF + RECEIVED_CLEAR:
85 case CLEAR_CONF + SENT_CLEAR:
86 case CLEAR_CONF + READY:
87 lcp -> lcd_state = READY;
88 break;
89
90 case DATA + DATA_TRANSFER:
a130a8be 91 SPS(xp, lcp -> lcd_ssn);
f3426482
KS
92 lcp -> lcd_input_window =
93 (lcp -> lcd_rsn + 1) % MODULUS;
a130a8be 94 SPR(xp, lcp -> lcd_input_window);
0164bb81
KS
95 lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
96 lcp -> lcd_ssn = (lcp -> lcd_ssn + 1) % MODULUS;
06aa10f5 97 if (lcp -> lcd_ssn == ((lcp -> lcd_output_window + lcp -> lcd_windowsize) % MODULUS))
0164bb81
KS
98 lcp -> lcd_window_condition = TRUE;
99 break;
100
101 case INTERRUPT + DATA_TRANSFER:
c4b47c42 102#ifdef ancient_history
0164bb81 103 xp -> packet_data = 0;
c4b47c42 104#endif
0164bb81
KS
105 lcp -> lcd_intrconf_pending = TRUE;
106 break;
107
108 case INTERRUPT_CONF + DATA_TRANSFER:
109 break;
110
111 case RR + DATA_TRANSFER:
0164bb81 112 case RNR + DATA_TRANSFER:
f3426482
KS
113 lcp -> lcd_input_window =
114 (lcp -> lcd_rsn + 1) % MODULUS;
a130a8be 115 SPR(xp, lcp -> lcd_input_window);
0164bb81
KS
116 lcp -> lcd_last_transmitted_pr = lcp -> lcd_input_window;
117 break;
118
119 case RESET + DATA_TRANSFER:
120 lcp -> lcd_reset_condition = TRUE;
121 break;
122
123 case RESET_CONF + DATA_TRANSFER:
124 lcp -> lcd_reset_condition = FALSE;
125 break;
126
127 /*
128 * A restart should be only generated internally. Therefore
129 * all logic for restart is in the pk_restart routine.
130 */
131 case RESTART + READY:
132 lcp -> lcd_timer = pk_t20;
133 break;
134
135 /*
136 * Restarts are all handled internally. Therefore all the
137 * logic for the incoming restart packet is handled in the
138 * pk_input routine.
139 */
140 case RESTART_CONF + READY:
141 break;
142
143 default:
144 m_freem (m);
145 return;
146 }
147
148 /* Trace the packet. */
c4b47c42 149 pk_trace (pkp -> pk_xcp, m, "P-Out");
0164bb81
KS
150
151 /* Pass the packet on down to the link layer */
94c03198
KS
152 if (pk_input_cache.mbc_size || pk_input_cache.mbc_oldsize) {
153 m->m_flags |= 0x08;
154 mbuf_cache(&pk_input_cache, m);
155 }
a130a8be 156 (*pkp -> pk_lloutput) (pkp -> pk_llnext, m, pkp -> pk_rt);
0164bb81
KS
157 }
158}
159
160/*
161 * This procedure returns the next packet to send or null. A
162 * packet is composed of one or more mbufs.
163 */
164
165struct mbuf *
166nextpk (lcp)
167struct pklcd *lcp;
168{
b84e7ca8
KS
169 register struct mbuf *m, *n;
170 struct socket *so = lcp -> lcd_so;
171 register struct sockbuf *sb = & (so ? so -> so_snd : lcp -> lcd_sb);
0164bb81
KS
172
173 if (lcp -> lcd_template) {
c4b47c42 174 m = lcp -> lcd_template;
0164bb81
KS
175 lcp -> lcd_template = NULL;
176 } else {
177 if (lcp -> lcd_rnr_condition || lcp -> lcd_window_condition ||
178 lcp -> lcd_reset_condition)
179 return (NULL);
180
b84e7ca8 181 if ((m = sb -> sb_mb) == 0)
0164bb81
KS
182 return (NULL);
183
b84e7ca8 184 sb -> sb_mb = m -> m_nextpkt;
0164bb81 185 m->m_act = 0;
b84e7ca8
KS
186 for (n = m; n; n = n -> m_next)
187 sbfree (sb, n);
0164bb81 188 }
0164bb81
KS
189 return (m);
190}