📄 rtl_e100.c
字号:
if (st_timeout) *st_timeout = !(le32_to_cpu(private_data.selftest->st_sign)); if (st_result) *st_result = le32_to_cpu(private_data.selftest->st_result); return false; } return true;}/** * e100_setup_iaaddr - issue IA setup sommand * @private_data: atapter's private data struct * @eaddr: new ethernet address * * This routine will issue the IA setup command. This command * will notify the 82557 (e100) of what its individual (node) * address is. This command will be executed in polled mode. * * Returns: * true: if the IA setup command was successfully issued and completed * false: otherwise */unsigned chare100_setup_iaaddr(u8 *eaddr){ unsigned int i; cb_header_t *ntcb_hdr; unsigned char res; nxmit_cb_entry_t *cmd; if ((cmd = e100_alloc_non_tx_cmd()) == NULL) { res = false; goto exit; } ntcb_hdr = (cb_header_t *) cmd->non_tx_cmd; ntcb_hdr->cb_cmd = 0; ntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_IA_ADDRESS); for (i = 0; i < ETH_ALEN; i++) { (cmd->non_tx_cmd)->ntcb.setup.ia_addr[i] = eaddr[i]; } res = e100_exec_non_cu_cmd( cmd); if (!res) rtl_printf(KERN_WARNING "e100: %s: IA setup failed\n", private_data.ifname);exit: return res;}/** * e100_start_ru - start the RU if needed * @private_data: atapter's private data struct * * This routine checks the status of the 82557's receive unit(RU), * and starts the RU if it was not already active. However, * before restarting the RU, the driver gives the RU the buffers * it freed up during the servicing of the ISR. If there are * have reached a * no resource condition) the RU will not be started till the * next ISR. */voide100_start_ru(){ struct rx_list_elem *rx_struct = private_data.rvhead; spin_lock(&private_data.bd_lock); if (!e100_wait_exec_cmplx( rx_struct->dma_addr, SCB_RUC_START, 0)) { rtl_printf(KERN_DEBUG "e100: start_ru: wait_scb failed\n"); e100_exec_cmplx( rx_struct->dma_addr, SCB_RUC_START); } if (private_data.next_cu_cmd == RESUME_NO_WAIT) { private_data.next_cu_cmd = RESUME_WAIT; } spin_unlock(&private_data.bd_lock);}/** * e100_cmd_complete_location * @private_data: atapter's private data struct * * This routine returns a pointer to the location of the command-complete * DWord in the dump statistical counters area, according to the statistical * counters mode (557 - basic, 558 - extended, or 559 - TCO mode). * See e100_config_init() for the setting of the statistical counters mode. */static u32 *e100_cmd_complete_location(void){ u32 *cmd_complete; max_counters_t *stats = private_data.stats_counters; switch (private_data.stat_mode) { case E100_EXTENDED_STATS: cmd_complete = (u32 *) &(((err_cntr_558_t *) (stats))->cmd_complete); break; case E100_TCO_STATS: cmd_complete = (u32 *) &(((err_cntr_559_t *) (stats))->cmd_complete); break; case E100_BASIC_STATS: default: cmd_complete = (u32 *) &(((err_cntr_557_t *) (stats))->cmd_complete); break; } return cmd_complete;}/** * e100_clr_cntrs - clear statistics counters * @private_data: atapter's private data struct * * This routine will clear the adapter error statistic counters. * * Returns: * true: if successfully cleared stat counters * false: otherwise */static unsigned chare100_clr_cntrs(){ volatile u32 *pcmd_complete; /* clear the dump counter complete word */ pcmd_complete = e100_cmd_complete_location(); *pcmd_complete = 0; wmb(); if (!e100_wait_exec_cmplx( private_data.stat_cnt_phys, SCB_CUC_DUMP_ADDR, 0)) return false; /* wait 10 microseconds for the command to complete */ udelay(10); if (!e100_wait_exec_simple( SCB_CUC_DUMP_RST_STAT)) return false; if (private_data.next_cu_cmd == RESUME_NO_WAIT) { private_data.next_cu_cmd = RESUME_WAIT; } return true;}/** * e100_exec_non_cu_cmd * @private_data: atapter's private data struct * @command: the non-cu command to execute * * This routine will submit a command block to be executed, *delay exe or exe immediately */unsigned chare100_exec_non_cu_cmd( nxmit_cb_entry_t *command){ cb_header_t *ntcb_hdr; unsigned long lock_flag; //unsigned long expiration_time; unsigned char rc = true; u8 sub_cmd; ntcb_hdr = (cb_header_t *) command->non_tx_cmd; /* get hdr of non tcb cmd */ sub_cmd = cpu_to_le16(ntcb_hdr->cb_cmd); /* Set the Command Block to be the last command block */ /*set EL is VIP since CU will go from active to idle*/ /*after the completion*/ ntcb_hdr->cb_cmd |= __constant_cpu_to_le16(CB_EL_BIT); ntcb_hdr->cb_status = 0; ntcb_hdr->cb_lnk_ptr = 0; wmb(); spin_lock_bh(&(private_data.bd_non_tx_lock)); /*if has tx command, delay exe*/ if (private_data.last_tcb) { rmb(); while ((private_data.last_tcb->tcb_hdr.cb_status & __constant_cpu_to_le16(CB_STATUS_COMPLETE)) == 0) { rmb(); mdelay(10); } //goto delayed_exec; } /*if CU is busy, delay exe*/ while ((readw(&private_data.scb->scb_status) & SCB_CUS_MASK) == SCB_CUS_ACTIVE) { rmb(); mdelay(10); //goto delayed_exec; } spin_lock_irqsave(&private_data.bd_lock, lock_flag); /* otherwise, exe non-tx command*/ if (!e100_wait_exec_cmplx( command->dma_addr, SCB_CUC_START, sub_cmd)) { spin_unlock_irqrestore(&(private_data.bd_lock), lock_flag); rc = false; goto exit; } private_data.next_cu_cmd = START_WAIT; spin_unlock_irqrestore(&(private_data.bd_lock), lock_flag); /* now wait for completion of non-cu CB up to 20 msec */ rmb(); while (!(ntcb_hdr->cb_status & __constant_cpu_to_le16(CB_STATUS_COMPLETE))) { rmb(); mdelay(20); }exit: e100_free_non_tx_cmd( command); spin_unlock_bh(&(private_data.bd_non_tx_lock)); return rc;}/** * e100_sw_reset * @private_data: atapter's private data struct * @reset_cmd: s/w reset or selective reset * * This routine will issue a software reset to the adapter. It * will also disable interrupts, as the are enabled after reset. */voide100_sw_reset( u32 reset_cmd){ /* Do a selective reset first to avoid a potential PCI hang */ writel(PORT_SELECTIVE_RESET, &private_data.scb->scb_port); readw(&(private_data.scb->scb_status)); /* flushes last write, read-safe */ /* wait for the reset to take effect */ udelay(20); if (reset_cmd == PORT_SOFTWARE_RESET) { writel(PORT_SOFTWARE_RESET, &private_data.scb->scb_port); /* wait 20 micro seconds for the reset to take effect */ udelay(20); } /* Mask off our interrupt line -- it is unmasked after reset */ e100_disable_clear_intr();#ifdef E100_CU_DEBUG private_data.last_cmd = 0; private_data.last_sub_cmd = 0;#endif }/** * e100_load_microcode - Download microsocde to controller. * @private_data: atapter's private data struct * * This routine downloads microcode on to the controller. This * microcode is available for the 82558/9, 82550. Currently the * microcode handles interrupt bundling and TCO workaround. * * Returns: * true: if successfull * false: otherwise */static unsigned chare100_load_microcode(){ static struct { u8 rev_id; u32 ucode[UCODE_MAX_DWORDS + 1]; int timer_dword; int bundle_dword; int min_size_dword; } ucode_opts[] = { { D101A4_REV_ID, D101_A_RCVBUNDLE_UCODE, D101_CPUSAVER_TIMER_DWORD, D101_CPUSAVER_BUNDLE_DWORD, D101_CPUSAVER_MIN_SIZE_DWORD }, { D101B0_REV_ID, D101_B0_RCVBUNDLE_UCODE, D101_CPUSAVER_TIMER_DWORD, D101_CPUSAVER_BUNDLE_DWORD, D101_CPUSAVER_MIN_SIZE_DWORD }, { D101MA_REV_ID, D101M_B_RCVBUNDLE_UCODE, D101M_CPUSAVER_TIMER_DWORD, D101M_CPUSAVER_BUNDLE_DWORD, D101M_CPUSAVER_MIN_SIZE_DWORD }, { D101S_REV_ID, D101S_RCVBUNDLE_UCODE, D101S_CPUSAVER_TIMER_DWORD, D101S_CPUSAVER_BUNDLE_DWORD, D101S_CPUSAVER_MIN_SIZE_DWORD }, { D102_REV_ID, D102_B_RCVBUNDLE_UCODE, D102_B_CPUSAVER_TIMER_DWORD, D102_B_CPUSAVER_BUNDLE_DWORD, D102_B_CPUSAVER_MIN_SIZE_DWORD }, { D102C_REV_ID, D102_C_RCVBUNDLE_UCODE, D102_C_CPUSAVER_TIMER_DWORD, D102_C_CPUSAVER_BUNDLE_DWORD, D102_C_CPUSAVER_MIN_SIZE_DWORD }, { D102E_REV_ID, D102_E_RCVBUNDLE_UCODE, D102_E_CPUSAVER_TIMER_DWORD, D102_E_CPUSAVER_BUNDLE_DWORD, D102_E_CPUSAVER_MIN_SIZE_DWORD }, { 0, {0}, 0, 0, 0} }, *opts; opts = ucode_opts; /* User turned ucode loading off */ if (!(private_data.params.b_params & PRM_UCODE)) return false; /* These controllers do not need ucode */ if (private_data.flags & IS_ICH) return false; /* Search for ucode match against h/w rev_id */ while (opts->rev_id) { if (private_data.rev_id == opts->rev_id) { int i; u32 *ucode_dword; load_ucode_cb_t *ucode_cmd_ptr; nxmit_cb_entry_t *cmd = e100_alloc_non_tx_cmd(); if (cmd != NULL) { ucode_cmd_ptr = (load_ucode_cb_t *) cmd->non_tx_cmd; ucode_dword = ucode_cmd_ptr->ucode_dword; rtl_printf(KERN_ERR "***e100_alloc_non_tx_cmd succeed\n"); } else { rtl_printf(KERN_ERR "***e100_alloc_non_tx_cmd failed\n"); return false; } memcpy(ucode_dword, opts->ucode, sizeof (opts->ucode)); /* Insert user-tunable settings */ ucode_dword[opts->timer_dword] &= 0xFFFF0000; ucode_dword[opts->timer_dword] |= (u16) private_data.params.IntDelay; ucode_dword[opts->bundle_dword] &= 0xFFFF0000; ucode_dword[opts->bundle_dword] |= (u16) private_data.params.BundleMax; ucode_dword[opts->min_size_dword] &= 0xFFFF0000; ucode_dword[opts->min_size_dword] |= (private_data.params.b_params & PRM_BUNDLE_SMALL) ? 0xFFFF : 0xFF80; for (i = 0; i < UCODE_MAX_DWORDS; i++) cpu_to_le32s(&(ucode_dword[i])); ucode_cmd_ptr->load_ucode_cbhdr.cb_cmd = __constant_cpu_to_le16(CB_LOAD_MICROCODE); return e100_exec_non_cu_cmd( cmd); } opts++; } return false;}/***************************************************************************//***************************************************************************//* EEPROM Functions *//***************************************************************************//* Read PWA (printed wired assembly) number */void e100_rd_pwa_no(){ private_data.pwa_no = e100_eeprom_read( EEPROM_PWA_NO); private_data.pwa_no <<= 16; private_data.pwa_no |= e100_eeprom_read( EEPROM_PWA_NO + 1);}/* Read the permanent ethernet address from the eprom. */void e100_rd_eaddr(){ int i; u16 eeprom_word; for (i = 0; i < 6; i += 2) { eeprom_word = e100_eeprom_read( EEPROM_NODE_ADDRESS_BYTE_0 + (i / 2)); private_data.dev_addr[i] = private_data.perm_node_address[i] = (u8) eeprom_word; private_data.dev_addr[i + 1] = private_data.perm_node_address[i + 1] = (u8) (eeprom_word >> 8); }}/***************************************************************************//***************************************************************************//***************************************************************************//***************************************************************************//* Auxilary Functions *//***************************************************************************//* Print the board's configuration */void rt_e100_print_brd_conf(){ /*Print the string if checksum Offloading was enabled*/ if (private_data.flags & DF_CSUM_OFFLOAD) rtl_printf(KERN_NOTICE " Hardware receive checksums enabled\n"); else { if (private_data.rev_id >= D101MA_REV_ID) rtl_printf(KERN_NOTICE " Hardware receive checksums disabled\n"); } if ((private_data.flags & DF_UCODE_LOADED)) rtl_printf(KERN_NOTICE " cpu cycle saver enabled\n");}/** * e100_pci_setup - setup the adapter's PCI information * @pcid: adapter's pci_dev struct * @private_data: atapter's private data struct * * This routine sets up all PCI information for the adapter. It enables the bus * master bit (some BIOS don't do this), requests memory ans I/O regions, and * calls ioremap() on the adapter's memory region. * * Returns: * true: if successfull * false: otherwise */int e
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -