-/* $Id: pci.c,v 1.7 2004/06/09 14:22:53 ekohl Exp $
+/* $Id: pci.c,v 1.8 2004/08/16 09:13:00 ekohl Exp $
*
* PROJECT: ReactOS PCI Bus driver
* FILE: pci.c
BOOLEAN
-PciCreateInstanceIDString(PUNICODE_STRING DeviceID,
+PciCreateInstanceIDString(PUNICODE_STRING InstanceID,
PPCI_DEVICE Device)
{
- /* FIXME */
-
#if 0
- swprintf(Buffer,
- L"%02lx&%04lx",
- Device->BusNumber,
- Device->SlotNumber.SlotNumber.u.AsULONG);
-#endif
+ WCHAR Buffer[32];
+ ULONG Length;
+ ULONG Index;
+
+ Index = swprintf(Buffer,
+ L"%lX&%02lX",
+ Device->BusNumber,
+ (Device->SlotNumber.u.bits.DeviceNumber << 3) +
+ Device->SlotNumber.u.bits.FunctionNumber);
+ Index++;
+ Buffer[Index] = UNICODE_NULL;
- return PciCreateUnicodeString(DeviceID, L"0000", PagedPool);
+ Length = (Index + 1) * sizeof(WCHAR);
+ InstanceID->Buffer = ExAllocatePool(PagedPool, Length);
+ if (InstanceID->Buffer == NULL)
+ {
+ return FALSE;
+ }
+
+ InstanceID->Length = Length - sizeof(WCHAR);
+ InstanceID->MaximumLength = Length;
+ RtlCopyMemory(InstanceID->Buffer, Buffer, Length);
+
+ return TRUE;
+#endif
+ return PciCreateUnicodeString(InstanceID, L"0000", PagedPool);
}
Length = (Index + 1) * sizeof(WCHAR);
HardwareIDs->Buffer = ExAllocatePool(PagedPool, Length);
- if (Buffer == NULL)
+ if (HardwareIDs->Buffer == NULL)
{
return FALSE;
}
BOOLEAN
-PciCreateCompatibleIDsString(PUNICODE_STRING HardwareIDs,
+PciCreateCompatibleIDsString(PUNICODE_STRING CompatibleIDs,
PPCI_DEVICE Device)
{
WCHAR Buffer[256];
Buffer[Index] = UNICODE_NULL;
Length = (Index + 1) * sizeof(WCHAR);
- HardwareIDs->Buffer = ExAllocatePool(PagedPool, Length);
- if (Buffer == NULL)
+ CompatibleIDs->Buffer = ExAllocatePool(PagedPool, Length);
+ if (CompatibleIDs->Buffer == NULL)
{
return FALSE;
}
- HardwareIDs->Length = Length - sizeof(WCHAR);
- HardwareIDs->MaximumLength = Length;
- RtlCopyMemory(HardwareIDs->Buffer, Buffer, Length);
+ CompatibleIDs->Length = Length - sizeof(WCHAR);
+ CompatibleIDs->MaximumLength = Length;
+ RtlCopyMemory(CompatibleIDs->Buffer, Buffer, Length);
+
+ return TRUE;
+}
+
+
+BOOLEAN
+PciCreateDeviceDescriptionString(PUNICODE_STRING DeviceDescription,
+ PPCI_DEVICE Device)
+{
+ PWSTR Description;
+ ULONG Length;
+
+ switch (Device->PciConfig.BaseClass)
+ {
+ case PCI_CLASS_MASS_STORAGE_CTLR:
+ switch (Device->PciConfig.BaseClass)
+ {
+ case PCI_SUBCLASS_MSC_SCSI_BUS_CTLR:
+ Description = L"SCSI controller";
+ break;
+
+ case PCI_SUBCLASS_MSC_IDE_CTLR:
+ Description = L"IDE controller";
+ break;
+
+ case PCI_SUBCLASS_MSC_FLOPPY_CTLR:
+ Description = L"Floppy disk controller";
+ break;
+
+ case PCI_SUBCLASS_MSC_IPI_CTLR:
+ Description = L"IPI controller";
+ break;
+
+ case PCI_SUBCLASS_MSC_RAID_CTLR:
+ Description = L"RAID controller";
+ break;
+
+ default:
+ Description = L"Mass storage controller";
+ }
+ break;
+
+ case PCI_CLASS_NETWORK_CTLR:
+ switch (Device->PciConfig.BaseClass)
+ {
+
+ default:
+ Description = L"Network controller";
+ }
+ break;
+
+ default:
+ Description = L"PCI-Device";
+ }
+
+ Length = (wcslen(Description) + 1) * sizeof(WCHAR);
+ DeviceDescription->Buffer = ExAllocatePool(PagedPool, Length);
+ if (DeviceDescription->Buffer == NULL)
+ {
+ return FALSE;
+ }
+
+ DeviceDescription->Length = Length - sizeof(WCHAR);
+ DeviceDescription->MaximumLength = Length;
+ RtlCopyMemory(DeviceDescription->Buffer, Description, Length);
+
+ return TRUE;
+}
+
+
+BOOLEAN
+PciCreateDeviceLocationString(PUNICODE_STRING DeviceLocation,
+ PPCI_DEVICE Device)
+{
+ WCHAR Buffer[256];
+ ULONG Length;
+ ULONG Index;
+
+ Index = 0;
+ Index += swprintf(&Buffer[Index],
+ L"PCI-Bus %lu, Device %u, Function %u",
+ Device->BusNumber,
+ Device->SlotNumber.u.bits.DeviceNumber,
+ Device->SlotNumber.u.bits.FunctionNumber);
+ Index++;
+
+ Buffer[Index] = UNICODE_NULL;
+
+ Length = (Index + 1) * sizeof(WCHAR);
+ DeviceLocation->Buffer = ExAllocatePool(PagedPool, Length);
+ if (DeviceLocation->Buffer == NULL)
+ {
+ return FALSE;
+ }
+
+ DeviceLocation->Length = Length - sizeof(WCHAR);
+ DeviceLocation->MaximumLength = Length;
+ RtlCopyMemory(DeviceLocation->Buffer, Buffer, Length);
return TRUE;
}
-/* $Id: pdo.c,v 1.5 2004/06/09 14:22:53 ekohl Exp $
+/* $Id: pdo.c,v 1.6 2004/08/16 09:13:00 ekohl Exp $
*
* PROJECT: ReactOS PCI bus driver
* FILE: pdo.c
/*** PRIVATE *****************************************************************/
-NTSTATUS
+static NTSTATUS
+PdoQueryDeviceText(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ PIO_STACK_LOCATION IrpSp)
+{
+ PPDO_DEVICE_EXTENSION DeviceExtension;
+ NTSTATUS Status;
+
+ DPRINT("Called\n");
+
+ DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ Status = STATUS_SUCCESS;
+
+ switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType)
+ {
+ case DeviceTextDescription:
+ DPRINT("DeviceTextDescription\n");
+ Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceLocation.Buffer;
+ break;
+
+ case DeviceTextLocationInformation:
+ DPRINT("DeviceTextLocationInformation\n");
+ Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceLocation.Buffer;
+ break;
+
+ default:
+ Irp->IoStatus.Information = 0;
+ Status = STATUS_INVALID_PARAMETER;
+ }
+
+ return Status;
+}
+
+
+static NTSTATUS
PdoQueryId(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
}
-NTSTATUS
+static NTSTATUS
PdoQueryBusInformation(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
}
-NTSTATUS
+static NTSTATUS
PdoQueryCapabilities(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
+ DeviceCapabilities->UniqueID = TRUE;
+
DeviceCapabilities->Address =
DeviceCapabilities->UINumber = DeviceExtension->SlotNumber.u.AsULONG;
}
-NTSTATUS
+static BOOLEAN
+PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
+ ULONG Offset,
+ PULONG Base,
+ PULONG Length,
+ PULONG Flags)
+{
+ ULONG OrigValue;
+ ULONG BaseValue;
+ ULONG NewValue;
+ ULONG Size;
+ ULONG XLength;
+
+ /* Save original value */
+ Size= HalGetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->BusNumber,
+ DeviceExtension->SlotNumber.u.AsULONG,
+ &OrigValue,
+ Offset,
+ sizeof(ULONG));
+ if (Size != sizeof(ULONG))
+ {
+ DPRINT1("Wrong size %lu\n", Size);
+ return FALSE;
+ }
+
+ BaseValue = (OrigValue & 0x00000001) ? (OrigValue & ~0x3) : (OrigValue & ~0xF);
+
+ *Base = BaseValue;
+
+ /* Set magic value */
+ NewValue = (ULONG)-1;
+ Size= HalSetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->BusNumber,
+ DeviceExtension->SlotNumber.u.AsULONG,
+ &NewValue,
+ Offset,
+ sizeof(ULONG));
+ if (Size != sizeof(ULONG))
+ {
+ DPRINT1("Wrong size %lu\n", Size);
+ return FALSE;
+ }
+
+ /* Get the range length */
+ Size= HalGetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->BusNumber,
+ DeviceExtension->SlotNumber.u.AsULONG,
+ &NewValue,
+ Offset,
+ sizeof(ULONG));
+ if (Size != sizeof(ULONG))
+ {
+ DPRINT1("Wrong size %lu\n", Size);
+ return FALSE;
+ }
+
+ /* Restore original value */
+ Size= HalSetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->BusNumber,
+ DeviceExtension->SlotNumber.u.AsULONG,
+ &OrigValue,
+ Offset,
+ sizeof(ULONG));
+ if (Size != sizeof(ULONG))
+ {
+ DPRINT1("Wrong size %lu\n", Size);
+ return FALSE;
+ }
+
+ if (NewValue == 0)
+ {
+ DPRINT("Unused address register\n");
+ *Base = 0;
+ *Length = 0;
+ *Flags = 0;
+ return TRUE;
+ }
+
+ XLength = ~((NewValue & 0x00000001) ? (NewValue & ~0x3) : (NewValue & ~0xF)) + 1;
+
+#if 0
+ DbgPrint("BaseAddress 0x%08lx Length 0x%08lx",
+ BaseValue, XLength);
+#endif
+
+ if (NewValue & 0x00000001)
+ {
+#if 0
+ DbgPrint(" IO range");
+#endif
+ }
+ else
+ {
+#if 0
+ DbgPrint(" Memory range");
+#endif
+ if ((NewValue & 0x00000006) == 0)
+ {
+#if 0
+ DbgPrint(" in 32-Bit address space");
+#endif
+ }
+ else if ((NewValue & 0x00000006) == 2)
+ {
+#if 0
+ DbgPrint("below 1BM ");
+#endif
+ }
+ else if ((NewValue & 0x00000006) == 4)
+ {
+#if 0
+ DbgPrint(" in 64-Bit address space");
+#endif
+ }
+
+ if (NewValue & 0x00000008)
+ {
+#if 0
+ DbgPrint(" prefetchable");
+#endif
+ }
+ }
+
+ DbgPrint("\n");
+
+ *Length = XLength;
+ *Flags = (NewValue & 0x00000001) ? (NewValue & 0x3) : (NewValue & 0xF);
+
+ return TRUE;
+}
+
+
+static NTSTATUS
+PdoQueryResourceRequirements(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ PIO_STACK_LOCATION IrpSp)
+{
+ DPRINT("PdoQueryResourceRequirements() called\n");
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+
+static NTSTATUS
+PdoQueryResources(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ PIO_STACK_LOCATION IrpSp)
+{
+ PPDO_DEVICE_EXTENSION DeviceExtension;
+ PCI_COMMON_CONFIG PciConfig;
+ PCM_RESOURCE_LIST ResourceList;
+ PCM_PARTIAL_RESOURCE_LIST PartialList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ ULONG Size;
+ ULONG ResCount;
+ ULONG ListSize;
+ ULONG i;
+ ULONG Base;
+ ULONG Length;
+ ULONG Flags;
+
+ DPRINT("PdoQueryResources() called\n");
+
+ DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* Get PCI configuration space */
+ Size= HalGetBusData(PCIConfiguration,
+ DeviceExtension->BusNumber,
+ DeviceExtension->SlotNumber.u.AsULONG,
+ &PciConfig,
+ sizeof(PCI_COMMON_CONFIG));
+ DPRINT("Size %lu\n", Size);
+ if (Size < sizeof(PCI_COMMON_CONFIG))
+ {
+ Irp->IoStatus.Information = 0;
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
+
+ /* Count required resource descriptors */
+ ResCount = 0;
+ if ((PciConfig.HeaderType & 0x7F) == 0)
+ {
+ for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+ {
+ if (PciConfig.u.type0.BaseAddresses[i] == 0)
+ break;
+
+ ResCount++;
+ }
+
+ if (PciConfig.u.type0.InterruptLine != 0xFF)
+ ResCount++;
+ }
+ else if ((PciConfig.HeaderType & 0x7F) == 1)
+ {
+ for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+ {
+ if (PciConfig.u.type0.BaseAddresses[i] != 0)
+ break;
+
+ ResCount++;
+ }
+ }
+ else
+ {
+ DPRINT1("Unsupported header type %u\n", PciConfig.HeaderType);
+ }
+
+ /* Calculate the resource list size */
+ ListSize = sizeof(CM_RESOURCE_LIST);
+ if (ResCount > 1)
+ {
+ ListSize += ((ResCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+ }
+
+ /* Allocate the resource list */
+ ResourceList = ExAllocatePool(PagedPool,
+ ListSize);
+ if (ResourceList == NULL)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ ResourceList->Count = 1;
+ ResourceList->List[0].InterfaceType = PCIConfiguration;
+ ResourceList->List[0].BusNumber = DeviceExtension->BusNumber;
+
+ PartialList = &ResourceList->List[0].PartialResourceList;
+ PartialList->Version = 0;
+ PartialList->Revision = 0;
+ PartialList->Count = ResCount;
+
+ Descriptor = &PartialList->PartialDescriptors[0];
+ if ((PciConfig.HeaderType & 0x7F) == 0)
+ {
+ for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+ {
+ if (!PdoGetRangeLength(DeviceExtension,
+ 0x10 + i * 4,
+ &Base,
+ &Length,
+ &Flags))
+ {
+ DPRINT1("PdoGetRangeLength() failed\n");
+ break;
+ }
+
+ if (Length == 0)
+ {
+ DPRINT("Unused address register\n");
+ break;
+ }
+
+ if (Flags & PCI_ADDRESS_IO_SPACE)
+ {
+ Descriptor->Type = CmResourceTypePort;
+// Descriptor->ShareDisposition =
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->u.Port.Start.QuadPart =
+ (ULONGLONG)Base;
+ Descriptor->u.Port.Length = Length;
+ }
+ else
+ {
+ Descriptor->Type = CmResourceTypeMemory;
+// Descriptor->ShareDisposition =
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->u.Memory.Start.QuadPart =
+ (ULONGLONG)Base;
+ Descriptor->u.Memory.Length = Length;
+ }
+
+ Descriptor++;
+ }
+
+ if (PciConfig.u.type0.InterruptLine != 0xFF)
+ {
+ Descriptor->Type = CmResourceTypeInterrupt;
+// Descriptor->ShareDisposition =
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
+ Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
+ Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
+ }
+ }
+#if 0
+ else if ((PciConfig.HeaderType & 0x7F) == 1)
+ {
+ for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+ {
+ if (PciConfig.u.type0.BaseAddresses[i] != 0)
+ ResCount++;
+ }
+ }
+#endif
+
+ Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+PdoReadConfig(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ PIO_STACK_LOCATION IrpSp)
+{
+ PPDO_DEVICE_EXTENSION DeviceExtension;
+ ULONG Size;
+
+ DPRINT1("PdoReadConfig() called\n");
+
+ DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+#if 0
+ if (IrpSp->Parameters.ReadWriteConfig.WhichSpace != PCI_WHICHSPACE_CONFIG)
+ return STATUS_NOT_SUPPORTED;
+#endif
+
+ /* Get PCI configuration space */
+ Size= HalGetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->BusNumber,
+ DeviceExtension->SlotNumber.u.AsULONG,
+ IrpSp->Parameters.ReadWriteConfig.Buffer,
+ IrpSp->Parameters.ReadWriteConfig.Offset,
+ IrpSp->Parameters.ReadWriteConfig.Length);
+ if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
+ {
+ DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
+ Irp->IoStatus.Information = 0;
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Irp->IoStatus.Information = Size;
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+PdoWriteConfig(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ PIO_STACK_LOCATION IrpSp)
+{
+ PPDO_DEVICE_EXTENSION DeviceExtension;
+ ULONG Size;
+
+ DPRINT1("PdoWriteConfig() called\n");
+
+ DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+#if 0
+ if (IrpSp->Parameters.ReadWriteConfig.WhichSpace != PCI_WHICHSPACE_CONFIG)
+ return STATUS_NOT_SUPPORTED;
+#endif
+
+ /* Get PCI configuration space */
+ Size= HalSetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->BusNumber,
+ DeviceExtension->SlotNumber.u.AsULONG,
+ IrpSp->Parameters.ReadWriteConfig.Buffer,
+ IrpSp->Parameters.ReadWriteConfig.Offset,
+ IrpSp->Parameters.ReadWriteConfig.Length);
+ if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
+ {
+ DPRINT1("Size %lu Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
+ Irp->IoStatus.Information = 0;
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Irp->IoStatus.Information = Size;
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
PdoSetPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
case IRP_MN_QUERY_DEVICE_RELATIONS:
/* FIXME: Possibly handle for RemovalRelations */
break;
+#endif
case IRP_MN_QUERY_DEVICE_TEXT:
+ DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
+ Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
break;
-#endif
case IRP_MN_QUERY_ID:
+ DPRINT("IRP_MN_QUERY_ID received\n");
Status = PdoQueryId(DeviceObject, Irp, IrpSp);
break;
case IRP_MN_QUERY_REMOVE_DEVICE:
break;
+#endif
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
+ DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
+ Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
break;
case IRP_MN_QUERY_RESOURCES:
+ DPRINT("IRP_MN_QUERY_RESOURCES received\n");
+ Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
break;
+#if 0
case IRP_MN_QUERY_STOP_DEVICE:
break;
case IRP_MN_SURPRISE_REMOVAL:
break;
#endif
+
+ case IRP_MN_READ_CONFIG:
+ DPRINT1("IRP_MN_READ_CONFIG received\n");
+ Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
+ break;
+
+ case IRP_MN_WRITE_CONFIG:
+ DPRINT1("IRP_MN_WRITE_CONFIG received\n");
+ Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
+ break;
+
default:
DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
break;