win-pvdrivers

view xenvbd/xenvbd.c @ 37:3ac5c4431dbb

manual merge
author Andy Grover <andy.grover@oracle.com>
date Wed Dec 05 11:14:28 2007 -0800 (2007-12-05)
parents 2e1d570b69e9 f56c47274c37
children 48261a2e2038
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_PreprocessWdmIrpDEVICE_CONTROL(WDFDEVICE Device, PIRP Irp);
50 static NTSTATUS
51 XenVbd_Child_PreprocessWdmIrpSomethingSomething(WDFDEVICE Device, PIRP Irp);
53 static VOID
54 XenVbd_HotPlugHandler(char *Path, PVOID Data);
56 #ifdef ALLOC_PRAGMA
57 #pragma alloc_text (INIT, DriverEntry)
58 #pragma alloc_text (PAGE, XenVbd_AddDevice)
59 #endif
61 #pragma warning(disable: 4127) // disable conditional expression is constant
63 LIST_ENTRY DeviceListHead;
64 XEN_IFACE_EVTCHN EvtChnInterface;
65 XEN_IFACE_XENBUS XenBusInterface;
66 XEN_IFACE_XEN XenInterface;
67 XEN_IFACE_GNTTBL GntTblInterface;
69 static BOOLEAN AutoEnumerate;
71 NTSTATUS
72 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
73 {
74 WDF_DRIVER_CONFIG config;
75 ULONG status;
76 UNICODE_STRING RegKeyName;
77 UNICODE_STRING RegValueName;
78 HANDLE RegHandle;
79 OBJECT_ATTRIBUTES RegObjectAttributes;
80 char Buf[200];
81 ULONG BufLen = 200;
82 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
83 int State = 0;
84 int StartPos = 0;
85 WCHAR *SystemStartOptions;
86 size_t SystemStartOptionsLen;
87 size_t i;
89 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
91 WDF_DRIVER_CONFIG_INIT(&config, XenVbd_AddDevice);
92 status = WdfDriverCreate(
93 DriverObject,
94 RegistryPath,
95 WDF_NO_OBJECT_ATTRIBUTES,
96 &config,
97 WDF_NO_HANDLE);
98 if(!NT_SUCCESS(status))
99 {
100 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%08x\n", status));
101 }
103 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
104 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
105 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
106 if(!NT_SUCCESS(status))
107 {
108 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
109 }
111 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
112 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
113 if(!NT_SUCCESS(status))
114 {
115 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
116 }
117 //KdPrint((__DRIVER_NAME " BufLen = %d\n", BufLen));
118 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
119 KdPrint((__DRIVER_NAME " Buf = %ws\n", KeyPartialValue->Data));
120 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
122 AutoEnumerate = FALSE;
124 RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
126 for (i = 0; i <= SystemStartOptionsLen/2; i++)
127 {
128 //KdPrint((__DRIVER_NAME " pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
130 switch (State)
131 {
132 case 0:
133 if (SystemStartOptions[i] == L'G')
134 {
135 StartPos = i;
136 State = 2;
137 } else if (SystemStartOptions[i] != L' ')
138 {
139 State = 1;
140 }
141 break;
142 case 1:
143 if (SystemStartOptions[i] == L' ')
144 State = 0;
145 break;
146 case 2:
147 if (SystemStartOptions[i] == L'P')
148 State = 3;
149 else
150 State = 0;
151 break;
152 case 3:
153 if (SystemStartOptions[i] == L'L')
154 State = 4;
155 else
156 State = 0;
157 break;
158 case 4:
159 if (SystemStartOptions[i] == L'P')
160 State = 5;
161 else
162 State = 0;
163 break;
164 case 5:
165 if (SystemStartOptions[i] == L'V')
166 State = 6;
167 else
168 State = 0;
169 break;
170 case 6:
171 if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
172 AutoEnumerate = TRUE;
173 State = 0;
174 break;
175 }
176 }
178 KdPrint((__DRIVER_NAME " AutoEnumerate = %d\n", AutoEnumerate));
180 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
182 return status;
183 }
185 static WDFDEVICE GlobalDevice;
186 static PDEVICE_OBJECT Pdo;
188 static NTSTATUS
189 XenVbd_AddDevice(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
190 {
191 WDF_CHILD_LIST_CONFIG ChildListConfig;
192 NTSTATUS status;
193 WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
195 UNREFERENCED_PARAMETER(Driver);
197 KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
199 Pdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit);
201 //WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
202 WDF_CHILD_LIST_CONFIG_INIT(&ChildListConfig, sizeof(XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION), XenVbd_ChildListCreateDevice);
203 WdfFdoInitSetDefaultChildListConfig(DeviceInit, &ChildListConfig, WDF_NO_OBJECT_ATTRIBUTES);
205 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_CONTROLLER);
206 //WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
207 WdfDeviceInitSetExclusive(DeviceInit, FALSE);
209 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
210 pnpPowerCallbacks.EvtDevicePrepareHardware = XenVbd_PrepareHardware;
211 pnpPowerCallbacks.EvtDeviceReleaseHardware = XenVbd_ReleaseHardware;
212 pnpPowerCallbacks.EvtDeviceD0Entry = XenVbd_D0Entry;
213 pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenVbd_D0EntryPostInterruptsEnabled;
214 pnpPowerCallbacks.EvtDeviceD0Exit = XenVbd_D0Exit;
215 pnpPowerCallbacks.EvtDeviceUsageNotification = XenVbd_DeviceUsageNotification;
216 WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
218 /*initialize storage for the device context*/
219 //WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENVBD_DEVICE_DATA);
221 //WdfDeviceInitSetPowerNotPageable(DeviceInit);
223 /*create a device instance.*/
224 status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &GlobalDevice);
225 if(!NT_SUCCESS(status))
226 {
227 KdPrint((__DRIVER_NAME "WdfDeviceCreate failed with status 0x%08x\n", status));
228 return status;
229 }
231 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFilePaging, TRUE);
232 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFileHibernation, TRUE);
233 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFileDump, TRUE);
235 status = STATUS_SUCCESS;
237 KdPrint((__DRIVER_NAME " <-- DeviceAdd\n"));
238 return status;
239 }
241 static NTSTATUS
242 XenVbd_PrepareHardware(
243 IN WDFDEVICE Device,
244 IN WDFCMRESLIST ResourceList,
245 IN WDFCMRESLIST ResourceListTranslated)
246 {
247 NTSTATUS status = STATUS_SUCCESS;
249 UNREFERENCED_PARAMETER(ResourceList);
250 UNREFERENCED_PARAMETER(ResourceListTranslated);
252 //KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware\n"));
254 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_EVTCHN, (PINTERFACE) &EvtChnInterface, sizeof(XEN_IFACE_EVTCHN), 1, NULL);
255 if(!NT_SUCCESS(status))
256 {
257 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (EvtChn) failed with status 0x%08x\n", status));
258 }
260 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XENBUS, (PINTERFACE)&XenBusInterface, sizeof(XEN_IFACE_XENBUS), 1, NULL);
261 if(!NT_SUCCESS(status))
262 {
263 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (XenBus) failed with status 0x%08x\n", status));
264 }
266 #if 0 // not used yet
267 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XEN, (PINTERFACE)&XenInterface, sizeof(XEN_IFACE_XEN), 1, NULL);
268 if(!NT_SUCCESS(status))
269 {
270 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (Xen) failed with status 0x%08x\n", status));
271 }
272 #endif
274 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_GNTTBL, (PINTERFACE)&GntTblInterface, sizeof(XEN_IFACE_GNTTBL), 1, NULL);
275 if(!NT_SUCCESS(status))
276 {
277 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (GntTbl) failed with status 0x%08x\n", status));
278 }
280 //KdPrint((__DRIVER_NAME " <-- EvtDevicePrepareHardware\n"));
282 InitializeListHead(&DeviceListHead);
284 return status;
285 }
287 static NTSTATUS
288 XenVbd_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated)
289 {
290 UNREFERENCED_PARAMETER(Device);
291 UNREFERENCED_PARAMETER(ResourcesTranslated);
293 // release interfaces here...
295 //XenVbd_Close();
297 return STATUS_SUCCESS;
298 }
300 static NTSTATUS
301 XenVbd_D0Entry(
302 IN WDFDEVICE Device,
303 IN WDF_POWER_DEVICE_STATE PreviousState
304 )
305 {
306 NTSTATUS status = STATUS_SUCCESS;
308 UNREFERENCED_PARAMETER(Device);
309 UNREFERENCED_PARAMETER(PreviousState);
311 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Entry\n"));
313 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
315 return status;
316 }
318 static LONG EnumeratedDevices;
319 static KEVENT WaitDevicesEvent;
321 static NTSTATUS
322 XenVbd_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
323 {
324 //OBJECT_ATTRIBUTES oa;
325 NTSTATUS status = STATUS_SUCCESS;
326 //HANDLE nothing;
327 //char *response;
328 PXENPCI_XEN_DEVICE_DATA PdoDeviceData;
329 char **VbdDevices;
330 char *msg;
331 char buffer[128];
332 int i;
333 LARGE_INTEGER WaitTimeout;
335 UNREFERENCED_PARAMETER(Device);
336 UNREFERENCED_PARAMETER(PreviousState);
338 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0EntryPostInterruptsEnabled\n"));
340 PdoDeviceData = (PXENPCI_XEN_DEVICE_DATA)Pdo->DeviceExtension; //GetXenDeviceData(Device);
342 //KdPrint((__DRIVER_NAME " BasePath = %s\n", PdoDeviceData->BasePath));
343 PdoDeviceData->WatchHandler = XenVbd_HotPlugHandler;
345 EnumeratedDevices = 0;
346 KeInitializeEvent(&WaitDevicesEvent, SynchronizationEvent, FALSE);
348 // TODO: Should probably do this in an EvtChildListScanForChildren
349 if (AutoEnumerate)
350 {
351 msg = XenBusInterface.List(XenBusInterface.InterfaceHeader.Context,
352 XBT_NIL, "device/vbd", &VbdDevices);
353 if (!msg) {
354 for (i = 0; VbdDevices[i]; i++)
355 {
356 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
357 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
358 XenVbd_HotPlugHandler(buffer, NULL);
359 //ExFreePoolWithTag(bdDevices[i], XENPCI_POOL_TAG);
360 }
361 KdPrint((__DRIVER_NAME " Waiting for devices to be enumerated\n"));
362 while (EnumeratedDevices != i)
363 {
364 WaitTimeout.QuadPart = -600000000;
365 if (KeWaitForSingleObject(&WaitDevicesEvent, Executive, KernelMode, FALSE, &WaitTimeout) == STATUS_TIMEOUT)
366 {
367 KdPrint((__DRIVER_NAME " Wait timed out\n"));
368 break;
369 }
370 KdPrint((__DRIVER_NAME " %d out of %d devices enumerated\n", EnumeratedDevices, i));
371 }
372 }
373 }
375 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0EntryPostInterruptsEnabled\n"));
377 return status;
378 }
380 static NTSTATUS
381 XenVbd_D0Exit(
382 IN WDFDEVICE Device,
383 IN WDF_POWER_DEVICE_STATE TargetState
384 )
385 {
386 NTSTATUS status = STATUS_SUCCESS;
387 //char *response;
389 UNREFERENCED_PARAMETER(Device);
390 UNREFERENCED_PARAMETER(TargetState);
392 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Exit\n"));
394 //response = XenBusInterface.RemWatch(XBT_NIL, XenBusInterface.InterfaceHeader.Context, XenVbd_HotPlugHandler, NULL);
396 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Exit\n"));
398 return status;
399 }
401 static NTSTATUS
402 XenVbd_DeviceUsageNotification(
403 WDFDEVICE Device,
404 WDF_SPECIAL_FILE_TYPE NotificationType,
405 BOOLEAN IsInNotificationPath)
406 {
407 UNREFERENCED_PARAMETER(Device);
409 // KdPrint((__DRIVER_NAME " --> DeviceUsageNotification\n"));
411 switch (NotificationType)
412 {
413 case WdfSpecialFilePaging:
414 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFilePaging, Using = %d\n", IsInNotificationPath));
415 break;
416 case WdfSpecialFileHibernation:
417 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFileHibernation, Using = %d\n", IsInNotificationPath));
418 break;
419 case WdfSpecialFileDump:
420 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFileDump, Using = %d\n", IsInNotificationPath));
421 break;
422 default:
423 KdPrint((__DRIVER_NAME " NotificationType = %d, Using = %d\n", NotificationType, IsInNotificationPath));
424 break;
425 }
426 // KdPrint((__DRIVER_NAME " <-- DeviceUsageNotification\n"));
428 return TRUE;
429 }
431 static VOID
432 XenVbd_IoDefault(
433 IN WDFQUEUE Queue,
434 IN WDFREQUEST Request
435 )
436 {
437 UNREFERENCED_PARAMETER(Queue);
439 //KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
441 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
443 //KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
444 }
446 static __inline uint64_t
447 GET_ID_FROM_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData)
448 {
449 uint64_t free;
451 free = ChildDeviceData->shadow_free;
453 //KdPrint((__DRIVER_NAME " A free = %d\n", free));
455 ChildDeviceData->shadow_free = ChildDeviceData->shadow[free].req.id;
457 //KdPrint((__DRIVER_NAME " A shadow_free now = %d\n", ChildDeviceData->shadow_free));
459 ChildDeviceData->shadow[free].req.id = 0x0fffffee; /* debug */
460 return free;
461 }
463 static __inline VOID
464 ADD_ID_TO_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, uint64_t Id)
465 {
466 ChildDeviceData->shadow[Id].req.id = ChildDeviceData->shadow_free;
467 ChildDeviceData->shadow[Id].Irp = NULL;
468 ChildDeviceData->shadow_free = Id;
469 }
471 static VOID
472 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp);
474 static PMDL
475 AllocatePages(int Pages)
476 {
477 PMDL Mdl;
478 PVOID Buf;
480 Buf = ExAllocatePoolWithTag(NonPagedPool, Pages * PAGE_SIZE, XENVBD_POOL_TAG);
481 if (Buf == NULL)
482 {
483 KdPrint((__DRIVER_NAME " AllocatePages Failed at ExAllocatePoolWithTag\n"));
484 }
485 Mdl = IoAllocateMdl(Buf, Pages * PAGE_SIZE, FALSE, FALSE, NULL);
486 if (Mdl == NULL)
487 {
488 KdPrint((__DRIVER_NAME " AllocatePages Failed at IoAllocateMdl\n"));
489 }
490 MmBuildMdlForNonPagedPool(Mdl);
492 return Mdl;
493 }
495 static PMDL
496 AllocatePage()
497 {
498 return AllocatePages(1);
499 }
501 static VOID
502 FreePages(PMDL Mdl)
503 {
504 PVOID Buf = MmGetMdlVirtualAddress(Mdl);
505 //KdPrint((__DRIVER_NAME " FreePages Failed at IoAllocateMdl\n"));
506 //KdPrint((__DRIVER_NAME " FreePages Buf = %08x\n", Buf));
507 IoFreeMdl(Mdl);
508 ExFreePoolWithTag(Buf, XENVBD_POOL_TAG);
509 }
511 static VOID
512 XenVbd_DpcThreadProc(WDFDPC Dpc)
513 {
514 PIRP Irp;
515 RING_IDX i, rp;
516 int j;
517 blkif_response_t *rep;
518 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
519 PSCSI_REQUEST_BLOCK Srb;
520 PIO_STACK_LOCATION IrpSp;
521 char *DataBuffer;
522 int more_to_do;
523 int IrpCount;
524 PIRP Irps[100];
525 int BlockCount;
526 KIRQL KIrql;
527 WDFDEVICE ChildDevice;
528 XenVbd_ListEntry *ListEntry;
529 int notify;
531 //!!!IRQL_DISPATCH!!!
533 //KdPrint((__DRIVER_NAME " --> XenVbd_DpcThreadProc\n"));
535 ChildDevice = WdfDpcGetParentObject(Dpc);
537 ChildDeviceData = *GetChildDeviceData(ChildDevice);
539 IrpCount = 0;
540 more_to_do = TRUE;
541 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
543 ChildDeviceData->IrpAddedToRingAtLastDpc = ChildDeviceData->IrpAddedToRing;
545 while (more_to_do)
546 {
547 rp = ChildDeviceData->Ring.sring->rsp_prod;
548 KeMemoryBarrier();
549 for (i = ChildDeviceData->Ring.rsp_cons; i != rp; i++)
550 {
551 rep = RING_GET_RESPONSE(&ChildDeviceData->Ring, i);
552 ChildDeviceData->IrpRemovedFromRing++;
553 Irp = ChildDeviceData->shadow[rep->id].Irp;
554 IrpSp = IoGetCurrentIrpStackLocation(Irp);
555 Srb = IrpSp->Parameters.Scsi.Srb;
557 if (rep->status != BLKIF_RSP_OKAY)
558 {
559 KdPrint((__DRIVER_NAME " Xen Operation returned error in DpcThreadProc\n"));
560 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));
561 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
562 {
563 KdPrint((__DRIVER_NAME " gref[%d] = %d\n", j, ChildDeviceData->shadow[rep->id].req.seg[j].gref));
564 }
565 KdPrint((__DRIVER_NAME " MmGetMdlByteOffset = %d\n", MmGetMdlByteOffset(Irp->MdlAddress)));
566 }
567 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
568 {
569 GntTblInterface.EndAccess(GntTblInterface.InterfaceHeader.Context,
570 ChildDeviceData->shadow[rep->id].req.seg[j].gref);
571 }
572 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
573 if (ChildDeviceData->shadow[rep->id].Buf != NULL)
574 {
575 if (Srb->Cdb[0] == SCSIOP_READ)
576 {
577 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
578 if (DataBuffer == NULL)
579 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe Failed in DpcThreadProc\n"));
580 memcpy(DataBuffer, ChildDeviceData->shadow[rep->id].Buf, BlockCount * ChildDeviceData->BytesPerSector);
581 }
582 FreePages(ChildDeviceData->shadow[rep->id].Mdl);
583 }
584 Srb->SrbStatus = SRB_STATUS_SUCCESS;
585 Srb->ScsiStatus = 0;
586 Irp->IoStatus.Status = STATUS_SUCCESS;
587 Irp->IoStatus.Information = BlockCount * ChildDeviceData->BytesPerSector;
589 Irps[IrpCount++] = Irp;
591 ADD_ID_TO_FREELIST(ChildDeviceData, rep->id);
592 }
594 ChildDeviceData->Ring.rsp_cons = i;
595 if (i != ChildDeviceData->Ring.req_prod_pvt)
596 {
597 RING_FINAL_CHECK_FOR_RESPONSES(&ChildDeviceData->Ring, more_to_do);
598 }
599 else
600 {
601 ChildDeviceData->Ring.sring->rsp_event = i + 1;
602 more_to_do = FALSE;
603 }
604 }
606 notify = 0;
607 while (!RING_FULL(&ChildDeviceData->Ring) && (ListEntry = (XenVbd_ListEntry *)RemoveHeadList(&ChildDeviceData->IrpListHead)) != (XenVbd_ListEntry *)&ChildDeviceData->IrpListHead)
608 {
609 ChildDeviceData->IrpRemovedFromList++;
610 XenVbd_PutIrpOnRing(ChildDevice, ListEntry->Irp);
611 ExFreePoolWithTag(ListEntry, XENVBD_POOL_TAG);
612 notify = 1;
613 }
614 if (notify)
615 {
616 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
617 if (notify)
618 EvtChnInterface.Notify(EvtChnInterface.InterfaceHeader.Context,
619 ChildDeviceData->EventChannel);
620 }
621 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
623 for (j = 0; j < IrpCount; j++)
624 {
625 IoCompleteRequest(Irps[j], IO_NO_INCREMENT);
626 ChildDeviceData->IrpCompleted++;
627 }
629 //KdPrint((__DRIVER_NAME " <-- XenVbd_DpcThreadProc\n"));
630 //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));
631 }
633 static BOOLEAN
634 XenVbd_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
635 {
636 BOOLEAN RetVal;
637 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
639 UNREFERENCED_PARAMETER(Interrupt);
640 // !!!RUNS AT DIRQL!!!
642 //KdPrint((__DRIVER_NAME " --> XenVbd_Interrupt\n"));
644 ChildDeviceData = (PXENVBD_CHILD_DEVICE_DATA)ServiceContext;
645 ChildDeviceData->IrpAddedToRingAtLastInterrupt = ChildDeviceData->IrpAddedToRing;
646 RetVal = WdfDpcEnqueue(ChildDeviceData->Dpc);
648 //KdPrint((__DRIVER_NAME " <-- XenVbd_Interrupt (RetVal = %d)\n", RetVal));
650 return STATUS_SUCCESS;
651 }
653 static VOID
654 XenVbd_BackEndStateHandler(char *Path, PVOID Data)
655 {
656 PXENVBD_CHILD_DEVICE_DATA DeviceData = Data;
657 char TmpPath[128];
658 char *Value;
659 int NewState;
660 PMDL Mdl;
661 grant_ref_t ref;
662 blkif_sring_t *SharedRing;
663 ULONG PFN;
664 XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION Description;
665 NTSTATUS status;
667 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
668 XBT_NIL, Path, &Value);
669 NewState = atoi(Value);
670 ExFreePool(Value);
672 switch (NewState)
673 {
674 case XenbusStateUnknown:
675 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
676 break;
678 case XenbusStateInitialising:
679 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
680 break;
682 case XenbusStateInitWait:
683 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
685 DeviceData->EventChannel = EvtChnInterface.AllocUnbound(
686 EvtChnInterface.InterfaceHeader.Context, 0);
687 EvtChnInterface.Bind(EvtChnInterface.InterfaceHeader.Context,
688 DeviceData->EventChannel, XenVbd_Interrupt, DeviceData);
689 Mdl = AllocatePage();
690 PFN = *MmGetMdlPfnArray(Mdl);
691 SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
692 SHARED_RING_INIT(SharedRing);
693 FRONT_RING_INIT(&DeviceData->Ring, SharedRing, PAGE_SIZE);
694 ref = GntTblInterface.GrantAccess(GntTblInterface.InterfaceHeader.Context,
695 0, PFN, FALSE);
697 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
698 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/ring-ref");
699 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
700 XBT_NIL, TmpPath, "%d", ref);
702 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
703 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/event-channel");
704 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
705 XBT_NIL, TmpPath, "%d", DeviceData->EventChannel);
707 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
708 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/state");
709 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
710 XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
712 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
713 break;
715 case XenbusStateInitialised:
716 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
717 // create the device
718 break;
720 case XenbusStateConnected:
721 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
723 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Description.Header, sizeof(Description));
725 Description.DeviceData = DeviceData;
727 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
728 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/device-type");
729 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
730 XBT_NIL, TmpPath, &Value);
731 if (strcmp(Value, "disk") == 0)
732 {
733 KdPrint((__DRIVER_NAME " DeviceType = Disk\n"));
734 DeviceData->DeviceType = XENVBD_DEVICETYPE_DISK;
735 }
736 else if (strcmp(Value, "cdrom") == 0)
737 {
738 KdPrint((__DRIVER_NAME " DeviceType = CDROM\n"));
739 DeviceData->DeviceType = XENVBD_DEVICETYPE_CDROM;
740 }
741 else
742 {
743 KdPrint((__DRIVER_NAME " DeviceType = %s (This probably won't work!)\n", Value));
744 }
746 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
747 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/type"); // should probably check that this is 'phy' or 'file' or at least not ''
748 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
749 XBT_NIL, TmpPath, &Value);
750 KdPrint((__DRIVER_NAME " Backend Type = %s\n", Value));
751 ExFreePool(Value);
753 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
754 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/mode"); // should store this...
755 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
756 XBT_NIL, TmpPath, &Value);
757 KdPrint((__DRIVER_NAME " Backend Mode = %s\n", Value));
758 ExFreePool(Value);
760 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
761 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/sector-size");
762 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
763 XBT_NIL, TmpPath, &Value);
764 // should complain if Value == NULL
765 DeviceData->BytesPerSector = atoi(Value);
766 ExFreePool(Value);
768 KdPrint((__DRIVER_NAME " BytesPerSector = %d\n", DeviceData->BytesPerSector));
770 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
771 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/sectors");
772 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
773 XBT_NIL, TmpPath, &Value);
774 // should complain if Value == NULL
775 DeviceData->TotalSectors = (ULONGLONG)atol(Value);
776 ExFreePool(Value);
778 KdPrint((__DRIVER_NAME " TotalSectors = %d\n", DeviceData->TotalSectors));
780 // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
781 DeviceData->Geometry.MediaType = FixedMedia;
782 DeviceData->Geometry.BytesPerSector = DeviceData->BytesPerSector;
783 DeviceData->Geometry.SectorsPerTrack = 63;
784 DeviceData->Geometry.TracksPerCylinder = 255;
785 DeviceData->Geometry.Cylinders.QuadPart = DeviceData->TotalSectors / DeviceData->Geometry.SectorsPerTrack / DeviceData->Geometry.TracksPerCylinder;
786 KdPrint((__DRIVER_NAME " Geometry C/H/S = %d/%d/%d\n", DeviceData->Geometry.Cylinders.LowPart, DeviceData->Geometry.TracksPerCylinder, DeviceData->Geometry.SectorsPerTrack));
788 // if we detected something wrong, we should not enumarate the device and should instead initiate a close
790 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(WdfFdoGetDefaultChildList(GlobalDevice), &Description.Header, NULL);
791 if (!NT_SUCCESS(status))
792 {
793 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed %08x\n", status));
794 }
796 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
797 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/state");
798 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
799 XBT_NIL, TmpPath, "%d", XenbusStateConnected);
801 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
802 InterlockedIncrement(&EnumeratedDevices);
803 KdPrint((__DRIVER_NAME " Added a device, notifying\n"));
805 KeSetEvent(&WaitDevicesEvent, 1, FALSE);
807 break;
809 case XenbusStateClosing:
810 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
811 break;
813 case XenbusStateClosed:
814 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
815 break;
817 default:
818 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
819 break;
820 }
821 }
823 static VOID
824 XenVbd_HotPlugHandler(char *Path, PVOID Data)
825 {
826 PXENVBD_CHILD_DEVICE_DATA DeviceData;
827 char **Bits;
828 int Count;
829 char TmpPath[128];
830 char *Value;
832 UNREFERENCED_PARAMETER(Data);
834 //KdPrint((__DRIVER_NAME " --> HotPlugHandler\n"));
836 //KdPrint((__DRIVER_NAME " Path = %s\n", Path));
838 Bits = SplitString(Path, '/', 4, &Count);
839 if (Count != 4)
840 {
841 KdPrint((__FUNCTION__ ": Count = %d, not 4!\n", Count));
842 goto cleanup;
843 }
845 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
846 goto cleanup;
848 /* ignore already known devices */
849 for (DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceListHead.Flink; DeviceData != (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead; DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceData->Entry.Flink)
850 {
851 if (strncmp(DeviceData->Path, Path, strlen(DeviceData->Path)) == 0 && Path[strlen(DeviceData->Path)] == '/')
852 {
853 goto cleanup;
854 }
855 }
857 /* new device found, alloc and init dev extension */
858 DeviceData = ExAllocatePoolWithTag(NonPagedPool,
859 sizeof(XENVBD_CHILD_DEVICE_DATA), XENVBD_POOL_TAG);
860 memset(DeviceData, 0, sizeof(XENVBD_CHILD_DEVICE_DATA));
862 //KdPrint((__DRIVER_NAME " Allocated ChildDeviceData = %08x\n", DeviceData));
864 InsertTailList(&DeviceListHead, &DeviceData->Entry);
865 RtlStringCbPrintfA(DeviceData->Path, ARRAY_SIZE(DeviceData->Path),
866 "%s/%s/%s", Bits[0], Bits[1], Bits[2]);
867 DeviceData->DeviceIndex = atoi(Bits[2]);
869 /* Get backend path */
870 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
871 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/backend");
872 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
873 XBT_NIL, TmpPath, &Value);
874 if (!Value)
875 {
876 KdPrint((__DRIVER_NAME " Read Failed\n"));
877 }
878 else
879 {
880 RtlStringCbCopyA(DeviceData->BackendPath,
881 ARRAY_SIZE(DeviceData->BackendPath), Value);
882 }
883 ExFreePool(Value);
885 /* Add watch on backend state */
886 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
887 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/state");
888 XenBusInterface.AddWatch(XenBusInterface.InterfaceHeader.Context,
889 XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, DeviceData);
891 cleanup:
892 FreeSplitString(Bits, Count);
894 //KdPrint((__DRIVER_NAME " <-- HotPlugHandler\n"));
895 }
897 static NTSTATUS
898 XenVbd_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit)
899 {
900 NTSTATUS status;
901 WDFDEVICE ChildDevice;
902 PXENVBD_DEVICE_IDENTIFICATION_DESCRIPTION XenVbdIdentificationDesc;
903 DECLARE_UNICODE_STRING_SIZE(buffer, 50);
904 WDF_OBJECT_ATTRIBUTES PdoAttributes;
905 DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
906 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
907 WDF_IO_QUEUE_CONFIG IoQueueConfig;
908 unsigned int i;
909 WDF_DPC_CONFIG DpcConfig;
910 WDF_OBJECT_ATTRIBUTES DpcObjectAttributes;
911 WDF_DEVICE_STATE DeviceState;
912 //UCHAR ScsiMinors[1] = { IRP_MN_SCSI_CLASS };
914 UNREFERENCED_PARAMETER(ChildList);
916 KdPrint((__DRIVER_NAME " --> ChildListCreateDevice\n"));
918 XenVbdIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION, Header);
920 ChildDeviceData = XenVbdIdentificationDesc->DeviceData;
922 // Capabilities = CM_DEVCAP_UNIQUEID
923 // Devnode Flages = DN_NEED_RESTART??? DN_DISABLEABLE???
925 switch (ChildDeviceData->DeviceType)
926 {
927 case XENVBD_DEVICETYPE_DISK:
928 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_DISK);
930 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk\0");
931 //status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk&Ven_James&Prod_James&Rev_1.00\0");
932 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
934 status = RtlUnicodeStringPrintf(&buffer, L"%02d\0", ChildDeviceData->DeviceIndex);
935 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
937 status = RtlUnicodeStringPrintf(&buffer, L"GenDisk\0");
938 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
939 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
941 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV Disk (%d)", ChildDeviceData->DeviceIndex);
942 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
943 break;
944 case XENVBD_DEVICETYPE_CDROM:
945 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_MASS_STORAGE);
946 WdfDeviceInitSetCharacteristics(ChildInit, FILE_READ_ONLY_DEVICE|FILE_REMOVABLE_MEDIA, TRUE);
948 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\CDROM\0");
949 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
951 status = RtlUnicodeStringPrintf(&buffer, L"%02d\0", ChildDeviceData->DeviceIndex);
952 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
954 status = RtlUnicodeStringPrintf(&buffer, L"GenCdRom\0");
955 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
956 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
958 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV CDROM (%d)\0", ChildDeviceData->DeviceIndex);
959 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
960 break;
961 default:
962 // wtf?
963 break;
964 }
966 WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
968 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, PXENVBD_CHILD_DEVICE_DATA);
970 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSCSI, IRP_MJ_SCSI, NULL, 0);
971 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpDEVICE_CONTROL, IRP_MJ_DEVICE_CONTROL, NULL, 0);
972 /*
973 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CLEANUP, NULL, 0);
974 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CLOSE, NULL, 0);
975 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CREATE, NULL, 0);
976 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_DIRECTORY_CONTROL, NULL, 0);
977 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_FILE_SYSTEM_CONTROL, NULL, 0);
978 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_FLUSH_BUFFERS, NULL, 0);
979 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_LOCK_CONTROL, NULL, 0);
980 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_POWER, NULL, 0);
981 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_EA, NULL, 0);
982 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_INFORMATION, NULL, 0);
983 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_SECURITY, NULL, 0);
984 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_VOLUME_INFORMATION, NULL, 0);
985 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_READ, NULL, 0);
986 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_INFORMATION, NULL, 0);
987 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_SECURITY, NULL, 0);
988 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_VOLUME_INFORMATION, NULL, 0);
989 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SHUTDOWN, NULL, 0);
990 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SYSTEM_CONTROL, NULL, 0);
991 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_WRITE, NULL, 0);
992 */
993 WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);
995 //WdfDeviceInitSetPowerNotPageable(ChildInit);
997 status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
998 if (!NT_SUCCESS(status))
999 {
1000 KdPrint((__DRIVER_NAME " WdfDeviceCreate status = %08X\n", status));
1003 switch (ChildDeviceData->DeviceType)
1005 case XENVBD_DEVICETYPE_DISK:
1006 WDF_DEVICE_STATE_INIT(&DeviceState);
1007 DeviceState.NotDisableable = WdfTrue;
1008 WdfDeviceSetDeviceState(ChildDevice, &DeviceState);
1009 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFilePaging, TRUE);
1010 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileHibernation, TRUE);
1011 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileDump, TRUE);
1012 break;
1013 case XENVBD_DEVICETYPE_CDROM:
1014 break;
1016 *GetChildDeviceData(ChildDevice) = ChildDeviceData;
1018 ChildDeviceData->FastPathUsed = 0;
1019 ChildDeviceData->SlowPathUsed = 0;
1020 ChildDeviceData->IrpAddedToList = 0;
1021 ChildDeviceData->IrpRemovedFromList = 0;
1022 ChildDeviceData->IrpAddedToRing = 0;
1023 ChildDeviceData->IrpAddedToRingAtLastNotify = 0;
1024 ChildDeviceData->IrpAddedToRingAtLastInterrupt = 0;
1025 ChildDeviceData->IrpAddedToRingAtLastDpc = 0;
1026 ChildDeviceData->IrpRemovedFromRing = 0;
1027 ChildDeviceData->IrpCompleted = 0;
1029 ChildDeviceData->Device = ChildDevice;
1031 KeInitializeSpinLock(&ChildDeviceData->Lock);
1032 KeInitializeSpinLock(&ChildDeviceData->IrpListLock);
1033 InitializeListHead(&ChildDeviceData->IrpListHead);
1035 ChildDeviceData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * BLK_RING_SIZE, XENVBD_POOL_TAG);
1036 memset(ChildDeviceData->shadow, 0, sizeof(blkif_shadow_t) * BLK_RING_SIZE);
1037 //KdPrint((__DRIVER_NAME " Allocated shadow = %08x\n", ChildDeviceData->shadow));
1038 for (i = 0; i < BLK_RING_SIZE; i++)
1039 ChildDeviceData->shadow[i].req.id = i + 1;
1040 ChildDeviceData->shadow_free = 0;
1041 ChildDeviceData->shadow[BLK_RING_SIZE - 1].req.id = 0x0fffffff;
1043 WDF_DPC_CONFIG_INIT(&DpcConfig, XenVbd_DpcThreadProc);
1044 WDF_OBJECT_ATTRIBUTES_INIT(&DpcObjectAttributes);
1045 DpcObjectAttributes.ParentObject = ChildDevice;
1046 WdfDpcCreate(&DpcConfig, &DpcObjectAttributes, &ChildDeviceData->Dpc);
1048 KdPrint((__DRIVER_NAME " <-- ChildListCreateDevice (status = %08x)\n", status));
1050 return status;
1054 // 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
1056 // Call with device lock held
1057 static VOID
1058 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp)
1060 char *DataBuffer;
1061 PSCSI_REQUEST_BLOCK Srb;
1062 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1063 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1064 blkif_request_t *req;
1065 int i;
1066 ULONG j;
1067 int BlockCount;
1068 UINT8 sect_offset;
1070 ChildDeviceData = *GetChildDeviceData(Device);
1072 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1073 // KdPrint((__DRIVER_NAME " --> PutIrpOnRing\n"));
1075 if (RING_FULL(&ChildDeviceData->Ring))
1077 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
1080 req = RING_GET_REQUEST(&ChildDeviceData->Ring, ChildDeviceData->Ring.req_prod_pvt);
1082 //KdPrint((__DRIVER_NAME " req = %08x\n", req));
1084 Srb = irpSp->Parameters.Scsi.Srb;
1086 req->sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
1087 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
1089 req->id = GET_ID_FROM_FREELIST(ChildDeviceData);
1091 if (req->id == 0x0fffffff)
1093 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutIrpOnRing\n"));
1096 //KdPrint((__DRIVER_NAME " id = %d\n", req->id));
1098 req->handle = 0;
1099 req->operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
1100 ChildDeviceData->shadow[req->id].Irp = Irp;
1102 if ((MmGetMdlByteOffset(Irp->MdlAddress) & 0x1ff) == 0) // 0x1ff shouldn't be hardcoded...
1104 // fast path - zero copy
1105 ChildDeviceData->shadow[req->id].Mdl = Irp->MdlAddress;
1106 ChildDeviceData->shadow[req->id].Buf = NULL; // we don't need the virtual address
1107 ChildDeviceData->FastPathUsed++;
1109 else
1111 // slow path - copy to bounce buffer
1112 ChildDeviceData->shadow[req->id].Mdl = AllocatePages((BlockCount * ChildDeviceData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE);
1113 ChildDeviceData->shadow[req->id].Buf = MmGetMdlVirtualAddress(ChildDeviceData->shadow[req->id].Mdl);
1114 if (ChildDeviceData->shadow[req->id].Buf == NULL)
1116 KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress returned NULL in PutIrpOnRing\n"));
1118 ChildDeviceData->SlowPathUsed++;
1121 // if (((ChildDeviceData->FastPathUsed + ChildDeviceData->SlowPathUsed) & 0x2FF) == 0)
1122 // {
1123 // KdPrint((__DRIVER_NAME " Fast Path = %d, Slow Path = %d\n", ChildDeviceData->FastPathUsed, ChildDeviceData->SlowPathUsed));
1124 // 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));
1125 // }
1127 sect_offset = (UINT8)(MmGetMdlByteOffset(ChildDeviceData->shadow[req->id].Mdl) >> 9);
1128 for (i = 0, req->nr_segments = 0; i < BlockCount; req->nr_segments++)
1130 req->seg[req->nr_segments].gref = GntTblInterface.GrantAccess(
1131 GntTblInterface.InterfaceHeader.Context,
1132 0,
1133 MmGetMdlPfnArray(ChildDeviceData->shadow[req->id].Mdl)[req->nr_segments],
1134 FALSE);
1135 req->seg[req->nr_segments].first_sect = sect_offset;
1136 for (j = sect_offset; i < BlockCount && j < PAGE_SIZE / ChildDeviceData->BytesPerSector; j++, i++)
1137 req->seg[req->nr_segments].last_sect = (uint8_t)j;
1138 sect_offset = 0;
1140 if (Srb->Cdb[0] == SCSIOP_WRITE && ChildDeviceData->shadow[req->id].Buf != NULL)
1142 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1143 if (DataBuffer == NULL)
1144 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe failed in PutIrpOnRing\n"));
1145 memcpy(ChildDeviceData->shadow[req->id].Buf, DataBuffer, BlockCount * ChildDeviceData->BytesPerSector);
1147 ChildDeviceData->shadow[req->id].req = *req;
1149 ChildDeviceData->Ring.req_prod_pvt++;
1151 ChildDeviceData->IrpAddedToRing++;
1153 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1154 // KdPrint((__DRIVER_NAME " <-- PutIrpOnRing\n"));
1157 static ULONG
1158 XenVBD_FillModePage(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
1160 PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
1162 switch (PageCode)
1164 case MODE_PAGE_RIGID_GEOMETRY:
1165 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_DISK)
1167 KdPrint((__DRIVER_NAME " MODE_PAGE_RIGID_GEOMETRY\n"));
1168 if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
1169 return 1;
1170 ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
1171 memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
1172 ModeRigidGeometry->PageCode = PageCode;
1173 ModeRigidGeometry->PageSavable = 0;
1174 ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
1175 ModeRigidGeometry->NumberOfCylinders[0] = (UCHAR)((ChildDeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF);
1176 ModeRigidGeometry->NumberOfCylinders[1] = (UCHAR)((ChildDeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF);
1177 ModeRigidGeometry->NumberOfCylinders[2] = (UCHAR)((ChildDeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF);
1178 ModeRigidGeometry->NumberOfHeads = (UCHAR)ChildDeviceData->Geometry.TracksPerCylinder;
1179 //ModeRigidGeometry->LandZoneCyclinder = 0;
1180 ModeRigidGeometry->RoataionRate[0] = 0x05;
1181 ModeRigidGeometry->RoataionRate[0] = 0x39;
1182 *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
1184 break;
1185 case MODE_PAGE_FAULT_REPORTING:
1186 break;
1187 default:
1188 break;
1190 return 0;
1193 static NTSTATUS
1194 XenVbd_Child_PreprocessWdmIrpDEVICE_CONTROL(WDFDEVICE Device, PIRP Irp)
1196 NTSTATUS Status;
1197 PIO_STACK_LOCATION IrpStack;
1198 PSCSI_ADDRESS ScsiAddress;
1199 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1200 PSTORAGE_PROPERTY_QUERY Spq;
1201 PSTORAGE_ADAPTER_DESCRIPTOR Sad;
1202 PSTORAGE_DEVICE_DESCRIPTOR Sdd;
1203 PSTORAGE_DEVICE_ID_DESCRIPTOR Sdid;
1204 PSTORAGE_IDENTIFIER Si;
1205 // ULONG Information;
1206 int StructEndOffset;
1208 KdPrint((__DRIVER_NAME " --> PreprocessWdmIrpDEVICE_CONTROL\n"));
1210 ChildDeviceData = *GetChildDeviceData(Device);
1212 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1214 switch (IrpStack->Parameters.DeviceIoControl.IoControlCode)
1216 case IOCTL_SCSI_GET_ADDRESS:
1217 KdPrint((__DRIVER_NAME " IOCTL_SCSI_GET_ADDRESS\n"));
1218 Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
1219 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(SCSI_ADDRESS))
1221 ScsiAddress = (PSCSI_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1222 ScsiAddress->Length = sizeof(SCSI_ADDRESS);
1223 ScsiAddress->PortNumber = 0;
1224 ScsiAddress->PathId = 0;
1225 ScsiAddress->TargetId = 0;
1226 ScsiAddress->Lun = 0;
1227 Status = STATUS_SUCCESS;
1228 Irp->IoStatus.Status = Status;
1229 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1231 else
1233 KdPrint((__DRIVER_NAME " (Buffer size too small @ %d\n", IrpStack->Parameters.DeviceIoControl.OutputBufferLength));
1235 break;
1236 case IOCTL_STORAGE_QUERY_PROPERTY:
1237 KdPrint((__DRIVER_NAME " IOCTL_STORAGE_QUERY_PROPERTY\n"));
1238 Spq = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
1239 if (Spq->PropertyId == StorageAdapterProperty && Spq->QueryType == PropertyStandardQuery)
1241 KdPrint((__DRIVER_NAME " PropertyId = StorageAdapterProperty, QueryType = PropertyStandardQuery\n"));
1242 Irp->IoStatus.Information = 0;
1243 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= 8)
1245 Irp->IoStatus.Information = 8;
1246 Sad = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1247 Sad->Version = 1;
1248 Sad->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
1249 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= Sad->Size)
1251 Irp->IoStatus.Information = Sad->Size;
1252 Sad->MaximumTransferLength = 45056;
1253 Sad->MaximumPhysicalPages = 11;
1254 Sad->AlignmentMask = 0;
1255 Sad->AdapterUsesPio = FALSE;
1256 Sad->AdapterScansDown = FALSE;
1257 Sad->CommandQueueing = FALSE;
1258 Sad->AcceleratedTransfer = FALSE;
1259 Sad->BusType = BusTypeScsi;
1260 Sad->BusMajorVersion = 0;
1261 Sad->BusMinorVersion = 0;
1264 Status = STATUS_SUCCESS;
1265 Irp->IoStatus.Status = Status;
1266 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1268 else if (Spq->PropertyId == StorageDeviceProperty && Spq->QueryType == PropertyStandardQuery)
1270 KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceProperty, QueryType = PropertyStandardQuery\n"));
1271 Irp->IoStatus.Information = 0;
1272 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= 8)
1274 Irp->IoStatus.Information = 8;
1275 Sdd = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1276 Sdd->Version = 1;
1277 Sdd->Size = &Sdd->RawDeviceProperties[36] - (PUCHAR)Sdd + 1;
1278 // 0 0 1 2 3
1279 // 0 7 5 4 1
1280 //"VENDOR\0PRODUCT\0Revision\0Serial\0"
1281 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= Sdd->Size)
1283 Irp->IoStatus.Information = Sdd->Size;
1284 switch (ChildDeviceData->DeviceType)
1286 case XENVBD_DEVICETYPE_DISK:
1287 Sdd->DeviceType = DIRECT_ACCESS_DEVICE;
1288 Sdd->DeviceTypeModifier = 0x00;
1289 Sdd->RemovableMedia = FALSE;
1290 break;
1291 case XENVBD_DEVICETYPE_CDROM:
1292 Sdd->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1293 Sdd->DeviceTypeModifier = 0x00;
1294 Sdd->RemovableMedia = TRUE;
1295 break;
1296 default:
1297 // wtf
1298 break;
1300 Sdd->CommandQueueing = FALSE;
1301 StructEndOffset = Sdd->RawDeviceProperties - (PUCHAR)Sdd;
1302 Sdd->VendorIdOffset = StructEndOffset + 0;
1303 Sdd->ProductIdOffset = StructEndOffset + 7;
1304 Sdd->ProductRevisionOffset = StructEndOffset + 15;
1305 Sdd->SerialNumberOffset = StructEndOffset + 24;
1306 Sdd->BusType = BusTypeScsi;
1307 Sdd->RawPropertiesLength = 36;
1308 memcpy(Sdd->RawDeviceProperties, "VENDOR\0PRODUCT\0Revision\0Serial99999\0", 36);
1311 Status = STATUS_SUCCESS;
1312 Irp->IoStatus.Status = Status;
1313 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1315 else if (Spq->PropertyId == StorageDeviceIdProperty && Spq->QueryType == PropertyStandardQuery)
1317 KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceIdProperty, QueryType = PropertyStandardQuery\n"));
1318 Irp->IoStatus.Information = 0;
1319 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= 8)
1321 Irp->IoStatus.Information = 8;
1322 Sdid = (PSTORAGE_DEVICE_ID_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1323 Sdid->Version = 1;
1324 Si = (PSTORAGE_IDENTIFIER)Sdid->Identifiers;
1325 Sdid->Size = &Si->Identifier[8] - (PUCHAR)Sdid + 1;
1326 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= Sdid->Size)
1328 Irp->IoStatus.Information = Sdid->Size;
1329 Sdid->NumberOfIdentifiers = 1;
1330 Si->CodeSet = StorageIdCodeSetAscii;
1331 Si->Type = StorageIdTypeScsiNameString;
1332 //Si->CodeSet = StorageIdCodeSetBinary;
1333 //Si->Type = StorageIdTypeEUI64;
1334 Si->IdentifierSize = 9;
1335 Si->NextOffset = 0;
1336 Si->Association = StorageIdAssocPort;
1337 Si->Identifier[0] = 'S';
1338 Si->Identifier[1] = 'e';
1339 Si->Identifier[2] = 'r';
1340 Si->Identifier[3] = 'i';
1341 Si->Identifier[4] = 'a';
1342 Si->Identifier[5] = 'l';
1343 Si->Identifier[6] = '9';
1344 Si->Identifier[7] = '9';
1345 Si->Identifier[6] = '9';
1346 Si->Identifier[7] = '9';
1347 Si->Identifier[8] = '9';
1348 //Si->Identifier[8] = 0;
1351 Status = STATUS_SUCCESS;
1352 Irp->IoStatus.Status = Status;
1353 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1355 else
1357 switch (Spq->PropertyId)
1359 case StorageDeviceProperty:
1360 KdPrint((__DRIVER_NAME " StorageDeviceProperty\n"));
1361 break;
1362 case StorageAccessAlignmentProperty:
1363 KdPrint((__DRIVER_NAME " StorageAccessAlignmentProperty\n"));
1364 break;
1365 case StorageAdapterProperty:
1366 KdPrint((__DRIVER_NAME " StorageAdapterProperty\n"));
1367 break;
1368 case StorageDeviceIdProperty:
1369 KdPrint((__DRIVER_NAME " StorageDeviceIdProperty\n"));
1370 break;
1371 case StorageDeviceUniqueIdProperty:
1372 KdPrint((__DRIVER_NAME " StorageDeviceUniqueIdProperty\n"));
1373 break;
1374 case StorageDeviceWriteCacheProperty:
1375 KdPrint((__DRIVER_NAME " StorageDeviceWriteCacheProperty\n"));
1376 break;
1377 default:
1378 KdPrint((__DRIVER_NAME " Unknown Property %08x\n", Spq->PropertyId));
1379 break;
1381 switch (Spq->QueryType)
1383 case PropertyStandardQuery:
1384 KdPrint((__DRIVER_NAME " PropertyStandardQuery\n"));
1385 break;
1386 case PropertyExistsQuery:
1387 KdPrint((__DRIVER_NAME " PropertyExistsQuery\n"));
1388 break;
1389 default:
1390 KdPrint((__DRIVER_NAME " Unknown Query %08x\n", Spq->QueryType));
1391 break;
1393 Status = STATUS_NOT_IMPLEMENTED;
1394 Irp->IoStatus.Status = Status;
1395 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1397 break;
1398 // http://www.osronline.com/article.cfm?article=229
1399 // 0x00560030 device = 0x56, Function = 0x00c =
1400 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
1401 KdPrint((__DRIVER_NAME " IOCTL_DISK_GET_DRIVE_GEOMETRY\n"));
1402 memcpy(Irp->AssociatedIrp.SystemBuffer, &ChildDeviceData->Geometry, sizeof(DISK_GEOMETRY));
1403 Status = STATUS_SUCCESS;
1404 Irp->IoStatus.Status = Status;
1405 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1406 break;
1407 case FT_BALANCED_READ_MODE: // just pretend we know what this is...
1408 KdPrint((__DRIVER_NAME " FT_BALANCED_READ_MODE\n"));
1409 Status = STATUS_SUCCESS;
1410 Irp->IoStatus.Status = Status;
1411 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1412 break;
1413 default:
1414 KdPrint((__DRIVER_NAME " Control Code = %08x\n", IrpStack->Parameters.DeviceIoControl.IoControlCode));
1415 Status = STATUS_NOT_IMPLEMENTED;
1416 Irp->IoStatus.Status = Status;
1417 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1420 KdPrint((__DRIVER_NAME " <-- PreprocessWdmIrpDEVICE_CONTROL\n"));
1422 return Status;
1425 static NTSTATUS
1426 XenVbd_Child_PreprocessWdmIrpSomethingSomething(WDFDEVICE Device, PIRP Irp)
1428 NTSTATUS Status;
1429 PIO_STACK_LOCATION IrpStack;
1431 KdPrint((__DRIVER_NAME " --> XenVbd_Child_PreprocessWdmIrpSomethingSomething\n"));
1433 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1434 KdPrint((__DRIVER_NAME " Major = %02X, Minor = %02X\n", IrpStack->MajorFunction, IrpStack->MinorFunction));
1436 IoSkipCurrentIrpStackLocation(Irp);
1438 Status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1440 KdPrint((__DRIVER_NAME " <-- XenVbd_Child_PreprocessWdmIrpSomethingSomething\n"));
1442 return Status;
1445 static NTSTATUS
1446 XenVbd_Child_PreprocessWdmIrpSCSI(WDFDEVICE Device, PIRP Irp)
1448 char *DataBuffer;
1449 NTSTATUS status = STATUS_SUCCESS;
1450 PSCSI_REQUEST_BLOCK Srb;
1451 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1452 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1453 KIRQL KIrql;
1454 XenVbd_ListEntry *ListEntry;
1455 int notify;
1456 PCDB cdb;
1457 //PUCHAR Ptr;
1458 ULONG i;
1460 ChildDeviceData = *GetChildDeviceData(Device);
1462 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1463 // KdPrint((__DRIVER_NAME " --> WdmIrpPreprocessSCSI\n"));
1465 //KdPrint((__DRIVER_NAME " SCSI Minor = %02X\n", irpSp->MinorFunction));
1467 Srb = irpSp->Parameters.Scsi.Srb;
1469 switch (Srb->Function)
1471 case SRB_FUNCTION_EXECUTE_SCSI:
1472 cdb = (PCDB)Srb->Cdb;
1473 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1474 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
1475 switch(cdb->CDB6GENERIC.OperationCode) //Srb->Cdb[0])
1477 case SCSIOP_TEST_UNIT_READY:
1478 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1479 // KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1480 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1481 Srb->ScsiStatus = 0;
1482 status = STATUS_SUCCESS;
1483 Irp->IoStatus.Status = status;
1484 Irp->IoStatus.Information = 0;
1485 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1486 break;
1487 case SCSIOP_INQUIRY:
1488 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1489 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1490 if ((Srb->Cdb[1] & 1) == 0)
1492 // DataBuffer = Srb->DataBuffer;
1493 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1494 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1496 DataBuffer[0] = 0x00; // disk
1497 DataBuffer[1] = 0x00; // not removable
1498 memcpy(DataBuffer + 8, "James ", 8); // vendor id
1499 memcpy(DataBuffer + 16, "XenVBD ", 8); // product id
1500 memcpy(DataBuffer + 32, "000", 8); // product revision level
1501 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1503 else
1505 KdPrint((__DRIVER_NAME " Command = INQUIRY (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1506 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1508 Srb->ScsiStatus = 0;
1509 status = STATUS_SUCCESS;
1510 Irp->IoStatus.Status = status;
1511 Irp->IoStatus.Information = 0;
1512 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1513 break;
1514 case SCSIOP_READ_CAPACITY:
1515 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1516 // KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1517 // DataBuffer = Srb->DataBuffer;
1518 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1519 DataBuffer[0] = (unsigned char)(ChildDeviceData->TotalSectors >> 24) & 0xff;
1520 DataBuffer[1] = (unsigned char)(ChildDeviceData->TotalSectors >> 16) & 0xff;
1521 DataBuffer[2] = (unsigned char)(ChildDeviceData->TotalSectors >> 8) & 0xff;
1522 DataBuffer[3] = (unsigned char)(ChildDeviceData->TotalSectors >> 0) & 0xff;
1523 DataBuffer[4] = (unsigned char)(ChildDeviceData->BytesPerSector >> 24) & 0xff;
1524 DataBuffer[5] = (unsigned char)(ChildDeviceData->BytesPerSector >> 16) & 0xff;
1525 DataBuffer[6] = (unsigned char)(ChildDeviceData->BytesPerSector >> 8) & 0xff;
1526 DataBuffer[7] = (unsigned char)(ChildDeviceData->BytesPerSector >> 0) & 0xff;
1527 Srb->ScsiStatus = 0;
1528 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1529 status = STATUS_SUCCESS;
1530 Irp->IoStatus.Status = status;
1531 Irp->IoStatus.Information = 0;
1532 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1533 break;
1534 case SCSIOP_MODE_SENSE:
1535 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));
1536 KdPrint((__DRIVER_NAME " Length = %d\n", Srb->DataTransferLength));
1538 status = STATUS_SUCCESS;
1539 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1540 // DataBuffer = Srb->DataBuffer;
1541 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1542 switch(cdb->MODE_SENSE.PageCode) //Srb->Cdb[2] & 0x3F)
1544 case MODE_SENSE_RETURN_ALL:
1545 Irp->IoStatus.Information = 0;
1546 //Ptr = (UCHAR *)Srb->DataBuffer;
1547 for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
1549 if (XenVBD_FillModePage(ChildDeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Irp->IoStatus.Information))
1551 break;
1554 break;
1555 default:
1556 XenVBD_FillModePage(ChildDeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Irp->IoStatus.Information);
1557 break;
1559 Srb->DataTransferLength = Irp->IoStatus.Information;
1560 // Srb->ScsiStatus = 0;
1561 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1562 Irp->IoStatus.Status = status;
1563 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1564 break;
1565 case SCSIOP_READ:
1566 case SCSIOP_WRITE:
1567 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1568 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1570 IoMarkIrpPending(Irp);
1572 //KdPrint((__DRIVER_NAME " Irp Acquiring Lock\n"));
1573 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
1574 //KdPrint((__DRIVER_NAME "A Got It\n"));
1576 if (RING_FULL(&ChildDeviceData->Ring))
1578 //KdPrint((__DRIVER_NAME "A Inserting into list\n"));
1579 ListEntry = (XenVbd_ListEntry *)ExAllocatePoolWithTag(NonPagedPool, sizeof(XenVbd_ListEntry), XENVBD_POOL_TAG);
1580 //KdPrint((__DRIVER_NAME " Allocate ListEntry = %08x\n", ListEntry));
1581 if (ListEntry == NULL)
1583 KdPrint((__DRIVER_NAME " CANNOT ALLOCATE MEMORY FOR ListEntry!!!\n"));
1585 ListEntry->Irp = Irp;
1586 InsertTailList(&ChildDeviceData->IrpListHead, &ListEntry->Entry);
1587 ChildDeviceData->IrpAddedToList++;
1589 else
1591 XenVbd_PutIrpOnRing(Device, Irp);
1592 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
1593 if (notify)
1594 EvtChnInterface.Notify(EvtChnInterface.InterfaceHeader.Context,
1595 ChildDeviceData->EventChannel);
1596 //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));
1598 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
1599 status = STATUS_PENDING;
1600 break;
1601 case SCSIOP_READ_TOC:
1602 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1603 /*
1604 #define READ_TOC_FORMAT_TOC 0x00
1605 #define READ_TOC_FORMAT_SESSION 0x01
1606 #define READ_TOC_FORMAT_FULL_TOC 0x02
1607 #define READ_TOC_FORMAT_PMA 0x03
1608 #define READ_TOC_FORMAT_ATIP 0x04
1609 */
1610 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1611 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1612 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1613 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1614 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1615 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1616 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1617 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1618 switch (cdb->READ_TOC.Format2)
1620 case READ_TOC_FORMAT_TOC:
1621 DataBuffer[0] = 0; // length MSB
1622 DataBuffer[1] = 10; // length LSB
1623 DataBuffer[2] = 1; // First Track
1624 DataBuffer[3] = 1; // Last Track
1625 DataBuffer[4] = 0; // Reserved
1626 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1627 DataBuffer[6] = 1; // last complete track
1628 DataBuffer[7] = 0; // reserved
1629 DataBuffer[8] = 0; // MSB Block
1630 DataBuffer[9] = 0;
1631 DataBuffer[10] = 0;
1632 DataBuffer[11] = 0; // LSB Block
1633 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1634 break;
1635 case READ_TOC_FORMAT_SESSION:
1636 case READ_TOC_FORMAT_FULL_TOC:
1637 case READ_TOC_FORMAT_PMA:
1638 case READ_TOC_FORMAT_ATIP:
1639 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1640 break;
1642 Irp->IoStatus.Status = status;
1643 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1644 break;
1645 /*
1646 case SCSIOP_GET_CONFIGURATION:
1647 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL 0x0
1648 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT 0x1
1649 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE 0x2
1651 UCHAR OperationCode; // 0x46 - SCSIOP_GET_CONFIGURATION
1652 UCHAR RequestType : 2; // SCSI_GET_CONFIGURATION_REQUEST_TYPE_*
1653 UCHAR Reserved1 : 6; // includes obsolete LUN field
1654 UCHAR StartingFeature[2];
1655 UCHAR Reserved2[3];
1656 UCHAR AllocationLength[2];
1657 UCHAR Control;
1658 break;
1659 */
1660 default:
1661 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1662 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1663 Irp->IoStatus.Status = status;
1664 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1665 break;
1667 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1668 break;
1669 case SRB_FUNCTION_CLAIM_DEVICE:
1670 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1671 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
1672 ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
1673 Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
1674 // Srb->DataBuffer = WdfDeviceWdmGetAttachedDevice(Device);
1675 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1676 status = STATUS_SUCCESS;
1677 Irp->IoStatus.Status = status;
1678 Irp->IoStatus.Information = 0;
1679 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1680 break;
1681 case SRB_FUNCTION_IO_CONTROL:
1682 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1683 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1684 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1685 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1686 status = STATUS_NOT_IMPLEMENTED;
1687 //Irp->IoStatus.Status = status;
1688 //Irp->IoStatus.Information = 0;
1689 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1690 break;
1691 case SRB_FUNCTION_FLUSH:
1692 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1693 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1694 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1695 status = STATUS_SUCCESS;
1696 Irp->IoStatus.Status = status;
1697 Irp->IoStatus.Information = 0;
1698 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1699 break;
1700 default:
1701 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1702 status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1703 break;
1706 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1707 // 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));
1708 //KdPrint((__DRIVER_NAME " <-- WdmIrpPreprocessSCSI\n"));
1710 return status;