xref: /csrg-svn/sys/netiso/if_lpb.c (revision 37518)
136383Ssklower /***********************************************************
236383Ssklower 		Copyright IBM Corporation 1987
336383Ssklower 
436383Ssklower                       All Rights Reserved
536383Ssklower 
636383Ssklower Permission to use, copy, modify, and distribute this software and its
736383Ssklower documentation for any purpose and without fee is hereby granted,
836383Ssklower provided that the above copyright notice appear in all copies and that
936383Ssklower both that copyright notice and this permission notice appear in
1036383Ssklower supporting documentation, and that the name of IBM not be
1136383Ssklower used in advertising or publicity pertaining to distribution of the
1236383Ssklower software without specific, written prior permission.
1336383Ssklower 
1436383Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
1536383Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
1636383Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
1736383Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
1836383Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
1936383Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
2036383Ssklower SOFTWARE.
2136383Ssklower 
2236383Ssklower ******************************************************************/
2336383Ssklower 
2436383Ssklower /*
2536383Ssklower  * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison
2636383Ssklower  */
2736383Ssklower /*
2836383Ssklower  * $Header: if_lpb.c,v 4.2 88/06/29 14:59:38 hagens Exp $
2936383Ssklower  * $Source: /usr/argo/sys/netiso/RCS/if_lpb.c,v $
3036383Ssklower  *
3136383Ssklower  *	LOOPBACK driver that mimics the
3236383Ssklower  *	Eicon x.25 board for use by CONS
3336383Ssklower  */
3436383Ssklower 
3536383Ssklower #ifndef lint
3636383Ssklower static char *rcsid = "$Header: if_lpb.c,v 4.2 88/06/29 14:59:38 hagens Exp $";
3736383Ssklower #endif lint
3836383Ssklower 
3936383Ssklower 
4036383Ssklower #include "param.h"
4136383Ssklower #include "systm.h"
4236383Ssklower #include "types.h"
4336383Ssklower #include "mbuf.h"
4436383Ssklower #include "buf.h"
4536383Ssklower #include "protosw.h"
4636383Ssklower #include "socket.h"
4736383Ssklower #include "ioctl.h"
4836383Ssklower #include "errno.h"
4936383Ssklower 
5036383Ssklower #include "../net/if.h"
5136383Ssklower #include "../net/netisr.h"
5236383Ssklower #include "../net/route.h"
53*37518Smckusick #include "machine/io.h"
5436383Ssklower #include "../machineio/ioccvar.h"
5536383Ssklower 
5636383Ssklower #include "ecn.h"
5737469Ssklower #include "iso.h"
5837469Ssklower #include "argo_debug.h"
5936383Ssklower #include "../caif/eicon.h"
6036383Ssklower #include "iso_errno.h"
6136383Ssklower 
6236383Ssklower #define LPB_DEBUG
6336383Ssklower #ifdef LPB_DEBUG
6436383Ssklower #define MT_LPB_OPEN	0x55
6536383Ssklower #define MT_LPB_ACK 	0x56
6636383Ssklower #else LPB_DEBUG
6736383Ssklower #define MT_LPB_DATA MT_DATA
6836383Ssklower #define MT_LPB_ACK MT_DATA
6936383Ssklower #endif LPB_DEBUG
7036383Ssklower 
7136383Ssklower extern struct ifqueue 	consintrq;
7236383Ssklower int						lpboutput();
7336383Ssklower 
7436383Ssklower /* These next 2 declarations are for Logical Unit Numbers - i.e. VC # -
7536383Ssklower  * the 2I assigns and frees them; we have to fake it
7636383Ssklower  */
7736383Ssklower 
7836383Ssklower static u_char 			free_luns[32];
7936383Ssklower static u_char 			*next_lun = free_luns;
8036383Ssklower 
8136383Ssklower /*
8236383Ssklower  * Initialize all LUNs as available for use.
8336383Ssklower  */
init_lpb()8436383Ssklower init_lpb()
8536383Ssklower {
8636383Ssklower 	register int i;
8736383Ssklower 
8836383Ssklower 	for (i = 0; i < 32; i++) {
8936383Ssklower 		free_luns[i] = i+1;
9036383Ssklower 	}
9136383Ssklower 	next_lun = free_luns;
9236383Ssklower }
9336383Ssklower 
9436383Ssklower /*
9536383Ssklower  *	Allocate new logical unit number.
9636383Ssklower  *  Allocating number n means that both n and -n are allocated & used.
9736383Ssklower  *  NOTE: next_lun always points to an UNALLOCATED lun, hence
9836383Ssklower  *	 take a lun then increment, or decrement then stash the lun.
9936383Ssklower  */
10036383Ssklower 
10136383Ssklower u_char
getlun()10236383Ssklower getlun()
10336383Ssklower {
10436383Ssklower 	if( ((next_lun) - free_luns) > 32 ) {
10536383Ssklower 		printf("PANIC: if_lpb: too many channels! \n");
10636383Ssklower 		return 0;
10736383Ssklower 	}
10836383Ssklower 	IFDEBUG(D_CCONN)
10936383Ssklower 		printf("getlun: returns 0x%x\n", *next_lun);
11036383Ssklower 	ENDDEBUG
11136383Ssklower 	ASSERT( *next_lun != 0 );
11236383Ssklower 	if( *next_lun == 0 ) {
11336383Ssklower 		register int i;
11436383Ssklower 
11536383Ssklower 		printf(
11636383Ssklower 		"PANIC IN lpb: free_luns 0x%x next_len 0x%x *next_lun 0x%x\n",
11736383Ssklower 			free_luns, next_lun, *next_lun);
11836383Ssklower 
11936383Ssklower 		for(i=0; i<32; i++) {
12036383Ssklower 			printf("free_luns[ 0x%x ] = 0x%x\n", i, free_luns[i] );
12136383Ssklower 		}
12236383Ssklower 	}
12336383Ssklower 	return *(next_lun++);
12436383Ssklower 
12536383Ssklower }
12636383Ssklower 
12736383Ssklower /*
12836383Ssklower  * When you free one you free its neg
12936383Ssklower  */
13036383Ssklower 
freelun(lun)13136383Ssklower freelun(lun)
13236383Ssklower u_char	lun;
13336383Ssklower {
13436383Ssklower 	IFDEBUG(D_CCONN)
13536383Ssklower 		printf("freelun(0x%x)\n", lun);
13636383Ssklower 	ENDDEBUG
13736383Ssklower 	if( lun > 32 )
13836383Ssklower 		return;
13936383Ssklower 
14036383Ssklower 	ASSERT( (lun & 0xc0) == 0 );
14136383Ssklower 	ASSERT( lun <= 32 );
14236383Ssklower 
14336383Ssklower 	/* check for lun already in the list */
14436383Ssklower 	{
14536383Ssklower 		register u_char *r = next_lun;
14636383Ssklower 
14736383Ssklower 		while( (int)(r - free_luns) <= 32 ) {
14836383Ssklower 			if( *r == lun ) {
14936383Ssklower 				return;
15036383Ssklower 			}
15136383Ssklower 			r++;
15236383Ssklower 		}
15336383Ssklower 	}
15436383Ssklower 
15536383Ssklower 	next_lun --;
15636383Ssklower 	*next_lun = lun;
15736383Ssklower }
15836383Ssklower 
15936383Ssklower 
16036383Ssklower /*
16136383Ssklower  * FUNCTION:		lpboutput
16236383Ssklower  *
16336383Ssklower  * PURPOSE:			Process an eicon x.25 request from a higher layer
16436383Ssklower  *					protocol.
16536383Ssklower  * ARGUMENTS:	 	(ifp) is points to the ifnet structure for this unit/device
16636383Ssklower  *					(m)  is an mbuf *, *m is an eicon request structure
16736383Ssklower  *
16836383Ssklower  * RETURNS:			unix error code
16936383Ssklower  *
17036383Ssklower  * NOTES:			Mimics the eicon driver.
17136383Ssklower  *
17236383Ssklower  */
lpboutput(ifp,m)17336383Ssklower lpboutput(ifp,m)
17436383Ssklower 	register struct ifnet 	*ifp;
17536383Ssklower 	register struct mbuf	*m;			/* request */
17636383Ssklower {
17736383Ssklower 	int							s;
17836383Ssklower 	struct eicon_request		*req;
17936383Ssklower 	int							error = 0;
18036383Ssklower 
18136383Ssklower 	/* Do this even if (ifp->if_flags & IFF_LOOPBACK) == 0
18236383Ssklower 	 * because whether or not a vc is on loopback is determined
18336383Ssklower 	 * at the time of connection establishement.
18436383Ssklower 	 */
18536383Ssklower 	s = splnet();
18636383Ssklower 	req = mtod(m, struct eicon_request *);
18736383Ssklower 	IFDEBUG(D_CDUMP_REQ)
18836383Ssklower 		dump_buf(req, sizeof(struct eicon_request));
18936383Ssklower 	ENDDEBUG
19036383Ssklower 	switch (req->e_cmd) {
19136383Ssklower 		case ECN_CALL: {
19236383Ssklower 			/*
19336383Ssklower 			 *	ECN_CALL	->	ECN_ACCEPT (for orig CONNECT)
19436383Ssklower 			 *				->	ECN_CONNECT	(other side's connect indication)
19536383Ssklower 			 */
19636383Ssklower 			struct mbuf *mdata;
19736383Ssklower 			struct mbuf *mopen;
19836383Ssklower 			struct eicon_request *open;
19936383Ssklower 
20036383Ssklower 			MGET(mopen, M_DONTWAIT, MT_LPB_OPEN);
20136383Ssklower 			if (mopen == NULL) {
20236383Ssklower 				printf("No mbufs for copy\n");
20336383Ssklower 				error = ENOBUFS;
20436383Ssklower 				break;
20536383Ssklower 			}
20636383Ssklower 			mopen->m_len = sizeof(struct eicon_request);
20736383Ssklower 
20836383Ssklower 			open = mtod(mopen, struct eicon_request *);
20936383Ssklower 			bcopy( req, open, sizeof(struct eicon_request) );
21036383Ssklower 
21136383Ssklower 			/* get mbuf for the connect data */
21236383Ssklower 			MGET(mdata, M_DONTWAIT, MT_LPB_OPEN);
21336383Ssklower 			if (mdata == NULL) {
21436383Ssklower 				printf("No mbufs for copy\n");
21536383Ssklower 				error = ENOBUFS;
21636383Ssklower 				break;
21736383Ssklower 			}
21836383Ssklower 			mdata->m_len = (e_data(req))->m_len;
21936383Ssklower 			e_data(open) = mdata; /* e_data is really mtod(open)->m_next */
22036383Ssklower 			/* make a copy of the connect data */
22136383Ssklower 			IFDEBUG(D_CCONN)
22236383Ssklower 				printf("bcopy( 0x%x, 0x%x, 0x%x)\n", mtod(e_data(req), caddr_t),
22336383Ssklower 						mtod(mdata, caddr_t),
22436383Ssklower 						(e_data(req))->m_len);
22536383Ssklower 			ENDDEBUG
22636383Ssklower 			bcopy( mtod(e_data(req), caddr_t), mtod(mdata, caddr_t),
22736383Ssklower 						(e_data(req))->m_len);
22836383Ssklower 			/* setup call */
22936383Ssklower 			open->e_cmd = ECN_CONNECT;
23036383Ssklower 			open->e_vc = getlun();
23136383Ssklower 
23236383Ssklower 			/* setup call confirm */
23336383Ssklower 			req->e_cmd = ECN_ACCEPT;
23436383Ssklower 			req->e_vc = -(open->e_vc);
23536383Ssklower 
23636383Ssklower 			IFDEBUG(D_CDUMP_REQ)
23736383Ssklower 				printf("lpboutput CALL middle \n");
23836383Ssklower 			ENDDEBUG
23936383Ssklower 
24036383Ssklower 			if (IF_QFULL(&consintrq)) {
24136383Ssklower 				IF_DROP(&consintrq);
24236383Ssklower 				m_freem(mopen);
24336383Ssklower 				printf("lpboutput: response dropped\n");
24436383Ssklower 				error = ENOBUFS;
24536383Ssklower 				break;
24636383Ssklower 			} else {
24736383Ssklower 				/* connect */
24836383Ssklower 				IFDEBUG(D_CCONS);
24936383Ssklower 					printf("CONNECT 0x%x --> X25INTRQ\n", mopen);
25036383Ssklower 				ENDDEBUG
25136383Ssklower 				IF_ENQUEUE(&consintrq, mopen);
25236383Ssklower 				IFDEBUG(D_CDUMP_REQ);
25336383Ssklower 					dump_buf(open, sizeof(struct eicon_request));
25436383Ssklower 				ENDDEBUG
25536383Ssklower 
25636383Ssklower 				/* confirm */
25736383Ssklower 				IFDEBUG(D_CCONS);
25836383Ssklower 					printf("CONFIRM 0x%x (data 0x%x =?= 0x%x) --> X25INTRQ\n",
25936383Ssklower 						m, m->m_next, e_data(req));
26036383Ssklower 				ENDDEBUG
26136383Ssklower 				IF_ENQUEUE(&consintrq, m);
26236383Ssklower 				IFDEBUG(D_CDUMP_REQ);
26336383Ssklower 					dump_buf(req, sizeof(struct eicon_request));
26436383Ssklower 				ENDDEBUG
26536383Ssklower 			}
26636383Ssklower 		} break;
26736383Ssklower 
26836383Ssklower 		case ECN_RESET:
26936383Ssklower 		case ECN_CLEAR: {
27036383Ssklower 			/*
27136383Ssklower 			 *	ECN_RESET	->	ECN_RESET	(other side's reset indication)
27236383Ssklower 			 *	ECN_CLEAR	->	ECN_CLEAR	(other side's close indication)
27336383Ssklower 			 * TODO: MAY HAVE DATA PACKET!
27436383Ssklower 			 * TODO: Have to be able to handle a 2nd CLEAR on on vc!
27536383Ssklower 			 */
27636383Ssklower 			freelun(req->e_vc);
27736383Ssklower 			freelun((-req->e_vc)&0xff);
27836383Ssklower 			req->e_vc = -req->e_vc; /* other side */
27936383Ssklower 			req->e_reason = E_CO_PDNCLRESET;
28036383Ssklower 			if (IF_QFULL(&consintrq)) {
28136383Ssklower 				IF_DROP(&consintrq);
28236383Ssklower 				printf("lpboutput: respose dropped\n");
28336383Ssklower 				error = ENOBUFS;
28436383Ssklower 			} else {
28536383Ssklower 				IFDEBUG(D_CCONS);
28636383Ssklower 					printf("CLOSE 0x%x --> X25INTRQ\n", m);
28736383Ssklower 				ENDDEBUG
28836383Ssklower 				IF_ENQUEUE(&consintrq, m);
28936383Ssklower 				IFDEBUG(D_CDUMP_REQ);
29036383Ssklower 					dump_buf(req, sizeof(struct eicon_request));
29136383Ssklower 				ENDDEBUG
29236383Ssklower 			}
29336383Ssklower 		} break;
29436383Ssklower 
29536383Ssklower 		case ECN_SEND: {
29636383Ssklower 			/*
29736383Ssklower 			 *	ECN_SEND 	->	ECN_RECEIVE	(data send becomes data recvd)
29836383Ssklower 			 */
29936383Ssklower 			struct mbuf *m0;
30036383Ssklower 			struct eicon_request *ack;
30136383Ssklower 
30236383Ssklower 			MGET(m0, M_DONTWAIT, MT_LPB_ACK); /* sets type, next, off */
30336383Ssklower 			if (m0 == NULL) {
30436383Ssklower 				printf("PANIC No mbufs for copy\n");
30536383Ssklower 				error = ENOBUFS;
30636383Ssklower 				break;
30736383Ssklower 			}
30836383Ssklower 			m0->m_len = sizeof(struct eicon_request);
30936383Ssklower 
31036383Ssklower 			ack = mtod(m0, struct eicon_request *);
31136383Ssklower 			/* setup ack */
31236383Ssklower 			ack->e_cmd = ECN_ACK;
31336383Ssklower 			ack->e_vc = req->e_vc;
31436383Ssklower 			req->e_vc = -req->e_vc;
31536383Ssklower 			req->e_cmd = ECN_RECEIVE;
31636383Ssklower 
31736383Ssklower 			if (IF_QFULL(&consintrq)) {
31836383Ssklower 				IF_DROP(&consintrq);
31936383Ssklower 				printf("lpboutput: ADR_ACK DROPPED\n");
32036383Ssklower 				m_freem(m0);
32136383Ssklower 				error = ECONNABORTED;
32236383Ssklower 			} else {
32336383Ssklower 				IF_ENQUEUE(&consintrq, m);
32436383Ssklower 				IFDEBUG(D_CCONS);
32536383Ssklower 					printf("DATA 0x%x --> X25INTRQ\n", m);
32636383Ssklower 				ENDDEBUG
32736383Ssklower 				IFDEBUG(D_CDUMP_REQ);
32836383Ssklower 					dump_buf(req, sizeof(struct eicon_request));
32936383Ssklower 				ENDDEBUG
33036383Ssklower 				IFDEBUG(D_CCONS);
33136383Ssklower 					printf("ACK 0x%x --> X25INTRQ\n", m0);
33236383Ssklower 				ENDDEBUG
33336383Ssklower 				IF_ENQUEUE(&consintrq, m0);
33436383Ssklower 				IFDEBUG(D_CDUMP_REQ);
33536383Ssklower 					dump_buf(ack, sizeof(struct eicon_request));
33636383Ssklower 				ENDDEBUG
33736383Ssklower 			}
33836383Ssklower 		} break;
33936383Ssklower 
34036383Ssklower 		default:
34136383Ssklower 			printf("Bad loopback request 0x%x\n", req->e_cmd);
34236383Ssklower 			error = EINVAL;
34336383Ssklower 	}
34436383Ssklower 
34536383Ssklower 	if( error ) {
34636383Ssklower 		m_freem(m);
34736383Ssklower 	} else
34836383Ssklower 		schednetisr(NETISR_X25);
34936383Ssklower 
35036383Ssklower 	splx(s);
35136383Ssklower 	return error;
35236383Ssklower }
35336383Ssklower 
35436383Ssklower #if NECN>0
35536383Ssklower 	/* nothing */
35636383Ssklower #else
35736383Ssklower 
35836383Ssklower /* KLUDGE: when no ecn board config-ed in, we need a routing
35936383Ssklower  * ecnifp to return null.  We want to be able to configure with
36036383Ssklower  * sw loopback only.
36136383Ssklower  */
36236383Ssklower struct ifnet  *
ecnifp(unit)36336383Ssklower ecnifp(unit)
36436383Ssklower int unit;
36536383Ssklower {
36636383Ssklower 	return (struct ifnet *)NULL;
36736383Ssklower }
36836383Ssklower 
36936383Ssklower int
ecnoutput(ifp,m)37036383Ssklower ecnoutput(ifp, m)
37136383Ssklower 	struct ifnet *ifp;
37236383Ssklower 	struct mbuf *m;
37336383Ssklower {
37436383Ssklower 	printf("ecnoutput: ecn not configured\n");
37536383Ssklower 	(void) m_freem(m);
37636383Ssklower 	return ENETDOWN;
37736383Ssklower 
37836383Ssklower }
37936383Ssklower 
ecnshutdown(ifp)38036383Ssklower ecnshutdown(ifp)
38136383Ssklower {
38236383Ssklower 	printf("ecnshutdown: ecn not configured\n");
38336383Ssklower }
38436383Ssklower 
ecnrestart(ifp)38536383Ssklower ecnrestart(ifp)
38636383Ssklower {
38736383Ssklower 	printf("ecnrestart: ecn not configured\n");
38836383Ssklower }
38936383Ssklower #endif NECN>0
390