📄 dp83815.c
字号:
/* 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 + -