IN PCM_RESOURCE_LIST DriverList | Resource list for driver |
IN ULONG DriverListSize | Driver resource list size |
IN PDEVICE_OBJECT DeviceObject | Device object pointer |
IN PCM_RESOURCE_LIST DeviceList | Resource list for device |
IN ULONG DeviceListSize | Device resource list size |
IN BOOLEAN OverrideConflict | If TRUE, store resource list even if a conflict was detected |
OUT PBOOLEAN ConflictDetected | BOOLEAN that is set TRUE if a conflict was detected |
A driver releases its claim on any resources by calling
Listing 18.5 UnclaimResources routine
void UnclaimResources(IN PDEVICE_OBJECT phddo) {
DebugPrintMsg('Freeing all allocated resources');
// Release all driver's resources by declaring we have none.
CM_RESOURCE_LIST ResourceList;
ResourceList.Count = 0;
BOOLEAN ConflictDetected;
IoReportResourceUsage(NULL,
phddo->DriverObject, &ResourceList, sizeof(ResourceList), // Driver
NULL, NULL, 0, // Device resources
FALSE, &ConflictDetected); // ignore return result
}
Translating Resources
At this point, PHDIo has found its raw resource requirements and claimed them for itself. The final stage is to translate the raw resource information into a form that can be used by the driver. Listing 18.6 shows the
The raw interrupt information must be translated using HalGetInterruptVector. The bus type and number as passed as before. For the ISA bus, specifying the IRQ number for the raw interrupt level and raw vector parameters seems to work. The translated interrupt Vector, Irql, and Affinity are stored in the PHDIo device extension. Do not forget that PHDIo still needs to connect to the interrupt to install its interrupt service routine.
The final step in
Listing 18.6 TranslateAndMapResources routine
NTSTATUS TranslateAndMapResources(IN PDEVICE_OBJECT phddo) {
PPHDIO_DEVICE_EXTENSION dx = (PPHDIO_DEVICE_EXTENSION)phddo->DeviceExtension;
// Translate IO port values
ULONG AddressSpace = 1; //IO space
if (!HalTranslateBusAddress(Isa, 0, dx->PortStartAddress, &AddressSpace, &dx->PortStartAddress)) {
DebugPrint('Create file: could not translate IO %x', dx->PortStartAddress.LowPart);
return STATUS_INVALID_PARAMETER;
}
DebugPrint('IO trans %x,%d', dx->PortStartAddress.LowPart, dx->PortLength);
dx->PortNeedsMapping = (AddressSpace==0);
dx->PortInIOSpace = (AddressSpace==1);
// Translate IRQ values
if (dx->GotInterrupt) {
ULONG irq = dx->Irql;
dx->Vector = HalGetInterruptVector(Isa, 0, irq, irq, &dx->Irql, &dx->Affinity);
if (dx->Vector==NULL) {
DebugPrint('Create filename: Could not get interrupt vector for IRQ %d', irq);
return STATUS_INVALID_PARAMETER;
}
DebugPrint('Interrupt vector %x IRQL %d Affinity %d Mode %d', dx->Vector, dx->Irql, dx->Affinity, dx->Mode);
}
// Map memory
if (dx->PortNeedsMapping) {
dx->PortBase = (PUCHAR)MmMapIoSpace(dx->PortStartAddress, dx->PortLength, MmNonCached);
if (dx->PortBase==NULL) DebugPrintMsg('Cannot map IO port');
return STATUS_NO_MEMORY;
} else dx->PortBase = (PUCHAR)dx->PortStartAddress.LowPart;
return STATUS_SUCCESS;
}
The
Well, that wraps up the discussion of PHDIo. The rest of its functionality is the same as WdmIo. The rest of the chapter backtracks to revisit the subject of finding the resources that a driver needs.