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