win-pvdrivers

view xenscsi/xenscsi.c @ 630:51012d703b75

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