win-pvdrivers

view xenvbd/xenvbd.c @ 31:f56c47274c37

Automated merge with ssh://win-pvdrivers@xenbits.xensource.com/win-pvdrivers.hg
author Andy Grover <andy.grover@oracle.com>
date Mon Dec 03 23:05:02 2007 -0800 (2007-12-03)
parents ce8bd97c4136 7fc983eddda8
children 3ac5c4431dbb
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 #pragma warning(disable: 4127) // disable conditional expression is constant
71 LIST_ENTRY DeviceListHead;
72 XEN_IFACE_EVTCHN EvtChnInterface;
73 XEN_IFACE_XENBUS XenBusInterface;
74 XEN_IFACE_XEN XenInterface;
75 XEN_IFACE_GNTTBL GntTblInterface;
77 static BOOLEAN AutoEnumerate;
79 NTSTATUS
80 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
81 {
82 WDF_DRIVER_CONFIG config;
83 ULONG status;
84 UNICODE_STRING RegKeyName;
85 UNICODE_STRING RegValueName;
86 HANDLE RegHandle;
87 OBJECT_ATTRIBUTES RegObjectAttributes;
88 char Buf[200];
89 ULONG BufLen = 200;
90 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
91 int State = 0;
92 int StartPos = 0;
93 WCHAR *SystemStartOptions;
94 size_t SystemStartOptionsLen;
95 size_t i;
97 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
99 WDF_DRIVER_CONFIG_INIT(&config, XenVbd_AddDevice);
100 status = WdfDriverCreate(
101 DriverObject,
102 RegistryPath,
103 WDF_NO_OBJECT_ATTRIBUTES,
104 &config,
105 WDF_NO_HANDLE);
106 if(!NT_SUCCESS(status))
107 {
108 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%08x\n", status));
109 }
111 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
112 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
113 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
114 if(!NT_SUCCESS(status))
115 {
116 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
117 }
119 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
120 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
121 if(!NT_SUCCESS(status))
122 {
123 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
124 }
125 //KdPrint((__DRIVER_NAME " BufLen = %d\n", BufLen));
126 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
127 KdPrint((__DRIVER_NAME " Buf = %ws\n", KeyPartialValue->Data));
128 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
130 AutoEnumerate = FALSE;
132 RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
134 for (i = 0; i <= SystemStartOptionsLen/2; i++)
135 {
136 //KdPrint((__DRIVER_NAME " pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
138 switch (State)
139 {
140 case 0:
141 if (SystemStartOptions[i] == L'G')
142 {
143 StartPos = i;
144 State = 2;
145 } else if (SystemStartOptions[i] != L' ')
146 {
147 State = 1;
148 }
149 break;
150 case 1:
151 if (SystemStartOptions[i] == L' ')
152 State = 0;
153 break;
154 case 2:
155 if (SystemStartOptions[i] == L'P')
156 State = 3;
157 else
158 State = 0;
159 break;
160 case 3:
161 if (SystemStartOptions[i] == L'L')
162 State = 4;
163 else
164 State = 0;
165 break;
166 case 4:
167 if (SystemStartOptions[i] == L'P')
168 State = 5;
169 else
170 State = 0;
171 break;
172 case 5:
173 if (SystemStartOptions[i] == L'V')
174 State = 6;
175 else
176 State = 0;
177 break;
178 case 6:
179 if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
180 AutoEnumerate = TRUE;
181 State = 0;
182 break;
183 }
184 }
186 KdPrint((__DRIVER_NAME " AutoEnumerate = %d\n", AutoEnumerate));
188 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
190 return status;
191 }
193 static WDFDEVICE GlobalDevice;
194 static PDEVICE_OBJECT Pdo;
196 static NTSTATUS
197 XenVbd_AddDevice(WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
198 {
199 WDF_CHILD_LIST_CONFIG ChildListConfig;
200 NTSTATUS status;
201 WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
203 UNREFERENCED_PARAMETER(Driver);
205 KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
207 Pdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit);
209 //WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
210 WDF_CHILD_LIST_CONFIG_INIT(&ChildListConfig, sizeof(XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION), XenVbd_ChildListCreateDevice);
211 WdfFdoInitSetDefaultChildListConfig(DeviceInit, &ChildListConfig, WDF_NO_OBJECT_ATTRIBUTES);
213 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_CONTROLLER);
214 //WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
215 WdfDeviceInitSetExclusive(DeviceInit, FALSE);
217 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
218 pnpPowerCallbacks.EvtDevicePrepareHardware = XenVbd_PrepareHardware;
219 pnpPowerCallbacks.EvtDeviceReleaseHardware = XenVbd_ReleaseHardware;
220 pnpPowerCallbacks.EvtDeviceD0Entry = XenVbd_D0Entry;
221 pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenVbd_D0EntryPostInterruptsEnabled;
222 pnpPowerCallbacks.EvtDeviceD0Exit = XenVbd_D0Exit;
223 pnpPowerCallbacks.EvtDeviceUsageNotification = XenVbd_DeviceUsageNotification;
224 WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
226 /*initialize storage for the device context*/
227 //WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENVBD_DEVICE_DATA);
229 //WdfDeviceInitSetPowerNotPageable(DeviceInit);
231 /*create a device instance.*/
232 status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &GlobalDevice);
233 if(!NT_SUCCESS(status))
234 {
235 KdPrint((__DRIVER_NAME "WdfDeviceCreate failed with status 0x%08x\n", status));
236 return status;
237 }
239 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFilePaging, TRUE);
240 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFileHibernation, TRUE);
241 WdfDeviceSetSpecialFileSupport(GlobalDevice, WdfSpecialFileDump, TRUE);
243 status = STATUS_SUCCESS;
245 KdPrint((__DRIVER_NAME " <-- DeviceAdd\n"));
246 return status;
247 }
249 static NTSTATUS
250 XenVbd_PrepareHardware(
251 IN WDFDEVICE Device,
252 IN WDFCMRESLIST ResourceList,
253 IN WDFCMRESLIST ResourceListTranslated)
254 {
255 NTSTATUS status = STATUS_SUCCESS;
257 UNREFERENCED_PARAMETER(ResourceList);
258 UNREFERENCED_PARAMETER(ResourceListTranslated);
260 //KdPrint((__DRIVER_NAME " --> EvtDevicePrepareHardware\n"));
262 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_EVTCHN, (PINTERFACE) &EvtChnInterface, sizeof(XEN_IFACE_EVTCHN), 1, NULL);
263 if(!NT_SUCCESS(status))
264 {
265 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (EvtChn) failed with status 0x%08x\n", status));
266 }
268 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XENBUS, (PINTERFACE)&XenBusInterface, sizeof(XEN_IFACE_XENBUS), 1, NULL);
269 if(!NT_SUCCESS(status))
270 {
271 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (XenBus) failed with status 0x%08x\n", status));
272 }
274 #if 0 // not used yet
275 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_XEN, (PINTERFACE)&XenInterface, sizeof(XEN_IFACE_XEN), 1, NULL);
276 if(!NT_SUCCESS(status))
277 {
278 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (Xen) failed with status 0x%08x\n", status));
279 }
280 #endif
282 status = WdfFdoQueryForInterface(Device, &GUID_XEN_IFACE_GNTTBL, (PINTERFACE)&GntTblInterface, sizeof(XEN_IFACE_GNTTBL), 1, NULL);
283 if(!NT_SUCCESS(status))
284 {
285 KdPrint((__DRIVER_NAME " WdfFdoQueryForInterface (GntTbl) failed with status 0x%08x\n", status));
286 }
288 //KdPrint((__DRIVER_NAME " <-- EvtDevicePrepareHardware\n"));
290 InitializeListHead(&DeviceListHead);
292 return status;
293 }
295 static NTSTATUS
296 XenVbd_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated)
297 {
298 UNREFERENCED_PARAMETER(Device);
299 UNREFERENCED_PARAMETER(ResourcesTranslated);
301 // release interfaces here...
303 //XenVbd_Close();
305 return STATUS_SUCCESS;
306 }
308 static NTSTATUS
309 XenVbd_D0Entry(
310 IN WDFDEVICE Device,
311 IN WDF_POWER_DEVICE_STATE PreviousState
312 )
313 {
314 NTSTATUS status = STATUS_SUCCESS;
316 UNREFERENCED_PARAMETER(Device);
317 UNREFERENCED_PARAMETER(PreviousState);
319 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Entry\n"));
321 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
323 return status;
324 }
326 static LONG EnumeratedDevices;
327 static KEVENT WaitDevicesEvent;
329 static NTSTATUS
330 XenVbd_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
331 {
332 //OBJECT_ATTRIBUTES oa;
333 NTSTATUS status = STATUS_SUCCESS;
334 //HANDLE nothing;
335 //char *response;
336 PXENPCI_XEN_DEVICE_DATA PdoDeviceData;
337 char **VbdDevices;
338 char *msg;
339 char buffer[128];
340 int i;
341 LARGE_INTEGER WaitTimeout;
343 UNREFERENCED_PARAMETER(Device);
344 UNREFERENCED_PARAMETER(PreviousState);
346 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0EntryPostInterruptsEnabled\n"));
348 PdoDeviceData = (PXENPCI_XEN_DEVICE_DATA)Pdo->DeviceExtension; //GetXenDeviceData(Device);
350 //KdPrint((__DRIVER_NAME " BasePath = %s\n", PdoDeviceData->BasePath));
351 PdoDeviceData->WatchHandler = XenVbd_HotPlugHandler;
353 EnumeratedDevices = 0;
354 KeInitializeEvent(&WaitDevicesEvent, SynchronizationEvent, FALSE);
356 // TODO: Should probably do this in an EvtChildListScanForChildren
357 if (AutoEnumerate)
358 {
359 msg = XenBusInterface.List(XenBusInterface.InterfaceHeader.Context,
360 XBT_NIL, "device/vbd", &VbdDevices);
361 if (!msg) {
362 for (i = 0; VbdDevices[i]; i++)
363 {
364 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
365 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
366 XenVbd_HotPlugHandler(buffer, NULL);
367 //ExFreePoolWithTag(bdDevices[i], XENPCI_POOL_TAG);
368 }
369 KdPrint((__DRIVER_NAME " Waiting for devices to be enumerated\n"));
370 while (EnumeratedDevices != i)
371 {
372 WaitTimeout.QuadPart = -600000000;
373 if (KeWaitForSingleObject(&WaitDevicesEvent, Executive, KernelMode, FALSE, &WaitTimeout) == STATUS_TIMEOUT)
374 {
375 KdPrint((__DRIVER_NAME " Wait timed out\n"));
376 break;
377 }
378 KdPrint((__DRIVER_NAME " %d out of %d devices enumerated\n", EnumeratedDevices, i));
379 }
380 }
381 }
383 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0EntryPostInterruptsEnabled\n"));
385 return status;
386 }
388 static NTSTATUS
389 XenVbd_D0Exit(
390 IN WDFDEVICE Device,
391 IN WDF_POWER_DEVICE_STATE TargetState
392 )
393 {
394 NTSTATUS status = STATUS_SUCCESS;
395 //char *response;
397 UNREFERENCED_PARAMETER(Device);
398 UNREFERENCED_PARAMETER(TargetState);
400 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Exit\n"));
402 //response = XenBusInterface.RemWatch(XBT_NIL, XenBusInterface.InterfaceHeader.Context, XenVbd_HotPlugHandler, NULL);
404 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Exit\n"));
406 return status;
407 }
409 static NTSTATUS
410 XenVbd_DeviceUsageNotification(
411 WDFDEVICE Device,
412 WDF_SPECIAL_FILE_TYPE NotificationType,
413 BOOLEAN IsInNotificationPath)
414 {
415 UNREFERENCED_PARAMETER(Device);
417 KdPrint((__DRIVER_NAME " --> DeviceUsageNotification\n"));
419 switch (NotificationType)
420 {
421 case WdfSpecialFilePaging:
422 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFilePaging, Using = %d\n", IsInNotificationPath));
423 break;
424 case WdfSpecialFileHibernation:
425 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFileHibernation, Using = %d\n", IsInNotificationPath));
426 break;
427 case WdfSpecialFileDump:
428 KdPrint((__DRIVER_NAME " NotificationType = WdfSpecialFileDump, Using = %d\n", IsInNotificationPath));
429 break;
430 default:
431 KdPrint((__DRIVER_NAME " NotificationType = %d, Using = %d\n", NotificationType, IsInNotificationPath));
432 break;
433 }
434 KdPrint((__DRIVER_NAME " <-- DeviceUsageNotification\n"));
436 return TRUE;
437 }
439 static VOID
440 XenVbd_IoDefault(
441 IN WDFQUEUE Queue,
442 IN WDFREQUEST Request
443 )
444 {
445 UNREFERENCED_PARAMETER(Queue);
447 //KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
449 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
451 //KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
452 }
454 static __inline uint64_t
455 GET_ID_FROM_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData)
456 {
457 uint64_t free;
459 free = ChildDeviceData->shadow_free;
461 //KdPrint((__DRIVER_NAME " A free = %d\n", free));
463 ChildDeviceData->shadow_free = ChildDeviceData->shadow[free].req.id;
465 //KdPrint((__DRIVER_NAME " A shadow_free now = %d\n", ChildDeviceData->shadow_free));
467 ChildDeviceData->shadow[free].req.id = 0x0fffffee; /* debug */
468 return free;
469 }
471 static __inline VOID
472 ADD_ID_TO_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, uint64_t Id)
473 {
474 ChildDeviceData->shadow[Id].req.id = ChildDeviceData->shadow_free;
475 ChildDeviceData->shadow[Id].Irp = NULL;
476 ChildDeviceData->shadow_free = Id;
477 }
479 static VOID
480 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp);
482 static PMDL
483 AllocatePages(int Pages)
484 {
485 PMDL Mdl;
486 PVOID Buf;
488 Buf = ExAllocatePoolWithTag(NonPagedPool, Pages * PAGE_SIZE, XENVBD_POOL_TAG);
489 if (Buf == NULL)
490 {
491 KdPrint((__DRIVER_NAME " AllocatePages Failed at ExAllocatePoolWithTag\n"));
492 }
493 Mdl = IoAllocateMdl(Buf, Pages * PAGE_SIZE, FALSE, FALSE, NULL);
494 if (Mdl == NULL)
495 {
496 KdPrint((__DRIVER_NAME " AllocatePages Failed at IoAllocateMdl\n"));
497 }
498 MmBuildMdlForNonPagedPool(Mdl);
500 return Mdl;
501 }
503 static PMDL
504 AllocatePage()
505 {
506 return AllocatePages(1);
507 }
509 static VOID
510 FreePages(PMDL Mdl)
511 {
512 PVOID Buf = MmGetMdlVirtualAddress(Mdl);
513 //KdPrint((__DRIVER_NAME " FreePages Failed at IoAllocateMdl\n"));
514 //KdPrint((__DRIVER_NAME " FreePages Buf = %08x\n", Buf));
515 IoFreeMdl(Mdl);
516 ExFreePoolWithTag(Buf, XENVBD_POOL_TAG);
517 }
519 static VOID
520 XenVbd_DpcThreadProc(WDFDPC Dpc)
521 {
522 PIRP Irp;
523 RING_IDX i, rp;
524 int j;
525 blkif_response_t *rep;
526 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
527 PSCSI_REQUEST_BLOCK Srb;
528 PIO_STACK_LOCATION IrpSp;
529 char *DataBuffer;
530 int more_to_do;
531 int IrpCount;
532 PIRP Irps[100];
533 int BlockCount;
534 KIRQL KIrql;
535 WDFDEVICE ChildDevice;
536 XenVbd_ListEntry *ListEntry;
537 int notify;
539 //!!!IRQL_DISPATCH!!!
541 //KdPrint((__DRIVER_NAME " --> XenVbd_DpcThreadProc\n"));
543 ChildDevice = WdfDpcGetParentObject(Dpc);
545 ChildDeviceData = *GetChildDeviceData(ChildDevice);
547 IrpCount = 0;
548 more_to_do = TRUE;
549 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
551 ChildDeviceData->IrpAddedToRingAtLastDpc = ChildDeviceData->IrpAddedToRing;
553 while (more_to_do)
554 {
555 rp = ChildDeviceData->Ring.sring->rsp_prod;
556 KeMemoryBarrier();
557 for (i = ChildDeviceData->Ring.rsp_cons; i != rp; i++)
558 {
559 rep = RING_GET_RESPONSE(&ChildDeviceData->Ring, i);
560 ChildDeviceData->IrpRemovedFromRing++;
561 Irp = ChildDeviceData->shadow[rep->id].Irp;
562 IrpSp = IoGetCurrentIrpStackLocation(Irp);
563 Srb = IrpSp->Parameters.Scsi.Srb;
565 if (rep->status != BLKIF_RSP_OKAY)
566 {
567 KdPrint((__DRIVER_NAME " Xen Operation returned error in DpcThreadProc\n"));
568 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));
569 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
570 {
571 KdPrint((__DRIVER_NAME " gref[%d] = %d\n", j, ChildDeviceData->shadow[rep->id].req.seg[j].gref));
572 }
573 KdPrint((__DRIVER_NAME " MmGetMdlByteOffset = %d\n", MmGetMdlByteOffset(Irp->MdlAddress)));
574 }
575 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
576 {
577 GntTblInterface.EndAccess(GntTblInterface.InterfaceHeader.Context,
578 ChildDeviceData->shadow[rep->id].req.seg[j].gref);
579 }
580 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
581 if (ChildDeviceData->shadow[rep->id].Buf != NULL)
582 {
583 if (Srb->Cdb[0] == SCSIOP_READ)
584 {
585 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
586 if (DataBuffer == NULL)
587 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe Failed in DpcThreadProc\n"));
588 memcpy(DataBuffer, ChildDeviceData->shadow[rep->id].Buf, BlockCount * ChildDeviceData->BytesPerSector);
589 }
590 FreePages(ChildDeviceData->shadow[rep->id].Mdl);
591 }
592 Srb->SrbStatus = SRB_STATUS_SUCCESS;
593 Srb->ScsiStatus = 0;
594 Irp->IoStatus.Status = STATUS_SUCCESS;
595 Irp->IoStatus.Information = BlockCount * ChildDeviceData->BytesPerSector;
597 Irps[IrpCount++] = Irp;
599 ADD_ID_TO_FREELIST(ChildDeviceData, rep->id);
600 }
602 ChildDeviceData->Ring.rsp_cons = i;
603 if (i != ChildDeviceData->Ring.req_prod_pvt)
604 {
605 RING_FINAL_CHECK_FOR_RESPONSES(&ChildDeviceData->Ring, more_to_do);
606 }
607 else
608 {
609 ChildDeviceData->Ring.sring->rsp_event = i + 1;
610 more_to_do = FALSE;
611 }
612 }
614 notify = 0;
615 while (!RING_FULL(&ChildDeviceData->Ring) && (ListEntry = (XenVbd_ListEntry *)RemoveHeadList(&ChildDeviceData->IrpListHead)) != (XenVbd_ListEntry *)&ChildDeviceData->IrpListHead)
616 {
617 ChildDeviceData->IrpRemovedFromList++;
618 XenVbd_PutIrpOnRing(ChildDevice, ListEntry->Irp);
619 ExFreePoolWithTag(ListEntry, XENVBD_POOL_TAG);
620 notify = 1;
621 }
622 if (notify)
623 {
624 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
625 if (notify)
626 EvtChnInterface.Notify(EvtChnInterface.InterfaceHeader.Context,
627 ChildDeviceData->EventChannel);
628 }
629 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
631 for (j = 0; j < IrpCount; j++)
632 {
633 IoCompleteRequest(Irps[j], IO_NO_INCREMENT);
634 ChildDeviceData->IrpCompleted++;
635 }
637 //KdPrint((__DRIVER_NAME " <-- XenVbd_DpcThreadProc\n"));
638 //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));
639 }
641 static BOOLEAN
642 XenVbd_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
643 {
644 BOOLEAN RetVal;
645 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
647 UNREFERENCED_PARAMETER(Interrupt);
648 // !!!RUNS AT DIRQL!!!
650 //KdPrint((__DRIVER_NAME " --> XenVbd_Interrupt\n"));
652 ChildDeviceData = (PXENVBD_CHILD_DEVICE_DATA)ServiceContext;
653 ChildDeviceData->IrpAddedToRingAtLastInterrupt = ChildDeviceData->IrpAddedToRing;
654 RetVal = WdfDpcEnqueue(ChildDeviceData->Dpc);
656 //KdPrint((__DRIVER_NAME " <-- XenVbd_Interrupt (RetVal = %d)\n", RetVal));
658 return STATUS_SUCCESS;
659 }
661 static VOID
662 XenVbd_BackEndStateHandler(char *Path, PVOID Data)
663 {
664 PXENVBD_CHILD_DEVICE_DATA DeviceData = Data;
665 char TmpPath[128];
666 char *Value;
667 int NewState;
668 PMDL Mdl;
669 grant_ref_t ref;
670 blkif_sring_t *SharedRing;
671 ULONG PFN;
672 XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION Description;
673 NTSTATUS status;
675 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
676 XBT_NIL, Path, &Value);
677 NewState = atoi(Value);
678 ExFreePool(Value);
680 switch (NewState)
681 {
682 case XenbusStateUnknown:
683 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
684 break;
686 case XenbusStateInitialising:
687 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
688 break;
690 case XenbusStateInitWait:
691 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
693 DeviceData->EventChannel = EvtChnInterface.AllocUnbound(
694 EvtChnInterface.InterfaceHeader.Context, 0);
695 EvtChnInterface.Bind(EvtChnInterface.InterfaceHeader.Context,
696 DeviceData->EventChannel, XenVbd_Interrupt, DeviceData);
697 Mdl = AllocatePage();
698 PFN = *MmGetMdlPfnArray(Mdl);
699 SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
700 SHARED_RING_INIT(SharedRing);
701 FRONT_RING_INIT(&DeviceData->Ring, SharedRing, PAGE_SIZE);
702 ref = GntTblInterface.GrantAccess(GntTblInterface.InterfaceHeader.Context,
703 0, PFN, FALSE);
705 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
706 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/ring-ref");
707 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
708 XBT_NIL, TmpPath, "%d", ref);
710 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
711 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/event-channel");
712 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
713 XBT_NIL, TmpPath, "%d", DeviceData->EventChannel);
715 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
716 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/state");
717 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
718 XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
720 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
721 break;
723 case XenbusStateInitialised:
724 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
725 // create the device
726 break;
728 case XenbusStateConnected:
729 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
731 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Description.Header, sizeof(Description));
733 Description.DeviceData = DeviceData;
735 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
736 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/device-type");
737 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
738 XBT_NIL, TmpPath, &Value);
739 if (strcmp(Value, "disk") == 0)
740 {
741 KdPrint((__DRIVER_NAME " DeviceType = Disk\n"));
742 DeviceData->DeviceType = XENVBD_DEVICETYPE_DISK;
743 }
744 else if (strcmp(Value, "cdrom") == 0)
745 {
746 KdPrint((__DRIVER_NAME " DeviceType = CDROM\n"));
747 DeviceData->DeviceType = XENVBD_DEVICETYPE_CDROM;
748 }
749 else
750 {
751 KdPrint((__DRIVER_NAME " DeviceType = %s (This probably won't work!)\n", Value));
752 }
754 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
755 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/type"); // should probably check that this is 'phy' or 'file' or at least not ''
756 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
757 XBT_NIL, TmpPath, &Value);
758 KdPrint((__DRIVER_NAME " Backend Type = %s\n", Value));
759 ExFreePool(Value);
761 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
762 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/mode"); // should store this...
763 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
764 XBT_NIL, TmpPath, &Value);
765 KdPrint((__DRIVER_NAME " Backend Mode = %s\n", Value));
766 ExFreePool(Value);
768 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
769 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/sector-size");
770 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
771 XBT_NIL, TmpPath, &Value);
772 // should complain if Value == NULL
773 DeviceData->BytesPerSector = atoi(Value);
774 ExFreePool(Value);
776 KdPrint((__DRIVER_NAME " BytesPerSector = %d\n", DeviceData->BytesPerSector));
778 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
779 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/sectors");
780 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
781 XBT_NIL, TmpPath, &Value);
782 // should complain if Value == NULL
783 DeviceData->TotalSectors = (ULONGLONG)atol(Value);
784 ExFreePool(Value);
786 KdPrint((__DRIVER_NAME " TotalSectors = %d\n", DeviceData->TotalSectors));
788 // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
789 DeviceData->Geometry.MediaType = FixedMedia;
790 DeviceData->Geometry.BytesPerSector = DeviceData->BytesPerSector;
791 DeviceData->Geometry.SectorsPerTrack = 63;
792 DeviceData->Geometry.TracksPerCylinder = 255;
793 DeviceData->Geometry.Cylinders.QuadPart = DeviceData->TotalSectors / DeviceData->Geometry.SectorsPerTrack / DeviceData->Geometry.TracksPerCylinder;
794 KdPrint((__DRIVER_NAME " Geometry C/H/S = %d/%d/%d\n", DeviceData->Geometry.Cylinders.LowPart, DeviceData->Geometry.TracksPerCylinder, DeviceData->Geometry.SectorsPerTrack));
796 // if we detected something wrong, we should not enumarate the device and should instead initiate a close
798 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(WdfFdoGetDefaultChildList(GlobalDevice), &Description.Header, NULL);
799 if (!NT_SUCCESS(status))
800 {
801 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed %08x\n", status));
802 }
804 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
805 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/state");
806 XenBusInterface.Printf(XenBusInterface.InterfaceHeader.Context,
807 XBT_NIL, TmpPath, "%d", XenbusStateConnected);
809 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
810 InterlockedIncrement(&EnumeratedDevices);
811 KdPrint((__DRIVER_NAME " Added a disk, notifying\n"));
813 KeSetEvent(&WaitDevicesEvent, 1, FALSE);
815 break;
817 case XenbusStateClosing:
818 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
819 break;
821 case XenbusStateClosed:
822 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
823 break;
825 default:
826 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
827 break;
828 }
829 }
831 static VOID
832 XenVbd_HotPlugHandler(char *Path, PVOID Data)
833 {
834 PXENVBD_CHILD_DEVICE_DATA DeviceData;
835 char **Bits;
836 int Count;
837 char TmpPath[128];
838 char *Value;
840 UNREFERENCED_PARAMETER(Data);
842 //KdPrint((__DRIVER_NAME " --> HotPlugHandler\n"));
844 //KdPrint((__DRIVER_NAME " Path = %s\n", Path));
846 Bits = SplitString(Path, '/', 4, &Count);
847 if (Count != 4)
848 {
849 KdPrint((__FUNCTION__ ": Count = %d, not 4!\n", Count));
850 goto cleanup;
851 }
853 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
854 goto cleanup;
856 /* ignore already known devices */
857 for (DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceListHead.Flink; DeviceData != (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead; DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceData->Entry.Flink)
858 {
859 if (strncmp(DeviceData->Path, Path, strlen(DeviceData->Path)) == 0 && Path[strlen(DeviceData->Path)] == '/')
860 {
861 goto cleanup;
862 }
863 }
865 /* new device found, alloc and init dev extension */
866 DeviceData = ExAllocatePoolWithTag(NonPagedPool,
867 sizeof(XENVBD_CHILD_DEVICE_DATA), XENVBD_POOL_TAG);
868 memset(DeviceData, 0, sizeof(XENVBD_CHILD_DEVICE_DATA));
870 //KdPrint((__DRIVER_NAME " Allocated ChildDeviceData = %08x\n", DeviceData));
872 InsertTailList(&DeviceListHead, &DeviceData->Entry);
873 RtlStringCbPrintfA(DeviceData->Path, ARRAY_SIZE(DeviceData->Path),
874 "%s/%s/%s", Bits[0], Bits[1], Bits[2]);
875 DeviceData->DeviceIndex = atoi(Bits[2]);
877 /* Get backend path */
878 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->Path);
879 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/backend");
880 XenBusInterface.Read(XenBusInterface.InterfaceHeader.Context,
881 XBT_NIL, TmpPath, &Value);
882 if (!Value)
883 {
884 KdPrint((__DRIVER_NAME " Read Failed\n"));
885 }
886 else
887 {
888 RtlStringCbCopyA(DeviceData->BackendPath,
889 ARRAY_SIZE(DeviceData->BackendPath), Value);
890 }
891 ExFreePool(Value);
893 /* Add watch on backend state */
894 RtlStringCbCopyA(TmpPath, ARRAY_SIZE(TmpPath), DeviceData->BackendPath);
895 RtlStringCbCatA(TmpPath, ARRAY_SIZE(TmpPath), "/state");
896 XenBusInterface.AddWatch(XenBusInterface.InterfaceHeader.Context,
897 XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, DeviceData);
899 cleanup:
900 FreeSplitString(Bits, Count);
902 //KdPrint((__DRIVER_NAME " <-- HotPlugHandler\n"));
903 }
905 static NTSTATUS
906 XenVbd_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit)
907 {
908 NTSTATUS status;
909 WDFDEVICE ChildDevice;
910 PXENVBD_DEVICE_IDENTIFICATION_DESCRIPTION XenVbdIdentificationDesc;
911 DECLARE_UNICODE_STRING_SIZE(buffer, 50);
912 WDF_OBJECT_ATTRIBUTES PdoAttributes;
913 DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
914 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
915 WDF_IO_QUEUE_CONFIG IoQueueConfig;
916 unsigned int i;
917 WDF_DPC_CONFIG DpcConfig;
918 WDF_OBJECT_ATTRIBUTES DpcObjectAttributes;
919 WDF_DEVICE_STATE DeviceState;
920 //UCHAR ScsiMinors[1] = { IRP_MN_SCSI_CLASS };
922 UNREFERENCED_PARAMETER(ChildList);
924 KdPrint((__DRIVER_NAME " --> ChildListCreateDevice\n"));
926 XenVbdIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION, Header);
928 ChildDeviceData = XenVbdIdentificationDesc->DeviceData;
930 // Capabilities = CM_DEVCAP_UNIQUEID
931 // Devnode Flages = DN_NEED_RESTART??? DN_DISABLEABLE???
933 switch (ChildDeviceData->DeviceType)
934 {
935 case XENVBD_DEVICETYPE_DISK:
936 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_DISK);
938 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk\0");
939 //status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk&Ven_James&Prod_James&Rev_1.00\0");
940 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
942 status = RtlUnicodeStringPrintf(&buffer, L"%02d\0", ChildDeviceData->DeviceIndex);
943 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
945 status = RtlUnicodeStringPrintf(&buffer, L"GenDisk\0");
946 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
947 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
949 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV Disk (%d)", ChildDeviceData->DeviceIndex);
950 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
951 break;
952 case XENVBD_DEVICETYPE_CDROM:
953 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_MASS_STORAGE);
954 WdfDeviceInitSetCharacteristics(ChildInit, FILE_READ_ONLY_DEVICE|FILE_REMOVABLE_MEDIA, TRUE);
956 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\CDROM\0");
957 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
959 status = RtlUnicodeStringPrintf(&buffer, L"%02d\0", ChildDeviceData->DeviceIndex);
960 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
962 status = RtlUnicodeStringPrintf(&buffer, L"GenCdRom\0");
963 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
964 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
966 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV CDROM (%d)\0", ChildDeviceData->DeviceIndex);
967 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
968 break;
969 default:
970 // wtf?
971 break;
972 }
974 WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
976 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, PXENVBD_CHILD_DEVICE_DATA);
978 //WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSCSI, IRP_MJ_SCSI, ScsiMinors, 1);
979 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSCSI, IRP_MJ_SCSI, NULL, 0);
980 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpDEVICE_CONTROL, IRP_MJ_DEVICE_CONTROL, NULL, 0);
982 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CLEANUP, NULL, 0);
983 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CLOSE, NULL, 0);
984 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_CREATE, NULL, 0);
985 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_DIRECTORY_CONTROL, NULL, 0);
986 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_FILE_SYSTEM_CONTROL, NULL, 0);
987 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_FLUSH_BUFFERS, NULL, 0);
988 /// WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_INTERNAL_DEVICE_CONTROL, NULL, 0);
989 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_LOCK_CONTROL, NULL, 0);
990 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_POWER, NULL, 0);
991 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_EA, NULL, 0);
992 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_INFORMATION, NULL, 0);
993 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_SECURITY, NULL, 0);
994 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_QUERY_VOLUME_INFORMATION, NULL, 0);
995 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_READ, NULL, 0);
996 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_INFORMATION, NULL, 0);
997 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_SECURITY, NULL, 0);
998 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SET_VOLUME_INFORMATION, NULL, 0);
999 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SHUTDOWN, NULL, 0);
1000 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_SYSTEM_CONTROL, NULL, 0);
1001 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSomethingSomething, IRP_MJ_WRITE, NULL, 0);
1003 WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);
1005 //WdfDeviceInitSetPowerNotPageable(ChildInit);
1007 status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
1008 if (!NT_SUCCESS(status))
1010 KdPrint((__DRIVER_NAME " WdfDeviceCreate status = %08X\n", status));
1013 switch (ChildDeviceData->DeviceType)
1015 case XENVBD_DEVICETYPE_DISK:
1016 WDF_DEVICE_STATE_INIT(&DeviceState);
1017 DeviceState.NotDisableable = WdfTrue;
1018 WdfDeviceSetDeviceState(ChildDevice, &DeviceState);
1019 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFilePaging, TRUE);
1020 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileHibernation, TRUE);
1021 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileDump, TRUE);
1022 break;
1023 case XENVBD_DEVICETYPE_CDROM:
1024 break;
1026 *GetChildDeviceData(ChildDevice) = ChildDeviceData;
1028 ChildDeviceData->FastPathUsed = 0;
1029 ChildDeviceData->SlowPathUsed = 0;
1030 ChildDeviceData->IrpAddedToList = 0;
1031 ChildDeviceData->IrpRemovedFromList = 0;
1032 ChildDeviceData->IrpAddedToRing = 0;
1033 ChildDeviceData->IrpAddedToRingAtLastNotify = 0;
1034 ChildDeviceData->IrpAddedToRingAtLastInterrupt = 0;
1035 ChildDeviceData->IrpAddedToRingAtLastDpc = 0;
1036 ChildDeviceData->IrpRemovedFromRing = 0;
1037 ChildDeviceData->IrpCompleted = 0;
1039 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoQueueConfig, WdfIoQueueDispatchSequential);
1040 IoQueueConfig.AllowZeroLengthRequests = TRUE;
1041 //IoQueueConfig.EvtIoDefault = XenVbd_Child_IoDefault;
1042 //IoQueueConfig.EvtIoRead = XenVbd_Child_IoReadWrite;
1043 //IoQueueConfig.EvtIoWrite = XenVbd_Child_IoReadWrite;
1044 IoQueueConfig.EvtIoDeviceControl = XenVbd_Child_IoDeviceControl;
1045 //IoQueueConfig.EvtIoInternalDeviceControl = XenVbd_Child_IoInternalDeviceControl; // is IRP_MJ_SCSI
1047 status = WdfIoQueueCreate(ChildDevice, &IoQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &ChildDeviceData->IoDefaultQueue);
1048 if(!NT_SUCCESS(status))
1050 KdPrint((__DRIVER_NAME "WdfIoQueueCreate failed with status 0x%08x\n", status));
1051 return status;
1054 ChildDeviceData->Device = ChildDevice;
1056 KeInitializeSpinLock(&ChildDeviceData->Lock);
1057 KeInitializeSpinLock(&ChildDeviceData->IrpListLock);
1058 InitializeListHead(&ChildDeviceData->IrpListHead);
1060 ChildDeviceData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * BLK_RING_SIZE, XENVBD_POOL_TAG);
1061 memset(ChildDeviceData->shadow, 0, sizeof(blkif_shadow_t) * BLK_RING_SIZE);
1062 //KdPrint((__DRIVER_NAME " Allocated shadow = %08x\n", ChildDeviceData->shadow));
1063 for (i = 0; i < BLK_RING_SIZE; i++)
1064 ChildDeviceData->shadow[i].req.id = i + 1;
1065 ChildDeviceData->shadow_free = 0;
1066 ChildDeviceData->shadow[BLK_RING_SIZE - 1].req.id = 0x0fffffff;
1068 WDF_DPC_CONFIG_INIT(&DpcConfig, XenVbd_DpcThreadProc);
1069 WDF_OBJECT_ATTRIBUTES_INIT(&DpcObjectAttributes);
1070 DpcObjectAttributes.ParentObject = ChildDevice;
1071 WdfDpcCreate(&DpcConfig, &DpcObjectAttributes, &ChildDeviceData->Dpc);
1073 KdPrint((__DRIVER_NAME " <-- ChildListCreateDevice (status = %08x)\n", status));
1075 return status;
1079 // 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
1081 // Call with device lock held
1082 static VOID
1083 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp)
1085 char *DataBuffer;
1086 PSCSI_REQUEST_BLOCK Srb;
1087 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1088 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1089 blkif_request_t *req;
1090 int i;
1091 ULONG j;
1092 int BlockCount;
1093 UINT8 sect_offset;
1095 ChildDeviceData = *GetChildDeviceData(Device);
1097 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1098 KdPrint((__DRIVER_NAME " --> PutIrpOnRing\n"));
1100 if (RING_FULL(&ChildDeviceData->Ring))
1102 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
1105 req = RING_GET_REQUEST(&ChildDeviceData->Ring, ChildDeviceData->Ring.req_prod_pvt);
1107 //KdPrint((__DRIVER_NAME " req = %08x\n", req));
1109 Srb = irpSp->Parameters.Scsi.Srb;
1111 req->sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
1112 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
1114 req->id = GET_ID_FROM_FREELIST(ChildDeviceData);
1116 if (req->id == 0x0fffffff)
1118 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutIrpOnRing\n"));
1121 //KdPrint((__DRIVER_NAME " id = %d\n", req->id));
1123 req->handle = 0;
1124 req->operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
1125 ChildDeviceData->shadow[req->id].Irp = Irp;
1127 if ((MmGetMdlByteOffset(Irp->MdlAddress) & 0x1ff) == 0) // 0x1ff shouldn't be hardcoded...
1129 // fast path - zero copy
1130 ChildDeviceData->shadow[req->id].Mdl = Irp->MdlAddress;
1131 ChildDeviceData->shadow[req->id].Buf = NULL; // we don't need the virtual address
1132 ChildDeviceData->FastPathUsed++;
1134 else
1136 // slow path - copy to bounce buffer
1137 ChildDeviceData->shadow[req->id].Mdl = AllocatePages((BlockCount * ChildDeviceData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE);
1138 ChildDeviceData->shadow[req->id].Buf = MmGetMdlVirtualAddress(ChildDeviceData->shadow[req->id].Mdl);
1139 if (ChildDeviceData->shadow[req->id].Buf == NULL)
1141 KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress returned NULL in PutIrpOnRing\n"));
1143 ChildDeviceData->SlowPathUsed++;
1146 // if (((ChildDeviceData->FastPathUsed + ChildDeviceData->SlowPathUsed) & 0x2FF) == 0)
1147 // {
1148 // KdPrint((__DRIVER_NAME " Fast Path = %d, Slow Path = %d\n", ChildDeviceData->FastPathUsed, ChildDeviceData->SlowPathUsed));
1149 // 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));
1150 // }
1152 sect_offset = (UINT8)(MmGetMdlByteOffset(ChildDeviceData->shadow[req->id].Mdl) >> 9);
1153 for (i = 0, req->nr_segments = 0; i < BlockCount; req->nr_segments++)
1155 req->seg[req->nr_segments].gref = GntTblInterface.GrantAccess(
1156 GntTblInterface.InterfaceHeader.Context,
1157 0,
1158 MmGetMdlPfnArray(ChildDeviceData->shadow[req->id].Mdl)[req->nr_segments],
1159 FALSE);
1160 req->seg[req->nr_segments].first_sect = sect_offset;
1161 for (j = sect_offset; i < BlockCount && j < PAGE_SIZE / ChildDeviceData->BytesPerSector; j++, i++)
1162 req->seg[req->nr_segments].last_sect = (uint8_t)j;
1163 sect_offset = 0;
1165 if (Srb->Cdb[0] == SCSIOP_WRITE && ChildDeviceData->shadow[req->id].Buf != NULL)
1167 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1168 if (DataBuffer == NULL)
1169 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe failed in PutIrpOnRing\n"));
1170 memcpy(ChildDeviceData->shadow[req->id].Buf, DataBuffer, BlockCount * ChildDeviceData->BytesPerSector);
1172 ChildDeviceData->shadow[req->id].req = *req;
1174 ChildDeviceData->Ring.req_prod_pvt++;
1176 ChildDeviceData->IrpAddedToRing++;
1178 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1179 KdPrint((__DRIVER_NAME " <-- PutIrpOnRing\n"));
1182 static ULONG
1183 XenVBD_FillModePage(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
1185 PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
1187 switch (PageCode)
1189 case MODE_PAGE_RIGID_GEOMETRY:
1190 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_DISK)
1192 KdPrint((__DRIVER_NAME " MODE_PAGE_RIGID_GEOMETRY\n"));
1193 if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
1194 return 1;
1195 ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
1196 memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
1197 ModeRigidGeometry->PageCode = PageCode;
1198 ModeRigidGeometry->PageSavable = 0;
1199 ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
1200 ModeRigidGeometry->NumberOfCylinders[0] = (UCHAR)((ChildDeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF);
1201 ModeRigidGeometry->NumberOfCylinders[1] = (UCHAR)((ChildDeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF);
1202 ModeRigidGeometry->NumberOfCylinders[2] = (UCHAR)((ChildDeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF);
1203 ModeRigidGeometry->NumberOfHeads = (UCHAR)ChildDeviceData->Geometry.TracksPerCylinder;
1204 //ModeRigidGeometry->LandZoneCyclinder = 0;
1205 ModeRigidGeometry->RoataionRate[0] = 0x05;
1206 ModeRigidGeometry->RoataionRate[0] = 0x39;
1207 *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
1209 break;
1210 case MODE_PAGE_FAULT_REPORTING:
1211 break;
1212 default:
1213 break;
1215 return 0;
1218 static NTSTATUS
1219 XenVbd_Child_PreprocessWdmIrpDEVICE_CONTROL(WDFDEVICE Device, PIRP Irp)
1221 NTSTATUS Status;
1222 PIO_STACK_LOCATION IrpStack;
1223 PSCSI_ADDRESS ScsiAddress;
1225 KdPrint((__DRIVER_NAME " --> PreprocessWdmIrpDEVICE_CONTROL\n"));
1227 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1229 switch (IrpStack->Parameters.DeviceIoControl.IoControlCode)
1231 case IOCTL_SCSI_GET_ADDRESS:
1232 KdPrint((__DRIVER_NAME " IOCTL_SCSI_GET_ADDRESS\n"));
1233 Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
1234 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(SCSI_ADDRESS))
1236 ScsiAddress = (PSCSI_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1237 ScsiAddress->Length = sizeof(SCSI_ADDRESS);
1238 ScsiAddress->PortNumber = 0;
1239 ScsiAddress->PathId = 0;
1240 ScsiAddress->TargetId = 0;
1241 ScsiAddress->Lun = 0;
1242 Status = STATUS_SUCCESS;
1243 Irp->IoStatus.Status = Status;
1244 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1246 else
1248 KdPrint((__DRIVER_NAME " (Buffer size too small @ %d\n", IrpStack->Parameters.DeviceIoControl.OutputBufferLength));
1250 break;
1251 default:
1252 KdPrint((__DRIVER_NAME " Control Code = %08x\n", IrpStack->Parameters.DeviceIoControl.IoControlCode));
1253 IoSkipCurrentIrpStackLocation(Irp);
1254 Status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1257 KdPrint((__DRIVER_NAME " <-- PreprocessWdmIrpDEVICE_CONTROL\n"));
1259 return Status;
1262 static NTSTATUS
1263 XenVbd_Child_PreprocessWdmIrpSomethingSomething(WDFDEVICE Device, PIRP Irp)
1265 NTSTATUS Status;
1266 PIO_STACK_LOCATION IrpStack;
1268 KdPrint((__DRIVER_NAME " --> XenVbd_Child_PreprocessWdmIrpSomethingSomething\n"));
1270 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1271 KdPrint((__DRIVER_NAME " Major = %02X, Minor = %02X\n", IrpStack->MajorFunction, IrpStack->MinorFunction));
1273 IoSkipCurrentIrpStackLocation(Irp);
1275 Status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1277 KdPrint((__DRIVER_NAME " <-- XenVbd_Child_PreprocessWdmIrpSomethingSomething\n"));
1279 return Status;
1282 static NTSTATUS
1283 XenVbd_Child_PreprocessWdmIrpSCSI(WDFDEVICE Device, PIRP Irp)
1285 char *DataBuffer;
1286 NTSTATUS status = STATUS_SUCCESS;
1287 PSCSI_REQUEST_BLOCK Srb;
1288 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1289 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1290 KIRQL KIrql;
1291 XenVbd_ListEntry *ListEntry;
1292 int notify;
1293 PCDB cdb;
1294 //PUCHAR Ptr;
1295 ULONG i;
1297 ChildDeviceData = *GetChildDeviceData(Device);
1299 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1300 KdPrint((__DRIVER_NAME " --> WdmIrpPreprocessSCSI\n"));
1302 //KdPrint((__DRIVER_NAME " SCSI Minor = %02X\n", irpSp->MinorFunction));
1304 Srb = irpSp->Parameters.Scsi.Srb;
1306 switch (Srb->Function)
1308 case SRB_FUNCTION_EXECUTE_SCSI:
1309 cdb = (PCDB)Srb->Cdb;
1310 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1311 KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
1312 switch(cdb->CDB6GENERIC.OperationCode) //Srb->Cdb[0])
1314 case SCSIOP_TEST_UNIT_READY:
1315 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1316 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1317 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1318 Srb->ScsiStatus = 0;
1319 status = STATUS_SUCCESS;
1320 Irp->IoStatus.Status = status;
1321 Irp->IoStatus.Information = 0;
1322 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1323 break;
1324 case SCSIOP_INQUIRY:
1325 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1326 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1327 if ((Srb->Cdb[1] & 1) == 0)
1329 // DataBuffer = Srb->DataBuffer;
1330 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1331 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1333 DataBuffer[0] = 0x00; // disk
1334 DataBuffer[1] = 0x00; // not removable
1335 memcpy(DataBuffer + 8, "James ", 8); // vendor id
1336 memcpy(DataBuffer + 16, "XenVBD ", 8); // product id
1337 memcpy(DataBuffer + 32, "000", 8); // product revision level
1338 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1340 else
1342 //KdPrint((__DRIVER_NAME " Command = INQUIRY (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1343 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1345 Srb->ScsiStatus = 0;
1346 status = STATUS_SUCCESS;
1347 Irp->IoStatus.Status = status;
1348 Irp->IoStatus.Information = 0;
1349 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1350 break;
1351 case SCSIOP_READ_CAPACITY:
1352 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1353 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1354 // DataBuffer = Srb->DataBuffer;
1355 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1356 DataBuffer[0] = (unsigned char)(ChildDeviceData->TotalSectors >> 24) & 0xff;
1357 DataBuffer[1] = (unsigned char)(ChildDeviceData->TotalSectors >> 16) & 0xff;
1358 DataBuffer[2] = (unsigned char)(ChildDeviceData->TotalSectors >> 8) & 0xff;
1359 DataBuffer[3] = (unsigned char)(ChildDeviceData->TotalSectors >> 0) & 0xff;
1360 DataBuffer[4] = (unsigned char)(ChildDeviceData->BytesPerSector >> 24) & 0xff;
1361 DataBuffer[5] = (unsigned char)(ChildDeviceData->BytesPerSector >> 16) & 0xff;
1362 DataBuffer[6] = (unsigned char)(ChildDeviceData->BytesPerSector >> 8) & 0xff;
1363 DataBuffer[7] = (unsigned char)(ChildDeviceData->BytesPerSector >> 0) & 0xff;
1364 Srb->ScsiStatus = 0;
1365 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1366 status = STATUS_SUCCESS;
1367 Irp->IoStatus.Status = status;
1368 Irp->IoStatus.Information = 0;
1369 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1370 break;
1371 case SCSIOP_MODE_SENSE:
1372 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));
1373 KdPrint((__DRIVER_NAME " Length = %d\n", Srb->DataTransferLength));
1375 status = STATUS_SUCCESS;
1376 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1377 // DataBuffer = Srb->DataBuffer;
1378 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1379 switch(cdb->MODE_SENSE.PageCode) //Srb->Cdb[2] & 0x3F)
1381 case MODE_SENSE_RETURN_ALL:
1382 Irp->IoStatus.Information = 0;
1383 //Ptr = (UCHAR *)Srb->DataBuffer;
1384 for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
1386 if (XenVBD_FillModePage(ChildDeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Irp->IoStatus.Information))
1388 break;
1391 break;
1392 default:
1393 XenVBD_FillModePage(ChildDeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Irp->IoStatus.Information);
1394 break;
1396 Srb->DataTransferLength = Irp->IoStatus.Information;
1397 // Srb->ScsiStatus = 0;
1398 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1399 Irp->IoStatus.Status = status;
1400 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1401 break;
1402 case SCSIOP_READ:
1403 case SCSIOP_WRITE:
1404 if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1405 KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1407 IoMarkIrpPending(Irp);
1409 //KdPrint((__DRIVER_NAME " Irp Acquiring Lock\n"));
1410 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
1411 //KdPrint((__DRIVER_NAME "A Got It\n"));
1413 if (RING_FULL(&ChildDeviceData->Ring))
1415 //KdPrint((__DRIVER_NAME "A Inserting into list\n"));
1416 ListEntry = (XenVbd_ListEntry *)ExAllocatePoolWithTag(NonPagedPool, sizeof(XenVbd_ListEntry), XENVBD_POOL_TAG);
1417 //KdPrint((__DRIVER_NAME " Allocate ListEntry = %08x\n", ListEntry));
1418 if (ListEntry == NULL)
1420 KdPrint((__DRIVER_NAME " CANNOT ALLOCATE MEMORY FOR ListEntry!!!\n"));
1422 ListEntry->Irp = Irp;
1423 InsertTailList(&ChildDeviceData->IrpListHead, &ListEntry->Entry);
1424 ChildDeviceData->IrpAddedToList++;
1426 else
1428 XenVbd_PutIrpOnRing(Device, Irp);
1429 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
1430 if (notify)
1431 EvtChnInterface.Notify(EvtChnInterface.InterfaceHeader.Context,
1432 ChildDeviceData->EventChannel);
1433 //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));
1435 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
1436 status = STATUS_PENDING;
1437 break;
1438 case SCSIOP_READ_TOC:
1439 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1440 /*
1441 #define READ_TOC_FORMAT_TOC 0x00
1442 #define READ_TOC_FORMAT_SESSION 0x01
1443 #define READ_TOC_FORMAT_FULL_TOC 0x02
1444 #define READ_TOC_FORMAT_PMA 0x03
1445 #define READ_TOC_FORMAT_ATIP 0x04
1446 */
1447 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1448 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1449 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1450 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1451 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1452 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1453 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1454 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1455 switch (cdb->READ_TOC.Format2)
1457 case READ_TOC_FORMAT_TOC:
1458 DataBuffer[0] = 0; // length MSB
1459 DataBuffer[1] = 10; // length LSB
1460 DataBuffer[2] = 1; // First Track
1461 DataBuffer[3] = 1; // Last Track
1462 DataBuffer[4] = 0; // Reserved
1463 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1464 DataBuffer[6] = 1; // last complete track
1465 DataBuffer[7] = 0; // reserved
1466 DataBuffer[8] = 0; // MSB Block
1467 DataBuffer[9] = 0;
1468 DataBuffer[10] = 0;
1469 DataBuffer[11] = 0; // LSB Block
1470 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1471 break;
1472 case READ_TOC_FORMAT_SESSION:
1473 case READ_TOC_FORMAT_FULL_TOC:
1474 case READ_TOC_FORMAT_PMA:
1475 case READ_TOC_FORMAT_ATIP:
1476 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1477 break;
1479 Irp->IoStatus.Status = status;
1480 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1481 break;
1482 /*
1483 case SCSIOP_GET_CONFIGURATION:
1484 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL 0x0
1485 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_CURRENT 0x1
1486 #define SCSI_GET_CONFIGURATION_REQUEST_TYPE_ONE 0x2
1488 UCHAR OperationCode; // 0x46 - SCSIOP_GET_CONFIGURATION
1489 UCHAR RequestType : 2; // SCSI_GET_CONFIGURATION_REQUEST_TYPE_*
1490 UCHAR Reserved1 : 6; // includes obsolete LUN field
1491 UCHAR StartingFeature[2];
1492 UCHAR Reserved2[3];
1493 UCHAR AllocationLength[2];
1494 UCHAR Control;
1495 break;
1496 */
1497 default:
1498 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1499 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1500 Irp->IoStatus.Status = status;
1501 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1502 break;
1504 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1505 break;
1506 case SRB_FUNCTION_CLAIM_DEVICE:
1507 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1508 KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
1509 // ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
1510 Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
1511 // Srb->DataBuffer = WdfDeviceWdmGetAttachedDevice(Device);
1512 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1513 status = STATUS_SUCCESS;
1514 Irp->IoStatus.Status = status;
1515 Irp->IoStatus.Information = 0;
1516 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1517 break;
1518 case SRB_FUNCTION_IO_CONTROL:
1519 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1520 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1521 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1522 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1523 status = STATUS_NOT_IMPLEMENTED;
1524 //Irp->IoStatus.Status = status;
1525 //Irp->IoStatus.Information = 0;
1526 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1527 break;
1528 case SRB_FUNCTION_FLUSH:
1529 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1530 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1531 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1532 status = STATUS_SUCCESS;
1533 Irp->IoStatus.Status = status;
1534 Irp->IoStatus.Information = 0;
1535 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1536 break;
1537 default:
1538 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1539 status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1540 break;
1543 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1544 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));
1545 //KdPrint((__DRIVER_NAME " <-- WdmIrpPreprocessSCSI\n"));
1547 return status;
1550 static VOID
1551 XenVbd_Child_IoDefault(WDFQUEUE Queue, WDFREQUEST Request)
1553 UNREFERENCED_PARAMETER(Queue);
1555 KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
1557 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1559 KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
1562 static VOID
1563 XenVbd_Child_IoReadWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t Length)
1565 UNREFERENCED_PARAMETER(Queue);
1566 UNREFERENCED_PARAMETER(Length);
1568 KdPrint((__DRIVER_NAME " --> IoReadWrite\n"));
1570 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1572 KdPrint((__DRIVER_NAME " <-- IoReadWrite\n"));
1575 static VOID
1576 XenVbd_Child_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode)
1578 WDFDEVICE Device;
1579 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1580 PIRP Irp;
1581 PSTORAGE_PROPERTY_QUERY Spq;
1582 PSTORAGE_ADAPTER_DESCRIPTOR Sad;
1583 PSTORAGE_DEVICE_DESCRIPTOR Sdd;
1584 PSTORAGE_DEVICE_ID_DESCRIPTOR Sdid;
1585 PSTORAGE_IDENTIFIER Si;
1586 PSCSI_ADDRESS Sa;
1587 ULONG Information;
1588 //NTSTATUS Status;
1589 int StructEndOffset;
1591 UNREFERENCED_PARAMETER(Queue);
1592 //UNREFERENCED_PARAMETER(Request);
1593 UNREFERENCED_PARAMETER(OutputBufferLength);
1594 UNREFERENCED_PARAMETER(InputBufferLength);
1596 Device = WdfIoQueueGetDevice(Queue);
1598 ChildDeviceData = *GetChildDeviceData(Device);
1600 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1601 KdPrint((__DRIVER_NAME " --> IoDeviceControl\n"));
1602 //KdPrint((__DRIVER_NAME " InputBufferLength = %d\n", InputBufferLength));
1603 //KdPrint((__DRIVER_NAME " OutputBufferLength = %d\n", OutputBufferLength));
1605 Irp = WdfRequestWdmGetIrp(Request);
1607 switch (IoControlCode)
1609 case IOCTL_STORAGE_QUERY_PROPERTY:
1610 KdPrint((__DRIVER_NAME " IOCTL_STORAGE_QUERY_PROPERTY\n"));
1611 Spq = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
1612 if (Spq->PropertyId == StorageAdapterProperty && Spq->QueryType == PropertyStandardQuery)
1614 KdPrint((__DRIVER_NAME " PropertyId = StorageAdapterProperty, QueryType = PropertyStandardQuery\n"));
1615 Information = 0;
1616 if (OutputBufferLength >= 8)
1618 Information = 8;
1619 Sad = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1620 Sad->Version = 1;
1621 Sad->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
1622 if (OutputBufferLength >= Sad->Size)
1624 Information = Sad->Size;
1625 Sad->MaximumTransferLength = 45056;
1626 Sad->MaximumPhysicalPages = 11;
1627 Sad->AlignmentMask = 0;
1628 Sad->AdapterUsesPio = FALSE;
1629 Sad->AdapterScansDown = FALSE;
1630 Sad->CommandQueueing = FALSE;
1631 Sad->AcceleratedTransfer = FALSE;
1632 Sad->BusType = BusTypeScsi;
1633 Sad->BusMajorVersion = 0;
1634 Sad->BusMinorVersion = 0;
1637 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Information);
1639 else if (Spq->PropertyId == StorageDeviceProperty && Spq->QueryType == PropertyStandardQuery)
1641 KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceProperty, QueryType = PropertyStandardQuery\n"));
1642 Information = 0;
1643 if (OutputBufferLength >= 8)
1645 Information = 8;
1646 Sdd = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1647 Sdd->Version = 1;
1648 Sdd->Size = &Sdd->RawDeviceProperties[36] - (PUCHAR)Sdd + 1;
1649 // 0 0 1 2 3
1650 // 0 7 5 4 1
1651 //"VENDOR\0PRODUCT\0Revision\0Serial\0"
1652 if (OutputBufferLength >= Sdd->Size)
1654 Information = Sdd->Size;
1655 switch (ChildDeviceData->DeviceType)
1657 case XENVBD_DEVICETYPE_DISK:
1658 Sdd->DeviceType = DIRECT_ACCESS_DEVICE;
1659 Sdd->DeviceTypeModifier = 0x00;
1660 Sdd->RemovableMedia = FALSE;
1661 break;
1662 case XENVBD_DEVICETYPE_CDROM:
1663 Sdd->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1664 Sdd->DeviceTypeModifier = 0x00;
1665 Sdd->RemovableMedia = TRUE;
1666 break;
1667 default:
1668 // wtf
1669 break;
1671 Sdd->CommandQueueing = FALSE;
1672 StructEndOffset = Sdd->RawDeviceProperties - (PUCHAR)Sdd;
1673 Sdd->VendorIdOffset = StructEndOffset + 0;
1674 Sdd->ProductIdOffset = StructEndOffset + 7;
1675 Sdd->ProductRevisionOffset = StructEndOffset + 15;
1676 Sdd->SerialNumberOffset = StructEndOffset + 24;
1677 Sdd->BusType = BusTypeScsi;
1678 Sdd->RawPropertiesLength = 36;
1679 memcpy(Sdd->RawDeviceProperties, "VENDOR\0PRODUCT\0Revision\0Serial99999\0", 36);
1682 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Information);
1684 else if (Spq->PropertyId == StorageDeviceIdProperty && Spq->QueryType == PropertyStandardQuery)
1686 KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceIdProperty, QueryType = PropertyStandardQuery\n"));
1687 Information = 0;
1688 if (OutputBufferLength >= 8)
1690 Information = 8;
1691 Sdid = (PSTORAGE_DEVICE_ID_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1692 Sdid->Version = 1;
1693 Si = (PSTORAGE_IDENTIFIER)Sdid->Identifiers;
1694 Sdid->Size = &Si->Identifier[8] - (PUCHAR)Sdid + 1;
1695 if (OutputBufferLength >= Sdid->Size)
1697 Information = Sdid->Size;
1698 Sdid->NumberOfIdentifiers = 1;
1699 Si->CodeSet = StorageIdCodeSetAscii;
1700 Si->Type = StorageIdTypeScsiNameString;
1701 //Si->CodeSet = StorageIdCodeSetBinary;
1702 //Si->Type = StorageIdTypeEUI64;
1703 Si->IdentifierSize = 9;
1704 Si->NextOffset = 0;
1705 Si->Association = StorageIdAssocPort;
1706 Si->Identifier[0] = 'S';
1707 Si->Identifier[1] = 'e';
1708 Si->Identifier[2] = 'r';
1709 Si->Identifier[3] = 'i';
1710 Si->Identifier[4] = 'a';
1711 Si->Identifier[5] = 'l';
1712 Si->Identifier[6] = '9';
1713 Si->Identifier[7] = '9';
1714 Si->Identifier[6] = '9';
1715 Si->Identifier[7] = '9';
1716 Si->Identifier[8] = '9';
1717 //Si->Identifier[8] = 0;
1720 WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, Information);
1722 else
1724 switch (Spq->PropertyId)
1726 case StorageDeviceProperty:
1727 KdPrint((__DRIVER_NAME " StorageDeviceProperty\n"));
1728 break;
1729 case StorageAccessAlignmentProperty:
1730 KdPrint((__DRIVER_NAME " StorageAccessAlignmentProperty\n"));
1731 break;
1732 case StorageAdapterProperty:
1733 KdPrint((__DRIVER_NAME " StorageAdapterProperty\n"));
1734 break;
1735 case StorageDeviceIdProperty:
1736 KdPrint((__DRIVER_NAME " StorageDeviceIdProperty\n"));
1737 break;
1738 case StorageDeviceUniqueIdProperty:
1739 KdPrint((__DRIVER_NAME " StorageDeviceUniqueIdProperty\n"));
1740 break;
1741 case StorageDeviceWriteCacheProperty:
1742 KdPrint((__DRIVER_NAME " StorageDeviceWriteCacheProperty\n"));
1743 break;
1744 default:
1745 KdPrint((__DRIVER_NAME " Unknown Property %08x\n", Spq->PropertyId));
1746 break;
1748 switch (Spq->QueryType)
1750 case PropertyStandardQuery:
1751 KdPrint((__DRIVER_NAME " PropertyStandardQuery\n"));
1752 break;
1753 case PropertyExistsQuery:
1754 KdPrint((__DRIVER_NAME " PropertyExistsQuery\n"));
1755 break;
1756 default:
1757 KdPrint((__DRIVER_NAME " Unknown Query %08x\n", Spq->QueryType));
1758 break;
1760 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1762 break;
1763 // http://www.osronline.com/article.cfm?article=229
1764 // 0x00560030 device = 0x56, Function = 0x00c =
1765 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
1766 KdPrint((__DRIVER_NAME " IOCTL_DISK_GET_DRIVE_GEOMETRY\n"));
1767 memcpy(Irp->AssociatedIrp.SystemBuffer, &ChildDeviceData->Geometry, sizeof(DISK_GEOMETRY));
1768 WdfRequestComplete(Request, STATUS_SUCCESS);
1769 break;
1770 case IOCTL_SCSI_GET_ADDRESS:
1771 KdPrint((__DRIVER_NAME " IOCTL_SCSI_GET_ADDRESS\n"));
1772 Sa = (PSCSI_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1773 Sa->Length = sizeof(SCSI_ADDRESS);
1774 Sa->PortNumber = 0;
1775 Sa->PathId = 0;
1776 Sa->TargetId = 0;
1777 Sa->Lun = 0;
1778 WdfRequestComplete(Request, STATUS_SUCCESS);
1779 break;
1780 case FT_BALANCED_READ_MODE: // just pretend we know what this is...
1781 KdPrint((__DRIVER_NAME " FT_BALANCED_READ_MODE\n"));
1782 WdfRequestComplete(Request, STATUS_SUCCESS);
1783 break;
1784 default:
1785 KdPrint((__DRIVER_NAME " Not Implemented IoControlCode=%08X\n", IoControlCode));
1786 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1787 break;
1790 // if (ChildDeviceData->DeviceType == XENVBD_DEVICETYPE_CDROM)
1791 KdPrint((__DRIVER_NAME " <-- IoDeviceControl\n"));
1794 static VOID
1795 XenVbd_Child_IoInternalDeviceControl(
1796 WDFQUEUE Queue,
1797 WDFREQUEST Request,
1798 size_t OutputBufferLength,
1799 size_t InputBufferLength,
1800 ULONG IoControlCode)
1802 UNREFERENCED_PARAMETER(Queue);
1803 UNREFERENCED_PARAMETER(Request);
1804 UNREFERENCED_PARAMETER(OutputBufferLength);
1805 UNREFERENCED_PARAMETER(InputBufferLength);
1806 UNREFERENCED_PARAMETER(IoControlCode);
1808 KdPrint((__DRIVER_NAME " --> IoInternalDeviceControl\n"));
1809 KdPrint((__DRIVER_NAME " <-- IoInternalDeviceControl\n"));