You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
442 lines
9.6 KiB
442 lines
9.6 KiB
/*++
|
|
|
|
Copyright (c) 1990-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dispatch.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the dispatch logic for ISAPNP
|
|
|
|
Author:
|
|
|
|
Shie-Lin Tzong (shielint)
|
|
|
|
Environment:
|
|
|
|
Kernel Mode Driver.
|
|
|
|
--*/
|
|
|
|
#include "busp.h"
|
|
#include "pnpisa.h"
|
|
#include <initguid.h>
|
|
#include <wdmguid.h>
|
|
#include "halpnpp.h"
|
|
|
|
//
|
|
// Prototype
|
|
//
|
|
|
|
VOID
|
|
PipCompleteRequest(
|
|
IN OUT PIRP Irp,
|
|
IN NTSTATUS Status,
|
|
IN PVOID Information
|
|
);
|
|
|
|
NTSTATUS
|
|
PipPassIrp(
|
|
PDEVICE_OBJECT pDeviceObject,
|
|
PIRP pIrp
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, PiUnload)
|
|
#pragma alloc_text(PAGE, PiDispatchPnp)
|
|
#pragma alloc_text(PAGE, PiDispatchDevCtl)
|
|
#pragma alloc_text(PAGE, PiDispatchCreate)
|
|
#pragma alloc_text(PAGE, PiDispatchClose)
|
|
#pragma alloc_text(PAGE, PiAddDevice)
|
|
#pragma alloc_text(PAGE, PipPassIrp)
|
|
#endif
|
|
|
|
VOID
|
|
PiUnload(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks if there is any pnpisa card in the machine. If non, it returns
|
|
STATUS_NO_SUCH_DEVICE.
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to our pseudo driver object.
|
|
|
|
DeviceObject - Pointer to the device object for which this requestapplies.
|
|
|
|
Return Value:
|
|
|
|
NT status.
|
|
|
|
--*/
|
|
{
|
|
|
|
PAGED_CODE();
|
|
// We can not be unload.
|
|
// ASSERT(0);
|
|
}
|
|
|
|
NTSTATUS
|
|
PiAddDevice(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks if there is any pnpisa card in the machine. If non, it returns
|
|
STATUS_NO_SUCH_DEVICE.
|
|
|
|
(Not any more, fix this)
|
|
|
|
Arguments:
|
|
|
|
DriverObject - Pointer to our pseudo driver object.
|
|
|
|
DeviceObject - Pointer to the device object for which this requestapplies.
|
|
|
|
Return Value:
|
|
|
|
NT status.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PDEVICE_OBJECT busFdo;
|
|
PPI_BUS_EXTENSION busExtension;
|
|
UNICODE_STRING interfaceName;
|
|
ULONG busNumber;
|
|
|
|
PAGED_CODE();
|
|
|
|
|
|
|
|
|
|
KeWaitForSingleObject( &IsaBusNumberLock,
|
|
Executive,
|
|
KernelMode,
|
|
FALSE,
|
|
NULL );
|
|
ActiveIsaCount++;
|
|
|
|
|
|
//
|
|
// We are creating the first instance of the ISA bus.
|
|
//
|
|
RtlInitUnicodeString(&interfaceName, NULL);
|
|
|
|
//
|
|
// Create an FDO to attatch to the PDO
|
|
//
|
|
status = IoCreateDevice( DriverObject,
|
|
sizeof(PI_BUS_EXTENSION), // Extension Size
|
|
NULL, // DeviceName
|
|
FILE_DEVICE_BUS_EXTENDER,
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
FALSE,
|
|
&busFdo);
|
|
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
busExtension = (PPI_BUS_EXTENSION) busFdo->DeviceExtension;
|
|
busExtension->Flags = DF_BUS;
|
|
busExtension->FunctionalBusDevice = busFdo;
|
|
busExtension->AttachedDevice = IoAttachDeviceToDeviceStack(busFdo, DeviceObject);
|
|
busExtension->PhysicalBusDevice = DeviceObject;
|
|
|
|
if (PiNeedDeferISABridge(DriverObject,DeviceObject)) {
|
|
busNumber = RtlFindClearBitsAndSet (BusNumBM,1,1);
|
|
ASSERT (busNumber != 0);
|
|
} else {
|
|
busNumber = RtlFindClearBitsAndSet (BusNumBM,1,0);
|
|
}
|
|
|
|
ASSERT (busNumber != 0xFFFFFFFF);
|
|
|
|
if (ActiveIsaCount == 1) {
|
|
if (PipFirstInit) {
|
|
#if ISOLATE_CARDS
|
|
PipResetGlobals();
|
|
#endif
|
|
}
|
|
PipDriverObject = DriverObject;
|
|
busExtension->ReadDataPort = NULL;
|
|
|
|
ASSERT (PipBusExtension == NULL);
|
|
//
|
|
//bus extension can get touched in pipdeletedevice
|
|
//
|
|
PipBusExtension = (PBUS_EXTENSION_LIST)ExAllocatePool (NonPagedPool,sizeof (BUS_EXTENSION_LIST));
|
|
if (!PipBusExtension) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
PipBusExtension->BusExtension = busExtension;
|
|
PipBusExtension->Next=NULL;
|
|
|
|
PipFirstInit = TRUE;
|
|
} else {
|
|
PBUS_EXTENSION_LIST busList;
|
|
|
|
ASSERT (PipDriverObject);
|
|
busExtension->ReadDataPort = NULL;
|
|
|
|
ASSERT (PipBusExtension);
|
|
busList = PipBusExtension;
|
|
while (busList->Next) {
|
|
busList = (PBUS_EXTENSION_LIST)busList->Next;
|
|
}
|
|
busList->Next = (PBUS_EXTENSION_LIST)ExAllocatePool (NonPagedPool,sizeof (BUS_EXTENSION_LIST));
|
|
|
|
if (!busList->Next) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
busList=busList->Next;
|
|
busList->BusExtension = busExtension;
|
|
busList->Next=NULL;
|
|
}
|
|
busExtension->BusNumber = busNumber;
|
|
|
|
busFdo->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
}
|
|
|
|
KeSetEvent( &IsaBusNumberLock,
|
|
0,
|
|
FALSE );
|
|
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PiDispatchPnp(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine handles all IRP_MJ_PNP_POWER IRPs.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - Pointer to the device object for which this IRP applies.
|
|
|
|
Irp - Pointer to the IRP_MJ_PNP_POWER IRP to dispatch.
|
|
|
|
Return Value:
|
|
|
|
NT status.
|
|
|
|
--*/
|
|
{
|
|
PIO_STACK_LOCATION irpSp;
|
|
NTSTATUS status;
|
|
ULONG length;
|
|
PVOID information = NULL;
|
|
PWCHAR requestId, ids;
|
|
PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
|
|
PCM_RESOURCE_LIST cmResources;
|
|
PDEVICE_INFORMATION deviceInfo;
|
|
PDEVICE_CAPABILITIES deviceCapabilities;
|
|
PPNP_BUS_INFORMATION busInfo;
|
|
PPI_BUS_EXTENSION busExtension;
|
|
PDEVICE_INFORMATION deviceExtension = NULL;
|
|
UNICODE_STRING unicodeString;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Get a pointer to our stack location and take appropriate action based
|
|
// on the minor function.
|
|
//
|
|
|
|
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
busExtension = DeviceObject->DeviceExtension;
|
|
if (busExtension->Flags & DF_BUS) {
|
|
if (busExtension->AttachedDevice == NULL) {
|
|
status = STATUS_NO_SUCH_DEVICE;
|
|
PipCompleteRequest(Irp, status, information);
|
|
goto exit;
|
|
}
|
|
} else {
|
|
busExtension = NULL;
|
|
deviceExtension = DeviceObject->DeviceExtension;
|
|
if (deviceExtension->Flags & DF_DELETED) {
|
|
if (irpSp->MinorFunction == IRP_MN_REMOVE_DEVICE) {
|
|
status = STATUS_SUCCESS;
|
|
} else {
|
|
status = STATUS_NO_SUCH_DEVICE;
|
|
}
|
|
PipCompleteRequest(Irp, status, information);
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Dispatch IRPs bound for the FDO
|
|
//
|
|
if (busExtension) {
|
|
status = PiDispatchPnpFdo(
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
|
|
//return status;
|
|
} else {
|
|
#if ISOLATE_CARDS
|
|
//
|
|
// Dispatch IRPs bound for the PDO
|
|
//
|
|
status = PiDispatchPnpPdo(
|
|
DeviceObject,
|
|
Irp
|
|
);
|
|
//return status;
|
|
#endif
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
//
|
|
// Complete the Irp and return.
|
|
//
|
|
|
|
// PipCompleteRequest(Irp, status, information);
|
|
return status;
|
|
} // PiDispatchPnp
|
|
|
|
|
|
VOID
|
|
PipCompleteRequest(
|
|
IN OUT PIRP Irp,
|
|
IN NTSTATUS Status,
|
|
IN PVOID Information
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine completes PnP irps for our pseudo driver.
|
|
|
|
Arguments:
|
|
|
|
Irp - Supplies a pointer to the irp to be completed.
|
|
|
|
Status - completion status.
|
|
|
|
Information - completion information to be passed back.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
//
|
|
// Complete the IRP. First update the status...
|
|
//
|
|
|
|
Irp->IoStatus.Status = Status;
|
|
Irp->IoStatus.Information = (ULONG_PTR)Information;
|
|
|
|
//
|
|
// ... and complete it.
|
|
//
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
NTSTATUS
|
|
PipPassIrp(
|
|
PDEVICE_OBJECT DeviceObject,
|
|
PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This function pass the Irp to lower level driver.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - the Fdo or Pdo
|
|
Irp - the request
|
|
|
|
Return:
|
|
|
|
STATUS_PENDING
|
|
|
|
--*/
|
|
{
|
|
|
|
PIO_STACK_LOCATION ioStackLocation; // our stack location
|
|
PIO_STACK_LOCATION nextIoStackLocation; // next guy's
|
|
PPI_BUS_EXTENSION busExtension = (PPI_BUS_EXTENSION) DeviceObject->DeviceExtension;
|
|
|
|
|
|
IoSkipCurrentIrpStackLocation(Irp);
|
|
|
|
//
|
|
// Io call next driver, we pass it to root hub's parent no matter which tier we are at.
|
|
//
|
|
|
|
return IoCallDriver( busExtension->AttachedDevice, Irp );
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
PiDispatchDevCtl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN OUT PIRP Irp
|
|
)
|
|
|
|
/*++
|
|
|
|
Description:
|
|
|
|
This function passes the Device Control Irp to lower level driver.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - the Fdo or Pdo
|
|
Irp - the request
|
|
|
|
Return:
|
|
|
|
STATUS_PENDING
|
|
|
|
--*/
|
|
{
|
|
PPI_BUS_EXTENSION busExtension = (PPI_BUS_EXTENSION) DeviceObject->DeviceExtension;
|
|
NTSTATUS status;
|
|
|
|
PAGED_CODE();
|
|
if (busExtension->Flags & DF_BUS) {
|
|
IoSkipCurrentIrpStackLocation (Irp);
|
|
return IoCallDriver( busExtension->AttachedDevice, Irp );
|
|
} else {
|
|
//
|
|
//We're at the bottom
|
|
//
|
|
status = Irp->IoStatus.Status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return status;
|
|
}
|
|
}
|