win-pvdrivers

view xenscsi/xenscsi.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 58ce01887603
children 874c3640830e
line source
1 #include "xenscsi.h"
2 #include <scsi.h>
3 #include <ntddscsi.h>
4 #include <ntdddisk.h>
5 #include <stdlib.h>
6 #include <xen_public.h>
7 #include <io/xenbus.h>
8 #include <io/protocols.h>
10 #pragma warning(disable: 4127)
12 #define wmb() KeMemoryBarrier()
13 #define mb() KeMemoryBarrier()
15 DRIVER_INITIALIZE DriverEntry;
17 static ULONG
18 XenScsi_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again);
19 static BOOLEAN
20 XenScsi_HwScsiInitialize(PVOID DeviceExtension);
21 static BOOLEAN
22 XenScsi_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb);
23 static BOOLEAN
24 XenScsi_HwScsiInterrupt(PVOID DeviceExtension);
25 static BOOLEAN
26 XenScsi_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId);
27 static BOOLEAN
28 XenScsi_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState);
29 static SCSI_ADAPTER_CONTROL_STATUS
30 XenScsi_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters);
32 #ifdef ALLOC_PRAGMA
33 #pragma alloc_text (INIT, DriverEntry)
34 #endif
36 NTSTATUS
37 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
38 {
39 ULONG Status;
40 HW_INITIALIZATION_DATA HwInitializationData;
42 KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
43 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
45 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
47 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
48 HwInitializationData.AdapterInterfaceType = Internal; //PNPBus;
49 HwInitializationData.HwInitialize = XenScsi_HwScsiInitialize;
50 HwInitializationData.HwStartIo = XenScsi_HwScsiStartIo;
51 HwInitializationData.HwInterrupt = XenScsi_HwScsiInterrupt;
52 HwInitializationData.HwFindAdapter = XenScsi_HwScsiFindAdapter;
53 HwInitializationData.HwResetBus = XenScsi_HwScsiResetBus;
54 HwInitializationData.HwDmaStarted = NULL;
55 HwInitializationData.HwAdapterState = XenScsi_HwScsiAdapterState;
56 HwInitializationData.DeviceExtensionSize = sizeof(XENSCSI_DEVICE_DATA);
57 HwInitializationData.SpecificLuExtensionSize = 0;
58 HwInitializationData.SrbExtensionSize = 0;
59 HwInitializationData.NumberOfAccessRanges = 1;
60 HwInitializationData.MapBuffers = TRUE;
61 HwInitializationData.NeedPhysicalAddresses = FALSE;
62 HwInitializationData.TaggedQueuing = TRUE;
63 HwInitializationData.AutoRequestSense = TRUE;
64 HwInitializationData.MultipleRequestPerLu = FALSE;
65 HwInitializationData.ReceiveEvent = FALSE;
66 HwInitializationData.VendorIdLength = 0;
67 HwInitializationData.VendorId = NULL;
68 HwInitializationData.DeviceIdLength = 0;
69 HwInitializationData.DeviceId = NULL;
70 HwInitializationData.HwAdapterControl = XenScsi_HwScsiAdapterControl;
72 Status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
74 if(!NT_SUCCESS(Status))
75 {
76 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", Status));
77 }
79 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
81 return Status;
82 }
84 static __inline uint16_t
85 GET_ID_FROM_FREELIST(PXENSCSI_TARGET_DATA TargetData)
86 {
87 uint16_t free;
88 free = TargetData->shadow_free;
89 TargetData->shadow_free = TargetData->shadow[free].req.rqid;
90 TargetData->shadow[free].req.rqid = 0x0fff; /* debug */
91 return free;
92 }
94 static __inline VOID
95 ADD_ID_TO_FREELIST(PXENSCSI_TARGET_DATA TargetData, uint16_t Id)
96 {
97 TargetData->shadow[Id].req.rqid = TargetData->shadow_free;
98 TargetData->shadow[Id].Srb = NULL;
99 TargetData->shadow_free = Id;
100 }
102 static BOOLEAN
103 XenScsi_Interrupt(PKINTERRUPT Interrupt, PVOID DeviceExtension)
104 {
105 PXENSCSI_TARGET_DATA TargetData = (PXENSCSI_TARGET_DATA)DeviceExtension;
107 UNREFERENCED_PARAMETER(Interrupt);
109 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
111 TargetData->PendingInterrupt = TRUE;
113 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
115 return TRUE;
116 }
118 static VOID
119 XenScsi_HwScsiInterruptTarget(PVOID DeviceExtension)
120 {
121 PXENSCSI_TARGET_DATA TargetData = (PXENSCSI_TARGET_DATA)DeviceExtension;
122 PSCSI_REQUEST_BLOCK Srb;
123 RING_IDX i, rp;
124 vscsiif_response_t *rep;
125 PXENSCSI_DEVICE_DATA DeviceData = (PXENSCSI_DEVICE_DATA)TargetData->DeviceData;
126 int more_to_do = TRUE;
128 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
130 while (more_to_do)
131 {
132 rp = TargetData->Ring.sring->rsp_prod;
133 KeMemoryBarrier();
134 for (i = TargetData->Ring.rsp_cons; i != rp; i++)
135 {
136 rep = RING_GET_RESPONSE(&TargetData->Ring, i);
137 Srb = TargetData->shadow[rep->rqid].Srb;
138 Srb->ScsiStatus = (UCHAR)rep->rslt;
139 if (!rep->rslt)
140 Srb->SrbStatus = SRB_STATUS_SUCCESS;
141 else
142 {
143 KdPrint((__DRIVER_NAME " Xen Operation returned error (result = 0x%08x)\n", rep->rslt));
144 Srb->SrbStatus = SRB_STATUS_ERROR;
145 if (rep->sense_len > 0 && rep->sense_len <= Srb->SenseInfoBufferLength && !(Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) && Srb->SenseInfoBuffer != NULL)
146 {
147 Srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
148 memcpy(Srb->SenseInfoBuffer, rep->sense_buffer, rep->sense_len);
149 }
150 }
151 if (Srb->SrbFlags & SRB_FLAGS_DATA_IN)
152 memcpy(Srb->DataBuffer, TargetData->shadow[rep->rqid].Buf, Srb->DataTransferLength);
154 ScsiPortNotification(RequestComplete, DeviceData, Srb);
155 ScsiPortNotification(NextLuRequest, DeviceData, Srb->PathId, Srb->TargetId, Srb->Lun);
156 // ScsiPortNotification(NextRequest, DeviceData);
158 ADD_ID_TO_FREELIST(TargetData, rep->rqid);
159 }
161 TargetData->Ring.rsp_cons = i;
162 if (i != TargetData->Ring.req_prod_pvt)
163 {
164 RING_FINAL_CHECK_FOR_RESPONSES(&TargetData->Ring, more_to_do);
165 }
166 else
167 {
168 TargetData->Ring.sring->rsp_event = i + 1;
169 more_to_do = FALSE;
170 }
171 }
173 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
174 }
176 static BOOLEAN
177 XenScsi_HwScsiInterrupt(PVOID DeviceExtension)
178 {
179 PXENSCSI_DEVICE_DATA DeviceData;
180 PXENSCSI_TARGET_DATA TargetData;
181 int i, j;
183 //KdPrint((__DRIVER_NAME " --> HwScsiInterrupt\n"));
185 DeviceData = (PXENSCSI_DEVICE_DATA)DeviceExtension;
187 KeMemoryBarrier();
188 for (i = 0; i < SCSI_BUSES; i++)
189 {
190 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
191 {
192 TargetData = &DeviceData->BusData[i].TargetData[j];
193 if (TargetData->PendingInterrupt)
194 XenScsi_HwScsiInterruptTarget(TargetData);
195 TargetData->PendingInterrupt = FALSE;
196 }
197 }
198 //KdPrint((__DRIVER_NAME " <-- HwScsiInterrupt\n"));
200 return FALSE;
201 }
203 static VOID
204 XenScsi_BackEndStateHandler(char *Path, PVOID Data)
205 {
206 PXENSCSI_TARGET_DATA TargetData;
207 PXENSCSI_DEVICE_DATA DeviceData;
208 char TmpPath[128];
209 char *Value;
210 int NewState;
211 int scanning;
212 PMDL Mdl;
213 grant_ref_t ref;
214 vscsiif_sring_t *SharedRing;
215 ULONG PFN;
216 ULONG i, j;
218 KdPrint((__DRIVER_NAME " --> BackEndStateHandler\n"));
219 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
221 TargetData = (PXENSCSI_TARGET_DATA)Data;
222 DeviceData = (PXENSCSI_DEVICE_DATA)TargetData->DeviceData;
224 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
225 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
226 XBT_NIL, Path, &Value);
228 NewState = atoi(Value);
229 switch (NewState)
230 {
231 case XenbusStateUnknown:
232 KdPrint((__DRIVER_NAME " Backend State Changed to Unknown\n"));
233 break;
235 case XenbusStateInitialising:
236 KdPrint((__DRIVER_NAME " Backend State Changed to Initialising\n"));
237 break;
239 case XenbusStateInitWait:
240 KdPrint((__DRIVER_NAME " Backend State Changed to InitWait\n"));
242 TargetData->EventChannel = DeviceData->XenDeviceData->XenInterface.EvtChn_AllocUnbound(
243 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, 0);
244 DeviceData->XenDeviceData->XenInterface.EvtChn_Bind(
245 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
246 TargetData->EventChannel, XenScsi_Interrupt, TargetData);
247 Mdl = AllocatePage();
248 PFN = (ULONG)*MmGetMdlPfnArray(Mdl);
249 SharedRing = (vscsiif_sring_t *)MmGetMdlVirtualAddress(Mdl);
250 RtlZeroMemory(SharedRing, PAGE_SIZE);
251 SHARED_RING_INIT(SharedRing);
252 FRONT_RING_INIT(&TargetData->Ring, SharedRing, PAGE_SIZE);
253 ref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
254 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
255 0, PFN, FALSE, 0);
256 ASSERT((signed short)ref >= 0);
257 TargetData->ring_detect_state = 0;
258 TargetData->shadow = ExAllocatePoolWithTag(NonPagedPool, sizeof(vscsiif_shadow_t) * VSCSIIF_RING_SIZE, XENSCSI_POOL_TAG);
260 memset(TargetData->shadow, 0, sizeof(vscsiif_shadow_t) * VSCSIIF_RING_SIZE);
261 for (i = 0; i < VSCSIIF_RING_SIZE; i++)
262 {
263 TargetData->shadow[i].req.rqid = (uint16_t)i + 1;
264 TargetData->shadow[i].Mdl = AllocatePages(VSCSIIF_SG_TABLESIZE); // stupid that we have to do this!
265 TargetData->shadow[i].Buf = MmGetMdlVirtualAddress(TargetData->shadow[i].Mdl);
266 for (j = 0; j < VSCSIIF_SG_TABLESIZE; j++)
267 {
268 TargetData->shadow[i].req.seg[j].gref = DeviceData->XenDeviceData->XenInterface.GntTbl_GrantAccess(
269 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
270 0, (ULONG)MmGetMdlPfnArray(TargetData->shadow[i].Mdl)[j], FALSE, 0);
271 ASSERT((signed short)TargetData->shadow[i].req.seg[j].gref >= 0);
272 }
273 }
274 TargetData->shadow_free = 0;
276 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
277 RtlStringCbCatA(TmpPath, 128, "/ring-ref");
278 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
279 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
280 XBT_NIL, TmpPath, "%d", ref);
282 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
283 RtlStringCbCatA(TmpPath, 128, "/event-channel");
284 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
285 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
286 XBT_NIL, TmpPath, "%d", TargetData->EventChannel);
288 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
289 RtlStringCbCatA(TmpPath, 128, "/state");
290 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
291 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
292 XBT_NIL, TmpPath, "%d", XenbusStateInitialised);
294 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
295 RtlStringCbCatA(TmpPath, 128, "/b-dev");
296 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
297 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
298 XBT_NIL, TmpPath, &Value);
300 KdPrint((__DRIVER_NAME " dev string = %s\n", Value));
302 i = 0;
303 j = 0;
304 scanning = TRUE;
305 while (scanning)
306 {
307 if (Value[i] == 0)
308 scanning = FALSE;
309 if (Value[i] == ':' || Value[i] == 0)
310 {
311 Value[i] = 0;
312 TargetData->host = TargetData->channel;
313 TargetData->channel = TargetData->id;
314 TargetData->id = TargetData->lun;
315 TargetData->lun = atoi(&Value[j]);
316 j = i + 1;
317 }
318 i++;
319 }
320 KdPrint((__DRIVER_NAME " host = %d, channel = %d, id = %d, lun = %d\n",
321 TargetData->host, TargetData->channel, TargetData->id, TargetData->lun));
323 /*
324 KdPrint((__DRIVER_NAME " sizeof(vscsiif_request) = %d\n", sizeof(struct vscsiif_request)));
325 KdPrint((__DRIVER_NAME " sizeof(vscsiif_request_segment) = %d\n", sizeof(struct vscsiif_request_segment)));
326 KdPrint((__DRIVER_NAME " sizeof(vscsiif_response) = %d\n", sizeof(struct vscsiif_response)));
327 KdPrint((__DRIVER_NAME " operation = %d\n", (int)((char *)(&req.operation) - (char *)(&req))));
328 KdPrint((__DRIVER_NAME " nr_segments = %d\n", (int)((char *)(&req.nr_segments) - (char *)(&req))));
329 KdPrint((__DRIVER_NAME " handle = %d\n", (int)((char *)(&req.handle) - (char *)(&req))));
330 KdPrint((__DRIVER_NAME " id = %d\n", (int)((char *)(&req.rqid) - (char *)(&req))));
331 KdPrint((__DRIVER_NAME " sector_number = %d\n", (int)((char *)(&req.sector_number) - (char *)(&req))));
332 KdPrint((__DRIVER_NAME " seg = %d\n", (int)((char *)(&req.seg) - (char *)(&req))));
334 KdPrint((__DRIVER_NAME " id = %d\n", (int)((char *)(&rep.id) - (char *)(&rep))));
335 KdPrint((__DRIVER_NAME " operation = %d\n", (int)((char *)(&rep.operation) - (char *)(&rep))));
336 KdPrint((__DRIVER_NAME " status = %d\n", (int)((char *)(&rep.status) - (char *)(&rep))));
338 KdPrint((__DRIVER_NAME " sizeof(union vscsiif_sring_entry) = %d\n", sizeof(union vscsiif_sring_entry)));
339 KdPrint((__DRIVER_NAME " %d\n", (int)((char *)(&entries[1]) - (char *)(&entries[0]))));
340 */
341 KdPrint((__DRIVER_NAME " Set Frontend state to Initialised\n"));
342 break;
344 case XenbusStateInitialised:
345 KdPrint((__DRIVER_NAME " Backend State Changed to Initialised\n"));
346 break;
348 case XenbusStateConnected:
349 KdPrint((__DRIVER_NAME " Backend State Changed to Connected\n"));
351 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
352 RtlStringCbCatA(TmpPath, 128, "/state");
353 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateConnected);
355 KdPrint((__DRIVER_NAME " Set Frontend state to Connected\n"));
356 InterlockedIncrement(&DeviceData->EnumeratedDevices);
357 KdPrint((__DRIVER_NAME " Added a device\n"));
359 // now ask windows to rescan the scsi bus...
360 DeviceData->BusChangePending = 1;
361 break;
363 case XenbusStateClosing:
364 KdPrint((__DRIVER_NAME " Backend State Changed to Closing\n"));
365 // this behaviour is only to properly close down to then restart in the case of a dump
366 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
367 RtlStringCbCatA(TmpPath, 128, "/state");
368 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateClosed);
369 KdPrint((__DRIVER_NAME " Set Frontend state to Closed\n"));
370 break;
372 case XenbusStateClosed:
373 KdPrint((__DRIVER_NAME " Backend State Changed to Closed\n"));
374 // this behaviour is only to properly close down to then restart in the case of a dump
375 RtlStringCbCopyA(TmpPath, 128, TargetData->Path);
376 RtlStringCbCatA(TmpPath, 128, "/state");
377 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context, XBT_NIL, TmpPath, "%d", XenbusStateInitialising);
378 KdPrint((__DRIVER_NAME " Set Frontend state to Initialising\n"));
379 break;
381 default:
382 KdPrint((__DRIVER_NAME " Backend State Changed to Undefined = %d\n", NewState));
383 break;
384 }
386 KdPrint((__DRIVER_NAME " <-- BackEndStateHandler\n"));
387 }
389 static VOID
390 XenScsi_WatchHandler(char *Path, PVOID DeviceExtension)
391 {
392 PXENSCSI_DEVICE_DATA DeviceData = (PXENSCSI_DEVICE_DATA)DeviceExtension;
393 char **Bits;
394 int Count;
395 char TmpPath[128];
396 char *Value;
397 int CurrentBus, CurrentTarget;
398 PXENSCSI_TARGET_DATA TargetData, VacantTarget;
399 KIRQL OldIrql;
400 int i;
402 KdPrint((__DRIVER_NAME " --> WatchHandler (DeviceData = %p)\n", DeviceData));
403 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
405 KdPrint((__DRIVER_NAME " Path = %s\n", Path));
407 Bits = SplitString(Path, '/', 4, &Count);
408 switch (Count)
409 {
410 case 0:
411 case 1:
412 case 2:
413 break; // should never happen
414 case 3:
415 break;
416 case 4:
417 if (strcmp(Bits[3], "state") != 0) // we only care when the state appears
418 break;
420 KeAcquireSpinLock(&DeviceData->Lock, &OldIrql);
422 for (VacantTarget = NULL,i = 0; i < SCSI_BUSES * SCSI_TARGETS_PER_BUS; i++)
423 {
424 CurrentBus = i / SCSI_TARGETS_PER_BUS;
425 CurrentTarget = i % SCSI_TARGETS_PER_BUS;
426 if (CurrentTarget == 7) // don't use 7 - it would be for the controller
427 continue;
428 TargetData = &DeviceData->BusData[CurrentBus].TargetData[CurrentTarget];
429 if (TargetData->Present && strncmp(TargetData->Path, Path, strlen(TargetData->Path)) == 0 && Path[strlen(TargetData->Path)] == '/')
430 break; // already exists
431 else if (!TargetData->Present && VacantTarget == NULL)
432 VacantTarget = TargetData;
433 }
434 if (i == SCSI_BUSES * SCSI_TARGETS_PER_BUS && VacantTarget != NULL)
435 {
436 VacantTarget->Present = 1;
437 KeReleaseSpinLock(&DeviceData->Lock, OldIrql);
439 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
440 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
441 XBT_NIL, Path, &Value);
443 if (Value == NULL)
444 {
445 KdPrint((__DRIVER_NAME " blank state?\n"));
446 break;
447 }
448 if (atoi(Value) != XenbusStateInitialising)
449 DeviceData->XenDeviceData->XenInterface.XenBus_Printf(
450 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
451 XBT_NIL, Path, "%d", XenbusStateClosing);
453 RtlStringCbCopyA(VacantTarget->Path, 128, Bits[0]);
454 RtlStringCbCatA(VacantTarget->Path, 128, "/");
455 RtlStringCbCatA(VacantTarget->Path, 128, Bits[1]);
456 RtlStringCbCatA(VacantTarget->Path, 128, "/");
457 RtlStringCbCatA(VacantTarget->Path, 128, Bits[2]);
459 VacantTarget->DeviceIndex = atoi(Bits[2]);
461 RtlStringCbCopyA(TmpPath, 128, VacantTarget->Path);
462 RtlStringCbCatA(TmpPath, 128, "/backend");
463 DeviceData->XenDeviceData->XenInterface.XenBus_Read(
464 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
465 XBT_NIL, TmpPath, &Value);
466 if (Value == NULL)
467 KdPrint((__DRIVER_NAME " Read Failed\n"));
468 else
469 RtlStringCbCopyA(VacantTarget->BackendPath, 128, Value);
470 RtlStringCbCopyA(TmpPath, 128, VacantTarget->BackendPath);
471 RtlStringCbCatA(TmpPath, 128, "/state");
473 DeviceData->XenDeviceData->XenInterface.XenBus_AddWatch(
474 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
475 XBT_NIL, TmpPath, XenScsi_BackEndStateHandler, VacantTarget);
476 }
477 else
478 KeReleaseSpinLock(&DeviceData->Lock, OldIrql);
479 break;
480 }
482 FreeSplitString(Bits, Count);
484 KdPrint((__DRIVER_NAME " <-- WatchHandler\n"));
486 return;
487 }
489 static ULONG
490 XenScsi_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
491 {
492 ULONG i, j;
493 PACCESS_RANGE AccessRange;
494 PXENSCSI_DEVICE_DATA DeviceData = (PXENSCSI_DEVICE_DATA)DeviceExtension;
495 char **ScsiDevices;
496 char *msg;
497 char buffer[128];
499 UNREFERENCED_PARAMETER(HwContext);
500 UNREFERENCED_PARAMETER(BusInformation);
501 UNREFERENCED_PARAMETER(ArgumentString);
502 KeInitializeSpinLock(&DeviceData->Lock);
503 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
504 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
506 // testing this for dump mode
507 // if (KeGetCurrentIrql() > ConfigInfo->BusInterruptLevel)
508 // ConfigInfo->BusInterruptLevel = KeGetCurrentIrql();
510 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
511 KdPrint((__DRIVER_NAME " BusInterruptVector = %d\n", ConfigInfo->BusInterruptVector));
513 KdPrint((__DRIVER_NAME " AccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
515 for (i = 0; i < ConfigInfo->NumberOfAccessRanges; i++)
516 {
517 AccessRange = &(*(ConfigInfo->AccessRanges))[i];
518 KdPrint((__DRIVER_NAME " AccessRange %2d: RangeStart = %p, RangeLength = %x, RangeInMemory = %d\n", i, AccessRange->RangeStart.QuadPart, AccessRange->RangeLength, AccessRange->RangeInMemory));
519 switch (i)
520 {
521 case 0:
522 DeviceData->XenDeviceData = (PVOID)(xen_ulong_t)AccessRange->RangeStart.QuadPart;
523 KdPrint((__DRIVER_NAME " Mapped to virtual address %p\n", DeviceData->XenDeviceData));
524 KdPrint((__DRIVER_NAME " Magic = %08x\n", DeviceData->XenDeviceData->Magic));
525 if (DeviceData->XenDeviceData->Magic != XEN_DATA_MAGIC)
526 {
527 KdPrint((__DRIVER_NAME " Invalid Magic Number\n"));
528 return SP_RETURN_NOT_FOUND;
529 }
530 break;
531 default:
532 break;
533 }
534 }
535 #if defined(__x86_64__)
536 ConfigInfo->Master = TRUE; // Won't work under x64 without this...
537 #endif
538 ConfigInfo->MaximumTransferLength = VSCSIIF_SG_TABLESIZE * PAGE_SIZE;
539 ConfigInfo->NumberOfPhysicalBreaks = VSCSIIF_SG_TABLESIZE - 1;
540 ConfigInfo->ScatterGather = TRUE;
541 ConfigInfo->AlignmentMask = 0;
542 ConfigInfo->NumberOfBuses = SCSI_BUSES;
543 for (i = 0; i < ConfigInfo->NumberOfBuses; i++)
544 {
545 ConfigInfo->InitiatorBusId[i] = 7;
546 }
547 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
548 ConfigInfo->MaximumNumberOfTargets = SCSI_TARGETS_PER_BUS;
549 // ConfigInfo->TaggedQueueing = TRUE;
550 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
551 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
552 // This all has to be initialized here as the real Initialize routine
553 // is called at DIRQL, and the XenBus stuff has to be called at
554 // <= DISPATCH_LEVEL
556 for (i = 0; i < SCSI_BUSES; i++)
557 {
558 for (j = 0; j < SCSI_TARGETS_PER_BUS; j++)
559 {
560 DeviceData->BusData[i].TargetData[j].Present = 0;
561 DeviceData->BusData[i].TargetData[j].DeviceData = DeviceData;
562 }
563 }
565 DeviceData->XenDeviceData->WatchContext = DeviceExtension;
566 KeMemoryBarrier();
567 DeviceData->XenDeviceData->WatchHandler = XenScsi_WatchHandler;
569 // KeInitializeEvent(&DeviceData->WaitDevicesEvent, SynchronizationEvent, FALSE);
570 DeviceData->EnumeratedDevices = 0;
571 DeviceData->TotalInitialDevices = 0;
573 // if (DeviceData->XenDeviceData->AutoEnumerate)
574 // {
575 msg = DeviceData->XenDeviceData->XenInterface.XenBus_List(
576 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
577 XBT_NIL, "device/vscsi", &ScsiDevices);
578 if (!msg)
579 {
580 for (i = 0; ScsiDevices[i]; i++)
581 {
582 KdPrint((__DRIVER_NAME " found existing scsi device %s\n", ScsiDevices[i]));
583 RtlStringCbPrintfA(buffer, ARRAY_SIZE(buffer), "device/vscsi/%s/state", ScsiDevices[i]);
584 XenScsi_WatchHandler(buffer, DeviceData);
585 DeviceData->TotalInitialDevices++;
586 }
587 }
588 // }
590 *Again = FALSE;
592 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
594 return SP_RETURN_FOUND;
595 }
597 static VOID
598 XenScsi_CheckBusChangedTimer(PVOID DeviceExtension);
600 static VOID
601 XenScsi_CheckBusEnumeratedTimer(PVOID DeviceExtension)
602 {
603 PXENSCSI_DEVICE_DATA DeviceData = (PXENSCSI_DEVICE_DATA)DeviceExtension;
605 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
606 // KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
608 if (DeviceData->BusChangePending && DeviceData->EnumeratedDevices >= DeviceData->TotalInitialDevices)
609 {
610 DeviceData->BusChangePending = 0;
611 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
612 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckBusChangedTimer, 1000000);
613 }
614 else
615 {
616 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckBusEnumeratedTimer, 100000);
617 }
618 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
619 }
621 static VOID
622 XenScsi_CheckBusChangedTimer(PVOID DeviceExtension)
623 {
624 PXENSCSI_DEVICE_DATA DeviceData = (PXENSCSI_DEVICE_DATA)DeviceExtension;
626 if (DeviceData->BusChangePending)
627 {
628 ScsiPortNotification(BusChangeDetected, DeviceData, 0);
629 DeviceData->BusChangePending = 0;
630 }
631 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckBusChangedTimer, 1000000);
632 }
634 static BOOLEAN
635 XenScsi_HwScsiInitialize(PVOID DeviceExtension)
636 {
637 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
638 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
640 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckBusEnumeratedTimer, 100000);
642 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
644 return TRUE;
645 }
647 // Call with device lock held
648 static VOID
649 XenScsi_PutSrbOnRing(PXENSCSI_TARGET_DATA TargetData, PSCSI_REQUEST_BLOCK Srb)
650 {
651 //PUCHAR DataBuffer;
652 int i;
653 vscsiif_shadow_t *shadow;
654 uint16_t id;
655 int remaining;
657 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
659 if (RING_FULL(&TargetData->Ring))
660 {
661 KdPrint((__DRIVER_NAME " RING IS FULL - EXPECT BADNESS\n"));
662 // TODO: Fail badly here
663 }
665 id = GET_ID_FROM_FREELIST(TargetData);
666 if (id == 0x0fff)
667 {
668 KdPrint((__DRIVER_NAME " Something is horribly wrong in PutSrbOnRing\n"));
669 }
671 shadow = &TargetData->shadow[id];
672 shadow->Srb = Srb;
673 shadow->req.rqid = id;
674 shadow->req.cmd = VSCSIIF_CMND_SCSI;
675 memset(shadow->req.cmnd, 0, VSCSIIF_MAX_COMMAND_SIZE);
676 memcpy(shadow->req.cmnd, Srb->Cdb, 16);
677 shadow->req.cmd_len = Srb->CdbLength;
678 shadow->req.id = (USHORT)TargetData->id;
679 shadow->req.lun = (USHORT)TargetData->lun;
680 shadow->req.channel = (USHORT)TargetData->channel;
681 if (Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_IN) && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT))
682 shadow->req.sc_data_direction = DMA_BIDIRECTIONAL;
683 else if (Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_IN))
684 shadow->req.sc_data_direction = DMA_FROM_DEVICE;
685 else if (Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT))
686 shadow->req.sc_data_direction = DMA_TO_DEVICE;
687 else
688 shadow->req.sc_data_direction = DMA_NONE;
689 shadow->req.use_sg = (UINT8)((Srb->DataTransferLength + PAGE_SIZE - 1) >> PAGE_SHIFT);
690 shadow->req.request_bufflen = Srb->DataTransferLength;
692 // KdPrint((__DRIVER_NAME " pages = %d\n", shadow->req.use_sg));
693 remaining = Srb->DataTransferLength;
694 shadow->req.seg[0].offset = 0;
695 shadow->req.seg[0].length = 0;
696 for (i = 0; remaining != 0; i++)
697 {
698 shadow->req.seg[i].offset = 0; // this is the offset into the page
699 if (remaining >= PAGE_SIZE)
700 {
701 shadow->req.seg[i].length = PAGE_SIZE;
702 remaining -= PAGE_SIZE;
703 }
704 else
705 {
706 shadow->req.seg[i].length = (USHORT)remaining;
707 remaining = 0;
708 }
709 // KdPrint((__DRIVER_NAME " sg %d: offset = %d, size = %d\n", i, shadow->req.seg[i].offset, shadow->req.seg[i].length));
710 }
711 if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)
712 memcpy(TargetData->shadow[shadow->req.rqid].Buf, Srb->DataBuffer, Srb->DataTransferLength);
714 *RING_GET_REQUEST(&TargetData->Ring, TargetData->Ring.req_prod_pvt) = shadow->req;
715 TargetData->Ring.req_prod_pvt++;
717 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
718 }
720 static BOOLEAN
721 XenScsi_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
722 {
723 PXENSCSI_DEVICE_DATA DeviceData = (PXENSCSI_DEVICE_DATA)DeviceExtension;
724 PXENSCSI_TARGET_DATA TargetData;
725 int notify;
727 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
729 // If we haven't enumerated all the devices yet then just defer the request
730 // A timer will issue a NextRequest to get things started again...
731 if (DeviceData->EnumeratedDevices < DeviceData->TotalInitialDevices)
732 {
733 Srb->SrbStatus = SRB_STATUS_BUSY;
734 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
735 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Bus not enumerated yet)\n"));
736 return TRUE;
737 }
739 if (Srb->PathId >= SCSI_BUSES || Srb->TargetId >= SCSI_TARGETS_PER_BUS)
740 {
741 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
742 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
743 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
744 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
745 return TRUE;
746 }
748 TargetData = &DeviceData->BusData[Srb->PathId].TargetData[Srb->TargetId];
750 if (!TargetData->Present)
751 {
752 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
753 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
754 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
755 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Not Present)\n"));
756 return TRUE;
757 }
759 switch (Srb->Function)
760 {
761 case SRB_FUNCTION_EXECUTE_SCSI:
762 #if 0
763 KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
764 KdPrint((__DRIVER_NAME " CdbLength = %d\n", Srb->CdbLength));
765 for (i = 0; i < Srb->CdbLength; i++)
766 KdPrint((__DRIVER_NAME " %02x: %02x\n", i, Srb->Cdb[i]));
767 KdPrint((__DRIVER_NAME " SrbFlags = 0x%02x\n", Srb->SrbFlags));
768 KdPrint((__DRIVER_NAME " DataTransferLength = %d\n", Srb->DataTransferLength));
769 #endif
770 XenScsi_PutSrbOnRing(TargetData, Srb);
771 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&TargetData->Ring, notify);
772 if (notify)
773 DeviceData->XenDeviceData->XenInterface.EvtChn_Notify(
774 DeviceData->XenDeviceData->XenInterface.InterfaceHeader.Context,
775 TargetData->EventChannel);
776 if (!RING_FULL(&TargetData->Ring))
777 ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
778 else
779 ScsiPortNotification(NextRequest, DeviceExtension);
780 break;
781 case SRB_FUNCTION_CLAIM_DEVICE:
782 KdPrint((__DRIVER_NAME " SRB_FUNCTION_CLAIM_DEVICE\n"));
783 // ObReferenceObject(WdfDeviceWdmGetDeviceObject(Device));
784 // Srb->DataBuffer = WdfDeviceWdmGetDeviceObject(Device);
785 Srb->SrbStatus = SRB_STATUS_SUCCESS;
786 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
787 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
788 break;
789 case SRB_FUNCTION_IO_CONTROL:
790 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
791 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
792 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
793 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
794 break;
795 case SRB_FUNCTION_FLUSH:
796 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
797 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
798 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
799 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
800 break;
801 default:
802 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
803 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
804 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
805 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
806 break;
807 }
809 // KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
811 return TRUE;
812 }
814 static BOOLEAN
815 XenScsi_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
816 {
817 UNREFERENCED_PARAMETER(DeviceExtension);
818 UNREFERENCED_PARAMETER(PathId);
821 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
822 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
824 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
826 return TRUE;
827 }
830 static BOOLEAN
831 XenScsi_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
832 {
833 UNREFERENCED_PARAMETER(DeviceExtension);
834 UNREFERENCED_PARAMETER(Context);
835 UNREFERENCED_PARAMETER(SaveState);
837 KdPrint((__DRIVER_NAME " --> HwScsiAdapterState\n"));
838 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
840 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterState\n"));
842 return TRUE;
843 }
845 static SCSI_ADAPTER_CONTROL_STATUS
846 XenScsi_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
847 {
848 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
849 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
851 UNREFERENCED_PARAMETER(DeviceExtension);
853 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
854 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
856 switch (ControlType)
857 {
858 case ScsiQuerySupportedControlTypes:
859 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
860 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
861 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
862 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
863 break;
864 case ScsiStopAdapter:
865 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
866 break;
867 case ScsiRestartAdapter:
868 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
869 break;
870 case ScsiSetBootConfig:
871 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
872 break;
873 case ScsiSetRunningConfig:
874 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
875 break;
876 default:
877 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
878 break;
879 }
881 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
883 return Status;
884 }