📄 genport.c
字号:
}
deviceInfo->ComBase [i] = (PVOID)((ULONG)deviceInfo->PortBase + (ULONG)COMBASE_PORT[i]);
deviceInfo->Inited [i] = FALSE;
}
//结束
} else {
ASSERT(addressSpace == 0x01);
#if DBG
DbgPrint("Address space is port\n");
#endif
//
// Port I/O space is only 16 bits long, so we can grab the low 32 bits
// of the address only.
//
deviceInfo->PortBase = (PULONG)address.LowPart;
deviceInfo->PortCount = portLength;
}
deviceInfo->Started = TRUE;//原来的代码
deviceInfo->Removed = FALSE;//原来的代码
//---------------查找PCI分配的954IO地址 结束
/////////////////////////////////////////////////////////////////////////////
return STATUS_SUCCESS;
}
NTSTATUS
GpdAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject
)
/*++
Routine Description:
The Plug & Play subsystem is handing us a brand new PDO, for which we
(by means of INF registration) have been asked to provide a driver.
We need to determine if we need to be in the driver stack for the device.
Create a functional device object to attach to the stack
Initialize that device object
Return status success.
Remember: we can NOT actually send ANY non pnp IRPS to the given driver
stack, UNTIL we have received an IRP_MN_START_DEVICE.
Arguments:
DeviceObject - pointer to a device object.
PhysicalDeviceObject - pointer to a device object created by the
underlying bus driver.
Return Value:
NT status code.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_OBJECT deviceObject = NULL;
PLOCAL_DEVICE_INFO deviceInfo;
UNICODE_STRING ntDeviceName;
UNICODE_STRING win32DeviceName;
DebugPrint (("-- Entered GpdAddDevice\n"));
PAGED_CODE();
RtlInitUnicodeString(&ntDeviceName, GPD_DEVICE_NAME); //GPD_DEVICE_NAME 就是宏定义 L"\\Device\\Gpd0"
DebugPrint((">>> ntDeviceName.len=%d Buffer=%s\n"
,ntDeviceName.Length
,ntDeviceName.Buffer));
//
// Create a device object.
//
status = IoCreateDevice (DriverObject,
sizeof (LOCAL_DEVICE_INFO),
&ntDeviceName,
GPD_TYPE,
0,
FALSE,
&deviceObject);//分配内存并初始化一个设备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.
//
return status;
}
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);//#define DOS_DEVICE_NAME L"\\DosDevices\\GpdDev"
DebugPrint((">>> win32DeviceName.Buffer=%s \n",win32DeviceName.Buffer));
status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );//在设备和用户可见设备名之间建立连接
if (!NT_SUCCESS(status)) // If we we couldn't create the link then
{ // abort installation.
IoDeleteDevice(deviceObject);
return status;
}
deviceInfo = (PLOCAL_DEVICE_INFO) deviceObject->DeviceExtension;//提取设备信息(包括地址:地址范围等)
DebugPrint((">>> PortAddr=%X PortCount=%d\n",
(unsigned int)deviceInfo->PortBase ,
deviceInfo->PortCount ));
DebugPrint((">>> PortMemyType=%d \n",
(unsigned int)deviceInfo->PortMemoryType ));
deviceInfo->NextLowerDriver = IoAttachDeviceToDeviceStack (//把deviceObject 附属到 物理设备PhysicalDeviceObject上
deviceObject,
PhysicalDeviceObject);//PhysicalDeviceObject是入口参数
if(NULL == deviceInfo->NextLowerDriver) {
IoDeleteSymbolicLink(&win32DeviceName);
IoDeleteDevice(deviceObject);
return STATUS_NO_SUCH_DEVICE;
}
IoInitializeRemoveLock (&deviceInfo->RemoveLock ,
PORTIO_TAG,
1, // MaxLockedMinutes
5); // HighWatermark, this parameter is
// used only on checked build.
//
// Set the flag if the device is not holding a pagefile
// crashdump file or hibernate file.
//
deviceObject->Flags |= DO_POWER_PAGABLE;
deviceInfo->DeviceObject = deviceObject;//deviceInfo就是我们自己定义的设备参数(地址,地址空间等)
deviceInfo->Removed = FALSE;
deviceInfo->Started = FALSE;
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
// deviceObject->Flags |= DO_BUFFERED_IO;
//
// This values is based on the hardware design.
// Let us assume the address is in I/O space.
//
deviceInfo->PortMemoryType = 0;//存贮器访问 20060216
DebugPrint(("AddDevice: %p to %p->%p \n", deviceObject,
deviceInfo->NextLowerDriver,
PhysicalDeviceObject));
return STATUS_SUCCESS;
}
NTSTATUS
GpdCompletionRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
/*++
Routine Description:
The completion routine for plug & play irps that needs to be
processed first by the lower drivers.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Context - pointer to an event object.
Return Value:
NT status code
--*/
{
PKEVENT event;
event = (PKEVENT) Context;
UNREFERENCED_PARAMETER(DeviceObject);
if (Irp->PendingReturned) {
IoMarkIrpPending(Irp);
}
//
// We could switch on the major and minor functions of the IRP to perform
// different functions, but we know that Context is an event that needs
// to be set.
//
KeSetEvent(event, 0, FALSE);
//
// Allows the caller to reuse the IRP
//
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
GpdDispatchPnp (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
The plug and play dispatch routines.
Most of these the driver will completely ignore.
In all cases it must pass the IRP to the next lower driver.
Arguments:
DeviceObject - pointer to a device object.
Irp - pointer to an I/O Request Packet.
Return Value:
NT status code
--*/
{
PIO_STACK_LOCATION irpStack;
NTSTATUS status = STATUS_SUCCESS;
KEVENT event;
UNICODE_STRING win32DeviceName;
PLOCAL_DEVICE_INFO deviceInfo;
PAGED_CODE();
deviceInfo = (PLOCAL_DEVICE_INFO) DeviceObject->DeviceExtension;
irpStack = IoGetCurrentIrpStackLocation(Irp);
status = IoAcquireRemoveLock (&deviceInfo->RemoveLock, Irp);
if (!NT_SUCCESS (status)) {
Irp->IoStatus.Status = status;
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
DebugPrint(("%s\n",PnPMinorFunctionString(irpStack->MinorFunction)));
switch (irpStack->MinorFunction) {
case IRP_MN_START_DEVICE:
//
// The device is starting.
//
// We cannot touch the device (send it any non pnp irps) until a
// start device has been passed down to the lower drivers.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
KeInitializeEvent(&event,
NotificationEvent,
FALSE
);
IoSetCompletionRoutine(Irp,
(PIO_COMPLETION_ROUTINE) GpdCompletionRoutine,
&event,
TRUE,
TRUE,
TRUE);
status = IoCallDriver(deviceInfo->NextLowerDriver, Irp);
if (STATUS_PENDING == status) {
KeWaitForSingleObject(
&event,
Executive, // Waiting for reason of a driver
KernelMode, // Must be kernelmode if event memory is in stack
FALSE, // No allert
NULL); // No timeout
}
if (NT_SUCCESS(status) && NT_SUCCESS(Irp->IoStatus.Status)) {
status = GpdStartDevice(DeviceObject, Irp);
if(NT_SUCCESS(status))
{
//
// As we are successfully now back from our start device
// we can do work.
//
deviceInfo->Started = TRUE;//原来的代码
deviceInfo->Removed = FALSE;//原来的代码
//我增加的代码
//IoConnectInterrupt(,,,);
/* status = IoConnectInterrupt(&deviceInfo->InterruptObject,
GpdInterruptService,
deviceInfo,
NULL,
deviceInfo->InterruptVector,
deviceInfo->InterruptLevel,
deviceInfo->InterruptLevel,
deviceInfo->InterruptMode,
TRUE,
deviceInfo->InterruptAffinity,
FALSE);
if (!NT_SUCCESS(status))
{
DebugPrint((">>> IoConnectInterrupt Failed!\n"));
}
else
{
DebugPrint((">>> IoConnectInterrupt Succeeded!\n"));
deviceInfo->Started = TRUE;//原来的代码
deviceInfo->Removed = FALSE;//原来的代码
deviceInfo->TestIsr = 0;
}
*/ //增加结束
}
else
{
DebugPrint((">>> GpdStartDevice Failed!\n"));
}
}
//
// We must now complete the IRP, since we stopped it in the
// completion routine with STATUS_MORE_PROCESSING_REQUIRED.
//
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_QUERY_STOP_DEVICE:
//
// Fail the query stop to prevent the system from taking away hardware
// resources. If you do support this you must have a queue to hold
// incoming requests between stop and subsequent start with new set of
// resources.
//
Irp->IoStatus.Status = status = STATUS_UNSUCCESSFUL;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
//
// The device can be removed without disrupting the machine.
//
Irp->IoStatus.Status = STATUS_SUCCESS;
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(deviceInfo->NextLowerDriver, Irp);
break;
case IRP_MN_SURPRISE_REMOVAL:
//
// The device has been unexpectedly removed from the machine
// and is no longer available for I/O. Stop all access to the device.
// Release any resources associated with the device, but leave the
// device object attached to the device stack until the PnP Manager
// sends a subsequent IRP_MN_REMOVE_DEVICE request.
// You should fail any outstanding I/O to the device. You will
// not get a remove until all the handles open to the device
// have been closed.
//
deviceInfo->Removed = TRUE;
deviceInfo->Started = FALSE;
if (deviceInfo->PortWasMapped)
{
MmUnmapIoSpace(deviceInfo->PortBase, deviceInfo->PortCount);
deviceInfo->PortWasMapped = FALSE;
}
RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&win32DeviceName);
IoSkipCurrentIrpStackLocation(Irp);
Irp->IoStatus.Status = STATUS_SUCCESS;
status = IoCallDriver(deviceInfo->NextLowerDriver, Irp);
break;
case IRP_MN_REMOVE_DEVICE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -