📄 rtl_e100.c
字号:
private_data.intr_mask = 0; e100_set_intr_mask(); e100_force_config(); e100_mdi_read( MII_BMSR,private_data.phy_addr, &int_reg); e100_mdi_read( MII_BMSR,private_data.phy_addr, &int_reg); e100_mdi_read( MII_ADVERTISE,private_data.phy_addr, &int_reg); e100_mdi_read( MII_ADVERTISE,private_data.phy_addr, &int_reg); private_data.next_cu_cmd = START_WAIT; goto exit;err_exit: e100_clear_pools();exit: return rc;}static inteth_close(struct pci_dev *dev){ e100_disable_clear_intr(); if(private_data.must_free_irq){ rtl_free_irq(dev->irq); private_data.must_free_irq = 0; } private_data.intr_mask = SCB_INT_MASK; private_data.cur_line_speed = 0; private_data.cur_dplx_mode = 0; e100_clear_pools(); return 0;}/** * e100init - initialize the adapter * @private_data: atapter's private data struct * * This routine is called when this driver is loaded. This is the initialization * routine which allocates memory, configures the adapter and determines the * system resources. * * Returns: * true: if successful * false: otherwise */static unsigned chare100_init(){ u32 st_timeout = 0; u32 st_result = 0; e100_sw_init(); if (!e100_selftest( &st_timeout, &st_result)) { if (st_timeout) { rtl_printf(KERN_ERR "e100: selftest timeout\n"); } else { rtl_printf(KERN_ERR "e100: selftest failed. Results: %x\n", st_result); } return false; } /* read the MAC address from the eprom */ e100_rd_eaddr(); if (!is_valid_ether_addr(private_data.dev_addr)) { rtl_printf(KERN_ERR "e100: Invalid Ethernet address\n"); return false; } /* read NIC's part number */ e100_rd_pwa_no(); if (!e100_hw_init()) { rtl_printf(KERN_ERR "e100: hw init failed\n"); return false; } /* Interrupts are enabled after device reset */ e100_disable_clear_intr(); return true;}/** * e100_sw_init - initialize software structs * @private_data: atapter's private data struct * * This routine initializes all software structures. Sets up the * circular structures for the RFD's & TCB's. Allocates the per board * structure for storing adapter information. The CSR is also memory * mapped in this routine. * * Returns : * true: if S/W was successfully initialized * false: otherwise */static unsigned chare100_sw_init(){ /*for the first TX command*/ private_data.next_cu_cmd = START_WAIT; // init the next cu state /* * Set the value for # of good xmits per underrun. the value assigned * here is an intelligent suggested default. Nothing magical about it. */ private_data.tx_per_underrun = DEFAULT_TX_PER_UNDERRUN; /* get the default transmit threshold value */ private_data.tx_thld = TX_THRSHLD; /* get the EPROM size */ private_data.eeprom_size = e100_eeprom_size(); /* Initialize our spinlocks */ spin_lock_init(&(private_data.bd_lock)); spin_lock_init(&(private_data.bd_non_tx_lock)); spin_lock_init(&(private_data.config_lock)); spin_lock_init(&(private_data.mdi_access_lock)); return 1;}static void e100_tco_workaround(){ int i; /* Do software reset */ e100_sw_reset( PORT_SOFTWARE_RESET); /* Do a dummy LOAD CU BASE command. */ /* This gets us out of pre-driver to post-driver. */ e100_exec_cmplx( 0, SCB_CUC_LOAD_BASE); /* Wait 20 msec for reset to take effect *///BUG: set_current_state(TASK_UNINTERRUPTIBLE); rtl_printf("usleep 1\n"); usleep(20000);//BUG: schedule_timeout(HZ / 50 + 1); /* disable interrupts since they are enabled */ /* after device reset */ e100_disable_clear_intr(); /* Wait for command to be cleared up to 1 sec */ for (i=0; i<100; i++) { if (!readb(&private_data.scb->scb_cmd_low)) break;//BUG: set_current_state(TASK_UNINTERRUPTIBLE); rtl_printf("usleep 2\n"); usleep(1000000);//BUG: schedule_timeout(HZ / 100 + 1); } /* Wait for TCO request bit in PMDR register to be clear */ for (i=0; i<50; i++) { if (!(readb(&private_data.scb->scb_ext.d101m_scb.scb_pmdr) & BIT_1)) break;//BUG: set_current_state(TASK_UNINTERRUPTIBLE); rtl_printf("usleep 3\n"); usleep(1000000);//BUG: schedule_timeout(HZ / 100 + 1); }}/** * e100_hw_init - initialized tthe hardware * @private_data: atapter's private data struct * * This routine performs a reset on the adapter, and configures the adapter. * This includes configuring the 82557 LAN controller, validating and setting * the node address, detecting and configuring the Phy chip on the adapter, * and initializing all of the on chip counters. * * Returns: * true - If the adapter was initialized * false - If the adapter failed initialization */unsigned char e100_hw_init(){ /**set params in rtl_e100main_phy.c***/ if (!e100_phy_init()) return false; e100_sw_reset(PORT_SELECTIVE_RESET); /* Only 82559 or above needs TCO workaround */ if (private_data.rev_id >= D101MA_REV_ID) { e100_tco_workaround(); rtl_printf(KERN_ERR "***e100_tco_workaround Finished\n"); } /* Load the CU BASE (set to 0, because we use linear mode) */ if (!e100_wait_exec_cmplx( 0, SCB_CUC_LOAD_BASE, 0)) return false; if (!e100_wait_exec_cmplx( 0, SCB_RUC_LOAD_BASE, 0)) return false; /* Load interrupt microcode */ if (e100_load_microcode()) { private_data.flags |= DF_UCODE_LOADED; } e100_config_init(); if (!e100_config()) { return false; } if (!e100_setup_iaaddr( private_data.dev_addr)) return false; /* Clear the internal counters */ if (!e100_clr_cntrs()) return false; /* Change for 82558 enhancement */ /* If 82558/9 and if the user has enabled flow control, set up the * Flow Control Reg. in the CSR */ if ((private_data.flags & IS_BACHELOR) && (private_data.params.b_params & PRM_FC)) { writeb(DFLT_FC_THLD, &private_data.scb->scb_ext.d101_scb.scb_fc_thld); writeb(DFLT_FC_CMD, &private_data.scb->scb_ext.d101_scb.scb_fc_xon_xoff); //rtl_printf(KERN_ERR "***FC done\n"); } return true;}/** * e100_setup_tcb_pool - setup TCB circular list *and initialize each TCB * @head: Pointer to head of the allocated TCBs * @qlen: Number of elements in the queue * @private_data: atapter's private data struct * * This routine arranges the contigiously allocated TCB's in a circular list. * Also does the one time initialization of the TCBs. */static voide100_setup_tcb_pool(tcb_t *head, unsigned int qlen){ int ele_no; tcb_t *pcurr_tcb; /* point to current tcb */ u32 next_phys; /* the next phys addr */ u16 txcommand = CB_S_BIT | CB_TX_SF_BIT; unsigned char *skb; private_data.tx_count = 0; if (private_data.flags & USE_IPCB) { txcommand |= CB_IPCB_TRANSMIT | CB_CID_DEFAULT; } else if (private_data.flags & IS_BACHELOR) { txcommand |= CB_TRANSMIT | CB_CID_DEFAULT; } else { txcommand |= CB_TRANSMIT; } for (ele_no = 0, next_phys = private_data.tcb_phys, pcurr_tcb = head; ele_no < qlen; ele_no++, pcurr_tcb++) { /* set the phys addr for this TCB, next_phys has not incr. yet */ pcurr_tcb->tcb_phys = next_phys; next_phys += sizeof (tcb_t); /* set up the circular tcb list */ if (ele_no == (qlen - 1)) pcurr_tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(private_data.tcb_phys); else pcurr_tcb->tcb_hdr.cb_lnk_ptr = cpu_to_le32(next_phys); pcurr_tcb->tcb_hdr.cb_status = 0; pcurr_tcb->tcb_hdr.cb_cmd = cpu_to_le16(txcommand); pcurr_tcb->tcb_cnt = 0; pcurr_tcb->tcb_thrshld = private_data.tx_thld; pcurr_tcb->tcb_tbd_num = 1; if (private_data.flags & IS_BACHELOR) { pcurr_tcb->tcb_tbd_ptr = __constant_cpu_to_le32(0xFFFFFFFF); } else { pcurr_tcb->tcb_tbd_ptr = cpu_to_le32(pcurr_tcb->tcb_phys + 0x10); } if (private_data.flags & IS_BACHELOR) { pcurr_tcb->tcb_tbd_expand_ptr = cpu_to_le32(pcurr_tcb->tcb_phys + 0x20); } else { pcurr_tcb->tcb_tbd_expand_ptr = cpu_to_le32(pcurr_tcb->tcb_phys + 0x10); } pcurr_tcb->tcb_tbd_dflt_ptr = pcurr_tcb->tcb_tbd_ptr; if (private_data.flags & USE_IPCB) { pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[1]); pcurr_tcb->tcbu.ipcb.ip_activation_high = IPCB_IP_ACTIVATION_DEFAULT; pcurr_tcb->tcbu.ipcb.vlan = 0; } else { pcurr_tcb->tbd_ptr = &(pcurr_tcb->tcbu.tbd_array[0]); } /*alloc skb to the curr tcb*/ skb = rtl_malloc(PKT_BUF_SZ); pcurr_tcb->tcb_skb = skb; if (skb == NULL) break; /* Bad news! */ (pcurr_tcb->tbd_ptr)->tbd_buf_addr = cpu_to_le32(pci_map_single(private_data.pdev, skb, PKT_BUF_SZ, PCI_DMA_TODEVICE)); } /* for */ wmb(); if (ele_no < qlen) { rtl_printf(KERN_EMERG "ele_no = %d: no enough memory for tx ring\n",ele_no); rtl_printf(KERN_EMERG "\nPlease unload the module and try again\n\n"); }}/***************************************************************************//***************************************************************************//* Memory Management Routines *//***************************************************************************//** * e100_alloc_space - allocate private driver data * @private_data: atapter's private data struct * * This routine allocates memory for the driver. Memory allocated is for the * selftest and statistics structures. * * Returns: * 0: if the operation was successful * %-ENOMEM: if memory allocation failed */unsigned char e100_alloc_space(){ unsigned long off; /* allocate all the dma-able structures in one call: * selftest results, adapter stats, and non-tx cb commands */ if (!(private_data.dma_able = pci_alloc_consistent(private_data.pdev, sizeof (bd_dma_able_t), &(private_data.dma_able_phys)))) { goto err; } /* now assign the various pointers into the struct we've just allocated */ off = offsetof(bd_dma_able_t, selftest); private_data.selftest = (self_test_t *) (private_data.dma_able + off); private_data.selftest_phys = private_data.dma_able_phys + off; off = offsetof(bd_dma_able_t, stats_counters); private_data.stats_counters = (max_counters_t *) (private_data.dma_able + off); private_data.stat_cnt_phys = private_data.dma_able_phys + off; return 0;err: rtl_printf(KERN_ERR "e100: Failed to allocate memory\n"); return -ENOMEM;}/** * e100_alloc_tcb_pool - allocate TCB circular list * @private_data: atapter's private data struct * * This routine allocates memory for the circular list of transmit descriptors. * * Returns: * 0: if allocation has failed. * 1: Otherwise. */inte100_alloc_tcb_pool(){ int stcb = sizeof (tcb_t) * private_data.params.TxDescriptors; /* allocate space for the TCBs */ if (!(private_data.tcb_pool.data = pci_alloc_consistent(private_data.pdev, stcb, &private_data.tcb_phys))) return 0; memset(private_data.tcb_pool.data, 0x00, stcb); return 1;}voide100_free_tcb_pool(){ int i; tcb_t * tcb; /*skb has to be free*/ for (i = 0; i < private_data.params.TxDescriptors; i++) { tcb = private_data.tcb_pool.data; tcb += i; mb(); e100_tx_skb_free(tcb); mb(); } pci_free_consistent(private_data.pdev, sizeof (tcb_t) * private_data.params.TxDescriptors, private_data.tcb_pool.data, private_data.tcb_phys); private_data.tcb_phys = 0;}static voide100_dealloc_space(){ if (private_data.dma_able) { pci_free_consistent(private_data.pdev, sizeof (bd_dma_able_t), private_data.dma_able, private_data.dma_able_phys); } private_data.selftest_phys = 0; private_data.stat_cnt_phys = 0; private_data.dma_able_phys = 0; private_data.dma_able = 0;}static voide100_free_rfd_pool(){ struct rx_list_elem *rx_struct; while (!list_empty(&(private_data.active_rx_list))) { rx_struct = list_entry(private_data.active_rx_list.next, struct rx_list_elem, list_elem);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -