]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/etherwavelan.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / etherwavelan.c
1 /* Pci/pcmcia code for wavelan.c */
2
3 #include "u.h"
4 #include "../port/lib.h"
5 #include "mem.h"
6 #include "dat.h"
7 #include "fns.h"
8 #include "io.h"
9 #include "../port/error.h"
10 #include "../port/netif.h"
11 #include "../port/etherif.h"
12
13 #include "wavelan.h"
14
15 static int
16 wavelanpcmciareset(Ether *ether)
17 {
18         int i;
19         char *p;
20         Ctlr *ctlr;
21
22         if((ctlr = malloc(sizeof(Ctlr))) == nil)
23                 return -1;
24
25         ilock(ctlr);
26         ctlr->ctlrno = ether->ctlrno;
27
28         if (ether->port==0)
29                 ether->port=WDfltIOB;
30         ctlr->iob = ether->port;
31
32         if (ether->irq==0)
33                 ether->irq=WDfltIRQ;
34
35         if (ioalloc(ether->port,WIOLen,0,"wavelan")<0){
36         //      print("#l%d: port 0x%lx in use\n",
37         //                      ether->ctlrno, ether->port);
38                 goto abort1;
39         }
40
41         /*
42          * If id= is specified, card must match.  Otherwise try generic.
43          */
44         ctlr->slot = -1;
45         for(i=0; i<ether->nopt; i++){
46                 if(cistrncmp(ether->opt[i], "id=", 3) == 0){
47                         if((ctlr->slot = pcmspecial(&ether->opt[i][3], ether)) < 0)
48                                 goto abort;
49                         break;
50                 }
51         }
52         if(ctlr->slot == -1){
53                 for (i=0; wavenames[i]; i++)
54                         if((ctlr->slot = pcmspecial(wavenames[i], ether))>=0)
55                                 break;
56                 if(!wavenames[i]){
57                         DEBUG("no wavelan found\n");
58                         goto abort;
59                 }
60         }
61
62         // DEBUG("#l%d: port=0x%lx irq=%ld\n",
63         //              ether->ctlrno, ether->port, ether->irq);
64
65         if(wavelanreset(ether, ctlr) < 0){
66         abort:
67                 iofree(ether->port);
68         abort1:
69                 iunlock(ctlr);
70                 free(ctlr);
71                 ether->ctlr = nil;
72                 return -1;
73         }
74
75         for(i = 0; i < ether->nopt; i++){
76                 if(p = strchr(ether->opt[i], '='))
77                         *p = ' ';
78                 w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
79         }
80
81         iunlock(ctlr);
82         return 0;
83 }
84
85 static struct {
86         int vid;
87         int did;
88 } wavelanpci[] = {
89         0x1260, 0x3873, /* Intersil Prism2.5 */
90         0x1737, 0x0019, /* Linksys WPC-11 untested */
91 };
92
93 static Ctlr *ctlrhead, *ctlrtail;
94
95 static void
96 wavelanpciscan(void)
97 {
98         int i;
99         void *mem;
100         Pcidev *p;
101         Ctlr *ctlr;
102
103         p = nil;
104         while(p = pcimatch(p, 0, 0)){
105                 for(i=0; i<nelem(wavelanpci); i++)
106                         if(p->vid == wavelanpci[i].vid && p->did == wavelanpci[i].did)
107                                 break;
108                 if(i==nelem(wavelanpci))
109                         continue;
110
111                 /*
112                  * On the Prism, bar[0] is the memory-mapped register address (4KB),
113                  */
114                 if(p->mem[0].size != 4096){
115                         print("wavelanpci: %.4ux %.4ux: unlikely mmio size\n", p->vid, p->did);
116                         continue;
117                 }
118
119                 ctlr = malloc(sizeof(Ctlr));
120                 if(ctlr == nil){
121                         print("wavelanpci: can't allocate memory\n");
122                         continue;
123                 }
124                 ctlr->pcidev = p;
125                 mem = vmap(p->mem[0].bar&~0xF, p->mem[0].size);
126                 if(mem == nil){
127                         print("wavelanpci: %.4ux %.4ux: vmap 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
128                         free(ctlr);
129                         continue;
130                 }
131                 ctlr->mmb = mem;
132                 if(ctlrhead != nil)
133                         ctlrtail->next = ctlr;
134                 else
135                         ctlrhead = ctlr;
136                 ctlrtail = ctlr;
137         }
138 }
139
140 static int
141 wavelanpcireset(Ether *ether)
142 {
143         int i;
144         char *p;
145         Ctlr *ctlr;
146
147         if(ctlrhead == nil)
148                 wavelanpciscan();
149
150         /*
151          * Allow plan9.ini to set vid, did?
152          */
153         for(ctlr=ctlrhead; ctlr!=nil; ctlr=ctlr->next)
154                 if(ctlr->active == 0)
155                         break;
156         if(ctlr == nil)
157                 return -1;
158
159         ctlr->active = 1;
160
161         ilock(ctlr);
162         pcienable(ctlr->pcidev);
163         ether->irq = ctlr->pcidev->intl;
164         ether->tbdf = ctlr->pcidev->tbdf;
165
166         /*
167          * Really hard reset.
168          */
169         csr_outs(ctlr, WR_PciCor, 0x0080);
170         delay(250);
171         csr_outs(ctlr, WR_PciCor, 0x0000);
172         delay(500);
173         for(i=0; i<2*10; i++){
174                 if(!(csr_ins(ctlr, WR_Cmd)&WCmdBusy))
175                         break;
176                 delay(100);
177         }
178         if(i >= 2*10)
179                 print("wavelan pci %.4ux %.4ux: reset timeout %.4ux\n",
180                         ctlr->pcidev->vid, ctlr->pcidev->did, csr_ins(ctlr, WR_Cmd));
181
182         if(wavelanreset(ether, ctlr) < 0){
183                 iunlock(ctlr);
184                 ether->ctlr = nil;
185                 return -1;
186         }
187
188         for(i = 0; i < ether->nopt; i++){
189                 if(p = strchr(ether->opt[i], '='))
190                         *p = ' ';
191                 w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
192         }
193         pcisetbme(ctlr->pcidev);
194         iunlock(ctlr);
195         return 0;
196 }
197         
198 void
199 etherwavelanlink(void)
200 {
201         addethercard("wavelan", wavelanpcmciareset);
202         addethercard("wavelanpci", wavelanpcireset);
203 }