📄 if_sn.c
字号:
** snStartOutput - start pending output** This routine removes mbuf chains from the driver queue and attempts to* set up a SONIC transmit descriptor for each chain. The transmit descriptors* are fed to the SONIC and subsequently transmitted onto the media.*/LOCAL void snStartOutput (unit) int unit; { DRV_CTRL *pDrvCtrl; MBUF *pMbuf; MBUF *pMbufTemp; TX_DESC *pTXD; int len; int adj_len; int fragIndex; int nUseableFrags; char *m_data; u_long temp; pDrvCtrl = & drvCtrl [unit]; /* Loop as long as our incoming queue is not empty */ while (pDrvCtrl->sn_if.if_snd.ifq_head != NULL) { IF_DEQUEUE (&pDrvCtrl->sn_if.if_snd, pMbuf); /* call output hook if any */ /* etherOutputHookRtn not supported. * This would require copying mbufs to contiguous buf. * if ((etherOutputHookRtn != NULL) && * (* etherOutputHookRtn) (&pDrvCtrl->sn_if, buf, len)) * continue; */ /* Calculate length & number of fragments */#ifdef SN_DEBUG if (SN_DEBUG_TRACE) { static char buf[ETHERMTU]; struct ether_header *pPktHdr; /* ptr to packet header */ FAST char *p = buf; FAST struct mbuf *m = pMbuf; for (; m != NULL; p += m->m_len, m = m->m_next) bcopy (mtod (m, char *), p, m->m_len); pPktHdr = (struct ether_header *)&buf; logMsg ("sn: Tx: packet type 0x%x from %s", pPktHdr->ether_type, (int)ether_sprintf (&pPktHdr->ether_shost), 0, 0, 0, 0); logMsg (" to %s\n", (int)ether_sprintf (&pPktHdr->ether_dhost), 0, 0, 0, 0, 0); }#endif pMbufTemp = pMbuf; len = nUseableFrags = 0; while (pMbufTemp != NULL) /* while valid pointer */ { if (pMbufTemp->m_len) /* only count non-zero length frags */ { len += pMbufTemp->m_len; /* add length of this fragment */ nUseableFrags++; /* bump fragment counter */ } pMbufTemp = pMbufTemp->m_next; /* advance to next mbuf fragment */ } /* Bail out if too many frags */ if (nUseableFrags >= MAX_TX_FRAGS) { logMsg ("sn: Tx: too many mbuf fragments\n",0,0,0,0,0,0); m_freem (pMbuf); /* packet is thrown away */ pDrvCtrl->sn_if.if_opackets--; /* correct the stats */ pDrvCtrl->sn_if.if_oerrors++; continue; } /* See if next transmit descriptor is available */ pTXD = pDrvCtrl->pTXDFree; if (pTXD->flag) /* still in use */ { m_freem (pMbuf); /* packet is thrown away */ pDrvCtrl->sn_if.if_opackets--; /* correct the stats */ pDrvCtrl->sn_if.if_oerrors++;#ifdef SN_DEBUG if (SN_DEBUG_TX) logMsg ("sn: Tx, no descriptors", 0, 0, 0, 0, 0, 0);#endif /* SN_DEBUG */ break; } /* Mark this descriptor as "in use" */ pTXD->flag = TRUE; pTXD->status = 0; /* remember the mbuf associated with this packet */ pTXD->pMbuf = pMbuf; /* Ensure we send a minimum sized packet */ adj_len = max (ETHERSMALL, len); /* Build a transmit descriptor. * Loop thru each fragment in the mbuf chain and stuff our info. */ for ( fragIndex = 0, pMbufTemp = pMbuf; pMbufTemp != NULL; /* while valid mbuf pointer */ pMbufTemp = pMbufTemp->m_next /* advance to next mbuf frag */ ) { /* ignore zero-length mbufs */ if ( pMbufTemp->m_len == 0 ) continue; m_data = mtod(pMbufTemp, char *); /* get pointer to mbuf data */ /* ensure data is flushed */ CACHE_USER_FLUSH (m_data, pMbufTemp->m_len);#ifdef notdef /* This is what we should be able to do... */ temp = (u_long) CACHE_DRV_VIRT_TO_PHYS (&cacheUserFuncs, m_data);#else temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (m_data);#endif pTXD->frag [fragIndex].frag_ptr0 = (u_long) temp & UMASK; pTXD->frag [fragIndex].frag_ptr1 = (u_long) temp >> 16; pTXD->frag [fragIndex].frag_size = pMbufTemp->m_len; fragIndex++; } pTXD->pkt_size = adj_len; /* set packet length */ pTXD->frag_count = fragIndex; /* set fragment count */ if (adj_len != len) /* pad pkt size to min */ pTXD->frag [fragIndex-1].frag_size += (adj_len-len); /* copy link field to where device will expect it */ pTXD->frag [fragIndex].frag_ptr0 = (u_long) CACHE_DMA_VIRT_TO_PHYS (pTXD->pLink) | TX_EOL;#ifdef SN_DEBUG if (SN_DEBUG_TX && SN_DEBUG_VERBOSE) logMsg ("sn: Tx: pTXD=%x\n", (int)pTXD, 0, 0, 0, 0, 0);#endif /* SN_DEBUG */ /* Find previous desc in chain. (see NOTE #1) * If prev desc has been used, then get a ptr to the actual * link field within the desc, and clear the EOL bit. */ { TX_DESC *pPrevTXD; u_long *pLink; if (pTXD == pDrvCtrl->pTDA) pPrevTXD = ((TX_DESC *)((char *)pDrvCtrl->pTDA + TDA_SIZE)) - 1; else pPrevTXD = pTXD - 1; if (pPrevTXD->frag_count) { pLink = & pPrevTXD->frag [pPrevTXD->frag_count].frag_ptr0; *pLink &= ~TX_EOL; } } /* start the transmitter */ pDrvCtrl->pDev->cr = TXP; /* And finally, adjust pointer to next TXD. */ pDrvCtrl->pTXDFree = pTXD->pLink; } }#else/********************************************************************************* snStartOutput - start pending output** This routine removes mbuf chains from the driver queue and attempts to* set up a SONIC transmit descriptor for each chain. The transmit descriptors* are fed to the SONIC and subsequently transmitted onto the media.*/LOCAL void snStartOutput ( DRV_CTRL * pDrvCtrl ) { MBUF *pMbuf; MBUF *pMbufTemp; TX_DESC *pTXD; int len; int adj_len; int fragIndex; int nUseableFrags; char *mbuf_data; u_long temp; /* Loop as long as our incoming queue is not empty */ while (pDrvCtrl->sn_ac.ac_if.if_snd.ifq_head != NULL) { IF_DEQUEUE (&pDrvCtrl->sn_if.if_snd, pMbuf); /* call output hook if any */ /* etherOutputHookRtn not supported. * This would require copying mbufs to contiguous buf. * if ((etherOutputHookRtn != NULL) && * (* etherOutputHookRtn) (&pDrvCtrl->sn_if, buf, len)) * continue; */ /* Calculate length & number of fragments */#ifdef SN_DEBUG if (SN_DEBUG_TRACE) { static char buf[ETHERMTU]; struct ether_header *pPktHdr; /* ptr to packet header */ FAST char *p = buf; FAST struct mbuf *m = pMbuf; for (; m != NULL; p += m->m_len, m = m->m_next) bcopy (mtod (m, char *), p, m->m_len); pPktHdr = (struct ether_header *)&buf; logMsg ("sn: Tx: packet type 0x%x from %s", pPktHdr->ether_type, (int)ether_sprintf (&pPktHdr->ether_shost), 0, 0, 0, 0); logMsg (" to %s\n", (int)ether_sprintf (&pPktHdr->ether_dhost), 0, 0, 0, 0, 0); }#endif pMbufTemp = pMbuf; len = nUseableFrags = 0; while (pMbufTemp != NULL) /* while valid pointer */ { if (pMbufTemp->m_len) /* only count non-zero length frags */ { len += pMbufTemp->m_len; /* add length of this fragment */ nUseableFrags++; /* bump fragment counter */ } pMbufTemp = pMbufTemp->m_next; /* advance to next mbuf fragment */ } /* Pull up the mbuf, if too many frags */ if (nUseableFrags >= MAX_TX_FRAGS) { pMbufTemp = pMbuf; pMbuf = m_pullup (pMbufTemp, len); m_freem (pMbufTemp); if (pMbuf == NULL) continue; } /* See if next transmit descriptor is available */ pTXD = pDrvCtrl->pTXDFree; if (pTXD->flag) /* still in use */ { m_freem (pMbuf); /* packet is thrown away */ pDrvCtrl->sn_if.if_oerrors++;#ifdef SN_DEBUG if (SN_DEBUG_TX) logMsg ("sn: Tx, no descriptors", 0, 0, 0, 0, 0, 0);#endif /* SN_DEBUG */ break; } /* Mark this descriptor as "in use" */ pTXD->flag = TRUE; pTXD->status = 0; /* remember the mbuf associated with this packet */ pTXD->pMbuf = pMbuf; /* Ensure we send a minimum sized packet */ adj_len = max (ETHERSMALL, len); /* Build a transmit descriptor. * Loop thru each fragment in the mbuf chain and stuff our info. */ fragIndex = 0; for (pMbufTemp = pMbuf; pMbufTemp != NULL; pMbufTemp = pMbufTemp->m_next) { /* ignore zero-length mbufs */ if ( pMbufTemp->m_len == 0 ) continue; mbuf_data = mtod(pMbufTemp, char *); /* get pointer to mbuf data */ /* ensure data is flushed */ CACHE_USER_FLUSH (mbuf_data, pMbufTemp->m_len);#ifdef notdef /* This is what we should be able to do... */ temp = (u_long) CACHE_DRV_VIRT_TO_PHYS (&cacheUserFuncs, mbuf_data);#else temp = (u_long) CACHE_DMA_VIRT_TO_PHYS (mbuf_data);#endif pTXD->frag [fragIndex].frag_ptr0 = (u_long) temp & UMASK; pTXD->frag [fragIndex].frag_ptr1 = (u_long) temp >> 16; pTXD->frag [fragIndex].frag_size = pMbufTemp->m_len; fragIndex++; } pTXD->pkt_size = adj_len; /* set packet length */ pTXD->frag_count = fragIndex; /* set fragment count */ if (adj_len != len) /* pad pkt size to min */ pTXD->frag [fragIndex-1].frag_size += (adj_len-len); /* copy link field to where device will expect it */ pTXD->frag [fragIndex].frag_ptr0 = (u_long) CACHE_DMA_VIRT_TO_PHYS (pTXD->pLink) | TX_EOL;#ifdef SN_DEBUG if (SN_DEBUG_TX && SN_DEBUG_VERBOSE) logMsg ("sn: Tx: pTXD=%x\n", (int)pTXD, 0, 0, 0, 0, 0);#endif /* SN_DEBUG */ /* Find previous desc in chain. (see NOTE #1) * If prev desc has been used, then get a ptr to the actual * link field within the desc, and clear the EOL bit. */ { TX_DESC *pPrevTXD; u_long *pLink; if (pTXD == pDrvCtrl->pTDA) pPrevTXD = ((TX_DESC *)((char *)pDrvCtrl->pTDA + TDA_SIZE)) - 1; else pPrevTXD = pTXD - 1; if (pPrevTXD->frag_count) { pLink = & pPrevTXD->frag [pPrevTXD->frag_count].frag_ptr0; *pLink &= ~TX_EOL; } } pDrvCtrl->sn_if.if_opackets++; /* bump the statistic */ /* start the transmitter */ pDrvCtrl->pDev->cr = TXP; /* And finally, adjust pointer to next TXD. */ pDrvCtrl->pTXDFree = pTXD->pLink; } }#endif /* BSD43_DRIVER *//********************************************************************************* snTxReclaim - reclaims transmit descriptors that the device has serviced**/LOCAL void snTxReclaim (pDrvCtrl) DRV_CTRL *pDrvCtrl; { TX_DESC *pTXD; int unit; unit = pDrvCtrl->sn_if.if_unit; /* get our unit number */ pTXD = pDrvCtrl->pTXDReclaim; /* get ptr to desc */ CACHE_DMA_INVALIDATE (&pTXD->status, sizeof (u_long)); /* The device is deemed to be done with the descriptor if the * the descriptor had been flagged as "given" to the device, * and the descriptor status field is set. */ while (pTXD->flag && pTXD->status) { if ( pTXD->status & PTX ) { /* Packet was transmitted successfully. Extract mbuf ptr and * free the mbufs. */ m_freem (pTXD->pMbuf); /* done with the desc, so clean it up */ pTXD->flag = FALSE; pTXD->status = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -