/*++ 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 #include #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; } }