win-pvdrivers

view xenvbd/scsiport.c @ 283:3c65d6c6453f

Fixed a sense problem with xenscsi. scsi passthrough now working properly.
author James Harper <james.harper@bendigoit.com.au>
date Tue May 27 22:46:06 2008 +1000 (2008-05-27)
parents 3ee7c3e5036d
children 4954c15a4921
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 "xenvbd.h"
21 #include <io/blkif.h>
22 #include <scsi.h>
23 #include <ntddscsi.h>
24 #include <ntdddisk.h>
25 #include <stdlib.h>
26 #include <xen_public.h>
27 #include <io/xenbus.h>
28 #include <io/protocols.h>
30 #pragma warning(disable: 4127)
32 static blkif_shadow_t *
33 get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
34 {
35 if (xvdd->shadow_free == 0)
36 {
37 KdPrint((__DRIVER_NAME " No more shadow entries\n"));
38 return NULL;
39 }
40 xvdd->shadow_free--;
41 return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
42 }
44 static VOID
45 put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
46 {
47 xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
48 shadow->srb = NULL;
49 xvdd->shadow_free++;
50 }
52 static grant_ref_t
53 get_grant_from_freelist(PXENVBD_DEVICE_DATA xvdd)
54 {
55 if (xvdd->grant_free == 0)
56 {
57 KdPrint((__DRIVER_NAME " No more grant refs\n"));
58 return (grant_ref_t)0x0FFFFFFF;
59 }
60 xvdd->grant_free--;
61 return xvdd->grant_free_list[xvdd->grant_free];
62 }
64 static VOID
65 put_grant_on_freelist(PXENVBD_DEVICE_DATA xvdd, grant_ref_t grant)
66 {
67 xvdd->grant_free_list[xvdd->grant_free] = grant;
68 xvdd->grant_free++;
69 }
71 static blkif_response_t *
72 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
73 {
74 blkif_other_response_t *rep;
75 if (!xvdd->use_other)
76 return RING_GET_RESPONSE(&xvdd->ring, i);
77 rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
78 xvdd->tmp_rep.id = rep->id;
79 xvdd->tmp_rep.operation = rep->operation;
80 xvdd->tmp_rep.status = rep->status;
81 return &xvdd->tmp_rep;
82 }
84 static ULONG
85 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
86 {
87 ULONG i;
88 // PACCESS_RANGE AccessRange;
89 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
90 // ULONG status;
91 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
92 PACCESS_RANGE access_range;
93 PUCHAR ptr;
94 USHORT type;
95 PCHAR setting, value;
96 blkif_sring_t *sring;
98 UNREFERENCED_PARAMETER(HwContext);
99 UNREFERENCED_PARAMETER(BusInformation);
100 UNREFERENCED_PARAMETER(ArgumentString);
102 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
103 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
105 *Again = FALSE;
107 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
108 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
110 if (ConfigInfo->NumberOfAccessRanges != 1)
111 {
112 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
113 return SP_RETURN_BAD_CONFIG;
114 }
116 access_range = &((*(ConfigInfo->AccessRanges))[0]);
118 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
119 access_range->RangeStart.LowPart, access_range->RangeLength));
121 ptr = ScsiPortGetDeviceBase(
122 DeviceExtension,
123 ConfigInfo->AdapterInterfaceType,
124 ConfigInfo->SystemIoBusNumber,
125 access_range->RangeStart,
126 access_range->RangeLength,
127 !access_range->RangeInMemory);
128 //ptr = MmMapIoSpace(access_range->RangeStart, access_range->RangeLength, MmCached);
129 if (ptr == NULL)
130 {
131 KdPrint((__DRIVER_NAME " Unable to map range\n"));
132 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
133 return SP_RETURN_BAD_CONFIG;
134 }
136 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
137 sring = NULL;
138 xvdd->event_channel = 0;
139 while((type = GET_XEN_INIT_RSP(&ptr, &setting, &value)) != XEN_INIT_TYPE_END)
140 {
141 switch(type)
142 {
143 case XEN_INIT_TYPE_RING: /* frontend ring */
144 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
145 if (strcmp(setting, "ring-ref") == 0)
146 {
148 sring = (blkif_sring_t *)value;
149 FRONT_RING_INIT(&xvdd->ring, sring, PAGE_SIZE);
150 }
151 break;
152 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
153 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
154 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value)));
155 if (strcmp(setting, "event-channel") == 0)
156 {
157 xvdd->event_channel = PtrToUlong(value);
158 }
159 break;
160 case XEN_INIT_TYPE_READ_STRING_BACK:
161 case XEN_INIT_TYPE_READ_STRING_FRONT:
162 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
163 if (strcmp(setting, "sectors") == 0)
164 xvdd->total_sectors = atoi(value);
165 else if (strcmp(setting, "sector-size") == 0)
166 xvdd->bytes_per_sector = atoi(value);
167 else if (strcmp(setting, "device-type") == 0)
168 {
169 if (strcmp(value, "disk") == 0)
170 {
171 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
172 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
173 }
174 else if (strcmp(value, "cdrom") == 0)
175 {
176 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
177 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
178 }
179 else
180 {
181 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
182 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
183 }
184 }
185 break;
186 case XEN_INIT_TYPE_VECTORS:
187 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
188 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
189 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
190 {
191 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
192 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
193 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
194 return SP_RETURN_BAD_CONFIG;
195 }
196 else
197 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
198 break;
199 case XEN_INIT_TYPE_GRANT_ENTRIES:
200 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - %d\n", PtrToUlong(setting)));
201 if (PtrToUlong(setting) != GRANT_ENTRIES)
202 {
203 KdPrint((__DRIVER_NAME " grant entries mismatch\n"));
204 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
205 return SP_RETURN_BAD_CONFIG;
206 }
207 else
208 {
209 memcpy(&xvdd->grant_free_list, value, sizeof(ULONG) * PtrToUlong(setting));
210 xvdd->grant_free = GRANT_ENTRIES;
211 }
212 break;
213 default:
214 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
215 break;
216 }
217 }
218 if (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
219 || sring == NULL
220 || xvdd->event_channel == 0)
221 {
222 KdPrint((__DRIVER_NAME " Missing settings\n"));
223 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
224 return SP_RETURN_BAD_CONFIG;
225 }
226 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
227 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
228 ConfigInfo->ScatterGather = TRUE;
229 ConfigInfo->AlignmentMask = 0;
230 ConfigInfo->NumberOfBuses = 1;
231 ConfigInfo->InitiatorBusId[0] = 1;
232 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
233 ConfigInfo->MaximumNumberOfTargets = 2;
234 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
235 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
236 {
237 ConfigInfo->Master = TRUE;
238 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
239 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
240 }
241 else
242 {
243 ConfigInfo->Master = FALSE;
244 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
245 }
247 xvdd->ring_detect_state = 0;
249 xvdd->shadow_free = 0;
250 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
251 for (i = 0; i < SHADOW_ENTRIES; i++)
252 {
253 xvdd->shadows[i].req.id = i;
254 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
255 }
257 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
259 return SP_RETURN_FOUND;
260 }
262 static BOOLEAN
263 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
264 {
265 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
266 blkif_request_t *req;
267 int i;
268 int notify;
270 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
271 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
273 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
274 KdPrint((__DRIVER_NAME " A\n"));
275 req->operation = 0xff;
276 req->nr_segments = 0;
277 for (i = 0; i < req->nr_segments; i++)
278 {
279 req->seg[i].gref = 0xffffffff;
280 req->seg[i].first_sect = 0xff;
281 req->seg[i].last_sect = 0xff;
282 }
283 xvdd->ring.req_prod_pvt++;
285 KdPrint((__DRIVER_NAME " B\n"));
287 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
288 KdPrint((__DRIVER_NAME " C\n"));
289 req->operation = 0xff;
290 req->nr_segments = 0;
291 for (i = 0; i < req->nr_segments; i++)
292 {
293 req->seg[i].gref = 0xffffffff;
294 req->seg[i].first_sect = 0xff;
295 req->seg[i].last_sect = 0xff;
296 }
297 xvdd->ring.req_prod_pvt++;
299 KdPrint((__DRIVER_NAME " D\n"));
301 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
302 KdPrint((__DRIVER_NAME " E\n"));
303 if (notify)
304 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
306 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
308 return TRUE;
309 }
311 static VOID
312 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
313 {
314 blkif_other_request_t *other_req;
316 if (!xvdd->use_other)
317 {
318 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
319 }
320 else
321 {
322 other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
323 other_req->operation = req->operation;
324 other_req->nr_segments = req->nr_segments;
325 other_req->handle = req->handle;
326 other_req->id = req->id;
327 other_req->sector_number = req->sector_number;
328 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
329 }
330 xvdd->ring.req_prod_pvt++;
331 }
333 static VOID
334 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, ULONG srb_offset)
335 {
336 int block_count;
337 blkif_shadow_t *shadow;
338 PHYSICAL_ADDRESS physical_address;
339 ULONG pfn;
340 ULONG remaining, offset, length;
341 PUCHAR ptr;
342 int notify;
344 // can use SRB_STATUS_BUSY to push the SRB back to windows...
346 // KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
348 shadow = get_shadow_from_freelist(xvdd);
349 shadow->req.sector_number = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
350 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
351 shadow->req.handle = 0;
352 shadow->req.operation = (srb->Cdb[0] == SCSIOP_READ)?BLKIF_OP_READ:BLKIF_OP_WRITE;
353 shadow->req.nr_segments = 0;
354 shadow->offset = srb_offset;
355 shadow->length = block_count * xvdd->bytes_per_sector;
356 shadow->srb = srb;
358 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
359 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
360 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
362 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
363 {
364 shadow->req.sector_number += srb_offset / xvdd->bytes_per_sector;
365 shadow->length = min(shadow->length - srb_offset, UNALIGNED_DOUBLE_BUFFER_SIZE);
366 //KdPrint((__DRIVER_NAME " (Put) id = %d, DataBuffer = %p, SrbExtension = %p, total length = %d, offset = %d, length = %d, sector = %d\n", (ULONG)shadow->req.id, srb->DataBuffer, srb->SrbExtension, block_count * xvdd->bytes_per_sector, shadow->offset, shadow->length, shadow->req.sector_number));
367 if (srb->Cdb[0] == SCSIOP_WRITE)
368 {
369 memcpy(srb->SrbExtension, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length);
370 //KdPrint((__DRIVER_NAME " (WR) memcpy(%p, %p, %d)\n", srb->SrbExtension, ((PUCHAR)srb->DataBuffer) + srb_offset, shadow->length));
371 }
372 else
373 {
374 RtlZeroMemory(srb->SrbExtension, shadow->length);
375 }
376 ptr = srb->SrbExtension;
377 }
378 else
379 {
380 ptr = srb->DataBuffer;
381 }
383 remaining = shadow->length;
384 while (remaining > 0)
385 {
386 physical_address = MmGetPhysicalAddress(ptr);
387 //KdPrint((__DRIVER_NAME " ptr = %p, physical = %08x:%08x\n", ptr, physical_address.HighPart, physical_address.LowPart));
388 pfn = (ULONG)(physical_address.QuadPart >> PAGE_SHIFT);
389 shadow->req.seg[shadow->req.nr_segments].gref = xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0, pfn, 0, get_grant_from_freelist(xvdd));
390 offset = (ULONG)(physical_address.QuadPart & (PAGE_SIZE - 1));
391 ASSERT((offset & 511) == 0);
392 length = min(PAGE_SIZE - offset, remaining);
393 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
394 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
395 //KdPrint((__DRIVER_NAME " length = %d, remaining = %d, pfn = %08x, offset = %d, first = %d, last = %d\n",
396 // length, remaining, pfn, offset, shadow->req.seg[shadow->req.nr_segments].first_sect, shadow->req.seg[shadow->req.nr_segments].last_sect));
397 remaining -= length;
398 ptr += length;
399 shadow->req.nr_segments++;
400 }
402 XenVbd_PutRequest(xvdd, &shadow->req);
404 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
405 if (notify)
406 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
408 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
409 }
411 static ULONG
412 XenVbd_FillModePage(PXENVBD_DEVICE_DATA DeviceData, UCHAR PageCode, PUCHAR DataBuffer, ULONG BufferLength, PULONG Offset)
413 {
414 //PMODE_RIGID_GEOMETRY_PAGE ModeRigidGeometry;
416 UNREFERENCED_PARAMETER(DeviceData);
417 UNREFERENCED_PARAMETER(DataBuffer);
418 UNREFERENCED_PARAMETER(BufferLength);
419 UNREFERENCED_PARAMETER(Offset);
421 switch (PageCode)
422 {
423 /*
424 case MODE_PAGE_RIGID_GEOMETRY:
425 if (DeviceData->ScsiData->DeviceType == XENVBD_DEVICETYPE_CDROM)
426 {
427 KdPrint((__DRIVER_NAME " MODE_PAGE_RIGID_GEOMETRY\n"));
428 if (*Offset + sizeof(MODE_RIGID_GEOMETRY_PAGE) > BufferLength)
429 return 1;
430 ModeRigidGeometry = (PMODE_RIGID_GEOMETRY_PAGE)(DataBuffer + *Offset);
431 memset(ModeRigidGeometry, 0, sizeof(MODE_RIGID_GEOMETRY_PAGE));
432 ModeRigidGeometry->PageCode = PageCode;
433 ModeRigidGeometry->PageSavable = 0;
434 ModeRigidGeometry->PageLength = sizeof(MODE_RIGID_GEOMETRY_PAGE);
435 ModeRigidGeometry->NumberOfCylinders[0] = (DeviceData->Geometry.Cylinders.LowPart >> 16) & 0xFF;
436 ModeRigidGeometry->NumberOfCylinders[1] = (DeviceData->Geometry.Cylinders.LowPart >> 8) & 0xFF;
437 ModeRigidGeometry->NumberOfCylinders[2] = (DeviceData->Geometry.Cylinders.LowPart >> 0) & 0xFF;
438 ModeRigidGeometry->NumberOfHeads = DeviceData->Geometry.TracksPerCylinder;
439 //ModeRigidGeometry->LandZoneCyclinder = 0;
440 ModeRigidGeometry->RoataionRate[0] = 0x05;
441 ModeRigidGeometry->RoataionRate[0] = 0x39;
442 *Offset += sizeof(MODE_RIGID_GEOMETRY_PAGE);
443 }
444 break;
445 */
446 case MODE_PAGE_FAULT_REPORTING:
447 break;
448 default:
449 break;
450 }
451 return 0;
452 }
454 static BOOLEAN
455 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
456 {
457 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
458 PSCSI_REQUEST_BLOCK srb;
459 RING_IDX i, rp;
460 int j;
461 blkif_response_t *rep;
462 int block_count;
463 int more_to_do = TRUE;
464 blkif_shadow_t *shadow;
465 ULONG offset;
467 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
469 while (more_to_do)
470 {
471 rp = xvdd->ring.sring->rsp_prod;
472 KeMemoryBarrier();
473 for (i = xvdd->ring.rsp_cons; i != rp; i++)
474 {
475 rep = XenVbd_GetResponse(xvdd, i);
476 /*
477 * This code is to automatically detect if the backend is using the same
478 * bit width or a different bit width to us. Later versions of Xen do this
479 * via a xenstore value, but not all. That 0x0fffffff (notice
480 * that the msb is not actually set, so we don't have any problems with
481 * sign extending) is to signify the last entry on the right, which is
482 * different under 32 and 64 bits, and that is why we set it up there.
484 * To do the detection, we put two initial entries on the ring, with an op
485 * of 0xff (which is invalid). The first entry is mostly okay, but the
486 * second will be grossly misaligned if the backend bit width is different,
487 * and we detect this and switch frontend structures.
488 */
489 switch (xvdd->ring_detect_state)
490 {
491 case 0:
492 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
493 xvdd->ring_detect_state = 1;
494 break;
495 case 1:
496 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
497 if (rep->operation != 0xff)
498 {
499 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
500 xvdd->use_other = TRUE;
501 }
502 xvdd->ring_detect_state = 2;
503 ScsiPortNotification(NextRequest, xvdd);
504 break;
505 case 2:
506 shadow = &xvdd->shadows[rep->id];
507 srb = shadow->srb;
508 ASSERT(srb != NULL);
509 block_count = (srb->Cdb[7] << 8) | srb->Cdb[8];
511 if (rep->status == BLKIF_RSP_OKAY)
512 srb->SrbStatus = SRB_STATUS_SUCCESS;
513 else
514 {
515 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
516 if (srb->Cdb[0] == SCSIOP_READ)
517 KdPrint((__DRIVER_NAME " Operation = Read\n"));
518 else
519 KdPrint((__DRIVER_NAME " Operation = Write\n"));
520 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", shadow->req.sector_number, block_count));
521 srb->SrbStatus = SRB_STATUS_ERROR;
522 }
523 for (j = 0; j < shadow->req.nr_segments; j++)
524 {
525 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context, shadow->req.seg[j].gref, TRUE);
526 put_grant_on_freelist(xvdd, shadow->req.seg[j].gref);
527 }
529 if (PtrToUlong(srb->DataBuffer) & 511) /* use SrbExtension intead of DataBuffer if DataBuffer is not aligned to sector size */
530 {
531 if (srb->Cdb[0] == SCSIOP_READ)
532 {
533 memcpy(((PUCHAR)srb->DataBuffer) + shadow->offset, srb->SrbExtension, shadow->length);
534 //KdPrint((__DRIVER_NAME " (RD) memcpy(%p, %p, %d)\n", ((PUCHAR)srb->DataBuffer) + shadow->offset, srb->SrbExtension, shadow->length));
535 }
536 //KdPrint((__DRIVER_NAME " (Get) id = %d, DataBuffer = %p, SrbExtension = %p, total length = %d, offset = %d, length = %d\n", (ULONG)shadow->req.id, srb->DataBuffer, srb->SrbExtension, block_count * xvdd->bytes_per_sector, shadow->offset, shadow->length));
537 offset = shadow->offset + shadow->length;
538 put_shadow_on_freelist(xvdd, shadow);
539 if (offset == block_count * xvdd->bytes_per_sector)
540 {
541 ScsiPortNotification(RequestComplete, xvdd, srb);
542 ScsiPortNotification(NextRequest, xvdd);
543 }
544 else
545 {
546 XenVbd_PutSrbOnRing(xvdd, srb, offset);
547 }
548 }
549 else
550 {
551 put_shadow_on_freelist(xvdd, shadow);
552 ScsiPortNotification(RequestComplete, xvdd, srb);
553 ScsiPortNotification(NextRequest, xvdd);
554 }
555 }
556 }
558 xvdd->ring.rsp_cons = i;
559 if (i != xvdd->ring.req_prod_pvt)
560 {
561 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
562 }
563 else
564 {
565 xvdd->ring.sring->rsp_event = i + 1;
566 more_to_do = FALSE;
567 }
568 }
570 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
572 return FALSE; /* we just don't know... */
573 }
576 static BOOLEAN
577 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
578 {
579 PUCHAR DataBuffer;
580 PCDB cdb;
581 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
582 unsigned int i;
584 //KdPrint((__DRIVER_NAME " --> HwScsiStartIo PathId = %d, TargetId = %d, Lun = %d\n", Srb->PathId, Srb->TargetId, Srb->Lun));
586 // If we haven't enumerated all the devices yet then just defer the request
587 // A timer will issue a NextRequest to get things started again...
588 if (xvdd->ring_detect_state < 2)
589 {
590 Srb->SrbStatus = SRB_STATUS_BUSY;
591 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
592 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
593 return TRUE;
594 }
596 if (Srb->PathId != 0 || Srb->TargetId != 0)
597 {
598 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
599 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
600 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
601 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
602 return TRUE;
603 }
605 switch (Srb->Function)
606 {
607 case SRB_FUNCTION_EXECUTE_SCSI:
608 cdb = (PCDB)Srb->Cdb;
609 // KdPrint((__DRIVER_NAME " SRB_FUNCTION_EXECUTE_SCSI\n"));
611 switch(cdb->CDB6GENERIC.OperationCode)
612 {
613 case SCSIOP_TEST_UNIT_READY:
614 // KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
615 Srb->SrbStatus = SRB_STATUS_SUCCESS;
616 Srb->ScsiStatus = 0;
617 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
618 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
619 break;
620 case SCSIOP_INQUIRY:
621 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
622 KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
623 KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
624 KdPrint((__DRIVER_NAME " (Srb->Databuffer = %08x)\n", Srb->DataBuffer));
625 DataBuffer = Srb->DataBuffer;
626 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
627 Srb->SrbStatus = SRB_STATUS_SUCCESS;
628 switch (xvdd->device_type)
629 {
630 case XENVBD_DEVICETYPE_DISK:
631 if ((Srb->Cdb[1] & 1) == 0)
632 {
633 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
634 DataBuffer[1] = 0x00; // not removable
635 DataBuffer[3] = 32;
636 memcpy(DataBuffer + 8, "XEN ", 8); // vendor id
637 memcpy(DataBuffer + 16, "PV VBD ", 16); // product id
638 memcpy(DataBuffer + 32, "0000", 4); // product revision level
639 }
640 else
641 {
642 switch (Srb->Cdb[2])
643 {
644 case 0x00:
645 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
646 DataBuffer[1] = 0x00;
647 DataBuffer[2] = 0x00;
648 DataBuffer[3] = 2;
649 DataBuffer[4] = 0x00;
650 DataBuffer[5] = 0x80;
651 break;
652 case 0x80:
653 DataBuffer[0] = DIRECT_ACCESS_DEVICE;
654 DataBuffer[1] = 0x80;
655 DataBuffer[2] = 0x00;
656 DataBuffer[3] = 8;
657 DataBuffer[4] = 0x31;
658 DataBuffer[5] = 0x32;
659 DataBuffer[6] = 0x33;
660 DataBuffer[7] = 0x34;
661 DataBuffer[8] = 0x35;
662 DataBuffer[9] = 0x36;
663 DataBuffer[10] = 0x37;
664 DataBuffer[11] = 0x38;
665 break;
666 default:
667 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
668 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
669 break;
670 }
671 }
672 break;
673 case XENVBD_DEVICETYPE_CDROM:
674 if ((Srb->Cdb[1] & 1) == 0)
675 {
676 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
677 DataBuffer[1] = 0x01; // removable
678 DataBuffer[3] = 32;
679 memcpy(DataBuffer + 8, "XEN ", 8); // vendor id
680 memcpy(DataBuffer + 16, "PV VBD ", 16); // product id
681 memcpy(DataBuffer + 32, "0000", 4); // product revision level
682 }
683 else
684 {
685 switch (Srb->Cdb[2])
686 {
687 case 0x00:
688 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
689 DataBuffer[1] = 0x00;
690 DataBuffer[2] = 0x00;
691 DataBuffer[3] = 2;
692 DataBuffer[4] = 0x00;
693 DataBuffer[5] = 0x80;
694 break;
695 case 0x80:
696 DataBuffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
697 DataBuffer[1] = 0x80;
698 DataBuffer[2] = 0x00;
699 DataBuffer[3] = 8;
700 DataBuffer[4] = 0x31;
701 DataBuffer[5] = 0x32;
702 DataBuffer[6] = 0x33;
703 DataBuffer[7] = 0x34;
704 DataBuffer[8] = 0x35;
705 DataBuffer[9] = 0x36;
706 DataBuffer[10] = 0x37;
707 DataBuffer[11] = 0x38;
708 break;
709 default:
710 KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
711 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
712 break;
713 }
714 }
715 break;
716 default:
717 KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
718 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
719 break;
720 }
721 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
722 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
723 break;
724 case SCSIOP_READ_CAPACITY:
725 //KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
726 DataBuffer = Srb->DataBuffer;
727 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
728 DataBuffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
729 DataBuffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
730 DataBuffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
731 DataBuffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
732 DataBuffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
733 DataBuffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
734 DataBuffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
735 DataBuffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
736 Srb->ScsiStatus = 0;
737 Srb->SrbStatus = SRB_STATUS_SUCCESS;
738 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
739 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
740 break;
741 case SCSIOP_MODE_SENSE:
742 //KdPrint((__DRIVER_NAME " Command = MODE_SENSE (DBD = %d, PC = %d, Page Code = %02x)\n", Srb->Cdb[1] & 0x10, Srb->Cdb[2] & 0xC0, Srb->Cdb[2] & 0x3F));
743 //KdPrint((__DRIVER_NAME " Length = %d\n", Srb->DataTransferLength));
745 Srb->ScsiStatus = 0;
746 Srb->SrbStatus = SRB_STATUS_SUCCESS;
747 Srb->DataTransferLength = 0;
748 DataBuffer = Srb->DataBuffer;
749 RtlZeroMemory(DataBuffer, Srb->DataTransferLength);
750 switch(cdb->MODE_SENSE.PageCode)
751 {
752 case MODE_SENSE_RETURN_ALL:
753 //Ptr = (UCHAR *)Srb->DataBuffer;
754 for (i = 0; i < MODE_SENSE_RETURN_ALL; i++)
755 {
756 if (XenVbd_FillModePage(xvdd, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength))
757 {
758 break;
759 }
760 }
761 break;
762 default:
763 XenVbd_FillModePage(xvdd, cdb->MODE_SENSE.PageCode, DataBuffer, cdb->MODE_SENSE.AllocationLength, &Srb->DataTransferLength);
764 break;
765 }
766 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
767 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
768 break;
769 case SCSIOP_WRITE:
770 case SCSIOP_READ:
771 //KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
772 XenVbd_PutSrbOnRing(xvdd, Srb, 0);
773 if (!xvdd->shadow_free)
774 ScsiPortNotification(NextRequest, DeviceExtension);
775 break;
776 case SCSIOP_VERIFY:
777 // Should we do more here?
778 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
779 Srb->SrbStatus = SRB_STATUS_SUCCESS; //SRB_STATUS_INVALID_REQUEST;
780 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
781 ScsiPortNotification(NextLuRequest, DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
782 break;
783 case SCSIOP_REPORT_LUNS:
784 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
785 Srb->SrbStatus = SRB_STATUS_SUCCESS; //SRB_STATUS_INVALID_REQUEST;
786 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
787 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
788 break;
789 case SCSIOP_READ_TOC:
790 DataBuffer = Srb->DataBuffer;
791 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
792 /*
793 #define READ_TOC_FORMAT_TOC 0x00
794 #define READ_TOC_FORMAT_SESSION 0x01
795 #define READ_TOC_FORMAT_FULL_TOC 0x02
796 #define READ_TOC_FORMAT_PMA 0x03
797 #define READ_TOC_FORMAT_ATIP 0x04
798 */
799 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
800 KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
801 KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
802 KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
803 KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
804 KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
805 KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
806 KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
807 switch (cdb->READ_TOC.Format2)
808 {
809 case READ_TOC_FORMAT_TOC:
810 DataBuffer[0] = 0; // length MSB
811 DataBuffer[1] = 10; // length LSB
812 DataBuffer[2] = 1; // First Track
813 DataBuffer[3] = 1; // Last Track
814 DataBuffer[4] = 0; // Reserved
815 DataBuffer[5] = 0x14; // current position data + uninterrupted data
816 DataBuffer[6] = 1; // last complete track
817 DataBuffer[7] = 0; // reserved
818 DataBuffer[8] = 0; // MSB Block
819 DataBuffer[9] = 0;
820 DataBuffer[10] = 0;
821 DataBuffer[11] = 0; // LSB Block
822 Srb->SrbStatus = SRB_STATUS_SUCCESS;
823 break;
824 case READ_TOC_FORMAT_SESSION:
825 case READ_TOC_FORMAT_FULL_TOC:
826 case READ_TOC_FORMAT_PMA:
827 case READ_TOC_FORMAT_ATIP:
828 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
829 break;
830 }
831 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
832 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
833 break;
834 case SCSIOP_START_STOP_UNIT:
835 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
836 Srb->SrbStatus = SRB_STATUS_SUCCESS;
837 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
838 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
839 break;
840 default:
841 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
842 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
843 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
844 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
845 break;
846 }
847 break;
848 case SRB_FUNCTION_IO_CONTROL:
849 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
850 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
851 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
852 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
853 break;
854 case SRB_FUNCTION_FLUSH:
855 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
856 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
857 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
858 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
859 break;
860 default:
861 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
862 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
863 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
864 ScsiPortNotification(NextRequest, DeviceExtension, NULL);
865 break;
866 }
868 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
869 return TRUE;
870 }
872 static BOOLEAN
873 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
874 {
875 UNREFERENCED_PARAMETER(DeviceExtension);
876 UNREFERENCED_PARAMETER(PathId);
878 KdPrint((__DRIVER_NAME " --> HwScsiResetBus\n"));
879 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
881 KdPrint((__DRIVER_NAME " <-- HwScsiResetBus\n"));
883 return TRUE;
884 }
886 static BOOLEAN
887 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
888 {
889 UNREFERENCED_PARAMETER(DeviceExtension);
890 UNREFERENCED_PARAMETER(Context);
891 UNREFERENCED_PARAMETER(SaveState);
893 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
894 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
896 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
898 return TRUE;
899 }
901 static SCSI_ADAPTER_CONTROL_STATUS
902 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
903 {
904 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
905 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
906 //KIRQL OldIrql;
908 UNREFERENCED_PARAMETER(DeviceExtension);
910 KdPrint((__DRIVER_NAME " --> HwScsiAdapterControl\n"));
911 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
913 switch (ControlType)
914 {
915 case ScsiQuerySupportedControlTypes:
916 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
917 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
918 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
919 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
920 break;
921 case ScsiStopAdapter:
922 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
923 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
924 break;
925 case ScsiRestartAdapter:
926 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
927 break;
928 case ScsiSetBootConfig:
929 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
930 break;
931 case ScsiSetRunningConfig:
932 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
933 break;
934 default:
935 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
936 break;
937 }
939 KdPrint((__DRIVER_NAME " <-- HwScsiAdapterControl\n"));
941 return Status;
942 }
944 VOID
945 XenVbd_FillInitCallbacks(PHW_INITIALIZATION_DATA HwInitializationData)
946 {
947 KdPrint((__DRIVER_NAME " --> "__FUNCTION__ "\n"));
948 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
950 HwInitializationData->HwInitialize = XenVbd_HwScsiInitialize;
951 HwInitializationData->HwStartIo = XenVbd_HwScsiStartIo;
952 HwInitializationData->HwInterrupt = XenVbd_HwScsiInterrupt;
953 HwInitializationData->HwFindAdapter = XenVbd_HwScsiFindAdapter;
954 HwInitializationData->HwResetBus = XenVbd_HwScsiResetBus;
955 HwInitializationData->HwAdapterState = XenVbd_HwScsiAdapterState;
956 HwInitializationData->HwAdapterControl = XenVbd_HwScsiAdapterControl;
958 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
959 }