defxx.c
来自「linux 内核源代码」· C语言 代码 · 共 2,079 行 · 第 1/5 页
C
2,079 行
* Overview: * Retrieves the address range used to access control and status * registers. * * Returns: * None * * Arguments: * bdev - pointer to device information * bar_start - pointer to store the start address * bar_len - pointer to store the length of the area * * Assumptions: * I am sure there are some. * * Side Effects: * None */static void dfx_get_bars(struct device *bdev, resource_size_t *bar_start, resource_size_t *bar_len){ int dfx_bus_pci = DFX_BUS_PCI(bdev); int dfx_bus_eisa = DFX_BUS_EISA(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; if (dfx_bus_pci) { int num = dfx_use_mmio ? 0 : 1; *bar_start = pci_resource_start(to_pci_dev(bdev), num); *bar_len = pci_resource_len(to_pci_dev(bdev), num); } if (dfx_bus_eisa) { unsigned long base_addr = to_eisa_device(bdev)->base_addr; resource_size_t bar; if (dfx_use_mmio) { bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2); bar <<= 8; bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1); bar <<= 8; bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0); bar <<= 16; *bar_start = bar; bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2); bar <<= 8; bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1); bar <<= 8; bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0); bar <<= 16; *bar_len = (bar | PI_MEM_ADD_MASK_M) + 1; } else { *bar_start = base_addr; *bar_len = PI_ESIC_K_CSR_IO_LEN; } } if (dfx_bus_tc) { *bar_start = to_tc_dev(bdev)->resource.start + PI_TC_K_CSR_OFFSET; *bar_len = PI_TC_K_CSR_LEN; }}/* * ================ * = dfx_register = * ================ * * Overview: * Initializes a supported FDDI controller * * Returns: * Condition code * * Arguments: * bdev - pointer to device information * * Functional Description: * * Return Codes: * 0 - This device (fddi0, fddi1, etc) configured successfully * -EBUSY - Failed to get resources, or dfx_driver_init failed. * * Assumptions: * It compiles so it should work :-( (PCI cards do :-) * * Side Effects: * Device structures for FDDI adapters (fddi0, fddi1, etc) are * initialized and the board resources are read and stored in * the device structure. */static int __devinit dfx_register(struct device *bdev){ static int version_disp; int dfx_bus_pci = DFX_BUS_PCI(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; char *print_name = bdev->bus_id; struct net_device *dev; DFX_board_t *bp; /* board pointer */ resource_size_t bar_start = 0; /* pointer to port */ resource_size_t bar_len = 0; /* resource length */ int alloc_size; /* total buffer size used */ struct resource *region; int err = 0; if (!version_disp) { /* display version info if adapter is found */ version_disp = 1; /* set display flag to TRUE so that */ printk(version); /* we only display this string ONCE */ } dev = alloc_fddidev(sizeof(*bp)); if (!dev) { printk(KERN_ERR "%s: Unable to allocate fddidev, aborting\n", print_name); return -ENOMEM; } /* Enable PCI device. */ if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) { printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n", print_name); goto err_out; } SET_NETDEV_DEV(dev, bdev); bp = netdev_priv(dev); bp->bus_dev = bdev; dev_set_drvdata(bdev, dev); dfx_get_bars(bdev, &bar_start, &bar_len); if (dfx_use_mmio) region = request_mem_region(bar_start, bar_len, print_name); else region = request_region(bar_start, bar_len, print_name); if (!region) { printk(KERN_ERR "%s: Cannot reserve I/O resource " "0x%lx @ 0x%lx, aborting\n", print_name, (long)bar_len, (long)bar_start); err = -EBUSY; goto err_out_disable; } /* Set up I/O base address. */ if (dfx_use_mmio) { bp->base.mem = ioremap_nocache(bar_start, bar_len); if (!bp->base.mem) { printk(KERN_ERR "%s: Cannot map MMIO\n", print_name); err = -ENOMEM; goto err_out_region; } } else { bp->base.port = bar_start; dev->base_addr = bar_start; } /* Initialize new device structure */ dev->get_stats = dfx_ctl_get_stats; dev->open = dfx_open; dev->stop = dfx_close; dev->hard_start_xmit = dfx_xmt_queue_pkt; dev->set_multicast_list = dfx_ctl_set_multicast_list; dev->set_mac_address = dfx_ctl_set_mac_address; if (dfx_bus_pci) pci_set_master(to_pci_dev(bdev)); if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) { err = -ENODEV; goto err_out_unmap; } err = register_netdev(dev); if (err) goto err_out_kfree; printk("%s: registered as %s\n", print_name, dev->name); return 0;err_out_kfree: alloc_size = sizeof(PI_DESCR_BLOCK) + PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +#ifndef DYNAMIC_BUFFERS (bp->rcv_bufs_to_post * PI_RCV_DATA_K_SIZE_MAX) +#endif sizeof(PI_CONSUMER_BLOCK) + (PI_ALIGN_K_DESC_BLK - 1); if (bp->kmalloced) dma_free_coherent(bdev, alloc_size, bp->kmalloced, bp->kmalloced_dma);err_out_unmap: if (dfx_use_mmio) iounmap(bp->base.mem);err_out_region: if (dfx_use_mmio) release_mem_region(bar_start, bar_len); else release_region(bar_start, bar_len);err_out_disable: if (dfx_bus_pci) pci_disable_device(to_pci_dev(bdev));err_out: free_netdev(dev); return err;}/* * ================ * = dfx_bus_init = * ================ * * Overview: * Initializes the bus-specific controller logic. * * Returns: * None * * Arguments: * dev - pointer to device information * * Functional Description: * Determine and save adapter IRQ in device table, * then perform bus-specific logic initialization. * * Return Codes: * None * * Assumptions: * bp->base has already been set with the proper * base I/O address for this device. * * Side Effects: * Interrupts are enabled at the adapter bus-specific logic. * Note: Interrupts at the DMA engine (PDQ chip) are not * enabled yet. */static void __devinit dfx_bus_init(struct net_device *dev){ DFX_board_t *bp = netdev_priv(dev); struct device *bdev = bp->bus_dev; int dfx_bus_pci = DFX_BUS_PCI(bdev); int dfx_bus_eisa = DFX_BUS_EISA(bdev); int dfx_bus_tc = DFX_BUS_TC(bdev); int dfx_use_mmio = DFX_MMIO || dfx_bus_tc; u8 val; DBG_printk("In dfx_bus_init...\n"); /* Initialize a pointer back to the net_device struct */ bp->dev = dev; /* Initialize adapter based on bus type */ if (dfx_bus_tc) dev->irq = to_tc_dev(bdev)->interrupt; if (dfx_bus_eisa) { unsigned long base_addr = to_eisa_device(bdev)->base_addr; /* Get the interrupt level from the ESIC chip. */ val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0); val &= PI_CONFIG_STAT_0_M_IRQ; val >>= PI_CONFIG_STAT_0_V_IRQ; switch (val) { case PI_CONFIG_STAT_0_IRQ_K_9: dev->irq = 9; break; case PI_CONFIG_STAT_0_IRQ_K_10: dev->irq = 10; break; case PI_CONFIG_STAT_0_IRQ_K_11: dev->irq = 11; break; case PI_CONFIG_STAT_0_IRQ_K_15: dev->irq = 15; break; } /* * Enable memory decoding (MEMCS0) and/or port decoding * (IOCS1/IOCS0) as appropriate in Function Control * Register. One of the port chip selects seems to be * used for the Burst Holdoff register, but this bit of * documentation is missing and as yet it has not been * determined which of the two. This is also the reason * the size of the decoded port range is twice as large * as one required by the PDQ. */ /* Set the decode range of the board. */ val = ((bp->base.port >> 12) << PI_IO_CMP_V_SLOT); outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_1, val); outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_0, 0); outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_1, val); outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_0, 0); val = PI_ESIC_K_CSR_IO_LEN - 1; outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_1, (val >> 8) & 0xff); outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_0, val & 0xff); outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_1, (val >> 8) & 0xff); outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_0, val & 0xff); /* Enable the decoders. */ val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0; if (dfx_use_mmio) val |= PI_FUNCTION_CNTRL_M_MEMCS0; outb(base_addr + PI_ESIC_K_FUNCTION_CNTRL, val); /* * Enable access to the rest of the module * (including PDQ and packet memory). */ val = PI_SLOT_CNTRL_M_ENB; outb(base_addr + PI_ESIC_K_SLOT_CNTRL, val); /* * Map PDQ registers into memory or port space. This is * done with a bit in the Burst Holdoff register. */ val = inb(base_addr + PI_DEFEA_K_BURST_HOLDOFF); if (dfx_use_mmio) val |= PI_BURST_HOLDOFF_V_MEM_MAP; else val &= ~PI_BURST_HOLDOFF_V_MEM_MAP; outb(base_addr + PI_DEFEA_K_BURST_HOLDOFF, val); /* Enable interrupts at EISA bus interface chip (ESIC) */ val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0); val |= PI_CONFIG_STAT_0_M_INT_ENB; outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val); } if (dfx_bus_pci) { struct pci_dev *pdev = to_pci_dev(bdev); /* Get the interrupt level from the PCI Configuration Table */ dev->irq = pdev->irq; /* Check Latency Timer and set if less than minimal */ pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val); if (val < PFI_K_LAT_TIMER_MIN) { val = PFI_K_LAT_TIMER_DEF; pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val); } /* Enable interrupts at PCI bus interface chip (PFI) */ val = PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB; dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, val); }}/* * ================== * = dfx_bus_uninit = * ================== * * Overview: * Uninitializes the bus-specific controller logic. * * Returns: * None * * Arguments: * dev - pointer to device information * * Functional Description: * Perform bus-specific logic uninitialization. * * Return Codes: * None * * Assumptions: * bp->base has already been set with the proper * base I/O address for this device. * * Side Effects: * Interrupts are disabled at the adapter bus-specific logic. */static void __devexit dfx_bus_uninit(struct net_device *dev){ DFX_board_t *bp = netdev_priv(dev); struct device *bdev = bp->bus_dev; int dfx_bus_pci = DFX_BUS_PCI(bdev); int dfx_bus_eisa = DFX_BUS_EISA(bdev); u8 val; DBG_printk("In dfx_bus_uninit...\n"); /* Uninitialize adapter based on bus type */ if (dfx_bus_eisa) { unsigned long base_addr = to_eisa_device(bdev)->base_addr; /* Disable interrupts at EISA bus interface chip (ESIC) */ val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0); val &= ~PI_CONFIG_STAT_0_M_INT_ENB; outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val); } if (dfx_bus_pci) { /* Disable interrupts at PCI bus interface chip (PFI) */ dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, 0); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?