win-pvdrivers

view xenscsi/xenscsi.c @ 783:644e5ddb1b47

Handle SCSI INQUIRY command better in xenvbd
author James Harper <james.harper@bendigoit.com.au>
date Mon Feb 15 20:53:57 2010 +1100 (2010-02-15)
parents 5bdb7251370c
children 150118f124a1
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 BOOLEAN
73 XenScsi_HwScsiInterrupt(PVOID DeviceExtension)
74 {
75 PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
76 PSCSI_REQUEST_BLOCK Srb;
77 RING_IDX i, rp;
78 int j;
79 vscsiif_response_t *rep;
80 int more_to_do = TRUE;
81 vscsiif_shadow_t *shadow;
82 BOOLEAN last_interrupt = FALSE;
84 if (xsdd->pause_ack != xsdd->pause_req)
85 {
86 xsdd->pause_ack = xsdd->pause_req;
87 KdPrint((__DRIVER_NAME " Pause state change to %d\n", xsdd->pause_ack));
88 if (!xsdd->pause_ack)
89 {
90 ScsiPortNotification(NextRequest, DeviceExtension);
91 }
92 }
93 if (!dump_mode && !xsdd->vectors.EvtChn_AckEvent(xsdd->vectors.context, xsdd->event_channel, &last_interrupt))
94 {
95 return FALSE;
96 }
98 //FUNCTION_ENTER();
100 while (more_to_do)
101 {
102 rp = xsdd->ring.sring->rsp_prod;
103 KeMemoryBarrier();
104 for (i = xsdd->ring.rsp_cons; i != rp; i++)
105 {
106 rep = RING_GET_RESPONSE(&xsdd->ring, i);
107 shadow = &xsdd->shadows[rep->rqid];
108 Srb = shadow->Srb;
109 Srb->ScsiStatus = (UCHAR)rep->rslt;
110 memset(Srb->SenseInfoBuffer, 0, Srb->SenseInfoBufferLength);
111 if (rep->sense_len > 0 && Srb->SenseInfoBuffer != NULL)
112 {
113 memcpy(Srb->SenseInfoBuffer, rep->sense_buffer, min(Srb->SenseInfoBufferLength, rep->sense_len));
114 }
115 switch(rep->rslt)
116 {
117 case 0:
118 //KdPrint((__DRIVER_NAME " Xen Operation complete - result = 0x%08x, sense_len = %d, residual = %d\n", rep->rslt, rep->sense_len, rep->residual_len));
119 Srb->SrbStatus = SRB_STATUS_SUCCESS;
120 if (Srb->Cdb[0] == 0x03)
121 {
122 KdPrint((__DRIVER_NAME " REQUEST_SENSE DataTransferLength = %d, residual = %d\n", Srb->DataTransferLength, rep->residual_len));
123 //for (j = 0; j < Srb->DataTransferLength - rep->residual_len; j++)
124 // KdPrint((__DRIVER_NAME " sense %02x: %02x\n", j, (ULONG)((PUCHAR)Srb->DataBuffer)[j]));
125 }
126 break;
127 case 0x00010000: /* Device does not exist */
128 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));
129 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
130 break;
131 default:
132 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));
133 Srb->SrbStatus = SRB_STATUS_ERROR;
135 //for (j = 0; j < Srb->SenseInfoBufferLength; j++)
136 // KdPrint((__DRIVER_NAME " sense %02x: %02x\n", j, (ULONG)((PUCHAR)Srb->SenseInfoBuffer)[j]));
138 if (rep->sense_len > 0 && !(Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) && Srb->SenseInfoBuffer != NULL)
139 {
140 KdPrint((__DRIVER_NAME " Doing autosense\n"));
141 Srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
142 }
143 else if (Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
144 {
145 PXENSCSI_LU_DATA lud = ScsiPortGetLogicalUnit(DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
146 KdPrint((__DRIVER_NAME " Autosense disabled\n"));
147 if (lud != NULL)
148 {
149 KdPrint((__DRIVER_NAME " Saving sense data\n"));
150 lud->sense_len = rep->sense_len;
151 memcpy(lud->sense_buffer, Srb->SenseInfoBuffer, lud->sense_len);
152 }
153 }
154 }
156 /* work around a bug in scsiback that gives an incorrect result to REPORT_LUNS - fail it if the output is only 8 bytes */
157 if (Srb->Cdb[0] == 0xa0 && Srb->SrbStatus == SRB_STATUS_SUCCESS &&
158 Srb->DataTransferLength - rep->residual_len == 8)
159 {
160 /* SRB_STATUS_ERROR appears to be sufficient here - no need to worry about sense data or anything */
161 KdPrint((__DRIVER_NAME " Worked around bad REPORT_LUNS emulation for %d:%d:%d\n",
162 Srb->PathId, Srb->TargetId, Srb->Lun));
163 Srb->SrbStatus = SRB_STATUS_ERROR;
164 }
165 //remaining = Srb->DataTransferLength;
166 for (j = 0; j < shadow->req.nr_segments; j++)
167 {
168 xsdd->vectors.GntTbl_EndAccess(xsdd->vectors.context, shadow->req.seg[j].gref, TRUE);
169 put_grant_on_freelist(xsdd, shadow->req.seg[j].gref);
170 shadow->req.seg[j].gref = 0;
171 }
173 if (Srb->SrbStatus == SRB_STATUS_SUCCESS && rep->residual_len)
174 {
175 // KdPrint((__DRIVER_NAME " SRB_STATUS_DATA_OVERRUN DataTransferLength = %d, adjusted = %d\n",
176 // Srb->DataTransferLength, Srb->DataTransferLength - rep->residual_len));
177 Srb->DataTransferLength -= rep->residual_len;
178 Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
179 }
181 put_shadow_on_freelist(xsdd, shadow);
182 ScsiPortNotification(RequestComplete, xsdd, Srb);
183 if (!xsdd->pause_ack)
184 ScsiPortNotification(NextRequest, DeviceExtension);
185 }
187 xsdd->ring.rsp_cons = i;
188 if (i != xsdd->ring.req_prod_pvt)
189 {
190 RING_FINAL_CHECK_FOR_RESPONSES(&xsdd->ring, more_to_do);
191 }
192 else
193 {
194 xsdd->ring.sring->rsp_event = i + 1;
195 more_to_do = FALSE;
196 }
197 }
199 //FUNCTION_EXIT();
201 return last_interrupt;
202 }
204 static VOID
205 XenScsi_ParseBackendDevice(scsi_dev_t *dev, PCHAR value)
206 {
207 int i = 0;
208 int j = 0;
209 BOOLEAN scanning = TRUE;
211 while (scanning)
212 {
213 if (value[i] == 0)
214 scanning = FALSE;
215 if (value[i] == ':' || value[i] == 0)
216 {
217 value[i] = 0;
218 dev->host = dev->channel;
219 dev->channel = dev->id;
220 dev->id = dev->lun;
221 dev->lun = (UCHAR)atoi(&value[j]);
222 j = i + 1;
223 }
224 i++;
225 }
226 KdPrint((__DRIVER_NAME " host = %d, channel = %d, id = %d, lun = %d\n",
227 dev->host, dev->channel, dev->id, dev->lun));
228 }
230 static VOID
231 XenScsi_WaitPause(PVOID DeviceExtension)
232 {
233 //PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
234 //LARGE_INTEGER wait_time;
236 UNREFERENCED_PARAMETER(DeviceExtension);
237 FUNCTION_ENTER();
238 #if 0
239 xsdd->vectors.EvtChn_Notify(xsdd->vectors.context, xsdd->device_state->pdo_event_channel);
240 while (xsdd->pause_ack != xsdd->pause_req)
241 {
242 KdPrint((__DRIVER_NAME " Waiting...\n"));
243 wait_time.QuadPart = -1 * 1000 * 10; /* 1ms */
244 KeDelayExecutionThread(KernelMode, FALSE, &wait_time);
245 xsdd->vectors.EvtChn_Notify(xsdd->vectors.context, xsdd->device_state->pdo_event_channel);
246 }
247 #endif
248 FUNCTION_EXIT();
249 }
251 /* CALLED AT PASSIVE LEVEL */
252 /* If Initialize fails then the watch still gets called but the waits will never be acked... */
253 static VOID
254 XenScsi_DevWatch(PCHAR path, PVOID DeviceExtension)
255 {
256 PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
257 CHAR tmp_path[128];
258 PCHAR msg;
259 PCHAR *devices;
260 PCHAR value;
261 scsi_dev_t *dev;
262 ULONG i;
263 ULONG dev_no;
264 ULONG state;
265 BOOLEAN changes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
267 UNREFERENCED_PARAMETER(path);
269 /* this can only be called from a watch and so is always serialised */
270 FUNCTION_ENTER();
271 xsdd->pause_req = TRUE;
272 XenScsi_WaitPause(DeviceExtension);
274 KdPrint((__DRIVER_NAME " Watch triggered on %s\n", path));
275 RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
276 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs");
277 msg = xsdd->vectors.XenBus_List(xsdd->vectors.context, XBT_NIL, tmp_path, &devices);
278 if (msg)
279 {
280 /* this is pretty fatal ... */
281 KdPrint((__DRIVER_NAME " cannot read - %s\n", msg));
282 return;
283 }
284 for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink;
285 dev != (scsi_dev_t *)&xsdd->dev_list_head;
286 dev = (scsi_dev_t *)dev->entry.Flink)
287 {
288 dev->validated = FALSE;
289 }
291 for (i = 0; devices[i]; i++)
292 {
293 if (strncmp(devices[i], "dev-", 4) != 0)
294 {
295 XenPci_FreeMem(devices[i]);
296 break; /* not a dev so we are not interested */
297 }
298 dev_no = atoi(devices[i] + 4);
299 RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
300 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
301 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
302 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/state");
303 msg = xsdd->vectors.XenBus_Read(xsdd->vectors.context, XBT_NIL, tmp_path, &value);
304 if (msg)
305 {
306 KdPrint((__DRIVER_NAME " failed to read state for device %d\n", dev_no));
307 state = 0;
308 }
309 else
310 state = atoi(value);
311 for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink;
312 dev != (scsi_dev_t *)&xsdd->dev_list_head;
313 dev = (scsi_dev_t * )dev->entry.Flink)
314 {
315 if (dev->dev_no == dev_no)
316 break;
317 }
318 if (dev == (scsi_dev_t *)&xsdd->dev_list_head)
319 {
320 KdPrint((__DRIVER_NAME " new dev %d\n", dev_no));
321 dev = ExAllocatePoolWithTag(NonPagedPool, sizeof(scsi_dev_t), XENSCSI_POOL_TAG);
322 dev->dev_no = dev_no;
323 dev->state = state;
324 dev->validated = TRUE;
325 RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.backend_path);
326 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
327 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
328 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/v-dev");
329 msg = xsdd->vectors.XenBus_Read(xsdd->vectors.context, XBT_NIL, tmp_path, &value);
330 if (msg)
331 {
332 KdPrint((__DRIVER_NAME " failed to read v-dev for device %d\n", dev_no));
333 continue;
334 }
335 else
336 {
337 XenScsi_ParseBackendDevice(dev, value);
338 // should verify that the controller = this
339 }
340 RtlStringCbCopyA(tmp_path, ARRAY_SIZE(tmp_path), xsdd->vectors.path);
341 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/vscsi-devs/");
342 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), devices[i]);
343 RtlStringCbCatA(tmp_path, ARRAY_SIZE(tmp_path), "/state");
344 msg = xsdd->vectors.XenBus_Write(xsdd->vectors.context, XBT_NIL, tmp_path, "4");
345 if (msg)
346 {
347 KdPrint((__DRIVER_NAME " failed to write state %d to %s\n", 4, tmp_path));
348 continue;
349 }
350 KdPrint((__DRIVER_NAME " setting changes[%d]\n", dev->channel));
351 changes[dev->channel] = TRUE;
352 InsertTailList(&xsdd->dev_list_head, (PLIST_ENTRY)dev);
353 }
354 else
355 {
356 // need to manage state change
357 // and write frontend state
358 dev->state = state;
359 dev->validated = TRUE;
360 KdPrint((__DRIVER_NAME " existing dev %d state = %d\n", dev_no, dev->state));
361 }
362 XenPci_FreeMem(devices[i]);
363 }
364 XenPci_FreeMem(devices);
366 for (i = 0; i < 8; i++)
367 {
368 if (changes[i])
369 {
370 KdPrint((__DRIVER_NAME " Sending BusChangeDetected for channel %d\n", i));
371 ScsiPortNotification(BusChangeDetected, DeviceExtension, i);
372 }
373 }
375 xsdd->pause_req = FALSE;
376 XenScsi_WaitPause(DeviceExtension);
377 KdPrint((__DRIVER_NAME " Unpaused\n"));
379 FUNCTION_EXIT();
380 }
382 static ULONG
383 XenScsi_HwScsiFindAdapter(PVOID DeviceExtension, PVOID Reserved1, PVOID Reserved2, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PUCHAR Reserved3)
384 {
385 ULONG i;
386 PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
387 PACCESS_RANGE access_range;
388 PUCHAR ptr;
389 USHORT type;
390 PCHAR setting, value, value2;
391 vscsiif_sring_t *sring;
392 CHAR path[128];
394 UNREFERENCED_PARAMETER(Reserved1);
395 UNREFERENCED_PARAMETER(Reserved2);
396 UNREFERENCED_PARAMETER(ArgumentString);
397 UNREFERENCED_PARAMETER(Reserved3);
399 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
400 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
402 xsdd->pause_req = TRUE;
403 xsdd->pause_ack = TRUE;
405 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
406 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
408 if (!ConfigInfo->BusInterruptVector)
409 {
410 KdPrint((__DRIVER_NAME " No Interrupt assigned\n"));
411 return SP_RETURN_BAD_CONFIG;
412 }
414 if (ConfigInfo->NumberOfAccessRanges != 1)
415 {
416 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
417 return SP_RETURN_BAD_CONFIG;
418 }
420 ptr = NULL;
421 access_range = &((*(ConfigInfo->AccessRanges))[0]);
422 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
423 access_range->RangeStart.LowPart, access_range->RangeLength));
424 ptr = ScsiPortGetDeviceBase(
425 DeviceExtension,
426 ConfigInfo->AdapterInterfaceType,
427 ConfigInfo->SystemIoBusNumber,
428 access_range->RangeStart,
429 access_range->RangeLength,
430 !access_range->RangeInMemory);
431 if (!ptr)
432 {
433 KdPrint((__DRIVER_NAME " Unable to map range\n"));
434 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
435 return SP_RETURN_BAD_CONFIG;
436 }
437 sring = NULL;
438 xsdd->event_channel = 0;
439 while((type = GET_XEN_INIT_RSP(&ptr, &setting, &value, &value2)) != XEN_INIT_TYPE_END)
440 {
441 switch(type)
442 {
443 case XEN_INIT_TYPE_RING: /* frontend ring */
444 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
445 if (strcmp(setting, "ring-ref") == 0)
446 {
447 sring = (vscsiif_sring_t *)value;
448 FRONT_RING_INIT(&xsdd->ring, sring, PAGE_SIZE);
449 }
450 break;
451 //case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
452 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
453 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
454 if (strcmp(setting, "event-channel") == 0)
455 {
456 xsdd->event_channel = PtrToUlong(value);
457 }
458 break;
459 case XEN_INIT_TYPE_READ_STRING_BACK:
460 case XEN_INIT_TYPE_READ_STRING_FRONT:
461 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
462 break;
463 case XEN_INIT_TYPE_VECTORS:
464 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
465 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
466 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
467 {
468 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
469 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
470 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
471 return SP_RETURN_BAD_CONFIG;
472 }
473 else
474 memcpy(&xsdd->vectors, value, sizeof(XENPCI_VECTORS));
475 break;
476 case XEN_INIT_TYPE_GRANT_ENTRIES:
477 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(setting)));
478 xsdd->grant_entries = (USHORT)PtrToUlong(setting);
479 memcpy(&xsdd->grant_free_list, value, sizeof(grant_ref_t) * xsdd->grant_entries);
480 xsdd->grant_free = xsdd->grant_entries;
481 break;
482 default:
483 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
484 break;
485 }
486 }
487 #if 0
488 if (xsdd->device_type == XENSCSI_DEVICETYPE_UNKNOWN
489 || sring == NULL
490 || xsdd->event_channel == 0)
491 {
492 KdPrint((__DRIVER_NAME " Missing settings\n"));
493 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
494 return SP_RETURN_BAD_CONFIG;
495 }
496 #endif
498 ConfigInfo->ScatterGather = TRUE;
499 ConfigInfo->NumberOfPhysicalBreaks = VSCSIIF_SG_TABLESIZE - 1;
500 ConfigInfo->MaximumTransferLength = VSCSIIF_SG_TABLESIZE * PAGE_SIZE;
501 ConfigInfo->CachesData = FALSE;
502 ConfigInfo->NumberOfBuses = 4; //SCSI_MAXIMUM_BUSES; //8
503 ConfigInfo->MaximumNumberOfTargets = 16;
504 ConfigInfo->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS; // 8
505 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
506 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
507 {
508 ConfigInfo->Master = TRUE;
509 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
510 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
511 }
512 else
513 {
514 ConfigInfo->Master = FALSE;
515 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
516 }
517 ConfigInfo->InitiatorBusId[0] = 7;
518 ConfigInfo->InitiatorBusId[1] = 7;
519 ConfigInfo->InitiatorBusId[2] = 7;
520 ConfigInfo->InitiatorBusId[3] = 7;
521 xsdd->shadow_free = 0;
522 memset(xsdd->shadows, 0, sizeof(vscsiif_shadow_t) * SHADOW_ENTRIES);
523 for (i = 0; i < SHADOW_ENTRIES; i++)
524 {
525 xsdd->shadows[i].req.rqid = (USHORT)i;
526 put_shadow_on_freelist(xsdd, &xsdd->shadows[i]);
527 }
529 if (!dump_mode)
530 {
531 InitializeListHead(&xsdd->dev_list_head);
532 /* should do something if we haven't enumerated in a certain time */
533 RtlStringCbCopyA(path, ARRAY_SIZE(path), xsdd->vectors.backend_path);
534 RtlStringCbCatA(path, ARRAY_SIZE(path), "/vscsi-devs");
535 xsdd->vectors.XenBus_AddWatch(xsdd->vectors.context, XBT_NIL, path,
536 XenScsi_DevWatch, xsdd);
537 }
538 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
540 return SP_RETURN_FOUND;
541 }
543 static BOOLEAN
544 XenScsi_HwScsiInitialize(PVOID DeviceExtension)
545 {
546 // PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
547 UNREFERENCED_PARAMETER(DeviceExtension);
549 FUNCTION_ENTER();
551 FUNCTION_EXIT();
553 return TRUE;
554 }
556 static VOID
557 XenScsi_PutSrbOnRing(PXENSCSI_DEVICE_DATA xsdd, PSCSI_REQUEST_BLOCK Srb)
558 {
559 PHYSICAL_ADDRESS physical_address;
560 ULONG remaining;
561 PUCHAR ptr;
562 //ULONG i;
563 PFN_NUMBER pfn;
564 vscsiif_shadow_t *shadow;
565 int notify;
567 //FUNCTION_ENTER();
569 shadow = get_shadow_from_freelist(xsdd);
570 ASSERT(shadow);
571 shadow->Srb = Srb;
572 shadow->req.act = VSCSIIF_ACT_SCSI_CDB;
573 memset(shadow->req.cmnd, 0, VSCSIIF_MAX_COMMAND_SIZE);
574 memcpy(shadow->req.cmnd, Srb->Cdb, min(Srb->CdbLength, VSCSIIF_MAX_COMMAND_SIZE));
575 shadow->req.cmd_len = min(Srb->CdbLength, VSCSIIF_MAX_COMMAND_SIZE);
576 shadow->req.timeout_per_command = (USHORT)Srb->TimeOutValue;
577 shadow->req.channel = (USHORT)Srb->PathId;
578 shadow->req.id = (USHORT)Srb->TargetId;
579 shadow->req.lun = (USHORT)Srb->Lun;
580 if (Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_IN) && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT))
581 {
582 //KdPrint((__DRIVER_NAME " Cmd = %02x, Length = %d, DMA_BIDIRECTIONAL\n", Srb->Cdb[0], Srb->DataTransferLength));
583 shadow->req.sc_data_direction = DMA_BIDIRECTIONAL;
584 }
585 else if (Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_IN))
586 {
587 //KdPrint((__DRIVER_NAME " Cmd = %02x, Length = %d, DMA_FROM_DEVICE\n", Srb->Cdb[0], Srb->DataTransferLength));
588 shadow->req.sc_data_direction = DMA_FROM_DEVICE;
589 }
590 else if (Srb->DataTransferLength && (Srb->SrbFlags & SRB_FLAGS_DATA_OUT))
591 {
592 //KdPrint((__DRIVER_NAME " Cmd = %02x, Length = %d, DMA_TO_DEVICE\n", Srb->Cdb[0], Srb->DataTransferLength));
593 shadow->req.sc_data_direction = DMA_TO_DEVICE;
594 }
595 else
596 {
597 //KdPrint((__DRIVER_NAME " Cmd = %02x, Length = %d, DMA_NONE\n", Srb->Cdb[0], Srb->DataTransferLength));
598 shadow->req.sc_data_direction = DMA_NONE;
599 }
601 remaining = Srb->DataTransferLength;
602 shadow->req.seg[0].offset = 0;
603 shadow->req.seg[0].length = 0;
604 shadow->req.nr_segments = 0;
606 for (ptr = Srb->DataBuffer, shadow->req.nr_segments = 0; remaining != 0; shadow->req.nr_segments++)
607 {
608 if (shadow->req.nr_segments >= VSCSIIF_SG_TABLESIZE)
609 {
610 KdPrint((__DRIVER_NAME " too many segments (length = %d, remaining = %d)\n", Srb->DataTransferLength, remaining));
611 }
612 physical_address = MmGetPhysicalAddress(ptr);
613 pfn = (ULONG)(physical_address.QuadPart >> PAGE_SHIFT);
614 shadow->req.seg[shadow->req.nr_segments].gref = get_grant_from_freelist(xsdd);
615 if (shadow->req.seg[shadow->req.nr_segments].gref == 0x0FFFFFFF)
616 {
617 return; /* better than crashing... */
618 }
619 xsdd->vectors.GntTbl_GrantAccess(xsdd->vectors.context, 0, (ULONG)pfn, 0, shadow->req.seg[shadow->req.nr_segments].gref);
620 shadow->req.seg[shadow->req.nr_segments].offset = (USHORT)(physical_address.LowPart & (PAGE_SIZE - 1));
621 shadow->req.seg[shadow->req.nr_segments].length = (USHORT)min(PAGE_SIZE - (ULONG)shadow->req.seg[shadow->req.nr_segments].offset, remaining);
622 remaining -= (ULONG)shadow->req.seg[shadow->req.nr_segments].length;
623 ptr += shadow->req.seg[shadow->req.nr_segments].length;
624 //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));
625 }
626 *RING_GET_REQUEST(&xsdd->ring, xsdd->ring.req_prod_pvt) = shadow->req;
627 xsdd->ring.req_prod_pvt++;
628 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xsdd->ring, notify);
629 if (notify)
630 {
631 //KdPrint((__DRIVER_NAME " Notifying %d\n", xsdd->event_channel));
632 xsdd->vectors.EvtChn_Notify(xsdd->vectors.context, xsdd->event_channel);
633 }
635 //FUNCTION_EXIT();
636 }
638 static BOOLEAN
639 XenScsi_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
640 {
641 PXENSCSI_DEVICE_DATA xsdd = DeviceExtension;
642 scsi_dev_t *dev;
644 //FUNCTION_ENTER();
646 if (xsdd->pause_ack != xsdd->pause_req)
647 {
648 xsdd->pause_ack = xsdd->pause_req;
649 }
651 if (xsdd->pause_ack)
652 {
653 FUNCTION_ENTER();
654 KdPrint((__DRIVER_NAME " Busy\n"));
655 Srb->SrbStatus = SRB_STATUS_BUSY;
656 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
657 FUNCTION_EXIT();
658 return TRUE;
659 }
661 for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink;
662 dev != (scsi_dev_t *)&xsdd->dev_list_head;
663 dev = (scsi_dev_t * )dev->entry.Flink)
664 {
665 if (dev->channel == Srb->PathId && dev->id == Srb->TargetId && dev->lun == Srb->Lun)
666 break;
667 }
668 if (dev == (scsi_dev_t *)&xsdd->dev_list_head)
669 {
670 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
671 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
672 //KdPrint((__DRIVER_NAME " Out of bounds\n"));
673 ScsiPortNotification(NextRequest, DeviceExtension);
674 //FUNCTION_EXIT();
675 return TRUE;
676 }
678 switch (Srb->Function)
679 {
680 case SRB_FUNCTION_EXECUTE_SCSI:
681 switch (Srb->Cdb[0])
682 {
683 case 0x03: { /* REQUEST_SENSE*/
684 /* but what about when we allow multiple requests per lu? */
685 PXENSCSI_LU_DATA lud = ScsiPortGetLogicalUnit(DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
686 if (lud != NULL && lud->sense_len)
687 {
688 KdPrint((__DRIVER_NAME " Emulating REQUEST_SENSE (lu data = %p)\n", lud));
689 memcpy(Srb->DataBuffer, lud->sense_buffer, min(lud->sense_len, Srb->DataTransferLength));
690 if (lud->sense_len < Srb->DataTransferLength)
691 {
692 Srb->DataTransferLength = lud->sense_len;
693 Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
694 }
695 else
696 {
697 Srb->SrbStatus = SRB_STATUS_SUCCESS;
698 }
699 //for (i = 0; i < Srb->DataTransferLength; i++)
700 // KdPrint((__DRIVER_NAME " sense %02x: %02x\n", i, (ULONG)((PUCHAR)Srb->DataBuffer)[i]));
701 lud->sense_len = 0;
702 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
703 ScsiPortNotification(NextRequest, DeviceExtension);
704 break;
705 }
706 else
707 {
708 KdPrint((__DRIVER_NAME " Issuing REQUEST_SENSE (lud = %p)\n", lud));
709 }
710 // fall through
711 }
712 default:
713 XenScsi_PutSrbOnRing(xsdd, Srb);
714 Srb->SrbStatus = SRB_STATUS_PENDING;
715 break;
716 }
717 break;
718 case SRB_FUNCTION_IO_CONTROL:
719 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
720 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
721 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
722 ScsiPortNotification(NextRequest, DeviceExtension);
723 break;
724 case SRB_FUNCTION_FLUSH:
725 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
726 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
727 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
728 ScsiPortNotification(NextRequest, DeviceExtension);
729 break;
730 default:
731 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
732 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
733 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
734 ScsiPortNotification(NextRequest, DeviceExtension);
735 break;
736 }
738 //FUNCTION_EXIT();
739 return TRUE;
740 }
742 static BOOLEAN
743 XenScsi_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
744 {
745 UNREFERENCED_PARAMETER(DeviceExtension);
746 UNREFERENCED_PARAMETER(PathId);
749 FUNCTION_ENTER();
750 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
751 ScsiPortNotification(NextRequest, DeviceExtension);
752 FUNCTION_EXIT();
754 return TRUE;
755 }
757 static SCSI_ADAPTER_CONTROL_STATUS
758 XenScsi_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
759 {
760 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
761 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
762 //KIRQL OldIrql;
764 UNREFERENCED_PARAMETER(DeviceExtension);
766 FUNCTION_ENTER();
767 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
769 switch (ControlType)
770 {
771 case ScsiQuerySupportedControlTypes:
772 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
773 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
774 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
775 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
776 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
777 break;
778 case ScsiStopAdapter:
779 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
780 break;
781 case ScsiRestartAdapter:
782 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
783 break;
784 case ScsiSetBootConfig:
785 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
786 break;
787 case ScsiSetRunningConfig:
788 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
789 break;
790 default:
791 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
792 break;
793 }
795 FUNCTION_EXIT();
797 return Status;
798 }
800 NTSTATUS
801 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
802 {
803 ULONG Status;
804 HW_INITIALIZATION_DATA HwInitializationData;
805 PVOID driver_extension;
806 PUCHAR ptr;
808 FUNCTION_ENTER();
810 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
812 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
813 ptr = driver_extension;
814 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
815 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
816 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
817 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, UlongToPtr(144), NULL);
818 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
819 /* RegistryPath == NULL when we are invoked as a crash dump driver */
820 if (!RegistryPath)
821 {
822 dump_mode = TRUE;
823 }
825 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
827 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
828 HwInitializationData.AdapterInterfaceType = PNPBus;
829 HwInitializationData.DeviceExtensionSize = sizeof(XENSCSI_DEVICE_DATA);
830 HwInitializationData.SpecificLuExtensionSize = sizeof(XENSCSI_LU_DATA);
831 HwInitializationData.SrbExtensionSize = 0;
832 HwInitializationData.NumberOfAccessRanges = 1;
833 HwInitializationData.MapBuffers = TRUE;
834 HwInitializationData.NeedPhysicalAddresses = FALSE;
835 HwInitializationData.TaggedQueuing = TRUE;
836 HwInitializationData.AutoRequestSense = TRUE;
837 HwInitializationData.MultipleRequestPerLu = TRUE;
839 HwInitializationData.HwInitialize = XenScsi_HwScsiInitialize;
840 HwInitializationData.HwStartIo = XenScsi_HwScsiStartIo;
841 HwInitializationData.HwInterrupt = XenScsi_HwScsiInterrupt;
842 HwInitializationData.HwFindAdapter = XenScsi_HwScsiFindAdapter;
843 HwInitializationData.HwResetBus = XenScsi_HwScsiResetBus;
844 HwInitializationData.HwAdapterControl = XenScsi_HwScsiAdapterControl;
846 Status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
848 if(!NT_SUCCESS(Status))
849 {
850 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", Status));
851 }
853 FUNCTION_EXIT();
855 return Status;
856 }