win-pvdrivers

view xenvbd/xenvbd.c @ 266:b88529df8b60

More wdm updates
author James Harper <james.harper@bendigoit.com.au>
date Wed May 07 10:47:03 2008 +1000 (2008-05-07)
parents 952b8aa9c44c
children f157f82e0293
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>
9 #include <io/protocols.h>
11 #pragma warning(disable: 4127)
13 #define wmb() KeMemoryBarrier()
14 #define mb() KeMemoryBarrier()
16 DRIVER_INITIALIZE DriverEntry;
18 static ULONG
19 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again);
20 static BOOLEAN
21 XenVbd_HwScsiInitialize(PVOID DeviceExtension);
22 static BOOLEAN
23 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb);
24 static BOOLEAN
25 XenVbd_HwScsiInterrupt(PVOID DeviceExtension);
26 static BOOLEAN
27 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId);
28 static BOOLEAN
29 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState);
30 static SCSI_ADAPTER_CONTROL_STATUS
31 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters);
33 #ifdef ALLOC_PRAGMA
34 #pragma alloc_text (INIT, DriverEntry)
35 #endif
37 static BOOLEAN DumpMode;
39 NTSTATUS
40 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
41 {
42 ULONG Status;
43 HW_INITIALIZATION_DATA HwInitializationData;
45 KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
46 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
48 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
50 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
51 HwInitializationData.AdapterInterfaceType = Internal; //PNPBus;
52 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
53 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
54 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
55 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
56 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
57 HwInitializationData.HwDmaStarted = NULL;
58 HwInitializationData.HwAdapterState = XenVbd_HwScsiAdapterState;
59 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_EXTENSION); //sizeof(XENVBD_DEVICE_DATA);
60 HwInitializationData.SpecificLuExtensionSize = 0;
61 HwInitializationData.SrbExtensionSize = 0;
62 HwInitializationData.NumberOfAccessRanges = 1;
63 HwInitializationData.MapBuffers = TRUE;
64 HwInitializationData.NeedPhysicalAddresses = FALSE;
65 HwInitializationData.TaggedQueuing = TRUE;
66 HwInitializationData.AutoRequestSense = FALSE;
67 HwInitializationData.MultipleRequestPerLu = TRUE;
68 HwInitializationData.ReceiveEvent = FALSE;
69 HwInitializationData.VendorIdLength = 0;
70 HwInitializationData.VendorId = NULL;
71 HwInitializationData.DeviceIdLength = 0;
72 HwInitializationData.DeviceId = NULL;
73 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
75 DumpMode = FALSE;
77 Status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
79 if(!NT_SUCCESS(Status))
80 {
81 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", Status));
82 }
84 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
86 return Status;
87 }
89 static __inline uint64_t
90 GET_ID_FROM_FREELIST(PXENVBD_TARGET_DATA TargetData)
91 {
92 uint64_t free;
93 free = TargetData->shadow_free;
94 TargetData->shadow_free = TargetData->shadow[free].req.id;
95 TargetData->shadow[free].req.id = 0x0fffffee; /* debug */
96 return free;
97 }
99 static __inline VOID
100 ADD_ID_TO_FREELIST(PXENVBD_TARGET_DATA TargetData, uint64_t Id)
101 {
102 TargetData->shadow[Id].req.id = TargetData->shadow_free;
103 TargetData->shadow[Id].Srb = NULL;
104 TargetData->shadow_free = Id;
105 }
107 static BOOLEAN
108 XenVbd_Interrupt(PKINTERRUPT Interrupt, PVOID DeviceExtension)
109 {
110 PXENVBD_TARGET_DATA TargetData = (PXENVBD_TARGET_DATA)DeviceExtension;
112 UNREFERENCED_PARAMETER(Interrupt);
114 KdPrint((__DRIVER_NAME " --> Interrupt\n"));
116 TargetData->PendingInterrupt = TRUE;
118 KdPrint((__DRIVER_NAME " <-- Interrupt\n"));
120 return TRUE;
121 }
123 static blkif_response_t *
124 XenVbd_GetResponse(PXENVBD_TARGET_DATA TargetData, int i)
125 {
126 blkif_other_response_t *rep;
127 if (!TargetData->use_other)
128 return RING_GET_RESPONSE(&TargetData->Ring, i);
129 rep = RING_GET_RESPONSE(&TargetData->OtherRing, i);
130 TargetData->tmp_rep.id = rep->id;
131 TargetData->tmp_rep.operation = rep->operation;
132 TargetData->tmp_rep.status = rep->status;
133 return &TargetData->tmp_rep;
134 }
136 static VOID
137 XenVbd_HwScsiInterruptTarget(PVOID DeviceExtension)
138 {
139 PXENVBD_TARGET_DATA TargetData = (PXENVBD_TARGET_DATA)DeviceExtension;
140 PSCSI_REQUEST_BLOCK Srb;
141 RING_IDX i, rp;
142 blkif_response_t *rep;
143 int BlockCount;
144 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)TargetData->DeviceData;
145 int more_to_do = TRUE;
147 KdPrint((__DRIVER_NAME " --> HwScsiInterruptTarget\n"));
149 #if 0
150 while (more_to_do)
151 {
152 rp = TargetData->Ring.sring->rsp_prod;
153 KeMemoryBarrier();
154 for (i = TargetData->Ring.rsp_cons; i != rp; i++)
155 {
156 rep = XenVbd_GetResponse(TargetData, i);
158 //KdPrint((__DRIVER_NAME " rep = %p\n", rep));
159 //KdPrint((__DRIVER_NAME " rep->id = %d\n", rep->id));
161 /*
162 * This code is to automatically detect if the backend is using the same
163 * bit width or a different bit width to us. Later versions of Xen do this
164 * via a xenstore value, but not all. That 0x0fffffff (notice
165 * that the msb is not actually set, so we don't have any problems with
166 * sign extending) is to signify the last entry on the right, which is
167 * different under 32 and 64 bits, and that is why we set it up there.
169 * To do the detection, we put two initial entries on the ring, with an op
170 * of 0xff (which is invalid). The first entry is mostly okay, but the
171 * second will be grossly misaligned if the backend bit width is different,
172 * and we detect this and switch frontend structures.
173 */
174 switch (TargetData->ring_detect_state)
175 {
176 case 0:
177 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", TargetData->ring_detect_state, rep->operation, rep->id, rep->status));
178 TargetData->ring_detect_state = 1;
179 break;
180 case 1:
181 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", TargetData->ring_detect_state, rep->operation, rep->id, rep->status));
182 if (rep->operation != 0xff)
183 {
184 TargetData->Ring.nr_ents = BLK_OTHER_RING_SIZE;
185 TargetData->use_other = TRUE;
186 }
187 TargetData->shadow[TargetData->Ring.nr_ents - 1].req.id = 0x0fffffff;
188 DeviceData->BusChangePending = 1;
189 TargetData->ring_detect_state = 2;
190 break;
191 case 2:
192 Srb = TargetData->shadow[rep->id].Srb;
193 if (Srb != NULL)
194 {
195 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
197 if (rep->status == BLKIF_RSP_OKAY)
198 Srb->SrbStatus = SRB_STATUS_SUCCESS;
199 else
200 {
201 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
202 if (Srb->Cdb[0] == SCSIOP_READ)
203 KdPrint((__DRIVER_NAME " Operation = Read\n"));
204 else
205 KdPrint((__DRIVER_NAME " Operation = Write\n"));
206 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", TargetData->shadow[rep->id].req.sector_number, BlockCount));
207 Srb->SrbStatus = SRB_STATUS_ERROR;
208 }
209 if (Srb->Cdb[0] == SCSIOP_READ)
210 memcpy(Srb->DataBuffer, TargetData->shadow[rep->id].Buf, BlockCount * TargetData->BytesPerSector);
212 ScsiPortNotification(RequestComplete, DeviceData->DeviceExtension, Srb);
213 if (!DumpMode)
214 ScsiPortNotification(NextLuRequest, DeviceData->DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
215 else
216 ScsiPortNotification(NextRequest, DeviceData->DeviceExtension);
217 }
218 ADD_ID_TO_FREELIST(TargetData, rep->id);
219 }
220 }
222 TargetData->Ring.rsp_cons = i;
223 if (i != TargetData->Ring.req_prod_pvt)
224 {
225 RING_FINAL_CHECK_FOR_RESPONSES(&TargetData->Ring, more_to_do);
226 }
227 else
228 {
229 TargetData->Ring.sring->rsp_event = i + 1;
230 more_to_do = FALSE;
231 }
232 }
234 #endif
236 KdPrint((__DRIVER_NAME " <-- HwScsiInterruptTarget\n"));
237 }
239 static BOOLEAN
240 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
241 {
242 PXENVBD_DEVICE_DATA DeviceData;
243 PXENVBD_TARGET_DATA TargetData;
244 int i, j;
246 // KdPrint((__DRIVER_NAME " --> HwScsiInterrupt\n"));
248 DeviceData = ((PXENVBD_DEVICE_EXTENSION)DeviceExtension)->XenVbdDeviceData;
250 KeMemoryBarrier();
251 for (i = 0; i < SCSI_BUSES; i++)
252 {
253 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
254 {
255 TargetData = &DeviceData->BusData[i].TargetData[j];
256 if (TargetData->Running && (TargetData->PendingInterrupt || (TargetData->Present && DumpMode)))
257 XenVbd_HwScsiInterruptTarget(TargetData);
258 TargetData->PendingInterrupt = FALSE;
259 }
260 }
261 // KdPrint((__DRIVER_NAME " <-- HwScsiInterrupt\n"));
263 return FALSE;
264 }
266 #if 0
267 static VOID
268 XenVbd_BackEndStateHandler(char *Path, PVOID Data)
269 {
270 PXENVBD_TARGET_DATA TargetData;
271 PXENVBD_DEVICE_DATA DeviceData;
272 char TmpPath[128];
273 char *Value;
274 int NewState;
275 PMDL Mdl;
276 grant_ref_t ref;
277 blkif_sring_t *SharedRing;
278 ULONG PFN;
279 ULONG i, j;
280 blkif_request_t *req;
281 int notify;
283 KdPrint((__DRIVER_NAME " --> BackEndStateHandler\n"));
284 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
286 TargetData = (PXENVBD_TARGET_DATA)Data;
287 DeviceData = (PXENVBD_DEVICE_DATA)TargetData->DeviceData;
289 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
290 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
291 XBT_NIL, Path, &Value);
293 NewState = atoi(Value);
294 switch (NewState)
295 {
296 case XenbusStateUnknown:
297 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
298 break;
300 case XenbusStateInitialising:
301 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
302 break;
304 case XenbusStateInitWait:
305 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
307 TargetData->EventChannel = DeviceData->XenDeviceData->XenInterface.EvtChn_AllocUnbound(
308 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, 0);
309 DeviceData->XenDeviceData->XenInterface.EvtChn_Bind(
310 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
311 TargetData->EventChannel, XenVbd_Interrupt, TargetData);
312 Mdl = AllocatePage();
313 PFN = (ULONG)*MmGetMdlPfnArray(Mdl);
314 SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
315 RtlZeroMemory(SharedRing, PAGE_SIZE);
316 SHARED_RING_INIT(SharedRing);
317 FRONT_RING_INIT(&TargetData->Ring, SharedRing, PAGE_SIZE);
318 ref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
319 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
320 0, PFN, FALSE, 0);
321 ASSERT((signed short)ref >= 0);
322 TargetData->ring_detect_state = 0;
323 TargetData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * max(BLK_RING_SIZE, BLK_OTHER_RING_SIZE), XENVBD_POOL_TAG);
325 memset(TargetData->shadow, 0, sizeof(blkif_shadow_t) * max(BLK_RING_SIZE, BLK_OTHER_RING_SIZE));
326 for (i = 0; i < max(BLK_RING_SIZE, BLK_OTHER_RING_SIZE); i++)
327 {
328 TargetData->shadow[i].req.id = i + 1;
329 TargetData->shadow[i].Mdl = AllocatePages(BLKIF_MAX_SEGMENTS_PER_REQUEST); // stupid that we have to do this!
330 TargetData->shadow[i].Buf = MmGetMdlVirtualAddress(TargetData->shadow[i].Mdl);
331 for (j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
332 {
333 TargetData->shadow[i].req.seg[j].gref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
334 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
335 0, (ULONG)MmGetMdlPfnArray(TargetData->shadow[i].Mdl)[j], FALSE, 0);
336 ASSERT((signed short)TargetData->shadow[i].req.seg[j].gref >= 0);
337 }
338 }
339 TargetData->shadow_free = 0;
341 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
342 RtlStringCbCatA(TmpPath, 128, "/protocol");
343 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
344 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
345 XBT_NIL, TmpPath, "%s", XEN_IO_PROTO_ABI_NATIVE);
347 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
348 RtlStringCbCatA(TmpPath, 128, "/ring-ref");
349 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
350 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
351 XBT_NIL, TmpPath, "%d", ref);
353 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
354 RtlStringCbCatA(TmpPath, 128, "/event-channel");
355 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
356 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
357 XBT_NIL, TmpPath, "%d", TargetData->EventChannel);
359 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
360 RtlStringCbCatA(TmpPath, 128, "/state");
361 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
362 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
363 XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
365 /*
366 KdPrint((__DRIVER_NAME " sizeof(blkif_request) = %d\n", sizeof(struct blkif_request)));
367 KdPrint((__DRIVER_NAME " sizeof(blkif_request_segment) = %d\n", sizeof(struct blkif_request_segment)));
368 KdPrint((__DRIVER_NAME " sizeof(blkif_response) = %d\n", sizeof(struct blkif_response)));
369 KdPrint((__DRIVER_NAME " operation = %d\n", (int)((char *)(&req.operation) - (char *)(&req))));
370 KdPrint((__DRIVER_NAME " nr_segments = %d\n", (int)((char *)(&req.nr_segments) - (char *)(&req))));
371 KdPrint((__DRIVER_NAME " handle = %d\n", (int)((char *)(&req.handle) - (char *)(&req))));
372 KdPrint((__DRIVER_NAME " id = %d\n", (int)((char *)(&req.id) - (char *)(&req))));
373 KdPrint((__DRIVER_NAME " sector_number = %d\n", (int)((char *)(&req.sector_number) - (char *)(&req))));
374 KdPrint((__DRIVER_NAME " seg = %d\n", (int)((char *)(&req.seg) - (char *)(&req))));
376 KdPrint((__DRIVER_NAME " id = %d\n", (int)((char *)(&rep.id) - (char *)(&rep))));
377 KdPrint((__DRIVER_NAME " operation = %d\n", (int)((char *)(&rep.operation) - (char *)(&rep))));
378 KdPrint((__DRIVER_NAME " status = %d\n", (int)((char *)(&rep.status) - (char *)(&rep))));
380 KdPrint((__DRIVER_NAME " sizeof(union blkif_sring_entry) = %d\n", sizeof(union blkif_sring_entry)));
381 KdPrint((__DRIVER_NAME " %d\n", (int)((char *)(&entries[1]) - (char *)(&entries[0]))));
382 */
383 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
384 break;
386 case XenbusStateInitialised:
387 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
388 break;
390 case XenbusStateConnected:
391 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
393 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
394 RtlStringCbCatA(TmpPath, 128, "/device-type");
395 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
396 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
397 XBT_NIL, TmpPath, &Value);
398 if (strcmp(Value, "disk") == 0)
399 {
400 KdPrint((__DRIVER_NAME " DeviceType = Disk\n"));
401 TargetData->DeviceType = XENVBD_DEVICETYPE_DISK;
402 }
403 else if (strcmp(Value, "cdrom") == 0)
404 {
405 KdPrint((__DRIVER_NAME " DeviceType = CDROM\n"));
406 TargetData->DeviceType = XENVBD_DEVICETYPE_CDROM;
407 }
408 else
409 {
410 KdPrint((__DRIVER_NAME " DeviceType = %s (This probably won't work!)\n", Value));
411 TargetData->DeviceType = XENVBD_DEVICETYPE_UNKNOWN;
412 }
414 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
415 RtlStringCbCatA(TmpPath, 128, "/type"); // should probably check that this is 'phy' or 'file' or at least not ''
416 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
417 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
418 XBT_NIL, TmpPath, &Value);
419 KdPrint((__DRIVER_NAME " Backend Type = %s\n", Value));
420 ExFreePool(Value);
422 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
423 RtlStringCbCatA(TmpPath, 128, "/mode"); // should store this...
424 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
425 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
426 XBT_NIL, TmpPath, &Value);
427 KdPrint((__DRIVER_NAME " Backend Mode = %s\n", Value));
428 ExFreePool(Value);
430 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
431 RtlStringCbCatA(TmpPath, 128, "/sector-size");
432 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
433 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
434 XBT_NIL, TmpPath, &Value);
435 // should complain if Value == NULL
436 TargetData->BytesPerSector = atoi(Value);
438 KdPrint((__DRIVER_NAME " BytesPerSector = %d\n", TargetData->BytesPerSector));
440 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
441 RtlStringCbCatA(TmpPath, 128, "/sectors");
442 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
443 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
444 XBT_NIL, TmpPath, &Value);
445 // should complain if Value == NULL
446 TargetData->TotalSectors = (ULONGLONG)atol(Value);
448 KdPrint((__DRIVER_NAME " TotalSectors = %d\n", TargetData->TotalSectors));
450 // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
451 TargetData->Geometry.MediaType = FixedMedia;
452 TargetData->Geometry.BytesPerSector = TargetData->BytesPerSector;
453 TargetData->Geometry.SectorsPerTrack = 63;
454 TargetData->Geometry.TracksPerCylinder = 255;
455 TargetData->Geometry.Cylinders.QuadPart = TargetData->TotalSectors / TargetData->Geometry.SectorsPerTrack / TargetData->Geometry.TracksPerCylinder;
456 KdPrint((__DRIVER_NAME " Geometry C/H/S = %d/%d/%d\n", TargetData->Geometry.Cylinders.LowPart, TargetData->Geometry.TracksPerCylinder, TargetData->Geometry.SectorsPerTrack));
458 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
459 RtlStringCbCatA(TmpPath, 128, "/state");
460 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateConnected);
462 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
464 TargetData->Running = 1;
465 KeMemoryBarrier();
467 req = RING_GET_REQUEST(&TargetData->Ring, TargetData->Ring.req_prod_pvt);
468 req->operation = 0xff;
469 req->nr_segments = 0;
470 for (i = 0; i < req->nr_segments; i++)
471 {
472 req->seg[i].gref = 0xffffffff;
473 req->seg[i].first_sect = 0xff;
474 req->seg[i].last_sect = 0xff;
475 }
476 TargetData->Ring.req_prod_pvt++;
478 req = RING_GET_REQUEST(&TargetData->Ring, TargetData->Ring.req_prod_pvt);
479 req->operation = 0xff;
480 req->nr_segments = 0;
481 for (i = 0; i < req->nr_segments; i++)
482 {
483 req->seg[i].gref = 0xffffffff;
484 req->seg[i].first_sect = 0xff;
485 req->seg[i].last_sect = 0xff;
486 }
487 TargetData->Ring.req_prod_pvt++;
489 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&TargetData->Ring, notify);
490 if (notify)
491 DeviceData->XenDeviceData->XenInterface.EvtChn_Notify(
492 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
493 TargetData->EventChannel);
495 InterlockedIncrement(&DeviceData->EnumeratedDevices);
496 KdPrint((__DRIVER_NAME " Added a device\n"));
498 // now ask windows to rescan the scsi bus...
499 // DeviceData->BusChangePending = 1;
500 break;
502 case XenbusStateClosing:
503 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
504 // this behaviour is only to properly close down to then restart in the case of a dump
505 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
506 RtlStringCbCatA(TmpPath, 128, "/state");
507 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateClosed);
508 KdPrint((__DRIVER_NAME " Set Frontend state to Closed\n"));
509 break;
511 case XenbusStateClosed:
512 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
513 // this behaviour is only to properly close down to then restart in the case of a dump
514 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
515 RtlStringCbCatA(TmpPath, 128, "/state");
516 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateInitialising);
517 KdPrint((__DRIVER_NAME " Set Frontend state to Initialising\n"));
518 break;
520 default:
521 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
522 break;
523 }
525 KdPrint((__DRIVER_NAME " <-- BackEndStateHandler\n"));
526 }
528 static VOID
529 XenVbd_WatchHandler(char *Path, PVOID DeviceExtension)
530 {
531 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
532 char **Bits;
533 int Count;
534 char TmpPath[128];
535 char *Value;
536 int CurrentBus, CurrentTarget;
537 PXENVBD_TARGET_DATA TargetData, VacantTarget;
538 KIRQL OldIrql;
539 int i;
541 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "(DeviceData = %p)\n", DeviceData));
542 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
544 KdPrint((__DRIVER_NAME " Path = %s\n", Path));
546 Bits = SplitString(Path, '/', 4, &Count);
547 switch (Count)
548 {
549 case 0:
550 case 1:
551 case 2:
552 break; // should never happen
553 case 3:
554 break;
555 case 4:
556 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
557 break;
559 KeAcquireSpinLock(&DeviceData->Lock, &OldIrql);
561 for (VacantTarget = NULL, i = 0; i < SCSI_BUSES * SCSI_TARGETS_PER_BUS; i++)
562 {
563 CurrentBus = i / SCSI_TARGETS_PER_BUS;
564 CurrentTarget = i % SCSI_TARGETS_PER_BUS;
565 if (CurrentTarget == 7) // don't use 7 - it would be for the controller
566 continue;
567 TargetData = &DeviceData->BusData[CurrentBus].TargetData[CurrentTarget];
568 if (TargetData->Present && strncmp(TargetData->Path, Path, strlen(TargetData->Path)) == 0 && Path[strlen(TargetData->Path)] == '/')
569 break; // already exists
570 else if (!TargetData->Present && VacantTarget == NULL)
571 VacantTarget = TargetData;
572 }
573 if (i == SCSI_BUSES * SCSI_TARGETS_PER_BUS && VacantTarget != NULL)
574 {
575 VacantTarget->Present = 1;
576 KeReleaseSpinLock(&DeviceData->Lock, OldIrql);
578 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
579 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
580 XBT_NIL, Path, &Value);
582 if (Value == NULL)
583 {
584 KdPrint((__DRIVER_NAME " blank state?\n"));
585 break;
586 }
587 if (atoi(Value) != XenbusStateInitialising)
588 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
589 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
590 XBT_NIL, Path, "%d", XenbusStateClosing);
592 RtlStringCbCopyA(VacantTarget->Path, 128, Bits[0]);
593 RtlStringCbCatA(VacantTarget->Path, 128, "/");
594 RtlStringCbCatA(VacantTarget->Path, 128, Bits[1]);
595 RtlStringCbCatA(VacantTarget->Path, 128, "/");
596 RtlStringCbCatA(VacantTarget->Path, 128, Bits[2]);
598 VacantTarget->DeviceIndex = atoi(Bits[2]);
600 RtlStringCbCopyA(TmpPath, 128, VacantTarget->Path);
601 RtlStringCbCatA(TmpPath, 128, "/backend");
602 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
603 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
604 XBT_NIL, TmpPath, &Value);
605 if (Value == NULL)
606 KdPrint((__DRIVER_NAME " Read Failed\n"));
607 else
608 RtlStringCbCopyA(VacantTarget->BackendPath, 128, Value);
609 RtlStringCbCopyA(TmpPath, 128, VacantTarget->BackendPath);
610 RtlStringCbCatA(TmpPath, 128, "/state");
612 DeviceData->XenDeviceData->XenInterface.XenBus_AddWatch(
613 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
614 XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, VacantTarget);
615 }
616 else
617 KeReleaseSpinLock(&DeviceData->Lock, OldIrql);
618 break;
619 }
621 FreeSplitString(Bits, Count);
623 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
625 return;
626 }
628 static VOID
629 XenVbd_EnumerateExisting(PXENVBD_DEVICE_DATA DeviceData)
630 {
631 char *msg;
632 ULONG i;
633 char **VbdDevices;
634 char buffer[128];
635 int TotalInitialDevices = 0;
637 msg = DeviceData->XenDeviceData->XenInterface.XenBus_List(
638 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
639 XBT_NIL, "device/vbd", &VbdDevices);
640 if (!msg)
641 {
642 for (i = 0; VbdDevices[i]; i++)
643 {
644 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
645 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
646 XenVbd_WatchHandler(buffer, DeviceData);
647 TotalInitialDevices++;
648 }
649 }
650 DeviceData->TotalInitialDevices = TotalInitialDevices;
651 }
653 static PXENPCI_XEN_DEVICE_DATA
654 XenVbd_GetXenDeviceData(PPORT_CONFIGURATION_INFORMATION ConfigInfo)
655 {
656 ULONG i;
657 PACCESS_RANGE AccessRange;
658 PXENPCI_XEN_DEVICE_DATA XenDeviceData = NULL;
660 for (i = 0; i < ConfigInfo->NumberOfAccessRanges; i++)
661 {
662 AccessRange = &(*(ConfigInfo->AccessRanges))[i];
663 KdPrint((__DRIVER_NAME " AccessRange %2d: RangeStart = %p, RangeLength = %x, RangeInMemory = %d\n", i, AccessRange->RangeStart.QuadPart, AccessRange->RangeLength, AccessRange->RangeInMemory));
664 switch (i)
665 {
666 case 0:
667 XenDeviceData = (PVOID)(xen_ulong_t)AccessRange->RangeStart.QuadPart;
668 KdPrint((__DRIVER_NAME " Mapped to virtual address %p\n", XenDeviceData));
669 KdPrint((__DRIVER_NAME " Magic = %08x\n", XenDeviceData->Magic));
670 break;
671 default:
672 break;
673 }
674 }
675 return XenDeviceData;
676 }
678 static VOID
679 XenVbd_InitDeviceData(PXENVBD_DEVICE_DATA DeviceData, PPORT_CONFIGURATION_INFORMATION ConfigInfo)
680 {
681 ULONG i, j;
682 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
684 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
686 KeInitializeSpinLock(&DeviceData->Lock);
688 DeviceData->XenDeviceData = XenVbd_GetXenDeviceData(ConfigInfo);
690 for (i = 0; i < SCSI_BUSES; i++)
691 {
692 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
693 {
694 DeviceData->BusData[i].TargetData[j].Present = 0;
695 DeviceData->BusData[i].TargetData[j].Running = 0;
696 DeviceData->BusData[i].TargetData[j].DeviceData = DeviceData;
697 }
698 }
700 DeviceData->XenDeviceData->WatchContext = DeviceData;
701 KeMemoryBarrier();
702 DeviceData->XenDeviceData->WatchHandler = XenVbd_WatchHandler;
704 DeviceData->EnumeratedDevices = 0;
705 DeviceData->TotalInitialDevices = 0;
707 if (DeviceData->XenDeviceData->AutoEnumerate)
708 {
709 DeviceData->TotalInitialDevices = SCSI_BUSES * SCSI_TARGETS_PER_BUS;
710 XenVbd_EnumerateExisting(DeviceData);
711 }
713 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
714 }
716 #endif
717 static ULONG
718 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
719 {
720 ULONG i, j, k;
721 // PACCESS_RANGE AccessRange;
722 PXENVBD_DEVICE_DATA DeviceData; // = ((PXENVBD_DEVICE_EXTENSION)DeviceExtension)->XenVbdDeviceData;
723 // ULONG status;
724 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
726 UNREFERENCED_PARAMETER(HwContext);
727 UNREFERENCED_PARAMETER(BusInformation);
728 UNREFERENCED_PARAMETER(ArgumentString);
730 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
731 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
733 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
734 KdPrint((__DRIVER_NAME " BusInterruptVector = %d\n", ConfigInfo->BusInterruptVector));
736 KdPrint((__DRIVER_NAME " AccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
738 if (KeGetCurrentIrql() == PASSIVE_LEVEL)
739 {
740 DeviceData = ((PXENVBD_DEVICE_EXTENSION)DeviceExtension)->XenVbdDeviceData = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENVBD_DEVICE_DATA), XENVBD_POOL_TAG);
741 // XenVbd_InitDeviceData(DeviceData, ConfigInfo);
742 // if (DeviceData->XenDeviceData->Magic != XEN_DATA_MAGIC)
743 // return SP_RETURN_NOT_FOUND;
744 }
745 #if 0
746 else
747 {
748 DumpMode = TRUE;
749 XenDeviceData = XenVbd_GetXenDeviceData(ConfigInfo);
750 if (XenDeviceData == NULL || XenDeviceData->Magic != XEN_DATA_MAGIC)
751 {
752 return SP_RETURN_NOT_FOUND;
753 }
754 DeviceData = XenDeviceData->WatchContext;
755 ((PXENVBD_DEVICE_EXTENSION)DeviceExtension)->XenVbdDeviceData = DeviceData;
756 DeviceData->XenDeviceData->WatchHandler = XenVbd_WatchHandler;
759 for (i = 0; i < SCSI_BUSES; i++)
760 {
761 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
762 {
763 for (k = 0; k < max(BLK_RING_SIZE, BLK_OTHER_RING_SIZE); k++)
764 {
765 if (DeviceData->BusData[i].TargetData[j].Present)
766 DeviceData->BusData[i].TargetData[j].shadow[k].Srb = NULL;
767 }
768 }
769 }
770 }
771 KdPrint((__DRIVER_NAME " DeviceData = %p\n", DeviceData));
772 #endif
774 DeviceData->DeviceExtension = DeviceExtension;
776 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
777 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
778 ConfigInfo->ScatterGather = TRUE;
779 ConfigInfo->AlignmentMask = 0;
780 ConfigInfo->NumberOfBuses = SCSI_BUSES;
781 for (i = 0; i < ConfigInfo->NumberOfBuses; i++)
782 {
783 ConfigInfo->InitiatorBusId[i] = 7;
784 }
785 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
786 ConfigInfo->MaximumNumberOfTargets = SCSI_TARGETS_PER_BUS;
787 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
788 {
789 ConfigInfo->Master = TRUE;
790 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
791 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
792 }
793 else
794 {
795 ConfigInfo->Master = FALSE;
796 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
797 }
799 // This all has to be initialized here as the real Initialize routine
800 // is called at DIRQL, and the XenBus stuff has to be called at
801 // <= DISPATCH_LEVEL
803 *Again = FALSE;
805 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
807 return SP_RETURN_FOUND;
808 }
810 static VOID
811 XenVbd_CheckBusChangedTimer(PVOID DeviceExtension);
813 static VOID
814 XenVbd_CheckBusEnumeratedTimer(PVOID DeviceExtension)
815 {
816 PXENVBD_DEVICE_DATA DeviceData = ((PXENVBD_DEVICE_EXTENSION)DeviceExtension)->XenVbdDeviceData;
818 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
819 // KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
821 if (DeviceData->EnumeratedDevices >= DeviceData->TotalInitialDevices)
822 {
823 DeviceData->BusChangePending = 0;
824 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
825 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusChangedTimer, 1000000);
826 }
827 else
828 {
829 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusEnumeratedTimer, 100000);
830 }
831 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
832 }
834 static VOID
835 XenVbd_CheckBusChangedTimer(PVOID DeviceExtension)
836 {
837 PXENVBD_DEVICE_DATA DeviceData = ((PXENVBD_DEVICE_EXTENSION)DeviceExtension)->XenVbdDeviceData;
839 if (DeviceData->BusChangePending)
840 {
841 ScsiPortNotification(BusChangeDetected, DeviceExtension, 0);
842 DeviceData->BusChangePending = 0;
843 }
844 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusChangedTimer, 1000000);
845 }
847 static BOOLEAN
848 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
849 {
850 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
851 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
853 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusEnumeratedTimer, 100000);
855 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
857 return TRUE;
858 }
860 static ULONG
861 XenVbd_FillModePage(PXENVBD_DEVICE_DATA DeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
862 {
863 //PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
865 UNREFERENCED_PARAMETER(DeviceData);
866 UNREFERENCED_PARAMETER(DataBuffer);
867 UNREFERENCED_PARAMETER(BufferLength);
868 UNREFERENCED_PARAMETER(Offset);
870 switch (PageCode)
871 {
872 /*
873 case MODE_PAGE_RIGID_GEOMETRY:
874 if (DeviceData->ScsiData->DeviceType == XENVBD_DEVICETYPE_CDROM)
875 {
876 KdPrint((__DRIVER_NAME " MODE_PAGE_RIGID_GEOMETRY\n"));
877 if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
878 return 1;
879 ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
880 memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
881 ModeRigidGeometry->PageCode = PageCode;
882 ModeRigidGeometry->PageSavable = 0;
883 ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
884 ModeRigidGeometry->NumberOfCylinders[0] = (DeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF;
885 ModeRigidGeometry->NumberOfCylinders[1] = (DeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF;
886 ModeRigidGeometry->NumberOfCylinders[2] = (DeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF;
887 ModeRigidGeometry->NumberOfHeads = DeviceData->Geometry.TracksPerCylinder;
888 //ModeRigidGeometry->LandZoneCyclinder = 0;
889 ModeRigidGeometry->RoataionRate[0] = 0x05;
890 ModeRigidGeometry->RoataionRate[0] = 0x39;
891 *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
892 }
893 break;
894 */
895 case MODE_PAGE_FAULT_REPORTING:
896 break;
897 default:
898 break;
899 }
900 return 0;
901 }
903 static VOID
904 XenVbd_PutRequest(PXENVBD_TARGET_DATA TargetData, blkif_request_t *req)
905 {
906 blkif_other_request_t *other_req;
908 if (!TargetData->use_other)
909 {
910 *RING_GET_REQUEST(&TargetData->Ring, TargetData->Ring.req_prod_pvt) = *req;
911 }
912 else
913 {
914 other_req = RING_GET_REQUEST(&TargetData->OtherRing, TargetData->Ring.req_prod_pvt);
915 other_req->operation = req->operation;
916 other_req->nr_segments = req->nr_segments;
917 other_req->handle = req->handle;
918 other_req->id = req->id;
919 other_req->sector_number = req->sector_number;
920 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
921 }
922 TargetData->Ring.req_prod_pvt++;
923 }
925 // Call with device lock held
926 static VOID
927 XenVbd_PutSrbOnRing(PXENVBD_TARGET_DATA TargetData, PSCSI_REQUEST_BLOCK Srb)
928 {
929 //PUCHAR DataBuffer;
930 int i;
931 int BlockCount;
932 blkif_shadow_t *shadow;
933 uint64_t id;
935 // can use SRB_STATUS_BUSY to push the SRB back to windows...
937 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
939 if (RING_FULL(&TargetData->Ring))
940 {
941 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
942 // TODO: Fail badly here
943 }
945 id = GET_ID_FROM_FREELIST(TargetData);
946 if (id == 0x0fffffff)
947 {
948 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutSrbOnRing\n"));
949 }
951 shadow = &TargetData->shadow[id];
952 shadow->req.id = id;
954 shadow->req.sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
955 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
956 shadow->req.handle = 0;
957 shadow->req.operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
958 shadow->Srb = Srb;
960 shadow->req.nr_segments = (UINT8)((BlockCount * TargetData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE);
962 for (i = 0; i < shadow->req.nr_segments; i++)
963 {
964 /*
965 shadow->req.seg[i].gref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
966 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
967 0, (ULONG)MmGetMdlPfnArray(TargetData->shadow[shadow->req.id].Mdl)[i], FALSE);
968 ASSERT((signed short)shadow->req.seg[i].gref >= 0);
969 */
970 shadow->req.seg[i].first_sect = 0;
971 if (i == shadow->req.nr_segments - 1)
972 shadow->req.seg[i].last_sect = (UINT8)((BlockCount - 1) % (PAGE_SIZE / TargetData->BytesPerSector));
973 else
974 shadow->req.seg[i].last_sect = (UINT8)(PAGE_SIZE / TargetData->BytesPerSector - 1);
975 }
976 if (Srb->Cdb[0] == SCSIOP_WRITE)
977 memcpy(TargetData->shadow[shadow->req.id].Buf, Srb->DataBuffer, BlockCount * TargetData->BytesPerSector);
979 XenVbd_PutRequest(TargetData, &shadow->req);
981 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
982 }
984 static BOOLEAN
985 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
986 {
987 PUCHAR DataBuffer;
988 PCDB cdb;
989 PXENVBD_DEVICE_DATA DeviceData = ((PXENVBD_DEVICE_EXTENSION)DeviceExtension)->XenVbdDeviceData;
990 PXENVBD_TARGET_DATA TargetData;
991 unsigned int i;
992 int notify;
994 KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
996 __asm { int 0x91 };
997 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
998 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
999 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1001 #if 0
1002 // KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1004 // If we haven't enumerated all the devices yet then just defer the request
1005 // A timer will issue a NextRequest to get things started again...
1006 if (DeviceData->EnumeratedDevices < DeviceData->TotalInitialDevices)
1008 Srb->SrbStatus = SRB_STATUS_BUSY;
1009 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1010 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (NotEnumeratedYet)\n"));
1011 return TRUE;
1014 if (Srb->PathId >= SCSI_BUSES || Srb->TargetId >= SCSI_TARGETS_PER_BUS)
1016 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1017 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1018 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1019 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
1020 return TRUE;
1023 TargetData = &DeviceData->BusData[Srb->PathId].TargetData[Srb->TargetId];
1025 if (!TargetData->Running)
1027 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1028 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1029 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1030 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Not Present)\n"));
1031 return TRUE;
1034 switch (Srb->Function)
1036 case SRB_FUNCTION_EXECUTE_SCSI:
1037 cdb = (PCDB)Srb->Cdb;
1038 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
1040 switch(cdb->CDB6GENERIC.OperationCode)
1042 case SCSIOP_TEST_UNIT_READY:
1043 // KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
1044 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1045 Srb->ScsiStatus = 0;
1046 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1047 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1048 break;
1049 case SCSIOP_INQUIRY:
1050 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
1051 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
1052 KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
1053 KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
1054 DataBuffer = Srb->DataBuffer;
1055 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1056 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1057 switch (TargetData->DeviceType)
1059 case XENVBD_DEVICETYPE_DISK:
1060 if ((Srb->Cdb[1] & 1) == 0)
1062 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
1063 DataBuffer[1] = 0x00; // not removable
1064 DataBuffer[3] = 32;
1065 memcpy(DataBuffer + 8, "XEN ", 8); // vendor id
1066 memcpy(DataBuffer + 16, "PV VBD ", 16); // product id
1067 memcpy(DataBuffer + 32, "0000", 4); // product revision level
1069 else
1071 switch (Srb->Cdb[2])
1073 case 0x00:
1074 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
1075 DataBuffer[1] = 0x00;
1076 DataBuffer[2] = 0x00;
1077 DataBuffer[3] = 2;
1078 DataBuffer[4] = 0x00;
1079 DataBuffer[5] = 0x80;
1080 break;
1081 case 0x80:
1082 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
1083 DataBuffer[1] = 0x80;
1084 DataBuffer[2] = 0x00;
1085 DataBuffer[3] = 8;
1086 DataBuffer[4] = 0x31;
1087 DataBuffer[5] = 0x32;
1088 DataBuffer[6] = 0x33;
1089 DataBuffer[7] = 0x34;
1090 DataBuffer[8] = 0x35;
1091 DataBuffer[9] = 0x36;
1092 DataBuffer[10] = 0x37;
1093 DataBuffer[11] = 0x38;
1094 break;
1095 default:
1096 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1097 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1098 break;
1101 break;
1102 case XENVBD_DEVICETYPE_CDROM:
1103 if ((Srb->Cdb[1] & 1) == 0)
1105 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1106 DataBuffer[1] = 0x01; // removable
1107 DataBuffer[3] = 32;
1108 memcpy(DataBuffer + 8, "XEN ", 8); // vendor id
1109 memcpy(DataBuffer + 16, "PV VBD ", 16); // product id
1110 memcpy(DataBuffer + 32, "0000", 4); // product revision level
1112 else
1114 switch (Srb->Cdb[2])
1116 case 0x00:
1117 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1118 DataBuffer[1] = 0x00;
1119 DataBuffer[2] = 0x00;
1120 DataBuffer[3] = 2;
1121 DataBuffer[4] = 0x00;
1122 DataBuffer[5] = 0x80;
1123 break;
1124 case 0x80:
1125 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1126 DataBuffer[1] = 0x80;
1127 DataBuffer[2] = 0x00;
1128 DataBuffer[3] = 8;
1129 DataBuffer[4] = 0x31;
1130 DataBuffer[5] = 0x32;
1131 DataBuffer[6] = 0x33;
1132 DataBuffer[7] = 0x34;
1133 DataBuffer[8] = 0x35;
1134 DataBuffer[9] = 0x36;
1135 DataBuffer[10] = 0x37;
1136 DataBuffer[11] = 0x38;
1137 break;
1138 default:
1139 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1140 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1141 break;
1144 break;
1145 default:
1146 KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", TargetData->DeviceType));
1147 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1148 break;
1150 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1151 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1152 break;
1153 case SCSIOP_READ_CAPACITY:
1154 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1155 DataBuffer = Srb->DataBuffer;
1156 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1157 DataBuffer[0] = (unsigned char)((TargetData->TotalSectors - 1) >> 24) & 0xff;
1158 DataBuffer[1] = (unsigned char)((TargetData->TotalSectors - 1) >> 16) & 0xff;
1159 DataBuffer[2] = (unsigned char)((TargetData->TotalSectors - 1) >> 8) & 0xff;
1160 DataBuffer[3] = (unsigned char)((TargetData->TotalSectors - 1) >> 0) & 0xff;
1161 DataBuffer[4] = (unsigned char)(TargetData->BytesPerSector >> 24) & 0xff;
1162 DataBuffer[5] = (unsigned char)(TargetData->BytesPerSector >> 16) & 0xff;
1163 DataBuffer[6] = (unsigned char)(TargetData->BytesPerSector >> 8) & 0xff;
1164 DataBuffer[7] = (unsigned char)(TargetData->BytesPerSector >> 0) & 0xff;
1165 Srb->ScsiStatus = 0;
1166 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1167 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1168 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1169 break;
1170 case SCSIOP_MODE_SENSE:
1171 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));
1172 KdPrint((__DRIVER_NAME " Length = %d\n", Srb->DataTransferLength));
1174 Srb->ScsiStatus = 0;
1175 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1176 Srb->DataTransferLength = 0;
1177 DataBuffer = Srb->DataBuffer;
1178 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1179 switch(cdb->MODE_SENSE.PageCode)
1181 case MODE_SENSE_RETURN_ALL:
1182 //Ptr = (UCHAR *)Srb->DataBuffer;
1183 for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
1185 if (XenVbd_FillModePage(DeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength))
1187 break;
1190 break;
1191 default:
1192 XenVbd_FillModePage(DeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength);
1193 break;
1195 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1196 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1197 break;
1198 case SCSIOP_READ:
1199 case SCSIOP_WRITE:
1200 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1201 XenVbd_PutSrbOnRing(TargetData, Srb);
1202 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&TargetData->Ring, notify);
1203 if (notify)
1204 DeviceData->XenDeviceData->XenInterface.EvtChn_Notify(
1205 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
1206 TargetData->EventChannel);
1207 if (!RING_FULL(&TargetData->Ring) && !DumpMode)
1208 ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
1209 else
1210 ScsiPortNotification(NextRequest, DeviceExtension);
1211 break;
1212 case SCSIOP_VERIFY:
1213 // Should we do more here?
1214 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1215 Srb->SrbStatus = SRB_STATUS_SUCCESS; //SRB_STATUS_INVALID_REQUEST;
1216 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1217 ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
1218 break;
1219 case SCSIOP_REPORT_LUNS:
1220 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1221 Srb->SrbStatus = SRB_STATUS_SUCCESS; //SRB_STATUS_INVALID_REQUEST;
1222 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1223 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1224 break;
1225 case SCSIOP_READ_TOC:
1226 DataBuffer = Srb->DataBuffer;
1227 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1228 /*
1229 #define READ_TOC_FORMAT_TOC 0x00
1230 #define READ_TOC_FORMAT_SESSION 0x01
1231 #define READ_TOC_FORMAT_FULL_TOC 0x02
1232 #define READ_TOC_FORMAT_PMA 0x03
1233 #define READ_TOC_FORMAT_ATIP 0x04
1234 */
1235 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1236 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1237 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1238 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1239 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1240 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1241 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1242 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1243 switch (cdb->READ_TOC.Format2)
1245 case READ_TOC_FORMAT_TOC:
1246 DataBuffer[0] = 0; // length MSB
1247 DataBuffer[1] = 10; // length LSB
1248 DataBuffer[2] = 1; // First Track
1249 DataBuffer[3] = 1; // Last Track
1250 DataBuffer[4] = 0; // Reserved
1251 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1252 DataBuffer[6] = 1; // last complete track
1253 DataBuffer[7] = 0; // reserved
1254 DataBuffer[8] = 0; // MSB Block
1255 DataBuffer[9] = 0;
1256 DataBuffer[10] = 0;
1257 DataBuffer[11] = 0; // LSB Block
1258 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1259 break;
1260 case READ_TOC_FORMAT_SESSION:
1261 case READ_TOC_FORMAT_FULL_TOC:
1262 case READ_TOC_FORMAT_PMA:
1263 case READ_TOC_FORMAT_ATIP:
1264 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1265 break;
1267 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1268 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1269 break;
1270 case SCSIOP_START_STOP_UNIT:
1271 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1272 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1273 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1274 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1275 break;
1276 default:
1277 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1278 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1279 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1280 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1281 break;
1283 break;
1284 case SRB_FUNCTION_CLAIM_DEVICE:
1285 KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
1286 // ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
1287 // Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
1288 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1289 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1290 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1291 break;
1292 case SRB_FUNCTION_IO_CONTROL:
1293 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1294 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1295 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1296 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1297 break;
1298 case SRB_FUNCTION_FLUSH:
1299 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1300 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1301 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1302 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1303 break;
1304 default:
1305 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1306 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1307 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1308 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1309 break;
1311 #endif
1313 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
1314 return TRUE;
1317 static BOOLEAN
1318 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1320 UNREFERENCED_PARAMETER(DeviceExtension);
1321 UNREFERENCED_PARAMETER(PathId);
1324 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1325 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1327 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1329 return TRUE;
1333 static BOOLEAN
1334 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1336 UNREFERENCED_PARAMETER(DeviceExtension);
1337 UNREFERENCED_PARAMETER(Context);
1338 UNREFERENCED_PARAMETER(SaveState);
1340 KdPrint((__DRIVER_NAME " --> HwScsiAdapterState\n"));
1341 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1343 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterState\n"));
1345 return TRUE;
1348 static SCSI_ADAPTER_CONTROL_STATUS
1349 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1351 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1352 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1353 KIRQL OldIrql;
1355 UNREFERENCED_PARAMETER(DeviceExtension);
1357 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
1358 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1360 //KdBreakPoint();
1362 KdPrint((__DRIVER_NAME " int 0x81 (xenvbd)"));
1363 __asm {
1364 cli
1365 int 0x81
1366 sti
1367 };
1369 KeRaiseIrql(7, &OldIrql);
1370 KdPrint((__DRIVER_NAME " int 0x81 (xenvbd)"));
1371 __asm {
1372 int 0x81
1373 };
1374 KeLowerIrql(OldIrql);
1376 KeRaiseIrql(7, &OldIrql);
1377 KdPrint((__DRIVER_NAME " int 0x81 (xenvbd)"));
1378 __asm {
1379 cli
1380 int 0x81
1381 sti
1382 };
1383 KeLowerIrql(OldIrql);
1385 /*
1386 KdPrint((__DRIVER_NAME " int 0x07"));
1387 __asm { int 0x07 };
1389 KdPrint((__DRIVER_NAME " int 0x37"));
1390 __asm { int 0x37 };
1391 */
1393 // KdPrint((__DRIVER_NAME " int 0x83 (xenpci)"));
1394 // __asm { int 0x83 };
1396 switch (ControlType)
1398 case ScsiQuerySupportedControlTypes:
1399 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1400 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1401 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1402 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1403 break;
1404 case ScsiStopAdapter:
1405 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1406 break;
1407 case ScsiRestartAdapter:
1408 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1409 break;
1410 case ScsiSetBootConfig:
1411 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1412 break;
1413 case ScsiSetRunningConfig:
1414 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1415 break;
1416 default:
1417 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1418 break;
1421 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
1423 return Status;