mb/amb/birman*/gpio: remove configuration for VDD_MEM_VID[0,1]
[coreboot2.git] / payloads / libpayload / drivers / usb / uhci.c
blob7590ab3c85082e55d16d63fe9ba72522bdfc7cdd
1 /*
3 * Copyright (C) 2008-2010 coresystems GmbH
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 //#define USB_DEBUG
31 #include <arch/virtual.h>
32 #include <inttypes.h>
33 #include <usb/usb.h>
34 #include "uhci.h"
35 #include "uhci_private.h"
37 static void uhci_start(hci_t *controller);
38 static void uhci_stop(hci_t *controller);
39 static void uhci_reset(hci_t *controller);
40 static void uhci_shutdown(hci_t *controller);
41 static int uhci_bulk(endpoint_t *ep, int size, u8 *data, int finalize);
42 static int uhci_control(usbdev_t *dev, direction_t dir, int drlen, void *devreq,
43 int dalen, u8 *data);
44 static void* uhci_create_intr_queue(endpoint_t *ep, int reqsize, int reqcount, int reqtiming);
45 static void uhci_destroy_intr_queue(endpoint_t *ep, void *queue);
46 static u8* uhci_poll_intr_queue(void *queue);
48 #if 0
49 /* dump uhci */
50 static void
51 uhci_dump(hci_t *controller)
53 usb_debug("dump:\nUSBCMD: %x\n", uhci_reg_read16(controller, USBCMD));
54 usb_debug("USBSTS: %x\n", uhci_reg_read16(controller, USBSTS));
55 usb_debug("USBINTR: %x\n", uhci_reg_read16(controller, USBINTR));
56 usb_debug("FRNUM: %x\n", uhci_reg_read16(controller, FRNUM));
57 usb_debug("FLBASEADD: %x\n", uhci_reg_read32(controller, FLBASEADD));
58 usb_debug("SOFMOD: %x\n", uhci_reg_read8(controller, SOFMOD));
59 usb_debug("PORTSC1: %x\n", uhci_reg_read16(controller, PORTSC1));
60 usb_debug("PORTSC2: %x\n", uhci_reg_read16(controller, PORTSC2));
62 #endif
64 static void td_dump(td_t *td)
66 usb_debug("+---------------------------------------------------+\n");
67 if ((td->token & TD_PID_MASK) == UHCI_SETUP)
68 usb_debug("|..[SETUP]..........................................|\n");
69 else if ((td->token & TD_PID_MASK) == UHCI_IN)
70 usb_debug("|..[IN].............................................|\n");
71 else if ((td->token & TD_PID_MASK) == UHCI_OUT)
72 usb_debug("|..[OUT]............................................|\n");
73 else
74 usb_debug("|..[]...............................................|\n");
75 usb_debug("|:|============ UHCI TD at [0x%08lx] ==========|:|\n", virt_to_phys(td));
76 usb_debug("|:+-----------------------------------------------+:|\n");
77 usb_debug("|:| Next TD/QH [0x%08lx] |:|\n", td->ptr & ~0xFUL);
78 usb_debug("|:+-----------------------------------------------+:|\n");
79 usb_debug("|:| Depth/Breath [%lx] | QH/TD [%lx] | TERMINATE [%lx] |:|\n",
80 (td->ptr & (1UL << 2)) >> 2, (td->ptr & (1UL << 1)) >> 1, td->ptr & 1UL);
81 usb_debug("|:+-----------------------------------------------+:|\n");
82 usb_debug("|:| T | Maximum Length | [%04lx] |:|\n", (td->token & (0x7FFUL << 21)) >> 21);
83 usb_debug("|:| O | PID CODE | [%04"PRIx32"] |:|\n", td->token & 0xFF);
84 usb_debug("|:| K | Endpoint | [%04"PRIx32"] |:|\n", (td->token & TD_EP_MASK) >> TD_EP_SHIFT);
85 usb_debug("|:| E | Device Address | [%04lx] |:|\n", (td->token & (0x7FUL << 8)) >> 8);
86 usb_debug("|:| N | Data Toggle | [%lx] |:|\n", (td->token & (1UL << 19)) >> 19);
87 usb_debug("|:+-----------------------------------------------+:|\n");
88 usb_debug("|:| C | Short Packet Detector | [%lx] |:|\n", (td->ctrlsts & (1UL << 29)) >> 29);
89 usb_debug("|:| O | Error Counter | [%lx] |:|\n",
90 (td->ctrlsts & (3UL << TD_COUNTER_SHIFT)) >> TD_COUNTER_SHIFT);
91 usb_debug("|:| N | Low Speed Device | [%lx] |:|\n", (td->ctrlsts & (1UL << 26)) >> 26);
92 usb_debug("|:| T | Isochronous Select | [%lx] |:|\n", (td->ctrlsts & (1UL << 25)) >> 25);
93 usb_debug("|:| R | Interrupt on Complete (IOC) | [%lx] |:|\n", (td->ctrlsts & (1UL << 24)) >> 24);
94 usb_debug("|:+ O ----------------------------------------+:|\n");
95 usb_debug("|:| L | Active | [%lx] |:|\n", (td->ctrlsts & (1UL << 23)) >> 23);
96 usb_debug("|:| & | Stalled | [%lx] |:|\n", (td->ctrlsts & (1UL << 22)) >> 22);
97 usb_debug("|:| S | Data Buffer Error | [%lx] |:|\n", (td->ctrlsts & (1UL << 21)) >> 21);
98 usb_debug("|:| T | Bubble Detected | [%lx] |:|\n", (td->ctrlsts & (1UL << 20)) >> 20);
99 usb_debug("|:| A | NAK Received | [%lx] |:|\n", (td->ctrlsts & (1UL << 19)) >> 19);
100 usb_debug("|:| T | CRC/Timeout Error | [%lx] |:|\n", (td->ctrlsts & (1UL << 18)) >> 18);
101 usb_debug("|:| U | Bitstuff Error | [%lx] |:|\n", (td->ctrlsts & (1UL << 17)) >> 17);
102 usb_debug("|:| S ----------------------------------------|:|\n");
103 usb_debug("|:| | Actual Length | [%04lx] |:|\n", td->ctrlsts & 0x7FFUL);
104 usb_debug("|:+-----------------------------------------------+:|\n");
105 usb_debug("|:| Buffer pointer [0x%08"PRIx32"] |:|\n", td->bufptr);
106 usb_debug("|:|-----------------------------------------------|:|\n");
107 usb_debug("|...................................................|\n");
108 usb_debug("+---------------------------------------------------+\n");
111 static void
112 uhci_reset(hci_t *controller)
114 /* reset */
115 uhci_reg_write16(controller, USBCMD, 4); /* Global Reset */
116 mdelay(50); /* uhci spec 2.1.1: at least 10ms */
117 uhci_reg_write16(controller, USBCMD, 0);
118 mdelay(10);
119 uhci_reg_write16(controller, USBCMD, 2); /* Host Controller Reset */
120 /* wait for controller to finish reset */
121 /* TOTEST: how long to wait? 100ms for now */
122 int timeout = 200; /* time out after 200 * 500us == 100ms */
123 while (((uhci_reg_read16(controller, USBCMD) & 2) != 0) && timeout--)
124 udelay(500);
125 if (timeout < 0)
126 usb_debug("Warning: uhci: host controller reset timed out.\n");
129 static void
130 uhci_reinit(hci_t *controller)
132 uhci_reg_write32(controller, FLBASEADD,
133 (u32) virt_to_phys(UHCI_INST(controller)->
134 framelistptr));
135 //usb_debug ("framelist at %p\n",UHCI_INST(controller)->framelistptr);
137 /* disable irqs */
138 uhci_reg_write16(controller, USBINTR, 0);
140 /* reset framelist index */
141 uhci_reg_write16(controller, FRNUM, 0);
143 uhci_reg_write16(controller, USBCMD,
144 uhci_reg_read16(controller, USBCMD) | 0xc0); // max packets, configure flag
146 uhci_start(controller);
149 hci_t *
150 uhci_pci_init(pcidev_t addr)
152 int i;
153 u16 reg16;
155 hci_t *controller = new_controller();
156 controller->pcidev = addr;
157 controller->instance = xzalloc(sizeof(uhci_t));
158 controller->type = UHCI;
159 controller->start = uhci_start;
160 controller->stop = uhci_stop;
161 controller->reset = uhci_reset;
162 controller->init = uhci_reinit;
163 controller->shutdown = uhci_shutdown;
164 controller->bulk = uhci_bulk;
165 controller->control = uhci_control;
166 controller->set_address = generic_set_address;
167 controller->finish_device_config = NULL;
168 controller->destroy_device = NULL;
169 controller->create_intr_queue = uhci_create_intr_queue;
170 controller->destroy_intr_queue = uhci_destroy_intr_queue;
171 controller->poll_intr_queue = uhci_poll_intr_queue;
172 init_device_entry(controller, 0);
173 UHCI_INST(controller)->roothub = controller->devices[0];
175 /* ~1 clears the register type indicator that is set to 1
176 * for IO space */
177 controller->reg_base = pci_read_config32(addr, 0x20) & ~1;
179 /* kill legacy support handler */
180 uhci_stop(controller);
181 mdelay(1);
182 uhci_reg_write16(controller, USBSTS, 0x3f);
183 reg16 = pci_read_config16(addr, 0xc0);
184 reg16 &= 0xdf80;
185 pci_write_config16(addr, 0xc0, reg16);
187 UHCI_INST(controller)->framelistptr = memalign(0x1000, 1024 * sizeof(flistp_t)); /* 4kb aligned to 4kb */
188 if (!UHCI_INST (controller)->framelistptr)
189 fatal("Not enough memory for USB frame list pointer.\n");
191 memset(UHCI_INST(controller)->framelistptr, 0,
192 1024 * sizeof(flistp_t));
194 /* According to the *BSD UHCI code, this one is needed on some
195 PIIX chips, because otherwise they misbehave. It must be
196 added to the last chain.
198 FIXME: this leaks, if the driver should ever be reinited
199 for some reason. Not a problem now.
201 td_t *antiberserk = memalign(16, sizeof(td_t));
202 if (!antiberserk)
203 fatal("Not enough memory for chipset workaround.\n");
204 memset(antiberserk, 0, sizeof(td_t));
206 UHCI_INST(controller)->qh_prei = memalign(16, sizeof(qh_t));
207 UHCI_INST(controller)->qh_intr = memalign(16, sizeof(qh_t));
208 UHCI_INST(controller)->qh_data = memalign(16, sizeof(qh_t));
209 UHCI_INST(controller)->qh_last = memalign(16, sizeof(qh_t));
211 if (!UHCI_INST (controller)->qh_prei ||
212 !UHCI_INST (controller)->qh_intr ||
213 !UHCI_INST (controller)->qh_data ||
214 !UHCI_INST (controller)->qh_last)
215 fatal("Not enough memory for USB controller queues.\n");
217 UHCI_INST(controller)->qh_prei->headlinkptr =
218 virt_to_phys(UHCI_INST(controller)->qh_intr) | FLISTP_QH;
219 UHCI_INST(controller)->qh_prei->elementlinkptr = 0 | FLISTP_TERMINATE;
221 UHCI_INST(controller)->qh_intr->headlinkptr =
222 virt_to_phys(UHCI_INST(controller)->qh_data) | FLISTP_QH;
223 UHCI_INST(controller)->qh_intr->elementlinkptr = 0 | FLISTP_TERMINATE;
225 UHCI_INST(controller)->qh_data->headlinkptr =
226 virt_to_phys(UHCI_INST(controller)->qh_last) | FLISTP_QH;
227 UHCI_INST(controller)->qh_data->elementlinkptr = 0 | FLISTP_TERMINATE;
229 UHCI_INST(controller)->qh_last->headlinkptr = virt_to_phys(UHCI_INST(controller)->qh_data) | FLISTP_TERMINATE;
230 UHCI_INST(controller)->qh_last->elementlinkptr = virt_to_phys(antiberserk) | FLISTP_TERMINATE;
232 for (i = 0; i < 1024; i++) {
233 UHCI_INST(controller)->framelistptr[i] =
234 virt_to_phys(UHCI_INST(controller)->qh_prei) | FLISTP_QH;
236 controller->devices[0]->controller = controller;
237 controller->devices[0]->init = uhci_rh_init;
238 controller->devices[0]->init(controller->devices[0]);
239 uhci_reset(controller);
240 uhci_reinit(controller);
241 return controller;
244 static void
245 uhci_shutdown(hci_t *controller)
247 if (controller == 0)
248 return;
249 detach_controller(controller);
250 uhci_reg_write16(controller, USBCMD,
251 uhci_reg_read16(controller, USBCMD) & 0); // stop work
252 free(UHCI_INST(controller)->framelistptr);
253 free(UHCI_INST(controller)->qh_prei);
254 free(UHCI_INST(controller)->qh_intr);
255 free(UHCI_INST(controller)->qh_data);
256 free(UHCI_INST(controller)->qh_last);
257 free(UHCI_INST(controller));
258 free(controller);
261 static void
262 uhci_start(hci_t *controller)
264 uhci_reg_write16(controller, USBCMD,
265 uhci_reg_read16(controller, USBCMD) | 1); // start work on schedule
268 static void
269 uhci_stop(hci_t *controller)
271 uhci_reg_write16(controller, USBCMD,
272 uhci_reg_read16(controller, USBCMD) & ~1); // stop work on schedule
275 #define UHCI_SLEEP_TIME_US 30
276 #define UHCI_TIMEOUT (USB_MAX_PROCESSING_TIME_US / UHCI_SLEEP_TIME_US)
277 #define GET_TD(x) ((void *)(((unsigned long)(x))&~0xf))
279 static td_t *
280 wait_for_completed_qh(hci_t *controller, qh_t *qh)
282 int timeout = UHCI_TIMEOUT;
283 void *current = GET_TD(qh->elementlinkptr);
284 while (((qh->elementlinkptr & FLISTP_TERMINATE) == 0) && (timeout-- > 0)) {
285 if (current != GET_TD(qh->elementlinkptr)) {
286 current = GET_TD(qh->elementlinkptr);
287 timeout = UHCI_TIMEOUT;
289 uhci_reg_write16(controller, USBSTS,
290 uhci_reg_read16(controller, USBSTS) | 0); // clear resettable registers
291 udelay(UHCI_SLEEP_TIME_US);
293 return (GET_TD(qh->elementlinkptr) ==
294 0) ? 0 : GET_TD(phys_to_virt(qh->elementlinkptr));
297 static int
298 maxlen(int size)
300 return (size - 1) & 0x7ff;
303 static int
304 min(int a, int b)
306 if (a < b)
307 return a;
308 else
309 return b;
312 static int
313 uhci_control(usbdev_t *dev, direction_t dir, int drlen, void *devreq, const int dalen,
314 unsigned char *data)
316 int endp = 0; /* this is control: always 0 */
317 int mlen = dev->endpoints[0].maxpacketsize;
318 int count = (2 + (dalen + mlen - 1) / mlen);
319 unsigned short req = ((unsigned short *) devreq)[0];
320 int i;
321 td_t *tds = memalign(16, sizeof(td_t) * count);
322 if (!tds)
323 fatal("Not enough memory for uhci control.\n");
324 memset(tds, 0, sizeof(td_t) * count);
325 count--; /* to compensate for 0-indexed array */
326 for (i = 0; i < count; i++) {
327 tds[i].ptr = virt_to_phys(&tds[i + 1]) | TD_DEPTH_FIRST;
329 tds[count].ptr = 0 | TD_DEPTH_FIRST | TD_TERMINATE;
331 tds[0].token = UHCI_SETUP |
332 dev->address << TD_DEVADDR_SHIFT |
333 endp << TD_EP_SHIFT |
334 TD_TOGGLE_DATA0 |
335 maxlen(drlen) << TD_MAXLEN_SHIFT;
336 tds[0].bufptr = virt_to_phys(devreq);
337 tds[0].ctrlsts = (3 << TD_COUNTER_SHIFT) |
338 (dev->speed?TD_LOWSPEED:0) |
339 TD_STATUS_ACTIVE;
341 int toggle = 1;
342 int len_left = dalen;
343 for (i = 1; i < count; i++) {
344 switch (dir) {
345 case SETUP: tds[i].token = UHCI_SETUP; break;
346 case IN: tds[i].token = UHCI_IN; break;
347 case OUT: tds[i].token = UHCI_OUT; break;
349 tds[i].token |= dev->address << TD_DEVADDR_SHIFT |
350 endp << TD_EP_SHIFT |
351 maxlen(min(mlen, len_left)) << TD_MAXLEN_SHIFT |
352 toggle << TD_TOGGLE_SHIFT;
353 tds[i].bufptr = virt_to_phys(data);
354 tds[i].ctrlsts = (3 << TD_COUNTER_SHIFT) |
355 (dev->speed?TD_LOWSPEED:0) |
356 TD_STATUS_ACTIVE;
357 toggle ^= 1;
358 len_left -= mlen;
359 data += mlen;
362 tds[count].token = ((dir == OUT) ? UHCI_IN : UHCI_OUT) |
363 dev->address << TD_DEVADDR_SHIFT |
364 endp << TD_EP_SHIFT |
365 maxlen(0) << TD_MAXLEN_SHIFT |
366 TD_TOGGLE_DATA1;
367 tds[count].bufptr = 0;
368 tds[count].ctrlsts = (0 << TD_COUNTER_SHIFT) | /* as Linux 2.4.10 does */
369 (dev->speed?TD_LOWSPEED:0) |
370 TD_STATUS_ACTIVE;
371 UHCI_INST(dev->controller)->qh_data->elementlinkptr =
372 virt_to_phys(tds) & ~(FLISTP_QH | FLISTP_TERMINATE);
373 td_t *td = wait_for_completed_qh(dev->controller,
374 UHCI_INST(dev->controller)->
375 qh_data);
376 int result;
377 if (td == 0) {
378 result = dalen; /* TODO: We should return the actually transferred length. */
379 } else {
380 usb_debug("control packet, req %x\n", req);
381 td_dump(td);
382 result = -1;
384 free(tds);
385 return result;
388 static td_t *
389 create_schedule(int numpackets)
391 if (numpackets == 0)
392 return 0;
393 td_t *tds = memalign(16, sizeof(td_t) * numpackets);
394 if (!tds)
395 fatal("Not enough memory for packets scheduling.\n");
396 memset(tds, 0, sizeof(td_t) * numpackets);
397 int i;
398 for (i = 0; i < numpackets; i++) {
399 tds[i].ptr = virt_to_phys(&tds[i + 1]) | TD_DEPTH_FIRST;
401 tds[numpackets - 1].ptr = 0 | TD_TERMINATE;
402 return tds;
405 static void
406 fill_schedule(td_t *td, endpoint_t *ep, int length, unsigned char *data,
407 int *toggle)
409 switch (ep->direction) {
410 case IN: td->token = UHCI_IN; break;
411 case OUT: td->token = UHCI_OUT; break;
412 case SETUP: td->token = UHCI_SETUP; break;
414 td->token |= ep->dev->address << TD_DEVADDR_SHIFT |
415 (ep->endpoint & 0xf) << TD_EP_SHIFT |
416 maxlen(length) << TD_MAXLEN_SHIFT |
417 (*toggle & 1) << TD_TOGGLE_SHIFT;
418 td->bufptr = virt_to_phys(data);
419 td->ctrlsts = ((ep->direction == SETUP?3:0) << TD_COUNTER_SHIFT) |
420 (ep->dev->speed?TD_LOWSPEED:0) |
421 TD_STATUS_ACTIVE;
422 *toggle ^= 1;
425 static int
426 run_schedule(usbdev_t *dev, td_t *td)
428 UHCI_INST(dev->controller)->qh_data->elementlinkptr =
429 virt_to_phys(td) & ~(FLISTP_QH | FLISTP_TERMINATE);
430 td = wait_for_completed_qh(dev->controller,
431 UHCI_INST(dev->controller)->qh_data);
432 if (td == 0) {
433 return 0;
434 } else {
435 td_dump(td);
436 return 1;
440 /* finalize == 1: if data is of packet aligned size, add a zero length packet */
441 static int
442 uhci_bulk(endpoint_t *ep, const int dalen, u8 *data, int finalize)
444 int maxpsize = ep->maxpacketsize;
445 if (maxpsize == 0)
446 fatal("MaxPacketSize == 0!!!");
447 int numpackets = (dalen + maxpsize - 1) / maxpsize;
448 if (finalize && ((dalen % maxpsize) == 0)) {
449 numpackets++;
451 if (numpackets == 0)
452 return 0;
453 td_t *tds = create_schedule(numpackets);
454 int i = 0, toggle = ep->toggle;
455 int len_left = dalen;
456 while ((len_left > 0) || ((len_left == 0) && (finalize != 0))) {
457 fill_schedule(&tds[i], ep, min(len_left, maxpsize), data,
458 &toggle);
459 i++;
460 data += maxpsize;
461 len_left -= maxpsize;
463 if (run_schedule(ep->dev, tds) == 1) {
464 free(tds);
465 return -1;
467 ep->toggle = toggle;
468 free(tds);
469 return dalen; /* TODO: We should return the actually transferred length. */
472 typedef struct {
473 qh_t *qh;
474 td_t *tds;
475 td_t *last_td;
476 u8 *data;
477 int lastread;
478 int total;
479 int reqsize;
480 } intr_q;
482 /* create and hook-up an intr queue into device schedule */
483 static void*
484 uhci_create_intr_queue(endpoint_t *ep, int reqsize, int reqcount, int reqtiming)
486 u8 *data = malloc(reqsize*reqcount);
487 td_t *tds = memalign(16, sizeof(td_t) * reqcount);
488 qh_t *qh = memalign(16, sizeof(qh_t));
490 if (!data || !tds || !qh)
491 fatal("Not enough memory to create USB intr queue prerequisites.\n");
493 qh->elementlinkptr = virt_to_phys(tds);
495 intr_q *q = malloc(sizeof(intr_q));
496 if (!q)
497 fatal("Not enough memory to create USB intr queue.\n");
498 q->qh = qh;
499 q->tds = tds;
500 q->data = data;
501 q->lastread = 0;
502 q->total = reqcount;
503 q->reqsize = reqsize;
504 q->last_td = &tds[reqcount - 1];
506 memset(tds, 0, sizeof(td_t) * reqcount);
507 int i;
508 for (i = 0; i < reqcount; i++) {
509 tds[i].ptr = virt_to_phys(&tds[i + 1]);
511 switch (ep->direction) {
512 case IN: tds[i].token = UHCI_IN; break;
513 case OUT: tds[i].token = UHCI_OUT; break;
514 case SETUP: tds[i].token = UHCI_SETUP; break;
516 tds[i].token |= ep->dev->address << TD_DEVADDR_SHIFT |
517 (ep->endpoint & 0xf) << TD_EP_SHIFT |
518 maxlen(reqsize) << TD_MAXLEN_SHIFT |
519 (ep->toggle & 1) << TD_TOGGLE_SHIFT;
520 tds[i].bufptr = virt_to_phys(data);
521 tds[i].ctrlsts = (0 << TD_COUNTER_SHIFT) |
522 (ep->dev->speed?TD_LOWSPEED:0) |
523 TD_STATUS_ACTIVE;
524 ep->toggle ^= 1;
525 data += reqsize;
527 tds[reqcount - 1].ptr = 0 | TD_TERMINATE;
529 /* insert QH into framelist */
530 uhci_t *const uhcic = UHCI_INST(ep->dev->controller);
531 const u32 def_ptr = virt_to_phys(uhcic->qh_prei) | FLISTP_QH;
532 int nothing_placed = 1;
533 qh->headlinkptr = def_ptr;
534 for (i = 0; i < 1024; i += reqtiming) {
535 /* advance to the next free position */
536 while ((i < 1024) && (uhcic->framelistptr[i] != def_ptr)) ++i;
537 if (i < 1024) {
538 uhcic->framelistptr[i] = virt_to_phys(qh) | FLISTP_QH;
539 nothing_placed = 0;
542 if (nothing_placed) {
543 usb_debug("Error: Failed to place UHCI interrupt queue "
544 "head into framelist: no space left\n");
545 uhci_destroy_intr_queue(ep, q);
546 return NULL;
549 return q;
552 /* remove queue from device schedule, dropping all data that came in */
553 static void
554 uhci_destroy_intr_queue(endpoint_t *ep, void *q_)
556 intr_q *const q = (intr_q*)q_;
558 /* remove QH from framelist */
559 uhci_t *const uhcic = UHCI_INST(ep->dev->controller);
560 const u32 qh_ptr = virt_to_phys(q->qh) | FLISTP_QH;
561 const u32 def_ptr = virt_to_phys(uhcic->qh_prei) | FLISTP_QH;
562 int i;
563 for (i = 0; i < 1024; ++i) {
564 if (uhcic->framelistptr[i] == qh_ptr)
565 uhcic->framelistptr[i] = def_ptr;
568 free(q->data);
569 free(q->tds);
570 free(q->qh);
571 free(q);
574 /* read one intr-packet from queue, if available. extend the queue for new input.
575 return NULL if nothing new available.
576 Recommended use: while (data=poll_intr_queue(q)) process(data);
578 static u8*
579 uhci_poll_intr_queue(void *q_)
581 intr_q *q = (intr_q*)q_;
582 if ((q->tds[q->lastread].ctrlsts & TD_STATUS_ACTIVE) == 0) {
583 int current = q->lastread;
584 int previous;
585 if (q->lastread == 0) {
586 previous = q->total - 1;
587 } else {
588 previous = q->lastread - 1;
590 q->tds[previous].ctrlsts &= ~TD_STATUS_MASK;
591 q->tds[previous].ptr = 0 | TD_TERMINATE;
592 if (q->last_td != &q->tds[previous]) {
593 q->last_td->ptr = virt_to_phys(&q->tds[previous]) & ~TD_TERMINATE;
594 q->last_td = &q->tds[previous];
596 q->tds[previous].ctrlsts |= TD_STATUS_ACTIVE;
597 q->lastread = (q->lastread + 1) % q->total;
598 if (!(q->tds[current].ctrlsts & TD_STATUS_MASK))
599 return &q->data[current*q->reqsize];
601 /* reset queue if we fully processed it after underrun */
602 else if (q->qh->elementlinkptr & FLISTP_TERMINATE) {
603 usb_debug("resetting underrun uhci interrupt queue.\n");
604 q->qh->elementlinkptr = virt_to_phys(q->tds + q->lastread);
606 return NULL;
609 void
610 uhci_reg_write32(hci_t *ctrl, usbreg reg, u32 value)
612 outl(value, ctrl->reg_base + reg);
616 uhci_reg_read32(hci_t *ctrl, usbreg reg)
618 return inl(ctrl->reg_base + reg);
621 void
622 uhci_reg_write16(hci_t *ctrl, usbreg reg, u16 value)
624 outw(value, ctrl->reg_base + reg);
628 uhci_reg_read16(hci_t *ctrl, usbreg reg)
630 return inw(ctrl->reg_base + reg);
633 void
634 uhci_reg_write8(hci_t *ctrl, usbreg reg, u8 value)
636 outb(value, ctrl->reg_base + reg);
640 uhci_reg_read8(hci_t *ctrl, usbreg reg)
642 return inb(ctrl->reg_base + reg);