PIO_STACK_LOCATION IrpSp)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
+ UNICODE_STRING String;
NTSTATUS Status;
DPRINT("Called\n");
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
- Status = STATUS_SUCCESS;
-
switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType)
{
case DeviceTextDescription:
+ Status = PciDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+ &DeviceExtension->DeviceDescription,
+ &String);
+
DPRINT("DeviceTextDescription\n");
- Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceDescription.Buffer;
+ Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
break;
case DeviceTextLocationInformation:
+ Status = PciDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+ &DeviceExtension->DeviceLocation,
+ &String);
+
DPRINT("DeviceTextLocationInformation\n");
- Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceLocation.Buffer;
+ Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
break;
default:
Irp->IoStatus.Information = 0;
Status = STATUS_INVALID_PARAMETER;
+ break;
}
return Status;
PIO_STACK_LOCATION IrpSp)
{
PPDO_DEVICE_EXTENSION DeviceExtension;
- PFDO_DEVICE_EXTENSION FdoDeviceExtension;
PPNP_BUS_INFORMATION BusInformation;
UNREFERENCED_PARAMETER(IrpSp);
DPRINT("Called\n");
DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
- FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
BusInformation = ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
Irp->IoStatus.Information = (ULONG_PTR)BusInformation;
if (BusInformation != NULL)
return FALSE;
}
- BaseValue = (OrigValue & 0x00000001) ? (OrigValue & ~0x3) : (OrigValue & ~0xF);
+ BaseValue = (OrigValue & PCI_ADDRESS_IO_SPACE)
+ ? (OrigValue & PCI_ADDRESS_IO_ADDRESS_MASK)
+ : (OrigValue & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
*Base = BaseValue;
return TRUE;
}
- XLength = ~((NewValue & 0x00000001) ? (NewValue & ~0x3) : (NewValue & ~0xF)) + 1;
+ XLength = ~((NewValue & PCI_ADDRESS_IO_SPACE)
+ ? (NewValue & PCI_ADDRESS_IO_ADDRESS_MASK)
+ : (NewValue & PCI_ADDRESS_MEMORY_ADDRESS_MASK)) + 1;
#if 0
DbgPrint("BaseAddress 0x%08lx Length 0x%08lx",
BaseValue, XLength);
- if (NewValue & 0x00000001)
+ if (NewValue & PCI_ADDRESS_IO_SPACE)
{
DbgPrint(" IO range");
}
else
{
DbgPrint(" Memory range");
- if ((NewValue & 0x00000006) == 0)
+ if ((NewValue & PCI_ADDRESS_MEMORY_TYPE_MASK) == 0)
{
DbgPrint(" in 32-Bit address space");
}
- else if ((NewValue & 0x00000006) == 2)
+ else if ((NewValue & PCI_ADDRESS_MEMORY_TYPE_MASK) == 2)
{
DbgPrint(" below 1BM ");
}
- else if ((NewValue & 0x00000006) == 4)
+ else if ((NewValue & PCI_ADDRESS_MEMORY_TYPE_MASK) == 4)
{
DbgPrint(" in 64-Bit address space");
}
- if (NewValue & 0x00000008)
+ if (NewValue & PCI_ADDRESS_MEMORY_PREFETCHABLE)
{
DbgPrint(" prefetchable");
}
#endif
*Length = XLength;
- *Flags = (NewValue & 0x00000001) ? (NewValue & 0x3) : (NewValue & 0xF);
+ *Flags = (NewValue & PCI_ADDRESS_IO_SPACE)
+ ? (NewValue & ~PCI_ADDRESS_IO_ADDRESS_MASK)
+ : (NewValue & ~PCI_ADDRESS_MEMORY_ADDRESS_MASK);
return TRUE;
}
RtlZeroMemory(ResourceList, ListSize);
ResourceList->ListSize = ListSize;
ResourceList->InterfaceType = PCIBus;
- ResourceList->BusNumber = 0;
- ResourceList->SlotNumber = 0;
+ ResourceList->BusNumber = DeviceExtension->PciDevice->BusNumber;
+ ResourceList->SlotNumber = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
ResourceList->AlternativeLists = 1;
ResourceList->List[0].Version = 1;
}
if ((PciConfig.u.type0.InterruptPin != 0) &&
+ (PciConfig.u.type0.InterruptLine != 0) &&
(PciConfig.u.type0.InterruptLine != 0xFF))
ResCount++;
}
RtlZeroMemory(ResourceList, ListSize);
ResourceList->Count = 1;
ResourceList->List[0].InterfaceType = PCIBus;
- ResourceList->List[0].BusNumber = 0;
+ ResourceList->List[0].BusNumber = DeviceExtension->PciDevice->BusNumber;
PartialList = &ResourceList->List[0].PartialResourceList;
PartialList->Version = 1;
Descriptor->u.Port.Start.QuadPart =
(ULONGLONG)Base;
Descriptor->u.Port.Length = Length;
+
+ /* Enable IO space access */
+ DeviceExtension->PciDevice->EnableIoSpace = TRUE;
}
else
{
Descriptor->u.Memory.Start.QuadPart =
(ULONGLONG)Base;
Descriptor->u.Memory.Length = Length;
+
+ /* Enable memory space access */
+ DeviceExtension->PciDevice->EnableMemorySpace = TRUE;
}
Descriptor++;
/* Add interrupt resource */
if ((PciConfig.u.type0.InterruptPin != 0) &&
+ (PciConfig.u.type0.InterruptLine != 0) &&
(PciConfig.u.type0.InterruptLine != 0xFF))
{
Descriptor->Type = CmResourceTypeInterrupt;
Descriptor->ShareDisposition = CmResourceShareShared;
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
- Descriptor->u.Interrupt.Vector = 0;
+ Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
}
+
+ /* Allow bus master mode */
+ DeviceExtension->PciDevice->EnableBusMaster = TRUE;
}
else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
{
Descriptor->u.Port.Start.QuadPart =
(ULONGLONG)Base;
Descriptor->u.Port.Length = Length;
+
+ /* Enable IO space access */
+ DeviceExtension->PciDevice->EnableIoSpace = TRUE;
}
else
{
Descriptor->u.Memory.Start.QuadPart =
(ULONGLONG)Base;
Descriptor->u.Memory.Length = Length;
+
+ /* Enable memory space access */
+ DeviceExtension->PciDevice->EnableMemorySpace = TRUE;
}
Descriptor++;
return Status;
}
+static NTSTATUS
+PdoStartDevice(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ PIO_STACK_LOCATION IrpSp)
+{
+ PCM_RESOURCE_LIST RawResList = IrpSp->Parameters.StartDevice.AllocatedResources;
+ PCM_FULL_RESOURCE_DESCRIPTOR RawFullDesc;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR RawPartialDesc;
+ ULONG i, ii;
+ PPDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+ UCHAR Irq;
+ USHORT Command;
+
+ if (!RawResList)
+ return STATUS_SUCCESS;
+
+ /* TODO: Assign the other resources we get to the card */
+
+ for (i = 0; i < RawResList->Count; i++)
+ {
+ RawFullDesc = &RawResList->List[i];
+
+ for (ii = 0; ii < RawFullDesc->PartialResourceList.Count; ii++)
+ {
+ RawPartialDesc = &RawFullDesc->PartialResourceList.PartialDescriptors[ii];
+
+ if (RawPartialDesc->Type == CmResourceTypeInterrupt)
+ {
+ DPRINT1("Assigning IRQ %d to PCI device 0x%x on bus 0x%x\n",
+ RawPartialDesc->u.Interrupt.Vector,
+ DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+ DeviceExtension->PciDevice->BusNumber);
+
+ Irq = (UCHAR)RawPartialDesc->u.Interrupt.Vector;
+ HalSetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->PciDevice->BusNumber,
+ DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+ &Irq,
+ 0x3c /* PCI_INTERRUPT_LINE */,
+ sizeof(UCHAR));
+ }
+ }
+ }
+
+ Command = 0;
+
+ DPRINT1("Enabling command flags for PCI device 0x%x on bus 0x%x: ",
+ DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+ DeviceExtension->PciDevice->BusNumber);
+ if (DeviceExtension->PciDevice->EnableBusMaster)
+ {
+ Command |= PCI_ENABLE_BUS_MASTER;
+ DbgPrint("[Bus master] ");
+ }
+
+ if (DeviceExtension->PciDevice->EnableMemorySpace)
+ {
+ Command |= PCI_ENABLE_MEMORY_SPACE;
+ DbgPrint("[Memory space enable] ");
+ }
+
+ if (DeviceExtension->PciDevice->EnableIoSpace)
+ {
+ Command |= PCI_ENABLE_IO_SPACE;
+ DbgPrint("[I/O space enable] ");
+ }
+
+ if (Command != 0)
+ {
+ DbgPrint("\n");
+
+ /* OR with the previous value */
+ Command |= DeviceExtension->PciDevice->PciConfig.Command;
+
+ HalSetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->PciDevice->BusNumber,
+ DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+ &Command,
+ FIELD_OFFSET(PCI_COMMON_CONFIG, Command),
+ sizeof(USHORT));
+ }
+ else
+ {
+ DbgPrint("None\n");
+ }
+
+ return STATUS_SUCCESS;
+}
static NTSTATUS
PdoReadConfig(
return STATUS_SUCCESS;
}
+static NTSTATUS
+PdoQueryDeviceRelations(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp,
+ PIO_STACK_LOCATION IrpSp)
+{
+ PDEVICE_RELATIONS DeviceRelations;
+
+ /* We only support TargetDeviceRelation for child PDOs */
+ if (IrpSp->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
+ return Irp->IoStatus.Status;
+
+ /* We can do this because we only return 1 PDO for TargetDeviceRelation */
+ DeviceRelations = ExAllocatePool(PagedPool, sizeof(*DeviceRelations));
+ if (!DeviceRelations)
+ return STATUS_INSUFFICIENT_RESOURCES;
+
+ DeviceRelations->Count = 1;
+ DeviceRelations->Objects[0] = DeviceObject;
+
+ /* The PnP manager will remove this when it is done with the PDO */
+ ObReferenceObject(DeviceObject);
+
+ Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
+
+ return STATUS_SUCCESS;
+}
static NTSTATUS
PdoSetPower(
IN PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
- PPDO_DEVICE_EXTENSION DeviceExtension;
NTSTATUS Status;
UNREFERENCED_PARAMETER(Irp);
DPRINT("Called\n");
- DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
if (IrpSp->Parameters.Power.Type == DevicePowerState) {
Status = STATUS_SUCCESS;
switch (IrpSp->Parameters.Power.State.SystemState) {
break;
case IRP_MN_QUERY_DEVICE_RELATIONS:
- /* FIXME: Possibly handle for RemovalRelations */
- DPRINT("Unimplemented IRP_MN_QUERY_DEVICE_RELATIONS received\n");
+ Status = PdoQueryDeviceRelations(DeviceObject, Irp, IrpSp);
break;
case IRP_MN_QUERY_DEVICE_TEXT:
break;
case IRP_MN_START_DEVICE:
+ Status = PdoStartDevice(DeviceObject, Irp, IrpSp);
+ break;
+
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
case IRP_MN_STOP_DEVICE:
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
- case IRP_MN_REMOVE_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
Status = STATUS_SUCCESS;
break;
+ case IRP_MN_REMOVE_DEVICE:
+ {
+ PPDO_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
+ PFDO_DEVICE_EXTENSION FdoDeviceExtension = DeviceExtension->Fdo->DeviceExtension;
+ KIRQL OldIrql;
+
+ /* Remove it from the device list */
+ KeAcquireSpinLock(&FdoDeviceExtension->DeviceListLock, &OldIrql);
+ RemoveEntryList(&DeviceExtension->PciDevice->ListEntry);
+ FdoDeviceExtension->DeviceListCount--;
+ KeReleaseSpinLock(&FdoDeviceExtension->DeviceListLock, OldIrql);
+
+ /* Free the device */
+ ExFreePool(DeviceExtension->PciDevice);
+
+ /* Complete the IRP */
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ /* Delete the DO */
+ IoDeleteDevice(DeviceObject);
+ return STATUS_SUCCESS;
+ }
+
case IRP_MN_QUERY_INTERFACE:
DPRINT("IRP_MN_QUERY_INTERFACE received\n");
Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);