📄 skge.c
字号:
return (0);} /* SkGeOpen *//**************************************************************************** * * SkGeClose - Stop initialized adapter * * Description: * Close initialized adapter. * * Returns: * 0 - on success * error code - on error */#if 0static int SkGeClose(#elseint SkGeClose(#endifstruct SK_NET_DEVICE *dev){ DEV_NET *pNet; SK_AC *pAC; unsigned long Flags; /* for spin lock */ int i; int PortIdx; SK_EVPARA EvPara; netif_stop_queue(dev); pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC; if (pAC->RlmtNets == 1) PortIdx = pAC->ActivePort; else PortIdx = pNet->NetNr; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC)); /* * Clear multicast table, promiscuous mode .... */ SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0); SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, SK_PROM_MODE_NONE); if (pAC->MaxPorts == 1) { spin_lock_irqsave(&pAC->SlowPathLock, Flags); /* disable interrupts */ SK_OUT32(pAC->IoBase, B0_IMSK, 0); EvPara.Para32[0] = pNet->NetNr; EvPara.Para32[1] = -1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); SkEventDispatcher(pAC, pAC->IoBase); SK_OUT32(pAC->IoBase, B0_IMSK, 0); /* stop the hardware */ SkGeDeInit(pAC, pAC->IoBase); pAC->BoardLevel = 0; spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); } else { spin_lock_irqsave(&pAC->SlowPathLock, Flags); EvPara.Para32[0] = pNet->NetNr; EvPara.Para32[1] = -1; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); SkEventDispatcher(pAC, pAC->IoBase); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); /* Stop port */ spin_lock_irqsave(&pAC->TxPort[pNet->PortNr] [TX_PRIO_LOW].TxDesRingLock, Flags); SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, SK_STOP_ALL, SK_HARD_RST); spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr] [TX_PRIO_LOW].TxDesRingLock, Flags); } if (pAC->RlmtNets == 1) { /* clear all descriptor rings */ for (i=0; i<pAC->GIni.GIMacsFound; i++) { ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); ClearRxRing(pAC, &pAC->RxPort[i]); ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]); } } else { /* clear port descriptor rings */ ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE); ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]); ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]); } SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeClose: done ")); pAC->MaxPorts--; pNet->Up = 0; MOD_DEC_USE_COUNT; return (0);} /* SkGeClose *//***************************************************************************** * * SkGeXmit - Linux frame transmit function * * Description: * The system calls this function to send frames onto the wire. * It puts the frame in the tx descriptor ring. If the ring is * full then, the 'tbusy' flag is set. * * Returns: * 0, if everything is ok * !=0, on error * WARNING: returning 1 in 'tbusy' case caused system crashes (double * allocated skb's) !!! */#if 0static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)#elseint SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev)#endif{DEV_NET *pNet;SK_AC *pAC;int Rc; /* return code of XmitFrame */ pNet = (DEV_NET*) dev->priv; pAC = pNet->pAC;#if 0 if ((!skb_shinfo(skb)->nr_frags) ||#else if (1 ||#endif (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) { /* Don't activate scatter-gather and hardware checksum */ if (pAC->RlmtNets == 2) Rc = XmitFrame( pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], skb); else Rc = XmitFrame( pAC, &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], skb); } else {#if 0 /* scatter-gather and hardware TCP checksumming anabled*/ if (pAC->RlmtNets == 2) Rc = XmitFrameSG( pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], skb); else Rc = XmitFrameSG( pAC, &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], skb);#endif } /* Transmitter out of resources? */ if (Rc <= 0) { netif_stop_queue(dev); } /* If not taken, give buffer ownership back to the * queueing layer. */ if (Rc < 0) return (1);#if 0 dev->trans_start = jiffies;#endif return (0);} /* SkGeXmit *//***************************************************************************** * * XmitFrame - fill one socket buffer into the transmit ring * * Description: * This function puts a message into the transmit descriptor ring * if there is a descriptors left. * Linux skb's consist of only one continuous buffer. * The first step locks the ring. It is held locked * all time to avoid problems with SWITCH_../PORT_RESET. * Then the descriptoris allocated. * The second part is linking the buffer to the descriptor. * At the very last, the Control field of the descriptor * is made valid for the BMU and a start TX command is given * if necessary. * * Returns: * > 0 - on succes: the number of bytes in the message * = 0 - on resource shortage: this frame sent or dropped, now * the ring is full ( -> set tbusy) * < 0 - on failure: other problems ( -> return failure to upper layers) */static int XmitFrame(SK_AC *pAC, /* pointer to adapter context */TX_PORT *pTxPort, /* pointer to struct of port to send to */struct sk_buff *pMessage) /* pointer to send-message */{TXD *pTxd; /* the rxd to fill */unsigned long Flags;SK_U64 PhysAddr;int BytesSend; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X")); spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);#ifndef USE_TX_COMPLETE FreeTxDescriptors(pAC, pTxPort);#endif if (pTxPort->TxdRingFree == 0) { /* no enough free descriptors in ring at the moment */ FreeTxDescriptors(pAC, pTxPort); if (pTxPort->TxdRingFree == 0) { spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex); SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("XmitFrame failed\n")); /* this message can not be sent now */ /* Because tbusy seems to be set, the message should not be freed here */ /* It will be used by the scheduler of the ethernet handler */ return (-1); } } /* advance head counter behind descriptor needed for this frame */ pTxd = pTxPort->pTxdRingHead; pTxPort->pTxdRingHead = pTxd->pNextTxd; pTxPort->TxdRingFree--; /* the needed descriptor is reserved now */ /* * everything allocated ok, so add buffer to descriptor */#ifdef SK_DUMP_TX DumpMsg(pMessage, "XmitFrame");#endif /* set up descriptor and CONTROL dword */#if 0 PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, virt_to_page(pMessage->data), ((unsigned long) pMessage->data & ~PAGE_MASK), pMessage->len, PCI_DMA_TODEVICE);#else PhysAddr = (SK_U64) pci_phys_to_mem(pAC->PciDev, (u32) pMessage->data);#endif pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); pTxd->pMBuf = pMessage; pTxd->TBControl = TX_CTRL_OWN_BMU | TX_CTRL_STF | TX_CTRL_CHECK_DEFAULT | TX_CTRL_SOFTWARE |#ifdef USE_TX_COMPLETE TX_CTRL_EOF | TX_CTRL_EOF_IRQ | pMessage->len;#else TX_CTRL_EOF | pMessage->len;#endif if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) { /* previous descriptor already done, so give tx start cmd */ /* StartTx(pAC, pTxPort->HwAddr); */ SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START); } pTxPort->pTxdRingPrev = pTxd; BytesSend = pMessage->len; spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); /* after releasing the lock, the skb may be immidiately freed */ if (pTxPort->TxdRingFree != 0) return (BytesSend); else return (0);} /* XmitFrame *//***************************************************************************** * * XmitFrameSG - fill one socket buffer into the transmit ring * (use SG and TCP/UDP hardware checksumming) * * Description: * This function puts a message into the transmit descriptor ring * if there is a descriptors left. * * Returns: * > 0 - on succes: the number of bytes in the message * = 0 - on resource shortage: this frame sent or dropped, now * the ring is full ( -> set tbusy) * < 0 - on failure: other problems ( -> return failure to upper layers) */#if 0static int XmitFrameSG(SK_AC *pAC, /* pointer to adapter context */TX_PORT *pTxPort, /* pointer to struct of port to send to */struct sk_buff *pMessage) /* pointer to send-message */{ int i; int BytesSend; int hlength; int protocol; skb_frag_t *sk_frag; TXD *pTxd; TXD *pTxdFst; TXD *pTxdLst; SK_U64 PhysAddr; unsigned long Flags; spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);#ifndef USE_TX_COMPLETE FreeTxDescriptors(pAC, pTxPort);#endif if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) { FreeTxDescriptors(pAC, pTxPort); if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) { spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex); SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("XmitFrameSG failed - Ring full\n")); /* this message can not be sent now */ return(-1); } } pTxd = pTxPort->pTxdRingHead; pTxdFst = pTxd; pTxdLst = pTxd; BytesSend = 0; protocol = 0; /* map first fragment (header) */ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, virt_to_page(pMessage->data), ((unsigned long) pMessage->data & ~PAGE_MASK), skb_headlen(pMessage), PCI_DMA_TODEVICE); pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); /* HW checksum? */ if (pMessage->ip_summed == CHECKSUM_HW) { pTxd->TBControl = TX_CTRL_STF | TX_CTRL_ST_FWD | skb_headlen(pMessage); /* We have to use the opcode for tcp here because the opcode for udp is not working in the hardware yet (revision 2.0)*/ protocol = ((SK_U8)pMessage->data[23] & 0xf); if ((protocol == 17) && (pAC->GIni.GIChipRev != 0)) pTxd->TBControl |= BMU_UDP_CHECK; else pTxd->TBControl |= BMU_TCP_CHECK ; hlength = ((SK_U8)pMessage->data[14] & 0xf) * 4; pTxd->TcpSumOfs = 0; /* PH-Checksum already claculated */ pTxd->TcpSumSt = 14+hlength+16; pTxd->TcpSumWr = 14+hlength; } else { pTxd->TBControl = TX_CTRL_CHECK_DEFAULT | TX_CTRL_SOFTWARE | TX_CTRL_STF | skb_headlen(pMessage); } pTxd = pTxd->pNextTxd; pTxPort->TxdRingFree--; BytesSend += skb_headlen(pMessage); /* Map SG fragments */ for (i = 0; i < skb_shinfo(pMessage)->nr_frags; i++) { sk_frag = &skb_shinfo(pMessage)->frags[i]; /* we already have the proper value in entry */ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, sk_frag->page, sk_frag->page_offset, sk_frag->size, PCI_DMA_TODEVICE); pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); pTxd->pMBuf = pMessage; /* HW checksum */ if (pMessage->ip_summed == CHECKSUM_HW) { pTxd->TBControl = TX_CTRL_OWN_BMU | TX_CTRL_SOFTWARE | TX_CTRL_ST_FWD; /* We have to use the opcode for tcp here because the opcode for udp is not working in the hardware yet (revision 2.0)*/ if ((protocol == 17) && (pAC->GIni.GIChipRev != 0)) pTxd->TBControl |= BMU_UDP_CHECK ; else pTxd->TBControl |= BMU_TCP_CHECK ; } else { pTxd->TBControl = TX_CTRL_CHECK_DEFAULT | TX_CTRL_SOFTWARE | TX_CTRL_OWN_BMU; } /* Last fragment */ if( (i+1) == skb_shinfo(pMessage)->nr_frags ) {#ifdef USE_TX_COMPLETE pTxd->TBControl |= TX_CTRL_EOF | TX_CTRL_EOF_IRQ | sk_frag->size;#else pTxd->TBControl |= TX_CTRL_EOF | sk_frag->size;#endif pTxdFst->TBControl |= TX_CTRL_OWN_BMU | TX_CTRL_SOFTWARE; } else { pTxd->TBControl |= sk_frag->size; } pTxdLst = pTxd; pTxd = pTxd->pNextTxd; pTxPort->TxdRingFree--; BytesSend += sk_frag->size; } if ((pTxPort->pTxdRingPrev->TBControl & TX_CTRL_OWN_BMU) == 0) { /* previous descriptor already done, so give tx start cmd */ /* StartTx(pAC, pTxPort->HwAddr); */ SK_OUT8(pTxPort->HwAddr, TX_Q_CTRL, TX_Q_CTRL_START); } pTxPort->pTxdRingPrev = pTxdLst; pTxPort->pTxdRingHead = pTxd; spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); if (pTxPort->TxdRingFree > 0) return (BytesSend); else return (0);}#endifvoid dump_frag( SK_U8 *data, int length){ int i; printk("Length: %d\n", length); for( i=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -