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