mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-12-23 19:29:18 +00:00
Import nt5 version of the ethernet driver from 2001 sources.
This commit is contained in:
parent
c34dd6ecd3
commit
235c71e1b2
80
BasiliskII/src/Windows/b2ether/nt5/B2Win2k.inf
Normal file
80
BasiliskII/src/Windows/b2ether/nt5/B2Win2k.inf
Normal 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
|
7
BasiliskII/src/Windows/b2ether/nt5/MAKEFILE
Normal file
7
BasiliskII/src/Windows/b2ether/nt5/MAKEFILE
Normal 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
|
17
BasiliskII/src/Windows/b2ether/nt5/SOURCES
Normal file
17
BasiliskII/src/Windows/b2ether/nt5/SOURCES
Normal 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
|
755
BasiliskII/src/Windows/b2ether/nt5/b2ether.c
Normal file
755
BasiliskII/src/Windows/b2ether/nt5/b2ether.c
Normal 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);
|
||||
}
|
||||
}
|
276
BasiliskII/src/Windows/b2ether/nt5/b2ether.h
Normal file
276
BasiliskII/src/Windows/b2ether/nt5/b2ether.h
Normal 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_
|
10
BasiliskII/src/Windows/b2ether/nt5/b2ether.rc
Normal file
10
BasiliskII/src/Windows/b2ether/nt5/b2ether.rc
Normal 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"
|
155
BasiliskII/src/Windows/b2ether/nt5/b2ether_openclose.c
Normal file
155
BasiliskII/src/Windows/b2ether/nt5/b2ether_openclose.c
Normal 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"));
|
||||
}
|
418
BasiliskII/src/Windows/b2ether/nt5/b2ether_read.c
Normal file
418
BasiliskII/src/Windows/b2ether/nt5/b2ether_read.c
Normal 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;
|
||||
}
|
101
BasiliskII/src/Windows/b2ether/nt5/b2ether_write.c
Normal file
101
BasiliskII/src/Windows/b2ether/nt5/b2ether_write.c
Normal 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user