Delen via


Opslagklassebestuurder's SplitTransferRequest Routine

De STORAGE_ADAPTER_DESCRIPTOR gegevens die worden geretourneerd naar de GetDescriptor-routine , geven de overdrachtsmogelijkheden van een bepaalde HBA aan het klassestuurprogramma aan. Deze gegevens geven in het bijzonder de MaximumTransferLength in bytes en de MaximumPhysicalPages aan: dat wil gezegd, hoeveel niet-aaneengesloten pagina's de HBA kan beheren in het fysieke geheugen dat een systeembuffer ondersteunt (dat wil gezegd de omvang van de spreidings-/verzamelondersteuning).

De meeste klassestuurprogramma's slaan een aanwijzer op naar deze configuratiegegevens in de apparaatextensie van elk apparaatobject, omdat opslagklassestuurprogramma's verantwoordelijk zijn voor het splitsen van alle overdrachtsaanvragen die de mogelijkheid van HBA overschrijden om gegevens over te dragen. Met andere woorden, de DispatchReadWrite-routine van een klassestuurprogramma moet bepalen of elke IRP een overdracht aanvraagt die meer is dan de HBA kan verwerken in één overdrachtsbewerking.

Een dergelijke DispatchReadWrite-routine kan bijvoorbeeld code bevatten die vergelijkbaar is met het volgende:

PSTORAGE_ADAPTER_DESCRIPTOR adapterDescriptor = 
    commonExtension->PartitionZeroExtension->AdapterDescriptor;
ULONG transferPages;
ULONG maximumTransferLength = 
    adapterDescriptor->MaximumTransferLength;
    :        : 
// 
// Calculate number of pages in this transfer 
// 
transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES( 
                    MmGetMdlVirtualAddress(Irp->MdlAddress), 
                        currentIrpStack->Parameters.Read.Length);
// 
// Check whether requested length is greater than the maximum number 
// of bytes that can be transferred in a single operation 
// 
if (currentIrpStack->Parameters.Read.Length > maximumTransferLength ||
        transferPages > adapterDescriptor->MaximumPhysicalPages) { 
    transferPages = adapterDescriptor->MaximumPhysicalPages - 1;
    if (maximumTransferLength > transferPages << PAGE_SHIFT) { 
        maximumTransferLength = transferPages << PAGE_SHIFT; 
    } 
    IoMarkIrpPending(Irp); 
    SplitTransferRequest(DeviceObject, 
                            Irp, 
                            maximumTransferLength); 
    return STATUS_PENDING; 
} 
    :        : 

Het class-stuurprogramma kan niet zien hoeveel fysieke onderbrekingen de buffer zal hebben zodra deze is gemapt, dus moet het ervan uitgaan dat elke pagina in de overdracht niet-contigue is en het aantal pagina's vergelijken met het aantal toegestane fysieke onderbrekingen.

Houd er rekening mee dat de DispatchReadWrite-routine van een dergelijk stuurprogramma IoMarkIrpPending aanroept en STATUS_PENDING retourneert direct na een aanroep naar de SplitTransferRequest-routine met de oorspronkelijke IRP.

Om de oorspronkelijke overdrachtsaanvraag uit te voeren, maakt de SplitTransferRequest-routine van het stuurprogramma een of meer IRP's om subbuffers af te handelen die passen bij de mogelijkheden van de HBA. Voor elk dergelijke IRP, de SplitTransferRequest routine:

  • Hiermee stelt u een SRB in, meestal door een interne BuildRequest-routine aan te roepen (zie BuildRequest Routine van Storage Class Driver)

  • Kopieert het MDL-adres van het oorspronkelijke IRP naar de nieuwe IRP

  • Hiermee stelt u de DataBuffer in de SRB in op een offset in bytes in de MDL voor dit deel van de overdracht

  • Hiermee stelt u de IoCompletion-routine in voordat u het IRP naar het poortstuurprogramma verzendt met IoCallDriver

Om elk deel van de overdracht bij te houden, registreert SplitTransferRequest een IoCompletion-routine voor elk door het stuurprogramma toegewezen IRP dat wordt verzonden naar het volgende lagere stuurprogramma. De IoCompletion-routine onderhoudt een telling van voltooide gedeeltelijke overdrachtsaanvragen in de oorspronkelijke IRP, met behulp van InterlockedIncrement en InterlockedDecrement om ervoor te zorgen dat het aantal nauwkeurig is.

Een dergelijke IoCompletion-routine moet alle IRP's en/of SRBS vrijmaken die het stuurprogramma heeft toegewezen en moet de oorspronkelijke IRP voltooien wanneer alle aangevraagde gegevens zijn overgedragen of wanneer het klassestuurprogramma de pogingen van het IRP heeft uitgeput en moet dit mislukken vanwege apparaatoverdrachtsfouten.