win-pvdrivers

view xenvbd/xenvbd.c @ 29:7fc983eddda8

Finally got CDROM access working. Lots of cleaning up to do though...
author James Harper <james.harper@bendigoit.com.au>
date Sun Dec 02 23:13:20 2007 +1100 (2007-12-02)
parents b55f3c61e509
children f56c47274c37 2e1d570b69e9
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);
52 static VOID
53 XenVbd_Child_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
54 static VOID
55 XenVbd_Child_IoReadWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t Length);
56 static VOID
57 XenVbd_Child_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode);
58 static VOID
59 XenVbd_Child_IoInternalDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode);
61 static VOID
62 XenVbd_HotPlugHandler(char *Path, PVOID Data);
64 #ifdef ALLOC_PRAGMA
65 #pragma alloc_text (INIT, DriverEntry)
66 #pragma alloc_text (PAGE, XenVbd_AddDevice)
67 #endif
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(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
196 {
197 WDF_CHILD_LIST_CONFIG ChildListConfig;
198 NTSTATUS status;
199 WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
201 UNREFERENCED_PARAMETER(Driver);
203 KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
205 Pdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit);
207 //WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
208 WDF_CHILD_LIST_CONFIG_INIT(&ChildListConfig, sizeof(XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION), XenVbd_ChildListCreateDevice);
209 WdfFdoInitSetDefaultChildListConfig(DeviceInit, &ChildListConfig, WDF_NO_OBJECT_ATTRIBUTES);
211 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_CONTROLLER);
212 //WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
213 WdfDeviceInitSetExclusive(DeviceInit, FALSE);
215 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
216 pnpPowerCallbacks.EvtDevicePrepareHardware = XenVbd_PrepareHardware;
217 pnpPowerCallbacks.EvtDeviceReleaseHardware = XenVbd_ReleaseHardware;
218 pnpPowerCallbacks.EvtDeviceD0Entry = XenVbd_D0Entry;
219 pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenVbd_D0EntryPostInterruptsEnabled;
220 pnpPowerCallbacks.EvtDeviceD0Exit = XenVbd_D0Exit;
221 pnpPowerCallbacks.EvtDeviceUsageNotification = XenVbd_DeviceUsageNotification;
222 WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
224 /*initialize storage for the device context*/
225 //WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENVBD_DEVICE_DATA);
227 //WdfDeviceInitSetPowerNotPageable(DeviceInit);
229 /*create a device instance.*/
230 status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &GlobalDevice);
231 if(!NT_SUCCESS(status))
232 {
233 KdPrint((__DRIVER_NAME "WdfDeviceCreate failed with status 0x%08x\n", status));
234 return status;
235 }
237 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFilePaging, TRUE);
238 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFileHibernation, TRUE);
239 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFileDump, TRUE);
241 status = STATUS_SUCCESS;
243 KdPrint((__DRIVER_NAME " <-- DeviceAdd\n"));
244 return status;
245 }
247 static NTSTATUS
248 XenVbd_PrepareHardware(
249 IN WDFDEVICE Device,
250 IN WDFCMRESLIST ResourceList,
251 IN WDFCMRESLIST ResourceListTranslated)
252 {
253 NTSTATUS status = STATUS_SUCCESS;
255 UNREFERENCED_PARAMETER(ResourceList);
256 UNREFERENCED_PARAMETER(ResourceListTranslated);
258 //KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware\n"));
260 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_EVTCHN, (PINTERFACE) &EvtChnInterface, sizeof(XEN_IFACE_EVTCHN), 1, NULL);
261 if(!NT_SUCCESS(status))
262 {
263 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (EvtChn) failed with status 0x%08x\n", status));
264 }
266 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XENBUS, (PINTERFACE)&XenBusInterface, sizeof(XEN_IFACE_XENBUS), 1, NULL);
267 if(!NT_SUCCESS(status))
268 {
269 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (XenBus) failed with status 0x%08x\n", status));
270 }
272 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XEN, (PINTERFACE)&XenInterface, sizeof(XEN_IFACE_XEN), 1, NULL);
273 if(!NT_SUCCESS(status))
274 {
275 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (Xen) failed with status 0x%08x\n", status));
276 }
278 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_GNTTBL, (PINTERFACE)&GntTblInterface, sizeof(XEN_IFACE_GNTTBL), 1, NULL);
279 if(!NT_SUCCESS(status))
280 {
281 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (GntTbl) failed with status 0x%08x\n", status));
282 }
284 //KdPrint((__DRIVER_NAME " <-- EvtDevicePrepareHardware\n"));
286 InitializeListHead(&DeviceListHead);
288 return status;
289 }
291 static NTSTATUS
292 XenVbd_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated)
293 {
294 UNREFERENCED_PARAMETER(Device);
295 UNREFERENCED_PARAMETER(ResourcesTranslated);
297 // release interfaces here...
299 //XenVbd_Close();
301 return STATUS_SUCCESS;
302 }
304 static NTSTATUS
305 XenVbd_D0Entry(
306 IN WDFDEVICE Device,
307 IN WDF_POWER_DEVICE_STATE PreviousState
308 )
309 {
310 NTSTATUS status = STATUS_SUCCESS;
312 UNREFERENCED_PARAMETER(Device);
313 UNREFERENCED_PARAMETER(PreviousState);
315 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Entry\n"));
317 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
319 return status;
320 }
322 static int EnumeratedDevices;
323 static KEVENT WaitDevicesEvent;
325 static NTSTATUS
326 XenVbd_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
327 {
328 //OBJECT_ATTRIBUTES oa;
329 NTSTATUS status = STATUS_SUCCESS;
330 //HANDLE nothing;
331 //char *response;
332 PXENPCI_XEN_DEVICE_DATA PdoDeviceData;
333 char **VbdDevices;
334 char *msg;
335 char buffer[128];
336 int i;
337 LARGE_INTEGER WaitTimeout;
339 UNREFERENCED_PARAMETER(Device);
340 UNREFERENCED_PARAMETER(PreviousState);
342 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0EntryPostInterruptsEnabled\n"));
344 PdoDeviceData = (PXENPCI_XEN_DEVICE_DATA)Pdo->DeviceExtension; //GetXenDeviceData(Device);
346 //KdPrint((__DRIVER_NAME " BasePath = %s\n", PdoDeviceData->BasePath));
347 PdoDeviceData->WatchHandler = XenVbd_HotPlugHandler;
349 EnumeratedDevices = 0;
350 KeInitializeEvent(&WaitDevicesEvent, SynchronizationEvent, FALSE);
352 // TODO: Should probably do this in an EvtChildListScanForChildren
353 if (AutoEnumerate)
354 {
355 msg = XenBusInterface.List(XBT_NIL, "device/vbd", &VbdDevices);
356 if (!msg) {
357 for (i = 0; VbdDevices[i]; i++)
358 {
359 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
360 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
361 XenVbd_HotPlugHandler(buffer, NULL);
362 //ExFreePoolWithTag(bdDevices[i], XENPCI_POOL_TAG);
363 }
364 KdPrint((__DRIVER_NAME " Waiting for devices to be enumerated\n"));
365 while (EnumeratedDevices != i)
366 {
367 WaitTimeout.QuadPart = -600000000;
368 if (KeWaitForSingleObject(&WaitDevicesEvent, Executive, KernelMode, FALSE, &WaitTimeout) == STATUS_TIMEOUT)
369 {
370 KdPrint((__DRIVER_NAME " Wait timed out\n"));
371 break;
372 }
373 KdPrint((__DRIVER_NAME " %d out of %d devices enumerated\n", EnumeratedDevices, i));
374 }
375 }
376 }
378 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0EntryPostInterruptsEnabled\n"));
380 return status;
381 }
383 static NTSTATUS
384 XenVbd_D0Exit(
385 IN WDFDEVICE Device,
386 IN WDF_POWER_DEVICE_STATE TargetState
387 )
388 {
389 NTSTATUS status = STATUS_SUCCESS;
390 //char *response;
392 UNREFERENCED_PARAMETER(Device);
393 UNREFERENCED_PARAMETER(TargetState);
395 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Exit\n"));
397 //response = XenBusInterface.RemWatch(XBT_NIL, XenBusInterface.InterfaceHeader.Context, XenVbd_HotPlugHandler, NULL);
399 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Exit\n"));
401 return status;
402 }
404 static NTSTATUS
405 XenVbd_DeviceUsageNotification(WDFDEVICE Device, WDF_SPECIAL_FILE_TYPE NotificationType, BOOLEAN IsInNotificationPath)
406 {
407 KdPrint((__DRIVER_NAME " --> DeviceUsageNotification\n"));
409 switch (NotificationType)
410 {
411 case WdfSpecialFilePaging:
412 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFilePaging, Using = %d\n", IsInNotificationPath));
413 break;
414 case WdfSpecialFileHibernation:
415 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFileHibernation, Using = %d\n", IsInNotificationPath));
416 break;
417 case WdfSpecialFileDump:
418 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFileDump, Using = %d\n", IsInNotificationPath));
419 break;
420 default:
421 KdPrint((__DRIVER_NAME " NotificationType = %d, Using = %d\n", NotificationType, IsInNotificationPath));
422 break;
423 }
424 KdPrint((__DRIVER_NAME " <-- DeviceUsageNotification\n"));
426 return TRUE;
427 }
429 static VOID
430 XenVbd_IoDefault(
431 IN WDFQUEUE Queue,
432 IN WDFREQUEST Request
433 )
434 {
435 UNREFERENCED_PARAMETER(Queue);
437 //KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
439 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
441 //KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
442 }
444 static __inline uint64_t
445 GET_ID_FROM_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData)
446 {
447 uint64_t free;
449 free = ChildDeviceData->shadow_free;
451 //KdPrint((__DRIVER_NAME " A free = %d\n", free));
453 ChildDeviceData->shadow_free = ChildDeviceData->shadow[free].req.id;
455 //KdPrint((__DRIVER_NAME " A shadow_free now = %d\n", ChildDeviceData->shadow_free));
457 ChildDeviceData->shadow[free].req.id = 0x0fffffee; /* debug */
458 return free;
459 }
461 static __inline VOID
462 ADD_ID_TO_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, uint64_t Id)
463 {
464 ChildDeviceData->shadow[Id].req.id = ChildDeviceData->shadow_free;
465 ChildDeviceData->shadow[Id].Irp = NULL;
466 ChildDeviceData->shadow_free = Id;
467 }
469 static VOID
470 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp);
472 static PMDL
473 AllocatePages(int Pages)
474 {
475 PMDL Mdl;
476 PVOID Buf;
478 Buf = ExAllocatePoolWithTag(NonPagedPool, Pages * PAGE_SIZE, XENVBD_POOL_TAG);
479 if (Buf == NULL)
480 {
481 KdPrint((__DRIVER_NAME " AllocatePages Failed at ExAllocatePoolWithTag\n"));
482 }
483 Mdl = IoAllocateMdl(Buf, Pages * PAGE_SIZE, FALSE, FALSE, NULL);
484 if (Mdl == NULL)
485 {
486 KdPrint((__DRIVER_NAME " AllocatePages Failed at IoAllocateMdl\n"));
487 }
488 MmBuildMdlForNonPagedPool(Mdl);
490 return Mdl;
491 }
493 static PMDL
494 AllocatePage()
495 {
496 return AllocatePages(1);
497 }
499 static VOID
500 FreePages(PMDL Mdl)
501 {
502 PVOID Buf = MmGetMdlVirtualAddress(Mdl);
503 //KdPrint((__DRIVER_NAME " FreePages Failed at IoAllocateMdl\n"));
504 //KdPrint((__DRIVER_NAME " FreePages Buf = %08x\n", Buf));
505 IoFreeMdl(Mdl);
506 ExFreePoolWithTag(Buf, XENVBD_POOL_TAG);
507 }
509 static VOID
510 XenVbd_DpcThreadProc(WDFDPC Dpc)
511 {
512 PIRP Irp;
513 RING_IDX i, rp;
514 int j;
515 blkif_response_t *rep;
516 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
517 PSCSI_REQUEST_BLOCK Srb;
518 PIO_STACK_LOCATION IrpSp;
519 char *DataBuffer;
520 int more_to_do;
521 int IrpCount;
522 PIRP Irps[100];
523 int BlockCount;
524 KIRQL KIrql;
525 WDFDEVICE ChildDevice;
526 XenVbd_ListEntry *ListEntry;
527 int notify;
529 //!!!IRQL_DISPATCH!!!
531 //KdPrint((__DRIVER_NAME " --> XenVbd_DpcThreadProc\n"));
533 ChildDevice = WdfDpcGetParentObject(Dpc);
535 ChildDeviceData = *GetChildDeviceData(ChildDevice);
537 IrpCount = 0;
538 more_to_do = TRUE;
539 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
541 ChildDeviceData->IrpAddedToRingAtLastDpc = ChildDeviceData->IrpAddedToRing;
543 while (more_to_do)
544 {
545 rp = ChildDeviceData->Ring.sring->rsp_prod;
546 KeMemoryBarrier();
547 for (i = ChildDeviceData->Ring.rsp_cons; i != rp; i++)
548 {
549 rep = RING_GET_RESPONSE(&ChildDeviceData->Ring, i);
550 ChildDeviceData->IrpRemovedFromRing++;
551 Irp = ChildDeviceData->shadow[rep->id].Irp;
552 IrpSp = IoGetCurrentIrpStackLocation(Irp);
553 Srb = IrpSp->Parameters.Scsi.Srb;
555 if (rep->status != BLKIF_RSP_OKAY)
556 {
557 KdPrint((__DRIVER_NAME " Xen Operation returned error in DpcThreadProc\n"));
558 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));
559 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
560 {
561 KdPrint((__DRIVER_NAME " gref[%d] = %d\n", j, ChildDeviceData->shadow[rep->id].req.seg[j].gref));
562 }
563 KdPrint((__DRIVER_NAME " MmGetMdlByteOffset = %d\n", MmGetMdlByteOffset(Irp->MdlAddress)));
564 }
565 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
566 {
567 GntTblInterface.EndAccess(ChildDeviceData->shadow[rep->id].req.seg[j].gref);
568 }
569 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
570 if (ChildDeviceData->shadow[rep->id].Buf != NULL)
571 {
572 if (Srb->Cdb[0] == SCSIOP_READ)
573 {
574 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
575 if (DataBuffer == NULL)
576 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe Failed in DpcThreadProc\n"));
577 memcpy(DataBuffer, ChildDeviceData->shadow[rep->id].Buf, BlockCount * ChildDeviceData->BytesPerSector);
578 }
579 FreePages(ChildDeviceData->shadow[rep->id].Mdl);
580 }
581 Srb->SrbStatus = SRB_STATUS_SUCCESS;
582 Srb->ScsiStatus = 0;
583 Irp->IoStatus.Status = STATUS_SUCCESS;
584 Irp->IoStatus.Information = BlockCount * ChildDeviceData->BytesPerSector;
586 Irps[IrpCount++] = Irp;
588 ADD_ID_TO_FREELIST(ChildDeviceData, rep->id);
589 }
591 ChildDeviceData->Ring.rsp_cons = i;
592 if (i != ChildDeviceData->Ring.req_prod_pvt)
593 {
594 RING_FINAL_CHECK_FOR_RESPONSES(&ChildDeviceData->Ring, more_to_do);
595 }
596 else
597 {
598 ChildDeviceData->Ring.sring->rsp_event = i + 1;
599 more_to_do = FALSE;
600 }
601 }
603 notify = 0;
604 while (!RING_FULL(&ChildDeviceData->Ring) && (ListEntry = (XenVbd_ListEntry *)RemoveHeadList(&ChildDeviceData->IrpListHead)) != (XenVbd_ListEntry *)&ChildDeviceData->IrpListHead)
605 {
606 ChildDeviceData->IrpRemovedFromList++;
607 XenVbd_PutIrpOnRing(ChildDevice, ListEntry->Irp);
608 ExFreePoolWithTag(ListEntry, XENVBD_POOL_TAG);
609 notify = 1;
610 }
611 if (notify)
612 {
613 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
614 if (notify)
615 EvtChnInterface.Notify(ChildDeviceData->EventChannel);
616 }
617 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
619 for (j = 0; j < IrpCount; j++)
620 {
621 IoCompleteRequest(Irps[j], IO_NO_INCREMENT);
622 ChildDeviceData->IrpCompleted++;
623 }
625 //KdPrint((__DRIVER_NAME " <-- XenVbd_DpcThreadProc\n"));
626 //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));
627 }
629 static BOOLEAN
630 XenVbd_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
631 {
632 BOOLEAN RetVal;
633 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
635 UNREFERENCED_PARAMETER(Interrupt);
636 // !!!RUNS AT DIRQL!!!
638 //KdPrint((__DRIVER_NAME " --> XenVbd_Interrupt\n"));
640 ChildDeviceData = (PXENVBD_CHILD_DEVICE_DATA)ServiceContext;
641 ChildDeviceData->IrpAddedToRingAtLastInterrupt = ChildDeviceData->IrpAddedToRing;
642 RetVal = WdfDpcEnqueue(ChildDeviceData->Dpc);
644 //KdPrint((__DRIVER_NAME " <-- XenVbd_Interrupt (RetVal = %d)\n", RetVal));
646 return STATUS_SUCCESS;
647 }
649 static VOID
650 XenVbd_BackEndStateHandler(char *Path, PVOID Data)
651 {
652 PXENVBD_CHILD_DEVICE_DATA DeviceData;
653 char TmpPath[128];
654 char *Value;
655 int NewState;
656 PMDL Mdl;
657 grant_ref_t ref;
658 blkif_sring_t *SharedRing;
659 ULONG PFN;
660 XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION Description;
661 NTSTATUS status;
663 DeviceData = (PXENVBD_CHILD_DEVICE_DATA)Data;
665 XenBusInterface.Read(XBT_NIL, Path, &Value);
667 NewState = atoi(Value);
668 switch (NewState)
669 {
670 case XenbusStateUnknown:
671 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
672 break;
674 case XenbusStateInitialising:
675 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
676 break;
678 case XenbusStateInitWait:
679 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
681 DeviceData->EventChannel = EvtChnInterface.AllocUnbound(0);
682 EvtChnInterface.Bind(DeviceData->EventChannel, XenVbd_Interrupt, DeviceData);
683 Mdl = AllocatePage();
684 PFN = *MmGetMdlPfnArray(Mdl);
685 SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
686 SHARED_RING_INIT(SharedRing);
687 FRONT_RING_INIT(&DeviceData->Ring, SharedRing, PAGE_SIZE);
688 ref = GntTblInterface.GrantAccess(0, PFN, FALSE);
690 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
691 RtlStringCbCatA(TmpPath, 128, "/ring-ref");
692 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", ref);
694 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
695 RtlStringCbCatA(TmpPath, 128, "/event-channel");
696 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", DeviceData->EventChannel);
698 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
699 RtlStringCbCatA(TmpPath, 128, "/state");
700 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
702 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
703 break;
705 case XenbusStateInitialised:
706 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
707 // create the device
708 break;
710 case XenbusStateConnected:
711 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
713 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Description.Header, sizeof(Description));
715 Description.DeviceData = DeviceData;
717 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
718 RtlStringCbCatA(TmpPath, 128, "/device-type");
719 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
720 if (strcmp(Value, "disk") == 0)
721 {
722 KdPrint((__DRIVER_NAME " DeviceType = Disk\n"));
723 DeviceData->DeviceType = XENVBD_DEVICETYPE_DISK;
724 }
725 else if (strcmp(Value, "cdrom") == 0)
726 {
727 KdPrint((__DRIVER_NAME " DeviceType = CDROM\n"));
728 DeviceData->DeviceType = XENVBD_DEVICETYPE_CDROM;
729 }
730 else
731 {
732 KdPrint((__DRIVER_NAME " DeviceType = %s (This probably won't work!)\n", Value));
733 }
735 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
736 RtlStringCbCatA(TmpPath, 128, "/type"); // should probably check that this is 'phy' or 'file' or at least not ''
737 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
738 KdPrint((__DRIVER_NAME " Backend Type = %s\n", Value));
740 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
741 RtlStringCbCatA(TmpPath, 128, "/mode"); // should store this...
742 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
743 KdPrint((__DRIVER_NAME " Backend Mode = %s\n", Value));
745 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
746 RtlStringCbCatA(TmpPath, 128, "/sector-size");
747 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
748 // should complain if Value == NULL
749 DeviceData->BytesPerSector = atoi(Value);
751 KdPrint((__DRIVER_NAME " BytesPerSector = %d\n", DeviceData->BytesPerSector));
753 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
754 RtlStringCbCatA(TmpPath, 128, "/sectors");
755 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
756 // should complain if Value == NULL
757 DeviceData->TotalSectors = (ULONGLONG)atol(Value);
759 KdPrint((__DRIVER_NAME " TotalSectors = %d\n", DeviceData->TotalSectors));
761 // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
762 DeviceData->Geometry.MediaType = FixedMedia;
763 DeviceData->Geometry.BytesPerSector = DeviceData->BytesPerSector;
764 DeviceData->Geometry.SectorsPerTrack = 63;
765 DeviceData->Geometry.TracksPerCylinder = 255;
766 DeviceData->Geometry.Cylinders.QuadPart = DeviceData->TotalSectors / DeviceData->Geometry.SectorsPerTrack / DeviceData->Geometry.TracksPerCylinder;
767 KdPrint((__DRIVER_NAME " Geometry C/H/S = %d/%d/%d\n", DeviceData->Geometry.Cylinders.LowPart, DeviceData->Geometry.TracksPerCylinder, DeviceData->Geometry.SectorsPerTrack));
769 // if we detected something wrong, we should not enumarate the device and should instead initiate a close
771 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(WdfFdoGetDefaultChildList(GlobalDevice), &Description.Header, NULL);
772 if (!NT_SUCCESS(status))
773 {
774 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed %08x\n", status));
775 }
777 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
778 RtlStringCbCatA(TmpPath, 128, "/state");
779 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", XenbusStateConnected);
781 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
782 InterlockedIncrement(&EnumeratedDevices);
783 KdPrint((__DRIVER_NAME " Added a disk, notifying\n"));
785 KeSetEvent(&WaitDevicesEvent, 1, FALSE);
787 break;
789 case XenbusStateClosing:
790 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
791 break;
793 case XenbusStateClosed:
794 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
795 break;
797 default:
798 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
799 break;
800 }
801 }
803 static VOID
804 XenVbd_HotPlugHandler(char *Path, PVOID Data)
805 {
806 PXENVBD_CHILD_DEVICE_DATA DeviceData;
807 char **Bits;
808 int Count;
809 char TmpPath[128];
810 char *Value;
812 UNREFERENCED_PARAMETER(Data);
814 //KdPrint((__DRIVER_NAME " --> HotPlugHandler\n"));
816 //KdPrint((__DRIVER_NAME " Path = %s\n", Path));
818 Bits = SplitString(Path, '/', 4, &Count);
819 switch (Count)
820 {
821 case 0:
822 case 1:
823 case 2:
824 break; // should never happen
825 case 3:
826 break;
827 case 4:
829 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
830 break;
831 for (DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceListHead.Flink; DeviceData != (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead; DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceData->Entry.Flink)
832 {
833 if (strncmp(DeviceData->Path, Path, strlen(DeviceData->Path)) == 0 && Path[strlen(DeviceData->Path)] == '/')
834 {
835 break;
836 }
837 }
838 if (DeviceData == (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead)
839 {
840 DeviceData = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENVBD_CHILD_DEVICE_DATA), XENVBD_POOL_TAG);
841 memset(DeviceData, 0, sizeof(XENVBD_CHILD_DEVICE_DATA));
843 //KdPrint((__DRIVER_NAME " Allocated ChildDeviceData = %08x\n", DeviceData));
845 InsertTailList(&DeviceListHead, &DeviceData->Entry);
846 RtlStringCbCopyA(DeviceData->Path, 128, Bits[0]);
847 RtlStringCbCatA(DeviceData->Path, 128, "/");
848 RtlStringCbCatA(DeviceData->Path, 128, Bits[1]);
849 RtlStringCbCatA(DeviceData->Path, 128, "/");
850 RtlStringCbCatA(DeviceData->Path, 128, Bits[2]);
852 DeviceData->DeviceIndex = atoi(Bits[2]);
854 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
855 RtlStringCbCatA(TmpPath, 128, "/backend");
856 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
857 if (Value == NULL)
858 {
859 KdPrint((__DRIVER_NAME " Read Failed\n"));
860 }
861 else
862 {
863 RtlStringCbCopyA(DeviceData->BackendPath, 128, Value);
864 }
865 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
866 RtlStringCbCatA(TmpPath, 128, "/state");
867 XenBusInterface.AddWatch(XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, DeviceData);
868 }
869 break;
870 }
872 FreeSplitString(Bits, Count);
874 //KdPrint((__DRIVER_NAME " <-- HotPlugHandler\n"));
876 return;
877 }
879 static NTSTATUS
880 XenVbd_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit)
881 {
882 NTSTATUS status;
883 WDFDEVICE ChildDevice;
884 PXENVBD_DEVICE_IDENTIFICATION_DESCRIPTION XenVbdIdentificationDesc;
885 DECLARE_UNICODE_STRING_SIZE(buffer, 50);
886 WDF_OBJECT_ATTRIBUTES PdoAttributes;
887 DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
888 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
889 WDF_IO_QUEUE_CONFIG IoQueueConfig;
890 unsigned int i;
891 WDF_DPC_CONFIG DpcConfig;
892 WDF_OBJECT_ATTRIBUTES DpcObjectAttributes;
893 WDF_DEVICE_STATE DeviceState;
894 UCHAR ScsiMinors[1] = { IRP_MN_SCSI_CLASS };
896 UNREFERENCED_PARAMETER(ChildList);
898 KdPrint((__DRIVER_NAME " --> ChildListCreateDevice\n"));
900 XenVbdIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION, Header);
902 ChildDeviceData = XenVbdIdentificationDesc->DeviceData;
904 // Capabilities = CM_DEVCAP_UNIQUEID
905 // Devnode Flages = DN_NEED_RESTART??? DN_DISABLEABLE???
907 switch (ChildDeviceData->DeviceType)
908 {
909 case XENVBD_DEVICETYPE_DISK:
910 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_DISK);
912 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk\0");
913 //status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk&Ven_James&Prod_James&Rev_1.00\0");
914 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
916 status = RtlUnicodeStringPrintf(&buffer, L"%02d\0", ChildDeviceData->DeviceIndex);
917 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
919 status = RtlUnicodeStringPrintf(&buffer, L"GenDisk\0");
920 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
921 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
923 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV Disk (%d)", ChildDeviceData->DeviceIndex);
924 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
925 break;
926 case XENVBD_DEVICETYPE_CDROM:
927 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_MASS_STORAGE);
928 WdfDeviceInitSetCharacteristics(ChildInit, FILE_READ_ONLY_DEVICE|FILE_REMOVABLE_MEDIA, TRUE);
930 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\CDROM\0");
931 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
933 status = RtlUnicodeStringPrintf(&buffer, L"%02d\0", ChildDeviceData->DeviceIndex);
934 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
936 status = RtlUnicodeStringPrintf(&buffer, L"GenCdRom\0");
937 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
938 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
940 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV CDROM (%d)\0", ChildDeviceData->DeviceIndex);
941 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
942 break;
943 default:
944 // wtf?
945 break;
946 }
948 WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
950 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, PXENVBD_CHILD_DEVICE_DATA);
952 //WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSCSI, IRP_MJ_SCSI, ScsiMinors, 1);
953 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSCSI, IRP_MJ_SCSI, NULL, 0);
954 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpDEVICE_CONTROL, IRP_MJ_DEVICE_CONTROL, NULL, 0);
956 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CLEANUP, NULL, 0);
957 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CLOSE, NULL, 0);
958 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CREATE, NULL, 0);
959 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_DIRECTORY_CONTROL, NULL, 0);
960 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_FILE_SYSTEM_CONTROL, NULL, 0);
961 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_FLUSH_BUFFERS, NULL, 0);
962 /// WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_INTERNAL_DEVICE_CONTROL, NULL, 0);
963 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_LOCK_CONTROL, NULL, 0);
964 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_POWER, NULL, 0);
965 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_EA, NULL, 0);
966 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_INFORMATION, NULL, 0);
967 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_SECURITY, NULL, 0);
968 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_VOLUME_INFORMATION, NULL, 0);
969 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_READ, NULL, 0);
970 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_INFORMATION, NULL, 0);
971 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_SECURITY, NULL, 0);
972 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_VOLUME_INFORMATION, NULL, 0);
973 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SHUTDOWN, NULL, 0);
974 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SYSTEM_CONTROL, NULL, 0);
975 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_WRITE, NULL, 0);
977 WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);
979 //WdfDeviceInitSetPowerNotPageable(ChildInit);
981 status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
982 if (!NT_SUCCESS(status))
983 {
984 KdPrint((__DRIVER_NAME " WdfDeviceCreate status = %08X\n", status));
985 }
987 switch (ChildDeviceData->DeviceType)
988 {
989 case XENVBD_DEVICETYPE_DISK:
990 WDF_DEVICE_STATE_INIT(&DeviceState);
991 DeviceState.NotDisableable = WdfTrue;
992 WdfDeviceSetDeviceState(ChildDevice, &DeviceState);
993 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFilePaging, TRUE);
994 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileHibernation, TRUE);
995 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileDump, TRUE);
996 break;
997 case XENVBD_DEVICETYPE_CDROM:
998 break;
999 }
1000 *GetChildDeviceData(ChildDevice) = ChildDeviceData;
1002 ChildDeviceData->FastPathUsed = 0;
1003 ChildDeviceData->SlowPathUsed = 0;
1004 ChildDeviceData->IrpAddedToList = 0;
1005 ChildDeviceData->IrpRemovedFromList = 0;
1006 ChildDeviceData->IrpAddedToRing = 0;
1007 ChildDeviceData->IrpAddedToRingAtLastNotify = 0;
1008 ChildDeviceData->IrpAddedToRingAtLastInterrupt = 0;
1009 ChildDeviceData->IrpAddedToRingAtLastDpc = 0;
1010 ChildDeviceData->IrpRemovedFromRing = 0;
1011 ChildDeviceData->IrpCompleted = 0;
1013 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoQueueConfig, WdfIoQueueDispatchSequential);
1014 IoQueueConfig.AllowZeroLengthRequests = TRUE;
1015 //IoQueueConfig.EvtIoDefault = XenVbd_Child_IoDefault;
1016 //IoQueueConfig.EvtIoRead = XenVbd_Child_IoReadWrite;
1017 //IoQueueConfig.EvtIoWrite = XenVbd_Child_IoReadWrite;
1018 IoQueueConfig.EvtIoDeviceControl = XenVbd_Child_IoDeviceControl;
1019 //IoQueueConfig.EvtIoInternalDeviceControl = XenVbd_Child_IoInternalDeviceControl; // is IRP_MJ_SCSI
1021 status = WdfIoQueueCreate(ChildDevice, &IoQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &ChildDeviceData->IoDefaultQueue);
1022 if(!NT_SUCCESS(status))
1024 KdPrint((__DRIVER_NAME "WdfIoQueueCreate failed with status 0x%08x\n", status));
1025 return status;
1028 ChildDeviceData->Device = ChildDevice;
1030 KeInitializeSpinLock(&ChildDeviceData->Lock);
1031 KeInitializeSpinLock(&ChildDeviceData->IrpListLock);
1032 InitializeListHead(&ChildDeviceData->IrpListHead);
1034 ChildDeviceData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * BLK_RING_SIZE, XENVBD_POOL_TAG);
1035 memset(ChildDeviceData->shadow, 0, sizeof(blkif_shadow_t) * BLK_RING_SIZE);
1036 //KdPrint((__DRIVER_NAME " Allocated shadow = %08x\n", ChildDeviceData->shadow));
1037 for (i = 0; i < BLK_RING_SIZE; i++)
1038 ChildDeviceData->shadow[i].req.id = i + 1;
1039 ChildDeviceData->shadow_free = 0;
1040 ChildDeviceData->shadow[BLK_RING_SIZE - 1].req.id = 0x0fffffff;
1042 WDF_DPC_CONFIG_INIT(&DpcConfig, XenVbd_DpcThreadProc);
1043 WDF_OBJECT_ATTRIBUTES_INIT(&DpcObjectAttributes);
1044 DpcObjectAttributes.ParentObject = ChildDevice;
1045 WdfDpcCreate(&DpcConfig, &DpcObjectAttributes, &ChildDeviceData->Dpc);
1047 KdPrint((__DRIVER_NAME " <-- ChildListCreateDevice (status = %08x)\n", status));
1049 return status;
1053 // 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
1055 // Call with device lock held
1056 static VOID
1057 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp)
1059 char *DataBuffer;
1060 PSCSI_REQUEST_BLOCK Srb;
1061 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1062 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1063 blkif_request_t *req;
1064 int i;
1065 int j;
1066 int BlockCount;
1067 int sect_offset;
1069 ChildDeviceData = *GetChildDeviceData(Device);
1071 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1072 KdPrint((__DRIVER_NAME " --> PutIrpOnRing\n"));
1074 if (RING_FULL(&ChildDeviceData->Ring))
1076 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
1079 req = RING_GET_REQUEST(&ChildDeviceData->Ring, ChildDeviceData->Ring.req_prod_pvt);
1081 //KdPrint((__DRIVER_NAME " req = %08x\n", req));
1083 Srb = irpSp->Parameters.Scsi.Srb;
1085 req->sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
1086 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
1088 req->id = GET_ID_FROM_FREELIST(ChildDeviceData);
1090 if (req->id == 0x0fffffff)
1092 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutIrpOnRing\n"));
1095 //KdPrint((__DRIVER_NAME " id = %d\n", req->id));
1097 req->handle = 0;
1098 req->operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
1099 ChildDeviceData->shadow[req->id].Irp = Irp;
1101 if ((MmGetMdlByteOffset(Irp->MdlAddress) & 0x1ff) == 0) // 0x1ff shouldn't be hardcoded...
1103 // fast path - zero copy
1104 ChildDeviceData->shadow[req->id].Mdl = Irp->MdlAddress;
1105 ChildDeviceData->shadow[req->id].Buf = NULL; // we don't need the virtual address
1106 ChildDeviceData->FastPathUsed++;
1108 else
1110 // slow path - copy to bounce buffer
1111 ChildDeviceData->shadow[req->id].Mdl = AllocatePages((BlockCount * ChildDeviceData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE);
1112 ChildDeviceData->shadow[req->id].Buf = MmGetMdlVirtualAddress(ChildDeviceData->shadow[req->id].Mdl);
1113 if (ChildDeviceData->shadow[req->id].Buf == NULL)
1115 KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress returned NULL in PutIrpOnRing\n"));
1117 ChildDeviceData->SlowPathUsed++;
1120 // if (((ChildDeviceData->FastPathUsed + ChildDeviceData->SlowPathUsed) & 0x2FF) == 0)
1121 // {
1122 // KdPrint((__DRIVER_NAME " Fast Path = %d, Slow Path = %d\n", ChildDeviceData->FastPathUsed, ChildDeviceData->SlowPathUsed));
1123 // 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));
1124 // }
1126 sect_offset = MmGetMdlByteOffset(ChildDeviceData->shadow[req->id].Mdl) >> 9;
1127 for (i = 0, req->nr_segments = 0; i < BlockCount; req->nr_segments++)
1129 req->seg[req->nr_segments].gref = GntTblInterface.GrantAccess(0, MmGetMdlPfnArray(ChildDeviceData->shadow[req->id].Mdl)[req->nr_segments], FALSE);
1130 req->seg[req->nr_segments].first_sect = sect_offset;
1131 for (j = sect_offset; i < BlockCount && j < PAGE_SIZE / ChildDeviceData->BytesPerSector; j++, i++)
1132 req->seg[req->nr_segments].last_sect = (uint8_t)j;
1133 sect_offset = 0;
1135 if (Srb->Cdb[0] == SCSIOP_WRITE && ChildDeviceData->shadow[req->id].Buf != NULL)
1137 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1138 if (DataBuffer == NULL)
1139 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe failed in PutIrpOnRing\n"));
1140 memcpy(ChildDeviceData->shadow[req->id].Buf, DataBuffer, BlockCount * ChildDeviceData->BytesPerSector);
1142 ChildDeviceData->shadow[req->id].req = *req;
1144 ChildDeviceData->Ring.req_prod_pvt++;
1146 ChildDeviceData->IrpAddedToRing++;
1148 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1149 KdPrint((__DRIVER_NAME " <-- PutIrpOnRing\n"));
1152 static ULONG
1153 XenVBD_FillModePage(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
1155 PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
1157 switch (PageCode)
1159 case MODE_PAGE_RIGID_GEOMETRY:
1160 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_DISK)
1162 KdPrint((__DRIVER_NAME " MODE_PAGE_RIGID_GEOMETRY\n"));
1163 if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
1164 return 1;
1165 ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
1166 memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
1167 ModeRigidGeometry->PageCode = PageCode;
1168 ModeRigidGeometry->PageSavable = 0;
1169 ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
1170 ModeRigidGeometry->NumberOfCylinders[0] = (ChildDeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF;
1171 ModeRigidGeometry->NumberOfCylinders[1] = (ChildDeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF;
1172 ModeRigidGeometry->NumberOfCylinders[2] = (ChildDeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF;
1173 ModeRigidGeometry->NumberOfHeads = ChildDeviceData->Geometry.TracksPerCylinder;
1174 //ModeRigidGeometry->LandZoneCyclinder = 0;
1175 ModeRigidGeometry->RoataionRate[0] = 0x05;
1176 ModeRigidGeometry->RoataionRate[0] = 0x39;
1177 *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
1179 break;
1180 case MODE_PAGE_FAULT_REPORTING:
1181 break;
1182 default:
1183 break;
1185 return 0;
1188 static NTSTATUS
1189 XenVbd_Child_PreprocessWdmIrpDEVICE_CONTROL(WDFDEVICE Device, PIRP Irp)
1191 NTSTATUS Status;
1192 PIO_STACK_LOCATION IrpStack;
1193 PSCSI_ADDRESS ScsiAddress;
1195 KdPrint((__DRIVER_NAME " --> PreprocessWdmIrpDEVICE_CONTROL\n"));
1197 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1199 switch (IrpStack->Parameters.DeviceIoControl.IoControlCode)
1201 case IOCTL_SCSI_GET_ADDRESS:
1202 KdPrint((__DRIVER_NAME " IOCTL_SCSI_GET_ADDRESS\n"));
1203 Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
1204 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(SCSI_ADDRESS))
1206 ScsiAddress = (PSCSI_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1207 ScsiAddress->Length = sizeof(SCSI_ADDRESS);
1208 ScsiAddress->PortNumber = 0;
1209 ScsiAddress->PathId = 0;
1210 ScsiAddress->TargetId = 0;
1211 ScsiAddress->Lun = 0;
1212 Status = STATUS_SUCCESS;
1213 Irp->IoStatus.Status = Status;
1214 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1216 else
1218 KdPrint((__DRIVER_NAME " (Buffer size too small @ %d\n", IrpStack->Parameters.DeviceIoControl.OutputBufferLength));
1220 break;
1221 default:
1222 KdPrint((__DRIVER_NAME " Control Code = %08x\n", IrpStack->Parameters.DeviceIoControl.IoControlCode));
1223 IoSkipCurrentIrpStackLocation(Irp);
1224 Status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1227 KdPrint((__DRIVER_NAME " <-- PreprocessWdmIrpDEVICE_CONTROL\n"));
1229 return Status;
1232 static NTSTATUS
1233 XenVbd_Child_PreprocessWdmIrpSomethingSomething(WDFDEVICE Device, PIRP Irp)
1235 NTSTATUS Status;
1236 PIO_STACK_LOCATION IrpStack;
1238 KdPrint((__DRIVER_NAME " --> XenVbd_Child_PreprocessWdmIrpSomethingSomething\n"));
1240 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1241 KdPrint((__DRIVER_NAME " Major = %02X, Minor = %02X\n", IrpStack->MajorFunction, IrpStack->MinorFunction));
1243 IoSkipCurrentIrpStackLocation(Irp);
1245 Status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1247 KdPrint((__DRIVER_NAME " <-- XenVbd_Child_PreprocessWdmIrpSomethingSomething\n"));
1249 return Status;
1252 static NTSTATUS
1253 XenVbd_Child_PreprocessWdmIrpSCSI(WDFDEVICE Device, PIRP Irp)
1255 char *DataBuffer;
1256 NTSTATUS status = STATUS_SUCCESS;
1257 PSCSI_REQUEST_BLOCK Srb;
1258 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1259 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1260 KIRQL KIrql;
1261 XenVbd_ListEntry *ListEntry;
1262 int notify;
1263 PCDB cdb;
1264 //PUCHAR Ptr;
1265 ULONG i;
1267 ChildDeviceData = *GetChildDeviceData(Device);
1269 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1270 KdPrint((__DRIVER_NAME " --> WdmIrpPreprocessSCSI\n"));
1272 //KdPrint((__DRIVER_NAME " SCSI Minor = %02X\n", irpSp->MinorFunction));
1274 Srb = irpSp->Parameters.Scsi.Srb;
1276 switch (Srb->Function)
1278 case SRB_FUNCTION_EXECUTE_SCSI:
1279 cdb = (PCDB)Srb->Cdb;
1280 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1281 KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
1282 switch(cdb->CDB6GENERIC.OperationCode) //Srb->Cdb[0])
1284 case SCSIOP_TEST_UNIT_READY:
1285 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1286 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1287 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1288 Srb->ScsiStatus = 0;
1289 status = STATUS_SUCCESS;
1290 Irp->IoStatus.Status = status;
1291 Irp->IoStatus.Information = 0;
1292 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1293 break;
1294 case SCSIOP_INQUIRY:
1295 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1296 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1297 if ((Srb->Cdb[1] & 1) == 0)
1299 // DataBuffer = Srb->DataBuffer;
1300 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1301 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1303 DataBuffer[0] = 0x00; // disk
1304 DataBuffer[1] = 0x00; // not removable
1305 memcpy(DataBuffer + 8, "James ", 8); // vendor id
1306 memcpy(DataBuffer + 16, "XenVBD ", 8); // product id
1307 memcpy(DataBuffer + 32, "000", 8); // product revision level
1308 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1310 else
1312 //KdPrint((__DRIVER_NAME " Command = INQUIRY (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1313 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1315 Srb->ScsiStatus = 0;
1316 status = STATUS_SUCCESS;
1317 Irp->IoStatus.Status = status;
1318 Irp->IoStatus.Information = 0;
1319 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1320 break;
1321 case SCSIOP_READ_CAPACITY:
1322 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1323 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1324 // DataBuffer = Srb->DataBuffer;
1325 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1326 DataBuffer[0] = (unsigned char)(ChildDeviceData->TotalSectors >> 24) & 0xff;
1327 DataBuffer[1] = (unsigned char)(ChildDeviceData->TotalSectors >> 16) & 0xff;
1328 DataBuffer[2] = (unsigned char)(ChildDeviceData->TotalSectors >> 8) & 0xff;
1329 DataBuffer[3] = (unsigned char)(ChildDeviceData->TotalSectors >> 0) & 0xff;
1330 DataBuffer[4] = (unsigned char)(ChildDeviceData->BytesPerSector >> 24) & 0xff;
1331 DataBuffer[5] = (unsigned char)(ChildDeviceData->BytesPerSector >> 16) & 0xff;
1332 DataBuffer[6] = (unsigned char)(ChildDeviceData->BytesPerSector >> 8) & 0xff;
1333 DataBuffer[7] = (unsigned char)(ChildDeviceData->BytesPerSector >> 0) & 0xff;
1334 Srb->ScsiStatus = 0;
1335 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1336 status = STATUS_SUCCESS;
1337 Irp->IoStatus.Status = status;
1338 Irp->IoStatus.Information = 0;
1339 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1340 break;
1341 case SCSIOP_MODE_SENSE:
1342 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));
1343 KdPrint((__DRIVER_NAME " Length = %d\n", Srb->DataTransferLength));
1345 status = STATUS_SUCCESS;
1346 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1347 // DataBuffer = Srb->DataBuffer;
1348 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1349 switch(cdb->MODE_SENSE.PageCode) //Srb->Cdb[2] & 0x3F)
1351 case MODE_SENSE_RETURN_ALL:
1352 Irp->IoStatus.Information = 0;
1353 //Ptr = (UCHAR *)Srb->DataBuffer;
1354 for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
1356 if (XenVBD_FillModePage(ChildDeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Irp->IoStatus.Information))
1358 break;
1361 break;
1362 default:
1363 XenVBD_FillModePage(ChildDeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Irp->IoStatus.Information);
1364 break;
1366 Srb->DataTransferLength = Irp->IoStatus.Information;
1367 // Srb->ScsiStatus = 0;
1368 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1369 Irp->IoStatus.Status = status;
1370 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1371 break;
1372 case SCSIOP_READ:
1373 case SCSIOP_WRITE:
1374 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1375 KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1377 IoMarkIrpPending(Irp);
1379 //KdPrint((__DRIVER_NAME " Irp Acquiring Lock\n"));
1380 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
1381 //KdPrint((__DRIVER_NAME "A Got It\n"));
1383 if (RING_FULL(&ChildDeviceData->Ring))
1385 //KdPrint((__DRIVER_NAME "A Inserting into list\n"));
1386 ListEntry = (XenVbd_ListEntry *)ExAllocatePoolWithTag(NonPagedPool, sizeof(XenVbd_ListEntry), XENVBD_POOL_TAG);
1387 //KdPrint((__DRIVER_NAME " Allocate ListEntry = %08x\n", ListEntry));
1388 if (ListEntry == NULL)
1390 KdPrint((__DRIVER_NAME " CANNOT ALLOCATE MEMORY FOR ListEntry!!!\n"));
1392 ListEntry->Irp = Irp;
1393 InsertTailList(&ChildDeviceData->IrpListHead, &ListEntry->Entry);
1394 ChildDeviceData->IrpAddedToList++;
1396 else
1398 XenVbd_PutIrpOnRing(Device, Irp);
1399 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
1400 if (notify)
1401 EvtChnInterface.Notify(ChildDeviceData->EventChannel);
1402 //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));
1404 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
1405 status = STATUS_PENDING;
1406 break;
1407 case SCSIOP_READ_TOC:
1408 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1409 /*
1410 #define READ_TOC_FORMAT_TOC 0x00
1411 #define READ_TOC_FORMAT_SESSION 0x01
1412 #define READ_TOC_FORMAT_FULL_TOC 0x02
1413 #define READ_TOC_FORMAT_PMA 0x03
1414 #define READ_TOC_FORMAT_ATIP 0x04
1415 */
1416 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1417 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1418 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1419 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1420 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1421 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1422 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1423 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1424 switch (cdb->READ_TOC.Format2)
1426 case READ_TOC_FORMAT_TOC:
1427 DataBuffer[0] = 0; // length MSB
1428 DataBuffer[1] = 10; // length LSB
1429 DataBuffer[2] = 1; // First Track
1430 DataBuffer[3] = 1; // Last Track
1431 DataBuffer[4] = 0; // Reserved
1432 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1433 DataBuffer[6] = 1; // last complete track
1434 DataBuffer[7] = 0; // reserved
1435 DataBuffer[8] = 0; // MSB Block
1436 DataBuffer[9] = 0;
1437 DataBuffer[10] = 0;
1438 DataBuffer[11] = 0; // LSB Block
1439 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1440 break;
1441 case READ_TOC_FORMAT_SESSION:
1442 case READ_TOC_FORMAT_FULL_TOC:
1443 case READ_TOC_FORMAT_PMA:
1444 case READ_TOC_FORMAT_ATIP:
1445 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1446 break;
1448 Irp->IoStatus.Status = status;
1449 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1450 break;
1451 /*
1452 case SCSIOP_GET_CONFIGURATION:
1453 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL 0x0
1454 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT 0x1
1455 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE 0x2
1457 UCHAR OperationCode; // 0x46 - SCSIOP_GET_CONFIGURATION
1458 UCHAR RequestType : 2; // SCSI_GET_CONFIGURATION_REQUEST_TYPE_*
1459 UCHAR Reserved1 : 6; // includes obsolete LUN field
1460 UCHAR StartingFeature[2];
1461 UCHAR Reserved2[3];
1462 UCHAR AllocationLength[2];
1463 UCHAR Control;
1464 break;
1465 */
1466 default:
1467 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1468 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1469 Irp->IoStatus.Status = status;
1470 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1471 break;
1473 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1474 break;
1475 case SRB_FUNCTION_CLAIM_DEVICE:
1476 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1477 KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
1478 // ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
1479 Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
1480 // Srb->DataBuffer = WdfDeviceWdmGetAttachedDevice(Device);
1481 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1482 status = STATUS_SUCCESS;
1483 Irp->IoStatus.Status = status;
1484 Irp->IoStatus.Information = 0;
1485 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1486 break;
1487 case SRB_FUNCTION_IO_CONTROL:
1488 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1489 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1490 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1491 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1492 status = STATUS_NOT_IMPLEMENTED;
1493 //Irp->IoStatus.Status = status;
1494 //Irp->IoStatus.Information = 0;
1495 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1496 break;
1497 case SRB_FUNCTION_FLUSH:
1498 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1499 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1500 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1501 status = STATUS_SUCCESS;
1502 Irp->IoStatus.Status = status;
1503 Irp->IoStatus.Information = 0;
1504 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1505 break;
1506 default:
1507 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1508 status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1509 break;
1512 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1513 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));
1514 //KdPrint((__DRIVER_NAME " <-- WdmIrpPreprocessSCSI\n"));
1516 return status;
1519 static VOID
1520 XenVbd_Child_IoDefault(WDFQUEUE Queue, WDFREQUEST Request)
1522 UNREFERENCED_PARAMETER(Queue);
1524 KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
1526 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1528 KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
1531 static VOID
1532 XenVbd_Child_IoReadWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t Length)
1534 UNREFERENCED_PARAMETER(Queue);
1536 KdPrint((__DRIVER_NAME " --> IoReadWrite\n"));
1538 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1540 KdPrint((__DRIVER_NAME " <-- IoReadWrite\n"));
1543 static VOID
1544 XenVbd_Child_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode)
1546 WDFDEVICE Device;
1547 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1548 PIRP Irp;
1549 PSTORAGE_PROPERTY_QUERY Spq;
1550 PSTORAGE_ADAPTER_DESCRIPTOR Sad;
1551 PSTORAGE_DEVICE_DESCRIPTOR Sdd;
1552 PSTORAGE_DEVICE_ID_DESCRIPTOR Sdid;
1553 PSTORAGE_IDENTIFIER Si;
1554 PSCSI_ADDRESS Sa;
1555 ULONG Information;
1556 //NTSTATUS Status;
1557 int StructEndOffset;
1559 UNREFERENCED_PARAMETER(Queue);
1560 //UNREFERENCED_PARAMETER(Request);
1561 UNREFERENCED_PARAMETER(OutputBufferLength);
1562 UNREFERENCED_PARAMETER(InputBufferLength);
1564 Device = WdfIoQueueGetDevice(Queue);
1566 ChildDeviceData = *GetChildDeviceData(Device);
1568 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1569 KdPrint((__DRIVER_NAME " --> IoDeviceControl\n"));
1570 //KdPrint((__DRIVER_NAME " InputBufferLength = %d\n", InputBufferLength));
1571 //KdPrint((__DRIVER_NAME " OutputBufferLength = %d\n", OutputBufferLength));
1573 Irp = WdfRequestWdmGetIrp(Request);
1575 switch (IoControlCode)
1577 case IOCTL_STORAGE_QUERY_PROPERTY:
1578 KdPrint((__DRIVER_NAME " IOCTL_STORAGE_QUERY_PROPERTY\n"));
1579 Spq = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
1580 if (Spq->PropertyId == StorageAdapterProperty && Spq->QueryType == PropertyStandardQuery)
1582 KdPrint((__DRIVER_NAME " PropertyId = StorageAdapterProperty, QueryType = PropertyStandardQuery\n"));
1583 Information = 0;
1584 if (OutputBufferLength >= 8)
1586 Information = 8;
1587 Sad = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1588 Sad->Version = 1;
1589 Sad->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
1590 if (OutputBufferLength >= Sad->Size)
1592 Information = Sad->Size;
1593 Sad->MaximumTransferLength = 45056;
1594 Sad->MaximumPhysicalPages = 11;
1595 Sad->AlignmentMask = 0;
1596 Sad->AdapterUsesPio = FALSE;
1597 Sad->AdapterScansDown = FALSE;
1598 Sad->CommandQueueing = FALSE;
1599 Sad->AcceleratedTransfer = FALSE;
1600 Sad->BusType = BusTypeScsi;
1601 Sad->BusMajorVersion = 0;
1602 Sad->BusMinorVersion = 0;
1605 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Information);
1607 else if (Spq->PropertyId == StorageDeviceProperty && Spq->QueryType == PropertyStandardQuery)
1609 KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceProperty, QueryType = PropertyStandardQuery\n"));
1610 Information = 0;
1611 if (OutputBufferLength >= 8)
1613 Information = 8;
1614 Sdd = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1615 Sdd->Version = 1;
1616 Sdd->Size = &Sdd->RawDeviceProperties[36] - (PUCHAR)Sdd + 1;
1617 // 0 0 1 2 3
1618 // 0 7 5 4 1
1619 //"VENDOR\0PRODUCT\0Revision\0Serial\0"
1620 if (OutputBufferLength >= Sdd->Size)
1622 Information = Sdd->Size;
1623 switch (ChildDeviceData->DeviceType)
1625 case XENVBD_DEVICETYPE_DISK:
1626 Sdd->DeviceType = DIRECT_ACCESS_DEVICE;
1627 Sdd->DeviceTypeModifier = 0x00;
1628 Sdd->RemovableMedia = FALSE;
1629 break;
1630 case XENVBD_DEVICETYPE_CDROM:
1631 Sdd->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1632 Sdd->DeviceTypeModifier = 0x00;
1633 Sdd->RemovableMedia = TRUE;
1634 break;
1635 default:
1636 // wtf
1637 break;
1639 Sdd->CommandQueueing = FALSE;
1640 StructEndOffset = Sdd->RawDeviceProperties - (PUCHAR)Sdd;
1641 Sdd->VendorIdOffset = StructEndOffset + 0;
1642 Sdd->ProductIdOffset = StructEndOffset + 7;
1643 Sdd->ProductRevisionOffset = StructEndOffset + 15;
1644 Sdd->SerialNumberOffset = StructEndOffset + 24;
1645 Sdd->BusType = BusTypeScsi;
1646 Sdd->RawPropertiesLength = 36;
1647 memcpy(Sdd->RawDeviceProperties, "VENDOR\0PRODUCT\0Revision\0Serial99999\0", 36);
1650 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Information);
1652 else if (Spq->PropertyId == StorageDeviceIdProperty && Spq->QueryType == PropertyStandardQuery)
1654 KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceIdProperty, QueryType = PropertyStandardQuery\n"));
1655 Information = 0;
1656 if (OutputBufferLength >= 8)
1658 Information = 8;
1659 Sdid = (PSTORAGE_DEVICE_ID_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1660 Sdid->Version = 1;
1661 Si = (PSTORAGE_IDENTIFIER)Sdid->Identifiers;
1662 Sdid->Size = &Si->Identifier[8] - (PUCHAR)Sdid + 1;
1663 if (OutputBufferLength >= Sdid->Size)
1665 Information = Sdid->Size;
1666 Sdid->NumberOfIdentifiers = 1;
1667 Si->CodeSet = StorageIdCodeSetAscii;
1668 Si->Type = StorageIdTypeScsiNameString;
1669 //Si->CodeSet = StorageIdCodeSetBinary;
1670 //Si->Type = StorageIdTypeEUI64;
1671 Si->IdentifierSize = 9;
1672 Si->NextOffset = 0;
1673 Si->Association = StorageIdAssocPort;
1674 Si->Identifier[0] = 'S';
1675 Si->Identifier[1] = 'e';
1676 Si->Identifier[2] = 'r';
1677 Si->Identifier[3] = 'i';
1678 Si->Identifier[4] = 'a';
1679 Si->Identifier[5] = 'l';
1680 Si->Identifier[6] = '9';
1681 Si->Identifier[7] = '9';
1682 Si->Identifier[6] = '9';
1683 Si->Identifier[7] = '9';
1684 Si->Identifier[8] = '9';
1685 //Si->Identifier[8] = 0;
1688 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Information);
1690 else
1692 switch (Spq->PropertyId)
1694 case StorageDeviceProperty:
1695 KdPrint((__DRIVER_NAME " StorageDeviceProperty\n"));
1696 break;
1697 case StorageAccessAlignmentProperty:
1698 KdPrint((__DRIVER_NAME " StorageAccessAlignmentProperty\n"));
1699 break;
1700 case StorageAdapterProperty:
1701 KdPrint((__DRIVER_NAME " StorageAdapterProperty\n"));
1702 break;
1703 case StorageDeviceIdProperty:
1704 KdPrint((__DRIVER_NAME " StorageDeviceIdProperty\n"));
1705 break;
1706 case StorageDeviceUniqueIdProperty:
1707 KdPrint((__DRIVER_NAME " StorageDeviceUniqueIdProperty\n"));
1708 break;
1709 case StorageDeviceWriteCacheProperty:
1710 KdPrint((__DRIVER_NAME " StorageDeviceWriteCacheProperty\n"));
1711 break;
1712 default:
1713 KdPrint((__DRIVER_NAME " Unknown Property %08x\n", Spq->PropertyId));
1714 break;
1716 switch (Spq->QueryType)
1718 case PropertyStandardQuery:
1719 KdPrint((__DRIVER_NAME " PropertyStandardQuery\n"));
1720 break;
1721 case PropertyExistsQuery:
1722 KdPrint((__DRIVER_NAME " PropertyExistsQuery\n"));
1723 break;
1724 default:
1725 KdPrint((__DRIVER_NAME " Unknown Query %08x\n", Spq->QueryType));
1726 break;
1728 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1730 break;
1731 // http://www.osronline.com/article.cfm?article=229
1732 // 0x00560030 device = 0x56, Function = 0x00c =
1733 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
1734 KdPrint((__DRIVER_NAME " IOCTL_DISK_GET_DRIVE_GEOMETRY\n"));
1735 memcpy(Irp->AssociatedIrp.SystemBuffer, &ChildDeviceData->Geometry, sizeof(DISK_GEOMETRY));
1736 WdfRequestComplete(Request, STATUS_SUCCESS);
1737 break;
1738 case IOCTL_SCSI_GET_ADDRESS:
1739 KdPrint((__DRIVER_NAME " IOCTL_SCSI_GET_ADDRESS\n"));
1740 Sa = (PSCSI_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1741 Sa->Length = sizeof(SCSI_ADDRESS);
1742 Sa->PortNumber = 0;
1743 Sa->PathId = 0;
1744 Sa->TargetId = 0;
1745 Sa->Lun = 0;
1746 WdfRequestComplete(Request, STATUS_SUCCESS);
1747 break;
1748 case FT_BALANCED_READ_MODE: // just pretend we know what this is...
1749 KdPrint((__DRIVER_NAME " FT_BALANCED_READ_MODE\n"));
1750 WdfRequestComplete(Request, STATUS_SUCCESS);
1751 break;
1752 default:
1753 KdPrint((__DRIVER_NAME " Not Implemented IoControlCode=%08X\n", IoControlCode));
1754 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1755 break;
1758 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1759 KdPrint((__DRIVER_NAME " <-- IoDeviceControl\n"));
1762 static VOID
1763 XenVbd_Child_IoInternalDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode)
1765 KdPrint((__DRIVER_NAME " --> IoInternalDeviceControl\n"));
1766 KdPrint((__DRIVER_NAME " <-- IoInternalDeviceControl\n"));