Files
yttrium-virtio-gpu/Balloon/sys/queue.c
T
2024-12-02 10:58:39 +02:00

165 lines
4.9 KiB
C

#include "precomp.h"
#if defined(EVENT_TRACING)
#include "queue.tmh"
#endif
#ifdef USE_BALLOON_SERVICE
EVT_WDF_IO_QUEUE_IO_WRITE BalloonIoWrite;
EVT_WDF_IO_QUEUE_IO_STOP BalloonIoStop;
EVT_WDF_REQUEST_CANCEL BalloonEvtRequestCancel;
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, BalloonQueueInitialize)
#endif
NTSTATUS
BalloonQueueInitialize(IN WDFDEVICE Device)
{
NTSTATUS status = STATUS_SUCCESS;
WDF_IO_QUEUE_CONFIG queueConfig = {0};
PAGED_CODE();
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig, WdfIoQueueDispatchSequential);
queueConfig.EvtIoWrite = BalloonIoWrite;
queueConfig.EvtIoStop = BalloonIoStop;
status = WdfIoQueueCreate(Device, &queueConfig, WDF_NO_OBJECT_ATTRIBUTES, WDF_NO_HANDLE);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfIoQueueCreate failed 0x%08x\n", status);
}
return status;
}
VOID BalloonIoWrite(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length)
{
PVOID buffer = NULL;
size_t buffSize;
PDEVICE_CONTEXT devCtx = NULL;
NTSTATUS status = STATUS_SUCCESS;
TraceEvents(TRACE_LEVEL_INFORMATION,
DBG_HW_ACCESS,
"BalloonIoWrite Called! Queue 0x%p, Request 0x%p Length %d\n",
Queue,
Request,
Length);
devCtx = GetDeviceContext(WdfIoQueueGetDevice(Queue));
if (Length < sizeof(BALLOON_STAT))
{
TraceEvents(TRACE_LEVEL_INFORMATION,
DBG_HW_ACCESS,
"BalloonIoWrite Buffer Length too small %d, expected is %d\n",
Length,
sizeof(BALLOON_STAT));
WdfRequestComplete(Request, STATUS_BUFFER_TOO_SMALL);
return;
}
status = WdfRequestRetrieveInputBuffer(Request, sizeof(BALLOON_STAT), &buffer, &buffSize);
if (!NT_SUCCESS(status) || (buffer == NULL))
{
TraceEvents(TRACE_LEVEL_INFORMATION,
DBG_HW_ACCESS,
"BalloonIoWrite Could not get request memory buffer 0x%08x\n",
status);
WdfRequestCompleteWithInformation(Request, status, 0L);
return;
}
if (devCtx->HandleWriteRequest)
{
Length = min(buffSize, sizeof(BALLOON_STAT) * VIRTIO_BALLOON_S_NR);
#if 0
{
size_t i;
PBALLOON_STAT stat = (PBALLOON_STAT)buffer;
for (i = 0; i < Length / sizeof(BALLOON_STAT); ++i)
{
TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS,
"tag = %d, val = %08I64X\n\n", stat[i].tag, stat[i].val);
}
}
#endif
RtlCopyMemory(devCtx->MemStats, buffer, Length);
WdfRequestCompleteWithInformation(Request, status, Length);
TraceEvents(TRACE_LEVEL_INFORMATION,
DBG_HW_ACCESS,
"WdfRequestCompleteWithInformation Called! Queue 0x%p, Request 0x%p Length %d Status 0x%08x\n",
Queue,
Request,
Length,
status);
devCtx->HandleWriteRequest = FALSE;
BalloonMemStats(WdfIoQueueGetDevice(Queue));
}
else
{
status = WdfRequestMarkCancelableEx(Request, BalloonEvtRequestCancel);
if (!NT_SUCCESS(status))
{
TraceEvents(TRACE_LEVEL_ERROR, DBG_READ, "WdfRequestMarkCancelableEx failed: 0x%08x\n", status);
WdfRequestCompleteWithInformation(Request, status, 0L);
return;
}
devCtx->PendingWriteRequest = Request;
}
}
VOID BalloonIoStop(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN ULONG ActionFlags)
{
UNREFERENCED_PARAMETER(Queue);
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "--> %!FUNC! Request: %p", Request);
if (ActionFlags & WdfRequestStopRequestCancelable)
{
NTSTATUS status = WdfRequestUnmarkCancelable(Request);
__analysis_assume(status != STATUS_NOT_SUPPORTED);
if (status == STATUS_CANCELLED)
{
WdfRequestStopAcknowledge(Request, FALSE);
goto end_io_stop;
}
}
if (ActionFlags & WdfRequestStopActionSuspend)
{
WdfRequestStopAcknowledge(Request, TRUE);
}
else if (ActionFlags & WdfRequestStopActionPurge)
{
WdfRequestComplete(Request, STATUS_CANCELLED);
}
else
{
WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
}
end_io_stop:
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- %!FUNC!");
}
VOID BalloonEvtRequestCancel(IN WDFREQUEST Request)
{
PDEVICE_CONTEXT devCtx = GetDeviceContext(WdfIoQueueGetDevice(WdfRequestGetIoQueue(Request)));
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "--> BalloonEvtRequestCancel Cancelled Request: %p\n", Request);
NT_ASSERT(devCtx->PendingWriteRequest == Request);
devCtx->PendingWriteRequest = NULL;
WdfRequestComplete(Request, STATUS_CANCELLED);
TraceEvents(TRACE_LEVEL_VERBOSE, DBG_READ, "<-- BalloonEvtRequestCancel\n");
}
#endif // USE_BALLOON_SERVICE