FreeBSD/Linux Kernel Cross Reference
sys/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 "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(ðer->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 ctlr->pcidev = p;
121 mem = vmap(p->mem[0].bar&~0xF, p->mem[0].size);
122 if(mem == nil){
123 print("wavelanpci: %.4ux %.4ux: vmap 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
124 free(ctlr);
125 continue;
126 }
127 ctlr->mmb = mem;
128 if(ctlrhead != nil)
129 ctlrtail->next = ctlr;
130 else
131 ctlrhead = ctlr;
132 ctlrtail = ctlr;
133 pcisetbme(p);
134 }
135 }
136
137 static int
138 wavelanpcireset(Ether *ether)
139 {
140 int i;
141 char *p;
142 Ctlr *ctlr;
143
144 if(ctlrhead == nil)
145 wavelanpciscan();
146
147 /*
148 * Allow plan9.ini to set vid, did?
149 */
150 for(ctlr=ctlrhead; ctlr!=nil; ctlr=ctlr->next)
151 if(ctlr->active == 0)
152 break;
153 if(ctlr == nil)
154 return -1;
155
156 ctlr->active = 1;
157 ilock(ctlr);
158 ether->irq = ctlr->pcidev->intl;
159 ether->tbdf = ctlr->pcidev->tbdf;
160
161 /*
162 * Really hard reset.
163 */
164 csr_outs(ctlr, WR_PciCor, 0x0080);
165 delay(250);
166 csr_outs(ctlr, WR_PciCor, 0x0000);
167 delay(500);
168 for(i=0; i<2*10; i++){
169 if(!(csr_ins(ctlr, WR_Cmd)&WCmdBusy))
170 break;
171 delay(100);
172 }
173 if(i >= 2*10)
174 print("wavelan pci %.4ux %.4ux: reset timeout %.4ux\n",
175 ctlr->pcidev->vid, ctlr->pcidev->did, csr_ins(ctlr, WR_Cmd));
176
177 if(wavelanreset(ether, ctlr) < 0){
178 iunlock(ctlr);
179 ether->ctlr = nil;
180 return -1;
181 }
182
183 for(i = 0; i < ether->nopt; i++){
184 if(p = strchr(ether->opt[i], '='))
185 *p = ' ';
186 w_option(ctlr, ether->opt[i], strlen(ether->opt[i]));
187 }
188 iunlock(ctlr);
189 return 0;
190 }
191
192 void
193 etherwavelanlink(void)
194 {
195 addethercard("wavelan", wavelanpcmciareset);
196 addethercard("wavelanpci", wavelanpcireset);
197 }
Cache object: ed7be3037e18cadb1a637723baa9d72f
|