📄 sn83932end.c
字号:
pTXD->frag [count].frag_size = totalLength; count++; /* Record the buffer's free routine for later invocation */ pDrvCtrl->freeBuf[pTXD->number].pfreeRtn = (FUNCPTR)netClFree; pDrvCtrl->freeBuf[pTXD->number].pSpare1= pDrvCtrl->endData.pNetPool; pDrvCtrl->freeBuf[pTXD->number].pSpare2=pBuf; } else /* * loop through the chain until last mblk is pointing to NULL, * consider clusters only if their length is positive number * and if not, * get the next mblk */ { pChunk =pMblk; for(count=0;pChunk != NULL;) { /* if all the data is contained in the first mblk */ if((pChunk->mBlkHdr.mLen == pMblk->mBlkPktHdr.len) && pChunk==pMblk) No_Mblk=TRUE; if (pChunk->mBlkHdr.mLen <= 0) { pChunk =pChunk->mBlkHdr.mNext; continue; } /* * Check if frame contains a broadcast/multicast destination * address. Update appropriate MIB variable accordingly. */ if ((count == 0) && (pChunk->mBlkHdr.mData[5] & 0x01)) END_M2_OUTNUCAST (&pDrvCtrl->endData); else END_M2_OUTUCAST (&pDrvCtrl->endData); /* ensure data is flushed */ CACHE_USER_FLUSH (pChunk->mBlkHdr.mData,pChunk->mBlkHdr.mLen); /* * set the data pointers and the correponding size of * each fragment */ addr = (u_long) CACHE_DMA_VIRT_TO_PHYS (pChunk->mBlkHdr.mData); pTXD->frag [count].frag_ptr0 = (u_long) addr & UMASK; pTXD->frag [count].frag_ptr1 = (u_long) addr >> 16; pTXD->frag [count].frag_size = pChunk->mBlkHdr.mLen; /* keep track of total packet length */ totalLength += pChunk->mBlkHdr.mLen; if(No_Mblk) { count=1; break; } /* loop through */ pChunk =pChunk->mBlkHdr.mNext; count++; } /* Record the buffer's free routine for later invocation */ pDrvCtrl->freeBuf[pTXD->number].pfreeRtn = (FUNCPTR)netMblkClChainFree; pDrvCtrl->freeBuf[pTXD->number].pSpare1= pMblk; pDrvCtrl->freeBuf[pTXD->number].pSpare2=NULL; } /* Set total packet size & fragment count */ pTXD->pkt_size = max (ETHERSMALL, totalLength); /* set packet size */ pTXD->frag_count = count; /* set fragment count */ if (totalLength < ETHERSMALL) { pTXD->frag[count-1].frag_size += (ETHERSMALL - totalLength); totalLength = ETHERSMALL; } /* Update MIB variable accordingly */ END_M2_OUTOCTETS (&pDrvCtrl->endData, totalLength); /* Reset the actual pLink field of the last transmitted descriptor */ pDrvCtrl->pTXDLast->frag[pDrvCtrl->pTXDLast->frag_count].frag_ptr0 &= ~TX_EOL; /* copy link field to where device will expect it & set the EOL bit */ pTXD->frag [count].frag_ptr0 = (u_long) CACHE_DMA_VIRT_TO_PHYS (pTXD->pLink) | TX_EOL; /* Adjust pointer to next TXD. */ pDrvCtrl->pTXDFree = (TX_DESC *)((u_long)pTXD->pLink & ~TX_EOL); pDrvCtrl->pTXDLast = pTXD; /* start the transmitter but make sure the load-cam bit is not set */ while (pDrvCtrl->pDev->cr & LCAM) continue; pDrvCtrl->pDev->cr = TXP; /* Release Transmit semaphore */ END_TX_SEM_GIVE (&pDrvCtrl->endData); return OK; }/********************************************************************************* sn83932PollSend - the driver send routine** This routine is valid only when called while the device is in Polling* mode. The NetBuffer passed in must not be in a chained configuration.* If either of these rules are broken, the driver returns EINVAL.* The transmit descriptor is filled with the relevant data and the* transmitter started. The transmit descriptor status is then polled for* completion. The transmit descriptor is cleared and the data buffer* is freed.* Note: The same descriptor is used for each invocation of this function.** RETURNS: OK,* EINVAL - invalid usage* EAGAIN - error in transmission or busy* NOMANUAL*/LOCAL STATUS sn83932PollSend ( DRV_CTRL * pDrvCtrl, M_BLK_ID pMblk ) { TX_DESC *pTXD; u_long addr; int retval; volatile u_short stat = 0; /* Sanity Check */ if (pDrvCtrl == NULL) return EINVAL; /* Buffer chaining not supported in Poll Mode */ if (!(pDrvCtrl->flags & SN_POLLING) || (pMblk->mBlkHdr.mNext!=NULL)) return (EINVAL); if (pDrvCtrl->txBlocked) return (END_ERR_BLOCK); /* See if transmit descriptor is available */ pTXD = pDrvCtrl->pTXDFree; if (pTXD->flag == IN_USE) {/* No Room */ return (EAGAIN); } /* Mark the descriptor as "in use" to reserve it */ pTXD->flag = IN_USE; pTXD->status = 0; /* ensure data is flushed */ CACHE_USER_FLUSH (pMblk->mBlkHdr.mData, pMblk->mBlkHdr.mLen); /* Set up descriptor */ pTXD->pkt_size = max (ETHERSMALL, pMblk->mBlkHdr.mLen); pTXD->frag_count = 1; /* Assign to a fragment */ addr = (u_long) CACHE_DMA_VIRT_TO_PHYS (pMblk->mBlkHdr.mData); pTXD->frag [0].frag_ptr0 = (u_long) addr & UMASK; pTXD->frag [0].frag_ptr1 = (u_long) addr >> 16; pTXD->frag [0].frag_size = pTXD->pkt_size; /* copy link field to where device will expect it & set the EOL bit */ pTXD->frag [pTXD->frag_count].frag_ptr0 = (u_long) CACHE_DMA_VIRT_TO_PHYS (pTXD->pLink) | TX_EOL; /* Set the transmitter on */ pDrvCtrl->pDev->cr = TXP; /* Poll for transmit completion */ do { CACHE_DMA_INVALIDATE (&pTXD->status, sizeof (pTXD->status)); stat = pTXD->status; }while (!stat); /* Update MIB variables */ END_M2_OUTOCTETS (&pDrvCtrl->endData, pTXD->pkt_size); /* Determine if unicast or not */ if (pMblk->mBlkHdr.mData[5] & 0x01) END_M2_OUTNUCAST (&pDrvCtrl->endData); else END_M2_OUTUCAST (&pDrvCtrl->endData); /* Check for successful transmission */ if (stat & PTX) retval = OK; /* Successful Send */ else { /* Error in Sending */ END_M2_OUTERRORS (&pDrvCtrl->endData); retval = EAGAIN; } /* Free this Descriptor for another poll request */ pTXD->flag = NOT_IN_USE; pTXD->status = 0; /* Adjust pointer to next TXD. */ pDrvCtrl->pTXDFree = (TX_DESC *)((u_long)pTXD->pLink & ~TX_EOL); pDrvCtrl->pTXDLast = pTXD; pDrvCtrl->pTXDReclaim = pDrvCtrl->pTXDFree; return (retval); }/******************************************************************************* snTxReclaim - reclaims transmit descriptors that the device has serviced** - Only valid if device is not in Polling Mode -**/LOCAL void snTxReclaim ( DRV_CTRL *pDrvCtrl, int maxReclaims ) { TX_DESC *pTXD; int intLevel; int numReclaims=0; /* No business here if we're in Poll Mode */ if (pDrvCtrl->flags & SN_POLLING) return; /* Check if someone else is in the midst of reclaiming */ if (pDrvCtrl->flags & SN_RECLAIMING) { SN_LOGMSG("someone else is busy reclaiming\n",0,0,0,0,0,0); return; } /* Close reclaiming to all others */ pDrvCtrl->flags |= SN_RECLAIMING; 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. */ /* * Check if descriptor was used status may return 0 if xmit error * occurred */ while ((pTXD->flag == IN_USE) && ((pTXD->status & PTX) || !(pDrvCtrl->pDev->cr & TXP))) { if ( pTXD->status & PTX ) { /* Packet was transmitted successfully. * * Release the data buffer(s) */ /* Release buffer associated with each fragment in the TXD */ (pDrvCtrl->freeBuf[pTXD->number].pfreeRtn) (pDrvCtrl->freeBuf[pTXD->number].pSpare1, pDrvCtrl->freeBuf[pTXD->number].pSpare2); /* done with the desc, so clean it up */ pTXD->flag = NOT_IN_USE; pTXD->status = 0; } else { /* ERROR! */ END_M2_OUTERRORS (&pDrvCtrl->endData); intLevel = intLock(); pTXD->status = 0; /* Make sure LCAM bit is not set or we'll lock up */ while (pDrvCtrl->pDev->cr & LCAM) continue; pDrvCtrl->pDev->cr = TXP; /* restart transmitter */ intUnlock (intLevel); /* Get out now! */ break; }/* ERROR */ /* Advance to the next TXD. */ pTXD = (TX_DESC *)((u_long)pTXD->pLink & ~TX_EOL); /* Update the reclaim pointer for next time. */ pDrvCtrl->pTXDReclaim = pTXD; /* Check if we've taken too long */ if (numReclaims++ == maxReclaims) break; /* invalidate the cache for this TXD */ CACHE_DMA_INVALIDATE (&pTXD->status, sizeof (pTXD->status)); } /* while */ pDrvCtrl->flags &= ~SN_RECLAIMING; }/*============================================================================* * R E C E I V E R O U T I N E S *============================================================================*//****************************************************************************** sn83932PollRecv - Returns the next packet waiting to be processed. If no* packet exists, EAGAIN indication is returned instead.** RETURNS: OK or EAGAIN**/LOCAL STATUS sn83932PollRecv ( DRV_CTRL *pDrvCtrl, M_BLK_ID pMblk ) { /* Sanity Check */ if (pDrvCtrl == NULL || !(pDrvCtrl->flags & SN_POLLING)) return EINVAL; if (pMblk == NULL || pMblk->mBlkHdr.mData == NULL) return (EINVAL); /* Process the received packet and give it to the mux */ if (snProcessRxPkts (pDrvCtrl, 1, pMblk) == 0) return EAGAIN; else return OK; }/********************************************************************************* snProcessRxPkts - Process the received packets up to the maximum* as indicated by the supplied argument. For each recieved* indication, the packet is extracted, the appropriate MIB variables* are updated and the packet is then sent up to the Mux. This* device does not support buffer loaning and therefore is not* utilized. Once the packet is sent to the mux, the receive* descriptor pointers are adjusted appropriately.** RETURNS - Number of packets processed exclusive of errors * */ LOCAL int snProcessRxPkts ( DRV_CTRL * pDrvCtrl, /* ptr to device's control info */ int maxPackets, /* Max number of packets to process */ M_BLK_ID pMblk /* Optional net buffer for packet */ ) { END_OBJ *pEnd; /* ptr to our End structure */ RX_DESC *pRXD; /* ptr to current descriptor */ SONIC *pDev; /* ptr to the device regs */ char *pPktHdr; /* ptr to packet */ int recvLen; /* size of packet received */ int ndx; /* index into RRA desc array */ int packetCount; /* num of packets processed */ int POLL_MODE=1; /* if in Poll mode */ CL_BLK_ID pClBlk; /* cluster block pointer */ UCHAR *pCluster; /* cluster pointer */ BOOL error=FALSE; /* set in case of bad packet or out of mblks, cluster blks or cluster */ /* Note the devices's End address */ pEnd = &pDrvCtrl->endData; /* check if NOT Poll mode */ if(pMblk==NULL) POLL_MODE=0; /* If a buffer is provided, then only one packet may be processed */ if (pMblk != NULL) maxPackets = 1; #ifdef LED_DEBUG if (!(pDrvCtrl->flags & SN_POLLING)) PutLED ('r',1);#endif /* Process all received packets up to the supplied MAX */ for (packetCount = 0; packetCount < maxPackets; ) { recvLen = 0; /* get the next receive descriptor */ pRXD = pDrvCtrl->pRXDNext; CACHE_DMA_INVALIDATE (pRXD, RX_DESC_SIZ); /* Check if next slot has a packet */ if (pRXD->in_use == IN_USE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -