📄 skge.c
字号:
spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); #endif /* 0 */#endif /* USE_TX_COMPLETE */ /* IRQ is processed - Enable IRQs again*/ SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); return;} /* SkGeIsrOnePort *//**************************************************************************** * * SkGeOpen - handle start of initialized adapter * * Description: * This function starts the initialized adapter. * The board level variable is set and the adapter is * brought to full functionality. * The device flags are set for operation. * Do all necessary level 2 initialization, enable interrupts and * give start command to RLMT. * * Returns: * 0 on success * != 0 on error */static int SkGeOpen(struct net_device *dev){SK_AC *pAC; /* pointer to adapter context struct */unsigned int Flags; /* for spin lock */int i;SK_EVPARA EvPara; /* an event parameter union */ pAC = (SK_AC*) dev->priv; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC)); if (pAC->BoardLevel == 0) { /* level 1 init common modules here */ if (SkGeInit(pAC, pAC->IoBase, 1) != 0) { printk("%s: HWInit(1) failed\n", pAC->dev->name); return (-1); } SkI2cInit (pAC, pAC->IoBase, 1); SkEventInit (pAC, pAC->IoBase, 1); SkPnmiInit (pAC, pAC->IoBase, 1); SkAddrInit (pAC, pAC->IoBase, 1); SkRlmtInit (pAC, pAC->IoBase, 1); SkTimerInit (pAC, pAC->IoBase, 1); pAC->BoardLevel = 1; } /* level 2 init modules here */ SkGeInit (pAC, pAC->IoBase, 2); SkI2cInit (pAC, pAC->IoBase, 2); SkEventInit (pAC, pAC->IoBase, 2); SkPnmiInit (pAC, pAC->IoBase, 2); SkAddrInit (pAC, pAC->IoBase, 2); SkRlmtInit (pAC, pAC->IoBase, 2); SkTimerInit (pAC, pAC->IoBase, 2); pAC->BoardLevel = 2; for (i=0; i<pAC->GIni.GIMacsFound; i++) { // Enable transmit descriptor polling. SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); FillRxRing(pAC, &pAC->RxPort[i]); } SkGeYellowLED(pAC, pAC->IoBase, 1);#ifdef USE_INT_MOD// moderate only TX complete interrupts (these are not time critical)#define IRQ_MOD_MASK (IRQ_EOF_AS_TX1 | IRQ_EOF_AS_TX2) { unsigned long ModBase; ModBase = 53125000 / INTS_PER_SEC; SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); SK_OUT32(pAC->IoBase, B2_IRQM_MSK, IRQ_MOD_MASK); SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); }#endif /* enable Interrupts */ SK_OUT32(pAC->IoBase, B0_IMSK, IRQ_MASK); SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); spin_lock_irqsave(&pAC->SlowPathLock, Flags); SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); if (pAC->RlmtMode != 0) { EvPara.Para32[0] = pAC->RlmtMode; SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE, EvPara); } SkEventDispatcher(pAC, pAC->IoBase); spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); MOD_INC_USE_COUNT; SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeOpen suceeded\n")); return (0);} /* SkGeOpen *//**************************************************************************** * * SkGeClose - Stop initialized adapter * * Description: * Close initialized adapter. * * Returns: * 0 - on success * error code - on error */static int SkGeClose(struct net_device *dev){SK_AC *pAC;unsigned int Flags; /* for spin lock */int i;SK_EVPARA EvPara; netif_stop_queue(dev); pAC = (SK_AC*) dev->priv; 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, pAC->ActivePort, 0); SkAddrPromiscuousChange(pAC, pAC->IoBase, pAC->ActivePort, SK_PROM_MODE_NONE); spin_lock_irqsave(&pAC->SlowPathLock, Flags); /* disable interrupts */ SK_OUT32(pAC->IoBase, B0_IMSK, 0); 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); for (i=0; i<pAC->GIni.GIMacsFound; i++) { /* clear all descriptor rings */ ReceiveIrq(pAC, &pAC->RxPort[i]); ClearRxRing(pAC, &pAC->RxPort[i]); ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]); } SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("SkGeClose: done ")); 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) !!! */static int SkGeXmit(struct sk_buff *skb, struct net_device *dev){SK_AC *pAC;int Rc; /* return code of XmitFrame */ pAC = (SK_AC*) dev->priv; Rc = XmitFrame(pAC, &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], skb); /* 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); dev->trans_start = jiffies; 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 int 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); 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); SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("XmitFrame failed\n")); /* this message can not be sent now */ 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 */ PhysAddr = (SK_U64) pci_map_single(&pAC->PciDev, pMessage->data, pMessage->len, PCI_DMA_TODEVICE); 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; /* after releasing the lock, the skb may be immidiately freed */ if (pTxPort->TxdRingFree != 0) { spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); return (BytesSend); } else { /* ring full: set tbusy on return */ spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); return (0); }} /* XmitFrame *//***************************************************************************** * * FreeTxDescriptors - release descriptors from the descriptor ring * * Description: * This function releases descriptors from a transmit ring if they * have been sent by the BMU. * If a descriptors is sent, it can be freed and the message can * be freed, too. * The SOFTWARE controllable bit is used to prevent running around a * completely free ring for ever. If this bit is no set in the * frame (by XmitFrame), this frame has never been sent or is * already freed. * The Tx descriptor ring lock must be held while calling this function !!! * * Returns: * none */static void FreeTxDescriptors(SK_AC *pAC, /* pointer to the adapter context */TX_PORT *pTxPort) /* pointer to destination port structure */{TXD *pTxd; /* pointer to the checked descriptor */TXD *pNewTail; /* pointer to 'end' of the ring */SK_U32 Control; /* TBControl field of descriptor */SK_U64 PhysAddr; /* address of DMA mapping */ pNewTail = pTxPort->pTxdRingTail; pTxd = pNewTail; /* * loop forever; exits if TX_CTRL_SOFTWARE bit not set in start frame * or TX_CTRL_OWN_BMU bit set in any frame */ while (1) { Control = pTxd->TBControl; if ((Control & TX_CTRL_SOFTWARE) == 0) { /* * software controllable bit is set in first * fragment when given to BMU. Not set means that * this fragment was never sent or is already * freed ( -> ring completely free now). */ pTxPort->pTxdRingTail = pTxd; netif_start_queue(pAC->dev); return; } if (Control & TX_CTRL_OWN_BMU) { pTxPort->pTxdRingTail = pTxd; if (pTxPort->TxdRingFree > 0) { netif_start_queue(pAC->dev); } return; } /* release the DMA mapping */ PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32; PhysAddr |= (SK_U64) pTxd->VDataLow; pci_unmap_single(&pAC->PciDev, PhysAddr, pTxd->pMBuf->len, PCI_DMA_TODEVICE); /* free message */ DEV_KFREE_SKB_ANY(pTxd->pMBuf); pTxPort->TxdRingFree++; pTxd->TBControl &= ~TX_CTRL_SOFTWARE; pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */ } /* while(forever) */} /* FreeTxDescriptors *//***************************************************************************** * * FillRxRing - fill the receive ring with valid descriptors * * Description: * This function fills the receive ring descriptors with data * segments and makes them valid for the BMU. * The active ring is filled completely, if possible. * The non-active ring is filled only partial to save memory. * * Description of rx ring structure: * head - points to the descriptor which will be used next by the BMU * tail - points to the next descriptor to give to the BMU * * Returns: N/A */static void FillRxRing(SK_AC *pAC, /* pointer to the adapter context */RX_PORT *pRxPort) /* ptr to port struct for which the ring should be filled */{unsigned int Flags; spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags); while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) { if(!FillRxDescriptor(pAC, pRxPort)) break; } spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags);} /* FillRxRing *//***************************************************************************** * * FillRxDescriptor - fill one buffer into the receive ring * * Description: * The function allocates a new receive buffer and * puts it into the next descriptor. * * Returns: * SK_TRUE - a buffer was added to the ring * SK_FALSE - a buffer could not be added */static SK_BOOL FillRxDescriptor(SK_AC *pAC, /* pointer to the adapter context struct */RX_PORT *pRxPort) /* ptr to port struct of ring to fill */{struct sk_buff *pMsgBlock; /* pointer to a new message block */RXD *pRxd; /* the rxd to fill */SK_U16 Length; /* data fragment length */SK_U64 PhysAddr; /* physical address of a rx buffer */ pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC); if (pMsgBlock == NULL) { SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, ("%s: Allocation of rx buffer failed !\n", pAC->dev->name)); SK_PNMI_CNT_NO_RX_BUF(pAC); return(SK_FALSE); } skb_reserve(pMsgBlock, 2); /* to align IP frames */ /* skb allocated ok, so add buffer */ pRxd = pRxPort->pRxdRingTail; pRxPort->pRxdRingTail = pRxd->pNextRxd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -