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

📄 tc86c001.c

📁 Linux2.4.20针对三星公司的s3c2440内核基础上的一些设备驱动代码
💻 C
📖 第 1 页 / 共 3 页
字号:
static struct tq_struct tc_task = {    routine:tc_do_task};static voidtc_start_out (unsigned int ep){    struct usb_endpoint_instance *endpoint = ep_endpoints[ep];    struct urb *urb = endpoint->rcv_urb;    int size;    if (!urb) {        dbg_rx (2, "no rcv_urb");        dbg_rx (1, "ep%d no rcv_urb available.  try again.", ep);        set_bit (ep, &tc_do_task_ep);        schedule_task (&tc_task);        // XXX could we call usbd_fill_rcv() here?        return;    }    if (!nodma && ep == UDC_MSTWR_ENDPOINT) {        /* DMA endpoint */        if (urb->actual_length == 0) {            if (ep_dmaaddrs[ep]) {                printk (KERN_ERR UDC_NAME ": receive DMA busy.\n");                //return;            }            ep_dmaaddrs[ep] =                pci_map_single (udc_pci_dev,                urb->buffer, urb->buffer_length, PCI_DMA_FROMDEVICE);            dbg_rx (2, "rx dmaaddr(%d) %x", ep, ep_dmaaddrs[ep]);            if (!ep_dmaaddrs[ep]) {                printk (KERN_ERR UDC_NAME ": pci_map_single failed.\n");                usbd_rcv_complete_irq (endpoint, 0, 1);                return;            }        }        /* start DMA (master write) */        /* check short packet without following three SOFs... */        size = tc_read_epxsize (ep);        if (size == endpoint->rcv_packetSize) {            /* fulll packet: transfer continuous packets */            size = min ((int) (urb->buffer_length - urb->actual_length),                endpoint->rcv_transferSize);        }        tc_mstwr_start (ep_dmaaddrs[ep] + urb->actual_length, size);        return;    }    /* check EPx_DSETA */    if (!(readl (&tc_udcregs->DataSet[0]) & (1 << (ep * 2)))) {        printk (KERN_ERR UDC_NAME ": ep%d FIFO empty\n", ep);        return;    }    size = tc_read_epxsize (ep);    if (size == 0) {        printk (KERN_ERR UDC_NAME ": ep%d SIZE 0\n", ep);        return;    }    dbg_rx (2, "ep%d rx size 0x%x (status %x)",        ep, size, readl (&tc_udcregs->EPxStatus[ep]));    tc_read_buffer (ep, urb->buffer + urb->actual_length, size);    usbd_rcv_complete_irq (endpoint, size, 0);}static voidtc_end_out (unsigned int ep, int tout){    struct usb_endpoint_instance *endpoint = ep_endpoints[ep];    struct urb *urb = endpoint->rcv_urb;    int size;    int org_buffer_length;    if (!ep_dmaaddrs[ep] || !urb) {        dbg_rx (0, "not mstwr");        return;    }    size = readl (&tc_regs->MstWrCurr) + 1 - ep_dmaaddrs[ep];    dbg_rx (2, "mstwr end (size 0x%x tout %d)", size, tout);    org_buffer_length = urb->buffer_length;    while (size > 0) {        int len = min (size, endpoint->rcv_packetSize);        if (endpoint->rcv_urb != urb) {            dbg_rx (0, "BUG: rcv_urb consumed!!!");            break;        }        usbd_rcv_complete_irq (endpoint, len, 0);        size -= len;        if (size == 0 && len == endpoint->rcv_packetSize &&            endpoint->rcv_urb == urb) {            /* null packet (send current rcv_urb to function driver) */            usbd_rcv_complete_irq (endpoint, 0, 0);        }    }    if (endpoint->rcv_urb != urb) {        pci_unmap_single (udc_pci_dev, ep_dmaaddrs[ep], org_buffer_length,            PCI_DMA_FROMDEVICE);        ep_dmaaddrs[ep] = 0;    }}/* *********************************************************************** *//* Bulk IN (tx) *//** * start_in - start transmit * @ep: */static voidtc_start_in (unsigned int ep){    struct usb_endpoint_instance *endpoint = ep_endpoints[ep];    struct urb *urb = endpoint->tx_urb;    if (!nodma) {        if (ep_dmaaddrs[ep]) {            dbg_tx (0, "ep%d DMA busy", ep);            return;        }        if (readl (&tc_regs->MstSetting) & MST_RD_ENA) {            dbg_tx (0, "ep%d DMARD busy", ep);            return;        }    }    usbd_tx_complete_irq (endpoint, 0);    /* send next urb */    if ((urb = endpoint->tx_urb) != NULL) {        if (!nodma && ep == UDC_MSTRD_ENDPOINT) {            /* start DMA (master read) */            if (endpoint->sent == 0) {                ep_dmaaddrs[ep] =                    pci_map_single (udc_pci_dev,                    urb->buffer, urb->buffer_length, PCI_DMA_TODEVICE);                dbg_tx (2, "tx dmaaddr(%d) %x", ep, ep_dmaaddrs[ep]);                if (!ep_dmaaddrs[ep]) {                    printk (KERN_ERR UDC_NAME ": pci_map_single failed.\n");                    endpoint->last = urb->actual_length;                    usbd_tx_complete_irq (endpoint, 0);                    return;                }            }            /* invoke master read for whole urb buffer */            endpoint->last = urb->actual_length - endpoint->sent;            if (endpoint->last == 0) {                /* send NULL packet */                dbg_tx (2, "ep%d EOPB", ep);                writel ((readl (&tc_regs->                            MstSetting) & MST_RW_BITS) | MST_RD_EOPB,                    &tc_regs->MstSetting);                while (readl (&tc_regs->MstSetting) & MST_RD_EOPB);            } else {                /* disable EOP if transfersize is multiple of packetsize */                int eop = (endpoint->last % endpoint->tx_packetSize != 0);                tc_mstrd_start (ep_dmaaddrs[ep] + endpoint->sent,                    endpoint->last, eop);            }            return;        }        /* check EPx_DSETA */        if (readl (&tc_udcregs->DataSet[0]) & (1 << (ep * 2))) {            printk (KERN_ERR UDC_NAME ": ep%d FIFO not empty"                " (urb length %d sent %d)\n",                ep, urb->actual_length, endpoint->sent);            return;        }        if ((urb->actual_length - endpoint->sent) > 0) {            endpoint->last =                min_t (int, urb->actual_length - endpoint->sent,                endpoint->tx_packetSize);            dbg_tx (2, "ep%d tx size 0x%x", ep, endpoint->last);            tc_write_buffer (ep, urb->buffer + endpoint->sent,                endpoint->last);            if (endpoint->last < endpoint->tx_packetSize) {                dbg_tx (2, "EOP %d", ep);                writel (~(1 << ep), &tc_udcregs->EOP);            }        } else {            // XXX ZLP            endpoint->last = 0;            dbg_tx (2, "EOP %d", ep);            writel (~(1 << ep), &tc_udcregs->EOP);        }    } else if (nodma && (endpoint->last == endpoint->tx_packetSize)) {        // XXX ZLP        dbg_tx (2, "EOP %d (last %d)", ep, endpoint->last);        endpoint->last = 0;        writel (~(1 << ep), &tc_udcregs->EOP);    }}static voidtc_end_in (unsigned int ep){    struct usb_endpoint_instance *endpoint = ep_endpoints[ep];    struct urb *urb = endpoint->tx_urb;    if (!ep_dmaaddrs[ep] || !urb)        return;    dbg_tx (2, "mstrd end (size 0x%x)",        readl (&tc_regs->MstRdCurr) + 1 - ep_dmaaddrs[ep]);    if (endpoint->sent + endpoint->last >= urb->actual_length) {        pci_unmap_single (udc_pci_dev, ep_dmaaddrs[ep], urb->buffer_length,            PCI_DMA_TODEVICE);        ep_dmaaddrs[ep] = 0;    }    /* complete current tx packet and start next transmit (if exists) */    tc_start_in (ep);}/* *********************************************************************** *//* Interrupt Handler */static voidtc_setup_descram_if (struct usb_device_instance *device,    int port, int nconf, int nint, int *ofs){    struct usb_interface_instance *iinst;    int nalt;    iinst = usbd_device_interface_instance (device, port, nconf, nint);    if (!iinst)        return;    for (nalt = 0; nalt < iinst->alternates; nalt++) {        struct usb_interface_descriptor *idesc;        struct usb_alternate_instance *ainst;        int nclass, nep;        ainst = usbd_device_alternate_instance (device, port,            nconf, nint, nalt);        if (!ainst)            break;        idesc = ainst->interface_descriptor;        copy_descram (idesc, sizeof (*idesc), ofs);        for (nclass = 0; nclass < ainst->classes; nclass++) {            struct usb_class_descriptor *cldesc;            cldesc = usbd_device_class_descriptor_index (device,                port, nconf, nint, nalt, nclass);            if (!cldesc)                break;            copy_descram (cldesc, cldesc->descriptor.generic.bFunctionLength,                ofs);        }        for (nep = 0; nep < ainst->endpoints; nep++) {            struct usb_endpoint_descriptor *edesc;            edesc = usbd_device_endpoint_descriptor_index (device,                port, nconf, nint, nalt, nep);            if (!edesc)                break;            copy_descram (edesc, sizeof (*edesc), ofs);        }    }}static voidtc_setup_descram_str (int *ofs){    u8 bLength[4] = { 0, 0, 0, 0 };    copy_descram (&bLength, 4, ofs);}static voidtc_setup_descram (void){    struct usb_device_descriptor *ddesc;    int ofs = 0, nconf;    int i;    ddesc = usbd_device_device_descriptor (udc_device, 0);    if (!ddesc)        return;    copy_descram (ddesc, sizeof (*ddesc), &ofs);    for (nconf = 0; nconf < ddesc->bNumConfigurations; nconf++) {        struct usb_configuration_descriptor *cdesc;        int nint;        cdesc = usbd_device_configuration_descriptor (udc_device, 0, nconf);        if (!cdesc)            break;        copy_descram (cdesc, sizeof (*cdesc), &ofs);        for (nint = 0; nint < cdesc->bNumInterfaces; nint++) {            tc_setup_descram_if (udc_device, 0, nconf, nint, &ofs);        }    }    tc_setup_descram_str (&ofs);    for (i = ofs; i < UDC_DESCRAM_SIZE; i++)        writel (0, &tc_ramregs->DescRam[i]);    for (i = 0; i < ofs; i += 8)        dbg_udc (2, "Descram: %02x %02x %02x %02x %02x %02x %02x %02x",            readl (&tc_ramregs->DescRam[i + 0]),            readl (&tc_ramregs->DescRam[i + 1]),            readl (&tc_ramregs->DescRam[i + 2]),            readl (&tc_ramregs->DescRam[i + 3]),            readl (&tc_ramregs->DescRam[i + 4]),            readl (&tc_ramregs->DescRam[i + 5]),            readl (&tc_ramregs->DescRam[i + 6]),            readl (&tc_ramregs->DescRam[i + 7]));}static voidtc_power_detected (void){    int i;    u8 bcs, single;    if (readl (&tc_regs->PowerDetect) & PW_DETECT) {        /* power detected */        dbg_udc (1, "Power detected");        usbd_device_event_irq (udc_device, DEVICE_HUB_CONFIGURED, 0);        /* assert reset */        writel (0, &tc_regs->PowerDetect);        readl (&tc_regs->IntStatus);        /* wbflush */        udelay (1);        /* deassert reset (USB_RESET still disabled) */        writel (MST_EOPB_ENA | MST_TIMEOUT_ENA, &tc_regs->MstSetting);        writel (PW_RESETB, &tc_regs->PowerDetect);        writel (STDREQ_S_CONFIG | STDREQ_G_CONFIG | STDREQ_G_DESCRIPT,            &tc_udcregs->StdReqMode);        /* EP[2:1]:DMA access, EP[3]:CPU access (single) */        bcs = single = 0;        for (i = 1; i < 4; i++) {            single |= 0x11 << i;            bcs |= ((i == 3 || nodma) ? 0x11 /*CPU*/ : 0x10 /*DMA*/) << i;        }        writel (single, &tc_udcregs->EPxSingle[0]);        writel (bcs, &tc_udcregs->EPxBCS[0]);        tc_setup_descram ();        /* enable USB_RESET detection */        writel (0, &tc_udcregs->UsbReady);    } else {        /* power down */        dbg_udc (1, "Power down");        usbd_device_event_irq (udc_device, DEVICE_RESET, 0);        usbd_device_event_irq (udc_device, DEVICE_POWER_INTERRUPTION, 0);        usbd_device_event_irq (udc_device, DEVICE_HUB_RESET, 0);    }}/** * int_hndlr - interrupt handler * */static voidtc_int_hndlr (int irq, void *dev_id, struct pt_regs *regs){    int count, i;    u32 stat, mask;    udc_interrupts++;    for (count = 0; count < 10; count++) {        stat = readl (&tc_regs->IntStatus);        mask = readl (&tc_regs->IntEnable);        if ((stat & mask) == 0)            break;        dbg_udc (3, "stat %x mask %x", stat, mask);        stat &= mask;        if (stat & INT_ERR) {            writel (~INT_ERR, &tc_regs->IntStatus);            printk (KERN_ERR UDC_NAME ": ERR interrupt.\n");            continue;        }        if (stat & INT_SYSERROR) {            writel (~INT_SYSERROR, &tc_regs->IntStatus);            printk (KERN_ERR UDC_NAME ": SYSERROR interrupt.\n");            continue;        }        if (stat & INT_PWRDETECT) {            writel (~INT_PWRDETECT, &tc_regs->IntStatus);            if (!udc_device)                continue;            //udc_cable_event();            tc_power_detected ();            continue;        }        if (stat & INT_USBRESET) {            writel (~INT_USBRESET, &tc_regs->IntStatus);            if (!udc_device)                continue;            /* USBRESET received */            usbd_device_event_irq (udc_device, DEVICE_RESET, 0);            /* enable pull-up */            dbg_udc (1, "Enabling pullup");            writel (PW_RESETB | PW_PLLUPENB, &tc_regs->PowerDetect);            continue;        }        if (stat & INT_SUSPEND) {            writel (~INT_SUSPEND, &tc_regs->IntStatus);            if (!udc_device)                continue;#if 0            if (udc_device->device_state == STATE_UNKNOWN ||                udc_device->device_state == STATE_INIT ||                udc_device->device_state == STATE_ATTACHED)                continue;#endif            if (readl (&tc_udcregs->EPxStatus[0]) & EPxSTATUS_SUSPEND) {                dbg_udc (1, "Suspend");                usbd_device_event (udc_device, DEVICE_BUS_INACTIVE, 0);            } else {                dbg_udc (1, "Resume");                usbd_device_event (udc_device, DEVICE_BUS_ACTIVITY, 0);            }            continue;        }        if (stat & INT_SETUP) {            dbg_udc (1, "Setup");            writel (~INT_SETUP, &tc_regs->IntStatus);            tc_ep0_setup ();            continue;        }        if (stat & INT_ENDPOINT0) {            writel (~INT_ENDPOINT0, &tc_regs->IntStatus);            usbd_tx_complete_irq (ep_endpoints[0], 0);            tc_in_ep0 (ep_endpoints[0]);            // XXX how about control write?            continue;        }        if (stat & INT_MSTWRTMOUT) {            writel (~INT_MSTWRTMOUT, &tc_regs->IntStatus);            tc_end_out (UDC_MSTWR_ENDPOINT, 1);            continue;        }        if (stat & INT_MSTWREND) {            writel (~INT_MSTWREND, &tc_regs->IntStatus);            tc_end_out (UDC_MSTWR_ENDPOINT, 0);            continue;        }        if (stat & INT_MSTWRSET) {            writel (~INT_MSTWRSET, &tc_regs->IntStatus);            /* start master write */            tc_start_out (UDC_MSTWR_ENDPOINT);            continue;        }        if (stat & INT_MSTRDEND) {            writel (~INT_MSTRDEND, &tc_regs->IntStatus);            tc_end_in (UDC_MSTRD_ENDPOINT);            continue;        }        for (i = 1; i < 4; i++) {            if (stat & INT_EPxDATASET (i)) {                writel (~INT_EPxDATASET (i), &tc_regs->IntStatus);                if (!ep_endpoints[i])                    continue;                if (ep_endpoints[i]->endpoint_address & USB_DIR_IN) {                    tc_start_in (i);                } else {                    tc_start_out (i);                }            }        }    }}/* *********************************************************************** */static int __devinitudc_probe (struct pci_dev *pdev, const struct pci_device_id *ent){    void *mmio;    if (udc_pci_dev) {        /* multiple instance is not supported */        return -ENODEV;    }    /* make sure PCI base addr 0 is MMIO */    if (!(pci_resource_flags (pdev, 0) & IORESOURCE_MEM)) {        printk (KERN_ERR UDC_NAME            ": region #0 not an MMIO resource, aborting\n");        return -ENODEV;    }    if (request_irq (pdev->irq, &tc_int_hndlr,            SA_SHIRQ | SA_SAMPLE_RANDOM, UDC_NAME, pdev)) {        printk (KERN_ERR UDC_NAME " could not request irq %d\n", pdev->irq);        return -EBUSY;    }    if (pci_request_regions (pdev, UDC_NAME)) {        printk (KERN_ERR UDC_NAME " could not request regions\n");        free_irq (pdev->irq, pdev);        return -EBUSY;    }    pci_set_master (pdev);    mmio = ioremap (pci_resource_start (pdev, 0), pci_resource_len (pdev, 0));    if (mmio == NULL) {        printk (KERN_ERR UDC_NAME " could not remap 0x%08lx(0x%lx)\n",            pci_resource_start (pdev, 0), pci_resource_len (pdev, 0));        free_irq (pdev->irq, pdev);        pci_release_regions (pdev);        return -EBUSY;    }    tc_regs = mmio;    tc_udcregs = (struct tc_udc_udcregs *) (mmio + 0x200);    tc_ramregs = (struct tc_udc_ramregs *) (mmio + 0x800);    printk (KERN_DEBUG UDC_NAME " found at %p irq %d (%s)\n",        mmio, pdev->irq, nodma ? "PIO" : "DMA");    udc_pci_dev = pdev;    return 0;}static void __devexitudc_remove (struct pci_dev *pdev){    if (tc_regs)        iounmap (tc_regs);    pci_release_regions (pdev);    free_irq (pdev->irq, pdev);    tc_regs = NULL;    tc_udcregs = NULL;    tc_ramregs = NULL;    udc_pci_dev = NULL;

⌨️ 快捷键说明

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