📄 u132-hcd.c
字号:
up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -EINTR); return; } else if (u132->going > 0) { dev_err(&u132->platform_dev->dev, "device is being removed urb=" "%p status=%d\n", urb, urb->status); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, -ENODEV); return; } else if (urb->status == -EINPROGRESS) { int retval; struct u132_ring *ring = endp->ring; up(&u132->scheduler_lock); retval = usb_ftdi_elan_edset_input(u132->platform_dev, ring->number, endp, urb, address, endp->usb_endp, 0, u132_hcd_initial_input_recv); if (retval == 0) { } else u132_hcd_giveback_urb(u132, endp, urb, retval); return; } else { dev_err(&u132->platform_dev->dev, "CALLBACK called urb=%p statu" "s=%d\n", urb, urb->status); up(&u132->scheduler_lock); u132_hcd_giveback_urb(u132, endp, urb, urb->status); return; }}/** this work function is only executed from the work queue**/static void u132_hcd_ring_work_scheduler(struct work_struct *work){ struct u132_ring *ring = container_of(work, struct u132_ring, scheduler.work); struct u132 *u132 = ring->u132; down(&u132->scheduler_lock); if (ring->in_use) { up(&u132->scheduler_lock); u132_ring_put_kref(u132, ring); return; } else if (ring->curr_endp) { struct u132_endp *last_endp = ring->curr_endp; struct list_head *scan; struct list_head *head = &last_endp->endp_ring; unsigned long wakeup = 0; list_for_each(scan, head) { struct u132_endp *endp = list_entry(scan, struct u132_endp, endp_ring); if (endp->queue_next == endp->queue_last) { } else if ((endp->delayed == 0) || time_after_eq(jiffies, endp->jiffies)) { ring->curr_endp = endp; u132_endp_cancel_work(u132, last_endp); u132_endp_queue_work(u132, last_endp, 0); up(&u132->scheduler_lock); u132_ring_put_kref(u132, ring); return; } else { unsigned long delta = endp->jiffies - jiffies; if (delta > wakeup) wakeup = delta; } } if (last_endp->queue_next == last_endp->queue_last) { } else if ((last_endp->delayed == 0) || time_after_eq(jiffies, last_endp->jiffies)) { u132_endp_cancel_work(u132, last_endp); u132_endp_queue_work(u132, last_endp, 0); up(&u132->scheduler_lock); u132_ring_put_kref(u132, ring); return; } else { unsigned long delta = last_endp->jiffies - jiffies; if (delta > wakeup) wakeup = delta; } if (wakeup > 0) { u132_ring_requeue_work(u132, ring, wakeup); up(&u132->scheduler_lock); return; } else { up(&u132->scheduler_lock); u132_ring_put_kref(u132, ring); return; } } else { up(&u132->scheduler_lock); u132_ring_put_kref(u132, ring); return; }}static void u132_hcd_endp_work_scheduler(struct work_struct *work){ struct u132_ring *ring; struct u132_endp *endp = container_of(work, struct u132_endp, scheduler.work); struct u132 *u132 = endp->u132; down(&u132->scheduler_lock); ring = endp->ring; if (endp->edset_flush) { endp->edset_flush = 0; if (endp->dequeueing) usb_ftdi_elan_edset_flush(u132->platform_dev, ring->number, endp); up(&u132->scheduler_lock); u132_endp_put_kref(u132, endp); return; } else if (endp->active) { up(&u132->scheduler_lock); u132_endp_put_kref(u132, endp); return; } else if (ring->in_use) { up(&u132->scheduler_lock); u132_endp_put_kref(u132, endp); return; } else if (endp->queue_next == endp->queue_last) { up(&u132->scheduler_lock); u132_endp_put_kref(u132, endp); return; } else if (endp->pipetype == PIPE_INTERRUPT) { u8 address = u132->addr[endp->usb_addr].address; if (ring->in_use) { up(&u132->scheduler_lock); u132_endp_put_kref(u132, endp); return; } else { int retval; struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]; endp->active = 1; ring->curr_endp = endp; ring->in_use = 1; up(&u132->scheduler_lock); retval = edset_single(u132, ring, endp, urb, address, endp->toggle_bits, u132_hcd_interrupt_recv); if (retval == 0) { } else u132_hcd_giveback_urb(u132, endp, urb, retval); return; } } else if (endp->pipetype == PIPE_CONTROL) { u8 address = u132->addr[endp->usb_addr].address; if (ring->in_use) { up(&u132->scheduler_lock); u132_endp_put_kref(u132, endp); return; } else if (address == 0) { int retval; struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]; endp->active = 1; ring->curr_endp = endp; ring->in_use = 1; up(&u132->scheduler_lock); retval = edset_setup(u132, ring, endp, urb, address, 0x2, u132_hcd_initial_setup_sent); if (retval == 0) { } else u132_hcd_giveback_urb(u132, endp, urb, retval); return; } else if (endp->usb_addr == 0) { int retval; struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]; endp->active = 1; ring->curr_endp = endp; ring->in_use = 1; up(&u132->scheduler_lock); retval = edset_setup(u132, ring, endp, urb, 0, 0x2, u132_hcd_enumeration_address_sent); if (retval == 0) { } else u132_hcd_giveback_urb(u132, endp, urb, retval); return; } else { int retval; u8 address = u132->addr[endp->usb_addr].address; struct urb *urb = endp->urb_list[ENDP_QUEUE_MASK & endp->queue_next]; endp->active = 1; ring->curr_endp = endp; ring->in_use = 1; up(&u132->scheduler_lock); retval = edset_setup(u132, ring, endp, urb, address, 0x2, u132_hcd_configure_setup_sent); if (retval == 0) { } else u132_hcd_giveback_urb(u132, endp, urb, retval); return; } } else { if (endp->input) { u8 address = u132->addr[endp->usb_addr].address; if (ring->in_use) { up(&u132->scheduler_lock); u132_endp_put_kref(u132, endp); return; } else { int retval; struct urb *urb = endp->urb_list[ ENDP_QUEUE_MASK & endp->queue_next]; endp->active = 1; ring->curr_endp = endp; ring->in_use = 1; up(&u132->scheduler_lock); retval = edset_input(u132, ring, endp, urb, address, endp->toggle_bits, u132_hcd_bulk_input_recv); if (retval == 0) { } else u132_hcd_giveback_urb(u132, endp, urb, retval); return; } } else { /* output pipe */ u8 address = u132->addr[endp->usb_addr].address; if (ring->in_use) { up(&u132->scheduler_lock); u132_endp_put_kref(u132, endp); return; } else { int retval; struct urb *urb = endp->urb_list[ ENDP_QUEUE_MASK & endp->queue_next]; endp->active = 1; ring->curr_endp = endp; ring->in_use = 1; up(&u132->scheduler_lock); retval = edset_output(u132, ring, endp, urb, address, endp->toggle_bits, u132_hcd_bulk_output_sent); if (retval == 0) { } else u132_hcd_giveback_urb(u132, endp, urb, retval); return; } } }}static void port_power(struct u132 *u132, int pn, int is_on){ u132->port[pn].power = is_on;}static void u132_power(struct u132 *u132, int is_on){ struct usb_hcd *hcd = u132_to_hcd(u132) ; /* hub is inactive unless the port is powered */ if (is_on) { if (u132->power) return; u132->power = 1; hcd->self.controller->power.power_state = PMSG_ON; } else { u132->power = 0; hcd->state = HC_STATE_HALT; hcd->self.controller->power.power_state = PMSG_SUSPEND; }}static int u132_periodic_reinit(struct u132 *u132){ int retval; u32 fi = u132->hc_fminterval & 0x03fff; u32 fit; u32 fminterval; retval = u132_read_pcimem(u132, fminterval, &fminterval); if (retval) return retval; fit = fminterval & FIT; retval = u132_write_pcimem(u132, fminterval, (fit ^ FIT) | u132->hc_fminterval); if (retval) return retval; retval = u132_write_pcimem(u132, periodicstart, ((9 *fi) / 10) & 0x3fff); if (retval) return retval; return 0;}static char *hcfs2string(int state){ switch (state) { case OHCI_USB_RESET: return "reset"; case OHCI_USB_RESUME: return "resume"; case OHCI_USB_OPER: return "operational"; case OHCI_USB_SUSPEND: return "suspend"; } return "?";}static int u132_init(struct u132 *u132){ int retval; u32 control; u132_disable(u132); u132->next_statechange = jiffies; retval = u132_write_pcimem(u132, intrdisable, OHCI_INTR_MIE); if (retval) return retval; retval = u132_read_pcimem(u132, control, &control); if (retval) return retval; if (u132->num_ports == 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -