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

📄 pcilynx.c

📁 ieee1394驱动,不多说了!直接可以在linux2.6内核中使用
💻 C
📖 第 1 页 / 共 4 页
字号:
	struct hpsb_host *host;        struct ti_lynx *lynx; /* shortcut to currently handled device */        struct ti_pcl pcl;        u32 *pcli;        int i;        int error;        error = -ENXIO;        if (pci_set_dma_mask(dev, DMA_32BIT_MASK))                FAIL("DMA address limits not supported for PCILynx hardware");        if (pci_enable_device(dev))                FAIL("failed to enable PCILynx hardware");        pci_set_master(dev);        error = -ENOMEM;	host = hpsb_alloc_host(&lynx_driver, sizeof(struct ti_lynx), &dev->dev);        if (!host) FAIL("failed to allocate control structure memory");        lynx = host->hostdata;	lynx->id = card_id++;        lynx->dev = dev;        lynx->state = clear;	lynx->host = host;        host->pdev = dev;        pci_set_drvdata(dev, lynx);        spin_lock_init(&lynx->lock);        spin_lock_init(&lynx->phy_reg_lock);        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");        }        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");        }        reg_set_bits(lynx, MISC_CONTROL, MISC_CONTROL_SWRESET);        /* Fix buggy cards with autoboot pin not tied low: */        reg_write(lynx, DMA0_CHAN_CTRL, 0);	sprintf (irq_buf, "%d", dev->irq);        if (!request_irq(dev->irq, lynx_irq_handler, IRQF_SHARED,                         PCILYNX_DRIVER_NAME, lynx)) {                PRINT(KERN_INFO, lynx->id, "allocated interrupt %s", irq_buf);                lynx->state = have_intr;        } else {                FAIL("failed to allocate shared interrupt %s", irq_buf);        }        /* alloc_pcl return values are not checked, it is expected that the         * provided PCL space is sufficient for the initial allocations */        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);	tasklet_init(&lynx->iso_rcv.tq, (void (*)(unsigned long))iso_rcv_bh,		     (unsigned long)lynx);        spin_lock_init(&lynx->iso_rcv.lock);        spin_lock_init(&lynx->async.queue_lock);        lynx->async.channel = CHANNEL_ASYNC_SEND;        spin_lock_init(&lynx->iso_send.queue_lock);        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");        }        lynx->selfid_size = -1;        lynx->phy_reg0 = -1;	INIT_LIST_HEAD(&lynx->async.queue);	INIT_LIST_HEAD(&lynx->async.pcl_queue);	INIT_LIST_HEAD(&lynx->iso_send.queue);	INIT_LIST_HEAD(&lynx->iso_send.pcl_queue);        pcl.next = pcl_bus(lynx, lynx->rcv_pcl);        put_pcl(lynx, lynx->rcv_pcl_start, &pcl);        pcl.next = PCL_NEXT_INVALID;        pcl.async_error_next = PCL_NEXT_INVALID;        pcl.buffer[0].control = PCL_CMD_RCV | 16;#ifndef __BIG_ENDIAN	pcl.buffer[0].control |= PCL_BIGENDIAN;#endif	pcl.buffer[1].control = PCL_LAST_BUFF | 4080;        pcl.buffer[0].pointer = lynx->rcv_page_dma;        pcl.buffer[1].pointer = lynx->rcv_page_dma + 16;        put_pcl(lynx, lynx->rcv_pcl, &pcl);        pcl.next = pcl_bus(lynx, lynx->async.pcl);        pcl.async_error_next = pcl_bus(lynx, lynx->async.pcl);        put_pcl(lynx, lynx->async.pcl_start, &pcl);        pcl.next = pcl_bus(lynx, lynx->iso_send.pcl);        pcl.async_error_next = PCL_NEXT_INVALID;        put_pcl(lynx, lynx->iso_send.pcl_start, &pcl);        pcl.next = PCL_NEXT_INVALID;        pcl.async_error_next = PCL_NEXT_INVALID;        pcl.buffer[0].control = PCL_CMD_RCV | 4;#ifndef __BIG_ENDIAN        pcl.buffer[0].control |= PCL_BIGENDIAN;#endif        pcl.buffer[1].control = PCL_LAST_BUFF | 2044;        for (i = 0; i < NUM_ISORCV_PCL; i++) {                int page = i / ISORCV_PER_PAGE;                int sec = i % ISORCV_PER_PAGE;                pcl.buffer[0].pointer = lynx->iso_rcv.page_dma[page]                        + sec * MAX_ISORCV_SIZE;                pcl.buffer[1].pointer = pcl.buffer[0].pointer + 4;                put_pcl(lynx, lynx->iso_rcv.pcl[i], &pcl);        }        pcli = (u32 *)&pcl;        for (i = 0; i < NUM_ISORCV_PCL; i++) {                pcli[i] = pcl_bus(lynx, lynx->iso_rcv.pcl[i]);        }        put_pcl(lynx, lynx->iso_rcv.pcl_start, &pcl);        /* FIFO sizes from left to right: ITF=48 ATF=48 GRF=160 */        reg_write(lynx, FIFO_SIZES, 0x003030a0);        /* 20 byte threshold before triggering PCI transfer */        reg_write(lynx, DMA_GLOBAL_REGISTER, 0x2<<24);        /* threshold on both send FIFOs before transmitting:           FIFO size - cache line size - 1 */        i = reg_read(lynx, PCI_LATENCY_CACHELINE) & 0xff;        i = 0x30 - i - 1;        reg_write(lynx, FIFO_XMIT_THRESHOLD, (i << 8) | i);        reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_1394);        reg_write(lynx, LINK_INT_ENABLE, LINK_INT_PHY_TIMEOUT                  | LINK_INT_PHY_REG_RCVD  | LINK_INT_PHY_BUSRESET                  | LINK_INT_ISO_STUCK     | LINK_INT_ASYNC_STUCK                  | LINK_INT_SENT_REJECT   | LINK_INT_TX_INVALID_TC                  | LINK_INT_GRF_OVERFLOW  | LINK_INT_ITF_UNDERFLOW                  | LINK_INT_ATF_UNDERFLOW);        reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ASYNC_RCV), 0);        reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ASYNC_RCV), 0xa<<4);        reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ASYNC_RCV), 0);        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ASYNC_RCV),                  DMA_WORD1_CMP_MATCH_LOCAL_NODE | DMA_WORD1_CMP_MATCH_BROADCAST                  | DMA_WORD1_CMP_MATCH_EXACT    | DMA_WORD1_CMP_MATCH_BUS_BCAST                  | DMA_WORD1_CMP_ENABLE_SELF_ID | DMA_WORD1_CMP_ENABLE_MASTER);        run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV);        reg_write(lynx, DMA_WORD0_CMP_VALUE(CHANNEL_ISO_RCV), 0);        reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ISO_RCV), 0x9<<4);        reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ISO_RCV), 0);        reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ISO_RCV), 0);        run_sub_pcl(lynx, lynx->iso_rcv.pcl_start, 0, CHANNEL_ISO_RCV);        reg_write(lynx, LINK_CONTROL, LINK_CONTROL_RCV_CMP_VALID                  | LINK_CONTROL_TX_ISO_EN   | LINK_CONTROL_RX_ISO_EN                  | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN                  | LINK_CONTROL_RESET_TX    | LINK_CONTROL_RESET_RX);	if (!lynx->phyic.reg_1394a) {		if (!hpsb_disable_irm) {			/* attempt to enable contender bit -FIXME- would this			 * work elsewhere? */			reg_set_bits(lynx, GPIO_CTRL_A, 0x1);			reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1);		}	} else {		/* set the contender (if appropriate) and LCtrl bit in the		 * extended PHY register set. (Should check that PHY_02_EXTENDED		 * is set in register 2?)		 */		i = get_phy_reg(lynx, 4);		i |= PHY_04_LCTRL;		if (hpsb_disable_irm)			i &= ~PHY_04_CONTENDER;		else			i |= PHY_04_CONTENDER;		if (i != -1) set_phy_reg(lynx, 4, i);	}	        if (!skip_eeprom)        {        	/* needed for i2c communication with serial eeprom */        	struct i2c_adapter *i2c_ad;        	struct i2c_algo_bit_data i2c_adapter_data;        	error = -ENOMEM;		i2c_ad = kmemdup(&bit_ops, sizeof(*i2c_ad), GFP_KERNEL);        	if (!i2c_ad) FAIL("failed to allocate I2C adapter memory");                i2c_adapter_data = bit_data;                i2c_ad->algo_data = &i2c_adapter_data;                i2c_adapter_data.data = lynx;		i2c_ad->dev.parent = &dev->dev;		PRINTD(KERN_DEBUG, lynx->id,"original eeprom control: %d",		       reg_read(lynx, SERIAL_EEPROM_CONTROL));        	/* reset hardware to sane state */        	lynx->i2c_driven_state = 0x00000070;        	reg_write(lynx, SERIAL_EEPROM_CONTROL, lynx->i2c_driven_state);        	if (i2c_bit_add_bus(i2c_ad) < 0)        	{			kfree(i2c_ad);			error = -ENXIO;			FAIL("unable to register i2c");        	}        	else        	{                        /* do i2c stuff */                        unsigned char i2c_cmd = 0x10;                        struct i2c_msg msg[2] = { { 0x50, 0, 1, &i2c_cmd },                                                  { 0x50, I2C_M_RD, 20, (unsigned char*) lynx->bus_info_block }                                                };                        /* we use i2c_transfer, because i2c_smbus_read_block_data does not work properly and we                           do it more efficiently in one transaction rather then using several reads */                        if (i2c_transfer(i2c_ad, msg, 2) < 0) {                                PRINT(KERN_ERR, lynx->id, "unable to read bus info block from i2c");                        } else {                                int i;                                PRINT(KERN_INFO, lynx->id, "got bus info block from serial eeprom");				/* FIXME: probably we shoud rewrite the max_rec, max_ROM(1394a),				 * generation(1394a) and link_spd(1394a) field and recalculate				 * the CRC */                                for (i = 0; i < 5 ; i++)                                        PRINTD(KERN_DEBUG, lynx->id, "Businfo block quadlet %i: %08x",					       i, be32_to_cpu(lynx->bus_info_block[i]));                                /* info_length, crc_length and 1394 magic number to check, if it is really a bus info block */				if (((be32_to_cpu(lynx->bus_info_block[0]) & 0xffff0000) == 0x04040000) &&				    (lynx->bus_info_block[1] == __constant_cpu_to_be32(0x31333934)))                                {                                        PRINT(KERN_DEBUG, lynx->id, "read a valid bus info block from");                                } else {					kfree(i2c_ad);					error = -ENXIO;					FAIL("read something from serial eeprom, but it does not seem to be a valid bus info block");                                }                        }			i2c_del_adapter(i2c_ad);			kfree(i2c_ad);                }        }	host->csr.guid_hi = be32_to_cpu(lynx->bus_info_block[3]);	host->csr.guid_lo = be32_to_cpu(lynx->bus_info_block[4]);	host->csr.cyc_clk_acc = (be32_to_cpu(lynx->bus_info_block[2]) >> 16) & 0xff;	host->csr.max_rec = (be32_to_cpu(lynx->bus_info_block[2]) >> 12) & 0xf;	if (!lynx->phyic.reg_1394a)		host->csr.lnk_spd = (get_phy_reg(lynx, 2) & 0xc0) >> 6;	else		host->csr.lnk_spd = be32_to_cpu(lynx->bus_info_block[2]) & 0x7;	if (hpsb_add_host(host)) {		error = -ENOMEM;		FAIL("Failed to register host with highlevel");	}	lynx->state = is_host;	return 0;#undef FAIL}static struct pci_device_id pci_table[] = {	{                .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_pci_driver = {        .name =     PCILYNX_DRIVER_NAME,        .id_table = pci_table,        .probe =    add_card,        .remove =   remove_card,};static struct hpsb_host_driver lynx_driver = {	.owner =	   THIS_MODULE,	.name =		   PCILYNX_DRIVER_NAME,	.set_hw_config_rom = NULL,        .transmit_packet = lynx_transmit,        .devctl =          lynx_devctl,	.isoctl =          NULL,};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 int __init pcilynx_init(void){        int ret;        ret = pci_register_driver(&lynx_pci_driver);        if (ret < 0) {                PRINT_G(KERN_ERR, "PCI module init failed");                return ret;        }        return 0;}static void __exit pcilynx_cleanup(void){        pci_unregister_driver(&lynx_pci_driver);}module_init(pcilynx_init);module_exit(pcilynx_cleanup);

⌨️ 快捷键说明

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