📄 e1000_main.c
字号:
/***************************************************************************** Name: e1000_open** Description: This routine is the open call for the interface.** This is a Linux required routine.** Author: IntelCorporation** Born on Date: 07/11/99** Arguments: * NONE** Returns:* It returns 0 on success * -EAGAIN on failure** Modification log:* Date Who Description* -------- --- -------------------------------------------------------- *****************************************************************************/static inte1000_open(device_t * dev){ bd_config_t *bdp; PADAPTER_STRUCT Adapter = 0; int ret_val; printk("v0 e1000 Alignment: %p %p\n", &(Adapter->FirstTxDescriptor), &(Adapter->NumRxDescriptors)); bdp = dev->priv; Adapter = bdp->bddp; if (e1000_debug_level >= 1) printk("open: SOR, bdp = 0x%p\n", bdp); /* make sure we have not already opened this interface */ if(bdp->flags & BOARD_OPEN) return -EBUSY; if (e1000_init(bdp)) { return -ENOMEM; } if (e1000_runtime_init(bdp)) { return -ENOMEM; } Adapter->AdapterStopped = FALSE; #ifdef IANS_BASE_VLAN_TAGGING /* on a close a global reset is issued to the hardware, * so VLAN settings are lost and need to be re-set on open */ if((IANS_BD_TAGGING_MODE)ANS_PRIVATE_DATA_FIELD(bdp)->tag_mode != IANS_BD_TAGGING_NONE) bd_ans_hw_EnableVLAN(bdp);#endif if (request_irq(dev->irq, &e1000_intr, SA_SHIRQ, "e1000", dev)) { if (e1000_debug_level >= 1) printk("open: request_irq failed"); return (-EAGAIN); } /* Check to see if promiscuous mode needs to be turned on */ if (dev->flags & IFF_PROMISC) { /* turn promisc mode on */ ret_val = e1000_set_promisc(bdp, B_TRUE); bdp->flags |= PROMISCUOUS; } else { /* turn promisc mode off */ ret_val = e1000_set_promisc(bdp, B_FALSE); bdp->flags &= ~PROMISCUOUS; }#ifdef MODULE /* up the mod use count used by the system */ MOD_INC_USE_COUNT;#endif /* setup and start the watchdog timer */ init_timer(&bdp->timer_id); /* set the timer value for 2 sec( i.e. 200 10msec tics ) * jiffies are mesured in tics and is equiv. to LBOLTS in Unix */ bdp->timer_id.expires = bdp->timer_val = jiffies + 200; bdp->timer_id.data = (ulong_t) dev; bdp->timer_id.function = (void *) &e1000_watchdog; /* start the timer */ add_timer(&bdp->timer_id); /* set the device flags */ netif_start_queue(dev); /* enable interrupts */ e1000EnableInterrupt(Adapter); /* init the basic stats stuff */ ClearHwStatsCounters(Adapter); bdp->flags |= BOARD_OPEN; return (0);}/***************************************************************************** Name: e1000_close** Description: This routine is an entry point into the driver.** This is a Linux required routine.** Author: IntelCorporation** Born on Date: 07/11/99** Arguments: * device_t pointer** Returns:* It returns 0 and can not fail.** Modification log:* Date Who Description* -------- --- -------------------------------------------------------- *****************************************************************************/static inte1000_close(device_t * dev){ bd_config_t *bdp; PADAPTER_STRUCT Adapter; ushort_t status; int j; bdp = dev->priv; Adapter = bdp->bddp; /* set the device to not started */ netif_stop_queue(dev); /* stop the hardware */ /* Disable all possible interrupts */ E1000_WRITE_REG(Imc, (0xffffffff)); status = E1000_READ_REG(Icr); /* Reset the chip */ AdapterStop(Adapter); /* kill the timer */ del_timer(&bdp->timer_id); /* free the irq back to the system */ if (e1000_debug_level >= 1) printk("E1000: close: free_irq\n"); free_irq(dev->irq, dev); /* * Free up the transmit descriptor area */ if (e1000_debug_level >= 2) printk("--Cleanup, free tx descriptor area\n"); free_contig(bdp->base_tx_tbds); bdp->base_tx_tbds = NULL; if(Adapter->TxSkBuffs) free_contig(Adapter->TxSkBuffs); /* * Free up the RX_SW_PACKET area also free any allocated * receive buffers */ if (e1000_debug_level >= 2) printk("--Cleanup, free rx packet area + skbuffs\n"); if(Adapter->RxSkBuffs){ for (j = 0; j < Adapter->NumRxDescriptors; j++) { if (Adapter->RxSkBuffs[j]){ if (e1000_debug_level >= 2) printk(" -- kfree_skb\n"); dev_kfree_skb(Adapter->RxSkBuffs[j]); Adapter->RxSkBuffs[j] = 0; } } free_contig(Adapter->RxSkBuffs); } /* * Free the receive descriptor area */ if (e1000_debug_level >= 2) printk("--Cleanup, free rx descriptor area\n"); /* free_contig( Adapter->e1000_rbd_data ); */ free_contig(bdp->base_rx_rbds); bdp->base_rx_rbds = NULL; bdp->flags &= ~BOARD_OPEN;#ifdef MODULE /* adjust the mod use count */ MOD_DEC_USE_COUNT;#endif return (0);}/* * the send a packet, may poke at e1000 to force it to start tx */ static inte1000_xmit_frame_aux(struct sk_buff *skb, device_t * dev, int poke){ bd_config_t *bdp; PADAPTER_STRUCT Adapter; int lock_flag; int ret; bdp = dev->priv; Adapter = (PADAPTER_STRUCT) bdp->bddp; if (test_and_set_bit(0, (void*)&dev->tbusy) != 0) { return 1; } if (e1000_debug_level >= 3) printk("e1000_tx_frame\n"); /* call the transmit routine */#ifdef CLICK_POLLING if(SendBuffer(skb, bdp, poke, dev->polling)){#else if(SendBuffer(skb, bdp, poke, 0)){#endif ret = 0; } else {#ifdef IANS if(bdp->iANSdata->iANS_status == IANS_COMMUNICATION_UP) { ans_notify(dev, IANS_IND_XMIT_QUEUE_FULL); }#endif ret = 1; } if(bdp->tx_out_res == 0) clear_bit(0, (void*)&dev->tbusy); return (ret);}/***************************************************************************** Name: e1000_xmit_frame** Description: This routine is called to transmit a frame.*** Author: IntelCorporation** Born on Date: 07/11/99** Arguments: * sb_buff pointer* device_t pointer** Returns:* It returns B_FALSE on success* B_TRUE on failure** Modification log:* Date Who Description* -------- --- -------------------------------------------------------- *****************************************************************************/static inte1000_xmit_frame(struct sk_buff *skb, device_t * dev){ return e1000_xmit_frame_aux(skb, dev, 1);}/***************************************************************************** Name: SendBuffer** Description: This routine physically sends the packet to the nic controller.*** Author: IntelCorporation** Born on Date: 07/11/99** Arguments: * TX_SW_PACKET pointer* bd_config_t pointer** Returns:* It returns B_TRUE always and can not fail.** Modification log:* Date Who Description* -------- --- -------------------------------------------------------- *****************************************************************************/static UINTSendBuffer(struct sk_buff *skb, bd_config_t * bdp, int poke, int polling){ PADAPTER_STRUCT Adapter; PE1000_TRANSMIT_DESCRIPTOR CurrentTxDescriptor, nxt; // net_device_stats_t *stats; int di; Adapter = bdp->bddp; // stats = &bdp->net_stats; CurrentTxDescriptor = Adapter->NextAvailTxDescriptor; /* Don't use the last descriptor! */ if (CurrentTxDescriptor == Adapter->LastTxDescriptor) nxt = Adapter->FirstTxDescriptor; else nxt = CurrentTxDescriptor + 1; if(nxt == Adapter->OldestUsedTxDescriptor){ printk("e1000: out of descs in Sendbuffer\n"); return(0); } di = CurrentTxDescriptor - Adapter->FirstTxDescriptor; if(Adapter->TxSkBuffs[di]) printk("e1000 oops di %d TxSkBuffs[di] %x\n", di, (di >= 0 && di < 80) ? Adapter->TxSkBuffs[di] : 0); Adapter->TxSkBuffs[di] = skb; CurrentTxDescriptor->BufferAddress = virt_to_bus(skb->data); CurrentTxDescriptor->Lower.DwordData = skb->len; /* zero out the status field in the descriptor. */ CurrentTxDescriptor->Upper.DwordData = 0;#ifdef IANS if(bdp->iANSdata->iANS_status == IANS_COMMUNICATION_UP) { if(bd_ans_os_Transmit(bdp, CurrentTxDescriptor, &skb)==BD_ANS_FAILURE) { dev_kfree_skb(skb); return B_FALSE; } }#endif Adapter->NextAvailTxDescriptor = nxt; CurrentTxDescriptor->Lower.DwordData |= (E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS);#if 1 /* * If there is a valid value for the transmit interrupt delay, set up the * delay in the descriptor field */ if (Adapter->TxIntDelay) CurrentTxDescriptor->Lower.DwordData |= E1000_TXD_CMD_IDE;#else /* * Ask for a transmit complete interrupt every 60 packets. RTM * This seems to be broken -- sometimes the tx complete * interrupts never happen -- sending waits until a receive * packet arrives. RTM Dec 22 2000. */ if(polling==0 && Adapter->TxIntDelay){ static int dctr; if(dctr++ > 60){ dctr = 0; /* Don't delay for this packet! */ } else { /* Delay tx complete interrupt for most packets. */ CurrentTxDescriptor->Lower.DwordData |= E1000_TXD_CMD_IDE; } }#endif /* Set the RS or the RPS bit by looking at the ReportTxEarly setting */ if (Adapter->ReportTxEarly == 1) CurrentTxDescriptor->Lower.DwordData |= E1000_TXD_CMD_RS; else CurrentTxDescriptor->Lower.DwordData |= E1000_TXD_CMD_RPS; if (poke) /* Advance the Transmit Descriptor Tail (Tdt), this tells the * E1000 that this frame is available to transmit. */ E1000_WRITE_REG(Tdt, (((unsigned long) Adapter->NextAvailTxDescriptor - (unsigned long) Adapter->FirstTxDescriptor) >> 4)); /* Could we queue another packet? */ if (Adapter->NextAvailTxDescriptor == Adapter->LastTxDescriptor) nxt = Adapter->FirstTxDescriptor; else nxt = Adapter->NextAvailTxDescriptor + 1; if(nxt == Adapter->OldestUsedTxDescriptor) bdp->tx_out_res = 1; return(1);}/***************************************************************************** Name: e1000_get_stats** Description: This routine is called when the OS wants the nic stats returned*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -