Annotation of lucent/sys/src/9/pc/f002530, revision 1.1

1.1     ! root        1: /*
        !             2:  * National Semiconductor DP8390
        !             3:  * and SMC 83C90
        !             4:  * Network Interface Controller.
        !             5:  */
        !             6: #include "u.h"
        !             7: #include "../port/lib.h"
        !             8: #include "mem.h"
        !             9: #include "dat.h"
        !            10: #include "fns.h"
        !            11: #include "../port/error.h"
        !            12: #include "io.h"
        !            13: #include "devtab.h"
        !            14: 
        !            15: #include "ether.h"
        !            16: 
        !            17: enum {
        !            18:        Cr              = 0x00,         /* command register, all pages */
        !            19: 
        !            20:        Stp             = 0x01,         /* stop */
        !            21:        Sta             = 0x02,         /* start */
        !            22:        Txp             = 0x04,         /* transmit packet */
        !            23:        RDMAread        = (1<<3),       /* remote DMA read */
        !            24:        RDMAwrite       = (2<<3),       /* remote DMA write */
        !            25:        RDMAsend        = (3<<3),       /* remote DMA send packet */
        !            26:        RDMAabort       = (4<<3),       /* abort/complete remote DMA */
        !            27:        Ps0             = 0x40,         /* page select */
        !            28:        Ps1             = 0x80,         /* page select */
        !            29:        Page0           = 0x00,
        !            30:        Page1           = Ps0,
        !            31:        Page2           = Ps1,
        !            32: };
        !            33: 
        !            34: enum {                                 /* Page 0, read */
        !            35:        Clda0           = 0x01,         /* current local DMA address 0 */
        !            36:        Clda1           = 0x02,         /* current local DMA address 1 */
        !            37:        Bnry            = 0x03,         /* boundary pointer (R/W) */
        !            38:        Tsr             = 0x04,         /* transmit status register */
        !            39:        Ncr             = 0x05,         /* number of collisions register */
        !            40:        Fifo            = 0x06,         /* FIFO */
        !            41:        Isr             = 0x07,         /* interrupt status register (R/W) */
        !            42:        Crda0           = 0x08,         /* current remote DMA address 0 */
        !            43:        Crda1           = 0x09,         /* current remote DMA address 1 */
        !            44:        Rsr             = 0x0C,         /* receive status register */
        !            45:        Cntr0           = 0x0D,         /* frame alignment errors */
        !            46:        Cntr1           = 0x0E,         /* CRC errors */
        !            47:        Cntr2           = 0x0F,         /* missed packet errors */
        !            48: };
        !            49: 
        !            50: enum {                                 /* Page 0, write */
        !            51:        Pstart          = 0x01,         /* page start register */
        !            52:        Pstop           = 0x02,         /* page stop register */
        !            53:        Tpsr            = 0x04,         /* transmit page start address */
        !            54:        Tbcr0           = 0x05,         /* transmit byte count register 0 */
        !            55:        Tbcr1           = 0x06,         /* transmit byte count register 1 */
        !            56:        Rsar0           = 0x08,         /* remote start address register 0 */
        !            57:        Rsar1           = 0x09,         /* remote start address register 1 */
        !            58:        Rbcr0           = 0x0A,         /* remote byte count register 0 */
        !            59:        Rbcr1           = 0x0B,         /* remote byte count register 1 */
        !            60:        Rcr             = 0x0C,         /* receive configuration register */
        !            61:        Tcr             = 0x0D,         /* transmit configuration register */
        !            62:        Dcr             = 0x0E,         /* data configuration register */
        !            63:        Imr             = 0x0F,         /* interrupt mask */
        !            64: };
        !            65: 
        !            66: enum {                                 /* Page 1, read/write */
        !            67:        Par0            = 0x01,         /* physical address register 0 */
        !            68:        Curr            = 0x07,         /* current page register */
        !            69:        Mar0            = 0x08,         /* multicast address register 0 */
        !            70: };
        !            71: 
        !            72: enum {                                 /* Interrupt Status Register */
        !            73:        Prx             = 0x01,         /* packet received */
        !            74:        Ptx             = 0x02,         /* packet transmitted */
        !            75:        Rxe             = 0x04,         /* receive error */
        !            76:        Txe             = 0x08,         /* transmit error */
        !            77:        Ovw             = 0x10,         /* overwrite warning */
        !            78:        Cnt             = 0x20,         /* counter overflow */
        !            79:        Rdc             = 0x40,         /* remote DMA complete */
        !            80:        Rst             = 0x80,         /* reset status */
        !            81: };
        !            82: 
        !            83: enum {                                 /* Interrupt Mask Register */
        !            84:        Prxe            = 0x01,         /* packet received interrupt enable */
        !            85:        Ptxe            = 0x02,         /* packet transmitted interrupt enable */
        !            86:        Rxee            = 0x04,         /* receive error interrupt enable */
        !            87:        Txee            = 0x08,         /* transmit error interrupt enable */
        !            88:        Ovwe            = 0x10,         /* overwrite warning interrupt enable */
        !            89:        Cnte            = 0x20,         /* counter overflow interrupt enable */
        !            90:        Rdce            = 0x40,         /* DMA complete interrupt enable */
        !            91: };
        !            92: 
        !            93: enum {                                 /* Data Configuration register */
        !            94:        Wts             = 0x01,         /* word transfer select */
        !            95:        Bos             = 0x02,         /* byte order select */
        !            96:        Las             = 0x04,         /* long address select */
        !            97:        Ls              = 0x08,         /* loopback select */
        !            98:        Arm             = 0x10,         /* auto-initialise remote */
        !            99:        Ft1             = (0x00<<5),    /* FIFO threshhold select 1 byte/word */
        !           100:        Ft2             = (0x01<<5),    /* FIFO threshhold select 2 bytes/words */
        !           101:        Ft4             = (0x02<<5),    /* FIFO threshhold select 4 bytes/words */
        !           102:        Ft6             = (0x03<<5),    /* FIFO threshhold select 6 bytes/words */
        !           103: };
        !           104: 
        !           105: enum {                                 /* Transmit Configuration Register */
        !           106:        Crc             = 0x01,         /* inhibit CRC */
        !           107:        Lb              = 0x02,         /* internal loopback */
        !           108:        Atd             = 0x08,         /* auto transmit disable */
        !           109:        Ofst            = 0x10,         /* collision offset enable */
        !           110: };
        !           111: 
        !           112: enum {                                 /* Transmit Status Register */
        !           113:        Ptxok           = 0x01,         /* packet transmitted */
        !           114:        Col             = 0x04,         /* transmit collided */
        !           115:        Abt             = 0x08,         /* tranmit aborted */
        !           116:        Crs             = 0x10,         /* carrier sense lost */
        !           117:        Fu              = 0x20,         /* FIFO underrun */
        !           118:        Cdh             = 0x40,         /* CD heartbeat */
        !           119:        Owc             = 0x80,         /* out of window collision */
        !           120: };
        !           121: 
        !           122: enum {                                 /* Receive Configuration Register */
        !           123:        Sep             = 0x01,         /* save errored packets */
        !           124:        Ar              = 0x02,         /* accept runt packets */
        !           125:        Ab              = 0x04,         /* accept broadcast */
        !           126:        Am              = 0x08,         /* accept multicast */
        !           127:        Pro             = 0x10,         /* promiscuous physical */
        !           128:        Mon             = 0x20,         /* monitor mode */
        !           129: };
        !           130: 
        !           131: enum {                                 /* Receive Status Register */
        !           132:        Prxok           = 0x01,         /* packet received intact */
        !           133:        Crce            = 0x02,         /* CRC error */
        !           134:        Fae             = 0x04,         /* frame alignment error */
        !           135:        Fo              = 0x08,         /* FIFO overrun */
        !           136:        Mpa             = 0x10,         /* missed packet */
        !           137:        Phy             = 0x20,         /* physical/multicast address */
        !           138:        Dis             = 0x40,         /* receiver disabled */
        !           139:        Dfr             = 0x80,         /* deferring */
        !           140: };
        !           141: 
        !           142: typedef struct {
        !           143:        uchar   status;
        !           144:        uchar   next;
        !           145:        uchar   len0;
        !           146:        uchar   len1;
        !           147: } Hdr;
        !           148: 
        !           149: static void
        !           150: dp8390disable(Ctlr *ctlr)
        !           151: {
        !           152:        ulong dp8390;
        !           153:        int timo;
        !           154: 
        !           155:        dp8390 = ctlr->card.dp8390;
        !           156:        /*
        !           157:         * Stop the chip. Set the Stp bit and wait for the chip
        !           158:         * to finish whatever was on its tiny mind before it sets
        !           159:         * the Rst bit.
        !           160:         * We need the timeout because there may not be a real
        !           161:         * chip there if this is called when probing for a device
        !           162:         * at boot.
        !           163:         */
        !           164:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
        !           165:        dp8390outb(dp8390+Rbcr0, 0);
        !           166:        dp8390outb(dp8390+Rbcr1, 0);
        !           167:        for(timo = 10000; (dp8390inb(dp8390+Isr) & Rst) == 0 && timo; timo--)
        !           168:                        ;
        !           169: }
        !           170: 
        !           171: static void
        !           172: dp8390ring(Ctlr *ctlr)
        !           173: {
        !           174:        ulong dp8390;
        !           175: 
        !           176:        dp8390 = ctlr->card.dp8390;
        !           177:        dp8390outb(dp8390+Pstart, ctlr->card.pstart);
        !           178:        dp8390outb(dp8390+Pstop, ctlr->card.pstop);
        !           179:        dp8390outb(dp8390+Bnry, ctlr->card.pstop-1);
        !           180: 
        !           181:        dp8390outb(dp8390+Cr, Page1|RDMAabort|Stp);
        !           182:        dp8390outb(dp8390+Curr, ctlr->card.pstart);
        !           183:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
        !           184: 
        !           185:        ctlr->card.nxtpkt = ctlr->card.pstart;
        !           186: }
        !           187: 
        !           188: void
        !           189: dp8390reset(Ctlr *ctlr)
        !           190: {
        !           191:        ulong dp8390;
        !           192: 
        !           193:        dp8390 = ctlr->card.dp8390;
        !           194:        /*
        !           195:         * This is the initialisation procedure described
        !           196:         * as 'mandatory' in the datasheet, with references
        !           197:         * to the 3Com503 technical reference manual.
        !           198:         */ 
        !           199:        dp8390disable(ctlr);
        !           200:        if(ctlr->card.bit16)
        !           201:                dp8390outb(dp8390+Dcr, Ft4|Ls|Wts);
        !           202:        else
        !           203:                dp8390outb(dp8390+Dcr, Ft4|Ls);
        !           204: 
        !           205:        dp8390outb(dp8390+Rbcr0, 0);
        !           206:        dp8390outb(dp8390+Rbcr1, 0);
        !           207: 
        !           208:        dp8390outb(dp8390+Tcr, 0);
        !           209:        dp8390outb(dp8390+Rcr, Mon);
        !           210: 
        !           211:        /*
        !           212:         * Init the ring hardware and software ring pointers.
        !           213:         * Can't initialise ethernet address as we may not know
        !           214:         * it yet.
        !           215:         */
        !           216:        dp8390ring(ctlr);
        !           217:        dp8390outb(dp8390+Tpsr, ctlr->card.tstart);
        !           218: 
        !           219:        dp8390outb(dp8390+Isr, 0xFF);
        !           220:        dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
        !           221: 
        !           222:        /*
        !           223:         * Leave the chip initialised,
        !           224:         * but in monitor mode.
        !           225:         */
        !           226:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
        !           227: }
        !           228: 
        !           229: void
        !           230: dp8390attach(Ctlr *ctlr)
        !           231: {
        !           232:        /*
        !           233:         * Enable the chip for transmit/receive.
        !           234:         * The init routine leaves the chip in monitor
        !           235:         * mode. Clear the missed-packet counter, it
        !           236:         * increments while in monitor mode.
        !           237:         */
        !           238:        dp8390outb(ctlr->card.dp8390+Rcr, Ab);
        !           239:        dp8390inb(ctlr->card.dp8390+Cntr2);
        !           240: }
        !           241: 
        !           242: void
        !           243: dp8390mode(Ctlr *ctlr, int on)
        !           244: {
        !           245:        /*
        !           246:         * Set/reset promiscuous mode.
        !           247:         */
        !           248:        if(on)
        !           249:                dp8390outb(ctlr->card.dp8390+Rcr, Pro|Ab);
        !           250:        else
        !           251:                dp8390outb(ctlr->card.dp8390+Rcr, Ab);
        !           252: }
        !           253: 
        !           254: void
        !           255: dp8390setea(Ctlr *ctlr)
        !           256: {
        !           257:        ulong dp8390;
        !           258:        uchar cr;
        !           259:        int i;
        !           260: 
        !           261:        dp8390 = ctlr->card.dp8390;
        !           262:        /*
        !           263:         * Set the ethernet address into the chip.
        !           264:         * Take care to restore the command register
        !           265:         * afterwards. We don't care about multicast
        !           266:         * addresses as we never set the multicast
        !           267:         * enable.
        !           268:         */
        !           269:        cr = dp8390inb(dp8390+Cr) & ~Txp;
        !           270:        dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
        !           271:        for(i = 0; i < sizeof(ctlr->ea); i++)
        !           272:                dp8390outb(dp8390+Par0+i, ctlr->ea[i]);
        !           273:        dp8390outb(dp8390+Cr, cr);
        !           274: }
        !           275: 
        !           276: void
        !           277: dp8390getea(Ctlr *ctlr)
        !           278: {
        !           279:        ulong dp8390;
        !           280:        uchar cr;
        !           281:        int i;
        !           282: 
        !           283:        dp8390 = ctlr->card.dp8390;
        !           284:        /*
        !           285:         * Set the ethernet address into the chip.
        !           286:         * Take care to restore the command register
        !           287:         * afterwards. We don't care about multicast
        !           288:         * addresses as we never set the multicast
        !           289:         * enable.
        !           290:         */
        !           291:        cr = dp8390inb(dp8390+Cr) & ~Txp;
        !           292:        dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
        !           293:        for(i = 0; i < sizeof(ctlr->ea); i++)
        !           294:                ctlr->ea[i] = dp8390inb(dp8390+Par0+i);
        !           295:        dp8390outb(dp8390+Cr, cr);
        !           296: }
        !           297: 
        !           298: void*
        !           299: dp8390read(Ctlr *ctlr, void *to, ulong from, ulong len)
        !           300: {
        !           301:        ulong dp8390;
        !           302:        uchar cr;
        !           303:        int timo;
        !           304: 
        !           305:        dp8390 = ctlr->card.dp8390;
        !           306:        /*
        !           307:         * Read some data at offset 'from' in the card's memory
        !           308:         * using the DP8390 remote DMA facility, and place it at
        !           309:         * 'to' in main memory, via the I/O data port.
        !           310:         */
        !           311:        cr = dp8390inb(dp8390+Cr) & ~Txp;
        !           312:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
        !           313:        dp8390outb(dp8390+Isr, Rdc);
        !           314: 
        !           315:        /*
        !           316:         * Set up the remote DMA address and count.
        !           317:         */
        !           318:        if(ctlr->card.bit16)
        !           319:                len = ROUNDUP(len, 2);
        !           320:        dp8390outb(dp8390+Rbcr0, len & 0xFF);
        !           321:        dp8390outb(dp8390+Rbcr1, (len>>8) & 0xFF);
        !           322:        dp8390outb(dp8390+Rsar0, from & 0xFF);
        !           323:        dp8390outb(dp8390+Rsar1, (from>>8) & 0xFF);
        !           324: 
        !           325:        /*
        !           326:         * Start the remote DMA read and suck the data
        !           327:         * out of the I/O port.
        !           328:         */
        !           329:        dp8390outb(dp8390+Cr, Page0|RDMAread|Sta);
        !           330:        if(ctlr->card.bit16)
        !           331:                inss(ctlr->card.data, to, len/2);
        !           332:        else
        !           333:                insb(ctlr->card.data, to, len);
        !           334: 
        !           335:        /*
        !           336:         * Wait for the remote DMA to complete. The timeout
        !           337:         * is necessary because we may call this routine on
        !           338:         * a non-existent chip during initialisation and, due
        !           339:         * to the miracles of the bus, we could get this far
        !           340:         * and still be talking to a slot full of nothing.
        !           341:         */
        !           342:        for(timo = 10000; (dp8390inb(dp8390+Isr) & Rdc) == 0 && timo; timo--)
        !           343:                        ;
        !           344: 
        !           345:        dp8390outb(dp8390+Isr, Rdc);
        !           346:        dp8390outb(dp8390+Cr, cr);
        !           347:        return to;
        !           348: }
        !           349: 
        !           350: void*
        !           351: dp8390write(Ctlr *ctlr, ulong to, void *from, ulong len)
        !           352: {
        !           353:        ulong dp8390, crda;
        !           354:        uchar cr;
        !           355: 
        !           356:        dp8390 = ctlr->card.dp8390;
        !           357:        /*
        !           358:         * Write some data to offset 'to' in the card's memory
        !           359:         * using the DP8390 remote DMA facility, reading it at
        !           360:         * 'from' in main memory, via the I/O data port.
        !           361:         */
        !           362:        cr = dp8390inb(dp8390+Cr) & ~Txp;
        !           363:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
        !           364:        dp8390outb(dp8390+Isr, Rdc);
        !           365: 
        !           366:        if(ctlr->card.bit16)
        !           367:                len = ROUNDUP(len, 2);
        !           368: 
        !           369:        /*
        !           370:         * Set up the remote DMA address and count.
        !           371:         * This is straight from the DP8390[12D] datasheet, hence
        !           372:         * the initial set up for read.
        !           373:         */
        !           374:        crda = to-1-ctlr->card.bit16;
        !           375:        dp8390outb(dp8390+Rbcr0, (len+1+ctlr->card.bit16) & 0xFF);
        !           376:        dp8390outb(dp8390+Rbcr1, ((len+1+ctlr->card.bit16)>>8) & 0xFF);
        !           377:        dp8390outb(dp8390+Rsar0, crda & 0xFF);
        !           378:        dp8390outb(dp8390+Rsar1, (crda>>8) & 0xFF);
        !           379:        dp8390outb(dp8390+Cr, Page0|RDMAread|Sta);
        !           380: 
        !           381:        for(;;){
        !           382:                crda = dp8390inb(dp8390+Crda0);
        !           383:                crda |= dp8390inb(dp8390+Crda1)<<8;
        !           384:                if(crda == to){
        !           385:                        /*
        !           386:                         * Start the remote DMA write and make sure
        !           387:                         * the registers are correct.
        !           388:                         */
        !           389:                        dp8390outb(dp8390+Cr, Page0|RDMAwrite|Sta);
        !           390: 
        !           391:                        crda = dp8390inb(dp8390+Crda0);
        !           392:                        crda |= dp8390inb(dp8390+Crda1)<<8;
        !           393:                        if(crda != to)
        !           394:                                panic("crda write %d to %d\n", crda, to);
        !           395: 
        !           396:                        break;
        !           397:                }
        !           398:        }
        !           399: 
        !           400:        /*
        !           401:         * Pump the data into the I/O port.
        !           402:         */
        !           403:        if(ctlr->card.bit16)
        !           404:                outss(ctlr->card.data, from, len/2);
        !           405:        else
        !           406:                outsb(ctlr->card.data, from, len);
        !           407: 
        !           408:        /*
        !           409:         * Wait for the remote DMA to finish. We'll need
        !           410:         * a timeout here if this ever gets called before
        !           411:         * we know there really is a chip there.
        !           412:         */
        !           413:        while((dp8390inb(dp8390+Isr) & Rdc) == 0)
        !           414:                        ;
        !           415: 
        !           416:        dp8390outb(dp8390+Isr, Rdc);
        !           417:        dp8390outb(dp8390+Cr, cr);
        !           418:        return (void*)to;
        !           419: }
        !           420: 
        !           421: static uchar
        !           422: getcurr(ulong dp8390)
        !           423: {
        !           424:        uchar cr, curr;
        !           425: 
        !           426:        cr = dp8390inb(dp8390+Cr) & ~Txp;
        !           427:        dp8390outb(dp8390+Cr, Page1|(~(Ps1|Ps0) & cr));
        !           428:        curr = dp8390inb(dp8390+Curr);
        !           429:        dp8390outb(dp8390+Cr, cr);
        !           430:        return curr;
        !           431: }
        !           432: 
        !           433: static void
        !           434: cldaquiet(ulong dp8390)
        !           435: {
        !           436:        uchar a, b, c;
        !           437: 
        !           438:        /*
        !           439:         * Hack to keep away from the card's memory while it is receiving
        !           440:         * a packet. This is only a problem on the NCR 3170 Safari.
        !           441:         *
        !           442:         * We peek at the current local DMA registers and, if they are
        !           443:         * changing, wait.
        !           444:         */
        !           445:        
        !           446:        for(;;delay(10)){
        !           447:                a = dp8390inb(dp8390+Clda0);
        !           448:                b = dp8390inb(dp8390+Clda0);
        !           449:                if(a != b)
        !           450:                        continue;
        !           451:                c = dp8390inb(dp8390+Clda0);
        !           452:                if(c != b)
        !           453:                        continue;
        !           454:                break;
        !           455:        }
        !           456: }
        !           457: 
        !           458: void
        !           459: dp8390receive(Ctlr *ctlr)
        !           460: {
        !           461:        RingBuf *ring;
        !           462:        uchar curr, len1, *pkt;
        !           463:        Hdr hdr;
        !           464:        ulong dp8390, data, len;
        !           465: 
        !           466:        dp8390 = ctlr->card.dp8390;
        !           467:        for(curr = getcurr(dp8390); ctlr->card.nxtpkt != curr; curr = getcurr(dp8390)){
        !           468:                if(strcmp(arch->id, "NCRD.0") == 0)
        !           469:                        cldaquiet(dp8390);
        !           470: 
        !           471:                ctlr->inpackets++;
        !           472: 
        !           473:                data = ctlr->card.nxtpkt*Dp8390BufSz;
        !           474:                (*ctlr->card.read)(ctlr, &hdr, data, sizeof(Hdr));
        !           475: 
        !           476:                /*
        !           477:                 * Don't believe the upper byte count, work it
        !           478:                 * out from the software next-page pointer and
        !           479:                 * the current next-page pointer.
        !           480:                 */
        !           481:                if(hdr.next > ctlr->card.nxtpkt)
        !           482:                        len1 = hdr.next - ctlr->card.nxtpkt - 1;
        !           483:                else
        !           484:                        len1 = (ctlr->card.pstop-ctlr->card.nxtpkt) + (hdr.next-ctlr->card.pstart) - 1;
        !           485:                if(hdr.len0 > (Dp8390BufSz-sizeof(Hdr)))
        !           486:                        len1--;
        !           487: 
        !           488:                len = ((len1<<8)|hdr.len0)-4;
        !           489: 
        !           490:                /*
        !           491:                 * Chip is badly scrogged, reinitialise the ring.
        !           492:                 */
        !           493:                if(hdr.next < ctlr->card.pstart || hdr.next >= ctlr->card.pstop
        !           494:                  || len < 60 || len > sizeof(Etherpkt)){
        !           495:                        print("H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%d|",
        !           496:                                hdr.status, hdr.next, hdr.len0, hdr.len1, len);
        !           497:                        dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
        !           498:                        dp8390ring(ctlr);
        !           499:                        dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
        !           500:                        return;
        !           501:                }
        !           502: 
        !           503:                /*
        !           504:                 * If it's a good packet and we have a place to put it,
        !           505:                 * read it in to the software ring.
        !           506:                 * If the packet wraps round the hardware ring, read it
        !           507:                 * in two pieces.
        !           508:                 */
        !           509:                ring = &ctlr->rb[ctlr->ri];
        !           510:                if((hdr.status & (Fo|Fae|Crce|Prxok)) == Prxok && ring->owner == Interface){
        !           511:                        pkt = ring->pkt;
        !           512:                        data += sizeof(Hdr);
        !           513:                        ring->len = len;
        !           514: 
        !           515:                        if((data+len) >= ctlr->card.pstop*Dp8390BufSz){
        !           516:                                ulong count = ctlr->card.pstop*Dp8390BufSz - data;
        !           517: 
        !           518:                                (*ctlr->card.read)(ctlr, pkt, data, count);
        !           519:                                pkt += count;
        !           520:                                data = ctlr->card.pstart*Dp8390BufSz;
        !           521:                                len -= count;
        !           522:                        }
        !           523:                        if(len)
        !           524:                                (*ctlr->card.read)(ctlr, pkt, data, len);
        !           525: 
        !           526:                        ring->owner = Host;
        !           527:                        ctlr->ri = NEXT(ctlr->ri, ctlr->nrb);
        !           528:                }
        !           529: 
        !           530:                /*
        !           531:                 * Finished woth this packet, update the
        !           532:                 * hardware and software ring pointers.
        !           533:                 */
        !           534:                ctlr->card.nxtpkt = hdr.next;
        !           535: 
        !           536:                hdr.next--;
        !           537:                if(hdr.next < ctlr->card.pstart)
        !           538:                        hdr.next = ctlr->card.pstop-1;
        !           539:                dp8390outb(dp8390+Bnry, hdr.next);
        !           540:        }
        !           541: }
        !           542: 
        !           543: /*
        !           544:  * Initiate a transmission. Must be called splhi().
        !           545:  */
        !           546: void
        !           547: dp8390transmit(Ctlr *ctlr)
        !           548: {
        !           549:        ulong dp8390;
        !           550:        RingBuf *ring;
        !           551: 
        !           552:        dp8390 = ctlr->card.dp8390;
        !           553:        ring = &ctlr->tb[ctlr->ti];
        !           554:        if(ctlr->tbusy == 0 && ring->owner == Interface){
        !           555: 
        !           556:                ctlr->tbusy = 1;
        !           557: 
        !           558:                (*ctlr->card.write)(ctlr, ctlr->card.tstart*Dp8390BufSz, ring->pkt, ring->len);
        !           559: 
        !           560:                dp8390outb(dp8390+Tbcr0, ring->len & 0xFF);
        !           561:                dp8390outb(dp8390+Tbcr1, (ring->len>>8) & 0xFF);
        !           562:                dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta);
        !           563:        }
        !           564: }
        !           565: 
        !           566: void
        !           567: dp8390overflow(Ctlr *ctlr)
        !           568: {
        !           569:        ulong dp8390;
        !           570:        uchar txp;
        !           571:        int resend;
        !           572: 
        !           573:        dp8390 = ctlr->card.dp8390;
        !           574:        /*
        !           575:         * The following procedure is taken from the DP8390[12D] datasheet,
        !           576:         * it seems pretty adamant that this is what has to be done.
        !           577:         */
        !           578:        txp = dp8390inb(dp8390+Cr) & Txp;
        !           579:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Stp);
        !           580:        delay(2);
        !           581:        dp8390outb(dp8390+Rbcr0, 0);
        !           582:        dp8390outb(dp8390+Rbcr1, 0);
        !           583: 
        !           584:        resend = 0;
        !           585:        if(txp && (dp8390inb(dp8390+Isr) & (Txe|Ptx)) == 0)
        !           586:                resend = 1;
        !           587: 
        !           588:        dp8390outb(dp8390+Tcr, Lb);
        !           589:        dp8390outb(dp8390+Cr, Page0|RDMAabort|Sta);
        !           590:        (*ctlr->card.receive)(ctlr);
        !           591:        dp8390outb(dp8390+Isr, Ovw);
        !           592:        wakeup(&ctlr->rr);
        !           593:        dp8390outb(dp8390+Tcr, 0);
        !           594: 
        !           595:        if(resend)
        !           596:                dp8390outb(dp8390+Cr, Page0|RDMAabort|Txp|Sta);
        !           597: }
        !           598: 
        !           599: void
        !           600: dp8390watch(Ctlr *ctlr)
        !           601: {
        !           602:        int s;
        !           603: 
        !           604:        /*
        !           605:         * Stub watchdog routine.
        !           606:         * Whine if a transmit takes too long.
        !           607:         */
        !           608:        s = splhi();
        !           609:        if(ctlr->tbusy){
        !           610:                ctlr->tbusy++;
        !           611:                if(ctlr->tbusy > 1 && ctlr->debug)
        !           612:                        print("TB%d|", ctlr->tbusy);
        !           613:        }
        !           614:        splx(s);
        !           615: }
        !           616: 
        !           617: void
        !           618: dp8390intr(Ctlr *ctlr)
        !           619: {
        !           620:        ulong dp8390;
        !           621:        RingBuf *ring;
        !           622:        uchar isr, r;
        !           623: 
        !           624:        dp8390 = ctlr->card.dp8390;
        !           625:        /*
        !           626:         * While there is something of interest,
        !           627:         * clear all the interrupts and process.
        !           628:         */
        !           629:        dp8390outb(dp8390+Imr, 0x00);
        !           630:        while(isr = dp8390inb(dp8390+Isr)){
        !           631: 
        !           632:                if(isr & Ovw){
        !           633:                        if(ctlr->card.overflow)
        !           634:                                (*ctlr->card.overflow)(ctlr);
        !           635:                        dp8390outb(dp8390+Isr, Ovw);
        !           636:                        ctlr->overflows++;
        !           637:                }
        !           638: 
        !           639:                /*
        !           640:                 * We have received packets.
        !           641:                 * Take a spin round the ring and
        !           642:                 * wakeup the kproc.
        !           643:                 */
        !           644:                if(isr & (Rxe|Prx)){
        !           645:                        (*ctlr->card.receive)(ctlr);
        !           646:                        dp8390outb(dp8390+Isr, Rxe|Prx);
        !           647:                        wakeup(&ctlr->rr);
        !           648:                }
        !           649: 
        !           650:                /*
        !           651:                 * A packet completed transmission, successfully or
        !           652:                 * not. Start transmission on the next buffered packet,
        !           653:                 * and wake the output routine.
        !           654:                 */
        !           655:                if(isr & (Txe|Ptx)){
        !           656:                        r = dp8390inb(dp8390+Tsr);
        !           657:                        if(isr & Txe){
        !           658:                                if((r & (Cdh|Fu|Crs|Abt)) && ctlr->debug)
        !           659:                                        print("Tsr#%2.2ux|", r);
        !           660:                                ctlr->oerrs++;
        !           661:                        }
        !           662: 
        !           663:                        dp8390outb(dp8390+Isr, Txe|Ptx);
        !           664: 
        !           665:                        if(isr & Ptx)
        !           666:                                ctlr->outpackets++;
        !           667: 
        !           668:                        ring = &ctlr->tb[ctlr->ti];
        !           669:                        ring->owner = Host;
        !           670:                        ctlr->tbusy = 0;
        !           671:                        ctlr->ti = NEXT(ctlr->ti, ctlr->ntb);
        !           672:                        (*ctlr->card.transmit)(ctlr);
        !           673:                        wakeup(&ctlr->tr);
        !           674:                }
        !           675: 
        !           676:                if(isr & Cnt){
        !           677:                        ctlr->frames += dp8390inb(dp8390+Cntr0);
        !           678:                        ctlr->crcs += dp8390inb(dp8390+Cntr1);
        !           679:                        ctlr->buffs += dp8390inb(dp8390+Cntr2);
        !           680:                        dp8390outb(dp8390+Isr, Cnt);
        !           681:                }
        !           682:        }
        !           683:        dp8390outb(dp8390+Imr, Cnte|Ovwe|Txee|Rxee|Ptxe|Prxe);
        !           684: }

unix.superglobalmegacorp.com

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