| /* | |
| * 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 ) | |
| { | |
| } |