LOCAL STATUS wdbEndPoll ( void * pDev ) { long type; M_BLK_ID pMblk; WDB_END_PKT_DEV * pPktDev = pDev; LL_HDR_INFO llHdrInfo; int mode = WDB_COMM_MODE_POLL; END_OBJ * pEnd = PCOOKIE_TO_ENDOBJ(pPktDev->pCookie); /* Reset the size to the maximum. */ pPktDev->pInBlk->mBlkHdr.mLen = pPktDev->pInBlk->pClBlk->clSize; pPktDev->pInBlk->mBlkHdr.mData = pPktDev->pInBlk->pClBlk->clNode.pClBuf; #ifdef WDB_NPT_CAPABLE if (muxTkPollReceive (pPktDev->pCookie, pPktDev->pInBlk, NULL) == OK) #else if (muxPollReceive (pPktDev->pCookie, pPktDev->pInBlk) == OK) #endif /* WDB_NPT_CAPABLE */ { if ((pMblk = mBlkGet (pEnd->pNetPool, M_DONTWAIT, MT_DATA)) == NULL) return (ERROR); /* duplicate the received mBlk so that wdbEndInt can free it */ pMblk = netMblkDup (pPktDev->pInBlk, pMblk); #ifndef WDB_NPT_CAPABLE if (muxPacketDataGet (pPktDev->pCookie, pMblk, &llHdrInfo) == ERROR) { return (ERROR); } #else if ((pEnd->mib2Tbl.ifType == M2_ifType_ethernet_csmacd) || (pEnd->mib2Tbl.ifType == M2_ifType_iso88023_csmacd)) { if (endEtherPacketDataGet (pMblk, &llHdrInfo) == ERROR) { return (ERROR); } } else return ERROR; #endif /* WDB_NPT_CAPABLE */ type = llHdrInfo.pktType; if (wdbEndInt (pPktDev->pCookie, type, pMblk, &llHdrInfo, (void *)&mode) == TRUE) return (OK); return (ERROR); } else { return (ERROR); } }
/* * Send the received packet to END driver */ int NetdrvSendToEnd(bcm_pkt_t *pPkt) { int len; M_BLK_ID pMblk; char* pCluster = NULL; CL_BLK_ID pClBlk; END_DEVICE *pDrvCtrl = __netDriver; if (pDrvCtrl == NULL) { return ERROR; } /* Add one to our unicast data. */ END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); /* * We implicitly are loaning here, if copying is necessary this * step may be skipped, but the data must be copied before being * passed up to the protocols. */ pCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId); if (pCluster == NULL) { DRV_LOG (1, "Cannot loan!\n",1,2,3,4,5,6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRXD; } /* Grab a cluster block to marry to the cluster we received. */ if ((pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT)) == NULL) { netClFree (pDrvCtrl->end.pNetPool, (UCHAR *)pCluster); DRV_LOG (DRV_DEBUG_RX, "Out of Cluster Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRXD; } /* * OK we've got a spare, let's get an M_BLK_ID and marry it to the * one in the ring. */ if ((pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA)) == NULL) { netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk); netClFree (pDrvCtrl->end.pNetPool, (UCHAR *)pCluster); DRV_LOG (DRV_DEBUG_RX, "Out of M Blocks!\n", 1, 2, 3, 4, 5, 6); END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1); goto cleanRXD; } /* remove tag */ len = pPkt->tot_len - 8; memcpy(pCluster + 2, (unsigned char *)(&(pPkt->_pkt_data.data[0])), 12); memcpy(pCluster + 14, (unsigned char *)(&(pPkt->_pkt_data.data[16])), len-12); /* Free buffer previously stolen */ bcm_rx_free(pPkt->unit, pPkt->_pkt_data.data); /* Join the cluster to the MBlock */ netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0); netMblkClJoin (pMblk, pClBlk); pMblk->mBlkHdr.mLen = len; pMblk->mBlkHdr.mData += 2; pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkPktHdr.len = len; /* Send the packet to END driver */ END_RCV_RTN_CALL(&__netDriver->end, pMblk); g_ulPktUp++; return OK; cleanRXD: return (ERROR); }
MBUF_ID _mbufDup ( MBUF_ID mbufId, /* mbuf ID to duplicate */ MBUF_SEG mbufSeg, /* mbuf base for <offset> */ int offset, /* relative byte offset */ int len /* number of bytes to duplicate */ ) { MBUF_ID mbufIdNew; /* mbuf ID of duplicate */ MBUF_SEG mbufNew; /* mbuf for duplicate */ MBUF_SEG * pMbufPrev; /* mbuf prev to mbufNew */ /* find the starting location for duplicate */ if ((mbufSeg = _mbufSegFind (mbufId, mbufSeg, &offset)) == NULL) return (NULL); if (len < 0) /* negative = rest of chain */ len = INT_MAX; MBUF_ID_CREATE (mbufIdNew); /* get ID for duplicate */ if (mbufIdNew == NULL) return (NULL); pMbufPrev = &mbufIdNew->mbufHead; /* init prev ptr to head */ while (len && (mbufSeg != NULL)) /* while more to duplicate */ { /* get mbuf for duplicate */ if ( (mbufNew = mBlkGet (_pNetDpool, M_WAIT, mbufSeg->m_type)) == NULL) { /* release on fail */ MBUF_ID_DELETE(mbufIdNew); return (NULL); } mbufNew->m_len = min (len, (mbufSeg->m_len - offset)); len -= mbufNew->m_len; /* num to duplicate */ /* copy the cluster header mbuf info to duplicate */ mbufNew->m_data = mtod (mbufSeg, char *) + offset; mbufNew->m_flags = mbufSeg->m_flags; mbufNew->m_ext = mbufSeg->m_ext; /* bump share count */ { int s = intLock (); ++(mbufNew->m_extRefCnt); intUnlock (s); } *pMbufPrev = mbufNew; /* hook prev into duplicate */ pMbufPrev = &mbufNew->m_next; /* update prev mbuf ptr */ mbufSeg = mbufSeg->m_next; /* bump original chain */ offset = 0; /* no more offset */ } return (mbufIdNew); /* return ID of duplicate */ }
MBUF_SEG _mbufInsertBuf ( MBUF_ID mbufId, /* mbuf ID which buffer is inserted */ MBUF_SEG mbufSeg, /* mbuf base for <offset> */ int offset, /* relative byte offset */ caddr_t buf, /* user buffer for mbuf cluster */ int len, /* number of bytes to insert */ VOIDFUNCPTR freeRtn, /* user free routine */ int freeArg /* argument to free routine */ ) { MBUF_ID mbufIdNew; /* mbuf ID containing <buf> */ MBUF_DESC mbufDesc; /* desc for <buf> cluster */ MBUF_SEG mbufNew; /* mbuf for <buf> cluster */ CL_BLK_ID pClBlk; /* pointer to cluster blk */ int lockKey; /* int lock cookie */ int ix; /* counter for list init */ if (len <= 0) /* have to insert some bytes */ { errno = S_mbufLib_LENGTH_INVALID; return (NULL); } MBUF_ID_CREATE (mbufIdNew); /* create new mbuf ID for buf */ if (mbufIdNew == NULL) return (NULL); lockKey = intLock (); if ((mbufDesc = mbufDescHead) != NULL) /* free list empty ? */ { mbufDescHead = mbufDesc->mbufDescNext; /* pop first desc off list */ intUnlock (lockKey); } else /* list is empty */ { intUnlock (lockKey); if ((mbufDesc = (MBUF_DESC) KHEAP_ALLOC((sizeof (struct mbufDesc) * MBUF_DESC_INC))) != NULL) /* alloc more desc's */ { for (ix = 0; ix < (MBUF_DESC_INC - 1); ix++) mbufDesc[ix].mbufDescNext = &mbufDesc[ix + 1]; lockKey = intLock (); mbufDesc[ix].mbufDescNext = mbufDescHead; mbufDescHead = mbufDesc->mbufDescNext;/* hook head onto new list */ intUnlock (lockKey); } } if (mbufDesc == NULL) /* able to get a new desc ? */ { MBUF_ID_DELETE_EMPTY(mbufIdNew); return (NULL); } mbufDesc->buf = buf; /* get mbuf for cluster */ if ( (mbufNew = mBlkGet (_pNetDpool, M_WAIT, MT_DATA)) == NULL) { /* release on fail */ lockKey = intLock (); mbufDescHead = mbufDesc; intUnlock (lockKey); MBUF_ID_DELETE_EMPTY (mbufIdNew); return (NULL); } pClBlk = clBlkGet (_pNetDpool, M_WAIT); if (pClBlk == NULL) /* out of cl Blks */ { m_free (mbufNew); lockKey = intLock (); mbufDescHead = mbufDesc; intUnlock (lockKey); MBUF_ID_DELETE_EMPTY (mbufIdNew); return (NULL); } mbufNew->pClBlk = pClBlk; /* build <buf> into an mbuf cluster */ mbufNew->m_data = buf; mbufNew->m_len = len; mbufNew->m_flags |= M_EXT; mbufNew->m_extBuf = buf; mbufNew->m_extSize = len; mbufNew->m_extFreeRtn = (FUNCPTR) _mbufBufFree; mbufNew->m_extRefCnt = 1; mbufNew->m_extArg1 = (int) mbufDesc; mbufNew->m_extArg2 = (int) freeRtn; mbufNew->m_extArg3 = freeArg; mbufIdNew->mbufHead = mbufNew; /* put cluster into new ID */ /* insert the new mbuf ID with <buf> into <mbufId> */ if ((mbufSeg = _mbufInsert (mbufId, mbufSeg, offset, mbufIdNew)) == NULL) { mbufNew->m_extArg2 = (int)NULL; /* don't call freeRtn on fail */ MBUF_ID_DELETE(mbufIdNew); } return (mbufSeg); /* return inserted mbuf */ }
void socend_receive_netjob(int pi, int pckti, int pckt_size) /* * Function: socend_receive_netjob * Purpose: Called from netjob after packet arrives. * Parameters: p - pointer to (se), cookied passed on registration * pckpi - pointer to packet data (int form). * pckt_size - received length of packet. * Returns: Nothing */ { socend_t *se = (socend_t *)pi; struct end_object *eo = &se->se_eo; void *pckt = (void *)pckti; bcm_vlan_t vid; CL_BLK_ID cb = NULL; M_BLK_ID mb = NULL; /* Check the DCB for errors */ #if defined(BROADCOM_DEBUG) /* Only compile in for debug */ if (LOG_CHECK(BSL_LS_SYS_END | BSL_INFO) && LOG_CHECK(BSL_LS_SOC_PACKET | BSL_INFO)) { d_packet_format("socend RX", DECODE_ETHER, pckt, pckt_size, NULL); } #endif /* BROADCOM_DEBUG */ /* * Build Cluster - then attach to mblks, 1 for each interface that * should get the packet. Broadcast/Multicast packets go up all the stacks. * * For multicast, it should only go up stacks that have registered for that * address, but for now, this will allow multiple interfaces to work. */ if ((NULL == (cb = netClBlkGet(eo->pNetPool, M_DONTWAIT)))) { if (mb) netMblkFree(eo->pNetPool, mb); netClFree(eo->pNetPool, pckt); /* Free packet */ END_ERR_ADD(eo, MIB2_IN_ERRS, +1); return; } #if defined(__mips__) if (SOC_IS_ESW(se->se_unit)) { seu_t *seu = &socend_seu[se->se_unit]; void *tmp; sal_memcpy((UINT8 *)seu->pkt_align_buf + 2, (UINT8 *)pckt, pckt_size); tmp = seu->pkt_align_buf; seu->pkt_align_buf = pckt; pckt = tmp; } #endif /* __mips__ */ /* 1 MBLK for each interface */ if ((mb = mBlkGet(eo->pNetPool, M_DONTWAIT, MT_DATA))) { netClBlkJoin(cb, pckt, SOC_END_PK_SZ, NULL, 0, 0, 0); netMblkClJoin(mb, cb); mb->mBlkPktHdr.len = mb->mBlkHdr.mLen = pckt_size; mb->mBlkHdr.mFlags |= M_PKTHDR; #if defined(__mips__) if (SOC_IS_ESW(se->se_unit)) { mb->mBlkHdr.mData +=2; } #endif /* __mips__ */ vid = VLAN_CTRL_ID(soc_ntohs(((enet_hdr_t *)mb->mBlkHdr.mData)->en_tag_ctrl)); if (SOC_IS_ESW(se->se_unit)) { socend_untag(mb); /* Untag packet for now */ } else { robo_socend_untag(mb); /* Untag packet for now */ } } else { netClBlkFree(eo->pNetPool, cb); netClFree(eo->pNetPool, pckt); /* Free packet */ return; } { M_BLK_ID tmb, fmb = mb; seu_t *seu = &socend_seu[se->se_unit]; /* * Duplicate MBLK, and point to same cluster. */ for (se = seu->seu_devices; se != NULL; se = se->se_next) { if (vid != se->se_vlan) { continue; } eo = &se->se_eo; if (se->se_next != NULL) { tmb = mBlkGet(eo->pNetPool, M_DONTWAIT, MT_DATA); netMblkDup(mb, tmb); } else { fmb = NULL; tmb = mb; } END_RCV_RTN_CALL(eo, tmb); } if (fmb) { netMblkClFree(fmb); } } }