Import nt5 version of the ethernet driver from 2001 sources.

This commit is contained in:
asvitkine 2012-04-22 03:13:32 +00:00
parent c34dd6ecd3
commit 235c71e1b2
9 changed files with 1819 additions and 0 deletions

View File

@ -0,0 +1,80 @@
[version]
Signature = "$Windows NT$"
Class = NetTrans
ClassGUID = {4d36e975-e325-11ce-bfc1-08002be10318}
Provider = %Msft%
DriverVer = 12/05/1999,5.00.2128
[Manufacturer]
%Msft%=MSFT
[MSFT]
%B2ETHER_Desc%=Install, MS_B2ETHER
;-------------------------------------------------------------------------
; Installation Section
;-------------------------------------------------------------------------
[Install]
AddReg=Inst_Ndi
Characteristics=0 ; Has no characterstic
CopyFiles=CpyFiles_Sys
;-------------------------------------------------------------------------
; Ndi installation support
;-------------------------------------------------------------------------
[Inst_Ndi]
HKR,Ndi,Service,,"B2Ether"
HKR,Ndi,HelpText,,%B2ETHER_HelpText%
HKR, Ndi\Interfaces, UpperRange,, noupper
HKR,"Ndi\Interfaces","LowerRange",,"ndis5,ndis4"
;-------------------------------------------------------------------------
; Service installation support
;-------------------------------------------------------------------------
[Install.Services]
AddService=B2Ether,,B2ETHER_Service_Inst
[B2Ether_Service_Inst]
DisplayName = %B2ETHER_Desc%
ServiceType = 1 ;SERVICE_KERNEL_DRIVER
StartType = 2 ;SERVICE_AUTO_START
ErrorControl = 1 ;SERVICE_ERROR_NORMAL
ServiceBinary = %12%\B2Ether.sys
LoadOrderGroup = "PNP_TDI"
AddReg = AddReg_B2ETHER_Service_Inst
Description = %B2ETHER_Desc%
[AddReg_B2ETHER_Service_Inst]
HKLM,"System\CurrentControlSet\Services\B2Ether","TextModeFlags",%REG_DWORD%,0x0001
HKR,"Parameters","Version",,"5.00.2128"
;-------------------------------------------------------------------------
; Support for removal of static registry settings
;-------------------------------------------------------------------------
[Install.Remove]
DelReg=Del_Static_Reg
[Install.Remove.Services]
DelService=B2Ether
[Del_Static_Reg]
HKLM,"System\CurrentControlSet\Services\B2Ether","TextModeFlags"
;-------------------------------------------------------------------------
; Declare Destination Directories for file copy/deletion
;-------------------------------------------------------------------------
[DestinationDirs]
CpyFiles_Sys = 12 ; DIRID_DRIVERS
;-------------------------------------------------------------------------
; Files to Copy/Delete - Referenced by Install and Remove sections above
;-------------------------------------------------------------------------
[CpyFiles_Sys]
B2Ether.sys,,,2
[Strings]
Msft = "Microsoft"
B2ETHER_Desc = "Basilisk II Ethernet Driver"
B2ETHER_HelpText = "Adds ethernet capability to the Basilisk II Macintosh II emulator."
REG_DWORD = 0x10001

View File

@ -0,0 +1,7 @@
#
# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
# file to this component. This file merely indirects to the real make file
# that is shared by all the driver components of the Windows NT DDK
#
!INCLUDE $(NTMAKEENV)\makefile.def

View File

@ -0,0 +1,17 @@
# MYMODE must be set
TARGETNAME=b2ether
TARGETPATH=obj
TARGETTYPE=DRIVER
TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib
C_DEFINES=$(C_DEFINES) -DNDIS50
INCLUDES=$(BASEDIR)\inc;$(BASEDIR)\src\network\inc;..\inc
MSC_WARNING_LEVEL=/W3 /WX /FR /FAcs /D$(MYMODE)
SOURCES=b2ether.c \
b2ether_openclose.c \
b2ether_read.c \
b2ether_write.c \
b2ether.rc

View File

@ -0,0 +1,755 @@
/*
* 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 "ntddk.h"
#include "ndis.h"
#include "ntddpack.h"
#include "b2ether.h"
#include "stdio.h"
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
NDIS_PROTOCOL_CHARACTERISTICS protocolChar;
NTSTATUS status = STATUS_SUCCESS;
NDIS_STRING protoName = NDIS_STRING_CONST("B2ether");
UNICODE_STRING ntDeviceName;
UNICODE_STRING win32DeviceName;
BOOLEAN fSymbolicLink = FALSE;
PDEVICE_OBJECT deviceObject;
// DebugPrint(("\n\nDriverEntry\n"));
Globals.DriverObject = DriverObject;
Globals.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
Globals.RegistryPath.Length = RegistryPath->Length;
Globals.RegistryPath.Buffer = ExAllocatePool( PagedPool, Globals.RegistryPath.MaximumLength );
if (!Globals.RegistryPath.Buffer) {
// DebugPrint (("Couldn't allocate pool for registry path."));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);
RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);
status = IoCreateDevice (DriverObject,
0,
&ntDeviceName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&deviceObject);
if (!NT_SUCCESS (status)) {
// Either not enough memory to create a deviceobject or another
// deviceobject with the same name exits. This could happen
// if you install another instance of this device.
goto ERROR;
}
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
if (!NT_SUCCESS(status)) goto ERROR;
fSymbolicLink = TRUE;
deviceObject->Flags |= DO_BUFFERED_IO;
Globals.ControlDeviceObject = deviceObject;
InitializeListHead(&Globals.AdapterList);
KeInitializeSpinLock(&Globals.GlobalLock);
NdisZeroMemory(&protocolChar,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
protocolChar.MajorNdisVersion = 5;
protocolChar.MinorNdisVersion = 0;
protocolChar.Name = protoName;
protocolChar.OpenAdapterCompleteHandler = PacketOpenAdapterComplete;
protocolChar.CloseAdapterCompleteHandler = PacketCloseAdapterComplete;
protocolChar.SendCompleteHandler = PacketSendComplete;
protocolChar.TransferDataCompleteHandler = PacketTransferDataComplete;
protocolChar.ResetCompleteHandler = PacketResetComplete;
protocolChar.RequestCompleteHandler = PacketRequestComplete;
protocolChar.ReceiveHandler = PacketReceiveIndicate;
protocolChar.ReceiveCompleteHandler = PacketReceiveComplete;
protocolChar.StatusHandler = PacketStatus;
protocolChar.StatusCompleteHandler = PacketStatusComplete;
protocolChar.BindAdapterHandler = PacketBindAdapter;
protocolChar.UnbindAdapterHandler = PacketUnbindAdapter;
protocolChar.UnloadHandler = NULL;
protocolChar.ReceivePacketHandler = PacketReceivePacket;
protocolChar.PnPEventHandler = PacketPNPHandler;
NdisRegisterProtocol(
&status,
&Globals.NdisProtocolHandle,
&protocolChar,
sizeof(NDIS_PROTOCOL_CHARACTERISTICS));
if (status != NDIS_STATUS_SUCCESS) {
// DebugPrint(("Failed to register protocol with NDIS\n"));
status = STATUS_UNSUCCESSFUL;
goto ERROR;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = PacketOpen;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = PacketClose;
DriverObject->MajorFunction[IRP_MJ_READ] = PacketRead;
DriverObject->MajorFunction[IRP_MJ_WRITE] = PacketWrite;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PacketCleanup;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PacketIoControl;
DriverObject->DriverUnload = PacketUnload;
return(STATUS_SUCCESS);
ERROR:
if(deviceObject)
IoDeleteDevice(deviceObject);
if(fSymbolicLink)
IoDeleteSymbolicLink(&win32DeviceName);
if(Globals.RegistryPath.Buffer)
ExFreePool(Globals.RegistryPath.Buffer);
return status;
}
VOID PacketUnload( IN PDRIVER_OBJECT DriverObject )
{
NDIS_STATUS status;
UNICODE_STRING win32DeviceName;
// DebugPrint(("Unload Enter\n"));
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&win32DeviceName);
if(Globals.ControlDeviceObject)
IoDeleteDevice(Globals.ControlDeviceObject);
// Unbind from all the adapters. The system removes the driver code
// pages from the memory as soon as the unload returns. So you
// must wait for all the CloseAdapterCompleteHandler to finish
// before returning from the unload routine. You don't any callbacks
// to trigger after the driver is unloaded.
while(DriverObject->DeviceObject) {
PacketUnbindAdapter(&status, DriverObject->DeviceObject->DeviceExtension,NULL);
}
if(Globals.RegistryPath.Buffer)
ExFreePool(Globals.RegistryPath.Buffer);
// DebugPrint(("Deregister\n"));
NdisDeregisterProtocol( &status, Globals.NdisProtocolHandle );
// DebugPrint(("Unload Exit\n"));
}
NTSTATUS PacketIoControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
POPEN_INSTANCE open;
PIO_STACK_LOCATION irpSp;
PINTERNAL_REQUEST pRequest;
ULONG functionCode;
NDIS_STATUS status;
ULONG dataLength =0;
// DebugPrint(("IoControl\n"));
irpSp = IoGetCurrentIrpStackLocation(Irp);
functionCode=irpSp->Parameters.DeviceIoControl.IoControlCode;
if (functionCode == IOCTL_ENUM_ADAPTERS) {
// If the request is not made to the controlobject, fail the request.
if(DeviceObject != Globals.ControlDeviceObject) {
status = STATUS_INVALID_DEVICE_REQUEST;
} else {
status = PacketGetAdapterList(
Irp->AssociatedIrp.SystemBuffer,
irpSp->Parameters.DeviceIoControl.OutputBufferLength,
&dataLength
);
}
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = dataLength;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
open = DeviceObject->DeviceExtension;
IoIncrement(open);
if(!open->Bound) {
Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
IoDecrement(open);
return status;
}
// DebugPrint(("Function code is %08lx buff size=%08lx %08lx\n",
// functionCode,irpSp->Parameters.DeviceIoControl.InputBufferLength,
// irpSp->Parameters.DeviceIoControl.OutputBufferLength));
// Important: Since we have marked the IRP pending, we must return
// STATUS_PENDING even we happen to complete the IRP synchronously.
IoMarkIrpPending(Irp);
if (functionCode == IOCTL_PROTOCOL_RESET) {
// DebugPrint(("IoControl - Reset request\n"));
//
// Since NDIS doesn't have an interface to cancel a request
// pending at miniport, we cannot set a cancel routine.
// As a result if the application that made the request
// terminates, we wait in the Cleanup routine for all pending
// NDIS requests to complete.
ExInterlockedInsertTailList(
&open->ResetIrpList,
&Irp->Tail.Overlay.ListEntry,
&open->ResetQueueLock);
NdisReset( &status, open->AdapterHandle );
if (status != NDIS_STATUS_PENDING) {
// DebugPrint(("IoControl - ResetComplete being called\n"));
PacketResetComplete( open, status );
}
} else {
// See if it is an Ndis request
PPACKET_OID_DATA OidData=Irp->AssociatedIrp.SystemBuffer;
pRequest = ExAllocatePool(NonPagedPool, sizeof(INTERNAL_REQUEST));
if(!pRequest) {
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
IoDecrement(open);
return STATUS_PENDING;
}
pRequest->Irp=Irp;
if (((functionCode == IOCTL_PROTOCOL_SET_OID) || (functionCode == IOCTL_PROTOCOL_QUERY_OID))
&&
(irpSp->Parameters.DeviceIoControl.InputBufferLength == irpSp->Parameters.DeviceIoControl.OutputBufferLength)
&&
(irpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA))
&&
(irpSp->Parameters.DeviceIoControl.InputBufferLength >= sizeof(PACKET_OID_DATA)-1+OidData->Length))
{
// DebugPrint(("IoControl: Request: Oid=%08lx, Length=%08lx\n", OidData->Oid,OidData->Length));
if (functionCode == IOCTL_PROTOCOL_SET_OID) {
pRequest->Request.RequestType = NdisRequestSetInformation;
pRequest->Request.DATA.SET_INFORMATION.Oid = OidData->Oid;
pRequest->Request.DATA.SET_INFORMATION.InformationBuffer = OidData->Data;
pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = OidData->Length;
} else {
pRequest->Request.RequestType=NdisRequestQueryInformation;
pRequest->Request.DATA.QUERY_INFORMATION.Oid = OidData->Oid;
pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = OidData->Data;
pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = OidData->Length;
}
NdisRequest( &status, open->AdapterHandle, &pRequest->Request );
} else {
status=NDIS_STATUS_FAILURE;
pRequest->Request.DATA.SET_INFORMATION.BytesRead=0;
pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten=0;
}
if (status != NDIS_STATUS_PENDING) {
// DebugPrint(("Calling RequestCompleteHandler\n"));
PacketRequestComplete( open, &pRequest->Request, status );
}
}
return STATUS_PENDING;
}
VOID
PacketRequestComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_REQUEST NdisRequest,
IN NDIS_STATUS Status
)
{
POPEN_INSTANCE open;
PIO_STACK_LOCATION irpSp;
PIRP irp;
PINTERNAL_REQUEST pRequest;
UINT functionCode;
PPACKET_OID_DATA OidData;
// DebugPrint(("RequestComplete\n"));
open = (POPEN_INSTANCE)ProtocolBindingContext;
pRequest=CONTAINING_RECORD(NdisRequest,INTERNAL_REQUEST,Request);
irp = pRequest->Irp;
if(Status == NDIS_STATUS_SUCCESS) {
irpSp = IoGetCurrentIrpStackLocation(irp);
functionCode=irpSp->Parameters.DeviceIoControl.IoControlCode;
OidData = irp->AssociatedIrp.SystemBuffer;
if (functionCode == IOCTL_PROTOCOL_SET_OID) {
OidData->Length=pRequest->Request.DATA.SET_INFORMATION.BytesRead;
} else {
if (functionCode == IOCTL_PROTOCOL_QUERY_OID) {
OidData->Length=pRequest->Request.DATA.QUERY_INFORMATION.BytesWritten;
}
}
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information=irpSp->Parameters.DeviceIoControl.InputBufferLength;
} else {
irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
irp->IoStatus.Information = 0;
}
ExFreePool(pRequest);
IoCompleteRequest(irp, IO_NO_INCREMENT);
IoDecrement(open);
}
VOID
PacketStatus(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
{
// DebugPrint(("Indication Status: %0x, StatusBufferSize: %d\n", Status, StatusBufferSize));
}
VOID PacketStatusComplete( IN NDIS_HANDLE ProtocolBindingContext )
{
// DebugPrint(("StatusIndicationComplete\n"));
}
NTSTATUS
PacketGetAdapterList(
IN PVOID Buffer,
IN ULONG Length,
IN OUT PULONG DataLength
)
{
ULONG requiredLength = 0, numOfAdapters = 0;
KIRQL oldIrql;
PLIST_ENTRY thisEntry, listHead;
POPEN_INSTANCE open;
// DebugPrint(("Enter PacketGetAdapterList\n"));
KeAcquireSpinLock(&Globals.GlobalLock, &oldIrql);
// Walks the list to find out total space required for AdapterName and Symbolic Link.
listHead = &Globals.AdapterList;
for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink) {
open = CONTAINING_RECORD(thisEntry, OPEN_INSTANCE, AdapterListEntry);
requiredLength += open->AdapterName.Length + sizeof(UNICODE_NULL);
requiredLength += open->SymbolicLink.Length + sizeof(UNICODE_NULL);
numOfAdapters++;
}
//
// We will return the data in the following format:
// numOfAdapters + One_Or_More("AdapterName\0" + "SymbolicLink\0") + UNICODE_NULL
// So let's include the numOfAdapters and UNICODE_NULL size
// to the total length.
//
requiredLength += sizeof(ULONG) + sizeof(UNICODE_NULL);
*DataLength = requiredLength;
if(requiredLength > Length) {
KeReleaseSpinLock(&Globals.GlobalLock, oldIrql);
return STATUS_BUFFER_TOO_SMALL;
}
*(PULONG)Buffer = numOfAdapters;
(PCHAR)Buffer += sizeof(ULONG);
for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink ) {
open = CONTAINING_RECORD(thisEntry, OPEN_INSTANCE, AdapterListEntry);
RtlCopyMemory( Buffer, open->AdapterName.Buffer, open->AdapterName.Length+sizeof(WCHAR) );
(PCHAR)Buffer += open->AdapterName.Length+sizeof(WCHAR);
RtlCopyMemory( Buffer, open->SymbolicLink.Buffer, open->SymbolicLink.Length+sizeof(WCHAR) );
(PCHAR)Buffer += open->SymbolicLink.Length+sizeof(WCHAR);
}
*(PWCHAR)Buffer = UNICODE_NULL;
KeReleaseSpinLock(&Globals.GlobalLock, oldIrql);
return STATUS_SUCCESS;
}
VOID
PacketBindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING DeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2
)
{
NDIS_STATUS status;
UINT mediumIndex;
USHORT length;
POPEN_INSTANCE open = NULL;
UNICODE_STRING unicodeDeviceName;
PDEVICE_OBJECT deviceObject = NULL;
PWSTR symbolicLink = NULL, deviceNameStr = NULL;
NDIS_MEDIUM mediumArray = NdisMedium802_3; // Ethernet medium
// DebugPrint(("Binding DeviceName %ws\n", DeviceName->Buffer));
do {
// Create a deviceobject for every adapter we bind to.
// To make a name for the deviceObject, we will append Packet_
// to the name portion of the input DeviceName.
unicodeDeviceName.Buffer = NULL;
length = DeviceName->Length + 7 * sizeof(WCHAR) + sizeof(UNICODE_NULL);
deviceNameStr = ExAllocatePool(NonPagedPool, length);
if (!deviceNameStr) {
// DebugPrint(("Memory allocation for create symbolic failed\n"));
*Status = NDIS_STATUS_FAILURE;
break;
}
swprintf(deviceNameStr, L"\\Device\\B2ether_%ws", &DeviceName->Buffer[8]);
RtlInitUnicodeString(&unicodeDeviceName, deviceNameStr);
// DebugPrint(("Exported DeviceName %ws\n", unicodeDeviceName.Buffer));
status = IoCreateDevice(
Globals.DriverObject,
sizeof(OPEN_INSTANCE),
&unicodeDeviceName,
FILE_DEVICE_PROTOCOL,
0,
TRUE, // only one handle to the device at a time.
&deviceObject
);
if (status != STATUS_SUCCESS) {
// DebugPrint(("CreateDevice Failed: %x\n", status));
*Status = NDIS_STATUS_FAILURE;
break;
}
deviceObject->Flags |= DO_DIRECT_IO;
open = (POPEN_INSTANCE) deviceObject->DeviceExtension;
open->DeviceObject = deviceObject;
// Create a symbolic link.
// We need to replace Device from \Device\Packet_{GUID} with DosDevices
// to create a symbolic link of the form \DosDevices\Packet_{GUID}
// There is a four character difference between these two
// strings.
length = unicodeDeviceName.Length + sizeof(UNICODE_NULL) + (4 * sizeof(WCHAR));
symbolicLink = ExAllocatePool(NonPagedPool, length);
if (!symbolicLink) {
// DebugPrint(("Memory allocation for create symbolic failed\n"));
*Status = NDIS_STATUS_FAILURE;
break;
}
swprintf( symbolicLink, L"\\DosDevices\\%ws", &unicodeDeviceName.Buffer[8]);
RtlInitUnicodeString(&open->SymbolicLink,symbolicLink);
// DebugPrint(("Symbolic Link: %ws\n", open->SymbolicLink.Buffer));
status = IoCreateSymbolicLink(
(PUNICODE_STRING) &open->SymbolicLink,
(PUNICODE_STRING) &unicodeDeviceName
);
if (status != STATUS_SUCCESS) {
// DebugPrint(("Create symbolic failed\n"));
*Status = NDIS_STATUS_FAILURE;
break;
}
ExFreePool(unicodeDeviceName.Buffer);
unicodeDeviceName.Buffer = NULL;
NdisAllocatePacketPool(
&status,
&open->PacketPool,
TRANSMIT_PACKETS,
sizeof(PACKET_RESERVED));
if (status != NDIS_STATUS_SUCCESS) {
// DebugPrint(("B2ether: Failed to allocate packet pool\n"));
break;
}
NdisInitializeEvent(&open->Event);
InitializeListHead(&open->ResetIrpList);
KeInitializeSpinLock(&open->ResetQueueLock);
KeInitializeSpinLock(&open->RcvQSpinLock);
InitializeListHead(&open->RcvList);
NdisOpenAdapter(Status,
&status,
&open->AdapterHandle,
&mediumIndex,
&mediumArray,
sizeof(mediumArray)/sizeof(NDIS_MEDIUM),
Globals.NdisProtocolHandle,
open,
DeviceName,
0,
NULL);
if(*Status == NDIS_STATUS_PENDING) {
NdisWaitEvent(&open->Event, 0);
*Status = open->Status;
}
if(*Status != NDIS_STATUS_SUCCESS) {
// DebugPrint(("Failed to openAdapter\n"));
break;
}
open->IrpCount = 0;
InterlockedExchange( (PLONG)&open->Bound, TRUE );
NdisInitializeEvent(&open->CleanupEvent);
NdisSetEvent(&open->CleanupEvent);
NdisQueryAdapterInstanceName( &open->AdapterName, open->AdapterHandle );
// DebugPrint(("Bound AdapterName %ws\n", open->AdapterName.Buffer));
open->Medium = mediumArray;
InitializeListHead(&open->AdapterListEntry);
ExInterlockedInsertTailList(&Globals.AdapterList,
&open->AdapterListEntry,
&Globals.GlobalLock);
// Clear the DO_DEVICE_INITIALIZING flag. This is required
// if you create deviceobjects outside of DriverEntry.
// Untill you do this, application cannot send I/O request.
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
} while (FALSE);
if (*Status != NDIS_STATUS_SUCCESS) {
if (open && open->PacketPool) NdisFreePacketPool(open->PacketPool);
if (deviceObject) IoDeleteDevice(deviceObject);
if(unicodeDeviceName.Buffer) ExFreePool(unicodeDeviceName.Buffer);
if(symbolicLink) {
IoDeleteSymbolicLink(&open->SymbolicLink);
ExFreePool(open->SymbolicLink.Buffer);
}
}
// DebugPrint(("Return BindAdapter :0x%x\n", *Status));
}
VOID
PacketUnbindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE UnbindContext
)
{
POPEN_INSTANCE open =(POPEN_INSTANCE)ProtocolBindingContext;
KIRQL oldIrql;
// DebugPrint(("PacketUnbindAdapter :%ws\n", open->AdapterName.Buffer));
if(open->AdapterHandle) {
NdisResetEvent(&open->Event);
InterlockedExchange( (PLONG) &open->Bound, FALSE );
PacketCancelReadIrps(open->DeviceObject);
// DebugPrint(("Waiting on CleanupEvent\n"));
NdisWaitEvent(&open->CleanupEvent, 0);
NdisCloseAdapter(Status, open->AdapterHandle);
// Wait for it to complete
if(*Status == NDIS_STATUS_PENDING) {
NdisWaitEvent(&open->Event, 0);
*Status = open->Status;
} else {
*Status = NDIS_STATUS_FAILURE;
// ASSERT(0);
}
KeAcquireSpinLock(&Globals.GlobalLock, &oldIrql);
RemoveEntryList(&open->AdapterListEntry);
KeReleaseSpinLock(&Globals.GlobalLock, oldIrql);
NdisFreePacketPool(open->PacketPool);
NdisFreeMemory(open->AdapterName.Buffer, open->AdapterName.Length, 0);
IoDeleteSymbolicLink(&open->SymbolicLink);
ExFreePool(open->SymbolicLink.Buffer);
IoDeleteDevice(open->DeviceObject);
}
// DebugPrint(("Exit PacketUnbindAdapter\n"));
}
VOID
PacketOpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
)
{
POPEN_INSTANCE open = ProtocolBindingContext;
// DebugPrint(("B2ether: OpenAdapterComplete\n"));
open->Status = Status;
NdisSetEvent(&open->Event);
}
VOID
PacketCloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
POPEN_INSTANCE open = ProtocolBindingContext;
// DebugPrint(("CloseAdapterComplete\n"));
open->Status = Status;
NdisSetEvent(&open->Event);
}
NDIS_STATUS
PacketPNPHandler(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNET_PNP_EVENT NetPnPEvent
)
{
POPEN_INSTANCE open =(POPEN_INSTANCE)ProtocolBindingContext;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
PNET_DEVICE_POWER_STATE powerState;
// DebugPrint(("PacketPNPHandler\n"));
powerState = (PNET_DEVICE_POWER_STATE)NetPnPEvent->Buffer;
// This will happen when all entities in the system need to be notified
//
//if(open == NULL)
//{
// return Status;
//}
switch(NetPnPEvent->NetEvent) {
case NetEventSetPower :
// DebugPrint(("NetEventSetPower\n"));
switch (*powerState) {
case NetDeviceStateD0:
Status = NDIS_STATUS_SUCCESS;
break;
default:
// We can't suspend, so we ask NDIS to Unbind us by
// returning this status:
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
break;
case NetEventQueryPower :
// DebugPrint(("NetEventQueryPower\n"));
break;
case NetEventQueryRemoveDevice :
// DebugPrint(("NetEventQueryRemoveDevice \n"));
break;
case NetEventCancelRemoveDevice :
// DebugPrint(("NetEventCancelRemoveDevice \n"));
break;
case NetEventReconfigure :
// The protocol should always succeed this event by returning NDIS_STATUS_SUCCESS
// DebugPrint(("NetEventReconfigure\n"));
break;
case NetEventBindsComplete :
// DebugPrint(("NetEventBindsComplete \n"));
break;
case NetEventPnPCapabilities :
// DebugPrint(("NetEventPnPCapabilities \n"));
case NetEventBindList:
// DebugPrint(("NetEventBindList \n"));
default:
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
return Status;
}
VOID IoIncrement( IN OUT POPEN_INSTANCE Open )
{
LONG result = InterlockedIncrement(&Open->IrpCount);
//DebugPrint(("IoIncrement %d\n", result));
// Need to clear event (when IrpCount bumps from 0 to 1)
if (result == 1) {
NdisResetEvent(&Open->CleanupEvent);
}
}
VOID IoDecrement ( IN OUT POPEN_INSTANCE Open )
{
LONG result = InterlockedDecrement(&Open->IrpCount);
//DebugPrint(("IoDecrement %d\n", result));
if (result == 0) {
// Set the event when the count transition from 1 to 0.
NdisSetEvent (&Open->CleanupEvent);
}
}

View File

@ -0,0 +1,276 @@
/*
* 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
*/
#ifndef _B2ETHER_H_
#define _B2ETHER_H_
#undef ExAllocatePool
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a, b, 'te2B')
#if DBG
#define DebugPrint(_x_) \
DbgPrint("B2ETHER: ");\
DbgPrint _x_;
#else
#define DebugPrint(_x_)
#endif
#define NT_DEVICE_NAME L"\\Device\\B2ether"
#define DOS_DEVICE_NAME L"\\DosDevices\\B2ether"
typedef struct _GLOBAL {
PDRIVER_OBJECT DriverObject;
NDIS_HANDLE NdisProtocolHandle;
UNICODE_STRING RegistryPath;
LIST_ENTRY AdapterList;
KSPIN_LOCK GlobalLock;
PDEVICE_OBJECT ControlDeviceObject;
} GLOBAL, *PGLOBAL;
GLOBAL Globals;
typedef struct _INTERNAL_REQUEST {
PIRP Irp;
NDIS_REQUEST Request;
} INTERNAL_REQUEST, *PINTERNAL_REQUEST;
typedef struct _OPEN_INSTANCE {
PDEVICE_OBJECT DeviceObject;
ULONG IrpCount;
NDIS_STRING AdapterName;
NDIS_STRING SymbolicLink;
NDIS_HANDLE AdapterHandle;
NDIS_HANDLE PacketPool;
KSPIN_LOCK RcvQSpinLock;
LIST_ENTRY RcvList;
NDIS_MEDIUM Medium;
KSPIN_LOCK ResetQueueLock;
LIST_ENTRY ResetIrpList;
NDIS_STATUS Status;
NDIS_EVENT Event;
NDIS_EVENT CleanupEvent;
LIST_ENTRY AdapterListEntry;
BOOLEAN Bound;
CHAR Filler[3];
} OPEN_INSTANCE, *POPEN_INSTANCE;
typedef struct _PACKET_RESERVED {
LIST_ENTRY ListElement;
PIRP Irp;
PMDL pMdl;
} PACKET_RESERVED, *PPACKET_RESERVED;
#define ETHERNET_HEADER_LENGTH 14
#define RESERVED(_p) ((PPACKET_RESERVED)((_p)->ProtocolReserved))
#define TRANSMIT_PACKETS 16
NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
);
NTSTATUS
PacketCancelReadIrps(
IN PDEVICE_OBJECT DeviceObject
);
NTSTATUS
PacketCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
PacketBindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING DeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2
);
VOID
PacketUnbindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE UnbindContext
);
VOID
PacketOpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
);
VOID
PacketCloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
);
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
);
VOID
PacketReceiveComplete(
IN NDIS_HANDLE ProtocolBindingContext
);
VOID
PacketRequestComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_REQUEST pRequest,
IN NDIS_STATUS Status
);
VOID
PacketSendComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pPacket,
IN NDIS_STATUS Status
);
VOID
PacketResetComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
);
VOID
PacketStatus(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
);
VOID
PacketStatusComplete(
IN NDIS_HANDLE ProtocolBindingContext
);
VOID
PacketTransferDataComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status,
IN UINT BytesTransferred
);
NTSTATUS
PacketShutdown(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
PacketUnload(
IN PDRIVER_OBJECT DriverObject
);
NTSTATUS
PacketOpen(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
PacketClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
PacketWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
PacketRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
NTSTATUS
PacketIoControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
VOID
PacketCancelRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
);
INT
PacketReceivePacket(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet
);
NTSTATUS
PacketGetAdapterList(
IN PVOID Buffer,
IN ULONG Length,
IN OUT PULONG DataLength
);
NDIS_STATUS
PacketPNPHandler(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNET_PNP_EVENT pNetPnPEvent
);
VOID
IoIncrement (
IN OUT POPEN_INSTANCE Open
);
VOID
IoDecrement (
IN OUT POPEN_INSTANCE Open
);
#endif //_B2ETHER_H_

View File

@ -0,0 +1,10 @@
#include <windows.h>
#include <ntverp.h>
#define VER_FILETYPE VFT_DRV
#define VER_FILESUBTYPE VFT2_DRV_NETWORK
#define VER_FILEDESCRIPTION_STR "Basilisk II Protocol Driver"
#define VER_INTERNALNAME_STR "B2ETHER.SYS"
#define VER_ORIGINALFILENAME_STR "B2ETHER.SYS"
#include "common.ver"

View File

@ -0,0 +1,155 @@
/*
* 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 "ntddk.h"
#include "ndis.h"
#include "b2ether.h"
NTSTATUS PacketOpen( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
POPEN_INSTANCE open;
NTSTATUS status = STATUS_SUCCESS;
// DebugPrint(("OpenAdapter\n"));
if(DeviceObject == Globals.ControlDeviceObject) {
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
open = DeviceObject->DeviceExtension;
// DebugPrint(("AdapterName :%ws\n", open->AdapterName.Buffer));
IoIncrement(open);
if(!open->Bound) {
status = STATUS_DEVICE_NOT_READY;
}
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
IoDecrement(open);
return status;
}
NTSTATUS PacketClose( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
POPEN_INSTANCE open;
NTSTATUS status = STATUS_SUCCESS;
// DebugPrint(("CloseAdapter \n"));
if(DeviceObject == Globals.ControlDeviceObject) {
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
open = DeviceObject->DeviceExtension;
IoIncrement(open);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
IoDecrement(open);
return status;
}
NTSTATUS PacketCleanup( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
POPEN_INSTANCE open;
NTSTATUS status = STATUS_SUCCESS;
// DebugPrint(("Packet: Cleanup\n"));
if(DeviceObject == Globals.ControlDeviceObject) {
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
open = DeviceObject->DeviceExtension;
IoIncrement(open);
PacketCancelReadIrps(DeviceObject);
// Since the current implementation of NDIS doesn't
// allow us to cancel requests pending at the
// minport, we must wait here until they complete.
IoDecrement(open);
NdisWaitEvent(&open->CleanupEvent, 0);
Irp->IoStatus.Information = 0;
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
VOID
PacketResetComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
POPEN_INSTANCE open;
PIRP irp;
PLIST_ENTRY resetListEntry;
// DebugPrint(("PacketResetComplte\n"));
open= (POPEN_INSTANCE)ProtocolBindingContext;
resetListEntry=ExInterlockedRemoveHeadList(
&open->ResetIrpList,
&open->ResetQueueLock
);
#if DBG
if (resetListEntry == NULL) {
DbgBreakPoint();
return;
}
#endif
irp=CONTAINING_RECORD(resetListEntry,IRP,Tail.Overlay.ListEntry);
if(Status == NDIS_STATUS_SUCCESS) {
irp->IoStatus.Status = STATUS_SUCCESS;
} else {
irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
irp->IoStatus.Information = 0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
IoDecrement(open);
// DebugPrint(("PacketResetComplte exit\n"));
}

View File

@ -0,0 +1,418 @@
/*
* 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 "ntddk.h"
#include "ndis.h"
#include "b2ether.h"
NTSTATUS PacketRead( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
POPEN_INSTANCE open;
PNDIS_PACKET pPacket;
NDIS_STATUS status;
NTSTATUS ntStatus;
PIO_STACK_LOCATION irpSp;
// DebugPrint(("Read\n"));
open = DeviceObject->DeviceExtension;
IoIncrement(open);
if(!open->Bound) {
ntStatus = STATUS_DEVICE_NOT_READY;
goto ERROR;
}
irpSp = IoGetCurrentIrpStackLocation(Irp);
if (irpSp->Parameters.Read.Length < ETHERNET_HEADER_LENGTH) {
ntStatus = STATUS_BUFFER_TOO_SMALL;
goto ERROR;
}
NdisAllocatePacket( &status, &pPacket, open->PacketPool );
if (status != NDIS_STATUS_SUCCESS) {
// DebugPrint(("Packet: Read- No free packets\n"));
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
goto ERROR;
}
RESERVED(pPacket)->Irp=Irp;
RESERVED(pPacket)->pMdl=NULL;
IoMarkIrpPending(Irp);
IoSetCancelRoutine(Irp, PacketCancelRoutine);
ExInterlockedInsertTailList(
&open->RcvList,
&RESERVED(pPacket)->ListElement,
&open->RcvQSpinLock);
return STATUS_PENDING;
ERROR:
Irp->IoStatus.Status = ntStatus;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
IoDecrement(open);
return ntStatus;
}
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 = 0;
ULONG bufferLength;
PPACKET_RESERVED reserved;
PMDL pMdl;
// DebugPrint(("ReceiveIndicate\n"));
open= (POPEN_INSTANCE)ProtocolBindingContext;
if (HeaderBufferSize > ETHERNET_HEADER_LENGTH) {
return NDIS_STATUS_SUCCESS;
}
// See if there are any pending read that we can satisfy
packetListEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock );
if (packetListEntry == NULL) {
// DebugPrint(("No pending read, dropping packets\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);
// 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);
bufferLength = irpSp->Parameters.Read.Length-ETHERNET_HEADER_LENGTH;
sizeToTransfer = (PacketSize < bufferLength) ? PacketSize : bufferLength;
NdisMoveMappedMemory(
MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority),
HeaderBuffer,
HeaderBufferSize
);
pMdl=IoAllocateMdl(
MmGetMdlVirtualAddress(irp->MdlAddress),
MmGetMdlByteCount(irp->MdlAddress),
FALSE,
FALSE,
NULL
);
if (pMdl == NULL) {
// DebugPrint(("Packet: Read-Failed to allocate Mdl\n"));
status = NDIS_STATUS_RESOURCES;
goto ERROR;
}
IoBuildPartialMdl(
irp->MdlAddress,
pMdl,
((PUCHAR)MmGetMdlVirtualAddress(irp->MdlAddress))+ETHERNET_HEADER_LENGTH,
0
);
pMdl->Next = NULL;
RESERVED(pPacket)->pMdl=pMdl;
NdisChainBufferAtFront(pPacket,pMdl);
NdisTransferData(
&status,
open->AdapterHandle,
MacReceiveContext,
0,
sizeToTransfer,
pPacket,
&bytesTransfered
);
if (status == NDIS_STATUS_PENDING) {
return NDIS_STATUS_SUCCESS;
}
ERROR:
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;
// DebugPrint(("Packet: TransferDataComplete\n"));
open = (POPEN_INSTANCE)ProtocolBindingContext;
irp = RESERVED(pPacket)->Irp;
irpSp = IoGetCurrentIrpStackLocation(irp);
pMdl = RESERVED(pPacket)->pMdl;
if(pMdl) IoFreeMdl(pMdl);
NdisFreePacket(pPacket);
if(Status == NDIS_STATUS_SUCCESS) {
irp->IoStatus.Status = STATUS_SUCCESS;
irp->IoStatus.Information = BytesTransfered+ETHERNET_HEADER_LENGTH;
} else {
irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
irp->IoStatus.Information = 0;
}
// DebugPrint(("BytesTransfered:%d\n", irp->IoStatus.Information));
IoCompleteRequest(irp, IO_NO_INCREMENT);
IoDecrement(open);
}
VOID PacketReceiveComplete( IN NDIS_HANDLE ProtocolBindingContext )
{
}
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;
}
VOID
PacketCancelRoutine (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
POPEN_INSTANCE open = DeviceObject->DeviceExtension;
KIRQL oldIrql;
PIRP irpToComplete = NULL;
PLIST_ENTRY thisEntry, listHead;
PIRP pendingIrp;
PNDIS_PACKET myPacket = NULL;
PPACKET_RESERVED reserved;
PMDL mdl;
// Don't assume that the IRP being cancelled is in the queue.
// Only complete the IRP if it IS in the queue.
//
// Must acquire the local spinlock before releasing
// the global cancel spinlock
//
// DebugPrint(("PacketCancelRoutine\n"));
oldIrql = Irp->CancelIrql;
// One should not intermix KeAcquireSpinLock(AtDpcLevel)
// and ExInterlocked...List() functions on the same spinlock if the
// routines that use the lock run at IRQL > DISPATCH_LEVEL.
// After acquiring the lock using Ke function, if we got interrupted
// and entered into an ISR and tried to manipulate the list using
// ExInterlocked...List function with the same lock, we deadlock.
// In this sample we can safely do that because none of our routines
// will be called at IRQL > DISPATCH_LEVEL.
KeAcquireSpinLockAtDpcLevel(&open->RcvQSpinLock);
IoReleaseCancelSpinLock( KeGetCurrentIrql() );
listHead = &open->RcvList;
for( thisEntry = listHead->Flink; thisEntry != listHead; thisEntry = thisEntry->Flink ) {
reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement);
myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);
pendingIrp = RESERVED(myPacket)->Irp;
if (pendingIrp == Irp) {
RemoveEntryList(thisEntry);
irpToComplete = pendingIrp;
break;
}
}
KeReleaseSpinLock(&open->RcvQSpinLock, oldIrql);
if(irpToComplete) {
// DebugPrint(("Cancelling IRP\n"));
// ASSERT(myPacket);
NdisFreePacket(myPacket);
irpToComplete->IoStatus.Status = STATUS_CANCELLED;
irpToComplete->IoStatus.Information = 0;
IoCompleteRequest(irpToComplete, IO_NO_INCREMENT);
IoDecrement(open);
}
}
NTSTATUS PacketCancelReadIrps( IN PDEVICE_OBJECT DeviceObject )
{
POPEN_INSTANCE open = DeviceObject->DeviceExtension;
PLIST_ENTRY thisEntry;
PIRP pendingIrp;
PNDIS_PACKET myPacket = NULL;
PPACKET_RESERVED reserved;
PMDL mdl;
// DebugPrint(("PacketCancelReadIrps\n"));
// Walk through the RcvList and cancel all read IRPs.
while( thisEntry = ExInterlockedRemoveHeadList( &open->RcvList, &open->RcvQSpinLock )) {
reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement);
myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);
ASSERT(myPacket);
pendingIrp = RESERVED(myPacket)->Irp;
NdisFreePacket(myPacket);
// DebugPrint(("Cancelled : 0%0x\n", pendingIrp));
IoSetCancelRoutine(pendingIrp, NULL);
pendingIrp->IoStatus.Information = 0;
pendingIrp->IoStatus.Status = STATUS_CANCELLED;
IoCompleteRequest(pendingIrp, IO_NO_INCREMENT);
IoDecrement(open);
}
return STATUS_SUCCESS;
}

View File

@ -0,0 +1,101 @@
/*
* 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 "ntddk.h"
#include "ndis.h"
#include "b2ether.h"
NTSTATUS PacketWrite( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp )
{
POPEN_INSTANCE open;
PNDIS_PACKET pPacket;
NDIS_STATUS Status;
// DebugPrint(("SendAdapter\n"));
open = DeviceObject->DeviceExtension;
IoIncrement(open);
if(!open->Bound) {
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
IoDecrement(open);
return STATUS_UNSUCCESSFUL;
}
NdisAllocatePacket( &Status, &pPacket, open->PacketPool );
if (Status != NDIS_STATUS_SUCCESS) {
Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
IoDecrement(open);
return STATUS_INSUFFICIENT_RESOURCES;
}
RESERVED(pPacket)->Irp=Irp;
NdisChainBufferAtFront(pPacket,Irp->MdlAddress);
// Important: Since we have marked the IRP pending, we must return
// STATUS_PENDING even we happen to complete the IRP synchronously.
IoMarkIrpPending(Irp);
NdisSend( &Status, open->AdapterHandle, pPacket );
if (Status != NDIS_STATUS_PENDING) {
PacketSendComplete( open, pPacket, Status );
}
return STATUS_PENDING;
}
VOID
PacketSendComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pPacket,
IN NDIS_STATUS Status
)
{
PIRP irp;
PIO_STACK_LOCATION irpSp;
// DebugPrint(("Packet: SendComplete :%x\n", Status));
irp = RESERVED(pPacket)->Irp;
irpSp = IoGetCurrentIrpStackLocation(irp);
NdisFreePacket(pPacket);
if(Status == NDIS_STATUS_SUCCESS) {
irp->IoStatus.Information = irpSp->Parameters.Write.Length;
irp->IoStatus.Status = STATUS_SUCCESS;
} else {
irp->IoStatus.Information = 0;
irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
IoCompleteRequest(irp, IO_NO_INCREMENT);
IoDecrement((POPEN_INSTANCE)ProtocolBindingContext);
}