win-pvdrivers

view xenvbd/xenvbd.c @ 35:2e1d570b69e9

Final commit before 0.4.0
author James Harper <james.harper@bendigoit.com.au>
date Wed Dec 05 19:56:11 2007 +1100 (2007-12-05)
parents 7fc983eddda8
children 3ac5c4431dbb d87e19a1eeeb
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 LIST_ENTRY DeviceListHead;
62 XEN_IFACE_EVTCHN EvtChnInterface;
63 XEN_IFACE_XENBUS XenBusInterface;
64 XEN_IFACE_XEN XenInterface;
65 XEN_IFACE_GNTTBL GntTblInterface;
67 static BOOLEAN AutoEnumerate;
69 NTSTATUS
70 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
71 {
72 WDF_DRIVER_CONFIG config;
73 ULONG status;
74 UNICODE_STRING RegKeyName;
75 UNICODE_STRING RegValueName;
76 HANDLE RegHandle;
77 OBJECT_ATTRIBUTES RegObjectAttributes;
78 char Buf[200];
79 ULONG BufLen = 200;
80 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
81 int State = 0;
82 int StartPos = 0;
83 WCHAR *SystemStartOptions;
84 size_t SystemStartOptionsLen;
85 size_t i;
87 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
89 WDF_DRIVER_CONFIG_INIT(&config, XenVbd_AddDevice);
90 status = WdfDriverCreate(
91 DriverObject,
92 RegistryPath,
93 WDF_NO_OBJECT_ATTRIBUTES,
94 &config,
95 WDF_NO_HANDLE);
96 if(!NT_SUCCESS(status))
97 {
98 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%08x\n", status));
99 }
101 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
102 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
103 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
104 if(!NT_SUCCESS(status))
105 {
106 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
107 }
109 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
110 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
111 if(!NT_SUCCESS(status))
112 {
113 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
114 }
115 //KdPrint((__DRIVER_NAME " BufLen = %d\n", BufLen));
116 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
117 KdPrint((__DRIVER_NAME " Buf = %ws\n", KeyPartialValue->Data));
118 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
120 AutoEnumerate = FALSE;
122 RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
124 for (i = 0; i <= SystemStartOptionsLen/2; i++)
125 {
126 //KdPrint((__DRIVER_NAME " pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
128 switch (State)
129 {
130 case 0:
131 if (SystemStartOptions[i] == L'G')
132 {
133 StartPos = i;
134 State = 2;
135 } else if (SystemStartOptions[i] != L' ')
136 {
137 State = 1;
138 }
139 break;
140 case 1:
141 if (SystemStartOptions[i] == L' ')
142 State = 0;
143 break;
144 case 2:
145 if (SystemStartOptions[i] == L'P')
146 State = 3;
147 else
148 State = 0;
149 break;
150 case 3:
151 if (SystemStartOptions[i] == L'L')
152 State = 4;
153 else
154 State = 0;
155 break;
156 case 4:
157 if (SystemStartOptions[i] == L'P')
158 State = 5;
159 else
160 State = 0;
161 break;
162 case 5:
163 if (SystemStartOptions[i] == L'V')
164 State = 6;
165 else
166 State = 0;
167 break;
168 case 6:
169 if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
170 AutoEnumerate = TRUE;
171 State = 0;
172 break;
173 }
174 }
176 KdPrint((__DRIVER_NAME " AutoEnumerate = %d\n", AutoEnumerate));
178 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
180 return status;
181 }
183 static WDFDEVICE GlobalDevice;
184 static PDEVICE_OBJECT Pdo;
186 static NTSTATUS
187 XenVbd_AddDevice(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
188 {
189 WDF_CHILD_LIST_CONFIG ChildListConfig;
190 NTSTATUS status;
191 WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
193 UNREFERENCED_PARAMETER(Driver);
195 KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
197 Pdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit);
199 //WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
200 WDF_CHILD_LIST_CONFIG_INIT(&ChildListConfig, sizeof(XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION), XenVbd_ChildListCreateDevice);
201 WdfFdoInitSetDefaultChildListConfig(DeviceInit, &ChildListConfig, WDF_NO_OBJECT_ATTRIBUTES);
203 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_CONTROLLER);
204 //WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
205 WdfDeviceInitSetExclusive(DeviceInit, FALSE);
207 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
208 pnpPowerCallbacks.EvtDevicePrepareHardware = XenVbd_PrepareHardware;
209 pnpPowerCallbacks.EvtDeviceReleaseHardware = XenVbd_ReleaseHardware;
210 pnpPowerCallbacks.EvtDeviceD0Entry = XenVbd_D0Entry;
211 pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenVbd_D0EntryPostInterruptsEnabled;
212 pnpPowerCallbacks.EvtDeviceD0Exit = XenVbd_D0Exit;
213 pnpPowerCallbacks.EvtDeviceUsageNotification = XenVbd_DeviceUsageNotification;
214 WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
216 /*initialize storage for the device context*/
217 //WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENVBD_DEVICE_DATA);
219 //WdfDeviceInitSetPowerNotPageable(DeviceInit);
221 /*create a device instance.*/
222 status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &GlobalDevice);
223 if(!NT_SUCCESS(status))
224 {
225 KdPrint((__DRIVER_NAME "WdfDeviceCreate failed with status 0x%08x\n", status));
226 return status;
227 }
229 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFilePaging, TRUE);
230 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFileHibernation, TRUE);
231 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFileDump, TRUE);
233 status = STATUS_SUCCESS;
235 KdPrint((__DRIVER_NAME " <-- DeviceAdd\n"));
236 return status;
237 }
239 static NTSTATUS
240 XenVbd_PrepareHardware(
241 IN WDFDEVICE Device,
242 IN WDFCMRESLIST ResourceList,
243 IN WDFCMRESLIST ResourceListTranslated)
244 {
245 NTSTATUS status = STATUS_SUCCESS;
247 UNREFERENCED_PARAMETER(ResourceList);
248 UNREFERENCED_PARAMETER(ResourceListTranslated);
250 //KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware\n"));
252 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_EVTCHN, (PINTERFACE) &EvtChnInterface, sizeof(XEN_IFACE_EVTCHN), 1, NULL);
253 if(!NT_SUCCESS(status))
254 {
255 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (EvtChn) failed with status 0x%08x\n", status));
256 }
258 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XENBUS, (PINTERFACE)&XenBusInterface, sizeof(XEN_IFACE_XENBUS), 1, NULL);
259 if(!NT_SUCCESS(status))
260 {
261 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (XenBus) failed with status 0x%08x\n", status));
262 }
264 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XEN, (PINTERFACE)&XenInterface, sizeof(XEN_IFACE_XEN), 1, NULL);
265 if(!NT_SUCCESS(status))
266 {
267 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (Xen) failed with status 0x%08x\n", status));
268 }
270 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_GNTTBL, (PINTERFACE)&GntTblInterface, sizeof(XEN_IFACE_GNTTBL), 1, NULL);
271 if(!NT_SUCCESS(status))
272 {
273 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (GntTbl) failed with status 0x%08x\n", status));
274 }
276 //KdPrint((__DRIVER_NAME " <-- EvtDevicePrepareHardware\n"));
278 InitializeListHead(&DeviceListHead);
280 return status;
281 }
283 static NTSTATUS
284 XenVbd_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated)
285 {
286 UNREFERENCED_PARAMETER(Device);
287 UNREFERENCED_PARAMETER(ResourcesTranslated);
289 // release interfaces here...
291 //XenVbd_Close();
293 return STATUS_SUCCESS;
294 }
296 static NTSTATUS
297 XenVbd_D0Entry(
298 IN WDFDEVICE Device,
299 IN WDF_POWER_DEVICE_STATE PreviousState
300 )
301 {
302 NTSTATUS status = STATUS_SUCCESS;
304 UNREFERENCED_PARAMETER(Device);
305 UNREFERENCED_PARAMETER(PreviousState);
307 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Entry\n"));
309 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
311 return status;
312 }
314 static int EnumeratedDevices;
315 static KEVENT WaitDevicesEvent;
317 static NTSTATUS
318 XenVbd_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
319 {
320 //OBJECT_ATTRIBUTES oa;
321 NTSTATUS status = STATUS_SUCCESS;
322 //HANDLE nothing;
323 //char *response;
324 PXENPCI_XEN_DEVICE_DATA PdoDeviceData;
325 char **VbdDevices;
326 char *msg;
327 char buffer[128];
328 int i;
329 LARGE_INTEGER WaitTimeout;
331 UNREFERENCED_PARAMETER(Device);
332 UNREFERENCED_PARAMETER(PreviousState);
334 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0EntryPostInterruptsEnabled\n"));
336 PdoDeviceData = (PXENPCI_XEN_DEVICE_DATA)Pdo->DeviceExtension; //GetXenDeviceData(Device);
338 //KdPrint((__DRIVER_NAME " BasePath = %s\n", PdoDeviceData->BasePath));
339 PdoDeviceData->WatchHandler = XenVbd_HotPlugHandler;
341 EnumeratedDevices = 0;
342 KeInitializeEvent(&WaitDevicesEvent, SynchronizationEvent, FALSE);
344 // TODO: Should probably do this in an EvtChildListScanForChildren
345 if (AutoEnumerate)
346 {
347 msg = XenBusInterface.List(XBT_NIL, "device/vbd", &VbdDevices);
348 if (!msg) {
349 for (i = 0; VbdDevices[i]; i++)
350 {
351 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
352 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
353 XenVbd_HotPlugHandler(buffer, NULL);
354 //ExFreePoolWithTag(bdDevices[i], XENPCI_POOL_TAG);
355 }
356 KdPrint((__DRIVER_NAME " Waiting for devices to be enumerated\n"));
357 while (EnumeratedDevices != i)
358 {
359 WaitTimeout.QuadPart = -600000000;
360 if (KeWaitForSingleObject(&WaitDevicesEvent, Executive, KernelMode, FALSE, &WaitTimeout) == STATUS_TIMEOUT)
361 {
362 KdPrint((__DRIVER_NAME " Wait timed out\n"));
363 break;
364 }
365 KdPrint((__DRIVER_NAME " %d out of %d devices enumerated\n", EnumeratedDevices, i));
366 }
367 }
368 }
370 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0EntryPostInterruptsEnabled\n"));
372 return status;
373 }
375 static NTSTATUS
376 XenVbd_D0Exit(
377 IN WDFDEVICE Device,
378 IN WDF_POWER_DEVICE_STATE TargetState
379 )
380 {
381 NTSTATUS status = STATUS_SUCCESS;
382 //char *response;
384 UNREFERENCED_PARAMETER(Device);
385 UNREFERENCED_PARAMETER(TargetState);
387 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Exit\n"));
389 //response = XenBusInterface.RemWatch(XBT_NIL, XenBusInterface.InterfaceHeader.Context, XenVbd_HotPlugHandler, NULL);
391 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Exit\n"));
393 return status;
394 }
396 static NTSTATUS
397 XenVbd_DeviceUsageNotification(WDFDEVICE Device, WDF_SPECIAL_FILE_TYPE NotificationType, BOOLEAN IsInNotificationPath)
398 {
399 // KdPrint((__DRIVER_NAME " --> DeviceUsageNotification\n"));
401 switch (NotificationType)
402 {
403 case WdfSpecialFilePaging:
404 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFilePaging, Using = %d\n", IsInNotificationPath));
405 break;
406 case WdfSpecialFileHibernation:
407 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFileHibernation, Using = %d\n", IsInNotificationPath));
408 break;
409 case WdfSpecialFileDump:
410 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFileDump, Using = %d\n", IsInNotificationPath));
411 break;
412 default:
413 KdPrint((__DRIVER_NAME " NotificationType = %d, Using = %d\n", NotificationType, IsInNotificationPath));
414 break;
415 }
416 // KdPrint((__DRIVER_NAME " <-- DeviceUsageNotification\n"));
418 return TRUE;
419 }
421 static VOID
422 XenVbd_IoDefault(
423 IN WDFQUEUE Queue,
424 IN WDFREQUEST Request
425 )
426 {
427 UNREFERENCED_PARAMETER(Queue);
429 //KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
431 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
433 //KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
434 }
436 static __inline uint64_t
437 GET_ID_FROM_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData)
438 {
439 uint64_t free;
441 free = ChildDeviceData->shadow_free;
443 //KdPrint((__DRIVER_NAME " A free = %d\n", free));
445 ChildDeviceData->shadow_free = ChildDeviceData->shadow[free].req.id;
447 //KdPrint((__DRIVER_NAME " A shadow_free now = %d\n", ChildDeviceData->shadow_free));
449 ChildDeviceData->shadow[free].req.id = 0x0fffffee; /* debug */
450 return free;
451 }
453 static __inline VOID
454 ADD_ID_TO_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, uint64_t Id)
455 {
456 ChildDeviceData->shadow[Id].req.id = ChildDeviceData->shadow_free;
457 ChildDeviceData->shadow[Id].Irp = NULL;
458 ChildDeviceData->shadow_free = Id;
459 }
461 static VOID
462 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp);
464 static PMDL
465 AllocatePages(int Pages)
466 {
467 PMDL Mdl;
468 PVOID Buf;
470 Buf = ExAllocatePoolWithTag(NonPagedPool, Pages * PAGE_SIZE, XENVBD_POOL_TAG);
471 if (Buf == NULL)
472 {
473 KdPrint((__DRIVER_NAME " AllocatePages Failed at ExAllocatePoolWithTag\n"));
474 }
475 Mdl = IoAllocateMdl(Buf, Pages * PAGE_SIZE, FALSE, FALSE, NULL);
476 if (Mdl == NULL)
477 {
478 KdPrint((__DRIVER_NAME " AllocatePages Failed at IoAllocateMdl\n"));
479 }
480 MmBuildMdlForNonPagedPool(Mdl);
482 return Mdl;
483 }
485 static PMDL
486 AllocatePage()
487 {
488 return AllocatePages(1);
489 }
491 static VOID
492 FreePages(PMDL Mdl)
493 {
494 PVOID Buf = MmGetMdlVirtualAddress(Mdl);
495 //KdPrint((__DRIVER_NAME " FreePages Failed at IoAllocateMdl\n"));
496 //KdPrint((__DRIVER_NAME " FreePages Buf = %08x\n", Buf));
497 IoFreeMdl(Mdl);
498 ExFreePoolWithTag(Buf, XENVBD_POOL_TAG);
499 }
501 static VOID
502 XenVbd_DpcThreadProc(WDFDPC Dpc)
503 {
504 PIRP Irp;
505 RING_IDX i, rp;
506 int j;
507 blkif_response_t *rep;
508 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
509 PSCSI_REQUEST_BLOCK Srb;
510 PIO_STACK_LOCATION IrpSp;
511 char *DataBuffer;
512 int more_to_do;
513 int IrpCount;
514 PIRP Irps[100];
515 int BlockCount;
516 KIRQL KIrql;
517 WDFDEVICE ChildDevice;
518 XenVbd_ListEntry *ListEntry;
519 int notify;
521 //!!!IRQL_DISPATCH!!!
523 //KdPrint((__DRIVER_NAME " --> XenVbd_DpcThreadProc\n"));
525 ChildDevice = WdfDpcGetParentObject(Dpc);
527 ChildDeviceData = *GetChildDeviceData(ChildDevice);
529 IrpCount = 0;
530 more_to_do = TRUE;
531 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
533 ChildDeviceData->IrpAddedToRingAtLastDpc = ChildDeviceData->IrpAddedToRing;
535 while (more_to_do)
536 {
537 rp = ChildDeviceData->Ring.sring->rsp_prod;
538 KeMemoryBarrier();
539 for (i = ChildDeviceData->Ring.rsp_cons; i != rp; i++)
540 {
541 rep = RING_GET_RESPONSE(&ChildDeviceData->Ring, i);
542 ChildDeviceData->IrpRemovedFromRing++;
543 Irp = ChildDeviceData->shadow[rep->id].Irp;
544 IrpSp = IoGetCurrentIrpStackLocation(Irp);
545 Srb = IrpSp->Parameters.Scsi.Srb;
547 if (rep->status != BLKIF_RSP_OKAY)
548 {
549 KdPrint((__DRIVER_NAME " Xen Operation returned error in DpcThreadProc\n"));
550 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));
551 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
552 {
553 KdPrint((__DRIVER_NAME " gref[%d] = %d\n", j, ChildDeviceData->shadow[rep->id].req.seg[j].gref));
554 }
555 KdPrint((__DRIVER_NAME " MmGetMdlByteOffset = %d\n", MmGetMdlByteOffset(Irp->MdlAddress)));
556 }
557 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
558 {
559 GntTblInterface.EndAccess(ChildDeviceData->shadow[rep->id].req.seg[j].gref);
560 }
561 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
562 if (ChildDeviceData->shadow[rep->id].Buf != NULL)
563 {
564 if (Srb->Cdb[0] == SCSIOP_READ)
565 {
566 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
567 if (DataBuffer == NULL)
568 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe Failed in DpcThreadProc\n"));
569 memcpy(DataBuffer, ChildDeviceData->shadow[rep->id].Buf, BlockCount * ChildDeviceData->BytesPerSector);
570 }
571 FreePages(ChildDeviceData->shadow[rep->id].Mdl);
572 }
573 Srb->SrbStatus = SRB_STATUS_SUCCESS;
574 Srb->ScsiStatus = 0;
575 Irp->IoStatus.Status = STATUS_SUCCESS;
576 Irp->IoStatus.Information = BlockCount * ChildDeviceData->BytesPerSector;
578 Irps[IrpCount++] = Irp;
580 ADD_ID_TO_FREELIST(ChildDeviceData, rep->id);
581 }
583 ChildDeviceData->Ring.rsp_cons = i;
584 if (i != ChildDeviceData->Ring.req_prod_pvt)
585 {
586 RING_FINAL_CHECK_FOR_RESPONSES(&ChildDeviceData->Ring, more_to_do);
587 }
588 else
589 {
590 ChildDeviceData->Ring.sring->rsp_event = i + 1;
591 more_to_do = FALSE;
592 }
593 }
595 notify = 0;
596 while (!RING_FULL(&ChildDeviceData->Ring) && (ListEntry = (XenVbd_ListEntry *)RemoveHeadList(&ChildDeviceData->IrpListHead)) != (XenVbd_ListEntry *)&ChildDeviceData->IrpListHead)
597 {
598 ChildDeviceData->IrpRemovedFromList++;
599 XenVbd_PutIrpOnRing(ChildDevice, ListEntry->Irp);
600 ExFreePoolWithTag(ListEntry, XENVBD_POOL_TAG);
601 notify = 1;
602 }
603 if (notify)
604 {
605 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
606 if (notify)
607 EvtChnInterface.Notify(ChildDeviceData->EventChannel);
608 }
609 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
611 for (j = 0; j < IrpCount; j++)
612 {
613 IoCompleteRequest(Irps[j], IO_NO_INCREMENT);
614 ChildDeviceData->IrpCompleted++;
615 }
617 //KdPrint((__DRIVER_NAME " <-- XenVbd_DpcThreadProc\n"));
618 //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));
619 }
621 static BOOLEAN
622 XenVbd_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
623 {
624 BOOLEAN RetVal;
625 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
627 UNREFERENCED_PARAMETER(Interrupt);
628 // !!!RUNS AT DIRQL!!!
630 //KdPrint((__DRIVER_NAME " --> XenVbd_Interrupt\n"));
632 ChildDeviceData = (PXENVBD_CHILD_DEVICE_DATA)ServiceContext;
633 ChildDeviceData->IrpAddedToRingAtLastInterrupt = ChildDeviceData->IrpAddedToRing;
634 RetVal = WdfDpcEnqueue(ChildDeviceData->Dpc);
636 //KdPrint((__DRIVER_NAME " <-- XenVbd_Interrupt (RetVal = %d)\n", RetVal));
638 return STATUS_SUCCESS;
639 }
641 static VOID
642 XenVbd_BackEndStateHandler(char *Path, PVOID Data)
643 {
644 PXENVBD_CHILD_DEVICE_DATA DeviceData;
645 char TmpPath[128];
646 char *Value;
647 int NewState;
648 PMDL Mdl;
649 grant_ref_t ref;
650 blkif_sring_t *SharedRing;
651 ULONG PFN;
652 XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION Description;
653 NTSTATUS status;
655 DeviceData = (PXENVBD_CHILD_DEVICE_DATA)Data;
657 XenBusInterface.Read(XBT_NIL, Path, &Value);
659 NewState = atoi(Value);
660 switch (NewState)
661 {
662 case XenbusStateUnknown:
663 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
664 break;
666 case XenbusStateInitialising:
667 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
668 break;
670 case XenbusStateInitWait:
671 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
673 DeviceData->EventChannel = EvtChnInterface.AllocUnbound(0);
674 EvtChnInterface.Bind(DeviceData->EventChannel, XenVbd_Interrupt, DeviceData);
675 Mdl = AllocatePage();
676 PFN = *MmGetMdlPfnArray(Mdl);
677 SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
678 SHARED_RING_INIT(SharedRing);
679 FRONT_RING_INIT(&DeviceData->Ring, SharedRing, PAGE_SIZE);
680 ref = GntTblInterface.GrantAccess(0, PFN, FALSE);
682 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
683 RtlStringCbCatA(TmpPath, 128, "/ring-ref");
684 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", ref);
686 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
687 RtlStringCbCatA(TmpPath, 128, "/event-channel");
688 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", DeviceData->EventChannel);
690 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
691 RtlStringCbCatA(TmpPath, 128, "/state");
692 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
694 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
695 break;
697 case XenbusStateInitialised:
698 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
699 // create the device
700 break;
702 case XenbusStateConnected:
703 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
705 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Description.Header, sizeof(Description));
707 Description.DeviceData = DeviceData;
709 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
710 RtlStringCbCatA(TmpPath, 128, "/device-type");
711 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
712 if (strcmp(Value, "disk") == 0)
713 {
714 KdPrint((__DRIVER_NAME " DeviceType = Disk\n"));
715 DeviceData->DeviceType = XENVBD_DEVICETYPE_DISK;
716 }
717 else if (strcmp(Value, "cdrom") == 0)
718 {
719 KdPrint((__DRIVER_NAME " DeviceType = CDROM\n"));
720 DeviceData->DeviceType = XENVBD_DEVICETYPE_CDROM;
721 }
722 else
723 {
724 KdPrint((__DRIVER_NAME " DeviceType = %s (This probably won't work!)\n", Value));
725 }
727 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
728 RtlStringCbCatA(TmpPath, 128, "/type"); // should probably check that this is 'phy' or 'file' or at least not ''
729 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
730 KdPrint((__DRIVER_NAME " Backend Type = %s\n", Value));
732 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
733 RtlStringCbCatA(TmpPath, 128, "/mode"); // should store this...
734 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
735 KdPrint((__DRIVER_NAME " Backend Mode = %s\n", Value));
737 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
738 RtlStringCbCatA(TmpPath, 128, "/sector-size");
739 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
740 // should complain if Value == NULL
741 DeviceData->BytesPerSector = atoi(Value);
743 KdPrint((__DRIVER_NAME " BytesPerSector = %d\n", DeviceData->BytesPerSector));
745 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
746 RtlStringCbCatA(TmpPath, 128, "/sectors");
747 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
748 // should complain if Value == NULL
749 DeviceData->TotalSectors = (ULONGLONG)atol(Value);
751 KdPrint((__DRIVER_NAME " TotalSectors = %d\n", DeviceData->TotalSectors));
753 // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
754 DeviceData->Geometry.MediaType = FixedMedia;
755 DeviceData->Geometry.BytesPerSector = DeviceData->BytesPerSector;
756 DeviceData->Geometry.SectorsPerTrack = 63;
757 DeviceData->Geometry.TracksPerCylinder = 255;
758 DeviceData->Geometry.Cylinders.QuadPart = DeviceData->TotalSectors / DeviceData->Geometry.SectorsPerTrack / DeviceData->Geometry.TracksPerCylinder;
759 KdPrint((__DRIVER_NAME " Geometry C/H/S = %d/%d/%d\n", DeviceData->Geometry.Cylinders.LowPart, DeviceData->Geometry.TracksPerCylinder, DeviceData->Geometry.SectorsPerTrack));
761 // if we detected something wrong, we should not enumarate the device and should instead initiate a close
763 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(WdfFdoGetDefaultChildList(GlobalDevice), &Description.Header, NULL);
764 if (!NT_SUCCESS(status))
765 {
766 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed %08x\n", status));
767 }
769 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
770 RtlStringCbCatA(TmpPath, 128, "/state");
771 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", XenbusStateConnected);
773 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
774 InterlockedIncrement(&EnumeratedDevices);
775 KdPrint((__DRIVER_NAME " Added a device, notifying\n"));
777 KeSetEvent(&WaitDevicesEvent, 1, FALSE);
779 break;
781 case XenbusStateClosing:
782 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
783 break;
785 case XenbusStateClosed:
786 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
787 break;
789 default:
790 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
791 break;
792 }
793 }
795 static VOID
796 XenVbd_HotPlugHandler(char *Path, PVOID Data)
797 {
798 PXENVBD_CHILD_DEVICE_DATA DeviceData;
799 char **Bits;
800 int Count;
801 char TmpPath[128];
802 char *Value;
804 UNREFERENCED_PARAMETER(Data);
806 //KdPrint((__DRIVER_NAME " --> HotPlugHandler\n"));
808 //KdPrint((__DRIVER_NAME " Path = %s\n", Path));
810 Bits = SplitString(Path, '/', 4, &Count);
811 switch (Count)
812 {
813 case 0:
814 case 1:
815 case 2:
816 break; // should never happen
817 case 3:
818 break;
819 case 4:
821 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
822 break;
823 for (DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceListHead.Flink; DeviceData != (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead; DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceData->Entry.Flink)
824 {
825 if (strncmp(DeviceData->Path, Path, strlen(DeviceData->Path)) == 0 && Path[strlen(DeviceData->Path)] == '/')
826 {
827 break;
828 }
829 }
830 if (DeviceData == (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead)
831 {
832 DeviceData = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENVBD_CHILD_DEVICE_DATA), XENVBD_POOL_TAG);
833 memset(DeviceData, 0, sizeof(XENVBD_CHILD_DEVICE_DATA));
835 //KdPrint((__DRIVER_NAME " Allocated ChildDeviceData = %08x\n", DeviceData));
837 InsertTailList(&DeviceListHead, &DeviceData->Entry);
838 RtlStringCbCopyA(DeviceData->Path, 128, Bits[0]);
839 RtlStringCbCatA(DeviceData->Path, 128, "/");
840 RtlStringCbCatA(DeviceData->Path, 128, Bits[1]);
841 RtlStringCbCatA(DeviceData->Path, 128, "/");
842 RtlStringCbCatA(DeviceData->Path, 128, Bits[2]);
844 DeviceData->DeviceIndex = atoi(Bits[2]);
846 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
847 RtlStringCbCatA(TmpPath, 128, "/backend");
848 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
849 if (Value == NULL)
850 {
851 KdPrint((__DRIVER_NAME " Read Failed\n"));
852 }
853 else
854 {
855 RtlStringCbCopyA(DeviceData->BackendPath, 128, Value);
856 }
857 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
858 RtlStringCbCatA(TmpPath, 128, "/state");
859 XenBusInterface.AddWatch(XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, DeviceData);
860 }
861 break;
862 }
864 FreeSplitString(Bits, Count);
866 //KdPrint((__DRIVER_NAME " <-- HotPlugHandler\n"));
868 return;
869 }
871 static NTSTATUS
872 XenVbd_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit)
873 {
874 NTSTATUS status;
875 WDFDEVICE ChildDevice;
876 PXENVBD_DEVICE_IDENTIFICATION_DESCRIPTION XenVbdIdentificationDesc;
877 DECLARE_UNICODE_STRING_SIZE(buffer, 50);
878 WDF_OBJECT_ATTRIBUTES PdoAttributes;
879 DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
880 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
881 WDF_IO_QUEUE_CONFIG IoQueueConfig;
882 unsigned int i;
883 WDF_DPC_CONFIG DpcConfig;
884 WDF_OBJECT_ATTRIBUTES DpcObjectAttributes;
885 WDF_DEVICE_STATE DeviceState;
886 UCHAR ScsiMinors[1] = { IRP_MN_SCSI_CLASS };
888 UNREFERENCED_PARAMETER(ChildList);
890 KdPrint((__DRIVER_NAME " --> ChildListCreateDevice\n"));
892 XenVbdIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION, Header);
894 ChildDeviceData = XenVbdIdentificationDesc->DeviceData;
896 // Capabilities = CM_DEVCAP_UNIQUEID
897 // Devnode Flages = DN_NEED_RESTART??? DN_DISABLEABLE???
899 switch (ChildDeviceData->DeviceType)
900 {
901 case XENVBD_DEVICETYPE_DISK:
902 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_DISK);
904 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk\0");
905 //status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk&Ven_James&Prod_James&Rev_1.00\0");
906 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
908 status = RtlUnicodeStringPrintf(&buffer, L"%02d\0", ChildDeviceData->DeviceIndex);
909 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
911 status = RtlUnicodeStringPrintf(&buffer, L"GenDisk\0");
912 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
913 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
915 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV Disk (%d)", ChildDeviceData->DeviceIndex);
916 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
917 break;
918 case XENVBD_DEVICETYPE_CDROM:
919 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_MASS_STORAGE);
920 WdfDeviceInitSetCharacteristics(ChildInit, FILE_READ_ONLY_DEVICE|FILE_REMOVABLE_MEDIA, TRUE);
922 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\CDROM\0");
923 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
925 status = RtlUnicodeStringPrintf(&buffer, L"%02d\0", ChildDeviceData->DeviceIndex);
926 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
928 status = RtlUnicodeStringPrintf(&buffer, L"GenCdRom\0");
929 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
930 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
932 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV CDROM (%d)\0", ChildDeviceData->DeviceIndex);
933 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
934 break;
935 default:
936 // wtf?
937 break;
938 }
940 WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
942 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, PXENVBD_CHILD_DEVICE_DATA);
944 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSCSI, IRP_MJ_SCSI, NULL, 0);
945 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpDEVICE_CONTROL, IRP_MJ_DEVICE_CONTROL, NULL, 0);
946 /*
947 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CLEANUP, NULL, 0);
948 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CLOSE, NULL, 0);
949 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CREATE, NULL, 0);
950 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_DIRECTORY_CONTROL, NULL, 0);
951 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_FILE_SYSTEM_CONTROL, NULL, 0);
952 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_FLUSH_BUFFERS, NULL, 0);
953 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_LOCK_CONTROL, NULL, 0);
954 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_POWER, NULL, 0);
955 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_EA, NULL, 0);
956 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_INFORMATION, NULL, 0);
957 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_SECURITY, NULL, 0);
958 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_VOLUME_INFORMATION, NULL, 0);
959 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_READ, NULL, 0);
960 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_INFORMATION, NULL, 0);
961 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_SECURITY, NULL, 0);
962 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_VOLUME_INFORMATION, NULL, 0);
963 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SHUTDOWN, NULL, 0);
964 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SYSTEM_CONTROL, NULL, 0);
965 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_WRITE, NULL, 0);
966 */
967 WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);
969 //WdfDeviceInitSetPowerNotPageable(ChildInit);
971 status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
972 if (!NT_SUCCESS(status))
973 {
974 KdPrint((__DRIVER_NAME " WdfDeviceCreate status = %08X\n", status));
975 }
977 switch (ChildDeviceData->DeviceType)
978 {
979 case XENVBD_DEVICETYPE_DISK:
980 WDF_DEVICE_STATE_INIT(&DeviceState);
981 DeviceState.NotDisableable = WdfTrue;
982 WdfDeviceSetDeviceState(ChildDevice, &DeviceState);
983 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFilePaging, TRUE);
984 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileHibernation, TRUE);
985 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileDump, TRUE);
986 break;
987 case XENVBD_DEVICETYPE_CDROM:
988 break;
989 }
990 *GetChildDeviceData(ChildDevice) = ChildDeviceData;
992 ChildDeviceData->FastPathUsed = 0;
993 ChildDeviceData->SlowPathUsed = 0;
994 ChildDeviceData->IrpAddedToList = 0;
995 ChildDeviceData->IrpRemovedFromList = 0;
996 ChildDeviceData->IrpAddedToRing = 0;
997 ChildDeviceData->IrpAddedToRingAtLastNotify = 0;
998 ChildDeviceData->IrpAddedToRingAtLastInterrupt = 0;
999 ChildDeviceData->IrpAddedToRingAtLastDpc = 0;
1000 ChildDeviceData->IrpRemovedFromRing = 0;
1001 ChildDeviceData->IrpCompleted = 0;
1003 ChildDeviceData->Device = ChildDevice;
1005 KeInitializeSpinLock(&ChildDeviceData->Lock);
1006 KeInitializeSpinLock(&ChildDeviceData->IrpListLock);
1007 InitializeListHead(&ChildDeviceData->IrpListHead);
1009 ChildDeviceData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * BLK_RING_SIZE, XENVBD_POOL_TAG);
1010 memset(ChildDeviceData->shadow, 0, sizeof(blkif_shadow_t) * BLK_RING_SIZE);
1011 //KdPrint((__DRIVER_NAME " Allocated shadow = %08x\n", ChildDeviceData->shadow));
1012 for (i = 0; i < BLK_RING_SIZE; i++)
1013 ChildDeviceData->shadow[i].req.id = i + 1;
1014 ChildDeviceData->shadow_free = 0;
1015 ChildDeviceData->shadow[BLK_RING_SIZE - 1].req.id = 0x0fffffff;
1017 WDF_DPC_CONFIG_INIT(&DpcConfig, XenVbd_DpcThreadProc);
1018 WDF_OBJECT_ATTRIBUTES_INIT(&DpcObjectAttributes);
1019 DpcObjectAttributes.ParentObject = ChildDevice;
1020 WdfDpcCreate(&DpcConfig, &DpcObjectAttributes, &ChildDeviceData->Dpc);
1022 KdPrint((__DRIVER_NAME " <-- ChildListCreateDevice (status = %08x)\n", status));
1024 return status;
1028 // 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
1030 // Call with device lock held
1031 static VOID
1032 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp)
1034 char *DataBuffer;
1035 PSCSI_REQUEST_BLOCK Srb;
1036 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1037 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1038 blkif_request_t *req;
1039 int i;
1040 int j;
1041 int BlockCount;
1042 int sect_offset;
1044 ChildDeviceData = *GetChildDeviceData(Device);
1046 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1047 // KdPrint((__DRIVER_NAME " --> PutIrpOnRing\n"));
1049 if (RING_FULL(&ChildDeviceData->Ring))
1051 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
1054 req = RING_GET_REQUEST(&ChildDeviceData->Ring, ChildDeviceData->Ring.req_prod_pvt);
1056 //KdPrint((__DRIVER_NAME " req = %08x\n", req));
1058 Srb = irpSp->Parameters.Scsi.Srb;
1060 req->sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
1061 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
1063 req->id = GET_ID_FROM_FREELIST(ChildDeviceData);
1065 if (req->id == 0x0fffffff)
1067 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutIrpOnRing\n"));
1070 //KdPrint((__DRIVER_NAME " id = %d\n", req->id));
1072 req->handle = 0;
1073 req->operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
1074 ChildDeviceData->shadow[req->id].Irp = Irp;
1076 if ((MmGetMdlByteOffset(Irp->MdlAddress) & 0x1ff) == 0) // 0x1ff shouldn't be hardcoded...
1078 // fast path - zero copy
1079 ChildDeviceData->shadow[req->id].Mdl = Irp->MdlAddress;
1080 ChildDeviceData->shadow[req->id].Buf = NULL; // we don't need the virtual address
1081 ChildDeviceData->FastPathUsed++;
1083 else
1085 // slow path - copy to bounce buffer
1086 ChildDeviceData->shadow[req->id].Mdl = AllocatePages((BlockCount * ChildDeviceData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE);
1087 ChildDeviceData->shadow[req->id].Buf = MmGetMdlVirtualAddress(ChildDeviceData->shadow[req->id].Mdl);
1088 if (ChildDeviceData->shadow[req->id].Buf == NULL)
1090 KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress returned NULL in PutIrpOnRing\n"));
1092 ChildDeviceData->SlowPathUsed++;
1095 // if (((ChildDeviceData->FastPathUsed + ChildDeviceData->SlowPathUsed) & 0x2FF) == 0)
1096 // {
1097 // KdPrint((__DRIVER_NAME " Fast Path = %d, Slow Path = %d\n", ChildDeviceData->FastPathUsed, ChildDeviceData->SlowPathUsed));
1098 // 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));
1099 // }
1101 sect_offset = MmGetMdlByteOffset(ChildDeviceData->shadow[req->id].Mdl) >> 9;
1102 for (i = 0, req->nr_segments = 0; i < BlockCount; req->nr_segments++)
1104 req->seg[req->nr_segments].gref = GntTblInterface.GrantAccess(0, MmGetMdlPfnArray(ChildDeviceData->shadow[req->id].Mdl)[req->nr_segments], FALSE);
1105 req->seg[req->nr_segments].first_sect = sect_offset;
1106 for (j = sect_offset; i < BlockCount && j < PAGE_SIZE / ChildDeviceData->BytesPerSector; j++, i++)
1107 req->seg[req->nr_segments].last_sect = (uint8_t)j;
1108 sect_offset = 0;
1110 if (Srb->Cdb[0] == SCSIOP_WRITE && ChildDeviceData->shadow[req->id].Buf != NULL)
1112 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1113 if (DataBuffer == NULL)
1114 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe failed in PutIrpOnRing\n"));
1115 memcpy(ChildDeviceData->shadow[req->id].Buf, DataBuffer, BlockCount * ChildDeviceData->BytesPerSector);
1117 ChildDeviceData->shadow[req->id].req = *req;
1119 ChildDeviceData->Ring.req_prod_pvt++;
1121 ChildDeviceData->IrpAddedToRing++;
1123 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1124 // KdPrint((__DRIVER_NAME " <-- PutIrpOnRing\n"));
1127 static ULONG
1128 XenVBD_FillModePage(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
1130 PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
1132 switch (PageCode)
1134 case MODE_PAGE_RIGID_GEOMETRY:
1135 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_DISK)
1137 KdPrint((__DRIVER_NAME " MODE_PAGE_RIGID_GEOMETRY\n"));
1138 if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
1139 return 1;
1140 ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
1141 memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
1142 ModeRigidGeometry->PageCode = PageCode;
1143 ModeRigidGeometry->PageSavable = 0;
1144 ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
1145 ModeRigidGeometry->NumberOfCylinders[0] = (ChildDeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF;
1146 ModeRigidGeometry->NumberOfCylinders[1] = (ChildDeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF;
1147 ModeRigidGeometry->NumberOfCylinders[2] = (ChildDeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF;
1148 ModeRigidGeometry->NumberOfHeads = ChildDeviceData->Geometry.TracksPerCylinder;
1149 //ModeRigidGeometry->LandZoneCyclinder = 0;
1150 ModeRigidGeometry->RoataionRate[0] = 0x05;
1151 ModeRigidGeometry->RoataionRate[0] = 0x39;
1152 *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
1154 break;
1155 case MODE_PAGE_FAULT_REPORTING:
1156 break;
1157 default:
1158 break;
1160 return 0;
1163 static NTSTATUS
1164 XenVbd_Child_PreprocessWdmIrpDEVICE_CONTROL(WDFDEVICE Device, PIRP Irp)
1166 NTSTATUS Status;
1167 PIO_STACK_LOCATION IrpStack;
1168 PSCSI_ADDRESS ScsiAddress;
1169 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1170 PSTORAGE_PROPERTY_QUERY Spq;
1171 PSTORAGE_ADAPTER_DESCRIPTOR Sad;
1172 PSTORAGE_DEVICE_DESCRIPTOR Sdd;
1173 PSTORAGE_DEVICE_ID_DESCRIPTOR Sdid;
1174 PSTORAGE_IDENTIFIER Si;
1175 // ULONG Information;
1176 int StructEndOffset;
1178 KdPrint((__DRIVER_NAME " --> PreprocessWdmIrpDEVICE_CONTROL\n"));
1180 ChildDeviceData = *GetChildDeviceData(Device);
1182 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1184 switch (IrpStack->Parameters.DeviceIoControl.IoControlCode)
1186 case IOCTL_SCSI_GET_ADDRESS:
1187 KdPrint((__DRIVER_NAME " IOCTL_SCSI_GET_ADDRESS\n"));
1188 Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
1189 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(SCSI_ADDRESS))
1191 ScsiAddress = (PSCSI_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1192 ScsiAddress->Length = sizeof(SCSI_ADDRESS);
1193 ScsiAddress->PortNumber = 0;
1194 ScsiAddress->PathId = 0;
1195 ScsiAddress->TargetId = 0;
1196 ScsiAddress->Lun = 0;
1197 Status = STATUS_SUCCESS;
1198 Irp->IoStatus.Status = Status;
1199 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1201 else
1203 KdPrint((__DRIVER_NAME " (Buffer size too small @ %d\n", IrpStack->Parameters.DeviceIoControl.OutputBufferLength));
1205 break;
1206 case IOCTL_STORAGE_QUERY_PROPERTY:
1207 KdPrint((__DRIVER_NAME " IOCTL_STORAGE_QUERY_PROPERTY\n"));
1208 Spq = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
1209 if (Spq->PropertyId == StorageAdapterProperty && Spq->QueryType == PropertyStandardQuery)
1211 KdPrint((__DRIVER_NAME " PropertyId = StorageAdapterProperty, QueryType = PropertyStandardQuery\n"));
1212 Irp->IoStatus.Information = 0;
1213 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= 8)
1215 Irp->IoStatus.Information = 8;
1216 Sad = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1217 Sad->Version = 1;
1218 Sad->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
1219 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= Sad->Size)
1221 Irp->IoStatus.Information = Sad->Size;
1222 Sad->MaximumTransferLength = 45056;
1223 Sad->MaximumPhysicalPages = 11;
1224 Sad->AlignmentMask = 0;
1225 Sad->AdapterUsesPio = FALSE;
1226 Sad->AdapterScansDown = FALSE;
1227 Sad->CommandQueueing = FALSE;
1228 Sad->AcceleratedTransfer = FALSE;
1229 Sad->BusType = BusTypeScsi;
1230 Sad->BusMajorVersion = 0;
1231 Sad->BusMinorVersion = 0;
1234 Status = STATUS_SUCCESS;
1235 Irp->IoStatus.Status = Status;
1236 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1238 else if (Spq->PropertyId == StorageDeviceProperty && Spq->QueryType == PropertyStandardQuery)
1240 KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceProperty, QueryType = PropertyStandardQuery\n"));
1241 Irp->IoStatus.Information = 0;
1242 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= 8)
1244 Irp->IoStatus.Information = 8;
1245 Sdd = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1246 Sdd->Version = 1;
1247 Sdd->Size = &Sdd->RawDeviceProperties[36] - (PUCHAR)Sdd + 1;
1248 // 0 0 1 2 3
1249 // 0 7 5 4 1
1250 //"VENDOR\0PRODUCT\0Revision\0Serial\0"
1251 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= Sdd->Size)
1253 Irp->IoStatus.Information = Sdd->Size;
1254 switch (ChildDeviceData->DeviceType)
1256 case XENVBD_DEVICETYPE_DISK:
1257 Sdd->DeviceType = DIRECT_ACCESS_DEVICE;
1258 Sdd->DeviceTypeModifier = 0x00;
1259 Sdd->RemovableMedia = FALSE;
1260 break;
1261 case XENVBD_DEVICETYPE_CDROM:
1262 Sdd->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1263 Sdd->DeviceTypeModifier = 0x00;
1264 Sdd->RemovableMedia = TRUE;
1265 break;
1266 default:
1267 // wtf
1268 break;
1270 Sdd->CommandQueueing = FALSE;
1271 StructEndOffset = Sdd->RawDeviceProperties - (PUCHAR)Sdd;
1272 Sdd->VendorIdOffset = StructEndOffset + 0;
1273 Sdd->ProductIdOffset = StructEndOffset + 7;
1274 Sdd->ProductRevisionOffset = StructEndOffset + 15;
1275 Sdd->SerialNumberOffset = StructEndOffset + 24;
1276 Sdd->BusType = BusTypeScsi;
1277 Sdd->RawPropertiesLength = 36;
1278 memcpy(Sdd->RawDeviceProperties, "VENDOR\0PRODUCT\0Revision\0Serial99999\0", 36);
1281 Status = STATUS_SUCCESS;
1282 Irp->IoStatus.Status = Status;
1283 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1285 else if (Spq->PropertyId == StorageDeviceIdProperty && Spq->QueryType == PropertyStandardQuery)
1287 KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceIdProperty, QueryType = PropertyStandardQuery\n"));
1288 Irp->IoStatus.Information = 0;
1289 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= 8)
1291 Irp->IoStatus.Information = 8;
1292 Sdid = (PSTORAGE_DEVICE_ID_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1293 Sdid->Version = 1;
1294 Si = (PSTORAGE_IDENTIFIER)Sdid->Identifiers;
1295 Sdid->Size = &Si->Identifier[8] - (PUCHAR)Sdid + 1;
1296 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= Sdid->Size)
1298 Irp->IoStatus.Information = Sdid->Size;
1299 Sdid->NumberOfIdentifiers = 1;
1300 Si->CodeSet = StorageIdCodeSetAscii;
1301 Si->Type = StorageIdTypeScsiNameString;
1302 //Si->CodeSet = StorageIdCodeSetBinary;
1303 //Si->Type = StorageIdTypeEUI64;
1304 Si->IdentifierSize = 9;
1305 Si->NextOffset = 0;
1306 Si->Association = StorageIdAssocPort;
1307 Si->Identifier[0] = 'S';
1308 Si->Identifier[1] = 'e';
1309 Si->Identifier[2] = 'r';
1310 Si->Identifier[3] = 'i';
1311 Si->Identifier[4] = 'a';
1312 Si->Identifier[5] = 'l';
1313 Si->Identifier[6] = '9';
1314 Si->Identifier[7] = '9';
1315 Si->Identifier[6] = '9';
1316 Si->Identifier[7] = '9';
1317 Si->Identifier[8] = '9';
1318 //Si->Identifier[8] = 0;
1321 Status = STATUS_SUCCESS;
1322 Irp->IoStatus.Status = Status;
1323 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1325 else
1327 switch (Spq->PropertyId)
1329 case StorageDeviceProperty:
1330 KdPrint((__DRIVER_NAME " StorageDeviceProperty\n"));
1331 break;
1332 case StorageAccessAlignmentProperty:
1333 KdPrint((__DRIVER_NAME " StorageAccessAlignmentProperty\n"));
1334 break;
1335 case StorageAdapterProperty:
1336 KdPrint((__DRIVER_NAME " StorageAdapterProperty\n"));
1337 break;
1338 case StorageDeviceIdProperty:
1339 KdPrint((__DRIVER_NAME " StorageDeviceIdProperty\n"));
1340 break;
1341 case StorageDeviceUniqueIdProperty:
1342 KdPrint((__DRIVER_NAME " StorageDeviceUniqueIdProperty\n"));
1343 break;
1344 case StorageDeviceWriteCacheProperty:
1345 KdPrint((__DRIVER_NAME " StorageDeviceWriteCacheProperty\n"));
1346 break;
1347 default:
1348 KdPrint((__DRIVER_NAME " Unknown Property %08x\n", Spq->PropertyId));
1349 break;
1351 switch (Spq->QueryType)
1353 case PropertyStandardQuery:
1354 KdPrint((__DRIVER_NAME " PropertyStandardQuery\n"));
1355 break;
1356 case PropertyExistsQuery:
1357 KdPrint((__DRIVER_NAME " PropertyExistsQuery\n"));
1358 break;
1359 default:
1360 KdPrint((__DRIVER_NAME " Unknown Query %08x\n", Spq->QueryType));
1361 break;
1363 Status = STATUS_NOT_IMPLEMENTED;
1364 Irp->IoStatus.Status = Status;
1365 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1367 break;
1368 // http://www.osronline.com/article.cfm?article=229
1369 // 0x00560030 device = 0x56, Function = 0x00c =
1370 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
1371 KdPrint((__DRIVER_NAME " IOCTL_DISK_GET_DRIVE_GEOMETRY\n"));
1372 memcpy(Irp->AssociatedIrp.SystemBuffer, &ChildDeviceData->Geometry, sizeof(DISK_GEOMETRY));
1373 Status = STATUS_SUCCESS;
1374 Irp->IoStatus.Status = Status;
1375 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1376 break;
1377 case FT_BALANCED_READ_MODE: // just pretend we know what this is...
1378 KdPrint((__DRIVER_NAME " FT_BALANCED_READ_MODE\n"));
1379 Status = STATUS_SUCCESS;
1380 Irp->IoStatus.Status = Status;
1381 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1382 break;
1383 default:
1384 KdPrint((__DRIVER_NAME " Control Code = %08x\n", IrpStack->Parameters.DeviceIoControl.IoControlCode));
1385 Status = STATUS_NOT_IMPLEMENTED;
1386 Irp->IoStatus.Status = Status;
1387 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1390 KdPrint((__DRIVER_NAME " <-- PreprocessWdmIrpDEVICE_CONTROL\n"));
1392 return Status;
1395 static NTSTATUS
1396 XenVbd_Child_PreprocessWdmIrpSomethingSomething(WDFDEVICE Device, PIRP Irp)
1398 NTSTATUS Status;
1399 PIO_STACK_LOCATION IrpStack;
1401 KdPrint((__DRIVER_NAME " --> XenVbd_Child_PreprocessWdmIrpSomethingSomething\n"));
1403 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1404 KdPrint((__DRIVER_NAME " Major = %02X, Minor = %02X\n", IrpStack->MajorFunction, IrpStack->MinorFunction));
1406 IoSkipCurrentIrpStackLocation(Irp);
1408 Status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1410 KdPrint((__DRIVER_NAME " <-- XenVbd_Child_PreprocessWdmIrpSomethingSomething\n"));
1412 return Status;
1415 static NTSTATUS
1416 XenVbd_Child_PreprocessWdmIrpSCSI(WDFDEVICE Device, PIRP Irp)
1418 char *DataBuffer;
1419 NTSTATUS status = STATUS_SUCCESS;
1420 PSCSI_REQUEST_BLOCK Srb;
1421 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1422 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1423 KIRQL KIrql;
1424 XenVbd_ListEntry *ListEntry;
1425 int notify;
1426 PCDB cdb;
1427 //PUCHAR Ptr;
1428 ULONG i;
1430 ChildDeviceData = *GetChildDeviceData(Device);
1432 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1433 // KdPrint((__DRIVER_NAME " --> WdmIrpPreprocessSCSI\n"));
1435 //KdPrint((__DRIVER_NAME " SCSI Minor = %02X\n", irpSp->MinorFunction));
1437 Srb = irpSp->Parameters.Scsi.Srb;
1439 switch (Srb->Function)
1441 case SRB_FUNCTION_EXECUTE_SCSI:
1442 cdb = (PCDB)Srb->Cdb;
1443 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1444 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
1445 switch(cdb->CDB6GENERIC.OperationCode) //Srb->Cdb[0])
1447 case SCSIOP_TEST_UNIT_READY:
1448 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1449 // KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1450 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1451 Srb->ScsiStatus = 0;
1452 status = STATUS_SUCCESS;
1453 Irp->IoStatus.Status = status;
1454 Irp->IoStatus.Information = 0;
1455 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1456 break;
1457 case SCSIOP_INQUIRY:
1458 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1459 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1460 if ((Srb->Cdb[1] & 1) == 0)
1462 // DataBuffer = Srb->DataBuffer;
1463 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1464 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1466 DataBuffer[0] = 0x00; // disk
1467 DataBuffer[1] = 0x00; // not removable
1468 memcpy(DataBuffer + 8, "James ", 8); // vendor id
1469 memcpy(DataBuffer + 16, "XenVBD ", 8); // product id
1470 memcpy(DataBuffer + 32, "000", 8); // product revision level
1471 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1473 else
1475 KdPrint((__DRIVER_NAME " Command = INQUIRY (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1476 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1478 Srb->ScsiStatus = 0;
1479 status = STATUS_SUCCESS;
1480 Irp->IoStatus.Status = status;
1481 Irp->IoStatus.Information = 0;
1482 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1483 break;
1484 case SCSIOP_READ_CAPACITY:
1485 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1486 // KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1487 // DataBuffer = Srb->DataBuffer;
1488 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1489 DataBuffer[0] = (unsigned char)(ChildDeviceData->TotalSectors >> 24) & 0xff;
1490 DataBuffer[1] = (unsigned char)(ChildDeviceData->TotalSectors >> 16) & 0xff;
1491 DataBuffer[2] = (unsigned char)(ChildDeviceData->TotalSectors >> 8) & 0xff;
1492 DataBuffer[3] = (unsigned char)(ChildDeviceData->TotalSectors >> 0) & 0xff;
1493 DataBuffer[4] = (unsigned char)(ChildDeviceData->BytesPerSector >> 24) & 0xff;
1494 DataBuffer[5] = (unsigned char)(ChildDeviceData->BytesPerSector >> 16) & 0xff;
1495 DataBuffer[6] = (unsigned char)(ChildDeviceData->BytesPerSector >> 8) & 0xff;
1496 DataBuffer[7] = (unsigned char)(ChildDeviceData->BytesPerSector >> 0) & 0xff;
1497 Srb->ScsiStatus = 0;
1498 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1499 status = STATUS_SUCCESS;
1500 Irp->IoStatus.Status = status;
1501 Irp->IoStatus.Information = 0;
1502 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1503 break;
1504 case SCSIOP_MODE_SENSE:
1505 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));
1506 KdPrint((__DRIVER_NAME " Length = %d\n", Srb->DataTransferLength));
1508 status = STATUS_SUCCESS;
1509 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1510 // DataBuffer = Srb->DataBuffer;
1511 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1512 switch(cdb->MODE_SENSE.PageCode) //Srb->Cdb[2] & 0x3F)
1514 case MODE_SENSE_RETURN_ALL:
1515 Irp->IoStatus.Information = 0;
1516 //Ptr = (UCHAR *)Srb->DataBuffer;
1517 for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
1519 if (XenVBD_FillModePage(ChildDeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Irp->IoStatus.Information))
1521 break;
1524 break;
1525 default:
1526 XenVBD_FillModePage(ChildDeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Irp->IoStatus.Information);
1527 break;
1529 Srb->DataTransferLength = Irp->IoStatus.Information;
1530 // Srb->ScsiStatus = 0;
1531 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1532 Irp->IoStatus.Status = status;
1533 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1534 break;
1535 case SCSIOP_READ:
1536 case SCSIOP_WRITE:
1537 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1538 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1540 IoMarkIrpPending(Irp);
1542 //KdPrint((__DRIVER_NAME " Irp Acquiring Lock\n"));
1543 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
1544 //KdPrint((__DRIVER_NAME "A Got It\n"));
1546 if (RING_FULL(&ChildDeviceData->Ring))
1548 //KdPrint((__DRIVER_NAME "A Inserting into list\n"));
1549 ListEntry = (XenVbd_ListEntry *)ExAllocatePoolWithTag(NonPagedPool, sizeof(XenVbd_ListEntry), XENVBD_POOL_TAG);
1550 //KdPrint((__DRIVER_NAME " Allocate ListEntry = %08x\n", ListEntry));
1551 if (ListEntry == NULL)
1553 KdPrint((__DRIVER_NAME " CANNOT ALLOCATE MEMORY FOR ListEntry!!!\n"));
1555 ListEntry->Irp = Irp;
1556 InsertTailList(&ChildDeviceData->IrpListHead, &ListEntry->Entry);
1557 ChildDeviceData->IrpAddedToList++;
1559 else
1561 XenVbd_PutIrpOnRing(Device, Irp);
1562 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
1563 if (notify)
1564 EvtChnInterface.Notify(ChildDeviceData->EventChannel);
1565 //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));
1567 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
1568 status = STATUS_PENDING;
1569 break;
1570 case SCSIOP_READ_TOC:
1571 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1572 /*
1573 #define READ_TOC_FORMAT_TOC 0x00
1574 #define READ_TOC_FORMAT_SESSION 0x01
1575 #define READ_TOC_FORMAT_FULL_TOC 0x02
1576 #define READ_TOC_FORMAT_PMA 0x03
1577 #define READ_TOC_FORMAT_ATIP 0x04
1578 */
1579 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1580 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1581 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1582 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1583 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1584 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1585 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1586 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1587 switch (cdb->READ_TOC.Format2)
1589 case READ_TOC_FORMAT_TOC:
1590 DataBuffer[0] = 0; // length MSB
1591 DataBuffer[1] = 10; // length LSB
1592 DataBuffer[2] = 1; // First Track
1593 DataBuffer[3] = 1; // Last Track
1594 DataBuffer[4] = 0; // Reserved
1595 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1596 DataBuffer[6] = 1; // last complete track
1597 DataBuffer[7] = 0; // reserved
1598 DataBuffer[8] = 0; // MSB Block
1599 DataBuffer[9] = 0;
1600 DataBuffer[10] = 0;
1601 DataBuffer[11] = 0; // LSB Block
1602 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1603 break;
1604 case READ_TOC_FORMAT_SESSION:
1605 case READ_TOC_FORMAT_FULL_TOC:
1606 case READ_TOC_FORMAT_PMA:
1607 case READ_TOC_FORMAT_ATIP:
1608 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1609 break;
1611 Irp->IoStatus.Status = status;
1612 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1613 break;
1614 /*
1615 case SCSIOP_GET_CONFIGURATION:
1616 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL 0x0
1617 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT 0x1
1618 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE 0x2
1620 UCHAR OperationCode; // 0x46 - SCSIOP_GET_CONFIGURATION
1621 UCHAR RequestType : 2; // SCSI_GET_CONFIGURATION_REQUEST_TYPE_*
1622 UCHAR Reserved1 : 6; // includes obsolete LUN field
1623 UCHAR StartingFeature[2];
1624 UCHAR Reserved2[3];
1625 UCHAR AllocationLength[2];
1626 UCHAR Control;
1627 break;
1628 */
1629 default:
1630 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1631 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1632 Irp->IoStatus.Status = status;
1633 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1634 break;
1636 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1637 break;
1638 case SRB_FUNCTION_CLAIM_DEVICE:
1639 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1640 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
1641 ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
1642 Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
1643 // Srb->DataBuffer = WdfDeviceWdmGetAttachedDevice(Device);
1644 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1645 status = STATUS_SUCCESS;
1646 Irp->IoStatus.Status = status;
1647 Irp->IoStatus.Information = 0;
1648 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1649 break;
1650 case SRB_FUNCTION_IO_CONTROL:
1651 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1652 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1653 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1654 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1655 status = STATUS_NOT_IMPLEMENTED;
1656 //Irp->IoStatus.Status = status;
1657 //Irp->IoStatus.Information = 0;
1658 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1659 break;
1660 case SRB_FUNCTION_FLUSH:
1661 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1662 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1663 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1664 status = STATUS_SUCCESS;
1665 Irp->IoStatus.Status = status;
1666 Irp->IoStatus.Information = 0;
1667 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1668 break;
1669 default:
1670 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1671 status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1672 break;
1675 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1676 // 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));
1677 //KdPrint((__DRIVER_NAME " <-- WdmIrpPreprocessSCSI\n"));
1679 return status;