Annotation of lucent/sys/src/9/pc/ether503.c, revision 1.1

1.1     ! root        1: #include "u.h"
        !             2: #include "../port/lib.h"
        !             3: #include "mem.h"
        !             4: #include "dat.h"
        !             5: #include "fns.h"
        !             6: #include "../port/error.h"
        !             7: #include "io.h"
        !             8: #include "devtab.h"
        !             9: 
        !            10: #include "ether.h"
        !            11: 
        !            12: /*
        !            13:  * 3Com 503 (EtherLink II).
        !            14:  * This driver doesn't work under load, the card gets blasted by
        !            15:  * overwrite-warning interrupts and eventually just hangs. Always clearing
        !            16:  * the Ovw bit in the DP8390 Isr along with the Rxe and Prx bits stops
        !            17:  * the overwrite-warning interrupts, but the card eventually hangs anyway.
        !            18:  * I really don't understand why this card doesn't work,
        !            19:  * there is plenty of evidence that other systems manage to use it.
        !            20:  * The only good thing about this driver is that both shared
        !            21:  * memory and polled I/O work (given the above restraints), although
        !            22:  * the polled I/O should be tuned.
        !            23:  */
        !            24: enum {                                 /* Gate Array Registers */
        !            25:        Pstr            = 0x400,        /* Page Start Register */
        !            26:        Pspr            = 0x401,        /* Page Stop Register */
        !            27:        Dqtr            = 0x402,        /* Drq Timer Register */
        !            28:        Bcfr            = 0x403,        /* Base Configuration Register */
        !            29:        Pcfr            = 0x404,        /* EPROM Configuration Register */
        !            30:        Gacfr           = 0x405,        /* GA Configuration Register */
        !            31:        Ctrl            = 0x406,        /* Control Register */
        !            32:        Streg           = 0x407,        /* Status Register */
        !            33:        Idcfr           = 0x408,        /* Interrupt/DMA Configuration Register */
        !            34:        Damsb           = 0x409,        /* DMA Address Register MSB */
        !            35:        Dalsb           = 0x40A,        /* DMA Address Register LSB */
        !            36:        Vptr2           = 0x40B,        /* Vector Pointer Register 2 */
        !            37:        Vptr1           = 0x40C,        /* Vector Pointer Register 1 */
        !            38:        Vptr0           = 0x40D,        /* Vector Pointer Register 0 */
        !            39:        Rfmsb           = 0x40E,        /* Register File Access MSB */
        !            40:        Rflsb           = 0x40F,        /* Register File Access LSB */
        !            41: };
        !            42: 
        !            43: enum {                                 /* Pcfr */
        !            44:        C8xxx           = 0x10,         /* memory address 0xC8000 */
        !            45:        CCxxx           = 0x20,         /* memory address 0xCC000 */
        !            46:        D8xxx           = 0x40,         /* memory address 0xD8000 */
        !            47:        DCxxx           = 0x80,         /* memory address 0xDC000 */
        !            48: };
        !            49: 
        !            50: enum {                                 /* Gacfr */
        !            51:        Mbs0            = 0x01,         /* memory bank select 0 */
        !            52:        Mbs1            = 0x02,         /* memory bank select 1 */
        !            53:        Mbs2            = 0x04,         /* memory bank select 2 */
        !            54:        Rsel            = 0x08,         /* RAM select */
        !            55:        Test            = 0x10,         /* test */
        !            56:        Ows             = 0x20,         /* 0 wait state */
        !            57:        Tcm             = 0x40,         /* terminal count mask */
        !            58:        Nim             = 0x80,         /* MIC interrupt mask */
        !            59: };
        !            60: 
        !            61: enum {                                 /* Ctrl */
        !            62:        Rst             = 0x01,         /* software reset */
        !            63:        Xsel            = 0x02,         /* transceiver select (BNC = 1, AUI = 0) */
        !            64:        Ealo            = 0x04,         /* ethernet address low */
        !            65:        Eahi            = 0x08,         /* ethernet address high */
        !            66:        Share           = 0x10,         /* interrupt share */
        !            67:        Dbsel           = 0x20,         /* double buffer select */
        !            68:        Ddir            = 0x40,         /* DMA direction */
        !            69:        Start           = 0x80,         /* DMA start */
        !            70: };
        !            71: 
        !            72: enum {                                 /* Streg */
        !            73:        Rev0            = 0x01,         /* gate array revision bit 0 */
        !            74:        Rev1            = 0x02,         /* gate array revision bit 1 */
        !            75:        Rev2            = 0x04,         /* gate array revision bit 2 */
        !            76:        Dip             = 0x08,         /* DMA in progress */
        !            77:        Dtc             = 0x10,         /* DMA terminal count */
        !            78:        Oflw            = 0x20,         /* overflow */
        !            79:        Uflw            = 0x40,         /* underflow */
        !            80:        Dprdy           = 0x80,         /* data port ready */
        !            81: };
        !            82: 
        !            83: enum {                                 /* Idcfr */
        !            84:        Drq1            = 0x01,         /* DMA request 1 */
        !            85:        Drq2            = 0x02,         /* DMA request 2 */
        !            86:        Drq3            = 0x04,         /* DMA request 3 */
        !            87:        Irq2            = 0x10,         /* interrupt request 2 */
        !            88:        Irq3            = 0x20,         /* interrupt request 3 */
        !            89:        Irq4            = 0x40,         /* interrupt request 4 */
        !            90:        Irq5            = 0x80,         /* interrupt request 5 */
        !            91: };
        !            92: 
        !            93: enum {
        !            94:        RamOffset       = 0x2000,       /* where the card sees the shared memory */
        !            95: };
        !            96: 
        !            97: typedef struct {
        !            98:        ulong   io;                     /* I/O base address */
        !            99:        uchar   irq;                    /* interrupt level */
        !           100:        uchar   bnc;                    /* use BNC connector */
        !           101: } Table;
        !           102: 
        !           103: /*
        !           104:  * The only configuration info we can get from the card is the
        !           105:  * I/O base address and the shared-memory address. So let's make
        !           106:  * a little hard-wired configuration table.
        !           107:  */
        !           108: static Table table[] = {
        !           109:        { 0x300, Irq2, 0, },            /* external transceiver */
        !           110:        { 0x310, Irq3, 0, },
        !           111:        { 0x330, Irq4, 0, },
        !           112:        { 0x350, Irq5, 0, },
        !           113: 
        !           114:        { 0x250, Irq2, Xsel, },         /* BNC */
        !           115:        { 0x280, Irq3, Xsel, },
        !           116:        { 0x2A0, Irq4, Xsel, },
        !           117:        { 0x2E0, Irq5, Xsel, },
        !           118: 
        !           119:        { 0 },
        !           120: };
        !           121: 
        !           122: 
        !           123: static int
        !           124: reset(Ctlr *ctlr)
        !           125: {
        !           126:        Table *tp;
        !           127:        int i;
        !           128:        uchar cfr;
        !           129: 
        !           130:        /*
        !           131:         * The Gate Array Ctrl register bits <3,2> determine what is
        !           132:         * mapped at the I/O base address. The options are the DP8390,
        !           133:         * PROM bytes 0-15 or PROM bytes 16-31.
        !           134:         * At power-on, the I/O base address contains PROM bytes 16-31.
        !           135:         */
        !           136:        for(tp = table; ctlr->card.io = tp->io; tp++){
        !           137:                /*
        !           138:                 * Toggle the software reset bit, this should initialise the
        !           139:                 * Ctrl register to 0x0A (Eahi|Xsel).
        !           140:                 * Hopefully there is no other card at the gate-array address.
        !           141:                 */
        !           142:                outb(ctlr->card.io+Ctrl, Rst);
        !           143:                delay(1);
        !           144:                outb(ctlr->card.io+Ctrl, 0);
        !           145:                if(inb(ctlr->card.io+Ctrl) == (Eahi|Xsel))
        !           146:                        break;
        !           147:        }
        !           148:        if(ctlr->card.io == 0)
        !           149:                return -1;
        !           150: 
        !           151:        /*
        !           152:         * Map PROM bytes 0-15 to the I/O base address
        !           153:         * and read the ethernet address.
        !           154:         * When done, map the DP8390 at the I/O base address
        !           155:         * and set the transceiver type and irq.
        !           156:         */
        !           157:        outb(ctlr->card.io+Ctrl, Ealo|Xsel);
        !           158:        for(i = 0; i < sizeof(ctlr->ea); i++)
        !           159:                ctlr->ea[i] = inb(ctlr->card.io+i);
        !           160: 
        !           161:        outb(ctlr->card.io+Gacfr, Nim|Tcm);
        !           162: 
        !           163:        outb(ctlr->card.io+Ctrl, 0|tp->bnc);
        !           164:        outb(ctlr->card.io+Idcfr, tp->irq);
        !           165: 
        !           166:        if(tp->irq == Irq2)
        !           167:                ctlr->card.irq = 2;
        !           168:        else if(tp->irq == Irq3)
        !           169:                ctlr->card.irq = 3;
        !           170:        else if(tp->irq == Irq4)
        !           171:                ctlr->card.irq = 4;
        !           172:        else if(tp->irq == Irq5)
        !           173:                ctlr->card.irq = 5;
        !           174:        else
        !           175:                return -1;
        !           176: 
        !           177:        /*
        !           178:         * Try to configure the shared memory.
        !           179:         * Assume this is an 8K card.
        !           180:         */
        !           181:        ctlr->card.ram = 1;
        !           182:        cfr = inb(ctlr->card.io+Pcfr);
        !           183:        if(cfr & C8xxx)
        !           184:                ctlr->card.ramstart = KZERO|0xC8000;
        !           185:        else if(cfr & CCxxx)
        !           186:                ctlr->card.ramstart = KZERO|0xCC000;
        !           187:        else if(cfr & D8xxx)
        !           188:                ctlr->card.ramstart = KZERO|0xD8000;
        !           189:        else if(cfr & DCxxx)
        !           190:                ctlr->card.ramstart = KZERO|0xDC000;
        !           191:        else
        !           192:                ctlr->card.ram = 0;
        !           193: 
        !           194:        ctlr->card.ramstop = ctlr->card.ramstart + 8*1024;
        !           195: 
        !           196:        /*
        !           197:         * Finish initialising the gate-array.
        !           198:         * The Pstr and Pspr registers must be the same as those
        !           199:         * given to the DP8390.
        !           200:         * Gacfr is set to enable shared memory and block DMA
        !           201:         * interrupts.
        !           202:         */
        !           203:        outb(ctlr->card.io+Pstr, ctlr->card.pstart);
        !           204:        outb(ctlr->card.io+Pspr, ctlr->card.pstop);
        !           205: 
        !           206:        outb(ctlr->card.io+Dqtr, 8);
        !           207:        outb(ctlr->card.io+Damsb, ctlr->card.tstart);
        !           208:        outb(ctlr->card.io+Dalsb, 0);
        !           209: 
        !           210:        outb(ctlr->card.io+Vptr2, 0xFF);
        !           211:        outb(ctlr->card.io+Vptr1, 0xFF);
        !           212:        outb(ctlr->card.io+Vptr0, 0x00);
        !           213: 
        !           214:        /*
        !           215:         * Finally, init the 8390, set the ethernet address
        !           216:         * and turn on the shared memory if any.
        !           217:         */
        !           218:        ctlr->card.dp8390 = ctlr->card.io;
        !           219:        dp8390reset(ctlr);
        !           220:        dp8390setea(ctlr);
        !           221: 
        !           222:        if(ctlr->card.ram)
        !           223:                outb(ctlr->card.io+Gacfr, Tcm|Rsel|Mbs0);
        !           224:        else
        !           225:                outb(ctlr->card.io+Gacfr, Tcm);
        !           226: 
        !           227:        return 0;
        !           228: }
        !           229: 
        !           230: static void*
        !           231: read(Ctlr *ctlr, void *to, ulong from, ulong len)
        !           232: {
        !           233:        uchar *addr, ctrl;
        !           234: 
        !           235:        /*
        !           236:         * If the interface has shared memory, just do a memmove.
        !           237:         * In this case, 'from' is an index into the shared memory.
        !           238:         * Due to 'hardware considerations', the memory is seen by
        !           239:         * the adapter at RamOffset, so we have to adjust.
        !           240:         */
        !           241:        if(ctlr->card.ram)
        !           242:                return memmove(to, (void*)(ctlr->card.ramstart+from-RamOffset), len);
        !           243: 
        !           244:        /*
        !           245:         * Polled I/O. This should be tuned.
        !           246:         * Set up the dma registers and pump the fifo.
        !           247:         */
        !           248:        outb(ctlr->card.io+Dalsb, from & 0xFF);
        !           249:        outb(ctlr->card.io+Damsb, (from>>8) & 0xFF);
        !           250:        ctrl = inb(ctlr->card.io+Ctrl);
        !           251:        outb(ctlr->card.io+Ctrl, Start|ctrl);
        !           252:        addr = to;
        !           253:        while(len){
        !           254:                /*
        !           255:                 * The fifo is 8 bytes deep, we have to wait
        !           256:                 * until it's ready before stuffing it.
        !           257:                 * The fifo is in its default configuration,
        !           258:                 * so we can do word accesses.
        !           259:                 */
        !           260:                while((inb(ctlr->card.io+Streg) & Dprdy) == 0)
        !           261:                        ;
        !           262:                if(len >= 8){
        !           263:                        inss(ctlr->card.io+Rfmsb, addr, 4);
        !           264:                        addr += 8;
        !           265:                        len -= 8;
        !           266:                }
        !           267:                else{
        !           268:                        insb(ctlr->card.io+Rfmsb, addr, len);
        !           269:                        break;
        !           270:                }
        !           271:        }
        !           272:        outb(ctlr->card.io+Ctrl, ctrl);
        !           273:        return to;
        !           274: }
        !           275: 
        !           276: static void*
        !           277: write(Ctlr *ctlr, ulong to, void *from, ulong len)
        !           278: {
        !           279:        uchar *addr, ctrl;
        !           280: 
        !           281:        /*
        !           282:         * See the comments in 'read()' above.
        !           283:         */
        !           284:        if(ctlr->card.ram)
        !           285:                return memmove((void*)(ctlr->card.ramstart+to-RamOffset), from, len);
        !           286: 
        !           287:        outb(ctlr->card.io+Dalsb, to & 0xFF);
        !           288:        outb(ctlr->card.io+Damsb, (to>>8) & 0xFF);
        !           289:        ctrl = inb(ctlr->card.io+Ctrl);
        !           290:        outb(ctlr->card.io+Ctrl, Start|Ddir|ctrl);
        !           291:        addr = from;
        !           292:        while(len){
        !           293:                while((inb(ctlr->card.io+Streg) & Dprdy) == 0)
        !           294:                        ;
        !           295:                if(len >= 8){
        !           296:                        outss(ctlr->card.io+Rfmsb, addr, 4);
        !           297:                        addr += 8;
        !           298:                        len -= 8;
        !           299:                }
        !           300:                else{
        !           301:                        outsb(ctlr->card.io+Rfmsb, addr, len);
        !           302:                        break;
        !           303:                }
        !           304:        }
        !           305:        outb(ctlr->card.io+Ctrl, ctrl);
        !           306:        return (void*)to;
        !           307: }
        !           308: 
        !           309: Card ether503 = {
        !           310:        "3Com503",                      /* ident */
        !           311: 
        !           312:        reset,                          /* reset */
        !           313:        0,                              /* init */
        !           314:        dp8390attach,                   /* attach */
        !           315:        dp8390mode,                     /* mode */
        !           316: 
        !           317:        read,                           /* read */
        !           318:        write,                          /* write */
        !           319: 
        !           320:        dp8390receive,                  /* receive */
        !           321:        dp8390transmit,                 /* transmit */
        !           322:        dp8390intr,                     /* interrupt */
        !           323:        dp8390watch,                    /* watch */
        !           324:        dp8390overflow,                 /* overflow */
        !           325: 
        !           326:        0,                              /* io */
        !           327:        0,                              /* irq */
        !           328:        0,                              /* bit16 */
        !           329: 
        !           330:        0,                              /* ram */
        !           331:        0,                              /* ramstart */
        !           332:        0,                              /* ramstop */
        !           333: 
        !           334:        0,                              /* dp8390 */
        !           335:        0,                              /* data */
        !           336:        0,                              /* software bndry */
        !           337:        RamOffset/Dp8390BufSz,          /* tstart */
        !           338:        (RamOffset+0x600)/Dp8390BufSz,  /* pstart */
        !           339:        (RamOffset+8*1024)/Dp8390BufSz, /* pstop */
        !           340: };
        !           341: 
        !           342: void
        !           343: ether503link(void)
        !           344: {
        !           345:        addethercard("3C503",  ccc503reset);
        !           346: }

unix.superglobalmegacorp.com

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