VOID NTAPI ProSendPackets( IN NDIS_HANDLE NdisBindingHandle, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets) { PADAPTER_BINDING AdapterBinding = NdisBindingHandle; PLOGICAL_ADAPTER Adapter = AdapterBinding->Adapter; KIRQL RaiseOldIrql; NDIS_STATUS NdisStatus; UINT i; if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler) { if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE) { (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)( Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets); } else { /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */ KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql); (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)( Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray, NumberOfPackets); KeLowerIrql(RaiseOldIrql); for (i = 0; i < NumberOfPackets; i++) { NdisStatus = NDIS_GET_PACKET_STATUS(PacketArray[i]); if (NdisStatus != NDIS_STATUS_PENDING) MiniSendComplete(Adapter, PacketArray[i], NdisStatus); } } } else { if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE) { for (i = 0; i < NumberOfPackets; i++) { NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)( Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags); if (NdisStatus != NDIS_STATUS_PENDING) MiniSendComplete(Adapter, PacketArray[i], NdisStatus); } } else { /* Send is called at DISPATCH_LEVEL for all serialized miniports */ KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql); for (i = 0; i < NumberOfPackets; i++) { NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)( Adapter->NdisMiniportBlock.MiniportAdapterContext, PacketArray[i], PacketArray[i]->Private.Flags); if (NdisStatus != NDIS_STATUS_PENDING) MiniSendComplete(Adapter, PacketArray[i], NdisStatus); } KeLowerIrql(RaiseOldIrql); } } }
/* ************************************************************************* * DeliverFullBuffers ************************************************************************* * * Deliver received packets to the protocol. * */ VOID DeliverFullBuffers(IrDevice *thisDev) { int rcvBufIndex = thisDev->firstRcvBufIndex; DBGOUT(("==> DeliverFullBuffers")); /* * Deliver all full rcv buffers */ while (rcvBufIndex != NO_BUF_INDEX){ rcvBuffer *rcvBuf = &thisDev->rcvBufs[rcvBufIndex]; NDIS_STATUS stat; PNDIS_BUFFER packetBuf; SLOW_IR_FCS_TYPE fcs; switch (rcvBuf->state){ case STATE_FREE: case STATE_PENDING: /* * This frame was already delivered. Just go to the next one. */ break; case STATE_FULL: /* * The packet we have already has had BOFs, EOF, and * escape-sequences removed. * It contains an FCS code at the end, * which we need to verify and then remove before * delivering the frame. * We compute the FCS on the packet with the packet FCS * attached; this should produce the constant value GOOD_FCS. */ fcs = ComputeFCS(rcvBuf->dataBuf, rcvBuf->dataLen); if (fcs != GOOD_FCS){ /* * FCS Error. Drop this frame. */ DBGERR(("Bad FCS in DeliverFullBuffers 0x%x!=0x%x.", (UINT)fcs, (UINT)GOOD_FCS)); rcvBuf->state = STATE_FREE; DBGSTAT(("Dropped %d/%d packets; packet with BAD FCS (%xh!=%xh):", ++thisDev->packetsDropped, thisDev->packetsDropped + thisDev->packetsRcvd, fcs, GOOD_FCS)); DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen); break; } /* * Remove the FCS from the end of the packet. */ rcvBuf->dataLen -= SLOW_IR_FCS_SIZE; #ifdef DBG_ADD_PKT_ID if (addPktIdOn){ /* * Remove dbg packet id. */ rcvBuf->dataLen -= sizeof(USHORT); DBGOUT((" RCVing packet %xh **", (UINT)*(USHORT *)(rcvBuf->dataBuf+rcvBuf->dataLen))); } #endif /* * The packet array is set up with its NDIS_PACKET. * Now we need to allocate a single NDIS_BUFFER for the * NDIS_PACKET and set the NDIS_BUFFER to the part of dataBuf * that we want to deliver. */ NdisAllocateBuffer( &stat, &packetBuf, thisDev->bufferPoolHandle, (PVOID)rcvBuf->dataBuf, rcvBuf->dataLen); if (stat != NDIS_STATUS_SUCCESS){ DBGERR(("NdisAllocateBuffer failed")); break; } NdisChainBufferAtFront(rcvBuf->packet, packetBuf); /* * Fix up some other packet fields. */ NDIS_SET_PACKET_HEADER_SIZE(rcvBuf->packet, SLOW_IR_ADDR_SIZE + SLOW_IR_CONTROL_SIZE); DBGPKT(("Indicating rcv packet 0x%x.", (UINT)rcvBuf->packet)); DBGPRINTBUF(rcvBuf->dataBuf, rcvBuf->dataLen); /* * Indicate to the protocol that another packet is ready. * Set the rcv buffer's state to PENDING first to avoid * a race condition with NDIS's call to the return packet * handler. */ rcvBuf->state = STATE_PENDING; NdisMIndicateReceivePacket(thisDev->ndisAdapterHandle, &rcvBuf->packet, 1); stat = NDIS_GET_PACKET_STATUS(rcvBuf->packet); if (stat == NDIS_STATUS_PENDING){ /* * The packet is being delivered asynchronously. * Leave the rcv buffer's state as PENDING; we'll * get a callback when the transfer is complete. * * Do NOT step firstRcvBufIndex. * We don't really need to break out here, * but we will anyways just to make things simple. * This is ok since we get this deferred interrupt callback * for each packet anyway. It'll give the protocol a chance * to catch up. */ DBGSTAT(("Rcv Pending. Rcvd %d packets", ++thisDev->packetsRcvd)); } else { /* * If there was an error, we are dropping this packet; * otherwise, this packet was delivered synchronously. * We can free the packet buffer and make this rcv frame * available. */ NdisUnchainBufferAtFront(rcvBuf->packet, &packetBuf); if (packetBuf){ NdisFreeBuffer(packetBuf); } rcvBuf->state = STATE_FREE; if (stat == NDIS_STATUS_SUCCESS){ DBGSTAT(("Rcvd %d packets", ++thisDev->packetsRcvd)); } else { DBGSTAT(("Dropped %d/%d rcv packets. ", thisDev->packetsDropped++, thisDev->packetsDropped+thisDev->packetsRcvd)); } } break; default: /* * This should never happen. */ DBGERR(("Bad rcv buffer state in DPC")); break; } /* * Step the buffer index */ if (rcvBufIndex == thisDev->lastRcvBufIndex){ rcvBufIndex = NO_BUF_INDEX; } else { rcvBufIndex = NEXT_RCV_BUF_INDEX(rcvBufIndex); } } DBGOUT(("<== DeliverFullBuffers")); }
INT LpxProtocolReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ){ PDEVICE_CONTEXT deviceContext; PNDIS_BUFFER ndisFirstBuffer; PVOID firstBuffer; UINT firstBufferSize; UINT totalBufferSize; USHORT protocol; PNDIS_PACKET packet = NULL; NDIS_STATUS status; INT pktReferenceCount = 0; UINT addiLlcHeaderSize = 0; PLPX_HEADER lpxHeader; USHORT lpxHeaderSize; UINT lpxPayload; UINT rawDataOffset; DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") ); deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext; // // Check to see if the device context is initialized. // ASSERT( deviceContext->NdisBindingHandle ); if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) { DebugPrint( 4,("Device is not initialized. Drop packet\n") ); return 0; } // // validation // NdisGetFirstBufferFromPacket( Packet, &ndisFirstBuffer, &firstBuffer, &firstBufferSize, &totalBufferSize); if (firstBufferSize < ETHERNET_HEADER_LENGTH) { DebugPrint( 1, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) ); return 0; } protocol = ((PETHERNET_HEADER)firstBuffer)->Type; // // Discard 802.2 LLC SNAP field. // // if Ether Type less than 0x0600 ( 1536 ) // if (NTOHS(protocol) < 0x0600 && NTOHS(protocol) != 0x0060 && // LOOP: Ethernet Loopback NTOHS(protocol) != 0x0200 && // PUP : Xerox PUP packet NTOHS(protocol) != 0x0201) { // PUPAP: Xerox PUP address trans packet protocol = *(PUSHORT)((PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2); if(firstBufferSize >= LENGTH_8022LLCSNAP) firstBufferSize -= LENGTH_8022LLCSNAP; else { DebugPrint( 1, ("ProtocolReceivePacket: Too small first buffer\n") ); return 0; } if(totalBufferSize >= LENGTH_8022LLCSNAP) totalBufferSize -= LENGTH_8022LLCSNAP; else { DebugPrint( 1, ("ProtocolReceivePacket: Too small total buffer\n") ); return 0; } addiLlcHeaderSize = LENGTH_8022LLCSNAP; } if (protocol != HTONS(ETH_P_LPX)) { DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", protocol) ); return 0; } if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) { DebugPrint( 1, ("ProtocolReceivePacket: too small packet(1).\n")); return 0; } // // Extract LPX header information // // lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize); lpxHeaderSize = sizeof(LPX_HEADER); lpxPayload = NTOHS(lpxHeader->PacketSize & ~LPX_TYPE_MASK) - lpxHeaderSize; #if __LPX_OPTION_ADDRESSS__ if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } #endif if(totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) { DebugPrint( 1, ("ProtocolReceivePacket: too small packet(2).\n")); return 0; } // // DROP PACKET for DEBUGGING!!!! // #if 1 //DBG // Enabled for testing if (PacketRxDropRate) { PacketRxCountForDrop++; if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) { PLPX_HEADER lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize); #if 0 if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) DebugPrint( 1, ("[Drop(%x,%x,%x))]\n", NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) ); #endif DebugPrint( 1, ("D\n") ); return 0; } } #endif ASSERT( addiLlcHeaderSize == 0 ); DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n", totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) ); // // If the miniport is out of resources, we can't queue // this packet - make a copy if this is so. // if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES) { UINT bytesCopied; DebugPrint( 1, ("ProtocolReceivePacket: Miniport reported low packet resources.\n")); status = RcvPacketAlloc( deviceContext, lpxPayload, &packet ); if (status == STATUS_SUCCESS) { ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); // // Copy lpx payload. payload contains only data. // NdisCopyFromPacketToPacket( packet, 0, lpxPayload, Packet, ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize, &bytesCopied); ASSERT(lpxPayload == bytesCopied); } rawDataOffset = 0; pktReferenceCount = 0; } else { PLPX_RESERVED externalReserved; // // No need to allocate new NDIS packet and copy data to the new NDIS packet. // But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context. // We should allocate our own. // packet = Packet; status = NdisAllocateMemoryWithTag(&externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED); if(status == NDIS_STATUS_SUCCESS) { RtlZeroMemory(externalReserved, sizeof(LPX_RESERVED)); // By setting the external reserved field, RESERVED() uses external reserved context automatically. ((PLPX_RESERVED)packet->ProtocolReserved)->ExternalReserved = externalReserved; // Initialize LPX reserved context instead of RcvPacketAlloc(). RESERVED(packet)->Cloned = 0; RESERVED(packet)->Type = LPX_PACKET_TYPE_RECEIVE; RESERVED(packet)->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT; // set data offset // Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data. rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize; lpxPayload += rawDataOffset; // return one reference count indicating LPX will call NdisReturnPackets() once. pktReferenceCount = 1; } } if (status != NDIS_STATUS_SUCCESS) { return 0; } // // Init LPX reserved context // LpxCopyEthLpxHeadersToLpxReserved(packet, firstBuffer, protocol, lpxHeader, lpxHeaderSize); RESERVED(Packet)->Packet = packet; RESERVED(Packet)->RecvTime = CurrentTime(); RESERVED(Packet)->PacketRawDataLength = lpxPayload; RESERVED(Packet)->PacketRawDataOffset = rawDataOffset; // // Queue to the device context. // ExInterlockedInsertTailList( &deviceContext->PacketInProgressList, &(RESERVED(Packet)->ListEntry), &deviceContext->PacketInProgressQSpinLock ); return pktReferenceCount; }
NDIS_STATUS proSendPacketToMiniport(PLOGICAL_ADAPTER Adapter, PNDIS_PACKET Packet) { #if WORKER_TEST MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE); return NDIS_STATUS_PENDING; #else KIRQL RaiseOldIrql; NDIS_STATUS NdisStatus; if(MiniIsBusy(Adapter, NdisWorkItemSend)) { MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, FALSE); return NDIS_STATUS_PENDING; } if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler) { if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE) { NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n")); (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)( Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1); NdisStatus = NDIS_STATUS_PENDING; } else { /* SendPackets is called at DISPATCH_LEVEL for all serialized miniports */ KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql); { NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's SendPackets handler\n")); (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendPacketsHandler)( Adapter->NdisMiniportBlock.MiniportAdapterContext, &Packet, 1); } KeLowerIrql(RaiseOldIrql); NdisStatus = NDIS_GET_PACKET_STATUS(Packet); if (NdisStatus == NDIS_STATUS_RESOURCES) { MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE); NdisStatus = NDIS_STATUS_PENDING; } } if (NdisStatus != NDIS_STATUS_PENDING) { MiniWorkItemComplete(Adapter, NdisWorkItemSend); } return NdisStatus; } else { if(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_DESERIALIZE) { NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n")); NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)( Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags); NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n")); } else { /* Send is called at DISPATCH_LEVEL for all serialized miniports */ KeRaiseIrql(DISPATCH_LEVEL, &RaiseOldIrql); NDIS_DbgPrint(MAX_TRACE, ("Calling miniport's Send handler\n")); NdisStatus = (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.SendHandler)( Adapter->NdisMiniportBlock.MiniportAdapterContext, Packet, Packet->Private.Flags); NDIS_DbgPrint(MAX_TRACE, ("back from miniport's send handler\n")); KeLowerIrql(RaiseOldIrql); if (NdisStatus == NDIS_STATUS_RESOURCES) { MiniQueueWorkItem(Adapter, NdisWorkItemSend, Packet, TRUE); NdisStatus = NDIS_STATUS_PENDING; } } if (NdisStatus != NDIS_STATUS_PENDING) { MiniWorkItemComplete(Adapter, NdisWorkItemSend); } return NdisStatus; } #endif }
INT natpReceivePacketPassThrough( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN FLT_PKT* pFltPkt ) { PFILTER_ADAPTER pAdapt =(PFILTER_ADAPTER)ProtocolBindingContext; NDIS_STATUS Status; PNDIS_PACKET MyPacket; BOOLEAN Remaining; PNDIS_BUFFER pNewBuffer; if (NULL == pAdapt->MiniportHandle || pAdapt->natmDeviceState > NdisDeviceStateD0) return 0; NdisIMGetCurrentPacketStack(Packet, &Remaining); if (NULL == pFltPkt && Remaining){ Status = NDIS_GET_PACKET_STATUS(Packet); NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1); return Status != NDIS_STATUS_RESOURCES ? 1 : 0; } if(NULL == pFltPkt){ NdisDprAllocatePacket( &Status, &MyPacket, pAdapt->RcvPP1 ); if (Status != NDIS_STATUS_SUCCESS){ return 0; } *((PVOID*)&MyPacket->MiniportReserved) = Packet; MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; }else{ NdisDprAllocatePacket( &Status, &MyPacket, pAdapt->RcvPP2 ); if (Status != NDIS_STATUS_SUCCESS) return NDIS_STATUS_NOT_ACCEPTED; *((PVOID*)&MyPacket->MiniportReserved) = pFltPkt; NdisAllocateBuffer( &Status, &pNewBuffer, pAdapt->RcvBP, pFltPkt->pBuf, pFltPkt->uLen ); if ( Status != NDIS_STATUS_SUCCESS ){ NdisReinitializePacket (MyPacket); NdisFreePacket (MyPacket); return 0; } NdisChainBufferAtFront(MyPacket, pNewBuffer ); } NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); Status = NDIS_GET_PACKET_STATUS(Packet); NDIS_SET_PACKET_STATUS(MyPacket, Status); NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet)); if (Status == NDIS_STATUS_RESOURCES){ natpQueueReceivedPacket(pAdapt, MyPacket, TRUE); }else{ natpQueueReceivedPacket(pAdapt, MyPacket, FALSE); } if (Status == NDIS_STATUS_RESOURCES) NdisDprFreePacket(MyPacket); return Status != NDIS_STATUS_RESOURCES ? 1 : 0; }
/****************************************************************************** * * Name: HandleRxReadyEvent() * * Description: Rx ready event handler * * Arguments: PMRVDRV_ADAPTER Adapter * * Return Value: * * Notes: * *****************************************************************************/ VOID HandleRxReadyEvent( IN PMRVDRV_ADAPTER Adapter ) { int IsRxOK = 0; PRxPD pRxPDCurrent; PNDIS_PACKET pPacket; NDIS_STATUS pStatus; DBGPRINT(DBG_RX | DBG_HELP,(L"+HandleRxReadyEvent()\n")); pRxPDCurrent = (PRxPD)(Adapter->pRxPD1); //lykao, 060905, begin if (pRxPDCurrent->Status & MRVDRV_RXPD_STATUS_OK) { Adapter->RcvOK++; Adapter->DirectedFramesRcvOK++; wlan_compute_rssi(Adapter,pRxPDCurrent); } else { DBGPRINT(DBG_RX | DBG_WARNING,(L"WARNING: frame received with bad status\n")); //dralee++ 09212005 for error handling pPacket = Adapter->pRxCurPkt; Adapter->pRxCurPkt = NULL; if ( pPacket ) ReturnRxPacketDesc(Adapter,pPacket); return; } pPacket = Adapter->pRxCurPkt; Adapter->pRxCurPkt = NULL; if (Adapter->MediaConnectStatus == NdisMediaStateConnected) { Adapter->ulRxByteInLastPeriod += Adapter->ulRxSize; NDIS_SET_PACKET_STATUS(pPacket, NDIS_STATUS_SUCCESS); NdisMIndicateReceivePacket(Adapter->MrvDrvAdapterHdl, &pPacket, 1); pStatus = NDIS_GET_PACKET_STATUS(pPacket); if ((pStatus == NDIS_STATUS_RESOURCES) || (pStatus == NDIS_STATUS_SUCCESS)) { // return packet DBGPRINT(DBG_RX|DBG_HELP, (L"Packet returned success or resources...\n")); ReturnRxPacketDesc(Adapter,pPacket); } else { DBGPRINT(DBG_RX|DBG_ERROR, (L"Packet returned pending...\n")); } } else { ///pmkcache: bug#16956 ++ if (Adapter->bIsReconnectAssociation == TRUE) { Adapter->isPktPending = TRUE; if ( Adapter->pPendedRxPkt ) { NKDbgPrintfW( L"ERROR, a pended RX packet has not been process!!\r\n" ); } Adapter->pPendedRxPkt = pPacket; return; } ///pmkcache: bug#16956 -- DBGPRINT(DBG_RX|DBG_ERROR, (L"Not connected, packet was dropped...\n")); ReturnRxPacketDesc(Adapter,pPacket); } return; }
INT PtReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ) /*++ Routine Description: ReceivePacket handler. Called by NDIS if the miniport below supports NDIS 4.0 style receives. Re-package the buffer chain in a new packet and indicate the new packet to protocols above us. Any context for packets indicated up must be kept in the MiniportReserved field. NDIS 5.1 - packet stacking - if there is sufficient "stack space" in the packet passed to us, we can use the same packet in a receive indication. Arguments: ProtocolBindingContext - Pointer to our adapter structure. Packet - Pointer to the packet Return Value: == 0 -> We are done with the packet != 0 -> We will keep the packet and call NdisReturnPackets() this many times when done. --*/ { PADAPT pAdapt =(PADAPT)ProtocolBindingContext; NDIS_STATUS Status; PNDIS_PACKET MyPacket; BOOLEAN Remaining; //------------------------------WestChamber--------------------------------- BOOLEAN result=WestChamberReceiverMain(Packet,pAdapt); if(result==FALSE) { //Simply drop the packet. //return NDIS_STATUS_NOT_ACCEPTED; return 0; //Thanks to Albert Jin. } //------------------------------WestChamber--------------------------------- // // Drop the packet silently if the upper miniport edge isn't initialized // if (!pAdapt->MiniportHandle) { return 0; } #ifdef NDIS51 // // Check if we can reuse the same packet for indicating up. // See also: PtReceive(). // (VOID)NdisIMGetCurrentPacketStack(Packet, &Remaining); if (Remaining) { // // We can reuse "Packet". Indicate it up and be done with it. // Status = NDIS_GET_PACKET_STATUS(Packet); NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &Packet, 1); return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0); } #endif // NDIS51 // // Get a packet off the pool and indicate that up // NdisDprAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { PRECV_RSVD RecvRsvd; RecvRsvd = (PRECV_RSVD)(MyPacket->MiniportReserved); RecvRsvd->OriginalPkt = Packet; MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; // // Get the original packet (it could be the same packet as the one // received or a different one based on the number of layered miniports // below) and set it on the indicated packet so the OOB data is visible // correctly to protocols above us. // NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet)); // // Set Packet Flags // NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); Status = NDIS_GET_PACKET_STATUS(Packet); NDIS_SET_PACKET_STATUS(MyPacket, Status); NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet)); NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1); // // Check if we had indicated up the packet with NDIS_STATUS_RESOURCES // NOTE -- do not use NDIS_GET_PACKET_STATUS(MyPacket) for this since // it might have changed! Use the value saved in the local variable. // if (Status == NDIS_STATUS_RESOURCES) { // // Our ReturnPackets handler will not be called for this packet. // We should reclaim it right here. // NdisDprFreePacket(MyPacket); } return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0); } else { // // We are out of packets. Silently drop it. // return(0); } }
INT LpxProtocolReceivePacket ( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ) { PDEVICE_CONTEXT deviceContext; PLPX_RESERVED reserved = NULL; PNDIS_BUFFER ndisFirstBuffer; PVOID firstBuffer; UINT firstBufferSize; UINT totalBufferSize; PNDIS_PACKET packet = NULL; NDIS_STATUS status; INT pktReferenceCount = 0; UINT addiLlcHeaderSize = 0; PLPX_HEADER lpxHeader; USHORT lpxHeaderSize; UINT lpxPayload; UINT rawDataOffset; ETHERNET_HEADER ethernetHeader; DebugPrint( 4, ("ProtocolReceivePacket: Entered\n") ); deviceContext = (PDEVICE_CONTEXT)ProtocolBindingContext; // Check to see if the device context is initialized. if (!FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_START) || FlagOn(deviceContext->LpxFlags, LPX_DEVICE_CONTEXT_STOP)) { DebugPrint( 1, ("Device is not initialized. Drop packet\n") ); return NDIS_STATUS_NOT_RECOGNIZED; } NDAS_ASSERT( deviceContext->NdisBindingHandle ); // validation #ifndef NTDDI_VERSION NdisGetFirstBufferFromPacket( Packet, &ndisFirstBuffer, &firstBuffer, &firstBufferSize, &totalBufferSize ); #else firstBufferSize = 0; NdisGetFirstBufferFromPacketSafe( Packet, &ndisFirstBuffer, &firstBuffer, &firstBufferSize, &totalBufferSize, HighPagePriority ); #endif if (firstBufferSize < ETHERNET_HEADER_LENGTH) { NDAS_ASSERT(FALSE); DebugPrint( 2, ("ProtocolReceivePacket: FirstBufferSize = %x\n", firstBufferSize) ); return 0; } RtlCopyMemory( ðernetHeader, firstBuffer, ETHERNET_HEADER_LENGTH ); if (ethernetHeader.DestinationAddress[5] != 0xFF) { DebugPrint( 3, ("LpxProtocolReceivePacket: Type = %X\n", ethernetHeader.Type) ); } // Discard 802.2 LLC SNAP field. // // if Ether Type less than 0x0600 ( 1536 ) if (NTOHS(ethernetHeader.Type) < 0x0600 && NTOHS(ethernetHeader.Type) != 0x0060 && // LOOP: Ethernet Loopback NTOHS(ethernetHeader.Type) != 0x0200 && // PUP : Xerox PUP packet NTOHS(ethernetHeader.Type) != 0x0201) { // PUPAP: Xerox PUP address trans packet RtlCopyMemory( ðernetHeader, (PUCHAR)firstBuffer + ETHERNET_HEADER_LENGTH + LENGTH_8022LLCSNAP - 2, ETHERNET_HEADER_LENGTH ); if (firstBufferSize >= LENGTH_8022LLCSNAP) { firstBufferSize -= LENGTH_8022LLCSNAP; } else { DebugPrint( 2, ("ProtocolReceivePacket: Too small first buffer\n") ); return 0; } if (totalBufferSize >= LENGTH_8022LLCSNAP) { totalBufferSize -= LENGTH_8022LLCSNAP; } else { DebugPrint( 2, ("ProtocolReceivePacket: Too small total buffer\n") ); return 0; } addiLlcHeaderSize = LENGTH_8022LLCSNAP; NDAS_ASSERT( ethernetHeader.Type != HTONS(ETH_P_LPX) ); } if (ethernetHeader.Type != HTONS(ETH_P_LPX)) { DebugPrint( 4, ("ProtocolReceivePacket: Type = %x\n", ethernetHeader.Type) ); return 0; } if (totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + sizeof(LPX_HEADER)) { DebugPrint( 2, ("ProtocolReceivePacket: too small packet(1).\n")); return 0; } // DROP PACKET for DEBUGGING!!!! if (PacketRxDropRate) { PacketRxCountForDrop++; if ((PacketRxCountForDrop % 1000) <= PacketRxDropRate) { PLPX_HEADER lpxHeader = (PLPX_HEADER)((PUCHAR)firstBuffer + addiLlcHeaderSize); if ((PacketRxCountForDrop % (PacketRxDropRate*20)) == 0) { DebugPrint( 6, ("[Drop(%x,%x,%x))]\n", NTOHS(lpxHeader->Lsctl), NTOHS(lpxHeader->Sequence), NTOHS(lpxHeader->AckSequence)) ); } DebugPrint( 2, ("D\n") ); return 0; } } if (!(RtlEqualMemory(ethernetHeader.DestinationAddress, deviceContext->LocalAddress.Address, ETHERNET_ADDRESS_LENGTH) || RtlEqualMemory(ethernetHeader.DestinationAddress, LpxBroadcastAddress, ETHERNET_ADDRESS_LENGTH))) { DebugPrint( 4, ("LpxProtocolReceivePacket, %02x%02x%02x%02x%02x%02x\n", deviceContext->LocalAddress.Address[0], deviceContext->LocalAddress.Address[1], deviceContext->LocalAddress.Address[2], deviceContext->LocalAddress.Address[3], deviceContext->LocalAddress.Address[4], deviceContext->LocalAddress.Address[5]) ); DebugPrint( 4, ("LpxProtocolReceivePacket, %02x%02x%02x%02x%02x%02x\n", ethernetHeader.DestinationAddress[0], ethernetHeader.DestinationAddress[1], ethernetHeader.DestinationAddress[2], ethernetHeader.DestinationAddress[3], ethernetHeader.DestinationAddress[4], ethernetHeader.DestinationAddress[5]) ); return 0; } // Extract LPX header information lpxHeader = (PLPX_HEADER)((PBYTE)firstBuffer + ETHERNET_HEADER_LENGTH + addiLlcHeaderSize); lpxHeaderSize = sizeof(LPX_HEADER); lpxPayload = NTOHS((UINT16)(lpxHeader->PacketSize & ~LPX_TYPE_MASK)) - lpxHeaderSize; if (lpxHeader->DestinationPort == NTOHS(LPXRP_HIX_PORT)) { DebugPrint( 1, ("[LPX] LpxProtocolReceivePacket: DataGram packet arrived.\n") ); } #if __LPX_OPTION_ADDRESSS__ if (FlagOn(lpxHeader->Option, LPX_OPTION_SOURCE_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } if (FlagOn(lpxHeader->Option, LPX_OPTION_DESTINATION_ADDRESS)) { lpxHeaderSize += ETHERNET_ADDRESS_LENGTH; } #endif if (totalBufferSize < ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize + lpxPayload) { DebugPrint( 2, ("ProtocolReceivePacket: too small packet(2).\n") ); return 0; } NDAS_ASSERT( addiLlcHeaderSize == 0 ); DebugPrint( 4, ("ProtocolReceivePacket: TotalBuffSz = %d, FirstBuffSz = %d, LPX_HEADER size = %d\n", totalBufferSize, firstBufferSize, sizeof(LPX_HEADER)) ); // If the miniport is out of resources, we can't queue // this packet - make a copy if this is so. NDAS_ASSERT( sizeof(ZeroProtocolReserved) == PROTOCOL_RESERVED_OFFSET ); if (NDIS_GET_PACKET_STATUS(Packet) == NDIS_STATUS_RESOURCES || !RtlEqualMemory(&Packet->ProtocolReserved[PROTOCOL_RESERVED_OFFSET], ZeroProtocolReserved, sizeof(ZeroProtocolReserved))) { UINT bytesCopied; INT i; for (i=0; i<16; i++) { DebugPrint( 1, ("Packet->ProtocolReserved[%d] = %d\n", i, Packet->ProtocolReserved[i]) ); } NDAS_ASSERT(FALSE); DebugPrint( 2, ("ProtocolReceivePacket: Miniport reported low packet resources.\n") ); status = RcvPacketAlloc( deviceContext, lpxPayload, &packet ); if (status == STATUS_SUCCESS) { NDAS_ASSERT( packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); // Copy lpx payload. payload contains only data. NdisCopyFromPacketToPacket( packet, 0, lpxPayload, Packet, ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize, &bytesCopied ); NDAS_ASSERT( lpxPayload == bytesCopied ); } rawDataOffset = 0; pktReferenceCount = 0; } else { PLPX_RESERVED externalReserved; // No need to allocate new NDIS packet and copy data to the new NDIS packet. // But, NDIS miniport allocates only 4 * sizeof(PVOID) for protocol reserved context. // We should allocate our own. packet = Packet; status = NdisAllocateMemoryWithTag( &externalReserved, sizeof(LPX_RESERVED), LPX_MEM_TAG_EXTERNAL_RESERVED ); if (status == NDIS_STATUS_SUCCESS) { RtlZeroMemory( externalReserved, sizeof(LPX_RESERVED) ); // By setting the external reserved field, LpxGetReserved() uses external reserved context automatically. ((PLPX_RESERVED)(&packet->ProtocolReserved[PROTOCOL_RESERVED_OFFSET]))->ExternalReserved = externalReserved; reserved = LpxGetReserved(packet); // Initialize LPX reserved context instead of RcvPacketAlloc(). reserved->Cloned = 0; reserved->Type = LPX_PACKET_TYPE_RECEIVE; reserved->RecvFlags |= LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT; // set data offset // Because NDIS miniport allocated the packet, the NDIS packet contains whole raw packet data. rawDataOffset = ETHERNET_HEADER_LENGTH + addiLlcHeaderSize + lpxHeaderSize; lpxPayload += rawDataOffset; // return one reference count indicating LPX will call NdisReturnPackets() once. pktReferenceCount = 1; } } if (status != NDIS_STATUS_SUCCESS) { DebugPrint( 2, ("ProtocolReceivePacket: status != NDIS_STATUS_SUCCESS\n") ); return 0; } // Init LPX reserved context LpxCopyEthLpxHeadersToLpxReserved( packet, firstBuffer, ethernetHeader.Type, lpxHeader, lpxHeaderSize ); reserved = LpxGetReserved(packet); reserved->Packet = packet; reserved->RecvTime = NdasCurrentTime(); reserved->PacketRawDataLength = lpxPayload; reserved->PacketRawDataOffset = rawDataOffset; // Queue to the device context. ExInterlockedInsertTailList( &deviceContext->PacketInProgressList, &(reserved->ListEntry), &deviceContext->PacketInProgressQSpinLock ); return pktReferenceCount; }
/*----------------------------------------------------------------------------*/ WLAN_STATUS kalRxIndicatePkts(IN P_GLUE_INFO_T prGlueInfo, IN PVOID apvPkts[], IN UINT_32 ucPktNum) { NDIS_STATUS arStatus[CFG_RX_MAX_PKT_NUM]; UINT_32 u4Idx; for (u4Idx = 0; u4Idx < ucPktNum; u4Idx++) { UINT_32 i, pivot; PVOID pvTmp; if (NDIS_GET_PACKET_STATUS((PNDIS_PACKET) apvPkts[u4Idx]) == NDIS_STATUS_RESOURCES) { pivot = u4Idx; for (i = u4Idx + 1; i < ucPktNum; i++) { if (NDIS_GET_PACKET_STATUS((PNDIS_PACKET) apvPkts[i]) != NDIS_STATUS_RESOURCES) { pvTmp = apvPkts[pivot]; apvPkts[pivot] = apvPkts[i]; apvPkts[i] = pvTmp; pivot++; } } break; } } for (u4Idx = 0; u4Idx < ucPktNum; u4Idx++) { arStatus[u4Idx] = NDIS_GET_PACKET_STATUS((PNDIS_PACKET) apvPkts[u4Idx]); if (arStatus[u4Idx] == NDIS_STATUS_SUCCESS) { /* 4 Increase the Pending Count before calling NdisMIndicateReceivePacket(). */ InterlockedIncrement(&prGlueInfo->i4RxPendingFrameNum); } } NdisMIndicateReceivePacket(prGlueInfo->rMiniportAdapterHandle, (PPNDIS_PACKET) apvPkts, (UINT) ucPktNum); for (u4Idx = 0; u4Idx < ucPktNum; u4Idx++) { /* 4 <1> Packets be retained. */ if (arStatus[u4Idx] != NDIS_STATUS_SUCCESS) { PNDIS_PACKET prNdisPacket = (PNDIS_PACKET) apvPkts[u4Idx]; PNDIS_BUFFER prNdisBuf = (PNDIS_BUFFER) NULL; ASSERT(prNdisPacket); NdisUnchainBufferAtBack(prNdisPacket, &prNdisBuf); if (prNdisBuf) { NdisFreeBuffer(prNdisBuf); } #if DBG else { ASSERT(0); } #endif /* DBG */ /* Reinitialize the packet descriptor for reuse. */ NdisReinitializePacket(prNdisPacket); #if CETK_NDIS_PERFORMANCE_WORKAROUND { PUINT_32 pu4Dummy; pu4Dummy = (PUINT_32) prNdisPacket->ProtocolReserved; *pu4Dummy = 0; } #endif /* CETK_NDIS_PERFORMANCE_WORKAROUND */ } } return WLAN_STATUS_SUCCESS; } /* kalIndicatePackets */