win-pvdrivers

view xenscsi/xenscsi.c @ 537:2a74ac2f43bb

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