Поделиться через


IOCTL_SRIOV_NOTIFICATION IOCTL (pcivirt.h)

Запрос указывает, что стек виртуализации хочет получать уведомления при возникновении одного из событий, перечисленных в SRIOV_PF_EVENT .

Основной код

IRP_MJ_DEVICE_CONTROL

Выходной буфер

Буфер, содержащий значение типа SRIOV_PF_EVENT, которое заполняется драйвером физической функции (PF) при выполнении запроса.

Длина выходного буфера

Указатель на переменную , которой назначается количество записанных байтов в выходной буфер после завершения запроса.

Блок состояния

Irp->IoStatus.Status имеет значение STATUS_SUCCESS, если запрос выполнен успешно. В противном случае — состояние соответствующего условия ошибки в виде кода NTSTATUS .

Комментарии

Этот запрос IOCTL отправляется стеком виртуализации драйверу физических функций PCI Express SR-IOV, который предоставляет GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE.

Драйвер PF удерживает запрос IOCTL_SRIOV_NOTIFICATION в очереди до тех пор, пока отправитель не отменит запрос или устройство не испытает одно из событий, перечисленных в SRIOV_PF_EVENT. Затем драйвер завершает ожидающий запрос.

Если драйвер PF получает этот запрос IOCTL во время обработки события Plug and Play, для которого драйвер еще не завершил уведомление, он должен немедленно завершить запрос IOCTL, указав сведения о событии в выходном буфере. В противном случае драйвер должен поместить запрос в очередь до тех пор, пока он не будет отменен или не произойдет событие Plug and Play, требующее уведомления.

Стек виртуализации может отправить запрос IOCTL_SRIOV_NOTIFICATION сразу после завершения предыдущего запроса IOCTL_SRIOV_NOTIFICATION . Драйвер PF должен отслеживать тот факт, что уведомление о событии было доставлено, и не должен дважды выполнять два запроса IOCTL для одного и того же события.

Он заполняется драйвером PF до тех пор, пока он не будет отменен отправителем или пока драйвер PF не испытает одно из нескольких событий PnP, после чего оно будет завершено.


case IOCTL_SRIOV_NOTIFICATION:
        TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL,
            "IOCTL_SRIOV_NOTIFICATION:\n");

        status = WdfRequestForwardToIoQueue(Request,
                                            fdoContext->NotificationQueue);
        if (!NT_SUCCESS(status))
        {
            // not able to push it into manual queue, too bad.
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                        "WdfRequestForwardToIoQueue failed status=%!STATUS!\n",
                        status);
            break;
        }

        //
        // Pnp might arrived before SRIOV_NOTIFICATION. Serve the new
        // outstanding pnp if there is one.
        //
        CheckPendingNotifications(fdoContext);
        status = STATUS_PENDING;
        break;



VOID
CheckPendingNotifications(
    __in PDEVICE_CONTEXT DeviceContext
    )
/*++

Routine Description:

    This routine checks if there is a pending event and a pending request
    for notification and if so completes the request.

Arguments:

    DeviceContext - Pointer to the device context

Return Value:

    None.

--*/
{
    PSRIOV_PF_EVENT notification;
    WDFQUEUE        queue;
    WDFREQUEST      request;
    NTSTATUS        status;

    PAGED_CODE();

    WdfWaitLockAcquire(DeviceContext->PnpStateLock, NULL);

    queue = DeviceContext->NotificationQueue;
    if (DeviceContext->PnpEventNew
        && NT_SUCCESS(WdfIoQueueRetrieveNextRequest(queue, &request)))
    {
        NT_ASSERT(DeviceContext->PnpEventPending != FALSE);
        DeviceContext->PnpEventNew = FALSE;

        status = WdfRequestRetrieveOutputBuffer(request,
                                                sizeof(*notification),
                                                &notification,
                                                NULL);
        if (!NT_SUCCESS(status))
        {
            TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP,
                "WdfRequestRetrieveOutputBuffer[SRIOV_NOTIFICATION] fail: %!STATUS!", status);
            WdfRequestComplete(request, status);
        }
        else
        {
            TraceEvents(TRACE_LEVEL_VERBOSE, DBG_IOCTL, "Retrieved IoQueue request buffer (notification)\n");

            *notification = DeviceContext->PnpEventCode;
            WdfRequestCompleteWithInformation(request,
                                              STATUS_SUCCESS,
                                              sizeof(*notification));
        }
    }

    WdfWaitLockRelease(DeviceContext->PnpStateLock);

    return;
}

Требования

Требование Значение
Заголовок pcivirt.h
IRQL PASSIVE_LEVEL