win-pvdrivers

view xenscsi/xenscsi.c @ 993:61fea9275419

Added tag 0.11.0.369 for changeset 58899e6ed48f
author James Harper <james.harper@bendigoit.com.au>
date Fri Sep 21 23:34:14 2012 +1000 (2012-09-21)
parents 941699790045
children
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenscsi.h"
22 /* Not really necessary but keeps PREfast happy */
23 DRIVER_INITIALIZE DriverEntry;
25 #ifdef ALLOC_PRAGMA
26 #pragma alloc_text (INIT, DriverEntry)
27 #endif
29 #pragma warning(disable: 4127)
31 static BOOLEAN dump_mode = FALSE;
33 static vscsiif_shadow_t *
34 get_shadow_from_freelist(PXENSCSI_DEVICE_DATA xsdd)
35 {
36 if (xsdd->shadow_free == 0)
37 {
38 KdPrint((__DRIVER_NAME " No more shadow entries\n"));
39 return NULL;
40 }
41 xsdd->shadow_free--;
42 return &xsdd->shadows[xsdd->shadow_free_list[xsdd->shadow_free]];
43 }
45 static VOID
46 put_shadow_on_freelist(PXENSCSI_DEVICE_DATA xsdd, vscsiif_shadow_t *shadow)
47 {
48 xsdd->shadow_free_list[xsdd->shadow_free] = (USHORT)shadow->req.rqid;
49 shadow->Srb = NULL;
50 xsdd->shadow_free++;
51 }
53 static grant_ref_t
54 get_grant_from_freelist(PXENSCSI_DEVICE_DATA xsdd)
55 {
56 if (xsdd->grant_free == 0)
57 {
58 KdPrint((__DRIVER_NAME " No more grant refs\n"));
59 return (grant_ref_t)0x0FFFFFFF;
60 }
61 xsdd->grant_free--;
62 return xsdd->grant_free_list[xsdd->grant_free];
63 }
65 static VOID
66 put_grant_on_freelist(PXENSCSI_DEVICE_DATA xsdd, grant_ref_t grant)
67 {
68 xsdd->grant_free_list[xsdd->grant_free] = grant;
69 xsdd->grant_free++;
70 }
72 static VOID
73 XenScsi_CheckNewDevice(PVOID DeviceExtension)
74 {
75 PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
77 //FUNCTION_ENTER();
79 if (InterlockedCompareExchange(&xsdd->shared_paused, SHARED_PAUSED_SCSIPORT_PAUSED, SHARED_PAUSED_PASSIVE_PAUSED) == SHARED_PAUSED_PASSIVE_PAUSED)
80 {
81 KdPrint((__DRIVER_NAME " scsiport paused\n"));
82 xsdd->scsiport_paused = TRUE;
83 }
84 if (InterlockedCompareExchange(&xsdd->shared_paused, SHARED_PAUSED_SCSIPORT_UNPAUSED, SHARED_PAUSED_PASSIVE_UNPAUSED) == SHARED_PAUSED_PASSIVE_UNPAUSED)
85 {
86 int i;
87 KdPrint((__DRIVER_NAME " scsiport unpaused\n"));
88 xsdd->scsiport_paused = FALSE;
89 for (i = 0; i < 8; i++)
90 {
91 if (xsdd->bus_changes[i])
92 {
93 KdPrint((__DRIVER_NAME " Sending BusChangeDetected for channel %d\n", i));
94 ScsiPortNotification(BusChangeDetected, DeviceExtension, i);
95 }
96 }
97 ScsiPortNotification(NextRequest, DeviceExtension);
98 }
99 if (xsdd->scsiport_paused) /* check more often if we are paused */
100 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckNewDevice, 100 * 1000); /* 100ms second from the last check */
101 else
102 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckNewDevice, 1 * 1000 * 1000); /* 1 second from the last check */
103 //FUNCTION_EXIT();
104 }
106 static BOOLEAN
107 XenScsi_HwScsiInterrupt(PVOID DeviceExtension)
108 {
109 PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
110 PSCSI_REQUEST_BLOCK Srb;
111 RING_IDX i, rp;
112 int j;
113 vscsiif_response_t *rep;
114 int more_to_do = TRUE;
115 vscsiif_shadow_t *shadow;
116 BOOLEAN last_interrupt = FALSE;
118 XenScsi_CheckNewDevice(DeviceExtension);
120 if (!dump_mode && !xsdd->vectors.EvtChn_AckEvent(xsdd->vectors.context, xsdd->event_channel, &last_interrupt))
121 {
122 return FALSE;
123 }
125 //FUNCTION_ENTER();
127 while (more_to_do)
128 {
129 rp = xsdd->ring.sring->rsp_prod;
130 KeMemoryBarrier();
131 for (i = xsdd->ring.rsp_cons; i != rp; i++)
132 {
133 rep = RING_GET_RESPONSE(&xsdd->ring, i);
134 shadow = &xsdd->shadows[rep->rqid];
135 Srb = shadow->Srb;
136 Srb->ScsiStatus = (UCHAR)rep->rslt;
137 memset(Srb->SenseInfoBuffer, 0, Srb->SenseInfoBufferLength);
138 if (rep->sense_len > 0 && Srb->SenseInfoBuffer != NULL)
139 {
140 memcpy(Srb->SenseInfoBuffer, rep->sense_buffer, min(Srb->SenseInfoBufferLength, rep->sense_len));
141 }
142 switch(rep->rslt)
143 {
144 case 0:
145 //KdPrint((__DRIVER_NAME " Xen Operation complete - result = 0x%08x, sense_len = %d, residual = %d\n", rep->rslt, rep->sense_len, rep->residual_len));
146 Srb->SrbStatus = SRB_STATUS_SUCCESS;
147 if (Srb->Cdb[0] == 0x03)
148 {
149 KdPrint((__DRIVER_NAME " REQUEST_SENSE DataTransferLength = %d, residual = %d\n", Srb->DataTransferLength, rep->residual_len));
150 //for (j = 0; j < Srb->DataTransferLength - rep->residual_len; j++)
151 // KdPrint((__DRIVER_NAME " sense %02x: %02x\n", j, (ULONG)((PUCHAR)Srb->DataBuffer)[j]));
152 }
153 break;
154 case 0x00010000: /* Device does not exist */
155 KdPrint((__DRIVER_NAME " Xen Operation error - cdb[0] = %02x, result = 0x%08x, sense_len = %d, residual = %d\n", (ULONG)Srb->Cdb[0], rep->rslt, rep->sense_len, rep->residual_len));
156 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
157 break;
158 default:
159 KdPrint((__DRIVER_NAME " Xen Operation error - cdb[0] = %02x, result = 0x%08x, sense_len = %d, residual = %d\n", (ULONG)Srb->Cdb[0], rep->rslt, rep->sense_len, rep->residual_len));
160 Srb->SrbStatus = SRB_STATUS_ERROR;
162 //for (j = 0; j < Srb->SenseInfoBufferLength; j++)
163 // KdPrint((__DRIVER_NAME " sense %02x: %02x\n", j, (ULONG)((PUCHAR)Srb->SenseInfoBuffer)[j]));
165 if (rep->sense_len > 0 && !(Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) && Srb->SenseInfoBuffer != NULL)
166 {
167 KdPrint((__DRIVER_NAME " Doing autosense\n"));
168 Srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
169 }
170 else if (Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
171 {
172 PXENSCSI_LU_DATA lud = ScsiPortGetLogicalUnit(DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
173 KdPrint((__DRIVER_NAME " Autosense disabled\n"));
174 if (lud != NULL)
175 {
176 KdPrint((__DRIVER_NAME " Saving sense data\n"));
177 lud->sense_len = rep->sense_len;
178 memcpy(lud->sense_buffer, Srb->SenseInfoBuffer, lud->sense_len);
179 }
180 }
181 }
183 /* work around a bug in scsiback that gives an incorrect result to REPORT_LUNS - fail it if the output is only 8 bytes */
184 if (Srb->Cdb[0] == 0xa0 && Srb->SrbStatus == SRB_STATUS_SUCCESS &&
185 Srb->DataTransferLength - rep->residual_len == 8)
186 {
187 /* SRB_STATUS_ERROR appears to be sufficient here - no need to worry about sense data or anything */
188 KdPrint((__DRIVER_NAME " Worked around bad REPORT_LUNS emulation for %d:%d:%d\n",
189 Srb->PathId, Srb->TargetId, Srb->Lun));
190 Srb->SrbStatus = SRB_STATUS_ERROR;
191 }
192 //remaining = Srb->DataTransferLength;
193 for (j = 0; j < shadow->req.nr_segments; j++)
194 {
195 xsdd->vectors.GntTbl_EndAccess(xsdd->vectors.context, shadow->req.seg[j].gref, TRUE, (ULONG)'SCSI');
196 put_grant_on_freelist(xsdd, shadow->req.seg[j].gref);
197 shadow->req.seg[j].gref = 0;
198 }
200 if (Srb->SrbStatus == SRB_STATUS_SUCCESS && rep->residual_len)
201 {
202 // KdPrint((__DRIVER_NAME " SRB_STATUS_DATA_OVERRUN DataTransferLength = %d, adjusted = %d\n",
203 // Srb->DataTransferLength, Srb->DataTransferLength - rep->residual_len));
204 Srb->DataTransferLength -= rep->residual_len;
205 Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
206 }
208 put_shadow_on_freelist(xsdd, shadow);
209 ScsiPortNotification(RequestComplete, xsdd, Srb);
210 if (!xsdd->scsiport_paused)
211 ScsiPortNotification(NextRequest, DeviceExtension);
212 }
214 xsdd->ring.rsp_cons = i;
215 if (i != xsdd->ring.req_prod_pvt)
216 {
217 RING_FINAL_CHECK_FOR_RESPONSES(&xsdd->ring, more_to_do);
218 }
219 else
220 {
221 xsdd->ring.sring->rsp_event = i + 1;
222 more_to_do = FALSE;
223 }
224 }
226 //FUNCTION_EXIT();
228 return last_interrupt;
229 }
231 static VOID
232 XenScsi_ParseBackendDevice(scsi_dev_t *dev, PCHAR value)
233 {
234 int i = 0;
235 int j = 0;
236 BOOLEAN scanning = TRUE;
238 while (scanning)
239 {
240 if (value[i] == 0)
241 scanning = FALSE;
242 if (value[i] == ':' || value[i] == 0)
243 {
244 value[i] = 0;
245 dev->host = dev->channel;
246 dev->channel = dev->id;
247 dev->id = dev->lun;
248 dev->lun = (UCHAR)atoi(&value[j]);
249 j = i + 1;
250 }
251 i++;
252 }
253 KdPrint((__DRIVER_NAME " host = %d, channel = %d, id = %d, lun = %d\n",
254 dev->host, dev->channel, dev->id, dev->lun));
255 }
257 /* CALLED AT PASSIVE LEVEL */
258 /* If Initialize fails then the watch still gets called but the waits will never be acked... */
259 static VOID
260 XenScsi_DevWatch(PCHAR path, PVOID DeviceExtension)
261 {
262 PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
263 CHAR tmp_path[128];
264 PCHAR msg;
265 PCHAR *devices;
266 PCHAR value;
267 scsi_dev_t *dev;
268 ULONG i;
269 ULONG dev_no;
270 ULONG state;
271 LARGE_INTEGER wait_time;
272 #if DBG
273 ULONG oldpause;
274 #endif
276 UNREFERENCED_PARAMETER(path);
278 /* this can only be called from a watch and so is always serialised */
279 FUNCTION_ENTER();
281 #if DBG
282 oldpause =
283 #endif
284 InterlockedExchange(&xsdd->shared_paused, SHARED_PAUSED_PASSIVE_PAUSED);
285 ASSERT(oldpause == SHARED_PAUSED_SCSIPORT_UNPAUSED);
287 while (InterlockedCompareExchange(&xsdd->shared_paused, SHARED_PAUSED_SCSIPORT_PAUSED, SHARED_PAUSED_SCSIPORT_PAUSED) != SHARED_PAUSED_SCSIPORT_PAUSED)
288 {
289 KdPrint((__DRIVER_NAME " Waiting for pause...\n"));
290 wait_time.QuadPart = -100 * 1000 * 10; /* 100ms */
291 KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
292 }
294 KdPrint((__DRIVER_NAME " Watch triggered on %s\n", path));
295 RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
296 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs");
297 msg = xsdd->vectors.XenBus_List(xsdd->vectors.context, XBT_NIL, tmp_path, &devices);
298 if (msg)
299 {
300 /* this is pretty fatal ... */
301 KdPrint((__DRIVER_NAME " cannot read - %s\n", msg));
302 return;
303 }
304 for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink;
305 dev != (scsi_dev_t *)&xsdd->dev_list_head;
306 dev = (scsi_dev_t *)dev->entry.Flink)
307 {
308 dev->validated = FALSE;
309 }
311 for (i = 0; devices[i]; i++)
312 {
313 if (strncmp(devices[i], "dev-", 4) != 0)
314 {
315 XenPci_FreeMem(devices[i]);
316 break; /* not a dev so we are not interested */
317 }
318 dev_no = atoi(devices[i] + 4);
319 RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
320 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
321 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
322 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/state");
323 msg = xsdd->vectors.XenBus_Read(xsdd->vectors.context, XBT_NIL, tmp_path, &value);
324 if (msg)
325 {
326 KdPrint((__DRIVER_NAME " failed to read state for device %d\n", dev_no));
327 state = 0;
328 }
329 else
330 state = atoi(value);
331 for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink;
332 dev != (scsi_dev_t *)&xsdd->dev_list_head;
333 dev = (scsi_dev_t * )dev->entry.Flink)
334 {
335 if (dev->dev_no == dev_no)
336 break;
337 }
338 if (dev == (scsi_dev_t *)&xsdd->dev_list_head)
339 {
340 KdPrint((__DRIVER_NAME " new dev %d\n", dev_no));
341 dev = ExAllocatePoolWithTag(NonPagedPool, sizeof(scsi_dev_t), XENSCSI_POOL_TAG);
342 dev->dev_no = dev_no;
343 dev->state = state;
344 dev->validated = TRUE;
345 RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
346 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
347 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
348 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/v-dev");
349 msg = xsdd->vectors.XenBus_Read(xsdd->vectors.context, XBT_NIL, tmp_path, &value);
350 if (msg)
351 {
352 KdPrint((__DRIVER_NAME " failed to read v-dev for device %d\n", dev_no));
353 continue;
354 }
355 else
356 {
357 XenScsi_ParseBackendDevice(dev, value);
358 // should verify that the controller = this
359 }
360 RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.path);
361 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
362 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
363 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/state");
364 msg = xsdd->vectors.XenBus_Write(xsdd->vectors.context, XBT_NIL, tmp_path, "4");
365 if (msg)
366 {
367 KdPrint((__DRIVER_NAME " failed to write state %d to %s\n", 4, tmp_path));
368 continue;
369 }
370 KdPrint((__DRIVER_NAME " setting changes[%d]\n", dev->channel));
371 xsdd->bus_changes[dev->channel] = 1;
372 InsertTailList(&xsdd->dev_list_head, (PLIST_ENTRY)dev);
373 }
374 else
375 {
376 // need to manage state change
377 // and write frontend state
378 dev->state = state;
379 dev->validated = TRUE;
380 KdPrint((__DRIVER_NAME " existing dev %d state = %d\n", dev_no, dev->state));
381 }
382 XenPci_FreeMem(devices[i]);
383 }
384 XenPci_FreeMem(devices);
386 #if DBG
387 oldpause =
388 #endif
389 InterlockedExchange(&xsdd->shared_paused, SHARED_PAUSED_PASSIVE_UNPAUSED);
390 ASSERT(oldpause == SHARED_PAUSED_SCSIPORT_PAUSED);
392 while (InterlockedCompareExchange(&xsdd->shared_paused, SHARED_PAUSED_SCSIPORT_UNPAUSED, SHARED_PAUSED_SCSIPORT_UNPAUSED) != SHARED_PAUSED_SCSIPORT_UNPAUSED)
393 {
394 KdPrint((__DRIVER_NAME " Waiting for unpause...\n"));
395 wait_time.QuadPart = -100 * 1000 * 10; /* 100ms */
396 KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
397 }
398 KdPrint((__DRIVER_NAME " Unpaused\n"));
400 FUNCTION_EXIT();
401 }
403 static ULONG
404 XenScsi_HwScsiFindAdapter(PVOID DeviceExtension, PVOID Reserved1, PVOID Reserved2, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PUCHAR Reserved3)
405 {
406 ULONG i;
407 PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
408 PACCESS_RANGE access_range;
409 PUCHAR ptr;
410 USHORT type;
411 PCHAR setting, value, value2;
412 vscsiif_sring_t *sring;
413 CHAR path[128];
415 UNREFERENCED_PARAMETER(Reserved1);
416 UNREFERENCED_PARAMETER(Reserved2);
417 UNREFERENCED_PARAMETER(ArgumentString);
418 UNREFERENCED_PARAMETER(Reserved3);
420 FUNCTION_ENTER();
421 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
423 xsdd->scsiport_paused = TRUE; /* wait for initial scan */
425 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
426 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
428 if (!ConfigInfo->BusInterruptVector)
429 {
430 KdPrint((__DRIVER_NAME " No Interrupt assigned\n"));
431 return SP_RETURN_BAD_CONFIG;
432 }
434 if (ConfigInfo->NumberOfAccessRanges != 1)
435 {
436 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
437 return SP_RETURN_BAD_CONFIG;
438 }
440 ptr = NULL;
441 access_range = &((*(ConfigInfo->AccessRanges))[0]);
442 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
443 access_range->RangeStart.LowPart, access_range->RangeLength));
444 ptr = ScsiPortGetDeviceBase(
445 DeviceExtension,
446 ConfigInfo->AdapterInterfaceType,
447 ConfigInfo->SystemIoBusNumber,
448 access_range->RangeStart,
449 access_range->RangeLength,
450 !access_range->RangeInMemory);
451 if (!ptr)
452 {
453 KdPrint((__DRIVER_NAME " Unable to map range\n"));
454 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
455 return SP_RETURN_BAD_CONFIG;
456 }
457 sring = NULL;
458 xsdd->event_channel = 0;
459 while((type = GET_XEN_INIT_RSP(&ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
460 {
461 switch(type)
462 {
463 case XEN_INIT_TYPE_RING: /* frontend ring */
464 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
465 if (strcmp(setting, "ring-ref") == 0)
466 {
467 sring = (vscsiif_sring_t *)value;
468 FRONT_RING_INIT(&xsdd->ring, sring, PAGE_SIZE);
469 }
470 break;
471 //case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
472 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
473 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
474 if (strcmp(setting, "event-channel") == 0)
475 {
476 xsdd->event_channel = PtrToUlong(value);
477 }
478 break;
479 case XEN_INIT_TYPE_READ_STRING_BACK:
480 case XEN_INIT_TYPE_READ_STRING_FRONT:
481 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
482 break;
483 case XEN_INIT_TYPE_VECTORS:
484 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
485 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
486 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
487 {
488 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
489 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
490 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
491 return SP_RETURN_BAD_CONFIG;
492 }
493 else
494 memcpy(&xsdd->vectors, value, sizeof(XENPCI_VECTORS));
495 break;
496 case XEN_INIT_TYPE_GRANT_ENTRIES:
497 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(value)));
498 xsdd->grant_entries = (USHORT)PtrToUlong(value);
499 memcpy(&xsdd->grant_free_list, value2, sizeof(grant_ref_t) * xsdd->grant_entries);
500 xsdd->grant_free = xsdd->grant_entries;
501 break;
502 default:
503 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
504 break;
505 }
506 }
508 if (sring == NULL || xsdd->event_channel == 0)
509 {
510 KdPrint((__DRIVER_NAME " Missing settings\n"));
511 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
512 return SP_RETURN_BAD_CONFIG;
513 }
515 ConfigInfo->ScatterGather = TRUE;
516 ConfigInfo->NumberOfPhysicalBreaks = VSCSIIF_SG_TABLESIZE - 1;
517 ConfigInfo->MaximumTransferLength = VSCSIIF_SG_TABLESIZE * PAGE_SIZE;
518 ConfigInfo->CachesData = FALSE;
519 ConfigInfo->NumberOfBuses = 4; //SCSI_MAXIMUM_BUSES; //8
520 ConfigInfo->MaximumNumberOfTargets = 16;
521 ConfigInfo->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS; // 8
522 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
523 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
524 {
525 ConfigInfo->Master = TRUE;
526 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
527 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
528 }
529 else
530 {
531 ConfigInfo->Master = FALSE;
532 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
533 }
534 ConfigInfo->InitiatorBusId[0] = 7;
535 ConfigInfo->InitiatorBusId[1] = 7;
536 ConfigInfo->InitiatorBusId[2] = 7;
537 ConfigInfo->InitiatorBusId[3] = 7;
538 xsdd->shadow_free = 0;
539 memset(xsdd->shadows, 0, sizeof(vscsiif_shadow_t) * SHADOW_ENTRIES);
540 for (i = 0; i < SHADOW_ENTRIES; i++)
541 {
542 xsdd->shadows[i].req.rqid = (USHORT)i;
543 put_shadow_on_freelist(xsdd, &xsdd->shadows[i]);
544 }
546 if (!dump_mode)
547 {
548 InitializeListHead(&xsdd->dev_list_head);
549 /* should do something if we haven't enumerated in a certain time */
550 RtlStringCbCopyA(path, ARRAY_SIZE(path), xsdd->vectors.backend_path);
551 RtlStringCbCatA(path, ARRAY_SIZE(path), "/vscsi-devs");
552 xsdd->vectors.XenBus_AddWatch(xsdd->vectors.context, XBT_NIL, path,
553 XenScsi_DevWatch, xsdd);
554 }
555 FUNCTION_EXIT();
557 return SP_RETURN_FOUND;
558 }
560 static BOOLEAN
561 XenScsi_HwScsiInitialize(PVOID DeviceExtension)
562 {
563 PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
564 UNREFERENCED_PARAMETER(DeviceExtension);
566 FUNCTION_ENTER();
567 xsdd->shared_paused = SHARED_PAUSED_SCSIPORT_UNPAUSED;
568 ScsiPortNotification(RequestTimerCall, DeviceExtension, XenScsi_CheckNewDevice, 1 * 1000 * 1000); /* 1 second */
570 FUNCTION_EXIT();
572 return TRUE;
573 }
575 static VOID
576 XenScsi_PutSrbOnRing(PXENSCSI_DEVICE_DATA xsdd, PSCSI_REQUEST_BLOCK Srb)
577 {
578 PHYSICAL_ADDRESS physical_address;
579 ULONG remaining;
580 PUCHAR ptr;
581 //ULONG i;
582 PFN_NUMBER pfn;
583 vscsiif_shadow_t *shadow;
584 int notify;
586 //FUNCTION_ENTER();
588 shadow = get_shadow_from_freelist(xsdd);
589 ASSERT(shadow);
590 shadow->Srb = Srb;
591 shadow->req.act = VSCSIIF_ACT_SCSI_CDB;
592 memset(shadow->req.cmnd, 0, VSCSIIF_MAX_COMMAND_SIZE);
593 memcpy(shadow->req.cmnd, Srb->Cdb, min(Srb->CdbLength, VSCSIIF_MAX_COMMAND_SIZE));
594 shadow->req.cmd_len = min(Srb->CdbLength, VSCSIIF_MAX_COMMAND_SIZE);
595 shadow->req.timeout_per_command = (USHORT)Srb->TimeOutValue;
596 shadow->req.channel = (USHORT)Srb->PathId;
597 shadow->req.id = (USHORT)Srb->TargetId;
598 shadow->req.lun = (USHORT)Srb->Lun;
599 if (Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_IN) && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT))
600 {
601 //KdPrint((__DRIVER_NAME " Cmd = %02x, Length = %d, DMA_BIDIRECTIONAL\n", Srb->Cdb[0], Srb->DataTransferLength));
602 shadow->req.sc_data_direction = DMA_BIDIRECTIONAL;
603 }
604 else if (Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_IN))
605 {
606 //KdPrint((__DRIVER_NAME " Cmd = %02x, Length = %d, DMA_FROM_DEVICE\n", Srb->Cdb[0], Srb->DataTransferLength));
607 shadow->req.sc_data_direction = DMA_FROM_DEVICE;
608 }
609 else if (Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT))
610 {
611 //KdPrint((__DRIVER_NAME " Cmd = %02x, Length = %d, DMA_TO_DEVICE\n", Srb->Cdb[0], Srb->DataTransferLength));
612 shadow->req.sc_data_direction = DMA_TO_DEVICE;
613 }
614 else
615 {
616 //KdPrint((__DRIVER_NAME " Cmd = %02x, Length = %d, DMA_NONE\n", Srb->Cdb[0], Srb->DataTransferLength));
617 shadow->req.sc_data_direction = DMA_NONE;
618 }
620 remaining = Srb->DataTransferLength;
621 shadow->req.seg[0].offset = 0;
622 shadow->req.seg[0].length = 0;
623 shadow->req.nr_segments = 0;
625 for (ptr = Srb->DataBuffer, shadow->req.nr_segments = 0; remaining != 0; shadow->req.nr_segments++)
626 {
627 if (shadow->req.nr_segments >= VSCSIIF_SG_TABLESIZE)
628 {
629 KdPrint((__DRIVER_NAME " too many segments (length = %d, remaining = %d)\n", Srb->DataTransferLength, remaining));
630 }
631 physical_address = MmGetPhysicalAddress(ptr);
632 pfn = (ULONG)(physical_address.QuadPart >> PAGE_SHIFT);
633 shadow->req.seg[shadow->req.nr_segments].gref = get_grant_from_freelist(xsdd);
634 if (shadow->req.seg[shadow->req.nr_segments].gref == 0x0FFFFFFF)
635 {
636 return; /* better than crashing... */
637 }
638 xsdd->vectors.GntTbl_GrantAccess(xsdd->vectors.context, 0, (ULONG)pfn, shadow->req.seg[shadow->req.nr_segments].gref, (ULONG)'SCSI');
639 shadow->req.seg[shadow->req.nr_segments].offset = (USHORT)(physical_address.LowPart & (PAGE_SIZE - 1));
640 shadow->req.seg[shadow->req.nr_segments].length = (USHORT)min(PAGE_SIZE - (ULONG)shadow->req.seg[shadow->req.nr_segments].offset, remaining);
641 remaining -= (ULONG)shadow->req.seg[shadow->req.nr_segments].length;
642 ptr += shadow->req.seg[shadow->req.nr_segments].length;
643 //KdPrint((__DRIVER_NAME " Page = %d, Offset = %d, Length = %d, Remaining = %d\n", shadow->req.nr_segments, shadow->req.seg[shadow->req.nr_segments].offset, shadow->req.seg[shadow->req.nr_segments].length, remaining));
644 }
645 *RING_GET_REQUEST(&xsdd->ring, xsdd->ring.req_prod_pvt) = shadow->req;
646 xsdd->ring.req_prod_pvt++;
647 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xsdd->ring, notify);
648 if (notify)
649 {
650 //KdPrint((__DRIVER_NAME " Notifying %d\n", xsdd->event_channel));
651 xsdd->vectors.EvtChn_Notify(xsdd->vectors.context, xsdd->event_channel);
652 }
654 //FUNCTION_EXIT();
655 }
657 static BOOLEAN
658 XenScsi_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
659 {
660 PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
661 scsi_dev_t *dev;
663 //FUNCTION_ENTER();
665 XenScsi_CheckNewDevice(DeviceExtension);
667 if (xsdd->scsiport_paused)
668 {
669 KdPrint((__DRIVER_NAME " Busy\n"));
670 Srb->SrbStatus = SRB_STATUS_BUSY;
671 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
672 //FUNCTION_EXIT();
673 return TRUE;
674 }
676 for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink;
677 dev != (scsi_dev_t *)&xsdd->dev_list_head;
678 dev = (scsi_dev_t * )dev->entry.Flink)
679 {
680 if (dev->channel == Srb->PathId && dev->id == Srb->TargetId && dev->lun == Srb->Lun)
681 break;
682 }
683 if (dev == (scsi_dev_t *)&xsdd->dev_list_head)
684 {
685 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
686 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
687 //KdPrint((__DRIVER_NAME " Out of bounds\n"));
688 ScsiPortNotification(NextRequest, DeviceExtension);
689 //FUNCTION_EXIT();
690 return TRUE;
691 }
693 switch (Srb->Function)
694 {
695 case SRB_FUNCTION_EXECUTE_SCSI:
696 switch (Srb->Cdb[0])
697 {
698 case 0x03: { /* REQUEST_SENSE*/
699 /* but what about when we allow multiple requests per lu? */
700 PXENSCSI_LU_DATA lud = ScsiPortGetLogicalUnit(DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
701 if (lud != NULL && lud->sense_len)
702 {
703 int i;
704 KdPrint((__DRIVER_NAME " Emulating REQUEST_SENSE (lu data = %p)\n", lud));
705 memcpy(Srb->DataBuffer, lud->sense_buffer, min(lud->sense_len, Srb->DataTransferLength));
706 if (lud->sense_len > Srb->DataTransferLength)
707 {
708 KdPrint((__DRIVER_NAME " Sense overrun Srb->DataTransferLength = %d, lud->sense_len = %d\n", Srb->DataTransferLength, lud->sense_len));
709 Srb->DataTransferLength = lud->sense_len;
710 Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
711 }
712 else
713 {
714 Srb->SrbStatus = SRB_STATUS_SUCCESS;
715 }
716 for (i = 0; i < min(lud->sense_len, 8); i++)
717 KdPrint((__DRIVER_NAME " sense %02x: %02x\n", i, (ULONG)((PUCHAR)lud->sense_buffer)[i]));
718 lud->sense_len = 0;
719 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
720 ScsiPortNotification(NextRequest, DeviceExtension);
721 break;
722 }
723 else
724 {
725 KdPrint((__DRIVER_NAME " Issuing REQUEST_SENSE (lud = %p)\n", lud));
726 }
727 // fall through
728 }
729 default:
730 XenScsi_PutSrbOnRing(xsdd, Srb);
731 Srb->SrbStatus = SRB_STATUS_PENDING;
732 break;
733 }
734 break;
735 case SRB_FUNCTION_IO_CONTROL:
736 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
737 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
738 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
739 ScsiPortNotification(NextRequest, DeviceExtension);
740 break;
741 case SRB_FUNCTION_FLUSH:
742 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
743 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
744 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
745 ScsiPortNotification(NextRequest, DeviceExtension);
746 break;
747 default:
748 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
749 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
750 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
751 ScsiPortNotification(NextRequest, DeviceExtension);
752 break;
753 }
755 //FUNCTION_EXIT();
756 return TRUE;
757 }
759 static BOOLEAN
760 XenScsi_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
761 {
762 UNREFERENCED_PARAMETER(DeviceExtension);
763 UNREFERENCED_PARAMETER(PathId);
766 FUNCTION_ENTER();
767 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
768 ScsiPortNotification(NextRequest, DeviceExtension);
769 FUNCTION_EXIT();
771 return TRUE;
772 }
774 static SCSI_ADAPTER_CONTROL_STATUS
775 XenScsi_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
776 {
777 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
778 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
779 //KIRQL OldIrql;
781 UNREFERENCED_PARAMETER(DeviceExtension);
783 FUNCTION_ENTER();
784 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
786 switch (ControlType)
787 {
788 case ScsiQuerySupportedControlTypes:
789 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
790 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
791 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
792 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
793 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
794 break;
795 case ScsiStopAdapter:
796 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
797 break;
798 case ScsiRestartAdapter:
799 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
800 break;
801 case ScsiSetBootConfig:
802 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
803 break;
804 case ScsiSetRunningConfig:
805 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
806 break;
807 default:
808 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
809 break;
810 }
812 FUNCTION_EXIT();
814 return Status;
815 }
817 NTSTATUS
818 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
819 {
820 ULONG Status;
821 HW_INITIALIZATION_DATA HwInitializationData;
822 PVOID driver_extension;
823 PUCHAR ptr;
825 FUNCTION_ENTER();
827 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
829 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
830 ptr = driver_extension;
831 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
832 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
833 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, UlongToPtr((ULONG)'SCSI'), UlongToPtr(144), NULL);
834 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_PRE_CONNECT, NULL, NULL, NULL);
835 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitialised);
836 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
837 __ADD_XEN_INIT_UCHAR(&ptr, 20);
838 __ADD_XEN_INIT_UCHAR(&ptr, 0);
839 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_POST_CONNECT, NULL, NULL, NULL);
840 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
841 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateConnected);
842 __ADD_XEN_INIT_UCHAR(&ptr, 20);
843 __ADD_XEN_INIT_UCHAR(&ptr, 0);
844 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_XB_STATE_MAP_SHUTDOWN, NULL, NULL, NULL);
845 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
846 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosing);
847 __ADD_XEN_INIT_UCHAR(&ptr, 50);
848 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
849 __ADD_XEN_INIT_UCHAR(&ptr, XenbusStateClosed);
850 __ADD_XEN_INIT_UCHAR(&ptr, 50);
851 //__ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait); //ialising);
852 //__ADD_XEN_INIT_UCHAR(&ptr, XenbusStateInitWait);
853 //__ADD_XEN_INIT_UCHAR(&ptr, 50);
854 __ADD_XEN_INIT_UCHAR(&ptr, 0);
855 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
856 /* RegistryPath == NULL when we are invoked as a crash dump driver */
857 if (!RegistryPath)
858 {
859 dump_mode = TRUE;
860 }
862 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
864 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
865 HwInitializationData.AdapterInterfaceType = PNPBus;
866 HwInitializationData.DeviceExtensionSize = sizeof(XENSCSI_DEVICE_DATA);
867 HwInitializationData.SpecificLuExtensionSize = sizeof(XENSCSI_LU_DATA);
868 HwInitializationData.SrbExtensionSize = 0;
869 HwInitializationData.NumberOfAccessRanges = 1;
870 HwInitializationData.MapBuffers = TRUE;
871 HwInitializationData.NeedPhysicalAddresses = FALSE;
872 HwInitializationData.TaggedQueuing = TRUE;
873 HwInitializationData.AutoRequestSense = TRUE;
874 HwInitializationData.MultipleRequestPerLu = TRUE;
876 HwInitializationData.HwInitialize = XenScsi_HwScsiInitialize;
877 HwInitializationData.HwStartIo = XenScsi_HwScsiStartIo;
878 HwInitializationData.HwInterrupt = XenScsi_HwScsiInterrupt;
879 HwInitializationData.HwFindAdapter = XenScsi_HwScsiFindAdapter;
880 HwInitializationData.HwResetBus = XenScsi_HwScsiResetBus;
881 HwInitializationData.HwAdapterControl = XenScsi_HwScsiAdapterControl;
883 Status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
885 if(!NT_SUCCESS(Status))
886 {
887 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", Status));
888 }
890 FUNCTION_EXIT();
892 return Status;
893 }