|
|
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.