|
|
1.1 root 1: /***********************************************************
2: Copyright IBM Corporation 1987
3:
4: All Rights Reserved
5:
6: Permission to use, copy, modify, and distribute this software and its
7: documentation for any purpose and without fee is hereby granted,
8: provided that the above copyright notice appear in all copies and that
9: both that copyright notice and this permission notice appear in
10: supporting documentation, and that the name of IBM not be
11: used in advertising or publicity pertaining to distribution of the
12: software without specific, written prior permission.
13:
14: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20: SOFTWARE.
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
36: static 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"
53: #include "machine/io.h"
54: #include "../machineio/ioccvar.h"
55:
56: #include "ecn.h"
57: #include "iso.h"
58: #include "argo_debug.h"
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:
71: extern struct ifqueue consintrq;
72: int 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:
78: static u_char free_luns[32];
79: static u_char *next_lun = free_luns;
80:
81: /*
82: * Initialize all LUNs as available for use.
83: */
84: init_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:
101: u_char
102: getlun()
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:
131: freelun(lun)
132: u_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: */
173: lpboutput(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: */
362: struct ifnet *
363: ecnifp(unit)
364: int unit;
365: {
366: return (struct ifnet *)NULL;
367: }
368:
369: int
370: ecnoutput(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:
380: ecnshutdown(ifp)
381: {
382: printf("ecnshutdown: ecn not configured\n");
383: }
384:
385: ecnrestart(ifp)
386: {
387: printf("ecnrestart: ecn not configured\n");
388: }
389: #endif NECN>0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.