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