Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Os dados STORAGE_ADAPTER_DESCRIPTOR retornados à rotina GetDescriptor indicam os recursos de transferência de um determinado HBA para o driver de classe. Em particular, esses dados indicam o MaximumTransferLength em bytes e o MaximumPhysicalPages: ou seja, quantas páginas não contíguas o HBA pode gerenciar na memória física que suporta um buffer do sistema (ou seja, a extensão de seu suporte de dispersão/coleta).
A maioria dos drivers de classe armazena um ponteiro para esses dados de configuração na extensão do dispositivo de cada objeto de dispositivo, uma vez que os drivers de classe de armazenamento são responsáveis por repartir todas as solicitações de transferência que excedem a capacidade do HBA de transferir dados. Em outras palavras, a rotina DispatchReadWrite de um driver de classe deve determinar se cada IRP solicita uma transferência maior do que o HBA pode lidar em uma única operação de transferência.
Por exemplo, essa rotina DispatchReadWrite pode ter um código semelhante ao seguinte:
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;
}
: :
O driver de classe não pode determinar quantas quebras físicas o buffer terá após o mapeamento, por isso deve assumir que cada página na transferência é descontígua e comparar o número de páginas com o limite de quebras físicas permitido.
Observe que a rotina DispatchReadWrite desse driver chama IoMarkIrpPending e retorna STATUS_PENDING imediatamente após uma chamada para sua rotina SplitTransferRequest com o IRP original.
Para executar a solicitação de transferência original, a rotina SplitTransferRequest do driver cria um ou mais IRPs para lidar com subbuffers dimensionados para atender aos recursos do HBA. Para cada um desses IRPs, a rotina SplitTransferRequest:
Configura um SRB, geralmente chamando uma rotina interna BuildRequest (consulte a Rotina BuildRequest do Driver de Classe de Armazenamento)
Copia o endereço MDL do IRP original para o novo IRP
Define o DataBuffer no SRB como um deslocamento em bytes no MDL para esta parte da transferência
Configura sua rotina IoCompletion antes de enviar o IRP para o driver de porta com IoCallDriver
Para rastrear cada parte da transferência, SplitTransferRequest registra uma rotina IoCompletion para cada IRP alocado pelo driver que envia para o próximo driver inferior. A rotina IoCompletion mantém uma contagem de solicitações de transferência parcial concluídas no IRP original, usando InterlockedIncrement e InterlockedDecrement para garantir que a contagem seja precisa.
Essa rotina IoCompletion deve liberar quaisquer IRPs e/ou SRBs que o driver tenha alocado e deve completar o IRP original quando todos os dados solicitados tiverem sido transferidos ou quando o driver de classe tiver esgotado as tentativas de repetir o IRP e precisar falhá-lo devido a erros de transferência de dispositivo.