win-pvdrivers

view xenvbd_filter/xenvbd_filter.c @ 1099:27bd2a5a4704

License change from GPL to BSD
author James Harper <james.harper@bendigoit.com.au>
date Thu Mar 13 13:38:31 2014 +1100 (2014-03-13)
parents 1b80cc14ee6d
children
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
4 Copyright (c) 2014, James Harper
5 All rights reserved.
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9 * Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 * Neither the name of James Harper nor the
15 names of its contributors may be used to endorse or promote products
16 derived from this software without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 DISCLAIMED. IN NO EVENT SHALL JAMES HARPER BE LIABLE FOR ANY
22 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
30 #include "xenvbd_filter.h"
31 #include "ntddscsi.h"
32 #include "srb.h"
34 DRIVER_INITIALIZE DriverEntry;
36 static EVT_WDF_DRIVER_UNLOAD XenVbd_EvtDriverUnload;
37 static EVT_WDF_DRIVER_DEVICE_ADD XenVbd_EvtDeviceAdd;
38 static EVT_WDF_REQUEST_COMPLETION_ROUTINE XenVbd_SendEventComplete;
39 static EVT_WDF_DEVICE_D0_ENTRY XenVbd_EvtDeviceD0Entry;
40 static EVT_WDF_DEVICE_D0_EXIT XenVbd_EvtDeviceD0Exit;
41 static EVT_WDFDEVICE_WDM_IRP_PREPROCESS XenVbd_EvtDeviceWdmIrpPreprocess_START_DEVICE;
42 static EVT_WDFDEVICE_WDM_IRP_PREPROCESS XenVbd_EvtDeviceWdmIrpPreprocess_SET_POWER;
43 static EVT_WDF_DPC XenVbd_EvtDpcEvent;
44 static IO_COMPLETION_ROUTINE XenVbd_IoCompletion_START_DEVICE;
46 static VOID XenVbd_DeviceCallback(PVOID context, ULONG callback_type, PVOID value);
47 static VOID XenVbd_HandleEventDIRQL(PVOID context);
48 static VOID XenVbd_StopRing(PXENVBD_DEVICE_DATA xvdd, BOOLEAN suspend);
49 static VOID XenVbd_StartRing(PXENVBD_DEVICE_DATA xvdd, BOOLEAN suspend);
51 #include "../xenvbd_common/common_xen.h"
53 static VOID XenVbd_SendEvent(WDFDEVICE device);
55 static VOID
56 XenVbd_StopRing(PXENVBD_DEVICE_DATA xvdd, BOOLEAN suspend) {
57 PXENVBD_FILTER_DATA xvfd = (PXENVBD_FILTER_DATA)xvdd->xvfd;
58 NTSTATUS status;
59 WDFREQUEST request;
60 WDF_REQUEST_SEND_OPTIONS send_options;
61 IO_STACK_LOCATION stack;
62 SCSI_REQUEST_BLOCK srb;
63 SRB_IO_CONTROL sic;
65 FUNCTION_ENTER();
67 /* send a 'stop' down if we are suspending */
68 if (suspend) {
69 status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request);
70 FUNCTION_MSG("WdfRequestCreate = %08x\n", status);
72 RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION));
73 stack.MajorFunction = IRP_MJ_SCSI;
74 stack.MinorFunction = IRP_MN_SCSI_CLASS;
75 stack.Parameters.Scsi.Srb = &srb;
77 RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE);
78 srb.SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE;
79 srb.Length = SCSI_REQUEST_BLOCK_SIZE;
80 srb.PathId = 0;
81 srb.TargetId = 0;
82 srb.Lun = 0;
83 srb.OriginalRequest = WdfRequestWdmGetIrp(request);
84 srb.Function = SRB_FUNCTION_IO_CONTROL;
85 srb.DataBuffer = &sic;
87 RtlZeroMemory(&sic, sizeof(SRB_IO_CONTROL));
88 sic.HeaderLength = sizeof(SRB_IO_CONTROL);
89 memcpy(sic.Signature, XENVBD_CONTROL_SIG, 8);
90 sic.Timeout = 60;
91 sic.ControlCode = XENVBD_CONTROL_STOP;
93 WdfRequestWdmFormatUsingStackLocation(request, &stack);
95 WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS);
96 if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) {
97 FUNCTION_MSG("Request was _NOT_ sent\n");
98 }
99 #if DBG
100 status = WdfRequestGetStatus(request);
101 FUNCTION_MSG("Request Status = %08x\n", status);
102 FUNCTION_MSG("SRB Status = %08x\n", srb.SrbStatus);
103 #endif
105 WdfObjectDelete(request);
106 }
108 status = XnWriteInt32(xvdd->handle, XN_BASE_FRONTEND, "state", XenbusStateClosing);
110 FUNCTION_EXIT();
111 }
113 static VOID
114 XenVbd_StartRing(PXENVBD_DEVICE_DATA xvdd, BOOLEAN suspend) {
115 PXENVBD_FILTER_DATA xvfd = (PXENVBD_FILTER_DATA)xvdd->xvfd;
116 NTSTATUS status;
117 WDFREQUEST request;
118 WDF_REQUEST_SEND_OPTIONS send_options;
119 IO_STACK_LOCATION stack;
120 SCSI_REQUEST_BLOCK srb;
121 SRB_IO_CONTROL sic;
123 FUNCTION_ENTER();
125 /* send a 'start' down if we are resuming from a suspend */
126 if (suspend) {
127 status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request);
128 FUNCTION_MSG("WdfRequestCreate = %08x\n", status);
130 RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION));
131 stack.MajorFunction = IRP_MJ_SCSI;
132 stack.Parameters.Scsi.Srb = &srb;
134 RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE);
135 srb.SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE;
136 srb.Length = SCSI_REQUEST_BLOCK_SIZE;
137 srb.PathId = 0;
138 srb.TargetId = 0;
139 srb.Lun = 0;
140 srb.OriginalRequest = WdfRequestWdmGetIrp(request);
141 srb.Function = SRB_FUNCTION_IO_CONTROL;
142 srb.DataBuffer = &sic;
144 RtlZeroMemory(&sic, sizeof(SRB_IO_CONTROL));
145 sic.HeaderLength = sizeof(SRB_IO_CONTROL);
146 memcpy(sic.Signature, XENVBD_CONTROL_SIG, 8);
147 sic.Timeout = 60;
148 sic.ControlCode = XENVBD_CONTROL_START;
150 WdfRequestWdmFormatUsingStackLocation(request, &stack);
152 WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, WDF_REQUEST_SEND_OPTION_SYNCHRONOUS);
153 if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) {
154 FUNCTION_MSG("Request was _NOT_ sent\n");
155 }
156 #if DBG
157 status = WdfRequestGetStatus(request);
158 FUNCTION_MSG("Request Status = %08x\n", status);
159 FUNCTION_MSG("SRB Status = %08x\n", srb.SrbStatus);
160 #endif
162 WdfObjectDelete(request);
163 }
165 FUNCTION_EXIT();
166 }
168 static VOID
169 XenVbd_SendEventComplete(WDFREQUEST request, WDFIOTARGET target, PWDF_REQUEST_COMPLETION_PARAMS params, WDFCONTEXT context) {
170 WDFDEVICE device = WdfIoTargetGetDevice(target);
171 PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
172 NTSTATUS status;
173 PSCSI_REQUEST_BLOCK srb = context;
174 LARGE_INTEGER systemtime;
175 ULONGLONG elapsed;
177 UNREFERENCED_PARAMETER(params);
178 UNREFERENCED_PARAMETER(context);
180 status = WdfRequestGetStatus(request);
181 if (status != 0 || srb->SrbStatus != SRB_STATUS_SUCCESS) {
182 FUNCTION_MSG("Request Status = %08x, SRB Status = %08x\n", status, srb->SrbStatus);
183 }
184 KeQuerySystemTime(&systemtime);
185 elapsed = systemtime.QuadPart - ((PLARGE_INTEGER)((PUCHAR)context + sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL)))->QuadPart;
186 elapsed = elapsed / 10000; // now in ms
187 if (elapsed > 1000) {
188 FUNCTION_MSG("Event took %d ms\n", (ULONG)elapsed);
189 }
190 ExFreePoolWithTag(context, XENVBD_POOL_TAG);
191 WdfObjectDelete(request);
193 for (;;) {
194 if (InterlockedCompareExchange(&xvfd->event_state, 0, 1) == 1) {
195 /* no pending event, and we cleared outstanding flag */
196 break;
197 }
198 if (InterlockedCompareExchange(&xvfd->event_state, 1, 2) == 2) {
199 /* there was a pending event, and we set the flag back to outstanding */
200 //FUNCTION_MSG("sending pended event\n");
201 XenVbd_SendEvent(device);
202 break;
203 }
204 /* event_state changed while we were looking at it, go round again */
205 }
206 }
208 static VOID
209 XenVbd_SendEvent(WDFDEVICE device) {
210 PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
211 NTSTATUS status;
212 WDFREQUEST request;
213 WDF_REQUEST_SEND_OPTIONS send_options;
214 IO_STACK_LOCATION stack;
215 PUCHAR buf;
216 PSCSI_REQUEST_BLOCK srb;
217 PSRB_IO_CONTROL sic;
219 status = WdfRequestCreate(WDF_NO_OBJECT_ATTRIBUTES, xvfd->wdf_target, &request);
220 if (status != STATUS_SUCCESS) {
221 FUNCTION_MSG("WdfRequestCreate failed %08x\n", status);
222 /* this is bad - event will be dropped */
223 return;
224 }
226 buf = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL) + sizeof(LARGE_INTEGER), XENVBD_POOL_TAG);
227 RtlZeroMemory(buf, sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL));
228 srb = (PSCSI_REQUEST_BLOCK)(buf);
229 sic = (PSRB_IO_CONTROL)(buf + sizeof(SCSI_REQUEST_BLOCK));
231 srb->Length = sizeof(SCSI_REQUEST_BLOCK);
232 srb->SrbFlags = SRB_FLAGS_BYPASS_FROZEN_QUEUE | SRB_FLAGS_NO_QUEUE_FREEZE;
233 srb->PathId = 0;
234 srb->TargetId = 0;
235 srb->Lun = 0;
236 srb->OriginalRequest = WdfRequestWdmGetIrp(request);
237 srb->Function = SRB_FUNCTION_IO_CONTROL;
238 srb->DataBuffer = sic;
239 srb->DataTransferLength = sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL);
240 srb->TimeOutValue = (ULONG)-1;
242 sic->HeaderLength = sizeof(SRB_IO_CONTROL);
243 memcpy(sic->Signature, XENVBD_CONTROL_SIG, 8);
244 sic->Timeout = (ULONG)-1;
245 sic->ControlCode = XENVBD_CONTROL_EVENT;
247 KeQuerySystemTime((PLARGE_INTEGER)((PUCHAR)buf + sizeof(SCSI_REQUEST_BLOCK) + sizeof(SRB_IO_CONTROL)));
249 RtlZeroMemory(&stack, sizeof(IO_STACK_LOCATION));
250 stack.MajorFunction = IRP_MJ_SCSI;
251 stack.MinorFunction = IRP_MN_SCSI_CLASS;
252 stack.Parameters.Scsi.Srb = srb;
254 WdfRequestWdmFormatUsingStackLocation(request, &stack);
255 WdfRequestSetCompletionRoutine(request, XenVbd_SendEventComplete, buf);
257 WDF_REQUEST_SEND_OPTIONS_INIT(&send_options, 0); //WDF_REQUEST_SEND_OPTION_IGNORE_TARGET_STATE);
258 if (!WdfRequestSend(request, xvfd->wdf_target, &send_options)) {
259 FUNCTION_MSG("Error sending request\n");
260 }
261 }
263 static VOID
264 XenVbd_EvtDpcEvent(WDFDPC dpc) {
265 WDFDEVICE device = WdfDpcGetParentObject(dpc);
266 PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
268 for (;;) {
269 if (InterlockedCompareExchange(&xvfd->event_state, 1, 0) == 0) {
270 /* was no event outstanding, now there is */
271 XenVbd_SendEvent(device);
272 break;
273 }
274 if (InterlockedCompareExchange(&xvfd->event_state, 2, 1) != 0) {
275 //FUNCTION_MSG("event already in progress\n");
276 /* event was outstanding. either we set the need new event flag or it was already set */
277 break;
278 }
279 /* event_state changed while we were looking at it, go around again */
280 }
281 }
283 static VOID
284 XenVbd_HandleEventDIRQL(PVOID context) {
285 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)context;
286 PXENVBD_FILTER_DATA xvfd = (PXENVBD_FILTER_DATA)xvdd->xvfd;
287 WdfDpcEnqueue(xvfd->dpc);
288 }
290 static NTSTATUS
291 XenVbd_EvtDeviceD0Entry(WDFDEVICE device, WDF_POWER_DEVICE_STATE previous_state) {
292 PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
293 NTSTATUS status;
295 UNREFERENCED_PARAMETER(previous_state);
296 // if waking from hibernate then same as suspend... maybe?
297 FUNCTION_ENTER();
298 status = XenVbd_Connect(&xvfd->xvdd, FALSE);
299 FUNCTION_EXIT();
300 return status;
301 }
303 static NTSTATUS
304 XenVbd_EvtDeviceD0Exit(WDFDEVICE device, WDF_POWER_DEVICE_STATE target_state) {
305 PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
306 NTSTATUS status = STATUS_SUCCESS;
308 FUNCTION_ENTER();
309 switch (target_state) {
310 case WdfPowerDeviceD0:
311 FUNCTION_MSG("WdfPowerDeviceD1\n");
312 break;
313 case WdfPowerDeviceD1:
314 FUNCTION_MSG("WdfPowerDeviceD1\n");
315 break;
316 case WdfPowerDeviceD2:
317 FUNCTION_MSG("WdfPowerDeviceD2\n");
318 break;
319 case WdfPowerDeviceD3:
320 FUNCTION_MSG("WdfPowerDeviceD3\n");
321 if (xvfd->hibernate_flag) {
322 FUNCTION_MSG("(but really WdfPowerDevicePrepareForHibernation)\n");
323 target_state = WdfPowerDevicePrepareForHibernation;
324 }
325 break;
326 case WdfPowerDeviceD3Final:
327 FUNCTION_MSG("WdfPowerDeviceD3Final\n");
328 break;
329 case WdfPowerDevicePrepareForHibernation:
330 FUNCTION_MSG("WdfPowerDevicePrepareForHibernation\n");
331 break;
332 default:
333 FUNCTION_MSG("Unknown WdfPowerDevice state %d\n", target_state);
334 break;
335 }
336 if (target_state != WdfPowerDevicePrepareForHibernation) {
337 status = XenVbd_Disconnect(&xvfd->xvdd, FALSE);
338 }
339 FUNCTION_EXIT();
340 return status;
341 }
343 static NTSTATUS
344 XenVbd_IoCompletion_START_DEVICE(PDEVICE_OBJECT device, PIRP irp, PVOID context) {
345 UNREFERENCED_PARAMETER(device);
346 UNREFERENCED_PARAMETER(irp);
347 FUNCTION_ENTER();
348 ExFreePoolWithTag(context, XENVBD_POOL_TAG);
349 FUNCTION_EXIT();
350 return STATUS_SUCCESS;
351 }
353 static NTSTATUS
354 XenVbd_EvtDeviceWdmIrpPreprocess_START_DEVICE(WDFDEVICE device, PIRP irp) {
355 PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
356 PIO_STACK_LOCATION stack;
357 PCM_RESOURCE_LIST crl;
358 PCM_FULL_RESOURCE_DESCRIPTOR cfrd;
359 PCM_PARTIAL_RESOURCE_LIST cprl;
360 PCM_PARTIAL_RESOURCE_DESCRIPTOR prd;
362 FUNCTION_ENTER();
364 /*
365 Pass down the xvdd area as a memory resource. This gives xenvbd the data in a known place
366 and also satisifies the scsiport requirement for a memory resource
367 */
368 IoCopyCurrentIrpStackLocationToNext(irp);
369 stack = IoGetNextIrpStackLocation(irp);
371 crl = ExAllocatePoolWithTag(NonPagedPool,
372 FIELD_OFFSET(CM_RESOURCE_LIST, List) +
373 FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) +
374 FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
375 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * 1, XENVBD_POOL_TAG);
376 if (!crl) {
377 // TODO: Fail this correctly
378 }
379 crl->Count = 1;
380 cfrd = &crl->List[0];
381 cfrd->InterfaceType = PNPBus;
382 cfrd->BusNumber = 0;
383 cprl = &cfrd->PartialResourceList;
384 cprl->Version = 1;
385 cprl->Revision = 1;
386 cprl->Count = 1;
387 prd = &cprl->PartialDescriptors[0];
388 prd->Type = CmResourceTypeMemory;
389 prd->ShareDisposition = CmResourceShareShared;
390 prd->Flags = CM_RESOURCE_MEMORY_READ_WRITE | CM_RESOURCE_MEMORY_CACHEABLE;
391 prd->u.Memory.Start.QuadPart = (ULONG_PTR)&xvfd->xvdd;
392 prd->u.Memory.Length = sizeof(XENVBD_DEVICE_DATA);
393 stack->Parameters.StartDevice.AllocatedResources = crl;
394 stack->Parameters.StartDevice.AllocatedResourcesTranslated = crl;
396 IoSetCompletionRoutine(irp, XenVbd_IoCompletion_START_DEVICE, crl, TRUE, TRUE, TRUE);
398 FUNCTION_EXIT();
400 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
401 }
403 /* scsiport doesn't process SET_POWER correctly so we have to fudge detection of hibernate */
404 static NTSTATUS
405 XenVbd_EvtDeviceWdmIrpPreprocess_SET_POWER(WDFDEVICE device, PIRP irp) {
406 PXENVBD_FILTER_DATA xvfd = GetXvfd(device);
407 PIO_STACK_LOCATION stack;
409 FUNCTION_ENTER();
410 stack = IoGetCurrentIrpStackLocation(irp);
411 if (stack->Parameters.Power.Type == DevicePowerState && stack->Parameters.Power.State.DeviceState == PowerDeviceD3 && stack->Parameters.Power.ShutdownType == PowerActionHibernate) {
412 FUNCTION_MSG("Going to hibernate\n");
413 xvfd->hibernate_flag = TRUE;
414 } else {
415 xvfd->hibernate_flag = FALSE;
416 }
417 IoSkipCurrentIrpStackLocation(irp);
418 FUNCTION_EXIT();
419 return WdfDeviceWdmDispatchPreprocessedIrp(device, irp);
420 }
422 static NTSTATUS
423 XenVbd_EvtDeviceAdd(WDFDRIVER driver, PWDFDEVICE_INIT device_init) {
424 PXENVBD_FILTER_DATA xvfd;
425 NTSTATUS status;
426 WDFDEVICE device;
427 WDF_OBJECT_ATTRIBUTES device_attributes;
428 WDF_PNPPOWER_EVENT_CALLBACKS pnp_power_callbacks;
429 WDF_DPC_CONFIG dpc_config;
430 WDF_OBJECT_ATTRIBUTES oa;
431 UCHAR pnp_minor_functions[] = { IRP_MN_START_DEVICE };
432 UCHAR power_minor_functions[] = { IRP_MN_SET_POWER };
434 UNREFERENCED_PARAMETER(driver);
436 FUNCTION_ENTER();
438 WdfDeviceInitSetDeviceType(device_init, FILE_DEVICE_UNKNOWN);
440 WdfFdoInitSetFilter(device_init);
442 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnp_power_callbacks);
443 pnp_power_callbacks.EvtDeviceD0Entry = XenVbd_EvtDeviceD0Entry;
444 pnp_power_callbacks.EvtDeviceD0Exit = XenVbd_EvtDeviceD0Exit;
445 WdfDeviceInitSetPnpPowerEventCallbacks(device_init, &pnp_power_callbacks);
447 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenVbd_EvtDeviceWdmIrpPreprocess_START_DEVICE,
448 IRP_MJ_PNP, pnp_minor_functions, ARRAY_SIZE(pnp_minor_functions));
449 if (!NT_SUCCESS(status)) {
450 return status;
451 }
453 status = WdfDeviceInitAssignWdmIrpPreprocessCallback(device_init, XenVbd_EvtDeviceWdmIrpPreprocess_SET_POWER,
454 IRP_MJ_POWER, power_minor_functions, ARRAY_SIZE(power_minor_functions));
455 if (!NT_SUCCESS(status)) {
456 return status;
457 }
459 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&device_attributes, XENVBD_FILTER_DATA);
460 status = WdfDeviceCreate(&device_init, &device_attributes, &device);
461 if (!NT_SUCCESS(status)) {
462 FUNCTION_MSG("Error creating device 0x%x\n", status);
463 return status;
464 }
466 xvfd = GetXvfd(device);
467 xvfd->wdf_device = device;
468 xvfd->wdf_target = WdfDeviceGetIoTarget(device);
469 xvfd->xvdd.xvfd = xvfd;
470 xvfd->xvdd.pdo = WdfDeviceWdmGetPhysicalDevice(device);
471 xvfd->xvdd.grant_tag = XENVBD_POOL_TAG;
473 KeInitializeEvent(&xvfd->xvdd.backend_event, SynchronizationEvent, FALSE);
475 WDF_DPC_CONFIG_INIT(&dpc_config, XenVbd_EvtDpcEvent);
476 WDF_OBJECT_ATTRIBUTES_INIT(&oa);
477 oa.ParentObject = device;
478 status = WdfDpcCreate(&dpc_config, &oa, &xvfd->dpc);
480 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFilePaging, TRUE);
481 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileHibernation, TRUE);
482 WdfDeviceSetSpecialFileSupport(device, WdfSpecialFileDump, TRUE);
484 FUNCTION_EXIT();
485 return status;
486 }
488 NTSTATUS
489 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
490 NTSTATUS status;
491 WDF_DRIVER_CONFIG config;
492 WDFDRIVER driver;
494 UNREFERENCED_PARAMETER(RegistryPath);
496 FUNCTION_ENTER();
498 WDF_DRIVER_CONFIG_INIT(&config, XenVbd_EvtDeviceAdd);
499 status = WdfDriverCreate(DriverObject, RegistryPath, WDF_NO_OBJECT_ATTRIBUTES, &config, &driver);
500 if (!NT_SUCCESS(status)) {
501 FUNCTION_MSG("WdfDriverCreate failed with status 0x%x\n", status);
502 FUNCTION_EXIT();
503 return status;
504 }
505 FUNCTION_EXIT();
506 return status;
507 }