static int run_schedule (usbdev_t *dev, td_t *td) { UHCI_INST (dev->controller)->qh_data->elementlinkptr = virt_to_phys (td) & ~(FLISTP_QH | FLISTP_TERMINATE); td = wait_for_completed_qh (dev->controller, UHCI_INST (dev->controller)->qh_data); if (td == 0) { return 0; } else { td_dump (td); return 1; } }
static int run_schedule (usbdev_t *dev, td_t *td) { UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr = virt_to_phys (td); UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0; UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0; td = wait_for_completed_qh (dev->controller, UHCI_INST (dev->controller)->qh_data); if (td == 0) { return 0; } else { td_dump (td); return 1; } }
static int uhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen, unsigned char *data) { int endp = 0; /* this is control: always 0 */ int mlen = dev->endpoints[0].maxpacketsize; int count = (2 + (dalen + mlen - 1) / mlen); unsigned short req = ((unsigned short *) devreq)[0]; int i; td_t *tds = memalign (16, sizeof (td_t) * count); memset (tds, 0, sizeof (td_t) * count); count--; /* to compensate for 0-indexed array */ for (i = 0; i < count; i++) { tds[i].ptr = virt_to_phys (&tds[i + 1]) | TD_DEPTH_FIRST; } tds[count].ptr = 0 | TD_DEPTH_FIRST | TD_TERMINATE; tds[0].token = UHCI_SETUP | dev->address << TD_DEVADDR_SHIFT | endp << TD_EP_SHIFT | TD_TOGGLE_DATA0 | maxlen(drlen) << TD_MAXLEN_SHIFT; tds[0].bufptr = virt_to_phys (devreq); tds[0].ctrlsts = (3 << TD_COUNTER_SHIFT) | (dev->speed?TD_LOWSPEED:0) | TD_STATUS_ACTIVE; int toggle = 1; for (i = 1; i < count; i++) { switch (dir) { case SETUP: tds[i].token = UHCI_SETUP; break; case IN: tds[i].token = UHCI_IN; break; case OUT: tds[i].token = UHCI_OUT; break; } tds[i].token |= dev->address << TD_DEVADDR_SHIFT | endp << TD_EP_SHIFT | maxlen (min (mlen, dalen)) << TD_MAXLEN_SHIFT | toggle << TD_TOGGLE_SHIFT; tds[i].bufptr = virt_to_phys (data); tds[i].ctrlsts = (3 << TD_COUNTER_SHIFT) | (dev->speed?TD_LOWSPEED:0) | TD_STATUS_ACTIVE; toggle ^= 1; dalen -= mlen; data += mlen; } tds[count].token = ((dir == OUT) ? UHCI_IN : UHCI_OUT) | dev->address << TD_DEVADDR_SHIFT | endp << TD_EP_SHIFT | maxlen(0) << TD_MAXLEN_SHIFT | TD_TOGGLE_DATA1; tds[count].bufptr = 0; tds[count].ctrlsts = (0 << TD_COUNTER_SHIFT) | /* as Linux 2.4.10 does */ (dev->speed?TD_LOWSPEED:0) | TD_STATUS_ACTIVE; UHCI_INST (dev->controller)->qh_data->elementlinkptr = virt_to_phys (tds) & ~(FLISTP_QH | FLISTP_TERMINATE); td_t *td = wait_for_completed_qh (dev->controller, UHCI_INST (dev->controller)-> qh_data); int result; if (td == 0) { result = 0; } else { usb_debug ("control packet, req %x\n", req); td_dump (td); result = 1; } free (tds); return result; }
static int uhci_control (usbdev_t *dev, direction_t dir, int drlen, void *devreq, int dalen, unsigned char *data) { int endp = 0; /* this is control: always 0 */ int mlen = dev->endpoints[0].maxpacketsize; int count = (2 + (dalen + mlen - 1) / mlen); unsigned short req = ((unsigned short *) devreq)[0]; int i; td_t *tds = memalign (16, sizeof (td_t) * count); memset (tds, 0, sizeof (td_t) * count); count--; /* to compensate for 0-indexed array */ for (i = 0; i < count; i++) { tds[i].ptr = virt_to_phys (&tds[i + 1]); tds[i].depth_first = 1; tds[i].terminate = 0; } tds[count].ptr = 0; tds[count].depth_first = 1; tds[count].terminate = 1; tds[0].pid = UHCI_SETUP; tds[0].dev_addr = dev->address; tds[0].endp = endp; tds[0].maxlen = maxlen (drlen); tds[0].counter = 3; tds[0].data_toggle = 0; tds[0].lowspeed = dev->speed; tds[0].bufptr = virt_to_phys (devreq); tds[0].status_active = 1; int toggle = 1; for (i = 1; i < count; i++) { switch (dir) { case SETUP: tds[i].pid = UHCI_SETUP; break; case IN: tds[i].pid = UHCI_IN; break; case OUT: tds[i].pid = UHCI_OUT; break; } tds[i].dev_addr = dev->address; tds[i].endp = endp; tds[i].maxlen = maxlen (min (mlen, dalen)); tds[i].counter = 3; tds[i].data_toggle = toggle; tds[i].lowspeed = dev->speed; tds[i].bufptr = virt_to_phys (data); tds[i].status_active = 1; toggle ^= 1; dalen -= mlen; data += mlen; } tds[count].pid = (dir == OUT) ? UHCI_IN : UHCI_OUT; tds[count].dev_addr = dev->address; tds[count].endp = endp; tds[count].maxlen = maxlen (0); tds[count].counter = 0; /* as per linux 2.4.10 */ tds[count].data_toggle = 1; tds[count].lowspeed = dev->speed; tds[count].bufptr = 0; tds[count].status_active = 1; UHCI_INST (dev->controller)->qh_data->elementlinkptr.ptr = virt_to_phys (tds); UHCI_INST (dev->controller)->qh_data->elementlinkptr.queue_head = 0; UHCI_INST (dev->controller)->qh_data->elementlinkptr.terminate = 0; td_t *td = wait_for_completed_qh (dev->controller, UHCI_INST (dev->controller)-> qh_data); int result; if (td == 0) { result = 0; } else { debug ("control packet, req %x\n", req); td_dump (td); result = 1; } free (tds); return result; }