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); }
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; }
NTSTATUS TCPReceiveData ( PCONNECTION_ENDPOINT Connection, PNDIS_BUFFER Buffer, ULONG ReceiveLength, PULONG BytesReceived, ULONG ReceiveFlags, PTCP_COMPLETION_ROUTINE Complete, PVOID Context ) { PTDI_BUCKET Bucket; PUCHAR DataBuffer; UINT DataLen, Received; NTSTATUS Status; TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Called for %d bytes (on socket %x)\n", ReceiveLength, Connection->SocketContext)); NdisQueryBuffer(Buffer, &DataBuffer, &DataLen); Status = LibTCPGetDataFromConnectionQueue(Connection, DataBuffer, DataLen, &Received); if (Status == STATUS_PENDING) { Bucket = ExAllocateFromNPagedLookasideList(&TdiBucketLookasideList); if (!Bucket) { TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Failed to allocate bucket\n")); return STATUS_NO_MEMORY; } Bucket->Request.RequestNotifyObject = Complete; Bucket->Request.RequestContext = Context; ExInterlockedInsertTailList( &Connection->ReceiveRequest, &Bucket->Entry, &Connection->Lock ); TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Queued read irp\n")); TI_DbgPrint(DEBUG_TCP,("[IP, TCPReceiveData] Leaving. Status = STATUS_PENDING\n")); (*BytesReceived) = 0; } else { (*BytesReceived) = Received; } return Status; }
/*----------------------------------------------------------------------------*/ 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; }
void CAR6KMini::ndis2ether(NDIS_PACKET *pPacket,ETHERNET_MAC_HEADER *ethHead) { PNDIS_BUFFER pBuffer; PBYTE pBuffData; ULONG cbBuffData; ETHERNET_MAC_HEADER *pEthHead; NdisQueryPacketFirstBuffer(pPacket,&pBuffer); if(NULL == pBuffer) { return; } NdisQueryBuffer(pBuffer,&pBuffData,&cbBuffData); pEthHead = (ETHERNET_MAC_HEADER *)pBuffData; memcpy(ethHead,pEthHead,sizeof(ETHERNET_MAC_HEADER)); }
__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; }
/*************************************************************************** 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); }
/****************************************************************************** * * Name: MrvDrvSend() * * Description: NDIS miniport serialized send packet routine * * Conditions for Use: Protocol driver will call this routine to pass Tx NDIS_PACKET * * Arguments: * IN NDIS_HANDLE MiniportAdapterContext * IN PPNDIS_PACKET Packet * IN UINT Flags * * Return Value: NDIS_STATUS_RESOURCES or NDIS_STATUS_PENDING * * Notes: * *****************************************************************************/ NDIS_STATUS MrvDrvSend( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet, IN UINT Flags) { PMRVDRV_ADAPTER Adapter; NDIS_STATUS Status; PNDIS_BUFFER pBuffer; UINT BufferCount; UINT Length; UINT TotalPacketLength = 0; PVOID pVirtualAddr; PTxCtrlNode pTxNode; PUCHAR pHeader = NULL; Status = NDIS_STATUS_SUCCESS; Adapter = (PMRVDRV_ADAPTER)MiniportAdapterContext; DBGPRINT(DBG_TX, (L"+MrvDrvSend()\n")); // printf ("+MrvDrvSend()\n"); // In Deep Sleep Mode no packet can be sent out //012207 //if (Adapter->IsDeepSleep) if( !IsThisDsState(Adapter, DS_STATE_NONE) ) { //Status = NDIS_STATUS_NO_CABLE; return NDIS_STATUS_FAILURE; } // Check device removal status if( Adapter->SurpriseRemoved == TRUE ) { DBGPRINT(DBG_TX|DBG_WARNING,(TEXT("[MrvSend]: NDIS_STATUS_FAILURE by supriseRemoved\r\n"))); return NDIS_STATUS_FAILURE; } if( Adapter->bIsPendingReset == TRUE || Adapter->ChipResetting == 1) { DBGPRINT(DBG_TX|DBG_CMD|DBG_WARNING,(L"[MrvSend]: NDIS RETURN FAILURE by bIsPendingReset or ChipReset\r\n")); return NDIS_STATUS_FAILURE; } if ( Adapter->MediaConnectStatus == NdisMediaStateDisconnected ) { DBGPRINT(DBG_TX|DBG_WARNING, (L"***WARNING: OS attempted to send packet while disconnected!\r\n")); if (IsIndicateDisconnect(Adapter) == TRUE) { Ndis_MediaStatus_Notify(Adapter,NDIS_STATUS_MEDIA_DISCONNECT); } else { NdisMSleep(100000); ///Sleep 100ms temporally } //dralee_20060712 ResetAllScanTypeAndPower(Adapter); CleanUpSingleTxBuffer(Adapter); ResetRxPDQ(Adapter); return NDIS_STATUS_FAILURE; } if( Adapter->bIsScanInProgress == TRUE ) { return NDIS_STATUS_SUCCESS; } *((ULONG *)(&Packet->MacReserved[0])) = GetTickCount(); // check if in key absent state, if so, block all packet other than // 802.1x if ( (Adapter->EncryptionStatus == Ndis802_11Encryption2KeyAbsent )|| (Adapter->EncryptionStatus == Ndis802_11Encryption3KeyAbsent ) ) { pTxNode = &Adapter->TxNode; NdisQueryPacket( Packet, NULL, &BufferCount, &pBuffer, &TotalPacketLength ); if (!pBuffer || !BufferCount || !TotalPacketLength) { return NDIS_STATUS_FAILURE; } NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length); pHeader = (PUCHAR)pVirtualAddr; if ( TotalPacketLength < 14 ) { // malformed packet, blocked! DBGPRINT(DBG_TX|DBG_WARNING,(L"Got packet with size less than 14 bytes, reject!\n")); return NDIS_STATUS_FAILURE; } if ( (pHeader[12] != 0x88) || (pHeader[13] != 0x8E) ) { DBGPRINT(DBG_TX|DBG_WARNING,(L"Still no key and packet type(0x%x 0x%x)is not 802.1x , drop!\n", pHeader[12], pHeader[13])); return NDIS_STATUS_FAILURE; } }// if ( (Adapter->EncryptionStatus == Ndis802_11Encryption2KeyAbsent )|| (Adapter->EncryptionStatus == Ndis802_11Encryption3KeyAbsent ) ) if(Adapter->TCloseWZCFlag==WZC_Ignore_Send_EAPOL_START) { if ( (Adapter->EncryptionStatus == Ndis802_11Encryption2Enabled )||(Adapter->EncryptionStatus == Ndis802_11Encryption2KeyAbsent )||(Adapter->EncryptionStatus == Ndis802_11Encryption3Enabled )||(Adapter->EncryptionStatus == Ndis802_11Encryption3KeyAbsent ) ) { pTxNode = &Adapter->TxNode; NdisQueryPacket( Packet, NULL, &BufferCount, &pBuffer, &TotalPacketLength ); if (!pBuffer || !BufferCount || !TotalPacketLength) { return NDIS_STATUS_FAILURE; } NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length); pHeader = (PUCHAR)pVirtualAddr; if ( (pHeader[12] == 0x88) && (pHeader[13] == 0x8E)&& (pHeader[14] == 0x01) &&(pHeader[15] == 0x01) ) { DBGPRINT(DBG_TX|DBG_HELP,(L"Temporary don't send EAPOL-start!!EncryptionStatus=0x%x, (0x%x, 0x%x, 0x%x, 0x%x)\n", Adapter->EncryptionStatus, pHeader[12], pHeader[13], pHeader[14], pHeader[15])); return NDIS_STATUS_SUCCESS; } } } EnterCriticalSection(&Adapter->TxCriticalSection); if(Adapter->TxPacketCount >= (MAX_TX_PACKETS-1) ) { UCHAR sts; //DBGPRINT(DBG_ERROR,(L"Tx queue is still full (count=%d), return FAILURE for this packet\r\n",Adapter->TxPacketCount)); sts = TxPacketEnQueue(Adapter, Packet); if( sts == TRUE ) //101607 { Adapter->TxPacketCount++; LeaveCriticalSection(&Adapter->TxCriticalSection); return NDIS_STATUS_SUCCESS; } else if ( sts == EQ_REPLACE_QUEUE ) { LeaveCriticalSection(&Adapter->TxCriticalSection); DBGPRINT(DBG_ERROR,(L"Replace a queued packet:%d\n\r",Adapter->TxPacketCount)); return NDIS_STATUS_SUCCESS; } else { LeaveCriticalSection(&Adapter->TxCriticalSection); //NdisMSleep(2000); DBGPRINT(DBG_ERROR,(L"Throw out current packet:%d\n\r",Adapter->TxPacketCount)); //return success otherwise the endpoint may retransmit this packet that low down the throughput. return NDIS_STATUS_SUCCESS; } } //record how many tx pkt is sent. Adapter->TxPacketSend++; DBGPRINT(DBG_TX|DBG_HELP,(L"[Marvell:MrvDrvSend] Adapter->TxPacketSend=%d\n", Adapter->TxPacketSend)); if ( TxPacketEnQueue(Adapter, Packet) != TRUE) { LeaveCriticalSection(&Adapter->TxCriticalSection); return NDIS_STATUS_SUCCESS; } Adapter->TxPacketCount++; LeaveCriticalSection(&Adapter->TxCriticalSection); if ( Adapter->SentPacket == NULL && Adapter->TxLock == 0 ) { // Fire TxThread! Adapter->SoftIntStatus |= MRVL_SOFT_INT_TxRequest; SetEvent(Adapter->hControllerInterruptEvent); } return NDIS_STATUS_SUCCESS; return Status; }
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; }
/****************************************************************************** * * 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; }
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; }
NDIS_STATUS CCX_SendSinglePacket( IN PMRVDRV_ADAPTER Adapter, IN PNDIS_PACKET Packet ) { NDIS_STATUS status; SDIO_TX_PKT downloadPkt; UCHAR *pCurPtr = (UCHAR *)downloadPkt.Buf.CmdBuf; UINT TotalPacketLength=0; UINT TotalBufferLength=0; UINT Length; UINT BufferCount; PNDIS_BUFFER pBuffer; PVOID pVirtualAddr; WCB LocalWCB; NdisQueryPacket(Packet, NULL, &BufferCount, &pBuffer, &TotalPacketLength); if(!pBuffer || !BufferCount || !TotalPacketLength) { DBGPRINT(DBG_CCX|DBG_HELP,(L"TX - NDIS buffer is not valid, return FAILURE \n")); status=NDIS_STATUS_FAILURE; goto end; } else { DBGPRINT(DBG_CCX|DBG_HELP,(L"BufferCount: %d\n", BufferCount)); } NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length); /// ///Fill the WCB /// NdisZeroMemory(&LocalWCB, sizeof(WCB)); LocalWCB.Status = MRVDRV_WCB_STATUS_USED; ///crlo:s36 ++ ///LocalWCB.PktLen = (USHORT)TotalPacketLength; LocalWCB.PktLen = (USHORT)Length; ///crlo:s36 -- LocalWCB.TxControl = 0; LocalWCB.PktPtr = sizeof(WCB); ///LocalWCB.PowerMgmt |= MRVDRV_WCB_POWER_MGMT_LAST_PACKET; downloadPkt.Buf.TxDataBuf.Wcb.PowerMgmt = MRVDRV_WCB_POWER_MGMT_LAST_PACKET; NdisMoveMemory((PVOID)LocalWCB.DestMACAdrHi, pVirtualAddr, MRVDRV_ETH_ADDR_LEN); NdisMoveMemory(pCurPtr, (PUCHAR)&LocalWCB, sizeof(WCB)); pCurPtr += sizeof(WCB); /// /// Fill in the packet data content /// ///NdisQueryBuffer(pBuffer, &pVirtualAddr, &Length); ///pHeader = (PUCHAR)pVirtualAddr; NdisMoveMemory(pCurPtr, (PUCHAR)pVirtualAddr, (USHORT)Length); pCurPtr += Length; ///downloadPkt.Len = ADD_SDIO_PKT_HDR_LENGTH(sizeof(WCB)); ///crlo:s36 ++ ///TotalBufferLength = TotalPacketLength; TotalBufferLength = Length; ///crlo:s36 -- TotalBufferLength += sizeof(WCB); downloadPkt.Len = ADD_SDIO_PKT_HDR_LENGTH(TotalBufferLength); downloadPkt.Type = IF_DATA_PKT; ///NdisZeroMemory(&downloadPkt.Buf.TxDataBuf.Wcb, sizeof(WCB)); ///downloadPkt.Buf.TxDataBuf.Wcb.PktPtr = sizeof(WCB); ///downloadPkt.Buf.TxDataBuf.Wcb.PowerMgmt = pwmgr; //RETAILMSG(1,(L"NULL pkt:%x\r\n",pwmgr)); DBGPRINT(DBG_CCX|DBG_HELP,(L"CCX_SendSinglePacket, calling If_DownloadPkt\n")); status = If_DownloadPkt(Adapter, &downloadPkt); if (!SD_API_SUCCESS(status)) { DBGPRINT(DBG_CCX|DBG_HELP,(L"[Marvell]SendSinglePacket:TX download failed! ")); status = NDIS_STATUS_FAILURE; goto end; } else { DBGPRINT(DBG_CCX|DBG_HELP,(L"CCX_SendSinglePacket, If_DownloadPkt success\n")); } end: return status; }
NTSTATUS DispTdiSendDatagram( PIRP Irp) /* * FUNCTION: TDI_SEND_DATAGRAM handler * ARGUMENTS: * Irp = Pointer to an I/O request packet * RETURNS: * Status of operation */ { PIO_STACK_LOCATION IrpSp; TDI_REQUEST Request; PTDI_REQUEST_KERNEL_SENDDG DgramInfo; PTRANSPORT_CONTEXT TranContext; NTSTATUS Status; TI_DbgPrint(DEBUG_IRP, ("Called.\n")); IrpSp = IoGetCurrentIrpStackLocation(Irp); DgramInfo = (PTDI_REQUEST_KERNEL_SENDDG)&(IrpSp->Parameters); TranContext = IrpSp->FileObject->FsContext; if (TranContext == NULL) { TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); Status = STATUS_INVALID_PARAMETER; goto done; } /* Initialize a send request */ Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; Request.RequestNotifyObject = DispDataRequestComplete; Request.RequestContext = Irp; Status = DispPrepareIrpForCancel( IrpSp->FileObject->FsContext, Irp, (PDRIVER_CANCEL)DispCancelRequest); if (NT_SUCCESS(Status)) { PVOID DataBuffer; UINT BufferSize; TI_DbgPrint(MID_TRACE,("About to query buffer %x\n", Irp->MdlAddress)); NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress, &DataBuffer, &BufferSize ); /* FIXME: DgramInfo->SendDatagramInformation->RemoteAddress must be of type PTDI_ADDRESS_IP */ TI_DbgPrint(MID_TRACE, ("About to call send routine %x\n", (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send))); if( (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send != NULL) ) { ULONG DataUsed = 0; Status = (*((PADDRESS_FILE)Request.Handle.AddressHandle)->Send)( Request.Handle.AddressHandle, DgramInfo->SendDatagramInformation, DataBuffer, BufferSize, &DataUsed); Irp->IoStatus.Information = DataUsed; } else { Status = STATUS_UNSUCCESSFUL; ASSERT(FALSE); } } done: if (Status != STATUS_PENDING) { DispDataRequestComplete(Irp, Status, Irp->IoStatus.Information); } else IoMarkIrpPending(Irp); TI_DbgPrint(DEBUG_IRP, ("Leaving.\n")); return Status; }
extern VOID Pc586ProcessLoopback( IN PPC586_ADAPTER Adapter ) /*++ Routine Description: This routine is responsible for indicating *one* packet on the loopback queue either completing it or moving on to the finish send queue. Arguments: Adapter - The adapter whose loopback queue we are processing. Return Value: None. --*/ { NdisAcquireSpinLock(&Adapter->Lock); if (Adapter->FirstLoopBack) { // // Packet at the head of the loopback list. // PNDIS_PACKET PacketToMove; // // The reserved portion of the above packet. // PPC586_RESERVED Reserved; // // Buffer for loopback. // CHAR Loopback[PC586_SIZE_OF_RECEIVE_BUFFERS]; // // The first buffer in the ndis packet to be loopbacked. // PNDIS_BUFFER FirstBuffer; // // The total amount of user data in the packet to be // loopbacked. // UINT TotalPacketLength; // // Eventually the address of the data to be indicated // to the transport. // PVOID BufferAddress; // // Eventually the length of the data to be indicated // to the transport. // UINT BufferLength; PacketToMove = Adapter->FirstLoopBack; Pc586RemovePacketFromLoopBack(Adapter); NdisReleaseSpinLock(&Adapter->Lock); Reserved = PPC586_RESERVED_FROM_PACKET(PacketToMove); // // See if we need to copy the data from the packet // into the loopback buffer. // // We need to copy to the local loopback buffer if // the first buffer of the packet is less than the // minimum loopback size AND the first buffer isn't // the total packet. // NdisQueryPacket( PacketToMove, NULL, NULL, &FirstBuffer, &TotalPacketLength ); NdisQueryBuffer( FirstBuffer, NULL, &BufferAddress, &BufferLength ); if ((BufferLength < PC586_SIZE_OF_RECEIVE_BUFFERS) && (BufferLength != TotalPacketLength)) { Pc586CopyFromPacketToBuffer( PacketToMove, 0, PC586_SIZE_OF_RECEIVE_BUFFERS, Loopback, &BufferLength ); BufferAddress = Loopback; } // // Indicate the packet to every open binding // that could want it. // MacFilterIndicateReceive( Adapter->FilterDB, PacketToMove, ((PCHAR)BufferAddress), BufferAddress, BufferLength, TotalPacketLength ); // // Remove the packet from the loopback queue and // either indicate that it is finished or put // it on the finishing up queue for the real transmits. // NdisAcquireSpinLock(&Adapter->Lock); if (!Reserved->STAGE.STAGE4.ReadyToComplete) { // // We can decrement the reference count on the open by one since // it is no longer being "referenced" by the packet on the // loopback queue. // PPC586_OPEN_FROM_BINDING_HANDLE( Reserved->MacBindingHandle )->References--; Pc586PutPacketOnFinishTrans( Adapter, PacketToMove ); } else { PPC586_OPEN Open; // // Increment the reference count on the open so that // it will not be deleted out from under us while // where indicating it. // Open = PPC586_OPEN_FROM_BINDING_HANDLE(Reserved->MacBindingHandle); Open->References++; NdisReleaseSpinLock(&Adapter->Lock); NdisCompleteSend( Open->NdisBindingContext, Reserved->RequestHandle, ((Reserved->STAGE.STAGE4.SuccessfulTransmit)? (NDIS_STATUS_SUCCESS):(NDIS_STATUS_FAILURE)) ); NdisAcquireSpinLock(&Adapter->Lock); // // We can decrement the reference count by two since it is // no longer being referenced to indicate and it is no longer // being "referenced" by the packet on the loopback queue. // Open->References -= 2; } // // If there is nothing else on the loopback queue // then indicate that reception is "done". // if (!Adapter->FirstLoopBack) { // // We need to signal every open binding that the // "receives" are complete. We increment the reference // count on the open binding while we're doing indications // so that the open can't be deleted out from under // us while we're indicating (recall that we can't own // the lock during the indication). // PPC586_OPEN Open; PLIST_ENTRY CurrentLink; CurrentLink = Adapter->OpenBindings.Flink; while (CurrentLink != &Adapter->OpenBindings) { Open = CONTAINING_RECORD( CurrentLink, PC586_OPEN, OpenList ); Open->References++; NdisReleaseSpinLock(&Adapter->Lock); NdisIndicateReceiveComplete(Open->NdisBindingContext); NdisAcquireSpinLock(&Adapter->Lock); Open->References--; CurrentLink = CurrentLink->Flink; } } } NdisReleaseSpinLock(&Adapter->Lock); }
NTSTATUS DispTdiReceiveDatagram( PIRP Irp) /* * FUNCTION: TDI_RECEIVE_DATAGRAM handler * ARGUMENTS: * Irp = Pointer to an I/O request packet * RETURNS: * Status of operation */ { PIO_STACK_LOCATION IrpSp; PTDI_REQUEST_KERNEL_RECEIVEDG DgramInfo; PTRANSPORT_CONTEXT TranContext; TDI_REQUEST Request; NTSTATUS Status; ULONG BytesReceived = 0; TI_DbgPrint(DEBUG_IRP, ("Called.\n")); IrpSp = IoGetCurrentIrpStackLocation(Irp); DgramInfo = (PTDI_REQUEST_KERNEL_RECEIVEDG)&(IrpSp->Parameters); TranContext = IrpSp->FileObject->FsContext; if (TranContext == NULL) { TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); Status = STATUS_INVALID_PARAMETER; goto done; } /* Initialize a receive request */ Request.Handle.AddressHandle = TranContext->Handle.AddressHandle; Request.RequestNotifyObject = DispDataRequestComplete; Request.RequestContext = Irp; Status = DispPrepareIrpForCancel( IrpSp->FileObject->FsContext, Irp, (PDRIVER_CANCEL)DispCancelRequest); if (NT_SUCCESS(Status)) { PVOID DataBuffer; UINT BufferSize; NdisQueryBuffer( (PNDIS_BUFFER)Irp->MdlAddress, &DataBuffer, &BufferSize ); Status = DGReceiveDatagram( Request.Handle.AddressHandle, DgramInfo->ReceiveDatagramInformation, DataBuffer, DgramInfo->ReceiveLength, DgramInfo->ReceiveFlags, DgramInfo->ReturnDatagramInformation, &BytesReceived, (PDATAGRAM_COMPLETION_ROUTINE)DispDataRequestComplete, Irp, Irp); } done: if (Status != STATUS_PENDING) { DispDataRequestComplete(Irp, Status, BytesReceived); } else IoMarkIrpPending(Irp); TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); return Status; }
NDIS_STATUS LoopSend( IN NDIS_HANDLE MacBindingHandle, IN PNDIS_PACKET Packet ) { PLOOP_ADAPTER Adapter = PLOOP_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle); PLOOP_OPEN Open = PLOOP_OPEN_FROM_BINDING_HANDLE(MacBindingHandle); UINT PacketLength; NDIS_STATUS StatusToReturn; DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, (" --> LoopSend\n")); // // Verify that the packet is correctly sized for the medium // NdisQueryPacket( Packet, NULL, NULL, NULL, &PacketLength ); if ((PacketLength < Adapter->MediumMinPacketLen) || (PacketLength > Adapter->MediumMaxPacketLen)) { return NDIS_STATUS_INVALID_PACKET; } NdisAcquireSpinLock(&Adapter->Lock); Adapter->References++; if (!Adapter->ResetInProgress) { if (!Open->BindingClosing) { PLOOP_PACKET_RESERVED Reserved = PLOOP_RESERVED_FROM_PACKET(Packet); BOOLEAN LoopIt=FALSE; PNDIS_BUFFER FirstBuffer; PVOID BufferVirtualAddress; UINT BufferLength; Open->References++; Reserved->Next = NULL; Reserved->MacBindingHandle = MacBindingHandle; Reserved->PacketLength = PacketLength; Reserved->HeaderLength = Adapter->MediumMacHeaderLen; NdisReleaseSpinLock(&Adapter->Lock); NdisQueryPacket( Packet, NULL, NULL, &FirstBuffer, NULL ); NdisQueryBuffer( FirstBuffer, &BufferVirtualAddress, &BufferLength ); NdisAcquireSpinLock(&Adapter->Lock); switch (Adapter->Medium) { case NdisMedium802_3: case NdisMediumDix: DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("Ethernet Dest Addr: %.2x-%.2x-%.2x-%.2x-%.2x-%.2x\n", *((PUCHAR)BufferVirtualAddress),*((PUCHAR)BufferVirtualAddress+1), *((PUCHAR)BufferVirtualAddress+2),*((PUCHAR)BufferVirtualAddress+3), *((PUCHAR)BufferVirtualAddress+4),*((PUCHAR)BufferVirtualAddress+5))); LoopIt = EthShouldAddressLoopBack( Adapter->Filter.Eth, BufferVirtualAddress ); break; case NdisMedium802_5: // check for source routing info and adjust header if (*((PUCHAR)BufferVirtualAddress+8) & 0x80) Reserved->HeaderLength += (*((PUCHAR)BufferVirtualAddress+14) & 0x1f); DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("TokenRing Dest Addr: %.2x-%.2x-%.2x-%.2x-%.2x-%.2x\n", *((PUCHAR)BufferVirtualAddress+2),*((PUCHAR)BufferVirtualAddress+3), *((PUCHAR)BufferVirtualAddress+4),*((PUCHAR)BufferVirtualAddress+5), *((PUCHAR)BufferVirtualAddress+6),*((PUCHAR)BufferVirtualAddress+7))); LoopIt = TrShouldAddressLoopBack( Adapter->Filter.Tr, (PCHAR)BufferVirtualAddress+2, Adapter->CurrentAddress ); if (!LoopIt) { // check if it's directed at ourselves TR_COMPARE_NETWORK_ADDRESSES_EQ( (PUCHAR)BufferVirtualAddress+2, (PUCHAR)(Adapter->Filter.Tr)->AdapterAddress, &BufferLength ); if (!BufferLength) LoopIt = TRUE; } break; case NdisMediumFddi: // check the address length bit and adjust the header length // if it is short. by default we assume a long address if (!(*((PUCHAR)BufferVirtualAddress) & 0x40)) { Reserved->HeaderLength = 2*FDDI_LENGTH_OF_SHORT_ADDRESS+1; BufferLength = FDDI_LENGTH_OF_SHORT_ADDRESS; } else BufferLength = FDDI_LENGTH_OF_LONG_ADDRESS; // hmmm... the DBGPRINT macro doesn't work too well to // dump out dest addr of varying lengths DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("Fddi Dest Addr: L(%d) %.2x-%.2x-%.2x-%.2x-%.2x-%.2x\n",BufferLength, *((PUCHAR)BufferVirtualAddress+1),*((PUCHAR)BufferVirtualAddress+2), *((PUCHAR)BufferVirtualAddress+3),*((PUCHAR)BufferVirtualAddress+4), *((PUCHAR)BufferVirtualAddress+5),*((PUCHAR)BufferVirtualAddress+6))); LoopIt = FddiShouldAddressLoopBack( Adapter->Filter.Fddi, (PCHAR)BufferVirtualAddress+1, BufferLength ); break; case NdisMediumWan: case NdisMediumLocalTalk: DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("LocalTalk Dest Addr: %.2x\n",((PUCHAR)BufferVirtualAddress)[0])); if ((((PUCHAR)BufferVirtualAddress)[1] == Adapter->CurrentAddress[0]) || LOOP_LT_IS_BROADCAST(((PUCHAR)BufferVirtualAddress)[0])) LoopIt = TRUE; else LoopIt = FALSE; break; case NdisMediumArcnet878_2: DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("Arcnet Dest Addr: %.2x\n",((PUCHAR)BufferVirtualAddress)[1])); if ((((PUCHAR)BufferVirtualAddress)[1] == Adapter->CurrentAddress[0]) || LOOP_ARC_IS_BROADCAST(((PUCHAR)BufferVirtualAddress)[1])) LoopIt = TRUE; else LoopIt = FALSE; break; default: // we should never get here... ASSERT(FALSE); break; } DBGPRINT(DBG_COMP_INIT, DBG_LEVEL_INFO, ("LoopIt = %c\n",(LoopIt)?'Y':'N')); if (LoopIt) { DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("Queueing packet %lx for loopback\n",Packet)); if (Adapter->LastLoopback == NULL) Adapter->Loopback = Packet; else PLOOP_RESERVED_FROM_PACKET(Adapter->LastLoopback)->Next = Packet; Adapter->LastLoopback = Packet; StatusToReturn = NDIS_STATUS_PENDING; } else { // // Since we're not looping this packet back, there's // nothing for us to do. just return success and make // like the packet was successfully sent out // Adapter->GeneralMandatory[GM_TRANSMIT_GOOD]++; Open->References--; StatusToReturn = NDIS_STATUS_SUCCESS; } } else StatusToReturn = NDIS_STATUS_CLOSING; } else StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS; Adapter->References--; // might not queue a packet, but setting the timer anyway ensures // we don't miss any packets sitting in the queue if (!Adapter->TimerSet) { Adapter->TimerSet = TRUE; NdisReleaseSpinLock(&Adapter->Lock); NdisSetTimer( &Adapter->LoopTimer, 25 ); } else NdisReleaseSpinLock(&Adapter->Lock); return StatusToReturn; }
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 }
// 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); }
VOID LtLoopProcessQueue( IN PLT_ADAPTER Adapter ) /*++ Routine Description: This routine is responsible for indicating *one* packet on the loopback queue either completing it or moving on to the finish send queue. Arguments: Adapter - The adapter whose loopback queue we are processing. Return Value: None. --*/ { // Packet at the head of the loopback list. PNDIS_PACKET Packet; // The reserved portion of the above packet. PLT_PACKET_RESERVED Reserved; // Buffer for loopback. CHAR Loopback[LT_MAX_INDICATE_SIZE]; // The first buffer in the ndis packet to be loopedback. PNDIS_BUFFER FirstBuffer; // The total amount of user data in the packet to be // loopedback. UINT PacketLength; // Eventually the address of the data to be indicated // to the transport. PCHAR BufferAddress, LinkAddress; // Eventually the length of the data to be indicated // to the transport. UINT BufferLength; PLIST_ENTRY p; PLT_OPEN Binding; NdisAcquireSpinLock(&Adapter->Lock); while((!IsListEmpty(&Adapter->LoopBack)) && ((Adapter->Flags & ADAPTER_RESET_IN_PROGRESS) == 0)) { p = RemoveHeadList(&Adapter->LoopBack); Packet = CONTAINING_RECORD( p, NDIS_PACKET, MacReserved); Reserved = (PLT_PACKET_RESERVED)Packet->MacReserved; // Remember this in CurrentLoopbackPacket in Adapter. // Used by Transfer data. Adapter->CurrentLoopbackPacket = Packet; NdisReleaseSpinLock(&Adapter->Lock); DBGPRINT(DBG_COMP_SEND, DBG_LEVEL_INFO, ("LtLoopProcessLoopback: Dequeued %lx \n", Packet)); // See if we need to copy the data from the packet // into the loopback buffer. // // We need to copy to the local loopback buffer if // the first buffer of the packet is less than the // minimum loopback size AND the first buffer isn't // the total packet. NdisQueryPacket( Packet, NULL, NULL, &FirstBuffer, &PacketLength); NdisQueryBuffer( FirstBuffer, &BufferAddress, &BufferLength); LinkAddress = BufferAddress; if (BufferLength != PacketLength) { // !!!BUGBUG: What do the sizes mean? LtUtilsCopyFromPacketToBuffer( Packet, LT_DGRAM_OFFSET, LT_MAX_INDICATE_SIZE, Loopback, &BufferLength); BufferAddress = Loopback; } else { // Adjust the buffer to account for the link header // which is not part of the lookahead. BufferAddress += LT_DGRAM_OFFSET; BufferLength -= LT_LINK_HEADER_LENGTH; } // Indicate the packet to every open binding // that could want it. Since loopback indications // are seralized, we use a NULL handle to indicate that it // is for a loopback packet. TransferData always gets the // first packet off the loopback queue. // Since we do not have an complicated filtering to do. // Just walk the list of Open bindings and Indicate the packet NdisAcquireSpinLock(&Adapter->Lock); LtRecvIndicatePacket( Adapter, LinkAddress, BufferAddress, BufferLength, PacketLength - LT_LINK_HEADER_LENGTH, (NDIS_HANDLE)NULL); NdisReleaseSpinLock(&Adapter->Lock); // We have indicated the packet to all the binding. Now we just // need to call send completion. DBGPRINT(DBG_COMP_LOOP, DBG_LEVEL_WARN, ("LtLoopProcessLoopback: NdisSendComplete Packet = %p\n", Packet )); Binding = (PLT_OPEN)(Reserved->MacBindingHandle); NdisCompleteSend( Binding->NdisBindingContext, Packet, NDIS_STATUS_SUCCESS); // Dereference the adapter and the binding for this completed // send. LtDeReferenceBinding(Binding); LtDeReferenceAdapter(Adapter); NdisAcquireSpinLock(&Adapter->Lock); } NdisReleaseSpinLock(&Adapter->Lock); return; }
NTSTATUS DispTdiSend( PIRP Irp) /* * FUNCTION: TDI_SEND handler * ARGUMENTS: * Irp = Pointer to an I/O request packet * RETURNS: * Status of operation */ { PIO_STACK_LOCATION IrpSp; PTDI_REQUEST_KERNEL_SEND SendInfo; PTRANSPORT_CONTEXT TranContext; NTSTATUS Status; ULONG BytesSent = 0; TI_DbgPrint(DEBUG_IRP, ("Called.\n")); IrpSp = IoGetCurrentIrpStackLocation(Irp); SendInfo = (PTDI_REQUEST_KERNEL_SEND)&(IrpSp->Parameters); TranContext = IrpSp->FileObject->FsContext; if (TranContext == NULL) { TI_DbgPrint(MID_TRACE, ("Bad transport context.\n")); Status = STATUS_INVALID_PARAMETER; goto done; } if (TranContext->Handle.ConnectionContext == NULL) { TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n")); Status = STATUS_INVALID_PARAMETER; goto done; } Status = DispPrepareIrpForCancel( IrpSp->FileObject->FsContext, Irp, (PDRIVER_CANCEL)DispCancelRequest); TI_DbgPrint(MID_TRACE,("TCPIP<<< Got an MDL: %x\n", Irp->MdlAddress)); if (NT_SUCCESS(Status)) { PVOID Data; UINT Len; NdisQueryBuffer( Irp->MdlAddress, &Data, &Len ); TI_DbgPrint(MID_TRACE,("About to TCPSendData\n")); Status = TCPSendData( TranContext->Handle.ConnectionContext, Data, SendInfo->SendLength, &BytesSent, SendInfo->SendFlags, DispDataRequestComplete, Irp); } done: if (Status != STATUS_PENDING) { DispDataRequestComplete(Irp, Status, BytesSent); } else IoMarkIrpPending(Irp); TI_DbgPrint(DEBUG_IRP, ("Leaving. Status is (0x%X)\n", Status)); return Status; }
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; }
NDIS_STATUS NIC_DRIVER_OBJECT::DriverSend( IN PNDIS_PACKET pPacket, IN UINT uFlags) { PCQUEUE_GEN_HEADER pobj; if (!(pobj = m_TQueue.Dequeue())) { m_bOutofResources = 1; DEBUG_PRINT((TEXT("[DM9ISA_d]: m_bOutofResources\n"))); return NDIS_STATUS_RESOURCES; } PNDIS_BUFFER pndisFirstBuffer; UINT uPhysicalBufferCount; UINT uBufferCount; UINT uTotalPacketLength; PNDIS_BUFFER pndisCurrBuffer; PU8 pcurr = (PU8)CQueueGetUserPointer(pobj); PVOID ptrBuffer; UINT nBuffer; U32 idx, check; NdisQueryPacket( pPacket, &uPhysicalBufferCount, &uBufferCount, &pndisFirstBuffer, &uTotalPacketLength); if (uTotalPacketLength > ETH_MAX_FRAME_SIZE) { return NDIS_STATUS_FAILURE; } uPhysicalBufferCount &= 0xFFFF; for (idx = 0, check = 0, pndisCurrBuffer = pndisFirstBuffer; idx < uBufferCount; idx++, pndisCurrBuffer = pndisCurrBuffer->Next) { NdisQueryBuffer(pndisCurrBuffer, &ptrBuffer, &nBuffer); if (!nBuffer) continue; NdisMoveMemory(pcurr, ptrBuffer, nBuffer); pcurr += nBuffer; check += nBuffer; } // of for gathering buffer if (uTotalPacketLength != check) return NDIS_STATUS_FAILURE; pobj->pPacket = (PVOID)pPacket; pobj->uFlags = uFlags; pobj->nLength = uTotalPacketLength; m_pLower->DeviceSend(pobj); #ifdef IMPL_SEND_INDICATION return NDIS_STATUS_PENDING; #else return NDIS_STATUS_SUCCESS; #endif }
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 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; }
NDIS_STATUS ElnkSend( IN NDIS_HANDLE MacBindingHandle, IN PNDIS_PACKET Packet ) /*++ Routine Description: The ElnkSend request instructs a MAC to transmit a packet through the adapter onto the medium. Arguments: MacBindingHandle - The context value returned by the MAC when the adapter was opened. In reality, it is a pointer to ELNK_OPEN. Packet - A pointer to a descriptor for the packet that is to be transmitted. Return Value: The function value is the status of the operation. --*/ { // // Holds the status that should be returned to the caller. // NDIS_STATUS StatusToReturn = NDIS_STATUS_PENDING; // // Pointer to the adapter. // PELNK_ADAPTER Adapter; if ELNKDEBUG DPrint2("ElnkSend Packet = %x\n",Packet); Adapter = PELNK_ADAPTER_FROM_BINDING_HANDLE(MacBindingHandle); NdisAcquireSpinLock(&Adapter->Lock); Adapter->References++; if (!Adapter->ResetInProgress) { PELNK_OPEN Open; Open = PELNK_OPEN_FROM_BINDING_HANDLE(MacBindingHandle); if (!Open->BindingShuttingDown) { UINT TotalPacketSize; // // Increment the references on the open while we are // accessing it in the interface. // Open->References++; NdisReleaseSpinLock(&Adapter->Lock); // // It is reasonable to do a quick check and fail if the packet // is larger than the maximum an ethernet can handle. // NdisQueryPacket( Packet, NULL, NULL, NULL, &TotalPacketSize ); NdisAcquireSpinLock(&Adapter->Lock); if ((!TotalPacketSize) || (TotalPacketSize > MAXIMUM_ETHERNET_PACKET_SIZE)) { Open->References--; StatusToReturn = NDIS_STATUS_RESOURCES; } else { PELNK_RESERVED Reserved = PELNK_RESERVED_FROM_PACKET(Packet); PNDIS_BUFFER FirstBuffer; PUCHAR BufferVA; UINT Length; // // Set Reserved->Loopback. // NdisQueryPacket(Packet, NULL, NULL, &FirstBuffer, NULL); // // Get VA of first buffer // NdisQueryBuffer( FirstBuffer, (PVOID *)&BufferVA, &Length ); if (Open->ProtOptionFlags & NDIS_PROT_OPTION_NO_LOOPBACK){ Reserved->Loopback = FALSE; } else { Reserved->Loopback = EthShouldAddressLoopBack(Adapter->FilterDB, BufferVA); } Reserved->MacBindingHandle = MacBindingHandle; // // Put on the stage queue. // if (!Adapter->LastStagePacket) { Adapter->FirstStagePacket = Packet; } else { PELNK_RESERVED_FROM_PACKET(Adapter->LastStagePacket)->Next = Packet; } Adapter->LastStagePacket = Packet; Reserved->Next = NULL; Adapter->TransmitsQueued++; // // Only try to push it through the stage queues // if somebody else isn't already doing it and // there is some hope of moving some packets // ahead. // while (!Adapter->AlreadyProcessingStage && Adapter->FirstStagePacket && Adapter->StageOpen ) { ElnkStagedAllocation(Adapter); } } // // We leave the reference for the pending send. // } else { StatusToReturn = NDIS_STATUS_CLOSING; } } else { StatusToReturn = NDIS_STATUS_RESET_IN_PROGRESS; } ELNK_DO_DEFERRED(Adapter); return StatusToReturn; }
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; }
/* * 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 */ }