示例#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);
}
示例#2
0
VOID FreeNdisPacketX
( PNDIS_PACKET Packet,
  PCHAR File,
  UINT Line )
/*
 * FUNCTION: Frees an NDIS packet
 * ARGUMENTS:
 *     Packet = Pointer to NDIS packet to be freed
 */
{
    PNDIS_BUFFER Buffer, NextBuffer;

    TI_DbgPrint(DEBUG_PBUFFER, ("Packet (0x%X)\n", Packet));

    /* Free all the buffers in the packet first */
    NdisQueryPacket(Packet, NULL, NULL, &Buffer, NULL);
    for (; Buffer != NULL; Buffer = NextBuffer) {
        PVOID Data;
        UINT Length;

        NdisGetNextBuffer(Buffer, &NextBuffer);
        XNdisQueryBuffer(Buffer, &Data, &Length);
	UntrackFL(File,Line,Buffer);
        NdisFreeBuffer(Buffer);
        exFreePool(Data);
    }

    /* Finally free the NDIS packet descriptor */
    UntrackFL(File,Line,Packet);
    NdisFreePacket(Packet);
}
示例#3
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;
}
示例#4
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;
}
示例#5
0
VOID
ArcFreeNdisPacket(
    IN PARC_PACKET Packet
    )
/*++

Routine description:

    This routine takes an arcnet packet and frees up the corresponding
    Ndis packet built for it.

Arguments:

    Packet - The packet to free up.

Return values:

    None

--*/
{
    PNDIS_BUFFER NdisBuffer, NextNdisBuffer;

    NdisQueryPacket(
        &(Packet->TmpNdisPacket),
        NULL,
        NULL,
        &NdisBuffer,
        NULL
        );

    while (NdisBuffer != NULL) {

        NdisGetNextBuffer(
            NdisBuffer,
            &NextNdisBuffer
            );

        NdisFreeBuffer(
            NdisBuffer
            );

        NdisBuffer = NextNdisBuffer;
    }

    NdisReinitializePacket(&(Packet->TmpNdisPacket));

}
/*----------------------------------------------------------------------------*/
VOID kalCopyFrame(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, OUT PUINT_8 pucDestBuffer)
{
	PNDIS_PACKET prNdisPacket;
	PNDIS_BUFFER prNdisBuffer, prNextNdisBuffer;
	UINT u4PacketLen;
	UINT u4BytesToCopy;
	PVOID pvMbuf;
	UINT u4MbufLength;
	UINT u4BytesCopied;

	ASSERT(pvPacket);

	prNdisPacket = (PNDIS_PACKET) pvPacket;
	NdisQueryPacket(prNdisPacket, NULL, NULL, &prNdisBuffer, &u4PacketLen);

	u4BytesToCopy = u4PacketLen;
	u4BytesCopied = 0;

	while (u4BytesToCopy != 0) {

#ifdef NDIS51_MINIPORT
		NdisQueryBufferSafe(prNdisBuffer, &pvMbuf, &u4MbufLength, HighPagePriority);
#else
		NdisQueryBuffer(prNdisBuffer, &pvMbuf, &u4MbufLength);
#endif				/* NDIS51_MINIPORT */

		if (pvMbuf == (PVOID) NULL) {
			ASSERT(pvMbuf);
			break;
		}

		NdisMoveMemory((PVOID) pucDestBuffer, pvMbuf, u4MbufLength);

		u4BytesToCopy -= u4MbufLength;
		u4BytesCopied += u4MbufLength;
		pucDestBuffer += u4MbufLength;

		NdisGetNextBuffer(prNdisBuffer, &prNextNdisBuffer);
		prNdisBuffer = prNextNdisBuffer;
	}

	ASSERT(u4BytesCopied == u4PacketLen);

	return;
}
示例#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;
}
示例#8
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 */
}
示例#9
0
INT
PacketReceivePacket(
	IN    NDIS_HANDLE         ProtocolBindingContext,
	IN    PNDIS_PACKET        Packet
)
{
	UINT                bytesTransfered = 0;
	POPEN_INSTANCE      open;
	PIRP                irp;
	PNDIS_PACKET        myPacket;
	PLIST_ENTRY         packetListEntry;
	ULONG               bufferLength;
	PPACKET_RESERVED    reserved;
	PIO_STACK_LOCATION  irpSp;
	PMDL                mdl;
	PVOID               startAddress;
	NTSTATUS           status;

	// DebugPrint(("PacketReceivePacket\n"));

	open = (POPEN_INSTANCE)ProtocolBindingContext;

	packetListEntry = ExInterlockedRemoveHeadList(
											&open->RcvList,
											&open->RcvQSpinLock
											);

	if (packetListEntry == NULL) {
		// DebugPrint(("No pending read, dropping packets\n"));
		return 0;
	}

	reserved = CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement);
	myPacket = CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);

	irp = RESERVED(myPacket)->Irp;
	irpSp = IoGetCurrentIrpStackLocation(irp);

	// We don't have to worry about the situation where the IRP is cancelled
	// after we remove it from the queue and before we reset the cancel
	// routine because the cancel routine has been coded to cancel an IRP
	// only if it's in the queue.

	IoSetCancelRoutine(irp, NULL);

	// Following block of code locks the destination packet
	// MDLs in a safe manner. This is a temporary workaround
	// for NdisCopyFromPacketToPacket that currently doesn't use
	// safe functions to lock pages of MDL. This is required to
	// prevent system from bugchecking under low memory resources.
	//
	{
		PVOID           virtualAddress;
		PNDIS_BUFFER    firstBuffer, nextBuffer;
		ULONG           totalLength;

		NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength);
		while( firstBuffer ) {
			NdisQueryBufferSafe( firstBuffer, &virtualAddress, &totalLength, NormalPagePriority );
			if(!virtualAddress) {
				status = STATUS_INSUFFICIENT_RESOURCES;
				goto CleanExit;
			}
			NdisGetNextBuffer(firstBuffer,  &nextBuffer);
			firstBuffer = nextBuffer;
		}
	}

	NdisChainBufferAtFront( myPacket, irp->MdlAddress );
	bufferLength=irpSp->Parameters.Read.Length;
	NdisCopyFromPacketToPacket( myPacket, 0, bufferLength, Packet, 0,  &bytesTransfered );

CleanExit:
	NdisFreePacket(myPacket);
	irp->IoStatus.Status = status;
	irp->IoStatus.Information = bytesTransfered;
	IoCompleteRequest(irp, IO_NO_INCREMENT);
	// DebugPrint(("BytesTransfered:%d\n", bytesTransfered));
	IoDecrement(open);
	return 0;
}
示例#10
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;

}
示例#11
0
BOOLEAN  
cdc_ncm_fill_tx_frame(PMP_ADAPTER Adapter,PNDIS_PACKET Packet,PTCB ptcb, NCMDWORD sign)
{
	PMP_USBPIPE  usbpipe = Adapter->UsbPipeForNIC;
	PUSB_CDC_NCM_NTH16  nth16;
	PUSB_CDC_NCM_NDP16 ndp16;
	USHORT n = 0, index, ndplen;
	UINT           PacketLength;  
	PNDIS_BUFFER   CurrentBuffer = NULL;
	PVOID          VirtualAddress = NULL;
	UINT           CurrentLength;
	BOOLEAN        bResult = TRUE;
	int            maxpacketsize;
	int max_datagrams;
	maxpacketsize=usbpipe->InterfaceData->Pipes[usbpipe->BulkPipeOutput].MaximumPacketSize;

	if (Packet == NULL) {
		return TRUE;
	}

	 max_datagrams=usbpipe->tx_max_datagrams;

	if (0==ptcb->ulSize) {

		/* fill out the initial 16-bit NTB header */
		nth16 = (PUSB_CDC_NCM_NTH16 )memset(tcb_put(ptcb, sizeof(USB_CDC_NCM_NTH16)), 0, sizeof(USB_CDC_NCM_NTH16));
		nth16->dwSignature = cpu_to_le32(USB_CDC_NCM_NTH16_SIGN);
		nth16->wHeaderLength = cpu_to_le16(sizeof(USB_CDC_NCM_NTH16));
		nth16->wSequence = cpu_to_le16(usbpipe->tx_seq++);

		/* count total number of frames in this NTB */
		ptcb->NumofOrgSendPacket= 0;
	}

	NdisQueryPacket(Packet,
		NULL,
		NULL,
		&CurrentBuffer,
		&PacketLength);

    n = ptcb->NumofOrgSendPacket;

	if(n>=max_datagrams)
	{
		ptcb->bRead2Send=1;
	}
	while(n<max_datagrams) {

		/* get the appropriate NDP for this skb */
		ndp16 = cdc_ncm_ndp(Adapter, ptcb, sign, PacketLength + usbpipe->tx_modulus + usbpipe->tx_remainder);

		/* align beginning of next frame */
		cdc_ncm_align_tail(ptcb,  usbpipe->tx_modulus, usbpipe->tx_remainder, usbpipe->tx_max);

		/* check if we had enough room left for both NDP and frame */
		if (NULL==ndp16 || ptcb->ulSize + PacketLength > usbpipe->tx_max) {
			if (n == 0) {
				ptcb->bRead2Send=0;
			} else {
				ptcb->bRead2Send = 1;
			}
			bResult=FALSE;
			break;
		}

		/* calculate frame number withing this NDP */
		ndplen = le16_to_cpu(ndp16->wLength);
		index = (ndplen - sizeof(USB_CDC_NCM_NDP16)) / sizeof(USB_CDC_NCM_DPE16);

		/* OK, add this Packet */
		ndp16->dpe16[index].wDatagramLength = cpu_to_le16((USHORT)PacketLength);
		ndp16->dpe16[index].wDatagramIndex = cpu_to_le16((USHORT)ptcb->ulSize);
		ndp16->wLength = cpu_to_le16(ndplen + sizeof(USB_CDC_NCM_DPE16));

		while(CurrentBuffer)
		{
			NdisQueryBufferSafe(
				CurrentBuffer,
				&VirtualAddress,
				&CurrentLength,
				NormalPagePriority);

			ASSERT(NULL!=VirtualAddress);

			CurrentLength = min(CurrentLength, PacketLength);         

			if(CurrentLength)
			{
				// Copy the data.
				NdisMoveMemory(tcb_put(ptcb, CurrentLength), VirtualAddress, CurrentLength);
				PacketLength -= CurrentLength;            
			}
			NdisGetNextBuffer(
				CurrentBuffer,
				&CurrentBuffer);
		}
		if(PacketLength){
			NdisZeroMemory(tcb_put(ptcb, PacketLength), PacketLength);
		    PacketLength=0;
		}


		InsertTailList(
			&ptcb->ListOrgSendPacket, 
			(PLIST_ENTRY)&Packet->MiniportReserved[0]);

		ptcb->NumofOrgSendPacket++;

		/* send now if this NDP is full */
		if (index >= CDC_NCM_DPT_DATAGRAMS_MAX) {
			ptcb->bRead2Send = 1;
			break;
		}
		break;
	}

	/* If collected data size is less or equal CDC_NCM_MIN_TX_PKT
	* bytes, we send buffers as it is. If we get more data, it
	* would be more efficient for USB HS mobile device with DMA
	* engine to receive a full size NTB, than canceling DMA
	* transfer and receiving a short packet.
	*
	* This optimization support is pointless if we end up sending
	* a ZLP after full sized NTBs.
	*/
	if (ptcb->bRead2Send==1&&(ptcb->ulSize%maxpacketsize== 0))
		memset(tcb_put(ptcb, 1), 0, 1);/* force short packet */

	/* set final frame length */
	nth16 = (PUSB_CDC_NCM_NTH16 )ptcb->pData;
	nth16->wBlockLength = cpu_to_le16((USHORT)ptcb->ulSize);

	return bResult;
}
示例#12
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);
}
示例#13
0
struct Send_Packet_Data*
Packet2PacketData(PNDIS_PACKET Packet) {

	UINT buffer_count;
	PNDIS_BUFFER buffer;
	UINT packet_len;
	UINT offset;
	PVOID addr;
	UINT len;
	struct Send_Packet_Data* packet_data;
	packet_data = NULL;
	
	NdisQueryPacket(Packet,
		NULL,
		&buffer_count,
		&buffer,
		&packet_len);
	if (!buffer_count ||
		!buffer)
		goto error_exit;

	if (buffer_count > 1) {
		packet_data = PreparePacketData(buffer_count,
			packet_len);
		if (!packet_data)
			goto error_exit;
		
		offset = 0;
		while(1) {
			NdisQueryBufferSafe(buffer,
				&addr,
				&len,
				NormalPagePriority);
			if (!addr ||
				!len)
				goto error_exit;
		
			RtlCopyMemory(packet_data->m_data+offset, 
				addr, 
				len);
			offset += len;
		
			NdisGetNextBuffer(buffer, 
				&buffer);
			if (!buffer)
				break;
		}
		packet_data->m_ndis_packet = Packet;
		packet_data->m_len = packet_len;
	}
	else {
		packet_data = PreparePacketData(buffer_count,
			0);
		if (!packet_data)
			goto error_exit;

		NdisQueryBufferSafe(buffer,
			&addr,
			&len,
			NormalPagePriority);
		if (!addr ||
			!len)
			goto error_exit;
		
		packet_data->m_ndis_packet = Packet;
		packet_data->m_len = packet_len;		
		packet_data->m_data = addr;
	}

	packet_data->m_mdl = IoAllocateMdl(packet_data->m_data,
		packet_data->m_len,
		FALSE,
		FALSE,
		NULL);
	if (!packet_data->m_mdl)
		goto error_exit;

	try {
		MmProbeAndLockPages(packet_data->m_mdl,
			KernelMode,
			IoReadAccess);
		packet_data->m_locked = 1;
	}
	except(EXCEPTION_EXECUTE_HANDLER) {
		packet_data->m_locked = 0;
	}

	packet_data->m_addr = MmMapLockedPagesSpecifyCache(packet_data->m_mdl,
		UserMode,
		MmCached,
		NULL,
		FALSE,
		NormalPagePriority);
	if (!packet_data->m_addr)
		goto error_exit;

	packet_data->m_map_process = PsGetCurrentProcessId();

	return packet_data;
	
error_exit:
	DbgPrint("Packet2PacketData failed, force to complete the lost packet\n");
	free_send_packet_data(packet_data);
	return NULL;
}
示例#14
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;
}
示例#15
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;
}
示例#16
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
}
示例#17
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);
}
示例#18
0
文件: packet.c 项目: Endt4sk/sebek
int
filter_packet(int direction, int iface, PNDIS_PACKET packet)
{
	PNDIS_BUFFER buffer;
	UINT packet_len, buffer_len, hdr_len;
	int result;
	void *pointer;
	struct ether_hdr *ether_hdr;
	struct ip_hdr *ip_hdr;

	//lint -e506 -e613 -e774 -e831 -e550 
	NdisQueryPacket(packet, NULL, NULL, &buffer, &packet_len);

	if (packet_len < sizeof(struct ether_hdr)) {
		DBGOUT(("filter_packet: too small packet for ether_hdr! (%u)\n", packet_len));
		return FILTER_UNKNOWN;
	}

	/* process ether_hdr */

	NdisQueryBufferSafe(buffer, &ether_hdr, &buffer_len, LowPagePriority);

	if (buffer_len < sizeof(struct ether_hdr)) {
		DBGOUT(("filter_packet: too small buffer for ether_hdr! (%u)\n", buffer_len));
		return FILTER_UNKNOWN;
	}
	
	// go to the next header
	if (buffer_len > sizeof(struct ether_hdr)) {

		pointer = (char *)ether_hdr + sizeof(struct ether_hdr);

		buffer_len -= sizeof(struct ether_hdr);

	} else {
		// use next buffer in chain
		NdisGetNextBuffer(buffer, &buffer);
		NdisQueryBufferSafe(buffer, &pointer, &buffer_len, LowPagePriority);
	}

	if (ether_hdr->ether_type == ETHERNET_TYPE_IP) {
		/* process ip_hdr */

		if (buffer_len < sizeof(struct ip_hdr)) {
			DBGOUT(("filter_packet: too small buffer for ip_hdr! (%u)\n",	buffer_len));
			return FILTER_UNKNOWN;
		}

		ip_hdr = (struct ip_hdr *)pointer;
		hdr_len = ip_hdr->ip_hl * 4;

		if (buffer_len < hdr_len) {
			DBGOUT(("filter_packet: too small buffer for ip_hdr! (%u vs. %u)\n", buffer_len, hdr_len));
			return FILTER_UNKNOWN;
		}

		// go to the next header
		if (buffer_len > hdr_len) {

			pointer = (char *)ip_hdr + hdr_len;
					
			buffer_len -= hdr_len;
			
		} else {
			// use next buffer in chain
			NdisGetNextBuffer(buffer, &buffer);
			NdisQueryBufferSafe(buffer, &pointer, &buffer_len, LowPagePriority);
		}

		result = process_transp(direction, iface, ip_hdr->ip_p, ip_hdr, pointer, buffer_len);
		if (result != FILTER_ALLOW)
			return result;
	}

	// default behavior
	return FILTER_ALLOW;
}
示例#19
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;
}
示例#20
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;
}
示例#21
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;
}
示例#22
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;

}
示例#23
0
VOID
ReadPacket (
	PNDIS_PACKET pPacket,
	PUCHAR pBuffer,
	ULONG ulBufSize
	)
/*++

Routine Description:

	Retrieves the buffer from a buffer descriptor.


Arguments:

	Packet - Pointer to the buffer descriptor.

	pBuffer - Pointer to the buffer.

	ulBufSize - Size of the buffer.

Return Value:

	None.


Author:

	xiaonie

	2012/07/12


--*/
{
	PVOID			pVA;
	PNDIS_BUFFER	pFirstBuffer, pNextBuffer;
	ULONG			ulTotalLength;
	ULONG			ulLen;
	PVOID			pBuf = NULL;
	ULONG			ulCount = 0;

	NdisQueryPacket(pPacket, NULL, NULL, &pFirstBuffer, NULL);
	while (pFirstBuffer != NULL)
	{
		NdisQueryBufferSafe(pFirstBuffer, &pVA, &ulLen, NormalPagePriority);

		if(!pVA)
		{
			// memory not enough
			DbgPrint("pVA == NULL, insufficient memory!\r\n");
			break;
		}
		if (ulCount + ulLen > ulBufSize) {
			DbgPrint("ulCount + ulLen(%d) > ulBufSize(%d)\r\n", ulCount + ulLen, ulBufSize);
			break;
		}

		NdisMoveMemory(pBuffer + ulCount, pVA, ulLen);
		ulCount += ulLen;
		NdisGetNextBuffer(pFirstBuffer,  &pNextBuffer);
		pFirstBuffer = pNextBuffer;
	}

	DbgPrint("ReadPacket: ulBufSize == %d, ulCount == %d\n", ulBufSize, ulCount);

	return;
}
示例#24
0
/* We've received a csum_blank packet, but we don't want to let
   Windows see it like.  Calculate the checksum and dump it in the
   packet.  This only works for TCP and UDP on IPv4; on anything else
   it's a no-op. */
static VOID
FixupChecksum(PNDIS_PACKET packet)
{
    PNDIS_BUFFER pbuf;
    PNDIS_BUFFER pbuf_next;
    UINT bufLength;
    UINT len;
    struct ethhdr *eh;
    struct iphdr *ih;
    uint32_t csum_accumulator;
    uint32_t *ptr;
    uint16_t *csum_field;

    NdisQueryPacket(packet, NULL, NULL, &pbuf, NULL);
    NdisQueryBufferSafe(pbuf, &eh, &bufLength, NormalPagePriority);
    if (!eh || bufLength < sizeof(*eh))
        return;
    if (eh->proto != TPID_IPV4) {
        static BOOLEAN warned;
        if (!warned) {
            TraceWarning(("Asked to perform checksum calculation on non-IP ethernet prototocol %x!\n", eh->proto));
            warned = TRUE;
        }
        return;
    }
    ih = (struct iphdr *)(eh + 1);
    bufLength -= sizeof(*eh);
    if (bufLength < sizeof(*ih) ||
        bufLength < (UINT)(ih->len_version & 0x0f) * 4)
        return;
    ptr = (uint32_t *)((ULONG_PTR)ih + (ih->len_version & 0x0f)*4);
    len = ntohs(ih->tot_len) - (ih->len_version & 0x0f) * 4;

    bufLength -= (ih->len_version & 0x0f) * 4;
    if (bufLength > len)
        bufLength = len;

    if (ih->proto == IPPROTO_UDP) {
        if (bufLength < sizeof(struct udphdr))
            return;
        csum_field = &((struct udphdr *)ptr)->checksum;
    } else if (ih->proto == IPPROTO_TCP) {
        if (bufLength < sizeof(struct tcphdr))
            return;
        csum_field = &((struct tcphdr *)ptr)->checksum;
    } else {
        static BOOLEAN warned;
        /* Uh oh: don't know what this protocol is, so can't do
           checksum calculation for it. */
        if (!warned) {
            TraceWarning(("Asked to perform checksum calculation for unknown protocol %d!\n",
                          ih->proto));
            warned = TRUE;
        }
        return;
    }

    if (ih->proto == IPPROTO_TCP) {
        struct tcp_pseudo_header tph;
        uint16_t csum;

        tph.saddr = ih->src;
        tph.daddr = ih->dest;
        tph.mbz = 0;
        tph.ptcl = IPPROTO_TCP;
        tph.length = htons((uint16_t)len);

        csum_accumulator = acc_ip_csum(&tph, sizeof(tph), 0);
        csum = fold_ip_csum(csum_accumulator);

        if (*csum_field != csum)
            TraceWarning(("invlid pseudo header checksum: expected %04x, found %04x\n", csum, *csum_field));

        *csum_field = csum;
    }

    csum_accumulator = acc_ip_csum(ptr, bufLength, 0);
    len -= bufLength;

    while (len) {
        NdisGetNextBuffer(pbuf, &pbuf_next);
        if (pbuf_next == NULL)
            break;
        pbuf = pbuf_next;
        NdisQueryBufferSafe(pbuf, &ptr, &bufLength, NormalPagePriority);

        /* The buffer is already mapped into our RX buffer pool, so we
           should always be able to get a virtual address for it. */
        XM_ASSERT(ptr != NULL);

        if (bufLength > len)
            bufLength = len;

        csum_accumulator = acc_ip_csum(ptr, bufLength, csum_accumulator);
        len -= bufLength;
    }

    *csum_field = ~fold_ip_csum(csum_accumulator);
}
BOOLEAN PickPacketFromList(PADAPT pAdapt,PIRP Irp)
{
	PIO_STACK_LOCATION IrpStack;
	ULONG PacketLenTotal=0;

    PNDIS_PACKET        pRcvPacket;
    PLIST_ENTRY         pRcvPacketEntry;
    PUCHAR              pSrc, pDst;
	PUCHAR              pDstFormer;
    ULONG               BytesRemaining; // at pDst
    PNDIS_BUFFER        pNdisBuffer;
    ULONG               BytesAvailable;
	ULONG               BytesToCopy;


    NdisAcquireSpinLock(&PacketListLock);

    if(!IsListEmpty(&PacketList))
    {
        //
        //  Get the first queued receive packet
        //
        pRcvPacketEntry = PacketList.Flink;
        RemoveEntryList(pRcvPacketEntry);

        PacketCount--;

        NdisReleaseSpinLock(&PacketListLock);


        pRcvPacket = SECLAB_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry);

        //
        //  Copy as much data as possible from the receive packet to
        //  the IRP MDL.
        //
        pDst = (PUCHAR)ExAllocatePool(NonPagedPool,MY_MTU);
        
		if(pDst==NULL)
		{
			DbgPrint("Can not allocate enough pool");
			DbgBreakPoint();
		}
        pDstFormer=pDst;

		IrpStack = IoGetCurrentIrpStackLocation(Irp);
	    BytesRemaining = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

        pNdisBuffer = pRcvPacket->Private.Head;

        while (BytesRemaining && (pNdisBuffer != NULL))
        {

            NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority);

            if (pSrc == NULL) 
            {
                DbgPrint("PickPacketFromList: QueryBuffer failed for buffer");
                break;
            }

            if (BytesAvailable)
            {
                BytesToCopy = MIN(BytesAvailable, BytesRemaining);

                NdisMoveMemory(pDstFormer, pSrc, BytesToCopy);
                BytesRemaining -= BytesToCopy;
                pDstFormer += BytesToCopy;
				PacketLenTotal += BytesToCopy;
            }

            NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer);
        }

        //
        //  Complete the IRP.
        //
		RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, pDst, PacketLenTotal);
	    IoSetCancelRoutine(Irp,NULL);
	    CompleteIrp(Irp,STATUS_SUCCESS,PacketLenTotal);

		ExFreePool(pDst);
        //
        //  Free up the receive packet - back to the miniport if it
        //  belongs to it, else reclaim it (local copy).
        //
        if (NdisGetPoolFromPacket(pRcvPacket) != pAdapt->RecvPacketPoolHandle)
        {
            NdisReturnPackets(&pRcvPacket, 1);
        }
        else
        {
            SecLabFreeReceivePacket(pAdapt, pRcvPacket);
        }

    }
	else
	{
		NdisReleaseSpinLock(&PacketListLock);
		return FALSE;
	}
   
	return TRUE;
}