rhine_main.c
来自「联想网卡驱动 linux环境下编写 初写驱动的同志参考以下」· C语言 代码 · 共 2,364 行 · 第 1/5 页
C
2,364 行
if (pInfo->byRevId>REV_ID_VT6102_A && pInfo->byRevId<REV_ID_VT6105M_A0) pInfo->IntMask|=IMR_TDWBRAI; writel(cpu_to_le32(pInfo->rd_pool_dma),&pMacRegs->dwCurrRxDescAddr); for (i=0;i<pInfo->nTxQueues;i++) writel(cpu_to_le32(pInfo->td_pool_dma[i]),&(pMacRegs->adwCurrTxDescAddr[i])); if (byRevId>=REV_ID_VT6105M_A0) rhine_init_cam_filter(pInfo); if (pInfo->flags & RHINE_FLAGS_FLOW_CTRL) enable_flow_control(pInfo); writew((CR0_DPOLL|CR0_TXON|CR0_RXON|CR0_STRT),&pMacRegs->byCR0); mii_status=rhine_get_opt_media_mode(pInfo); rhine_set_media_mode(pInfo,mii_status); rhine_print_link_status(pInfo); if (byRevId>=REV_ID_VT6102_A) enable_flow_control_ability(pInfo); rhine_ClearISR(pInfo->pMacRegs);}static BOOL rhine_soft_reset(PRHINE_INFO pInfo) { PMAC_REGS pMacRegs=pInfo->pMacRegs; int i=0; BYTE_REG_BITS_ON(CR1_SFRST, &pMacRegs->byCR1); /* VT86C100A may need long delay after reset (dlink) */ if (pInfo->chip_id == VT86C100A) udelay(100); for (i=0;i<W_MAX_TIMEOUT;i++) { udelay(5); if (!(readb(&pMacRegs->byCR1) & CR1_SFRST)) break; } if (i==W_MAX_TIMEOUT) { if (pInfo->chip_id==VT86C100A) { printk(KERN_ERR "%s: reset did not complete in 10 ms.\n", pInfo->dev->name); return FALSE; } writeb(MISC_CR1_FORSRST, &pMacRegs->byMISCCR1); // delay 2ms mdelay(2); } return TRUE; }static int rhine_found1(struct pci_dev *pcid, const struct pci_device_id *ent){ static BOOL bFirst=TRUE; struct net_device* dev=NULL; int i; PCHIP_INFO pChip_info=(PCHIP_INFO) ent->driver_data; PRHINE_INFO pInfo; PMAC_REGS pMacRegs; if (rhine_nics++>=MAX_UINTS) { printk(KERN_NOTICE RHINE_NAME ": already found %d NICs\n", rhine_nics); return -ENODEV; } dev=init_etherdev(dev,0); if (dev==NULL) { printk(KERN_ERR RHINE_NAME ": allocate net device failed"); return -ENODEV; } if (bFirst) { printk(KERN_NOTICE "%s Ver. %s\n",RHINE_FULL_DRV_NAM, RHINE_VERSION); printk(KERN_NOTICE "Copyright (c) 2002 VIA Technologies, Inc.\n"); printk(KERN_NOTICE "Copyright (c) 2002 D-Link Corporation.\n"); bFirst=FALSE; } if (!rhine_init_info(pcid,&pInfo, pChip_info)) { return -ENOMEM; } pInfo->dev=dev; rhine_create_proc_entry(pInfo); dev->priv=pInfo; dev->irq=pcid->irq; if (pci_enable_device(pcid)) { rhine_free_info(pInfo); return -ENODEV; } if (rhine_get_pci_info(pInfo,pcid)==FALSE) { printk(KERN_ERR RHINE_NAME ": Failed to find PCI device\n"); rhine_free_info(pInfo); return -ENODEV; } enable_mmio(pInfo); pMacRegs=ioremap(pInfo->memaddr & PCI_BASE_ADDRESS_MEM_MASK, pInfo->io_size); pInfo->pMacRegs=pMacRegs; if (check_region(pInfo->ioaddr,pInfo->io_size)) { printk(KERN_ERR RHINE_NAME ": Failed to find PCI device\n"); pInfo->ioaddr=0; rhine_free_info(pInfo); return -ENODEV; } request_region(pInfo->ioaddr,pInfo->io_size,RHINE_NAME); //Set back-off algorithm BYTE_REG_BITS_OFF((CFGD_CRADOM | CFGD_CAP | CFGD_MBA | CFGD_BAKOPT), &pMacRegs->byCFGD); dev->base_addr=pInfo->ioaddr; for (i=0;i<6;i++) dev->dev_addr[i]=readb(&pMacRegs->abyPAR[i]); rhine_print_info(pInfo); rhine_get_options(&pInfo->sOpts,rhine_nics-1,dev->name); //Mask out the options cannot be set to the chip pInfo->sOpts.flags &= pChip_info->flags; //Enable the chip specified capbilities pInfo->flags=pInfo->sOpts.flags | (pChip_info->flags & 0xFF000000UL); // rhine_print_options(pInfo); dev->irq=pcid->irq; dev->open = rhine_open; dev->hard_start_xmit = rhine_xmit; dev->stop = rhine_close; dev->get_stats = rhine_get_stats; dev->set_multicast_list = rhine_set_multi; dev->do_ioctl = rhine_ioctl; #ifdef RHINE_ZERO_COPY_SUPPORT dev->features |= NETIF_F_SG;#endif#ifdef RHINE_TX_CSUM_SUPPORT if ((pInfo->byRevId>=REV_ID_VT6105M_A0) && (pInfo->flags & RHINE_FLAGS_TX_CSUM)) { dev->features |= NETIF_F_IP_CSUM; }#endif pci_set_drvdata(pcid,pInfo); return 0;}static void rhine_print_info(PRHINE_INFO pInfo){ struct net_device* dev=pInfo->dev; printk(KERN_INFO "%s: %s\n",dev->name, get_chip_name(pInfo->chip_id)); printk(KERN_INFO "%s: MAC=%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", dev->name, dev->dev_addr[0],dev->dev_addr[1],dev->dev_addr[2], dev->dev_addr[3],dev->dev_addr[4],dev->dev_addr[5]); printk(" IO=0x%lx Mem=0x%lx ",(ULONG) pInfo->ioaddr,(ULONG) pInfo->pMacRegs); printk(" IRQ=%d \n", pInfo->dev->irq); }static BOOL rhine_init_info(struct pci_dev* pcid, PRHINE_INFO* ppInfo, PCHIP_INFO pChip_info) { PRHINE_INFO p; *ppInfo=kmalloc(sizeof(RHINE_INFO),GFP_ATOMIC); if (*ppInfo==NULL) return FALSE; memset(*ppInfo,0,sizeof(RHINE_INFO)); if (pRhine3_Infos==NULL) { pRhine3_Infos=*ppInfo; } else { for (p=pRhine3_Infos;p->next!=NULL;p=p->next) do {} while (0); p->next=*ppInfo; (*ppInfo)->prev=p; } (*ppInfo)->pcid=pcid; (*ppInfo)->chip_id=pChip_info->chip_id; (*ppInfo)->io_size=pChip_info->io_size; (*ppInfo)->nTxQueues=pChip_info->nTxQueue; (*ppInfo)->multicast_limit=32; #ifdef VMNS (*ppInfo)->vmns_priv=kmalloc(sizeof(VMNS_DRV_PRIVATE),GFP_ATOMIC); if ((*ppInfo)->vmns_priv==NULL) return FALSE; memset((*ppInfo)->vmns_priv,0,sizeof(VMNS_DRV_PRIVATE));#endif spin_lock_init(&((*ppInfo)->lock));#ifdef CONFIG_PROC_FS rhine_init_proc_fs(*ppInfo);#endif return TRUE;}static BOOL rhine_get_pci_info(PRHINE_INFO pInfo, struct pci_dev* pcid) { U16 pci_cmd; pci_read_config_byte(pcid, PCI_REVISION_ID, &pInfo->byRevId); pci_read_config_word(pcid, PCI_SUBSYSTEM_ID,&pInfo->SubSystemID); pci_read_config_word(pcid, PCI_SUBSYSTEM_VENDOR_ID, &pInfo->SubVendorID); pci_read_config_word(pcid, PCI_COMMAND, (u16 *) & (pci_cmd)); pci_set_master(pcid); pInfo->ioaddr=pci_resource_start(pcid,0); pInfo->memaddr=pci_resource_start(pcid,1); pInfo->pcid=pcid; if (pInfo->byRevId>=0x40) { U8 b; pci_read_config_byte(pcid,0x53, &b); pci_write_config_byte(pcid,0x53,b|0x04); } if (pInfo->byRevId>=0x8A && pInfo->byRevId< 0x90) { U8 b; pci_read_config_byte(pcid,0x52, &b); pci_write_config_byte(pcid,0x52,b|0x02); } return TRUE; }static void rhine_free_info(PRHINE_INFO pInfo) { PRHINE_INFO ptr; struct net_device* dev=pInfo->dev; ASSERT(pInfo); if (pRhine3_Infos==NULL) return; for (ptr=pRhine3_Infos;ptr && (ptr!=pInfo);ptr=ptr->next) do {} while (0); if (ptr==pInfo) { if (ptr==pRhine3_Infos) pRhine3_Infos=ptr->next; else ptr->prev->next=ptr->next; } else { RHINE_PRT(MSG_LEVEL_ERR, KERN_ERR "vmns: info struct not found\n"); return; }#ifdef CONFIG_PROC_FS rhine_free_proc_fs(pInfo); #endif if (dev) unregister_netdev(dev); if (pInfo->pMacRegs) iounmap(pInfo->pMacRegs); if (pInfo->ioaddr) release_region(pInfo->ioaddr,pInfo->io_size); if (dev) kfree(dev); if (pInfo->pcid) { pci_set_drvdata(pInfo->pcid,NULL); } #ifdef VMNS if (pInfo->vmns_priv) kfree(pInfo->vmns_priv);#endif kfree(pInfo); }static BOOL rhine_init_rings(PRHINE_INFO pInfo) { void* vir_pool; int i; /*allocate all RD/TD rings a single pool*/ vir_pool=pci_alloc_consistent(pInfo->pcid, pInfo->sOpts.nRxDescs * sizeof(RX_DESC) + pInfo->sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->nTxQueues, &pInfo->pool_dma); if (vir_pool==NULL) { printk(KERN_ERR "%s : allocate dma memory failed\n", pInfo->dev->name); return FALSE; } memset(vir_pool,0, pInfo->sOpts.nRxDescs * sizeof(RX_DESC) + pInfo->sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->nTxQueues); pInfo->aRDRing=vir_pool; pInfo->rd_pool_dma=pInfo->pool_dma; pInfo->tx_bufs=pci_alloc_consistent(pInfo->pcid, pInfo->sOpts.nTxDescs * PKT_BUF_SZ*pInfo->nTxQueues, &pInfo->tx_bufs_dma); if (pInfo->tx_bufs==NULL) { printk(KERN_ERR "%s: allocate dma memory failed\n", pInfo->dev->name); pci_free_consistent(pInfo->pcid, pInfo->sOpts.nRxDescs * sizeof(RX_DESC) + pInfo->sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->nTxQueues, pInfo->aRDRing, pInfo->pool_dma); return FALSE; } memset(pInfo->tx_bufs,0,pInfo->sOpts.nTxDescs * PKT_BUF_SZ*pInfo->nTxQueues); for (i=0;i<pInfo->nTxQueues;i++) { pInfo->td_pool_dma[i]=pInfo->rd_pool_dma+ pInfo->sOpts.nRxDescs*sizeof(RX_DESC)+ pInfo->sOpts.nTxDescs*sizeof(TX_DESC)*i; pInfo->apTDRings[i]=vir_pool+ pInfo->sOpts.nRxDescs*sizeof(RX_DESC)+ pInfo->sOpts.nTxDescs*sizeof(TX_DESC)*i; } return TRUE; }static void rhine_free_rings(PRHINE_INFO pInfo) { pci_free_consistent(pInfo->pcid, pInfo->sOpts.nRxDescs * sizeof(RX_DESC) + pInfo->sOpts.nTxDescs * sizeof(TX_DESC)*pInfo->nTxQueues, pInfo->aRDRing, pInfo->pool_dma); if (pInfo->tx_bufs) pci_free_consistent(pInfo->pcid, pInfo->sOpts.nTxDescs * PKT_BUF_SZ*pInfo->nTxQueues, pInfo->tx_bufs, pInfo->tx_bufs_dma); }static void rhine_init_rd_ring(PRHINE_INFO pInfo) { int i; dma_addr_t curr=pInfo->rd_pool_dma; PRX_DESC pDesc; /* Init the RD ring entries */ for (i = 0; i < pInfo->sOpts.nRxDescs; i++, curr+=sizeof(RX_DESC)) { pDesc=&(pInfo->aRDRing[i]); pDesc->pInfo=alloc_rd_info(); ASSERT(pDesc->pInfo); if (!rhine_alloc_rx_buf(pInfo, pDesc)) { RHINE_PRT(MSG_LEVEL_ERR,KERN_ERR "%s: can not alloc rx bufs\n", pInfo->dev->name); } pDesc->next=&(pInfo->aRDRing[(i+1) % pInfo->sOpts.nRxDescs]); pDesc->pInfo->curr_desc=cpu_to_le32(curr); pDesc->next_desc = cpu_to_le32(curr+sizeof(RX_DESC)); } pInfo->aRDRing[i-1].next_desc=cpu_to_le32(pInfo->rd_pool_dma); pInfo->pCurrRD=&(pInfo->aRDRing[0]);}static void rhine_free_rd_ring(PRHINE_INFO pInfo) { int i; /* Init the RD ring entries */ for (i = 0; i < pInfo->sOpts.nRxDescs; i++) { PRX_DESC pDesc=&(pInfo->aRDRing[i]); PRHINE_RD_INFO pRDInfo=pDesc->pInfo; pci_unmap_single(pInfo->pcid,pRDInfo->skb_dma, pInfo->rx_buf_sz, PCI_DMA_FROMDEVICE); dev_kfree_skb(pRDInfo->skb); kfree(pDesc->pInfo); }}static void rhine_init_td_ring(PRHINE_INFO pInfo) { int i,j; dma_addr_t curr; PTX_DESC pDesc; /* Init the RD ring entries */ for (j=0;j<pInfo->nTxQueues;j++) { curr=pInfo->td_pool_dma[j]; for (i = 0; i < pInfo->sOpts.nTxDescs; i++, curr+=sizeof(TX_DESC)) { pDesc=&(pInfo->apTDRings[j][i]); pDesc->pInfo=alloc_td_info(); ASSERT(pDesc->pInfo); if (pInfo->flags & RHINE_FLAGS_TX_ALIGN) { pDesc->pInfo->buf=pInfo->tx_bufs+(i+j)*PKT_BUF_SZ; pDesc->pInfo->buf_dma=pInfo->tx_bufs_dma+(i+j)*PKT_BUF_SZ; } pDesc->next=&(pInfo->apTDRings[j][(i+1) % pInfo->sOpts.nTxDescs]); pDesc->pInfo->curr_desc=cpu_to_le32(curr); pDesc->tdesc1.f1Chain=1; pDesc->next_desc = cpu_to_le32(curr+sizeof(TX_DESC)); } pInfo->apTDRings[j][i-1].next_desc=cpu_to_le32(pInfo->td_pool_dma[j]); pInfo->apTailTD[j]=pInfo->apCurrTD[j]=&(pInfo->apTDRings[j][0]); } }static void rhine_free_td_ring(PRHINE_INFO pInfo) { int i, j; for (j=0;j<pInfo->nTxQueues;j++) { for (i = 0; i < pInfo->sOpts.nTxDescs; i++) { PTX_DESC pDesc=&(pInfo->apTDRings[j][i]); PRHINE_TD_INFO pTDInfo=pDesc->pInfo; if (pTDInfo->skb_dma) pci_unmap_single(pInfo->pcid,pTDInfo->skb_dma, pTDInfo->skb->len, PCI_DMA_TODEVICE); if (pTDInfo->skb) dev_kfree_skb(pTDInfo->skb); kfree(pDesc->pInfo); } } }/*-----------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?