📄 hc_simple.c
字号:
dma_addr_t *dma){ hci_t *hci = bus->hcpriv; /* some USB hosts just use PIO */ if (!bus->controller->dma_mask) { *dma = ~(dma_addr_t) 0; return kmalloc (size, mem_flags); } return dma_alloc_coherent (hci->bus->controller, size, dma, 0);}static void hci_buffer_free ( struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma){ hci_t *hci = bus->hcpriv; if (!addr) return; if (!bus->controller->dma_mask) { kfree (addr); return; } dma_free_coherent (hci->bus->controller, size, addr, dma);}/*************************************************************************** * List of all io-functions **************************************************************************/static struct usb_operations hci_device_operations = { allocate: hci_alloc_dev, deallocate: hci_free_dev, get_frame_number: hci_get_current_frame_number, submit_urb: hci_submit_urb, unlink_urb: hci_unlink_urb, buffer_alloc: hci_buffer_alloc, buffer_free: hci_buffer_free,};/*************************************************************************** * URB queueing: * * For each type of transfer (INTR, BULK, ISO, CTRL) there is a list of * active URBs. * (hci->intr_list, hci->bulk_list, hci->iso_list, hci->ctrl_list) * For every endpoint the head URB of the queued URBs is linked to one of * those lists. * * The rest of the queued URBs of an endpoint are linked into a * private URB list for each endpoint. (hci_dev->ed [endpoint_io].urb_queue) * hci_dev->ed [endpoint_io].pipe_head .. points to the head URB which is * in one of the active URB lists. * * The index of an endpoint consists of its number and its direction. * * The state of an intr and iso URB is 0. * For ctrl URBs the states are US_CTRL_SETUP, US_CTRL_DATA, US_CTRL_ACK * Bulk URBs states are US_BULK and US_BULK0 (with 0-len packet) * **************************************************************************//*************************************************************************** * Function Name : qu_urb_timeout * * This function is called when the URB timeout. The function unlinks the * URB. * * Input: lurb: URB * * Return: none **************************************************************************/#ifdef HC_URB_TIMEOUTstatic void qu_urb_timeout (unsigned long lurb){ struct urb *urb = (struct urb *) lurb; DBGFUNC ("enter qu_urb_timeout\n"); urb->transfer_flags |= USB_TIMEOUT_KILLED; hci_unlink_urb (urb, 0);}#endif/*************************************************************************** * Function Name : qu_pipeindex * * This function gets the index of the pipe. * * Input: pipe: the urb pipe * * Return: index **************************************************************************/static inline int qu_pipeindex (__u32 pipe){ DBGFUNC ("enter qu_pipeindex\n"); return (usb_pipeendpoint (pipe) << 1) | (usb_pipecontrol (pipe) ? 0 : usb_pipeout (pipe));}/*************************************************************************** * Function Name : qu_seturbstate * * This function set the state of the URB. * * control pipe: 3 states -- Setup, data, status * interrupt and bulk pipe: 1 state -- data * * Input: urb = USB request block data structure * state = the urb state * * Return: none **************************************************************************/static inline void qu_seturbstate (struct urb * urb, int state){ DBGFUNC ("enter qu_seturbstate/\n"); urb->pipe &= ~0x1f; urb->pipe |= (state & 0x1f);}/*************************************************************************** * Function Name : qu_urbstate * * This function get the current state of the URB. * * Input: urb = USB request block data structure * * Return: none **************************************************************************/static inline int qu_urbstate (struct urb * urb){ DBGFUNC ("enter qu_urbstate\n"); return urb->pipe & 0x1f;}/*************************************************************************** * Function Name : qu_queue_active_urb * * This function adds the urb to the appropriate active urb list and set * the urb state. * * There are four active lists: isochoronous list, interrupt list, * control list, and bulk list. * * Input: hci = data structure for the host controller * urb = USB request block data structure * ed = endpoint descriptor * * Return: none **************************************************************************/static inline void qu_queue_active_urb (hci_t * hci, struct urb * urb, epd_t * ed){ int urb_state = 0; switch (usb_pipetype (urb->pipe)) { case PIPE_CONTROL: list_add (&urb->urb_list, &hci->ctrl_list); urb_state = US_CTRL_SETUP; break; case PIPE_BULK: list_add (&urb->urb_list, &hci->bulk_list); if ((urb->transfer_flags & USB_ZERO_PACKET) && urb->transfer_buffer_length > 0 && ((urb->transfer_buffer_length % usb_maxpacket (urb->dev, urb->pipe, usb_pipeout (urb->pipe))) == 0)) { urb_state = US_BULK0; } break; case PIPE_INTERRUPT: urb->start_frame = hci->frame_number; list_add (&urb->urb_list, &hci->intr_list); break; case PIPE_ISOCHRONOUS: list_add (&urb->urb_list, &hci->iso_list); break; }#ifdef HC_URB_TIMEOUT if (urb->timeout) { ed->timeout.data = (unsigned long) urb; ed->timeout.expires = urb->timeout + jiffies; ed->timeout.function = qu_urb_timeout; add_timer (&ed->timeout); }#endif qu_seturbstate (urb, urb_state);}/*************************************************************************** * Function Name : qu_queue_urb * * This function adds the urb to the endpoint descriptor list * * Input: hci = data structure for the host controller * urb = USB request block data structure * * Return: none **************************************************************************/static int qu_queue_urb (hci_t * hci, struct urb * urb){ struct hci_device *hci_dev = usb_to_hci (urb->dev); epd_t *ed = &hci_dev->ed[qu_pipeindex (urb->pipe)]; /* for ISOC transfers calculate start frame index */ if (usb_pipeisoc (urb->pipe) && urb->transfer_flags & URB_ISO_ASAP) { urb->start_frame = ((ed->pipe_head) ? (ed->last_iso + 1) : hci_get_current_frame_number (urb-> dev) + 1) & 0xffff; } if (ed->pipe_head) { __list_add (&urb->urb_list, ed->urb_queue.prev, &(ed->urb_queue)); } else { ed->pipe_head = urb; qu_queue_active_urb (hci, urb, ed); if (++hci->active_urbs == 1) hc_start_int (hci); } return 0;}/*************************************************************************** * Function Name : qu_next_urb * * This function removes the URB from the queue and add the next URB to * active list. * * Input: hci = data structure for the host controller * urb = USB request block data structure * resub_ok = resubmit flag * * Return: pointer to the next urb **************************************************************************/static struct urb *qu_next_urb (hci_t * hci, struct urb * urb, int resub_ok){ struct hci_device *hci_dev = usb_to_hci (urb->dev); epd_t *ed = &hci_dev->ed[qu_pipeindex (urb->pipe)]; DBGFUNC ("enter qu_next_urb\n"); list_del (&urb->urb_list); INIT_LIST_HEAD (&urb->urb_list); if (ed->pipe_head == urb) {#ifdef HC_URB_TIMEOUT if (urb->timeout) del_timer (&ed->timeout);#endif if (!--hci->active_urbs) hc_stop_int (hci); if (!list_empty (&ed->urb_queue)) { urb = list_entry (ed->urb_queue.next, struct urb, urb_list); list_del (&urb->urb_list); INIT_LIST_HEAD (&urb->urb_list); ed->pipe_head = urb; qu_queue_active_urb (hci, urb, ed); } else { ed->pipe_head = NULL; urb = NULL; } } return urb;}/*************************************************************************** * Function Name : qu_return_urb * * This function is part of the return path. * * Input: hci = data structure for the host controller * urb = USB request block data structure * resub_ok = resubmit flag * * Return: pointer to the next urb **************************************************************************/static struct urb *qu_return_urb (hci_t * hci, struct urb * urb, int resub_ok){ struct urb *next_urb; DBGFUNC ("enter qu_return_rub\n"); next_urb = qu_next_urb (hci, urb, resub_ok); hcs_return_urb (hci, urb, resub_ok); return next_urb;}/*************************************************************************** * Function Name : sh_scan_iso_urb_list * * This function goes throught the isochronous urb list and schedule the * the transfer. * * Note: This function has not tested yet * * Input: hci = data structure for the host controller * list_lh = pointer to the isochronous list * frame_number = the frame number * * Return: 0 = unsuccessful; 1 = successful **************************************************************************/static int sh_scan_iso_urb_list (hci_t * hci, struct list_head *list_lh, int frame_number){ struct list_head *lh = list_lh->next; struct urb *urb; DBGFUNC ("enter sh_scan_iso_urb_list\n"); hci->td_array->len = 0; while (lh != list_lh) { urb = list_entry (lh, struct urb, urb_list); lh = lh->next; if (((frame_number - urb->start_frame) & 0x7ff) < urb->number_of_packets) { if (!sh_add_packet (hci, urb)) { return 0; } else { if (((frame_number - urb->start_frame) & 0x7ff) > 0x400) { if (qu_urbstate (urb) > 0) { urb = qu_return_urb (hci, urb, 1); } else { urb = qu_next_urb (hci, urb, 1); } if (lh == list_lh && urb) lh = &urb->urb_list; } } } } return 1;}/*************************************************************************** * Function Name : sh_scan_urb_list * * This function goes through the urb list and schedule the * the transaction. * * Input: hci = data structure for the host controller * list_lh = pointer to the isochronous list * * Return: 0 = unsuccessful; 1 = successful **************************************************************************/static int sh_scan_urb_list (hci_t * hci, struct list_head *list_lh){ struct list_head *lh = NULL; struct urb *urb; if (list_lh == NULL) { DBGERR ("sh_scan_urb_list: error, list_lh == NULL\n"); } DBGFUNC ("enter sh_scan_urb_list: frame# \n"); list_for_each (lh, list_lh) { urb = list_entry (lh, struct urb, urb_list); if (urb == NULL) return 1; if (!usb_pipeint (urb->pipe) || (((hci->frame_number - urb->start_frame) & 0x7ff) >= urb->interval)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -