Condividi tramite


Avvio di un dispositivo in un driver di funzione

Un driver di funzione imposta una routine IoCompletion, passa una richiesta IRP_MN_START_DEVICE nello stack di dispositivi e posticipa le operazioni di avvio fino a quando tutti i driver inferiori non hanno terminato l'IRP. Vedere Postponing PnP IRP Processing Until Lower Drivers Finish per ottenere informazioni dettagliate su come utilizzare un evento del kernel e una routine IoCompletion per posticipare l'elaborazione dell'IRP.

Quando la routine di DispatchPnP riprende il controllo dopo che tutti i driver inferiori hanno completato l'IRP, il driver di funzione esegue le attività per avviare il dispositivo. Un driver di funzione avvia il dispositivo con una procedura simile alla seguente:

  1. Se un driver inferiore ha avuto esito negativo nell'IRP (IoCallDriver ha restituito un errore), non continuare a elaborare l'IRP. Eseguire le operazioni di pulizia necessarie e tornare dalla routine DispatchPnP (passare all'ultimo passaggio in questo elenco).

  2. Se i driver inferiori hanno elaborato correttamente l'IRP, avviare il dispositivo.

    I passaggi esatti per avviare un dispositivo variano da dispositivo a dispositivo. Tali passaggi possono includere il mapping dello spazio di I/O, l'inizializzazione dei registri hardware, l'impostazione del dispositivo nello stato di alimentazione D0 e la connessione dell'interrupt con IoConnectInterrupt. Se il driver riavvia un dispositivo dopo una richiesta di IRP_MN_STOP_DEVICE, il driver potrebbe avere lo stato del dispositivo da ripristinare.

    Il dispositivo deve essere acceso prima che i driver possano accedervi. Per ulteriori informazioni, vedere Accensione di un dispositivo.

    Se il dispositivo deve essere abilitato alla riattivazione, il proprietario dei criteri di alimentazione (in genere il driver di funzione) deve inviare un IRP di attesa/riattivazione dopo aver alimentato il dispositivo e prima di completare la richiesta di IRP_MN_START_DEVICE. Per informazioni dettagliate, vedere Invio di un IRP di attesa/riattivazione.

  3. Avviare gli IRP nella coda di attesa IRP.

    Deselezionare il flag HOLD_NEW_REQUESTS definito dal driver e avviare gli IRP nella coda di attesa dell'IRP. I driver devono eseguire questa operazione quando si avvia un dispositivo per la prima volta e quando si riavvia un dispositivo dopo un query-stop o uno stop IRP. Per ulteriori informazioni, vedere Gestire gli IRP in arrivo quando un dispositivo è in pausa.

  4. [Facoltativo] Abilitare le interfacce per il dispositivo chiamando IoSetDeviceInterfaceState.

    Abilitare le interfacce, se presenti, che il driver aveva registrato in precedenza nella sua routine AddDevice (o in un INF o da un altro componente come un co-installatore).

    In Windows 2000 e versioni successive di Windows, il gestore PnP non invia notifiche degli arrivi dell'interfaccia dispositivo fino al completamento dell'IRP IRP_MN_START_DEVICE, a indicare che tutti i driver per il dispositivo hanno completato le operazioni di avvio. Il gestore PnP fallisce anche qualsiasi richiesta di creazione che arriva prima che tutti i driver per il dispositivo completino l'IRP di avvio.

  5. Completare l'IRP.

    La routine IoCompletion del driver di funzione ha restituito STATUS_MORE_PROCESSING_REQUIRED, come descritto in Postponing PnP IRP Processing Until Lower Drivers Finish, quindi la routine DispatchPnP del driver di funzione deve chiamare IoCompleteRequest per riprendere l'elaborazione della richiesta di completamento I/O.

    Se le operazioni di avvio del driver di funzione hanno avuto esito positivo, il driver imposta Irp->IoStatus.Status su STATUS_SUCCESS, chiama IoCompleteRequest con un aumento di priorità di IO_NO_INCREMENT e restituisce STATUS_SUCCESS dalla routine DispatchPnP.

    Se il driver funzionale rileva un errore durante le operazioni di avvio del sistema, il driver imposta uno stato di errore nell'IRP, chiama IoCompleteRequest con IO_NO_INCREMENT e restituisce l'errore dalla routine DispatchPnP.

    Se un driver inferiore ha avuto esito negativo su IRP (IoCallDriver ha restituito un errore), il driver della funzione chiama IoCompleteRequest con IO_NO_INCREMENT e restituisce l'errore IoCallDriver dalla routine DispatchPnP. Il driver di funzione non imposta Irp->IoStatus.Status in questo caso perché lo stato è già stato impostato dal driver di livello inferiore che ha fallito l'IRP.

Quando un driver di funzione riceve una richiesta di IRP_MN_START_DEVICE, deve esaminare le strutture in IrpSp->Parameters.StartDevice.AllocateResources e IrpSp->Parameters.StartDevice.AllocateResourcesTranslated, che descrivono rispettivamente le risorse non elaborate e tradotte assegnate dal manager PnP al dispositivo. I driver devono salvare una copia di ogni elenco di risorse nell'estensione del dispositivo come supporto per il debug.

Gli elenchi delle risorse sono accoppiati in strutture CM_RESOURCE_LIST , in cui ogni elemento dell'elenco non elaborato corrisponde allo stesso elemento dell'elenco tradotto. Ad esempio, se AllocateResources.List[0] descrive un intervallo di porte I/O non elaborato, AllocateResourcesTranslated.List[0] descrive lo stesso intervallo dopo la conversione. Ogni risorsa tradotta include un indirizzo fisico e il tipo della risorsa.

Se a un driver viene assegnata una risorsa di memoria tradotta (CmResourceTypeMemory), deve chiamare MmMapIoSpace per eseguire il mapping dell'indirizzo fisico in un indirizzo virtuale tramite il quale può accedere ai registri dei dispositivi. Affinché un driver funzioni in modo indipendente dalla piattaforma, deve controllare ogni risorsa restituita, tradotta ed eseguirne il mapping, se necessario.

Un driver di funzione deve eseguire le operazioni seguenti in risposta a un IRP_MN_START_DEVICE per garantire l'accesso a tutte le risorse del dispositivo:

  1. Copiare IrpSp->Parameters.StartDevice.AllocateResources nell'estensione del dispositivo.

  2. Copiare IrpSp->Parameters.StartDevice.AllocateResourcesTranslated nell'estensione del dispositivo.

  3. In un ciclo esaminare ogni elemento descrittore in AllocateResourcesTranslated. Se il tipo di risorsa descrittore è CmResourceTypeMemory, chiamare MmMapIoSpace, fornendo l'indirizzo fisico e la lunghezza della risorsa tradotta.

Quando il driver riceve una richiesta di IRP_MN_STOP_DEVICE, IRP_MN_REMOVE_DEVICEo IRP_MN_SURPRISE_REMOVAL, deve rilasciare i mapping chiamando MmUnmapIoSpace in un ciclo simile. Il driver deve anche chiamare MmUnmapIoSpace se deve fallire la richiesta IRP_MN_START_DEVICE.

Per ulteriori informazioni, vedere Mappatura degli indirizzi Bus-Relative verso indirizzi virtuali.