⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dp83815.c

📁 linux下的DP83815网卡驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:


        /* initialize the device data */
        dev->base_addr          = iobase;
        dev->irq                = irq;
        dev->open               = &dp83815_open;
        dev->stop               = &dp83815_close;
        dev->get_stats          = &dp83815_get_stats;
        dev->do_ioctl           = &dp83815_ioctl;
        dev->hard_start_xmit    = &dp83815_start_xmit;
        dev->set_multicast_list = &dp83815_set_multicast_list;
        
        ether_setup (dev);        /* initialize generic fields */

        /* reserve IO region */
        request_region (iobase, DP83815_PCI_IO_SIZE, dev->name);
        
        /* Display board info */
        version = DP_REG32_READ(DP_SRR);
        printk (KERN_INFO "%s: bus=%d func=%d io=0x%x irq=%d ver=%d.%d\n",
                dev->name, bus, func, iobase, irq,
                (version & DP_SRR_MAJ) >> DP_SRR_MAJ_SHF,
                (version & DP_SRR_MIN));
        
        printk (KERN_INFO "%s: ethernet addr=%02x:%02x:%02x:%02x:%02x:%02x\n",
                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]);
        
        /* Chain the device */
        ((struct dp83815_priv *)(dev->priv))->next = dp83815_dev_list;
        dp83815_dev_list = dev;

#ifdef DEBUG
        printk (KERN_INFO "%s: DebugInfo: dev=0x%x priv=0x%x "
                "&dp_debug_level=0x%x\n",
                dev->name, (u32)dev, (u32)dev->priv, (u32)&dp_debug_level);
#endif

        /* Update Counters */
        dev_count++;
#ifdef LINK_AGGR
        memcpy (pAdp->PermMacAddr, dev->dev_addr, 6);
        memcpy (pAdp->CurrMacAddr, dev->dev_addr, 6);

        /* intialize call back routines for LACP */
        pAdp->FuncStruct.HsmSendPkt = dp83815_send_packet;
        pAdp->FuncStruct.HsmSendPkts = NULL;
        pAdp->FuncStruct.DrvSend = NULL;            
        pAdp->FuncStruct.HsmMulticastAdd = dp83815_multicast_add;
        pAdp->FuncStruct.HsmMulticastDelete = dp83815_multicast_delete;
        pAdp->FuncStruct.HsmSetMacAddress = dp83815_mac_address_set;
        pAdp->FuncStruct.HsmRxFilter = dp83815_rxfilter;
        pAdp->FuncStruct.HsmSetPhyCapabilities = dp83815_setphy;
        pAdp->FuncStruct.NsmSetPktStatus = NULL;
        pAdp->FuncStruct.NsmIndicateLinkStatus = dp83815_IndicateLinkStatus;
        pAdp->FuncStruct.HsmRxControl = dp83815_rx_control;
        
        /* register ethernet adapter with LACP */
        LacpRegister (pAdp);
#endif
        
        dev=NULL;
    }
    return dev_count ? OK : -ENODEV;
}

/* dp83815_open - open and initialize a device */
static int
dp83815_open (struct net_device *dev)
{
    u32     iobase = dev->base_addr;
    struct dp83815_priv* priv   = dev->priv;
    u32     txcfg, rxcfg, phy_status;
#ifdef LINK_AGGR
    NsmContext     *pNsm = &(priv->NsmCtxt);
    AdapterContext *pAdp = &(pNsm->AdpCtxt);
#endif

    /* Disable PME */
    DP_REG32_WRITE (DP_CCSR, 0x0000);
    /* Reset the device -- paranoia! */
#ifdef LINK_AGGR    
    if (dp83815_dev_reset (pAdp) != OK)
#else        
    if (dp83815_dev_reset (iobase) != OK)
#endif        
        return -EAGAIN;
    
    /* Allocate Tx and Rx queues */
    if (dp83815_queue_create (&priv->tx_queue, priv->tx_desc,
                            DP_QUEUE_TYPE_TX) != OK) {
        printk (KERN_INFO "%s: Failed to create tx queue\n", dev->name);
        return -EAGAIN;
    }
    
    if (dp83815_queue_create (&priv->rx_queue, priv->rx_desc,
                            DP_QUEUE_TYPE_RX) != OK) {
        dp83815_queue_delete (&priv->tx_queue);
        printk (KERN_INFO "%s: Failed to create rx queue\n", dev->name);
        return -EAGAIN;
    }

    DP_DEBUG (DP_DEBUG_OPEN,
              (KERN_INFO "%s: tx queue size %d rx queue size %d \n",
               dev->name, priv->tx_desc, priv->rx_desc));    

    /* Install the Tx and Rx queues on the device */
    DP_REG32_WRITE (DP_TXDP, virt_to_bus(priv->tx_queue.first_desc_addr));
    DP_REG32_WRITE (DP_RXDP, virt_to_bus(priv->rx_queue.first_desc_addr));
    
    DP_DEBUG (DP_DEBUG_OPEN,
              (KERN_INFO "dp: setting TXDP=0x%x RXDP=0x%x\n",
               (u32)virt_to_bus (priv->tx_queue.first_desc_addr),
               (u32)virt_to_bus (priv->rx_queue.first_desc_addr)));
    
   printk       (KERN_INFO "IP printk dp: setting TXDP=0x%x RXDP=0x%x\n",
               (u32)virt_to_bus (priv->tx_queue.first_desc_addr),
               (u32)virt_to_bus (priv->rx_queue.first_desc_addr));

    /* Install interrupt vector */
    if (request_irq (dev->irq, &dp83815_interrupt, SA_SHIRQ,
                     dev->name, dev) != OK) {
        dp83815_queue_delete (&priv->tx_queue);
        dp83815_queue_delete (&priv->rx_queue);
        return -EAGAIN;
    }
    
    /* Setup phy capabilities */
    if (dp83815_phy_setup (dev) != OK) {
        printk (KERN_INFO "%s: Warning PHY setup did not complete. 
                           Check cable.\n",    dev->name);
    }
    
    phy_status = DP_REG16_READ (DP_PHYSTS);

    /* Setup transmit control */
    txcfg =  DP_TXCFG_DRTH_SET(DP_TXCFG_DRTH_VAL) | 
             DP_TXCFG_FLTH_SET(DP_TXCFG_FLTH_VAL) |
             DP_TXCFG_MXDMA_32       |
             //IP DP_TXCFG_MXDMA_128       |
	     0x00040000		     |
             DP_TXCFG_ATP;

    /* if full duplex set the CSI and HBI in TXCFG */
    if (phy_status & DP_PHYSTS_FDX){
        txcfg |= DP_TXCFG_CSI | DP_TXCFG_HBI;
    }

    if (phy_status & DP_PHYSTS_SPEED_10)
	txcfg &= ~0x00040000;

    DP_REG32_WRITE (DP_TXCFG, txcfg);
    
    DP_DEBUG (DP_DEBUG_OPEN,
              (KERN_INFO "%s: TXCFG set to 0x%x\n", dev->name, txcfg));
    

    /* Setup receive control */
    rxcfg = DP_RXCFG_DRTH_SET(DP_RXCFG_DRTH_VAL) |
            DP_RXCFG_MXDMA_32;  
            //IP DP_RXCFG_MXDMA_128;  

    /* if full duplex set the ATX in RXCFG */
    if (phy_status & DP_PHYSTS_FDX)
        rxcfg |= DP_RXCFG_ATX;


    DP_REG32_WRITE (DP_RXCFG, rxcfg);
    
    DP_DEBUG (DP_DEBUG_OPEN,
              (KERN_INFO "%s: RXCFG set to 0x%x\n", dev->name, rxcfg));
    
    /* Setup the ethernet address */
#ifdef LINK_AGGR    
    dp83815_mac_address_set (pAdp, dev->dev_addr);
#else    
    dp83815_mac_address_set (iobase, dev->dev_addr);
#endif    
    
    /* Receive perfect match and broadcast packets */
    DP_REG32_WRITE (DP_RFCR, 0);
    DP_REG32_WRITE (DP_RFCR, (DP_RFCR_AAB  | /* all broadcast pkts */
                              DP_RFCR_APM  | /* perfect match pkts */
                              DP_RFCR_RFEN));

    DP_DEBUG (DP_DEBUG_OPEN,
              (KERN_INFO "dp: RFCR set to 0x%x\n",
               DP_RFCR_RFEN | DP_RFCR_APM | DP_RFCR_AAB));
    
    /* Turn on device interrupts */
    DP_REG32_WRITE (DP_IMR, (DP_IMR_RXOK   | DP_IMR_TXOK   |
                             DP_IMR_TXERR  | DP_IMR_TXURN  |
                             DP_IMR_MIB    | DP_IMR_TXDESC |
                             DP_IMR_RTABT  | DP_IMR_RMABT  |
                             DP_IMR_SSERR  | DP_IMR_PHY));

    DP_REG32_WRITE (DP_IER, DP_IER_IE);

    /* Enable Tx/Rx */
    DP_REG32_WRITE (DP_CR, DP_CR_TXE | DP_CR_RXE);
    
    /* Increment module reference count */
    MOD_INC_USE_COUNT;

#ifdef LINK_AGGR
    pAdp->lacprxFilterFlag = 0;
    pAdp->AdapterStatus |= ADAPTER_OPEN;
#endif
    
    return OK;
}
 
/* dp83815_close - close a device, and reclaim resources */
static int
dp83815_close (struct net_device *dev)
{
    u32  iobase = dev->base_addr;
    struct dp83815_priv* priv   = dev->priv;
    
#ifdef LINK_AGGR
    NsmContext     *pNsm = &(priv->NsmCtxt);
    AdapterContext *pAdp = &(pNsm->AdpCtxt);
#endif
    
    /* Stop the Tx/Rx */
    /* XXX Do we need to do this ??? */
    DP_REG32_WRITE (DP_CR, (DP_CR_TXD | DP_CR_RXD)); 
    
    /* Reset the device */
#ifdef LINK_AGGR
    dp83815_dev_reset (pAdp);
#else    
    dp83815_dev_reset (iobase);
#endif    

    /* Uninstall the interrupt vector */
    free_irq (dev->irq, dev);
            
    /* Free the Tx and Rx queues */
    dp83815_queue_delete (&priv->tx_queue);
    dp83815_queue_delete (&priv->rx_queue);

    /* Decrement module reference count */
    MOD_DEC_USE_COUNT;
    
    return OK;
}

/*
 * dp83815_start_xmit - transmit an ethernet packet.
 *
 * This routine writes to a tx descriptor, sets the ownership bit of the
 * CMDSTS, and signals the chip
 */
static int
dp83815_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
#ifdef LINK_AGGR
    int CableStatus;
    PktInfo     Pkt;
    NsmContext     *pNsm = &((struct dp83815_priv *)(dev->priv))->NsmCtxt;
    AdapterContext *pAdp = &(pNsm->AdpCtxt);
    int Priority;
    unsigned char status;
    
    Pkt.FragArray[0].pFrag =
        (UCHAR *)virt_to_phys (skb->data);
    
    Pkt.FragArray[0].FragLen = skb->len;

    Pkt.pOSCtrlBlk = skb;

    Pkt.NumFrags = 1;

    Pkt.pDLHeader = (void *)(skb->data);

    Priority = 0;

    if ((pAdp->nFlags) & GEC_FLAG)
        status = AggrSendPacket(pAdp, &Pkt, Priority, &CableStatus);
    else
        status = dp83815_send_packet(pAdp, &Pkt, Priority);
    
    if (status == FAILURE)
    {
        /* just for debug */
        printk (KERN_INFO "%s : error sending packets \n",dev->name);
        return ERROR;
    }
    
#else
    dp83815_send_packet(skb, dev);
#endif
    return OK;
}

#ifdef LINK_AGGR
static UCHAR
dp83815_send_packet (AdapterContext *pAdp, PktInfo *pPkt, int Priority)
#else    
static int
dp83815_send_packet (struct sk_buff *skb, struct net_device *dev)
#endif    
{
#ifdef LINK_AGGR
    struct net_device *dev = ((NsmContext *)(pAdp->pNsmContext))->dev;
    struct sk_buff *skb = pPkt->pOSCtrlBlk;
#endif
    u32        iobase = dev->base_addr;
    u32        cmdsts;
    virt_addr  tx_desc;
    struct net_device_stats *stats_p;
    int count;

    count = DP_DEFAULT_TXQ_SIZE; 

    if (skb->len > ETH_MAX_PKT_SIZE)
        return ERROR;

    tx_desc = dp83815_tx_desc_get(dev);
    while (tx_desc == NULL && --count) {
        DP_REG32_SET (DP_CR, DP_CR_TXE);
        DP_REG32_SET (DP_IMR, DP_IMR_TXOK | DP_IMR_TXIDLE);
        tx_desc = dp83815_tx_desc_get (dev);
    }

    stats_p = &((struct dp83815_priv *)(dev->priv))->stats;

    /* Update tx_desc to point to SKB data, set CMDSTS, and signal the chip */
    if (tx_desc != NULL) {

        /* update statistics of the previous transmit */
        cmdsts = DP_DESC_CMDSTS_XLATE_GET (tx_desc);
        if (cmdsts & DP_DESC_CMDSTS_TX_ERRORS) {

            stats_p->tx_errors++;
            
            /* Update individual counters */

            stats_p->collisions += DP_DESC_CMDSTS_TX_COLLISIONS_GET(cmdsts);

            if (cmdsts & DP_DESC_CMDSTS_TX_TXA) /* tx aborted */
                stats_p->tx_packets--;
            
            if (cmdsts & DP_DESC_CMDSTS_TX_TFU) /* fifo errors */
                stats_p->tx_fifo_errors++;

            if (cmdsts & DP_DESC_CMDSTS_TX_CRS) /* lost carrier */
                stats_p->tx_carrier_errors++;

            if (cmdsts & DP_DESC_CMDSTS_TX_OWC) /* out of window collisions */
                stats_p->tx_window_errors++;
        } else {
#ifdef LINK_AGGR
          pAdp->MacStats.txOkCount++;
#endif        
	  stats_p->tx_bytes += skb->len; /* number bytes transmitted */ 
	}

        /* clean up the descriptor */
        DP_DESC_CMDSTS_XLATE_SET (tx_desc, 0);
        /* Update the descriptor */
        DP_DESC_CMDSTS_XLATE_SET (tx_desc, DP_DESC_CMDSTS_OWN|
                                  DP_DESC_CMDSTS_INTR|skb->len);
        DP_DESC_BUFPTR_XLATE_SET (tx_desc, skb->data);
        DP_DESC_SKBPTR_SET (tx_desc, (u32)skb);
        
        dev->trans_start = jiffies;
        DP_REG32_SET (DP_CR, DP_CR_TXE);
        DP_DEBUG (DP_DEBUG_TX, 
                  (KERN_INFO "%s Tx: tx_desc=0x%x ", dev->name, (u32)tx_desc));
        stats_p->tx_packets++;
    } else {
        stats_p->tx_dropped++;
        dev_kfree_skb (skb);
    }

    return OK;
}
    

/*
 * dp83815_start_receive - receive the data from a Rx Queue descriptor
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -