Zuordnen Bus-Relative Adressen zu virtuellen Adressen

Einige Prozessoren implementieren separate Speicher- und E/A-Adressräume, andere Prozessoren hingegen nicht. Aufgrund dieser Unterschiede bei Hardwareplattformen unterscheiden sich die Mechanismustreiber, die für den Zugriff auf E/A- oder speicherresidente Geräteressourcen verwenden, von Plattform zu Plattform.

Ein Treiber fordert Geräte-E/A- und Speicherressourcen als Reaktion auf die IRP_MN_QUERY_RESOURCE_REQUIREMENTS IRP des PnP-Managers an. Abhängig von der Hardwarearchitektur kann die HAL E/A-Ressourcen im E/A-Bereich oder im Arbeitsspeicher zuweisen und Speicherressourcen im E/A-Bereich oder im Arbeitsspeicher zuweisen.

Wenn die HAL den busrelativen Speicherplatz für den Zugriff auf Geräteressourcen (z. B. Geräteregister) verwendet, muss ein Treiber E/A-Speicherplatz dem virtuellen Arbeitsspeicher zuordnen, damit er auf diese Ressourcen zugreifen kann. Der Treiber kann ermitteln, ob die Ressourcen E/A- oder Speicherresident sind, indem er die übersetzten Ressourcen überprüft, die der PnP-Manager beim Gerätestart an den Treiber übergeben hat. Wenn die HAL E/A-Speicherplatz verwendet, ist keine Zuordnung erforderlich.

Wenn ein Treiber eine IRP_MN_START_DEVICE-Anforderung empfängt, sollte er die Strukturen unter IrpSp-Parameters.StartDevice.AssignedResources> und IrpSp-Parameters.StartDevice.AssignedResourcesTranslated> untersuchen, die die rohen (busrelativen) und übersetzten Ressourcen beschreiben, die der PnP-Manager dem Gerät zugewiesen hat. Treiber sollten eine Kopie jeder Ressourcenliste in der Geräteerweiterung speichern, um das Debuggen zu erleichtern.

Die Ressourcenlisten werden CM_RESOURCE_LIST Strukturen gekoppelt, in denen jedes Element der rohen Liste demselben Element der übersetzten Liste entspricht. Wenn beispielsweise AllocatedResources.List[0] einen unformatierten E/A-Portbereich beschreibt, beschreibt AllocatedResourcesTranslated.List[0] den gleichen Bereich nach der Übersetzung. Jede übersetzte Ressource enthält eine physische Adresse und den Typ der Ressource.

Wenn einem Treiber eine übersetzte Speicherressource (CmResourceTypeMemory) zugewiesen wird, muss mmMapIoSpace aufgerufen werden, um die physische Adresse einer virtuellen Adresse zuzuordnen, über die er auf Geräteregister zugreifen kann. Damit ein Treiber plattformunabhängig arbeitet, sollte er jede zurückgegebene, übersetzte Ressource überprüfen und bei Bedarf zuordnen.

Ein Kernelmodustreiber sollte als Reaktion auf eine IRP_MN_START_DEVICE Anforderung die folgenden Schritte ausführen, um den Zugriff auf alle Geräteressourcen sicherzustellen.

  1. Kopieren Sie IrpSp-Parameters.StartDevice.AllocatedResources> in die Geräteerweiterung.

  2. Kopieren Sie IrpSp-Parameters.StartDevice.AllocatedResourcesTranslated> in die Geräteerweiterung.

  3. Überprüfen Sie in einer Schleife jedes Deskriptorelement in AllocatedResourcesTranslated. Wenn der Deskriptorressourcentyp CmResourceTypeMemory ist, rufen Sie MmMapIoSpace auf, und übergeben Sie die physische Adresse und länge der übersetzten Ressource.

Wenn der Treiber eine IRP_MN_STOP_DEVICE - oder IRP_MN_REMOVE_DEVICE-Anforderung vom PnP-Manager empfängt, muss er die Zuordnungen freigeben, indem er MmUnmapIoSpace in einer ähnlichen Schleife aufruft. Der Treiber sollte auch MmUnmapIoSpace aufrufen, wenn die IRP_MN_START_DEVICE-Anforderung fehlschlagen muss.

Der Rohressourcentyp gibt an, welche HAL-Zugriffsroutine ein Treiber aufrufen soll (READ_REGISTER_XXX, WRITE_REGISTER_XXX, READ_PORT_XXX, WRITE_PORT_XXX). Die meisten Treiber müssen die Rohressourcenliste nicht überprüfen, um festzustellen, welche dieser Routinen verwendet werden sollen, da der Treiber selbst die Ressource angefordert hat oder der Treiberschreiber den erforderlichen Typ aufgrund der Art der Gerätehardware kennt.

Für eine Ressource im E/A-Raum (CmResourceTypePort, CmResourceTypeInterrupt, CmResourceTypeDma) sollte der Treiber die 32 Bits der zurückgegebenen physischen Adresse in niedriger Reihenfolge verwenden, um auf die Geräteressource zuzugreifen, z. B. über die Lese- und Schreibroutinen READ_REGISTER_XXX, WRITE_REGISTER_XXX, READ_PORT_XXX, WRITE_PORT_XXX .