diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 21:39:35 +0000 |
| commit | 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch) | |
| tree | c6e220ba61db3a6ea4052e6841296d829654e664 /os/pc/etherec2t.c | |
| parent | 46439007cf417cbd9ac8049bb4122c890097a0fa (diff) | |
20060303
Diffstat (limited to 'os/pc/etherec2t.c')
| -rw-r--r-- | os/pc/etherec2t.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/os/pc/etherec2t.c b/os/pc/etherec2t.c new file mode 100644 index 00000000..ffbec852 --- /dev/null +++ b/os/pc/etherec2t.c @@ -0,0 +1,173 @@ +/* + * Supposed NE2000 PCMCIA clones, see the comments in ether2000.c + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "io.h" +#include "../port/error.h" +#include "../port/netif.h" + +#include "etherif.h" +#include "ether8390.h" + +enum { + Data = 0x10, /* offset from I/O base of data port */ + Reset = 0x1F, /* offset from I/O base of reset port */ +}; + +typedef struct Ec2t { + char* name; + int iochecksum; +} Ec2t; + +static Ec2t ec2tpcmcia[] = { + { "EC2T", 0, }, /* Linksys Combo PCMCIA EthernetCard */ + { "PCMPC100", 1, }, /* EtherFast 10/100 PC Card */ + { "PCM100", 1, }, /* EtherFast PCM100 Card */ + { "EN2216", 0, }, /* Accton EtherPair-PCMCIA */ + { "FA410TX", 1, }, /* Netgear FA410TX */ + { "Network Everywhere", 0, }, /* Linksys NP10T 10BaseT Card */ + { "10/100 Port Attached", 1, }, /* SMC 8040TX */ + { "FA411", 0 }, /* Netgear FA411 PCMCIA */ + { nil, 0, }, +}; + +static int +reset(Ether* ether) +{ + ushort buf[16]; + ulong port; + Dp8390 *ctlr; + int i, slot; + uchar ea[Eaddrlen], sum, x; + Ec2t *ec2t, tmpec2t; + + /* + * Set up the software configuration. + * Use defaults for port, irq, mem and size + * if not specified. + * The manual says 16KB memory, the box + * says 32KB. The manual seems to be correct. + */ + if(ether->port == 0) + ether->port = 0x300; + if(ether->irq == 0) + ether->irq = 9; + if(ether->mem == 0) + ether->mem = 0x4000; + if(ether->size == 0) + ether->size = 16*1024; + port = ether->port; + + if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0) + return -1; + slot = -1; + for(ec2t = ec2tpcmcia; ec2t->name != nil; ec2t++){ + if((slot = pcmspecial(ec2t->name, ether)) >= 0) + break; + } + if(ec2t->name == nil){ + ec2t = &tmpec2t; + ec2t->name = nil; + ec2t->iochecksum = 0; + for(i = 0; i < ether->nopt; i++){ + if(cistrncmp(ether->opt[i], "id=", 3) == 0){ + ec2t->name = ðer->opt[i][3]; + slot = pcmspecial(ec2t->name, ether); + } + else if(cistrncmp(ether->opt[i], "iochecksum", 10) == 0) + ec2t->iochecksum = 1; + } + } + if(slot < 0){ + iofree(port); + return -1; + } + + ether->ctlr = malloc(sizeof(Dp8390)); + ctlr = ether->ctlr; + ctlr->width = 2; + ctlr->ram = 0; + + ctlr->port = port; + ctlr->data = port+Data; + + ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz); + ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz); + ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz); + + ctlr->dummyrr = 0; + for(i = 0; i < ether->nopt; i++){ + if(cistrcmp(ether->opt[i], "nodummyrr") == 0) + ctlr->dummyrr = 0; + else if(cistrncmp(ether->opt[i], "dummyrr=", 8) == 0) + ctlr->dummyrr = strtol(ðer->opt[i][8], nil, 0); + } + + /* + * Reset the board. This is done by doing a read + * followed by a write to the Reset address. + */ + buf[0] = inb(port+Reset); + delay(2); + outb(port+Reset, buf[0]); + delay(2); + + /* + * Init the (possible) chip, then use the (possible) + * chip to read the (possible) PROM for ethernet address + * and a marker byte. + * Could just look at the DP8390 command register after + * initialisation has been tried, but that wouldn't be + * enough, there are other ethernet boards which could + * match. + */ + dp8390reset(ether); + sum = 0; + if(ec2t->iochecksum){ + /* + * These cards have the ethernet address in I/O space. + * There's a checksum over 8 bytes which sums to 0xFF. + */ + for(i = 0; i < 8; i++){ + x = inb(port+0x14+i); + sum += x; + buf[i] = (x<<8)|x; + } + } + else{ + memset(buf, 0, sizeof(buf)); + dp8390read(ctlr, buf, 0, sizeof(buf)); + if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57) + sum = 0xFF; + } + if(sum != 0xFF){ + pcmspecialclose(slot); + iofree(ether->port); + free(ether->ctlr); + return -1; + } + + /* + * Stupid machine. Shorts were asked for, + * shorts were delivered, although the PROM is a byte array. + * Set the ethernet address. + */ + memset(ea, 0, Eaddrlen); + if(memcmp(ea, ether->ea, Eaddrlen) == 0){ + for(i = 0; i < sizeof(ether->ea); i++) + ether->ea[i] = buf[i]; + } + dp8390setea(ether); + + return 0; +} + +void +etherec2tlink(void) +{ + addethercard("EC2T", reset); +} |
