Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
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ãotiguos o HBA pode gerenciar na memória física que faz backup de um buffer do sistema (ou seja, a extensão de seu suporte de dispersão/coleta).
A maioria dos drivers de classe de armazenamento armazena um ponteiro para esses dados de configuração na extensão do dispositivo de cada objeto de dispositivo, pois são responsáveis por dividir 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 manipular em uma única operação de transferência.
Por exemplo, tal 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 dizer quantas quebras físicas o buffer terá depois de mapeado, portanto, ele deve assumir que cada página na transferência é discontigua e comparar o número de páginas com o número de quebras físicas permitidas.
Observe que a rotina DispatchReadWrite de um driver chama IoMarkIrpPending e retorna STATUS_PENDING imediatamente após uma chamada para sua rotina SplitTransferRequest com o IRP original.
Para realizar a solicitação de transferência original, a rotina SplitTransferRequest do driver cria um ou mais IRPs para lidar com subbuffers que são dimensionados para atender aos recursos do HBA. Para cada tal IRP, a rotina SplitTransferRequest:
Configura um SRB, geralmente chamando uma rotina interna BuildRequest (consulte a rotina do Driver de Classe de Armazenamento BuildRequest)
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 de IoCompletion antes de enviar o IRP para o driver de porta com IoCallDriver
Para acompanhar cada parte da transferência, SplitTransferRequest registra uma rotina IoCompletion para cada IRP alocado pelo driver que envia para o driver inferior seguinte. 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 de IoCompletion deve liberar todos os IRPs e/ou SRBs alocados pelo driver e deve concluir o IRP original quando todos os dados solicitados tiverem sido transferidos ou quando o driver de classe tiver esgotado as novas tentativas do IRP e tiver que falhar devido a erros de transferência do dispositivo.