Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


SEABIOS updates to support reset and to simplify
[palacios.git] / bios / seabios / src / usb-ohci.c
1 // Code for handling OHCI 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 "usb-ohci.h" // struct ohci_hcca
11 #include "pci_regs.h" // PCI_BASE_ADDRESS_0
12 #include "usb.h" // struct usb_s
13 #include "farptr.h" // GET_FLATPTR
14
15 #define FIT                     (1 << 31)
16
17 struct usb_ohci_s {
18     struct usb_s usb;
19     struct ohci_regs *regs;
20 };
21
22
23 /****************************************************************
24  * Root hub
25  ****************************************************************/
26
27 // Check if device attached to port
28 static int
29 ohci_hub_detect(struct usbhub_s *hub, u32 port)
30 {
31     struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
32     u32 sts = readl(&cntl->regs->roothub_portstatus[port]);
33     if (!(sts & RH_PS_CCS))
34         // No device.
35         return -1;
36
37     // XXX - need to wait for USB_TIME_ATTDB if just powered up?
38
39     return 0;
40 }
41
42 // Disable port
43 static void
44 ohci_hub_disconnect(struct usbhub_s *hub, u32 port)
45 {
46     struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
47     writel(&cntl->regs->roothub_portstatus[port], RH_PS_CCS|RH_PS_LSDA);
48 }
49
50 // Reset device on port
51 static int
52 ohci_hub_reset(struct usbhub_s *hub, u32 port)
53 {
54     struct usb_ohci_s *cntl = container_of(hub->cntl, struct usb_ohci_s, usb);
55     writel(&cntl->regs->roothub_portstatus[port], RH_PS_PRS);
56     u32 sts;
57     u64 end = calc_future_tsc(USB_TIME_DRSTR * 2);
58     for (;;) {
59         sts = readl(&cntl->regs->roothub_portstatus[port]);
60         if (!(sts & RH_PS_PRS))
61             // XXX - need to ensure USB_TIME_DRSTR time in reset?
62             break;
63         if (check_tsc(end)) {
64             // Timeout.
65             warn_timeout();
66             ohci_hub_disconnect(hub, port);
67             return -1;
68         }
69         yield();
70     }
71
72     if ((sts & (RH_PS_CCS|RH_PS_PES)) != (RH_PS_CCS|RH_PS_PES))
73         // Device no longer present
74         return -1;
75
76     return !!(sts & RH_PS_LSDA);
77 }
78
79 static struct usbhub_op_s ohci_HubOp = {
80     .detect = ohci_hub_detect,
81     .reset = ohci_hub_reset,
82     .disconnect = ohci_hub_disconnect,
83 };
84
85 // Find any devices connected to the root hub.
86 static int
87 check_ohci_ports(struct usb_ohci_s *cntl)
88 {
89     ASSERT32FLAT();
90     // Turn on power for all devices on roothub.
91     u32 rha = readl(&cntl->regs->roothub_a);
92     rha &= ~(RH_A_PSM | RH_A_OCPM);
93     writel(&cntl->regs->roothub_status, RH_HS_LPSC);
94     writel(&cntl->regs->roothub_b, RH_B_PPCM);
95     msleep((rha >> 24) * 2);
96     // XXX - need to sleep for USB_TIME_SIGATT if just powered up?
97
98     struct usbhub_s hub;
99     memset(&hub, 0, sizeof(hub));
100     hub.cntl = &cntl->usb;
101     hub.portcount = rha & RH_A_NDP;
102     hub.op = &ohci_HubOp;
103     usb_enumerate(&hub);
104     return hub.devcount;
105 }
106
107
108 /****************************************************************
109  * Setup
110  ****************************************************************/
111
112 static int
113 start_ohci(struct usb_ohci_s *cntl, struct ohci_hcca *hcca)
114 {
115     u32 oldfminterval = readl(&cntl->regs->fminterval);
116     u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC;
117
118     // XXX - check if already running?
119
120     // Do reset
121     writel(&cntl->regs->control, OHCI_USB_RESET | oldrwc);
122     readl(&cntl->regs->control); // flush writes
123     msleep(USB_TIME_DRSTR);
124
125     // Do software init (min 10us, max 2ms)
126     u64 end = calc_future_tsc_usec(10);
127     writel(&cntl->regs->cmdstatus, OHCI_HCR);
128     for (;;) {
129         u32 status = readl(&cntl->regs->cmdstatus);
130         if (! status & OHCI_HCR)
131             break;
132         if (check_tsc(end)) {
133             warn_timeout();
134             return -1;
135         }
136     }
137
138     // Init memory
139     writel(&cntl->regs->ed_controlhead, 0);
140     writel(&cntl->regs->ed_bulkhead, 0);
141     writel(&cntl->regs->hcca, (u32)hcca);
142
143     // Init fminterval
144     u32 fi = oldfminterval & 0x3fff;
145     writel(&cntl->regs->fminterval
146            , (((oldfminterval & FIT) ^ FIT)
147               | fi | (((6 * (fi - 210)) / 7) << 16)));
148     writel(&cntl->regs->periodicstart, ((9 * fi) / 10) & 0x3fff);
149     readl(&cntl->regs->control); // flush writes
150
151     // XXX - verify that fminterval was setup correctly.
152
153     // Go into operational state
154     writel(&cntl->regs->control
155            , (OHCI_CTRL_CBSR | OHCI_CTRL_CLE | OHCI_CTRL_PLE
156               | OHCI_USB_OPER | oldrwc));
157     readl(&cntl->regs->control); // flush writes
158
159     return 0;
160 }
161
162 static void
163 stop_ohci(struct usb_ohci_s *cntl)
164 {
165     u32 oldrwc = readl(&cntl->regs->control) & OHCI_CTRL_RWC;
166     writel(&cntl->regs->control, oldrwc);
167     readl(&cntl->regs->control); // flush writes
168 }
169
170 static void
171 configure_ohci(void *data)
172 {
173     struct usb_ohci_s *cntl = data;
174
175     // Allocate memory
176     struct ohci_hcca *hcca = memalign_high(256, sizeof(*hcca));
177     struct ohci_ed *intr_ed = malloc_high(sizeof(*intr_ed));
178     if (!hcca || !intr_ed) {
179         warn_noalloc();
180         goto free;
181     }
182     memset(hcca, 0, sizeof(*hcca));
183     memset(intr_ed, 0, sizeof(*intr_ed));
184     intr_ed->hwINFO = ED_SKIP;
185     int i;
186     for (i=0; i<ARRAY_SIZE(hcca->int_table); i++)
187         hcca->int_table[i] = (u32)intr_ed;
188
189     int ret = start_ohci(cntl, hcca);
190     if (ret)
191         goto err;
192
193     int count = check_ohci_ports(cntl);
194     free_pipe(cntl->usb.defaultpipe);
195     if (! count)
196         goto err;
197     return;
198
199 err:
200     stop_ohci(cntl);
201 free:
202     free(hcca);
203     free(intr_ed);
204 }
205
206 void
207 ohci_init(struct pci_device *pci, int busid)
208 {
209     if (! CONFIG_USB_OHCI)
210         return;
211     struct usb_ohci_s *cntl = malloc_tmphigh(sizeof(*cntl));
212     if (!cntl) {
213         warn_noalloc();
214         return;
215     }
216     memset(cntl, 0, sizeof(*cntl));
217     cntl->usb.busid = busid;
218     cntl->usb.pci = pci;
219     cntl->usb.type = USB_TYPE_OHCI;
220
221     u16 bdf = pci->bdf;
222     u32 baseaddr = pci_config_readl(bdf, PCI_BASE_ADDRESS_0);
223     cntl->regs = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK);
224
225     dprintf(1, "OHCI init on dev %02x:%02x.%x (regs=%p)\n"
226             , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf)
227             , pci_bdf_to_fn(bdf), cntl->regs);
228
229     // Enable bus mastering and memory access.
230     pci_config_maskw(bdf, PCI_COMMAND
231                      , 0, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY);
232
233     // XXX - check for and disable SMM control?
234
235     // Disable interrupts
236     writel(&cntl->regs->intrdisable, ~0);
237     writel(&cntl->regs->intrstatus, ~0);
238
239     run_thread(configure_ohci, cntl);
240 }
241
242
243 /****************************************************************
244  * End point communication
245  ****************************************************************/
246
247 static int
248 wait_ed(struct ohci_ed *ed)
249 {
250     // XXX - 500ms just a guess
251     u64 end = calc_future_tsc(500);
252     for (;;) {
253         if (ed->hwHeadP == ed->hwTailP)
254             return 0;
255         if (check_tsc(end)) {
256             warn_timeout();
257             return -1;
258         }
259         yield();
260     }
261 }
262
263 // Wait for next USB frame to start - for ensuring safe memory release.
264 static void
265 ohci_waittick(struct usb_ohci_s *cntl)
266 {
267     barrier();
268     struct ohci_hcca *hcca = (void*)cntl->regs->hcca;
269     u32 startframe = hcca->frame_no;
270     u64 end = calc_future_tsc(1000 * 5);
271     for (;;) {
272         if (hcca->frame_no != startframe)
273             break;
274         if (check_tsc(end)) {
275             warn_timeout();
276             return;
277         }
278         yield();
279     }
280 }
281
282 static void
283 signal_freelist(struct usb_ohci_s *cntl)
284 {
285     u32 v = readl(&cntl->regs->control);
286     if (v & OHCI_CTRL_CLE) {
287         writel(&cntl->regs->control, v & ~(OHCI_CTRL_CLE|OHCI_CTRL_BLE));
288         ohci_waittick(cntl);
289         writel(&cntl->regs->ed_controlcurrent, 0);
290         writel(&cntl->regs->ed_bulkcurrent, 0);
291         writel(&cntl->regs->control, v);
292     } else {
293         ohci_waittick(cntl);
294     }
295 }
296
297 struct ohci_pipe {
298     struct ohci_ed ed;
299     struct usb_pipe pipe;
300     void *data;
301     int count;
302     struct ohci_td *tds;
303 };
304
305 void
306 ohci_free_pipe(struct usb_pipe *p)
307 {
308     if (! CONFIG_USB_OHCI)
309         return;
310     dprintf(7, "ohci_free_pipe %p\n", p);
311     struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
312     struct usb_ohci_s *cntl = container_of(
313         pipe->pipe.cntl, struct usb_ohci_s, usb);
314
315     u32 *pos = &cntl->regs->ed_controlhead;
316     for (;;) {
317         struct ohci_ed *next = (void*)*pos;
318         if (!next) {
319             // Not found?!  Exit without freeing.
320             warn_internalerror();
321             return;
322         }
323         if (next == &pipe->ed) {
324             *pos = next->hwNextED;
325             signal_freelist(cntl);
326             free(pipe);
327             return;
328         }
329         pos = &next->hwNextED;
330     }
331 }
332
333 struct usb_pipe *
334 ohci_alloc_control_pipe(struct usb_pipe *dummy)
335 {
336     if (! CONFIG_USB_OHCI)
337         return NULL;
338     struct usb_ohci_s *cntl = container_of(
339         dummy->cntl, struct usb_ohci_s, usb);
340     dprintf(7, "ohci_alloc_control_pipe %p\n", &cntl->usb);
341
342     // Allocate a queue head.
343     struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe));
344     if (!pipe) {
345         warn_noalloc();
346         return NULL;
347     }
348     memset(pipe, 0, sizeof(*pipe));
349     memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
350     pipe->ed.hwINFO = ED_SKIP;
351
352     // Add queue head to controller list.
353     pipe->ed.hwNextED = cntl->regs->ed_controlhead;
354     barrier();
355     cntl->regs->ed_controlhead = (u32)&pipe->ed;
356     return &pipe->pipe;
357 }
358
359 int
360 ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
361              , void *data, int datasize)
362 {
363     if (! CONFIG_USB_OHCI)
364         return -1;
365     dprintf(5, "ohci_control %p\n", p);
366     if (datasize > 4096) {
367         // XXX - should support larger sizes.
368         warn_noalloc();
369         return -1;
370     }
371     struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
372     struct usb_ohci_s *cntl = container_of(
373         pipe->pipe.cntl, struct usb_ohci_s, usb);
374     int maxpacket = pipe->pipe.maxpacket;
375     int lowspeed = pipe->pipe.speed;
376     int devaddr = pipe->pipe.devaddr | (pipe->pipe.ep << 7);
377
378     // Setup transfer descriptors
379     struct ohci_td *tds = malloc_tmphigh(sizeof(*tds) * 3);
380     if (!tds) {
381         warn_noalloc();
382         return -1;
383     }
384     struct ohci_td *td = tds;
385     td->hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC;
386     td->hwCBP = (u32)cmd;
387     td->hwNextTD = (u32)&td[1];
388     td->hwBE = (u32)cmd + cmdsize - 1;
389     td++;
390     if (datasize) {
391         td->hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | TD_T_DATA1 | TD_CC;
392         td->hwCBP = (u32)data;
393         td->hwNextTD = (u32)&td[1];
394         td->hwBE = (u32)data + datasize - 1;
395         td++;
396     }
397     td->hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC;
398     td->hwCBP = 0;
399     td->hwNextTD = (u32)&td[1];
400     td->hwBE = 0;
401     td++;
402
403     // Transfer data
404     pipe->ed.hwINFO = ED_SKIP;
405     barrier();
406     pipe->ed.hwHeadP = (u32)tds;
407     pipe->ed.hwTailP = (u32)td;
408     barrier();
409     pipe->ed.hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0);
410     writel(&cntl->regs->cmdstatus, OHCI_CLF);
411
412     int ret = wait_ed(&pipe->ed);
413     pipe->ed.hwINFO = ED_SKIP;
414     if (ret)
415         ohci_waittick(cntl);
416     free(tds);
417     return ret;
418 }
419
420 struct usb_pipe *
421 ohci_alloc_bulk_pipe(struct usb_pipe *dummy)
422 {
423     if (! CONFIG_USB_OHCI)
424         return NULL;
425     dprintf(1, "OHCI Bulk transfers not supported.\n");
426     return NULL;
427 }
428
429 int
430 ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
431 {
432     return -1;
433 }
434
435 struct usb_pipe *
436 ohci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp)
437 {
438     if (! CONFIG_USB_OHCI)
439         return NULL;
440     struct usb_ohci_s *cntl = container_of(
441         dummy->cntl, struct usb_ohci_s, usb);
442     dprintf(7, "ohci_alloc_intr_pipe %p %d\n", &cntl->usb, frameexp);
443
444     if (frameexp > 5)
445         frameexp = 5;
446     int maxpacket = dummy->maxpacket;
447     int lowspeed = dummy->speed;
448     int devaddr = dummy->devaddr | (dummy->ep << 7);
449     // Determine number of entries needed for 2 timer ticks.
450     int ms = 1<<frameexp;
451     int count = DIV_ROUND_UP(PIT_TICK_INTERVAL * 1000 * 2, PIT_TICK_RATE * ms)+1;
452     struct ohci_pipe *pipe = malloc_low(sizeof(*pipe));
453     struct ohci_td *tds = malloc_low(sizeof(*tds) * count);
454     void *data = malloc_low(maxpacket * count);
455     if (!pipe || !tds || !data)
456         goto err;
457     memset(pipe, 0, sizeof(*pipe));
458     memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
459     pipe->data = data;
460     pipe->count = count;
461     pipe->tds = tds;
462
463     struct ohci_ed *ed = &pipe->ed;
464     ed->hwHeadP = (u32)&tds[0];
465     ed->hwTailP = (u32)&tds[count-1];
466     ed->hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0);
467
468     int i;
469     for (i=0; i<count-1; i++) {
470         tds[i].hwINFO = TD_DP_IN | TD_T_TOGGLE | TD_CC;
471         tds[i].hwCBP = (u32)data + maxpacket * i;
472         tds[i].hwNextTD = (u32)&tds[i+1];
473         tds[i].hwBE = tds[i].hwCBP + maxpacket - 1;
474     }
475
476     // Add to interrupt schedule.
477     barrier();
478     struct ohci_hcca *hcca = (void*)cntl->regs->hcca;
479     if (frameexp == 0) {
480         // Add to existing interrupt entry.
481         struct ohci_ed *intr_ed = (void*)hcca->int_table[0];
482         ed->hwNextED = intr_ed->hwNextED;
483         intr_ed->hwNextED = (u32)ed;
484     } else {
485         int startpos = 1<<(frameexp-1);
486         ed->hwNextED = hcca->int_table[startpos];
487         for (i=startpos; i<ARRAY_SIZE(hcca->int_table); i+=ms)
488             hcca->int_table[i] = (u32)ed;
489     }
490
491     return &pipe->pipe;
492
493 err:
494     free(pipe);
495     free(tds);
496     free(data);
497     return NULL;
498 }
499
500 int
501 ohci_poll_intr(struct usb_pipe *p, void *data)
502 {
503     ASSERT16();
504     if (! CONFIG_USB_OHCI)
505         return -1;
506
507     struct ohci_pipe *pipe = container_of(p, struct ohci_pipe, pipe);
508     struct ohci_td *tds = GET_FLATPTR(pipe->tds);
509     struct ohci_td *head = (void*)(GET_FLATPTR(pipe->ed.hwHeadP) & ~(ED_C|ED_H));
510     struct ohci_td *tail = (void*)GET_FLATPTR(pipe->ed.hwTailP);
511     int count = GET_FLATPTR(pipe->count);
512     int pos = (tail - tds + 1) % count;
513     struct ohci_td *next = &tds[pos];
514     if (head == next)
515         // No intrs found.
516         return -1;
517     // XXX - check for errors.
518
519     // Copy data.
520     int maxpacket = GET_FLATPTR(pipe->pipe.maxpacket);
521     void *pipedata = GET_FLATPTR(pipe->data);
522     void *intrdata = pipedata + maxpacket * pos;
523     memcpy_far(GET_SEG(SS), data
524                , FLATPTR_TO_SEG(intrdata), (void*)FLATPTR_TO_OFFSET(intrdata)
525                , maxpacket);
526
527     // Reenable this td.
528     SET_FLATPTR(tail->hwINFO, TD_DP_IN | TD_T_TOGGLE | TD_CC);
529     intrdata = pipedata + maxpacket * (tail-tds);
530     SET_FLATPTR(tail->hwCBP, (u32)intrdata);
531     SET_FLATPTR(tail->hwNextTD, (u32)next);
532     SET_FLATPTR(tail->hwBE, (u32)intrdata + maxpacket - 1);
533     barrier();
534     SET_FLATPTR(pipe->ed.hwTailP, (u32)next);
535
536     return 0;
537 }