win-pvdrivers

view xenvbd/xenvbd.c @ 5:2b0f6930eeeb

Trying to get Windows to allow a page file to exist on the PV disk
author James Harper <james.harper@bendigoit.com.au>
date Sun Nov 11 22:50:42 2007 +1100 (2007-11-11)
parents 3bf1f48005d8
children d25a6f733a8e
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);
21 static NTSTATUS
22 XenVbd_PrepareHardware(WDFDEVICE hDevice, WDFCMRESLIST Resources, WDFCMRESLIST ResourcesTranslated);
24 static NTSTATUS
25 XenVbd_ReleaseHardware(WDFDEVICE Device, WDFCMRESLIST ResourcesTranslated);
27 static NTSTATUS
28 XenVbd_D0Entry(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
30 static NTSTATUS
31 XenVbd_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState);
33 static NTSTATUS
34 XenVbd_D0Exit(WDFDEVICE Device, WDF_POWER_DEVICE_STATE TargetState);
36 static VOID
37 XenVbd_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
38 static VOID
39 XenVbd_IoRead(WDFQUEUE Queue, WDFREQUEST Request, size_t Length);
40 static VOID
41 XenVbd_IoWrite(WDFQUEUE Queue, WDFREQUEST Request, size_t Length);
42 static VOID
43 XenVbd_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, IN size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode);
45 static NTSTATUS
46 XenVbd_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit);
47 //static NTSTATUS
48 //XenVbd_DeviceResourceRequirementsQuery(WDFDEVICE Device, WDFIORESREQLIST IoResourceRequirementsList);
49 static NTSTATUS
50 XenVbd_Child_PreprocessWdmIrpSCSI(WDFDEVICE Device, PIRP Irp);
51 static VOID
52 XenVbd_Child_IoDefault(WDFQUEUE Queue, WDFREQUEST Request);
53 static VOID
54 XenVbd_Child_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode);
56 static VOID
57 XenVbd_HotPlugHandler(char *Path, PVOID Data);
59 #ifdef ALLOC_PRAGMA
60 #pragma alloc_text (INIT, DriverEntry)
61 #pragma alloc_text (PAGE, XenVbd_AddDevice)
62 #endif
64 LIST_ENTRY DeviceListHead;
65 XEN_IFACE_EVTCHN EvtChnInterface;
66 XEN_IFACE_XENBUS XenBusInterface;
67 XEN_IFACE_XEN XenInterface;
68 XEN_IFACE_GNTTBL GntTblInterface;
70 static BOOLEAN AutoEnumerate;
72 NTSTATUS
73 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
74 {
75 WDF_DRIVER_CONFIG config;
76 ULONG status;
77 UNICODE_STRING RegKeyName;
78 UNICODE_STRING RegValueName;
79 HANDLE RegHandle;
80 OBJECT_ATTRIBUTES RegObjectAttributes;
81 char Buf[200];
82 ULONG BufLen = 200;
83 PKEY_VALUE_PARTIAL_INFORMATION KeyPartialValue;
84 int State = 0;
85 int StartPos = 0;
86 WCHAR *SystemStartOptions;
87 size_t SystemStartOptionsLen;
88 size_t i;
90 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
92 WDF_DRIVER_CONFIG_INIT(&config, XenVbd_AddDevice);
93 status = WdfDriverCreate(
94 DriverObject,
95 RegistryPath,
96 WDF_NO_OBJECT_ATTRIBUTES,
97 &config,
98 WDF_NO_HANDLE);
99 if(!NT_SUCCESS(status))
100 {
101 KdPrint((__DRIVER_NAME " WdfDriverCreate failed with status 0x%08x\n", status));
102 }
104 RtlInitUnicodeString(&RegKeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Control");
105 InitializeObjectAttributes(&RegObjectAttributes, &RegKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL);
106 status = ZwOpenKey(&RegHandle, KEY_READ, &RegObjectAttributes);
107 if(!NT_SUCCESS(status))
108 {
109 KdPrint((__DRIVER_NAME " ZwOpenKey returned %08x\n", status));
110 }
112 RtlInitUnicodeString(&RegValueName, L"SystemStartOptions");
113 status = ZwQueryValueKey(RegHandle, &RegValueName, KeyValuePartialInformation, Buf, BufLen, &BufLen);
114 if(!NT_SUCCESS(status))
115 {
116 KdPrint((__DRIVER_NAME " ZwQueryKeyValue returned %08x\n", status));
117 }
118 //KdPrint((__DRIVER_NAME " BufLen = %d\n", BufLen));
119 KeyPartialValue = (PKEY_VALUE_PARTIAL_INFORMATION)Buf;
120 KdPrint((__DRIVER_NAME " Buf = %ws\n", KeyPartialValue->Data));
121 SystemStartOptions = (WCHAR *)KeyPartialValue->Data;
123 AutoEnumerate = FALSE;
125 RtlStringCbLengthW(SystemStartOptions, KeyPartialValue->DataLength, &SystemStartOptionsLen);
127 for (i = 0; i <= SystemStartOptionsLen/2; i++)
128 {
129 //KdPrint((__DRIVER_NAME " pos = %d, state = %d, char = '%wc' (%d)\n", i, State, SystemStartOptions[i], SystemStartOptions[i]));
131 switch (State)
132 {
133 case 0:
134 if (SystemStartOptions[i] == L'G')
135 {
136 StartPos = i;
137 State = 2;
138 } else if (SystemStartOptions[i] != L' ')
139 {
140 State = 1;
141 }
142 break;
143 case 1:
144 if (SystemStartOptions[i] == L' ')
145 State = 0;
146 break;
147 case 2:
148 if (SystemStartOptions[i] == L'P')
149 State = 3;
150 else
151 State = 0;
152 break;
153 case 3:
154 if (SystemStartOptions[i] == L'L')
155 State = 4;
156 else
157 State = 0;
158 break;
159 case 4:
160 if (SystemStartOptions[i] == L'P')
161 State = 5;
162 else
163 State = 0;
164 break;
165 case 5:
166 if (SystemStartOptions[i] == L'V')
167 State = 6;
168 else
169 State = 0;
170 break;
171 case 6:
172 if (SystemStartOptions[i] == L' ' || SystemStartOptions[i] == 0)
173 AutoEnumerate = TRUE;
174 State = 0;
175 break;
176 }
177 }
179 KdPrint((__DRIVER_NAME " AutoEnumerate = %d\n", AutoEnumerate));
181 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
183 return status;
184 }
186 static WDFDEVICE GlobalDevice;
187 static PDEVICE_OBJECT Pdo;
189 static NTSTATUS
190 XenVbd_AddDevice(
191 IN WDFDRIVER Driver,
192 IN PWDFDEVICE_INIT DeviceInit
193 )
194 {
195 WDF_CHILD_LIST_CONFIG ChildListConfig;
196 NTSTATUS status;
197 WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
199 UNREFERENCED_PARAMETER(Driver);
201 KdPrint((__DRIVER_NAME " --> DeviceAdd\n"));
203 Pdo = WdfFdoInitWdmGetPhysicalDevice(DeviceInit);
205 //*** just changed ***
206 //WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_BUS_EXTENDER);
207 WDF_CHILD_LIST_CONFIG_INIT(&ChildListConfig, sizeof(XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION), XenVbd_ChildListCreateDevice);
208 WdfFdoInitSetDefaultChildListConfig(DeviceInit, &ChildListConfig, WDF_NO_OBJECT_ATTRIBUTES);
210 WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_CONTROLLER);
211 //WdfDeviceInitSetIoType(DeviceInit, WdfDeviceIoBuffered);
212 WdfDeviceInitSetExclusive(DeviceInit, FALSE);
214 WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
215 pnpPowerCallbacks.EvtDevicePrepareHardware = XenVbd_PrepareHardware;
216 pnpPowerCallbacks.EvtDeviceReleaseHardware = XenVbd_ReleaseHardware;
217 pnpPowerCallbacks.EvtDeviceD0Entry = XenVbd_D0Entry;
218 pnpPowerCallbacks.EvtDeviceD0EntryPostInterruptsEnabled = XenVbd_D0EntryPostInterruptsEnabled;
219 pnpPowerCallbacks.EvtDeviceD0Exit = XenVbd_D0Exit;
220 WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
222 /*initialize storage for the device context*/
223 //WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, XENVBD_DEVICE_DATA);
225 /*create a device instance.*/
226 status = WdfDeviceCreate(&DeviceInit, WDF_NO_OBJECT_ATTRIBUTES, &GlobalDevice);
227 if(!NT_SUCCESS(status))
228 {
229 KdPrint((__DRIVER_NAME "WdfDeviceCreate failed with status 0x%08x\n", status));
230 return status;
231 }
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"));
310 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Entry\n"));
312 return status;
313 }
315 static int EnumeratedDevices;
316 static KEVENT WaitDevicesEvent;
318 static NTSTATUS
319 XenVbd_D0EntryPostInterruptsEnabled(WDFDEVICE Device, WDF_POWER_DEVICE_STATE PreviousState)
320 {
321 //OBJECT_ATTRIBUTES oa;
322 NTSTATUS status = STATUS_SUCCESS;
323 //HANDLE nothing;
324 //char *response;
325 PXENPCI_XEN_DEVICE_DATA PdoDeviceData;
326 char **VbdDevices;
327 char *msg;
328 char buffer[128];
329 int i;
330 LARGE_INTEGER WaitTimeout;
332 UNREFERENCED_PARAMETER(Device);
333 UNREFERENCED_PARAMETER(PreviousState);
335 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0EntryPostInterruptsEnabled\n"));
337 PdoDeviceData = (PXENPCI_XEN_DEVICE_DATA)Pdo->DeviceExtension; //GetXenDeviceData(Device);
339 //KdPrint((__DRIVER_NAME " BasePath = %s\n", PdoDeviceData->BasePath));
340 PdoDeviceData->WatchHandler = XenVbd_HotPlugHandler;
342 EnumeratedDevices = 0;
343 KeInitializeEvent(&WaitDevicesEvent, SynchronizationEvent, FALSE);
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 // TODO: need to not wait forever here...
360 WaitTimeout.QuadPart = -600000000;
361 if (KeWaitForSingleObject(&WaitDevicesEvent, Executive, KernelMode, FALSE, &WaitTimeout) == STATUS_TIMEOUT)
362 {
363 KdPrint((__DRIVER_NAME " Wait timed out\n"));
364 break;
365 }
366 KdPrint((__DRIVER_NAME " %d out of %d devices enumerated\n", EnumeratedDevices, i));
367 }
368 }
369 }
371 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0EntryPostInterruptsEnabled\n"));
373 return status;
374 }
376 static NTSTATUS
377 XenVbd_D0Exit(
378 IN WDFDEVICE Device,
379 IN WDF_POWER_DEVICE_STATE TargetState
380 )
381 {
382 NTSTATUS status = STATUS_SUCCESS;
383 //char *response;
385 UNREFERENCED_PARAMETER(Device);
386 UNREFERENCED_PARAMETER(TargetState);
388 //KdPrint((__DRIVER_NAME " --> EvtDeviceD0Exit\n"));
390 //response = XenBusInterface.RemWatch(XBT_NIL, XenBusInterface.InterfaceHeader.Context, XenVbd_HotPlugHandler, NULL);
392 //KdPrint((__DRIVER_NAME " <-- EvtDeviceD0Exit\n"));
394 return status;
395 }
397 static VOID
398 XenVbd_IoDefault(
399 IN WDFQUEUE Queue,
400 IN WDFREQUEST Request
401 )
402 {
403 UNREFERENCED_PARAMETER(Queue);
405 //KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
407 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
409 //KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
410 }
412 static __inline uint64_t
413 GET_ID_FROM_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData)
414 {
415 uint64_t free;
417 free = ChildDeviceData->shadow_free;
419 //KdPrint((__DRIVER_NAME " A free = %d\n", free));
421 ChildDeviceData->shadow_free = ChildDeviceData->shadow[free].req.id;
423 //KdPrint((__DRIVER_NAME " A shadow_free now = %d\n", ChildDeviceData->shadow_free));
425 ChildDeviceData->shadow[free].req.id = 0x0fffffee; /* debug */
426 return free;
427 }
429 static __inline VOID
430 ADD_ID_TO_FREELIST(PXENVBD_CHILD_DEVICE_DATA ChildDeviceData, uint64_t Id)
431 {
432 ChildDeviceData->shadow[Id].req.id = ChildDeviceData->shadow_free;
433 ChildDeviceData->shadow[Id].Irp = NULL;
434 ChildDeviceData->shadow_free = Id;
435 }
437 static VOID
438 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp);
440 static PMDL
441 AllocatePages(int Pages)
442 {
443 PMDL Mdl;
444 PVOID Buf;
446 Buf = ExAllocatePoolWithTag(NonPagedPool, Pages * PAGE_SIZE, XENVBD_POOL_TAG);
447 if (Buf == NULL)
448 {
449 KdPrint((__DRIVER_NAME " AllocatePages Failed at ExAllocatePoolWithTag\n"));
450 }
451 Mdl = IoAllocateMdl(Buf, Pages * PAGE_SIZE, FALSE, FALSE, NULL);
452 if (Mdl == NULL)
453 {
454 KdPrint((__DRIVER_NAME " AllocatePages Failed at IoAllocateMdl\n"));
455 }
456 MmBuildMdlForNonPagedPool(Mdl);
458 return Mdl;
459 }
461 static PMDL
462 AllocatePage()
463 {
464 return AllocatePages(1);
465 }
467 static VOID
468 FreePages(PMDL Mdl)
469 {
470 PVOID Buf = MmGetMdlVirtualAddress(Mdl);
471 //KdPrint((__DRIVER_NAME " FreePages Failed at IoAllocateMdl\n"));
472 //KdPrint((__DRIVER_NAME " FreePages Buf = %08x\n", Buf));
473 IoFreeMdl(Mdl);
474 ExFreePoolWithTag(Buf, XENVBD_POOL_TAG);
475 }
477 static VOID
478 XenVbd_DpcThreadProc(WDFDPC Dpc)
479 {
480 PIRP Irp;
481 RING_IDX i, rp;
482 int j;
483 blkif_response_t *rep;
484 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
485 PSCSI_REQUEST_BLOCK Srb;
486 PIO_STACK_LOCATION IrpSp;
487 char *DataBuffer;
488 int more_to_do;
489 int IrpCount;
490 PIRP Irps[100];
491 int BlockCount;
492 KIRQL KIrql;
493 WDFDEVICE ChildDevice;
494 XenVbd_ListEntry *ListEntry;
496 //!!!IRQL_DISPATCH!!!
498 //KdPrint((__DRIVER_NAME " --> XenVbd_DpcThreadProc\n"));
500 ChildDevice = WdfDpcGetParentObject(Dpc);
502 ChildDeviceData = *GetChildDeviceData(ChildDevice);
504 IrpCount = 0;
505 more_to_do = TRUE;
506 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
508 //ChildDeviceData->IrpAddedToRingAtLastDpc = ChildDeviceData->IrpAddedToRing;
510 while (more_to_do)
511 {
512 rp = ChildDeviceData->Ring.sring->rsp_prod;
513 KeMemoryBarrier();
514 for (i = ChildDeviceData->Ring.rsp_cons; i != rp; i++)
515 {
516 rep = RING_GET_RESPONSE(&ChildDeviceData->Ring, i);
517 //ChildDeviceData->IrpRemovedFromRing++;
518 Irp = ChildDeviceData->shadow[rep->id].Irp;
519 IrpSp = IoGetCurrentIrpStackLocation(Irp);
520 Srb = IrpSp->Parameters.Scsi.Srb;
522 if (rep->status != BLKIF_RSP_OKAY)
523 {
524 KdPrint((__DRIVER_NAME " Xen Operation returned error in DpcThreadProc\n"));
525 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));
526 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
527 {
528 KdPrint((__DRIVER_NAME " gref[%d] = %d\n", j, ChildDeviceData->shadow[rep->id].req.seg[j].gref));
529 }
530 KdPrint((__DRIVER_NAME " MmGetMdlByteOffset = %d\n", MmGetMdlByteOffset(Irp->MdlAddress)));
531 }
532 for (j = 0; j < ChildDeviceData->shadow[rep->id].req.nr_segments; j++)
533 {
534 GntTblInterface.EndAccess(ChildDeviceData->shadow[rep->id].req.seg[j].gref);
535 }
536 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
537 if (Srb->Cdb[0] == SCSIOP_READ && ChildDeviceData->shadow[rep->id].Buf != NULL)
538 {
539 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
540 if (DataBuffer == NULL)
541 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe Failed in DpcThreadProc\n"));
542 memcpy(DataBuffer, ChildDeviceData->shadow[rep->id].Buf, BlockCount * ChildDeviceData->BytesPerSector);
543 FreePages(ChildDeviceData->shadow[rep->id].Mdl);
544 }
545 Srb->SrbStatus = SRB_STATUS_SUCCESS;
546 Srb->ScsiStatus = 0;
547 Irp->IoStatus.Status = STATUS_SUCCESS;
548 Irp->IoStatus.Information = BlockCount * ChildDeviceData->BytesPerSector;
550 Irps[IrpCount++] = Irp;
552 ADD_ID_TO_FREELIST(ChildDeviceData, rep->id);
553 }
555 ChildDeviceData->Ring.rsp_cons = i;
556 if (i != ChildDeviceData->Ring.req_prod_pvt)
557 {
558 RING_FINAL_CHECK_FOR_RESPONSES(&ChildDeviceData->Ring, more_to_do);
559 }
560 else
561 {
562 ChildDeviceData->Ring.sring->rsp_event = i + 1;
563 more_to_do = FALSE;
564 }
565 }
567 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
569 for (j = 0; j < IrpCount; j++)
570 {
571 IoCompleteRequest(Irps[j], IO_NO_INCREMENT);
572 //ChildDeviceData->IrpCompleted++;
573 }
575 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
577 while (!RING_FULL(&ChildDeviceData->Ring) && (ListEntry = (XenVbd_ListEntry *)/*ExInterlocked*/RemoveHeadList(&ChildDeviceData->IrpListHead)) != (XenVbd_ListEntry *)&ChildDeviceData->IrpListHead)
578 {
579 //ChildDeviceData->IrpRemovedFromList++;
580 XenVbd_PutIrpOnRing(ChildDevice, ListEntry->Irp);
581 ExFreePoolWithTag(ListEntry, XENVBD_POOL_TAG);
582 }
584 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
586 //KdPrint((__DRIVER_NAME " <-- XenVbd_DpcThreadProc\n"));
587 //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));
588 }
590 static BOOLEAN
591 XenVbd_Interrupt(PKINTERRUPT Interrupt, PVOID ServiceContext)
592 {
593 BOOLEAN RetVal;
594 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
596 UNREFERENCED_PARAMETER(Interrupt);
597 // !!!RUNS AT DIRQL!!!
599 //KdPrint((__DRIVER_NAME " --> XenVbd_Interrupt\n"));
601 ChildDeviceData = (PXENVBD_CHILD_DEVICE_DATA)ServiceContext;
602 //ChildDeviceData->IrpAddedToRingAtLastInterrupt = ChildDeviceData->IrpAddedToRing;
603 RetVal = WdfDpcEnqueue(ChildDeviceData->Dpc);
605 //KdPrint((__DRIVER_NAME " <-- XenVbd_Interrupt (RetVal = %d)\n", RetVal));
607 return STATUS_SUCCESS;
608 }
610 static VOID
611 XenVbd_BackEndStateHandler(char *Path, PVOID Data)
612 {
613 PXENVBD_CHILD_DEVICE_DATA DeviceData;
614 char TmpPath[128];
615 char *Value;
616 int NewState;
617 PMDL Mdl;
618 grant_ref_t ref;
619 blkif_sring_t *SharedRing;
620 ULONG PFN;
621 XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION Description;
622 NTSTATUS status;
624 DeviceData = (PXENVBD_CHILD_DEVICE_DATA)Data;
626 XenBusInterface.Read(XBT_NIL, Path, &Value);
628 NewState = atoi(Value);
629 switch (NewState)
630 {
631 case XenbusStateUnknown:
632 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
633 break;
635 case XenbusStateInitialising:
636 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
637 break;
639 case XenbusStateInitWait:
640 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
642 DeviceData->EventChannel = EvtChnInterface.AllocUnbound(0);
643 EvtChnInterface.Bind(DeviceData->EventChannel, XenVbd_Interrupt, DeviceData);
644 Mdl = AllocatePage();
645 PFN = *MmGetMdlPfnArray(Mdl);
646 SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
647 SHARED_RING_INIT(SharedRing);
648 FRONT_RING_INIT(&DeviceData->Ring, SharedRing, PAGE_SIZE);
649 ref = GntTblInterface.GrantAccess(0, PFN, FALSE);
651 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
652 RtlStringCbCatA(TmpPath, 128, "/ring-ref");
653 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", ref);
655 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
656 RtlStringCbCatA(TmpPath, 128, "/event-channel");
657 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", DeviceData->EventChannel);
659 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
660 RtlStringCbCatA(TmpPath, 128, "/state");
661 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
663 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
664 break;
666 case XenbusStateInitialised:
667 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
668 // create the device
669 break;
671 case XenbusStateConnected:
672 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
674 WDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER_INIT(&Description.Header, sizeof(Description));
676 Description.DeviceData = DeviceData;
678 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
679 RtlStringCbCatA(TmpPath, 128, "/type"); // should probably check that this is 'phy'
680 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
682 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
683 RtlStringCbCatA(TmpPath, 128, "/mode"); // should store this...
684 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
686 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
687 RtlStringCbCatA(TmpPath, 128, "/sector-size");
688 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
689 // should complain if Value == NULL
690 DeviceData->BytesPerSector = atoi(Value);
692 KdPrint((__DRIVER_NAME " BytesPerSector = %d\n", DeviceData->BytesPerSector));
694 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
695 RtlStringCbCatA(TmpPath, 128, "/sectors");
696 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
697 // should complain if Value == NULL
698 DeviceData->TotalSectors = (ULONGLONG)atol(Value);
700 KdPrint((__DRIVER_NAME " TotalSectors = %d\n", DeviceData->TotalSectors));
702 // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
703 DeviceData->Geometry.MediaType = FixedMedia;
704 DeviceData->Geometry.BytesPerSector = DeviceData->BytesPerSector;
705 DeviceData->Geometry.SectorsPerTrack = 63;
706 DeviceData->Geometry.TracksPerCylinder = 255;
707 DeviceData->Geometry.Cylinders.QuadPart = DeviceData->TotalSectors / DeviceData->Geometry.SectorsPerTrack / DeviceData->Geometry.TracksPerCylinder;
708 KdPrint((__DRIVER_NAME " Geometry C/H/S = %d/%d/%d\n", DeviceData->Geometry.Cylinders.LowPart, DeviceData->Geometry.TracksPerCylinder, DeviceData->Geometry.SectorsPerTrack));
710 status = WdfChildListAddOrUpdateChildDescriptionAsPresent(WdfFdoGetDefaultChildList(GlobalDevice), &Description.Header, NULL);
711 if (!NT_SUCCESS(status))
712 {
713 KdPrint((__DRIVER_NAME " WdfChildListAddOrUpdateChildDescriptionAsPresent failed %08x\n", status));
714 }
716 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
717 RtlStringCbCatA(TmpPath, 128, "/state");
718 XenBusInterface.Printf(XBT_NIL, TmpPath, "%d", XenbusStateConnected);
720 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
721 InterlockedIncrement(&EnumeratedDevices);
722 KdPrint((__DRIVER_NAME " Added a disk, notifying\n"));
724 KeSetEvent(&WaitDevicesEvent, 1, FALSE);
726 break;
728 case XenbusStateClosing:
729 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
730 break;
732 case XenbusStateClosed:
733 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
734 break;
736 default:
737 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
738 break;
739 }
740 }
742 static VOID
743 XenVbd_HotPlugHandler(char *Path, PVOID Data)
744 {
745 PXENVBD_CHILD_DEVICE_DATA DeviceData;
746 char **Bits;
747 int Count;
748 char TmpPath[128];
749 char *Value;
751 UNREFERENCED_PARAMETER(Data);
753 //KdPrint((__DRIVER_NAME " --> HotPlugHandler\n"));
755 //KdPrint((__DRIVER_NAME " Path = %s\n", Path));
757 Bits = SplitString(Path, '/', 4, &Count);
758 switch (Count)
759 {
760 case 0:
761 case 1:
762 case 2:
763 break; // should never happen
764 case 3:
765 break;
766 case 4:
768 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
769 break;
770 for (DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceListHead.Flink; DeviceData != (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead; DeviceData = (PXENVBD_CHILD_DEVICE_DATA)DeviceData->Entry.Flink)
771 {
772 if (strncmp(DeviceData->Path, Path, strlen(DeviceData->Path)) == 0 && Path[strlen(DeviceData->Path)] == '/')
773 {
774 break;
775 }
776 }
777 if (DeviceData == (PXENVBD_CHILD_DEVICE_DATA)&DeviceListHead)
778 {
779 DeviceData = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENVBD_CHILD_DEVICE_DATA), XENVBD_POOL_TAG);
780 memset(DeviceData, 0, sizeof(XENVBD_CHILD_DEVICE_DATA));
782 //KdPrint((__DRIVER_NAME " Allocated ChildDeviceData = %08x\n", DeviceData));
784 InsertTailList(&DeviceListHead, &DeviceData->Entry);
785 RtlStringCbCopyA(DeviceData->Path, 128, Bits[0]);
786 RtlStringCbCatA(DeviceData->Path, 128, "/");
787 RtlStringCbCatA(DeviceData->Path, 128, Bits[1]);
788 RtlStringCbCatA(DeviceData->Path, 128, "/");
789 RtlStringCbCatA(DeviceData->Path, 128, Bits[2]);
791 DeviceData->DeviceIndex = atoi(Bits[2]);
793 RtlStringCbCopyA(TmpPath, 128, DeviceData->Path);
794 RtlStringCbCatA(TmpPath, 128, "/backend");
795 XenBusInterface.Read(XBT_NIL, TmpPath, &Value);
796 if (Value == NULL)
797 {
798 KdPrint((__DRIVER_NAME " Read Failed\n"));
799 }
800 else
801 {
802 RtlStringCbCopyA(DeviceData->BackendPath, 128, Value);
803 }
804 RtlStringCbCopyA(TmpPath, 128, DeviceData->BackendPath);
805 RtlStringCbCatA(TmpPath, 128, "/state");
806 XenBusInterface.AddWatch(XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, DeviceData);
807 }
808 break;
809 }
811 FreeSplitString(Bits, Count);
813 //KdPrint((__DRIVER_NAME " <-- HotPlugHandler\n"));
815 return;
816 }
818 static NTSTATUS
819 XenVbd_ChildListCreateDevice(WDFCHILDLIST ChildList, PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription, PWDFDEVICE_INIT ChildInit)
820 {
821 NTSTATUS status;
822 WDFDEVICE ChildDevice;
823 PXENVBD_DEVICE_IDENTIFICATION_DESCRIPTION XenVbdIdentificationDesc;
824 DECLARE_UNICODE_STRING_SIZE(buffer, 50);
825 WDF_OBJECT_ATTRIBUTES PdoAttributes;
826 DECLARE_CONST_UNICODE_STRING(DeviceLocation, L"Xen Bus");
827 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
828 WDF_IO_QUEUE_CONFIG IoQueueConfig;
829 unsigned int i;
830 WDF_DPC_CONFIG DpcConfig;
831 WDF_OBJECT_ATTRIBUTES DpcObjectAttributes;
833 UNREFERENCED_PARAMETER(ChildList);
835 //KdPrint((__DRIVER_NAME " --> ChildListCreateDevice\n"));
837 XenVbdIdentificationDesc = CONTAINING_RECORD(IdentificationDescription, XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION, Header);
839 ChildDeviceData = XenVbdIdentificationDesc->DeviceData;
841 WdfDeviceInitSetDeviceType(ChildInit, FILE_DEVICE_MASS_STORAGE);
843 // Capabilities = CM_DEVCAP_UNIQUEID
844 // Devnode Flages = DN_NEED_RESTART??? DN_DISABLEABLE???
846 status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk&Ven_James&Prod_James&Rev_1.00\0");
847 status = WdfPdoInitAssignDeviceID(ChildInit, &buffer);
849 status = RtlUnicodeStringPrintf(&buffer, L"%02d", ChildDeviceData->DeviceIndex);
850 status = WdfPdoInitAssignInstanceID(ChildInit, &buffer);
852 //status = RtlUnicodeStringPrintf(&buffer, L"XEN\\Disk\0");
853 //status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
854 //status = RtlUnicodeStringPrintf(&buffer, L"XEN\\RAW\0");
855 //status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
856 status = RtlUnicodeStringPrintf(&buffer, L"GenDisk\0");
857 status = WdfPdoInitAddCompatibleID(ChildInit, &buffer);
858 status = WdfPdoInitAddHardwareID(ChildInit, &buffer);
860 status = RtlUnicodeStringPrintf(&buffer, L"Xen PV Disk (%d)", ChildDeviceData->DeviceIndex);
861 status = WdfPdoInitAddDeviceText(ChildInit, &buffer, &DeviceLocation, 0x409);
863 WdfPdoInitSetDefaultLocale(ChildInit, 0x409);
865 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&PdoAttributes, PXENVBD_CHILD_DEVICE_DATA);
867 WdfDeviceInitAssignWdmIrpPreprocessCallback(ChildInit, XenVbd_Child_PreprocessWdmIrpSCSI, IRP_MJ_SCSI, NULL, 0);
869 WdfDeviceInitSetIoType(ChildInit, WdfDeviceIoDirect);
871 status = WdfDeviceCreate(&ChildInit, &PdoAttributes, &ChildDevice);
872 if (!NT_SUCCESS(status))
873 {
874 KdPrint((__DRIVER_NAME " WdfDeviceCreate status = %08X\n", status));
875 }
877 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFilePaging, TRUE);
878 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileHibernation, TRUE);
879 WdfDeviceSetSpecialFileSupport(ChildDevice, WdfSpecialFileDump, TRUE);
881 WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&IoQueueConfig, WdfIoQueueDispatchSequential);
882 IoQueueConfig.EvtIoDefault = XenVbd_Child_IoDefault;
883 IoQueueConfig.EvtIoDeviceControl = XenVbd_Child_IoDeviceControl;
885 *GetChildDeviceData(ChildDevice) = ChildDeviceData;
887 //ChildDeviceData->IrpAddedToList = 0;
888 //ChildDeviceData->IrpRemovedFromList = 0;
889 //ChildDeviceData->IrpAddedToRing = 0;
890 //ChildDeviceData->IrpAddedToRingAtLastNotify = 0;
891 //ChildDeviceData->IrpAddedToRingAtLastInterrupt = 0;
892 //ChildDeviceData->IrpAddedToRingAtLastDpc = 0;
893 //ChildDeviceData->IrpRemovedFromRing = 0;
894 //ChildDeviceData->IrpCompleted = 0;
896 status = WdfIoQueueCreate(ChildDevice, &IoQueueConfig, WDF_NO_OBJECT_ATTRIBUTES, &ChildDeviceData->IoDefaultQueue);
897 if(!NT_SUCCESS(status))
898 {
899 KdPrint((__DRIVER_NAME "WdfIoQueueCreate failed with status 0x%08x\n", status));
900 return status;
901 }
903 ChildDeviceData->Device = ChildDevice;
905 KeInitializeSpinLock(&ChildDeviceData->Lock);
906 KeInitializeSpinLock(&ChildDeviceData->IrpListLock);
907 InitializeListHead(&ChildDeviceData->IrpListHead);
909 ChildDeviceData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * BLK_RING_SIZE, XENVBD_POOL_TAG);
910 memset(ChildDeviceData->shadow, 0, sizeof(blkif_shadow_t) * BLK_RING_SIZE);
911 //KdPrint((__DRIVER_NAME " Allocated shadow = %08x\n", ChildDeviceData->shadow));
912 for (i = 0; i < BLK_RING_SIZE; i++)
913 ChildDeviceData->shadow[i].req.id = i + 1;
914 ChildDeviceData->shadow_free = 0;
915 ChildDeviceData->shadow[BLK_RING_SIZE - 1].req.id = 0x0fffffff;
917 WDF_DPC_CONFIG_INIT(&DpcConfig, XenVbd_DpcThreadProc);
918 WDF_OBJECT_ATTRIBUTES_INIT(&DpcObjectAttributes);
919 DpcObjectAttributes.ParentObject = ChildDevice;
920 WdfDpcCreate(&DpcConfig, &DpcObjectAttributes, &ChildDeviceData->Dpc);
922 //KdPrint((__DRIVER_NAME " <-- ChildListCreateDevice\n"));
924 return status;
925 }
928 // Call with device lock held
929 static VOID
930 XenVbd_PutIrpOnRing(WDFDEVICE Device, PIRP Irp)
931 {
932 char *DataBuffer;
933 PSCSI_REQUEST_BLOCK Srb;
934 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
935 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
936 blkif_request_t *req;
937 int notify;
938 int i;
939 int j;
940 int BlockCount;
941 int sect_offset;
943 //KdPrint((__DRIVER_NAME " --> PutIrpOnRing\n"));
945 ChildDeviceData = *GetChildDeviceData(Device);
947 if (RING_FULL(&ChildDeviceData->Ring))
948 {
949 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
950 }
952 req = RING_GET_REQUEST(&ChildDeviceData->Ring, ChildDeviceData->Ring.req_prod_pvt);
954 //KdPrint((__DRIVER_NAME " req = %08x\n", req));
956 Srb = irpSp->Parameters.Scsi.Srb;
958 req->sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
959 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
961 req->id = GET_ID_FROM_FREELIST(ChildDeviceData);
963 if (req->id == 0x0fffffff)
964 {
965 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutIrpOnRing\n"));
966 }
968 //KdPrint((__DRIVER_NAME " id = %d\n", req->id));
970 req->handle = 0;
971 req->operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
972 ChildDeviceData->shadow[req->id].Irp = Irp;
974 if ((MmGetMdlByteOffset(Irp->MdlAddress) & 0x1ff) == 0) // 0x1ff shouldn't be hardcoded...
975 {
976 // fast path - zero copy
977 ChildDeviceData->shadow[req->id].Mdl = Irp->MdlAddress;
978 ChildDeviceData->shadow[req->id].Buf = NULL; // we don't need the virtual address
979 }
980 else
981 {
982 // slow path - copy to bounce buffer
983 ChildDeviceData->shadow[req->id].Mdl = AllocatePages((BlockCount * ChildDeviceData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE);
984 ChildDeviceData->shadow[req->id].Buf = MmGetMdlVirtualAddress(ChildDeviceData->shadow[req->id].Mdl);
985 if (ChildDeviceData->shadow[req->id].Buf == NULL)
986 {
987 KdPrint((__DRIVER_NAME " MmGetMdlVirtualAddress returned NULL in PutIrpOnRing\n"));
988 }
989 }
991 sect_offset = MmGetMdlByteOffset(ChildDeviceData->shadow[req->id].Mdl) >> 9;
992 for (i = 0, req->nr_segments = 0; i < BlockCount; req->nr_segments++)
993 {
994 req->seg[req->nr_segments].gref = GntTblInterface.GrantAccess(0, MmGetMdlPfnArray(ChildDeviceData->shadow[req->id].Mdl)[req->nr_segments], FALSE);
995 req->seg[req->nr_segments].first_sect = sect_offset;
996 for (j = sect_offset; i < BlockCount && j < PAGE_SIZE / ChildDeviceData->BytesPerSector; j++, i++)
997 req->seg[req->nr_segments].last_sect = (uint8_t)j;
998 sect_offset = 0;
999 }
1000 if (Srb->Cdb[0] == SCSIOP_WRITE && ChildDeviceData->shadow[req->id].Buf != NULL)
1002 DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1003 if (DataBuffer == NULL)
1004 KdPrint((__DRIVER_NAME " MmGetSystemAddressForMdlSafe failed in PutIrpOnRing\n"));
1005 memcpy(ChildDeviceData->shadow[req->id].Buf, DataBuffer, BlockCount * ChildDeviceData->BytesPerSector);
1007 ChildDeviceData->shadow[req->id].req = *req;
1009 ChildDeviceData->Ring.req_prod_pvt++;
1010 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&ChildDeviceData->Ring, notify);
1011 if (notify)
1013 EvtChnInterface.Notify(ChildDeviceData->EventChannel);
1014 //KdPrint((__DRIVER_NAME " Notified\n"));
1015 //ChildDeviceData->IrpAddedToRing++;
1016 //ChildDeviceData->IrpAddedToRingAtLastNotify = ChildDeviceData->IrpAddedToRing;
1018 else
1020 //ChildDeviceData->IrpAddedToRing++;
1022 //KdPrint((__DRIVER_NAME " <-- PutIrpOnRing\n"));
1025 static NTSTATUS
1026 XenVbd_Child_PreprocessWdmIrpSCSI(WDFDEVICE Device, PIRP Irp)
1028 char *DataBuffer;
1029 NTSTATUS status = STATUS_SUCCESS;
1030 PSCSI_REQUEST_BLOCK Srb;
1031 PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
1032 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1033 KIRQL KIrql;
1034 XenVbd_ListEntry *ListEntry;
1036 //KdPrint((__DRIVER_NAME " --> WdmIrpPreprocessSCSI\n"));
1038 ChildDeviceData = *GetChildDeviceData(Device);
1040 Srb = irpSp->Parameters.Scsi.Srb;
1042 switch (Srb->Function)
1044 case SRB_FUNCTION_EXECUTE_SCSI:
1045 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
1046 switch(Srb->Cdb[0]) {
1047 case SCSIOP_TEST_UNIT_READY:
1048 //KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1049 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1050 Srb->ScsiStatus = 0;
1051 status = STATUS_SUCCESS;
1052 Irp->IoStatus.Status = status;
1053 Irp->IoStatus.Information = 0;
1054 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1055 break;
1056 case SCSIOP_INQUIRY:
1057 //KdPrint((__DRIVER_NAME " Command = INQUIRY (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1058 if ((Srb->Cdb[1] & 1) == 0)
1060 memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
1061 DataBuffer = Srb->DataBuffer;
1062 DataBuffer[0] = 0x00; // disk
1063 DataBuffer[1] = 0x00; // not removable
1064 memcpy(DataBuffer + 8, "James", 5); // vendor id
1065 memcpy(DataBuffer + 16, "XenVBD", 6); // product id
1066 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1068 else
1070 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1072 Srb->ScsiStatus = 0;
1073 status = STATUS_SUCCESS;
1074 Irp->IoStatus.Status = status;
1075 Irp->IoStatus.Information = 0;
1076 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1077 break;
1078 case SCSIOP_READ_CAPACITY:
1079 DataBuffer = Srb->DataBuffer;
1080 DataBuffer[0] = (unsigned char)(ChildDeviceData->TotalSectors >> 24) & 0xff;
1081 DataBuffer[1] = (unsigned char)(ChildDeviceData->TotalSectors >> 16) & 0xff;
1082 DataBuffer[2] = (unsigned char)(ChildDeviceData->TotalSectors >> 8) & 0xff;
1083 DataBuffer[3] = (unsigned char)(ChildDeviceData->TotalSectors >> 0) & 0xff;
1084 DataBuffer[4] = 0x00;
1085 DataBuffer[5] = 0x00;
1086 DataBuffer[6] = 0x02;
1087 DataBuffer[7] = 0x00;
1088 Srb->ScsiStatus = 0;
1089 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1090 status = STATUS_SUCCESS;
1091 Irp->IoStatus.Status = status;
1092 Irp->IoStatus.Information = 0;
1093 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1094 break;
1095 case SCSIOP_MODE_SENSE:
1096 //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));
1097 switch(Srb->Cdb[2] & 0x3F)
1099 default:
1100 memset(Srb->DataBuffer, 0, Srb->DataTransferLength);
1101 Srb->ScsiStatus = 0;
1102 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1103 status = STATUS_SUCCESS;
1104 Irp->IoStatus.Status = status;
1105 Irp->IoStatus.Information = Srb->DataTransferLength;
1106 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1108 break;
1109 case SCSIOP_READ:
1110 case SCSIOP_WRITE:
1111 IoMarkIrpPending(Irp);
1113 //KdPrint((__DRIVER_NAME " Irp Acquiring Lock\n"));
1114 KeAcquireSpinLock(&ChildDeviceData->Lock, &KIrql);
1115 //KdPrint((__DRIVER_NAME "A Got It\n"));
1117 if (RING_FULL(&ChildDeviceData->Ring))
1119 //KdPrint((__DRIVER_NAME "A Inserting into list\n"));
1120 ListEntry = (XenVbd_ListEntry *)ExAllocatePoolWithTag(NonPagedPool, sizeof(XenVbd_ListEntry), XENVBD_POOL_TAG);
1121 //KdPrint((__DRIVER_NAME " Allocate ListEntry = %08x\n", ListEntry));
1122 if (ListEntry == NULL)
1124 KdPrint((__DRIVER_NAME " CANNOT ALLOCATE MEMORY FOR ListEntry!!!\n"));
1126 ListEntry->Irp = Irp;
1127 InsertTailList(&ChildDeviceData->IrpListHead, &ListEntry->Entry);
1128 //ChildDeviceData->IrpAddedToList++;
1130 else
1132 XenVbd_PutIrpOnRing(Device, Irp);
1133 //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));
1135 KeReleaseSpinLock(&ChildDeviceData->Lock, KIrql);
1136 status = STATUS_PENDING;
1137 break;
1138 default:
1139 status = STATUS_NOT_IMPLEMENTED;
1140 Irp->IoStatus.Status = status;
1141 Irp->IoStatus.Information = 0;
1142 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1143 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1144 break;
1146 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1147 break;
1148 case SRB_FUNCTION_CLAIM_DEVICE:
1149 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
1150 ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
1151 Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
1152 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1153 status = STATUS_SUCCESS;
1154 Irp->IoStatus.Status = status;
1155 Irp->IoStatus.Information = 0;
1156 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1157 break;
1158 case SRB_FUNCTION_IO_CONTROL:
1159 //KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1160 //status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1161 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1162 status = STATUS_NOT_IMPLEMENTED;
1163 //Irp->IoStatus.Status = status;
1164 //Irp->IoStatus.Information = 0;
1165 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1166 break;
1167 case SRB_FUNCTION_FLUSH:
1168 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1169 status = STATUS_SUCCESS;
1170 Irp->IoStatus.Status = status;
1171 Irp->IoStatus.Information = 0;
1172 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1173 break;
1174 default:
1175 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1176 status = WdfDeviceWdmDispatchPreprocessedIrp(Device, Irp);
1177 break;
1180 //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));
1181 //KdPrint((__DRIVER_NAME " <-- WdmIrpPreprocessSCSI\n"));
1183 return status;
1186 static VOID
1187 XenVbd_Child_IoDefault(WDFQUEUE Queue, WDFREQUEST Request)
1189 UNREFERENCED_PARAMETER(Queue);
1191 KdPrint((__DRIVER_NAME " --> EvtDeviceIoDefault\n"));
1193 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1195 KdPrint((__DRIVER_NAME " <-- EvtDeviceIoDefault\n"));
1198 static VOID
1199 XenVbd_Child_IoDeviceControl(WDFQUEUE Queue, WDFREQUEST Request, size_t OutputBufferLength, size_t InputBufferLength, ULONG IoControlCode)
1201 WDFDEVICE Device;
1202 PXENVBD_CHILD_DEVICE_DATA ChildDeviceData;
1203 PIRP Irp;
1204 PSTORAGE_PROPERTY_QUERY Spq;
1205 PSTORAGE_ADAPTER_DESCRIPTOR Sad;
1206 PSTORAGE_DEVICE_DESCRIPTOR Sdd;
1207 PSTORAGE_DEVICE_ID_DESCRIPTOR Sdid;
1208 PSTORAGE_IDENTIFIER Si;
1209 PSCSI_ADDRESS Sa;
1211 UNREFERENCED_PARAMETER(Queue);
1212 //UNREFERENCED_PARAMETER(Request);
1213 UNREFERENCED_PARAMETER(OutputBufferLength);
1214 UNREFERENCED_PARAMETER(InputBufferLength);
1216 Device = WdfIoQueueGetDevice(Queue);
1218 ChildDeviceData = *GetChildDeviceData(Device);
1220 //KdPrint((__DRIVER_NAME " --> IoDeviceControl\n"));
1221 //KdPrint((__DRIVER_NAME " InputBufferLength = %d\n", InputBufferLength));
1222 //KdPrint((__DRIVER_NAME " OutputBufferLength = %d\n", OutputBufferLength));
1224 Irp = WdfRequestWdmGetIrp(Request);
1226 switch (IoControlCode)
1228 case IOCTL_STORAGE_QUERY_PROPERTY:
1229 //KdPrint((__DRIVER_NAME " IOCTL_STORAGE_QUERY_PROPERTY\n"));
1230 Spq = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
1231 if (Spq->PropertyId == StorageAdapterProperty && Spq->QueryType == PropertyStandardQuery)
1233 //KdPrint((__DRIVER_NAME " PropertyId = StorageAdapterProperty, QueryType = PropertyStandardQuery\n"));
1234 if (OutputBufferLength >= 8)
1236 Sad = (PSTORAGE_ADAPTER_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1237 Sad->Version = 1;
1238 Sad->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR);
1239 if (OutputBufferLength >= sizeof(STORAGE_ADAPTER_DESCRIPTOR))
1241 Sad->MaximumTransferLength = 45056;
1242 Sad->MaximumPhysicalPages = 11;
1243 Sad->AlignmentMask = 0;
1244 Sad->AdapterUsesPio = FALSE;
1245 Sad->AdapterScansDown = FALSE;
1246 Sad->CommandQueueing = FALSE;
1247 Sad->AcceleratedTransfer = FALSE;
1248 Sad->BusType = BusTypeScsi;
1249 Sad->BusMajorVersion = 0;
1250 Sad->BusMinorVersion = 0;
1253 WdfRequestComplete(Request, STATUS_SUCCESS);
1255 else if (Spq->PropertyId == StorageDeviceProperty && Spq->QueryType == PropertyStandardQuery)
1257 //KdPrint((__DRIVER_NAME " PropertyId = StorageDeviceProperty, QueryType = PropertyStandardQuery\n"));
1258 if (OutputBufferLength >= 8)
1260 Sdd = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1261 Sdd->Version = 1;
1262 Sdd->Size = sizeof(STORAGE_DEVICE_DESCRIPTOR) + 31 - 1;
1263 // 0 0 1 2 3
1264 // 0 7 5 4 1
1265 //"VENDOR\0PRODUCT\0Revision\0Serial\0"
1266 if (OutputBufferLength >= sizeof(STORAGE_DEVICE_DESCRIPTOR) - 1 + 31)
1268 Sdd->DeviceType = 0x00;
1269 Sdd->DeviceTypeModifier = 0x00;
1270 Sdd->RemovableMedia = FALSE;
1271 Sdd->CommandQueueing = FALSE;
1272 Sdd->VendorIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - 1 + 0;
1273 Sdd->ProductIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - 1 + 7;
1274 Sdd->ProductRevisionOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - 1 + 15;
1275 Sdd->SerialNumberOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - 1 + 24;
1276 Sdd->BusType = BusTypeScsi;
1277 Sdd->RawPropertiesLength = 31;
1278 memcpy(Sdd->RawDeviceProperties, "VENDOR\0PRODUCT\0Revision\0Serial\0", 31);
1281 WdfRequestComplete(Request, STATUS_SUCCESS);
1283 else if (Spq->PropertyId == StorageDeviceIdProperty && Spq->QueryType == PropertyStandardQuery)
1285 if (OutputBufferLength >= 8)
1287 Sdid = (PSTORAGE_DEVICE_ID_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
1288 Sdid->Version = 1;
1289 Sdid->Size = sizeof(STORAGE_DEVICE_ID_DESCRIPTOR) - 1 + sizeof(STORAGE_IDENTIFIER) - 1 + 5;
1290 if (OutputBufferLength >= Sdid->Size)
1292 Sdid->NumberOfIdentifiers = 1;
1293 Si = (PSTORAGE_IDENTIFIER)Sdid->Identifiers;
1294 Si->CodeSet = 0;
1295 Si->Type = StorageIdTypeScsiNameString;
1296 Si->IdentifierSize = 5;
1297 Si->NextOffset = 0;
1298 Si->Association = StorageIdAssocDevice;
1299 Si->Identifier[0] = 'J';
1300 Si->Identifier[0] = 'a';
1301 Si->Identifier[0] = 'm';
1302 Si->Identifier[0] = 'e';
1303 Si->Identifier[0] = 's';
1306 WdfRequestComplete(Request, STATUS_SUCCESS);
1308 else
1310 switch (Spq->PropertyId)
1312 case StorageDeviceProperty:
1313 KdPrint((__DRIVER_NAME " StorageDeviceProperty\n"));
1314 break;
1315 case StorageAccessAlignmentProperty:
1316 KdPrint((__DRIVER_NAME " StorageAccessAlignmentProperty\n"));
1317 break;
1318 case StorageAdapterProperty:
1319 KdPrint((__DRIVER_NAME " StorageAdapterProperty\n"));
1320 break;
1321 case StorageDeviceIdProperty:
1322 KdPrint((__DRIVER_NAME " StorageDeviceIdProperty\n"));
1323 break;
1324 case StorageDeviceUniqueIdProperty:
1325 KdPrint((__DRIVER_NAME " StorageDeviceUniqueIdProperty\n"));
1326 break;
1327 case StorageDeviceWriteCacheProperty:
1328 KdPrint((__DRIVER_NAME " StorageDeviceWriteCacheProperty\n"));
1329 break;
1330 default:
1331 KdPrint((__DRIVER_NAME " Unknown Property %08x\n", Spq->PropertyId));
1332 break;
1334 switch (Spq->QueryType)
1336 case PropertyStandardQuery:
1337 KdPrint((__DRIVER_NAME " PropertyStandardQuery\n"));
1338 break;
1339 /*
1340 case PropertyIncludeSwIds:
1341 KdPrint((__DRIVER_NAME " PropertyIncludeSwIds\n"));
1342 break;
1343 */
1344 case PropertyExistsQuery:
1345 KdPrint((__DRIVER_NAME " PropertyExistsQuery\n"));
1346 break;
1347 default:
1348 KdPrint((__DRIVER_NAME " Unknown Query %08x\n", Spq->QueryType));
1349 break;
1351 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1353 break;
1354 // http://www.osronline.com/article.cfm?article=229
1355 // 0x00560030 device = 0x56, Function = 0x00c =
1356 case IOCTL_DISK_GET_DRIVE_GEOMETRY:
1357 KdPrint((__DRIVER_NAME " IOCTL_DISK_GET_DRIVE_GEOMETRY\n"));
1358 memcpy(Irp->AssociatedIrp.SystemBuffer, &ChildDeviceData->Geometry, sizeof(DISK_GEOMETRY));
1359 WdfRequestComplete(Request, STATUS_SUCCESS);
1360 break;
1361 case IOCTL_SCSI_GET_ADDRESS:
1362 //KdPrint((__DRIVER_NAME " IOCTL_SCSI_GET_ADDRESS\n"));
1363 Sa = (PSCSI_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
1364 Sa->Length = sizeof(SCSI_ADDRESS);
1365 Sa->PortNumber = 0;
1366 Sa->PathId = 0;
1367 Sa->TargetId = 0;
1368 Sa->Lun = 0;
1369 WdfRequestComplete(Request, STATUS_SUCCESS);
1370 break;
1371 case FT_BALANCED_READ_MODE: // just pretend we know what this is...
1372 WdfRequestComplete(Request, STATUS_SUCCESS);
1373 break;
1374 default:
1375 KdPrint((__DRIVER_NAME " Not Implemented IoControlCode=%08X\n", IoControlCode));
1376 WdfRequestComplete(Request, STATUS_NOT_IMPLEMENTED);
1377 break;
1380 //KdPrint((__DRIVER_NAME " <-- IoDeviceControl\n"));