Replace USB encoded 'u32 endp' scheme with explicit struct fields.
[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     dprintf(7, "uhci_free_pipe %p\n", p);
255     struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
256     struct usb_s *cntl = pipe->pipe.cntl;
257
258     struct uhci_framelist *fl = cntl->uhci.framelist;
259     struct uhci_qh *pos = (void*)(fl->links[0] & ~UHCI_PTR_BITS);
260     for (;;) {
261         u32 link = pos->link;
262         if (link == UHCI_PTR_TERM) {
263             // Not found?!  Exit without freeing.
264             warn_internalerror();
265             return;
266         }
267         struct uhci_qh *next = (void*)(link & ~UHCI_PTR_BITS);
268         if (next == &pipe->qh) {
269             pos->link = next->link;
270             if (cntl->uhci.control_qh == next)
271                 cntl->uhci.control_qh = pos;
272             if (cntl->uhci.bulk_qh == next)
273                 cntl->uhci.bulk_qh = pos;
274             uhci_waittick(cntl);
275             free(pipe);
276             return;
277         }
278         pos = next;
279     }
280 }
281
282 struct usb_pipe *
283 uhci_alloc_control_pipe(struct usb_pipe *dummy)
284 {
285     if (! CONFIG_USB_UHCI)
286         return NULL;
287     struct usb_s *cntl = dummy->cntl;
288     dprintf(7, "uhci_alloc_control_pipe %p\n", cntl);
289
290     // Allocate a queue head.
291     struct uhci_pipe *pipe = malloc_tmphigh(sizeof(*pipe));
292     if (!pipe) {
293         warn_noalloc();
294         return NULL;
295     }
296     memset(pipe, 0, sizeof(*pipe));
297     pipe->qh.element = UHCI_PTR_TERM;
298     memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
299
300     // Add queue head to controller list.
301     struct uhci_qh *control_qh = cntl->uhci.control_qh;
302     pipe->qh.link = control_qh->link;
303     barrier();
304     control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
305     if (cntl->uhci.bulk_qh == control_qh)
306         cntl->uhci.bulk_qh = &pipe->qh;
307     return &pipe->pipe;
308 }
309
310 int
311 uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
312              , void *data, int datasize)
313 {
314     ASSERT32FLAT();
315     if (! CONFIG_USB_UHCI)
316         return -1;
317     dprintf(5, "uhci_control %p\n", p);
318     struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
319
320     struct usb_s *cntl = pipe->pipe.cntl;
321     int maxpacket = pipe->pipe.maxpacket;
322     int lowspeed = pipe->pipe.lowspeed;
323     int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7);
324
325     // Setup transfer descriptors
326     int count = 2 + DIV_ROUND_UP(datasize, maxpacket);
327     struct uhci_td *tds = malloc_tmphigh(sizeof(*tds) * count);
328
329     tds[0].link = (u32)&tds[1] | UHCI_PTR_DEPTH;
330     tds[0].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
331                      | TD_CTRL_ACTIVE);
332     tds[0].token = (uhci_explen(cmdsize) | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
333                     | USB_PID_SETUP);
334     tds[0].buffer = (void*)cmd;
335     int toggle = TD_TOKEN_TOGGLE;
336     int i;
337     for (i=1; i<count-1; i++) {
338         tds[i].link = (u32)&tds[i+1] | UHCI_PTR_DEPTH;
339         tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
340                          | TD_CTRL_ACTIVE);
341         int len = (i == count-2 ? (datasize - (i-1)*maxpacket) : maxpacket);
342         tds[i].token = (uhci_explen(len) | toggle
343                         | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
344                         | (dir ? USB_PID_IN : USB_PID_OUT));
345         tds[i].buffer = data + (i-1) * maxpacket;
346         toggle ^= TD_TOKEN_TOGGLE;
347     }
348     tds[i].link = UHCI_PTR_TERM;
349     tds[i].status = (uhci_maxerr(0) | (lowspeed ? TD_CTRL_LS : 0)
350                      | TD_CTRL_ACTIVE);
351     tds[i].token = (uhci_explen(0) | TD_TOKEN_TOGGLE
352                     | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
353                     | (dir ? USB_PID_OUT : USB_PID_IN));
354     tds[i].buffer = 0;
355
356     // Transfer data
357     barrier();
358     pipe->qh.element = (u32)&tds[0];
359     int ret = wait_qh(cntl, &pipe->qh);
360     if (ret) {
361         pipe->qh.element = UHCI_PTR_TERM;
362         uhci_waittick(cntl);
363     }
364     free(tds);
365     return ret;
366 }
367
368 struct usb_pipe *
369 uhci_alloc_bulk_pipe(struct usb_pipe *dummy)
370 {
371     if (! CONFIG_USB_UHCI)
372         return NULL;
373     struct usb_s *cntl = dummy->cntl;
374     dprintf(7, "uhci_alloc_bulk_pipe %p\n", cntl);
375
376     // Allocate a queue head.
377     struct uhci_pipe *pipe = malloc_low(sizeof(*pipe));
378     if (!pipe) {
379         warn_noalloc();
380         return NULL;
381     }
382     memset(pipe, 0, sizeof(*pipe));
383     pipe->qh.element = UHCI_PTR_TERM;
384     memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
385
386     // Add queue head to controller list.
387     struct uhci_qh *bulk_qh = cntl->uhci.bulk_qh;
388     pipe->qh.link = bulk_qh->link;
389     barrier();
390     bulk_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
391
392     return &pipe->pipe;
393 }
394
395 static int
396 wait_td(struct uhci_td *td)
397 {
398     u64 end = calc_future_tsc(5000); // XXX - lookup real time.
399     u32 status;
400     for (;;) {
401         status = td->status;
402         if (!(status & TD_CTRL_ACTIVE))
403             break;
404         if (check_time(end)) {
405             warn_timeout();
406             return -1;
407         }
408         yield();
409     }
410     if (status & TD_CTRL_ANY_ERROR) {
411         dprintf(1, "wait_td error - status=%x\n", status);
412         return -2;
413     }
414     return 0;
415 }
416
417 #define STACKTDS 4
418 #define TDALIGN 16
419
420 int
421 uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
422 {
423     struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
424     dprintf(7, "uhci_send_bulk qh=%p dir=%d data=%p size=%d\n"
425             , &pipe->qh, dir, data, datasize);
426     int maxpacket = GET_FLATPTR(pipe->pipe.maxpacket);
427     int lowspeed = GET_FLATPTR(pipe->pipe.lowspeed);
428     int devaddr = (GET_FLATPTR(pipe->pipe.devaddr)
429                    | (GET_FLATPTR(pipe->pipe.ep) << 7));
430     int toggle = GET_FLATPTR(pipe->pipe.toggle) ? TD_TOKEN_TOGGLE : 0;
431
432     // Allocate 4 tds on stack (16byte aligned)
433     u8 tdsbuf[sizeof(struct uhci_td) * STACKTDS + TDALIGN - 1];
434     struct uhci_td *tds = (void*)ALIGN((u32)tdsbuf, TDALIGN);
435     memset(tds, 0, sizeof(*tds) * STACKTDS);
436
437     // Enable tds
438     SET_FLATPTR(pipe->qh.element, (u32)MAKE_FLATPTR(GET_SEG(SS), tds));
439
440     int tdpos = 0;
441     while (datasize) {
442         struct uhci_td *td = &tds[tdpos++ % STACKTDS];
443         int ret = wait_td(td);
444         if (ret)
445             goto fail;
446
447         int transfer = datasize;
448         if (transfer > maxpacket)
449             transfer = maxpacket;
450         struct uhci_td *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS)
451                                                  , &tds[tdpos % STACKTDS]);
452         td->link = (transfer==datasize ? UHCI_PTR_TERM : (u32)nexttd_fl);
453         td->token = (uhci_explen(transfer) | toggle
454                      | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
455                      | (dir ? USB_PID_IN : USB_PID_OUT));
456         td->buffer = data;
457         barrier();
458         td->status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
459                       | TD_CTRL_ACTIVE);
460         toggle ^= TD_TOKEN_TOGGLE;
461
462         data += transfer;
463         datasize -= transfer;
464     }
465     int i;
466     for (i=0; i<STACKTDS; i++) {
467         struct uhci_td *td = &tds[tdpos++ % STACKTDS];
468         int ret = wait_td(td);
469         if (ret)
470             goto fail;
471     }
472
473     SET_FLATPTR(pipe->pipe.toggle, !!toggle);
474     return 0;
475 fail:
476     dprintf(1, "uhci_send_bulk failed\n");
477     SET_FLATPTR(pipe->qh.element, UHCI_PTR_TERM);
478     uhci_waittick(GET_FLATPTR(pipe->pipe.cntl));
479     return -1;
480 }
481
482 struct usb_pipe *
483 uhci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp)
484 {
485     if (! CONFIG_USB_UHCI)
486         return NULL;
487     struct usb_s *cntl = dummy->cntl;
488     dprintf(7, "uhci_alloc_intr_pipe %p %d\n", cntl, frameexp);
489
490     if (frameexp > 10)
491         frameexp = 10;
492     int maxpacket = dummy->maxpacket;
493     int lowspeed = dummy->lowspeed;
494     int devaddr = dummy->devaddr | (dummy->ep << 7);
495     // Determine number of entries needed for 2 timer ticks.
496     int ms = 1<<frameexp;
497     int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms);
498     struct uhci_pipe *pipe = malloc_low(sizeof(*pipe));
499     struct uhci_td *tds = malloc_low(sizeof(*tds) * count);
500     if (!pipe || !tds) {
501         warn_noalloc();
502         goto fail;
503     }
504     if (maxpacket > sizeof(tds[0].data))
505         goto fail;
506     memset(pipe, 0, sizeof(*pipe));
507     pipe->qh.element = (u32)tds;
508     pipe->next_td = &tds[0];
509     memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
510
511     int toggle = 0;
512     int i;
513     for (i=0; i<count; i++) {
514         tds[i].link = (i==count-1 ? (u32)&tds[0] : (u32)&tds[i+1]);
515         tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
516                          | TD_CTRL_ACTIVE);
517         tds[i].token = (uhci_explen(maxpacket) | toggle
518                         | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
519                         | USB_PID_IN);
520         tds[i].buffer = &tds[i].data;
521         toggle ^= TD_TOKEN_TOGGLE;
522     }
523
524     // Add to interrupt schedule.
525     struct uhci_framelist *fl = cntl->uhci.framelist;
526     if (frameexp == 0) {
527         // Add to existing interrupt entry.
528         struct uhci_qh *intr_qh = (void*)(fl->links[0] & ~UHCI_PTR_BITS);
529         pipe->qh.link = intr_qh->link;
530         barrier();
531         intr_qh->link = (u32)&pipe->qh | UHCI_PTR_QH;
532         if (cntl->uhci.control_qh == intr_qh)
533             cntl->uhci.control_qh = &pipe->qh;
534         if (cntl->uhci.bulk_qh == intr_qh)
535             cntl->uhci.bulk_qh = &pipe->qh;
536     } else {
537         int startpos = 1<<(frameexp-1);
538         pipe->qh.link = fl->links[startpos];
539         barrier();
540         for (i=startpos; i<ARRAY_SIZE(fl->links); i+=ms)
541             fl->links[i] = (u32)&pipe->qh | UHCI_PTR_QH;
542     }
543
544     return &pipe->pipe;
545 fail:
546     free(pipe);
547     free(tds);
548     return NULL;
549 }
550
551 int
552 uhci_poll_intr(struct usb_pipe *p, void *data)
553 {
554     ASSERT16();
555     if (! CONFIG_USB_UHCI)
556         return -1;
557
558     struct uhci_pipe *pipe = container_of(p, struct uhci_pipe, pipe);
559     struct uhci_td *td = GET_FLATPTR(pipe->next_td);
560     u32 status = GET_FLATPTR(td->status);
561     u32 token = GET_FLATPTR(td->token);
562     if (status & TD_CTRL_ACTIVE)
563         // No intrs found.
564         return -1;
565     // XXX - check for errors.
566
567     // Copy data.
568     memcpy_far(GET_SEG(SS), data
569                , FLATPTR_TO_SEG(td->data), (void*)FLATPTR_TO_OFFSET(td->data)
570                , uhci_expected_length(token));
571
572     // Reenable this td.
573     u32 next = GET_FLATPTR(td->link);
574     barrier();
575     SET_FLATPTR(td->status, (uhci_maxerr(0) | (status & TD_CTRL_LS)
576                              | TD_CTRL_ACTIVE));
577     SET_FLATPTR(pipe->next_td, (void*)(next & ~UHCI_PTR_BITS));
578
579     return 0;
580 }