win-pvdrivers

view xenvbd/xenvbd.c @ 181:762547e8a0db

add James' description of what's going on in HwScsiInterruptTarget
author Andy Grover <andy.grover@oracle.com>
date Mon Feb 11 15:54:10 2008 -0800 (2008-02-11)
parents f4c428c040ea
children 8c87bd40fe36
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 //#define BUF_PAGES_PER_SRB 11
18 DRIVER_INITIALIZE DriverEntry;
20 static ULONG
21 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again);
22 static BOOLEAN
23 XenVbd_HwScsiInitialize(PVOID DeviceExtension);
24 static BOOLEAN
25 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb);
26 static BOOLEAN
27 XenVbd_HwScsiInterrupt(PVOID DeviceExtension);
28 static BOOLEAN
29 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId);
30 static BOOLEAN
31 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState);
32 static SCSI_ADAPTER_CONTROL_STATUS
33 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters);
35 #ifdef ALLOC_PRAGMA
36 #pragma alloc_text (INIT, DriverEntry)
37 #endif
39 //static BOOLEAN AutoEnumerate;
41 NTSTATUS
42 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
43 {
44 ULONG Status;
45 HW_INITIALIZATION_DATA HwInitializationData;
47 KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
48 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
50 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
52 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
53 HwInitializationData.AdapterInterfaceType = Internal; //PNPBus;
54 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
55 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
56 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
57 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
58 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
59 HwInitializationData.HwDmaStarted = NULL;
60 HwInitializationData.HwAdapterState = XenVbd_HwScsiAdapterState;
61 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
62 HwInitializationData.SpecificLuExtensionSize = 0;
63 HwInitializationData.SrbExtensionSize = 0;
64 HwInitializationData.NumberOfAccessRanges = 1;
65 HwInitializationData.MapBuffers = TRUE;
66 HwInitializationData.NeedPhysicalAddresses = FALSE;
67 HwInitializationData.TaggedQueuing = TRUE;
68 HwInitializationData.AutoRequestSense = FALSE;
69 HwInitializationData.MultipleRequestPerLu = TRUE;
70 HwInitializationData.ReceiveEvent = FALSE;
71 HwInitializationData.VendorIdLength = 0;
72 HwInitializationData.VendorId = NULL;
73 HwInitializationData.DeviceIdLength = 0;
74 HwInitializationData.DeviceId = NULL;
75 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
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 while (more_to_do)
150 {
151 rp = TargetData->Ring.sring->rsp_prod;
152 KeMemoryBarrier();
153 for (i = TargetData->Ring.rsp_cons; i != rp; i++)
154 {
155 rep = XenVbd_GetResponse(TargetData, i);
157 //KdPrint((__DRIVER_NAME " rep = %p\n", rep));
158 //KdPrint((__DRIVER_NAME " rep->id = %d\n", rep->id));
160 /*
161 * This code is to automatically detect if the backend is using the same
162 * bit width or a different bit width to us. Later versions of Xen do this
163 * via a xenstore value, but not all. That 0x0fffffff (notice
164 * that the msb is not actually set, so we don't have any problems with
165 * sign extending) is to signify the last entry on the right, which is
166 * different under 32 and 64 bits, and that is why we set it up there.
168 * To do the detection, we put two initial entries on the ring, with an op
169 * of 0xff (which is invalid). The first entry is mostly okay, but the
170 * second will be grossly misaligned if the backend bit width is different,
171 * and we detect this and switch frontend structures.
172 */
173 switch (TargetData->ring_detect_state)
174 {
175 case 0:
176 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", TargetData->ring_detect_state, rep->operation, rep->id, rep->status));
177 TargetData->ring_detect_state = 1;
178 break;
179 case 1:
180 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", TargetData->ring_detect_state, rep->operation, rep->id, rep->status));
181 if (rep->operation != 0xff)
182 {
183 TargetData->Ring.nr_ents = BLK_OTHER_RING_SIZE;
184 TargetData->use_other = TRUE;
185 }
186 TargetData->shadow[TargetData->Ring.nr_ents - 1].req.id = 0x0fffffff;
187 DeviceData->BusChangePending = 1;
188 TargetData->ring_detect_state = 2;
189 break;
190 case 2:
191 Srb = TargetData->shadow[rep->id].Srb;
192 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
194 if (rep->status == BLKIF_RSP_OKAY)
195 Srb->SrbStatus = SRB_STATUS_SUCCESS;
196 else
197 {
198 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
199 if (Srb->Cdb[0] == SCSIOP_READ)
200 KdPrint((__DRIVER_NAME " Operation = Read\n"));
201 else
202 KdPrint((__DRIVER_NAME " Operation = Write\n"));
203 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", TargetData->shadow[rep->id].req.sector_number, BlockCount));
204 Srb->SrbStatus = SRB_STATUS_ERROR;
205 }
206 /*
207 for (j = 0; j < TargetData->shadow[rep->id].req.nr_segments; j++)
208 DeviceData->XenDeviceData->XenInterface.GntTbl_EndAccess(
209 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
210 TargetData->shadow[rep->id].req.seg[j].gref);
211 */
212 if (Srb->Cdb[0] == SCSIOP_READ)
213 memcpy(Srb->DataBuffer, TargetData->shadow[rep->id].Buf, BlockCount * TargetData->BytesPerSector);
215 ScsiPortNotification(RequestComplete, DeviceData, Srb);
216 ScsiPortNotification(NextLuRequest, DeviceData, Srb->PathId, Srb->TargetId, Srb->Lun);
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 // KdPrint((__DRIVER_NAME " <-- HwScsiInterruptTarget\n"));
235 }
237 static BOOLEAN
238 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
239 {
240 PXENVBD_DEVICE_DATA DeviceData;
241 PXENVBD_TARGET_DATA TargetData;
242 int i, j;
244 // KdPrint((__DRIVER_NAME " --> HwScsiInterrupt\n"));
246 DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
248 KeMemoryBarrier();
249 for (i = 0; i < SCSI_BUSES; i++)
250 {
251 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
252 {
253 TargetData = &DeviceData->BusData[i].TargetData[j];
254 if (TargetData->PendingInterrupt)
255 XenVbd_HwScsiInterruptTarget(TargetData);
256 TargetData->PendingInterrupt = FALSE;
257 }
258 }
259 // KdPrint((__DRIVER_NAME " <-- HwScsiInterrupt\n"));
261 return TRUE;
262 }
264 static VOID
265 XenVbd_BackEndStateHandler(char *Path, PVOID Data)
266 {
267 PXENVBD_TARGET_DATA TargetData;
268 PXENVBD_DEVICE_DATA DeviceData;
269 char TmpPath[128];
270 char *Value;
271 int NewState;
272 PMDL Mdl;
273 grant_ref_t ref;
274 blkif_sring_t *SharedRing;
275 ULONG PFN;
276 ULONG i, j;
277 blkif_request_t *req;
278 int notify;
280 KdPrint((__DRIVER_NAME " --> BackEndStateHandler\n"));
281 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
283 TargetData = (PXENVBD_TARGET_DATA)Data;
284 DeviceData = (PXENVBD_DEVICE_DATA)TargetData->DeviceData;
286 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
287 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
288 XBT_NIL, Path, &Value);
290 NewState = atoi(Value);
291 switch (NewState)
292 {
293 case XenbusStateUnknown:
294 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
295 break;
297 case XenbusStateInitialising:
298 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
299 break;
301 case XenbusStateInitWait:
302 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
304 TargetData->EventChannel = DeviceData->XenDeviceData->XenInterface.EvtChn_AllocUnbound(
305 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, 0);
306 DeviceData->XenDeviceData->XenInterface.EvtChn_Bind(
307 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
308 TargetData->EventChannel, XenVbd_Interrupt, TargetData);
309 Mdl = AllocatePage();
310 PFN = (ULONG)*MmGetMdlPfnArray(Mdl);
311 SharedRing = (blkif_sring_t *)MmGetMdlVirtualAddress(Mdl);
312 RtlZeroMemory(SharedRing, PAGE_SIZE);
313 SHARED_RING_INIT(SharedRing);
314 FRONT_RING_INIT(&TargetData->Ring, SharedRing, PAGE_SIZE);
315 ref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
316 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
317 0, PFN, FALSE);
318 ASSERT((signed short)ref >= 0);
319 TargetData->ring_detect_state = 0;
320 TargetData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(blkif_shadow_t) * max(BLK_RING_SIZE, BLK_OTHER_RING_SIZE), XENVBD_POOL_TAG);
322 memset(TargetData->shadow, 0, sizeof(blkif_shadow_t) * max(BLK_RING_SIZE, BLK_OTHER_RING_SIZE));
323 for (i = 0; i < max(BLK_RING_SIZE, BLK_OTHER_RING_SIZE); i++)
324 {
325 TargetData->shadow[i].req.id = i + 1;
326 TargetData->shadow[i].Mdl = AllocatePages(BLKIF_MAX_SEGMENTS_PER_REQUEST); // stupid that we have to do this!
327 TargetData->shadow[i].Buf = MmGetMdlVirtualAddress(TargetData->shadow[i].Mdl);
328 for (j = 0; j < BLKIF_MAX_SEGMENTS_PER_REQUEST; j++)
329 {
330 TargetData->shadow[i].req.seg[j].gref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
331 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
332 0, (ULONG)MmGetMdlPfnArray(TargetData->shadow[i].Mdl)[j], FALSE);
333 ASSERT((signed short)TargetData->shadow[i].req.seg[j].gref >= 0);
334 }
335 }
336 TargetData->shadow_free = 0;
338 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
339 RtlStringCbCatA(TmpPath, 128, "/protocol");
340 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
341 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
342 XBT_NIL, TmpPath, "%s", XEN_IO_PROTO_ABI_NATIVE);
344 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
345 RtlStringCbCatA(TmpPath, 128, "/ring-ref");
346 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
347 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
348 XBT_NIL, TmpPath, "%d", ref);
350 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
351 RtlStringCbCatA(TmpPath, 128, "/event-channel");
352 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
353 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
354 XBT_NIL, TmpPath, "%d", TargetData->EventChannel);
356 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
357 RtlStringCbCatA(TmpPath, 128, "/state");
358 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
359 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
360 XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
362 /*
363 KdPrint((__DRIVER_NAME " sizeof(blkif_request) = %d\n", sizeof(struct blkif_request)));
364 KdPrint((__DRIVER_NAME " sizeof(blkif_request_segment) = %d\n", sizeof(struct blkif_request_segment)));
365 KdPrint((__DRIVER_NAME " sizeof(blkif_response) = %d\n", sizeof(struct blkif_response)));
366 KdPrint((__DRIVER_NAME " operation = %d\n", (int)((char *)(&req.operation) - (char *)(&req))));
367 KdPrint((__DRIVER_NAME " nr_segments = %d\n", (int)((char *)(&req.nr_segments) - (char *)(&req))));
368 KdPrint((__DRIVER_NAME " handle = %d\n", (int)((char *)(&req.handle) - (char *)(&req))));
369 KdPrint((__DRIVER_NAME " id = %d\n", (int)((char *)(&req.id) - (char *)(&req))));
370 KdPrint((__DRIVER_NAME " sector_number = %d\n", (int)((char *)(&req.sector_number) - (char *)(&req))));
371 KdPrint((__DRIVER_NAME " seg = %d\n", (int)((char *)(&req.seg) - (char *)(&req))));
373 KdPrint((__DRIVER_NAME " id = %d\n", (int)((char *)(&rep.id) - (char *)(&rep))));
374 KdPrint((__DRIVER_NAME " operation = %d\n", (int)((char *)(&rep.operation) - (char *)(&rep))));
375 KdPrint((__DRIVER_NAME " status = %d\n", (int)((char *)(&rep.status) - (char *)(&rep))));
377 KdPrint((__DRIVER_NAME " sizeof(union blkif_sring_entry) = %d\n", sizeof(union blkif_sring_entry)));
378 KdPrint((__DRIVER_NAME " %d\n", (int)((char *)(&entries[1]) - (char *)(&entries[0]))));
379 */
380 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
381 break;
383 case XenbusStateInitialised:
384 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
385 break;
387 case XenbusStateConnected:
388 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
390 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
391 RtlStringCbCatA(TmpPath, 128, "/device-type");
392 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
393 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
394 XBT_NIL, TmpPath, &Value);
395 if (strcmp(Value, "disk") == 0)
396 {
397 KdPrint((__DRIVER_NAME " DeviceType = Disk\n"));
398 TargetData->DeviceType = XENVBD_DEVICETYPE_DISK;
399 }
400 else if (strcmp(Value, "cdrom") == 0)
401 {
402 KdPrint((__DRIVER_NAME " DeviceType = CDROM\n"));
403 TargetData->DeviceType = XENVBD_DEVICETYPE_CDROM;
404 }
405 else
406 {
407 KdPrint((__DRIVER_NAME " DeviceType = %s (This probably won't work!)\n", Value));
408 TargetData->DeviceType = XENVBD_DEVICETYPE_UNKNOWN;
409 }
411 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
412 RtlStringCbCatA(TmpPath, 128, "/type"); // should probably check that this is 'phy' or 'file' or at least not ''
413 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
414 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
415 XBT_NIL, TmpPath, &Value);
416 KdPrint((__DRIVER_NAME " Backend Type = %s\n", Value));
417 ExFreePool(Value);
419 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
420 RtlStringCbCatA(TmpPath, 128, "/mode"); // should store this...
421 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
422 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
423 XBT_NIL, TmpPath, &Value);
424 KdPrint((__DRIVER_NAME " Backend Mode = %s\n", Value));
425 ExFreePool(Value);
427 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
428 RtlStringCbCatA(TmpPath, 128, "/sector-size");
429 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
430 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
431 XBT_NIL, TmpPath, &Value);
432 // should complain if Value == NULL
433 TargetData->BytesPerSector = atoi(Value);
435 KdPrint((__DRIVER_NAME " BytesPerSector = %d\n", TargetData->BytesPerSector));
437 RtlStringCbCopyA(TmpPath, 128, TargetData->BackendPath);
438 RtlStringCbCatA(TmpPath, 128, "/sectors");
439 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
440 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
441 XBT_NIL, TmpPath, &Value);
442 // should complain if Value == NULL
443 TargetData->TotalSectors = (ULONGLONG)atol(Value);
445 KdPrint((__DRIVER_NAME " TotalSectors = %d\n", TargetData->TotalSectors));
447 // should probably use the partition table (if one exists) here for the sectorspertrack and trackspercylinder values
448 TargetData->Geometry.MediaType = FixedMedia;
449 TargetData->Geometry.BytesPerSector = TargetData->BytesPerSector;
450 TargetData->Geometry.SectorsPerTrack = 63;
451 TargetData->Geometry.TracksPerCylinder = 255;
452 TargetData->Geometry.Cylinders.QuadPart = TargetData->TotalSectors / TargetData->Geometry.SectorsPerTrack / TargetData->Geometry.TracksPerCylinder;
453 KdPrint((__DRIVER_NAME " Geometry C/H/S = %d/%d/%d\n", TargetData->Geometry.Cylinders.LowPart, TargetData->Geometry.TracksPerCylinder, TargetData->Geometry.SectorsPerTrack));
455 req = RING_GET_REQUEST(&TargetData->Ring, TargetData->Ring.req_prod_pvt);
456 req->operation = 0xff;
457 req->nr_segments = 0;
458 for (i = 0; i < req->nr_segments; i++)
459 {
460 req->seg[i].gref = 0xffffffff;
461 req->seg[i].first_sect = 0xff;
462 req->seg[i].last_sect = 0xff;
463 }
464 TargetData->Ring.req_prod_pvt++;
465 req = RING_GET_REQUEST(&TargetData->Ring, TargetData->Ring.req_prod_pvt);
466 req->operation = 0xff;
467 req->nr_segments = 0;
468 for (i = 0; i < req->nr_segments; i++)
469 {
470 req->seg[i].gref = 0xffffffff;
471 req->seg[i].first_sect = 0xff;
472 req->seg[i].last_sect = 0xff;
473 }
474 TargetData->Ring.req_prod_pvt++;
475 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&TargetData->Ring, notify);
476 if (notify)
477 DeviceData->XenDeviceData->XenInterface.EvtChn_Notify(
478 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
479 TargetData->EventChannel);
481 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
482 RtlStringCbCatA(TmpPath, 128, "/state");
483 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateConnected);
485 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
486 InterlockedIncrement(&DeviceData->EnumeratedDevices);
487 KdPrint((__DRIVER_NAME " Added a device\n"));
489 // now ask windows to rescan the scsi bus...
490 // DeviceData->BusChangePending = 1;
491 break;
493 case XenbusStateClosing:
494 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
495 // this behaviour is only to properly close down to then restart in the case of a dump
496 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
497 RtlStringCbCatA(TmpPath, 128, "/state");
498 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateClosed);
499 KdPrint((__DRIVER_NAME " Set Frontend state to Closed\n"));
500 break;
502 case XenbusStateClosed:
503 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\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", XenbusStateInitialising);
508 KdPrint((__DRIVER_NAME " Set Frontend state to Initialising\n"));
509 break;
511 default:
512 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
513 break;
514 }
516 KdPrint((__DRIVER_NAME " <-- BackEndStateHandler\n"));
517 }
519 static VOID
520 XenVbd_WatchHandler(char *Path, PVOID DeviceExtension)
521 {
522 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
523 char **Bits;
524 int Count;
525 char TmpPath[128];
526 char *Value;
527 int CurrentBus, CurrentTarget;
528 PXENVBD_TARGET_DATA TargetData, VacantTarget;
529 KIRQL OldIrql;
530 int i;
532 KdPrint((__DRIVER_NAME " --> WatchHandler (DeviceData = %p)\n", DeviceData));
533 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
535 KdPrint((__DRIVER_NAME " Path = %s\n", Path));
537 Bits = SplitString(Path, '/', 4, &Count);
538 switch (Count)
539 {
540 case 0:
541 case 1:
542 case 2:
543 break; // should never happen
544 case 3:
545 break;
546 case 4:
547 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
548 break;
550 KeAcquireSpinLock(&DeviceData->Lock, &OldIrql);
552 for (VacantTarget = NULL,i = 0; i < SCSI_BUSES * SCSI_TARGETS_PER_BUS; i++)
553 {
554 CurrentBus = i / SCSI_TARGETS_PER_BUS;
555 CurrentTarget = i % SCSI_TARGETS_PER_BUS;
556 if (CurrentTarget == 7) // don't use 7 - it would be for the controller
557 continue;
558 TargetData = &DeviceData->BusData[CurrentBus].TargetData[CurrentTarget];
559 if (TargetData->Present && strncmp(TargetData->Path, Path, strlen(TargetData->Path)) == 0 && Path[strlen(TargetData->Path)] == '/')
560 break; // already exists
561 else if (!TargetData->Present && VacantTarget == NULL)
562 VacantTarget = TargetData;
563 }
564 if (i == SCSI_BUSES * SCSI_TARGETS_PER_BUS && VacantTarget != NULL)
565 {
566 VacantTarget->Present = 1;
567 KeReleaseSpinLock(&DeviceData->Lock, OldIrql);
569 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
570 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
571 XBT_NIL, Path, &Value);
573 if (Value == NULL)
574 {
575 KdPrint((__DRIVER_NAME " blank state?\n"));
576 break;
577 }
578 if (atoi(Value) != XenbusStateInitialising)
579 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
580 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
581 XBT_NIL, Path, "%d", XenbusStateClosing);
583 RtlStringCbCopyA(VacantTarget->Path, 128, Bits[0]);
584 RtlStringCbCatA(VacantTarget->Path, 128, "/");
585 RtlStringCbCatA(VacantTarget->Path, 128, Bits[1]);
586 RtlStringCbCatA(VacantTarget->Path, 128, "/");
587 RtlStringCbCatA(VacantTarget->Path, 128, Bits[2]);
589 VacantTarget->DeviceIndex = atoi(Bits[2]);
591 RtlStringCbCopyA(TmpPath, 128, VacantTarget->Path);
592 RtlStringCbCatA(TmpPath, 128, "/backend");
593 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
594 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
595 XBT_NIL, TmpPath, &Value);
596 if (Value == NULL)
597 KdPrint((__DRIVER_NAME " Read Failed\n"));
598 else
599 RtlStringCbCopyA(VacantTarget->BackendPath, 128, Value);
600 RtlStringCbCopyA(TmpPath, 128, VacantTarget->BackendPath);
601 RtlStringCbCatA(TmpPath, 128, "/state");
603 DeviceData->XenDeviceData->XenInterface.XenBus_AddWatch(
604 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
605 XBT_NIL, TmpPath, XenVbd_BackEndStateHandler, VacantTarget);
606 }
607 else
608 KeReleaseSpinLock(&DeviceData->Lock, OldIrql);
609 break;
610 }
612 FreeSplitString(Bits, Count);
614 KdPrint((__DRIVER_NAME " <-- WatchHandler\n"));
616 return;
617 }
619 static ULONG
620 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
621 {
622 ULONG i, j;
623 PACCESS_RANGE AccessRange;
624 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
625 char **VbdDevices;
626 char *msg;
627 char buffer[128];
629 UNREFERENCED_PARAMETER(HwContext);
630 UNREFERENCED_PARAMETER(BusInformation);
631 UNREFERENCED_PARAMETER(ArgumentString);
632 KeInitializeSpinLock(&DeviceData->Lock);
633 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
634 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
636 // testing this for dump mode
637 // if (KeGetCurrentIrql() > ConfigInfo->BusInterruptLevel)
638 // ConfigInfo->BusInterruptLevel = KeGetCurrentIrql();
640 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
641 KdPrint((__DRIVER_NAME " BusInterruptVector = %d\n", ConfigInfo->BusInterruptVector));
643 KdPrint((__DRIVER_NAME " AccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
645 for (i = 0; i < ConfigInfo->NumberOfAccessRanges; i++)
646 {
647 AccessRange = &(*(ConfigInfo->AccessRanges))[i];
648 KdPrint((__DRIVER_NAME " AccessRange %2d: RangeStart = %p, RangeLength = %x, RangeInMemory = %d\n", i, AccessRange->RangeStart.QuadPart, AccessRange->RangeLength, AccessRange->RangeInMemory));
649 switch (i)
650 {
651 case 0:
652 DeviceData->XenDeviceData = (PVOID)(xen_ulong_t)AccessRange->RangeStart.QuadPart;
653 KdPrint((__DRIVER_NAME " Mapped to virtual address %p\n", DeviceData->XenDeviceData));
654 KdPrint((__DRIVER_NAME " Magic = %08x\n", DeviceData->XenDeviceData->Magic));
655 if (DeviceData->XenDeviceData->Magic != XEN_DATA_MAGIC)
656 {
657 KdPrint((__DRIVER_NAME " Invalid Magic Number\n"));
658 return SP_RETURN_NOT_FOUND;
659 }
660 break;
661 default:
662 break;
663 }
664 }
665 #if defined(__x86_64__)
666 ConfigInfo->Master = TRUE; // Won't work under x64 without this...
667 #endif
668 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
669 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
670 ConfigInfo->ScatterGather = TRUE;
671 ConfigInfo->AlignmentMask = 0;
672 ConfigInfo->NumberOfBuses = SCSI_BUSES;
673 for (i = 0; i < ConfigInfo->NumberOfBuses; i++)
674 {
675 ConfigInfo->InitiatorBusId[i] = 7;
676 }
677 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
678 ConfigInfo->MaximumNumberOfTargets = SCSI_TARGETS_PER_BUS;
679 // ConfigInfo->TaggedQueueing = TRUE;
680 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
681 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
682 // This all has to be initialized here as the real Initialize routine
683 // is called at DIRQL, and the XenBus stuff has to be called at
684 // <= DISPATCH_LEVEL
686 for (i = 0; i < SCSI_BUSES; i++)
687 {
688 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
689 {
690 DeviceData->BusData[i].TargetData[j].Present = 0;
691 DeviceData->BusData[i].TargetData[j].DeviceData = DeviceData;
692 }
693 }
695 DeviceData->XenDeviceData->WatchContext = DeviceExtension;
696 KeMemoryBarrier();
697 DeviceData->XenDeviceData->WatchHandler = XenVbd_WatchHandler;
699 // KeInitializeEvent(&DeviceData->WaitDevicesEvent, SynchronizationEvent, FALSE);
700 DeviceData->EnumeratedDevices = 0;
701 DeviceData->TotalInitialDevices = 0;
703 if (DeviceData->XenDeviceData->AutoEnumerate)
704 {
705 msg = DeviceData->XenDeviceData->XenInterface.XenBus_List(
706 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
707 XBT_NIL, "device/vbd", &VbdDevices);
708 if (!msg)
709 {
710 for (i = 0; VbdDevices[i]; i++)
711 {
712 KdPrint((__DRIVER_NAME " found existing vbd device %s\n", VbdDevices[i]));
713 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vbd/%s/state", VbdDevices[i]);
714 XenVbd_WatchHandler(buffer, DeviceData);
715 DeviceData->TotalInitialDevices++;
716 }
717 }
718 }
720 *Again = FALSE;
722 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
724 return SP_RETURN_FOUND;
725 }
727 static VOID
728 XenVbd_CheckBusChangedTimer(PVOID DeviceExtension);
730 static VOID
731 XenVbd_CheckBusEnumeratedTimer(PVOID DeviceExtension)
732 {
733 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
735 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
736 // KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
738 if (DeviceData->EnumeratedDevices >= DeviceData->TotalInitialDevices)
739 {
740 DeviceData->BusChangePending = 0;
741 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
742 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusChangedTimer, 1000000);
743 }
744 else
745 {
746 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusEnumeratedTimer, 100000);
747 }
748 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
749 }
751 static VOID
752 XenVbd_CheckBusChangedTimer(PVOID DeviceExtension)
753 {
754 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
756 if (DeviceData->BusChangePending)
757 {
758 ScsiPortNotification(BusChangeDetected, DeviceData, 0);
759 DeviceData->BusChangePending = 0;
760 }
761 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusChangedTimer, 1000000);
762 }
764 static BOOLEAN
765 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
766 {
767 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
768 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
770 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenVbd_CheckBusEnumeratedTimer, 100000);
772 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
774 return TRUE;
775 }
777 static ULONG
778 XenVbd_FillModePage(PXENVBD_DEVICE_DATA DeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
779 {
780 //PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
782 UNREFERENCED_PARAMETER(DeviceData);
783 UNREFERENCED_PARAMETER(DataBuffer);
784 UNREFERENCED_PARAMETER(BufferLength);
785 UNREFERENCED_PARAMETER(Offset);
787 switch (PageCode)
788 {
789 /*
790 case MODE_PAGE_RIGID_GEOMETRY:
791 if (DeviceData->ScsiData->DeviceType == XENVBD_DEVICETYPE_CDROM)
792 {
793 KdPrint((__DRIVER_NAME " MODE_PAGE_RIGID_GEOMETRY\n"));
794 if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
795 return 1;
796 ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
797 memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
798 ModeRigidGeometry->PageCode = PageCode;
799 ModeRigidGeometry->PageSavable = 0;
800 ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
801 ModeRigidGeometry->NumberOfCylinders[0] = (DeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF;
802 ModeRigidGeometry->NumberOfCylinders[1] = (DeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF;
803 ModeRigidGeometry->NumberOfCylinders[2] = (DeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF;
804 ModeRigidGeometry->NumberOfHeads = DeviceData->Geometry.TracksPerCylinder;
805 //ModeRigidGeometry->LandZoneCyclinder = 0;
806 ModeRigidGeometry->RoataionRate[0] = 0x05;
807 ModeRigidGeometry->RoataionRate[0] = 0x39;
808 *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
809 }
810 break;
811 */
812 case MODE_PAGE_FAULT_REPORTING:
813 break;
814 default:
815 break;
816 }
817 return 0;
818 }
820 static VOID
821 XenVbd_PutRequest(PXENVBD_TARGET_DATA TargetData, blkif_request_t *req)
822 {
823 blkif_other_request_t *other_req;
825 if (!TargetData->use_other)
826 {
827 *RING_GET_REQUEST(&TargetData->Ring, TargetData->Ring.req_prod_pvt) = *req;
828 }
829 else
830 {
831 other_req = RING_GET_REQUEST(&TargetData->OtherRing, TargetData->Ring.req_prod_pvt);
832 other_req->operation = req->operation;
833 other_req->nr_segments = req->nr_segments;
834 other_req->handle = req->handle;
835 other_req->id = req->id;
836 other_req->sector_number = req->sector_number;
837 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
838 }
839 TargetData->Ring.req_prod_pvt++;
840 }
842 // Call with device lock held
843 static VOID
844 XenVbd_PutSrbOnRing(PXENVBD_TARGET_DATA TargetData, PSCSI_REQUEST_BLOCK Srb)
845 {
846 //PUCHAR DataBuffer;
847 int i;
848 int BlockCount;
849 blkif_shadow_t *shadow;
850 uint64_t id;
852 // can use SRB_STATUS_BUSY to push the SRB back to windows...
854 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
856 if (RING_FULL(&TargetData->Ring))
857 {
858 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
859 // TODO: Fail badly here
860 }
862 id = GET_ID_FROM_FREELIST(TargetData);
863 if (id == 0x0fffffff)
864 {
865 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutSrbOnRing\n"));
866 }
868 shadow = &TargetData->shadow[id];
869 shadow->req.id = id;
871 shadow->req.sector_number = (Srb->Cdb[2] << 24) | (Srb->Cdb[3] << 16) | (Srb->Cdb[4] << 8) | Srb->Cdb[5];
872 BlockCount = (Srb->Cdb[7] << 8) | Srb->Cdb[8];
873 shadow->req.handle = 0;
874 shadow->req.operation = (Srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
875 shadow->Srb = Srb;
877 shadow->req.nr_segments = (UINT8)((BlockCount * TargetData->BytesPerSector + PAGE_SIZE - 1) / PAGE_SIZE);
879 for (i = 0; i < shadow->req.nr_segments; i++)
880 {
881 /*
882 shadow->req.seg[i].gref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
883 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
884 0, (ULONG)MmGetMdlPfnArray(TargetData->shadow[shadow->req.id].Mdl)[i], FALSE);
885 ASSERT((signed short)shadow->req.seg[i].gref >= 0);
886 */
887 shadow->req.seg[i].first_sect = 0;
888 if (i == shadow->req.nr_segments - 1)
889 shadow->req.seg[i].last_sect = (UINT8)((BlockCount - 1) % (PAGE_SIZE / TargetData->BytesPerSector));
890 else
891 shadow->req.seg[i].last_sect = (UINT8)(PAGE_SIZE / TargetData->BytesPerSector - 1);
892 }
893 if (Srb->Cdb[0] == SCSIOP_WRITE)
894 memcpy(TargetData->shadow[shadow->req.id].Buf, Srb->DataBuffer, BlockCount * TargetData->BytesPerSector);
896 XenVbd_PutRequest(TargetData, &shadow->req);
898 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
899 }
901 static BOOLEAN
902 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
903 {
904 PUCHAR DataBuffer;
905 PCDB cdb;
906 PXENVBD_DEVICE_DATA DeviceData = (PXENVBD_DEVICE_DATA)DeviceExtension;
907 PXENVBD_TARGET_DATA TargetData;
908 unsigned int i;
909 int notify;
911 // KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
912 // KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
914 // If we haven't enumerated all the devices yet then just defer the request
915 // A timer will issue a NextRequest to get things started again...
916 if (DeviceData->EnumeratedDevices < DeviceData->TotalInitialDevices)
917 {
918 Srb->SrbStatus = SRB_STATUS_BUSY;
919 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
920 return TRUE;
921 }
923 if (Srb->PathId >= SCSI_BUSES || Srb->TargetId >= SCSI_TARGETS_PER_BUS)
924 {
925 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
926 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
927 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
928 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
929 return TRUE;
930 }
932 TargetData = &DeviceData->BusData[Srb->PathId].TargetData[Srb->TargetId];
934 if (!TargetData->Present)
935 {
936 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
937 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
938 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
939 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Not Present)\n"));
940 return TRUE;
941 }
943 switch (Srb->Function)
944 {
945 case SRB_FUNCTION_EXECUTE_SCSI:
946 cdb = (PCDB)Srb->Cdb;
947 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
948 switch(cdb->CDB6GENERIC.OperationCode)
949 {
950 case SCSIOP_TEST_UNIT_READY:
951 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
952 Srb->SrbStatus = SRB_STATUS_SUCCESS;
953 Srb->ScsiStatus = 0;
954 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
955 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
956 break;
957 case SCSIOP_INQUIRY:
958 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
959 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
960 KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
961 KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
962 // KdPrint((__DRIVER_NAME " PhysicalAddress.LowPart = %08x\n", ScsiPortGetPhysicalAddress(DeviceData, Srb, Srb->DataBuffer, &Length).LowPart));
963 // DataBuffer = ScsiPortGetVirtualAddress(DeviceData, ScsiPortGetPhysicalAddress(DeviceData, Srb, Srb->DataBuffer, &Length));
964 // KdPrint((__DRIVER_NAME " (Databuffer = %08x)\n", DataBuffer));
965 // break;
966 DataBuffer = Srb->DataBuffer;
967 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
968 Srb->SrbStatus = SRB_STATUS_SUCCESS;
969 switch (TargetData->DeviceType)
970 {
971 case XENVBD_DEVICETYPE_DISK:
972 if ((Srb->Cdb[1] & 1) == 0)
973 {
974 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
975 DataBuffer[1] = 0x00; // not removable
976 DataBuffer[3] = 32;
977 memcpy(DataBuffer + 8, "XEN ", 8); // vendor id
978 memcpy(DataBuffer + 16, "PV VBD ", 16); // product id
979 memcpy(DataBuffer + 32, "0000", 4); // product revision level
980 }
981 else
982 {
983 switch (Srb->Cdb[2])
984 {
985 case 0x00:
986 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
987 DataBuffer[1] = 0x00;
988 DataBuffer[2] = 0x00;
989 DataBuffer[3] = 2;
990 DataBuffer[4] = 0x00;
991 DataBuffer[5] = 0x80;
992 break;
993 case 0x80:
994 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
995 DataBuffer[1] = 0x80;
996 DataBuffer[2] = 0x00;
997 DataBuffer[3] = 8;
998 DataBuffer[4] = 0x31;
999 DataBuffer[5] = 0x32;
1000 DataBuffer[6] = 0x33;
1001 DataBuffer[7] = 0x34;
1002 DataBuffer[8] = 0x35;
1003 DataBuffer[9] = 0x36;
1004 DataBuffer[10] = 0x37;
1005 DataBuffer[11] = 0x38;
1006 break;
1007 default:
1008 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1009 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1010 break;
1013 break;
1014 case XENVBD_DEVICETYPE_CDROM:
1015 if ((Srb->Cdb[1] & 1) == 0)
1017 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1018 DataBuffer[1] = 0x01; // removable
1019 DataBuffer[3] = 32;
1020 memcpy(DataBuffer + 8, "XEN ", 8); // vendor id
1021 memcpy(DataBuffer + 16, "PV VBD ", 16); // product id
1022 memcpy(DataBuffer + 32, "0000", 4); // product revision level
1024 else
1026 switch (Srb->Cdb[2])
1028 case 0x00:
1029 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1030 DataBuffer[1] = 0x00;
1031 DataBuffer[2] = 0x00;
1032 DataBuffer[3] = 2;
1033 DataBuffer[4] = 0x00;
1034 DataBuffer[5] = 0x80;
1035 break;
1036 case 0x80:
1037 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1038 DataBuffer[1] = 0x80;
1039 DataBuffer[2] = 0x00;
1040 DataBuffer[3] = 8;
1041 DataBuffer[4] = 0x31;
1042 DataBuffer[5] = 0x32;
1043 DataBuffer[6] = 0x33;
1044 DataBuffer[7] = 0x34;
1045 DataBuffer[8] = 0x35;
1046 DataBuffer[9] = 0x36;
1047 DataBuffer[10] = 0x37;
1048 DataBuffer[11] = 0x38;
1049 break;
1050 default:
1051 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1052 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1053 break;
1056 break;
1057 default:
1058 KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", TargetData->DeviceType));
1059 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1060 break;
1062 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1063 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1064 break;
1065 case SCSIOP_READ_CAPACITY:
1066 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1067 DataBuffer = Srb->DataBuffer;
1068 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1069 DataBuffer[0] = (unsigned char)((TargetData->TotalSectors - 1) >> 24) & 0xff;
1070 DataBuffer[1] = (unsigned char)((TargetData->TotalSectors - 1) >> 16) & 0xff;
1071 DataBuffer[2] = (unsigned char)((TargetData->TotalSectors - 1) >> 8) & 0xff;
1072 DataBuffer[3] = (unsigned char)((TargetData->TotalSectors - 1) >> 0) & 0xff;
1073 DataBuffer[4] = (unsigned char)(TargetData->BytesPerSector >> 24) & 0xff;
1074 DataBuffer[5] = (unsigned char)(TargetData->BytesPerSector >> 16) & 0xff;
1075 DataBuffer[6] = (unsigned char)(TargetData->BytesPerSector >> 8) & 0xff;
1076 DataBuffer[7] = (unsigned char)(TargetData->BytesPerSector >> 0) & 0xff;
1077 Srb->ScsiStatus = 0;
1078 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1079 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1080 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1081 break;
1082 case SCSIOP_MODE_SENSE:
1083 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));
1084 KdPrint((__DRIVER_NAME " Length = %d\n", Srb->DataTransferLength));
1086 Srb->ScsiStatus = 0;
1087 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1088 Srb->DataTransferLength = 0;
1089 DataBuffer = Srb->DataBuffer;
1090 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
1091 switch(cdb->MODE_SENSE.PageCode)
1093 case MODE_SENSE_RETURN_ALL:
1094 //Ptr = (UCHAR *)Srb->DataBuffer;
1095 for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
1097 if (XenVbd_FillModePage(DeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength))
1099 break;
1102 break;
1103 default:
1104 XenVbd_FillModePage(DeviceData, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength);
1105 break;
1107 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1108 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1109 break;
1110 case SCSIOP_READ:
1111 case SCSIOP_WRITE:
1112 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1113 XenVbd_PutSrbOnRing(TargetData, Srb);
1114 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&TargetData->Ring, notify);
1115 if (notify)
1116 DeviceData->XenDeviceData->XenInterface.EvtChn_Notify(
1117 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
1118 TargetData->EventChannel);
1119 if (!RING_FULL(&TargetData->Ring))
1120 ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
1121 else
1122 ScsiPortNotification(NextRequest, DeviceExtension);
1123 break;
1124 case SCSIOP_REPORT_LUNS:
1125 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1126 Srb->SrbStatus = SRB_STATUS_SUCCESS; //SRB_STATUS_INVALID_REQUEST;
1127 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1128 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1129 break;
1130 case SCSIOP_READ_TOC:
1131 DataBuffer = Srb->DataBuffer;
1132 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1133 /*
1134 #define READ_TOC_FORMAT_TOC 0x00
1135 #define READ_TOC_FORMAT_SESSION 0x01
1136 #define READ_TOC_FORMAT_FULL_TOC 0x02
1137 #define READ_TOC_FORMAT_PMA 0x03
1138 #define READ_TOC_FORMAT_ATIP 0x04
1139 */
1140 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1141 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1142 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1143 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1144 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1145 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1146 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1147 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1148 switch (cdb->READ_TOC.Format2)
1150 case READ_TOC_FORMAT_TOC:
1151 DataBuffer[0] = 0; // length MSB
1152 DataBuffer[1] = 10; // length LSB
1153 DataBuffer[2] = 1; // First Track
1154 DataBuffer[3] = 1; // Last Track
1155 DataBuffer[4] = 0; // Reserved
1156 DataBuffer[5] = 0x14; // current position data + uninterrupted data
1157 DataBuffer[6] = 1; // last complete track
1158 DataBuffer[7] = 0; // reserved
1159 DataBuffer[8] = 0; // MSB Block
1160 DataBuffer[9] = 0;
1161 DataBuffer[10] = 0;
1162 DataBuffer[11] = 0; // LSB Block
1163 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1164 break;
1165 case READ_TOC_FORMAT_SESSION:
1166 case READ_TOC_FORMAT_FULL_TOC:
1167 case READ_TOC_FORMAT_PMA:
1168 case READ_TOC_FORMAT_ATIP:
1169 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1170 break;
1172 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1173 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1174 break;
1175 default:
1176 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1177 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1178 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1179 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1180 break;
1182 break;
1183 case SRB_FUNCTION_CLAIM_DEVICE:
1184 KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
1185 // ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
1186 // Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
1187 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1188 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1189 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1190 break;
1191 case SRB_FUNCTION_IO_CONTROL:
1192 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1193 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1194 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1195 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1196 break;
1197 case SRB_FUNCTION_FLUSH:
1198 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1199 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1200 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1201 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1202 break;
1203 default:
1204 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1205 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1206 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1207 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
1208 break;
1211 // KdPrint((__DRIVER_NAME " <-- HwScsiStartIo\n"));
1213 return TRUE;
1216 static BOOLEAN
1217 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1219 UNREFERENCED_PARAMETER(DeviceExtension);
1220 UNREFERENCED_PARAMETER(PathId);
1223 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
1224 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1226 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
1228 return TRUE;
1232 static BOOLEAN
1233 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1235 UNREFERENCED_PARAMETER(DeviceExtension);
1236 UNREFERENCED_PARAMETER(Context);
1237 UNREFERENCED_PARAMETER(SaveState);
1239 KdPrint((__DRIVER_NAME " --> HwScsiAdapterState\n"));
1240 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1242 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterState\n"));
1244 return TRUE;
1247 static SCSI_ADAPTER_CONTROL_STATUS
1248 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1250 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1251 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1253 UNREFERENCED_PARAMETER(DeviceExtension);
1255 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
1256 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1258 switch (ControlType)
1260 case ScsiQuerySupportedControlTypes:
1261 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1262 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1263 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1264 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1265 break;
1266 case ScsiStopAdapter:
1267 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1268 break;
1269 case ScsiRestartAdapter:
1270 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1271 break;
1272 case ScsiSetBootConfig:
1273 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1274 break;
1275 case ScsiSetRunningConfig:
1276 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1277 break;
1278 default:
1279 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1280 break;
1283 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
1285 return Status;