Annotation of lucent/sys/src/9/pc/f002532, 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:  * 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.