win-pvdrivers

view xenvbd/xenvbd.c @ 538:e75bb8d68370

Lots more changes...
author James Harper <james.harper@bendigoit.com.au>
date Tue Mar 03 09:51:24 2009 +1100 (2009-03-03)
parents 2a74ac2f43bb
children ee8236b44af3
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 #define INITGUID
21 #include "xenvbd.h"
22 #include <io/blkif.h>
23 #include <scsi.h>
24 #include <ntddscsi.h>
25 #include <ntdddisk.h>
26 #include <stdlib.h>
27 #include <xen_public.h>
28 #include <io/xenbus.h>
29 #include <io/protocols.h>
31 #pragma warning(disable: 4127)
33 #if defined(__x86_64__)
34 #define LongLongToPtr(x) (PVOID)(x)
35 #else
36 #define LongLongToPtr(x) UlongToPtr(x)
37 #endif
39 static BOOLEAN dump_mode = FALSE;
41 ULONGLONG parse_numeric_string(PCHAR string)
42 {
43 ULONGLONG val = 0;
44 while (*string != 0)
45 {
46 val = val * 10 + (*string - '0');
47 string++;
48 }
49 return val;
50 }
52 static blkif_shadow_t *
53 get_shadow_from_freelist(PXENVBD_DEVICE_DATA xvdd)
54 {
55 if (xvdd->shadow_free == 0)
56 {
57 KdPrint((__DRIVER_NAME " No more shadow entries\n"));
58 return NULL;
59 }
60 xvdd->shadow_free--;
61 if (xvdd->shadow_free < xvdd->shadow_min_free)
62 xvdd->shadow_min_free = xvdd->shadow_free;
63 return &xvdd->shadows[xvdd->shadow_free_list[xvdd->shadow_free]];
64 }
66 static VOID
67 put_shadow_on_freelist(PXENVBD_DEVICE_DATA xvdd, blkif_shadow_t *shadow)
68 {
69 xvdd->shadow_free_list[xvdd->shadow_free] = (USHORT)shadow->req.id;
70 shadow->srb = NULL;
71 xvdd->shadow_free++;
72 }
74 static blkif_response_t *
75 XenVbd_GetResponse(PXENVBD_DEVICE_DATA xvdd, int i)
76 {
77 blkif_other_response_t *rep;
78 if (!xvdd->use_other)
79 return RING_GET_RESPONSE(&xvdd->ring, i);
80 rep = RING_GET_RESPONSE(&xvdd->other_ring, i);
81 xvdd->tmp_rep.id = rep->id;
82 xvdd->tmp_rep.operation = rep->operation;
83 xvdd->tmp_rep.status = rep->status;
84 return &xvdd->tmp_rep;
85 }
87 static VOID
88 XenVbd_PutRequest(PXENVBD_DEVICE_DATA xvdd, blkif_request_t *req)
89 {
90 blkif_other_request_t *other_req;
92 if (!xvdd->use_other)
93 {
94 *RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt) = *req;
95 }
96 else
97 {
98 other_req = RING_GET_REQUEST(&xvdd->other_ring, xvdd->ring.req_prod_pvt);
99 other_req->operation = req->operation;
100 other_req->nr_segments = req->nr_segments;
101 other_req->handle = req->handle;
102 other_req->id = req->id;
103 other_req->sector_number = req->sector_number;
104 memcpy(other_req->seg, req->seg, sizeof(struct blkif_request_segment) * req->nr_segments);
105 }
106 xvdd->ring.req_prod_pvt++;
107 }
109 static ULONG
110 XenVbd_InitFromConfig(PXENVBD_DEVICE_DATA xvdd)
111 {
112 ULONG i;
113 PUCHAR ptr;
114 USHORT type;
115 PCHAR setting, value, value2;
116 ULONG qemu_protocol_version = 0;
118 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
119 xvdd->sring = NULL;
120 xvdd->event_channel = 0;
122 xvdd->inactive = TRUE;
123 ptr = xvdd->device_base;
124 while((type = GET_XEN_INIT_RSP(&ptr, (PVOID)&setting, (PVOID)&value, (PVOID)&value2)) != XEN_INIT_TYPE_END)
125 {
126 switch(type)
127 {
128 case XEN_INIT_TYPE_RING: /* frontend ring */
129 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_RING - %s = %p\n", setting, value));
130 if (strcmp(setting, "ring-ref") == 0)
131 {
132 xvdd->sring = (blkif_sring_t *)value;
133 FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE);
134 /* this bit is for when we have to take over an existing ring on a crash dump */
135 xvdd->ring.req_prod_pvt = xvdd->sring->req_prod;
136 xvdd->ring.rsp_cons = xvdd->ring.req_prod_pvt;
137 }
138 break;
139 case XEN_INIT_TYPE_EVENT_CHANNEL: /* frontend event channel */
140 case XEN_INIT_TYPE_EVENT_CHANNEL_IRQ: /* frontend event channel */
141 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_EVENT_CHANNEL - %s = %d\n", setting, PtrToUlong(value) & 0x3FFFFFFF));
142 if (strcmp(setting, "event-channel") == 0)
143 {
144 /* cheat here - save the state of the ring in the topmost bits of the event-channel */
145 xvdd->event_channel_ptr = (ULONG *)(((PCHAR)ptr) - sizeof(ULONG));
146 xvdd->event_channel = PtrToUlong(value) & 0x3FFFFFFF;
147 if (PtrToUlong(value) & 0x80000000)
148 {
149 xvdd->cached_use_other = (BOOLEAN)!!(PtrToUlong(value) & 0x40000000);
150 KdPrint((__DRIVER_NAME " cached_use_other = %d\n", xvdd->cached_use_other));
151 }
152 }
153 break;
154 case XEN_INIT_TYPE_READ_STRING_BACK:
155 case XEN_INIT_TYPE_READ_STRING_FRONT:
156 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_READ_STRING - %s = %s\n", setting, value));
157 if (strcmp(setting, "sectors") == 0)
158 xvdd->total_sectors = parse_numeric_string(value);
159 else if (strcmp(setting, "sector-size") == 0)
160 xvdd->bytes_per_sector = (ULONG)parse_numeric_string(value);
161 else if (strcmp(setting, "device-type") == 0)
162 {
163 if (strcmp(value, "disk") == 0)
164 {
165 KdPrint((__DRIVER_NAME " device-type = Disk\n"));
166 xvdd->device_type = XENVBD_DEVICETYPE_DISK;
167 }
168 else if (strcmp(value, "cdrom") == 0)
169 {
170 KdPrint((__DRIVER_NAME " device-type = CDROM\n"));
171 xvdd->device_type = XENVBD_DEVICETYPE_CDROM;
172 }
173 else
174 {
175 KdPrint((__DRIVER_NAME " device-type = %s (This probably won't work!)\n", value));
176 xvdd->device_type = XENVBD_DEVICETYPE_UNKNOWN;
177 }
178 }
179 else if (strcmp(setting, "mode") == 0)
180 {
181 if (strncmp(value, "r", 1) == 0)
182 {
183 KdPrint((__DRIVER_NAME " mode = r\n"));
184 xvdd->device_mode = XENVBD_DEVICEMODE_READ;
185 }
186 else if (strncmp(value, "w", 1) == 0)
187 {
188 KdPrint((__DRIVER_NAME " mode = w\n"));
189 xvdd->device_mode = XENVBD_DEVICEMODE_WRITE;
190 }
191 else
192 {
193 KdPrint((__DRIVER_NAME " mode = unknown\n"));
194 xvdd->device_mode = XENVBD_DEVICEMODE_UNKNOWN;
195 }
196 }
197 break;
198 case XEN_INIT_TYPE_VECTORS:
199 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_VECTORS\n"));
200 if (((PXENPCI_VECTORS)value)->length != sizeof(XENPCI_VECTORS) ||
201 ((PXENPCI_VECTORS)value)->magic != XEN_DATA_MAGIC)
202 {
203 KdPrint((__DRIVER_NAME " vectors mismatch (magic = %08x, length = %d)\n",
204 ((PXENPCI_VECTORS)value)->magic, ((PXENPCI_VECTORS)value)->length));
205 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
206 return SP_RETURN_BAD_CONFIG;
207 }
208 else
209 memcpy(&xvdd->vectors, value, sizeof(XENPCI_VECTORS));
210 break;
211 case XEN_INIT_TYPE_STATE_PTR:
212 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_DEVICE_STATE - %p\n", PtrToUlong(value)));
213 xvdd->device_state = (PXENPCI_DEVICE_STATE)value;
214 break;
215 case XEN_INIT_TYPE_ACTIVE:
216 xvdd->inactive = FALSE;
217 break;
218 case XEN_INIT_TYPE_QEMU_PROTOCOL_VERSION:
219 qemu_protocol_version = PtrToUlong(value);
220 break;
221 case XEN_INIT_TYPE_GRANT_ENTRIES:
222 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_GRANT_ENTRIES - entries = %d\n", PtrToUlong(setting)));
223 memcpy(xvdd->dump_grant_refs, value, PtrToUlong(setting) * sizeof(grant_ref_t));
224 break;
225 default:
226 KdPrint((__DRIVER_NAME " XEN_INIT_TYPE_%d\n", type));
227 break;
228 }
229 }
230 if (xvdd->device_type == XENVBD_DEVICETYPE_UNKNOWN
231 || xvdd->sring == NULL
232 || xvdd->event_channel == 0
233 || xvdd->total_sectors == 0
234 || xvdd->bytes_per_sector == 0)
235 {
236 KdPrint((__DRIVER_NAME " Missing settings\n"));
237 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
238 return SP_RETURN_BAD_CONFIG;
239 }
240 if (!xvdd->inactive && xvdd->device_type == XENVBD_DEVICETYPE_CDROM && qemu_protocol_version > 0)
241 {
242 xvdd->inactive = TRUE;
243 }
245 if (xvdd->inactive)
246 KdPrint((__DRIVER_NAME " Device is inactive\n"));
248 if (xvdd->device_type == XENVBD_DEVICETYPE_CDROM)
249 {
250 /* CD/DVD drives must have bytes_per_sector = 2048. */
251 xvdd->bytes_per_sector = 2048;
252 }
254 /* for some reason total_sectors is measured in 512 byte sectors always, so correct this to be in bytes_per_sectors */
255 #ifdef __MINGW32__
256 /* mingw can't divide, so shift instead (assumes bps is ^2 and at least 512) */
257 {
258 ULONG num_512_byte_sectors = xvdd->bytes_per_sector / 512;
259 ULONG index;
261 bit_scan_forward(&index, num_512_byte_sectors);
262 xvdd->total_sectors <<= index-1;
263 }
264 #else
265 xvdd->total_sectors /= xvdd->bytes_per_sector / 512;
266 #endif
269 xvdd->shadow_free = 0;
270 memset(xvdd->shadows, 0, sizeof(blkif_shadow_t) * SHADOW_ENTRIES);
271 for (i = 0; i < SHADOW_ENTRIES; i++)
272 {
273 xvdd->shadows[i].req.id = i;
274 put_shadow_on_freelist(xvdd, &xvdd->shadows[i]);
275 }
277 return SP_RETURN_FOUND;
278 }
280 static __inline ULONG
281 decode_cdb_length(PSCSI_REQUEST_BLOCK srb)
282 {
283 switch (srb->Cdb[0])
284 {
285 case SCSIOP_READ:
286 case SCSIOP_WRITE:
287 return (srb->Cdb[7] << 8) | srb->Cdb[8];
288 case SCSIOP_READ16:
289 case SCSIOP_WRITE16:
290 return (srb->Cdb[10] << 24) | (srb->Cdb[11] << 16) | (srb->Cdb[12] << 8) | srb->Cdb[13];
291 default:
292 return 0;
293 }
294 }
296 static __inline ULONGLONG
297 decode_cdb_sector(PSCSI_REQUEST_BLOCK srb)
298 {
299 ULONGLONG sector;
301 switch (srb->Cdb[0])
302 {
303 case SCSIOP_READ:
304 case SCSIOP_WRITE:
305 sector = (srb->Cdb[2] << 24) | (srb->Cdb[3] << 16) | (srb->Cdb[4] << 8) | srb->Cdb[5];
306 break;
307 case SCSIOP_READ16:
308 case SCSIOP_WRITE16:
309 sector = ((ULONGLONG)srb->Cdb[2] << 56) | ((ULONGLONG)srb->Cdb[3] << 48)
310 | ((ULONGLONG)srb->Cdb[4] << 40) | ((ULONGLONG)srb->Cdb[5] << 32)
311 | ((ULONGLONG)srb->Cdb[6] << 24) | ((ULONGLONG)srb->Cdb[7] << 16)
312 | ((ULONGLONG)srb->Cdb[8] << 8) | ((ULONGLONG)srb->Cdb[9]);
313 //KdPrint((__DRIVER_NAME " sector_number = %d (high) %d (low)\n", (ULONG)(sector >> 32), (ULONG)sector));
314 break;
315 default:
316 sector = 0;
317 break;
318 }
319 return sector;
320 }
322 static __inline BOOLEAN
323 decode_cdb_is_read(PSCSI_REQUEST_BLOCK srb)
324 {
325 switch (srb->Cdb[0])
326 {
327 case SCSIOP_READ:
328 case SCSIOP_READ16:
329 return TRUE;
330 case SCSIOP_WRITE:
331 case SCSIOP_WRITE16:
332 return FALSE;
333 default:
334 return FALSE;
335 }
336 }
338 static __forceinline PVOID
339 get_databuffer_virtual(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
340 {
341 ULONG data_buffer_length;
343 if (!dump_mode)
344 {
345 return LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
346 }
347 else
348 {
349 /* in dump mode, we can count on srb->DataBuffer being the virtual address we want */
350 return srb->DataBuffer;
351 }
352 }
354 static VOID
355 XenVbd_PutSrbOnRing(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
356 {
357 ULONG block_count;
358 blkif_shadow_t *shadow;
359 ULONG remaining, offset, length;
360 grant_ref_t gref;
361 ULONG gref_index;
362 PUCHAR ptr;
363 int notify;
365 //FUNCTION_ENTER();
367 ptr = srb->DataBuffer;
369 block_count = decode_cdb_length(srb);;
370 block_count *= xvdd->bytes_per_sector / 512;
371 remaining = block_count * 512;
373 shadow = get_shadow_from_freelist(xvdd);
374 ASSERT(shadow);
375 shadow->req.sector_number = decode_cdb_sector(srb);
376 shadow->req.sector_number *= xvdd->bytes_per_sector / 512;
377 shadow->req.handle = 0;
378 shadow->req.operation = decode_cdb_is_read(srb)?BLKIF_OP_READ:BLKIF_OP_WRITE;
379 shadow->req.nr_segments = 0;
380 shadow->srb = srb;
382 //KdPrint((__DRIVER_NAME " sector_number = %d, block_count = %d\n", (ULONG)shadow->req.sector_number, block_count));
383 //KdPrint((__DRIVER_NAME " SrbExtension = %p\n", srb->SrbExtension));
384 //KdPrint((__DRIVER_NAME " DataBuffer = %p\n", srb->DataBuffer));
386 //KdPrint((__DRIVER_NAME " sector_number = %d\n", (ULONG)shadow->req.sector_number));
387 //KdPrint((__DRIVER_NAME " handle = %d\n", shadow->req.handle));
388 //KdPrint((__DRIVER_NAME " operation = %d\n", shadow->req.operation));
389 gref_index = 0;
390 while (remaining > 0)
391 {
392 PHYSICAL_ADDRESS physical_address;
393 physical_address = ScsiPortGetPhysicalAddress(xvdd, srb, ptr, &length);
394 if (!dump_mode)
395 {
396 gref = (grant_ref_t)(physical_address.QuadPart >> PAGE_SHIFT);
397 }
398 else
399 {
400 gref = (grant_ref_t)xvdd->vectors.GntTbl_GrantAccess(xvdd->vectors.context, 0,
401 (ULONG)(physical_address.QuadPart >> PAGE_SHIFT), FALSE, xvdd->dump_grant_refs[gref_index++]);
402 }
403 offset = physical_address.LowPart & (PAGE_SIZE - 1);
404 length = min(PAGE_SIZE - offset, remaining);
405 ASSERT((offset & 511) == 0);
406 ASSERT((length & 511) == 0);
407 //KdPrint((__DRIVER_NAME " length(a) = %d\n", length));
408 shadow->req.seg[shadow->req.nr_segments].gref = gref;
409 //KdPrint((__DRIVER_NAME " length(b) = %d\n", length));
410 shadow->req.seg[shadow->req.nr_segments].first_sect = (UCHAR)(offset >> 9);
411 shadow->req.seg[shadow->req.nr_segments].last_sect = (UCHAR)(((offset + length) >> 9) - 1);
412 remaining -= length;
413 ptr += length;
414 shadow->req.nr_segments++;
415 }
417 //KdPrint((__DRIVER_NAME " nr_segments = %d\n", shadow->req.nr_segments));
419 XenVbd_PutRequest(xvdd, &shadow->req);
421 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
422 if (notify)
423 {
424 //KdPrint((__DRIVER_NAME " Notifying\n"));
425 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
426 }
428 if (xvdd->shadow_free)
429 ScsiPortNotification(NextLuRequest, xvdd, 0, 0, 0);
431 //FUNCTION_EXIT();
432 }
434 #if 0
435 static VOID
436 XenVbd_Resume(PVOID DeviceExtension)
437 {
438 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
439 ULONG i;
441 FUNCTION_ENTER();
442 KdPrint((__DRIVER_NAME " found device in resume state\n"));
443 //FRONT_RING_INIT(&xvdd->ring, xvdd->sring, PAGE_SIZE); what was this for???
444 // re-submit srb's
446 KdPrint((__DRIVER_NAME " About to call InitFromConfig\n"));
447 XenVbd_InitFromConfig(xvdd);
448 KdPrint((__DRIVER_NAME " Back from InitFromConfig\n"));
451 xvdd->device_state->resume_state = RESUME_STATE_RUNNING;
453 KdPrint((__DRIVER_NAME " resume_state set to RESUME_STATE_RUNNING\n"));
455 if (i == 0)
456 {
457 /* no requests, so we might need to tell scsiport that we can accept a new one if we deferred one earlier */
458 KdPrint((__DRIVER_NAME " No shadows - notifying to get things started again\n"));
459 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
460 }
461 FUNCTION_EXIT();
462 }
463 #endif
465 static ULONG DDKAPI
466 XenVbd_HwScsiFindAdapter(PVOID DeviceExtension, PVOID HwContext, PVOID BusInformation, PCHAR ArgumentString, PPORT_CONFIGURATION_INFORMATION ConfigInfo, PBOOLEAN Again)
467 {
468 // PACCESS_RANGE AccessRange;
469 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
470 ULONG status;
471 // PXENPCI_XEN_DEVICE_DATA XenDeviceData;
472 PACCESS_RANGE access_range;
474 UNREFERENCED_PARAMETER(HwContext);
475 UNREFERENCED_PARAMETER(BusInformation);
476 UNREFERENCED_PARAMETER(ArgumentString);
478 FUNCTION_ENTER();
479 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
481 *Again = FALSE;
483 KdPrint((__DRIVER_NAME " BusInterruptLevel = %d\n", ConfigInfo->BusInterruptLevel));
484 KdPrint((__DRIVER_NAME " BusInterruptVector = %03x\n", ConfigInfo->BusInterruptVector));
486 KdPrint((__DRIVER_NAME " NumberOfAccessRanges = %d\n", ConfigInfo->NumberOfAccessRanges));
487 if (ConfigInfo->NumberOfAccessRanges != 1 && ConfigInfo->NumberOfAccessRanges != 2)
488 {
489 return SP_RETURN_BAD_CONFIG;
490 }
492 access_range = &((*(ConfigInfo->AccessRanges))[0]);
493 KdPrint((__DRIVER_NAME " RangeStart = %08x, RangeLength = %08x\n",
494 access_range->RangeStart.LowPart, access_range->RangeLength));
495 xvdd->device_base = ScsiPortGetDeviceBase(
496 DeviceExtension,
497 ConfigInfo->AdapterInterfaceType,
498 ConfigInfo->SystemIoBusNumber,
499 access_range->RangeStart,
500 access_range->RangeLength,
501 !access_range->RangeInMemory);
502 if (!xvdd->device_base)
503 {
504 KdPrint((__DRIVER_NAME " Invalid config\n"));
505 FUNCTION_EXIT();
506 return SP_RETURN_BAD_CONFIG;
507 }
509 status = XenVbd_InitFromConfig(xvdd);
510 if (status != SP_RETURN_FOUND)
511 {
512 FUNCTION_EXIT();
513 return status;
514 }
516 if (!dump_mode)
517 {
518 ConfigInfo->MaximumTransferLength = BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE;
519 ConfigInfo->NumberOfPhysicalBreaks = BLKIF_MAX_SEGMENTS_PER_REQUEST - 1;
520 ConfigInfo->ScatterGather = TRUE;
521 }
522 else
523 {
524 ConfigInfo->MaximumTransferLength = 4096;
525 ConfigInfo->NumberOfPhysicalBreaks = 0;
526 ConfigInfo->ScatterGather = FALSE;
527 }
528 ConfigInfo->AlignmentMask = 0;
529 ConfigInfo->NumberOfBuses = 1;
530 ConfigInfo->InitiatorBusId[0] = 1;
531 ConfigInfo->MaximumNumberOfLogicalUnits = 1;
532 ConfigInfo->MaximumNumberOfTargets = 2;
533 ConfigInfo->BufferAccessScsiPortControlled = TRUE;
534 if (ConfigInfo->Dma64BitAddresses == SCSI_DMA64_SYSTEM_SUPPORTED)
535 {
536 ConfigInfo->Master = TRUE;
537 ConfigInfo->Dma64BitAddresses = SCSI_DMA64_MINIPORT_SUPPORTED;
538 ConfigInfo->Dma32BitAddresses = FALSE;
539 KdPrint((__DRIVER_NAME " Dma64BitAddresses supported\n"));
540 }
541 else
542 {
543 ConfigInfo->Master = TRUE; //FALSE;
544 ConfigInfo->Dma32BitAddresses = TRUE;
545 KdPrint((__DRIVER_NAME " Dma64BitAddresses not supported\n"));
546 }
548 FUNCTION_EXIT();
550 return SP_RETURN_FOUND;
551 }
553 static BOOLEAN DDKAPI
554 XenVbd_HwScsiInitialize(PVOID DeviceExtension)
555 {
556 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
557 blkif_request_t *req;
558 int i;
559 int notify;
561 FUNCTION_ENTER();
562 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
564 if (!dump_mode)
565 {
566 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
567 req->operation = 0xff;
568 req->nr_segments = 0;
569 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
570 {
571 req->seg[i].gref = 0; //0xffffffff;
572 req->seg[i].first_sect = 0; //0xff;
573 req->seg[i].last_sect = 0; //0xff;
574 }
575 xvdd->ring.req_prod_pvt++;
577 req = RING_GET_REQUEST(&xvdd->ring, xvdd->ring.req_prod_pvt);
578 req->operation = 0xff;
579 req->nr_segments = 0;
580 for (i = 0; i < BLKIF_MAX_SEGMENTS_PER_REQUEST; i++)
581 {
582 req->seg[i].gref = 0; //0xffffffff;
583 req->seg[i].first_sect = 0; //0xff;
584 req->seg[i].last_sect = 0; //0xff;
585 }
586 xvdd->ring.req_prod_pvt++;
588 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&xvdd->ring, notify);
589 if (notify)
590 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->event_channel);
591 xvdd->ring_detect_state = 0;
592 }
593 else
594 {
595 if (xvdd->cached_use_other)
596 {
597 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
598 xvdd->use_other = TRUE;
599 }
600 xvdd->ring_detect_state = 2;
601 }
603 FUNCTION_EXIT();
605 return TRUE;
606 }
608 static ULONG
609 XenVbd_FillModePage(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
610 {
611 PMODE_PARAMETER_HEADER parameter_header;
612 PMODE_PARAMETER_BLOCK param_block;
613 PMODE_FORMAT_PAGE format_page;
614 ULONG offset;
615 UCHAR buffer[256];
616 BOOLEAN valid_page = FALSE;
617 BOOLEAN cdb_llbaa;
618 BOOLEAN cdb_dbd;
619 UCHAR cdb_page_code;
620 USHORT cdb_allocation_length;
621 PVOID data_buffer;
622 //ULONG data_buffer_length;
624 UNREFERENCED_PARAMETER(xvdd);
626 //KdPrint((__DRIVER_NAME " --> " __FUNCTION__ "\n"));
628 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, srb, srb->DataBuffer, &data_buffer_length).QuadPart);
629 data_buffer = get_databuffer_virtual(xvdd, srb);
630 //cdb = (PCDB)srb->Cdb;
631 switch (srb->Cdb[0])
632 {
633 case SCSIOP_MODE_SENSE:
634 cdb_llbaa = FALSE;
635 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
636 cdb_page_code = srb->Cdb[2] & 0x3f;
637 cdb_allocation_length = srb->Cdb[4];
638 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
639 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
640 break;
641 case SCSIOP_MODE_SENSE10:
642 cdb_llbaa = (BOOLEAN)!!(srb->Cdb[1] & 16);
643 cdb_dbd = (BOOLEAN)!!(srb->Cdb[1] & 8);
644 cdb_page_code = srb->Cdb[2] & 0x3f;
645 cdb_allocation_length = (srb->Cdb[7] << 8) | srb->Cdb[8];
646 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE10 llbaa = %d, dbd = %d, page_code = %d, allocation_length = %d\n",
647 cdb_llbaa, cdb_dbd, cdb_page_code, cdb_allocation_length));
648 break;
649 default:
650 KdPrint((__DRIVER_NAME " SCSIOP_MODE_SENSE_WTF (%02x)\n", (ULONG)srb->Cdb[0]));
651 return FALSE;
652 }
653 offset = 0;
655 RtlZeroMemory(data_buffer, srb->DataTransferLength);
656 RtlZeroMemory(buffer, ARRAY_SIZE(buffer));
658 parameter_header = (PMODE_PARAMETER_HEADER)&buffer[offset];
659 parameter_header->MediumType = 0;
660 parameter_header->DeviceSpecificParameter = 0;
661 parameter_header->BlockDescriptorLength = 0;
662 offset += sizeof(MODE_PARAMETER_HEADER);
664 if (xvdd->device_mode == XENVBD_DEVICEMODE_READ)
665 {
666 KdPrint((__DRIVER_NAME " Mode sense to a read only disk.\n"));
667 parameter_header->DeviceSpecificParameter|=MODE_DSP_WRITE_PROTECT;
668 }
670 if (!cdb_dbd)
671 {
672 parameter_header->BlockDescriptorLength += sizeof(MODE_PARAMETER_BLOCK);
673 param_block = (PMODE_PARAMETER_BLOCK)&buffer[offset];
674 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK)
675 {
676 if (xvdd->total_sectors >> 32)
677 {
678 param_block->DensityCode = 0xff;
679 param_block->NumberOfBlocks[0] = 0xff;
680 param_block->NumberOfBlocks[1] = 0xff;
681 param_block->NumberOfBlocks[2] = 0xff;
682 }
683 else
684 {
685 param_block->DensityCode = (UCHAR)((xvdd->total_sectors >> 24) & 0xff);
686 param_block->NumberOfBlocks[0] = (UCHAR)((xvdd->total_sectors >> 16) & 0xff);
687 param_block->NumberOfBlocks[1] = (UCHAR)((xvdd->total_sectors >> 8) & 0xff);
688 param_block->NumberOfBlocks[2] = (UCHAR)((xvdd->total_sectors >> 0) & 0xff);
689 }
690 param_block->BlockLength[0] = (UCHAR)((xvdd->bytes_per_sector >> 16) & 0xff);
691 param_block->BlockLength[1] = (UCHAR)((xvdd->bytes_per_sector >> 8) & 0xff);
692 param_block->BlockLength[2] = (UCHAR)((xvdd->bytes_per_sector >> 0) & 0xff);
693 }
694 offset += sizeof(MODE_PARAMETER_BLOCK);
695 }
696 if (xvdd->device_type == XENVBD_DEVICETYPE_DISK && (cdb_page_code == MODE_PAGE_FORMAT_DEVICE || cdb_page_code == MODE_SENSE_RETURN_ALL))
697 {
698 valid_page = TRUE;
699 format_page = (PMODE_FORMAT_PAGE)&buffer[offset];
700 format_page->PageCode = MODE_PAGE_FORMAT_DEVICE;
701 format_page->PageLength = sizeof(MODE_FORMAT_PAGE) - FIELD_OFFSET(MODE_FORMAT_PAGE, PageLength);
702 /* 256 sectors per track */
703 format_page->SectorsPerTrack[0] = 0x01;
704 format_page->SectorsPerTrack[1] = 0x00;
705 /* xxx bytes per sector */
706 format_page->BytesPerPhysicalSector[0] = (UCHAR)(xvdd->bytes_per_sector >> 8);
707 format_page->BytesPerPhysicalSector[1] = (UCHAR)(xvdd->bytes_per_sector & 0xff);
708 format_page->HardSectorFormating = TRUE;
709 format_page->SoftSectorFormating = TRUE;
710 offset += sizeof(MODE_FORMAT_PAGE);
711 }
712 parameter_header->ModeDataLength = (UCHAR)(offset - 1);
713 if (!valid_page && cdb_page_code != MODE_SENSE_RETURN_ALL)
714 {
715 srb->SrbStatus = SRB_STATUS_ERROR;
716 }
717 else if(offset < srb->DataTransferLength)
718 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
719 else
720 srb->SrbStatus = SRB_STATUS_SUCCESS;
721 srb->DataTransferLength = min(srb->DataTransferLength, offset);
722 srb->ScsiStatus = 0;
723 memcpy(data_buffer, buffer, srb->DataTransferLength);
725 //KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
727 return TRUE;
728 }
730 static VOID
731 XenVbd_MakeSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb, UCHAR sense_key, UCHAR additional_sense_code)
732 {
733 PSENSE_DATA sd = srb->SenseInfoBuffer;
735 UNREFERENCED_PARAMETER(xvdd);
737 if (!srb->SenseInfoBuffer)
738 return;
740 sd->ErrorCode = 0x70;
741 sd->Valid = 1;
742 sd->SenseKey = sense_key;
743 sd->AdditionalSenseLength = sizeof(SENSE_DATA) - FIELD_OFFSET(SENSE_DATA, AdditionalSenseLength);
744 sd->AdditionalSenseCode = additional_sense_code;
745 return;
746 }
748 static VOID
749 XenVbd_MakeAutoSense(PXENVBD_DEVICE_DATA xvdd, PSCSI_REQUEST_BLOCK srb)
750 {
751 if (srb->SrbStatus == SRB_STATUS_SUCCESS || srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
752 return;
753 XenVbd_MakeSense(xvdd, srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
754 srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
755 }
757 static BOOLEAN DDKAPI
758 XenVbd_HwScsiInterrupt(PVOID DeviceExtension)
759 {
760 PXENVBD_DEVICE_DATA xvdd = (PXENVBD_DEVICE_DATA)DeviceExtension;
761 PSCSI_REQUEST_BLOCK srb;
762 RING_IDX i, rp;
763 ULONG j;
764 blkif_response_t *rep;
765 int block_count;
766 int more_to_do = TRUE;
767 blkif_shadow_t *shadow;
768 ULONG suspend_resume_state_pdo;
770 /* in dump mode I think we get called on a timer, not by an actual IRQ */
771 if (!dump_mode && !xvdd->vectors.EvtChn_AckEvent(xvdd->vectors.context, xvdd->event_channel))
772 return FALSE; /* interrupt was not for us */
774 suspend_resume_state_pdo = xvdd->device_state->suspend_resume_state_pdo;
775 KeMemoryBarrier();
777 if (suspend_resume_state_pdo != xvdd->device_state->suspend_resume_state_fdo)
778 {
779 FUNCTION_ENTER();
780 switch (suspend_resume_state_pdo)
781 {
782 case SR_STATE_SUSPENDING:
783 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_SUSPENDING\n"));
784 break;
785 case SR_STATE_RESUMING:
786 KdPrint((__DRIVER_NAME " New pdo state SR_STATE_RESUMING\n"));
787 XenVbd_InitFromConfig(xvdd);
788 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
789 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
790 break;
791 case SR_STATE_RUNNING:
792 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
793 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
794 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
795 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
796 default:
797 KdPrint((__DRIVER_NAME " New pdo state %d\n", suspend_resume_state_pdo));
798 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
799 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
800 break;
801 }
802 KeMemoryBarrier();
803 }
805 if (xvdd->device_state->suspend_resume_state_fdo != SR_STATE_RUNNING)
806 {
807 return FALSE;
808 }
810 while (more_to_do)
811 {
812 rp = xvdd->ring.sring->rsp_prod;
813 KeMemoryBarrier();
814 for (i = xvdd->ring.rsp_cons; i < rp; i++)
815 {
816 rep = XenVbd_GetResponse(xvdd, i);
817 /*
818 * This code is to automatically detect if the backend is using the same
819 * bit width or a different bit width to us. Later versions of Xen do this
820 * via a xenstore value, but not all. That 0x0fffffff (notice
821 * that the msb is not actually set, so we don't have any problems with
822 * sign extending) is to signify the last entry on the right, which is
823 * different under 32 and 64 bits, and that is why we set it up there.
825 * To do the detection, we put two initial entries on the ring, with an op
826 * of 0xff (which is invalid). The first entry is mostly okay, but the
827 * second will be grossly misaligned if the backend bit width is different,
828 * and we detect this and switch frontend structures.
829 */
830 switch (xvdd->ring_detect_state)
831 {
832 case 0:
833 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
834 xvdd->ring_detect_state = 1;
835 break;
836 case 1:
837 KdPrint((__DRIVER_NAME " ring_detect_state = %d, operation = %x, id = %lx, status = %d\n", xvdd->ring_detect_state, rep->operation, rep->id, rep->status));
838 *xvdd->event_channel_ptr |= 0x80000000;
839 if (rep->operation != 0xff)
840 {
841 xvdd->ring.nr_ents = BLK_OTHER_RING_SIZE;
842 xvdd->use_other = TRUE;
843 *xvdd->event_channel_ptr |= 0x40000000;
844 }
845 xvdd->ring_detect_state = 2;
846 ScsiPortNotification(NextRequest, DeviceExtension);
847 break;
848 case 2:
849 shadow = &xvdd->shadows[rep->id];
850 srb = shadow->srb;
851 ASSERT(srb != NULL);
852 block_count = decode_cdb_length(srb);
853 block_count *= xvdd->bytes_per_sector / 512;
854 if (rep->status == BLKIF_RSP_OKAY)
855 srb->SrbStatus = SRB_STATUS_SUCCESS;
856 else
857 {
858 KdPrint((__DRIVER_NAME " Xen Operation returned error\n"));
859 if (decode_cdb_is_read(srb))
860 KdPrint((__DRIVER_NAME " Operation = Read\n"));
861 else
862 KdPrint((__DRIVER_NAME " Operation = Write\n"));
863 KdPrint((__DRIVER_NAME " Sector = %08X, Count = %d\n", (ULONG)shadow->req.sector_number, block_count));
864 srb->SrbStatus = SRB_STATUS_ERROR;
865 srb->ScsiStatus = 0x02;
866 xvdd->last_sense_key = SCSI_SENSE_MEDIUM_ERROR;
867 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
868 XenVbd_MakeAutoSense(xvdd, srb);
869 }
870 put_shadow_on_freelist(xvdd, shadow);
871 if (dump_mode)
872 {
873 for (j = 0; j < shadow->req.nr_segments; j++)
874 {
875 ASSERT(shadow->req.seg[j].gref == xvdd->dump_grant_refs[j]);
876 xvdd->vectors.GntTbl_EndAccess(xvdd->vectors.context,
877 shadow->req.seg[j].gref, TRUE);
878 }
879 }
880 ScsiPortNotification(RequestComplete, xvdd, srb);
881 if (suspend_resume_state_pdo == SR_STATE_RUNNING)
882 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
883 break;
884 }
885 }
887 xvdd->ring.rsp_cons = i;
888 if (i != xvdd->ring.req_prod_pvt)
889 {
890 RING_FINAL_CHECK_FOR_RESPONSES(&xvdd->ring, more_to_do);
891 }
892 else
893 {
894 xvdd->ring.sring->rsp_event = i + 1;
895 more_to_do = FALSE;
896 }
897 }
899 if (suspend_resume_state_pdo == SR_STATE_SUSPENDING)
900 {
901 if (xvdd->shadow_free == SHADOW_ENTRIES)
902 {
903 /* all entries are purged from the list. ready to suspend */
904 xvdd->device_state->suspend_resume_state_fdo = suspend_resume_state_pdo;
905 KeMemoryBarrier();
906 KdPrint((__DRIVER_NAME " Set fdo state SR_STATE_SUSPENDING\n"));
907 KdPrint((__DRIVER_NAME " Notifying event channel %d\n", xvdd->device_state->pdo_event_channel));
908 xvdd->vectors.EvtChn_Notify(xvdd->vectors.context, xvdd->device_state->pdo_event_channel);
909 }
910 FUNCTION_EXIT();
911 }
913 return FALSE; /* always fall through to the next ISR... */
914 }
916 static BOOLEAN DDKAPI
917 XenVbd_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb)
918 {
919 PUCHAR data_buffer;
920 //ULONG data_buffer_length;
921 PCDB cdb;
922 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
924 if (xvdd->inactive)
925 {
926 KdPrint((__DRIVER_NAME " Inactive Srb->Function = %08X\n", Srb->Function));
927 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
928 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
929 ScsiPortNotification(NextRequest, DeviceExtension);
930 return TRUE;
931 }
933 // If we haven't enumerated all the devices yet then just defer the request
934 if (xvdd->ring_detect_state < 2)
935 {
936 Srb->SrbStatus = SRB_STATUS_BUSY;
937 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
938 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Still figuring out ring)\n"));
939 return TRUE;
940 }
942 if (xvdd->device_state->suspend_resume_state_pdo != SR_STATE_RUNNING)
943 {
944 KdPrint((__DRIVER_NAME " --> HwScsiStartIo (Resuming)\n"));
945 Srb->SrbStatus = SRB_STATUS_BUSY;
946 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
947 KdPrint((__DRIVER_NAME " <-- HwScsiStartIo (Resuming)\n"));
948 return TRUE;
949 }
951 if (Srb->PathId != 0 || Srb->TargetId != 0)
952 {
953 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
954 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
955 ScsiPortNotification(NextRequest, DeviceExtension);
956 KdPrint((__DRIVER_NAME " --- HwScsiStartIo (Out of bounds)\n"));
957 return TRUE;
958 }
960 switch (Srb->Function)
961 {
962 case SRB_FUNCTION_EXECUTE_SCSI:
963 cdb = (PCDB)Srb->Cdb;
965 switch(cdb->CDB6GENERIC.OperationCode)
966 {
967 case SCSIOP_TEST_UNIT_READY:
968 if (dump_mode)
969 KdPrint((__DRIVER_NAME " Command = TEST_UNIT_READY\n"));
970 Srb->SrbStatus = SRB_STATUS_SUCCESS;
971 Srb->ScsiStatus = 0;
972 break;
973 case SCSIOP_INQUIRY:
974 if (dump_mode)
975 {
976 //PHYSICAL_ADDRESS physical;
977 KdPrint((__DRIVER_NAME " Command = INQUIRY\n"));
978 //KdPrint((__DRIVER_NAME " Srb->Databuffer = %p\n", Srb->DataBuffer));
979 //physical = ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length);
980 //KdPrint((__DRIVER_NAME " ScsiPortGetPhysicalAddress = %08x:%08x\n", physical.LowPart, physical.HighPart));
981 }
982 // KdPrint((__DRIVER_NAME " (LUN = %d, EVPD = %d, Page Code = %02X)\n", Srb->Cdb[1] >> 5, Srb->Cdb[1] & 1, Srb->Cdb[2]));
983 // KdPrint((__DRIVER_NAME " (Length = %d)\n", Srb->DataTransferLength));
985 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
986 data_buffer = get_databuffer_virtual(xvdd, Srb);
987 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
988 Srb->SrbStatus = SRB_STATUS_SUCCESS;
989 switch (xvdd->device_type)
990 {
991 case XENVBD_DEVICETYPE_DISK:
992 if ((Srb->Cdb[1] & 1) == 0)
993 {
994 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
995 id->DeviceType = DIRECT_ACCESS_DEVICE;
996 id->Versions = 3;
997 id->ResponseDataFormat = 0;
998 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
999 id->CommandQueue = 1;
1000 memcpy(id->VendorId, "XEN ", 8); // vendor id
1001 memcpy(id->ProductId, "PV DISK ", 16); // product id
1002 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1004 else
1006 switch (Srb->Cdb[2])
1008 case 0x00:
1009 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1010 data_buffer[1] = 0x00;
1011 data_buffer[2] = 0x00;
1012 data_buffer[3] = 2;
1013 data_buffer[4] = 0x00;
1014 data_buffer[5] = 0x80;
1015 break;
1016 case 0x80:
1017 data_buffer[0] = DIRECT_ACCESS_DEVICE;
1018 data_buffer[1] = 0x80;
1019 data_buffer[2] = 0x00;
1020 data_buffer[3] = 8;
1021 memset(&data_buffer[4], ' ', 8);
1022 break;
1023 default:
1024 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1025 Srb->SrbStatus = SRB_STATUS_ERROR;
1026 break;
1029 break;
1030 case XENVBD_DEVICETYPE_CDROM:
1031 if ((Srb->Cdb[1] & 1) == 0)
1033 PINQUIRYDATA id = (PINQUIRYDATA)data_buffer;
1034 id->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
1035 id->RemovableMedia = 1;
1036 id->Versions = 3;
1037 id->ResponseDataFormat = 0;
1038 id->AdditionalLength = FIELD_OFFSET(INQUIRYDATA, VendorSpecific) - FIELD_OFFSET(INQUIRYDATA, AdditionalLength);
1039 id->CommandQueue = 1;
1040 memcpy(id->VendorId, "XEN ", 8); // vendor id
1041 memcpy(id->ProductId, "PV CDROM ", 16); // product id
1042 memcpy(id->ProductRevisionLevel, "0000", 4); // product revision level
1044 else
1046 switch (Srb->Cdb[2])
1048 case 0x00:
1049 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1050 data_buffer[1] = 0x00;
1051 data_buffer[2] = 0x00;
1052 data_buffer[3] = 2;
1053 data_buffer[4] = 0x00;
1054 data_buffer[5] = 0x80;
1055 break;
1056 case 0x80:
1057 data_buffer[0] = READ_ONLY_DIRECT_ACCESS_DEVICE;
1058 data_buffer[1] = 0x80;
1059 data_buffer[2] = 0x00;
1060 data_buffer[3] = 8;
1061 data_buffer[4] = 0x31;
1062 data_buffer[5] = 0x32;
1063 data_buffer[6] = 0x33;
1064 data_buffer[7] = 0x34;
1065 data_buffer[8] = 0x35;
1066 data_buffer[9] = 0x36;
1067 data_buffer[10] = 0x37;
1068 data_buffer[11] = 0x38;
1069 break;
1070 default:
1071 //KdPrint((__DRIVER_NAME " Unknown Page %02x requested\n", Srb->Cdb[2]));
1072 Srb->SrbStatus = SRB_STATUS_ERROR;
1073 break;
1076 break;
1077 default:
1078 //KdPrint((__DRIVER_NAME " Unknown DeviceType %02x requested\n", xvdd->device_type));
1079 Srb->SrbStatus = SRB_STATUS_ERROR;
1080 break;
1082 break;
1083 case SCSIOP_READ_CAPACITY:
1084 if (dump_mode)
1085 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1086 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1087 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1088 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1089 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1090 data_buffer = get_databuffer_virtual(xvdd, Srb);
1091 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1092 if ((xvdd->total_sectors - 1) >> 32)
1094 data_buffer[0] = 0xff;
1095 data_buffer[1] = 0xff;
1096 data_buffer[2] = 0xff;
1097 data_buffer[3] = 0xff;
1099 else
1101 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1102 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1103 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1104 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1106 data_buffer[4] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1107 data_buffer[5] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1108 data_buffer[6] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1109 data_buffer[7] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1110 Srb->ScsiStatus = 0;
1111 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1112 break;
1113 case SCSIOP_READ_CAPACITY16:
1114 if (dump_mode)
1115 KdPrint((__DRIVER_NAME " Command = READ_CAPACITY\n"));
1116 //KdPrint((__DRIVER_NAME " LUN = %d, RelAdr = %d\n", Srb->Cdb[1] >> 4, Srb->Cdb[1] & 1));
1117 //KdPrint((__DRIVER_NAME " LBA = %02x%02x%02x%02x\n", Srb->Cdb[2], Srb->Cdb[3], Srb->Cdb[4], Srb->Cdb[5]));
1118 //KdPrint((__DRIVER_NAME " PMI = %d\n", Srb->Cdb[8] & 1));
1119 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1120 data_buffer = get_databuffer_virtual(xvdd, Srb);
1121 RtlZeroMemory(data_buffer, Srb->DataTransferLength);
1122 data_buffer[0] = (unsigned char)((xvdd->total_sectors - 1) >> 56) & 0xff;
1123 data_buffer[1] = (unsigned char)((xvdd->total_sectors - 1) >> 48) & 0xff;
1124 data_buffer[2] = (unsigned char)((xvdd->total_sectors - 1) >> 40) & 0xff;
1125 data_buffer[3] = (unsigned char)((xvdd->total_sectors - 1) >> 32) & 0xff;
1126 data_buffer[4] = (unsigned char)((xvdd->total_sectors - 1) >> 24) & 0xff;
1127 data_buffer[5] = (unsigned char)((xvdd->total_sectors - 1) >> 16) & 0xff;
1128 data_buffer[6] = (unsigned char)((xvdd->total_sectors - 1) >> 8) & 0xff;
1129 data_buffer[7] = (unsigned char)((xvdd->total_sectors - 1) >> 0) & 0xff;
1130 data_buffer[8] = (unsigned char)(xvdd->bytes_per_sector >> 24) & 0xff;
1131 data_buffer[9] = (unsigned char)(xvdd->bytes_per_sector >> 16) & 0xff;
1132 data_buffer[10] = (unsigned char)(xvdd->bytes_per_sector >> 8) & 0xff;
1133 data_buffer[11] = (unsigned char)(xvdd->bytes_per_sector >> 0) & 0xff;
1134 Srb->ScsiStatus = 0;
1135 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1136 break;
1137 case SCSIOP_MODE_SENSE:
1138 case SCSIOP_MODE_SENSE10:
1139 if (dump_mode)
1140 KdPrint((__DRIVER_NAME " Command = MODE_SENSE (DBD = %d, PC = %d, Page Code = %02x)\n", Srb->Cdb[1] & 0x08, Srb->Cdb[2] & 0xC0, Srb->Cdb[2] & 0x3F));
1141 XenVbd_FillModePage(xvdd, Srb);
1142 break;
1143 case SCSIOP_READ:
1144 case SCSIOP_READ16:
1145 case SCSIOP_WRITE:
1146 case SCSIOP_WRITE16:
1147 //if (dump_mode)
1148 // KdPrint((__DRIVER_NAME " Command = READ/WRITE\n"));
1149 XenVbd_PutSrbOnRing(xvdd, Srb);
1150 break;
1151 case SCSIOP_VERIFY:
1152 // Should we do more here?
1153 if (dump_mode)
1154 KdPrint((__DRIVER_NAME " Command = VERIFY\n"));
1155 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1156 break;
1157 case SCSIOP_REPORT_LUNS:
1158 if (dump_mode)
1159 KdPrint((__DRIVER_NAME " Command = REPORT_LUNS\n"));
1160 Srb->SrbStatus = SRB_STATUS_SUCCESS;;
1161 break;
1162 case SCSIOP_REQUEST_SENSE:
1163 if (dump_mode)
1164 KdPrint((__DRIVER_NAME " Command = REQUEST_SENSE\n"));
1165 XenVbd_MakeSense(xvdd, Srb, xvdd->last_sense_key, xvdd->last_additional_sense_code);
1166 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1167 break;
1168 case SCSIOP_READ_TOC:
1169 if (dump_mode)
1170 KdPrint((__DRIVER_NAME " Command = READ_TOC\n"));
1171 //data_buffer = LongLongToPtr(ScsiPortGetPhysicalAddress(xvdd, Srb, Srb->DataBuffer, &data_buffer_length).QuadPart);
1172 data_buffer = get_databuffer_virtual(xvdd, Srb);
1173 // DataBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, HighPagePriority);
1174 /*
1175 #define READ_TOC_FORMAT_TOC 0x00
1176 #define READ_TOC_FORMAT_SESSION 0x01
1177 #define READ_TOC_FORMAT_FULL_TOC 0x02
1178 #define READ_TOC_FORMAT_PMA 0x03
1179 #define READ_TOC_FORMAT_ATIP 0x04
1180 */
1181 // KdPrint((__DRIVER_NAME " Msf = %d\n", cdb->READ_TOC.Msf));
1182 // KdPrint((__DRIVER_NAME " LogicalUnitNumber = %d\n", cdb->READ_TOC.LogicalUnitNumber));
1183 // KdPrint((__DRIVER_NAME " Format2 = %d\n", cdb->READ_TOC.Format2));
1184 // KdPrint((__DRIVER_NAME " StartingTrack = %d\n", cdb->READ_TOC.StartingTrack));
1185 // KdPrint((__DRIVER_NAME " AllocationLength = %d\n", (cdb->READ_TOC.AllocationLength[0] << 8) | cdb->READ_TOC.AllocationLength[1]));
1186 // KdPrint((__DRIVER_NAME " Control = %d\n", cdb->READ_TOC.Control));
1187 // KdPrint((__DRIVER_NAME " Format = %d\n", cdb->READ_TOC.Format));
1188 switch (cdb->READ_TOC.Format2)
1190 case READ_TOC_FORMAT_TOC:
1191 data_buffer[0] = 0; // length MSB
1192 data_buffer[1] = 10; // length LSB
1193 data_buffer[2] = 1; // First Track
1194 data_buffer[3] = 1; // Last Track
1195 data_buffer[4] = 0; // Reserved
1196 data_buffer[5] = 0x14; // current position data + uninterrupted data
1197 data_buffer[6] = 1; // last complete track
1198 data_buffer[7] = 0; // reserved
1199 data_buffer[8] = 0; // MSB Block
1200 data_buffer[9] = 0;
1201 data_buffer[10] = 0;
1202 data_buffer[11] = 0; // LSB Block
1203 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1204 break;
1205 case READ_TOC_FORMAT_SESSION:
1206 case READ_TOC_FORMAT_FULL_TOC:
1207 case READ_TOC_FORMAT_PMA:
1208 case READ_TOC_FORMAT_ATIP:
1209 Srb->SrbStatus = SRB_STATUS_ERROR;
1210 break;
1212 break;
1213 case SCSIOP_START_STOP_UNIT:
1214 KdPrint((__DRIVER_NAME " Command = SCSIOP_START_STOP_UNIT\n"));
1215 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1216 break;
1217 case SCSIOP_RESERVE_UNIT:
1218 KdPrint((__DRIVER_NAME " Command = SCSIOP_RESERVE_UNIT\n"));
1219 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1220 break;
1221 case SCSIOP_RELEASE_UNIT:
1222 KdPrint((__DRIVER_NAME " Command = SCSIOP_RELEASE_UNIT\n"));
1223 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1224 break;
1225 default:
1226 KdPrint((__DRIVER_NAME " Unhandled EXECUTE_SCSI Command = %02X\n", Srb->Cdb[0]));
1227 Srb->SrbStatus = SRB_STATUS_ERROR;
1228 break;
1230 if (Srb->SrbStatus == SRB_STATUS_ERROR)
1232 KdPrint((__DRIVER_NAME " EXECUTE_SCSI Command = %02X returned error %02x\n", Srb->Cdb[0], xvdd->last_sense_key));
1233 if (xvdd->last_sense_key == SCSI_SENSE_NO_SENSE)
1235 xvdd->last_sense_key = SCSI_SENSE_ILLEGAL_REQUEST;
1236 xvdd->last_additional_sense_code = SCSI_ADSENSE_INVALID_CDB;
1238 Srb->ScsiStatus = 0x02;
1239 XenVbd_MakeAutoSense(xvdd, Srb);
1240 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1241 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1242 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1244 else if (Srb->SrbStatus != SRB_STATUS_PENDING)
1246 xvdd->last_sense_key = SCSI_SENSE_NO_SENSE;
1247 xvdd->last_additional_sense_code = SCSI_ADSENSE_NO_SENSE;
1248 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1249 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1250 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1252 break;
1253 case SRB_FUNCTION_IO_CONTROL:
1254 KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n"));
1255 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1256 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1257 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1258 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1259 break;
1260 case SRB_FUNCTION_FLUSH:
1261 KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n"));
1262 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1263 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1264 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1265 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1266 break;
1267 case SRB_FUNCTION_SHUTDOWN:
1268 KdPrint((__DRIVER_NAME " SRB_FUNCTION_SHUTDOWN %p\n", Srb));
1269 Srb->SrbStatus = SRB_STATUS_SUCCESS;
1270 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1271 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1272 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1273 break;
1274 default:
1275 KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function));
1276 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
1277 ScsiPortNotification(RequestComplete, DeviceExtension, Srb);
1278 if (xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1279 ScsiPortNotification(NextLuRequest, DeviceExtension, 0, 0, 0);
1280 break;
1283 //FUNCTION_EXIT();
1284 return TRUE;
1287 static BOOLEAN
1288 XenVbd_HwScsiResetBus(PVOID DeviceExtension, ULONG PathId)
1290 PXENVBD_DEVICE_DATA xvdd = DeviceExtension;
1292 UNREFERENCED_PARAMETER(DeviceExtension);
1293 UNREFERENCED_PARAMETER(PathId);
1295 FUNCTION_ENTER();
1297 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1298 if (xvdd->ring_detect_state == 2 && xvdd->device_state->suspend_resume_state_pdo == SR_STATE_RUNNING)
1300 ScsiPortNotification(NextRequest, DeviceExtension);
1303 FUNCTION_EXIT();
1306 return TRUE;
1309 static BOOLEAN
1310 XenVbd_HwScsiAdapterState(PVOID DeviceExtension, PVOID Context, BOOLEAN SaveState)
1312 UNREFERENCED_PARAMETER(DeviceExtension);
1313 UNREFERENCED_PARAMETER(Context);
1314 UNREFERENCED_PARAMETER(SaveState);
1316 FUNCTION_ENTER();
1317 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1319 FUNCTION_EXIT();
1321 return TRUE;
1324 static SCSI_ADAPTER_CONTROL_STATUS DDKAPI
1325 XenVbd_HwScsiAdapterControl(PVOID DeviceExtension, SCSI_ADAPTER_CONTROL_TYPE ControlType, PVOID Parameters)
1327 SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
1328 PSCSI_SUPPORTED_CONTROL_TYPE_LIST SupportedControlTypeList;
1329 //KIRQL OldIrql;
1331 UNREFERENCED_PARAMETER(DeviceExtension);
1333 FUNCTION_ENTER();
1334 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1336 switch (ControlType)
1338 case ScsiQuerySupportedControlTypes:
1339 SupportedControlTypeList = (PSCSI_SUPPORTED_CONTROL_TYPE_LIST)Parameters;
1340 KdPrint((__DRIVER_NAME " ScsiQuerySupportedControlTypes (Max = %d)\n", SupportedControlTypeList->MaxControlType));
1341 SupportedControlTypeList->SupportedTypeList[ScsiQuerySupportedControlTypes] = TRUE;
1342 SupportedControlTypeList->SupportedTypeList[ScsiStopAdapter] = TRUE;
1343 SupportedControlTypeList->SupportedTypeList[ScsiRestartAdapter] = TRUE;
1344 break;
1345 case ScsiStopAdapter:
1346 KdPrint((__DRIVER_NAME " ScsiStopAdapter\n"));
1347 //KdBreakPoint();
1348 /* I don't think we actually have to do anything here... xenpci cleans up all the xenbus stuff for us */
1349 break;
1350 case ScsiRestartAdapter:
1351 KdPrint((__DRIVER_NAME " ScsiRestartAdapter\n"));
1352 break;
1353 case ScsiSetBootConfig:
1354 KdPrint((__DRIVER_NAME " ScsiSetBootConfig\n"));
1355 break;
1356 case ScsiSetRunningConfig:
1357 KdPrint((__DRIVER_NAME " ScsiSetRunningConfig\n"));
1358 break;
1359 default:
1360 KdPrint((__DRIVER_NAME " UNKNOWN\n"));
1361 break;
1364 FUNCTION_EXIT();
1366 return Status;
1369 PVOID init_driver_extension;
1371 static BOOLEAN
1372 XenVbd_DmaNeedVirtualAddress(PIRP irp)
1374 PIO_STACK_LOCATION stack;
1376 //FUNCTION_ENTER();
1378 stack = IoGetCurrentIrpStackLocation(irp);
1379 if (stack->MajorFunction != IRP_MJ_SCSI)
1381 KdPrint((__DRIVER_NAME " Not IRP_MJ_SCSI\n"));
1382 //FUNCTION_EXIT();
1383 return FALSE; /* this actually shouldn't happen */
1386 switch (stack->Parameters.Scsi.Srb->Cdb[0])
1388 case SCSIOP_READ:
1389 case SCSIOP_READ16:
1390 case SCSIOP_WRITE:
1391 case SCSIOP_WRITE16:
1392 //KdPrint((__DRIVER_NAME " read/write operation\n"));
1393 //FUNCTION_EXIT();
1394 return FALSE;
1395 default:
1396 //KdPrint((__DRIVER_NAME " not a read/write operation\n"));
1397 //FUNCTION_EXIT();
1398 return TRUE;
1402 static ULONG
1403 XenVbd_DmaGetAlignment(PIRP irp)
1405 UNREFERENCED_PARAMETER(irp);
1407 //FUNCTION_ENTER();
1408 //FUNCTION_EXIT();
1409 return 512;
1412 dma_driver_extension_t *dma_driver_extension;
1414 NTSTATUS
1415 DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
1417 ULONG status;
1418 HW_INITIALIZATION_DATA HwInitializationData;
1419 PVOID driver_extension;
1420 PUCHAR ptr;
1422 FUNCTION_ENTER();
1423 KdPrint((__DRIVER_NAME " IRQL = %d\n", KeGetCurrentIrql()));
1424 KdPrint((__DRIVER_NAME " DriverObject = %p, RegistryPath = %p\n", DriverObject, RegistryPath));
1426 /* RegistryPath == NULL when we are invoked as a crash dump driver */
1427 if (!RegistryPath)
1429 dump_mode = TRUE;
1432 if (!dump_mode)
1434 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_INIT_DRIVER_EXTENSION_MAGIC), PAGE_SIZE, &driver_extension);
1435 ptr = driver_extension;
1436 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RUN, NULL, NULL, NULL);
1437 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_RING, "ring-ref", NULL, NULL);
1438 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_EVENT_CHANNEL_IRQ, "event-channel", NULL, NULL);
1439 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_FRONT, "device-type", NULL, NULL);
1440 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "mode", NULL, NULL);
1441 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sectors", NULL, NULL);
1442 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_READ_STRING_BACK, "sector-size", NULL, NULL);
1443 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_GRANT_ENTRIES, NULL, ULongToPtr(BLKIF_MAX_SEGMENTS_PER_REQUEST), NULL); /* for use in crash dump */
1444 ADD_XEN_INIT_REQ(&ptr, XEN_INIT_TYPE_END, NULL, NULL, NULL);
1446 IoAllocateDriverObjectExtension(DriverObject, UlongToPtr(XEN_DMA_DRIVER_EXTENSION_MAGIC), sizeof(dma_driver_extension), &dma_driver_extension);
1447 dma_driver_extension->need_virtual_address = XenVbd_DmaNeedVirtualAddress;
1448 dma_driver_extension->get_alignment = XenVbd_DmaGetAlignment;
1451 RtlZeroMemory(&HwInitializationData, sizeof(HW_INITIALIZATION_DATA));
1453 HwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
1454 HwInitializationData.AdapterInterfaceType = PNPBus;
1455 HwInitializationData.DeviceExtensionSize = sizeof(XENVBD_DEVICE_DATA);
1456 HwInitializationData.SpecificLuExtensionSize = 0;
1457 HwInitializationData.SrbExtensionSize = 0;
1458 HwInitializationData.NumberOfAccessRanges = 1;
1459 HwInitializationData.MapBuffers = FALSE;
1460 HwInitializationData.NeedPhysicalAddresses = TRUE;
1461 HwInitializationData.TaggedQueuing = TRUE;
1462 HwInitializationData.AutoRequestSense = TRUE;
1463 HwInitializationData.MultipleRequestPerLu = TRUE;
1464 HwInitializationData.ReceiveEvent = FALSE;
1465 HwInitializationData.VendorIdLength = 0;
1466 HwInitializationData.VendorId = NULL;
1467 HwInitializationData.DeviceIdLength = 0;
1468 HwInitializationData.DeviceId = NULL;
1470 HwInitializationData.HwInitialize = XenVbd_HwScsiInitialize;
1471 HwInitializationData.HwStartIo = XenVbd_HwScsiStartIo;
1472 HwInitializationData.HwInterrupt = XenVbd_HwScsiInterrupt;
1473 HwInitializationData.HwFindAdapter = XenVbd_HwScsiFindAdapter;
1474 HwInitializationData.HwResetBus = XenVbd_HwScsiResetBus;
1475 HwInitializationData.HwDmaStarted = NULL;
1476 HwInitializationData.HwAdapterState = NULL; //XenVbd_HwScsiAdapterState;
1477 HwInitializationData.HwAdapterControl = XenVbd_HwScsiAdapterControl;
1479 status = ScsiPortInitialize(DriverObject, RegistryPath, &HwInitializationData, NULL);
1481 if(!NT_SUCCESS(status))
1483 KdPrint((__DRIVER_NAME " ScsiPortInitialize failed with status 0x%08x\n", status));
1486 FUNCTION_EXIT();
1488 return status;