Annotation of coherent/d/PS2_KERNEL/io.286/tn.c, revision 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.