StartIo Routines in Lowest-Level Drivers

De oproep van de I/O-manager aan de verzendroutine van een chauffeur is de eerste fase bij het voldoen aan een I/O-aanvraag van een apparaat. De StartIo-routine is de tweede fase. Elk apparaatstuurprogramma met een StartIo-routine roept waarschijnlijk IoStartPacket aan vanuit de DispatchRead - en DispatchWrite-routines , en meestal voor een subset van de I/O-besturingscodes die worden ondersteund in de DispatchDeviceControl-routine . De IoStartPacket-routine voegt het IRP toe aan de door het systeem geleverde apparaatwachtrij van het apparaat of roept, als de wachtrij leeg is, onmiddellijk de StartIo-routine van het stuurprogramma aan om de IRP te verwerken.

U kunt ervan uitgaan dat wanneer de StartIo-routine van een stuurprogramma wordt aangeroepen, het doelapparaat niet bezet is. Dit komt doordat de I/O-manager StartIo onder twee omstandigheden aanroept; een van de verzendroutines van het stuurprogramma heeft net IoStartPacket genoemd en de apparaatwachtrij is leeg, of de DpcForIsr-routine van het stuurprogramma voltooit een andere aanvraag en heeft net IoStartNextPacket genoemd om de volgende IRP uit de wachtrij te verwijderen.

Voordat de StartIo-routine in een apparaatstuurprogramma op het hoogste niveau wordt aangeroepen, moet de verzendroutine van dat stuurprogramma de gebruikersbuffer indien nodig hebben getest en vergrendeld om geldige toegewezen bufferadressen in te stellen in de IRP die in de wachtrij is geplaatst voor de StartIo-routine . Als een apparaatstuurprogramma op het hoogste niveau de apparaatobjecten instelt voor directe I/O (of voor niet-gebufferde of directe I/O), kan het stuurprogramma de vergrendeling van een gebruikersbuffer niet uitstellen naar de StartIo-routine ; elke StartIo-routine wordt aangeroepen in een willekeurige threadcontext bij IRQL = DISPATCH_LEVEL.

Opmerking

Elk buffergeheugen dat toegankelijk is voor de StartIo-routine van een stuurprogramma, moet worden vergrendeld of toegewezen vanuit het systeemgeheugen en moet toegankelijk zijn in een willekeurige threadcontext.

Over het algemeen is de StartIo-routine van een apparaatstuurprogramma op lager niveau verantwoordelijk voor het aanroepen van IoGetCurrentIrpStackLocation met de invoer-IRP en vervolgens het uitvoeren van elke aanvraagspecifieke verwerking is nodig om de I/O-bewerking op het apparaat te starten. Aanvraagspecifieke verwerking kan het volgende omvatten:

  • Instellen of bijwerken van de statusinformatie over het actuele verzoek dat het stuurprogramma onderhoudt. De statusgegevens kunnen worden opgeslagen in de apparaatextensie van het doelapparaatobject of elders in een niet-gepaginade pool die door het stuurprogramma is toegewezen.

    Als een apparaatstuurprogramma bijvoorbeeld een Booleaanse Waarde van InterruptExpected onderhoudt voor de huidige overdrachtsbewerking, kan de StartIo-routine deze variabele instellen op TRUE. Als het stuurprogramma een time-outteller voor de huidige bewerking onderhoudt, kan de StartIo-routine deze waarde instellen, of kan de StartIo-routine de CustomTimerDpc-routine van het stuurprogramma in de wachtrij plaatsen.

    Als de StartIo-routine toegang deelt tot statusinformatie of hardwareresources met andere stuurprogrammaroutines, moet de statusinformatie of resource worden beveiligd door een kringvergrendeling. (Zie Spin Locks.)

    Als de StartIo-routine toegang deelt tot statusinformatie of resources met de InterruptService-routine van het stuurprogramma, moet StartIoKeSynchronizeExecution gebruiken om een SynchCritSection-routine aan te roepen die toegang heeft tot de status- of resourcegegevens. (Zie Het gebruik van kritieke secties.)

  • Het toewijzen van een volgnummer aan de IRP voor het geval het stuurprogramma een I/O-fout van het apparaat moet registreren tijdens het verwerken van de IRP.

    Zie Fouten bij logboekregistratie voor meer informatie.

  • Vertaal indien nodig de parameters in de I/O-stacklocatie van het stuurprogramma naar apparaatspecifieke waarden.

    Een schijfstuurprogramma moet bijvoorbeeld de beginsector of byte-offset berekenen naar het adres van de fysieke schijf voor een overdrachtsbewerking en of de aangevraagde lengte van de overdracht een bepaalde sectorgrens overschrijdt of de overdrachtscapaciteit van het fysieke apparaat overschrijdt.

  • Als het stuurprogramma een verwisselbaar media-apparaat beheert, controleert het of er mediawijzigingen zijn voordat het apparaat voor I/O wordt geprogrammeerd, en meldt het aan het bovenliggende bestandssysteem als de media zijn gewijzigd.

    Zie Ondersteuning van verwisselbare media voor meer informatie.

  • Als het apparaat DMA gebruikt, moet u controleren of de aangevraagde lengte (aantal te overdragen bytes, te vinden in de I/O-stacklocatie van het stuurprogramma van de IRP) moet worden opgesplitst in gedeeltelijke overdracht operaties, zoals wordt uitgelegd in invoer-/uitvoertechnieken, ervan uitgaande dat een nauw gekoppeld stuurprogramma op hoger niveau geen grote overdrachten voor het apparaatstuurprogramma vooraf splitst.

    De StartIo-routine van een dergelijk apparaatstuurprogramma kan ook verantwoordelijk zijn voor het aanroepen van KeFlushIoBuffers en, als het stuurprogramma gebruikmaakt van DMA op basis van pakketten, voor het aanroepen van AllocateAdapterChannel met de AdapterControl-routine van het stuurprogramma.

    Zie Adapterobjecten en DMA en Coherency van cache onderhouden voor meer informatie.

  • Als het apparaat GEBRUIKMAAKTvanen VAN MICROSOFT, wordt het virtuele basisadres van de buffer, zoals beschreven in de IRP bij Irp-MdlAddress>, toegewezen aan een systeemruimteadres met MmGetSystemAddressForMdlSafe.

    Voor leesaanvragen kan de StartIo-routine van het apparaatstuurprogramma verantwoordelijk zijn voor het aanroepen van KeFlushIoBuffers voordat de PIO-bewerkingen beginnen. Zie Onderhouden van cache-coherentie voor meer informatie.

  • Als een niet-WDM-stuurprogramma een controllerobject gebruikt, gebruikt men IoAllocateController om de ControllerControl-routine te registreren.

  • Als het stuurprogramma annuleerbare IR's verwerkt, controleert u of de invoer-IRP al is geannuleerd.

  • Als een invoer-IRP kan worden geannuleerd voordat deze tot voltooiing wordt verwerkt, moet de StartIo-routineIoSetCancelRoutine aanroepen met de IRP en het toegangspunt van de routine Annuleren van het stuurprogramma. De StartIo-routine moet de annuleringsspinlock verkrijgen voor zijn aanroep naar IoSetCancelRoutine. Een stuurprogramma kan ook IoSetStartIoAttributes gebruiken om het kenmerk NonCancelable voor de StartIo-routine in te stellen op TRUE. Dit voorkomt dat het systeem probeert een IRP te annuleren die is doorgegeven aan StartIo door een aanroep naar IoStartPacket.

Over het algemeen heeft een stuurprogramma dat gebruikmaakt van gebufferde I/O een eenvoudigere StartIo-routine dan een die directe I/O gebruikt. nl-NL: Stuurprogramma's die gebruikmaken van gebufferde I/O dragen kleine hoeveelheden gegevens over voor elke overdrachtsaanvraag, terwijl stuurprogramma's die gebruikmaken van directe I/O (of DMA of PIO) grote hoeveelheden gegevens overdragen naar of van vergrendelde buffers die fysieke paginagrenzen in het systeemgeheugen kunnen overschrijden.

Stuurprogramma's op een hoger niveau die boven fysieke apparaatstuurprogramma's worden geplaatst, stellen meestal hun apparaatobjecten in zodat deze overeenkomen met die van hun respectieve apparaatstuurprogramma's. Een stuurprogramma op het hoogste niveau, met name een bestandssysteemstuurprogramma, kan echter apparaatobjecten instellen voor noch directe noch gebufferde I/O.

Stuurprogramma's die hun apparaatobjecten voor gebufferde I/O instellen, kunnen afhankelijk zijn van de I/O-manager om geldige buffers door te geven in alle IRP's die naar het stuurprogramma worden verzonden. Stuurprogramma's op lager niveau die apparaatobjecten voor directe I/O instellen, kunnen afhankelijk zijn van het stuurprogramma op het hoogste niveau in hun keten om geldige buffers door te geven in alle IR's die via tussenliggende stuurprogramma's worden verzonden naar het onderliggende apparaatstuurprogramma op lager niveau.

Gebufferde I/O gebruiken in StartIo-routines

Als de routine DispatchRead, DispatchWrite of DispatchDeviceControl van een stuurprogramma bepaalt dat een aanvraag geldig is en IoStartPacket aanroept, roept de I/O-manager de StartIo-routine van het stuurprogramma aan om de IRP onmiddellijk te verwerken als de apparaatwachtrij leeg is. Als de wachtrij niet leeg is, plaatst IoStartPacket de IRP in de wachtrij. Uiteindelijk zorgt een aanroep van IoStartNextPacket vanuit de DpcForIsr- of CustomDpc-routine ervoor dat de I/O-manager de IRP uit de wachtrij verwijdert en de StartIo-routine van het stuurprogramma aanroept.

De StartIo-routine roept IoGetCurrentIrpStackLocation aan en bepaalt welke bewerking moet worden uitgevoerd om aan de aanvraag te voldoen. Het verwerkt de IRP op enige manier die nodig is voordat het fysieke apparaat wordt programmeren om de I/O-aanvraag uit te voeren.

Als toegang tot het fysieke apparaat (of de apparaatextensie) moet worden gesynchroniseerd met een InterruptService-routine , moet de StartIo-routine een SynchCritSection-routine aanroepen om de benodigde apparaatprogrammering uit te voeren. Voor meer informatie, zie Kritieke secties gebruiken.

Een fysiek apparaatstuurprogramma dat gebruikmaakt van gebufferde I/O-overdrachtsgegevens naar of van een systeemruimtebuffer, toegewezen door de I/O-manager, die het stuurprogramma vindt in elke IRP bij Irp-AssociatedIrp.SystemBuffer>.

Directe I/O gebruiken in StartIo-routines

Als de routine DispatchRead, DispatchWrite of DispatchDeviceControl van een stuurprogramma bepaalt dat een aanvraag geldig is en IoStartPacket aanroept, roept de I/O-manager de StartIo-routine van het stuurprogramma aan om de IRP onmiddellijk te verwerken als de apparaatwachtrij leeg is. Als de wachtrij niet leeg is, plaatst IoStartPacket de IRP in de wachtrij. Uiteindelijk zorgt een aanroep van IoStartNextPacket van de DpcForIsr - of CustomDpc-routine ervoor dat de I/O-manager de I/O-routine van het stuurprogramma loslaat en de StartIo-routine van het stuurprogramma aanroept.

De StartIo-routine roept IoGetCurrentIrpStackLocation aan en bepaalt welke bewerking moet worden uitgevoerd om aan de aanvraag te voldoen. Het verwerkt de IRP op elke manier die nodig is, zoals het splitsen van een grote DMA-overdrachtsaanvraag in gedeeltelijke overdrachtsbereiken en het opslaan van de status over de lengte van een binnenkomende overdrachtsaanvraag die moet worden gesplitst. Vervolgens wordt het fysieke apparaat geprogrammad om de I/O-aanvraag uit te voeren.

Als toegang tot het fysieke apparaat (of de apparaatextensie) moet worden gesynchroniseerd met de ISR van het stuurprogramma, moet de StartIo-routine een door het stuurprogramma geleverde SynchCritSection-routine gebruiken om de benodigde programmering uit te voeren. Voor meer informatie, zie Kritieke secties gebruiken.

Elk stuurprogramma dat directe I/O gebruikt, leest gegevens in of schrijft gegevens uit een vergrendelde buffer, zoals beschreven door een MDL (Memory Descriptor List), die het stuurprogramma vindt in de IRP bij Irp-MdlAddress>. Een dergelijk stuurprogramma maakt vaak gebruik van gebufferde I/O voor apparaatbeheeraanvragen. Zie I/O-beheeraanvragen verwerken in StartIo-routines voor meer informatie.

Het MDL-type is een ondoorzichtig type dat drivers niet rechtstreeks benaderen. In plaats daarvan wijzen stuurprogramma's die gebruikmaken van gebruikersruimte-buffers deze opnieuw toe door MmGetSystemAddressForMdlSafe aan te roepen met Irp-MdlAddress> als parameter. Stuurprogramma's die gebruikmaken van DMA geven ook Irp-MdlAddress> door aan ondersteunende routines tijdens hun overdrachtsbewerkingen, zodat de bufferadressen opnieuw worden toegewezen aan logische bereiken voor hun apparaten.

Tenzij een nauw gekoppeld stuurprogramma op een hoger niveau grote DMA-overdrachtsaanvragen voor het onderliggende apparaatstuurprogramma splitst, moet de StartIo-routine van een apparaatstuurprogramma op het laagste niveau elke overdrachtsaanvraag splitsen die groter is dan het apparaat kan beheren in één overdrachtsbewerking. Stuurprogramma's die gebruikmaken van systeem-DMA zijn verplicht om overdrachtsaanvragen te splitsen die te groot zijn voor de DMA-controller van het systeem of voor hun apparaten om in één bewerking uit te voeren.

Als het apparaat een ondergeschikt DMA-apparaat is, moet het stuurprogramma overdrachten synchroniseren via een systeem-DMA-controller met een door het stuurprogramma toegewezen adapterobject, dat het DMA-kanaal vertegenwoordigt en een door het stuurprogramma geleverde AdapterControl-routine . Het stuurprogramma van een DMA-apparaat met busmaster moet ook een door het stuurprogramma toegewezen adapterobject gebruiken om de overdrachten te synchroniseren en moet een AdapterControl-routine leveren als het gebruikmaakt van de DMA-ondersteuning op basis van pakketten van het systeem, of een AdapterListControl-routine als deze gebruikmaakt van de spreidings- of verzamelondersteuning van het systeem.

Afhankelijk van het ontwerp van het stuurprogramma kan het overdrachts- en apparaatbeheerbewerkingen op een fysiek apparaat synchroniseren met een controllerobject en een ControllerControl-routine leveren.

Zie Adapterobjecten en DMA - en controllerobjecten voor meer informatie.

I/O-beheeraanvragen verwerken in StartIo-routines

Over het algemeen worden alleen een subset van I/O-beheeraanvragen van het apparaat doorgegeven vanuit de DispatchDeviceControl - of DispatchInternalDeviceControl-routine voor verdere verwerking door de StartIo-routine van het stuurprogramma. De StartIo-routine van het stuurprogramma hoeft alleen geldige aanvragen voor apparaatbeheer af te handelen waarvoor wijzigingen in de apparaatstatus zijn vereist of vluchtige informatie over de huidige apparaatstatus te retourneren.

Elk nieuw stuurprogramma moet dezelfde set openbare I/O-besturingscodes ondersteunen als alle andere stuurprogramma's voor hetzelfde type apparaat. Het systeem definieert openbare, apparaattypespecifieke I/O-besturingscodes voor IRP_MJ_DEVICE_CONTROL aanvragen als gebufferde aanvragen.

Daarom maken fysieke apparaatstuurprogramma's gegevensoverdrachten naar of van een systeemruimtebuffer die elk stuurprogramma vindt in de IRP bij Irp-AssociatedIrp.SystemBuffer> voor aanvragen voor apparaatbeheer. Zelfs stuurprogramma's die hun apparaatobjecten instellen voor directe I/O gebruiken gebufferde I/O om te voldoen aan aanvragen voor apparaatbeheer met openbare I/O-besturingscodes.

De definitie van elke I/O-besturingscode bepaalt of de gegevens die voor die aanvraag worden overgedragen, worden gebufferd. Eventuele privé gedefinieerde I/O-besturingscodes voor stuurprogrammaspecifieke IRP_MJ_INTERNAL_DEVICE_CONTROL aanvragen tussen gekoppelde stuurprogramma's kunnen een code definiëren met een methode die is gebufferd, methode direct of geen van beide methoden. In het algemeen moet elke privé gedefinieerde I/O-besturingscode worden gedefinieerd zonder methode als een hecht gekoppeld stuurprogramma op hoger niveau een buffer voor dat verzoek moet toewijzen.

Het apparaat programmeren voor I/O-bewerkingen

Meestal moet de StartIo-routine in een apparaatstuurprogramma op het laagste niveau de toegang synchroniseren tot elk geheugen of apparaat registreert dat het deelt met de ISR van het stuurprogramma met behulp van KeSynchronizeExecution om een door het stuurprogramma geleverde SynchCritSection-routine aan te roepen. De StartIo-routine van het stuurprogramma maakt gebruik van de SynchCritSection-routine om het fysieke apparaat voor I/O bij DIRQL daadwerkelijk te programmeren. Voor meer informatie, zie Kritieke secties gebruiken.

Voordat u KeSynchronizeExecution aanroept, moet de StartIo-routine een voorverwerking uitvoeren die nodig is voor de aanvraag. Voorverwerking kan bestaan uit het berekenen van een eerste bereik voor gedeeltelijke overdracht en het opslaan van statusinformatie over de oorspronkelijke aanvraag voor andere stuurprogrammaroutines.

Als een apparaatstuurprogramma DMA gebruikt, roept de Bijbehorende StartIo-routine meestal AllocateAdapterChannel aan met een door het stuurprogramma geleverde AdapterControl-routine . In deze omstandigheden stelt de StartIo-routine de verantwoordelijkheid voor het programmeren van het fysieke apparaat uit naar de AdapterControl-routine . Het kan op zijn beurt KeSynchronizeExecution aanroepen, zodat een door de stuurprogramma geleverde routine genaamd SynchCritSection het apparaat kan programmeren voor een DMA-overdracht.