Annotation of lucent/sys/src/9/pc/f002532, 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:  * Western Digital/Standard Microsystems Corporation cards (WD80[01]3).
                     14:  * Configuration code based on that provided by SMC.
                     15:  */
                     16: enum {                                 /* 83C584 Bus Interface Controller */
                     17:        Msr             = 0x00,         /* Memory Select Register */
                     18:        Icr             = 0x01,         /* Interface Configuration Register */
                     19:        Iar             = 0x02,         /* I/O Address Register */
                     20:        Bio             = 0x03,         /* BIOS ROM Address Register */
                     21:        Ear             = 0x03,         /* EEROM Address Register (shared with Bio) */
                     22:        Irr             = 0x04,         /* Interrupt Request Register */
                     23:        Laar            = 0x05,         /* LA Address Register */
                     24:        Ijr             = 0x06,         /* Initialisation Jumpers */
                     25:        Gp2             = 0x07,         /* General Purpose Data Register */
                     26:        Lar             = 0x08,         /* LAN Address Registers */
                     27:        Id              = 0x0E,         /* Card ID byte */
                     28:        Cksum           = 0x0F,         /* Checksum */
                     29: };
                     30: 
                     31: enum {                                 /* Msr */
                     32:        Rst             = 0x80,         /* software reset */
                     33:        Menb            = 0x40,         /* memory enable */
                     34: };
                     35: 
                     36: enum {                                 /* Icr */
                     37:        Bit16           = 0x01,         /* 16-bit bus */
                     38:        Other           = 0x02,         /* other register access */
                     39:        Ir2             = 0x04,         /* IR2 */
                     40:        Msz             = 0x08,         /* SRAM size */
                     41:        Rla             = 0x10,         /* recall LAN address */
                     42:        Rx7             = 0x20,         /* recall all but I/O and LAN address */
                     43:        Rio             = 0x40,         /* recall I/O address from EEROM */
                     44:        Sto             = 0x80,         /* non-volatile EEROM store */
                     45: };
                     46: 
                     47: enum {                                 /* Laar */
                     48:        ZeroWS16        = (1<<5),       /* zero wait states for 16-bit ops */
                     49:        L16en           = (1<<6),       /* enable 16-bit LAN operation */
                     50:        M16en           = (1<<7),       /* enable 16-bit memory access */
                     51: };
                     52: 
                     53: /*
                     54:  * Mapping from configuration bits to interrupt level.
                     55:  */
                     56: static int intrmap[] = {
                     57:        9, 3, 5, 7, 10, 11, 15, 4,
                     58: };
                     59: 
                     60: static void*
                     61: read(Ctlr *ctlr, void *to, ulong from, ulong len)
                     62: {
                     63:        /*
                     64:         * In this case, 'from' is an index into the shared memory.
                     65:         */
                     66:        memmove(to, (void*)(ctlr->card.mem+from), len);
                     67:        return to;
                     68: }
                     69: 
                     70: static void*
                     71: write(Ctlr *ctlr, ulong to, void *from, ulong len)
                     72: {
                     73:        /*
                     74:         * In this case, 'to' is an index into the shared memory.
                     75:         */
                     76:        memmove((void*)(ctlr->card.mem+to), from, len);
                     77:        return (void*)to;
                     78: }
                     79: 
                     80: static void
                     81: watch(Ctlr *ctlr)
                     82: {
                     83:        uchar msr;
                     84:        int s;
                     85: 
                     86:        s = splhi();
                     87:        msr = inb(ctlr->card.port+Msr);
                     88:        /*
                     89:         * If the card has reset itself,
                     90:         * start again.
                     91:         */
                     92:        if((msr & Menb) == 0){
                     93:                delay(100);
                     94: 
                     95:                dp8390reset(ctlr);
                     96:                etherinit();
                     97: 
                     98:                wakeup(&ctlr->tr);
                     99:                wakeup(&ctlr->rr);
                    100:        }
                    101:        splx(s);
                    102: }
                    103: 
                    104: /*
                    105:  * Get configuration parameters, enable memory.
                    106:  * There are opportunities here for buckets of code.
                    107:  * We'll try to resist.
                    108:  */
                    109: int
                    110: wd8003reset(Ctlr *ctlr)
                    111: {
                    112:        int i;
                    113:        uchar ea[Eaddrlen], ic[8], sum;
                    114:        ulong wd8003;
                    115: 
                    116:        /*
                    117:         * Set up the software configuration.
                    118:         * Use defaults for port, irq, mem and size if not specified.
                    119:         * Defaults are set for the dumb 8003E which can't be
                    120:         * autoconfigured.
                    121:         */
                    122:        if(ctlr->card.port == 0)
                    123:                ctlr->card.port = 0x280;
                    124:        if(ctlr->card.irq == 0)
                    125:                ctlr->card.irq = 3;
                    126:        if(ctlr->card.mem == 0)
                    127:                ctlr->card.mem = 0xD0000;
                    128:        if(ctlr->card.size == 0)
                    129:                ctlr->card.size = 8*1024;
                    130: 
                    131:        ctlr->card.reset = wd8003reset;
                    132:        ctlr->card.attach = dp8390attach;
                    133:        ctlr->card.mode = dp8390mode;
                    134:        ctlr->card.read = read;
                    135:        ctlr->card.write = write;
                    136:        ctlr->card.receive = dp8390receive;
                    137:        ctlr->card.transmit = dp8390transmit;
                    138:        ctlr->card.intr = dp8390intr;
                    139:        ctlr->card.watch = watch;
                    140:        ctlr->card.ram = 1;
                    141: 
                    142:        wd8003 = ctlr->card.port;
                    143:        /*
                    144:         * Look for the interface. We read the LAN address ROM
                    145:         * and validate the checksum - the sum of all 8 bytes
                    146:         * should be 0xFF.
                    147:         * While we're at it, get the (possible) interface chip
                    148:         * registers, we'll use them to check for aliasing later.
                    149:         */
                    150:        sum = 0;
                    151:        for(i = 0; i < sizeof(ctlr->ea); i++){
                    152:                ea[i] = inb(wd8003+Lar+i);
                    153:                sum += ea[i];
                    154:                ic[i] = inb(wd8003+i);
                    155:        }
                    156:        sum += inb(wd8003+Id);
                    157:        sum += inb(wd8003+Cksum);
                    158:        if(sum != 0xFF)
                    159:                return -1;
                    160: 
                    161:        /*
                    162:         * Check for old, dumb 8003E, which doesn't have an interface
                    163:         * chip. Only the msr exists out of the 1st eight registers, reads
                    164:         * of the others just alias the 2nd eight registers, the LAN
                    165:         * address ROM. We can check icr, irr and laar against the ethernet
                    166:         * address read above and if they match it's an 8003E (or an
                    167:         * 8003EBT, 8003S, 8003SH or 8003WT, we don't care), in which
                    168:         * case the default irq gets used.
                    169:         */
                    170:        if(memcmp(&ctlr->ea[1], &ic[1], 5) == 0){
                    171:                memset(ic, 0, sizeof(ic));
                    172:                ic[Msr] = (((ulong)ctlr->card.mem)>>13) & 0x3F;
                    173:                ctlr->card.watch = 0;
                    174:        }
                    175:        else{
                    176:                /*
                    177:                 * As a final sanity check for the 8013EBT, which doesn't have
                    178:                 * the 83C584 interface chip, but has 2 real registers, write Gp2 and if
                    179:                 * it reads back the same, it's not an 8013EBT.
                    180:                 */
                    181:                outb(wd8003+Gp2, 0xAA);
                    182:                inb(wd8003+Msr);                                /* wiggle bus */
                    183:                if(inb(wd8003+Gp2) != 0xAA){
                    184:                        memset(ic, 0, sizeof(ic));
                    185:                        ic[Msr] = (((ulong)ctlr->card.mem)>>13) & 0x3F;
                    186:                        ctlr->card.watch = 0;
                    187:                }
                    188:                else
                    189:                        ctlr->card.irq = intrmap[((ic[Irr]>>5) & 0x3)|(ic[Icr] & Ir2)];
                    190: 
                    191:                /*
                    192:                 * Check if 16-bit card.
                    193:                 * If Bit16 is read/write, then we have an 8-bit card.
                    194:                 * If Bit16 is set, we're in a 16-bit slot.
                    195:                 */
                    196:                outb(wd8003+Icr, ic[Icr]^Bit16);
                    197:                inb(wd8003+Msr);                                /* wiggle bus */
                    198:                if((inb(wd8003+Icr) & Bit16) == (ic[Icr] & Bit16)){
                    199:                        ctlr->card.bit16 = 1;
                    200:                        ic[Icr] &= ~Bit16;
                    201:                }
                    202:                outb(wd8003+Icr, ic[Icr]);
                    203: 
                    204:                if(ctlr->card.bit16 && (inb(wd8003+Icr) & Bit16) == 0)
                    205:                        ctlr->card.bit16 = 0;
                    206: 
                    207:                /*
                    208:                 * Force the memory size.
                    209:                 */
                    210:                if(ctlr->card.bit16)
                    211:                        ctlr->card.size = 16*1024;
                    212:                else
                    213:                        ctlr->card.size = 8*1024;
                    214:        }
                    215: 
                    216:        ctlr->card.mem = KZERO|((ic[Msr] & 0x3F)<<13);
                    217:        if(ctlr->card.bit16)
                    218:                ctlr->card.mem |= (ic[Laar] & 0x1F)<<19;
                    219:        else
                    220:                ctlr->card.mem |= 0x80000;
                    221: 
                    222:        if(ic[Icr] & Msz)
                    223:                ctlr->card.size <<= 2;
                    224: 
                    225:        /*
                    226:         * Set the DP8390 ring addresses.
                    227:         */
                    228:        ctlr->card.dp8390 = wd8003+0x10;
                    229:        ctlr->card.tstart = 0;
                    230:        ctlr->card.pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz);
                    231:        ctlr->card.pstop = HOWMANY(ctlr->card.size, Dp8390BufSz);
                    232: 
                    233:        /*
                    234:         * Enable interface RAM, set interface width.
                    235:         */
                    236:        outb(wd8003+Msr, ic[Msr]|Menb);
                    237:        if(ctlr->card.bit16)
                    238:                outb(wd8003+Laar, ic[Laar]|L16en|M16en|ZeroWS16);
                    239: 
                    240:        /*
                    241:         * Finally, init the 8390 and set the
                    242:         * ethernet address.
                    243:         */
                    244:        dp8390reset(ctlr);
                    245:        if((ctlr->ea[0]|ctlr->ea[1]|ctlr->ea[2]|ctlr->ea[3]|ctlr->ea[4]|ctlr->ea[5]) == 0)
                    246:                memmove(ctlr->ea, ea, Eaddrlen);
                    247:        dp8390setea(ctlr);
                    248: 
                    249:        if(getisa(ctlr->card.mem, ctlr->card.size, 0) == 0)
                    250:                panic("ether8003: 0x%lux reused", ctlr->card.mem);
                    251: 
                    252:        return 0;
                    253: }
                    254: 
                    255: void
                    256: ether8003link(void)
                    257: {
                    258:        addethercard("WD8003", wd8003reset);
                    259: }

unix.superglobalmegacorp.com

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