Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 6
0
 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));
 }
Exemplo n.º 7
0
__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;
}
Exemplo n.º 8
0
/***************************************************************************
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);
}
Exemplo n.º 9
0
/******************************************************************************
 *
 *  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;
} 
Exemplo n.º 10
0
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;
}
Exemplo n.º 11
0
/******************************************************************************
 *
 *  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;
}
Exemplo n.º 12
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;

}
Exemplo n.º 13
0
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;
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
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);

}
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
0
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;
}
Exemplo n.º 18
0
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
}
Exemplo n.º 19
0
// 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);
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
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;
}
Exemplo n.º 22
0
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;
}
Exemplo n.º 23
0
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
}
Exemplo n.º 24
0
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;
}
Exemplo n.º 25
0
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;
}
Exemplo n.º 26
0
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;
}
Exemplo n.º 27
0
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;

}
Exemplo n.º 28
0
/*
 * 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 */
}