📄 defxx.c
字号:
* * Returns: * Condition code * * Arguments: * pdev - pointer to pci device information (NULL for EISA) * * 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_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr){ struct net_device *dev; DFX_board_t *bp; /* board pointer */ static int version_disp; 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 */ } /* * init_fddidev() allocates a device structure with private data, clears the device structure and private data, * and calls fddi_setup() and register_netdev(). Not much left to do for us here. */ dev = init_fddidev( NULL, sizeof(*bp)); if (!dev) { printk (KERN_ERR "defxx: unable to allocate fddidev, aborting\n"); return -ENOMEM; } bp = (DFX_board_t*)dev->priv; if (!request_region (ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, dev->name)) { printk (KERN_ERR "%s: Cannot reserve I/O resource 0x%x @ 0x%lx, aborting\n", dev->name, PFI_K_CSR_IO_LEN, ioaddr); goto err_out; } /* Initialize new device structure */ dev->base_addr = ioaddr; /* save port (I/O) base address */ 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 (pdev == NULL) { /* EISA board */ bp->bus_type = DFX_BUS_TYPE_EISA; bp->next = root_dfx_eisa_dev; root_dfx_eisa_dev = dev; } else { /* PCI board */ bp->bus_type = DFX_BUS_TYPE_PCI; bp->pci_dev = pdev; pdev->driver_data = dev; if (pci_enable_device (pdev)) goto err_out_region; pci_set_master (pdev); } if (dfx_driver_init(dev) != DFX_K_SUCCESS) goto err_out_region; return 0;err_out_region: release_region(ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN);err_out: unregister_netdev(dev); kfree(dev); return -ENODEV;}static int __devinit dfx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent){ return dfx_init_one_pci_or_eisa(pdev, pci_resource_start (pdev, 1));}static int __init dfx_eisa_init(void){ int rc = -NODEV; int i; /* used in for loops */ u16 port; /* temporary I/O (port) address */ u32 slot_id; /* EISA hardware (slot) ID read from adapter */ DBG_printk("In dfx_eisa_init...\n"); /* Scan for FDDI EISA controllers */ for (i=0; i < DFX_MAX_EISA_SLOTS; i++) /* only scan for up to 16 EISA slots */ { port = (i << 12) + PI_ESIC_K_SLOT_ID; /* port = I/O address for reading slot ID */ slot_id = inl(port); /* read EISA HW (slot) ID */ if ((slot_id & 0xF0FFFFFF) == DEFEA_PRODUCT_ID) { port = (i << 12); /* recalc base addr */ if (dfx_init_one_pci_or_eisa(NULL, port) == 0) rc = 0; } } return rc;}/* * ================ * = dfx_bus_init = * ================ * * Overview: * Initializes EISA and PCI controller bus-specific 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: * dev->base_addr 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 = (DFX_board_t *)dev->priv; u8 val; /* used for I/O read/writes */ DBG_printk("In dfx_bus_init...\n"); /* * Initialize base I/O address field in bp structure * * Note: bp->base_addr is the same as dev->base_addr. * It's useful because often we'll need to read * or write registers where we already have the * bp pointer instead of the dev pointer. Having * the base address in the bp structure will * save a pointer dereference. * * IMPORTANT!! This field must be defined before * any of the dfx_port_* inline functions are * called. */ bp->base_addr = dev->base_addr; /* And a pointer back to the net_device struct */ bp->dev = dev; /* Initialize adapter based on bus type */ if (bp->bus_type == DFX_BUS_TYPE_EISA) { /* Get the interrupt level from the ESIC chip */ dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val); switch ((val & PI_CONFIG_STAT_0_M_IRQ) >> PI_CONFIG_STAT_0_V_IRQ) { 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 access to I/O on the board by writing 0x03 to Function Control Register */ dfx_port_write_byte(bp, PI_ESIC_K_FUNCTION_CNTRL, PI_ESIC_K_FUNCTION_CNTRL_IO_ENB); /* Set the I/O decode range of the board */ val = ((dev->base_addr >> 12) << PI_IO_CMP_V_SLOT); dfx_port_write_byte(bp, PI_ESIC_K_IO_CMP_0_1, val); dfx_port_write_byte(bp, PI_ESIC_K_IO_CMP_1_1, val); /* Enable access to rest of module (including PDQ and packet memory) */ dfx_port_write_byte(bp, PI_ESIC_K_SLOT_CNTRL, PI_SLOT_CNTRL_M_ENB); /* * Map PDQ registers into I/O space. This is done by clearing a bit * in Burst Holdoff register. */ dfx_port_read_byte(bp, PI_ESIC_K_BURST_HOLDOFF, &val); dfx_port_write_byte(bp, PI_ESIC_K_BURST_HOLDOFF, (val & ~PI_BURST_HOLDOFF_M_MEM_MAP)); /* Enable interrupts at EISA bus interface chip (ESIC) */ dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val); dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, (val | PI_CONFIG_STAT_0_M_INT_ENB)); } else { struct pci_dev *pdev = bp->pci_dev; /* 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) /* if less than min, override with default */ { val = PFI_K_LAT_TIMER_DEF; pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val); } /* Enable interrupts at PCI bus interface chip (PFI) */ dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, (PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB)); } return; }/* * ======================== * = dfx_bus_config_check = * ======================== * * Overview: * Checks the configuration (burst size, full-duplex, etc.) If any parameters * are illegal, then this routine will set new defaults. * * Returns: * None * * Arguments: * bp - pointer to board information * * Functional Description: * For Revision 1 FDDI EISA, Revision 2 or later FDDI EISA with rev E or later * PDQ, and all FDDI PCI controllers, all values are legal. * * Return Codes: * None * * Assumptions: * dfx_adap_init has NOT been called yet so burst size and other items have * not been set. * * Side Effects: * None */static void __devinit dfx_bus_config_check(DFX_board_t *bp){ int status; /* return code from adapter port control call */ u32 slot_id; /* EISA-bus hardware id (DEC3001, DEC3002,...) */ u32 host_data; /* LW data returned from port control call */ DBG_printk("In dfx_bus_config_check...\n"); /* Configuration check only valid for EISA adapter */ if (bp->bus_type == DFX_BUS_TYPE_EISA) { dfx_port_read_long(bp, PI_ESIC_K_SLOT_ID, &slot_id); /* * First check if revision 2 EISA controller. Rev. 1 cards used * PDQ revision B, so no workaround needed in this case. Rev. 3 * cards used PDQ revision E, so no workaround needed in this * case, either. Only Rev. 2 cards used either Rev. D or E * chips, so we must verify the chip revision on Rev. 2 cards. */ if (slot_id == DEFEA_PROD_ID_2) { /* * Revision 2 FDDI EISA controller found, so let's check PDQ * revision of adapter. */ status = dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_SUB_CMD, PI_SUB_CMD_K_PDQ_REV_GET, 0, &host_data); if ((status != DFX_K_SUCCESS) || (host_data == 2)) { /* * Either we couldn't determine the PDQ revision, or * we determined that it is at revision D. In either case, * we need to implement the workaround. */ /* Ensure that the burst size is set to 8 longwords or less */ switch (bp->burst_size) { case PI_PDATA_B_DMA_BURST_SIZE_32: case PI_PDATA_B_DMA_BURST_SIZE_16: bp->burst_size = PI_PDATA_B_DMA_BURST_SIZE_8; break; default: break; } /* Ensure that full-duplex mode is not enabled */ bp->full_duplex_enb = PI_SNMP_K_FALSE; } } } return; }/* * =================== * = dfx_driver_init = * =================== * * Overview: * Initializes remaining adapter board structure information * and makes sure adapter is in a safe state prior to dfx_open(). * * Returns: * Condition code * * Arguments: * dev - pointer to device information * * Functional Description: * This function allocates additional resources such as the host memory * blocks needed by the adapter (eg. descriptor and consumer blocks). * Remaining bus initialization steps are also completed. The adapter * is also reset so that it is in the DMA_UNAVAILABLE state. The OS * must call dfx_open() to open the adapter and bring it on-line. * * Return Codes: * DFX_K_SUCCESS - initialization succeeded * DFX_K_FAILURE - initialization failed - could not allocate memory * or read adapter MAC address * * Assumptions: * Memory allocated from kmalloc() call is physically contiguous, locked * memory whose physical address equals its virtual address. * * Side Effects: * Adapter is reset and should be in DMA_UNAVAILABLE state before * returning from this routine. */static int __devinit dfx_driver_init(struct net_device *dev){ DFX_board_t *bp = (DFX_board_t *)dev->priv;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -