⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hc_simple.c

📁 isp1161a USB主控制芯片驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/*-------------------------------------------------------------------------* * simple generic USB HCD frontend Version 0.9.6 (??/??/2003) * for embedded HCs (SL811HS, ISP1161 etc) *  * USB URB handling, hci_ hcs_ * URB queueing, qu_ * Transfer scheduling, sh_ * * Version history: *    0.9.5 (10/28/2001)    - taken from Linux 2.4.20 *    0.9.6 (??/??/2003)    - hacked up to use for isp1161 driver * * Authors: *    Original version (ISP1161) - Roman Weissgaerber <weissg@vienna.at> *    Cleaned up for  SL811HS    - Pei Liu <pbl@cypress.com> *      Updated to use for both    - Alex Bennee <kernel-hacker@bennee.com> * *-------------------------------------------------------------------------* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *-------------------------------------------------------------------------*//* main lock for urb access */static spinlock_t usb_urb_lock = SPIN_LOCK_UNLOCKED;/*-------------------------------------------------------------------------*//*-------------------------------------------------------------------------*//* URB HCD API function layer * * * *//*************************************************************************** * Function Name : hcs_urb_queue * * This function initializes the urb status and length before queueing the  * urb.  * * Input:  hci = data structure for the host controller *         urb = USB request block data structure  * * Return: 0  **************************************************************************/static inline int hcs_urb_queue (hci_t * hci, struct urb * urb){    int i;    if (usb_pipeisoc (urb->pipe)) {        DBGVERBOSE ("hcs_urb_queue: isoc pipe\n");        for (i = 0; i < urb->number_of_packets; i++) {            urb->iso_frame_desc[i].actual_length = 0;            urb->iso_frame_desc[i].status = -EXDEV;        }        /* urb->next hack : 1 .. resub, 0 .. single shot */        /* urb->interval = urb->next ? 1 : 0; */    }    urb->status = -EINPROGRESS;    urb->actual_length = 0;    urb->error_count = 0;    if (usb_pipecontrol (urb->pipe))        hc_flush_data_cache (hci, urb->setup_packet, 8);    if (usb_pipeout (urb->pipe))        hc_flush_data_cache (hci, urb->transfer_buffer,                     urb->transfer_buffer_length);    qu_queue_urb (hci, urb);    return 0;}/*************************************************************************** * Function Name : hcs_return_urb * * This function the return path of URB back to the USB core. It calls the * the urb complete function if exist, and also handles the resubmition of * interrupt URBs. * * Input:  hci = data structure for the host controller *         urb = USB request block data structure  *         resub_ok = resubmit flag: 1 = submit urb again, 0 = not submit  * * Return: 0  **************************************************************************/static int hcs_return_urb (hci_t * hci, struct urb * urb, int resub_ok){    struct usb_device *dev = urb->dev;    int resubmit = 0;    DBGFUNC ("enter hcs_return_urb, urb pointer = 0x%p, "         "transferbuffer point = 0x%p, "         " setup packet pointer = 0x%p, context pointer = 0x%p, "        " status = %d\n",         (__u32 *) urb, (__u32 *) urb->transfer_buffer,         (__u32 *) urb->setup_packet, (__u32 *) urb->context, urb->status);    if (urb_debug)        urb_print (urb, "RET", usb_pipeout (urb->pipe));    resubmit = urb->interval && resub_ok;    urb->dev = urb->hcpriv = NULL;    if (urb->complete) {        urb->complete (urb, hci->regs);    /* call complete */    }    if (resubmit) {        /* requeue the URB */        urb->dev = dev;        hcs_urb_queue (hci, urb);    }    return 0;}/*************************************************************************** * Function Name : hci_submit_urb * * This function is called by the USB core API when an URB is available to * process.  This function does the following * * 1) Check the validity of the URB * 2) Parse the device number from the URB * 3) Pass the URB to the root hub routine if its intended for the hub, else *    queue the urb for the attached device.  * * Input: urb = USB request block data structure  * * Return: 0 if success or error code  **************************************************************************/static int hci_submit_urb (struct urb * urb, int mem_flags){    hci_t *hci;    unsigned int pipe = urb->pipe;    unsigned long flags;    int ret;    /* for debugging     printk(KERN_ALERT "hci_submit_urb, urb=%p\n",urb);    usb_dump_urb(urb);    */    DBGFUNC ("enter hci_submit_urb, urb=%p pipe = 0x%x\n", urb, urb->pipe);    if (!urb->dev || !urb->dev->bus || urb->hcpriv)    {        printk(KERN_ALERT "hci_submit_urb: urb->dev:%p urb->dev->bus:%p urb->hcpriv:%p",            urb->dev, urb->dev->bus, urb->hcpriv);        return -EINVAL;    }//commented by xiongly for kernel 2.6/*    if (usb_endpoint_halted        (urb->dev, usb_pipeendpoint (pipe), usb_pipeout (pipe))) {        printk (KERN_ALERT "hci_submit_urb: endpoint_halted\n");        return -EPIPE;    }*/    hci = (hci_t *) urb->dev->bus->hcpriv;    /* a request to the virtual root hub */    if (usb_pipedevice (pipe) == hci->rh.devnum) {        if (urb_debug > 1)            urb_print (urb, "SUB-RH", usb_pipein (pipe));        return rh_submit_urb (urb);    }    /* queue the URB to its endpoint-queue */    spin_lock_irqsave (&usb_urb_lock, flags);    ret = hcs_urb_queue (hci, urb);    if (ret != 0) {        /* error on return */        DBGERR            ("hci_submit_urb: return err, ret = 0x%x, urb->status = 0x%x\n",             ret, urb->status);    }    spin_unlock_irqrestore (&usb_urb_lock, flags);    return ret;}/*************************************************************************** * Function Name : hci_unlink_urb * * This function mark the URB to unlink * * Input: urb = USB request block data structure  * * Return: 0 if success or error code  **************************************************************************/static int hci_unlink_urb (struct urb * urb, int status){    unsigned long flags;    hci_t *hci;    DECLARE_WAITQUEUE (wait, current);    void *comp = NULL;    DBGFUNC ("enter hci_unlink_urb\n");    if (!urb)        /* just to be sure */        return -EINVAL;    if (!urb->dev || !urb->dev->bus)        return -ENODEV;    hci = (hci_t *) urb->dev->bus->hcpriv;    /* a request to the virtual root hub */    if (usb_pipedevice (urb->pipe) == hci->rh.devnum) {        return rh_unlink_urb (urb);    }    if (urb_debug)        urb_print (urb, "UNLINK", 1);    spin_lock_irqsave (&usb_urb_lock, flags);    if (!list_empty (&urb->urb_list) && urb->status == -EINPROGRESS) {        /* URB active? */        if (urb->            transfer_flags & (USB_ASYNC_UNLINK | USB_TIMEOUT_KILLED)) {            /* asynchron with callback */            list_del (&urb->urb_list);    /* relink the urb to the del list */            list_add (&urb->urb_list, &hci->del_list);            spin_unlock_irqrestore (&usb_urb_lock, flags);        } else {            /* synchron without callback */            add_wait_queue (&hci->waitq, &wait);            set_current_state (TASK_UNINTERRUPTIBLE);            comp = urb->complete;            urb->complete = NULL;            list_del (&urb->urb_list);    /* relink the urb to the del list */            list_add (&urb->urb_list, &hci->del_list);            spin_unlock_irqrestore (&usb_urb_lock, flags);            schedule_timeout (HZ / 50);//            if (!list_empty (&urb->urb_list))//                list_del (&urb->urb_list);            urb->complete = comp;            urb->hcpriv = NULL;            remove_wait_queue (&hci->waitq, &wait);        }    } else {        /* hcd does not own URB but we keep the driver happy anyway */        spin_unlock_irqrestore (&usb_urb_lock, flags);        if (urb->complete && (urb->transfer_flags & USB_ASYNC_UNLINK)) {            urb->status = -ENOENT;            urb->actual_length = 0;            urb->complete (urb, hci->regs);            urb->status = 0;        } else {            urb->status = -ENOENT;        }    }    return 0;}/*************************************************************************** * Function Name : hci_alloc_dev * * This function allocates private data space for the usb device and  * initialize the endpoint descriptor heads. * * Input: usb_dev = pointer to the usb device  * * Return: 0 if success or error code  **************************************************************************/static int hci_alloc_dev (struct usb_device *usb_dev){    struct hci_device *dev;    int i;    DBGFUNC ("enter hci_alloc_dev\n");    dev = kmalloc (sizeof (*dev), GFP_KERNEL);    if (!dev)        return -ENOMEM;    memset (dev, 0, sizeof (*dev));    for (i = 0; i < 32; i++) {        INIT_LIST_HEAD (&(dev->ed[i].urb_queue));        dev->ed[i].pipe_head = NULL;    }    usb_dev->hcpriv = dev;    DBGVERBOSE ("USB HC dev alloc %d bytes\n", sizeof (*dev));    return 0;}/*************************************************************************** * Function Name : hci_free_dev * * This function de-allocates private data space for the usb devic * * Input: usb_dev = pointer to the usb device  * * Return: 0   **************************************************************************/static int hci_free_dev (struct usb_device *usb_dev){    DBGFUNC ("enter hci_free_dev\n");    if (usb_dev->hcpriv)        kfree (usb_dev->hcpriv);    usb_dev->hcpriv = NULL;    return 0;}/*************************************************************************** * Function Name : hci_get_current_frame_number * * This function get the current USB frame number * * Input: usb_dev = pointer to the usb device  * * Return: frame number   **************************************************************************/static int hci_get_current_frame_number (struct usb_device *usb_dev){    hci_t *hci = usb_dev->bus->hcpriv;    DBGFUNC ("enter hci_get_current_frame_number, frame = 0x%x \r\n",         hci->frame_number);    return (hci->frame_number);}/* sometimes alloc/free could use kmalloc with SLAB_DMA, for * better sharing and to leverage mm/slab.c intelligence. */static void *hci_buffer_alloc (        struct usb_bus          *bus,        size_t                  size,        int                     mem_flags,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -