|
|
1.1 ! root 1: #define BSD41 ! 2: #define VAXONE ! 3: #define TIMEOUT ! 4: ! 5: #ifdef MARVIN ! 6: #define TXDRIVER ! 7: #endif ! 8: #ifdef CANTOR ! 9: #define TXDRIVER ! 10: #endif ! 11: #ifdef HILBERT ! 12: #define TXDRIVER ! 13: #endif ! 14: #ifdef DAISY ! 15: #define TXDRIVER ! 16: #endif ! 17: ! 18: #ifdef USG5 ! 19: #define NSN 1 ! 20: #else ! 21: #include "sn.h" ! 22: #endif ! 23: #if NSN > 0 ! 24: ! 25: #ifdef BSD41 ! 26: #include "../h/param.h" ! 27: #include "../h/systm.h" ! 28: #include "../h/buf.h" ! 29: #include "../h/conf.h" ! 30: #include "../h/dir.h" ! 31: #include "../h/user.h" ! 32: #include "../h/pte.h" ! 33: #include "../h/map.h" ! 34: #include "../h/vm.h" ! 35: #include "../h/dk.h" ! 36: #include "../h/cmap.h" ! 37: #include "../h/ubareg.h" ! 38: #include "../h/ubavar.h" ! 39: #include "../h/cpu.h" ! 40: #include "../h/proc.h" ! 41: #include "../h/snet.h" ! 42: #include "../h/packet.h" ! 43: #include "../h/channel.h" ! 44: #include "../h/status.h" ! 45: #endif ! 46: ! 47: #ifdef SNDEBUG ! 48: int sndebug = 1; ! 49: #else ! 50: int sndebug = 0; ! 51: #endif ! 52: ! 53: /* flags for status */ ! 54: #define INPUT 1 ! 55: #define OUTPUT 2 ! 56: ! 57: #define min(x,y) ((x) < (y) ? (x) : (y)) ! 58: #define swab(x) (unsigned short)((((x)>>8)&0xff) | ((x) << 8)) ! 59: ! 60: #define SNPRI 28 ! 61: ! 62: #define CHKINIT 0xbf37 ! 63: ! 64: struct device { ! 65: short drcs; ! 66: short drout; ! 67: short drin; ! 68: }; ! 69: ! 70: /* Command and Status word */ ! 71: #define CSR0 0x1 ! 72: #define CSR1 0x2 ! 73: #define RIE 0x20 ! 74: #define TIE 0x40 ! 75: #define TEMPTY 0x80 ! 76: #define RFULL 0x8000 ! 77: ! 78: /* ! 79: * CSR1 CSR0 ! 80: * 0 0 Write Data ! 81: * 0 1 Write EOP ! 82: * 1 0 Write Command ! 83: * 1 1 Read Status ! 84: */ ! 85: #define DATA_MODE (RIE) ! 86: #define EOP_MODE (CSR0 | RIE) ! 87: #define CMD_MODE (CSR1 | RIE) ! 88: #define STATUS_MODE (CSR0 | CSR1 | RIE) ! 89: ! 90: /* Command word format ! 91: * ! 92: * +-----------------------------------------------+ ! 93: * | |B |R |A | | | | ! 94: * | |C |S |B | DID | | FCN | ! 95: * | |T |T |T | | | | ! 96: * +-----------------------------------------------+ ! 97: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ! 98: */ ! 99: /* Function codes */ ! 100: #define NOP 0x0 ! 101: #define BOARD_RESET 0x5 ! 102: #define MASTER_CLEAR 0x6 ! 103: ! 104: #define ABORT(did) (0x1000 | (did)) ! 105: #define RESET(did) (0x2000 | (did)) ! 106: #define BROAD_CAST(did) (0x4000 | (did)) ! 107: ! 108: ! 109: /* SNET status word bits ! 110: * ! 111: * +-----------------------------------------------+ ! 112: * | |E |S |I |O | | | ! 113: * | |O |N |B |B | | | ! 114: * | |P |K |E |E | | | ! 115: * +-----------------------------------------------+ ! 116: * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 ! 117: */ ! 118: #define OUTBUF_E 0x4 ! 119: #define INBUF_E 0x8 ! 120: #define SNACK 0x10 /* transmitter error */ ! 121: #define EOP 0x20 /* we have read and EOP frame */ ! 122: ! 123: static int sn_multiplex; ! 124: ! 125: struct openwait sn_openwait[NUMDEV]; ! 126: struct openwait *sn_owhead, *sn_owtail; ! 127: ! 128: #define SNFILE(dev) (minor(dev) & 0x3f) ! 129: #define SNUNIT(dev) ((minor(dev) & 0xc0) >> 6) ! 130: ! 131: struct chdat sn_chans[NUMLCH]; ! 132: #define MAXMSGLEN (512+8) ! 133: struct sn_buffers { ! 134: short inbuf[MAXMSGLEN]; ! 135: short outbuf[MAXMSGLEN]; ! 136: } sn_buffers[NUMLCH]; ! 137: ! 138: #define NOPDID -1 ! 139: ! 140: #ifdef TIMEOUT ! 141: #define CKFUZZ 4 /* number of timeouts we wait for a response */ ! 142: #ifdef USG5 ! 143: #define CKTICKS (HZ/4) /* number of ticks per timeout */ ! 144: #else ! 145: #define CKTICKS (hz/4) /* number of ticks per timeout */ ! 146: #endif ! 147: ! 148: int sn_state; ! 149: #define OPEN 1 /* set if at least one sn? is open */ ! 150: #define TIMER 2 /* set if at timer is running */ ! 151: ! 152: int cktimchk(); ! 153: int sn_opncnt; ! 154: #endif TIMEOUT ! 155: ! 156: struct snmach snmach[NUMDEV] = { ! 157: { 1, 255 }, ! 158: { 2, 254 }, ! 159: { 3, 253 }, ! 160: { 4, 252 }, ! 161: { 5, 251 }, ! 162: { 6, 250 }, ! 163: { 7, 249 }, ! 164: { 8, 248 } }; ! 165: ! 166: int sn_once; ! 167: ! 168: #ifdef BSD42 ! 169: #define RETURN(x) {return(x);} ! 170: #define ARGS(x) args->x ! 171: #else ! 172: #define RETURN(x) {u.u_error = x; return;} ! 173: #define ARGS(x) args.x ! 174: #endif ! 175: ! 176: #ifdef USG5 ! 177: extern struct sninfo sn_sninfo[]; ! 178: extern int sn_cnt; ! 179: extern struct device *sn_addr[]; ! 180: #else ! 181: struct sninfo sn_sninfo[NSN]; ! 182: int snprobe(), snattach(); ! 183: struct uba_device *sndinfo[NSN]; ! 184: u_short snstd[] = {0}; ! 185: struct uba_driver sndriver = ! 186: { snprobe, 0, snattach, 0, snstd, "sn", sndinfo}; ! 187: ! 188: snprobe(reg) ! 189: caddr_t reg; ! 190: { ! 191: register int br, cvec; /* value result */ ! 192: register struct device *snaddr = (struct device *)reg; ! 193: ! 194: br = 0x15; ! 195: #ifdef VAXONE ! 196: cvec = 0510; ! 197: #else ! 198: #ifdef CANTOR ! 199: if (((int)snaddr & 017777) == 007770) ! 200: cvec = 0504; ! 201: if (((int)snaddr & 017777) == 007750) ! 202: cvec = 0464; ! 203: #else ! 204: cvec = 0504; ! 205: #endif ! 206: #endif ! 207: #ifdef BSD41 ! 208: return(1); ! 209: #endif ! 210: #ifdef BSD42 ! 211: return(sizeof(struct device)); ! 212: #endif ! 213: } ! 214: ! 215: /*ARGSUSED*/ ! 216: snattach(ui) ! 217: register struct uba_device *ui; ! 218: { ! 219: } ! 220: #endif ! 221: ! 222: snopen(dev, rw) ! 223: dev_t dev; ! 224: int rw; ! 225: { ! 226: register struct device *draddr; ! 227: #ifndef USG5 ! 228: struct uba_device *ui; ! 229: #endif ! 230: register struct sninfo *sninfop; ! 231: int mdev = SNFILE(dev); ! 232: int unit = SNUNIT(dev); ! 233: ! 234: if( sndebug ) ! 235: printf("snopen(%x,%x)\n", dev, rw); ! 236: ! 237: #ifdef USG5 ! 238: if ( mdev > NUMDEV || unit >= sn_cnt) { ! 239: RETURN ( ENXIO ); ! 240: } ! 241: draddr = sn_addr[unit]; ! 242: #else ! 243: if (mdev > NUMDEV || unit >= NSN || ! 244: (ui = sndinfo[unit]) == 0 || ui->ui_alive == 0) { ! 245: RETURN ( ENXIO ); ! 246: } ! 247: draddr = (struct device *)ui->ui_addr; ! 248: #endif ! 249: ! 250: if ( sn_once == 0 ) { ! 251: struct chdat *cp = sn_chans; ! 252: ! 253: sn_once++; ! 254: for( ; cp<&sn_chans[NUMLCH]; cp++) { ! 255: cp->lchnum = -1; ! 256: cp->dlchnum = -1; ! 257: } ! 258: sn_owhead = sn_owtail = sn_openwait; ! 259: } ! 260: ! 261: sninfop = &sn_sninfo[unit]; ! 262: spl6(); ! 263: if (sninfop->sndevlock[mdev]++ != 0) { ! 264: spl0(); ! 265: RETURN ( EBUSY ); ! 266: } ! 267: #ifdef TIMEOUT ! 268: sn_opncnt++; ! 269: sn_state |= OPEN; ! 270: if ((sn_state & TIMER) == 0) { ! 271: sn_state |= TIMER; ! 272: timeout(cktimchk, (caddr_t)0, CKTICKS); ! 273: } ! 274: #endif TIMEOUT ! 275: if( sninfop->snlock++ == 0 ) { ! 276: #ifdef TXDRIVER ! 277: { ! 278: extern struct txinfo tx_sninfo[]; ! 279: ! 280: if (tx_sninfo[unit].snlock != 0) { ! 281: spl0(); ! 282: return; ! 283: } ! 284: } ! 285: #endif ! 286: draddr->drcs = CMD_MODE; ! 287: draddr->drout = 0; ! 288: draddr->drout = BOARD_RESET; ! 289: draddr->drout = 0; ! 290: draddr->drcs = DATA_MODE; ! 291: } ! 292: ! 293: spl0(); ! 294: return(0); ! 295: } ! 296: ! 297: snclose(dev) ! 298: { ! 299: register struct chdat *cp; ! 300: #ifndef USG5 ! 301: struct uba_device *ui; ! 302: #endif ! 303: register struct sninfo *sninfop; ! 304: register struct device *draddr; ! 305: int mdev = SNFILE(dev); ! 306: int unit = SNUNIT(dev); ! 307: int resetmachno; ! 308: struct openwait *curtail; ! 309: ! 310: if( sndebug ) ! 311: printf("snclose(%x)\n", dev); ! 312: #ifdef USG5 ! 313: if ( unit >= sn_cnt) { ! 314: RETURN ( ENXIO ); ! 315: } ! 316: draddr = sn_addr[unit]; ! 317: #else ! 318: if ( unit >= NSN) { ! 319: RETURN ( ENXIO ); ! 320: } ! 321: ui = sndinfo[unit]; ! 322: draddr = (struct device *)ui->ui_addr; ! 323: #endif ! 324: ! 325: sninfop = &sn_sninfo[unit]; ! 326: spl6(); ! 327: if( sninfop->snlock == 0 || mdev > NUMDEV ! 328: || sninfop->sndevlock[mdev] == 0 ) { ! 329: spl0(); ! 330: RETURN ( ENXIO ); ! 331: } ! 332: ! 333: resetmachno = -1; ! 334: for(cp=sninfop->snlink[mdev]; cp; cp=cp->link) { ! 335: if (cp->pdid == NOPDID) ! 336: resetmachno = cp->machno; ! 337: chclose(cp); ! 338: } ! 339: if (resetmachno != -1) { ! 340: for(cp=sn_chans; cp < &sn_chans[NUMLCH]; cp++) { ! 341: if (cp->pdid == NOPDID && cp->machno == resetmachno) ! 342: goto noreset; ! 343: } ! 344: draddr->drcs = CMD_MODE; ! 345: draddr->drout = RESET(resetmachno << 8); ! 346: draddr->drcs = EOP_MODE; ! 347: draddr->drout = 0; ! 348: draddr->drcs = DATA_MODE; ! 349: } ! 350: ! 351: noreset: ! 352: for (curtail = sn_owtail; curtail != sn_owhead; ! 353: curtail = ownext(curtail)) { ! 354: if (curtail->pid == u.u_procp->p_pid) { ! 355: curtail->pid = 0; ! 356: goto nowakeup; ! 357: } ! 358: } ! 359: while (sn_owtail != sn_owhead) { ! 360: curtail = sn_owtail; ! 361: sn_owtail = ownext(sn_owtail); ! 362: if (curtail->pid) { ! 363: wakeup(curtail); ! 364: break; ! 365: } ! 366: } ! 367: ! 368: nowakeup: ! 369: sninfop->snlink[mdev] = 0; ! 370: sninfop->sndevlock[mdev] = 0; ! 371: #ifdef TIMEOUT ! 372: if (--sn_opncnt <= 0) { ! 373: sn_state &= ~OPEN; ! 374: sn_opncnt = 0; ! 375: } ! 376: #endif TIMEOUT ! 377: if (--sninfop->snlock == 0 ) { ! 378: #ifdef TXDRIVER ! 379: { ! 380: if (tx_sninfo[unit].snlock != 0) ! 381: return; ! 382: } ! 383: #endif ! 384: draddr->drcs &= ~RIE; ! 385: } ! 386: spl0(); ! 387: return(0); ! 388: } ! 389: ! 390: static short ratshole[MAXMSGLEN]; ! 391: static struct chdat ratschan; ! 392: ! 393: #ifdef USG5 ! 394: snintr(unit) ! 395: #else ! 396: snrint(unit) ! 397: #endif ! 398: int unit; ! 399: { ! 400: register struct chdat *cp; ! 401: register short *sp, *dp; ! 402: register int i; ! 403: register struct sninfo *sninfop; ! 404: register struct device *draddr; ! 405: unsigned short chksum, xchk; ! 406: short len; ! 407: unsigned short chan; ! 408: short *osp; ! 409: #ifndef USG5 ! 410: struct uba_device *ui; ! 411: #endif ! 412: ! 413: #ifdef USG5 ! 414: draddr = sn_addr[unit]; ! 415: #else ! 416: ui = sndinfo[unit]; ! 417: draddr = (struct device *)ui->ui_addr; ! 418: #endif ! 419: dp = &draddr->drin; ! 420: ! 421: sninfop = &sn_sninfo[unit]; ! 422: sninfop->snrcnt++; ! 423: ! 424: loop: ! 425: chksum = CHKINIT; ! 426: ! 427: chan = *dp; ! 428: #ifdef TXDRIVER ! 429: /* unusual process numbers go to tx driver */ ! 430: if ((chan & 0xff) <= 200 || ((unsigned int)chan) >= 0x2000 ) { ! 431: txintrmt(unit, chan); ! 432: goto getstatus; ! 433: } ! 434: #endif ! 435: chksum ^= chan; ! 436: chan = swab(chan); ! 437: len = *dp; ! 438: chksum ^= len; ! 439: len = swab(len); ! 440: if( len > MAXMSGLEN ) { ! 441: sninfop->snnbadlen++; ! 442: goto getstatus; ! 443: } ! 444: sninfop->sninbytes += len+4; ! 445: ! 446: for(cp=sn_chans; cp < &sn_chans[NUMLCH]; cp++) ! 447: if( cp->xchan == chan && cp->snunit == unit ) { ! 448: if( cp->input.done == 0 && len <= cp->input.len ) ! 449: osp = sp = cp->input.buf; ! 450: else ! 451: osp = sp = ratshole; ! 452: goto found; ! 453: } ! 454: osp = sp = ratshole; ! 455: cp = &ratschan; ! 456: sninfop->snnnolc++; ! 457: found: ! 458: ! 459: for(i=len; i>0; i-=8) { ! 460: switch( i ) { ! 461: default: ! 462: *sp = *dp; ! 463: chksum ^= *sp++; ! 464: case 7: ! 465: *sp = *dp; ! 466: chksum ^= *sp++; ! 467: case 6: ! 468: *sp = *dp; ! 469: chksum ^= *sp++; ! 470: case 5: ! 471: *sp = *dp; ! 472: chksum ^= *sp++; ! 473: case 4: ! 474: *sp = *dp; ! 475: chksum ^= *sp++; ! 476: case 3: ! 477: *sp = *dp; ! 478: chksum ^= *sp++; ! 479: case 2: ! 480: *sp = *dp; ! 481: chksum ^= *sp++; ! 482: case 1: ! 483: *sp = *dp; ! 484: chksum ^= *sp++; ! 485: } ! 486: } ! 487: if( (i = ((len < 0 ? 0 : len) + 3)&0xf) != 0 ) { ! 488: for(i^=0xf; i-->=0; ) ! 489: chksum ^= *dp; ! 490: } ! 491: if( chksum != (xchk = *dp) ) { ! 492: sninfop->snnchksum++; ! 493: if( sndebug ) { ! 494: short *usp = osp; ! 495: int x = len; ! 496: ! 497: printf("snchksum (%x, %x):", chan, len); ! 498: for(; --x>=0; ) ! 499: printf(" %x", *usp++); ! 500: printf(" %x (%x)\n", xchk, chksum); ! 501: } ! 502: } else if( len > 0 ) { ! 503: if( osp == ratshole ) { ! 504: cp->flags |= SENTRNR; ! 505: snxstart(unit, cp, RNR); ! 506: sninfop->snsrnr++; ! 507: } else { ! 508: sninfop->snndata++; ! 509: cp->input.done = 1; ! 510: cp->input.len = len; ! 511: snxstart(unit, cp, ACK); ! 512: sninfop->snsack++; ! 513: wakeup((caddr_t)cp->input.buf); ! 514: if( cp->flags&MULTIPLEX ) ! 515: wakeup((caddr_t)&sn_multiplex); ! 516: } ! 517: } else { ! 518: switch( len ) { ! 519: case ACK: ! 520: sninfop->snnack++; ! 521: cp->flags &= ~SENTDATA; ! 522: cp->output.done = 1; ! 523: wakeup((caddr_t)cp->output.buf); ! 524: break; ! 525: ! 526: case RDY: ! 527: sninfop->snnrdy++; ! 528: snxstart(unit, cp, RACK); ! 529: if( cp->output.done == 0 && cp->output.len > 0 ) { ! 530: snxstart(unit, cp, DATA); ! 531: sninfop->snrout++; ! 532: } ! 533: break; ! 534: ! 535: case RNR: ! 536: sninfop->snnrnr++; ! 537: cp->flags &= ~SENTDATA; ! 538: break; ! 539: ! 540: case RACK: ! 541: sninfop->snnrack++; ! 542: cp->flags &= ~SENTRDY; ! 543: break; ! 544: ! 545: default: ! 546: printf("snrint: unit %d, bad type %d\n", unit, len); ! 547: break; ! 548: } ! 549: } ! 550: ! 551: getstatus: ! 552: draddr->drcs = STATUS_MODE; ! 553: i = *dp; ! 554: draddr->drcs = DATA_MODE; ! 555: if ((i&INBUF_E) == 0) { ! 556: sninfop->sninloop++; ! 557: goto loop; ! 558: } ! 559: } ! 560: ! 561: snxstart(unit, cp, type) ! 562: int unit; ! 563: register struct chdat *cp; ! 564: int type; ! 565: { ! 566: register short *sp, *dp; ! 567: register struct sninfo *sninfop; ! 568: register struct device *draddr; ! 569: register int i; ! 570: unsigned short chksum; ! 571: #ifndef USG5 ! 572: struct uba_device *ui; ! 573: #endif ! 574: int len, numretry; ! 575: ! 576: #ifdef USG5 ! 577: draddr = sn_addr[unit]; ! 578: #else ! 579: ui = sndinfo[unit]; ! 580: draddr = (struct device *)ui->ui_addr; ! 581: #endif ! 582: dp = &draddr->drout; ! 583: ! 584: sninfop = &sn_sninfo[unit]; ! 585: ! 586: if( type == DATA ) { ! 587: len = cp->output.len; ! 588: sninfop->snoutbytes += len+4; ! 589: } else { ! 590: len = type; ! 591: sninfop->snoutbytes += 4; ! 592: } ! 593: draddr->drcs = STATUS_MODE; ! 594: ! 595: i = draddr->drin; ! 596: if ( (i&OUTBUF_E) == 0 ) { ! 597: sninfop->snoutfull++; ! 598: do { ! 599: i = draddr->drin; ! 600: sninfop->sncntoutfull++; ! 601: } while( (i&OUTBUF_E) == 0 ); ! 602: } ! 603: ! 604: numretry = 0; ! 605: sninfop->snxcnt++; ! 606: retry: ! 607: sp = cp->output.buf; ! 608: chksum = CHKINIT; ! 609: if (cp->pdid == NOPDID) { ! 610: draddr->drcs = CMD_MODE; ! 611: *dp = cp->machno<<8; ! 612: draddr->drcs = DATA_MODE; ! 613: *dp = i = swab(cp->dlchnum); ! 614: } else { ! 615: draddr->drcs = CMD_MODE; ! 616: *dp = cp->pdid<<8; ! 617: draddr->drcs = DATA_MODE; ! 618: *dp = i = (cp->dlchnum<<8) | cp->machno; ! 619: } ! 620: chksum ^= (unsigned short)i; ! 621: *dp = i = swab(len); ! 622: chksum ^= (unsigned short)i; ! 623: for( i=len; i>0; i-=8 ) { ! 624: switch( i ) { ! 625: default: ! 626: chksum ^= *sp; ! 627: *dp = *sp++; ! 628: case 7: ! 629: chksum ^= *sp; ! 630: *dp = *sp++; ! 631: case 6: ! 632: chksum ^= *sp; ! 633: *dp = *sp++; ! 634: case 5: ! 635: chksum ^= *sp; ! 636: *dp = *sp++; ! 637: case 4: ! 638: chksum ^= *sp; ! 639: *dp = *sp++; ! 640: case 3: ! 641: chksum ^= *sp; ! 642: *dp = *sp++; ! 643: case 2: ! 644: chksum ^= *sp; ! 645: *dp = *sp++; ! 646: case 1: ! 647: chksum ^= *sp; ! 648: *dp = *sp++; ! 649: } ! 650: } ! 651: if( (i = ((len < 0 ? 0 : len) + 3)&0xf) != 0 ) { ! 652: for(i^=0xf; i-->=0; ) ! 653: *dp = 0; ! 654: } ! 655: draddr->drcs = EOP_MODE; ! 656: *dp = chksum; ! 657: draddr->drcs = STATUS_MODE; ! 658: i = draddr->drin; ! 659: draddr->drcs = DATA_MODE; ! 660: if( i&SNACK ) { ! 661: sninfop->snsnack++; ! 662: if( ++numretry < 100 ) ! 663: goto retry; ! 664: sninfop->snlost++; ! 665: } ! 666: cp->ckticks = CKFUZZ; ! 667: if( type == DATA ) { ! 668: cp->flags |= SENTDATA; ! 669: } ! 670: } ! 671: ! 672: snioctl(dev, cmd, addr, flag) ! 673: caddr_t addr; ! 674: dev_t dev; ! 675: { ! 676: register struct chdat *cp; ! 677: register struct reqinfo *rp; ! 678: register struct sninfo *sninfop; ! 679: register struct bufinfo *bp; ! 680: register struct chdat *dp; ! 681: struct status status; ! 682: int i; ! 683: struct status *ustatus; ! 684: char *usaddr; ! 685: int ulen; ! 686: int error; ! 687: int mdev = SNFILE(dev); ! 688: int unit = SNUNIT(dev); ! 689: ! 690: #ifdef USG5 ! 691: if ( unit >= sn_cnt) { ! 692: RETURN ( ENXIO ); ! 693: } ! 694: #else ! 695: if ( unit >= NSN) { ! 696: RETURN ( ENXIO ); ! 697: } ! 698: #endif ! 699: sninfop = &sn_sninfo[unit]; ! 700: ! 701: switch( cmd ) { ! 702: case NIOOPEN: { ! 703: #ifdef BSD42 ! 704: struct oargs *args = (struct oargs *)addr; ! 705: #else ! 706: struct oargs args; ! 707: ! 708: if (copyin(addr, (caddr_t)&args, sizeof(args))) { ! 709: RETURN ( EFAULT ); ! 710: } ! 711: #endif ! 712: spl6(); ! 713: for(cp=sn_chans; cp<&sn_chans[NUMLCH]; cp++) ! 714: if( cp->lchnum == -1 && cp->dlchnum == -1 ) ! 715: break; ! 716: if( cp >= &sn_chans[NUMLCH] ) { ! 717: spl0(); ! 718: RETURN( ENFILE ); ! 719: } ! 720: for(dp=sn_chans; dp<&sn_chans[NUMLCH]; dp++) ! 721: if( dp->lchnum != -1 && dp->lmachno == ARGS(lmachno) ! 722: && dp->lchnum == ARGS(lchno) ! 723: && dp->snunit == unit ) { ! 724: spl0(); ! 725: RETURN( EEXIST ); ! 726: } ! 727: cp->lchnum = ARGS(lchno); ! 728: cp->dlchnum = ARGS(dlchno); ! 729: spl0(); ! 730: cp->lmachno = ARGS(lmachno); ! 731: cp->machno = ARGS(dmachno); ! 732: cp->xchan = (cp->lmachno<<8)|cp->lchnum; ! 733: cp->snunit = unit; ! 734: cp->pdid = NOPDID; ! 735: bp = &cp->input; ! 736: i = cp-sn_chans; ! 737: bp->buf = sn_buffers[i].inbuf; ! 738: bp->len = MAXMSGLEN; ! 739: bp->done = 0; ! 740: bp = &cp->output; ! 741: bp->buf = sn_buffers[i].outbuf; ! 742: bp->len = bp->done = 0; ! 743: cp->flags = 0; ! 744: cp->link = sninfop->snlink[mdev]; ! 745: sninfop->snlink[mdev] = cp; ! 746: return(0); ! 747: } ! 748: ! 749: case NIOXOPEN: { ! 750: struct snmach *snmachp; ! 751: struct openwait *nexthead, *thishead; ! 752: #ifdef BSD42 ! 753: struct oargs *args = (struct oargs *)addr; ! 754: #else ! 755: struct oargs args; ! 756: ! 757: if (copyin(addr, (caddr_t)&args, sizeof(args))) { ! 758: RETURN ( EFAULT ); ! 759: } ! 760: #endif ! 761: for (;;) { ! 762: for (snmachp = &snmach[0]; ! 763: snmachp < &snmach[NUMDEV] && ! 764: snmachp->machno; ! 765: snmachp++) { ! 766: spl6(); ! 767: for (cp=sn_chans; cp<&sn_chans[NUMLCH]; cp++) ! 768: if( cp->lchnum == -1 && ! 769: cp->dlchnum == -1 ) ! 770: break; ! 771: if( cp >= &sn_chans[NUMLCH] ) { ! 772: goto xopensleep; ! 773: } ! 774: for(dp=sn_chans; dp<&sn_chans[NUMLCH]; dp++) { ! 775: if( dp->lchnum != -1 ! 776: && dp->lmachno == snmachp->lmachno ! 777: && dp->lchnum == ARGS(lchno) ! 778: && dp->snunit == unit ) { ! 779: /* Channel already in use */ ! 780: break; ! 781: } ! 782: } ! 783: if( dp >= &sn_chans[NUMLCH] ) ! 784: goto okmachp; ! 785: spl0(); ! 786: } ! 787: xopensleep: ! 788: nexthead = ownext(sn_owhead); ! 789: if (nexthead == sn_owtail) { ! 790: RETURN ( ENXIO ); ! 791: } ! 792: thishead = sn_owhead; ! 793: thishead->pid = u.u_procp->p_pid; ! 794: sn_owhead = nexthead; ! 795: sleep((caddr_t)thishead, SNPRI); ! 796: } ! 797: okmachp: ! 798: cp->lchnum = ARGS(lchno); ! 799: cp->lmachno = snmachp->lmachno; ! 800: spl0(); ! 801: cp->dlchnum = ARGS(dlchno); ! 802: cp->machno = snmachp->machno; ! 803: cp->xchan = (cp->lmachno<<8)|cp->lchnum; ! 804: cp->snunit = unit; ! 805: cp->pdid = NOPDID; ! 806: bp = &cp->input; ! 807: i = cp-sn_chans; ! 808: bp->buf = sn_buffers[i].inbuf; ! 809: bp->len = MAXMSGLEN; ! 810: bp->done = 0; ! 811: bp = &cp->output; ! 812: bp->buf = sn_buffers[i].outbuf; ! 813: bp->len = bp->done = 0; ! 814: cp->flags = 0; ! 815: cp->link = sninfop->snlink[mdev]; ! 816: sninfop->snlink[mdev] = cp; ! 817: ! 818: ARGS(lmachno) = snmachp->lmachno; ! 819: ARGS(dmachno) = snmachp->machno; ! 820: #ifndef BSD42 ! 821: if (copyout((caddr_t)&args, addr, sizeof(args))) { ! 822: RETURN ( EFAULT ); ! 823: } ! 824: #endif ! 825: return(0); ! 826: } ! 827: ! 828: case NIOPOPEN: { ! 829: #ifdef BSD42 ! 830: struct voargs *args = (struct voargs *)addr; ! 831: #else ! 832: struct voargs args; ! 833: ! 834: if (copyin(addr, (caddr_t)&args, sizeof(args))) { ! 835: RETURN ( EFAULT ); ! 836: } ! 837: #endif ! 838: spl6(); ! 839: for(cp=sn_chans; cp<&sn_chans[NUMLCH]; cp++) ! 840: if( cp->lchnum == -1 && cp->dlchnum == -1 ) ! 841: break; ! 842: if( cp >= &sn_chans[NUMLCH] ) { ! 843: spl0(); ! 844: RETURN( ENFILE ); ! 845: } ! 846: for(dp=sn_chans; dp<&sn_chans[NUMLCH]; dp++) ! 847: if( dp->lchnum != -1 && dp->lmachno == ARGS(lmachno) ! 848: && dp->lchnum == ARGS(lchno) ! 849: && dp->snunit == unit ) { ! 850: spl0(); ! 851: RETURN( EEXIST ); ! 852: } ! 853: cp->lchnum = ARGS(lchno); ! 854: cp->lmachno = ARGS(lmachno); ! 855: spl0(); ! 856: cp->dlchnum = ARGS(dlchno); ! 857: cp->machno = ARGS(dmachno); ! 858: cp->xchan = (cp->lmachno<<8)|cp->lchnum; ! 859: cp->snunit = unit; ! 860: cp->pdid = ARGS(pdid); ! 861: bp = &cp->input; ! 862: i = cp-sn_chans; ! 863: bp->buf = sn_buffers[i].inbuf; ! 864: bp->len = MAXMSGLEN; ! 865: bp->done = 0; ! 866: bp = &cp->output; ! 867: bp->buf = sn_buffers[i].outbuf; ! 868: bp->len = bp->done = 0; ! 869: cp->flags = 0; ! 870: cp->link = sninfop->snlink[mdev]; ! 871: sninfop->snlink[mdev] = cp; ! 872: return(0); ! 873: } ! 874: ! 875: case NIOCLOSE: { ! 876: #ifdef BSD42 ! 877: struct cargs *args = (struct cargs *)addr; ! 878: #else ! 879: struct cargs args; ! 880: ! 881: if (copyin(addr, (caddr_t)&args, sizeof(args))) { ! 882: RETURN ( EFAULT ); ! 883: } ! 884: #endif ! 885: for(cp=sninfop->snlink[mdev], dp=0; cp; dp=cp, cp=cp->link) ! 886: if( cp->lmachno == ARGS(lmachno) ! 887: && cp->lchnum == ARGS(lchno) ) { ! 888: /* TIMING !!! */ ! 889: if( dp ) ! 890: dp->link = cp->link; ! 891: else ! 892: sninfop->snlink[mdev] = cp->link; ! 893: chclose(cp); ! 894: return(0); ! 895: } ! 896: RETURN( EBADF ); ! 897: } ! 898: ! 899: case NIOGET: ! 900: case NIOPUT: ! 901: { ! 902: #ifdef BSD42 ! 903: struct gpargs *args = (struct gpargs *)addr; ! 904: #else ! 905: struct gpargs args; ! 906: ! 907: if (copyin(addr, (caddr_t)&args, sizeof(args))) { ! 908: RETURN ( EFAULT ); ! 909: } ! 910: #endif ! 911: status.lchdir = (cmd == NIOGET ? INPUT : OUTPUT); ! 912: status.lchnum = ARGS(lch); ! 913: ustatus = ARGS(status); ! 914: usaddr = ARGS(addr); ! 915: ulen = ARGS(len); ! 916: for(cp=sninfop->snlink[mdev]; cp; cp=cp->link) { ! 917: if( cp->lchnum == ARGS(lch) ! 918: && cp->lmachno == ARGS(lmachno)) { ! 919: do_getput: ! 920: bp = (cmd == NIOGET ? &cp->input : &cp->output); ! 921: if( cmd == NIOPUT ) { ! 922: copyin(usaddr, bp->buf, ulen); ! 923: spl5(); ! 924: bp->len = (ulen+1)/2; ! 925: snxstart(unit, cp, DATA); ! 926: sninfop->snsdata++; ! 927: } else { ! 928: spl5(); ! 929: /* ! 930: * The following may be ! 931: * unnecessary in light of ! 932: * the later check. ! 933: */ ! 934: if( bp->done == 0 && cp->flags&SENTRNR ) { ! 935: cp->flags &= ~SENTRNR; ! 936: cp->flags |= SENTRDY; ! 937: snxstart(unit, cp, RDY); ! 938: sninfop->sns1rdy++; ! 939: } ! 940: } ! 941: for (;;) { ! 942: spl5(); ! 943: if (bp->done) break; ! 944: sleep((caddr_t)bp->buf, SNPRI); ! 945: #ifdef TIMEOUT ! 946: spl6(); ! 947: if (cp->flags & RETRY) { ! 948: cp->flags &= ~RETRY; ! 949: sninfop->sntimeout++; ! 950: snxstart(unit, cp, (cp->flags&SENTDATA) ? DATA : RDY); ! 951: } ! 952: #endif TIMEOUT ! 953: } ! 954: status.code = ST_OK; ! 955: status.len = 2*bp->len; ! 956: if( cmd == NIOGET ) { ! 957: spl0(); ! 958: copyout(bp->buf, usaddr, 2*bp->len); ! 959: spl5(); ! 960: bp->len = MAXMSGLEN; ! 961: /* ! 962: * Believe it or not, we must check ! 963: * this here. This is because ! 964: * we lowered the ipl to do the ! 965: * copyout(). During that time ! 966: * another message may have tried ! 967: * to sneak in. ! 968: */ ! 969: if( cp->flags&SENTRNR ) { ! 970: cp->flags &= ~SENTRNR; ! 971: snxstart(unit, cp, RDY); ! 972: sninfop->snsrdy++; ! 973: } ! 974: } else ! 975: bp->len = 0; ! 976: bp->done = 0; ! 977: spl0(); ! 978: error = 0; ! 979: goto cpyout; ! 980: } ! 981: } ! 982: status.code = ST_IARGS; ! 983: error = EIO; ! 984: cpyout: ! 985: copyout((caddr_t)&status, (caddr_t)ustatus, sizeof(status)); ! 986: RETURN ( error ); ! 987: } ! 988: ! 989: case NIOGETM: ! 990: { ! 991: struct pair pair; ! 992: struct chdat *lchns[MAXMUX+1]; ! 993: register struct chdat **chp = lchns, **chpe = lchns; ! 994: #ifdef BSD42 ! 995: struct gmargs *args = (struct gmargs *)addr; ! 996: #else ! 997: struct gmargs args; ! 998: ! 999: if (copyin(addr, (caddr_t)&args, sizeof(args))) { ! 1000: RETURN ( EFAULT ); ! 1001: } ! 1002: #endif ! 1003: status.lchdir = INPUT; ! 1004: ustatus = ARGS(status); ! 1005: usaddr = ARGS(addr); ! 1006: ulen = ARGS(len); ! 1007: for(i=0; i<MAXMUX; i++) { ! 1008: if (copyin((caddr_t)ARGS(pairp++), (caddr_t)&pair, ! 1009: sizeof(struct pair))) { ! 1010: RETURN ( EFAULT ); ! 1011: } ! 1012: if( pair.lchno == -1 ) ! 1013: break; ! 1014: if (pair.lchno < 0 || pair.lchno >= 512 ! 1015: || pair.lmachno < 0 || pair.lmachno >= 512) { ! 1016: RETURN ( EBADF ); ! 1017: } ! 1018: for(cp=sninfop->snlink[mdev]; cp; cp=cp->link) { ! 1019: if( cp->lchnum == pair.lchno ! 1020: && cp->lmachno == pair.lmachno ) { ! 1021: *chpe++ = cp; ! 1022: break; ! 1023: } ! 1024: } ! 1025: if( cp >= &sn_chans[NUMLCH] ) { ! 1026: RETURN ( EBADF ); ! 1027: } ! 1028: } ! 1029: spl5(); ! 1030: for(chp=lchns; chp<chpe; chp++) { ! 1031: if( (*chp)->flags&MULTIPLEX ) { ! 1032: spl0(); ! 1033: RETURN ( EBUSY ); ! 1034: } ! 1035: } ! 1036: for(chp=lchns; chp<chpe; chp++) ! 1037: (*chp)->flags |= MULTIPLEX; ! 1038: ! 1039: loop: ! 1040: spl5(); ! 1041: for(chp=lchns; chp<chpe; chp++) { ! 1042: if( (*chp)->input.done ) { ! 1043: goto gotone; ! 1044: } ! 1045: } ! 1046: sleep((caddr_t)&sn_multiplex, SNPRI); ! 1047: goto loop; ! 1048: ! 1049: gotone: ! 1050: cp = *chp; ! 1051: for(chp=lchns; chp<chpe; chp++) ! 1052: (*chp)->flags &= ~MULTIPLEX; ! 1053: spl0(); ! 1054: status.lchnum = cp->lchnum; ! 1055: cmd = NIOGET; ! 1056: goto do_getput; ! 1057: } ! 1058: ! 1059: case NIOABORT: ! 1060: case NIORESET: { ! 1061: struct device *draddr; ! 1062: #ifndef USG5 ! 1063: struct uba_device *ui; ! 1064: #endif ! 1065: #ifdef BSD42 ! 1066: struct raargs *args = (struct raargs *)addr; ! 1067: #else ! 1068: struct raargs args; ! 1069: ! 1070: if (copyin(addr, (caddr_t)&args, sizeof(args))) { ! 1071: RETURN ( EFAULT ); ! 1072: } ! 1073: #endif ! 1074: ! 1075: #ifdef USG5 ! 1076: draddr = sn_addr[unit]; ! 1077: #else ! 1078: ui = sndinfo[unit]; ! 1079: draddr = (struct device *)ui->ui_addr; ! 1080: #endif ! 1081: ! 1082: spl5(); ! 1083: i = ARGS(machno) << 8; ! 1084: draddr->drcs = CMD_MODE; ! 1085: draddr->drout = (cmd == NIOABORT ? ABORT(i) : RESET(i)); ! 1086: draddr->drcs = EOP_MODE; ! 1087: draddr->drout = 0; ! 1088: draddr->drcs = DATA_MODE; ! 1089: spl0(); ! 1090: return(0); ! 1091: } ! 1092: ! 1093: case NIOREADSTATUS: ! 1094: #ifdef BSD42 ! 1095: copyout((caddr_t)sninfop, *(caddr_t *)addr, ! 1096: sizeof sn_sninfo[0]); ! 1097: #else ! 1098: copyout((caddr_t)sninfop, (caddr_t)addr, ! 1099: sizeof sn_sninfo[0]); ! 1100: #endif ! 1101: return(0); ! 1102: ! 1103: case NIOCHSTATUS: { ! 1104: ! 1105: struct chinfo chinfo; ! 1106: ! 1107: chinfo.numlch = NUMLCH; ! 1108: chinfo.chanaddr = &sn_chans[0]; ! 1109: #ifdef BSD42 ! 1110: copyout((caddr_t)&chinfo, *(caddr_t *)addr, ! 1111: sizeof chinfo); ! 1112: copyout((caddr_t)chinfo.chanaddr, ! 1113: (*(caddr_t *)addr)+sizeof chinfo, ! 1114: NUMLCH*sizeof sn_chans[0]); ! 1115: #else ! 1116: copyout((caddr_t)&chinfo, (caddr_t)addr, ! 1117: sizeof chinfo); ! 1118: copyout((caddr_t)chinfo.chanaddr, ! 1119: (caddr_t)(addr+sizeof chinfo), ! 1120: NUMLCH*sizeof sn_chans[0]); ! 1121: #endif ! 1122: return(0); ! 1123: } ! 1124: ! 1125: case NIOSETMACH: ! 1126: #ifdef BSD42 ! 1127: copyin(*(caddr_t *)addr, (caddr_t)snmach, sizeof snmach); ! 1128: #else ! 1129: copyin((caddr_t)addr, (caddr_t)snmach, sizeof snmach); ! 1130: #endif ! 1131: return(0); ! 1132: ! 1133: ! 1134: case NIOGETMACH: ! 1135: #ifdef BSD42 ! 1136: copyout((caddr_t)snmach, *(caddr_t *)addr, sizeof snmach); ! 1137: #else ! 1138: copyout((caddr_t)snmach, (caddr_t)addr, sizeof snmach); ! 1139: #endif ! 1140: return(0); ! 1141: ! 1142: ! 1143: case NIOQSTATUS: { ! 1144: struct openinfo openinfo; ! 1145: ! 1146: openinfo.owaddr = sn_openwait; ! 1147: openinfo.head = sn_owhead; ! 1148: openinfo.tail = sn_owtail; ! 1149: ! 1150: #ifdef BSD42 ! 1151: copyout((caddr_t)&openinfo, *(caddr_t *)addr, sizeof openinfo); ! 1152: copyout((caddr_t)sn_openwait, ! 1153: (*(caddr_t *)addr)+sizeof openinfo, ! 1154: NUMDEV*sizeof sn_openwait[0]); ! 1155: #else ! 1156: copyout((caddr_t)&openinfo, (caddr_t)addr, sizeof openinfo); ! 1157: copyout((caddr_t)sn_openwait, (caddr_t)(addr+sizeof openinfo), ! 1158: NUMDEV*sizeof sn_openwait[0]); ! 1159: #endif ! 1160: return(0); ! 1161: } ! 1162: ! 1163: case NIOZEROSTAT: ! 1164: { ! 1165: ! 1166: register char *p, *low, *high; ! 1167: ! 1168: low = (char *) &sn_sninfo[0]; ! 1169: #ifdef USG5 ! 1170: high = low + sn_cnt*sizeof (struct sninfo); ! 1171: #else ! 1172: high = low + NSN*sizeof (struct sninfo); ! 1173: #endif ! 1174: ! 1175: for (p=low; p<high; p++) ! 1176: *p = '\0'; ! 1177: return(0); ! 1178: } ! 1179: case NIOCHECK: ! 1180: case NIOWAIT: ! 1181: case NIOPURGE: ! 1182: case NIOSETVEC: ! 1183: ; ! 1184: } ! 1185: } ! 1186: ! 1187: static ! 1188: chclose(cp) ! 1189: register struct chdat *cp; ! 1190: { ! 1191: cp->lchnum = cp->dlchnum = cp->machno = -1; ! 1192: cp->flags = cp->xchan = cp->input.len = 0; ! 1193: } ! 1194: ! 1195: #ifdef TIMEOUT ! 1196: cktimchk() ! 1197: { ! 1198: register struct chdat *cp; ! 1199: register struct sninfo *sninfop; ! 1200: int unit; ! 1201: int s; ! 1202: ! 1203: for(cp=sn_chans; cp < &sn_chans[NUMLCH]; cp++) { ! 1204: if( cp->flags&(SENTDATA|SENTRDY) && --cp->ckticks == 0 ) { ! 1205: unit = cp->snunit; ! 1206: sninfop = &sn_sninfo[unit]; ! 1207: sninfop->snsched++; ! 1208: sninfop->snenqlost[cp->machno]++; ! 1209: cp->flags |= RETRY; ! 1210: if (cp->flags & SENTDATA) { ! 1211: wakeup((caddr_t)cp->output.buf); ! 1212: } else { ! 1213: wakeup((caddr_t)cp->input.buf); ! 1214: } ! 1215: } ! 1216: } ! 1217: s = spl6(); ! 1218: if (sn_state & OPEN) { ! 1219: timeout(cktimchk, (caddr_t)0, CKTICKS); ! 1220: } else { ! 1221: sn_state &= ~TIMER; ! 1222: } ! 1223: splx(s); ! 1224: } ! 1225: #endif TIMEOUT ! 1226: ! 1227: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.