Annotation of coherent/d/286_KERNEL/USRSRC/io/tn.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.