win-pvdrivers

view xenvbd/xenvbd.c @ 73:f74723639713

Corrected merge of dpc patches.
Releasing 0.5.0.0
author James Harper <james.harper@bendigoit.com.au>
date Thu Dec 20 13:07:44 2007 +1100 (2007-12-20)
parents 21502e79acc3
children 06b4321b7068
line source
1 #include "xenvbd.h"
2 #include <io/blkif.h>
3 #include <scsi.h>
4 #include <ntddscsi.h>
5 #include <ntdddisk.h>
6 #include <stdlib.h>
7 #include <xen_public.h>
8 #include <io/xenbus.h>
10 #define wmb() KeMemoryBarrier()
11 #define mb() KeMemoryBarrier()
13 #define BUF_PAGES_PER_SRB 11
15 DRIVER_INITIALIZE DriverEntry;
17 static ULONG
18 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again);
19 static BOOLEAN
20 XenVbd_HwScsiInitialize(PVOID DeviceExtension);
21 static BOOLEAN
22 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb);
23 static BOOLEAN
24 XenVbd_HwScsiInterrupt(PVOID DeviceExtension);
25 static BOOLEAN
26 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId);
27 static BOOLEAN
28 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState);
29 static SCSI_ADAPTER_CONTROL_STATUS
30 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters);
32 #ifdef ALLOC_PRAGMA
33 #pragma alloc_text (INIT, DriverEntry)
34 #endif
36 static BOOLEAN AutoEnumerate;
38 NTSTATUS
39 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
40 {
41 ULONG Status;
42 HW_INITIALIZATION_DATA HwInitializationData;
44 KdPrint((__DRIVER_NAME " --> DriverEntry\n"));
46 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
48 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
49 HwInitializationData.AdapterInterfaceType = Internal; //PNPBus;
50 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
51 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
52 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
53 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
54 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
55 HwInitializationData.HwDmaStarted = NULL;
56 HwInitializationData.HwAdapterState = NULL;
57 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
58 HwInitializationData.SpecificLuExtensionSize = 0;
59 HwInitializationData.SrbExtensionSize = 0;
60 HwInitializationData.NumberOfAccessRanges = 1;
62 //HwInitializationData.MapBuffers = FALSE;
63 HwInitializationData.MapBuffers = TRUE;
65 HwInitializationData.NeedPhysicalAddresses = FALSE;
66 // HwInitializationData.NeedPhysicalAddresses = TRUE;
68 HwInitializationData.TaggedQueuing = TRUE; //FALSE;
69 HwInitializationData.AutoRequestSense = FALSE;
70 HwInitializationData.MultipleRequestPerLu = FALSE;
71 HwInitializationData.ReceiveEvent = FALSE; // check this
72 HwInitializationData.VendorIdLength = 0;
73 HwInitializationData.VendorId = NULL;
74 HwInitializationData.DeviceIdLength = 0;
75 HwInitializationData.DeviceId = NULL;
76 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
78 Status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
80 if(!NT_SUCCESS(Status))
81 {
82 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", Status));
83 }
85 KdPrint((__DRIVER_NAME " <-- DriverEntry\n"));
87 return Status;
88 }
90 static PMDL
91 AllocatePages(int Pages)
92 {
93 PMDL Mdl;
94 PVOID Buf;
96 //KdPrint((__DRIVER_NAME " --- AllocatePages IRQL = %d\n", KeGetCurrentIrql()));
97 Buf = ExAllocatePoolWithTag(NonPagedPool, Pages * PAGE_SIZE, XENVBD_POOL_TAG);
98 if (Buf == NULL)
99 {
100 KdPrint((__DRIVER_NAME " AllocatePages Failed at ExAllocatePoolWithTag\n"));
101 }
102 Mdl = IoAllocateMdl(Buf, Pages * PAGE_SIZE, FALSE, FALSE, NULL);
103 if (Mdl == NULL)
104 {
105 KdPrint((__DRIVER_NAME " AllocatePages Failed at IoAllocateMdl\n"));
106 }
107 MmBuildMdlForNonPagedPool(Mdl);
109 return Mdl;
110 }
112 static PMDL
113 AllocatePage()
114 {
115 return AllocatePages(1);
116 }
118 static VOID
119 FreePages(PMDL Mdl)
120 {
121 PVOID Buf = MmGetMdlVirtualAddress(Mdl);
122 //KdPrint((__DRIVER_NAME " --- FreePages IRQL = %d\n", KeGetCurrentIrql()));
123 //KdPrint((__DRIVER_NAME " FreePages Failed at IoAllocateMdl\n"));
124 //KdPrint((__DRIVER_NAME " FreePages Buf = %08x\n", Buf));
125 IoFreeMdl(Mdl);
126 ExFreePoolWithTag(Buf, XENVBD_POOL_TAG);
127 }
129 static ULONG
130 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
131 {
132 ULONG Status = SP_RETURN_FOUND;
133 ULONG i;
134 PACCESS_RANGE AccessRange;
135 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
137 KeInitializeSpinLock(&DeviceData->Lock);
138 KdPrint((__DRIVER_NAME " --> HwScsiFindAdapter\n"));
139 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
141 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
142 KdPrint((__DRIVER_NAME " BusInterruptVector = %d\n", ConfigInfo->BusInterruptVector));
144 KdPrint((__DRIVER_NAME " AccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
146 for (i = 0; i < ConfigInfo->NumberOfAccessRanges; i++)
147 {
148 AccessRange = &(*(ConfigInfo->AccessRanges))[i];
149 KdPrint((__DRIVER_NAME " AccessRange %2d: RangeStart = %08x, RangeLength = %08x, RangeInMemory = %d\n", i, AccessRange->RangeStart.LowPart, AccessRange->RangeLength, AccessRange->RangeInMemory));
150 switch (i)
151 {
152 case 0:
153 DeviceData->XenDeviceData = (PXENPCI_XEN_DEVICE_DATA)AccessRange->RangeStart.QuadPart;
154 KdPrint((__DRIVER_NAME " Mapped to virtual address %08x\n", DeviceData->XenDeviceData));
155 KdPrint((__DRIVER_NAME " Magic = %08x\n", DeviceData->XenDeviceData->Magic));
156 if (DeviceData->XenDeviceData->Magic == XEN_DATA_MAGIC)
157 {
158 }
159 break;
160 default:
161 break;
162 }
163 }
165 ConfigInfo->NumberOfBuses = SCSI_BUSES;
166 ConfigInfo->MaximumTransferLength = BUF_PAGES_PER_SRB * PAGE_SIZE;
167 ConfigInfo->NumberOfPhysicalBreaks = BUF_PAGES_PER_SRB - 1; //11 - 1;
168 ConfigInfo->ScatterGather = TRUE;
169 ConfigInfo->Master = FALSE;
170 ConfigInfo->AlignmentMask = 0;
171 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
172 ConfigInfo->MaximumNumberOfTargets = SCSI_TARGETS_PER_BUS;
173 //ConfigInfo->TaggedQueueing = TRUE;
175 *Again = FALSE;
177 KdPrint((__DRIVER_NAME " <-- HwScsiFindAdapter\n"));
179 return Status;
180 }
182 static __inline uint64_t
183 GET_ID_FROM_FREELIST(PXENVBD_TARGET_DATA TargetData)
184 {
185 uint64_t free;
186 free = TargetData->shadow_free;
187 TargetData->shadow_free = TargetData->shadow[free].req.id;
188 TargetData->shadow[free].req.id = 0x0fffffee; /* debug */
189 return free;
190 }
192 static __inline VOID
193 ADD_ID_TO_FREELIST(PXENVBD_TARGET_DATA TargetData, uint64_t Id)
194 {
195 TargetData->shadow[Id].req.id = TargetData->shadow_free;
196 TargetData->shadow[Id].Srb = NULL;
197 TargetData->shadow_free = Id;
198 }
200 //static HANDLE XenVbd_ScsiPortThreadHandle;
201 //static KEVENT XenVbd_ScsiPortThreadEvent;
203 static VOID
204 XenVbd_Interrupt(PKINTERRUPT Interrupt, PVOID DeviceExtension)
205 {
206 PXENVBD_TARGET_DATA TargetData = (PXENVBD_TARGET_DATA)DeviceExtension;
208 // KdPrint((__DRIVER_NAME " --> Interrupt\n"));
210 TargetData->PendingInterrupt = TRUE;
212 // KdPrint((__DRIVER_NAME " <-- Interrupt\n"));
213 return;
214 }
216 static VOID
217 XenVbd_HwScsiInterruptTarget(PVOID DeviceExtension)
218 {
219 PXENVBD_TARGET_DATA TargetData = (PXENVBD_TARGET_DATA)DeviceExtension;
220 PSCSI_REQUEST_BLOCK Srb;
221 RING_IDX i, rp;
222 int j;
223 blkif_response_t *rep;
224 char *DataBuffer;
225 int more_to_do;
226 int BlockCount;
227 KIRQL Irql;
228 int notify;
229 KAPC_STATE ApcState;
230 PIRP Irp;
231 PXENVBD_DEVICE_DATA DeviceData;
233 // KdPrint((__DRIVER_NAME " --> HwScsiInterruptTarget\n"));
235 DeviceData = (PXENVBD_DEVICE_DATA)TargetData->DeviceData;
236 more_to_do = TRUE;
238 while (more_to_do)
239 {
240 rp = TargetData->Ring.sring->rsp_prod;
241 KeMemoryBarrier();
242 for (i = TargetData->Ring.rsp_cons; i != rp; i++)
243 {
244 rep = RING_GET_RESPONSE(&TargetData->Ring, i);
245 Srb = TargetData->shadow[rep->id].Srb;
246 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
248 if (rep->status == BLKIF_RSP_OKAY)
249 Srb->SrbStatus = SRB_STATUS_SUCCESS;
250 else
251 {
252 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
253 if (Srb->Cdb[0] == SCSIOP_READ)
254 KdPrint((__DRIVER_NAME " Operation = Read\n"));
255 else
256 KdPrint((__DRIVER_NAME " Operation = Write\n"));
257 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", TargetData->shadow[rep->id].req.sector_number, BlockCount));
258 Srb->SrbStatus = SRB_STATUS_ERROR;
259 }
260 for (j = 0; j < TargetData->shadow[rep->id].req.nr_segments; j++)
261 DeviceData->XenDeviceData->GntTblInterface.EndAccess(
262 DeviceData->XenDeviceData->GntTblInterface.InterfaceHeader.Context,
263 TargetData->shadow[rep->id].req.seg[j].gref);
264 if (Srb->Cdb[0] == SCSIOP_READ)
265 memcpy(Srb->DataBuffer, TargetData->shadow[rep->id].Buf, BlockCount * TargetData->BytesPerSector);
267 ScsiPortNotification(RequestComplete, DeviceData, Srb);
268 ScsiPortNotification(NextLuRequest, DeviceData, Srb->PathId, Srb->TargetId, Srb->Lun);
270 ADD_ID_TO_FREELIST(TargetData, rep->id);
271 }
273 TargetData->Ring.rsp_cons = i;
274 if (i != TargetData->Ring.req_prod_pvt)
275 {
276 RING_FINAL_CHECK_FOR_RESPONSES(&TargetData->Ring, more_to_do);
277 }
278 else
279 {
280 TargetData->Ring.sring->rsp_event = i + 1;
281 more_to_do = FALSE;
282 }
283 }
285 // KdPrint((__DRIVER_NAME " <-- HwScsiInterruptTarget\n"));
287 return FALSE;
288 }
290 static BOOLEAN
291 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
292 {
293 PXENVBD_DEVICE_DATA DeviceData;
294 PXENVBD_TARGET_DATA TargetData;
295 int i, j;
297 // KdPrint((__DRIVER_NAME " --> HwScsiInterrupt\n"));
299 DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
301 KeMemoryBarrier();
302 for (i = 0; i < SCSI_BUSES; i++)
303 {
304 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
305 {
306 TargetData = &DeviceData->BusData[i].TargetData[j];
307 if (TargetData->PendingInterrupt)
308 XenVbd_HwScsiInterruptTarget(TargetData);
309 TargetData->PendingInterrupt = FALSE;
310 }
311 }
312 // KdPrint((__DRIVER_NAME " <-- HwScsiInterrupt\n"));
314 return TRUE;
315 }
317 static VOID
318 XenVbd_BackEndStateHandler(char *Path, PVOID Data)
319 {
320 PXENVBD_TARGET_DATA TargetData;
321 PXENVBD_DEVICE_DATA DeviceData;
322 char TmpPath[128];
323 char *Value;
324 int NewState;
325 PMDL Mdl;
326 grant_ref_t ref;
327 blkif_sring_t *SharedRing;
328 ULONG PFN;
329 //XENVBD_DEVICE_IDENTIFICATION_DESCRIPTION Description;
330 KIRQL OldIrql;
331 NTSTATUS status;
332 int i;
334 KdPrint((__DRIVER_NAME " --> BackEndStateHandler\n"));
335 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
337 TargetData = (PXENVBD_TARGET_DATA)Data;
338 DeviceData = (PXENVBD_DEVICE_DATA)TargetData->DeviceData;
340 DeviceData->XenDeviceData->XenBusInterface.Read(
341 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
342 XBT_NIL, Path, &Value);
344 NewState = atoi(Value);
345 switch (NewState)
346 {
347 case XenbusStateUnknown:
348 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
349 break;
351 case XenbusStateInitialising:
352 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
353 break;
355 case XenbusStateInitWait:
356 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
358 TargetData->EventChannel = DeviceData->XenDeviceData->EvtChnInterface.AllocUnbound(
359 DeviceData->XenDeviceData->EvtChnInterface.InterfaceHeader.Context, 0);
360 DeviceData->XenDeviceData->EvtChnInterface.Bind(
361 DeviceData->XenDeviceData->EvtChnInterface.InterfaceHeader.Context,
362 TargetData->EventChannel, XenVbd_Interrupt, TargetData);
363 Mdl = AllocatePage();
364 PFN = *MmGetMdlPfnArray(Mdl);
365 SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
366 SHARED_RING_INIT(SharedRing);
367 FRONT_RING_INIT(&TargetData->Ring, SharedRing, PAGE_SIZE);
368 ref = DeviceData->XenDeviceData->GntTblInterface.GrantAccess(
369 DeviceData->XenDeviceData->GntTblInterface.InterfaceHeader.Context,
370 0, PFN, FALSE);
372 TargetData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * BLK_RING_SIZE, XENVBD_POOL_TAG);
374 memset(TargetData->shadow, 0, sizeof(blkif_shadow_t) * BLK_RING_SIZE);
375 for (i = 0; i < BLK_RING_SIZE; i++)
376 {
377 TargetData->shadow[i].req.id = i + 1;
378 TargetData->shadow[i].Mdl = AllocatePages(BUF_PAGES_PER_SRB); // stupid that we have to do this!
379 TargetData->shadow[i].Buf = MmGetMdlVirtualAddress(TargetData->shadow[i].Mdl);
380 }
381 TargetData->shadow_free = 0;
382 TargetData->shadow[BLK_RING_SIZE - 1].req.id = 0x0fffffff;
384 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
385 RtlStringCbCatA(TmpPath, 128, "/ring-ref");
386 DeviceData->XenDeviceData->XenBusInterface.Printf(DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", ref);
388 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
389 RtlStringCbCatA(TmpPath, 128, "/event-channel");
390 DeviceData->XenDeviceData->XenBusInterface.Printf(DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", TargetData->EventChannel);
392 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
393 RtlStringCbCatA(TmpPath, 128, "/state");
394 DeviceData->XenDeviceData->XenBusInterface.Printf(DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
396 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
397 break;
399 case XenbusStateInitialised:
400 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
401 break;
403 case XenbusStateConnected:
404 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
406 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
407 RtlStringCbCatA(TmpPath, 128, "/device-type");
408 DeviceData->XenDeviceData->XenBusInterface.Read(
409 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
410 XBT_NIL, TmpPath, &Value);
411 if (strcmp(Value, "disk") == 0)
412 {
413 KdPrint((__DRIVER_NAME " DeviceType = Disk\n"));
414 TargetData->DeviceType = XENVBD_DEVICETYPE_DISK;
415 }
416 else if (strcmp(Value, "cdrom") == 0)
417 {
418 KdPrint((__DRIVER_NAME " DeviceType = CDROM\n"));
419 TargetData->DeviceType = XENVBD_DEVICETYPE_CDROM;
420 }
421 else
422 {
423 KdPrint((__DRIVER_NAME " DeviceType = %s (This probably won't work!)\n", Value));
424 TargetData->DeviceType = XENVBD_DEVICETYPE_UNKNOWN;
425 }
427 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
428 RtlStringCbCatA(TmpPath, 128, "/type"); // should probably check that this is 'phy' or 'file' or at least not ''
429 DeviceData->XenDeviceData->XenBusInterface.Read(
430 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
431 XBT_NIL, TmpPath, &Value);
432 KdPrint((__DRIVER_NAME " Backend Type = %s\n", Value));
433 ExFreePool(Value);
435 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
436 RtlStringCbCatA(TmpPath, 128, "/mode"); // should store this...
437 DeviceData->XenDeviceData->XenBusInterface.Read(
438 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
439 XBT_NIL, TmpPath, &Value);
440 KdPrint((__DRIVER_NAME " Backend Mode = %s\n", Value));
441 ExFreePool(Value);
443 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
444 RtlStringCbCatA(TmpPath, 128, "/sector-size");
445 DeviceData->XenDeviceData->XenBusInterface.Read(
446 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
447 XBT_NIL, TmpPath, &Value);
448 // should complain if Value == NULL
449 TargetData->BytesPerSector = atoi(Value);
451 KdPrint((__DRIVER_NAME " BytesPerSector = %d\n", TargetData->BytesPerSector));
453 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
454 RtlStringCbCatA(TmpPath, 128, "/sectors");
455 DeviceData->XenDeviceData->XenBusInterface.Read(
456 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
457 XBT_NIL, TmpPath, &Value);
458 // should complain if Value == NULL
459 TargetData->TotalSectors = (ULONGLONG)atol(Value);
461 KdPrint((__DRIVER_NAME " TotalSectors = %d\n", TargetData->TotalSectors));
463 // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
464 TargetData->Geometry.MediaType = FixedMedia;
465 TargetData->Geometry.BytesPerSector = TargetData->BytesPerSector;
466 TargetData->Geometry.SectorsPerTrack = 63;
467 TargetData->Geometry.TracksPerCylinder = 255;
468 TargetData->Geometry.Cylinders.QuadPart = TargetData->TotalSectors / TargetData->Geometry.SectorsPerTrack / TargetData->Geometry.TracksPerCylinder;
469 KdPrint((__DRIVER_NAME " Geometry C/H/S = %d/%d/%d\n", TargetData->Geometry.Cylinders.LowPart, TargetData->Geometry.TracksPerCylinder, TargetData->Geometry.SectorsPerTrack));
471 // now ask windows to rescan the scsi bus...
472 DeviceData->BusChangePending = 1;
474 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
475 RtlStringCbCatA(TmpPath, 128, "/state");
476 DeviceData->XenDeviceData->XenBusInterface.Printf(DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateConnected);
478 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
479 InterlockedIncrement(&DeviceData->EnumeratedDevices);
480 KdPrint((__DRIVER_NAME " Added a device, notifying\n"));
481 KeSetEvent(&DeviceData->WaitDevicesEvent, 1, FALSE);
483 break;
485 case XenbusStateClosing:
486 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
487 break;
489 case XenbusStateClosed:
490 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
491 break;
493 default:
494 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
495 break;
496 }
498 KdPrint((__DRIVER_NAME " <-- BackEndStateHandler\n"));
499 }
501 static VOID
502 XenVbd_WatchHandler(char *Path, PVOID DeviceExtension)
503 {
504 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
505 char **Bits;
506 int Count;
507 char TmpPath[128];
508 char *Value;
509 int CurrentBus, CurrentTarget;
510 PXENVBD_TARGET_DATA TargetData, VacantTarget;
511 KIRQL OldIrql;
512 int i, j;
514 KdPrint((__DRIVER_NAME " --> WatchHandler (DeviceData = %08x)\n", DeviceData));
516 KdPrint((__DRIVER_NAME " Path = %s\n", Path));
518 Bits = SplitString(Path, '/', 4, &Count);
519 switch (Count)
520 {
521 case 0:
522 case 1:
523 case 2:
524 break; // should never happen
525 case 3:
526 break;
527 case 4:
528 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
529 break;
531 KeAcquireSpinLock(&DeviceData->Lock, &OldIrql);
533 for (VacantTarget = NULL,i = 0; i < SCSI_BUSES * SCSI_TARGETS_PER_BUS; i++)
534 {
535 CurrentBus = i / SCSI_TARGETS_PER_BUS;
536 CurrentTarget = i % SCSI_TARGETS_PER_BUS;
537 if (CurrentTarget == 7) // don't use 7 - it would be for the controller
538 continue;
539 TargetData = &DeviceData->BusData[CurrentBus].TargetData[CurrentTarget];
540 if (TargetData->Present && strncmp(TargetData->Path, Path, strlen(TargetData->Path)) == 0 && Path[strlen(TargetData->Path)] == '/')
541 break; // already exists
542 else if (!TargetData->Present && VacantTarget == NULL)
543 VacantTarget = TargetData;
544 }
545 if (i == SCSI_BUSES * SCSI_TARGETS_PER_BUS && VacantTarget != NULL)
546 {
547 VacantTarget->Present = 1;
548 KeReleaseSpinLock(&DeviceData->Lock, OldIrql);
550 RtlStringCbCopyA(VacantTarget->Path, 128, Bits[0]);
551 RtlStringCbCatA(VacantTarget->Path, 128, "/");
552 RtlStringCbCatA(VacantTarget->Path, 128, Bits[1]);
553 RtlStringCbCatA(VacantTarget->Path, 128, "/");
554 RtlStringCbCatA(VacantTarget->Path, 128, Bits[2]);
556 VacantTarget->DeviceIndex = atoi(Bits[2]);
558 RtlStringCbCopyA(TmpPath, 128, VacantTarget->Path);
559 RtlStringCbCatA(TmpPath, 128, "/backend");
560 DeviceData->XenDeviceData->XenBusInterface.Read(
561 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
562 XBT_NIL, TmpPath, &Value);
563 if (Value == NULL)
564 KdPrint((__DRIVER_NAME " Read Failed\n"));
565 else
566 RtlStringCbCopyA(VacantTarget->BackendPath, 128, Value);
567 RtlStringCbCopyA(TmpPath, 128, VacantTarget->BackendPath);
568 RtlStringCbCatA(TmpPath, 128, "/state");
570 DeviceData->XenDeviceData->XenBusInterface.AddWatch(
571 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
572 XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, VacantTarget);
573 }
574 else
575 KeReleaseSpinLock(&DeviceData->Lock, OldIrql);
576 break;
577 }
579 FreeSplitString(Bits, Count);
581 KdPrint((__DRIVER_NAME " <-- WatchHandler\n"));
583 return;
584 }
586 static VOID
587 XenVbd_CheckBusChangedTimer(PVOID DeviceExtension)
588 {
589 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
591 if (DeviceData->BusChangePending)
592 {
593 ScsiPortNotification(BusChangeDetected, DeviceData, 0);
594 DeviceData->BusChangePending = 0;
595 }
596 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusChangedTimer, 1000000);
597 }
599 static BOOLEAN
600 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
601 {
602 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
603 unsigned int i, j;
604 NTSTATUS Status;
605 char **VbdDevices;
606 char *msg;
607 char buffer[128];
608 LARGE_INTEGER WaitTimeout;
610 KdPrint((__DRIVER_NAME " --> HwScsiInitialize\n"));
611 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
613 for (i = 0; i < SCSI_BUSES; i++)
614 {
615 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
616 {
617 DeviceData->BusData[i].TargetData[j].Present = 0;
618 DeviceData->BusData[i].TargetData[j].DeviceData = DeviceData;
619 }
620 }
622 DeviceData->XenDeviceData->WatchContext = DeviceExtension;
623 KeMemoryBarrier();
624 DeviceData->XenDeviceData->WatchHandler = XenVbd_WatchHandler;
626 KeInitializeEvent(&DeviceData->WaitDevicesEvent, SynchronizationEvent, FALSE);
627 DeviceData->EnumeratedDevices = 0;
628 if (DeviceData->XenDeviceData->AutoEnumerate)
629 {
630 msg = DeviceData->XenDeviceData->XenBusInterface.List(
631 DeviceData->XenDeviceData->XenBusInterface.InterfaceHeader.Context,
632 XBT_NIL, "device/vbd", &VbdDevices);
633 if (!msg) {
634 for (i = 0; VbdDevices[i]; i++)
635 {
636 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
637 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
638 XenVbd_WatchHandler(buffer, DeviceData);
639 // WaitTimeout.QuadPart = -600000000;
640 KeWaitForSingleObject(&DeviceData->WaitDevicesEvent, Executive, KernelMode, FALSE, NULL);
641 KdPrint((__DRIVER_NAME " %d devices enumerated\n", DeviceData->EnumeratedDevices));
642 }
643 }
644 /*
645 for (i = 0; VbdDevices[i]; i++)
646 {
647 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
648 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
649 XenVbd_WatchHandler(buffer, DeviceData);
650 //ExFreePoolWithTag(bdDevices[i], XENPCI_POOL_TAG);
651 }
652 KdPrint((__DRIVER_NAME " Waiting for %d devices to be enumerated\n", i));
653 while (DeviceData->EnumeratedDevices < i)
654 {
655 WaitTimeout.QuadPart = -600000000;
656 if (KeWaitForSingleObject(&DeviceData->WaitDevicesEvent, Executive, KernelMode, FALSE, &WaitTimeout) == STATUS_TIMEOUT)
657 {
658 KdPrint((__DRIVER_NAME " Wait timed out\n"));
659 break;
660 }
661 KdPrint((__DRIVER_NAME " %d out of %d devices enumerated\n", DeviceData->EnumeratedDevices, i));
662 }
663 }
664 */
665 ScsiPortNotification(BusChangeDetected, DeviceData, 0);
666 DeviceData->BusChangePending = 0;
667 }
668 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusChangedTimer, 1000000);
670 KdPrint((__DRIVER_NAME " <-- HwScsiInitialize\n"));
672 return TRUE;
673 }
675 static ULONG
676 XenVbd_FillModePage(PXENVBD_DEVICE_DATA DeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
677 {
678 PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
680 switch (PageCode)
681 {
682 /*
683 case MODE_PAGE_RIGID_GEOMETRY:
684 if (DeviceData->ScsiData->DeviceType == XENVBD_DEVICETYPE_CDROM)
685 {
686 KdPrint((__DRIVER_NAME " MODE_PAGE_RIGID_GEOMETRY\n"));
687 if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
688 return 1;
689 ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
690 memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
691 ModeRigidGeometry->PageCode = PageCode;
692 ModeRigidGeometry->PageSavable = 0;
693 ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
694 ModeRigidGeometry->NumberOfCylinders[0] = (DeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF;
695 ModeRigidGeometry->NumberOfCylinders[1] = (DeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF;
696 ModeRigidGeometry->NumberOfCylinders[2] = (DeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF;
697 ModeRigidGeometry->NumberOfHeads = DeviceData->Geometry.TracksPerCylinder;
698 //ModeRigidGeometry->LandZoneCyclinder = 0;
699 ModeRigidGeometry->RoataionRate[0] = 0x05;
700 ModeRigidGeometry->RoataionRate[0] = 0x39;
701 *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
702 }
703 break;
704 */
705 case MODE_PAGE_FAULT_REPORTING:
706 break;
707 default:
708 break;
709 }
710 return 0;
711 }
713 // Call with device lock held
714 static VOID
715 XenVbd_PutSrbOnRing(PXENVBD_TARGET_DATA TargetData, PSCSI_REQUEST_BLOCK Srb)
716 {
717 //PUCHAR DataBuffer;
718 blkif_request_t *req;
719 int i;
720 int j;
721 int BlockCount;
722 int sect_offset;
723 PVOID CurrentVirtual;
724 ULONG CurrentLength;
725 ULONG SegmentLength;
726 SCSI_PHYSICAL_ADDRESS PageAddress;
727 int Iterations;
728 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)TargetData->DeviceData;
730 // can use SRB_STATUS_BUSY to push the SRB back to windows...
732 // KdPrint((__DRIVER_NAME " --> PutSrbOnRing\n"));
734 if (RING_FULL(&TargetData->Ring))
735 {
736 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
737 // TODO: Fail badly here
738 }
740 req = RING_GET_REQUEST(&TargetData->Ring, TargetData->Ring.req_prod_pvt);
742 req->sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
743 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
745 req->id = GET_ID_FROM_FREELIST(TargetData);
747 if (req->id == 0x0fffffff)
748 {
749 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutSrbOnRing\n"));
750 }
752 req->handle = 0;
753 req->operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
754 TargetData->shadow[req->id].Srb = Srb;
756 // KdPrint((__DRIVER_NAME " DataBuffer = %08X\n", Srb->DataBuffer));
757 // KdPrint((__DRIVER_NAME " BlockCount = %08X\n", BlockCount));
759 req->nr_segments = (BlockCount * TargetData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE;
760 // KdPrint((__DRIVER_NAME " req->nr_segments = %08X\n", req->nr_segments));
762 for (i = 0; i < req->nr_segments; i++)
763 {
764 req->seg[i].gref = DeviceData->XenDeviceData->GntTblInterface.GrantAccess(
765 DeviceData->XenDeviceData->GntTblInterface.InterfaceHeader.Context,
766 0, MmGetMdlPfnArray(TargetData->shadow[req->id].Mdl)[i], FALSE);
767 req->seg[i].first_sect = 0;
768 if (i == req->nr_segments - 1)
769 req->seg[i].last_sect = (BlockCount - 1) % (PAGE_SIZE / TargetData->BytesPerSector);
770 else
771 req->seg[i].last_sect = PAGE_SIZE / TargetData->BytesPerSector - 1;
772 // KdPrint((__DRIVER_NAME " Page %d, first_sect = %d, last_sect = %d\n", i, req->seg[i].first_sect, req->seg[i].last_sect));
773 }
774 if (Srb->Cdb[0] == SCSIOP_WRITE)
775 memcpy(TargetData->shadow[req->id].Buf, Srb->DataBuffer, BlockCount * TargetData->BytesPerSector);
776 TargetData->shadow[req->id].req = *req;
777 TargetData->Ring.req_prod_pvt++;
779 // KdPrint((__DRIVER_NAME " <-- PutSrbOnRing\n"));
780 }
782 static BOOLEAN
783 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
784 {
785 PUCHAR DataBuffer;
786 PCDB cdb;
787 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
788 PXENVBD_TARGET_DATA TargetData;
789 unsigned int i;
790 KIRQL KIrql;
791 int notify;
792 SCSI_PHYSICAL_ADDRESS ScsiPhysicalAddress;
793 ULONG Length;
795 // KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
796 // KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
798 if (Srb->PathId >= SCSI_BUSES || Srb->TargetId >= SCSI_TARGETS_PER_BUS)
799 {
800 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
801 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
802 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
803 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
804 return TRUE;
805 }
807 TargetData = &DeviceData->BusData[Srb->PathId].TargetData[Srb->TargetId];
809 if (!TargetData->Present)
810 {
811 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
812 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
813 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
814 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Not Present)\n"));
815 return TRUE;
816 }
818 switch (Srb->Function)
819 {
820 case SRB_FUNCTION_EXECUTE_SCSI:
821 cdb = (PCDB)Srb->Cdb;
822 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
823 switch(cdb->CDB6GENERIC.OperationCode)
824 {
825 case SCSIOP_TEST_UNIT_READY:
826 // KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
827 Srb->SrbStatus = SRB_STATUS_SUCCESS;
828 Srb->ScsiStatus = 0;
829 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
830 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
831 break;
832 case SCSIOP_INQUIRY:
833 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
834 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
835 KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
836 KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
837 // KdPrint((__DRIVER_NAME " PhysicalAddress.LowPart = %08x\n", ScsiPortGetPhysicalAddress(DeviceData, Srb, Srb->DataBuffer, &Length).LowPart));
838 // DataBuffer = ScsiPortGetVirtualAddress(DeviceData, ScsiPortGetPhysicalAddress(DeviceData, Srb, Srb->DataBuffer, &Length));
839 // KdPrint((__DRIVER_NAME " (Databuffer = %08x)\n", DataBuffer));
840 // break;
841 DataBuffer = Srb->DataBuffer;
842 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
843 Srb->SrbStatus = SRB_STATUS_SUCCESS;
844 switch (TargetData->DeviceType)
845 {
846 case XENVBD_DEVICETYPE_DISK:
847 if ((Srb->Cdb[1] & 1) == 0)
848 {
849 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
850 DataBuffer[1] = 0x00; // not removable
851 DataBuffer[3] = 32;
852 memcpy(DataBuffer + 8, "XEN ", 8); // vendor id
853 memcpy(DataBuffer + 16, "PV VBD ", 16); // product id
854 memcpy(DataBuffer + 32, "0000", 4); // product revision level
855 }
856 else
857 {
858 switch (Srb->Cdb[2])
859 {
860 case 0x00:
861 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
862 DataBuffer[1] = 0x00;
863 DataBuffer[2] = 0x00;
864 DataBuffer[3] = 2;
865 DataBuffer[4] = 0x00;
866 DataBuffer[5] = 0x80;
867 break;
868 case 0x80:
869 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
870 DataBuffer[1] = 0x80;
871 DataBuffer[2] = 0x00;
872 DataBuffer[3] = 8;
873 DataBuffer[4] = 0x31;
874 DataBuffer[5] = 0x32;
875 DataBuffer[6] = 0x33;
876 DataBuffer[7] = 0x34;
877 DataBuffer[8] = 0x35;
878 DataBuffer[9] = 0x36;
879 DataBuffer[10] = 0x37;
880 DataBuffer[11] = 0x38;
881 break;
882 default:
883 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
884 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
885 break;
886 }
887 }
888 break;
889 case XENVBD_DEVICETYPE_CDROM:
890 if ((Srb->Cdb[1] & 1) == 0)
891 {
892 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
893 DataBuffer[1] = 0x01; // removable
894 DataBuffer[3] = 32;
895 memcpy(DataBuffer + 8, "XEN ", 8); // vendor id
896 memcpy(DataBuffer + 16, "PV VBD ", 16); // product id
897 memcpy(DataBuffer + 32, "0000", 4); // product revision level
898 }
899 else
900 {
901 switch (Srb->Cdb[2])
902 {
903 case 0x00:
904 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
905 DataBuffer[1] = 0x00;
906 DataBuffer[2] = 0x00;
907 DataBuffer[3] = 2;
908 DataBuffer[4] = 0x00;
909 DataBuffer[5] = 0x80;
910 break;
911 case 0x80:
912 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
913 DataBuffer[1] = 0x80;
914 DataBuffer[2] = 0x00;
915 DataBuffer[3] = 8;
916 DataBuffer[4] = 0x31;
917 DataBuffer[5] = 0x32;
918 DataBuffer[6] = 0x33;
919 DataBuffer[7] = 0x34;
920 DataBuffer[8] = 0x35;
921 DataBuffer[9] = 0x36;
922 DataBuffer[10] = 0x37;
923 DataBuffer[11] = 0x38;
924 break;
925 default:
926 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
927 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
928 break;
929 }
930 }
931 break;
932 default:
933 KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", TargetData->DeviceType));
934 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
935 break;
936 }
937 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
938 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
939 break;
940 case SCSIOP_READ_CAPACITY:
941 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
942 DataBuffer = Srb->DataBuffer;
943 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
944 DataBuffer[0] = (unsigned char)((TargetData->TotalSectors - 1) >> 24) & 0xff;
945 DataBuffer[1] = (unsigned char)((TargetData->TotalSectors - 1) >> 16) & 0xff;
946 DataBuffer[2] = (unsigned char)((TargetData->TotalSectors - 1) >> 8) & 0xff;
947 DataBuffer[3] = (unsigned char)((TargetData->TotalSectors - 1) >> 0) & 0xff;
948 DataBuffer[4] = (unsigned char)(TargetData->BytesPerSector >> 24) & 0xff;
949 DataBuffer[5] = (unsigned char)(TargetData->BytesPerSector >> 16) & 0xff;
950 DataBuffer[6] = (unsigned char)(TargetData->BytesPerSector >> 8) & 0xff;
951 DataBuffer[7] = (unsigned char)(TargetData->BytesPerSector >> 0) & 0xff;
952 Srb->ScsiStatus = 0;
953 Srb->SrbStatus = SRB_STATUS_SUCCESS;
954 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
955 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
956 break;
957 case SCSIOP_MODE_SENSE:
958 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));
959 KdPrint((__DRIVER_NAME " Length = %d\n", Srb->DataTransferLength));
961 Srb->ScsiStatus = 0;
962 Srb->SrbStatus = SRB_STATUS_SUCCESS;
963 Srb->DataTransferLength = 0;
964 DataBuffer = Srb->DataBuffer;
965 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
966 switch(cdb->MODE_SENSE.PageCode)
967 {
968 case MODE_SENSE_RETURN_ALL:
969 //Ptr = (UCHAR *)Srb->DataBuffer;
970 for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
971 {
972 if (XenVbd_FillModePage(DeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength))
973 {
974 break;
975 }
976 }
977 break;
978 default:
979 XenVbd_FillModePage(DeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength);
980 break;
981 }
982 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
983 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
984 break;
985 case SCSIOP_READ:
986 case SCSIOP_WRITE:
987 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
988 XenVbd_PutSrbOnRing(TargetData, Srb);
989 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&TargetData->Ring, notify);
990 if (notify)
991 DeviceData->XenDeviceData->EvtChnInterface.Notify(
992 DeviceData->XenDeviceData->EvtChnInterface.InterfaceHeader.Context,
993 TargetData->EventChannel);
994 if (!RING_FULL(&TargetData->Ring))
995 ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
996 else
997 ScsiPortNotification(NextRequest, DeviceExtension);
998 break;
999 case SCSIOP_REPORT_LUNS:
1000 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1001 Srb->SrbStatus = SRB_STATUS_SUCCESS; //SRB_STATUS_INVALID_REQUEST;
1002 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1003 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1004 break;
1005 case SCSIOP_READ_TOC:
1006 DataBuffer = Srb->DataBuffer;
1007 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1008 /*
1009 #define READ_TOC_FORMAT_TOC 0x00
1010 #define READ_TOC_FORMAT_SESSION 0x01
1011 #define READ_TOC_FORMAT_FULL_TOC 0x02
1012 #define READ_TOC_FORMAT_PMA 0x03
1013 #define READ_TOC_FORMAT_ATIP 0x04
1014 */
1015 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1016 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1017 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1018 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1019 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1020 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1021 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1022 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1023 switch (cdb->READ_TOC.Format2)
1025 case READ_TOC_FORMAT_TOC:
1026 DataBuffer[0] = 0; // length MSB
1027 DataBuffer[1] = 10; // length LSB
1028 DataBuffer[2] = 1; // First Track
1029 DataBuffer[3] = 1; // Last Track
1030 DataBuffer[4] = 0; // Reserved
1031 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1032 DataBuffer[6] = 1; // last complete track
1033 DataBuffer[7] = 0; // reserved
1034 DataBuffer[8] = 0; // MSB Block
1035 DataBuffer[9] = 0;
1036 DataBuffer[10] = 0;
1037 DataBuffer[11] = 0; // LSB Block
1038 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1039 break;
1040 case READ_TOC_FORMAT_SESSION:
1041 case READ_TOC_FORMAT_FULL_TOC:
1042 case READ_TOC_FORMAT_PMA:
1043 case READ_TOC_FORMAT_ATIP:
1044 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1045 break;
1047 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1048 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1049 break;
1050 default:
1051 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1052 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1053 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1054 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1055 break;
1057 break;
1058 case SRB_FUNCTION_CLAIM_DEVICE:
1059 KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
1060 // ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
1061 // Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
1062 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1063 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1064 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1065 break;
1066 case SRB_FUNCTION_IO_CONTROL:
1067 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1068 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1069 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1070 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1071 break;
1072 case SRB_FUNCTION_FLUSH:
1073 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1074 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1075 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1076 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1077 break;
1078 default:
1079 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1080 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1081 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1082 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1083 break;
1086 // KdPrint((__DRIVER_NAME " <-- HwScsiStartIo\n"));
1088 return TRUE;
1091 static BOOLEAN
1092 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1094 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1095 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1097 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1099 return TRUE;
1103 static BOOLEAN
1104 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1106 KdPrint((__DRIVER_NAME " --> HwScsiAdapterState\n"));
1107 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1109 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterState\n"));
1111 return TRUE;
1114 static SCSI_ADAPTER_CONTROL_STATUS
1115 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1117 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1118 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1120 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
1121 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1123 switch (ControlType)
1125 case ScsiQuerySupportedControlTypes:
1126 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1127 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1128 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1129 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1130 break;
1131 case ScsiStopAdapter:
1132 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1133 break;
1134 case ScsiRestartAdapter:
1135 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1136 break;
1137 case ScsiSetBootConfig:
1138 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1139 break;
1140 case ScsiSetRunningConfig:
1141 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1142 break;
1143 default:
1144 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1145 break;
1148 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
1150 return Status;