cltp_usrreq.c made separate file in conf/files
[unix-history] / usr / src / sys / netiso / if_lpb.c
CommitLineData
b5c41248
KS
1/***********************************************************
2 Copyright IBM Corporation 1987
3
4 All Rights Reserved
5
6Permission to use, copy, modify, and distribute this software and its
7documentation for any purpose and without fee is hereby granted,
8provided that the above copyright notice appear in all copies and that
9both that copyright notice and this permission notice appear in
10supporting documentation, and that the name of IBM not be
11used in advertising or publicity pertaining to distribution of the
12software without specific, written prior permission.
13
14IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20SOFTWARE.
21
22******************************************************************/
23
24/*
25 * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
26 */
27/*
28 * $Header: if_lpb.c,v 4.2 88/06/29 14:59:38 hagens Exp $
29 * $Source: /usr/argo/sys/netiso/RCS/if_lpb.c,v $
30 *
31 * LOOPBACK driver that mimics the
32 * Eicon x.25 board for use by CONS
33 */
34
35#ifndef lint
36static char *rcsid = "$Header: if_lpb.c,v 4.2 88/06/29 14:59:38 hagens Exp $";
37#endif lint
38
39
40#include "param.h"
41#include "systm.h"
42#include "types.h"
43#include "mbuf.h"
44#include "buf.h"
45#include "protosw.h"
46#include "socket.h"
47#include "ioctl.h"
48#include "errno.h"
49
50#include "../net/if.h"
51#include "../net/netisr.h"
52#include "../net/route.h"
d301d150 53#include "machine/io.h"
b5c41248
KS
54#include "../machineio/ioccvar.h"
55
56#include "ecn.h"
a50e2bc0
KS
57#include "iso.h"
58#include "argo_debug.h"
b5c41248
KS
59#include "../caif/eicon.h"
60#include "iso_errno.h"
61
62#define LPB_DEBUG
63#ifdef LPB_DEBUG
64#define MT_LPB_OPEN 0x55
65#define MT_LPB_ACK 0x56
66#else LPB_DEBUG
67#define MT_LPB_DATA MT_DATA
68#define MT_LPB_ACK MT_DATA
69#endif LPB_DEBUG
70
71extern struct ifqueue consintrq;
72int lpboutput();
73
74/* These next 2 declarations are for Logical Unit Numbers - i.e. VC # -
75 * the 2I assigns and frees them; we have to fake it
76 */
77
78static u_char free_luns[32];
79static u_char *next_lun = free_luns;
80
81/*
82 * Initialize all LUNs as available for use.
83 */
84init_lpb()
85{
86 register int i;
87
88 for (i = 0; i < 32; i++) {
89 free_luns[i] = i+1;
90 }
91 next_lun = free_luns;
92}
93
94/*
95 * Allocate new logical unit number.
96 * Allocating number n means that both n and -n are allocated & used.
97 * NOTE: next_lun always points to an UNALLOCATED lun, hence
98 * take a lun then increment, or decrement then stash the lun.
99 */
100
101u_char
102getlun()
103{
104 if( ((next_lun) - free_luns) > 32 ) {
105 printf("PANIC: if_lpb: too many channels! \n");
106 return 0;
107 }
108 IFDEBUG(D_CCONN)
109 printf("getlun: returns 0x%x\n", *next_lun);
110 ENDDEBUG
111 ASSERT( *next_lun != 0 );
112 if( *next_lun == 0 ) {
113 register int i;
114
115 printf(
116 "PANIC IN lpb: free_luns 0x%x next_len 0x%x *next_lun 0x%x\n",
117 free_luns, next_lun, *next_lun);
118
119 for(i=0; i<32; i++) {
120 printf("free_luns[ 0x%x ] = 0x%x\n", i, free_luns[i] );
121 }
122 }
123 return *(next_lun++);
124
125}
126
127/*
128 * When you free one you free its neg
129 */
130
131freelun(lun)
132u_char lun;
133{
134 IFDEBUG(D_CCONN)
135 printf("freelun(0x%x)\n", lun);
136 ENDDEBUG
137 if( lun > 32 )
138 return;
139
140 ASSERT( (lun & 0xc0) == 0 );
141 ASSERT( lun <= 32 );
142
143 /* check for lun already in the list */
144 {
145 register u_char *r = next_lun;
146
147 while( (int)(r - free_luns) <= 32 ) {
148 if( *r == lun ) {
149 return;
150 }
151 r++;
152 }
153 }
154
155 next_lun --;
156 *next_lun = lun;
157}
158
159
160/*
161 * FUNCTION: lpboutput
162 *
163 * PURPOSE: Process an eicon x.25 request from a higher layer
164 * protocol.
165 * ARGUMENTS: (ifp) is points to the ifnet structure for this unit/device
166 * (m) is an mbuf *, *m is an eicon request structure
167 *
168 * RETURNS: unix error code
169 *
170 * NOTES: Mimics the eicon driver.
171 *
172 */
173lpboutput(ifp,m)
174 register struct ifnet *ifp;
175 register struct mbuf *m; /* request */
176{
177 int s;
178 struct eicon_request *req;
179 int error = 0;
180
181 /* Do this even if (ifp->if_flags & IFF_LOOPBACK) == 0
182 * because whether or not a vc is on loopback is determined
183 * at the time of connection establishement.
184 */
185 s = splnet();
186 req = mtod(m, struct eicon_request *);
187 IFDEBUG(D_CDUMP_REQ)
188 dump_buf(req, sizeof(struct eicon_request));
189 ENDDEBUG
190 switch (req->e_cmd) {
191 case ECN_CALL: {
192 /*
193 * ECN_CALL -> ECN_ACCEPT (for orig CONNECT)
194 * -> ECN_CONNECT (other side's connect indication)
195 */
196 struct mbuf *mdata;
197 struct mbuf *mopen;
198 struct eicon_request *open;
199
200 MGET(mopen, M_DONTWAIT, MT_LPB_OPEN);
201 if (mopen == NULL) {
202 printf("No mbufs for copy\n");
203 error = ENOBUFS;
204 break;
205 }
206 mopen->m_len = sizeof(struct eicon_request);
207
208 open = mtod(mopen, struct eicon_request *);
209 bcopy( req, open, sizeof(struct eicon_request) );
210
211 /* get mbuf for the connect data */
212 MGET(mdata, M_DONTWAIT, MT_LPB_OPEN);
213 if (mdata == NULL) {
214 printf("No mbufs for copy\n");
215 error = ENOBUFS;
216 break;
217 }
218 mdata->m_len = (e_data(req))->m_len;
219 e_data(open) = mdata; /* e_data is really mtod(open)->m_next */
220 /* make a copy of the connect data */
221 IFDEBUG(D_CCONN)
222 printf("bcopy( 0x%x, 0x%x, 0x%x)\n", mtod(e_data(req), caddr_t),
223 mtod(mdata, caddr_t),
224 (e_data(req))->m_len);
225 ENDDEBUG
226 bcopy( mtod(e_data(req), caddr_t), mtod(mdata, caddr_t),
227 (e_data(req))->m_len);
228 /* setup call */
229 open->e_cmd = ECN_CONNECT;
230 open->e_vc = getlun();
231
232 /* setup call confirm */
233 req->e_cmd = ECN_ACCEPT;
234 req->e_vc = -(open->e_vc);
235
236 IFDEBUG(D_CDUMP_REQ)
237 printf("lpboutput CALL middle \n");
238 ENDDEBUG
239
240 if (IF_QFULL(&consintrq)) {
241 IF_DROP(&consintrq);
242 m_freem(mopen);
243 printf("lpboutput: response dropped\n");
244 error = ENOBUFS;
245 break;
246 } else {
247 /* connect */
248 IFDEBUG(D_CCONS);
249 printf("CONNECT 0x%x --> X25INTRQ\n", mopen);
250 ENDDEBUG
251 IF_ENQUEUE(&consintrq, mopen);
252 IFDEBUG(D_CDUMP_REQ);
253 dump_buf(open, sizeof(struct eicon_request));
254 ENDDEBUG
255
256 /* confirm */
257 IFDEBUG(D_CCONS);
258 printf("CONFIRM 0x%x (data 0x%x =?= 0x%x) --> X25INTRQ\n",
259 m, m->m_next, e_data(req));
260 ENDDEBUG
261 IF_ENQUEUE(&consintrq, m);
262 IFDEBUG(D_CDUMP_REQ);
263 dump_buf(req, sizeof(struct eicon_request));
264 ENDDEBUG
265 }
266 } break;
267
268 case ECN_RESET:
269 case ECN_CLEAR: {
270 /*
271 * ECN_RESET -> ECN_RESET (other side's reset indication)
272 * ECN_CLEAR -> ECN_CLEAR (other side's close indication)
273 * TODO: MAY HAVE DATA PACKET!
274 * TODO: Have to be able to handle a 2nd CLEAR on on vc!
275 */
276 freelun(req->e_vc);
277 freelun((-req->e_vc)&0xff);
278 req->e_vc = -req->e_vc; /* other side */
279 req->e_reason = E_CO_PDNCLRESET;
280 if (IF_QFULL(&consintrq)) {
281 IF_DROP(&consintrq);
282 printf("lpboutput: respose dropped\n");
283 error = ENOBUFS;
284 } else {
285 IFDEBUG(D_CCONS);
286 printf("CLOSE 0x%x --> X25INTRQ\n", m);
287 ENDDEBUG
288 IF_ENQUEUE(&consintrq, m);
289 IFDEBUG(D_CDUMP_REQ);
290 dump_buf(req, sizeof(struct eicon_request));
291 ENDDEBUG
292 }
293 } break;
294
295 case ECN_SEND: {
296 /*
297 * ECN_SEND -> ECN_RECEIVE (data send becomes data recvd)
298 */
299 struct mbuf *m0;
300 struct eicon_request *ack;
301
302 MGET(m0, M_DONTWAIT, MT_LPB_ACK); /* sets type, next, off */
303 if (m0 == NULL) {
304 printf("PANIC No mbufs for copy\n");
305 error = ENOBUFS;
306 break;
307 }
308 m0->m_len = sizeof(struct eicon_request);
309
310 ack = mtod(m0, struct eicon_request *);
311 /* setup ack */
312 ack->e_cmd = ECN_ACK;
313 ack->e_vc = req->e_vc;
314 req->e_vc = -req->e_vc;
315 req->e_cmd = ECN_RECEIVE;
316
317 if (IF_QFULL(&consintrq)) {
318 IF_DROP(&consintrq);
319 printf("lpboutput: ADR_ACK DROPPED\n");
320 m_freem(m0);
321 error = ECONNABORTED;
322 } else {
323 IF_ENQUEUE(&consintrq, m);
324 IFDEBUG(D_CCONS);
325 printf("DATA 0x%x --> X25INTRQ\n", m);
326 ENDDEBUG
327 IFDEBUG(D_CDUMP_REQ);
328 dump_buf(req, sizeof(struct eicon_request));
329 ENDDEBUG
330 IFDEBUG(D_CCONS);
331 printf("ACK 0x%x --> X25INTRQ\n", m0);
332 ENDDEBUG
333 IF_ENQUEUE(&consintrq, m0);
334 IFDEBUG(D_CDUMP_REQ);
335 dump_buf(ack, sizeof(struct eicon_request));
336 ENDDEBUG
337 }
338 } break;
339
340 default:
341 printf("Bad loopback request 0x%x\n", req->e_cmd);
342 error = EINVAL;
343 }
344
345 if( error ) {
346 m_freem(m);
347 } else
348 schednetisr(NETISR_X25);
349
350 splx(s);
351 return error;
352}
353
354#if NECN>0
355 /* nothing */
356#else
357
358/* KLUDGE: when no ecn board config-ed in, we need a routing
359 * ecnifp to return null. We want to be able to configure with
360 * sw loopback only.
361 */
362struct ifnet *
363ecnifp(unit)
364int unit;
365{
366 return (struct ifnet *)NULL;
367}
368
369int
370ecnoutput(ifp, m)
371 struct ifnet *ifp;
372 struct mbuf *m;
373{
374 printf("ecnoutput: ecn not configured\n");
375 (void) m_freem(m);
376 return ENETDOWN;
377
378}
379
380ecnshutdown(ifp)
381{
382 printf("ecnshutdown: ecn not configured\n");
383}
384
385ecnrestart(ifp)
386{
387 printf("ecnrestart: ecn not configured\n");
388}
389#endif NECN>0