blob: 87ade9a9ff0f6e2783ae4eca803398614b1950b6 [file]
/*
* b2ether driver -- derived from DDK packet driver sample
*
* Basilisk II (C) 1997-1999 Christian Bauer
*
* Windows platform specific code copyright (C) Lauri Pesonen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"
#include "b2ether.h"
#undef DBG
#define DBG 0
#include "debug.h"
NTSTATUS PacketRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PNDIS_PACKET pPacket;
PMDL pMdl;
NDIS_STATUS Status;
IF_LOUD(DbgPrint("Packet: Read\n");)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open = IrpSp->FileObject->FsContext;
if (IrpSp->Parameters.Read.Length < ETHERNET_HEADER_LENGTH) {
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
pMdl=IoAllocateMdl(
MmGetMdlVirtualAddress(Irp->MdlAddress),
MmGetMdlByteCount(Irp->MdlAddress),
FALSE,
FALSE,
NULL
);
if (!pMdl) {
IF_LOUD(DbgPrint("Packet: Read-Failed to allocate Mdl\n");)
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
IoBuildPartialMdl(
Irp->MdlAddress,
pMdl,
((PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress))+ETHERNET_HEADER_LENGTH,
0
);
pMdl->Next = NULL;
//
// Try to get a packet from our list of free ones
//
NdisAllocatePacket( &Status, &pPacket, Open->PacketPool );
if (Status != NDIS_STATUS_SUCCESS) {
IF_LOUD(DbgPrint("Packet: Read- No free packets\n");)
IoFreeMdl(pMdl);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_UNSUCCESSFUL;
}
//
// Get a pointer to the packet itself
//
RESERVED(pPacket)->Irp = Irp;
RESERVED(pPacket)->pMdl = pMdl;
IoMarkIrpPending(Irp);
Irp->IoStatus.Status = STATUS_PENDING;
//
// Attach our new MDL to the packet
//
NdisChainBufferAtFront(pPacket,pMdl);
//
// Put this packet in a list of pending reads.
// The receive indication handler will attemp to remove packets
// from this list for use in transfer data calls
//
ExInterlockedInsertTailList(
&Open->RcvList,
&RESERVED(pPacket)->ListElement,
&Open->RcvQSpinLock);
return(STATUS_PENDING);
}
NDIS_STATUS
PacketReceiveIndicate (
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookaheadBufferSize,
IN UINT PacketSize
)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PIRP Irp;
PLIST_ENTRY PacketListEntry;
PNDIS_PACKET pPacket;
ULONG SizeToTransfer;
NDIS_STATUS Status;
UINT BytesTransfered;
ULONG BufferLength;
PPACKET_RESERVED Reserved;
IF_LOUD(DbgPrint("Packet: ReceiveIndicate\n");)
Open = (POPEN_INSTANCE)ProtocolBindingContext;
if (HeaderBufferSize > ETHERNET_HEADER_LENGTH) {
return NDIS_STATUS_NOT_ACCEPTED; // NDIS_STATUS_SUCCESS;
}
// See if there are any pending read that we can satisfy
PacketListEntry=ExInterlockedRemoveHeadList(
&Open->RcvList,
&Open->RcvQSpinLock
);
if (PacketListEntry == NULL) {
IF_LOUD(DbgPrint("Packet: ReceiveIndicate dropped a packet\n");)
return NDIS_STATUS_NOT_ACCEPTED;
}
Reserved=CONTAINING_RECORD(PacketListEntry,PACKET_RESERVED,ListElement);
pPacket=CONTAINING_RECORD(Reserved,NDIS_PACKET,ProtocolReserved);
Irp=RESERVED(pPacket)->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
// This is the length of our partial MDL
BufferLength = IrpSp->Parameters.Read.Length-ETHERNET_HEADER_LENGTH;
SizeToTransfer = (PacketSize < BufferLength) ? PacketSize : BufferLength;
// copy the ethernet header into the actual readbuffer
NdisMoveMappedMemory(
MmGetSystemAddressForMdl(Irp->MdlAddress),
HeaderBuffer,
HeaderBufferSize
);
// Call the Mac to transfer the packet
NdisTransferData(
&Status,
Open->AdapterHandle,
MacReceiveContext,
0,
SizeToTransfer,
pPacket,
&BytesTransfered);
if (Status != NDIS_STATUS_PENDING) {
PacketTransferDataComplete( Open, pPacket, Status, BytesTransfered );
}
return NDIS_STATUS_SUCCESS;
}
VOID PacketTransferDataComplete (
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pPacket,
IN NDIS_STATUS Status,
IN UINT BytesTransfered
)
{
PIO_STACK_LOCATION IrpSp;
POPEN_INSTANCE Open;
PIRP Irp;
PMDL pMdl;
IF_LOUD(DbgPrint("Packet: TransferDataComplete\n");)
Open = (POPEN_INSTANCE)ProtocolBindingContext;
Irp = RESERVED(pPacket)->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
pMdl = RESERVED(pPacket)->pMdl;
// Free the MDL that we allocated
IoFreeMdl(pMdl);
// recycle the packet
NdisReinitializePacket(pPacket);
// Put the packet on the free queue
NdisFreePacket(pPacket);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = BytesTransfered+ETHERNET_HEADER_LENGTH;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
VOID PacketReceiveComplete( IN NDIS_HANDLE ProtocolBindingContext )
{
}