|
|
1.1 ! root 1: /* (-lgl ! 2: * COHERENT Driver Kit Version 1.1.0 ! 3: * Copyright (c) 1982, 1990 by Mark Williams Company. ! 4: * All rights reserved. May not be copied without permission. ! 5: -lgl) */ ! 6: /* ! 7: * Tiac ARCNET PC-234 Device Driver ! 8: * ! 9: * True support for up to 4 network cards through minor devices 0-3. ! 10: * Up to 4 protocols now supported. Novell access is through normal ! 11: * minor device. Netbios access is through novell minor device + 16. ! 12: */ ! 13: ! 14: #include <sys/coherent.h> ! 15: #include <sys/con.h> ! 16: #include <sys/devices.h> ! 17: #include <sys/sched.h> ! 18: #include <sys/seg.h> ! 19: #include <sys/stat.h> ! 20: #include <sys/uproc.h> ! 21: #include <sys/tnioctl.h> ! 22: #include <errno.h> ! 23: ! 24: /* ! 25: * External functions. ! 26: */ ! 27: extern int wakeup(); ! 28: extern void pollwake(); ! 29: extern void defer(); ! 30: ! 31: /* ! 32: * Driver functions. ! 33: */ ! 34: void tnopen(); ! 35: void tnclose(); ! 36: int tnread(); ! 37: int tnwrite(); ! 38: int tnioctl(); ! 39: void tncycle(); ! 40: void tnload(); ! 41: void tnuload(); ! 42: int tnpoll(); ! 43: int nonedev(); ! 44: int nulldev(); ! 45: void tn0intr(); ! 46: void tn1intr(); ! 47: void tn2intr(); ! 48: void tn3intr(); ! 49: void tnintr(); ! 50: ! 51: /* ! 52: * Driver Configuration. ! 53: */ ! 54: CON ! 55: tncon = { ! 56: DFCHR|DFPOL, /* Flags */ ! 57: TN_MAJOR, /* Major Index */ ! 58: tnopen, /* Open */ ! 59: tnclose, /* Close */ ! 60: nonedev, /* Block */ ! 61: tnread, /* Read */ ! 62: tnwrite, /* Write */ ! 63: tnioctl, /* Ioctl */ ! 64: nulldev, /* Power fail */ ! 65: tncycle, /* Timeout */ ! 66: tnload, /* Load */ ! 67: tnuload, /* Unload */ ! 68: tnpoll /* Poll */ ! 69: }; ! 70: ! 71: /* ! 72: * Interrupt Entry Points. ! 73: */ ! 74: void (*tnintf[4])() = { ! 75: tn0intr, ! 76: tn1intr, ! 77: tn2intr, ! 78: tn3intr ! 79: }; ! 80: ! 81: #define BIT(n) (1 << (n)) ! 82: ! 83: /* ! 84: * Bitmask, indexed by bit numbers 0..7. ! 85: */ ! 86: static unsigned char bitm[8] = { BIT(0), BIT(1), BIT(2), BIT(3), ! 87: BIT(4), BIT(5), BIT(6), BIT(7) }; ! 88: ! 89: /* ! 90: * Patchable parameters - Cards 0-3. ! 91: */ ! 92: /* Card 0 1 2 3 */ ! 93: int TNIRQ [4] = { 2, 7, 4, 0 }; ! 94: saddr_t TNSEL [4] = { 0xD000, 0x0000, 0x0000, 0x0000 }; ! 95: int TNPORT[4] = { 0x2E0, 0x220, 0x240, 0x000 }; ! 96: ! 97: /* ! 98: * Patchable parameters - Prefix Byte. ! 99: * Indexed by high nibble of minor device. ! 100: */ ! 101: int TNPREFIX[4] = { 0x00, 0xF3, 0x00, 0x00 }; ! 102: ! 103: /* ! 104: * Patchable variables. ! 105: * TNTIME = Transmit watchdog timer in seconds. ! 106: */ ! 107: int TNTIME = 5; ! 108: ! 109: /* ! 110: * Register addresses. ! 111: */ ! 112: #define NIR (tp->tnport) /* Network Interrupt Mask Reg (w) */ ! 113: #define NSR (tp->tnport) /* Network Status Register (r) */ ! 114: #define NCR (tp->tnport+1) /* Network Command Register (w) */ ! 115: #define NZR (tp->tnport+8) /* Network Zap (reset) Reg (w) */ ! 116: ! 117: /* ! 118: * Network Interrupt Register (NIR). ! 119: */ ! 120: #define NI_Tx BIT(0) /* Enable Transmitter Avail Intr */ ! 121: #define NI_RECON BIT(2) /* Enable Reconfiguration Intr */ ! 122: #define NI_Rx BIT(7) /* Enable Receiver Full Intr */ ! 123: ! 124: /* ! 125: * Network Status Register (NSR). ! 126: */ ! 127: #define NS_TxRDY BIT(0) /* Transmitter Available */ ! 128: #define NS_TxACK BIT(1) /* Transmit Message Acknowledged */ ! 129: #define NS_RECON BIT(2) /* Network Reconfiguration */ ! 130: #define NS_TEST BIT(3) /* Test */ ! 131: #define NS_POR BIT(4) /* Power on Reset */ ! 132: #define NS_ETS1 BIT(5) /* Extended Timeout Status 1 */ ! 133: #define NS_ETS2 BIT(6) /* Extended Timeout Status 2 */ ! 134: #define NS_RxRDY BIT(7) /* Packet Received - Receiver Off */ ! 135: ! 136: /* ! 137: * Network Command Register (NCR). ! 138: */ ! 139: #define NC_TxDIS (((0)<<3) + 1) /* Disable Transmitter */ ! 140: #define NC_RxDIS (((0)<<3) + 2) /* Disable Receiver */ ! 141: #define NC_TxENA(n) (((n)<<3) + 3) /* Enable Transmitter on Page n */ ! 142: #define NC_RxENA(n) (((n)<<3)+0x84) /* Enable Receiver on Page n */ ! 143: #define NC_DFC (((1)<<3) + 5) /* Define Configuration (2k buf) */ ! 144: #define NC_POR (((1)<<3) + 6) /* Clear NS_POR flag */ ! 145: #define NC_RECON (((2)<<3) + 6) /* Clear NS_RECON flag */ ! 146: ! 147: /* ! 148: * Packet Control. ! 149: */ ! 150: struct tnet_s { ! 151: ! 152: /* ! 153: * Four buffers per card - 2 receive, 2 transmit. ! 154: */ ! 155: struct tnbuf_s { /* tnget*,tnput* use tn_sel:tn_off */ ! 156: unsigned tn_off; /* tn_sel:tn_off = current byte */ ! 157: saddr_t tn_sel; /* network buffer selector */ ! 158: struct tnbuf_s *tn_next;/* pointer to next pkt in queue */ ! 159: unsigned tn_ena; /* Command to enable packet */ ! 160: unsigned tn_base;/* tn_sel:tn_base = pkt address */ ! 161: unsigned tn_xnid;/* Transmit node id */ ! 162: unsigned tn_xlen;/* Transmit length */ ! 163: } tnbuf [4]; ! 164: ! 165: struct tnbuf_s * RxBusy[4];/* Queues of full receive packets*/ ! 166: struct tnbuf_s * RxIdle; /* Queue of empty receive packets */ ! 167: ! 168: struct tnbuf_s * TxBusy; /* Queue of full transmit packets */ ! 169: struct tnbuf_s * TxIdle; /* Queue of empty transmit packets */ ! 170: ! 171: event_t RxPoll[4];/* Polls for input packets */ ! 172: event_t TxPoll; /* Polls for empty output packets */ ! 173: ! 174: char RxReq[4];/* 1 = Proc waiting for recv buf */ ! 175: char TxReq; /* 1 = Proc waiting for xmit buf */ ! 176: char refc[4];/* # opens, indexed by prefix code */ ! 177: ! 178: unsigned tnmask; /* Interrupt enable mask */ ! 179: unsigned tnport; /* Base I/O port */ ! 180: char tnaddr[8];/* ARC-NET Node ID, low byte 1st */ ! 181: ! 182: unsigned tntime; /* transmit watchdog timer */ ! 183: unsigned recon; /* number of long reconfigurations */ ! 184: unsigned pri; /* priority event occurred */ ! 185: long rbolt; /* lbolt at last reconfiguration */ ! 186: unsigned char bad[32];/* bit mask of bad nodes */ ! 187: unsigned char mod[32];/* bit mask of changed nodes */ ! 188: long recons; /* reconfiguration statistic */ ! 189: SEG * statseg;/* Segment containing stats */ ! 190: ! 191: } tnet [4]; ! 192: ! 193: /* ! 194: * Load Routine. ! 195: */ ! 196: void ! 197: tnload() ! 198: { ! 199: register struct tnet_s * tp; ! 200: register struct tnbuf_s * np; ! 201: faddr_t faddr; ! 202: paddr_t paddr; ! 203: int i; ! 204: int nid; ! 205: long delay; ! 206: ! 207: for ( tp = &tnet[0], i = 0; i < 4; i++, tp++ ) { ! 208: ! 209: /* ! 210: * Validate patchable parameters. ! 211: */ ! 212: if ( (TNSEL[i] == 0) || (TNPORT[i] == 0) || (TNIRQ[i] == 0) ) { ! 213: TNPORT[i] = 0; ! 214: TNSEL[i] = 0; ! 215: TNIRQ[i] = 0; ! 216: continue; ! 217: } ! 218: ! 219: tp->tnport = TNPORT[i]; ! 220: ! 221: /* ! 222: * Clear Power-On-Reset Flag. ! 223: */ ! 224: outb( NCR, NC_POR ); ! 225: ! 226: /* ! 227: * Validate card presence. ! 228: * NOTE: tp->tnport must be programmed before using NIR macro. ! 229: */ ! 230: if ( inb(NSR) & (NS_TEST|NS_POR) ) { ! 231: tp->tnport = 0; ! 232: continue; ! 233: } ! 234: ! 235: /* ! 236: * Convert physical address into virtual address. ! 237: */ ! 238: paddr = TNSEL[i] << 4L; ! 239: faddr = ptov( paddr, (fsize_t) 2048 ); ! 240: ! 241: /* ! 242: * Verify dual-port memory existence. ! 243: * NOTE: Do not overwrite first two bytes [0xD1,nid]. ! 244: */ ! 245: sfword( faddr+8, 0x1234 ); ! 246: if ( ffword( faddr+8 ) != 0x1234 ) { ! 247: vrelse( faddr ); ! 248: tp->tnport = 0; ! 249: continue; ! 250: } ! 251: ! 252: /* ! 253: * Allocate statistics segment. ! 254: */ ! 255: tp->statseg = salloc( (fsize_t) (256*NTNST*4), SFSYST|SFHIGH ); ! 256: ! 257: /* ! 258: * Out of memory. ! 259: */ ! 260: if ( ! tp->statseg ) { ! 261: printf( "tn%d: out of memory\n", i ); ! 262: vrelse( faddr ); ! 263: tp->tnport = 0; ! 264: continue; ! 265: } ! 266: ! 267: tp->tnbuf[0].tn_sel = ! 268: tp->tnbuf[1].tn_sel = ! 269: tp->tnbuf[2].tn_sel = ! 270: tp->tnbuf[3].tn_sel = FP_SEL(faddr); ! 271: ! 272: tp->tnbuf[0].tn_ena = NC_TxENA(0); ! 273: tp->tnbuf[1].tn_ena = NC_TxENA(1); ! 274: tp->tnbuf[2].tn_ena = NC_RxENA(2); ! 275: tp->tnbuf[3].tn_ena = NC_RxENA(3); ! 276: ! 277: tp->tnbuf[0].tn_base = 0 * 512; ! 278: tp->tnbuf[1].tn_base = 1 * 512; ! 279: tp->tnbuf[2].tn_base = 2 * 512; ! 280: tp->tnbuf[3].tn_base = 3 * 512; ! 281: ! 282: /* ! 283: * Initialize transmit idle queue. ! 284: */ ! 285: tp->TxIdle = &tp->tnbuf[0]; ! 286: tp->tnbuf[0].tn_next = &tp->tnbuf[1]; ! 287: ! 288: /* ! 289: * Initialize receive idle queue. ! 290: */ ! 291: tp->RxIdle = &tp->tnbuf[2]; ! 292: tp->tnbuf[2].tn_next = &tp->tnbuf[3]; ! 293: ! 294: /* ! 295: * Validate Node Id. ! 296: */ ! 297: np = &tp->tnbuf[0]; ! 298: np->tn_off = 0; ! 299: if ( tngetc(np) != 0xD1 ) { ! 300: ! 301: /* ! 302: * Initiate Power On Reset. ! 303: */ ! 304: outb( NZR, 1 ); ! 305: ! 306: /* ! 307: * Wait minimimum of 180 [suggest 250] milli-seconds. ! 308: * Should function properly up to at least 16 Mhz clock. ! 309: */ ! 310: for ( delay = 250000L; --delay != 0; ) ! 311: ; ! 312: } ! 313: ! 314: /* ! 315: * Validate and Remember Node Id. ! 316: */ ! 317: np->tn_off = 0; ! 318: if ( tngetc(np) == 0xD1 ) ! 319: tp->tnaddr[0] = tngetc( np ); ! 320: ! 321: /* ! 322: * Record starting time of statistics collection. ! 323: */ ! 324: faddr = tp->statseg->s_faddr + TnELAPSED*4; ! 325: for ( nid = 0; nid < 256; nid++, faddr += NTNST*4 ) ! 326: kfcopy( &lbolt, faddr, sizeof(lbolt) ); ! 327: ! 328: memset( tp->bad, -1, 32 ); /* Assume LAN is down */ ! 329: memset( tp->mod, 0, 32 ); /* Assume no node changes */ ! 330: tp->tnmask = NI_Rx | NI_RECON; /* Interrupts to enable */ ! 331: outb( NIR, 0 ); /* Disable Interrupts */ ! 332: outb( NCR, NC_POR ); /* Clear POR Flag */ ! 333: outb( NCR, NC_DFC ); /* Define 2K buf config */ ! 334: outb( NCR, NC_TxDIS ); /* Disable Transmitter */ ! 335: outb( NCR, tp->RxIdle->tn_ena); /* Enable receiver */ ! 336: setivec( TNIRQ[i], tnintf[i] ); /* Seize Interrupt Vector */ ! 337: outb( NIR, tp->tnmask ); /* Enable Interrupts */ ! 338: } ! 339: ! 340: /* ! 341: * Enable watchdog timer ! 342: */ ! 343: drvl[TN_MAJOR].d_time = 1; ! 344: } ! 345: ! 346: /* ! 347: * Unload Routine. ! 348: */ ! 349: void ! 350: tnuload( dev ) ! 351: dev_t dev; ! 352: { ! 353: register struct tnet_s * tp; ! 354: register int i; ! 355: faddr_t faddr; ! 356: ! 357: /* ! 358: * Disable watchdog timer. ! 359: */ ! 360: drvl[TN_MAJOR].d_time = 0; ! 361: ! 362: /* ! 363: * Scan network adaptors. ! 364: */ ! 365: for ( tp = &tnet[0], i = 0; i < 4; i++, tp++ ) { ! 366: ! 367: if ( tp->tnport == 0 ) ! 368: continue; ! 369: ! 370: /* ! 371: * Disable Interrupts ! 372: */ ! 373: outb( NIR, 0 ); ! 374: ! 375: /* ! 376: * Release interrupt vector. ! 377: */ ! 378: clrivec( TNIRQ[i] ); ! 379: ! 380: /* ! 381: * Release virtual address AFTER disabling interrupts. ! 382: */ ! 383: if ( FP_SEL(faddr) = tp->tnbuf[0].tn_sel ) ! 384: vrelse( faddr ); ! 385: ! 386: /* ! 387: * Release stats segment. ! 388: */ ! 389: if ( tp->statseg != NULL ) ! 390: sfree( tp->statseg ); ! 391: } ! 392: } ! 393: ! 394: /* ! 395: * Open Routine. ! 396: * ! 397: * Low nibble of minor device is card identifier 0 to 3. ! 398: * High nibble of minor device is code identifier 0 to 3. ! 399: */ ! 400: void ! 401: tnopen( dev, mode ) ! 402: dev_t dev; ! 403: { ! 404: register struct tnet_s * tp; ! 405: int card = (dev & 0x0F); ! 406: int code = (dev & 0xF0) >> 4; ! 407: ! 408: /* ! 409: * Validate minor device and card existence. ! 410: */ ! 411: if ( (card > 3) || (code > 3) || (tnet[card].tnport == 0)) { ! 412: u.u_error = ENXIO; ! 413: return; ! 414: } ! 415: ! 416: /* ! 417: * Code identifiers 1 to 3 are only valid if a prefix code is known. ! 418: */ ! 419: if ( (code > 0) && (TNPREFIX[code] == 0) ) { ! 420: u.u_error = ENXIO; ! 421: return; ! 422: } ! 423: ! 424: /* ! 425: * Access network information. ! 426: */ ! 427: tp = &tnet[card]; ! 428: ! 429: /* ! 430: * Increment reference count (# opens). ! 431: */ ! 432: tp->refc[code]++; ! 433: } ! 434: ! 435: /* ! 436: * Close Routine. ! 437: */ ! 438: void ! 439: tnclose( dev ) ! 440: dev_t dev; ! 441: { ! 442: register struct tnet_s * tp =tp = &tnet[ dev & 3]; ! 443: register struct tnbuf_s * np; ! 444: int code = (dev & 0x30) >> 4; ! 445: int s; ! 446: ! 447: /* ! 448: * Decrement reference count. ! 449: */ ! 450: if ( --tp->refc[code] != 0 ) ! 451: return; ! 452: ! 453: /* ! 454: * Last close. ! 455: * Release all queued packets. ! 456: */ ! 457: while ( np = tp->RxBusy[code] ) { ! 458: s = sphi( ); ! 459: tp->RxBusy[code] = np->tn_next; ! 460: tn_rxena( tp, np ); ! 461: spl( s ); ! 462: } ! 463: } ! 464: ! 465: /* ! 466: * Watchdog Timing Routine ! 467: * ! 468: * If transmit has been enabled for 1-2 seconds: ! 469: * Abort transmission of packet, forcing interrupt. ! 470: */ ! 471: void ! 472: tncycle( ) ! 473: { ! 474: register struct tnet_s * tp; ! 475: register int code; ! 476: int s; ! 477: ! 478: /* ! 479: * Scan all network cards. ! 480: */ ! 481: for ( tp = &tnet[0]; tp <= &tnet[3]; tp++ ) { ! 482: ! 483: if ( ! tp->tnport ) ! 484: continue; ! 485: ! 486: /* ! 487: * Disable interrupts. ! 488: */ ! 489: s = sphi(); ! 490: ! 491: /* ! 492: * Enable broadcasts after 5 seconds without reconfiguration. ! 493: */ ! 494: if ( (tp->recon > 0) && ((lbolt - tp->rbolt) > (5*HZ)) ) { ! 495: /* ! 496: * LAN was previously down. ! 497: */ ! 498: if ( tp->bad[0] & 1 ) { ! 499: faddr_t fp = tp->statseg->s_faddr; ! 500: aflong( fp+TnSTATMOD*4, 1 ); ! 501: tp->mod[0] |= 1; ! 502: tp->pri = 1; ! 503: } ! 504: tp->bad[0] &= ~1; ! 505: tp->recon = 0; ! 506: } ! 507: ! 508: /* ! 509: * Discard bad packet on transmit watchdog timeout. ! 510: */ ! 511: if ( (tp->tntime > 0) && (--(tp->tntime) == 0) ) ! 512: outb( NCR, NC_TxDIS ); ! 513: ! 514: /* ! 515: * Enable interrupts. ! 516: */ ! 517: spl( s ); ! 518: ! 519: /* ! 520: * LAN/DEVICE UP/DOWN event has occurred. ! 521: */ ! 522: if ( tp->pri == 1 ) { ! 523: ! 524: tp->pri = 2; ! 525: ! 526: for ( code = 0; code < 4; code++ ) ! 527: if ( tp->RxPoll[code].e_procp ) ! 528: pollwake( &tp->RxPoll[code] ); ! 529: } ! 530: } ! 531: } ! 532: ! 533: static ! 534: tnioctl( dev, com, arg ) ! 535: dev_t dev; ! 536: int com; ! 537: register tnattr_t * arg; ! 538: { ! 539: register struct tnet_s * tp = &tnet[dev & 3]; ! 540: faddr_t fp; ! 541: int nid; ! 542: long t; ! 543: tnattr_t local; /* to avoid fucopy() problems */ ! 544: ! 545: switch ( com ) { ! 546: ! 547: case TNGETA: ! 548: case TNGETAF: ! 549: /* ! 550: * Access node statistics. ! 551: */ ! 552: nid = getubd( &arg->host[5] ); ! 553: fp = tp->statseg->s_faddr + nid * (NTNST*4); ! 554: ! 555: /* ! 556: * Disable interrupts to avoid race condition with tnintr(). ! 557: */ ! 558: sphi(); ! 559: ! 560: /* ! 561: * Copy node status. ! 562: */ ! 563: if ( tp->bad[nid/8] & bitm[nid%8] ) ! 564: putubd( &arg->bad, 1 ); ! 565: else ! 566: putubd( &arg->bad, 0 ); ! 567: ! 568: /* ! 569: * Copy network reconfigurations to user space. ! 570: * NOTE: This is not a node statistic, but a network stat. ! 571: */ ! 572: kucopy( &tp->recons, &arg->recons, sizeof(tp->recons) ); ! 573: ! 574: /* ! 575: * Copy node statistics to user space. ! 576: */ ! 577: fkcopy( fp, &local.stats[0], sizeof(local.stats) ); ! 578: kucopy( &local.stats[0], &arg->stats[0], sizeof(arg->stats) ); ! 579: ! 580: /* ! 581: * Copy true elapsed time of statistics collection. ! 582: */ ! 583: fkcopy( fp+TnELAPSED*4, &t, sizeof(t) ); ! 584: t = lbolt - t; ! 585: kucopy( &t, &arg->stats[TnELAPSED], sizeof(arg->stats[0]) ); ! 586: ! 587: /* ! 588: * Clear node statistics. ! 589: * NOTE: Elapsed time statistic is time of last clear. ! 590: */ ! 591: if ( com == TNGETAF ) { ! 592: fclear( fp, NTNST * 4 ); ! 593: kfcopy( &lbolt, fp+TnELAPSED*4, sizeof(lbolt) ); ! 594: if ( nid == 0 ) ! 595: tp->recons = 0; ! 596: } ! 597: ! 598: /* ! 599: * Enable interrupts. ! 600: */ ! 601: splo(); ! 602: ! 603: return( 0 ); ! 604: ! 605: default: ! 606: u.u_error = EINVAL; ! 607: } ! 608: } ! 609: ! 610: /* ! 611: * Polling Routine. ! 612: * ! 613: * Note: Double-looks are performed to prevent critical race with ! 614: * interrupt handlers, without having to disable interrupts. ! 615: */ ! 616: static ! 617: tnpoll( dev, ev, msec ) ! 618: dev_t dev; ! 619: int ev; ! 620: int msec; ! 621: { ! 622: register struct tnet_s * tp = &tnet[dev & 3]; ! 623: int code = (dev & 0x30) >> 4; ! 624: int rev = 0; ! 625: ! 626: /* ! 627: * Fast check for priority, input, and output polls. ! 628: * Priority poll checks for LAN UP/DOWN transition. ! 629: * Input poll checks for a full receive buffer. ! 630: * Output poll checks for an empty transmit buffer, or LAN down. ! 631: */ ! 632: if ( (ev & POLLPRI) && (tp->pri != 0) ) ! 633: rev |= POLLPRI; ! 634: if ( (ev & POLLIN) && (tp->RxBusy[code] != NULL) ) ! 635: rev |= POLLIN; ! 636: if ( (ev & POLLOUT) && ((tp->TxIdle != 0) || (tp->bad[0] & 1)) ) ! 637: rev |= POLLOUT; ! 638: ! 639: /* ! 640: * Fast check found an event, or this is a non-blocking poll. ! 641: */ ! 642: if ( (rev != 0) || (msec == 0) ) ! 643: return( rev ); ! 644: ! 645: /* ! 646: * Blocking Input poll. ! 647: */ ! 648: if ( ev & POLLIN ) { ! 649: ! 650: pollopen( &tp->RxPoll[code] ); ! 651: ! 652: /* ! 653: * Second look to avoid interrupt race. ! 654: */ ! 655: if ( tp->RxBusy[code] ) ! 656: return( POLLIN ); ! 657: } ! 658: ! 659: /* ! 660: * Blocking Output poll. ! 661: */ ! 662: if ( ev & POLLOUT ) { ! 663: ! 664: pollopen( &tp->TxPoll ); ! 665: ! 666: /* ! 667: * Second look to avoid interrupt race. ! 668: * NOTE: When the LAN is down broadcasts [nid 0] are disabled. ! 669: */ ! 670: if ( (tp->TxIdle != 0) || (tp->bad[0] & 1) ) ! 671: return( POLLOUT ); ! 672: } ! 673: ! 674: return( rev ); ! 675: } ! 676: ! 677: /* ! 678: * Interrupt Entry Point - Card 0. ! 679: */ ! 680: void ! 681: tn0intr() ! 682: { ! 683: tnintr( &tnet[0] ); ! 684: } ! 685: ! 686: /* ! 687: * Interrupt Entry Point - Card 1. ! 688: */ ! 689: void ! 690: tn1intr() ! 691: { ! 692: tnintr( &tnet[1] ); ! 693: } ! 694: ! 695: /* ! 696: * Interrupt Entry Point - Card 2. ! 697: */ ! 698: void ! 699: tn2intr() ! 700: { ! 701: tnintr( &tnet[2] ); ! 702: } ! 703: ! 704: /* ! 705: * Interrupt Entry Point - Card 3. ! 706: */ ! 707: void ! 708: tn3intr() ! 709: { ! 710: tnintr( &tnet[3] ); ! 711: } ! 712: ! 713: /* ! 714: * Interrupt Handler. ! 715: * ! 716: * Process transmit/receive interrupts. ! 717: */ ! 718: void ! 719: tnintr( tp ) ! 720: register struct tnet_s * tp; ! 721: { ! 722: register struct tnbuf_s * np; ! 723: register int csr; ! 724: int nid; ! 725: int n; ! 726: int bit; ! 727: ! 728: /* ! 729: * Read interrupt status. ! 730: * Disable interrupts to ensure edge occurs later. ! 731: */ ! 732: csr = inb( NSR ); ! 733: tp->tnmask = NI_RECON; ! 734: outb( NIR, 0 ); ! 735: ! 736: /* ! 737: * Reconfigurations with a period of 840 msec [600-1100] ! 738: * increment tp->recon. Other periods clear tp->recon. ! 739: * After 5 reconfigurations at 840 msecs, the network is down. ! 740: * After 1 reconfiguration at another interval, the network is up. ! 741: * Network also comes up in tncycle() 5 seconds after last reconfig. ! 742: */ ! 743: if ( csr & NS_RECON ) { ! 744: ! 745: outb( NCR, NC_RECON ); ! 746: nid = (unsigned) (lbolt - tp->rbolt) * (1000/HZ); ! 747: tp->rbolt = lbolt; ! 748: tp->recons++; ! 749: ! 750: /* ! 751: * Not a chained reconfiguration. ! 752: * Assume the network is up. ! 753: * NOTE: Expect 840 msecs, but allow interrupt latency slip. ! 754: */ ! 755: if ( (nid < 700) || (nid > 1000) ) { ! 756: if ( tp->bad[0] & 1 ) { ! 757: tp->mod[0] |= 1; ! 758: tp->bad[0] &= ~1; ! 759: tp->pri = 1; ! 760: } ! 761: tp->recon = 0; ! 762: } ! 763: ! 764: /* ! 765: * Chained reconfiguration - threshold exceeded. ! 766: */ ! 767: else if ( (++(tp->recon) == 5) && ((tp->bad[0] & 1) == 0) ) { ! 768: faddr_t fp = tp->statseg->s_faddr; ! 769: aflong( fp+TnSTATMOD*4, 1 ); ! 770: memset( tp->bad, -1, sizeof(tp->bad) ); ! 771: tp->mod[0] |= 1; ! 772: tp->pri = 1; ! 773: } ! 774: } ! 775: ! 776: /* ! 777: * Service Power on Resets. ! 778: */ ! 779: if ( csr & NS_POR ) { ! 780: ! 781: csr &= ~(NS_RxRDY|NS_TxRDY); /* Ignore receive/transmit */ ! 782: outb( NCR, NC_DFC ); /* Define 2K buf config */ ! 783: outb( NCR, NC_POR ); /* Clear POR flag */ ! 784: ! 785: /* ! 786: * Enable receiver ! 787: */ ! 788: if ( np = tp->RxIdle ) ! 789: outb( NCR, np->tn_ena ); ! 790: ! 791: /* ! 792: * Enable transmitter ! 793: */ ! 794: if ( np = tp->TxBusy ) ! 795: outb( NCR, np->tn_ena ); ! 796: } ! 797: ! 798: /* ! 799: * Service transmit interupts if transmit is pending. ! 800: */ ! 801: if ( np = tp->TxBusy ) { ! 802: ! 803: tp->tnmask |= NI_Tx; ! 804: ! 805: /* ! 806: * Check for transmission completed. ! 807: */ ! 808: if ( csr & NS_TxRDY ) { ! 809: ! 810: /* ! 811: * Destination Node Id is in 2nd byte of packet. ! 812: */ ! 813: np->tn_off = np->tn_base + 1; ! 814: nid = tngetc( np ); ! 815: ! 816: /* ! 817: * Get length of short/long packets. ! 818: */ ! 819: n = 256 - tngetc(np); ! 820: if ( n == 256 ) ! 821: n = 512 - tngetc(np); ! 822: ! 823: /* ! 824: * Transmitted packet was acknowledged. ! 825: */ ! 826: if ( csr & NS_TxACK ) { ! 827: /* ! 828: * Adjust global and node statistics. ! 829: */ ! 830: faddr_t fp = tp->statseg->s_faddr; ! 831: aflong( fp+TnTxPACKS*4, 1 ); ! 832: aflong( fp+TnTxBYTES*4, n ); ! 833: fp += nid * (NTNST * 4); ! 834: aflong( fp+TnTxPACKS*4, 1 ); ! 835: aflong( fp+TnTxBYTES*4, n ); ! 836: } ! 837: ! 838: /* ! 839: * Transmitted packet was discarded. ! 840: * NOTE: Do not flag broadcast [nid 0] as bad. ! 841: */ ! 842: else if ( nid != 0 ) { ! 843: /* ! 844: * Adjust global and node statistics. ! 845: */ ! 846: faddr_t fp = tp->statseg->s_faddr; ! 847: aflong( fp+TnDISCARD*4, 1 ); ! 848: fp += nid * (NTNST * 4); ! 849: aflong( fp+TnDISCARD*4, 1 ); ! 850: aflong( fp+TnSTATMOD*4, 1 ); ! 851: ! 852: /* ! 853: * Flag node as being bad. ! 854: */ ! 855: bit = bitm[ nid % 8 ]; ! 856: tp->bad[ nid / 8 ] |= bit; ! 857: tp->mod[ nid / 8 ] |= bit; ! 858: tp->pri = 1; ! 859: } ! 860: ! 861: /* ! 862: * Move packet buffer to idle transmit queue. ! 863: */ ! 864: tp->TxBusy = np->tn_next; ! 865: np->tn_next = tp->TxIdle; ! 866: tp->TxIdle = np; ! 867: ! 868: /* ! 869: * Check for another packet to transmit. ! 870: */ ! 871: if ( np = tp->TxBusy ) { ! 872: ! 873: /* ! 874: * Enable transmitter, start watchdog timer. ! 875: */ ! 876: outb( NCR, np->tn_ena ); ! 877: tp->tntime = TNTIME; ! 878: } ! 879: ! 880: /* ! 881: * Disable Transmit Interrupt, clear watchdog timer. ! 882: */ ! 883: else { ! 884: tp->tnmask &= ~NI_Tx; ! 885: tp->tntime = 0; ! 886: } ! 887: ! 888: /* ! 889: * Wake processes waiting to transmit. ! 890: */ ! 891: if ( tp->TxReq ) { ! 892: tp->TxReq = 0; ! 893: defer( wakeup, &tp->TxReq ); ! 894: } ! 895: ! 896: if ( tp->TxPoll.e_procp ) ! 897: defer( pollwake, &tp->TxPoll ); ! 898: } ! 899: } ! 900: ! 901: /* ! 902: * Check for receive request. ! 903: */ ! 904: if ( np = tp->RxIdle ) { ! 905: ! 906: tp->tnmask |= NI_Rx; ! 907: ! 908: /* ! 909: * Check for packet received. ! 910: */ ! 911: if ( csr & NS_RxRDY ) { ! 912: ! 913: /* ! 914: * Remove first packet from receive ready queue. ! 915: * Re-enable receiver or disable receive interrupts. ! 916: */ ! 917: if ( tp->RxIdle = np->tn_next ) { ! 918: outb( NCR, np->tn_next->tn_ena ); ! 919: np->tn_next = 0; ! 920: } ! 921: else ! 922: tp->tnmask &= ~NI_Rx; ! 923: ! 924: /* ! 925: * Source Node Id is in 1st byte of packet. ! 926: */ ! 927: np->tn_off = np->tn_base; ! 928: nid = tngetc( np ); ! 929: ! 930: /* ! 931: * Try to establish our Node Id if not already set. ! 932: * Destination Node Id (our station) ! 933: * is in 2nd byte of the received packet. ! 934: * NOTE: Always read node id byte. ! 935: * This ensures offset bytes can be read. ! 936: */ ! 937: if ( (n = tngetc(np)) && (tp->tnaddr[0] == 0) ) ! 938: tp->tnaddr[0] = n; ! 939: ! 940: /* ! 941: * Get offset to first data byte in short/long packet. ! 942: * Short packet offset is in 3rd byte of packet. ! 943: * Long packet offset is in 4th byte of packet. ! 944: */ ! 945: if ( n = tngetc(np) ) ! 946: np->tn_off = np->tn_base + n; ! 947: else ! 948: np->tn_off = np->tn_base + tngetc(np); ! 949: ! 950: /* ! 951: * LAN has come up. ! 952: * Clear bad flag for the broadcast node. ! 953: */ ! 954: if ( tp->bad[0] & 1 ) { ! 955: tp->bad[ 0 ] &= ~1; ! 956: tp->mod[ 0 ] |= 1; ! 957: tp->pri = 1; ! 958: } ! 959: ! 960: /* ! 961: * Node has come up. ! 962: * Clear bad flag for the Source Node. ! 963: */ ! 964: bit = bitm[ nid % 8 ]; ! 965: if ( tp->bad[ nid / 8 ] & bit ) { ! 966: faddr_t fp = tp->statseg->s_faddr; ! 967: aflong( fp+TnSTATMOD*4, 1 ); ! 968: fp += nid * (NTNST * 4); ! 969: aflong( fp+TnSTATMOD*4, 1 ); ! 970: tp->bad[ nid / 8 ] &= ~bit; ! 971: tp->mod[ nid / 8 ] |= bit; ! 972: tp->pri = 1; ! 973: } ! 974: ! 975: /* ! 976: * Get first data byte from packet. ! 977: */ ! 978: bit = tngetc( np ); ! 979: ! 980: /* ! 981: * Determine prefix code associated with packet. ! 982: */ ! 983: for ( n = 3; n > 0; n-- ) { ! 984: if ( TNPREFIX[n] == bit ) ! 985: break; ! 986: } ! 987: ! 988: /* ! 989: * Interface is open. ! 990: */ ! 991: if ( tp->refc[n] ) { ! 992: ! 993: /* ! 994: * Append received packet to received queue. ! 995: * NOTE: At most 2 packets in any queue. ! 996: */ ! 997: if ( tp->RxBusy[n] ) ! 998: tp->RxBusy[n]->tn_next = np; ! 999: else ! 1000: tp->RxBusy[n] = np; ! 1001: ! 1002: /* ! 1003: * Wake processes waiting to read. ! 1004: */ ! 1005: if ( tp->RxReq[n] ) { ! 1006: tp->RxReq[n] = 0; ! 1007: defer( wakeup, &tp->RxReq[n] ); ! 1008: } ! 1009: ! 1010: if ( tp->RxPoll[n].e_procp ) ! 1011: defer( pollwake, &tp->RxPoll[n] ); ! 1012: } ! 1013: ! 1014: /* ! 1015: * Interface is closed. ! 1016: * Return packet to end of receive idle queue. ! 1017: */ ! 1018: else ! 1019: tn_rxena( tp, np ); ! 1020: } ! 1021: } ! 1022: ! 1023: /* ! 1024: * Restore interrupt mask. ! 1025: */ ! 1026: outb( NIR, tp->tnmask ); ! 1027: } ! 1028: ! 1029: /* ! 1030: * Read Routine. ! 1031: * ! 1032: * Wait for a packet to be received. ! 1033: * Transform packet header and copy packet body. ! 1034: * Place packet buffer on receive idle queue. ! 1035: * If receiver was inhibited, enable receiver. ! 1036: */ ! 1037: ! 1038: ! 1039: tnread ( dev, iop ) ! 1040: ! 1041: dev_t dev; ! 1042: register IO * iop; ! 1043: ! 1044: { ! 1045: register struct tnet_s * tp = &tnet[ dev & 3 ]; ! 1046: register struct tnbuf_s * np; ! 1047: int code = (dev & 0x30) >> 4; ! 1048: unsigned len; ! 1049: unsigned cnt; ! 1050: unsigned srcid; ! 1051: int s; ! 1052: ! 1053: /* ! 1054: * Driver information requested. ! 1055: */ ! 1056: if ( iop->io_ioc <= 2 + sizeof(tp->bad) + sizeof(tp->mod) ) { ! 1057: ! 1058: /* ! 1059: * Supply null byte, then our node id. ! 1060: */ ! 1061: ioputc( 0, iop ); ! 1062: ioputc( tp->tnaddr[0], iop ); ! 1063: ! 1064: /* ! 1065: * Bad and modified node bit masks requested. ! 1066: * Disable interrupts during transfer to prevent ! 1067: * critical race with tnintr(). ! 1068: */ ! 1069: if ( iop->io_ioc == sizeof(tp->bad) + sizeof(tp->mod) ) { ! 1070: sphi(); ! 1071: iowrite( iop, tp->bad, sizeof(tp->bad) ); ! 1072: iowrite( iop, tp->mod, sizeof(tp->mod) ); ! 1073: kclear( tp->mod, sizeof(tp->mod) ); ! 1074: tp->pri = 0; ! 1075: splo(); ! 1076: } ! 1077: ! 1078: /* ! 1079: * Bad node bit mask requested. ! 1080: */ ! 1081: else if ( iop->io_ioc == sizeof(tp->bad) ) ! 1082: iowrite( iop, tp->bad, sizeof(tp->bad) ); ! 1083: ! 1084: return; ! 1085: } ! 1086: ! 1087: /* ! 1088: * Wait for packet reception. ! 1089: */ ! 1090: for ( ; ; ) { ! 1091: ! 1092: s = sphi( ); ! 1093: ! 1094: /* ! 1095: * Check for received packet. ! 1096: */ ! 1097: if ( np = tp->RxBusy[code] ) { ! 1098: tp->RxBusy[code] = np->tn_next; ! 1099: np->tn_next = 0; ! 1100: spl( s ); ! 1101: break; ! 1102: } ! 1103: ! 1104: /* ! 1105: * Non-blocking reads. ! 1106: */ ! 1107: if ( iop->io_flag & IONDLY ) { ! 1108: u.u_error = EAGAIN; ! 1109: spl( s ); ! 1110: return; ! 1111: } ! 1112: ! 1113: tp->RxReq[code] = 1; ! 1114: ! 1115: sleep( &tp->RxReq[code], CVTTIN, IVTTIN, SVTTIN ); ! 1116: spl( s ); ! 1117: ! 1118: /* ! 1119: * Check for pending signal. ! 1120: */ ! 1121: if ( nondsig() ) { ! 1122: u.u_error = EINTR; ! 1123: return; ! 1124: } ! 1125: } ! 1126: ! 1127: /* ! 1128: * Copy source and destination node ids ! 1129: */ ! 1130: np->tn_off = np->tn_base; ! 1131: ioputc( srcid = tngetc(np), iop ); ! 1132: ioputc( tngetc(np), iop ); ! 1133: ! 1134: /* ! 1135: * Check for short packet. ! 1136: */ ! 1137: if ( cnt = tngetc(np) ) { ! 1138: ! 1139: np->tn_off = np->tn_base + cnt; ! 1140: len = 256 - cnt; ! 1141: } ! 1142: ! 1143: /* ! 1144: * Check for long packet. ! 1145: */ ! 1146: else if ( cnt = tngetc(np) ) { ! 1147: ! 1148: np->tn_off = np->tn_base + cnt; ! 1149: len = 512 - cnt; ! 1150: } ! 1151: ! 1152: /* ! 1153: * Check for non-empty packet. ! 1154: */ ! 1155: if ( cnt != 0 ) { ! 1156: ! 1157: /* ! 1158: * Truncate packet if necessary. ! 1159: */ ! 1160: if ( iop->io_ioc < len ) ! 1161: len = iop->io_ioc; ! 1162: ! 1163: /* ! 1164: * Copy packet body. ! 1165: */ ! 1166: tucopy( np, iop->io_base, len ); ! 1167: iop->io_ioc -= len; ! 1168: iop->io_base += len; ! 1169: } ! 1170: ! 1171: /* ! 1172: * Adjust received data statistics. ! 1173: */ ! 1174: if ( tp->statseg != NULL ) { ! 1175: faddr_t fp = tp->statseg->s_faddr; ! 1176: aflong( fp+TnRxPACKS*4, 1 ); ! 1177: aflong( fp+TnRxBYTES*4, len ); ! 1178: fp += srcid * (NTNST * 4); ! 1179: aflong( fp+TnRxPACKS*4, 1 ); ! 1180: aflong( fp+TnRxBYTES*4, len ); ! 1181: } ! 1182: ! 1183: /* ! 1184: * Enable packet reception with buffer. ! 1185: */ ! 1186: tn_rxena( tp, np ); ! 1187: } ! 1188: ! 1189: ! 1190: /* ! 1191: * Write Routine. ! 1192: * ! 1193: * Wait for a empty transmit buffer to become available. ! 1194: * Format the buffer and place on transmit queue. ! 1195: * If transmit queue was empty, start transmitter. ! 1196: */ ! 1197: ! 1198: tnwrite ( dev, iop ) ! 1199: ! 1200: dev_t dev; ! 1201: register IO * iop; ! 1202: ! 1203: { ! 1204: register struct tnet_s * tp = &tnet[ dev & 3 ]; ! 1205: register struct tnbuf_s * np; ! 1206: unsigned len, cnt; ! 1207: int dstid; ! 1208: int s; ! 1209: ! 1210: /* ! 1211: * Validate size of write. ! 1212: */ ! 1213: if ( ( iop->io_ioc < 3 ) || ( iop->io_ioc > 510 ) ) { ! 1214: u.u_error = EINVAL; ! 1215: return; ! 1216: } ! 1217: ! 1218: /* ! 1219: * Destination Node Id is 2nd byte of write. ! 1220: */ ! 1221: iogetc( iop ); ! 1222: dstid = iogetc( iop ); ! 1223: ! 1224: /* ! 1225: * Wait for empty transmit buffer. ! 1226: */ ! 1227: for ( ; ; ) { ! 1228: ! 1229: /* ! 1230: * If Destination Node appears bad, set errno to EDATTN. ! 1231: */ ! 1232: if ( tp->bad[ dstid / 8 ] & (1 << (dstid % 8)) ) { ! 1233: u.u_error = EDATTN; ! 1234: return; ! 1235: } ! 1236: ! 1237: s = sphi( ); ! 1238: ! 1239: /* ! 1240: * Check for empty transmit buffer. ! 1241: */ ! 1242: if ( np = tp->TxIdle ) { ! 1243: ! 1244: tp->TxIdle = np->tn_next; ! 1245: np->tn_next = 0; ! 1246: spl( s ); ! 1247: break; ! 1248: } ! 1249: ! 1250: /* ! 1251: * Non-blocking writes. ! 1252: */ ! 1253: if ( iop->io_flag & IONDLY ) { ! 1254: /* ! 1255: * Adjust delayed write stats. ! 1256: */ ! 1257: faddr_t fp = tp->statseg->s_faddr; ! 1258: aflong( fp+TnWRTDLYS*4, 1 ); ! 1259: fp += dstid * (NTNST * 4); ! 1260: aflong( fp+TnWRTDLYS*4, 1 ); ! 1261: ! 1262: u.u_error = EAGAIN; ! 1263: spl( s ); ! 1264: return; ! 1265: } ! 1266: ! 1267: tp->TxReq = 1; ! 1268: sleep( &tp->TxReq, CVTTOUT, IVTTOUT, SVTTOUT ); ! 1269: spl( s ); ! 1270: ! 1271: /* ! 1272: * Check for pending signal. ! 1273: */ ! 1274: if ( nondsig() ) { ! 1275: u.u_error = EINTR; ! 1276: return; ! 1277: } ! 1278: } ! 1279: ! 1280: /* ! 1281: * Copy source and destination node ids ! 1282: * NOTE: Hardware inserts source node id automatically. ! 1283: */ ! 1284: np->tn_off = np->tn_base; ! 1285: tnputc( np, 0 ); ! 1286: tnputc( np, dstid ); ! 1287: ! 1288: len = iop->io_ioc; ! 1289: ! 1290: /* ! 1291: * Check for long packet. ! 1292: */ ! 1293: if ( len > 253 ) { ! 1294: tnputc( np, 0 ); ! 1295: tnputc( np, cnt = 512 - len ); ! 1296: np->tn_off = np->tn_base + cnt; ! 1297: } ! 1298: ! 1299: /* ! 1300: * Short packet. ! 1301: */ ! 1302: else { ! 1303: tnputc( np, cnt = 256 - len ); ! 1304: np->tn_off = np->tn_base + cnt; ! 1305: } ! 1306: ! 1307: /* ! 1308: * Copy packet body. ! 1309: */ ! 1310: utcopy( iop->io_base, np, len ); ! 1311: iop->io_base += len; ! 1312: iop->io_ioc -= len; ! 1313: ! 1314: /* ! 1315: * Record length in header structure. ! 1316: */ ! 1317: np->tn_xlen = iop->io_ioc; ! 1318: ! 1319: sphi(); ! 1320: ! 1321: /* ! 1322: * Put packet on transmit ready queue, prime transmitter if necessary. ! 1323: */ ! 1324: if ( ! tp->TxBusy ) { ! 1325: tp->TxBusy = np; ! 1326: outb( NCR, np->tn_ena ); /* enable transmitter */ ! 1327: outb( NIR, tp->tnmask |= NI_Tx); /* enable xmit intr */ ! 1328: tp->tntime = TNTIME; /* restart watchdog */ ! 1329: } ! 1330: else ! 1331: tp->TxBusy->tn_next = np; ! 1332: ! 1333: spl(s); ! 1334: } ! 1335: ! 1336: /* ! 1337: * Enable packet reception with buffer. ! 1338: */ ! 1339: tn_rxena( tp, np ) ! 1340: register struct tnet_s * tp; ! 1341: register struct tnbuf_s * np; ! 1342: { ! 1343: int s; ! 1344: ! 1345: s = sphi( ); ! 1346: ! 1347: /* ! 1348: * Put packet on receive ready queue, prime receiver if necessary. ! 1349: */ ! 1350: if ( tp->RxIdle == NULL ) { ! 1351: tp->RxIdle = np; ! 1352: outb( NCR, np->tn_ena ); ! 1353: outb( NIR, tp->tnmask |= NI_Rx ); ! 1354: } ! 1355: else ! 1356: tp->RxIdle->tn_next = np; ! 1357: ! 1358: np->tn_next = 0; ! 1359: spl( s ); ! 1360: } ! 1361: ! 1362: /* ! 1363: * Adjust far long. ! 1364: */ ! 1365: static ! 1366: aflong( fp, i ) ! 1367: faddr_t fp; ! 1368: int i; ! 1369: { ! 1370: long lw; ! 1371: ! 1372: fkcopy( fp, &lw, sizeof(lw) ); ! 1373: lw += i; ! 1374: kfcopy( &lw, fp, sizeof(lw) ); ! 1375: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.