/*++ Copyright (c) 1999-2000 Microsoft Corporation Module Name: Iocltdispatch.c Abstract: This module contains functions for handling supported IOCTL codes. Author: Nicholas Owens (Nichow) - 1999 Revision History: --*/ #include "pch.h" NTSTATUS SoftPCIOpenDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Handles all CREATES' we receive Arguments: DeviceObject - Pointer to the device object. Irp - PnP Irp to be dispatched. Return Value: NTSTATUS. --*/ { NTSTATUS status = STATUS_SUCCESS; // // Set Irp Status and Information // Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; // // Increment Reference Count // ObReferenceObject( DeviceObject ); // // Complete the Irp // IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } NTSTATUS SoftPCICloseDeviceControl( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Handles all CLOSES' we receive Arguments: DeviceObject - Pointer to the device object. Irp - PnP Irp to be dispatched. Return Value: NTSTATUS. --*/ { NTSTATUS status = STATUS_SUCCESS; // // Set Irp Status and Information // Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = 0; // // Decrement Reference Count // ObDereferenceObject( DeviceObject ); // // Complete the Irp // IoCompleteRequest( Irp, IO_NO_INCREMENT ); return status; } NTSTATUS SoftPCIIoctlAddDevice( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Handles all SOFTPCI_IOCTL_CREATE_DEVICE IOCLTS we receive. Here we attempt to create a new SoftPCI device. Arguments: DeviceObject - Pointer to the device object. Irp - PnP Irp to be dispatched. Return Value: NTSTATUS. --*/ { NTSTATUS status = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION irpSl; PVOID inputBuffer; PBOOLEAN outputBuffer; ULONG inputBufferLength; ULONG outputBufferLength; KIRQL irql; PSOFTPCI_DEVICE newSoftPciDevice; PSOFTPCI_DEVICE previousDevice; PSOFTPCI_DEVICE existingDevice; PSOFTPCI_SCRIPT_DEVICE scriptDevice; UNREFERENCED_PARAMETER(DeviceObject); // // Get Current Stack Location // irpSl = IoGetCurrentIrpStackLocation(Irp); // // Initialize input and output buffers to Irp->AssociatedIrp.SystemBuffer // inputBuffer = Irp->AssociatedIrp.SystemBuffer; outputBuffer = Irp->AssociatedIrp.SystemBuffer; // // Initialize input and output lengths. // inputBufferLength = irpSl->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpSl->Parameters.DeviceIoControl.OutputBufferLength; if (inputBufferLength == sizeof (SOFTPCI_DEVICE)) { newSoftPciDevice = (PSOFTPCI_DEVICE) inputBuffer; SoftPCIDbgPrint( SOFTPCI_INFO, "SOFTPCI: AddDeviceIoctl - BUS_%02x&DEV_%02x&FUN_%02x (0x%x)\n", newSoftPciDevice->Bus, newSoftPciDevice->Slot.Device, newSoftPciDevice->Slot.Function, &newSoftPciDevice->Config ); previousDevice = NULL; SoftPCILockDeviceTree(&irql); existingDevice = SoftPCIFindDevice( newSoftPciDevice->Bus, newSoftPciDevice->Slot.AsUSHORT, &previousDevice, FALSE ); SoftPCIUnlockDeviceTree(irql); if (!existingDevice) { if (!SoftPCIRealHardwarePresent(newSoftPciDevice)) { #if DBG if (IS_BRIDGE(newSoftPciDevice)){ ASSERT((newSoftPciDevice->Config.Mask.u.type1.PrimaryBus != 0) && (newSoftPciDevice->Config.Mask.u.type1.SecondaryBus != 0) && (newSoftPciDevice->Config.Mask.u.type1.SubordinateBus != 0)); } #endif // // Doesnt look like real hardware is here so lets allow a fake one. // status = SoftPCIAddNewDevice(newSoftPciDevice); }else{ // // We dont allow fake devices to be placed on real ones! // SoftPCIDbgPrint( SOFTPCI_ERROR, "SOFTPCI: AddDeviceIoctl - Physical Hardware exists at BUS_%02x&DEV_%02x&FUN_%02x\n", newSoftPciDevice->Bus, newSoftPciDevice->Slot.Device, newSoftPciDevice->Slot.Function ); status = STATUS_ACCESS_DENIED; } } }else{ // // We must be installing a path based device // ASSERT(inputBufferLength > sizeof(SOFTPCI_DEVICE)); scriptDevice = (PSOFTPCI_SCRIPT_DEVICE) inputBuffer; ASSERT(scriptDevice->ParentPathLength > 0 ); ASSERT(scriptDevice->ParentPath != NULL); status = SoftPCIAddNewDeviceByPath(scriptDevice); } // // Set outputBuffer to True // if (outputBufferLength >= sizeof(BOOLEAN)) { if (NT_SUCCESS(status)) { *outputBuffer = TRUE; } else { *outputBuffer = FALSE; } // // Set IoStatus.Information to the size of a Boolean or to outputBufferLength, whichever is lesser. // Irp->IoStatus.Information = (sizeof(BOOLEAN)AssociatedIrp.SystemBuffer // inputBuffer = Irp->AssociatedIrp.SystemBuffer; outputBuffer = Irp->AssociatedIrp.SystemBuffer; // // Initialize input and output lengths. // inputBufferLength = irpSl->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpSl->Parameters.DeviceIoControl.OutputBufferLength; Irp->IoStatus.Information = 0; if (inputBufferLength == sizeof(SOFTPCI_DEVICE)) { SoftPCIDbgPrint( SOFTPCI_INFO, "SOFTPCI: RemoveDeviceIoctl - BUS_%02x&DEV_%02x&FUN_%02x\n", inputBuffer->Bus, inputBuffer->Slot.Device, inputBuffer->Slot.Function ); status = SoftPCIRemoveDevice(inputBuffer); } // // Set outputBuffer to True // if (outputBufferLength >= sizeof(BOOLEAN)) { if (NT_SUCCESS(status)) { *outputBuffer = TRUE; } else { *outputBuffer = FALSE; } // // Set IoStatus.Information to the size of a Boolean // Irp->IoStatus.Information = sizeof(BOOLEAN); } else { status = STATUS_INSUFFICIENT_RESOURCES; } SoftPCIDbgPrint( SOFTPCI_IOCTL_LEVEL, "SOFTPCI: RemoveDeviceIoctl - BUS_%02x&DEV_%02x&FUN_%02x status=0x%x\n", inputBuffer->Bus, inputBuffer->Slot.Device, inputBuffer->Slot.Function, status ); return status; } NTSTATUS SoftPCIIoctlGetDeviceCount( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Handles all SOFTPCI_IOCTL_GET_NUMBER_OF_DEVICES IOCLTS we receive. Arguments: DeviceObject - Pointer to the device object. Irp - PnP Irp to be dispatched. Return Value: NTSTATUS. --*/ { NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION irpSl; PULONG outputBuffer; ULONG outputBufferLength; UNREFERENCED_PARAMETER(DeviceObject); // // Get Current Stack Location // irpSl = IoGetCurrentIrpStackLocation(Irp); // // Initialize input and output buffers to Irp->AssociatedIrp.SystemBuffer // outputBuffer = Irp->AssociatedIrp.SystemBuffer; // // Initialize input and output lengths. // outputBufferLength = irpSl->Parameters.DeviceIoControl.OutputBufferLength; // // Set outputBuffer to True // if (outputBufferLength >= sizeof(ULONG)) { *outputBuffer = SoftPciTree.DeviceCount; // // Set IoStatus.Information to the size of a Boolean or to outputBufferLength, whichever is lesser. // Irp->IoStatus.Information = (sizeof(ULONG)AssociatedIrp.SystemBuffer // inputBuffer = (PSOFTPCI_DEVICE)Irp->AssociatedIrp.SystemBuffer; outputBuffer = (PSOFTPCI_DEVICE)Irp->AssociatedIrp.SystemBuffer; // // Initialize input and output lengths. // inputBufferLength = irpSp->Parameters.DeviceIoControl.InputBufferLength; outputBufferLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength; device = NULL; if (inputBufferLength == sizeof(SOFTPCI_DEVICE)) { device = SoftPCIFindDevice( inputBuffer->Bus, inputBuffer->Slot.AsUSHORT, NULL, TRUE ); } // // Set outputBuffer to True // if (outputBufferLength >= sizeof(SOFTPCI_DEVICE)) { if (device) { RtlCopyMemory(outputBuffer, device, sizeof(SOFTPCI_DEVICE)); outputBufferLength = sizeof(SOFTPCI_DEVICE); status = STATUS_SUCCESS; } else { outputBufferLength = 0; } // // Set IoStatus.Information to number of bytes returned // Irp->IoStatus.Information = outputBufferLength; } else { status = STATUS_INSUFFICIENT_RESOURCES; } SoftPCIUnlockDeviceTree(irql); return status; } NTSTATUS SoftPCIIocltReadWriteConfig( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) /*++ Routine Description: Handles all SOFTPCI_IOCTL_RW_CONFIG we receive. Arguments: DeviceObject - Pointer to the device object. Irp - PnP Irp to be dispatched. Return Value: NTSTATUS. --*/ { PIO_STACK_LOCATION irpSl; PUCHAR outputBuffer; ULONG outputBufferLength; ULONG bytes; PSOFTPCI_RW_CONTEXT context; PCI_SLOT_NUMBER slot; UNREFERENCED_PARAMETER(DeviceObject); irpSl = IoGetCurrentIrpStackLocation(Irp); // // Initialize input and output buffers // context = (PSOFTPCI_RW_CONTEXT) Irp->AssociatedIrp.SystemBuffer; outputBuffer = (PUCHAR)Irp->AssociatedIrp.SystemBuffer; // // Initialize input and output lengths. // outputBufferLength = irpSl->Parameters.DeviceIoControl.OutputBufferLength; slot.u.AsULONG = 0; slot.u.bits.DeviceNumber = context->Slot.Device; slot.u.bits.FunctionNumber = context->Slot.Function; Irp->IoStatus.Information = 0; bytes = 0; switch (context->WriteConfig) { case SoftPciWriteConfig: bytes = SoftPCIWriteConfigSpace( SoftPciTree.BusInterface, (UCHAR)context->Bus, slot.u.AsULONG, context->Data, context->Offset, outputBufferLength ); break; case SoftPciReadConfig: bytes = SoftPCIReadConfigSpace( SoftPciTree.BusInterface, (UCHAR)context->Bus, slot.u.AsULONG, outputBuffer, context->Offset, outputBufferLength ); break; default: return STATUS_UNSUCCESSFUL; } if (bytes != outputBufferLength) { // // We failed to get all the data we wanted. // return STATUS_UNSUCCESSFUL; } // // Set IoStatus.Information to the number of bytes returned // Irp->IoStatus.Information = bytes; return STATUS_SUCCESS; }