Annotation of lucent/sys/src/9/pc/ether503.c, revision 1.1.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.