1 /* 2 * Supposed NE2000 PCMCIA clones, see the comments in ether2000.c 3 */ 4 #include "u.h" 5 #include "../port/lib.h" 6 #include "mem.h" 7 #include "dat.h" 8 #include "fns.h" 9 #include "io.h" 10 #include "../port/error.h" 11 #include "../port/netif.h" 12 13 #include "etherif.h" 14 #include "ether8390.h" 15 16 enum { 17 Data = 0x10, /* offset from I/O base of data port */ 18 Reset = 0x1F, /* offset from I/O base of reset port */ 19 }; 20 21 typedef struct Ec2t { 22 char* name; 23 int iochecksum; 24 } Ec2t; 25 26 static Ec2t ec2tpcmcia[] = { 27 { "EC2T", 0, }, /* Linksys Combo PCMCIA EthernetCard */ 28 { "PCMPC100", 1, }, /* EtherFast 10/100 PC Card */ 29 { "PCM100", 1, }, /* EtherFast PCM100 Card */ 30 { "EN2216", 0, }, /* Accton EtherPair-PCMCIA */ 31 { "FA410TX", 1, }, /* Netgear FA410TX */ 32 { "FA411", 0 }, /* Netgear FA411 PCMCIA */ 33 { "Network Everywhere", 0, }, /* Linksys NP10T 10BaseT Card */ 34 { "10/100 Port Attached", 1, }, /* SMC 8040TX */ 35 { "8041TX-10/100-PC-Card-V2", 0 }, /* SMC 8041TX */ 36 { "SMC8022", 0}, /* SMC 8022 / EZCard-10-PCMCIA */ 37 { nil, 0, }, 38 }; 39 40 static int 41 reset(Ether* ether) 42 { 43 ushort buf[16]; 44 ulong port; 45 Dp8390 *ctlr; 46 int i, slot; 47 uchar ea[Eaddrlen], sum, x; 48 Ec2t *ec2t, tmpec2t; 49 50 /* 51 * Set up the software configuration. 52 * Use defaults for port, irq, mem and size 53 * if not specified. 54 * The manual says 16KB memory, the box 55 * says 32KB. The manual seems to be correct. 56 */ 57 if(ether->port == 0) 58 ether->port = 0x300; 59 if(ether->irq == 0) 60 ether->irq = 9; 61 if(ether->mem == 0) 62 ether->mem = 0x4000; 63 if(ether->size == 0) 64 ether->size = 16*1024; 65 port = ether->port; 66 67 if(ioalloc(ether->port, 0x20, 0, "ec2t") < 0) 68 return -1; 69 slot = -1; 70 for(ec2t = ec2tpcmcia; ec2t->name != nil; ec2t++){ 71 if((slot = pcmspecial(ec2t->name, ether)) >= 0) 72 break; 73 } 74 if(ec2t->name == nil){ 75 ec2t = &tmpec2t; 76 ec2t->name = nil; 77 ec2t->iochecksum = 0; 78 for(i = 0; i < ether->nopt; i++){ 79 if(cistrncmp(ether->opt[i], "id=", 3) == 0){ 80 ec2t->name = ðer->opt[i][3]; 81 slot = pcmspecial(ec2t->name, ether); 82 } 83 else if(cistrncmp(ether->opt[i], "iochecksum", 10) == 0) 84 ec2t->iochecksum = 1; 85 } 86 } 87 if(slot < 0){ 88 iofree(port); 89 return -1; 90 } 91 92 ether->ctlr = malloc(sizeof(Dp8390)); 93 ctlr = ether->ctlr; 94 ctlr->width = 2; 95 ctlr->ram = 0; 96 97 ctlr->port = port; 98 ctlr->data = port+Data; 99 100 ctlr->tstart = HOWMANY(ether->mem, Dp8390BufSz); 101 ctlr->pstart = ctlr->tstart + HOWMANY(sizeof(Etherpkt), Dp8390BufSz); 102 ctlr->pstop = ctlr->tstart + HOWMANY(ether->size, Dp8390BufSz); 103 104 ctlr->dummyrr = 0; 105 for(i = 0; i < ether->nopt; i++){ 106 if(cistrcmp(ether->opt[i], "nodummyrr") == 0) 107 ctlr->dummyrr = 0; 108 else if(cistrncmp(ether->opt[i], "dummyrr=", 8) == 0) 109 ctlr->dummyrr = strtol(ðer->opt[i][8], nil, 0); 110 } 111 112 /* 113 * Reset the board. This is done by doing a read 114 * followed by a write to the Reset address. 115 */ 116 buf[0] = inb(port+Reset); 117 delay(2); 118 outb(port+Reset, buf[0]); 119 delay(2); 120 121 /* 122 * Init the (possible) chip, then use the (possible) 123 * chip to read the (possible) PROM for ethernet address 124 * and a marker byte. 125 * Could just look at the DP8390 command register after 126 * initialisation has been tried, but that wouldn't be 127 * enough, there are other ethernet boards which could 128 * match. 129 */ 130 dp8390reset(ether); 131 sum = 0; 132 if(ec2t->iochecksum){ 133 /* 134 * These cards have the ethernet address in I/O space. 135 * There's a checksum over 8 bytes which sums to 0xFF. 136 */ 137 for(i = 0; i < 8; i++){ 138 x = inb(port+0x14+i); 139 sum += x; 140 buf[i] = (x<<8)|x; 141 } 142 } 143 else{ 144 memset(buf, 0, sizeof(buf)); 145 dp8390read(ctlr, buf, 0, sizeof(buf)); 146 if((buf[0x0E] & 0xFF) == 0x57 && (buf[0x0F] & 0xFF) == 0x57) 147 sum = 0xFF; 148 } 149 if(sum != 0xFF){ 150 pcmspecialclose(slot); 151 iofree(ether->port); 152 free(ether->ctlr); 153 return -1; 154 } 155 156 /* 157 * Stupid machine. Shorts were asked for, 158 * shorts were delivered, although the PROM is a byte array. 159 * Set the ethernet address. 160 */ 161 memset(ea, 0, Eaddrlen); 162 if(memcmp(ea, ether->ea, Eaddrlen) == 0){ 163 for(i = 0; i < sizeof(ether->ea); i++) 164 ether->ea[i] = buf[i]; 165 } 166 dp8390setea(ether); 167 168 return 0; 169 } 170 171 void 172 etherec2tlink(void) 173 { 174 addethercard("EC2T", reset); 175 } 176