📄 rtl_e100.c
字号:
rtl_printf(KERN_ERR "e100: Last command (%x/%x) " "timeout\n", private_data.last_cmd, private_data.last_sub_cmd); rtl_printf(KERN_ERR "e100: Current simple command (%x) " "can't be executed\n", scb_cmd_low);#endif return false; } e100_exec_cmd( scb_cmd_low);#ifdef E100_CU_DEBUG private_data.last_cmd = scb_cmd_low; private_data.last_sub_cmd = 0;#endif return true;}voide100_exec_cmplx(u32 phys_addr, u8 cmd){ writel(phys_addr, &(private_data.scb->scb_gen_ptr)); readw(&(private_data.scb->scb_status)); /* flushes last write, read-safe */ e100_exec_cmd( cmd);}unsigned chare100_wait_exec_cmplx(u32 phys_addr, u8 cmd, u8 sub_cmd){ if (!e100_wait_scb()) {#ifdef E100_CU_DEBUG rtl_printf(KERN_ERR "e100: Last command (%x/%x) " "timeout\n", private_data.last_cmd, private_data.last_sub_cmd); rtl_printf(KERN_ERR "e100: Current complex command " "(%x/%x) can't be executed\n", cmd, sub_cmd);#endif return false; } e100_exec_cmplx( phys_addr, cmd);#ifdef E100_CU_DEBUG private_data.last_cmd = cmd; private_data.last_sub_cmd = sub_cmd;#endif return true;}inline u8e100_wait_cus_idle(void){ int i; /* loop on the scb for a few times */ for (i = 0; i < 100; i++) { if (((readw(&(private_data.scb->scb_status)) & SCB_CUS_MASK) != SCB_CUS_ACTIVE)) { return true; } cpu_relax(); } for (i = 0; i < E100_MAX_CU_IDLE_WAIT; i++) { if (((readw(&(private_data.scb->scb_status)) & SCB_CUS_MASK) != SCB_CUS_ACTIVE)) { return true; } cpu_relax(); udelay(1); } return false;}/** * e100_disable_clear_intr - disable and clear/ack interrupts * @private_data: atapter's private data struct * * This routine disables interrupts at the hardware, by setting * the M (mask) bit in the adapter's CSR SCB command word. * It also clear/ack interrupts. */static inline voide100_disable_clear_intr(void){ u16 intr_status; /* Disable interrupts on our PCI board by setting the mask bit */ writeb(SCB_INT_MASK, &private_data.scb->scb_cmd_hi); intr_status = readw(&private_data.scb->scb_status); /* ack and clear intrs */ writew(intr_status, &private_data.scb->scb_status); readw(&private_data.scb->scb_status);}/** * e100_set_intr_mask - set interrupts * @private_data: atapter's private data struct * * This routine sets interrupts at the hardware, by resetting * the M (mask) bit in the adapter's CSR SCB command word */static inline voide100_set_intr_mask(void){ writeb(private_data.intr_mask, &private_data.scb->scb_cmd_hi); readw(&(private_data.scb->scb_status)); /* flushes last write, read-safe */}static inline voide100_trigger_SWI(void){ /* Trigger interrupt on our PCI board by asserting SWI bit */ writeb(SCB_SOFT_INT, &private_data.scb->scb_cmd_hi); readw(&(private_data.scb->scb_status)); }static int e100_found1(struct pci_dev *pcid){ static int first_time = true; int rc = 0; u16 cal_checksum, read_checksum; if (first_time) { first_time = false; rtl_printf(KERN_NOTICE "%s - version %s\n", e100_full_driver_name, e100_driver_version); rtl_printf(KERN_NOTICE "%s\n", e100_copyright); rtl_printf(KERN_NOTICE "\n"); } private_data.pdev = pcid; private_data.last_tcb = NULL; /*alloc bd_dma_able_t to private str*/ if ((rc = e100_alloc_space()) != 0) { goto err_dev; } private_data.flags = 0; private_data.ifs_state = 0; private_data.ifs_value = 0; private_data.scb = 0; /*enable and reserve pci resources and scb*/ if ((rc = e100_pci_setup(pcid)) != 0) { rtl_printf("e100_pci_setup is not successful\n"); goto err_dealloc; } if (private_data.rev_id == 0xff) private_data.rev_id = 1; if ((u8) private_data.rev_id >= D101A4_REV_ID) { private_data.flags |= IS_BACHELOR; } if ((u8) private_data.rev_id >= D102_REV_ID) { private_data.flags |= USE_IPCB; private_data.rfd_size = 32; } else { private_data.rfd_size = 16; } /*check command line options*/ e100_check_options(e100nics); if (!e100_init()) { rtl_printf(KERN_ERR "e100: Failed to initialize, instance #%d\n", e100nics); rc = -ENODEV; goto err_pci; } /* Check if checksum is valid */ cal_checksum = e100_eeprom_calculate_chksum(); read_checksum = e100_eeprom_read( (private_data.eeprom_size - 1)); if (cal_checksum != read_checksum) { rtl_printf(KERN_ERR "e100: Corrupted EEPROM on instance #%d\n", e100nics); rc = -ENODEV; goto err_pci; } e100nics++; e100_get_speed_duplex_caps(); memcpy(private_data.ifname, "rtle100", IFNAMSIZ); private_data.ifname[IFNAMSIZ-1] = 0; rtl_printf(KERN_NOTICE "e100: %s: %s\n", private_data.ifname, "Intel(R) PRO/100 Network Connection"); rt_e100_print_brd_conf(); private_data.wolsupported = 0; private_data.wolopts = 0; /* Check if WoL is enabled on EEPROM */ if (e100_eeprom_read( EEPROM_ID_WORD) & BIT_5) { /* Magic Packet WoL is enabled on device by default */ /* if EEPROM WoL bit is TRUE */ private_data.wolsupported = WAKE_MAGIC; private_data.wolopts = WAKE_MAGIC; if (private_data.rev_id >= D101A4_REV_ID) private_data.wolsupported = WAKE_PHY | WAKE_MAGIC; if (private_data.rev_id >= D101MA_REV_ID) private_data.wolsupported |= WAKE_UCAST | WAKE_ARP; rtl_printf(KERN_NOTICE "***EEPROM WoL bit is TRUE\n"); } rtl_printf("antes del open\n"); e100_open(pcid); rtl_printf("despues del open\n"); goto out;err_pci: iounmap(private_data.scb); pci_release_regions(pcid); pci_disable_device(pcid);err_dealloc: e100_dealloc_space();err_dev: pci_set_drvdata(pcid, NULL);out: return rc;}/** * e100_clear_structs - free resources * @dev: adapter's net_device struct * * Free all device specific structs, unmap i/o address, etc. */static voide100_clear_structs(struct pci_dev *dev){ iounmap(private_data.scb); /**Releases the PCI I/O and memory resources reserved by apci_request_region() call**/ pci_release_regions(dev); /**disabling PCI bus-mastering**/ pci_disable_device(dev); /*deallocate bd_dma_able_t structure**/ e100_dealloc_space(); pci_set_drvdata(dev, NULL);}static void eth_remove_one(struct pci_dev *pcid){ e100_clear_structs(pcid); --e100nics;}/** * e100_check_options - check command line options * @board: board number * @private_data: atapter's private data struct * * This routine does range checking on command-line options */voide100_check_options(int board){ if (board >= E100_MAX_NIC) { rtl_printf(KERN_NOTICE "e100: No configuration available for board #%d\n", board); rtl_printf(KERN_NOTICE "e100: Using defaults for all values\n"); board = E100_MAX_NIC; } e100_set_int_option(&(private_data.params.TxDescriptors), TxDescriptors[board], E100_MIN_TCB, E100_MAX_TCB, E100_DEFAULT_TCB, "TxDescriptor count"); e100_set_int_option(&(private_data.params.RxDescriptors), RxDescriptors[board], E100_MIN_RFD, E100_MAX_RFD, E100_DEFAULT_RFD, "RxDescriptor count"); e100_set_int_option(&(private_data.params.e100_speed_duplex), e100_speed_duplex[board], 0, 4, E100_DEFAULT_SPEED_DUPLEX, "speed/duplex mode"); e100_set_int_option(&(private_data.params.ber), ber[board], 0, ZLOCK_MAX_ERRORS, E100_DEFAULT_BER, "Bit Error Rate count"); e100_set_bool_option( XsumRX[board], PRM_XSUMRX, E100_DEFAULT_XSUM, "XsumRX value"); /* Default ucode value depended on controller revision */ if (private_data.rev_id >= D101MA_REV_ID) { e100_set_bool_option( ucode[board], PRM_UCODE, E100_DEFAULT_UCODE, "ucode value"); } else { e100_set_bool_option( ucode[board], PRM_UCODE, false, "ucode value"); } e100_set_bool_option( flow_control[board], PRM_FC, E100_DEFAULT_FC, "flow control value"); e100_set_bool_option( IFS[board], PRM_IFS, E100_DEFAULT_IFS, "IFS value"); e100_set_bool_option( BundleSmallFr[board], PRM_BUNDLE_SMALL, E100_DEFAULT_BUNDLE_SMALL_FR, "CPU saver bundle small frames value"); e100_set_int_option(&(private_data.params.IntDelay), IntDelay[board], 0x0, 0xFFFF, E100_DEFAULT_CPUSAVER_INTERRUPT_DELAY, "CPU saver interrupt delay value"); e100_set_int_option(&(private_data.params.BundleMax), BundleMax[board], 0x1, 0xFFFF, E100_DEFAULT_CPUSAVER_BUNDLE_MAX, "CPU saver bundle max value");}/** * e100_set_int_option - check and set an integer option * @option: a pointer to the relevant option field * @val: the value specified * @min: the minimum valid value * @max: the maximum valid value * @default_val: the default value * @name: the name of the option * * This routine does range checking on a command-line option. * If the option's value is '-1' use the specified default. * Otherwise, if the value is invalid, change it to the default. */void e100_set_int_option(int *option, int val, int min, int max, int default_val, char *name){ if (val == -1) { /* no value specified. use default */ *option = default_val; } else if ((val < min) || (val > max)) { rtl_printf(KERN_NOTICE "e100: Invalid %s specified (%i). " "Valid range is %i-%i\n", name, val, min, max); rtl_printf(KERN_NOTICE "e100: Using default %s of %i\n", name, default_val); *option = default_val; } else { rtl_printf(KERN_INFO "e100: Using specified %s of %i\n", name, val); *option = val; }}/** * e100_set_bool_option - check and set a boolean option * @private_data: atapter's private data struct * @val: the value specified * @mask: the mask for the relevant option * @default_val: the default value * @name: the name of the option * * This routine checks a boolean command-line option. * If the option's value is '-1' use the specified default. * Otherwise, if the value is invalid (not 0 or 1), * change it to the default. */voide100_set_bool_option(int val, u32 mask, int default_val, char *name){ if (val == -1) { if (default_val) private_data.params.b_params |= mask; } else if ((val != true) && (val != false)) { rtl_printf(KERN_NOTICE "e100: Invalid %s specified (%i). " "Valid values are %i/%i\n", name, val, false, true); rtl_printf(KERN_NOTICE "e100: Using default %s of %i\n", name, default_val); if (default_val) private_data.params.b_params |= mask; } else { rtl_printf(KERN_INFO "e100: Using specified %s of %i\n", name, val); if (val) private_data.params.b_params |= mask; }}static inte100_open(struct pci_dev *pdev){ int retval,rc = 0; u16 int_reg; /*print the params*/ /*read the control register from phy*/ e100_mdi_read( MII_BMSR,private_data.phy_addr, &int_reg); e100_mdi_read( MII_BMSR,private_data.phy_addr, &int_reg); /* setup the tcb pool */ if (!e100_alloc_tcb_pool()) { rc = -ENOMEM; rtl_printf(KERN_ERR "***e100_alloc_tcb_pool failed\n"); goto err_exit; } private_data.last_tcb = NULL; private_data.tcb_pool.head = 1;/*modified from 0 to 1*/ private_data.tcb_pool.tail = 1; e100_setup_tcb_pool((tcb_t *) private_data.tcb_pool.data, private_data.params.TxDescriptors); if (!e100_alloc_rfd_pool()) { rtl_printf(KERN_ERR "***e100_alloc_rfd_pool failed\n"); rc = -ENOMEM; goto err_exit; } /*for receiving pool*/ private_data.rvhead = (struct rx_list_elem *)(private_data.active_rx_list.next); private_data.rvprev = (struct rx_list_elem *)(private_data.active_rx_list.prev); if (!e100_wait_exec_cmplx( 0, SCB_CUC_LOAD_BASE, 0)) { rc = -EAGAIN; goto err_exit; } if (!e100_wait_exec_cmplx( 0, SCB_RUC_LOAD_BASE, 0)) { rc = -EAGAIN; goto err_exit; } e100_start_ru(); /* Use the now-standard shared IRQ implementation. */ /* IRQ is got from pci_enable_device() */ if ((retval = rtl_request_irq(pdev->irq, &e100intr))) { rtl_printf(KERN_ERR "%s: Could not reserve IRQ %d\n", pdev->name, pdev->irq); goto err_exit; }else private_data.must_free_irq = 1; /* allow interrupts*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -