- To read/write CMD register of hte PCI config space we used 1) WinDBG: “!pci 0x100 8 1 0” / “!ecw 8.1.0 4 0xFFFF” and 2) Read(Write)PCIConfig routines:
PDEVICE_OBJECT pdo;
DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) UCHAR buffer[PCI_COMMON_HDR_LENGTH];
PPCI_COMMON_CONFIG pPciConfig = (PPCI_COMMON_CONFIG) buffer;
NTSTATUS
ReadPCIConfig(
IN PDEVICE_CONTEXT pContext
)
{
PAGED_CODE();
pdo = WdfDeviceWdmGetDeviceObject(pContext->WdfDevice);
return ReadWriteConfigSpace(pdo, 0, buffer, 0, PCI_COMMON_HDR_LENGTH);
}
NTSTATUS
WritePCIConfig(
IN PDEVICE_CONTEXT pContext
)
{
PAGED_CODE();
pdo = WdfDeviceWdmGetDeviceObject(pContext->WdfDevice);
// Set CMD register manually
pPciConfig->Command = 0xFFFF;
return ReadWriteConfigSpace(pdo, 1, buffer, FIELD_OFFSET(PCI_COMMON_CONFIG, Command), sizeof(pPciConfig->Command));
}
…and the ReadWriteConfigSpace routine we’ve used from some PCI config space read/write example:
NTSTATUS
ReadWriteConfigSpace(
__in PDEVICE_OBJECT DeviceObject,
__in ULONG ReadOrWrite,
__in PVOID Buffer,
__in ULONG Offset,
__in ULONG Length
)
/*++
Routine Description:
Worker function to read & write to PCI config space at
PASSIVE_LEVEL
Arguments:
DeviceObject - Pointer to the PDO
ReadOrWrite - Whichspace - 0 for read 1 for write
Buffer - Buffer to be written to or read from
Offset - Offset in to the PCI config space
Length - Length of the buffer
Return Value:
NT Status code
–*/
{
KEVENT event;
NTSTATUS status;
PIRP irp;
IO_STATUS_BLOCK ioStatusBlock;
PIO_STACK_LOCATION irpStack;
PDEVICE_OBJECT targetObject;
PAGED_CODE();
KeInitializeEvent(&event, NotificationEvent, FALSE);
targetObject = IoGetAttachedDeviceReference(DeviceObject);
irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP,
targetObject,
NULL,
0,
NULL,
&event,
&ioStatusBlock );
if (irp == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
// Done with reference
ObDereferenceObject(targetObject);
return status;
}
irpStack = IoGetNextIrpStackLocation( irp );
irpStack->MinorFunction = ReadOrWrite ? IRP_MN_WRITE_CONFIG : IRP_MN_READ_CONFIG;
irpStack->Parameters.ReadWriteConfig.WhichSpace = PCI_WHICHSPACE_CONFIG;
irpStack->Parameters.ReadWriteConfig.Buffer = Buffer;
irpStack->Parameters.ReadWriteConfig.Offset = Offset;
irpStack->Parameters.ReadWriteConfig.Length = Length;
//
// Initialize the status to error in case the bus driver does not
// set it correctly.
irp->IoStatus.Status = STATUS_NOT_SUPPORTED ;
status = IoCallDriver(targetObject, irp);
if (status == STATUS_PENDING) {
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = ioStatusBlock.Status;
}
// Done with reference
ObDereferenceObject( targetObject );
return status;
}
On some PC with Windows 7 CMD eq 0x02 after WritePCIConfig(…)
- Probably we missed something in configuring our device. How can one specify to KMDF that our device is bus master capable (Pavel) ?