📄 sky2.c
字号:
*/ if (SkGeInitPort(pAC, IoC, Port)) { if (Port == 0) { printk("%s: SkGeInitPort A failed.\n",pAC->dev[0]->name); } else { printk("%s: SkGeInitPort B failed.\n",pAC->dev[1]->name); } } if (IS_GMAC(pAC)) { /* disable Rx GMAC FIFO Flush Mode */ SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8) GMF_RX_F_FL_OFF); } /* ** Initialize the MC addresses */ SkAddrMcUpdate(pAC,IoC, Port); SkMacRxTxEnable(pAC, IoC,Port); SkGeRxCsum(pAC, IoC, Port, SK_TRUE); GET_RX_LE(pLE, &pAC->RxPort[Port].RxLET); RXLE_SET_STACS1(pLE, pAC->CsOfs1); RXLE_SET_STACS2(pLE, pAC->CsOfs2); RXLE_SET_CTRL(pLE, 0); RXLE_SET_OPC(pLE, OP_TCPSTART | HW_OWNER); FLUSH_OPC(pLE); if (Port == 0) { PrefetchReg=Y2_PREF_Q_ADDR(Q_R1,PREF_UNIT_PUT_IDX_REG); } else { PrefetchReg=Y2_PREF_Q_ADDR(Q_R2,PREF_UNIT_PUT_IDX_REG); } DWord = GET_PUT_IDX(&pAC->RxPort[Port].RxLET); SK_OUT32(IoC, PrefetchReg, DWord); UPDATE_HWPUT_IDX(&pAC->RxPort[Port].RxLET); pAC->GIni.GP[Port].PState = SK_PRT_RUN; SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG, ("<== SkY2PortStart()\n"));}#ifdef USE_ASF_DASH_FW/* LC Packet fields. */#define SK_LLC_DSAP 0x00#define SK_LLC_SSAP 0x00#define SK_LLC_CTRL 0xE3 /* LLC Test*/#define SK_LLC_INDICATOR0 0x00#define SK_LLC_INDICATOR1 0x00 #define SK_LLC_INDICATOR2 0x00 #define SK_LLC_INDICATOR3 0x00 #define SK_LLC_INDICATOR4 0x00 #define SK_LLC_INDICATOR5 0x00 #define SK_LLC_INDICATOR6 0x00 #define SK_LLC_PACKET_VERSION 0#define SK_LLC_MIN_PACKET_SIZE 34#define SK_LLC_MAX_PACKET_SIZE 64#define SK_LLC_PACKET_DATA_LEN (SK_LLC_MAX_PACKET_SIZE - SK_LLC_MIN_PACKET_SIZE - 4)/* LLC packet. Length: SK_LLC_MAX_PACKET_SIZE (64) bytes. */typedef struct s_LLCPacket { SK_U8 DstAddr[SK_MAC_ADDR_LEN]; SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; SK_U8 TypeLen[2]; SK_U8 DSap; SK_U8 SSap; SK_U8 Ctrl; SK_U8 Indicator[7]; SK_U8 LLCPacketType[2]; SK_U8 Align1[2]; SK_U8 Random[4]; SK_U8 LLCPacketVersion[2]; /* LLC Packet version. */ SK_U8 Data[SK_LLC_PACKET_DATA_LEN]; SK_U32 CheckSum;} SK_LLC_PACKET;#ifdef SK_LITTLE_ENDIAN#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \ SK_U8 *_Addr = (SK_U8*)(Addr); \ SK_U16 _Val = (SK_U16)(Val); \ *_Addr++ = (SK_U8)(_Val >> 8); \ *_Addr = (SK_U8)(_Val & 0xFF); \}#endif#ifdef SK_BIG_ENDIAN#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))#endif/***************************************************************************** * * SkDrvAllocLLCMbuf - allocate an LLC mbuf * * Description: * This routine returns an LLC mbuf or NULL. The LLC Mbuf structure * is embedded into a socket buff data area. * * Context: * runtime * * Returns: * NULL or pointer to Mbuf. */SK_MBUF *SkDrvAllocLLCMbuf(SK_AC *pAC, /* pointer to adapter context */SK_IOC IoC, /* the IO-context */unsigned BufferSize) /* size of the requested buffer */{SK_MBUF *pLLCMbuf; /* pointer to a new LLC-mbuf structure */struct sk_buff *pMsgBlock; /* pointer to a new message block */ pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC); if (pMsgBlock == NULL) { return (NULL); } pLLCMbuf = (SK_MBUF*) pMsgBlock->data; skb_reserve(pMsgBlock, sizeof(SK_MBUF)); pLLCMbuf->pNext = NULL; pLLCMbuf->pOs = pMsgBlock; pLLCMbuf->pData = pMsgBlock->data; /* Data buffer. */ pLLCMbuf->Size = BufferSize; /* Data buffer size. */ pLLCMbuf->Length = 0; /* Length of packet (<= Size). */ return (pLLCMbuf);} /* SkDrvAllocLLCMbuf *//****************************************************************************** * * SkLLCBuildPacket - build an LLC packet * * Description: * This routine sets up an LLC packet. * * Context: * runtime, pageable? * * Returns: * NULL or pointer to LLC mbuf */SK_MBUF *SkLLCBuildPacket(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 PortNumber, /* Sending port */SK_U16 PacketType, /* Packet type */SK_MAC_ADDR *SrcAddr, /* Source address */SK_MAC_ADDR *DestAddr) /* Destination address */{ int i; SK_U16 Length; SK_MBUF *pMb; SK_LLC_PACKET *pPacket;#ifdef DEBUG SK_U8 CheckSrc = 0; SK_U8 CheckDest = 0; for (i = 0; i < SK_MAC_ADDR_LEN; ++i) { CheckSrc |= SrcAddr->a[i]; CheckDest |= DestAddr->a[i]; } if ((CheckSrc == 0) || (CheckDest == 0)) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR, ("SkBuildLLCPacket: Invalid %s%saddr.\n", (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : ""))); }#endif if ((pMb = SkDrvAllocLLCMbuf(pAC, IoC, SK_LLC_MAX_PACKET_SIZE)) != NULL) { pPacket = (SK_LLC_PACKET*)pMb->pData; for (i = 0; i < SK_MAC_ADDR_LEN; i++) { pPacket->DstAddr[i] = DestAddr->a[i]; pPacket->SrcAddr[i] = SrcAddr->a[i]; } pPacket->DSap = SK_LLC_DSAP; pPacket->SSap = SK_LLC_SSAP; pPacket->Ctrl = SK_LLC_CTRL; pPacket->Indicator[0] = SK_LLC_INDICATOR0; pPacket->Indicator[1] = SK_LLC_INDICATOR1; pPacket->Indicator[2] = SK_LLC_INDICATOR2; pPacket->Indicator[3] = SK_LLC_INDICATOR3; pPacket->Indicator[4] = SK_LLC_INDICATOR4; pPacket->Indicator[5] = SK_LLC_INDICATOR5; pPacket->Indicator[6] = SK_LLC_INDICATOR6; pPacket->LLCPacketType[0] = 0x00; pPacket->LLCPacketType[1] = 0x00; // SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->LLCPacketType[0]); pPacket->Align1[0] = 0x00; pPacket->Align1[1] = 0x00; for (i = 0; i < 4; i++) { pPacket->Random[i] = 0x00; } pPacket->LLCPacketVersion[0] = 0x00; pPacket->LLCPacketVersion[1] = 0x00; SK_U16_TO_NETWORK_ORDER( SK_LLC_PACKET_VERSION, &pPacket->LLCPacketVersion[0]); for (i = 0; i < SK_LLC_PACKET_DATA_LEN; i++) { pPacket->Data[i] = 0x00; } Length = SK_LLC_MAX_PACKET_SIZE; /* Or smaller. */ pMb->Length = Length; pMb->PortIdx = PortNumber; Length -= 14; SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]); pPacket->CheckSum = 0xFFFFFFFF; /* Inverse of 0 */#if 0 if (PacketType == SK_PACKET_ALIVE) { pAC->Rlmt.Port[PortNumber].TxHelloCts++; }#endif } return (pMb);} /* SkBuildLLCPacket */void SkSendLLCPacket(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 PortNumber /* Sending port */){ SK_U16 PacketType = 0x02; SK_MAC_ADDR SkLLCMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}}; SK_MBUF *pLLCMbuf; struct sk_buff *pMsg; pLLCMbuf = SkLLCBuildPacket(pAC, IoC, PortNumber, PacketType, &pAC->Addr.Port[PortNumber].CurrentMacAddress, &SkLLCMcAddr); pMsg = (struct sk_buff*) pLLCMbuf->pOs; skb_put(pMsg, pLLCMbuf->Length); skb_shinfo(pMsg)->nr_frags = (2*MAX_SKB_FRAGS) + PortNumber; SkY2Xmit(pMsg, pAC->dev[PortNumber]); // SkY2Xmit needs device} /* SkSendLLCPacket */#endif/****************************************************************************** * * Local Functions * *****************************************************************************//***************************************************************************** * * InitPacketQueues - initialize SW settings of packet queues * * Description: * This function will initialize the packet queues for a port. * * Returns: N/A */static void InitPacketQueues(SK_AC *pAC, /* pointer to adapter control context */int Port) /* index of port to be initialized */{ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, ("==> InitPacketQueues(Port %c)\n", 'A' + Port)); pAC->RxPort[Port].RxQ_working.pHead = NULL; pAC->RxPort[Port].RxQ_working.pTail = NULL; spin_lock_init(&pAC->RxPort[Port].RxQ_working.QueueLock); pAC->RxPort[Port].RxQ_waiting.pHead = NULL; pAC->RxPort[Port].RxQ_waiting.pTail = NULL; spin_lock_init(&pAC->RxPort[Port].RxQ_waiting.QueueLock); pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.pHead = NULL; pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.pTail = NULL; spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.QueueLock); pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.pHead = NULL; pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.pTail = NULL; spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.QueueLock); pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.pHead = NULL; pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.pTail = NULL; spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.QueueLock); #ifdef USE_SYNC_TX_QUEUE pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.pHead = NULL; pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.pTail = NULL; spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.QueueLock); pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.pHead = NULL; pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.pTail = NULL; spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.QueueLock);#endif SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT, ("<== InitPacketQueues(Port %c)\n", 'A' + Port));} /* InitPacketQueues *//***************************************************************************** * * GiveTxBufferToHw - commits a previously allocated DMA area to HW * * Description: * This functions gives transmit buffers to HW. If no list elements * are available the buffers will be queued. * * Notes: * This function can run only once in a system at one time. * * Returns: N/A */static void GiveTxBufferToHw(SK_AC *pAC, /* pointer to adapter control context */SK_IOC IoC, /* I/O control context (address of registers) */int Port) /* port index for which the buffer is used */{ SK_HWLE *pLE; SK_PACKET *pSkPacket; SK_FRAG *pFrag; SK_PKT_QUEUE *pWorkQueue; /* corresponding TX queue */ SK_PKT_QUEUE *pWaitQueue; SK_LE_TABLE *pLETab; /* corresponding LETable */ SK_BOOL SetOpcodePacketFlag; SK_U32 HighAddress; SK_U32 LowAddress; SK_U16 TcpSumStart = 0; SK_U16 TcpSumWrite = 0; SK_U8 OpCode; SK_U8 Ctrl; unsigned long Flags; unsigned long LockFlag; int Protocol;#ifdef NETIF_F_TSO SK_U16 Mss; int TcpOptLen; int IpTcpLen;#endif SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("==> GiveTxBufferToHw\n")); if (HW_FEATURE(pAC, HWF_WA_DEV_510)) { SK_OUT32(pAC->IoBase, TBMU_TEST, TBMU_TEST_BMU_TX_CHK_AUTO_OFF); } if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting))) { return; } spin_lock_irqsave(&pAC->TxQueueLock, LockFlag); /* ** Initialize queue settings */ pWorkQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working); pWaitQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting); pLETab = &(pAC->TxPort[Port][TX_PRIO_LOW].TxALET); POP_FIRST_PKT_FROM_QUEUE(pWaitQueue, pSkPacket); while (pSkPacket != NULL) { SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("\tWe have a packet to send %p\n", pSkPacket)); /* ** the first frag of a packet gets opcode OP_PACKET */ SetOpcodePacketFlag = SK_TRUE; pFrag = pSkPacket->pFrag; /* ** fill list elements with data from fragments */ while (pFrag != NULL) { SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("\tGet LE\n"));#ifdef NETIF_F_TSO#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17) Mss = skb_shinfo(pSkPacket->pMBuf)->gso_size;#else Mss = skb_shinfo(pSkPacket->pMBuf)->tso_size;#endif if (Mss) {#ifdef SK_EXTREME if (!HW_IS_EXT_LE_FORMAT(pAC)) {#endif#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,21) struct iphdr *iph = ip_hdr(pSkPacket->pMBuf); struct tcphdr *tcph = tcp_hdr(pSkPacket->pMBuf); TcpOptLen = ((tcph->doff - 5) * 4); IpTcpLen = ((iph->ihl * 4) + sizeof(struct tcphdr));#else TcpOptLen = ((pSkPacket->pMBuf->h.th->doff - 5) * 4); IpTcpLen = ((pSkPacket->pMBuf->nh.iph->ihl * 4) + sizeof(struct tcphdr));#endif Mss += (TcpOptLen + IpTcpLen + C_LEN_ETHERMAC_HEADER);#ifdef SK_EXTREME }#endif } if (pLETab->Bmu.RxTx.MssValue != Mss) { pLETab->Bmu.RxTx.MssValue = Mss; /* Take a new LE for TSO from the table */ GET_TX_LE(pLE, pLETab);#ifdef SK_EXTREME if (HW_IS_EXT_LE_FORMAT(pAC)) { TXLE_SET_OPC(pLE, OP_MSS | HW_OWNER); TXLE_SET_MSSVAL(pLE, pLETab->Bmu.RxTx.MssValue); } else {#endif TXLE_SET_OPC(pLE, OP_LRGLEN | HW_OWNER); TXLE_SET_LSLEN(pLE, pLETab->Bmu.RxTx.MssValue);#ifdef SK_EXTREME }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -