Added -lgcc_pic back again.
[unix-history] / sys / netccitt / hd_subr.c
CommitLineData
15637ed4
RG
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 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
1cdffd64
RG
38 * from: @(#)hd_subr.c 7.6 (Berkeley) 5/29/91
39 * $Id$
15637ed4
RG
40 */
41
42#include "param.h"
43#include "systm.h"
44#include "mbuf.h"
45#include "domain.h"
46#include "socket.h"
47#include "protosw.h"
48#include "errno.h"
49#include "time.h"
50#include "kernel.h"
51
52#include "../net/if.h"
53
54#include "hdlc.h"
55#include "hd_var.h"
56#include "x25.h"
57
58hd_init ()
59{
60
61 hdintrq.ifq_maxlen = IFQ_MAXLEN;
62}
63
64hd_ctlinput (prc, addr)
65struct sockaddr *addr;
66{
67 register struct x25config *xcp = (struct x25config *)addr;
68 register struct hdcb *hdp;
69 register struct ifaddr *ifa;
70 struct ifnet *ifp;
71 caddr_t pk_newlink();
72
73 if (addr->sa_family != AF_CCITT)
74 return (EAFNOSUPPORT);
75 if (xcp->xc_lptype != HDLCPROTO_LAPB)
76 return (EPROTONOSUPPORT);
77 ifa = ifa_ifwithaddr(addr);
78 if (ifa == 0 || ifa->ifa_addr->sa_family != AF_CCITT ||
79 (ifp = ifa->ifa_ifp) == 0)
80 panic ("hd_ctlinput");
81 for (hdp = hdcbhead; hdp; hdp = hdp->hd_next)
82 if (hdp->hd_ifp == ifp)
83 break;
84
85 if (hdp == 0) { /* new interface */
86 int error, hd_ifoutput(), hd_output();
87
88 /* an hdcb is now too big to fit in an mbuf */
89 MALLOC(hdp, struct hdcb *, sizeof (*hdp), M_PCB, M_DONTWAIT);
90 if (hdp == 0)
91 return (ENOBUFS);
92 bzero((caddr_t)hdp, sizeof(*hdp));
93 hdp->hd_pkp =
94 pk_newlink ((struct x25_ifaddr *)ifa, (caddr_t)hdp);
95 if (hdp -> hd_pkp == 0) {
96 free(hdp, M_PCB);
97 return (ENOBUFS);
98 }
99 hdp->hd_ifp = ifp;
100 hdp->hd_ifa = ifa;
101 hdp->hd_xcp = xcp;
102 hdp->hd_state = INIT;
103 hdp->hd_output = hd_ifoutput;
104 hdp->hd_next = hdcbhead;
105 hdcbhead = hdp;
106 }
107
108 switch (prc) {
109 case PRC_IFUP:
110 if (xcp->xc_lwsize == 0 ||
111 xcp->xc_lwsize > MAX_WINDOW_SIZE)
112 xcp->xc_lwsize = MAX_WINDOW_SIZE;
113 if (hdp->hd_state == INIT)
114 SET_TIMER (hdp);
115 break;
116
117 case PRC_IFDOWN:
118 if (hdp->hd_state == ABM)
119 hd_message (hdp, "Operator shutdown: link closed");
120 (void) pk_ctlinput (PRC_LINKDOWN, hdp->hd_pkp);
121 hd_writeinternal (hdp, DISC, POLLON);
122 hdp->hd_state = DISC_SENT;
123 SET_TIMER (hdp);
124 }
125 return (0);
126}
127
128hd_initvars (hdp)
129register struct hdcb *hdp;
130{
131 register struct mbuf *m;
132 register int i;
133
134 /* Clear Transmit queue. */
135 while ((m = hd_remove (&hdp->hd_txq)) != NULL)
136 m_freem (m);
137
138 /* Clear Retransmit queue. */
139 i = hdp->hd_lastrxnr;
140 while (i != hdp->hd_retxqi) {
141 m_freem (hdp->hd_retxq[i]);
142 i = (i + 1) % MODULUS;
143 }
144 hdp->hd_retxqi = 0;
145
146 hdp->hd_vs = hdp->hd_vr = 0;
147 hdp->hd_lasttxnr = hdp->hd_lastrxnr = 0;
148 hdp->hd_rrtimer = 0;
149 KILL_TIMER(hdp);
150 hdp->hd_retxcnt = 0;
151 hdp->hd_condition = 0;
152}
153
154hd_decode (hdp, frame)
155register struct hdcb *hdp;
156struct Hdlc_frame *frame;
157{
158 register int frametype = ILLEGAL;
159 register struct Hdlc_iframe *iframe = (struct Hdlc_iframe *) frame;
160 register struct Hdlc_sframe *sframe = (struct Hdlc_sframe *) frame;
161 register struct Hdlc_uframe *uframe = (struct Hdlc_uframe *) frame;
162
163 if (iframe -> hdlc_0 == 0) {
164 frametype = IFRAME;
165 hdp->hd_iframes_in++;
166 }
167
168 else if (sframe -> hdlc_01 == 1) {
169 /* Supervisory format. */
170 switch (sframe -> s2) {
171 case 0:
172 frametype = RR;
173 hdp->hd_rrs_in++;
174 break;
175
176 case 1:
177 frametype = RNR;
178 hdp->hd_rnrs_in++;
179 break;
180
181 case 2:
182 frametype = REJ;
183 hdp->hd_rejs_in++;
184 }
185 }
186 else if (uframe -> hdlc_11 == 3) {
187 /* Unnumbered format. */
188 switch (uframe -> m3) {
189 case 0:
190 frametype = DM;
191 break;
192
193 case 1:
194 frametype = SABM;
195 break;
196
197 case 2:
198 frametype = DISC;
199 break;
200
201 case 3:
202 frametype = UA;
203 break;
204
205 case 4:
206 frametype = FRMR;
207 hdp->hd_frmrs_in++;
208 }
209 }
210 return (frametype);
211}
212
213/*
214 * This routine is called when the HDLC layer internally generates a
215 * command or response for the remote machine ( eg. RR, UA etc. ).
216 * Only supervisory or unnumbered frames are processed.
217 */
218
219hd_writeinternal (hdp, frametype, pf)
220register struct hdcb *hdp;
221register int frametype, pf;
222{
223 register struct mbuf *buf;
224 struct Hdlc_frame *frame;
225 register struct Hdlc_sframe *sframe;
226 register struct Hdlc_uframe *uframe;
227
228 MGETHDR (buf, M_DONTWAIT, MT_HEADER);
229 if (buf == 0)
230 return;
231 frame = mtod (buf, struct Hdlc_frame *);
232 sframe = mtod (buf, struct Hdlc_sframe *);
233 uframe = mtod (buf, struct Hdlc_uframe *);
234
235 /* Assume a response - address structure for DTE */
236 frame -> address = ADDRESS_A;
237 buf -> m_len = 2;
238 buf -> m_act = buf -> m_next = NULL;
239
240 switch (frametype) {
241 case RR:
242 frame -> control = RR_CONTROL;
243 hdp->hd_rrs_out++;
244 break;
245
246 case RNR:
247 frame -> control = RNR_CONTROL;
248 hdp->hd_rnrs_out++;
249 break;
250
251 case REJ:
252 frame -> control = REJ_CONTROL;
253 hdp->hd_rejs_out++;
254 break;
255
256 case SABM:
257 frame -> control = SABM_CONTROL;
258 frame -> address = ADDRESS_B;
259 break;
260
261 case DISC:
262 if ((hdp->hd_ifp->if_flags & IFF_UP) == 0) {
263 hdp->hd_state = DISCONNECTED;
264 (void) m_freem (buf);
265 hd_flush (hdp->hd_ifp);
266 return;
267 }
268 frame -> control = DISC_CONTROL;
269 frame -> address = ADDRESS_B;
270 break;
271
272 case DM:
273 frame -> control = DM_CONTROL;
274 break;
275
276 case UA:
277 frame -> control = UA_CONTROL;
278 break;
279
280 case FRMR:
281 frame -> control = FRMR_CONTROL;
282 bcopy ((caddr_t)&hd_frmr, (caddr_t)frame -> info, 3);
283 buf -> m_len = 5;
284 hdp->hd_frmrs_out++;
285
286 }
287
288 if (sframe -> hdlc_01 == 1) {
289 /* Supervisory format - RR, REJ, or RNR. */
290 sframe -> nr = hdp->hd_vr;
291 sframe -> pf = pf;
292 hdp->hd_lasttxnr = hdp->hd_vr;
293 hdp->hd_rrtimer = 0;
294 }
295 else
296 uframe -> pf = pf;
297
298 hd_trace (hdp, TX, frame);
299 buf -> m_pkthdr.len = buf -> m_len;
300 (*hdp->hd_output) (hdp, buf);
301}
302
303struct mbuf *
304hd_remove (q)
305struct hdtxq *q;
306{
307 register struct mbuf *m;
308
309 m = q -> head;
310 if (m) {
311 if ((q -> head = m -> m_act) == NULL)
312 q -> tail = NULL;
313 m -> m_act = 0;
314 }
315 return (m);
316}
317
318hd_append (q, m)
319register struct hdtxq *q;
320register struct mbuf *m;
321{
322
323 m -> m_act = NULL;
324 if (q -> tail == NULL)
325 q -> head = m;
326 else
327 q -> tail -> m_act = m;
328 q -> tail = m;
329}
330
331hd_flush (ifp)
332struct ifnet *ifp;
333{
334 register struct mbuf *m;
335 register int s;
336
337 while (1) {
338 s = splimp ();
339 IF_DEQUEUE (&ifp->if_snd, m);
340 splx (s);
341 if (m == 0)
342 break;
343 m_freem (m);
344 }
345}
346
347hd_message (hdp, msg)
348struct hdcb *hdp;
349char *msg;
350{
351 char *format_ntn ();
352
353 if (hdcbhead -> hd_next)
354 printf ("HDLC(%s): %s\n", format_ntn (hdp->hd_xcp), msg);
355 else
356 printf ("HDLC: %s\n", msg);
357}
358
359#ifdef HDLCDEBUG
360hd_status (hdp)
361struct hdcb *hdp;
362{
363 printf ("HDLC STATUS:\n V(S)=%d, V(R)=%d, retxqi=%d,\n",
364 hdp->hd_vs, hdp->hd_vr, hdp->hd_retxqi);
365
366 printf ("Last_rx_nr=%d, Last_tx_nr=%d,\n Condition=%d, Xx=%d\n",
367 hdp->hd_lastrxnr, hdp->hd_lasttxnr, hdp->hd_condition, hdp->hd_xx);
368}
369#endif