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

📄 pcilynx.c

📁 idt mips 32365上面移植实现的iee1394驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
                packet = lynx->iso_send.queue;                lynx->iso_send.queue = packet->xnext;                pci_unmap_single(lynx->dev, lynx->iso_send.header_dma,                                 packet->header_size, PCI_DMA_TODEVICE);                if (packet->data_size) {                        pci_unmap_single(lynx->dev, lynx->iso_send.data_dma,                                         packet->data_size, PCI_DMA_TODEVICE);                }                if (lynx->iso_send.queue != NULL) {                        send_next(lynx, hpsb_iso);                }                spin_unlock(&lynx->iso_send.queue_lock);                hpsb_packet_sent(host, packet, ACK_COMPLETE);        }        if (intmask & PCI_INT_DMA_HLT(CHANNEL_ASYNC_RCV)) {                /* general receive DMA completed */                int stat = reg_read(lynx, DMA_CHAN_STAT(CHANNEL_ASYNC_RCV));                PRINTD(KERN_DEBUG, lynx->id, "received packet size %d",                       stat & 0x1fff);                 if (stat & DMA_CHAN_STAT_SELFID) {                        lynx->selfid_size = stat & 0x1fff;                        handle_selfid(lynx, host);                } else {                        quadlet_t *q_data = lynx->rcv_page;                        if ((*q_data >> 4 & 0xf) == TCODE_READQ_RESPONSE                            || (*q_data >> 4 & 0xf) == TCODE_WRITEQ) {                                cpu_to_be32s(q_data + 3);                        }                        hpsb_packet_received(host, q_data, stat & 0x1fff, 0);                }                run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV);        }}static void iso_rcv_bh(struct ti_lynx *lynx){        unsigned int idx;        quadlet_t *data;        unsigned long flags;        spin_lock_irqsave(&lynx->iso_rcv.lock, flags);        while (lynx->iso_rcv.used) {                idx = lynx->iso_rcv.last;                spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);                data = lynx->iso_rcv.page[idx / ISORCV_PER_PAGE]                        + (idx % ISORCV_PER_PAGE) * MAX_ISORCV_SIZE;                if ((*data >> 16) + 4 != (lynx->iso_rcv.stat[idx] & 0x1fff)) {                        PRINT(KERN_ERR, lynx->id,                              "iso length mismatch 0x%08x/0x%08x", *data,                              lynx->iso_rcv.stat[idx]);                }                if (lynx->iso_rcv.stat[idx]                     & (DMA_CHAN_STAT_PCIERR | DMA_CHAN_STAT_PKTERR)) {                        PRINT(KERN_INFO, lynx->id,                              "iso receive error on %d to 0x%p", idx, data);                } else {                        hpsb_packet_received(lynx->host, data,                                             lynx->iso_rcv.stat[idx] & 0x1fff,                                             0);                }                spin_lock_irqsave(&lynx->iso_rcv.lock, flags);                lynx->iso_rcv.last = (idx + 1) % NUM_ISORCV_PCL;                lynx->iso_rcv.used--;        }        if (lynx->iso_rcv.chan_count) {                reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV),                          DMA_WORD1_CMP_ENABLE_MASTER);        }        spin_unlock_irqrestore(&lynx->iso_rcv.lock, flags);}static int __devinit add_card(struct pci_dev *dev,                              const struct pci_device_id *devid){#define FAIL(fmt, args...) do { \        PRINT_G(KERN_ERR, fmt , ## args); \        num_of_cards--; \        remove_card(dev); \        return -1; \        } while (0)        struct ti_lynx *lynx; /* shortcut to currently handled device */        unsigned int i;        if (num_of_cards == MAX_PCILYNX_CARDS) {                PRINT_G(KERN_WARNING, "cannot handle more than %d cards.  "                        "Adjust MAX_PCILYNX_CARDS in pcilynx.h.",                        MAX_PCILYNX_CARDS);                return -1;        }        lynx = &cards[num_of_cards++];        if (pci_set_dma_mask(dev, 0xffffffff))                FAIL("DMA address limits not supported for PCILynx hardware %d",                     lynx->id);        if (pci_enable_device(dev))                FAIL("failed to enable PCILynx hardware %d", lynx->id);        pci_set_master(dev);        lynx->host = hpsb_get_host(&lynx_template, 0);        if (!lynx->host)                FAIL("failed to allocate host structure");        lynx->state = have_host_struct;	lynx->host->hostdata = lynx;        lynx->id = num_of_cards-1;        lynx->dev = dev;	lynx->host->pdev = dev;        lynx->lock = SPIN_LOCK_UNLOCKED;        lynx->phy_reg_lock = SPIN_LOCK_UNLOCKED;#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM        lynx->pcl_mem = pci_alloc_consistent(dev, LOCALRAM_SIZE,                                             &lynx->pcl_mem_dma);        if (lynx->pcl_mem != NULL) {                lynx->state = have_pcl_mem;                PRINT(KERN_INFO, lynx->id,                       "allocated PCL memory %d Bytes @ 0x%p", LOCALRAM_SIZE,                      lynx->pcl_mem);        } else {                FAIL("failed to allocate PCL memory area");        }#endif#ifdef CONFIG_IEEE1394_PCILYNX_PORTS        lynx->mem_dma_buffer = pci_alloc_consistent(dev, 65536,                                                    &lynx->mem_dma_buffer_dma);        if (lynx->mem_dma_buffer == NULL) {                FAIL("failed to allocate DMA buffer for aux");        }        lynx->state = have_aux_buf;#endif        lynx->rcv_page = pci_alloc_consistent(dev, PAGE_SIZE,                                              &lynx->rcv_page_dma);        if (lynx->rcv_page == NULL) {                FAIL("failed to allocate receive buffer");        }        lynx->state = have_1394_buffers;        for (i = 0; i < ISORCV_PAGES; i++) {                lynx->iso_rcv.page[i] =                        pci_alloc_consistent(dev, PAGE_SIZE,                                             &lynx->iso_rcv.page_dma[i]);                if (lynx->iso_rcv.page[i] == NULL) {                        FAIL("failed to allocate iso receive buffers");                }        }        lynx->registers = ioremap_nocache(pci_resource_start(dev,0),                                          PCILYNX_MAX_REGISTER);        lynx->local_ram = ioremap(pci_resource_start(dev,1), PCILYNX_MAX_MEMORY);        lynx->aux_port  = ioremap(pci_resource_start(dev,2), PCILYNX_MAX_MEMORY);        lynx->local_rom = ioremap(pci_resource_start(dev,PCI_ROM_RESOURCE),                                  PCILYNX_MAX_MEMORY);        lynx->state = have_iomappings;        if (lynx->registers == NULL) {                FAIL("failed to remap registers - card not accessible");        }#ifdef CONFIG_IEEE1394_PCILYNX_LOCALRAM        if (lynx->local_ram == NULL) {                FAIL("failed to remap local RAM which is required for "                     "operation");        }#endif        reg_write(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);        if (!request_irq(dev->irq, lynx_irq_handler, SA_SHIRQ,                         PCILYNX_DRIVER_NAME, lynx)) {                PRINT(KERN_INFO, lynx->id, "allocated interrupt %d", dev->irq);                lynx->state = have_intr;        } else {                FAIL("failed to allocate shared interrupt %d", dev->irq);        }        /* alloc_pcl return values are not checked, it is expected that the         * provided PCL space is sufficient for the initial allocations */#ifdef CONFIG_IEEE1394_PCILYNX_PORTS        if (lynx->aux_port != NULL) {                lynx->dmem_pcl = alloc_pcl(lynx);                aux_setup_pcls(lynx);                sema_init(&lynx->mem_dma_mutex, 1);        }#endif        lynx->rcv_pcl = alloc_pcl(lynx);        lynx->rcv_pcl_start = alloc_pcl(lynx);        lynx->async.pcl = alloc_pcl(lynx);        lynx->async.pcl_start = alloc_pcl(lynx);        lynx->iso_send.pcl = alloc_pcl(lynx);        lynx->iso_send.pcl_start = alloc_pcl(lynx);        for (i = 0; i < NUM_ISORCV_PCL; i++) {                lynx->iso_rcv.pcl[i] = alloc_pcl(lynx);        }        lynx->iso_rcv.pcl_start = alloc_pcl(lynx);        /* all allocations successful - simple init stuff follows */        reg_write(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL);#ifdef CONFIG_IEEE1394_PCILYNX_PORTS        reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_AUX_INT);        init_waitqueue_head(&lynx->mem_dma_intr_wait);        init_waitqueue_head(&lynx->aux_intr_wait);#endif	tasklet_init(&lynx->iso_rcv.tq, (void (*)(unsigned long))iso_rcv_bh,		     (unsigned long)lynx);        lynx->iso_rcv.lock = SPIN_LOCK_UNLOCKED;        lynx->async.queue_lock = SPIN_LOCK_UNLOCKED;        lynx->async.channel = CHANNEL_ASYNC_SEND;        lynx->iso_send.queue_lock = SPIN_LOCK_UNLOCKED;        lynx->iso_send.channel = CHANNEL_ISO_SEND;                PRINT(KERN_INFO, lynx->id, "remapped memory spaces reg 0x%p, rom 0x%p, "              "ram 0x%p, aux 0x%p", lynx->registers, lynx->local_rom,              lynx->local_ram, lynx->aux_port);        /* now, looking for PHY register set */        if ((get_phy_reg(lynx, 2) & 0xe0) == 0xe0) {                lynx->phyic.reg_1394a = 1;                PRINT(KERN_INFO, lynx->id,                      "found 1394a conform PHY (using extended register set)");                lynx->phyic.vendor = get_phy_vendorid(lynx);                lynx->phyic.product = get_phy_productid(lynx);        } else {                lynx->phyic.reg_1394a = 0;                PRINT(KERN_INFO, lynx->id, "found old 1394 PHY");        }	/* Tell the highlevel this host is ready */	highlevel_add_one_host (lynx->host);        return 0;#undef FAIL}static void remove_card(struct pci_dev *dev){        struct ti_lynx *lynx;        int i;        lynx = cards;        while (lynx->dev != dev) lynx++;        switch (lynx->state) {        case have_intr:                reg_write(lynx, PCI_INT_ENABLE, 0);                free_irq(lynx->dev->irq, lynx);        case have_iomappings:                reg_write(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);                iounmap(lynx->registers);                iounmap(lynx->local_rom);                iounmap(lynx->local_ram);                iounmap(lynx->aux_port);        case have_1394_buffers:                for (i = 0; i < ISORCV_PAGES; i++) {                        if (lynx->iso_rcv.page[i]) {                                pci_free_consistent(lynx->dev, PAGE_SIZE,                                                    lynx->iso_rcv.page[i],                                                    lynx->iso_rcv.page_dma[i]);                        }                }                pci_free_consistent(lynx->dev, PAGE_SIZE, lynx->rcv_page,                                    lynx->rcv_page_dma);        case have_aux_buf:#ifdef CONFIG_IEEE1394_PCILYNX_PORTS                pci_free_consistent(lynx->dev, 65536, lynx->mem_dma_buffer,                                    lynx->mem_dma_buffer_dma);#endif        case have_pcl_mem:#ifndef CONFIG_IEEE1394_PCILYNX_LOCALRAM                pci_free_consistent(lynx->dev, LOCALRAM_SIZE, lynx->pcl_mem,                                    lynx->pcl_mem_dma);#endif        case have_host_struct:                /* FIXME - verify host freeing */        case clear:;                /* do nothing - already freed */        }	tasklet_kill(&lynx->iso_rcv.tq);        lynx->state = clear;}#if 0static int init_driver(){        struct pci_dev *dev = NULL;        int success = 0;        if (num_of_cards) {                PRINT_G(KERN_DEBUG, __PRETTY_FUNCTION__ " called again");                return 0;        }        PRINT_G(KERN_INFO, "looking for PCILynx cards");        while ((dev = pci_find_device(PCI_VENDOR_ID_TI,                                      PCI_DEVICE_ID_TI_PCILYNX, dev))                != NULL) {                if (add_card(dev) == 0) {                        success = 1;                }        }        if (success == 0) {                PRINT_G(KERN_WARNING, "no operable PCILynx cards found");                return -ENXIO;        }#ifdef CONFIG_IEEE1394_PCILYNX_PORTS        if (register_chrdev(PCILYNX_MAJOR, PCILYNX_DRIVER_NAME, &aux_ops)) {                PRINT_G(KERN_ERR, "allocation of char major number %d failed",                        PCILYNX_MAJOR);                return -EBUSY;        }#endif        return 0;}#endifstatic size_t get_lynx_rom(struct hpsb_host *host, const quadlet_t **ptr){        *ptr = lynx_csr_rom;        return sizeof(lynx_csr_rom);}static struct hpsb_host_template lynx_template = {	name:             PCILYNX_DRIVER_NAME,	initialize_host:  lynx_initialize,	release_host:     lynx_release,	get_rom:          get_lynx_rom,	transmit_packet:  lynx_transmit,	devctl:           lynx_devctl};static struct pci_device_id pci_table[] __devinitdata = {	{                vendor:     PCI_VENDOR_ID_TI,                device:     PCI_DEVICE_ID_TI_PCILYNX,                subvendor:  PCI_ANY_ID,                subdevice:  PCI_ANY_ID,	},	{ }			/* Terminating entry */};static struct pci_driver lynx_pcidriver = {        name:      PCILYNX_DRIVER_NAME,        id_table:  pci_table,        probe:     add_card,        remove:    remove_card,};MODULE_AUTHOR("Andreas E. Bombe <andreas.bombe@munich.netsurf.de>");MODULE_DESCRIPTION("driver for Texas Instruments PCI Lynx IEEE-1394 controller");MODULE_LICENSE("GPL");MODULE_SUPPORTED_DEVICE("pcilynx");MODULE_DEVICE_TABLE(pci, pci_table);static void __exit pcilynx_cleanup(void){        hpsb_unregister_lowlevel(&lynx_template);	pci_unregister_driver(&lynx_pcidriver);        PRINT_G(KERN_INFO, "removed " PCILYNX_DRIVER_NAME " module");}static int __init pcilynx_init(void){        int ret;        if (hpsb_register_lowlevel(&lynx_template)) {                PRINT_G(KERN_ERR, "registering failed");                return -ENXIO;        }        ret = pci_module_init(&lynx_pcidriver);        if (ret < 0) {                PRINT_G(KERN_ERR, "PCI module init failed");                hpsb_unregister_lowlevel(&lynx_template);        }        return ret;}module_init(pcilynx_init);module_exit(pcilynx_cleanup);

⌨️ 快捷键说明

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