Annotation of coherent/d/PS2_KERNEL/io.286/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/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: }

unix.superglobalmegacorp.com

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