win-pvdrivers

view xenvbd/xenvbd.c @ 17:ce8bd97c4136

xenvbd: cleanups

clean up warnings
simplify XenVbd_HotPlugHandler flow, add comments
eliminate literals in backendstatehandler
fix XenBusInterface.Printf for context parameter
author Andy Grover <andy@groveronline.com>
date Thu Nov 29 12:29:08 2007 -0800 (2007-11-29)
parents be8c09632f31
children f56c47274c37
line source
1 #include "xenvbd.h"
2 #include <io/blkif.h>
3 #include <srb.h>
4 #include <scsi.h>
5 #include <ntddscsi.h>
6 #include <ntdddisk.h>
7 #include <stdlib.h>
8 #include <xen_public.h>
9 #include <gnttbl_public.h>
10 #include <io/xenbus.h>
11 #include <ntddft.h>
13 #define wmb() KeMemoryBarrier()
14 #define mb() KeMemoryBarrier()
16 DRIVER_INITIALIZE DriverEntry;
18 static NTSTATUS
19 XenVbd_AddDevice(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit);
20 static NTSTATUS
21 XenVbd_PrepareHardware(WDFDEVICE hDevice, WDFCMRESLIST Resources, WDFCMRESLIST ResourcesTranslated);
22 static NTSTATUS
23 XenVbd_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated);
24 static NTSTATUS
25 XenVbd_D0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
26 static NTSTATUS
27 XenVbd_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
28 static NTSTATUS
29 XenVbd_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState);
30 static NTSTATUS
31 XenVbd_DeviceUsageNotification(WDFDEVICE Device, WDF_SPECIAL_FILE_TYPE NotificationType, BOOLEAN IsInNotificationPath);
33 static VOID
34 XenVbd_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
35 static VOID
36 XenVbd_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length);
37 static VOID
38 XenVbd_IoWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t Length);
39 static VOID
40 XenVbd_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, IN size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode);
42 static NTSTATUS
43 XenVbd_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit);
44 //static NTSTATUS
45 //XenVbd_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
46 static NTSTATUS
47 XenVbd_Child_PreprocessWdmIrpSCSI(WDFDEVICE Device, PIRP Irp);
48 static NTSTATUS
49 XenVbd_Child_PreprocessWdmIrpSomethingSomething(WDFDEVICE Device, PIRP Irp);
50 static VOID
51 XenVbd_Child_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
52 static VOID
53 XenVbd_Child_IoReadWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t Length);
54 static VOID
55 XenVbd_Child_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode);
56 static VOID
57 XenVbd_Child_IoInternalDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode);
59 static VOID
60 XenVbd_HotPlugHandler(char *Path, PVOID Data);
62 #ifdef ALLOC_PRAGMA
63 #pragma alloc_text (INIT, DriverEntry)
64 #pragma alloc_text (PAGE, XenVbd_AddDevice)
65 #endif
67 #pragma warning(disable: 4127) // disable conditional expression is constant
69 LIST_ENTRY DeviceListHead;
70 XEN_IFACE_EVTCHN EvtChnInterface;
71 XEN_IFACE_XENBUS XenBusInterface;
72 XEN_IFACE_XEN XenInterface;
73 XEN_IFACE_GNTTBL GntTblInterface;
75 static BOOLEAN AutoEnumerate;
77 NTSTATUS
78 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
79 {
80 WDF_DRIVER_CONFIG config;
81 ULONG status;
82 UNICODE_STRING RegKeyName;
83 UNICODE_STRING RegValueName;
84 HANDLE RegHandle;
85 OBJECT_ATTRIBUTES RegObjectAttributes;
86 char Buf[200];
87 ULONG BufLen = 200;
88 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
89 int State = 0;
90 int StartPos = 0;
91 WCHAR *SystemStartOptions;
92 size_t SystemStartOptionsLen;
93 size_t i;
95 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
97 WDF_DRIVER_CONFIG_INIT(&config, XenVbd_AddDevice);
98 status = WdfDriverCreate(
99 DriverObject,
100 RegistryPath,
101 WDF_NO_OBJECT_ATTRIBUTES,
102 &config,
103 WDF_NO_HANDLE);
104 if(!NT_SUCCESS(status))
105 {
106 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%08x\n", status));
107 }
109 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
110 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
111 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
112 if(!NT_SUCCESS(status))
113 {
114 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
115 }
117 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
118 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
119 if(!NT_SUCCESS(status))
120 {
121 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
122 }
123 //KdPrint((__DRIVER_NAME " BufLen = %d\n", BufLen));
124 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
125 KdPrint((__DRIVER_NAME " Buf = %ws\n", KeyPartialValue->Data));
126 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
128 AutoEnumerate = FALSE;
130 RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
132 for (i = 0; i <= SystemStartOptionsLen/2; i++)
133 {
134 //KdPrint((__DRIVER_NAME " pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
136 switch (State)
137 {
138 case 0:
139 if (SystemStartOptions[i] == L'G')
140 {
141 StartPos = i;
142 State = 2;
143 } else if (SystemStartOptions[i] != L' ')
144 {
145 State = 1;
146 }
147 break;
148 case 1:
149 if (SystemStartOptions[i] == L' ')
150 State = 0;
151 break;
152 case 2:
153 if (SystemStartOptions[i] == L'P')
154 State = 3;
155 else
156 State = 0;
157 break;
158 case 3:
159 if (SystemStartOptions[i] == L'L')
160 State = 4;
161 else
162 State = 0;
163 break;
164 case 4:
165 if (SystemStartOptions[i] == L'P')
166 State = 5;
167 else
168 State = 0;
169 break;
170 case 5:
171 if (SystemStartOptions[i] == L'V')
172 State = 6;
173 else
174 State = 0;
175 break;
176 case 6:
177 if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
178 AutoEnumerate = TRUE;
179 State = 0;
180 break;
181 }
182 }
184 KdPrint((__DRIVER_NAME " AutoEnumerate = %d\n", AutoEnumerate));
186 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
188 return status;
189 }
191 static WDFDEVICE GlobalDevice;
192 static PDEVICE_OBJECT Pdo;
194 static NTSTATUS
195 XenVbd_AddDevice(
196 IN WDFDRIVER Driver,
197 IN PWDFDEVICE_INIT DeviceInit
198 )
199 {
200 WDF_CHILD_LIST_CONFIG ChildListConfig;
201 NTSTATUS status;
202 WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
204 UNREFERENCED_PARAMETER(Driver);
206 KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
208 Pdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit);
210 //WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
211 WDF_CHILD_LIST_CONFIG_INIT(&ChildListConfig, sizeof(XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION), XenVbd_ChildListCreateDevice);
212 WdfFdoInitSetDefaultChildListConfig(DeviceInit, &ChildListConfig, WDF_NO_OBJECT_ATTRIBUTES);
214 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_CONTROLLER);
215 //WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
216 WdfDeviceInitSetExclusive(DeviceInit, FALSE);
218 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
219 pnpPowerCallbacks.EvtDevicePrepareHardware = XenVbd_PrepareHardware;
220 pnpPowerCallbacks.EvtDeviceReleaseHardware = XenVbd_ReleaseHardware;
221 pnpPowerCallbacks.EvtDeviceD0Entry = XenVbd_D0Entry;
222 pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenVbd_D0EntryPostInterruptsEnabled;
223 pnpPowerCallbacks.EvtDeviceD0Exit = XenVbd_D0Exit;
224 pnpPowerCallbacks.EvtDeviceUsageNotification = XenVbd_DeviceUsageNotification;
225 WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
227 /*initialize storage for the device context*/
228 //WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENVBD_DEVICE_DATA);
230 //WdfDeviceInitSetPowerNotPageable(DeviceInit);
232 /*create a device instance.*/
233 status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &GlobalDevice);
234 if(!NT_SUCCESS(status))
235 {
236 KdPrint((__DRIVER_NAME "WdfDeviceCreate failed with status 0x%08x\n", status));
237 return status;
238 }
240 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFilePaging, TRUE);
241 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFileHibernation, TRUE);
242 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFileDump, TRUE);
244 status = STATUS_SUCCESS;
246 KdPrint((__DRIVER_NAME " <-- DeviceAdd\n"));
247 return status;
248 }
250 static NTSTATUS
251 XenVbd_PrepareHardware(
252 IN WDFDEVICE Device,
253 IN WDFCMRESLIST ResourceList,
254 IN WDFCMRESLIST ResourceListTranslated)
255 {
256 NTSTATUS status = STATUS_SUCCESS;
258 UNREFERENCED_PARAMETER(ResourceList);
259 UNREFERENCED_PARAMETER(ResourceListTranslated);
261 //KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware\n"));
263 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_EVTCHN, (PINTERFACE) &EvtChnInterface, sizeof(XEN_IFACE_EVTCHN), 1, NULL);
264 if(!NT_SUCCESS(status))
265 {
266 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (EvtChn) failed with status 0x%08x\n", status));
267 }
269 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XENBUS, (PINTERFACE)&XenBusInterface, sizeof(XEN_IFACE_XENBUS), 1, NULL);
270 if(!NT_SUCCESS(status))
271 {
272 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (XenBus) failed with status 0x%08x\n", status));
273 }
275 #if 0 // not used yet
276 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XEN, (PINTERFACE)&XenInterface, sizeof(XEN_IFACE_XEN), 1, NULL);
277 if(!NT_SUCCESS(status))
278 {
279 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (Xen) failed with status 0x%08x\n", status));
280 }
281 #endif
283 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_GNTTBL, (PINTERFACE)&GntTblInterface, sizeof(XEN_IFACE_GNTTBL), 1, NULL);
284 if(!NT_SUCCESS(status))
285 {
286 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (GntTbl) failed with status 0x%08x\n", status));
287 }
289 //KdPrint((__DRIVER_NAME " <-- EvtDevicePrepareHardware\n"));
291 InitializeListHead(&DeviceListHead);
293 return status;
294 }
296 static NTSTATUS
297 XenVbd_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated)
298 {
299 UNREFERENCED_PARAMETER(Device);
300 UNREFERENCED_PARAMETER(ResourcesTranslated);
302 // release interfaces here...
304 //XenVbd_Close();
306 return STATUS_SUCCESS;
307 }
309 static NTSTATUS
310 XenVbd_D0Entry(
311 IN WDFDEVICE Device,
312 IN WDF_POWER_DEVICE_STATE PreviousState
313 )
314 {
315 NTSTATUS status = STATUS_SUCCESS;
317 UNREFERENCED_PARAMETER(Device);
318 UNREFERENCED_PARAMETER(PreviousState);
320 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Entry\n"));
322 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
324 return status;
325 }
327 static LONG EnumeratedDevices;
328 static KEVENT WaitDevicesEvent;
330 static NTSTATUS
331 XenVbd_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
332 {
333 //OBJECT_ATTRIBUTES oa;
334 NTSTATUS status = STATUS_SUCCESS;
335 //HANDLE nothing;
336 //char *response;
337 PXENPCI_XEN_DEVICE_DATA PdoDeviceData;
338 char **VbdDevices;
339 char *msg;
340 char buffer[128];
341 int i;
342 LARGE_INTEGER WaitTimeout;
344 UNREFERENCED_PARAMETER(Device);
345 UNREFERENCED_PARAMETER(PreviousState);
347 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0EntryPostInterruptsEnabled\n"));
349 PdoDeviceData = (PXENPCI_XEN_DEVICE_DATA)Pdo->DeviceExtension; //GetXenDeviceData(Device);
351 //KdPrint((__DRIVER_NAME " BasePath = %s\n", PdoDeviceData->BasePath));
352 PdoDeviceData->WatchHandler = XenVbd_HotPlugHandler;
354 EnumeratedDevices = 0;
355 KeInitializeEvent(&WaitDevicesEvent, SynchronizationEvent, FALSE);
357 // TODO: Should probably do this in an EvtChildListScanForChildren
358 if (AutoEnumerate)
359 {
360 msg = XenBusInterface.List(XenBusInterface.InterfaceHeader.Context,
361 XBT_NIL, "device/vbd", &VbdDevices);
362 if (!msg) {
363 for (i = 0; VbdDevices[i]; i++)
364 {
365 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
366 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
367 XenVbd_HotPlugHandler(buffer, NULL);
368 //ExFreePoolWithTag(bdDevices[i], XENPCI_POOL_TAG);
369 }
370 KdPrint((__DRIVER_NAME " Waiting for devices to be enumerated\n"));
371 while (EnumeratedDevices != i)
372 {
373 WaitTimeout.QuadPart = -600000000;
374 if (KeWaitForSingleObject(&WaitDevicesEvent, Executive, KernelMode, FALSE, &WaitTimeout) == STATUS_TIMEOUT)
375 {
376 KdPrint((__DRIVER_NAME " Wait timed out\n"));
377 break;
378 }
379 KdPrint((__DRIVER_NAME " %d out of %d devices enumerated\n", EnumeratedDevices, i));
380 }
381 }
382 }
384 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0EntryPostInterruptsEnabled\n"));
386 return status;
387 }
389 static NTSTATUS
390 XenVbd_D0Exit(
391 IN WDFDEVICE Device,
392 IN WDF_POWER_DEVICE_STATE TargetState
393 )
394 {
395 NTSTATUS status = STATUS_SUCCESS;
396 //char *response;
398 UNREFERENCED_PARAMETER(Device);
399 UNREFERENCED_PARAMETER(TargetState);
401 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Exit\n"));
403 //response = XenBusInterface.RemWatch(XBT_NIL, XenBusInterface.InterfaceHeader.Context, XenVbd_HotPlugHandler, NULL);
405 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Exit\n"));
407 return status;
408 }
410 static NTSTATUS
411 XenVbd_DeviceUsageNotification(
412 WDFDEVICE Device,
413 WDF_SPECIAL_FILE_TYPE NotificationType,
414 BOOLEAN IsInNotificationPath)
415 {
416 UNREFERENCED_PARAMETER(Device);
418 KdPrint((__DRIVER_NAME " --> DeviceUsageNotification\n"));
420 switch (NotificationType)
421 {
422 case WdfSpecialFilePaging:
423 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFilePaging, Using = %d\n", IsInNotificationPath));
424 break;
425 case WdfSpecialFileHibernation:
426 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFileHibernation, Using = %d\n", IsInNotificationPath));
427 break;
428 case WdfSpecialFileDump:
429 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFileDump, Using = %d\n", IsInNotificationPath));
430 break;
431 default:
432 KdPrint((__DRIVER_NAME " NotificationType = %d, Using = %d\n", NotificationType, IsInNotificationPath));
433 break;
434 }
435 KdPrint((__DRIVER_NAME " <-- DeviceUsageNotification\n"));
437 return TRUE;
438 }
440 static VOID
441 XenVbd_IoDefault(
442 IN WDFQUEUE Queue,
443 IN WDFREQUEST Request
444 )
445 {
446 UNREFERENCED_PARAMETER(Queue);
448 //KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
450 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
452 //KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
453 }
455 static __inline uint64_t
456 GET_ID_FROM_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData)
457 {
458 uint64_t free;
460 free = ChildDeviceData->shadow_free;
462 //KdPrint((__DRIVER_NAME " A free = %d\n", free));
464 ChildDeviceData->shadow_free = ChildDeviceData->shadow[free].req.id;
466 //KdPrint((__DRIVER_NAME " A shadow_free now = %d\n", ChildDeviceData->shadow_free));
468 ChildDeviceData->shadow[free].req.id = 0x0fffffee; /* debug */
469 return free;
470 }
472 static __inline VOID
473 ADD_ID_TO_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, uint64_t Id)
474 {
475 ChildDeviceData->shadow[Id].req.id = ChildDeviceData->shadow_free;
476 ChildDeviceData->shadow[Id].Irp = NULL;
477 ChildDeviceData->shadow_free = Id;
478 }
480 static VOID
481 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp);
483 static PMDL
484 AllocatePages(int Pages)
485 {
486 PMDL Mdl;
487 PVOID Buf;
489 Buf = ExAllocatePoolWithTag(NonPagedPool, Pages * PAGE_SIZE, XENVBD_POOL_TAG);
490 if (Buf == NULL)
491 {
492 KdPrint((__DRIVER_NAME " AllocatePages Failed at ExAllocatePoolWithTag\n"));
493 }
494 Mdl = IoAllocateMdl(Buf, Pages * PAGE_SIZE, FALSE, FALSE, NULL);
495 if (Mdl == NULL)
496 {
497 KdPrint((__DRIVER_NAME " AllocatePages Failed at IoAllocateMdl\n"));
498 }
499 MmBuildMdlForNonPagedPool(Mdl);
501 return Mdl;
502 }
504 static PMDL
505 AllocatePage()
506 {
507 return AllocatePages(1);
508 }
510 static VOID
511 FreePages(PMDL Mdl)
512 {
513 PVOID Buf = MmGetMdlVirtualAddress(Mdl);
514 //KdPrint((__DRIVER_NAME " FreePages Failed at IoAllocateMdl\n"));
515 //KdPrint((__DRIVER_NAME " FreePages Buf = %08x\n", Buf));
516 IoFreeMdl(Mdl);
517 ExFreePoolWithTag(Buf, XENVBD_POOL_TAG);
518 }
520 static VOID
521 XenVbd_DpcThreadProc(WDFDPC Dpc)
522 {
523 PIRP Irp;
524 RING_IDX i, rp;
525 int j;
526 blkif_response_t *rep;
527 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
528 PSCSI_REQUEST_BLOCK Srb;
529 PIO_STACK_LOCATION IrpSp;
530 char *DataBuffer;
531 int more_to_do;
532 int IrpCount;
533 PIRP Irps[100];
534 int BlockCount;
535 KIRQL KIrql;
536 WDFDEVICE ChildDevice;
537 XenVbd_ListEntry *ListEntry;
538 int notify;
540 //!!!IRQL_DISPATCH!!!
542 //KdPrint((__DRIVER_NAME " --> XenVbd_DpcThreadProc\n"));
544 ChildDevice = WdfDpcGetParentObject(Dpc);
546 ChildDeviceData = *GetChildDeviceData(ChildDevice);
548 IrpCount = 0;
549 more_to_do = TRUE;
550 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
552 ChildDeviceData->IrpAddedToRingAtLastDpc = ChildDeviceData->IrpAddedToRing;
554 while (more_to_do)
555 {
556 rp = ChildDeviceData->Ring.sring->rsp_prod;
557 KeMemoryBarrier();
558 for (i = ChildDeviceData->Ring.rsp_cons; i != rp; i++)
559 {
560 rep = RING_GET_RESPONSE(&ChildDeviceData->Ring, i);
561 ChildDeviceData->IrpRemovedFromRing++;
562 Irp = ChildDeviceData->shadow[rep->id].Irp;
563 IrpSp = IoGetCurrentIrpStackLocation(Irp);
564 Srb = IrpSp->Parameters.Scsi.Srb;
566 if (rep->status != BLKIF_RSP_OKAY)
567 {
568 KdPrint((__DRIVER_NAME " Xen Operation returned error in DpcThreadProc\n"));
569 KdPrint((__DRIVER_NAME " operation = %d, nr_segments = %d, sector_number = %d\n", ChildDeviceData->shadow[rep->id].req.operation, ChildDeviceData->shadow[rep->id].req.nr_segments, ChildDeviceData->shadow[rep->id].req.sector_number));
570 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
571 {
572 KdPrint((__DRIVER_NAME " gref[%d] = %d\n", j, ChildDeviceData->shadow[rep->id].req.seg[j].gref));
573 }
574 KdPrint((__DRIVER_NAME " MmGetMdlByteOffset = %d\n", MmGetMdlByteOffset(Irp->MdlAddress)));
575 }
576 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
577 {
578 GntTblInterface.EndAccess(GntTblInterface.InterfaceHeader.Context,
579 ChildDeviceData->shadow[rep->id].req.seg[j].gref);
580 }
581 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
582 if (ChildDeviceData->shadow[rep->id].Buf != NULL)
583 {
584 if (Srb->Cdb[0] == SCSIOP_READ)
585 {
586 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
587 if (DataBuffer == NULL)
588 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe Failed in DpcThreadProc\n"));
589 memcpy(DataBuffer, ChildDeviceData->shadow[rep->id].Buf, BlockCount * ChildDeviceData->BytesPerSector);
590 }
591 FreePages(ChildDeviceData->shadow[rep->id].Mdl);
592 }
593 Srb->SrbStatus = SRB_STATUS_SUCCESS;
594 Srb->ScsiStatus = 0;
595 Irp->IoStatus.Status = STATUS_SUCCESS;
596 Irp->IoStatus.Information = BlockCount * ChildDeviceData->BytesPerSector;
598 Irps[IrpCount++] = Irp;
600 ADD_ID_TO_FREELIST(ChildDeviceData, rep->id);
601 }
603 ChildDeviceData->Ring.rsp_cons = i;
604 if (i != ChildDeviceData->Ring.req_prod_pvt)
605 {
606 RING_FINAL_CHECK_FOR_RESPONSES(&ChildDeviceData->Ring, more_to_do);
607 }
608 else
609 {
610 ChildDeviceData->Ring.sring->rsp_event = i + 1;
611 more_to_do = FALSE;
612 }
613 }
615 notify = 0;
616 while (!RING_FULL(&ChildDeviceData->Ring) && (ListEntry = (XenVbd_ListEntry *)RemoveHeadList(&ChildDeviceData->IrpListHead)) != (XenVbd_ListEntry *)&ChildDeviceData->IrpListHead)
617 {
618 ChildDeviceData->IrpRemovedFromList++;
619 XenVbd_PutIrpOnRing(ChildDevice, ListEntry->Irp);
620 ExFreePoolWithTag(ListEntry, XENVBD_POOL_TAG);
621 notify = 1;
622 }
623 if (notify)
624 {
625 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
626 if (notify)
627 EvtChnInterface.Notify(EvtChnInterface.InterfaceHeader.Context,
628 ChildDeviceData->EventChannel);
629 }
630 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
632 for (j = 0; j < IrpCount; j++)
633 {
634 IoCompleteRequest(Irps[j], IO_NO_INCREMENT);
635 ChildDeviceData->IrpCompleted++;
636 }
638 //KdPrint((__DRIVER_NAME " <-- XenVbd_DpcThreadProc\n"));
639 //KdPrint((__DRIVER_NAME " <-- XenVbd_DpcThreadProc (AddedToList = %d, RemovedFromList = %d, AddedToRing = %d, AddedToRingAtLastNotify = %d, AddedToRingAtLastInterrupt = %d, AddedToRingAtLastDpc = %d, RemovedFromRing = %d, IrpCompleted = %d)\n", ChildDeviceData->IrpAddedToList, ChildDeviceData->IrpRemovedFromList, ChildDeviceData->IrpAddedToRing, ChildDeviceData->IrpAddedToRingAtLastNotify, ChildDeviceData->IrpAddedToRingAtLastInterrupt, ChildDeviceData->IrpAddedToRingAtLastDpc, ChildDeviceData->IrpRemovedFromRing, ChildDeviceData->IrpCompleted));
640 }
642 static BOOLEAN
643 XenVbd_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
644 {
645 BOOLEAN RetVal;
646 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
648 UNREFERENCED_PARAMETER(Interrupt);
649 // !!!RUNS AT DIRQL!!!
651 //KdPrint((__DRIVER_NAME " --> XenVbd_Interrupt\n"));
653 ChildDeviceData = (PXENVBD_CHILD_DEVICE_DATA)ServiceContext;
654 ChildDeviceData->IrpAddedToRingAtLastInterrupt = ChildDeviceData->IrpAddedToRing;
655 RetVal = WdfDpcEnqueue(ChildDeviceData->Dpc);
657 //KdPrint((__DRIVER_NAME " <-- XenVbd_Interrupt (RetVal = %d)\n", RetVal));
659 return STATUS_SUCCESS;
660 }
662 static VOID
663 XenVbd_BackEndStateHandler(char *Path, PVOID Data)
664 {
665 PXENVBD_CHILD_DEVICE_DATA DeviceData = Data;
666 char TmpPath[128];
667 char *Value;
668 int NewState;
669 PMDL Mdl;
670 grant_ref_t ref;
671 blkif_sring_t *SharedRing;
672 ULONG PFN;
673 XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION Description;
674 NTSTATUS status;
676 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
677 XBT_NIL, Path, &Value);
678 NewState = atoi(Value);
679 ExFreePool(Value);
681 switch (NewState)
682 {
683 case XenbusStateUnknown:
684 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
685 break;
687 case XenbusStateInitialising:
688 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
689 break;
691 case XenbusStateInitWait:
692 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
694 DeviceData->EventChannel = EvtChnInterface.AllocUnbound(
695 EvtChnInterface.InterfaceHeader.Context, 0);
696 EvtChnInterface.Bind(EvtChnInterface.InterfaceHeader.Context,
697 DeviceData->EventChannel, XenVbd_Interrupt, DeviceData);
698 Mdl = AllocatePage();
699 PFN = *MmGetMdlPfnArray(Mdl);
700 SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
701 SHARED_RING_INIT(SharedRing);
702 FRONT_RING_INIT(&DeviceData->Ring, SharedRing, PAGE_SIZE);
703 ref = GntTblInterface.GrantAccess(GntTblInterface.InterfaceHeader.Context,
704 0, PFN, FALSE);
706 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
707 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/ring-ref");
708 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
709 XBT_NIL, TmpPath, "%d", ref);
711 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
712 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/event-channel");
713 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
714 XBT_NIL, TmpPath, "%d", DeviceData->EventChannel);
716 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
717 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/state");
718 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
719 XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
721 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
722 break;
724 case XenbusStateInitialised:
725 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
726 // create the device
727 break;
729 case XenbusStateConnected:
730 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
732 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Description.Header, sizeof(Description));
734 Description.DeviceData = DeviceData;
736 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
737 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/device-type");
738 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
739 XBT_NIL, TmpPath, &Value);
740 if (strcmp(Value, "disk") == 0)
741 {
742 KdPrint((__DRIVER_NAME " DeviceType = Disk\n"));
743 DeviceData->DeviceType = XENVBD_DEVICETYPE_DISK;
744 }
745 else if (strcmp(Value, "cdrom") == 0)
746 {
747 KdPrint((__DRIVER_NAME " DeviceType = CDROM\n"));
748 DeviceData->DeviceType = XENVBD_DEVICETYPE_CDROM;
749 }
750 else
751 {
752 KdPrint((__DRIVER_NAME " DeviceType = %s (This probably won't work!)\n", Value));
753 }
755 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
756 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/type"); // should probably check that this is 'phy' or 'file' or at least not ''
757 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
758 XBT_NIL, TmpPath, &Value);
759 KdPrint((__DRIVER_NAME " Backend Type = %s\n", Value));
760 ExFreePool(Value);
762 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
763 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/mode"); // should store this...
764 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
765 XBT_NIL, TmpPath, &Value);
766 KdPrint((__DRIVER_NAME " Backend Mode = %s\n", Value));
767 ExFreePool(Value);
769 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
770 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/sector-size");
771 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
772 XBT_NIL, TmpPath, &Value);
773 // should complain if Value == NULL
774 DeviceData->BytesPerSector = atoi(Value);
775 ExFreePool(Value);
777 KdPrint((__DRIVER_NAME " BytesPerSector = %d\n", DeviceData->BytesPerSector));
779 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
780 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/sectors");
781 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
782 XBT_NIL, TmpPath, &Value);
783 // should complain if Value == NULL
784 DeviceData->TotalSectors = (ULONGLONG)atol(Value);
785 ExFreePool(Value);
787 KdPrint((__DRIVER_NAME " TotalSectors = %d\n", DeviceData->TotalSectors));
789 // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
790 DeviceData->Geometry.MediaType = FixedMedia;
791 DeviceData->Geometry.BytesPerSector = DeviceData->BytesPerSector;
792 DeviceData->Geometry.SectorsPerTrack = 63;
793 DeviceData->Geometry.TracksPerCylinder = 255;
794 DeviceData->Geometry.Cylinders.QuadPart = DeviceData->TotalSectors / DeviceData->Geometry.SectorsPerTrack / DeviceData->Geometry.TracksPerCylinder;
795 KdPrint((__DRIVER_NAME " Geometry C/H/S = %d/%d/%d\n", DeviceData->Geometry.Cylinders.LowPart, DeviceData->Geometry.TracksPerCylinder, DeviceData->Geometry.SectorsPerTrack));
797 // if we detected something wrong, we should not enumarate the device and should instead initiate a close
799 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(WdfFdoGetDefaultChildList(GlobalDevice), &Description.Header, NULL);
800 if (!NT_SUCCESS(status))
801 {
802 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed %08x\n", status));
803 }
805 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
806 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/state");
807 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
808 XBT_NIL, TmpPath, "%d", XenbusStateConnected);
810 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
811 InterlockedIncrement(&EnumeratedDevices);
812 KdPrint((__DRIVER_NAME " Added a disk, notifying\n"));
814 KeSetEvent(&WaitDevicesEvent, 1, FALSE);
816 break;
818 case XenbusStateClosing:
819 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
820 break;
822 case XenbusStateClosed:
823 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
824 break;
826 default:
827 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
828 break;
829 }
830 }
832 static VOID
833 XenVbd_HotPlugHandler(char *Path, PVOID Data)
834 {
835 PXENVBD_CHILD_DEVICE_DATA DeviceData;
836 char **Bits;
837 int Count;
838 char TmpPath[128];
839 char *Value;
841 UNREFERENCED_PARAMETER(Data);
843 //KdPrint((__DRIVER_NAME " --> HotPlugHandler\n"));
845 //KdPrint((__DRIVER_NAME " Path = %s\n", Path));
847 Bits = SplitString(Path, '/', 4, &Count);
848 if (Count != 4)
849 {
850 KdPrint((__FUNCTION__ ": Count = %d, not 4!\n", Count));
851 goto cleanup;
852 }
854 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
855 goto cleanup;
857 /* ignore already known devices */
858 for (DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceListHead.Flink; DeviceData != (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead; DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceData->Entry.Flink)
859 {
860 if (strncmp(DeviceData->Path, Path, strlen(DeviceData->Path)) == 0 && Path[strlen(DeviceData->Path)] == '/')
861 {
862 goto cleanup;
863 }
864 }
866 /* new device found, alloc and init dev extension */
867 DeviceData = ExAllocatePoolWithTag(NonPagedPool,
868 sizeof(XENVBD_CHILD_DEVICE_DATA), XENVBD_POOL_TAG);
869 memset(DeviceData, 0, sizeof(XENVBD_CHILD_DEVICE_DATA));
871 //KdPrint((__DRIVER_NAME " Allocated ChildDeviceData = %08x\n", DeviceData));
873 InsertTailList(&DeviceListHead, &DeviceData->Entry);
874 RtlStringCbPrintfA(DeviceData->Path, ARRAY_SIZE(DeviceData->Path),
875 "%s/%s/%s", Bits[0], Bits[1], Bits[2]);
876 DeviceData->DeviceIndex = atoi(Bits[2]);
878 /* Get backend path */
879 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
880 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/backend");
881 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
882 XBT_NIL, TmpPath, &Value);
883 if (!Value)
884 {
885 KdPrint((__DRIVER_NAME " Read Failed\n"));
886 }
887 else
888 {
889 RtlStringCbCopyA(DeviceData->BackendPath,
890 ARRAY_SIZE(DeviceData->BackendPath), Value);
891 }
892 ExFreePool(Value);
894 /* Add watch on backend state */
895 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
896 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/state");
897 XenBusInterface.AddWatch(XenBusInterface.InterfaceHeader.Context,
898 XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, DeviceData);
900 cleanup:
901 FreeSplitString(Bits, Count);
903 //KdPrint((__DRIVER_NAME " <-- HotPlugHandler\n"));
904 }
906 static NTSTATUS
907 XenVbd_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit)
908 {
909 NTSTATUS status;
910 WDFDEVICE ChildDevice;
911 PXENVBD_DEVICE_IDENTIFICATION_DESCRIPTION XenVbdIdentificationDesc;
912 DECLARE_UNICODE_STRING_SIZE(buffer, 50);
913 WDF_OBJECT_ATTRIBUTES PdoAttributes;
914 DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
915 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
916 WDF_IO_QUEUE_CONFIG IoQueueConfig;
917 unsigned int i;
918 WDF_DPC_CONFIG DpcConfig;
919 WDF_OBJECT_ATTRIBUTES DpcObjectAttributes;
920 WDF_DEVICE_STATE DeviceState;
921 //UCHAR ScsiMinors[1] = { IRP_MN_SCSI_CLASS };
923 UNREFERENCED_PARAMETER(ChildList);
925 KdPrint((__DRIVER_NAME " --> ChildListCreateDevice\n"));
927 XenVbdIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION, Header);
929 ChildDeviceData = XenVbdIdentificationDesc->DeviceData;
931 // Capabilities = CM_DEVCAP_UNIQUEID
932 // Devnode Flages = DN_NEED_RESTART??? DN_DISABLEABLE???
934 switch (ChildDeviceData->DeviceType)
935 {
936 case XENVBD_DEVICETYPE_DISK:
937 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_DISK);
939 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk\0");
940 //status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk&Ven_James&Prod_James&Rev_1.00\0");
941 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
943 status = RtlUnicodeStringPrintf(&buffer, L"%02d\0", ChildDeviceData->DeviceIndex);
944 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
946 status = RtlUnicodeStringPrintf(&buffer, L"GenDisk\0");
947 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
948 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
950 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV Disk (%d)", ChildDeviceData->DeviceIndex);
951 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
952 break;
953 case XENVBD_DEVICETYPE_CDROM:
954 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_MASS_STORAGE);
955 WdfDeviceInitSetCharacteristics(ChildInit, FILE_READ_ONLY_DEVICE|FILE_REMOVABLE_MEDIA, TRUE);
957 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\CDROM\0");
958 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
960 status = RtlUnicodeStringPrintf(&buffer, L"%02d\0", ChildDeviceData->DeviceIndex);
961 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
963 status = RtlUnicodeStringPrintf(&buffer, L"GenCdRom\0");
964 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
965 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
967 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV CDROM (%d)\0", ChildDeviceData->DeviceIndex);
968 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
969 break;
970 default:
971 // wtf?
972 break;
973 }
975 WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
977 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, PXENVBD_CHILD_DEVICE_DATA);
979 //WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSCSI, IRP_MJ_SCSI, ScsiMinors, 1);
980 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSCSI, IRP_MJ_SCSI, NULL, 0);
982 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_VOLUME_INFORMATION, NULL, 0);
983 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_DEVICE_CHANGE, NULL, 0);
985 WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);
987 //WdfDeviceInitSetPowerNotPageable(ChildInit);
989 status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
990 if (!NT_SUCCESS(status))
991 {
992 KdPrint((__DRIVER_NAME " WdfDeviceCreate status = %08X\n", status));
993 }
995 switch (ChildDeviceData->DeviceType)
996 {
997 case XENVBD_DEVICETYPE_DISK:
998 WDF_DEVICE_STATE_INIT(&DeviceState);
999 DeviceState.NotDisableable = WdfTrue;
1000 WdfDeviceSetDeviceState(ChildDevice, &DeviceState);
1001 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFilePaging, TRUE);
1002 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileHibernation, TRUE);
1003 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileDump, TRUE);
1004 break;
1005 case XENVBD_DEVICETYPE_CDROM:
1006 break;
1008 *GetChildDeviceData(ChildDevice) = ChildDeviceData;
1010 ChildDeviceData->FastPathUsed = 0;
1011 ChildDeviceData->SlowPathUsed = 0;
1012 ChildDeviceData->IrpAddedToList = 0;
1013 ChildDeviceData->IrpRemovedFromList = 0;
1014 ChildDeviceData->IrpAddedToRing = 0;
1015 ChildDeviceData->IrpAddedToRingAtLastNotify = 0;
1016 ChildDeviceData->IrpAddedToRingAtLastInterrupt = 0;
1017 ChildDeviceData->IrpAddedToRingAtLastDpc = 0;
1018 ChildDeviceData->IrpRemovedFromRing = 0;
1019 ChildDeviceData->IrpCompleted = 0;
1021 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoQueueConfig, WdfIoQueueDispatchSequential);
1022 IoQueueConfig.AllowZeroLengthRequests = TRUE;
1023 //IoQueueConfig.EvtIoDefault = XenVbd_Child_IoDefault;
1024 //IoQueueConfig.EvtIoRead = XenVbd_Child_IoReadWrite;
1025 //IoQueueConfig.EvtIoWrite = XenVbd_Child_IoReadWrite;
1026 IoQueueConfig.EvtIoDeviceControl = XenVbd_Child_IoDeviceControl;
1027 //IoQueueConfig.EvtIoInternalDeviceControl = XenVbd_Child_IoInternalDeviceControl;
1029 status = WdfIoQueueCreate(ChildDevice, &IoQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &ChildDeviceData->IoDefaultQueue);
1030 if(!NT_SUCCESS(status))
1032 KdPrint((__DRIVER_NAME "WdfIoQueueCreate failed with status 0x%08x\n", status));
1033 return status;
1036 ChildDeviceData->Device = ChildDevice;
1038 KeInitializeSpinLock(&ChildDeviceData->Lock);
1039 KeInitializeSpinLock(&ChildDeviceData->IrpListLock);
1040 InitializeListHead(&ChildDeviceData->IrpListHead);
1042 ChildDeviceData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * BLK_RING_SIZE, XENVBD_POOL_TAG);
1043 memset(ChildDeviceData->shadow, 0, sizeof(blkif_shadow_t) * BLK_RING_SIZE);
1044 //KdPrint((__DRIVER_NAME " Allocated shadow = %08x\n", ChildDeviceData->shadow));
1045 for (i = 0; i < BLK_RING_SIZE; i++)
1046 ChildDeviceData->shadow[i].req.id = i + 1;
1047 ChildDeviceData->shadow_free = 0;
1048 ChildDeviceData->shadow[BLK_RING_SIZE - 1].req.id = 0x0fffffff;
1050 WDF_DPC_CONFIG_INIT(&DpcConfig, XenVbd_DpcThreadProc);
1051 WDF_OBJECT_ATTRIBUTES_INIT(&DpcObjectAttributes);
1052 DpcObjectAttributes.ParentObject = ChildDevice;
1053 WdfDpcCreate(&DpcConfig, &DpcObjectAttributes, &ChildDeviceData->Dpc);
1055 KdPrint((__DRIVER_NAME " <-- ChildListCreateDevice (status = %08x)\n", status));
1057 return status;
1061 // if the list isn't empty, then we should always add the request to the end of the list and then try and clear the list onto the ring
1063 // Call with device lock held
1064 static VOID
1065 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp)
1067 char *DataBuffer;
1068 PSCSI_REQUEST_BLOCK Srb;
1069 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1070 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1071 blkif_request_t *req;
1072 int i;
1073 ULONG j;
1074 int BlockCount;
1075 UINT8 sect_offset;
1077 ChildDeviceData = *GetChildDeviceData(Device);
1079 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1080 KdPrint((__DRIVER_NAME " --> PutIrpOnRing\n"));
1082 if (RING_FULL(&ChildDeviceData->Ring))
1084 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
1087 req = RING_GET_REQUEST(&ChildDeviceData->Ring, ChildDeviceData->Ring.req_prod_pvt);
1089 //KdPrint((__DRIVER_NAME " req = %08x\n", req));
1091 Srb = irpSp->Parameters.Scsi.Srb;
1093 req->sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
1094 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
1096 req->id = GET_ID_FROM_FREELIST(ChildDeviceData);
1098 if (req->id == 0x0fffffff)
1100 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutIrpOnRing\n"));
1103 //KdPrint((__DRIVER_NAME " id = %d\n", req->id));
1105 req->handle = 0;
1106 req->operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
1107 ChildDeviceData->shadow[req->id].Irp = Irp;
1109 if ((MmGetMdlByteOffset(Irp->MdlAddress) & 0x1ff) == 0) // 0x1ff shouldn't be hardcoded...
1111 // fast path - zero copy
1112 ChildDeviceData->shadow[req->id].Mdl = Irp->MdlAddress;
1113 ChildDeviceData->shadow[req->id].Buf = NULL; // we don't need the virtual address
1114 ChildDeviceData->FastPathUsed++;
1116 else
1118 // slow path - copy to bounce buffer
1119 ChildDeviceData->shadow[req->id].Mdl = AllocatePages((BlockCount * ChildDeviceData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE);
1120 ChildDeviceData->shadow[req->id].Buf = MmGetMdlVirtualAddress(ChildDeviceData->shadow[req->id].Mdl);
1121 if (ChildDeviceData->shadow[req->id].Buf == NULL)
1123 KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress returned NULL in PutIrpOnRing\n"));
1125 ChildDeviceData->SlowPathUsed++;
1128 // if (((ChildDeviceData->FastPathUsed + ChildDeviceData->SlowPathUsed) & 0x2FF) == 0)
1129 // {
1130 // KdPrint((__DRIVER_NAME " Fast Path = %d, Slow Path = %d\n", ChildDeviceData->FastPathUsed, ChildDeviceData->SlowPathUsed));
1131 // KdPrint((__DRIVER_NAME " AddedToList = %d, RemovedFromList = %d, AddedToRing = %d, AddedToRingAtLastNotify = %d, AddedToRingAtLastInterrupt = %d, AddedToRingAtLastDpc = %d, RemovedFromRing = %d, IrpCompleted = %d\n", ChildDeviceData->IrpAddedToList, ChildDeviceData->IrpRemovedFromList, ChildDeviceData->IrpAddedToRing, ChildDeviceData->IrpAddedToRingAtLastNotify, ChildDeviceData->IrpAddedToRingAtLastInterrupt, ChildDeviceData->IrpAddedToRingAtLastDpc, ChildDeviceData->IrpRemovedFromRing, ChildDeviceData->IrpCompleted));
1132 // }
1134 sect_offset = (UINT8)(MmGetMdlByteOffset(ChildDeviceData->shadow[req->id].Mdl) >> 9);
1135 for (i = 0, req->nr_segments = 0; i < BlockCount; req->nr_segments++)
1137 req->seg[req->nr_segments].gref = GntTblInterface.GrantAccess(
1138 GntTblInterface.InterfaceHeader.Context,
1139 0,
1140 MmGetMdlPfnArray(ChildDeviceData->shadow[req->id].Mdl)[req->nr_segments],
1141 FALSE);
1142 req->seg[req->nr_segments].first_sect = sect_offset;
1143 for (j = sect_offset; i < BlockCount && j < PAGE_SIZE / ChildDeviceData->BytesPerSector; j++, i++)
1144 req->seg[req->nr_segments].last_sect = (uint8_t)j;
1145 sect_offset = 0;
1147 if (Srb->Cdb[0] == SCSIOP_WRITE && ChildDeviceData->shadow[req->id].Buf != NULL)
1149 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1150 if (DataBuffer == NULL)
1151 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe failed in PutIrpOnRing\n"));
1152 memcpy(ChildDeviceData->shadow[req->id].Buf, DataBuffer, BlockCount * ChildDeviceData->BytesPerSector);
1154 ChildDeviceData->shadow[req->id].req = *req;
1156 ChildDeviceData->Ring.req_prod_pvt++;
1158 ChildDeviceData->IrpAddedToRing++;
1160 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1161 KdPrint((__DRIVER_NAME " <-- PutIrpOnRing\n"));
1164 static ULONG
1165 XenVBD_FillModePage(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
1167 PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
1169 switch (PageCode)
1171 case MODE_PAGE_RIGID_GEOMETRY:
1172 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1174 KdPrint((__DRIVER_NAME " MODE_PAGE_RIGID_GEOMETRY\n"));
1175 if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
1176 return 1;
1177 ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
1178 memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
1179 ModeRigidGeometry->PageCode = PageCode;
1180 ModeRigidGeometry->PageSavable = 0;
1181 ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
1182 ModeRigidGeometry->NumberOfCylinders[0] = (UCHAR)((ChildDeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF);
1183 ModeRigidGeometry->NumberOfCylinders[1] = (UCHAR)((ChildDeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF);
1184 ModeRigidGeometry->NumberOfCylinders[2] = (UCHAR)((ChildDeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF);
1185 ModeRigidGeometry->NumberOfHeads = (UCHAR)ChildDeviceData->Geometry.TracksPerCylinder;
1186 //ModeRigidGeometry->LandZoneCyclinder = 0;
1187 ModeRigidGeometry->RoataionRate[0] = 0x05;
1188 ModeRigidGeometry->RoataionRate[0] = 0x39;
1189 *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
1191 break;
1192 case MODE_PAGE_FAULT_REPORTING:
1193 break;
1194 default:
1195 break;
1197 return 0;
1200 static NTSTATUS
1201 XenVbd_Child_PreprocessWdmIrpSomethingSomething(WDFDEVICE Device, PIRP Irp)
1203 NTSTATUS Status;
1205 KdPrint((__DRIVER_NAME " --> XenVbd_Child_PreprocessWdmIrpSomethingSomething\n"));
1207 Status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1209 KdPrint((__DRIVER_NAME " <-- XenVbd_Child_PreprocessWdmIrpSomethingSomething\n"));
1211 return Status;
1214 static NTSTATUS
1215 XenVbd_Child_PreprocessWdmIrpSCSI(WDFDEVICE Device, PIRP Irp)
1217 char *DataBuffer;
1218 NTSTATUS status = STATUS_SUCCESS;
1219 PSCSI_REQUEST_BLOCK Srb;
1220 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1221 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1222 KIRQL KIrql;
1223 XenVbd_ListEntry *ListEntry;
1224 int notify;
1225 PCDB cdb;
1226 //PUCHAR Ptr;
1227 ULONG i;
1229 ChildDeviceData = *GetChildDeviceData(Device);
1231 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1232 KdPrint((__DRIVER_NAME " --> WdmIrpPreprocessSCSI\n"));
1234 //KdPrint((__DRIVER_NAME " SCSI Minor = %02X\n", irpSp->MinorFunction));
1236 Srb = irpSp->Parameters.Scsi.Srb;
1238 switch (Srb->Function)
1240 case SRB_FUNCTION_EXECUTE_SCSI:
1241 cdb = (PCDB)Srb->Cdb;
1242 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1243 KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
1244 switch(cdb->CDB6GENERIC.OperationCode) //Srb->Cdb[0])
1246 case SCSIOP_TEST_UNIT_READY:
1247 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1248 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1249 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1250 Srb->ScsiStatus = 0;
1251 status = STATUS_SUCCESS;
1252 Irp->IoStatus.Status = status;
1253 Irp->IoStatus.Information = 0;
1254 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1255 break;
1256 case SCSIOP_INQUIRY:
1257 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1258 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1259 if ((Srb->Cdb[1] & 1) == 0)
1261 memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
1262 DataBuffer = Srb->DataBuffer;
1263 DataBuffer[0] = 0x00; // disk
1264 DataBuffer[1] = 0x00; // not removable
1265 memcpy(DataBuffer + 8, "James ", 8); // vendor id
1266 memcpy(DataBuffer + 16, "XenVBD ", 8); // product id
1267 memcpy(DataBuffer + 32, "000", 8); // product revision level
1268 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1270 else
1272 //KdPrint((__DRIVER_NAME " Command = INQUIRY (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1273 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1275 Srb->ScsiStatus = 0;
1276 status = STATUS_SUCCESS;
1277 Irp->IoStatus.Status = status;
1278 Irp->IoStatus.Information = 0;
1279 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1280 break;
1281 case SCSIOP_READ_CAPACITY:
1282 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1283 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1284 DataBuffer = Srb->DataBuffer;
1285 DataBuffer[0] = (unsigned char)(ChildDeviceData->TotalSectors >> 24) & 0xff;
1286 DataBuffer[1] = (unsigned char)(ChildDeviceData->TotalSectors >> 16) & 0xff;
1287 DataBuffer[2] = (unsigned char)(ChildDeviceData->TotalSectors >> 8) & 0xff;
1288 DataBuffer[3] = (unsigned char)(ChildDeviceData->TotalSectors >> 0) & 0xff;
1289 DataBuffer[4] = (unsigned char)(ChildDeviceData->BytesPerSector >> 24) & 0xff;
1290 DataBuffer[5] = (unsigned char)(ChildDeviceData->BytesPerSector >> 16) & 0xff;
1291 DataBuffer[6] = (unsigned char)(ChildDeviceData->BytesPerSector >> 8) & 0xff;
1292 DataBuffer[7] = (unsigned char)(ChildDeviceData->BytesPerSector >> 0) & 0xff;
1293 Srb->ScsiStatus = 0;
1294 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1295 status = STATUS_SUCCESS;
1296 Irp->IoStatus.Status = status;
1297 Irp->IoStatus.Information = 0;
1298 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1299 break;
1300 case SCSIOP_MODE_SENSE:
1301 KdPrint((__DRIVER_NAME " Command = MODE_SENSE (DBD = %d, PC = %d, Page Code = %02x)\n", Srb->Cdb[1] & 0x10, Srb->Cdb[2] & 0xC0, Srb->Cdb[2] & 0x3F));
1302 KdPrint((__DRIVER_NAME " Length = %d\n", Srb->DataTransferLength));
1304 Srb->ScsiStatus = 0;
1305 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1306 status = STATUS_SUCCESS;
1307 switch(cdb->MODE_SENSE.PageCode) //Srb->Cdb[2] & 0x3F)
1309 case MODE_SENSE_RETURN_ALL:
1310 Irp->IoStatus.Information = 0;
1311 //Ptr = (UCHAR *)Srb->DataBuffer;
1312 for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
1314 if (XenVBD_FillModePage(ChildDeviceData, cdb->MODE_SENSE.PageCode, Srb->DataBuffer, cdb->MODE_SENSE.AllocationLength, &Irp->IoStatus.Information))
1316 break;
1319 break;
1320 default:
1321 XenVBD_FillModePage(ChildDeviceData, cdb->MODE_SENSE.PageCode, Srb->DataBuffer, cdb->MODE_SENSE.AllocationLength, &Irp->IoStatus.Information);
1322 break;
1324 Srb->DataTransferLength = Irp->IoStatus.Information;
1325 Irp->IoStatus.Status = status;
1326 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1327 break;
1328 case SCSIOP_READ:
1329 case SCSIOP_WRITE:
1330 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1331 KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1333 IoMarkIrpPending(Irp);
1335 //KdPrint((__DRIVER_NAME " Irp Acquiring Lock\n"));
1336 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
1337 //KdPrint((__DRIVER_NAME "A Got It\n"));
1339 if (RING_FULL(&ChildDeviceData->Ring))
1341 //KdPrint((__DRIVER_NAME "A Inserting into list\n"));
1342 ListEntry = (XenVbd_ListEntry *)ExAllocatePoolWithTag(NonPagedPool, sizeof(XenVbd_ListEntry), XENVBD_POOL_TAG);
1343 //KdPrint((__DRIVER_NAME " Allocate ListEntry = %08x\n", ListEntry));
1344 if (ListEntry == NULL)
1346 KdPrint((__DRIVER_NAME " CANNOT ALLOCATE MEMORY FOR ListEntry!!!\n"));
1348 ListEntry->Irp = Irp;
1349 InsertTailList(&ChildDeviceData->IrpListHead, &ListEntry->Entry);
1350 ChildDeviceData->IrpAddedToList++;
1352 else
1354 XenVbd_PutIrpOnRing(Device, Irp);
1355 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
1356 if (notify)
1357 EvtChnInterface.Notify(EvtChnInterface.InterfaceHeader.Context,
1358 ChildDeviceData->EventChannel);
1359 //KdPrint((__DRIVER_NAME " WdmIrpPreprocessSCSI (AddedToList = %d, RemovedFromList = %d, AddedToRing = %d, AddedToRingAtLastNotify = %d, AddedToRingAtLastInterrupt = %d, AddedToRingAtLastDpc = %d, RemovedFromRing = %d, IrpCompleted = %d)\n", ChildDeviceData->IrpAddedToList, ChildDeviceData->IrpRemovedFromList, ChildDeviceData->IrpAddedToRing, ChildDeviceData->IrpAddedToRingAtLastNotify, ChildDeviceData->IrpAddedToRingAtLastInterrupt, ChildDeviceData->IrpAddedToRingAtLastDpc, ChildDeviceData->IrpRemovedFromRing, ChildDeviceData->IrpCompleted));
1361 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
1362 status = STATUS_PENDING;
1363 break;
1364 default:
1365 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1366 status = STATUS_NOT_IMPLEMENTED;
1367 Irp->IoStatus.Status = status;
1368 Irp->IoStatus.Information = 0;
1369 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1370 break;
1372 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1373 break;
1374 case SRB_FUNCTION_CLAIM_DEVICE:
1375 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1376 KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
1377 ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
1378 Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
1379 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1380 status = STATUS_SUCCESS;
1381 Irp->IoStatus.Status = status;
1382 Irp->IoStatus.Information = 0;
1383 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1384 break;
1385 case SRB_FUNCTION_IO_CONTROL:
1386 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1387 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1388 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1389 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1390 status = STATUS_NOT_IMPLEMENTED;
1391 //Irp->IoStatus.Status = status;
1392 //Irp->IoStatus.Information = 0;
1393 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1394 break;
1395 case SRB_FUNCTION_FLUSH:
1396 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1397 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1398 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1399 status = STATUS_SUCCESS;
1400 Irp->IoStatus.Status = status;
1401 Irp->IoStatus.Information = 0;
1402 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1403 break;
1404 default:
1405 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1406 status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1407 break;
1410 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1411 KdPrint((__DRIVER_NAME " <-- WdmIrpPreprocessSCSI (AddedToList = %d, RemovedFromList = %d, AddedToRing = %d, AddedToRingAtLastNotify = %d, AddedToRingAtLastInterrupt = %d, RemovedFromRing = %d)\n", ChildDeviceData->IrpAddedToList, ChildDeviceData->IrpRemovedFromList, ChildDeviceData->IrpAddedToRing, ChildDeviceData->IrpAddedToRingAtLastNotify, ChildDeviceData->IrpAddedToRingAtLastInterrupt, ChildDeviceData->IrpCompleted));
1412 //KdPrint((__DRIVER_NAME " <-- WdmIrpPreprocessSCSI\n"));
1414 return status;
1417 static VOID
1418 XenVbd_Child_IoDefault(WDFQUEUE Queue, WDFREQUEST Request)
1420 UNREFERENCED_PARAMETER(Queue);
1422 KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
1424 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1426 KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
1429 static VOID
1430 XenVbd_Child_IoReadWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t Length)
1432 UNREFERENCED_PARAMETER(Queue);
1433 UNREFERENCED_PARAMETER(Length);
1435 KdPrint((__DRIVER_NAME " --> IoReadWrite\n"));
1437 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1439 KdPrint((__DRIVER_NAME " <-- IoReadWrite\n"));
1442 static VOID
1443 XenVbd_Child_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode)
1445 WDFDEVICE Device;
1446 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1447 PIRP Irp;
1448 PSTORAGE_PROPERTY_QUERY Spq;
1449 PSTORAGE_ADAPTER_DESCRIPTOR Sad;
1450 PSTORAGE_DEVICE_DESCRIPTOR Sdd;
1451 PSTORAGE_DEVICE_ID_DESCRIPTOR Sdid;
1452 PSTORAGE_IDENTIFIER Si;
1453 PSCSI_ADDRESS Sa;
1454 ULONG Information;
1455 //NTSTATUS Status;
1456 int StructEndOffset;
1458 UNREFERENCED_PARAMETER(Queue);
1459 //UNREFERENCED_PARAMETER(Request);
1460 UNREFERENCED_PARAMETER(OutputBufferLength);
1461 UNREFERENCED_PARAMETER(InputBufferLength);
1463 Device = WdfIoQueueGetDevice(Queue);
1465 ChildDeviceData = *GetChildDeviceData(Device);
1467 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1468 KdPrint((__DRIVER_NAME " --> IoDeviceControl\n"));
1469 //KdPrint((__DRIVER_NAME " InputBufferLength = %d\n", InputBufferLength));
1470 //KdPrint((__DRIVER_NAME " OutputBufferLength = %d\n", OutputBufferLength));
1472 Irp = WdfRequestWdmGetIrp(Request);
1474 switch (IoControlCode)
1476 case IOCTL_STORAGE_QUERY_PROPERTY:
1477 KdPrint((__DRIVER_NAME " IOCTL_STORAGE_QUERY_PROPERTY\n"));
1478 Spq = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
1479 if (Spq->PropertyId == StorageAdapterProperty && Spq->QueryType == PropertyStandardQuery)
1481 KdPrint((__DRIVER_NAME " PropertyId = StorageAdapterProperty, QueryType = PropertyStandardQuery\n"));
1482 Information = 0;
1483 if (OutputBufferLength >= 8)
1485 Information = 8;
1486 Sad = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1487 Sad->Version = 1;
1488 Sad->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
1489 if (OutputBufferLength >= Sad->Size)
1491 Information = Sad->Size;
1492 Sad->MaximumTransferLength = 45056;
1493 Sad->MaximumPhysicalPages = 11;
1494 Sad->AlignmentMask = 0;
1495 Sad->AdapterUsesPio = FALSE;
1496 Sad->AdapterScansDown = FALSE;
1497 Sad->CommandQueueing = FALSE;
1498 Sad->AcceleratedTransfer = FALSE;
1499 Sad->BusType = BusTypeScsi;
1500 Sad->BusMajorVersion = 0;
1501 Sad->BusMinorVersion = 0;
1504 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Information);
1506 else if (Spq->PropertyId == StorageDeviceProperty && Spq->QueryType == PropertyStandardQuery)
1508 KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceProperty, QueryType = PropertyStandardQuery\n"));
1509 Information = 0;
1510 if (OutputBufferLength >= 8)
1512 Information = 8;
1513 Sdd = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1514 Sdd->Version = 1;
1515 Sdd->Size = &Sdd->RawDeviceProperties[36] - (PUCHAR)Sdd + 1;
1516 // 0 0 1 2 3
1517 // 0 7 5 4 1
1518 //"VENDOR\0PRODUCT\0Revision\0Serial\0"
1519 if (OutputBufferLength >= Sdd->Size)
1521 Information = Sdd->Size;
1522 switch (ChildDeviceData->DeviceType)
1524 case XENVBD_DEVICETYPE_DISK:
1525 Sdd->DeviceType = DIRECT_ACCESS_DEVICE;
1526 Sdd->DeviceTypeModifier = 0x00;
1527 Sdd->RemovableMedia = FALSE;
1528 break;
1529 case XENVBD_DEVICETYPE_CDROM:
1530 Sdd->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1531 Sdd->DeviceTypeModifier = 0x00;
1532 Sdd->RemovableMedia = TRUE;
1533 break;
1534 default:
1535 // wtf
1536 break;
1538 Sdd->CommandQueueing = FALSE;
1539 StructEndOffset = Sdd->RawDeviceProperties - (PUCHAR)Sdd;
1540 Sdd->VendorIdOffset = StructEndOffset + 0;
1541 Sdd->ProductIdOffset = StructEndOffset + 7;
1542 Sdd->ProductRevisionOffset = StructEndOffset + 15;
1543 Sdd->SerialNumberOffset = StructEndOffset + 24;
1544 Sdd->BusType = BusTypeScsi;
1545 Sdd->RawPropertiesLength = 36;
1546 memcpy(Sdd->RawDeviceProperties, "VENDOR\0PRODUCT\0Revision\0Serial99999\0", 36);
1549 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Information);
1551 else if (Spq->PropertyId == StorageDeviceIdProperty && Spq->QueryType == PropertyStandardQuery)
1553 KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceIdProperty, QueryType = PropertyStandardQuery\n"));
1554 Information = 0;
1555 if (OutputBufferLength >= 8)
1557 Information = 8;
1558 Sdid = (PSTORAGE_DEVICE_ID_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1559 Sdid->Version = 1;
1560 Si = (PSTORAGE_IDENTIFIER)Sdid->Identifiers;
1561 Sdid->Size = &Si->Identifier[8] - (PUCHAR)Sdid + 1;
1562 if (OutputBufferLength >= Sdid->Size)
1564 Information = Sdid->Size;
1565 Sdid->NumberOfIdentifiers = 1;
1566 Si->CodeSet = StorageIdCodeSetAscii;
1567 Si->Type = StorageIdTypeScsiNameString;
1568 //Si->CodeSet = StorageIdCodeSetBinary;
1569 //Si->Type = StorageIdTypeEUI64;
1570 Si->IdentifierSize = 9;
1571 Si->NextOffset = 0;
1572 Si->Association = StorageIdAssocPort;
1573 Si->Identifier[0] = 'S';
1574 Si->Identifier[1] = 'e';
1575 Si->Identifier[2] = 'r';
1576 Si->Identifier[3] = 'i';
1577 Si->Identifier[4] = 'a';
1578 Si->Identifier[5] = 'l';
1579 Si->Identifier[6] = '9';
1580 Si->Identifier[7] = '9';
1581 Si->Identifier[6] = '9';
1582 Si->Identifier[7] = '9';
1583 Si->Identifier[8] = '9';
1584 //Si->Identifier[8] = 0;
1587 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Information);
1589 else
1591 switch (Spq->PropertyId)
1593 case StorageDeviceProperty:
1594 KdPrint((__DRIVER_NAME " StorageDeviceProperty\n"));
1595 break;
1596 case StorageAccessAlignmentProperty:
1597 KdPrint((__DRIVER_NAME " StorageAccessAlignmentProperty\n"));
1598 break;
1599 case StorageAdapterProperty:
1600 KdPrint((__DRIVER_NAME " StorageAdapterProperty\n"));
1601 break;
1602 case StorageDeviceIdProperty:
1603 KdPrint((__DRIVER_NAME " StorageDeviceIdProperty\n"));
1604 break;
1605 case StorageDeviceUniqueIdProperty:
1606 KdPrint((__DRIVER_NAME " StorageDeviceUniqueIdProperty\n"));
1607 break;
1608 case StorageDeviceWriteCacheProperty:
1609 KdPrint((__DRIVER_NAME " StorageDeviceWriteCacheProperty\n"));
1610 break;
1611 default:
1612 KdPrint((__DRIVER_NAME " Unknown Property %08x\n", Spq->PropertyId));
1613 break;
1615 switch (Spq->QueryType)
1617 case PropertyStandardQuery:
1618 KdPrint((__DRIVER_NAME " PropertyStandardQuery\n"));
1619 break;
1620 case PropertyExistsQuery:
1621 KdPrint((__DRIVER_NAME " PropertyExistsQuery\n"));
1622 break;
1623 default:
1624 KdPrint((__DRIVER_NAME " Unknown Query %08x\n", Spq->QueryType));
1625 break;
1627 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1629 break;
1630 // http://www.osronline.com/article.cfm?article=229
1631 // 0x00560030 device = 0x56, Function = 0x00c =
1632 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
1633 KdPrint((__DRIVER_NAME " IOCTL_DISK_GET_DRIVE_GEOMETRY\n"));
1634 memcpy(Irp->AssociatedIrp.SystemBuffer, &ChildDeviceData->Geometry, sizeof(DISK_GEOMETRY));
1635 WdfRequestComplete(Request, STATUS_SUCCESS);
1636 break;
1637 case IOCTL_SCSI_GET_ADDRESS:
1638 KdPrint((__DRIVER_NAME " IOCTL_SCSI_GET_ADDRESS\n"));
1639 Sa = (PSCSI_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1640 Sa->Length = sizeof(SCSI_ADDRESS);
1641 Sa->PortNumber = 0;
1642 Sa->PathId = 0;
1643 Sa->TargetId = 0;
1644 Sa->Lun = 0;
1645 WdfRequestComplete(Request, STATUS_SUCCESS);
1646 break;
1647 case FT_BALANCED_READ_MODE: // just pretend we know what this is...
1648 KdPrint((__DRIVER_NAME " FT_BALANCED_READ_MODE\n"));
1649 WdfRequestComplete(Request, STATUS_SUCCESS);
1650 break;
1651 default:
1652 KdPrint((__DRIVER_NAME " Not Implemented IoControlCode=%08X\n", IoControlCode));
1653 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1654 break;
1657 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1658 KdPrint((__DRIVER_NAME " <-- IoDeviceControl\n"));
1661 static VOID
1662 XenVbd_Child_IoInternalDeviceControl(
1663 WDFQUEUE Queue,
1664 WDFREQUEST Request,
1665 size_t OutputBufferLength,
1666 size_t InputBufferLength,
1667 ULONG IoControlCode)
1669 UNREFERENCED_PARAMETER(Queue);
1670 UNREFERENCED_PARAMETER(Request);
1671 UNREFERENCED_PARAMETER(OutputBufferLength);
1672 UNREFERENCED_PARAMETER(InputBufferLength);
1673 UNREFERENCED_PARAMETER(IoControlCode);
1675 KdPrint((__DRIVER_NAME " --> IoInternalDeviceControl\n"));
1676 KdPrint((__DRIVER_NAME " <-- IoInternalDeviceControl\n"));