win-pvdrivers

view xenscsi/xenscsi.c @ 685:c13ccf5a629b

Fixed a bug in the dma routines which was causing memory corruption. In some cases when Windows gave an MDL that was longer than the buffer to be dma'd, the end of the buffer would be overwritten. The only time I am aware of this occuring is on one particular map in Call Of Duty 4.

Split out the dma routines from xenpci_pdo.c into xenpci_dma.c
author James Harper <james.harper@bendigoit.com.au>
date Wed Oct 14 14:46:39 2009 +1100 (2009-10-14)
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 }