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