Запуск устройства в драйвере функции

Драйвер-функция задает подпрограмму IoCompletion , передает IRP_MN_START_DEVICE запрос в стеке устройств и откладывает свои начальные операции до тех пор, пока все более низкие драйверы не завершат работу с IRP. Подробные сведения об использовании события ядра и процедуры IoCompletion для откладывания обработки IRP см. в разделе Перенос обработки IRP PnP до завершения более низких драйверов.

Когда ее подпрограмма DispatchPnP восстанавливает контроль после того, как все более низкие драйверы завершат работу с IRP, драйвер-функция выполняет свои задачи по запуску устройства. Драйвер функции запускает устройство с помощью следующей процедуры:

  1. Если драйвер более низкого уровня не выполнил IRP (IoCallDriver вернул ошибку), не продолжайте обработку IRP. Выполните необходимую очистку и вернитесь из подпрограммы DispatchPnP (перейдите к последнему шагу в этом списке).

  2. Если более низкие драйверы успешно обработали IRP, запустите устройство.

    Конкретные шаги для запуска устройства зависят от устройства. Такие действия могут включать сопоставление пространства ввода-вывода, инициализацию аппаратных регистров, настройку устройства в состоянии питания D0 и подключение прерывания с помощью IoConnectInterrupt. Если драйвер перезапускает устройство после запроса IRP_MN_STOP_DEVICE , драйвер может иметь состояние устройства для восстановления.

    Устройство должно быть включено, прежде чем какие-либо драйверы смогут получить к нему доступ. Дополнительные сведения см. в разделе Питание устройства .

    Если устройство должно быть включено для пробуждения, его владелец политики питания (обычно драйвер функции) должен отправить IRP ожидания/пробуждения после включения устройства и до завершения запроса IRP_MN_START_DEVICE . Дополнительные сведения см. в разделе Отправка IRP ожидания или пробуждения.

  3. Запустите IRP в очереди хранения IRP.

    Снимите флаг HOLD_NEW_REQUESTS, определенный драйвером, и запустите IRP в очереди хранения IRP. Драйверы должны делать это при первом запуске устройства и при перезапуске устройства после остановки запроса или остановки IRP. Дополнительные сведения см. в разделе Удержание входящих IRP при приостановке устройства .

  4. [Необязательно] Включите интерфейсы для устройства, вызвав IoSetDeviceInterfaceState.

    Включите интерфейсы , если таковые есть, которые драйвер ранее зарегистрировал в своей подпрограмме AddDevice (или в INF-файле или другом компоненте, например совместном установщике).

    В Windows 2000 и более поздних версиях Windows диспетчер PnP не отправляет уведомления о поступлении интерфейса устройства до завершения IRP_MN_START_DEVICE IRP, указывая, что все драйверы устройства завершили свои операции запуска. Диспетчер PnP также не выполняет любые запросы на создание, которые поступают до того, как все драйверы для устройства завершат запуск IRP.

  5. Завершите IRP.

    Подпрограмма IoCompletion драйвера функции вернула STATUS_MORE_PROCESSING_REQUIRED, как описано в разделе Отложение обработки IRP PnP до завершения более низких драйверов, поэтому подпрограмма DispatchPnP драйвера функции должна вызвать IoCompleteRequest , чтобы возобновить обработку завершения ввода-вывода.

    Если операции запуска драйвера функции были успешными, драйвер устанавливает значение Irp-IoStatus.Status> в STATUS_SUCCESS, вызывает IoCompleteRequest с повышением приоритета IO_NO_INCREMENT и возвращает STATUS_SUCCESS из своей подпрограммы DispatchPnP.

    Если драйвер-функция обнаруживает ошибку во время выполнения операций запуска, драйвер устанавливает состояние ошибки в IRP, вызывает IoCompleteRequest с IO_NO_INCREMENT и возвращает ошибку из своей подпрограммы DispatchPnP .

    Если драйвер более низкого уровня не выполнил IRP (IoCallDriver вернул ошибку), драйвер функции вызывает IoCompleteRequest с IO_NO_INCREMENT и возвращает ошибку IoCallDriver из подпрограммы DispatchPnP . Драйвер функции не задает Irp-IoStatus.Status> в этом случае, так как состояние уже задано драйвером нижнего уровня, не выполнившим IRP.

Когда драйвер функции получает запрос IRP_MN_START_DEVICE, он должен изучить структуры в IrpSp-Parameters.StartDevice.AllocatedResources> и IrpSp-Parameters.StartDevice.AllocatedResourcesTranslated>, которые описывают необработанные и переведенные ресурсы соответственно, назначенные диспетчером PnP устройству. Драйверы должны сохранять копию каждого списка ресурсов в расширении устройства в качестве средства отладки.

Списки ресурсов связаны CM_RESOURCE_LIST структурами, в которых каждый элемент необработанного списка соответствует одному и тому же элементу переведенного списка. Например, если AllocatedResources.List[0] описывает необработанный диапазон портов ввода-вывода, то AllocatedResourcesTranslated.List[0] описывает тот же диапазон после преобразования. Каждый переведенный ресурс содержит физический адрес и тип ресурса.

Если драйверу назначен преобразованный ресурс памяти (CmResourceTypeMemory), он должен вызвать MmMapIoSpace , чтобы сопоставить физический адрес с виртуальным адресом, по которому он может получить доступ к регистрам устройств. Чтобы драйвер работал независимо от платформы, он должен проверка каждый возвращенный, переведенный ресурс и сопоставить его, если это необходимо.

Драйвер-функция должен выполнить следующие действия в ответ на IRP_MN_START_DEVICE , чтобы обеспечить доступ ко всем ресурсам устройства:

  1. Скопируйте IrpSp-Parameters.StartDevice.AllocatedResources> в расширение устройства.

  2. Скопируйте IrpSp-Parameters.StartDevice.AllocatedResourcesTranslated> в расширение устройства.

  3. В цикле проверьте каждый элемент дескриптора в AllocatedResourcesTranslated. Если тип ресурса дескриптора — CmResourceTypeMemory, вызовите MmMapIoSpace, передав физический адрес и длину преобразованного ресурса.

Когда драйвер получает запрос IRP_MN_STOP_DEVICE, IRP_MN_REMOVE_DEVICE или IRP_MN_SURPRISE_REMOVAL , он должен освободить сопоставления, вызвав MmUnmapIoSpace в аналогичном цикле. Драйвер также должен вызвать MmUnmapIoSpace , если он должен завершить запрос IRP_MN_START_DEVICE .

Дополнительные сведения см. в разделе Сопоставление Bus-Relative адресов с виртуальными адресами .