📄 rhine_main.c
字号:
/***************************************************************************** ***************************************************************************** Copyright (c) 2001 - 2002, VIA Technologies, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of VIA Technologies, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ***************************************************************************** ****************************************************************************/ #undef __NO_VERSION__#include "rhine.h"static int rhine_nics =0;static PRHINE_INFO pRhine3_Infos =NULL;static int msglevel =MSG_LEVEL_INFO;#ifdef SIOCETHTOOL#define RHINE_ETHTOOL_IOCTL_SUPPORT#include <linux/ethtool.h>static int rhine_ethtool_ioctl(struct net_device* dev, struct ifreq* ifr);#else#undef RHINE_ETHTOOL_IOCTL_SUPPORT#endif#ifdef SIOCGMIIPHY#define RHINE_MII_IOCTL_SUPPORTstatic int rhine_mii_ioctl(struct net_device* dev, struct ifreq* ifr, int cmd);#include <linux/mii.h>#else#undef RHINE_MII_IOCTL_SUPPORT#endif#if 0//The skb fragments of this version isn't be tested.#ifdef MAX_SKB_FRAGS#define RHINE_ZERO_COPY_SUPPORT#else#undef RHINE_ZERO_COPY_SUPPORT#endif#endif#ifdef NETIF_F_IP_CSUM#include <linux/in.h>#include <linux/ip.h>#include <linux/tcp.h>#include <linux/udp.h>#define RHINE_TX_CSUM_SUPPORT#else#undef RHINE_TX_CSUM_SUPPORT#endif/* Define module options*/MODULE_AUTHOR("VIA Technologies, Inc., <ShingChuang@via.com.tw>");MODULE_LICENSE("Dual BSD/GPL");MODULE_DESCRIPTION("D-Link DFE-530TX PCI Fast Ethernet Adapter Driver");#define RHINE_PARAM(N,D) \ static const int N[MAX_UINTS]=OPTION_DEFAULT;\ MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UINTS) "i");\ MODULE_PARM_DESC(N, D);#define RX_DESC_MIN 16#define RX_DESC_MAX 128#define RX_DESC_DEF 64RHINE_PARAM(RxDescriptors,"Number of receive descriptors");#define TX_DESC_MIN 16#define TX_DESC_MAX 64#define TX_DESC_DEF 64RHINE_PARAM(TxDescriptors,"Number of transmit descriptors");#define VLAN_ID_MIN 0#define VLAN_ID_MAX 4095#define VLAN_ID_DEF 0/* VID_setting[] is used for setting the VID of NIC. 0: default VID. 1-4094: other VIDs.*/RHINE_PARAM(VID_setting,"802.1q VLAN ID");#define TX_THRESH_MIN 0#define TX_THRESH_MAX 4#define TX_THRESH_DEF 0/* tx_thresh[] is used for controlling the transmit fifo threshold. 0: indicate the txfifo threshold is 128 bytes. 1: indicate the txfifo threshold is 256 bytes. 2: indicate the txfifo threshold is 512 bytes. 3: indicate the txfifo threshold is 1024 bytes. 4: indicate that we use store and forward*/RHINE_PARAM(tx_thresh,"Transmit fifo threshold");#define RX_THRESH_MIN 0#define RX_THRESH_MAX 7#define RX_THRESH_DEF 0/* rx_thresh[] is used for controlling the receive fifo threshold. 0: indicate the rxfifo threshold is 64 bytes. 1: indicate the rxfifo threshold is 32 bytes. 2: indicate the rxfifo threshold is 128 bytes. 3: indicate the rxfifo threshold is 256 bytes. 4: indicate the rxfifo threshold is 512 bytes. 5: indicate the rxfifo threshold is 768 bytes. 6: indicate the rxfifo threshold is 1024 bytes. 7: indicate that we use store and forward*/RHINE_PARAM(rx_thresh,"Receive fifo threshold");#define DMA_LENGTH_MIN 0#define DMA_LENGTH_MAX 7#define DMA_LENGTH_DEF 0/* DMA_length[] is used for controlling the DMA length 0: 8 DWORDs 1: 16 DWORDs 2: 32 DWORDs 3: 64 DWORDs 4: 128 DWORDs 5: 256 DWORDs 6: SF(flush till emply) 7: SF(flush till emply)*/RHINE_PARAM(DMA_length,"DMA length");#define TAGGING_DEF 0/* enable_tagging[] is used for enabling 802.1q VID tagging. 0: disable VID seeting(default). 1: enable VID setting.*/RHINE_PARAM(enable_tagging,"Enable 802.1Q tagging");#define IP_ALIG_DEF 0/* IP_byte_align[] is used for IP header DWORD byte aligned 0: indicate the IP header won't be DWORD byte aligned.(Default) . 1: indicate the IP header will be DWORD byte aligned. In some enviroment, the IP header should be DWORD byte aligned, or the packet will be droped when we receive it. (eg: IPVS)*/RHINE_PARAM(IP_byte_align,"Enable IP header dword aligned");#define RX_CSUM_DEF 1/* rxcsum_offload[] is used for setting the checksum offload ability of NIC. (We only support RX checksum offload now) 0: disable csum_offload[checksum offload 1: enable checksum offload. (Default)*/RHINE_PARAM(rxcsum_offload,"Enable receive packet checksum offload");#ifdef RHINE_TX_CSUM_SUPPORT#define TX_CSUM_DEF 0/* txcsum_offload[] is used for setting the checksum offload ability of NIC. (We only support RX checksum offload now) 0: disable csum_offload[checksum offload 1: enable checksum offload. (Default)*/RHINE_PARAM(txcsum_offload,"Enable transmit packet checksum offload");#endif#define FLOW_CNTL_DEF 1#define FLOW_CNTL_MIN 1#define FLOW_CNTL_MAX 3/* flow_control[] is used for setting the flow control ability of NIC. 1: hardware deafult(default). Use Hardware default value in ANAR. 2: disable PAUSE in ANAR. 3: enable PAUSE in ANAR.*/RHINE_PARAM(flow_control,"Enable flow control ability");#define MED_LNK_DEF 0#define MED_LNK_MIN 0#define MED_LNK_MAX 4/* speed_duplex[] is used for setting the speed and duplex mode of NIC. 0: indicate autonegotiation for both speed and duplex mode 1: indicate 100Mbps half duplex mode 2: indicate 100Mbps full duplex mode 3: indicate 10Mbps half duplex mode 4: indicate 10Mbps full duplex mode Note: if EEPROM have been set to the force mode, this option is ignored by driver.*/RHINE_PARAM(speed_duplex,"Setting the speed and duplex mode");static int rhine_found1(struct pci_dev *pcid, const struct pci_device_id *ent);static BOOL rhine_init_info(struct pci_dev* pcid, PRHINE_INFO* ppInfo, PCHIP_INFO);static void rhine_free_info(PRHINE_INFO pInfo);static BOOL rhine_get_pci_info(PRHINE_INFO, struct pci_dev* pcid);static void rhine_print_info(PRHINE_INFO pInfo);static int rhine_open(struct net_device *dev);static int rhine_xmit(struct sk_buff *skb, struct net_device *dev);static void rhine_intr(int irq, void *dev_instance, struct pt_regs *regs);static void rhine_set_multi(struct net_device *dev);static struct net_device_stats *rhine_get_stats(struct net_device *dev);static int rhine_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static int rhine_close(struct net_device *dev);static void rhine_rx_srv(PRHINE_INFO pInfo,int status);static BOOL rhine_receive_frame(PRHINE_INFO ,PRX_DESC pDesc);static BOOL rhine_alloc_rx_buf(PRHINE_INFO pInfo, PRX_DESC pDesc);static void rhine_init_registers(PRHINE_INFO pInfo);static void rhine_free_tx_buf(PRHINE_INFO pInfo, PTX_DESC pDesc);static BOOL rhine_soft_reset(PRHINE_INFO pInfo);static BOOL rhine_mii_read(PRHINE_INFO pInfo, U8 byIdx, PU16 pdata);static BOOL rhine_mii_write (PRHINE_INFO pInfo, BYTE byMiiAddr, WORD wData);static void rhine_set_media_mode(PRHINE_INFO pInfo, U32 mii_status);static U32 rhine_get_opt_media_mode(PRHINE_INFO pInfo);static void rhine_print_link_status(PRHINE_INFO pInfo);static void SafeDisableMiiAutoPoll (PRHINE_INFO pInfo);static void rhine_shutdown(PRHINE_INFO pInfo);static void enable_flow_control_ability(PRHINE_INFO pInfo);static CHIP_INFO chip_info_table[]= { { VT86C100A, "D-Link DFE-530TX PCI Fast Ethernet Adapter (rev.A) ", 128, 1, RHINE_FLAGS_IP_ALIGN|RHINE_FLAGS_TX_ALIGN}, { VT6102, "D-Link DFE-530TX PCI Fast Ethernet Adapter (rev.A3/B) ", 256, 1, RHINE_FLAGS_IP_ALIGN }, { VT6105, "D-Link DFE-530TX PCI Fast Ethernet Adapter (rev.C) ", 256, 1, RHINE_FLAGS_IP_ALIGN|RHINE_FLAGS_FLOW_CTRL}, { VT6105M, "D-Link DFE-530TX PCI Fast Ethernet Adapter (rev.D) ", 256, 1, RHINE_FLAGS_IP_ALIGN|RHINE_FLAGS_FLOW_CTRL| RHINE_FLAGS_TAGGING| RHINE_FLAGS_TX_CSUM| RHINE_FLAGS_HAVE_CAM| RHINE_FLAGS_RX_CSUM}, {0,NULL}};static struct pci_device_id rhine_id_table[] __devinitdata = {{ 0x1106, 0x3043, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (int)&chip_info_table[0]},{ 0x1106, 0x3065, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (int)&chip_info_table[1]},{ 0x1106, 0x3106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (int)&chip_info_table[2]},{ 0x1106, 0x3053, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (int)&chip_info_table[3]},{ 0, }};static char* get_chip_name(int chip_id) { int i; for (i=0;chip_info_table[i].name!=NULL;i++) if (chip_info_table[i].chip_id==chip_id) break; return chip_info_table[i].name; }static void __devexit rhine_remove1(struct pci_dev *pcid){ PRHINE_INFO pInfo=pci_get_drvdata(pcid); if (pInfo==NULL) return; #ifdef CONFIG_PROC_FS rhine_free_proc_entry(pInfo); #endif rhine_free_info(pInfo);}static void rhine_set_int_opt(int *opt, int val, int min, int max, int def,char* name,char* devname) { if (val==-1) *opt=def; else if (val<min || val>max) { RHINE_PRT(MSG_LEVEL_INFO, KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n" , devname,name, min,max); *opt=def; } else { RHINE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: set value of parameter %s to %d\n", devname, name, val); *opt=val; }}static void rhine_set_bool_opt(PU32 opt, int val,BOOL def,U32 flag, char* name,char* devname) { (*opt)&=(~flag); if (val==-1) *opt|=(def ? flag : 0); else if (val<0 || val>1) { printk(KERN_NOTICE "%s: the value of parameter %s is invalid, the valid range is (0-1)\n",devname,name); *opt|=(def ? flag : 0); } else { printk(KERN_INFO "%s: set parameter %s to %s\n", devname,name , val ? "TRUE" : "FALSE"); *opt|=(val ? flag : 0); }}static voidrhine_get_options(POPTIONS pOpts,int index,char* devname) { rhine_set_int_opt(&pOpts->tx_thresh,tx_thresh[index], TX_THRESH_MIN, TX_THRESH_MAX, RX_THRESH_DEF,"tx_thresh",devname); rhine_set_int_opt(&pOpts->rx_thresh,rx_thresh[index], RX_THRESH_MIN, RX_THRESH_MAX, RX_THRESH_DEF,"rx_thresh",devname); rhine_set_int_opt(&pOpts->DMA_length,DMA_length[index], DMA_LENGTH_MIN, DMA_LENGTH_MAX, DMA_LENGTH_DEF,"DMA_length",devname); rhine_set_int_opt(&pOpts->nRxDescs,RxDescriptors[index], RX_DESC_MIN, RX_DESC_MAX, RX_DESC_DEF, "RxDescriptors",devname); rhine_set_int_opt(&pOpts->nTxDescs,TxDescriptors[index], TX_DESC_MIN, TX_DESC_MAX, TX_DESC_DEF, "TxDescriptors",devname); rhine_set_int_opt(&pOpts->vid,VID_setting[index], VLAN_ID_MIN, VLAN_ID_MAX, VLAN_ID_DEF,"VID_setting",devname); rhine_set_bool_opt(&pOpts->flags,enable_tagging[index], TAGGING_DEF,RHINE_FLAGS_TAGGING, "enable_tagging",devname); rhine_set_bool_opt(&pOpts->flags,rxcsum_offload[index], RX_CSUM_DEF,RHINE_FLAGS_RX_CSUM,"rxcsum_offload",devname); #ifdef RHINE_TX_CSUM_SUPPORT rhine_set_bool_opt(&pOpts->flags,txcsum_offload[index], TX_CSUM_DEF,RHINE_FLAGS_TX_CSUM,"txcsum_offload",devname);#endif rhine_set_int_opt(&pOpts->flow_cntl,flow_control[index], FLOW_CNTL_MIN,FLOW_CNTL_MAX, FLOW_CNTL_DEF, "flow_control",devname); rhine_set_bool_opt(&pOpts->flags,IP_byte_align[index], IP_ALIG_DEF, RHINE_FLAGS_IP_ALIGN, "IP_byte_align",devname); rhine_set_int_opt((int*) &pOpts->spd_dpx,speed_duplex[index], MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF,"Media link mode",devname); }/*static void rhine_print_options(PRHINE_INFO pInfo) { if (pInfo->flags & RHINE_FLAGS_TAGGING) RHINE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: OPTION: Hardware 802.1q tagging enabled (VID=%d)\n", pInfo->dev->name, pInfo->sOpts.vid); if (pInfo->flags & RHINE_FLAGS_TX_CSUM) RHINE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: OPTION: Hardware TX checksum offload enabled\n", pInfo->dev->name); if (pInfo->flags & RHINE_FLAGS_RX_CSUM) RHINE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: OPTION: Hardware RX checksum offload enabled\n", pInfo->dev->name); if (pInfo->flags & RHINE_FLAGS_FLOW_CTRL) RHINE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: OPTION: Hardware flow control enabled\n", pInfo->dev->name); if (pInfo->flags & RHINE_FLAGS_HAVE_CAM) RHINE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: OPTION: Hardware multicast cam enabled\n", pInfo->dev->name); if (pInfo->flags & RHINE_FLAGS_TX_ALIGN) RHINE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: OPTION: TX buffer dword alignment enabled\n", pInfo->dev->name); if (pInfo->flags & RHINE_FLAGS_IP_ALIGN) RHINE_PRT(MSG_LEVEL_INFO, KERN_INFO "%s: OPTION: RX buffer IP header dword alignment enabled\n", pInfo->dev->name); }*/static void rhine_init_cam_filter(PRHINE_INFO pInfo) { PMAC_REGS pMacRegs=pInfo->pMacRegs; BYTE_REG_BITS_SET((TCR_PQEN),(TCR_RTGOPT|TCR_PQEN),&pMacRegs->byTCR); BYTE_REG_BITS_ON(BCR1_VIDFR,&pMacRegs->byBCR1); //Disable all cam rhine_set_cam_mask(pInfo,0,RHINE_VLAN_ID_CAM); rhine_set_cam_mask(pInfo,0,RHINE_MULTICAST_CAM); //Enable first vcam if (pInfo->flags & RHINE_FLAGS_TAGGING) { rhine_set_cam(pInfo,0,(PU8) &(pInfo->sOpts.vid),RHINE_VLAN_ID_CAM); rhine_set_cam_mask(pInfo,1,RHINE_VLAN_ID_CAM); rhine_set_cam_mask(pInfo,0,RHINE_MULTICAST_CAM); } }//// Initialiation of MAC registers//static void rhine_init_registers(PRHINE_INFO pInfo) { PMAC_REGS pMacRegs=pInfo->pMacRegs; int i,mii_status; U8 byRevId=pInfo->byRevId; for (i = 0; i < 6; i++) writeb(pInfo->dev->dev_addr[i], &pMacRegs->abyPAR[i]); if (byRevId>REV_ID_VT86C100A_E) { // clear sticky bits BYTE_REG_BITS_OFF((STICKHW_DS1_SHADOW|STICKHW_DS0_SHADOW), &pMacRegs->bySTICKHW); // disable force PME-enable writeb(WOLCR_LNKOFF_EN, &pMacRegs->byWOLCRClr); // disable power-event config bit writeb(0xFF, &pMacRegs->byWOLCGClr); // clear power status writeb(0xFF, &pMacRegs->byPWRCSRClr); } // do reset rhine_soft_reset(pInfo); mdelay(5); reload_eeprom(pInfo); rhine_set_tx_thresh(pInfo,pInfo->sOpts.tx_thresh); rhine_set_rx_thresh(pInfo,pInfo->sOpts.rx_thresh); rhine_set_DMA_length(pInfo,pInfo->sOpts.DMA_length); // for VT3043,VT3071 only if (byRevId < REV_ID_VT6102_A) { // disable queue packet, PATCH.... Aladdin 4/5 bug BYTE_REG_BITS_ON(CFGB_QPKTDIS, &pMacRegs->byCFGB); } else { // enable queue packet BYTE_REG_BITS_OFF(CFGB_QPKTDIS, &pMacRegs->byCFGB); // suspend-well accept broadcast, multicast writeb(WOLCFG_SAM|WOLCFG_SAB, &pMacRegs->byWOLCGSet); } // back off algorithm use original IEEE standard BYTE_REG_BITS_OFF((CFGD_CRADOM | CFGD_CAP | CFGD_MBA | CFGD_BAKOPT), &pMacRegs->byCFGD); // set packet filter // receive directed and broadcast address rhine_set_multi(pInfo->dev); pInfo->IntMask= (IMR_PRXM | IMR_PTXM | IMR_RXEM | IMR_TXEM | IMR_TUM | IMR_RUM | IMR_BEM | IMR_CNTM | IMR_ERM | IMR_ETM | IMR_OVFM | IMR_NORBFM| IMR_ABTM | IMR_SRCM );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -