Code: Select all
#include "pciidex.h"
#include <initguid.h>
#include <wdmguid.h>
#define NDEBUG
#include <debug.h>
//#define MAX_SG_ELEMENTS 0x20 <-- in reactos\hal\halx86\generic\dma.c
//PDRIVER_LIST_CONTROL
static VOID NTAPI
AdapterListControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PSCATTER_GATHER_LIST ScatterGather,
IN PVOID DeviceExtension)
{
PPDO_DEVICE_EXTENSION ChannelPdoExtension;
PFDO_DEVICE_EXTENSION ControllerFdoExtension;
PPHYSICAL_REGION_DESCRIPTOR_TABLE TablePRD;
ULONG LengthElement;
ULONG AddressElement;
ULONG BusMasterChannelBase;
ULONG ix, jx;
ULONG len;
ULONG BytesLimit = 0x10000; //64K boundary
DPRINT("AdapterListControl \n");
ChannelPdoExtension = (PPDO_DEVICE_EXTENSION)DeviceExtension;
ChannelPdoExtension->SGList = ScatterGather;
ix = 0;
jx = 0;
if ( ScatterGather->NumberOfElements > 0 )
{
for (ix = 0; ix < ScatterGather->NumberOfElements; ix++)
{
DPRINT("AdapterListControl: ix - %x\n", ix);
AddressElement = ScatterGather->Elements[ix].Address.LowPart;
LengthElement = ScatterGather->Elements[ix].Length;
DPRINT("AdapterListControl: AddressElement - %p\n", AddressElement);
DPRINT("AdapterListControl: LengthElement - %p\n", LengthElement);
if ( LengthElement > 0 )
{
do
{
DPRINT("AdapterListControl: NumberOfMapRegisters - %x\n", ChannelPdoExtension->NumberOfMapRegisters);
TablePRD = ChannelPdoExtension->CommonBuffer;
DPRINT("AdapterListControl: TablePRD - %p\n", TablePRD);
TablePRD->Elements[jx].BaseAddress = AddressElement;
len = BytesLimit - (USHORT)AddressElement;
DPRINT("AdapterListControl: AddressElement - %p\n", AddressElement);
DPRINT("AdapterListControl: len - %x\n", len);
if ( len >= LengthElement )
{
DPRINT("AdapterListControl: len >= LengthElement\n");
if ( LengthElement > BytesLimit )
{
DPRINT("AdapterListControl: LengthElement > BytesLimit\n");
TablePRD->Elements[jx].ByteCount = 0;
AddressElement += BytesLimit;
LengthElement -= BytesLimit;
}
else
{
DPRINT("AdapterListControl: LengthElement <= BytesLimit\n");
TablePRD->Elements[jx].ByteCount = (USHORT)(LengthElement & 0x0000FFFE);
AddressElement += (USHORT)(LengthElement & 0x0000FFFE);
LengthElement = 0;
}
}
else
{
DPRINT("AdapterListControl: len < LengthElement\n");
AddressElement += len;
TablePRD->Elements[jx].ByteCount = (USHORT)len;
LengthElement -= len;
}
TablePRD->Elements[jx].EndTable &= 0x7FFF;
DPRINT("AdapterListControl: TablePRD->Elements[%x].BaseAddress - %p\n", jx, TablePRD->Elements[jx].BaseAddress);
DPRINT("AdapterListControl: TablePRD->Elements[%x].ByteCount - %x\n", jx, TablePRD->Elements[jx].ByteCount);
DPRINT("AdapterListControl: TablePRD->Elements[%x].EndTable - %x\n", jx, TablePRD->Elements[jx].EndTable);
++jx;
}
while ( LengthElement );
}
}
}
if ( jx > 0 )
TablePRD->Elements[jx-1].EndTable |= 0x8000;
else
TablePRD->Elements[jx].EndTable |= 0x8000;
ControllerFdoExtension = (PFDO_DEVICE_EXTENSION)ChannelPdoExtension->ControllerFdo->DeviceExtension;
BusMasterChannelBase = ControllerFdoExtension->BusMasterBase + 8 * (ChannelPdoExtension->Channel & 1);//BAR4+0 - Primary channel, BAR4+8 - Secondary channel
DPRINT("AdapterListControl: BusMasterChannelBase - %p\n", BusMasterChannelBase);
//BusMasterDisable
WRITE_PORT_UCHAR((PUCHAR)BusMasterChannelBase, 0);
WRITE_PORT_UCHAR((PUCHAR)(BusMasterChannelBase + 2), 6);
//Write to Descriptor Table Pointer Register
DPRINT("AdapterListControl: ChannelPdoExtension->LogicalAddress.LowPart - %p\n", ChannelPdoExtension->LogicalAddress.LowPart);
WRITE_PORT_ULONG((PULONG)(BusMasterChannelBase + 4), ChannelPdoExtension->LogicalAddress.LowPart);
((PALLOCATE_ADAPTER)ChannelPdoExtension->AllocateAdapter)(ChannelPdoExtension->AllocateAdapterContext);
}
static NTSTATUS NTAPI
BusMasterPrepare(
IN PPDO_DEVICE_EXTENSION DeviceExtension,
IN PVOID CurrentVirtualAddress,
IN ULONG Length,
IN PMDL Mdl,
IN BOOLEAN WriteToDevice,
IN PVOID AllocateAdapter,
IN PDEVICE_OBJECT AtaXChannelFdo)
{
NTSTATUS Status;
PDMA_ADAPTER DmaAdapter = DeviceExtension->DmaAdapter;
DeviceExtension->WriteToDevice = WriteToDevice;
DPRINT("BusMasterPrepare: DeviceExtension - %p\n", DeviceExtension);
DPRINT("BusMasterPrepare: CurrentVirtualAddress - %p\n", CurrentVirtualAddress);
DPRINT("BusMasterPrepare: Length - %p\n", Length);
DPRINT("BusMasterPrepare: Mdl - %p\n", Mdl);
DPRINT("BusMasterPrepare: WriteToDevice - %p\n", WriteToDevice);
DPRINT("BusMasterPrepare: AllocateAdapter - %p\n", AllocateAdapter);
DPRINT("BusMasterPrepare: AtaXChannelFdo - %p\n", AtaXChannelFdo);
DeviceExtension->AllocateAdapter = AllocateAdapter;
DeviceExtension->AllocateAdapterContext = (ULONG)AtaXChannelFdo;
Status = DmaAdapter->DmaOperations->GetScatterGatherList(
DmaAdapter,
DeviceExtension->SelfDevice,
Mdl,
CurrentVirtualAddress,
Length,
(PDRIVER_LIST_CONTROL)AdapterListControl,
DeviceExtension,
WriteToDevice);
DPRINT("BusMasterPrepare: return - %p\n", Status);
return Status;
}
static NTSTATUS NTAPI
BusMasterStart(IN PPDO_DEVICE_EXTENSION DeviceExtension)//ChannelPdoExtension
{
PFDO_DEVICE_EXTENSION ControllerFdoExtension;
ULONG BusMasterChannelBase;
DPRINT("BusMasterEnable: DeviceExtension - %p\n", DeviceExtension);
ControllerFdoExtension = DeviceExtension->ControllerFdo->DeviceExtension;
BusMasterChannelBase = ControllerFdoExtension->BusMasterBase + 8 * (DeviceExtension->Channel & 1);
if ( DeviceExtension->WriteToDevice )
{
DPRINT("BusMasterEnable: Write to device (1). BusMasterChannelBase - %p\n", BusMasterChannelBase);
//Start Bus Master. PCI bus master reads are performed.
WRITE_PORT_UCHAR((PUCHAR)BusMasterChannelBase, 1);
}
else
{
DPRINT("BusMasterEnable: Read from device (9). BusMasterChannelBase - %p\n", BusMasterChannelBase);
//Start Bus Master. PCI bus master writes are performed.
WRITE_PORT_UCHAR((PUCHAR)BusMasterChannelBase, 9);
}
DPRINT("BusMasterEnable: return STATUS_SUCCESS\n");
return STATUS_SUCCESS;
}
static NTSTATUS NTAPI
BusMasterStop(IN PPDO_DEVICE_EXTENSION DeviceExtension)//ChannelPdoExtension
{
PFDO_DEVICE_EXTENSION ControllerFdoExtension;
ULONG BusMasterChannelBase;
DPRINT("BusMasterDisable: DeviceExtension - %p\n", DeviceExtension);
ControllerFdoExtension = DeviceExtension->ControllerFdo->DeviceExtension;
BusMasterChannelBase = ControllerFdoExtension->BusMasterBase + 8 * (DeviceExtension->Channel & 1);
DPRINT("BusMasterDisable: BusMasterChannelBase - %p\n", BusMasterChannelBase);
/*
Start/Stop Bus Master: Writing a '1' to this bit enables bus master operation of the controller.
Bus master operation begins when this bit is detected changing from a zero to a one. The
controller will transfer data between the IDE device and memory only when this bit is set.
Master operation can be halted by writing a '0' to this bit. All state information is lost when a '0'
is written; Master mode operation cannot be stopped and then resumed. If this bit is reset while
bus master operation is still active (i.e., the Bus Master IDE Active bit of the Bus Master IDE
Status register for that IDE channel is set) and the drive has not yet finished its data transfer (The
Interupt bit in the Bus Master IDE Status register for that IDE channel is not set), the bus master
command is said to be aborted and data transfered from the drive may be discarded before being
written to system memory. This bit is intended to be reset after the data transfer is completed, as
indicated by either the Bus Master IDE Active bit or the Interrupt bit of the Bus Master IDE
Status register for that IDE channel being set, or both. */
WRITE_PORT_UCHAR((PUCHAR)BusMasterChannelBase, 0); //Stop Bus Master (Bus Master IDE Command Register)
/*
Interrupt: This bit is set by the rising edge of the IDE interrupt line. This bit is cleared when a
'1' is written to it by software. Software can use this bit to determine if an IDE device has
asserted its interrupt line. When this bit is read as a one, all data transfered from the drive is
visible in system memory. */
WRITE_PORT_UCHAR((PUCHAR)(BusMasterChannelBase + 2), 4); //Clear Interrupt bit (Bus Master IDE Status Register)
DPRINT("BusMasterDisable: return STATUS_SUCCESS\n");
return STATUS_SUCCESS;
}
static ULONG NTAPI
BusMasterReadStatus(IN PPDO_DEVICE_EXTENSION DeviceExtension)//ChannelPdoExtension
{
PFDO_DEVICE_EXTENSION ControllerFdoExtension;
ULONG BusMasterChannelBase;
ULONG Status = 0;
UCHAR Result;
DPRINT("BusMasterReadStatus: DeviceExtension - %p\n", DeviceExtension);
ControllerFdoExtension = DeviceExtension->ControllerFdo->DeviceExtension;
BusMasterChannelBase = ControllerFdoExtension->BusMasterBase + 8 * (DeviceExtension->Channel & 1);
Result = READ_PORT_UCHAR((PUCHAR)(BusMasterChannelBase + 2));
DPRINT("BusMasterReadStatus: Result - %p\n", Result);
/* Bus Master IDE Active: This bit is set when the Start bit is written to the Command register.
This bit is cleared when the last transfer for a region is performed, where EOT for that region is
set in the region descriptor. It is also cleared when the Start bit is cleared in the Command
register. When this bit is read as a zero, all data transfered from the drive during the previous
bus master command is visible in system memory, unless the bus master command was aborted.
*/
if ( Result & 1 )
Status = 1;
/* Error: This bit is set when the controller encounters an error in transferring data to/from
memory. The exact error condition is bus specific and can be determined in a bus specific
manner. This bit is cleared when a '1' is written to it by software.
*/
if ( Result & 2 )
Status |= 2;
/* Interrupt: This bit is set by the rising edge of the IDE interrupt line. This bit is cleared when a
'1' is written to it by software. Software can use this bit to determine if an IDE device has
asserted its interrupt line. When this bit is read as a one, all data transfered from the drive is
visible in system memory.
*/
if ( Result & 4 )
Status |= 4;
DPRINT("BusMasterReadStatus: return - %p\n", Status);
return Status;
}
static NTSTATUS NTAPI
BusMasterComplete(IN PPDO_DEVICE_EXTENSION DeviceExtension)//ChannelPdoExtension
{
PDMA_ADAPTER DmaAdapter = DeviceExtension->DmaAdapter;
DPRINT("BusMasterComplete: DeviceExtension - %p\n", DeviceExtension);
DmaAdapter->DmaOperations->PutScatterGatherList(
DeviceExtension->DmaAdapter,
DeviceExtension->SGList,
DeviceExtension->WriteToDevice);
DeviceExtension->SGList = 0;
DeviceExtension->AllocateAdapter = 0;
DeviceExtension->AllocateAdapterContext = 0;
DPRINT("BusMasterComplete: return STATUS_SUCCESS\n");
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
QueryBusMasterInterface(IN PPDO_DEVICE_EXTENSION DeviceExtension, IN PIO_STACK_LOCATION Stack)
{
PBUS_MASTER_INTERFACE BusMasterInterface;
PFDO_DEVICE_EXTENSION FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension;
DPRINT("QueryBusMasterInterface: FdoDeviceExtension - %p, BusMasterBase - %p\n", FdoDeviceExtension, FdoDeviceExtension->BusMasterBase);
BusMasterInterface = (PBUS_MASTER_INTERFACE)Stack->Parameters.QueryInterface.Interface;
BusMasterInterface->Size = sizeof(BUS_MASTER_INTERFACE);
DPRINT("QueryBusMasterInterface: BusMasterInterface->Size - %p \n", BusMasterInterface->Size);
BusMasterInterface->ChannelPdoExtension = DeviceExtension;
BusMasterInterface->BusMasterBase = FdoDeviceExtension->BusMasterBase;
BusMasterInterface->BusMasterPrepare = (PBUS_MASTER_PREPARE)BusMasterPrepare;
BusMasterInterface->BusMasterStart = (PBUS_MASTER_START)BusMasterStart;
BusMasterInterface->BusMasterStop = (PBUS_MASTER_STOP)BusMasterStop;
BusMasterInterface->BusMasterReadStatus = (PBUS_MASTER_READ_STATUS)BusMasterReadStatus;
BusMasterInterface->BusMasterComplete = (PBUS_MASTER_COMPLETE)BusMasterComplete;
DPRINT("QueryBusMasterInterface: return STATUS_SUCCESS\n");
return STATUS_SUCCESS;
}
Code: Select all
typedef NTSTATUS
(NTAPI *PBUS_MASTER_PREPARE)(
IN PVOID DeviceExtension,
IN PVOID CurrentVirtualAddress,
IN ULONG Length,
IN PMDL Mdl,
IN BOOLEAN WriteToDevice,
IN PVOID AllocateAdapter,
IN PDEVICE_OBJECT AtaXChannelFdo);
typedef NTSTATUS
(NTAPI *PBUS_MASTER_START)(IN PVOID DeviceExtension);
typedef NTSTATUS
(NTAPI *PBUS_MASTER_STOP)(IN PVOID DeviceExtension);
typedef NTSTATUS
(NTAPI *PBUS_MASTER_READ_STATUS)(IN PVOID DeviceExtension);
typedef NTSTATUS
(NTAPI *PBUS_MASTER_COMPLETE)(IN PVOID DeviceExtension);
typedef struct _BUS_MASTER_INTERFACE {
// generic interface header
USHORT Size;
USHORT Version;
PVOID Context;
PINTERFACE_REFERENCE InterfaceReference;
PINTERFACE_DEREFERENCE InterfaceDereference;
// bus master interface
PVOID ChannelPdoExtension;
ULONG BusMasterBase;
PBUS_MASTER_PREPARE BusMasterPrepare;
PBUS_MASTER_START BusMasterStart;
PBUS_MASTER_STOP BusMasterStop;
PBUS_MASTER_READ_STATUS BusMasterReadStatus;
PBUS_MASTER_COMPLETE BusMasterComplete;
} BUS_MASTER_INTERFACE, *PBUS_MASTER_INTERFACE;
typedef struct _PHYSICAL_REGION_DESCRIPTOR {
ULONG BaseAddress;
USHORT ByteCount;
USHORT EndTable;
} PHYSICAL_REGION_DESCRIPTOR, *PPHYSICAL_REGION_DESCRIPTOR;
typedef struct _PHYSICAL_REGION_DESCRIPTOR_TABLE {
PHYSICAL_REGION_DESCRIPTOR Elements[1];
} PHYSICAL_REGION_DESCRIPTOR_TABLE, *PPHYSICAL_REGION_DESCRIPTOR_TABLE;
Code: Select all
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: PCI IDE bus driver extension
* FILE: drivers/storage/pciidex/fdo.c
* PURPOSE: IRP_MJ_PNP operations for FDOs
* PROGRAMMERS: Hervй Poussineau (hpoussin@reactos.org)
*/
#include "pciidex.h"
//#define NDEBUG
#include <debug.h>
#include <initguid.h>
#include <wdmguid.h>
static NTSTATUS
GetBusInterface(
IN PFDO_DEVICE_EXTENSION DeviceExtension)
{
PBUS_INTERFACE_STANDARD BusInterface = NULL;
KEVENT Event;
IO_STATUS_BLOCK IoStatus;
PIRP Irp;
PIO_STACK_LOCATION Stack;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
if (DeviceExtension->BusInterface)
{
DPRINT("We already have the bus interface\n");
goto cleanup;
}
BusInterface = ExAllocatePool(PagedPool, sizeof(BUS_INTERFACE_STANDARD));
if (!BusInterface)
{
DPRINT("ExAllocatePool() failed\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(
IRP_MJ_PNP,
DeviceExtension->LowerDevice,
NULL,
0,
NULL,
&Event,
&IoStatus);
if (!Irp)
{
DPRINT("IoBuildSynchronousFsdRequest() failed\n");
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;
Stack = IoGetNextIrpStackLocation(Irp);
Stack->MajorFunction = IRP_MJ_PNP;
Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&GUID_BUS_INTERFACE_STANDARD;
Stack->Parameters.QueryInterface.Version = 1;
Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
Stack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = IoStatus.Status;
}
if (!NT_SUCCESS(Status))
goto cleanup;
DeviceExtension->BusInterface = BusInterface;
BusInterface = NULL;
Status = STATUS_SUCCESS;
cleanup:
if (BusInterface) ExFreePool(BusInterface);
return Status;
}
static NTSTATUS
ReleaseBusInterface(
IN PFDO_DEVICE_EXTENSION DeviceExtension)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
if (DeviceExtension->BusInterface)
{
(*DeviceExtension->BusInterface->InterfaceDereference)(
DeviceExtension->BusInterface->Context);
DeviceExtension->BusInterface = NULL;
Status = STATUS_SUCCESS;
}
return Status;
}
NTSTATUS NTAPI
PciIdeXAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT Pdo)
{
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_OBJECT Fdo;
ULONG BytesRead;
PCI_COMMON_CONFIG PciConfig;
NTSTATUS Status;
DPRINT("PciIdeXAddDevice(%p %p)\n", DriverObject, Pdo);
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
ASSERT(DriverExtension);
Status = IoCreateDevice(
DriverObject,
sizeof(FDO_DEVICE_EXTENSION) + DriverExtension->MiniControllerExtensionSize,
NULL,
FILE_DEVICE_BUS_EXTENDER,
FILE_DEVICE_SECURE_OPEN,
TRUE,
&Fdo);
if (!NT_SUCCESS(Status))
{
DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
return Status;
}
DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
DeviceExtension->Common.IsFDO = TRUE;
Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
if (!NT_SUCCESS(Status))
{
DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
return Status;
}
Status = GetBusInterface(DeviceExtension);
if (!NT_SUCCESS(Status))
{
DPRINT("GetBusInterface() failed with status 0x%08lx\n", Status);
IoDetachDevice(DeviceExtension->LowerDevice);
return Status;
}
BytesRead = (*DeviceExtension->BusInterface->GetBusData)(
DeviceExtension->BusInterface->Context,
PCI_WHICHSPACE_CONFIG,
&PciConfig,
0,
PCI_COMMON_HDR_LENGTH);
if (BytesRead != PCI_COMMON_HDR_LENGTH)
{
DPRINT("BusInterface->GetBusData() failed()\n");
ReleaseBusInterface(DeviceExtension);
IoDetachDevice(DeviceExtension->LowerDevice);
return STATUS_IO_DEVICE_ERROR;
}
/*
DPRINT("PciConfig.VendorID - %x\n", PciConfig.VendorID);
DPRINT("PciConfig.DeviceID - %x\n", PciConfig.DeviceID);
DPRINT("PciConfig.Command - %x\n", PciConfig.Command);
DPRINT("PciConfig.Status - %x\n", PciConfig.Status);
DPRINT("PciConfig.RevisionID - %x\n", PciConfig.RevisionID);
DPRINT("PciConfig.ProgIf - %x\n", PciConfig.ProgIf);
DPRINT("PciConfig.SubClass - %x\n", PciConfig.SubClass);
DPRINT("PciConfig.BaseClass - %x\n", PciConfig.BaseClass);
DPRINT("PciConfig.CacheLineSize - %x\n", PciConfig.CacheLineSize);
DPRINT("PciConfig.LatencyTimer - %x\n", PciConfig.LatencyTimer);
DPRINT("PciConfig.HeaderType - %x\n", PciConfig.HeaderType);
DPRINT("PciConfig.BIST - %x\n", PciConfig.BIST);
DPRINT("PciConfig.u.type0.BaseAddresses[0] - %x\n", PciConfig.u.type0.BaseAddresses[0]);
DPRINT("PciConfig.u.type0.BaseAddresses[1] - %x\n", PciConfig.u.type0.BaseAddresses[1]);
DPRINT("PciConfig.u.type0.BaseAddresses[2] - %x\n", PciConfig.u.type0.BaseAddresses[2]);
DPRINT("PciConfig.u.type0.BaseAddresses[3] - %x\n", PciConfig.u.type0.BaseAddresses[3]);
DPRINT("PciConfig.u.type0.BaseAddresses[4] - %x\n", PciConfig.u.type0.BaseAddresses[4]);
DPRINT("PciConfig.u.type0.BaseAddresses[5] - %x\n", PciConfig.u.type0.BaseAddresses[5]);
DPRINT("PciConfig.u.type0.CIS - %x\n", PciConfig.u.type0.CIS);
DPRINT("PciConfig.u.type0.SubVendorID - %x\n", PciConfig.u.type0.SubVendorID);
DPRINT("PciConfig.u.type0.SubSystemID - %x\n", PciConfig.u.type0.SubSystemID);
DPRINT("PciConfig.u.type0.ROMBaseAddress - %x\n", PciConfig.u.type0.ROMBaseAddress);
DPRINT("PciConfig.u.type0.CapabilitiesPtr - %x\n", PciConfig.u.type0.CapabilitiesPtr);
DPRINT("PciConfig.u.type0.Reserved1[0] - %x\n", PciConfig.u.type0.Reserved1[0]);
DPRINT("PciConfig.u.type0.Reserved1[1] - %x\n", PciConfig.u.type0.Reserved1[1]);
DPRINT("PciConfig.u.type0.Reserved1[2] - %x\n", PciConfig.u.type0.Reserved1[2]);
DPRINT("PciConfig.u.type0.Reserved2 - %x\n", PciConfig.u.type0.Reserved2);
DPRINT("PciConfig.u.type0.InterruptLine - %x\n", PciConfig.u.type0.InterruptLine);
DPRINT("PciConfig.u.type0.InterruptPin - %x\n", PciConfig.u.type0.InterruptPin);
DPRINT("PciConfig.u.type0.MinimumGrant - %x\n", PciConfig.u.type0.MinimumGrant);
DPRINT("PciConfig.u.type0.MaximumLatency - %x\n", PciConfig.u.type0.MaximumLatency);
*/
DeviceExtension->VendorId = PciConfig.VendorID;
DeviceExtension->DeviceId = PciConfig.DeviceID;
DeviceExtension->ControllerMode[PRIMARY_CHANNEL] =
DeviceExtension->ControllerMode[SECONDARY_CHANNEL] = FALSE; // compatible BM PCI IDE mode
if ((PciConfig.BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
(PciConfig.SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
{
UCHAR PrimaryMode, SecondaryMode, PrimaryFixed, SecondaryFixed, ProgIf;
ProgIf = PciConfig.ProgIf;
PrimaryMode = (ProgIf & 1) == 1; // Primary channel mode is PCI (native mode)
PrimaryFixed = (ProgIf & 2) == 0; // Primary channel mode can changed == FALSE
SecondaryMode = (ProgIf & 4) == 4; // Secondary channel mode is PCI (native mode)
SecondaryFixed = (ProgIf & 8) == 0;// Secondary channel mode can changed == FALSE
if ((ProgIf & 0x80) && (PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_SPACE))
{
DPRINT("PciIdeXAddDevice: found IDE Bus Master controller!\n");
DeviceExtension->BusMasterBase = PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_ADDRESS_MASK;
DPRINT("PciIdeXAddDevice: IDE Bus Master Registers at IO %lx\n", DeviceExtension->BusMasterBase);
/*
* [..] In order for Windows XP SP1 and Windows Server 2003 to switch an ATA
* ATA controller from compatible mode to native mode, the following must be
* true:
*
* - The controller must indicate in its programming interface that both channels
* can be switched to native mode. Windows XP SP1 and Windows Server 2003 do
* not support switching only one IDE channel to native mode. See the PCI IDE
* Controller Specification Revision 1.0 for details.
*/
if ((PrimaryMode != SecondaryMode) || (PrimaryFixed != SecondaryFixed))
{
/* does not support this configuration, fail */
DPRINT1("PciIdeXAddDevice: unsupported IDE controller configuration for VEN_%04x&DEV_%04x!\n",
DeviceExtension->VendorId, DeviceExtension->DeviceId);
DeviceExtension->BusMasterBase = 0;
}
else
{
if ( !(PciConfig.Command & 4) )
{
PciConfig.Command |= 4; //enable bus master PCI
//write Command register
BytesRead = (*DeviceExtension->BusInterface->SetBusData)(
DeviceExtension->BusInterface->Context,
PCI_WHICHSPACE_CONFIG,
&PciConfig.Command,
FIELD_OFFSET(PCI_COMMON_HEADER, Command),
sizeof(PciConfig.Command));
if (BytesRead != sizeof(PciConfig.Command))
{
DPRINT("PciIdeXAddDevice: BusInterface->SetBusData() failed: BytesRead - %lx\n", BytesRead);
}
}
/* Check if the controller is already in native mode */
if ((PrimaryMode) && (SecondaryMode))
{
/* The controller is now in native mode */
DeviceExtension->ControllerMode[PRIMARY_CHANNEL] =
DeviceExtension->ControllerMode[SECONDARY_CHANNEL] = TRUE; //native BM PCI IDE mode
}
else
{
DPRINT1("PciIdeXAddDevice: FIXME! Enable NATIVE PCI IDE mode!\n");
}
}
}
else
{
DeviceExtension->BusMasterBase = 0;
}
}
Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
static NTSTATUS NTAPI
PciIdeXGetTransferModes(
IN IDENTIFY_DATA IdentifyData,
OUT PULONG BestXferMode,
OUT PULONG CurrentXferMode)
{
ULONG Best = PIO_MODE0;
ULONG Current = PIO_MODE0;
DPRINT("PciIdeXGetTransferModes(%lu, %p %p)\n",
IdentifyData, BestXferMode, CurrentXferMode);
/* FIXME: if current mode is a PIO mode, how to get it?
* At the moment, PIO_MODE0 is always returned...
*/
if (IdentifyData.TranslationFieldsValid & 0x2)
{
/* PIO modes and some DMA modes are supported */
if (IdentifyData.AdvancedPIOModes & 0x02)
Best = PIO_MODE4;
else if (IdentifyData.AdvancedPIOModes & 0x01)
Best = PIO_MODE3;
else if (IdentifyData.PioCycleTimingMode == 0x02)
Best = PIO_MODE2;
else if (IdentifyData.PioCycleTimingMode == 0x01)
Best = PIO_MODE1;
else if (IdentifyData.PioCycleTimingMode == 0x00)
Best = PIO_MODE0;
else
Best = PIO_MODE0;
DPRINT("PciIdeXGetTransferModes: PIO Best - %x)\n", Best);
if (IdentifyData.SingleWordDMASupport & 0x4)
Best = SWDMA_MODE2;
else if (IdentifyData.SingleWordDMASupport & 0x2)
Best = SWDMA_MODE1;
else if (IdentifyData.SingleWordDMASupport & 0x1)
Best = SWDMA_MODE0;
if (IdentifyData.SingleWordDMAActive & 0x4)
Current = SWDMA_MODE2;
else if (IdentifyData.SingleWordDMAActive & 0x2)
Current = SWDMA_MODE1;
else if (IdentifyData.SingleWordDMAActive & 0x1)
Current = SWDMA_MODE0;
DPRINT("PciIdeXGetTransferModes: SingleWordDMA Best - %x)\n", Best);
if (IdentifyData.MultiWordDMASupport & 0x4)
Best = MWDMA_MODE2;
else if (IdentifyData.MultiWordDMASupport & 0x2)
Best = MWDMA_MODE1;
else if (IdentifyData.MultiWordDMASupport & 0x1)
Best = MWDMA_MODE0;
if (IdentifyData.MultiWordDMAActive & 0x4)
Current = MWDMA_MODE2;
else if (IdentifyData.MultiWordDMAActive & 0x2)
Current = MWDMA_MODE1;
else if (IdentifyData.MultiWordDMAActive & 0x1)
Current = MWDMA_MODE0;
DPRINT("PciIdeXGetTransferModes: MultiWordDMA Best - %x)\n", Best);
}
if (IdentifyData.TranslationFieldsValid & 0x4)
{
/* UDMA modes are supported */
if (IdentifyData.UltraDMAActive & 0x10)
Current = UDMA_MODE4;
else if (IdentifyData.UltraDMAActive & 0x8)
Current = UDMA_MODE3;
else if (IdentifyData.UltraDMAActive & 0x4)
Current = UDMA_MODE2;
else if (IdentifyData.UltraDMAActive & 0x2)
Current = UDMA_MODE1;
else if (IdentifyData.UltraDMAActive & 0x1)
Current = UDMA_MODE0;
if (IdentifyData.UltraDMASupport & 0x10)
Best = UDMA_MODE4;
else if (IdentifyData.UltraDMASupport & 0x8)
Best = UDMA_MODE3;
else if (IdentifyData.UltraDMASupport & 0x4)
Best = UDMA_MODE2;
else if (IdentifyData.UltraDMASupport & 0x2)
Best = UDMA_MODE1;
else if (IdentifyData.UltraDMASupport & 0x1)
Best = UDMA_MODE0;
}
DPRINT("PciIdeXGetTransferModes: Best - %x)\n", Best);
DPRINT("PciIdeXGetTransferModes: Current - %x)\n", Best);
*BestXferMode = Best;
*CurrentXferMode = Current;
return TRUE;
}
static NTSTATUS
PciIdeXFdoStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PPCIIDEX_DRIVER_EXTENSION DriverExtension;
PFDO_DEVICE_EXTENSION DeviceExtension;
PCM_RESOURCE_LIST ResourceList;
NTSTATUS Status;
DPRINT("PciIdeXStartDevice(%p %p)\n", DeviceObject, Irp);
DriverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject, DeviceObject->DriverObject);
ASSERT(DriverExtension);
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension);
ASSERT(DeviceExtension->Common.IsFDO);
DeviceExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
DeviceExtension->Properties.ExtensionSize = DriverExtension->MiniControllerExtensionSize;
Status = DriverExtension->HwGetControllerProperties(
DeviceExtension->MiniControllerExtension,
&DeviceExtension->Properties);
if (!NT_SUCCESS(Status))
return Status;
DriverExtension->HwUdmaModesSupported = DeviceExtension->Properties.PciIdeUdmaModesSupported;
if (!DriverExtension->HwUdmaModesSupported)
/* This method is optional, so provide our own one */
DriverExtension->HwUdmaModesSupported = PciIdeXGetTransferModes;
/* Get bus master port base, if any */
ResourceList = IoGetCurrentIrpStackLocation(Irp)->Parameters.StartDevice.AllocatedResources;
if (ResourceList
&& ResourceList->Count == 1
&& ResourceList->List[0].PartialResourceList.Count == 1
&& ResourceList->List[0].PartialResourceList.Version == 1
&& ResourceList->List[0].PartialResourceList.Revision == 1
&& ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Type == CmResourceTypePort
&& ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Length == 16)
{
DeviceExtension->BusMasterPortBase = ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start;
}
return STATUS_SUCCESS;
}
static NTSTATUS
PciIdeXFdoQueryBusRelations(
IN PDEVICE_OBJECT DeviceObject,
OUT PDEVICE_RELATIONS* pDeviceRelations)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_RELATIONS DeviceRelations = NULL;
PDEVICE_OBJECT Pdo;
PPDO_DEVICE_EXTENSION PdoDeviceExtension;
ULONG i, j;
ULONG PDOs = 0;
IDE_CHANNEL_STATE ChannelState;
NTSTATUS Status;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension);
ASSERT(DeviceExtension->Common.IsFDO);
for (i = 0; i < MAX_IDE_CHANNEL; i++)
{
if (DeviceExtension->Pdo[i])
{
PDOs++;
continue;
}
ChannelState = DeviceExtension->Properties.PciIdeChannelEnabled(
DeviceExtension->MiniControllerExtension, i);
if (ChannelState == ChannelDisabled)
{
DPRINT("Channel %lu is disabled\n", i);
continue;
}
/* Need to create a PDO */
Status = IoCreateDevice(
DeviceObject->DriverObject,
sizeof(PDO_DEVICE_EXTENSION),
NULL,
FILE_DEVICE_CONTROLLER,
FILE_AUTOGENERATED_DEVICE_NAME,
FALSE,
&Pdo);
if (!NT_SUCCESS(Status))
/* FIXME: handle error */
continue;
PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension;
RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
PdoDeviceExtension->Common.IsFDO = FALSE;
PdoDeviceExtension->Channel = i;
PdoDeviceExtension->ControllerFdo = DeviceObject;
PdoDeviceExtension->SelfDevice = Pdo;
Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
DeviceExtension->Pdo[i] = Pdo;
PDOs++;
}
if (PDOs == 0)
{
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
PagedPool,
sizeof(DEVICE_RELATIONS));
}
else
{
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
PagedPool,
sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (PDOs - 1));
}
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
DeviceRelations->Count = PDOs;
for (i = 0, j = 0; i < MAX_IDE_CHANNEL; i++)
{
if (DeviceExtension->Pdo[i])
{
ObReferenceObject(DeviceExtension->Pdo[i]);
DeviceRelations->Objects[j++] = DeviceExtension->Pdo[i];
}
}
*pDeviceRelations = DeviceRelations;
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
PciIdeXFdoPnpDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG MinorFunction;
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = Irp->IoStatus.Information;
NTSTATUS Status;
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
switch (MinorFunction)
{
case IRP_MN_START_DEVICE: /* 0x00 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
/* Call lower driver */
Status = ForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status))
Status = PciIdeXFdoStartDevice(DeviceObject, Irp);
break;
}
case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
Status = STATUS_UNSUCCESSFUL;
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
{
switch (Stack->Parameters.QueryDeviceRelations.Type)
{
case BusRelations:
{
PDEVICE_RELATIONS DeviceRelations = NULL;
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
Status = PciIdeXFdoQueryBusRelations(DeviceObject, &DeviceRelations);
Information = (ULONG_PTR)DeviceRelations;
break;
}
default:
{
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
Stack->Parameters.QueryDeviceRelations.Type);
Status = STATUS_NOT_IMPLEMENTED;
break;
}
}
break;
}
case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
Information |= PNP_DEVICE_NOT_DISABLEABLE;
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */
{
DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
return ForwardIrpAndForget(DeviceObject, Irp);
}
default:
{
DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction);
return ForwardIrpAndForget(DeviceObject, Irp);
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
Code: Select all
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: PCI IDE bus driver extension
* FILE: drivers/storage/pciidex/pdo.c
* PURPOSE: IRP_MJ_PNP operations for PDOs
* PROGRAMMERS: Hervй Poussineau (hpoussin@reactos.org)
*/
#include "pciidex.h"
#include <stdio.h>
#include <wdmguid.h>
//#define NDEBUG
#include <debug.h>
static NTSTATUS
PciIdeXPdoQueryId(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
OUT ULONG_PTR* Information)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
WCHAR Buffer[256];
ULONG Index = 0;
ULONG IdType;
UNICODE_STRING SourceString;
UNICODE_STRING String;
NTSTATUS Status;
IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension;
switch (IdType)
{
case BusQueryDeviceID:
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
RtlInitUnicodeString(&SourceString, L"PCIIDE\\IDEChannel");
break;
}
case BusQueryHardwareIDs:
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
switch (FdoDeviceExtension->VendorId)
{
case 0x0e11:
Index += swprintf(&Buffer[Index], L"Compaq-%04x", FdoDeviceExtension->DeviceId) + 1;
break;
case 0x1039:
Index += swprintf(&Buffer[Index], L"SiS-%04x", FdoDeviceExtension->DeviceId) + 1;
break;
case 0x1050:
Index += swprintf(&Buffer[Index], L"WinBond-%04x", FdoDeviceExtension->DeviceId) + 1;
break;
case 0x1095:
Index += swprintf(&Buffer[Index], L"CMD-%04x", FdoDeviceExtension->DeviceId) + 1;
break;
case 0x8086:
{
switch (FdoDeviceExtension->DeviceId)
{
case 0x1230:
Index += swprintf(&Buffer[Index], L"Intel-PIIX") + 1;
break;
case 0x7010:
Index += swprintf(&Buffer[Index], L"Intel-PIIX3") + 1;
break;
case 0x7111:
Index += swprintf(&Buffer[Index], L"Intel-PIIX4") + 1;
break;
default:
Index += swprintf(&Buffer[Index], L"Intel-%04x", FdoDeviceExtension->DeviceId) + 1;
break;
}
break;
}
default:
break;
}
if (DeviceExtension->Channel == 0)
Index += swprintf(&Buffer[Index], L"Primary_IDE_Channel") + 1;
else
Index += swprintf(&Buffer[Index], L"Secondary_IDE_Channel") + 1;
Index += swprintf(&Buffer[Index], L"*PNP0600") + 1;
Buffer[Index] = UNICODE_NULL;
SourceString.Length = SourceString.MaximumLength = Index * sizeof(WCHAR);
SourceString.Buffer = Buffer;
break;
}
case BusQueryCompatibleIDs:
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
Index += swprintf(&Buffer[Index], L"*PNP0600") + 1;
Buffer[Index] = UNICODE_NULL;
SourceString.Length = SourceString.MaximumLength = Index * sizeof(WCHAR);
SourceString.Buffer = Buffer;
break;
}
case BusQueryInstanceID:
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
swprintf(Buffer, L"%lu", DeviceExtension->Channel);
RtlInitUnicodeString(&SourceString, Buffer);
break;
}
default:
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
ASSERT(FALSE);
return STATUS_NOT_SUPPORTED;
}
Status = DuplicateUnicodeString(
RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
&SourceString,
&String);
*Information = (ULONG_PTR)String.Buffer;
return Status;
}
static NTSTATUS
GetCurrentResources(
IN PDEVICE_OBJECT DeviceObject,
OUT PULONG CommandPortBase,
OUT PULONG ControlPortBase,
OUT PULONG BusMasterPortBase,
OUT PULONG InterruptVector)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
PFDO_DEVICE_EXTENSION FdoDeviceExtension;
ULONG BaseIndex;
ULONG BytesRead;
PCI_COMMON_CONFIG PciConfig;
NTSTATUS ret = STATUS_UNSUCCESSFUL;
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension;
BaseIndex = DeviceExtension->Channel * 2;
BytesRead = (*FdoDeviceExtension->BusInterface->GetBusData)(
FdoDeviceExtension->BusInterface->Context,
PCI_WHICHSPACE_CONFIG,
&PciConfig,
0,
PCI_COMMON_HDR_LENGTH);
if (BytesRead != PCI_COMMON_HDR_LENGTH)
return STATUS_IO_DEVICE_ERROR;
/* We have found a known native pci ide controller */
if ((PciConfig.ProgIf & 0x80) && (PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_SPACE))
{
DPRINT("Found IDE Bus Master controller!\n");
*BusMasterPortBase = PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_ADDRESS_MASK;
DPRINT(" IDE Bus Master Registers at IO %lx\n", *BusMasterPortBase);
}
else
{
*BusMasterPortBase = 0;
}
if ((PciConfig.ProgIf >> BaseIndex) & 0x1)
{
/* Native mode */
if ((PciConfig.u.type0.BaseAddresses[BaseIndex + 0] & PCI_ADDRESS_IO_SPACE) &&
(PciConfig.u.type0.BaseAddresses[BaseIndex + 1] & PCI_ADDRESS_IO_SPACE))
{
/* Channel is enabled */
*CommandPortBase = PciConfig.u.type0.BaseAddresses[BaseIndex + 0] & PCI_ADDRESS_IO_ADDRESS_MASK;
*ControlPortBase = PciConfig.u.type0.BaseAddresses[BaseIndex + 1] & PCI_ADDRESS_IO_ADDRESS_MASK;
*InterruptVector = PciConfig.u.type0.InterruptLine;
ret = STATUS_SUCCESS;
}
}
else
{
/* Compatibility mode */
switch (DeviceExtension->Channel)
{
case 0:
if (IoGetConfigurationInformation()->AtDiskPrimaryAddressClaimed)
ret = STATUS_INSUFFICIENT_RESOURCES;
else
{
*CommandPortBase = 0x1F0;
*ControlPortBase = 0x3F6;
*InterruptVector = 14;
ret = STATUS_SUCCESS;
}
break;
case 1:
if (IoGetConfigurationInformation()->AtDiskSecondaryAddressClaimed)
ret = STATUS_INSUFFICIENT_RESOURCES;
else
{
*CommandPortBase = 0x170;
*ControlPortBase = 0x376;
*InterruptVector = 15;
ret = STATUS_SUCCESS;
}
break;
}
}
return ret;
}
static NTSTATUS
PciIdeXPdoQueryResourceRequirements(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
OUT ULONG_PTR* Information)
{
ULONG CommandPortBase;
ULONG ControlPortBase;
ULONG BusMasterPortBase;
ULONG InterruptVector;
ULONG ListSize;
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
PIO_RESOURCE_DESCRIPTOR Descriptor;
NTSTATUS Status;
Status = GetCurrentResources(DeviceObject, &CommandPortBase,
&ControlPortBase, &BusMasterPortBase, &InterruptVector);
if (!NT_SUCCESS(Status))
return Status;
DPRINT("IDE Channel %lu: IO %x and %x, BM %lx, Irq %lu\n",
((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Channel,
CommandPortBase, ControlPortBase,
BusMasterPortBase, InterruptVector);
/* FIXME: what to do with BusMasterPortBase? */
ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
+ 2 * sizeof(IO_RESOURCE_DESCRIPTOR);
RequirementsList = ExAllocatePool(PagedPool, ListSize);
if (!RequirementsList)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(RequirementsList, ListSize);
RequirementsList->ListSize = ListSize;
RequirementsList->AlternativeLists = 1;
RequirementsList->List[0].Version = 1;
RequirementsList->List[0].Revision = 1;
RequirementsList->List[0].Count = 3;
Descriptor = &RequirementsList->List[0].Descriptors[0];
/* Command port base */
Descriptor->Option = 0; /* Required */
Descriptor->Type = CmResourceTypePort;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
Descriptor->Flags = CM_RESOURCE_PORT_IO |
CM_RESOURCE_PORT_16_BIT_DECODE |
CM_RESOURCE_PORT_POSITIVE_DECODE;
Descriptor->u.Port.Length = 8;
Descriptor->u.Port.Alignment = 1;
Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)CommandPortBase;
Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(CommandPortBase + 8 - 1);
Descriptor++;
/* Control port base */
Descriptor->Option = 0; /* Required */
Descriptor->Type = CmResourceTypePort;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
Descriptor->Flags = CM_RESOURCE_PORT_IO |
CM_RESOURCE_PORT_16_BIT_DECODE |
CM_RESOURCE_PORT_POSITIVE_DECODE;
Descriptor->u.Port.Length = 1;
Descriptor->u.Port.Alignment = 1;
Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)ControlPortBase;
Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(ControlPortBase + 1 - 1);
Descriptor++;
/* Interrupt */
Descriptor->Option = 0; /* Required */
Descriptor->Type = CmResourceTypeInterrupt;
Descriptor->ShareDisposition = CmResourceShareShared;
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_LATCHED_BITS; //CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; (?? CM_RESOURCE_INTERRUPT_LATCHED == CM_RESOURCE_INTERRUPT_LEVEL_LATCHED_BITS);
Descriptor->u.Interrupt.MinimumVector = InterruptVector;
Descriptor->u.Interrupt.MaximumVector = InterruptVector;
*Information = (ULONG_PTR)RequirementsList;
return STATUS_SUCCESS;
}
static NTSTATUS
PciIdeXPdoQueryDeviceText(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
OUT ULONG_PTR* Information)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
ULONG DeviceTextType;
PCWSTR SourceString;
UNICODE_STRING String;
DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType;
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
switch (DeviceTextType)
{
case DeviceTextDescription:
case DeviceTextLocationInformation:
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / %S\n",
DeviceTextType == DeviceTextDescription ? L"DeviceTextDescription" : L"DeviceTextLocationInformation");
if (DeviceExtension->Channel == 0)
SourceString = L"Primary channel";
else
SourceString = L"Secondary channel";
break;
}
default:
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n", DeviceTextType);
ASSERT(FALSE);
return STATUS_NOT_SUPPORTED;
}
if (RtlCreateUnicodeString(&String, SourceString))
{
*Information = (ULONG_PTR)String.Buffer;
return STATUS_SUCCESS;
}
else
return STATUS_INSUFFICIENT_RESOURCES;
}
static NTSTATUS
PciIdeXPdoQueryDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
OUT PDEVICE_RELATIONS* pDeviceRelations)
{
PFDO_DEVICE_EXTENSION DeviceExtension;
PDEVICE_RELATIONS DeviceRelations;
DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
ASSERT(DeviceExtension->Common.IsFDO);
DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
PagedPool,
sizeof(DEVICE_RELATIONS));
if (!DeviceRelations)
return STATUS_INSUFFICIENT_RESOURCES;
ObReferenceObject(DeviceObject);
DeviceRelations->Count = 1;
DeviceRelations->Objects[0] = DeviceObject;
*pDeviceRelations = DeviceRelations;
return STATUS_SUCCESS;
}
static NTSTATUS
PciIdeXStartChannel(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
PFDO_DEVICE_EXTENSION FdoDeviceExtension; //ControllerFdoExtension
PDMA_ADAPTER DmaAdapter;
PDMA_OPERATIONS DmaOperations;
DEVICE_DESCRIPTION DeviceDescription;
PVOID CommonBuffer;
ULONG Length;
DPRINT("PciIdeXStartChannel: DeviceObject - %p, Irp - %p\n", DeviceObject, Irp);
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension;
RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
DeviceDescription.Master = TRUE;
DeviceDescription.ScatterGather = TRUE;
DeviceDescription.DemandMode = FALSE;
DeviceDescription.AutoInitialize = FALSE;
DeviceDescription.Dma32BitAddresses = TRUE;
DeviceDescription.IgnoreCount = FALSE;
DeviceDescription.InterfaceType = PCIBus; //?InterfaceTypeUndefined
DeviceDescription.MaximumLength = 0x20000;
DmaAdapter = IoGetDmaAdapter(FdoDeviceExtension->LowerDevice,
&DeviceDescription,
&DeviceExtension->NumberOfMapRegisters);
if ( DmaAdapter == NULL )
{
DPRINT1("PciIdeXStartChannel: IoGetDmaAdapter() failed\n");
}
else
{
DeviceExtension->DmaAdapter = DmaAdapter;
DPRINT("PciIdeXStartChannel: DmaAdapter - %p, *DmaAdapter - %p\n", DmaAdapter, *(PULONG)DmaAdapter);
DmaOperations = DmaAdapter->DmaOperations;
DPRINT("PciIdeXStartChannel: DmaOperations - %x\n", DmaOperations);
Length = DeviceExtension->NumberOfMapRegisters * sizeof(PHYSICAL_ADDRESS);
DPRINT("PciIdeXStartChannel: Length - %x\n", Length);
CommonBuffer = DmaOperations->AllocateCommonBuffer(
DmaAdapter,
Length,
(PPHYSICAL_ADDRESS)&DeviceExtension->LogicalAddress,
FALSE); //CacheEnabled
DPRINT("PciIdeXStartChannel: CommonBuffer - %x\n", CommonBuffer);
DPRINT("PciIdeXStartChannel: DeviceExtension->LogicalAddress.LowPart - %x\n", DeviceExtension->LogicalAddress.LowPart);
DPRINT("PciIdeXStartChannel: DeviceExtension->LogicalAddress.HighPart - %x\n", DeviceExtension->LogicalAddress.HighPart);
DeviceExtension->CommonBuffer = CommonBuffer;
if ( !DeviceExtension->CommonBuffer )
DPRINT(" PciIdeXStartChannel: No RDT!\n");
if ( !DeviceExtension->LogicalAddress.QuadPart )
DPRINT(" PciIdeXStartChannel: No PRDT!\n");
if ( DeviceExtension->CommonBuffer )
{
RtlZeroMemory(DeviceExtension->CommonBuffer, Length);
}
}
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
PciIdeXPdoPnpDispatch(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
ULONG MinorFunction;
PIO_STACK_LOCATION Stack;
ULONG_PTR Information = Irp->IoStatus.Information;
NTSTATUS Status;
PPDO_DEVICE_EXTENSION DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
PFDO_DEVICE_EXTENSION FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(Irp);
MinorFunction = Stack->MinorFunction;
switch (MinorFunction)
{
/* FIXME:
* Those are required:
* IRP_MN_START_DEVICE (done)
* IRP_MN_QUERY_STOP_DEVICE
* IRP_MN_STOP_DEVICE
* IRP_MN_CANCEL_STOP_DEVICE
* IRP_MN_QUERY_REMOVE_DEVICE
* IRP_MN_REMOVE_DEVICE
* IRP_MN_CANCEL_REMOVE_DEVICE
* IRP_MN_SURPRISE_REMOVAL
* IRP_MN_QUERY_CAPABILITIES (done)
* IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelations (done)
* IRP_MN_QUERY_ID / BusQueryDeviceID (done)
* Those may be required/optional:
* IRP_MN_DEVICE_USAGE_NOTIFICATION
* IRP_MN_QUERY_RESOURCES
* IRP_MN_QUERY_RESOURCE_REQUIREMENTS (done)
* IRP_MN_QUERY_DEVICE_TEXT
* IRP_MN_QUERY_BUS_INFORMATION
* IRP_MN_QUERY_INTERFACE
* IRP_MN_READ_CONFIG
* IRP_MN_WRITE_CONFIG
* IRP_MN_EJECT
* IRP_MN_SET_LOCK
* Those are optional:
* IRP_MN_QUERY_DEVICE_RELATIONS / EjectionRelations
* IRP_MN_QUERY_ID / BusQueryHardwareIDs (done)
* IRP_MN_QUERY_ID / BusQueryCompatibleIDs (done)
* IRP_MN_QUERY_ID / BusQueryInstanceID (done)
*/
case IRP_MN_START_DEVICE: /* 0x00 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
Status = PciIdeXStartChannel(DeviceObject, Irp);
break;
}
case IRP_MN_QUERY_REMOVE_DEVICE: /* 0x01 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_REMOVE_DEVICE\n");
Status = STATUS_UNSUCCESSFUL;
break;
}
case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
{
switch (Stack->Parameters.QueryDeviceRelations.Type)
{
case TargetDeviceRelation:
{
PDEVICE_RELATIONS DeviceRelations = NULL;
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
Status = PciIdeXPdoQueryDeviceRelations(DeviceObject, &DeviceRelations);
Information = (ULONG_PTR)DeviceRelations;
break;
}
default:
{
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
Stack->Parameters.QueryDeviceRelations.Type);
ASSERT(FALSE);
Status = STATUS_NOT_SUPPORTED;
break;
}
}
break;
}
case IRP_MN_QUERY_INTERFACE: /* 0x08 */
{
// It get pseudo Interface. QueryInterface.Size - type Interface. QueryInterface.Interface - pointer on Interface.
// and replace GUID_BUS_INTERFACE_STANDARD on ... ?
if (IsEqualGUIDAligned(Stack->Parameters.QueryInterface.InterfaceType, &GUID_BUS_INTERFACE_STANDARD))
{
switch (Stack->Parameters.QueryInterface.Size)
{
case 1: //QueryControllerProperties
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_INTERFACE / QueryControllerProperties\n");
*(PVOID *)Stack->Parameters.QueryInterface.Interface = &FdoDeviceExtension->Properties;
*(PVOID *)((PULONG)Stack->Parameters.QueryInterface.Interface + 1) = FdoDeviceExtension->MiniControllerExtension;
DPRINT("PciIdeXPdoPnpDispatch: DeviceObject - %p\n", DeviceObject);
Status = STATUS_SUCCESS;
break;
case 3: //QueryPciBusInterface
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_INTERFACE / QueryPciBusInterface\n");
*(PVOID *)Stack->Parameters.QueryInterface.Interface = FdoDeviceExtension->BusInterface;
DPRINT("PciIdeXPdoPnpDispatch: BusInterface - %p\n", FdoDeviceExtension->BusInterface);
Status = STATUS_SUCCESS;
break;
case 5: //QueryBusMasterInterface
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_INTERFACE / QueryBusMasterInterface\n");
if (FdoDeviceExtension->BusMasterBase)
Status = QueryBusMasterInterface(DeviceExtension, Stack);
else
Status = STATUS_NOT_IMPLEMENTED;
break;
case 7: //QueryAhciInterface
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_INTERFACE / QueryAhciInterface. NOT_SUPPORTED\n");
Status = STATUS_NOT_SUPPORTED;
break;
default:
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_INTERFACE / Unknown Size\n");
Status = STATUS_NOT_SUPPORTED;
break;
}
break;
}
else
{
DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_INTERFACE / Unknown type\n");
ASSERT(FALSE);
Status = STATUS_NOT_SUPPORTED;
break;
}
}
case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */
{
PDEVICE_CAPABILITIES DeviceCapabilities;
ULONG i;
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
/* FIXME: capabilities can change with connected device */
DeviceCapabilities->LockSupported = FALSE;
DeviceCapabilities->EjectSupported = FALSE;
DeviceCapabilities->Removable = TRUE;
DeviceCapabilities->DockDevice = FALSE;
DeviceCapabilities->UniqueID = FALSE;
DeviceCapabilities->SilentInstall = FALSE;
DeviceCapabilities->RawDeviceOK = FALSE;
DeviceCapabilities->SurpriseRemovalOK = TRUE;
DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME */
//DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* FIXME */
for (i = 0; i < PowerSystemMaximum; i++)
DeviceCapabilities->DeviceState[i] = PowerDeviceD3; /* FIXME */
//DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */
DeviceCapabilities->D1Latency = 0; /* FIXME */
DeviceCapabilities->D2Latency = 0; /* FIXME */
DeviceCapabilities->D3Latency = 0; /* FIXME */
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_RESOURCES: /* 0x0a */
{
/* This IRP is optional; do nothing */
Information = Irp->IoStatus.Information;
Status = Irp->IoStatus.Status;
break;
}
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
Status = PciIdeXPdoQueryResourceRequirements(DeviceObject, Irp, &Information);
break;
}
case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */
{
Status = PciIdeXPdoQueryDeviceText(DeviceObject, Irp, &Information);
break;
}
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: /* 0x0d */
{
DPRINT("IRP_MJ_PNP / IRP_MN_FILTER_RESOURCE_REQUIREMENTS\n");
Information = Irp->IoStatus.Information;
Status = Irp->IoStatus.Status;
break;
}
case IRP_MN_QUERY_ID: /* 0x13 */
{
Status = PciIdeXPdoQueryId(DeviceObject, Irp, &Information);
break;
}
case IRP_MN_QUERY_PNP_DEVICE_STATE: /* 0x14 */
{
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_PNP_DEVICE_STATE\n");
Information |= PNP_DEVICE_NOT_DISABLEABLE;
Status = STATUS_SUCCESS;
break;
}
case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */
{
PPNP_BUS_INFORMATION BusInfo;
DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
if (!BusInfo)
Status = STATUS_INSUFFICIENT_RESOURCES;
else
{
/*RtlCopyMemory(
&BusInfo->BusTypeGuid,
&GUID_DEVINTERFACE_XXX,
sizeof(GUID));*/
BusInfo->LegacyBusType = PNPBus;
BusInfo->BusNumber = 0; /* FIXME */
Information = (ULONG_PTR)BusInfo;
Status = STATUS_SUCCESS;
}
break;
}
default:
{
/* We can't forward request to the lower driver, because
* we are a Pdo, so we don't have lower driver... */
DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction);
ASSERT(FALSE);
Information = Irp->IoStatus.Information;
Status = Irp->IoStatus.Status;
}
}
Irp->IoStatus.Information = Information;
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}