Further parallelize USB init by launching a thread per usb port.
[seabios.git] / src / usb-uhci.c
1 // Code for handling UHCI USB controllers.
2 //
3 // Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
4 //
5 // This file may be distributed under the terms of the GNU LGPLv3 license.
6
7 #include "util.h" // dprintf
8 #include "pci.h" // pci_bdf_to_bus
9 #include "config.h" // CONFIG_*
10 #include "ioport.h" // outw
11 #include "usb-uhci.h" // USBLEGSUP
12 #include "pci_regs.h" // PCI_BASE_ADDRESS_4
13 #include "usb.h" // struct usb_s
14 #include "farptr.h" // GET_FLATPTR
15 #include "biosvar.h" // GET_GLOBAL
16 #include "usb-hub.h" // struct usbhub_s
17
18
19 /****************************************************************
20  * Root hub
21  ****************************************************************/
22
23 static void
24 init_uhci_port(void *data)
25 {
26     struct usbhub_s *hub = data;
27     u32 port = hub->port; // XXX - find better way to pass port
28     u16 ioport = hub->cntl->uhci.iobase + USBPORTSC1 + port * 2;
29
30     u16 status = inw(ioport);
31     if (!(status & USBPORTSC_CCS))
32         // No device
33         goto done;
34
35     // XXX - if just powered up, need to wait for USB_TIME_ATTDB?
36
37     // Reset port
38     outw(USBPORTSC_PR, ioport);
39     msleep(USB_TIME_DRSTR);
40     mutex_lock(&hub->cntl->resetlock);
41     outw(0, ioport);
42     udelay(6); // 64 high-speed bit times
43     status = inw(ioport);
44     if (!(status & USBPORTSC_CCS))
45         // No longer connected
46         goto resetfail;
47     outw(USBPORTSC_PE, ioport);
48     struct usb_pipe *pipe = usb_set_address(
49         hub->cntl, !!(status & USBPORTSC_LSDA));
50     if (!pipe)
51         goto resetfail;
52     mutex_unlock(&hub->cntl->resetlock);
53
54     // Configure port
55     int count = configure_usb_device(pipe);
56     free_pipe(pipe);
57     if (! count)
58         // Disable port
59         outw(0, ioport);
60     hub->devcount += count;
61 done:
62     hub->threads--;
63     return;
64
65 resetfail:
66     outw(0, ioport);
67     mutex_unlock(&hub->cntl->resetlock);
68     goto done;
69 }
70
71 // Find any devices connected to the root hub.
72 static int
73 check_ports(struct usb_s *cntl)
74 {
75     ASSERT32FLAT();
76     struct usbhub_s hub;
77     memset(&hub, 0, sizeof(hub));
78     hub.cntl = cntl;
79     hub.threads = 2;
80
81     // Launch a thread for every port.
82     run_thread(init_uhci_port, &hub);
83     hub.port = 1;
84     run_thread(init_uhci_port, &hub);
85
86     // Wait for threads to complete.
87     while (hub.threads)
88         yield();
89
90     return hub.devcount;
91 }
92
93
94 /****************************************************************
95  * Setup
96  ****************************************************************/
97
98 static void
99 reset_uhci(struct usb_s *cntl)
100 {
101     // XXX - don't reset if not needed.
102
103     // Reset PIRQ and SMI
104     pci_config_writew(cntl->bdf, USBLEGSUP, USBLEGSUP_RWC);
105
106     // Reset the HC
107     outw(USBCMD_HCRESET, cntl->uhci.iobase + USBCMD);
108     udelay(5);
109
110     // Disable interrupts and commands (just to be safe).
111     outw(0, cntl->uhci.iobase + USBINTR);
112     outw(0, cntl->uhci.iobase + USBCMD);
113 }
114
115 static void
116 configure_uhci(struct usb_s *cntl)
117 {
118     // Allocate ram for schedule storage
119     struct uhci_td *term_td = malloc_high(sizeof(*term_td));
120     struct uhci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl));
121     struct uhci_qh *intr_qh = malloc_high(sizeof(*intr_qh));
122     struct uhci_qh *term_qh = malloc_high(sizeof(*term_qh));
123     if (!term_td || !fl || !intr_qh || !term_qh) {
124         warn_noalloc();
125         free(term_td);
126         free(fl);
127         free(intr_qh);
128         free(term_qh);
129         return;
130     }
131
132     // Work around for PIIX errata
133     memset(term_td, 0, sizeof(*term_td));
134     term_td->link = UHCI_PTR_TERM;
135     term_td->token = (uhci_explen(0) | (0x7f << TD_TOKEN_DEVADDR_SHIFT)
136                       | USB_PID_IN);
137     memset(term_qh, 0, sizeof(*term_qh));
138     term_qh->element = (u32)term_td;
139     term_qh->link = UHCI_PTR_TERM;
140
141     // Set schedule to point to primary intr queue head
142     memset(intr_qh, 0, sizeof(*intr_qh));
143     intr_qh->element = UHCI_PTR_TERM;
144     intr_qh->link = (u32)term_qh | UHCI_PTR_QH;
145     int i;
146     for (i=0; i<ARRAY_SIZE(fl->links); i++)
147         fl->links[i] = (u32)intr_qh | UHCI_PTR_QH;
148     cntl->uhci.framelist = fl;
149     cntl->uhci.control_qh = cntl->uhci.bulk_qh = intr_qh;
150     barrier();
151
152     // Set the frame length to the default: 1 ms exactly
153     outb(USBSOF_DEFAULT, cntl->uhci.iobase + USBSOF);
154
155     // Store the frame list base address
156     outl((u32)fl->links, cntl->uhci.iobase + USBFLBASEADD);
157
158     // Set the current frame number
159     outw(0, cntl->uhci.iobase + USBFRNUM);
160 }
161
162 static void
163 start_uhci(struct usb_s *cntl)
164 {
165     // Mark as configured and running with a 64-byte max packet.
166     outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, cntl->uhci.iobase + USBCMD);
167 }
168
169 void
170 uhci_init(void *data)
171 {
172     if (! CONFIG_USB_UHCI)
173         return;
174     struct usb_s *cntl = data;
175
176     // XXX - don't call pci_config_XXX from a thread
177     cntl->type = USB_TYPE_UHCI;
178     cntl->uhci.iobase = (pci_config_readl(cntl->bdf, PCI_BASE_ADDRESS_4)
179                          & PCI_BASE_ADDRESS_IO_MASK);
180
181     dprintf(3, "UHCI init on dev %02x:%02x.%x (io=%x)\n"
182             , pci_bdf_to_bus(cntl->bdf), pci_bdf_to_dev(cntl->bdf)
183             , pci_bdf_to_fn(cntl->bdf), cntl->uhci.iobase);
184
185     pci_config_maskw(cntl->bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
186
187     reset_uhci(cntl);
188     configure_uhci(cntl);
189     start_uhci(cntl);
190
191     int count = check_ports(cntl);
192     free_pipe(cntl->defaultpipe);
193     if (! count) {
194         // XXX - no devices; free data structures.
195     }
196 }
197
198
199 /****************************************************************
200  * End point communication
201  ****************************************************************/
202
203 static int
204 wait_qh(struct usb_s *cntl, struct uhci_qh *qh)
205 {
206     // XXX - 500ms just a guess
207     u64 end = calc_future_tsc(500);
208     for (;;) {
209         if (qh->element & UHCI_PTR_TERM)
210             return 0;
211         if (check_time(end)) {
212             warn_timeout();
213             struct uhci_td *td = (void*)(qh->element & ~UHCI_PTR_BITS);
214             dprintf(1, "Timeout on wait_qh %p (td=%p s=%x c=%x/%x)\n"
215                     , qh, td, td->status
216                     , inw(cntl->uhci.iobase + USBCMD)
217                     , inw(cntl->uhci.iobase + USBSTS));
218             return -1;
219         }
220         yield();
221     }
222 }
223
224 // Wait for next USB frame to start - for ensuring safe memory release.
225 static void
226 uhci_waittick(struct usb_s *cntl)
227 {
228     barrier();
229     u16 iobase = GET_GLOBAL(cntl->uhci.iobase);
230     u16 startframe = inw(iobase + USBFRNUM);
231     u64 end = calc_future_tsc(1000 * 5);
232     for (;;) {
233         if (inw(iobase + USBFRNUM) != startframe)
234             break;
235         if (check_time(end)) {
236             warn_timeout();
237             return;
238         }
239         yield();
240     }
241 }
242
243 struct uhci_pipe {
244     struct uhci_qh qh;
245     struct uhci_td *next_td;
246     struct usb_pipe pipe;
247 };
248
249 void
250 uhci_free_pipe(struct usb_pipe *p)
251 {
252     if (! CONFIG_USB_UHCI)
253         return;
254     struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
255     u32 endp = pipe->pipe.endp;
256     dprintf(7, "uhci_free_pipe %x\n", endp);
257     struct usb_s *cntl = endp2cntl(endp);
258
259     struct uhci_framelist *fl = cntl->uhci.framelist;
260     struct uhci_qh *pos = (void*)(fl->links[0] & ~UHCI_PTR_BITS);
261     for (;;) {
262         u32 link = pos->link;
263         if (link == UHCI_PTR_TERM) {
264             // Not found?!  Exit without freeing.
265             warn_internalerror();
266             return;
267         }
268         struct uhci_qh *next = (void*)(link & ~UHCI_PTR_BITS);
269         if (next == &pipe->qh) {
270             pos->link = next->link;
271             if (cntl->uhci.control_qh == next)
272                 cntl->uhci.control_qh = pos;
273             if (cntl->uhci.bulk_qh == next)
274                 cntl->uhci.bulk_qh = pos;
275             uhci_waittick(cntl);
276             free(pipe);
277             return;
278         }
279         pos = next;
280     }
281 }
282
283 struct usb_pipe *
284 uhci_alloc_control_pipe(u32 endp)
285 {
286     if (! CONFIG_USB_UHCI)
287         return NULL;
288     struct usb_s *cntl = endp2cntl(endp);
289     dprintf(7, "uhci_alloc_control_pipe %x\n", endp);
290
291     // Allocate a queue head.
292     struct uhci_pipe *pipe = malloc_tmphigh(sizeof(*pipe));
293     if (!pipe) {
294         warn_noalloc();
295         return NULL;
296     }
297     pipe->qh.element = UHCI_PTR_TERM;
298     pipe->next_td = 0;
299     pipe->pipe.endp = endp;
300
301     // Add queue head to controller list.
302     struct uhci_qh *control_qh = cntl->uhci.control_qh;
303     pipe->qh.link = control_qh->link;
304     barrier();
305     control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
306     if (cntl->uhci.bulk_qh == control_qh)
307         cntl->uhci.bulk_qh = &pipe->qh;
308     return &pipe->pipe;
309 }
310
311 int
312 uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
313              , void *data, int datasize)
314 {
315     ASSERT32FLAT();
316     if (! CONFIG_USB_UHCI)
317         return -1;
318     struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
319     u32 endp = pipe->pipe.endp;
320
321     dprintf(5, "uhci_control %x\n", endp);
322     struct usb_s *cntl = endp2cntl(endp);
323     int maxpacket = endp2maxsize(endp);
324     int lowspeed = endp2speed(endp);
325     int devaddr = endp2devaddr(endp) | (endp2ep(endp) << 7);
326
327     // Setup transfer descriptors
328     int count = 2 + DIV_ROUND_UP(datasize, maxpacket);
329     struct uhci_td *tds = malloc_tmphigh(sizeof(*tds) * count);
330
331     tds[0].link = (u32)&tds[1] | UHCI_PTR_DEPTH;
332     tds[0].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
333                      | TD_CTRL_ACTIVE);
334     tds[0].token = (uhci_explen(cmdsize) | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
335                     | USB_PID_SETUP);
336     tds[0].buffer = (void*)cmd;
337     int toggle = TD_TOKEN_TOGGLE;
338     int i;
339     for (i=1; i<count-1; i++) {
340         tds[i].link = (u32)&tds[i+1] | UHCI_PTR_DEPTH;
341         tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
342                          | TD_CTRL_ACTIVE);
343         int len = (i == count-2 ? (datasize - (i-1)*maxpacket) : maxpacket);
344         tds[i].token = (uhci_explen(len) | toggle
345                         | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
346                         | (dir ? USB_PID_IN : USB_PID_OUT));
347         tds[i].buffer = data + (i-1) * maxpacket;
348         toggle ^= TD_TOKEN_TOGGLE;
349     }
350     tds[i].link = UHCI_PTR_TERM;
351     tds[i].status = (uhci_maxerr(0) | (lowspeed ? TD_CTRL_LS : 0)
352                      | TD_CTRL_ACTIVE);
353     tds[i].token = (uhci_explen(0) | TD_TOKEN_TOGGLE
354                     | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
355                     | (dir ? USB_PID_OUT : USB_PID_IN));
356     tds[i].buffer = 0;
357
358     // Transfer data
359     barrier();
360     pipe->qh.element = (u32)&tds[0];
361     int ret = wait_qh(cntl, &pipe->qh);
362     if (ret) {
363         pipe->qh.element = UHCI_PTR_TERM;
364         uhci_waittick(cntl);
365     }
366     free(tds);
367     return ret;
368 }
369
370 struct usb_pipe *
371 uhci_alloc_bulk_pipe(u32 endp)
372 {
373     if (! CONFIG_USB_UHCI)
374         return NULL;
375     struct usb_s *cntl = endp2cntl(endp);
376     dprintf(7, "uhci_alloc_bulk_pipe %x\n", endp);
377
378     // Allocate a queue head.
379     struct uhci_pipe *pipe = malloc_low(sizeof(*pipe));
380     if (!pipe) {
381         warn_noalloc();
382         return NULL;
383     }
384     pipe->qh.element = UHCI_PTR_TERM;
385     pipe->next_td = 0;
386     pipe->pipe.endp = endp;
387
388     // Add queue head to controller list.
389     struct uhci_qh *bulk_qh = cntl->uhci.bulk_qh;
390     pipe->qh.link = bulk_qh->link;
391     barrier();
392     bulk_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
393
394     return &pipe->pipe;
395 }
396
397 static int
398 wait_td(struct uhci_td *td)
399 {
400     u64 end = calc_future_tsc(5000); // XXX - lookup real time.
401     u32 status;
402     for (;;) {
403         status = td->status;
404         if (!(status & TD_CTRL_ACTIVE))
405             break;
406         if (check_time(end)) {
407             warn_timeout();
408             return -1;
409         }
410         yield();
411     }
412     if (status & TD_CTRL_ANY_ERROR) {
413         dprintf(1, "wait_td error - status=%x\n", status);
414         return -2;
415     }
416     return 0;
417 }
418
419 #define STACKTDS 4
420 #define TDALIGN 16
421
422 int
423 uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
424 {
425     struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
426     u32 endp = GET_FLATPTR(pipe->pipe.endp);
427     dprintf(7, "uhci_send_bulk qh=%p endp=%x dir=%d data=%p size=%d\n"
428             , &pipe->qh, endp, dir, data, datasize);
429     int maxpacket = endp2maxsize(endp);
430     int lowspeed = endp2speed(endp);
431     int devaddr = endp2devaddr(endp) | (endp2ep(endp) << 7);
432     int toggle = (u32)GET_FLATPTR(pipe->next_td); // XXX
433
434     // Allocate 4 tds on stack (16byte aligned)
435     u8 tdsbuf[sizeof(struct uhci_td) * STACKTDS + TDALIGN - 1];
436     struct uhci_td *tds = (void*)ALIGN((u32)tdsbuf, TDALIGN);
437     memset(tds, 0, sizeof(*tds) * STACKTDS);
438
439     // Enable tds
440     SET_FLATPTR(pipe->qh.element, (u32)MAKE_FLATPTR(GET_SEG(SS), tds));
441
442     int tdpos = 0;
443     while (datasize) {
444         struct uhci_td *td = &tds[tdpos++ % STACKTDS];
445         int ret = wait_td(td);
446         if (ret)
447             goto fail;
448
449         int transfer = datasize;
450         if (transfer > maxpacket)
451             transfer = maxpacket;
452         struct uhci_td *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS)
453                                                  , &tds[tdpos % STACKTDS]);
454         td->link = (transfer==datasize ? UHCI_PTR_TERM : (u32)nexttd_fl);
455         td->token = (uhci_explen(transfer) | toggle
456                      | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
457                      | (dir ? USB_PID_IN : USB_PID_OUT));
458         td->buffer = data;
459         barrier();
460         td->status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
461                       | TD_CTRL_ACTIVE);
462         toggle ^= TD_TOKEN_TOGGLE;
463
464         data += transfer;
465         datasize -= transfer;
466     }
467     int i;
468     for (i=0; i<STACKTDS; i++) {
469         struct uhci_td *td = &tds[tdpos++ % STACKTDS];
470         int ret = wait_td(td);
471         if (ret)
472             goto fail;
473     }
474
475     SET_FLATPTR(pipe->next_td, (void*)toggle); // XXX
476     return 0;
477 fail:
478     dprintf(1, "uhci_send_bulk failed\n");
479     SET_FLATPTR(pipe->qh.element, UHCI_PTR_TERM);
480     uhci_waittick(endp2cntl(endp));
481     return -1;
482 }
483
484 struct usb_pipe *
485 uhci_alloc_intr_pipe(u32 endp, int frameexp)
486 {
487     if (! CONFIG_USB_UHCI)
488         return NULL;
489
490     dprintf(7, "uhci_alloc_intr_pipe %x %d\n", endp, frameexp);
491     if (frameexp > 10)
492         frameexp = 10;
493     struct usb_s *cntl = endp2cntl(endp);
494     int maxpacket = endp2maxsize(endp);
495     int lowspeed = endp2speed(endp);
496     int devaddr = endp2devaddr(endp) | (endp2ep(endp) << 7);
497     // Determine number of entries needed for 2 timer ticks.
498     int ms = 1<<frameexp;
499     int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms);
500     struct uhci_pipe *pipe = malloc_low(sizeof(*pipe));
501     struct uhci_td *tds = malloc_low(sizeof(*tds) * count);
502     if (!pipe || !tds) {
503         warn_noalloc();
504         goto fail;
505     }
506     if (maxpacket > sizeof(tds[0].data))
507         goto fail;
508     pipe->qh.element = (u32)tds;
509     int toggle = 0;
510     int i;
511     for (i=0; i<count; i++) {
512         tds[i].link = (i==count-1 ? (u32)&tds[0] : (u32)&tds[i+1]);
513         tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
514                          | TD_CTRL_ACTIVE);
515         tds[i].token = (uhci_explen(maxpacket) | toggle
516                         | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
517                         | USB_PID_IN);
518         tds[i].buffer = &tds[i].data;
519         toggle ^= TD_TOKEN_TOGGLE;
520     }
521
522     pipe->next_td = &tds[0];
523     pipe->pipe.endp = endp;
524
525     // Add to interrupt schedule.
526     struct uhci_framelist *fl = cntl->uhci.framelist;
527     if (frameexp == 0) {
528         // Add to existing interrupt entry.
529         struct uhci_qh *intr_qh = (void*)(fl->links[0] & ~UHCI_PTR_BITS);
530         pipe->qh.link = intr_qh->link;
531         barrier();
532         intr_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
533         if (cntl->uhci.control_qh == intr_qh)
534             cntl->uhci.control_qh = &pipe->qh;
535         if (cntl->uhci.bulk_qh == intr_qh)
536             cntl->uhci.bulk_qh = &pipe->qh;
537     } else {
538         int startpos = 1<<(frameexp-1);
539         pipe->qh.link = fl->links[startpos];
540         barrier();
541         for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms)
542             fl->links[i] = (u32)&pipe->qh | UHCI_PTR_QH;
543     }
544
545     return &pipe->pipe;
546 fail:
547     free(pipe);
548     free(tds);
549     return NULL;
550 }
551
552 int
553 uhci_poll_intr(struct usb_pipe *p, void *data)
554 {
555     ASSERT16();
556     if (! CONFIG_USB_UHCI)
557         return -1;
558
559     struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
560     struct uhci_td *td = GET_FLATPTR(pipe->next_td);
561     u32 status = GET_FLATPTR(td->status);
562     u32 token = GET_FLATPTR(td->token);
563     if (status & TD_CTRL_ACTIVE)
564         // No intrs found.
565         return -1;
566     // XXX - check for errors.
567
568     // Copy data.
569     memcpy_far(GET_SEG(SS), data
570                , FLATPTR_TO_SEG(td->data), (void*)FLATPTR_TO_OFFSET(td->data)
571                , uhci_expected_length(token));
572
573     // Reenable this td.
574     u32 next = GET_FLATPTR(td->link);
575     barrier();
576     SET_FLATPTR(td->status, (uhci_maxerr(0) | (status & TD_CTRL_LS)
577                              | TD_CTRL_ACTIVE));
578     SET_FLATPTR(pipe->next_td, (void*)(next & ~UHCI_PTR_BITS));
579
580     return 0;
581 }