| plan 9 kernel history: overview | file list | diff list |
1993/0212/pc/ether8003.c (diff list | history)
| pc/ether8003.c on 1992/1222 | ||
| 1992/1222 | #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "io.h" #include "devtab.h" #include "ether.h" enum { /* 83C584 Bus Interface Controller */ Msr = 0x00, /* Memory Select Register */ Icr = 0x01, /* Interface Configuration Register */ Iar = 0x02, /* I/O Address Register */ Bio = 0x03, /* BIOS ROM Address Register */ Irr = 0x04, /* Interrupt Request Register */ Laar = 0x05, /* LA Address Register */ Ijr = 0x06, /* Initialisation Jumpers */ Gp2 = 0x07, /* General Purpose Data Register */ Lar = 0x08, /* LAN Address Registers */ | |
| 1993/0212 | Id = 0x0E, /* Card ID byte */ | |
| 1992/1222 | Cksum = 0x0F, /* Checksum */ }; enum { /* Msr */ Rst = 0x80, /* software reset */ Menb = 0x40, /* memory enable */ }; enum { /* Laar */ ZeroWS16 = (1<<5), /* zero wait states for 16-bit ops */ L16en = (1<<6), /* enable 16-bit LAN operation */ M16en = (1<<7), /* enable 16-bit memory access */ }; /* * Mapping from configuration bits to interrupt level. */ static int intrmap[] = { 9, 3, 5, 7, 10, 11, 15, 4, }; /* * Get configuration parameters, enable memory. */ static int reset(Ctlr *ctlr) { int i; uchar msr, icr, laar, irr, sum; /* * Look for the interface. We read the LAN address ROM * and validate the checksum - the sum of all 8 bytes * should be 0xFF. */ | |
| 1993/0212 | for(ctlr->card.io = 0x200; ctlr->card.io < 0x400; ctlr->card.io += 0x20){ | |
| 1992/1222 | sum = 0; for(i = 0; i < sizeof(ctlr->ea); i++){ | |
| 1993/0212 | ctlr->ea[i] = inb(ctlr->card.io+Lar+i); | |
| 1992/1222 | sum += ctlr->ea[i]; } | |
| 1993/0212 | sum += inb(ctlr->card.io+Id); sum += inb(ctlr->card.io+Cksum); | |
| 1992/1222 | if(sum == 0xFF) break; } | |
| 1993/0212 | if(ctlr->card.io >= 0x400) | |
| 1992/1222 | return -1; /* * Found it, reset it. * Be careful to preserve the Msr address bits, * they don't get reloaded from the EEPROM on reset. */ | |
| 1993/0212 | msr = inb(ctlr->card.io+Msr); outb(ctlr->card.io+Msr, Rst|msr); | |
| 1992/1222 | delay(1); | |
| 1993/0212 | outb(ctlr->card.io+Msr, msr); | |
| 1992/1222 | delay(2); /* * Check for old, dumb 8003E, which doesn't have an interface * chip. Only the msr exists out of the 1st eight registers, reads * of the others just alias the 2nd eight registers, the LAN * address ROM. We can check icr, irr and laar against the ethernet * address read above and if they match it's an 8003E (or an * 8003EBT, 8003S, 8003SH or 8003WT, we don't care), in which * case the default irq gets used. */ | |
| 1993/0212 | msr = inb(ctlr->card.io+Msr); icr = inb(ctlr->card.io+Icr); laar = inb(ctlr->card.io+Laar); irr = inb(ctlr->card.io+Irr); | |
| 1992/1222 | if(icr != ctlr->ea[1] || irr != ctlr->ea[4] || laar != ctlr->ea[5]) | |
| 1993/0212 | ctlr->card.irq = intrmap[((irr>>5) & 0x3)|(icr & 0x4)]; | |
| 1992/1222 | else { | |
| 1993/0212 | msr = (((ulong)ctlr->card.ramstart)>>13) & 0x3F; | |
| 1992/1222 | icr = laar = 0; | |
| 1993/0212 | ctlr->card.watch = 0; | |
| 1992/1222 | } /* * Set up the bus-size, RAM address and RAM size * from the info in the configuration registers. */ | |
| 1993/0212 | ctlr->card.bit16 = icr & 0x1; | |
| 1992/1222 | ||
| 1993/0212 | ctlr->card.ram = 1; ctlr->card.ramstart = KZERO|((msr & 0x3F)<<13); if(ctlr->card.bit16) ctlr->card.ramstart |= (laar & 0x1F)<<19; | |
| 1992/1222 | else | |
| 1993/0212 | ctlr->card.ramstart |= 0x80000; | |
| 1992/1222 | if(icr & (1<<3)) | |
| 1993/0212 | ctlr->card.ramstop = 32*1024; | |
| 1992/1222 | else | |
| 1993/0212 | ctlr->card.ramstop = 8*1024; if(ctlr->card.bit16) ctlr->card.ramstop <<= 1; ctlr->card.ramstop += ctlr->card.ramstart; | |
| 1992/1222 | /* * Set the DP8390 ring addresses. */ | |
| 1993/0212 | ctlr->card.dp8390 = ctlr->card.io+0x10; ctlr->card.pstart = HOWMANY(sizeof(Etherpkt), Dp8390BufSz); ctlr->card.pstop = HOWMANY(ctlr->card.ramstop-ctlr->card.ramstart, Dp8390BufSz); ctlr->card.tstart = 0; | |
| 1992/1222 | /* * Enable interface RAM, set interface width. */ | |
| 1993/0212 | outb(ctlr->card.io+Msr, Menb|msr); if(ctlr->card.bit16) outb(ctlr->card.io+Laar, laar|L16en|M16en|ZeroWS16); | |
| 1992/1222 | /* * Finally, init the 8390 and set the * ethernet address. */ dp8390reset(ctlr); dp8390setea(ctlr); return 0; } | |
| 1993/0212 | static void* read(Ctlr *ctlr, void *to, ulong from, ulong len) { /* * In this case, 'from' is an index into the shared memory. */ memmove(to, (void*)(ctlr->card.ramstart+from), len); return to; } static void* write(Ctlr *ctlr, ulong to, void *from, ulong len) { /* * In this case, 'to' is an index into the shared memory. */ memmove((void*)(ctlr->card.ramstart+to), from, len); return (void*)to; } | |
| 1992/1222 | static void watch(Ctlr *ctlr) { uchar msr; int s; s = splhi(); | |
| 1993/0212 | msr = inb(ctlr->card.io+Msr); | |
| 1992/1222 | /* | |
| 1993/0212 | * If the card has reset itself, | |
| 1992/1222 | * start again. */ if((msr & Menb) == 0){ delay(100); dp8390reset(ctlr); etherinit(); wakeup(&ctlr->tr); wakeup(&ctlr->rr); } splx(s); } /* * Defaults are set for the dumb 8003E * which can't be autoconfigured. */ | |
| 1993/0212 | Card ether8003 = { "WD8003", /* ident */ | |
| 1992/1222 | ||
| 1993/0212 | reset, /* reset */ 0, /* init */ dp8390attach, /* attach */ dp8390mode, /* mode */ | |
| 1992/1222 | ||
| 1993/0212 | read, /* read */ write, /* write */ dp8390receive, /* receive */ dp8390transmit, /* transmit */ dp8390intr, /* interrupt */ watch, /* watch */ 0, /* overflow */ 0x280, /* io */ 3, /* irq */ 0, /* bit16 */ 1, /* ram */ 0xD0000, /* ramstart */ 0xD0000+8*1024, /* ramstop */ | |
| 1992/1222 | }; | |