VOID FreeNdisPacket ( PNDIS_PACKET Packet ) /* * FUNCTION: Frees an NDIS packet * ARGUMENTS: * Packet = Pointer to NDIS packet to be freed */ { PNDIS_BUFFER Buffer, NextBuffer; TI_DbgPrint(DEBUG_PBUFFER, ("Packet (0x%X)\n", Packet)); /* Free all the buffers in the packet first */ NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL); for (; Buffer != NULL; Buffer = NextBuffer) { PVOID Data; UINT Length; NdisGetNextBuffer(Buffer, &NextBuffer); NdisQueryBuffer(Buffer, &Data, &Length); TI_DbgPrint(DEBUG_PBUFFER, ("Freeing ndis buffer (0x%X)\n", Buffer)); NdisFreeBuffer(Buffer); TI_DbgPrint(DEBUG_PBUFFER, ("Freeing exal buffer (0x%X)\n", Data)); ExFreePoolWithTag(Data, PACKET_BUFFER_TAG); } /* Finally free the NDIS packet discriptor */ NdisFreePacket(Packet); }
VOID FreeNdisPacketX ( PNDIS_PACKET Packet, PCHAR File, UINT Line ) /* * FUNCTION: Frees an NDIS packet * ARGUMENTS: * Packet = Pointer to NDIS packet to be freed */ { PNDIS_BUFFER Buffer, NextBuffer; TI_DbgPrint(DEBUG_PBUFFER, ("Packet (0x%X)\n", Packet)); /* Free all the buffers in the packet first */ NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL); for (; Buffer != NULL; Buffer = NextBuffer) { PVOID Data; UINT Length; NdisGetNextBuffer(Buffer, &NextBuffer); XNdisQueryBuffer(Buffer, &Data, &Length); UntrackFL(File,Line,Buffer); NdisFreeBuffer(Buffer); exFreePool(Data); } /* Finally free the NDIS packet descriptor */ UntrackFL(File,Line,Packet); NdisFreePacket(Packet); }
UINT CopyBufferChainToBuffer( PCHAR DstData, PNDIS_BUFFER SrcBuffer, UINT SrcOffset, UINT Length) /* * FUNCTION: Copies data from an NDIS buffer chain to a buffer * ARGUMENTS: * DstData = Pointer to destination buffer * SrcBuffer = Pointer to source NDIS buffer * SrcOffset = Source start offset * Length = Number of bytes to copy * RETURNS: * Number of bytes copied to destination buffer * NOTES: * The number of bytes copied may be limited by the source * buffer size */ { UINT BytesCopied, BytesToCopy, SrcSize; PCHAR SrcData; TI_DbgPrint(DEBUG_PBUFFER, ("DstData 0x%X SrcBuffer 0x%X SrcOffset 0x%X Length %d\n",DstData,SrcBuffer, SrcOffset, Length)); /* Skip SrcOffset bytes in the source buffer chain */ if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1) return 0; /* Start copying the data */ BytesCopied = 0; for (;;) { BytesToCopy = MIN(SrcSize, Length); TI_DbgPrint(DEBUG_PBUFFER, ("Copying (%d) bytes from 0x%X to 0x%X\n", BytesToCopy, SrcData, DstData)); RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy); BytesCopied += BytesToCopy; DstData = (PCHAR)((ULONG_PTR)DstData + BytesToCopy); Length -= BytesToCopy; if (Length == 0) break; SrcSize -= BytesToCopy; if (SrcSize == 0) { /* No more bytes in source buffer. Proceed to the next buffer in the source buffer chain */ NdisGetNextBuffer(SrcBuffer, &SrcBuffer); if (!SrcBuffer) break; NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); } } return BytesCopied; }
UINT CopyBufferToBufferChain( PNDIS_BUFFER DstBuffer, UINT DstOffset, PCHAR SrcData, UINT Length) /* * FUNCTION: Copies data from a buffer to an NDIS buffer chain * ARGUMENTS: * DstBuffer = Pointer to destination NDIS buffer * DstOffset = Destination start offset * SrcData = Pointer to source buffer * Length = Number of bytes to copy * RETURNS: * Number of bytes copied to destination buffer * NOTES: * The number of bytes copied may be limited by the destination * buffer size */ { UINT BytesCopied, BytesToCopy, DstSize; PCHAR DstData; TI_DbgPrint(DEBUG_PBUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcData (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcData, Length)); /* Skip DstOffset bytes in the destination buffer chain */ if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1) return 0; /* Start copying the data */ BytesCopied = 0; for (;;) { BytesToCopy = MIN(DstSize, Length); RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, BytesToCopy); BytesCopied += BytesToCopy; SrcData = (PCHAR)((ULONG_PTR)SrcData + BytesToCopy); Length -= BytesToCopy; if (Length == 0) break; DstSize -= BytesToCopy; if (DstSize == 0) { /* No more bytes in desination buffer. Proceed to the next buffer in the destination buffer chain */ NdisGetNextBuffer(DstBuffer, &DstBuffer); if (!DstBuffer) break; NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); } } return BytesCopied; }
VOID ArcFreeNdisPacket( IN PARC_PACKET Packet ) /*++ Routine description: This routine takes an arcnet packet and frees up the corresponding Ndis packet built for it. Arguments: Packet - The packet to free up. Return values: None --*/ { PNDIS_BUFFER NdisBuffer, NextNdisBuffer; NdisQueryPacket( &(Packet->TmpNdisPacket), NULL, NULL, &NdisBuffer, NULL ); while (NdisBuffer != NULL) { NdisGetNextBuffer( NdisBuffer, &NextNdisBuffer ); NdisFreeBuffer( NdisBuffer ); NdisBuffer = NextNdisBuffer; } NdisReinitializePacket(&(Packet->TmpNdisPacket)); }
/*----------------------------------------------------------------------------*/ VOID kalCopyFrame(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, OUT PUINT_8 pucDestBuffer) { PNDIS_PACKET prNdisPacket; PNDIS_BUFFER prNdisBuffer, prNextNdisBuffer; UINT u4PacketLen; UINT u4BytesToCopy; PVOID pvMbuf; UINT u4MbufLength; UINT u4BytesCopied; ASSERT(pvPacket); prNdisPacket = (PNDIS_PACKET) pvPacket; NdisQueryPacket(prNdisPacket, NULL, NULL, &prNdisBuffer, &u4PacketLen); u4BytesToCopy = u4PacketLen; u4BytesCopied = 0; while (u4BytesToCopy != 0) { #ifdef NDIS51_MINIPORT NdisQueryBufferSafe(prNdisBuffer, &pvMbuf, &u4MbufLength, HighPagePriority); #else NdisQueryBuffer(prNdisBuffer, &pvMbuf, &u4MbufLength); #endif /* NDIS51_MINIPORT */ if (pvMbuf == (PVOID) NULL) { ASSERT(pvMbuf); break; } NdisMoveMemory((PVOID) pucDestBuffer, pvMbuf, u4MbufLength); u4BytesToCopy -= u4MbufLength; u4BytesCopied += u4MbufLength; pucDestBuffer += u4MbufLength; NdisGetNextBuffer(prNdisBuffer, &prNextNdisBuffer); prNdisBuffer = prNextNdisBuffer; } ASSERT(u4BytesCopied == u4PacketLen); return; }
__inline INT SkipToOffset( PNDIS_BUFFER Buffer, UINT Offset, PCHAR *Data, PUINT Size) /* * FUNCTION: Skip Offset bytes into a buffer chain * ARGUMENTS: * Buffer = Pointer to NDIS buffer * Offset = Number of bytes to skip * Data = Address of a pointer that on return will contain the * address of the offset in the buffer * Size = Address of a pointer that on return will contain the * size of the destination buffer * RETURNS: * Offset into buffer, -1 if buffer chain was smaller than Offset bytes * NOTES: * Buffer may be NULL */ { for (;;) { if (!Buffer) return -1; NdisQueryBuffer(Buffer, (PVOID)Data, Size); if (Offset < *Size) { *Data = (PCHAR)((ULONG_PTR) *Data + Offset); *Size -= Offset; break; } Offset -= *Size; NdisGetNextBuffer(Buffer, &Buffer); } return Offset; }
/* * Convert the ndis packet chain into an lbuf . */ struct lbuf* shared_txlb_convert(shared_info_t *sh, ND_PKT *p) { #ifndef NDIS60 struct lbuf *lb; PNDIS_BUFFER b, next; uchar *bdata, *buf; uint blen, tot; struct lbfree *txlbfree; ASSERT(p); NdisQueryPacket(p, NULL, NULL, &b, &tot); ASSERT(b); ASSERT(tot <= LBDATASZ); if ((b == NULL) || (tot > LBDATASZ)) return (NULL); txlbfree = &sh->txfree; /* txqueue free buffer count shouldn't go below threshold */ if (txlbfree->count <= TXLB_FREEPOOL_THREHOLD(txlbfree->total)) return (NULL); /* alloc lbuf */ if ((lb = shared_lb_get(sh, txlbfree)) == NULL) return (NULL); /* Adjust for the head room requested */ ASSERT(txlbfree->size > txlbfree->headroom); lb->data += txlbfree->headroom; /* * In case of dongle, make sure the begining of the buffer is * aligned at 32 bytes for DMA efficiency, after inserting * header of 16 bytes later in DHD layer */ if (((uintptr)lb->data % 32) <= 16) lb->data += 16 - (uintptr)lb->data % 32; else lb->data -= (uintptr)lb->data % 32 - 16; buf = lb->data; while (b && tot) { #if defined(NDIS51) NdisQueryBufferSafe(b, &bdata, &blen, NormalPagePriority); #else NdisQueryBuffer(b, &bdata, &blen); #endif /* defined (NDIS51) */ blen = MIN(blen, tot); if (blen) { bcopy(bdata, buf, blen); lb->tail += blen; lb->len += blen; buf += blen; tot -= blen; } NdisGetNextBuffer(b, &next); b = next; } /* save a pointer to the ndis packet for later sendcomplete */ lb->p = p; return (lb); #else /* !NDIS60 */ struct lbuf *lb; PNET_BUFFER nb; PMDL b, next; uint offset; uchar *bdata, *buf; uint blen, tot; struct lbfree *txlbfree; ASSERT(p); tot = 0; for (nb = NET_BUFFER_LIST_FIRST_NB(p); nb; nb = NET_BUFFER_NEXT_NB(nb)) tot += NET_BUFFER_DATA_LENGTH(nb); nb = NET_BUFFER_LIST_FIRST_NB(p); if (nb == NULL) return (NULL); b = NET_BUFFER_CURRENT_MDL(nb); offset = NET_BUFFER_CURRENT_MDL_OFFSET(nb); ASSERT(b); ASSERT(tot <= LBDATASZ); if ((b == NULL) || (tot > LBDATASZ)) return (NULL); txlbfree = &sh->txfree; /* txqueue free buffer count shouldn't go below threshold */ if (txlbfree->count <= TXLB_FREEPOOL_THREHOLD(txlbfree->total)) return (NULL); /* alloc lbuf */ if ((lb = shared_lb_get(sh, txlbfree)) == NULL) return (NULL); #if defined(NDIS60) /* Adjust for the head room requested */ /* ASSERT(txlbfree->size > txlbfree->headroom); */ lb->data += txlbfree->headroom; /* * In case of dongle, make sure the begining of the buffer is * aligned at 32 bytes for DMA efficiency, after inserting * header of 16 bytes later in DHD layer */ if (((uintptr)lb->data % 32) <= 16) lb->data += 16 - (uintptr)lb->data % 32; else lb->data -= (uintptr)lb->data % 32 - 16; #endif /* UNDER_CE && NDIS60 */ buf = lb->data; while (b && tot) { NdisQueryMdl(b, &bdata, &blen, NormalPagePriority); if (bdata == NULL) goto next_mdl; if (blen > offset) { bdata += offset; blen -= offset; } else { offset -= blen; goto next_mdl; } blen = MIN(blen, tot); if (blen) { bcopy(bdata, buf, blen); lb->tail += blen; lb->len += blen; buf += blen; tot -= blen; offset = 0; } next_mdl: NdisGetNextMdl(b, &next); if (!next) { nb = NET_BUFFER_NEXT_NB(nb); if (nb) { next = NET_BUFFER_CURRENT_MDL(nb); offset = NET_BUFFER_CURRENT_MDL_OFFSET(nb); } } b = next; } /* save a pointer to the ndis packet for later sendcomplete */ lb->p = p; return (lb); #endif /* !NDIS60 */ }
INT PacketReceivePacket( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet ) { UINT bytesTransfered = 0; POPEN_INSTANCE open; PIRP irp; PNDIS_PACKET myPacket; PLIST_ENTRY packetListEntry; ULONG bufferLength; PPACKET_RESERVED reserved; PIO_STACK_LOCATION irpSp; PMDL mdl; PVOID startAddress; NTSTATUS status; // DebugPrint(("PacketReceivePacket\n")); open = (POPEN_INSTANCE)ProtocolBindingContext; packetListEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock ); if (packetListEntry == NULL) { // DebugPrint(("No pending read, dropping packets\n")); return 0; } reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement); myPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved); irp = RESERVED(myPacket)->Irp; irpSp = IoGetCurrentIrpStackLocation(irp); // We don't have to worry about the situation where the IRP is cancelled // after we remove it from the queue and before we reset the cancel // routine because the cancel routine has been coded to cancel an IRP // only if it's in the queue. IoSetCancelRoutine(irp, NULL); // Following block of code locks the destination packet // MDLs in a safe manner. This is a temporary workaround // for NdisCopyFromPacketToPacket that currently doesn't use // safe functions to lock pages of MDL. This is required to // prevent system from bugchecking under low memory resources. // { PVOID virtualAddress; PNDIS_BUFFER firstBuffer, nextBuffer; ULONG totalLength; NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength); while( firstBuffer ) { NdisQueryBufferSafe( firstBuffer, &virtualAddress, &totalLength, NormalPagePriority ); if(!virtualAddress) { status = STATUS_INSUFFICIENT_RESOURCES; goto CleanExit; } NdisGetNextBuffer(firstBuffer, &nextBuffer); firstBuffer = nextBuffer; } } NdisChainBufferAtFront( myPacket, irp->MdlAddress ); bufferLength=irpSp->Parameters.Read.Length; NdisCopyFromPacketToPacket( myPacket, 0, bufferLength, Packet, 0, &bytesTransfered ); CleanExit: NdisFreePacket(myPacket); irp->IoStatus.Status = status; irp->IoStatus.Information = bytesTransfered; IoCompleteRequest(irp, IO_NO_INCREMENT); // DebugPrint(("BytesTransfered:%d\n", bytesTransfered)); IoDecrement(open); return 0; }
extern VOID Pc586CopyFromPacketToPacket( IN PNDIS_PACKET Destination, IN UINT DestinationOffset, IN UINT BytesToCopy, IN PNDIS_PACKET Source, IN UINT SourceOffset, OUT PUINT BytesCopied ) /*++ Routine Description: Copy from an ndis packet to an ndis packet. Arguments: Destination - The packet should be copied in to. DestinationOffset - The offset from the beginning of the packet into which the data should start being placed. BytesToCopy - The number of bytes to copy from the source packet. Source - The ndis packet from which to copy data. SourceOffset - The offset from the start of the packet from which to start copying data. BytesCopied - The number of bytes actually copied from the source packet. This can be less than BytesToCopy if the source or destination packet is too short. Return Value: None --*/ { // // Holds the count of the number of ndis buffers comprising the // destination packet. // UINT DestinationBufferCount; // // Holds the count of the number of ndis buffers comprising the // source packet. // UINT SourceBufferCount; // // Points to the buffer into which we are putting data. // PNDIS_BUFFER DestinationCurrentBuffer; // // Points to the buffer from which we are extracting data. // PNDIS_BUFFER SourceCurrentBuffer; // // Holds the virtual address of the current destination buffer. // PVOID DestinationVirtualAddress; // // Holds the virtual address of the current source buffer. // PVOID SourceVirtualAddress; // // Holds the length of the current destination buffer. // UINT DestinationCurrentLength; // // Holds the length of the current source buffer. // UINT SourceCurrentLength; // // Keep a local variable of BytesCopied so we aren't referencing // through a pointer. // UINT LocalBytesCopied = 0; // // Take care of boundary condition of zero length copy. // *BytesCopied = 0; if (!BytesToCopy) return; // // Get the first buffer of the destination. // NdisQueryPacket( Destination, NULL, &DestinationBufferCount, &DestinationCurrentBuffer, NULL ); // // Could have a null packet. // if (!DestinationBufferCount) return; NdisQueryBuffer( DestinationCurrentBuffer, NULL, &DestinationVirtualAddress, &DestinationCurrentLength ); // // Get the first buffer of the source. // NdisQueryPacket( Source, NULL, &SourceBufferCount, &SourceCurrentBuffer, NULL ); // // Could have a null packet. // if (!SourceBufferCount) return; NdisQueryBuffer( SourceCurrentBuffer, NULL, &SourceVirtualAddress, &SourceCurrentLength ); while (LocalBytesCopied < BytesToCopy) { // // Check to see whether we've exhausted the current destination // buffer. If so, move onto the next one. // if (!DestinationCurrentLength) { NdisGetNextBuffer( DestinationCurrentBuffer, &DestinationCurrentBuffer ); if (!DestinationCurrentBuffer) { // // We've reached the end of the packet. We return // with what we've done so far. (Which must be shorter // than requested.) // break; } NdisQueryBuffer( DestinationCurrentBuffer, NULL, &DestinationVirtualAddress, &DestinationCurrentLength ); continue; } // // Check to see whether we've exhausted the current source // buffer. If so, move onto the next one. // if (!SourceCurrentLength) { NdisGetNextBuffer( SourceCurrentBuffer, &SourceCurrentBuffer ); if (!SourceCurrentBuffer) { // // We've reached the end of the packet. We return // with what we've done so far. (Which must be shorter // than requested.) // break; } NdisQueryBuffer( SourceCurrentBuffer, NULL, &SourceVirtualAddress, &SourceCurrentLength ); continue; } // // Try to get us up to the point to start the copy. // if (DestinationOffset) { if (DestinationOffset > DestinationCurrentLength) { // // What we want isn't in this buffer. // DestinationOffset -= DestinationCurrentLength; DestinationCurrentLength = 0; continue; } else { DestinationVirtualAddress = (PCHAR)DestinationVirtualAddress + DestinationOffset; DestinationCurrentLength -= DestinationOffset; DestinationOffset = 0; } } // // Try to get us up to the point to start the copy. // if (SourceOffset) { if (SourceOffset > SourceCurrentLength) { // // What we want isn't in this buffer. // SourceOffset -= SourceCurrentLength; SourceCurrentLength = 0; continue; } else { SourceVirtualAddress = (PCHAR)SourceVirtualAddress + SourceOffset; SourceCurrentLength -= SourceOffset; SourceOffset = 0; } } // // Copy the data. // { // // Holds the amount of data to move. // UINT AmountToMove; // // Holds the amount desired remaining. // UINT Remaining = BytesToCopy - LocalBytesCopied; AmountToMove = ((SourceCurrentLength <= DestinationCurrentLength)? (SourceCurrentLength):(DestinationCurrentLength)); AmountToMove = ((Remaining < AmountToMove)? (Remaining):(AmountToMove)); PC586_MOVE_MEMORY( DestinationVirtualAddress, SourceVirtualAddress, AmountToMove ); DestinationVirtualAddress = (PCHAR)DestinationVirtualAddress + AmountToMove; SourceVirtualAddress = (PCHAR)SourceVirtualAddress + AmountToMove; LocalBytesCopied += AmountToMove; SourceCurrentLength -= AmountToMove; DestinationCurrentLength -= AmountToMove; } } *BytesCopied = LocalBytesCopied; }
BOOLEAN cdc_ncm_fill_tx_frame(PMP_ADAPTER Adapter,PNDIS_PACKET Packet,PTCB ptcb, NCMDWORD sign) { PMP_USBPIPE usbpipe = Adapter->UsbPipeForNIC; PUSB_CDC_NCM_NTH16 nth16; PUSB_CDC_NCM_NDP16 ndp16; USHORT n = 0, index, ndplen; UINT PacketLength; PNDIS_BUFFER CurrentBuffer = NULL; PVOID VirtualAddress = NULL; UINT CurrentLength; BOOLEAN bResult = TRUE; int maxpacketsize; int max_datagrams; maxpacketsize=usbpipe->InterfaceData->Pipes[usbpipe->BulkPipeOutput].MaximumPacketSize; if (Packet == NULL) { return TRUE; } max_datagrams=usbpipe->tx_max_datagrams; if (0==ptcb->ulSize) { /* fill out the initial 16-bit NTB header */ nth16 = (PUSB_CDC_NCM_NTH16 )memset(tcb_put(ptcb, sizeof(USB_CDC_NCM_NTH16)), 0, sizeof(USB_CDC_NCM_NTH16)); nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN); nth16->wHeaderLength = cpu_to_le16(sizeof(USB_CDC_NCM_NTH16)); nth16->wSequence = cpu_to_le16(usbpipe->tx_seq++); /* count total number of frames in this NTB */ ptcb->NumofOrgSendPacket= 0; } NdisQueryPacket(Packet, NULL, NULL, &CurrentBuffer, &PacketLength); n = ptcb->NumofOrgSendPacket; if(n>=max_datagrams) { ptcb->bRead2Send=1; } while(n<max_datagrams) { /* get the appropriate NDP for this skb */ ndp16 = cdc_ncm_ndp(Adapter, ptcb, sign, PacketLength + usbpipe->tx_modulus + usbpipe->tx_remainder); /* align beginning of next frame */ cdc_ncm_align_tail(ptcb, usbpipe->tx_modulus, usbpipe->tx_remainder, usbpipe->tx_max); /* check if we had enough room left for both NDP and frame */ if (NULL==ndp16 || ptcb->ulSize + PacketLength > usbpipe->tx_max) { if (n == 0) { ptcb->bRead2Send=0; } else { ptcb->bRead2Send = 1; } bResult=FALSE; break; } /* calculate frame number withing this NDP */ ndplen = le16_to_cpu(ndp16->wLength); index = (ndplen - sizeof(USB_CDC_NCM_NDP16)) / sizeof(USB_CDC_NCM_DPE16); /* OK, add this Packet */ ndp16->dpe16[index].wDatagramLength = cpu_to_le16((USHORT)PacketLength); ndp16->dpe16[index].wDatagramIndex = cpu_to_le16((USHORT)ptcb->ulSize); ndp16->wLength = cpu_to_le16(ndplen + sizeof(USB_CDC_NCM_DPE16)); while(CurrentBuffer) { NdisQueryBufferSafe( CurrentBuffer, &VirtualAddress, &CurrentLength, NormalPagePriority); ASSERT(NULL!=VirtualAddress); CurrentLength = min(CurrentLength, PacketLength); if(CurrentLength) { // Copy the data. NdisMoveMemory(tcb_put(ptcb, CurrentLength), VirtualAddress, CurrentLength); PacketLength -= CurrentLength; } NdisGetNextBuffer( CurrentBuffer, &CurrentBuffer); } if(PacketLength){ NdisZeroMemory(tcb_put(ptcb, PacketLength), PacketLength); PacketLength=0; } InsertTailList( &ptcb->ListOrgSendPacket, (PLIST_ENTRY)&Packet->MiniportReserved[0]); ptcb->NumofOrgSendPacket++; /* send now if this NDP is full */ if (index >= CDC_NCM_DPT_DATAGRAMS_MAX) { ptcb->bRead2Send = 1; break; } break; } /* If collected data size is less or equal CDC_NCM_MIN_TX_PKT * bytes, we send buffers as it is. If we get more data, it * would be more efficient for USB HS mobile device with DMA * engine to receive a full size NTB, than canceling DMA * transfer and receiving a short packet. * * This optimization support is pointless if we end up sending * a ZLP after full sized NTBs. */ if (ptcb->bRead2Send==1&&(ptcb->ulSize%maxpacketsize== 0)) memset(tcb_put(ptcb, 1), 0, 1);/* force short packet */ /* set final frame length */ nth16 = (PUSB_CDC_NCM_NTH16 )ptcb->pData; nth16->wBlockLength = cpu_to_le16((USHORT)ptcb->ulSize); return bResult; }
// Packet send handler void NeoNdisSendPackets(NDIS_HANDLE MiniportAdapterContext, NDIS_PACKET **PacketArray, UINT NumberOfPackets) { UCHAR *Buf,*BufCopy; PNDIS_BUFFER Buffer; UCHAR *Tmp; UINT PacketLength; UINT CurrentLength; UINT i; if (ctx == NULL) { return; } // Update the connection state NeoCheckConnectState(); if (NumberOfPackets == 0) { // The number of packets is 0 return; } if (NeoNdisSendPacketsHaltCheck(PacketArray, NumberOfPackets) == FALSE) { // Device is stopped return; } // Operation of the packet queue NeoLockPacketQueue(); { if (NeoNdisSendPacketsHaltCheck(PacketArray, NumberOfPackets) == FALSE) { // Device is stopped NeoUnlockPacketQueue(); return; } // Place the packet in the queue in order for (i = 0;i < NumberOfPackets;i++) { // Get a packet NdisQueryPacket(PacketArray[i], NULL, NULL, &Buffer, &PacketLength); // Extract the packet. // Memory allocated here is used for the queue and is released at the time of releasing the queue. Buf = NeoMalloc(PacketLength); BufCopy = Buf; while (Buffer) { NdisQueryBuffer(Buffer, &Tmp, &CurrentLength); if (CurrentLength == 0) { // Complete break; } NeoCopy(BufCopy, Tmp, CurrentLength); BufCopy += CurrentLength; NdisGetNextBuffer(Buffer, &Buffer); } // Process this packet if (PacketLength > NEO_MIN_PACKET_SIZE) { if (PacketLength > NEO_MAX_PACKET_SIZE) { // Packet is too large NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_FAILURE); if (g_is_win8) { NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_FAILURE); } ctx->Status.NumPacketSendError++; NeoFree(Buf); } else { // Insert the packet into the queue NeoInsertQueue(Buf, PacketLength); NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS); if (g_is_win8) { NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_SUCCESS); } ctx->Status.NumPacketSend++; } } else { // Release if the packet doesn't contain data NDIS_SET_PACKET_STATUS(PacketArray[i], NDIS_STATUS_SUCCESS); if (g_is_win8) { NdisMSendComplete(ctx->NdisMiniport, PacketArray[i], NDIS_STATUS_SUCCESS); } NeoFree(Buf); } } } NeoUnlockPacketQueue(); // Reception event NeoSet(ctx->Event); }
struct Send_Packet_Data* Packet2PacketData(PNDIS_PACKET Packet) { UINT buffer_count; PNDIS_BUFFER buffer; UINT packet_len; UINT offset; PVOID addr; UINT len; struct Send_Packet_Data* packet_data; packet_data = NULL; NdisQueryPacket(Packet, NULL, &buffer_count, &buffer, &packet_len); if (!buffer_count || !buffer) goto error_exit; if (buffer_count > 1) { packet_data = PreparePacketData(buffer_count, packet_len); if (!packet_data) goto error_exit; offset = 0; while(1) { NdisQueryBufferSafe(buffer, &addr, &len, NormalPagePriority); if (!addr || !len) goto error_exit; RtlCopyMemory(packet_data->m_data+offset, addr, len); offset += len; NdisGetNextBuffer(buffer, &buffer); if (!buffer) break; } packet_data->m_ndis_packet = Packet; packet_data->m_len = packet_len; } else { packet_data = PreparePacketData(buffer_count, 0); if (!packet_data) goto error_exit; NdisQueryBufferSafe(buffer, &addr, &len, NormalPagePriority); if (!addr || !len) goto error_exit; packet_data->m_ndis_packet = Packet; packet_data->m_len = packet_len; packet_data->m_data = addr; } packet_data->m_mdl = IoAllocateMdl(packet_data->m_data, packet_data->m_len, FALSE, FALSE, NULL); if (!packet_data->m_mdl) goto error_exit; try { MmProbeAndLockPages(packet_data->m_mdl, KernelMode, IoReadAccess); packet_data->m_locked = 1; } except(EXCEPTION_EXECUTE_HANDLER) { packet_data->m_locked = 0; } packet_data->m_addr = MmMapLockedPagesSpecifyCache(packet_data->m_mdl, UserMode, MmCached, NULL, FALSE, NormalPagePriority); if (!packet_data->m_addr) goto error_exit; packet_data->m_map_process = PsGetCurrentProcessId(); return packet_data; error_exit: DbgPrint("Packet2PacketData failed, force to complete the lost packet\n"); free_send_packet_data(packet_data); return NULL; }
/****************************************************************************** * * Name: PrepareDownloadPacket() * * Description: Prepare the DownloadPacket from packet send by upper layer * * Conditions for Use: * * Arguments: * IN PMRVDRV_ADAPTER Adapter, * IN PNDIS_PACKET Packet, * IN PSDIO_TX_PKT pDnldPacket * * Return Value: None * * Notes: * *****************************************************************************/ NDIS_STATUS PrepareDownloadPacket(PMRVDRV_ADAPTER Adapter,PNDIS_PACKET Packet, PSDIO_TX_PKT pDnldPacket) { NDIS_STATUS Status = NDIS_STATUS_SUCCESS; UINT BufferCount; UINT TotalPacketLength=0; UINT TotalBufferLength=0; UINT BytesCopied=0; UINT Length,AccumLength; PNDIS_BUFFER pBuffer, pNextBuffer; PVOID pVirtualAddr; PUCHAR pHeader = NULL; ULONG coBufferLength = 0; ULONG i; PWCB pWcb; UCHAR *pCurPtr = pDnldPacket->Buf.CmdBuf; Status = NDIS_STATUS_SUCCESS; NdisQueryPacket( Packet, NULL, &BufferCount, &pBuffer, &TotalPacketLength); if(!pBuffer || !BufferCount || !TotalPacketLength) { Status=NDIS_STATUS_FAILURE; DBGPRINT(DBG_TX|DBG_WARNING,(L"TX - NDIS buffer is not valid, return FAILURE \n")); return Status; } //RETAILMSG(1,(TEXT("[Marvell]SendSinglePacket:1 NdisQueryBuffer"))); NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length); //RETAILMSG(1,(TEXT("[Marvell]SendSinglePacket:2 NdisQueryBuffer"))); pHeader = (PUCHAR)pVirtualAddr; DBGPRINT(DBG_TX|DBG_HELP,(L"SendSinglePacket: buffers %d, packet len %d\n",BufferCount, TotalPacketLength)); pWcb = (PWCB)&(pDnldPacket->Buf.TxDataBuf.Wcb); NdisZeroMemory(pWcb,sizeof(WCB)); pWcb->Status = MRVDRV_WCB_STATUS_USED; pWcb->PktLen = (USHORT)TotalPacketLength; DBGPRINT(DBG_TX|DBG_HELP,(L"DataRate = %x\n", (ULONG)Adapter -> DataRate)); // number of retry is 3 // pWcb->TxControl = ( (3 << 12 ) | Adapter->DataRate); // pWcb->TxControl =0; pWcb->TxControl = Adapter->TX_Control_Value; pWcb->PktPtr = sizeof(WCB); // First buffer contains the MAC header // Call NdisMoveMemory() to copy DEST MAC adress to WCB //RETAILMSG(1,(TEXT("[Marvell]SendSinglePacket:1 NdisMoveMemory"))); NdisMoveMemory( (PVOID)&(pWcb->DestMACAdrHi), pVirtualAddr, MRVDRV_ETH_ADDR_LEN); //RETAILMSG(1,(TEXT("[Marvell]SendSinglePacket:2 NdisMoveMemory"))); { ULONG currenttime, packettime; currenttime = GetTickCount(); packettime = *((ULONG *)(&Packet->MacReserved[0])); // PKtdelay in driver layer , unit 2ms pWcb->Reserved[0]=(UCHAR)((currenttime - packettime) / 2); DBGPRINT(DBG_CCX_V4,(L"PktDelay%02x ",pWcb->Reserved[0])); } // Start the packet. TotalBufferLength = TotalPacketLength; TotalBufferLength += sizeof(WCB); // TotalBufferLength contains the size of the packet pDnldPacket->Len = ADD_SDIO_PKT_HDR_LENGTH(TotalBufferLength); DBGPRINT(DBG_TX,(L"TX %d bytes: packet size %d\n",(ULONG)TotalBufferLength, (ULONG)TotalPacketLength)); pCurPtr += sizeof(WCB); AccumLength = sizeof(WCB); // Query each buffer for the packet and move data to SQ for(i=0; i<BufferCount; i++) { NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length); AccumLength += Length; if( AccumLength > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE ) // PJG: accum length already counts the header... need to compare to entire buffer size break; if( pVirtualAddr ) { NdisMoveMemory(pCurPtr, (PUCHAR)pVirtualAddr, (USHORT)Length); pCurPtr += Length; } NdisGetNextBuffer(pBuffer, &pNextBuffer); if( !pNextBuffer ) break; pBuffer = pNextBuffer; }//for(i=0; i<BufferCount; i++) DBGPRINT(DBG_TX|DBG_HELP,(L"\n")); DBGPRINT(DBG_TX|DBG_HELP,(L"[Marvell]TX SendSinglePacket!\n")); pDnldPacket->Type = IF_DATA_PKT; return NDIS_STATUS_SUCCESS; }
UINT CopyPacketToBufferChain( PNDIS_BUFFER DstBuffer, UINT DstOffset, PNDIS_PACKET SrcPacket, UINT SrcOffset, UINT Length) /* * FUNCTION: Copies data from an NDIS packet to an NDIS buffer chain * ARGUMENTS: * DstBuffer = Pointer to destination NDIS buffer * DstOffset = Destination start offset * SrcPacket = Pointer to source NDIS packet * SrcOffset = Source start offset * Length = Number of bytes to copy * RETURNS: * Number of bytes copied to destination buffer * NOTES: * The number of bytes copied may be limited by the source and * destination buffer sizes */ { PNDIS_BUFFER SrcBuffer; PCHAR DstData, SrcData; UINT DstSize, SrcSize; UINT Count, Total; TI_DbgPrint(DEBUG_PBUFFER, ("DstBuffer (0x%X) DstOffset (0x%X) SrcPacket (0x%X) SrcOffset (0x%X) Length (%d)\n", DstBuffer, DstOffset, SrcPacket, SrcOffset, Length)); /* Skip DstOffset bytes in the destination buffer chain */ NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); if (SkipToOffset(DstBuffer, DstOffset, &DstData, &DstSize) == -1) return 0; /* Skip SrcOffset bytes in the source packet */ NdisGetFirstBufferFromPacket(SrcPacket, &SrcBuffer, (PVOID)&SrcData, &SrcSize, &Total); if (SkipToOffset(SrcBuffer, SrcOffset, &SrcData, &SrcSize) == -1) return 0; /* Copy the data */ for (Total = 0;;) { /* Find out how many bytes we can copy at one time */ if (Length < SrcSize) Count = Length; else Count = SrcSize; if (DstSize < Count) Count = DstSize; RtlCopyMemory((PVOID)DstData, (PVOID)SrcData, Count); Total += Count; Length -= Count; if (Length == 0) break; DstSize -= Count; if (DstSize == 0) { /* No more bytes in destination buffer. Proceed to the next buffer in the destination buffer chain */ NdisGetNextBuffer(DstBuffer, &DstBuffer); if (!DstBuffer) break; NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize); } SrcSize -= Count; if (SrcSize == 0) { /* No more bytes in source buffer. Proceed to the next buffer in the source buffer chain */ NdisGetNextBuffer(SrcBuffer, &SrcBuffer); if (!SrcBuffer) break; NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); } } return Total; }
VOID ndisprotServiceReads( IN PNDISPROT_OPEN_CONTEXT pOpenContext ) /*++ Routine Description: Utility routine to copy received data into user buffers and complete READ IRPs. Arguments: pOpenContext - pointer to open context Return Value: None --*/ { PIRP pIrp = NULL; PLIST_ENTRY pIrpEntry; PNDIS_PACKET pRcvPacket; PLIST_ENTRY pRcvPacketEntry; PUCHAR pSrc, pDst; ULONG BytesRemaining; // at pDst PNDIS_BUFFER pNdisBuffer; ULONG BytesAvailable; BOOLEAN FoundPendingIrp; DEBUGP(DL_VERY_LOUD, ("ServiceReads: open %p/%x\n", pOpenContext, pOpenContext->Flags)); NPROT_REF_OPEN(pOpenContext); // temp ref - service reads NPROT_ACQUIRE_LOCK(&pOpenContext->Lock); while (!NPROT_IS_LIST_EMPTY(&pOpenContext->PendedReads) && !NPROT_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue)) { FoundPendingIrp = FALSE; // // Get the first pended Read IRP // pIrpEntry = pOpenContext->PendedReads.Flink; while (pIrpEntry != &pOpenContext->PendedReads) { pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry); // // Check to see if it is being cancelled. // if (IoSetCancelRoutine(pIrp, NULL)) { // // It isn't being cancelled, and can't be cancelled henceforth. // NPROT_REMOVE_ENTRY_LIST(pIrpEntry); FoundPendingIrp = TRUE; break; // // NOTE: we decrement PendedReadCount way below in the // while loop, to avoid letting through a thread trying // to unbind. // } else { // // The IRP is being cancelled; let the cancel routine handle it. // DEBUGP(DL_INFO, ("ServiceReads: open %p, skipping cancelled IRP %p\n", pOpenContext, pIrp)); pIrpEntry = pIrpEntry->Flink; } } // // If no pending IRP // if (FoundPendingIrp == FALSE) { break; } // // Get the first queued receive packet // pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink; NPROT_REMOVE_ENTRY_LIST(pRcvPacketEntry); pOpenContext->RecvPktCount --; NPROT_RELEASE_LOCK(&pOpenContext->Lock); NPROT_DEREF_OPEN(pOpenContext); // Service: dequeue rcv packet pRcvPacket = NPROT_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry); // // Copy as much data as possible from the receive packet to // the IRP MDL. // pDst = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); __analysis_assume(pDst); NPROT_ASSERT(pDst != NULL); // since it was already mapped BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress); pNdisBuffer = NDIS_PACKET_FIRST_NDIS_BUFFER(pRcvPacket); // // Copy the data in the received packet into the buffer provided by the client. // If the length of the receive packet is greater than length of the given buffer, // we just copy as many bytes as we can. Once the buffer is full, we just discard // the rest of the data, and complete the IRP sucessfully even we only did a partial copy. // while (BytesRemaining && (pNdisBuffer != NULL)) { #ifndef WIN9X NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority); if (pSrc == NULL) { DEBUGP(DL_FATAL, ("ServiceReads: Open %p, QueryBuffer failed for buffer %p\n", pOpenContext, pNdisBuffer)); break; } #else NdisQueryBuffer(pNdisBuffer, &pSrc, &BytesAvailable); #endif if (BytesAvailable) { ULONG BytesToCopy = MIN(BytesAvailable, BytesRemaining); NPROT_COPY_MEM(pDst, pSrc, BytesToCopy); BytesRemaining -= BytesToCopy; pDst += BytesToCopy; } NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer); } // // Complete the IRP. // pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining; DEBUGP(DL_INFO, ("ServiceReads: Open %p, IRP %p completed with %d bytes\n", pOpenContext, pIrp, pIrp->IoStatus.Information)); IoCompleteRequest(pIrp, IO_NO_INCREMENT); // // Free up the receive packet - back to the miniport if it // belongs to it, else reclaim it (local copy). // if (NdisGetPoolFromPacket(pRcvPacket) != pOpenContext->RecvPacketPool) { NdisReturnPackets(&pRcvPacket, 1); } else { ndisprotFreeReceivePacket(pOpenContext, pRcvPacket); } NPROT_DEREF_OPEN(pOpenContext); // took out pended Read NPROT_ACQUIRE_LOCK(&pOpenContext->Lock); pOpenContext->PendedReadCount--; } NPROT_RELEASE_LOCK(&pOpenContext->Lock); NPROT_DEREF_OPEN(pOpenContext); // temp ref - service reads }
/*************************************************************************** Routine Description: A protocol calls the R6040TransferData request (indirectly via NdisTransferData) from within its Receive event handler to instruct the driver to copy the contents of the received packet a specified packet buffer. Arguments: MiniportAdapterContext - Context registered with the wrapper, really a pointer to the adapter. MiniportReceiveContext - The context value passed by the driver on its call to NdisMEthIndicateReceive. The driver can use this value to determine which packet, on which adapter, is being received. ByteOffset - An unsigned integer specifying the offset within the received packet at which the copy is to begin. If the entire packet is to be copied, ByteOffset must be zero. BytesToTransfer - An unsigned integer specifying the number of bytes to copy. It is legal to transfer zero bytes; this has no effect. If the sum of ByteOffset and BytesToTransfer is greater than the size of the received packet, then the remainder of the packet (starting from ByteOffset) is transferred, and the trailing portion of the receive buffer is not modified. Packet - A pointer to a descriptor for the packet storage into which the MAC is to copy the received packet. BytesTransfered - A pointer to an unsigned integer. The MAC writes the actual number of bytes transferred into this location. This value is not valid if the return status is STATUS_PENDING. Notes: - The MacReceiveContext will be a pointer to the open block for the packet. *****************************************************************************/ NDIS_STATUS R6040TransferData( OUT PNDIS_PACKET InPacket, OUT PUINT BytesTransferred, IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_HANDLE MiniportReceiveContext, IN UINT ByteOffset, IN UINT BytesToTransfer) { // Variables for the number of bytes to copy, how much can be // copied at this moment, and the total number of bytes to copy. UINT BytesLeft, BytesNow, BytesWanted; // Current NDIS_BUFFER to copy into PNDIS_BUFFER CurBuffer; PUCHAR BufStart; // Address on the adapter to copy from const UCHAR *CurCardLoc; // Length and offset into the buffer. UINT BufLen, BufOff; // The adapter to transfer from. PR6040_ADAPTER Adapter = ((PR6040_ADAPTER)MiniportReceiveContext); //RETAILMSG(R6040DBG, (TEXT("R6040TransferData()\r\n"))); NdisDprAcquireSpinLock(&Adapter->RcvLock); // Add the packet header onto the offset. ByteOffset+= R6040_HEADER_SIZE; // See how much data there is to transfer. if (ByteOffset+BytesToTransfer > Adapter->PacketLen) { if (Adapter->PacketLen < ByteOffset) { *BytesTransferred = 0; return(NDIS_STATUS_FAILURE); } BytesWanted = Adapter->PacketLen - ByteOffset; } else { BytesWanted = BytesToTransfer; } // Set the number of bytes left to transfer BytesLeft = BytesWanted; { // Copy data from the card -- it is not completely stored in the // adapter structure. // Determine where the copying should start. CurCardLoc = Adapter->PacketHeaderLoc + ByteOffset; // Get location to copy into NdisQueryPacket(InPacket, NULL, NULL, &CurBuffer, NULL); NdisQueryBuffer(CurBuffer, (PVOID *)&BufStart, &BufLen); BufOff = 0; // Loop, filling each buffer in the packet until there // are no more buffers or the data has all been copied. while (CurBuffer && BytesLeft > 0) { // See how much data to read into this buffer. if ((BufLen-BufOff) > BytesLeft) { BytesNow = BytesLeft; } else { BytesNow = (BufLen - BufOff); } // Copy up the data. NdisMoveMemory(BufStart+BufOff,CurCardLoc,BytesNow); // Update offsets and counts CurCardLoc += BytesNow; BytesLeft -= BytesNow; // Is the transfer done now? if (BytesLeft == 0) { break; } // Was the end of this packet buffer reached? BufOff += BytesNow; if (BufOff == BufLen) { NdisGetNextBuffer(CurBuffer, &CurBuffer); if (CurBuffer == (PNDIS_BUFFER)NULL) { break; } NdisQueryBuffer(CurBuffer, (PVOID *)&BufStart, &BufLen); BufOff = 0; } } *BytesTransferred = BytesWanted - BytesLeft; NdisDprReleaseSpinLock(&Adapter->RcvLock); return(NDIS_STATUS_SUCCESS); } NdisDprReleaseSpinLock(&Adapter->RcvLock); return(NDIS_STATUS_SUCCESS); }
int filter_packet(int direction, int iface, PNDIS_PACKET packet) { PNDIS_BUFFER buffer; UINT packet_len, buffer_len, hdr_len; int result; void *pointer; struct ether_hdr *ether_hdr; struct ip_hdr *ip_hdr; //lint -e506 -e613 -e774 -e831 -e550 NdisQueryPacket(packet, NULL, NULL, &buffer, &packet_len); if (packet_len < sizeof(struct ether_hdr)) { DBGOUT(("filter_packet: too small packet for ether_hdr! (%u)\n", packet_len)); return FILTER_UNKNOWN; } /* process ether_hdr */ NdisQueryBufferSafe(buffer, ðer_hdr, &buffer_len, LowPagePriority); if (buffer_len < sizeof(struct ether_hdr)) { DBGOUT(("filter_packet: too small buffer for ether_hdr! (%u)\n", buffer_len)); return FILTER_UNKNOWN; } // go to the next header if (buffer_len > sizeof(struct ether_hdr)) { pointer = (char *)ether_hdr + sizeof(struct ether_hdr); buffer_len -= sizeof(struct ether_hdr); } else { // use next buffer in chain NdisGetNextBuffer(buffer, &buffer); NdisQueryBufferSafe(buffer, &pointer, &buffer_len, LowPagePriority); } if (ether_hdr->ether_type == ETHERNET_TYPE_IP) { /* process ip_hdr */ if (buffer_len < sizeof(struct ip_hdr)) { DBGOUT(("filter_packet: too small buffer for ip_hdr! (%u)\n", buffer_len)); return FILTER_UNKNOWN; } ip_hdr = (struct ip_hdr *)pointer; hdr_len = ip_hdr->ip_hl * 4; if (buffer_len < hdr_len) { DBGOUT(("filter_packet: too small buffer for ip_hdr! (%u vs. %u)\n", buffer_len, hdr_len)); return FILTER_UNKNOWN; } // go to the next header if (buffer_len > hdr_len) { pointer = (char *)ip_hdr + hdr_len; buffer_len -= hdr_len; } else { // use next buffer in chain NdisGetNextBuffer(buffer, &buffer); NdisQueryBufferSafe(buffer, &pointer, &buffer_len, LowPagePriority); } result = process_transp(direction, iface, ip_hdr->ip_p, ip_hdr, pointer, buffer_len); if (result != FILTER_ALLOW) return result; } // default behavior return FILTER_ALLOW; }
extern NDIS_STATUS IbmtokTransferData( IN NDIS_HANDLE MacBindingHandle, IN NDIS_HANDLE MacReceiveContext, IN UINT ByteOffset, IN UINT BytesToTransfer, OUT PNDIS_PACKET Packet, OUT PUINT BytesTransferred ) /*++ Routine Description: A protocol calls the IbmtokTransferData request (indirectly via NdisTransferData) from within its Receive event handler to instruct the MAC to copy the contents of the received packet a specified packet buffer. Arguments: MacBindingHandle - The context value returned by the MAC when the adapter was opened. In reality this is a pointer to IBMTOK. MacReceiveContext - The context value passed by the MAC on its call to NdisIndicateReceive. The MAC can use this value to determine which packet, on which adapter, is being received. ByteOffset - An unsigned integer specifying the offset within the received packet at which the copy is to begin. If the entire packet is to be copied, ByteOffset must be zero. BytesToTransfer - An unsigned integer specifying the number of bytes to copy. It is legal to transfer zero bytes; this has no effect. If the sum of ByteOffset and BytesToTransfer is greater than the size of the received packet, then the remainder of the packet (starting from ByteOffset) is transferred, and the trailing portion of the receive buffer is not modified. Packet - A pointer to a descriptor for the packet storage into which the MAC is to copy the received packet. BytesTransfered - A pointer to an unsigned integer. The MAC writes the actual number of bytes transferred into this location. This value is not valid if the return status is STATUS_PENDING. Return Value: The function value is the status of the operation. --*/ { PIBMTOK_ADAPTER Adapter; NDIS_STATUS StatusToReturn; Adapter = PIBMTOK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle); NdisAcquireSpinLock(&Adapter->Lock); Adapter->References++; if (!Adapter->NotAcceptingRequests) { PIBMTOK_OPEN Open = PIBMTOK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle); if (!Open->BindingShuttingDown) { // // The code in this section is quite similar to the // code in CopyFromPacketToPacket. It could easily go // into its own routine, except that it is not likely // to be used in any other implementation. // SRAM_PTR SourceReceiveBuffer = Adapter->IndicatedReceiveBuffer; // // Holds the count of the number of ndis buffers comprising // the destination packet. // UINT DestinationBufferCount; // // Points to the buffer into which we are putting data. // PNDIS_BUFFER DestinationCurrentBuffer; // // Holds the virtual address of the current destination // buffer. // PVOID DestinationVirtualAddress; // // Holds the virtual address of the current source buffer. // PRECEIVE_BUFFER SourceBufferAddress; // // Holds the address of the data in the current source buffer. // PVOID SourceVirtualAddress; // // Holds the length of the current destination buffer. // UINT DestinationCurrentLength; // // Holds the length of the current source buffer. // UINT SourceCurrentLength; // // Keep a local variable of BytesTransferred so we aren't // referencing through a pointer. // UINT LocalBytesTransferred = 0; USHORT PortValue; Open->References++; NdisReleaseSpinLock(&Adapter->Lock); *BytesTransferred = 0; ASSERT(sizeof(UINT) >= 2); ASSERT(sizeof(UINT) == sizeof(NDIS_HANDLE)); // // Get the first buffer of the destination. // NdisQueryPacket( Packet, NULL, &DestinationBufferCount, &DestinationCurrentBuffer, NULL ); // // Could have a null packet. // if (DestinationBufferCount != 0) { NdisQueryBuffer( DestinationCurrentBuffer, &DestinationVirtualAddress, &DestinationCurrentLength ); // // Get the information for the first buffer of the source. // SourceBufferAddress = (PRECEIVE_BUFFER) ((PUCHAR)SRAM_PTR_TO_PVOID(Adapter, SourceReceiveBuffer) + 2); // // Adjust the address and length to account for the // header for this frame. // SourceVirtualAddress = SourceBufferAddress->FrameData + Adapter->IndicatedHeaderLength; NdisReadRegisterUshort(&SourceBufferAddress->BufferLength, &PortValue ); SourceCurrentLength = IBMSHORT_TO_USHORT(PortValue) - Adapter->IndicatedHeaderLength; // // Take care of boundary condition of zero length copy. // while (LocalBytesTransferred < BytesToTransfer) { // // Check to see whether we've exhausted the current // destination buffer. If so, move onto the next one. // if (!DestinationCurrentLength) { NdisGetNextBuffer( DestinationCurrentBuffer, &DestinationCurrentBuffer ); if (!DestinationCurrentBuffer) { // // We've reached the end of the packet. We // return with what we've done so far. (Which // must be shorter than requested.) // break; } NdisQueryBuffer( DestinationCurrentBuffer, &DestinationVirtualAddress, &DestinationCurrentLength ); continue; } // // Check to see whether we've exhausted the current // source buffer. If so, move onto the next one. // if (!SourceCurrentLength) { NdisReadRegisterUshort( &SourceBufferAddress->NextBuffer, &SourceReceiveBuffer ); if (SourceReceiveBuffer == NULL_SRAM_PTR) { // // We've reached the end of the frame. We // return with what we've done so far. (Which // must be shorter than requested.) // break; } SourceBufferAddress = (PRECEIVE_BUFFER) SRAM_PTR_TO_PVOID(Adapter, SourceReceiveBuffer); SourceVirtualAddress = (PVOID)SourceBufferAddress->FrameData; NdisReadRegisterUshort( &SourceBufferAddress->BufferLength, &SourceCurrentLength ); SourceCurrentLength = IBMSHORT_TO_USHORT( SourceCurrentLength ); continue; } // // Try to get us up to the point to start the copy. // if (ByteOffset) { if (ByteOffset > SourceCurrentLength) { // // What we want isn't in this buffer. // ByteOffset -= SourceCurrentLength; SourceCurrentLength = 0; continue; } else { SourceVirtualAddress = (PCHAR)SourceVirtualAddress + ByteOffset; SourceCurrentLength -= ByteOffset; ByteOffset = 0; } } // // Copy the data. // { // // Holds the amount of data to move. // UINT AmountToMove; // // Holds the amount desired remaining. // UINT Remaining = BytesToTransfer - LocalBytesTransferred; AmountToMove = ((SourceCurrentLength <= DestinationCurrentLength)? (SourceCurrentLength):(DestinationCurrentLength)); AmountToMove = ((Remaining < AmountToMove)? (Remaining):(AmountToMove)); IBMTOK_MOVE_FROM_MAPPED_MEMORY( DestinationVirtualAddress, SourceVirtualAddress, AmountToMove ); DestinationVirtualAddress = (PCHAR)DestinationVirtualAddress + AmountToMove; SourceVirtualAddress = (PCHAR)SourceVirtualAddress + AmountToMove; LocalBytesTransferred += AmountToMove; SourceCurrentLength -= AmountToMove; DestinationCurrentLength -= AmountToMove; } } *BytesTransferred = LocalBytesTransferred; } NdisAcquireSpinLock(&Adapter->Lock); Open->References--; StatusToReturn = NDIS_STATUS_SUCCESS; } else { StatusToReturn = NDIS_STATUS_REQUEST_ABORTED; } } else { if (Adapter->ResetInProgress) { StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS; } else if (Adapter->OpenInProgress) { StatusToReturn = NDIS_STATUS_FAILURE; } else { NdisWriteErrorLogEntry( Adapter->NdisAdapterHandle, NDIS_ERROR_CODE_DRIVER_FAILURE, 2, IBMTOK_ERRMSG_INVALID_STATE, 1 ); } } IBMTOK_DO_DEFERRED(Adapter); return StatusToReturn; }
extern NDIS_STATUS SonicTransferData( OUT PNDIS_PACKET Packet, OUT PUINT BytesTransferred, IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_HANDLE MiniportReceiveContext, IN UINT ByteOffset, IN UINT BytesToTransfer ) /*++ Routine Description: A protocol calls the SonicTransferData request (indirectly via NdisTransferData) from within its Receive event handler to instruct the driver to copy the contents of the received packet a specified paqcket buffer. Arguments: MiniportAdapterContext - Context registered with the wrapper, really a pointer to the adapter. MiniportReceiveContext - The context value passed by the driver on its call to NdisMEthIndicateReceive. The driver can use this value to determine which packet, on which adapter, is being received. ByteOffset - An unsigned integer specifying the offset within the received packet at which the copy is to begin. If the entire packet is to be copied, ByteOffset must be zero. BytesToTransfer - An unsigned integer specifying the number of bytes to copy. It is legal to transfer zero bytes; this has no effect. If the sum of ByteOffset and BytesToTransfer is greater than the size of the received packet, then the remainder of the packet (starting from ByteOffset) is transferred, and the trailing portion of the receive buffer is not modified. Packet - A pointer to a descriptor for the packet storage into which the MAC is to copy the received packet. BytesTransfered - A pointer to an unsigned integer. The MAC writes the actual number of bytes transferred into this location. This value is not valid if the return status is STATUS_PENDING. Return Value: The function value is the status of the operation. --*/ { // // Buffer is the buffer to copy from. // PCHAR Buffer = (PCHAR)MiniportReceiveContext + ByteOffset; // // Holds the count of the number of ndis buffers comprising the // destination packet. // UINT DestinationBufferCount; // // Points to the buffer into which we are putting data. // PNDIS_BUFFER DestinationCurrentBuffer; // // Points to the location in Buffer from which we are extracting data. // PUCHAR SourceCurrentAddress; // // Holds the virtual address of the current destination buffer. // PVOID DestinationVirtualAddress; // // Holds the length of the current destination buffer. // UINT DestinationCurrentLength; // // Keep a local variable of BytesTransferred so we aren't referencing // through a pointer. // UINT LocalBytesTransferred = 0; // // MiniportAdapterContext is not referenced. // MiniportAdapterContext; // // Take care of boundary condition of zero length copy. // if (BytesToTransfer == 0) { *BytesTransferred = 0; return NDIS_STATUS_SUCCESS; } // // Get the first buffer of the destination. // NdisQueryPacket( Packet, NULL, &DestinationBufferCount, &DestinationCurrentBuffer, NULL ); // // Could have a null packet. // if (DestinationBufferCount == 0) { *BytesTransferred = 0; return NDIS_STATUS_SUCCESS; } NdisQueryBuffer( DestinationCurrentBuffer, &DestinationVirtualAddress, &DestinationCurrentLength ); // // Set up the source address. // SourceCurrentAddress = Buffer; while (LocalBytesTransferred < BytesToTransfer) { // // Check to see whether we've exhausted the current destination // buffer. If so, move onto the next one. // if (DestinationCurrentLength == 0) { NdisGetNextBuffer( DestinationCurrentBuffer, &DestinationCurrentBuffer ); if (DestinationCurrentBuffer == NULL) { // // We've reached the end of the packet. We return // with what we've done so far. (Which must be shorter // than requested.) // break; } NdisQueryBuffer( DestinationCurrentBuffer, &DestinationVirtualAddress, &DestinationCurrentLength ); continue; } // // Copy the data. // { // // Holds the amount of data to move. // UINT AmountToMove; // // Holds the amount desired remaining. // UINT Remaining = BytesToTransfer - LocalBytesTransferred; AmountToMove = DestinationCurrentLength; AmountToMove = ((Remaining < AmountToMove)? (Remaining):(AmountToMove)); SONIC_MOVE_MEMORY( DestinationVirtualAddress, SourceCurrentAddress, AmountToMove ); SourceCurrentAddress += AmountToMove; LocalBytesTransferred += AmountToMove; DestinationCurrentLength -= AmountToMove; } } *BytesTransferred = LocalBytesTransferred; return NDIS_STATUS_SUCCESS; }
NTSTATUS NdisuioDoFastRead( IN PNDISUIO_OPEN_CONTEXT pOpenContext, IN PIRP pIrp ) /*++ Routine Description: Utility routine to copy received data into user buffers and complete READ IRPs. Arguments: pOpenContext - pointer to open context Return Value: None --*/ { PNDIS_PACKET pRcvPacket; PLIST_ENTRY pRcvPacketEntry; PUCHAR pSrc, pDst; ULONG BytesRemaining; // at pDst PNDIS_BUFFER pNdisBuffer; ULONG BytesAvailable; PPACKET_GROUP pGroup; CCHAR PriorityBoost = IO_NETWORK_INCREMENT; DEBUGP(DL_VERY_LOUD, ("FastRead: open %p/%x\n", pOpenContext, pOpenContext->Flags)); if (NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue)) return STATUS_UNSUCCESSFUL; // // Copy as much data as possible from the receive packet to // the IRP MDL. // #ifndef WIN9X pGroup = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); NUIO_ASSERT(pGroup != NULL); // since it was already mapped #else pGroup = MmGetSystemAddressForMdl(pIrp->MdlAddress); // Win9x #endif BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress); // // Get the first queued receive packet // pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink; pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry); do { NUIO_REMOVE_ENTRY_LIST(pRcvPacketEntry); pOpenContext->RecvPktCount--; NUIO_RELEASE_LOCK(&pOpenContext->Lock); NUIO_DEREF_OPEN(pOpenContext); // Service: dequeue rcv packet pNdisBuffer = pRcvPacket->Private.Head; pDst = pGroup->Data; BytesRemaining -= sizeof(PACKET_GROUP); while (BytesRemaining && (pNdisBuffer != NULL)) { #ifndef WIN9X NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority); if (pSrc == NULL) { DEBUGP(DL_FATAL, ("FastRead: Open %p, QueryBuffer failed for buffer %p\n", pOpenContext, pNdisBuffer)); break; } #else NdisQueryBuffer(pNdisBuffer, &pSrc, &BytesAvailable); #endif if (BytesAvailable) { ULONG BytesToCopy = MIN(BytesAvailable, BytesRemaining); NUIO_COPY_MEM(pDst, pSrc, BytesToCopy); BytesRemaining -= BytesToCopy; pDst += BytesToCopy; } NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer); } ndisuioFreeReceivePacket(pOpenContext, pRcvPacket); pGroup->Length = pDst - pGroup->Data; pGroup = (PPACKET_GROUP)pDst; NUIO_ACQUIRE_LOCK(&pOpenContext->Lock); if (NUIO_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue)) { PriorityBoost = IO_NO_INCREMENT; break; } pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink; pRcvPacket = NUIO_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry); NdisQueryPacketLength(pRcvPacket, &BytesAvailable); if (BytesRemaining < BytesAvailable + sizeof(PACKET_GROUP)) break; } while (TRUE); NUIO_RELEASE_LOCK(&pOpenContext->Lock); // // Complete the IRP. // pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining; DEBUGP(DL_INFO, ("FastRead: Open %p, IRP %p completed with %d bytes\n", pOpenContext, pIrp, pIrp->IoStatus.Information)); IoCompleteRequest(pIrp, PriorityBoost); return STATUS_SUCCESS; }
extern VOID Pc586CopyFromPacketToBuffer( IN PNDIS_PACKET Packet, IN UINT Offset, IN UINT BytesToCopy, OUT PCHAR Buffer, OUT PUINT BytesCopied ) /*++ Routine Description: Copy from an ndis packet into a buffer. Arguments: Packet - The packet to copy from. Offset - The offset from which to start the copy. BytesToCopy - The number of bytes to copy from the packet. Buffer - The destination of the copy. BytesCopied - The number of bytes actually copied. Can be less then BytesToCopy if the packet is shorter than BytesToCopy. Return Value: None --*/ { // // Holds the number of ndis buffers comprising the packet. // UINT NdisBufferCount; // // Points to the buffer from which we are extracting data. // PNDIS_BUFFER CurrentBuffer; // // Holds the virtual address of the current buffer. // PVOID VirtualAddress; // // Holds the length of the current buffer of the packet. // UINT CurrentLength; // // Keep a local variable of BytesCopied so we aren't referencing // through a pointer. // UINT LocalBytesCopied = 0; // // Take care of boundary condition of zero length copy. // *BytesCopied = 0; if (!BytesToCopy) return; // // Get the first buffer. // NdisQueryPacket( Packet, NULL, &NdisBufferCount, &CurrentBuffer, NULL ); // // Could have a null packet. // if (!NdisBufferCount) return; NdisQueryBuffer( CurrentBuffer, NULL, &VirtualAddress, &CurrentLength ); while (LocalBytesCopied < BytesToCopy) { if (!CurrentLength) { NdisGetNextBuffer( CurrentBuffer, &CurrentBuffer ); // // We've reached the end of the packet. We return // with what we've done so far. (Which must be shorter // than requested. // if (!CurrentBuffer) break; NdisQueryBuffer( CurrentBuffer, NULL, &VirtualAddress, &CurrentLength ); continue; } // // Try to get us up to the point to start the copy. // if (Offset) { if (Offset > CurrentLength) { // // What we want isn't in this buffer. // Offset -= CurrentLength; CurrentLength = 0; continue; } else { VirtualAddress = (PCHAR)VirtualAddress + Offset; CurrentLength -= Offset; Offset = 0; } } // // Copy the data. // { // // Holds the amount of data to move. // UINT AmountToMove; AmountToMove = ((CurrentLength <= (BytesToCopy - LocalBytesCopied))? (CurrentLength):(BytesToCopy - LocalBytesCopied)); PC586_MOVE_MEMORY( Buffer, VirtualAddress, AmountToMove ); Buffer = (PCHAR)Buffer + AmountToMove; VirtualAddress = (PCHAR)VirtualAddress + AmountToMove; LocalBytesCopied += AmountToMove; CurrentLength -= AmountToMove; } } *BytesCopied = LocalBytesCopied; }
VOID ReadPacket ( PNDIS_PACKET pPacket, PUCHAR pBuffer, ULONG ulBufSize ) /*++ Routine Description: Retrieves the buffer from a buffer descriptor. Arguments: Packet - Pointer to the buffer descriptor. pBuffer - Pointer to the buffer. ulBufSize - Size of the buffer. Return Value: None. Author: xiaonie 2012/07/12 --*/ { PVOID pVA; PNDIS_BUFFER pFirstBuffer, pNextBuffer; ULONG ulTotalLength; ULONG ulLen; PVOID pBuf = NULL; ULONG ulCount = 0; NdisQueryPacket(pPacket, NULL, NULL, &pFirstBuffer, NULL); while (pFirstBuffer != NULL) { NdisQueryBufferSafe(pFirstBuffer, &pVA, &ulLen, NormalPagePriority); if(!pVA) { // memory not enough DbgPrint("pVA == NULL, insufficient memory!\r\n"); break; } if (ulCount + ulLen > ulBufSize) { DbgPrint("ulCount + ulLen(%d) > ulBufSize(%d)\r\n", ulCount + ulLen, ulBufSize); break; } NdisMoveMemory(pBuffer + ulCount, pVA, ulLen); ulCount += ulLen; NdisGetNextBuffer(pFirstBuffer, &pNextBuffer); pFirstBuffer = pNextBuffer; } DbgPrint("ReadPacket: ulBufSize == %d, ulCount == %d\n", ulBufSize, ulCount); return; }
/* We've received a csum_blank packet, but we don't want to let Windows see it like. Calculate the checksum and dump it in the packet. This only works for TCP and UDP on IPv4; on anything else it's a no-op. */ static VOID FixupChecksum(PNDIS_PACKET packet) { PNDIS_BUFFER pbuf; PNDIS_BUFFER pbuf_next; UINT bufLength; UINT len; struct ethhdr *eh; struct iphdr *ih; uint32_t csum_accumulator; uint32_t *ptr; uint16_t *csum_field; NdisQueryPacket(packet, NULL, NULL, &pbuf, NULL); NdisQueryBufferSafe(pbuf, &eh, &bufLength, NormalPagePriority); if (!eh || bufLength < sizeof(*eh)) return; if (eh->proto != TPID_IPV4) { static BOOLEAN warned; if (!warned) { TraceWarning(("Asked to perform checksum calculation on non-IP ethernet prototocol %x!\n", eh->proto)); warned = TRUE; } return; } ih = (struct iphdr *)(eh + 1); bufLength -= sizeof(*eh); if (bufLength < sizeof(*ih) || bufLength < (UINT)(ih->len_version & 0x0f) * 4) return; ptr = (uint32_t *)((ULONG_PTR)ih + (ih->len_version & 0x0f)*4); len = ntohs(ih->tot_len) - (ih->len_version & 0x0f) * 4; bufLength -= (ih->len_version & 0x0f) * 4; if (bufLength > len) bufLength = len; if (ih->proto == IPPROTO_UDP) { if (bufLength < sizeof(struct udphdr)) return; csum_field = &((struct udphdr *)ptr)->checksum; } else if (ih->proto == IPPROTO_TCP) { if (bufLength < sizeof(struct tcphdr)) return; csum_field = &((struct tcphdr *)ptr)->checksum; } else { static BOOLEAN warned; /* Uh oh: don't know what this protocol is, so can't do checksum calculation for it. */ if (!warned) { TraceWarning(("Asked to perform checksum calculation for unknown protocol %d!\n", ih->proto)); warned = TRUE; } return; } if (ih->proto == IPPROTO_TCP) { struct tcp_pseudo_header tph; uint16_t csum; tph.saddr = ih->src; tph.daddr = ih->dest; tph.mbz = 0; tph.ptcl = IPPROTO_TCP; tph.length = htons((uint16_t)len); csum_accumulator = acc_ip_csum(&tph, sizeof(tph), 0); csum = fold_ip_csum(csum_accumulator); if (*csum_field != csum) TraceWarning(("invlid pseudo header checksum: expected %04x, found %04x\n", csum, *csum_field)); *csum_field = csum; } csum_accumulator = acc_ip_csum(ptr, bufLength, 0); len -= bufLength; while (len) { NdisGetNextBuffer(pbuf, &pbuf_next); if (pbuf_next == NULL) break; pbuf = pbuf_next; NdisQueryBufferSafe(pbuf, &ptr, &bufLength, NormalPagePriority); /* The buffer is already mapped into our RX buffer pool, so we should always be able to get a virtual address for it. */ XM_ASSERT(ptr != NULL); if (bufLength > len) bufLength = len; csum_accumulator = acc_ip_csum(ptr, bufLength, csum_accumulator); len -= bufLength; } *csum_field = ~fold_ip_csum(csum_accumulator); }
BOOLEAN PickPacketFromList(PADAPT pAdapt,PIRP Irp) { PIO_STACK_LOCATION IrpStack; ULONG PacketLenTotal=0; PNDIS_PACKET pRcvPacket; PLIST_ENTRY pRcvPacketEntry; PUCHAR pSrc, pDst; PUCHAR pDstFormer; ULONG BytesRemaining; // at pDst PNDIS_BUFFER pNdisBuffer; ULONG BytesAvailable; ULONG BytesToCopy; NdisAcquireSpinLock(&PacketListLock); if(!IsListEmpty(&PacketList)) { // // Get the first queued receive packet // pRcvPacketEntry = PacketList.Flink; RemoveEntryList(pRcvPacketEntry); PacketCount--; NdisReleaseSpinLock(&PacketListLock); pRcvPacket = SECLAB_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry); // // Copy as much data as possible from the receive packet to // the IRP MDL. // pDst = (PUCHAR)ExAllocatePool(NonPagedPool,MY_MTU); if(pDst==NULL) { DbgPrint("Can not allocate enough pool"); DbgBreakPoint(); } pDstFormer=pDst; IrpStack = IoGetCurrentIrpStackLocation(Irp); BytesRemaining = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; pNdisBuffer = pRcvPacket->Private.Head; while (BytesRemaining && (pNdisBuffer != NULL)) { NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority); if (pSrc == NULL) { DbgPrint("PickPacketFromList: QueryBuffer failed for buffer"); break; } if (BytesAvailable) { BytesToCopy = MIN(BytesAvailable, BytesRemaining); NdisMoveMemory(pDstFormer, pSrc, BytesToCopy); BytesRemaining -= BytesToCopy; pDstFormer += BytesToCopy; PacketLenTotal += BytesToCopy; } NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer); } // // Complete the IRP. // RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, pDst, PacketLenTotal); IoSetCancelRoutine(Irp,NULL); CompleteIrp(Irp,STATUS_SUCCESS,PacketLenTotal); ExFreePool(pDst); // // Free up the receive packet - back to the miniport if it // belongs to it, else reclaim it (local copy). // if (NdisGetPoolFromPacket(pRcvPacket) != pAdapt->RecvPacketPoolHandle) { NdisReturnPackets(&pRcvPacket, 1); } else { SecLabFreeReceivePacket(pAdapt, pRcvPacket); } } else { NdisReleaseSpinLock(&PacketListLock); return FALSE; } return TRUE; }