]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/usbehcipc.c
kernel: cleanup the software mouse cursor mess
[plan9front.git] / sys / src / 9 / pc / usbehcipc.c
1 /*
2  * PC-specific code for
3  * USB Enhanced Host Controller Interface (EHCI) driver
4  * High speed USB 2.0.
5  */
6
7 #include        "u.h"
8 #include        "../port/lib.h"
9 #include        "mem.h"
10 #include        "dat.h"
11 #include        "fns.h"
12 #include        "io.h"
13 #include        "../port/error.h"
14 #include        "../port/usb.h"
15 #include        "usbehci.h"
16
17 static Ctlr* ctlrs[Nhcis];
18 static int maxehci = Nhcis;
19
20 static int
21 ehciecap(Ctlr *ctlr, int cap)
22 {
23         int i, off;
24
25         off = (ctlr->capio->capparms >> Ceecpshift) & Ceecpmask;
26         for(i=0; i<48; i++){
27                 if(off < 0x40 || (off & 3) != 0)
28                         break;
29                 if(pcicfgr8(ctlr->pcidev, off) == cap)
30                         return off;
31                 off = pcicfgr8(ctlr->pcidev, off+1);
32         }
33         return -1;
34 }
35
36 static void
37 getehci(Ctlr* ctlr)
38 {
39         int i, off;
40
41         off = ehciecap(ctlr, Clegacy);
42         if(off == -1)
43                 return;
44         if(getconf("*noehcihandoff") == nil && pcicfgr8(ctlr->pcidev, off+CLbiossem) != 0){
45                 dprint("ehci %#p: bios active, taking over...\n", ctlr->capio);
46                 pcicfgw8(ctlr->pcidev, off+CLossem, 1);
47                 for(i = 0; i < 100; i++){
48                         if(pcicfgr8(ctlr->pcidev, off+CLbiossem) == 0)
49                                 break;
50                         delay(10);
51                 }
52                 if(i == 100)
53                         print("ehci %#p: bios timed out\n", ctlr->capio);
54         }
55         pcicfgw32(ctlr->pcidev, off+CLcontrol, 0);      /* no SMIs */
56 }
57
58 static void
59 ehcireset(Ctlr *ctlr)
60 {
61         Eopio *opio;
62         int i;
63
64         ilock(ctlr);
65         dprint("ehci %#p reset\n", ctlr->capio);
66         opio = ctlr->opio;
67
68         /*
69          * reclaim from bios
70          */
71         getehci(ctlr);
72
73         /*
74          * halt and route ports to companion controllers
75          * until we are setup
76          */
77         ehcirun(ctlr, 0);
78         opio->config = 0;
79         coherence();
80
81         /* clear high 32 bits of address signals if it's 64 bits capable.
82          * This is probably not needed but it does not hurt and others do it.
83          */
84         if((ctlr->capio->capparms & C64) != 0){
85                 dprint("ehci: 64 bits\n");
86                 opio->seg = 0;
87                 coherence();
88         }
89
90         if(ehcidebugcapio != ctlr->capio){
91                 opio->cmd |= Chcreset;  /* controller reset */
92                 coherence();
93                 for(i = 0; i < 100; i++){
94                         if((opio->cmd & Chcreset) == 0)
95                                 break;
96                         delay(1);
97                 }
98                 if(i == 100)
99                         print("ehci %#p controller reset timed out\n", ctlr->capio);
100         }
101         opio->cmd |= Citc1;             /* 1 intr. per µframe */
102         coherence();
103         switch(opio->cmd & Cflsmask){
104         case Cfls1024:
105                 ctlr->nframes = 1024;
106                 break;
107         case Cfls512:
108                 ctlr->nframes = 512;
109                 break;
110         case Cfls256:
111                 ctlr->nframes = 256;
112                 break;
113         default:
114                 panic("ehci: unknown fls %ld", opio->cmd & Cflsmask);
115         }
116         dprint("ehci: %d frames\n", ctlr->nframes);
117         iunlock(ctlr);
118 }
119
120 static void
121 setdebug(Hci*, int d)
122 {
123         ehcidebug = d;
124 }
125
126 static void
127 shutdown(Hci *hp)
128 {
129         int i;
130         Ctlr *ctlr;
131         Eopio *opio;
132
133         ctlr = hp->aux;
134         ilock(ctlr);
135         opio = ctlr->opio;
136         opio->cmd |= Chcreset;          /* controller reset */
137         coherence();
138         for(i = 0; i < 100; i++){
139                 if((opio->cmd & Chcreset) == 0)
140                         break;
141                 delay(1);
142         }
143         if(i >= 100)
144                 print("ehci %#p controller reset timed out\n", ctlr->capio);
145         delay(100);
146         ehcirun(ctlr, 0);
147         opio->frbase = 0;
148         iunlock(ctlr);
149 }
150
151 static void
152 scanpci(void)
153 {
154         static int already = 0;
155         int i;
156         uintptr io;
157         Ctlr *ctlr;
158         Pcidev *p;
159         Ecapio *capio;
160
161         if(already)
162                 return;
163         already = 1;
164         p = nil;
165         while ((p = pcimatch(p, 0, 0)) != nil) {
166                 /*
167                  * Find EHCI controllers (Programming Interface = 0x20).
168                  */
169                 if(p->ccrb != Pcibcserial || p->ccru != Pciscusb)
170                         continue;
171                 switch(p->ccrp){
172                 case 0x20:
173                         io = p->mem[0].bar & ~0x0f;
174                         break;
175                 default:
176                         continue;
177                 }
178                 if(io == 0)
179                         continue;
180
181                 print("usbehci: %#x %#x: port %#p size %#x irq %d\n",
182                         p->vid, p->did, io, p->mem[0].size, p->intl);
183
184                 ctlr = malloc(sizeof(Ctlr));
185                 if(ctlr == nil){
186                         print("usbehci: no memory\n");
187                         continue;
188                 }
189
190                 if((capio = vmap(io, p->mem[0].size)) == nil){
191                         print("usbehci: cannot map mmio\n");
192                         free(ctlr);
193                         continue;
194                 }
195
196                 ctlr->pcidev = p;
197                 ctlr->base = io;
198                 ctlr->capio = capio;
199                 for(i = 0; i < Nhcis; i++)
200                         if(ctlrs[i] == nil){
201                                 ctlrs[i] = ctlr;
202                                 break;
203                         }
204                 if(i >= Nhcis)
205                         print("ehci: bug: more than %d controllers\n", Nhcis);
206
207                 /*
208                  * currently, if we enable a second ehci controller,
209                  * we'll wedge solid after iunlock in init for the second one.
210                  */
211                 if (i >= maxehci) {
212                         iprint("usbehci: ignoring controllers after first %d, "
213                                 "at %#p\n", maxehci, io);
214                         ctlrs[i] = nil;
215                 }
216         }
217 }
218
219 static int
220 reset(Hci *hp)
221 {
222         int i;
223         char *s;
224         Ctlr *ctlr;
225         Ecapio *capio;
226         Pcidev *p;
227         static Lock resetlck;
228
229         s = getconf("*maxehci");
230         if (s != nil && s[0] >= '0' && s[0] <= '9')
231                 maxehci = atoi(s);
232         if(maxehci == 0 || getconf("*nousbehci"))
233                 return -1;
234         ilock(&resetlck);
235         scanpci();
236
237         /*
238          * Any adapter matches if no hp->port is supplied,
239          * otherwise the ports must match.
240          */
241         ctlr = nil;
242         for(i = 0; i < Nhcis && ctlrs[i] != nil; i++){
243                 ctlr = ctlrs[i];
244                 if(ctlr->active == 0)
245                 if(hp->port == 0 || hp->port == ctlr->base){
246                         ctlr->active = 1;
247                         break;
248                 }
249         }
250         iunlock(&resetlck);
251         if(i >= Nhcis || ctlrs[i] == nil)
252                 return -1;
253
254         p = ctlr->pcidev;
255         pcienable(p);
256
257         hp->aux = ctlr;
258         hp->port = ctlr->base;
259         hp->irq = p->intl;
260         hp->tbdf = p->tbdf;
261
262         capio = ctlr->capio;
263         hp->nports = capio->parms & Cnports;
264
265         ddprint("echi: %s, ncc %lud npcc %lud\n",
266                 capio->parms & 0x10000 ? "leds" : "no leds",
267                 (capio->parms >> 12) & 0xf, (capio->parms >> 8) & 0xf);
268         ddprint("ehci: routing %s, %sport power ctl, %d ports\n",
269                 capio->parms & 0x40 ? "explicit" : "automatic",
270                 capio->parms & 0x10 ? "" : "no ", hp->nports);
271
272         ctlr->opio = (Eopio*)((uintptr)capio + (capio->cap & 0xff));
273         ehcireset(ctlr);
274         ehcimeminit(ctlr);
275         
276         pcisetbme(p);
277
278         /*
279          * Linkage to the generic HCI driver.
280          */
281         ehcilinkage(hp);
282         hp->shutdown = shutdown;
283         hp->debug = setdebug;
284         intrenable(hp->irq, hp->interrupt, hp, hp->tbdf, hp->type);
285
286         return 0;
287 }
288
289 void
290 usbehcilink(void)
291 {
292         addhcitype("ehci", reset);
293 }