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