disk, diskdump, pciidex, scsiport.
[reactos.git] / reactos / drivers / storage / scsiport / scsiport.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2001, 2002 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
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.
14 *
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: services/storage/scsiport/scsiport.c
24 * PURPOSE: SCSI port driver
25 * PROGRAMMER: Eric Kohl (ekohl@rz-online.de)
26 * Hartmut Birr
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #include <ntddk.h>
32 #include <srb.h>
33 #include <scsi.h>
34 #include <ntddscsi.h>
35 #include <ntddstor.h>
36 #include <ntdddisk.h>
37 #include <stdio.h>
38 #include <stdarg.h>
39
40 #define NDEBUG
41 #include <debug.h>
42
43 #include "scsiport_int.h"
44
45 /* TYPES *********************************************************************/
46
47 #define IRP_FLAG_COMPLETE 0x00000001
48 #define IRP_FLAG_NEXT 0x00000002
49 #define IRP_FLAG_NEXT_LU 0x00000004
50
51 /* GLOBALS *******************************************************************/
52
53 static ULONG InternalDebugLevel = 0;
54
55 static VOID
56 SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
57 PIRP NextIrp);
58
59 static VOID
60 SpiStartIo(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
61 PIRP Irp);
62
63 static BOOLEAN
64 SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
65 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
66 IN ULONG BusNumber,
67 IN OUT PPCI_SLOT_NUMBER NextSlotNumber);
68
69 static NTSTATUS STDCALL
70 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
71 IN PIRP Irp);
72
73 static NTSTATUS STDCALL
74 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
75 IN PIRP Irp);
76
77 static NTSTATUS STDCALL
78 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
79 IN PIRP Irp);
80
81 static BOOLEAN STDCALL
82 ScsiPortStartPacket(IN OUT PVOID Context);
83
84
85 static PSCSI_PORT_LUN_EXTENSION
86 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
87 IN UCHAR PathId,
88 IN UCHAR TargetId,
89 IN UCHAR Lun);
90
91 static VOID
92 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension);
93
94 static PSCSI_PORT_LUN_EXTENSION
95 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
96 IN UCHAR PathId,
97 IN UCHAR TargetId,
98 IN UCHAR Lun);
99
100 static NTSTATUS
101 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
102 IN OUT PSCSI_REQUEST_BLOCK Srb,
103 IN OUT PIO_STATUS_BLOCK IoStatusBlock,
104 IN OUT PKEVENT Event);
105
106 static VOID
107 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension);
108
109 static ULONG
110 SpiGetInquiryData (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
111 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo);
112
113 static BOOLEAN STDCALL
114 ScsiPortIsr(IN PKINTERRUPT Interrupt,
115 IN PVOID ServiceContext);
116
117 static VOID STDCALL
118 ScsiPortDpc(IN PKDPC Dpc,
119 IN PDEVICE_OBJECT DpcDeviceObject,
120 IN PIRP DpcIrp,
121 IN PVOID DpcContext);
122
123 static VOID STDCALL
124 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
125 PVOID Context);
126
127 static PSCSI_REQUEST_BLOCK
128 ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb);
129
130 static NTSTATUS
131 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
132 PUNICODE_STRING RegistryPath);
133
134 static VOID
135 SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
136 PSCSI_REQUEST_BLOCK Srb);
137
138 static VOID
139 SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
140 PSCSI_REQUEST_BLOCK Srb);
141
142
143 static NTSTATUS
144 SpiScsiMiniport(IN PDEVICE_OBJECT DeviceObject,
145 IN PIRP Irp);
146
147 /* FUNCTIONS *****************************************************************/
148
149 /**********************************************************************
150 * NAME EXPORTED
151 * DriverEntry
152 *
153 * DESCRIPTION
154 * This function initializes the driver.
155 *
156 * RUN LEVEL
157 * PASSIVE_LEVEL
158 *
159 * ARGUMENTS
160 * DriverObject
161 * System allocated Driver Object for this driver.
162 *
163 * RegistryPath
164 * Name of registry driver service key.
165 *
166 * RETURN VALUE
167 * Status.
168 */
169
170 NTSTATUS STDCALL
171 DriverEntry(IN PDRIVER_OBJECT DriverObject,
172 IN PUNICODE_STRING RegistryPath)
173 {
174 DPRINT("ScsiPort Driver %s\n", VERSION);
175 return(STATUS_SUCCESS);
176 }
177
178
179 /**********************************************************************
180 * NAME EXPORTED
181 * ScsiDebugPrint
182 *
183 * DESCRIPTION
184 * Prints debugging messages.
185 *
186 * RUN LEVEL
187 * PASSIVE_LEVEL
188 *
189 * ARGUMENTS
190 * DebugPrintLevel
191 * Debug level of the given message.
192 *
193 * DebugMessage
194 * Pointer to printf()-compatible format string.
195 *
196 * ...
197 Additional output data (see printf()).
198 *
199 * RETURN VALUE
200 * None.
201 *
202 * @implemented
203 */
204
205 VOID
206 ScsiDebugPrint(IN ULONG DebugPrintLevel,
207 IN PCHAR DebugMessage,
208 ...)
209 {
210 char Buffer[256];
211 va_list ap;
212
213 if (DebugPrintLevel >= InternalDebugLevel)
214 return;
215
216 va_start(ap, DebugMessage);
217 vsprintf(Buffer, DebugMessage, ap);
218 va_end(ap);
219
220 DbgPrint(Buffer);
221 }
222
223
224 /*
225 * @unimplemented
226 */
227 VOID STDCALL
228 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
229 IN UCHAR PathId,
230 IN UCHAR TargetId,
231 IN UCHAR Lun,
232 IN UCHAR SrbStatus)
233 {
234 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
235 PSCSI_PORT_LUN_EXTENSION LunExtension;
236 PLIST_ENTRY Entry;
237 PIRP Irp;
238 PSCSI_REQUEST_BLOCK Srb;
239
240 DPRINT("ScsiPortCompleteRequest(HwDeviceExtension %x, PathId %d, TargetId %d, Lun %d, SrbStatus %x)\n",
241 HwDeviceExtension, PathId, TargetId, Lun, SrbStatus);
242
243 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
244 SCSI_PORT_DEVICE_EXTENSION,
245 MiniPortDeviceExtension);
246
247 Entry = DeviceExtension->LunExtensionListHead.Flink;
248 while (Entry != &DeviceExtension->LunExtensionListHead)
249 {
250 LunExtension = CONTAINING_RECORD(Entry,
251 SCSI_PORT_LUN_EXTENSION,
252 List);
253
254
255
256 if (PathId == (UCHAR)SP_UNTAGGED ||
257 (PathId == LunExtension->PathId && TargetId == (UCHAR)SP_UNTAGGED) ||
258 (PathId == LunExtension->PathId && TargetId == LunExtension->TargetId && Lun == (UCHAR)SP_UNTAGGED) ||
259 (PathId == LunExtension->PathId && TargetId == LunExtension->TargetId && Lun == LunExtension->Lun))
260 {
261 Irp = LunExtension->NextIrp;
262 while (Irp)
263 {
264 Srb = (PSCSI_REQUEST_BLOCK)Irp->Tail.Overlay.DriverContext[3];
265 if (Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)
266 {
267 Srb->SrbStatus = SrbStatus;
268 ScsiPortNotification(RequestComplete,
269 HwDeviceExtension,
270 Srb);
271 }
272 Irp = Irp->Tail.Overlay.DriverContext[1];
273 }
274 }
275 Entry = Entry->Flink;
276 }
277 }
278
279
280 /*
281 * @implemented
282 */
283 #undef ScsiPortConvertPhysicalAddressToUlong
284 ULONG STDCALL
285 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
286 {
287 DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
288 return(Address.u.LowPart);
289 }
290
291
292 /*
293 * @unimplemented
294 */
295 VOID STDCALL
296 ScsiPortFlushDma(IN PVOID HwDeviceExtension)
297 {
298 DPRINT("ScsiPortFlushDma()\n");
299 UNIMPLEMENTED;
300 }
301
302
303 /*
304 * @implemented
305 */
306 VOID STDCALL
307 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
308 IN PVOID MappedAddress)
309 {
310 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
311 PSCSI_PORT_DEVICE_BASE DeviceBase;
312 PLIST_ENTRY Entry;
313
314 DPRINT("ScsiPortFreeDeviceBase() called\n");
315
316 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
317 SCSI_PORT_DEVICE_EXTENSION,
318 MiniPortDeviceExtension);
319 if (IsListEmpty(&DeviceExtension->DeviceBaseListHead))
320 return;
321
322 Entry = DeviceExtension->DeviceBaseListHead.Flink;
323 while (Entry != &DeviceExtension->DeviceBaseListHead)
324 {
325 DeviceBase = CONTAINING_RECORD(Entry,
326 SCSI_PORT_DEVICE_BASE,
327 List);
328 if (DeviceBase->MappedAddress == MappedAddress)
329 {
330 MmUnmapIoSpace(DeviceBase->MappedAddress,
331 DeviceBase->NumberOfBytes);
332 RemoveEntryList(Entry);
333 ExFreePool(DeviceBase);
334
335 return;
336 }
337
338 Entry = Entry->Flink;
339 }
340 }
341
342
343 /*
344 * @implemented
345 */
346 ULONG STDCALL
347 ScsiPortGetBusData(IN PVOID DeviceExtension,
348 IN ULONG BusDataType,
349 IN ULONG SystemIoBusNumber,
350 IN ULONG SlotNumber,
351 IN PVOID Buffer,
352 IN ULONG Length)
353 {
354 return(HalGetBusData(BusDataType,
355 SystemIoBusNumber,
356 SlotNumber,
357 Buffer,
358 Length));
359 }
360
361
362 /*
363 * @implemented
364 */
365 PVOID STDCALL
366 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
367 IN INTERFACE_TYPE BusType,
368 IN ULONG SystemIoBusNumber,
369 IN SCSI_PHYSICAL_ADDRESS IoAddress,
370 IN ULONG NumberOfBytes,
371 IN BOOLEAN InIoSpace)
372 {
373 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
374 PHYSICAL_ADDRESS TranslatedAddress;
375 PSCSI_PORT_DEVICE_BASE DeviceBase;
376 ULONG AddressSpace;
377 PVOID MappedAddress;
378
379 DPRINT ("ScsiPortGetDeviceBase() called\n");
380
381 AddressSpace = (ULONG)InIoSpace;
382 if (HalTranslateBusAddress(BusType,
383 SystemIoBusNumber,
384 IoAddress,
385 &AddressSpace,
386 &TranslatedAddress) == FALSE)
387 return NULL;
388
389 /* i/o space */
390 if (AddressSpace != 0)
391 return((PVOID)TranslatedAddress.u.LowPart);
392
393 MappedAddress = MmMapIoSpace(TranslatedAddress,
394 NumberOfBytes,
395 MmNonCached);
396
397 DeviceBase = ExAllocatePool(NonPagedPool,
398 sizeof(SCSI_PORT_DEVICE_BASE));
399 if (DeviceBase == NULL)
400 return(MappedAddress);
401
402 DeviceBase->MappedAddress = MappedAddress;
403 DeviceBase->NumberOfBytes = NumberOfBytes;
404 DeviceBase->IoAddress = IoAddress;
405 DeviceBase->SystemIoBusNumber = SystemIoBusNumber;
406
407 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
408 SCSI_PORT_DEVICE_EXTENSION,
409 MiniPortDeviceExtension);
410
411 InsertHeadList(&DeviceExtension->DeviceBaseListHead,
412 &DeviceBase->List);
413
414 return(MappedAddress);
415 }
416
417
418 /*
419 * @implemented
420 */
421 PVOID STDCALL
422 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
423 IN UCHAR PathId,
424 IN UCHAR TargetId,
425 IN UCHAR Lun)
426 {
427 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
428 PSCSI_PORT_LUN_EXTENSION LunExtension;
429 PLIST_ENTRY Entry;
430
431 DPRINT("ScsiPortGetLogicalUnit() called\n");
432
433 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
434 SCSI_PORT_DEVICE_EXTENSION,
435 MiniPortDeviceExtension);
436 if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
437 return NULL;
438
439 Entry = DeviceExtension->LunExtensionListHead.Flink;
440 while (Entry != &DeviceExtension->LunExtensionListHead)
441 {
442 LunExtension = CONTAINING_RECORD(Entry,
443 SCSI_PORT_LUN_EXTENSION,
444 List);
445 if (LunExtension->PathId == PathId &&
446 LunExtension->TargetId == TargetId &&
447 LunExtension->Lun == Lun)
448 {
449 return (PVOID)&LunExtension->MiniportLunExtension;
450 }
451
452 Entry = Entry->Flink;
453 }
454
455 return NULL;
456 }
457
458
459 /*
460 * @unimplemented
461 */
462 SCSI_PHYSICAL_ADDRESS STDCALL
463 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
464 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
465 IN PVOID VirtualAddress,
466 OUT ULONG *Length)
467 {
468 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
469 SCSI_PHYSICAL_ADDRESS PhysicalAddress;
470 SCSI_PHYSICAL_ADDRESS NextPhysicalAddress;
471 ULONG BufferLength = 0;
472 ULONG Offset;
473 PVOID EndAddress;
474
475 DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
476 HwDeviceExtension, Srb, VirtualAddress, Length);
477
478 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
479 SCSI_PORT_DEVICE_EXTENSION,
480 MiniPortDeviceExtension);
481
482 if (Length != NULL)
483 {
484 *Length = 0;
485 }
486 if (Srb == NULL)
487 {
488 EndAddress = (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + DeviceExtension->CommonBufferLength);
489 if (VirtualAddress >= DeviceExtension->VirtualAddress && VirtualAddress < EndAddress)
490 {
491 Offset = (ULONG_PTR)VirtualAddress - (ULONG_PTR)DeviceExtension->VirtualAddress;
492 PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset;
493 BufferLength = (ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress;
494 }
495 else
496 {
497 /*
498 * The given virtual address is not within the range
499 * of the drivers uncached extension or srb extension.
500 */
501 /*
502 * FIXME:
503 * Check if the address is a sense info buffer of an active srb.
504 */
505 PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
506 if (PhysicalAddress.QuadPart == 0LL)
507 {
508 CHECKPOINT;
509 return PhysicalAddress;
510 }
511 BufferLength = PAGE_SIZE - PhysicalAddress.u.LowPart % PAGE_SIZE;
512 }
513 }
514 else
515 {
516 EndAddress = (PVOID)((ULONG_PTR)Srb->DataBuffer + Srb->DataTransferLength);
517 if (VirtualAddress == NULL)
518 {
519 VirtualAddress = Srb->DataBuffer;
520 }
521 else if (VirtualAddress < Srb->DataBuffer || VirtualAddress >= EndAddress)
522 {
523 EndAddress = (PVOID)((ULONG_PTR)Srb->SenseInfoBuffer + Srb->SenseInfoBufferLength);
524 if (VirtualAddress < Srb->SenseInfoBuffer || VirtualAddress >= EndAddress)
525 {
526 PhysicalAddress.QuadPart = 0LL;
527 CHECKPOINT;
528 return PhysicalAddress;
529 }
530 }
531
532 PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
533 if (PhysicalAddress.QuadPart == 0LL)
534 {
535 CHECKPOINT;
536 return PhysicalAddress;
537 }
538
539 BufferLength = PAGE_SIZE - (ULONG_PTR)VirtualAddress % PAGE_SIZE;
540 while ((ULONG_PTR)VirtualAddress + BufferLength < (ULONG_PTR)EndAddress)
541 {
542 NextPhysicalAddress = MmGetPhysicalAddress((PVOID)((ULONG_PTR)VirtualAddress + BufferLength));
543 if (PhysicalAddress.QuadPart + BufferLength != NextPhysicalAddress.QuadPart)
544 {
545 break;
546 }
547 BufferLength += PAGE_SIZE;
548 }
549 if ((ULONG_PTR)VirtualAddress + BufferLength >= (ULONG_PTR)EndAddress)
550 {
551 BufferLength = (ULONG)((ULONG_PTR)EndAddress - (ULONG_PTR)VirtualAddress);
552 }
553 }
554 if (Length != NULL)
555 {
556 *Length = BufferLength;
557 }
558 DPRINT("Address %I64x, Length %d\n", PhysicalAddress.QuadPart, BufferLength);
559 return PhysicalAddress;
560 }
561
562
563 /*
564 * @unimplemented
565 */
566 PSCSI_REQUEST_BLOCK STDCALL
567 ScsiPortGetSrb(IN PVOID HwDeviceExtension,
568 IN UCHAR PathId,
569 IN UCHAR TargetId,
570 IN UCHAR Lun,
571 IN LONG QueueTag)
572 {
573 DPRINT1("ScsiPortGetSrb() unimplemented\n");
574 UNIMPLEMENTED;
575 return NULL;
576 }
577
578
579 /*
580 * @implemented
581 */
582 PVOID STDCALL
583 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
584 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
585 IN ULONG NumberOfBytes)
586 {
587 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
588 DEVICE_DESCRIPTION DeviceDescription;
589
590 DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
591 HwDeviceExtension, ConfigInfo, NumberOfBytes);
592
593 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
594 SCSI_PORT_DEVICE_EXTENSION,
595 MiniPortDeviceExtension);
596
597 /* Check for allocated common DMA buffer */
598 if (DeviceExtension->VirtualAddress != NULL)
599 {
600 DPRINT1("The HBA has already got a common DMA buffer!\n");
601 return NULL;
602 }
603
604 /* Check for DMA adapter object */
605 if (DeviceExtension->AdapterObject == NULL)
606 {
607 /* Initialize DMA adapter description */
608 RtlZeroMemory(&DeviceDescription,
609 sizeof(DEVICE_DESCRIPTION));
610 DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
611 DeviceDescription.Master = ConfigInfo->Master;
612 DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
613 DeviceDescription.DemandMode = ConfigInfo->DemandMode;
614 DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
615 DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
616 DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
617 DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
618 DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
619 DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
620 DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
621 DeviceDescription.DmaPort = ConfigInfo->DmaPort;
622
623 /* Get a DMA adapter object */
624 DeviceExtension->AdapterObject = HalGetAdapter(&DeviceDescription,
625 &DeviceExtension->MapRegisterCount);
626 if (DeviceExtension->AdapterObject == NULL)
627 {
628 DPRINT1("HalGetAdapter() failed\n");
629 return NULL;
630 }
631 }
632 if (DeviceExtension->SrbExtensionSize > 0)
633 {
634 PVOID Buffer;
635 DeviceExtension->CurrentSrbExtensions = 0;
636 if (DeviceExtension->PortConfig->MultipleRequestPerLu)
637 {
638 DeviceExtension->MaxSrbExtensions = 1024;
639 }
640 else
641 {
642 DeviceExtension->MaxSrbExtensions = 32;
643 }
644 Buffer = ExAllocatePool(NonPagedPool, ROUND_UP(DeviceExtension->MaxSrbExtensions / 8, sizeof(ULONG)));
645 if (Buffer == NULL)
646 {
647 KEBUGCHECK(0);
648 return NULL;
649 }
650 RtlInitializeBitMap(&DeviceExtension->SrbExtensionAllocMap, Buffer, DeviceExtension->MaxSrbExtensions);
651 RtlClearAllBits(&DeviceExtension->SrbExtensionAllocMap);
652 }
653
654 /* Allocate a common DMA buffer */
655 DeviceExtension->CommonBufferLength =
656 NumberOfBytes + PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * DeviceExtension->MaxSrbExtensions);
657 DeviceExtension->VirtualAddress =
658 HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
659 DeviceExtension->CommonBufferLength,
660 &DeviceExtension->PhysicalAddress,
661 FALSE);
662 if (DeviceExtension->VirtualAddress == NULL)
663 {
664 DPRINT1("HalAllocateCommonBuffer() failed!\n");
665 DeviceExtension->CommonBufferLength = 0;
666 return NULL;
667 }
668
669 return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress +
670 PAGE_ROUND_UP(DeviceExtension->SrbExtensionSize * DeviceExtension->MaxSrbExtensions));
671 }
672
673
674 /*
675 * @implemented
676 */
677 PVOID STDCALL
678 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
679 IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
680 {
681 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
682 ULONG Offset;
683
684 DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
685 HwDeviceExtension, PhysicalAddress.QuadPart);
686
687 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
688 SCSI_PORT_DEVICE_EXTENSION,
689 MiniPortDeviceExtension);
690
691 if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart)
692 return NULL;
693
694 Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart);
695 if (Offset >= DeviceExtension->CommonBufferLength)
696 return NULL;
697
698 return (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + Offset);
699 }
700
701
702 /**********************************************************************
703 * NAME EXPORTED
704 * ScsiPortInitialize
705 *
706 * DESCRIPTION
707 * Initializes SCSI port driver specific data.
708 *
709 * RUN LEVEL
710 * PASSIVE_LEVEL
711 *
712 * ARGUMENTS
713 * Argument1
714 * Pointer to the miniport driver's driver object.
715 *
716 * Argument2
717 * Pointer to the miniport driver's registry path.
718 *
719 * HwInitializationData
720 * Pointer to port driver specific configuration data.
721 *
722 * HwContext
723 Miniport driver specific context.
724 *
725 * RETURN VALUE
726 * Status.
727 *
728 * @implemented
729 */
730
731 ULONG STDCALL
732 ScsiPortInitialize(IN PVOID Argument1,
733 IN PVOID Argument2,
734 IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
735 IN PVOID HwContext)
736 {
737 PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
738 // PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
739 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
740 PCONFIGURATION_INFORMATION SystemConfig;
741 PPORT_CONFIGURATION_INFORMATION PortConfig;
742 ULONG DeviceExtensionSize;
743 ULONG PortConfigSize;
744 BOOLEAN Again;
745 BOOLEAN DeviceFound = FALSE;
746 ULONG i;
747 ULONG Result;
748 NTSTATUS Status;
749 ULONG MaxBus;
750 ULONG BusNumber;
751 PCI_SLOT_NUMBER SlotNumber;
752
753 PDEVICE_OBJECT PortDeviceObject;
754 WCHAR NameBuffer[80];
755 UNICODE_STRING DeviceName;
756 WCHAR DosNameBuffer[80];
757 UNICODE_STRING DosDeviceName;
758 PIO_SCSI_CAPABILITIES PortCapabilities;
759 ULONG MappedIrq;
760 KIRQL Dirql;
761 KAFFINITY Affinity;
762
763
764 DPRINT ("ScsiPortInitialize() called!\n");
765 #if 0
766 DPRINT1("HwInitializationDataSize: %d\n", HwInitializationData->HwInitializationDataSize);
767 DPRINT1("AdapterInterfaceType: %d\n", HwInitializationData->AdapterInterfaceType);
768 DPRINT1("HwInitialize: %x\n", HwInitializationData->HwInitialize);
769 DPRINT1("HwStartIo: %x\n", HwInitializationData->HwStartIo);
770 DPRINT1("HwInterrupt: %x\n", HwInitializationData->HwInterrupt);
771 DPRINT1("HwFindAdapter: %x\n", HwInitializationData->HwFindAdapter);
772 DPRINT1("HwResetBus: %x\n", HwInitializationData->HwResetBus);
773 DPRINT1("HwDmaStarted: %x\n", HwInitializationData->HwDmaStarted);
774 DPRINT1("HwAdapterState: %x\n", HwInitializationData->HwAdapterState);
775 DPRINT1("DeviceExtensionSize: %d\n", HwInitializationData->DeviceExtensionSize);
776 DPRINT1("SpecificLuExtensionSize: %d\n", HwInitializationData->SpecificLuExtensionSize);
777 DPRINT1("SrbExtensionSize: %d\n", HwInitializationData->SrbExtensionSize);
778 DPRINT1("NumberOfAccessRanges: %d\n", HwInitializationData->NumberOfAccessRanges);
779 DPRINT1("Reserved: %x\n", HwInitializationData->Reserved);
780 DPRINT1("MapBuffers: %d\n", HwInitializationData->MapBuffers);
781 DPRINT1("NeedPhysicalAddresses: %d\n", HwInitializationData->NeedPhysicalAddresses);
782 DPRINT1("TaggedQueueing: %d\n", HwInitializationData->TaggedQueueing);
783 DPRINT1("AutoRequestSense: %d\n", HwInitializationData->AutoRequestSense);
784 DPRINT1("MultipleRequestPerLu: %d\n", HwInitializationData->MultipleRequestPerLu);
785 DPRINT1("ReceiveEvent: %d\n", HwInitializationData->ReceiveEvent);
786 DPRINT1("VendorIdLength: %d\n", HwInitializationData->VendorIdLength);
787 DPRINT1("VendorId: %x\n", HwInitializationData->VendorId);
788 DPRINT1("ReservedUshort: %d\n", HwInitializationData->ReservedUshort);
789 DPRINT1("DeviceIdLength: %d\n", HwInitializationData->DeviceIdLength);
790 DPRINT1("DeviceId: %x\n", HwInitializationData->DeviceId);
791 #endif
792 if ((HwInitializationData->HwInitialize == NULL) ||
793 (HwInitializationData->HwStartIo == NULL) ||
794 (HwInitializationData->HwInterrupt == NULL) ||
795 (HwInitializationData->HwFindAdapter == NULL) ||
796 (HwInitializationData->HwResetBus == NULL))
797 return(STATUS_INVALID_PARAMETER);
798
799 DriverObject->DriverStartIo = NULL;
800 DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
801 DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
802 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
803 DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
804
805 SystemConfig = IoGetConfigurationInformation();
806
807 DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
808 HwInitializationData->DeviceExtensionSize;
809 PortConfigSize = sizeof(PORT_CONFIGURATION_INFORMATION) +
810 HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE);
811
812
813 MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1;
814 DPRINT("MaxBus: %lu\n", MaxBus);
815
816 PortDeviceObject = NULL;
817 BusNumber = 0;
818 SlotNumber.u.AsULONG = 0;
819 while (TRUE)
820 {
821 /* Create a unicode device name */
822 swprintf (NameBuffer,
823 L"\\Device\\ScsiPort%lu",
824 SystemConfig->ScsiPortCount);
825 RtlInitUnicodeString (&DeviceName,
826 NameBuffer);
827
828 DPRINT("Creating device: %wZ\n", &DeviceName);
829
830 /* Create the port device */
831 Status = IoCreateDevice (DriverObject,
832 DeviceExtensionSize,
833 &DeviceName,
834 FILE_DEVICE_CONTROLLER,
835 0,
836 FALSE,
837 &PortDeviceObject);
838 if (!NT_SUCCESS(Status))
839 {
840 DbgPrint ("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
841 PortDeviceObject = NULL;
842 goto ByeBye;
843 }
844
845 DPRINT ("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
846
847 /* Increase the stacksize. We reenter our device on IOCTL_SCSI_MINIPORT */
848 PortDeviceObject->StackSize++;
849
850 /* Set the buffering strategy here... */
851 PortDeviceObject->Flags |= DO_DIRECT_IO;
852 PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;
853
854 DeviceExtension = PortDeviceObject->DeviceExtension;
855 RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
856 DeviceExtension->Length = DeviceExtensionSize;
857 DeviceExtension->DeviceObject = PortDeviceObject;
858 DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
859
860 DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
861 DeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
862 DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
863 DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
864 DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
865
866 DeviceExtension->AdapterObject = NULL;
867 DeviceExtension->MapRegisterCount = 0;
868 DeviceExtension->PhysicalAddress.QuadPart = 0ULL;
869 DeviceExtension->VirtualAddress = NULL;
870 DeviceExtension->CommonBufferLength = 0;
871
872 /* Initialize the device base list */
873 InitializeListHead (&DeviceExtension->DeviceBaseListHead);
874
875 /* Initialize the irp lists */
876 InitializeListHead (&DeviceExtension->PendingIrpListHead);
877 DeviceExtension->NextIrp = NULL;
878 DeviceExtension->PendingIrpCount = 0;
879 DeviceExtension->ActiveIrpCount = 0;
880
881 /* Initialize LUN-Extension list */
882 InitializeListHead (&DeviceExtension->LunExtensionListHead);
883
884 /* Initialize the spin lock in the controller extension */
885 KeInitializeSpinLock (&DeviceExtension->Lock);
886
887 /* Initialize the DPC object */
888 IoInitializeDpcRequest (PortDeviceObject,
889 ScsiPortDpc);
890
891 /* Initialize the device timer */
892 DeviceExtension->TimerState = IDETimerIdle;
893 DeviceExtension->TimerCount = 0;
894 IoInitializeTimer (PortDeviceObject,
895 ScsiPortIoTimer,
896 DeviceExtension);
897
898 /* Allocate and initialize port configuration info */
899 DeviceExtension->PortConfig = ExAllocatePool (NonPagedPool,
900 PortConfigSize);
901 if (DeviceExtension->PortConfig == NULL)
902 {
903 Status = STATUS_INSUFFICIENT_RESOURCES;
904 goto ByeBye;
905 }
906 RtlZeroMemory (DeviceExtension->PortConfig,
907 PortConfigSize);
908
909 PortConfig = DeviceExtension->PortConfig;
910 PortConfig->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
911 PortConfig->SystemIoBusNumber = BusNumber;
912 PortConfig->AdapterInterfaceType = HwInitializationData->AdapterInterfaceType;
913 PortConfig->InterruptMode =
914 (PortConfig->AdapterInterfaceType == PCIBus) ? LevelSensitive : Latched;
915 PortConfig->MaximumTransferLength = SP_UNINITIALIZED_VALUE;
916 PortConfig->NumberOfPhysicalBreaks = SP_UNINITIALIZED_VALUE;
917 PortConfig->DmaChannel = SP_UNINITIALIZED_VALUE;
918 PortConfig->DmaPort = SP_UNINITIALIZED_VALUE;
919 PortConfig->DmaWidth = 0;
920 PortConfig->DmaSpeed = Compatible;
921 PortConfig->AlignmentMask = 0;
922 PortConfig->NumberOfAccessRanges = HwInitializationData->NumberOfAccessRanges;
923 PortConfig->NumberOfBuses = 0;
924
925 for (i = 0; i < SCSI_MAXIMUM_BUSES; i++)
926 PortConfig->InitiatorBusId[i] = 255;
927
928 PortConfig->ScatterGather = FALSE;
929 PortConfig->Master = FALSE;
930 PortConfig->CachesData = FALSE;
931 PortConfig->AdapterScansDown = FALSE;
932 PortConfig->AtdiskPrimaryClaimed = SystemConfig->AtDiskPrimaryAddressClaimed;
933 PortConfig->AtdiskSecondaryClaimed = SystemConfig->AtDiskSecondaryAddressClaimed;
934 PortConfig->Dma32BitAddresses = FALSE;
935 PortConfig->DemandMode = FALSE;
936 PortConfig->MapBuffers = HwInitializationData->MapBuffers;
937 PortConfig->NeedPhysicalAddresses = HwInitializationData->NeedPhysicalAddresses;
938 PortConfig->TaggedQueuing = HwInitializationData->TaggedQueuing;
939 PortConfig->AutoRequestSense = HwInitializationData->AutoRequestSense;
940 PortConfig->MultipleRequestPerLu = HwInitializationData->MultipleRequestPerLu;
941 PortConfig->ReceiveEvent = HwInitializationData->ReceiveEvent;
942 PortConfig->RealModeInitialized = FALSE;
943 PortConfig->BufferAccessScsiPortControlled = FALSE;
944 PortConfig->MaximumNumberOfTargets = SCSI_MAXIMUM_TARGETS;
945 // PortConfig->MaximumNumberOfLogicalUnits = SCSI_MAXIMUM_LOGICAL_UNITS;
946
947 PortConfig->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
948 PortConfig->SpecificLuExtensionSize = HwInitializationData->SpecificLuExtensionSize;
949
950 PortConfig->AccessRanges = (ACCESS_RANGE(*)[])(PortConfig + 1);
951
952 /* Search for matching PCI device */
953 if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
954 (HwInitializationData->VendorIdLength > 0) &&
955 (HwInitializationData->VendorId != NULL) &&
956 (HwInitializationData->DeviceIdLength > 0) &&
957 (HwInitializationData->DeviceId != NULL))
958 {
959 /* Get PCI device data */
960 DPRINT("VendorId '%.*s' DeviceId '%.*s'\n",
961 HwInitializationData->VendorIdLength,
962 HwInitializationData->VendorId,
963 HwInitializationData->DeviceIdLength,
964 HwInitializationData->DeviceId);
965
966 if (!SpiGetPciConfigData (HwInitializationData,
967 PortConfig,
968 BusNumber,
969 &SlotNumber))
970 {
971 Status = STATUS_UNSUCCESSFUL;
972 goto ByeBye;
973 }
974 }
975
976 /* Note: HwFindAdapter is called once for each bus */
977 Again = FALSE;
978 DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
979 Result = (HwInitializationData->HwFindAdapter)(&DeviceExtension->MiniPortDeviceExtension,
980 HwContext,
981 0, /* BusInformation */
982 "", /* ArgumentString */
983 PortConfig,
984 &Again);
985 DPRINT("HwFindAdapter() Result: %lu Again: %s\n",
986 Result, (Again) ? "True" : "False");
987
988 if (Result == SP_RETURN_FOUND)
989 {
990 DPRINT("ScsiPortInitialize(): Found HBA! (%x)\n", PortConfig->BusInterruptVector);
991
992 #if 0
993 DPRINT1("SystemIoBusNumber: %x\n", PortConfig->SystemIoBusNumber);
994 DPRINT1("AdapterInterfaceType: %x\n", PortConfig->AdapterInterfaceType);
995 DPRINT1("BusInterruptLevel: %x\n", PortConfig->BusInterruptLevel);
996 DPRINT1("BusInterruptVector: %x\n", PortConfig->BusInterruptVector);
997 DPRINT1("InterruptMode: %x\n", PortConfig->InterruptMode);
998 DPRINT1("MaximumTransferLength: %x\n", PortConfig->MaximumTransferLength);
999 DPRINT1("NumberOfPhysicalBreaks: %x\n", PortConfig->NumberOfPhysicalBreaks);
1000 DPRINT1("DmaChannel: %x\n", PortConfig->DmaChannel);
1001 DPRINT1("DmaPort: %d\n", PortConfig->DmaPort);
1002 DPRINT1("DmaWidth: %d\n", PortConfig->DmaWidth);
1003 DPRINT1("DmaSpeed: %d\n", PortConfig->DmaSpeed);
1004 DPRINT1("AlignmentMask: %d\n", PortConfig->AlignmentMask);
1005 DPRINT1("NumberOfAccessRanges: %d\n", PortConfig->NumberOfAccessRanges);
1006 DPRINT1("NumberOfBuses: %d\n", PortConfig->NumberOfBuses);
1007 DPRINT1("ScatterGather: %d\n", PortConfig->ScatterGather);
1008 DPRINT1("Master: %d\n", PortConfig->Master);
1009 DPRINT1("CachesData: %d\n", PortConfig->CachesData);
1010 DPRINT1("AdapterScansDown: %d\n", PortConfig->AdapterScansDown);
1011 DPRINT1("AtdiskPrimaryClaimed: %d\n", PortConfig->AtdiskPrimaryClaimed);
1012 DPRINT1("AtdiskSecondaryClaimed: %d\n", PortConfig->AtdiskSecondaryClaimed);
1013 DPRINT1("Dma32BitAddresses: %d\n", PortConfig->Dma32BitAddresses);
1014 DPRINT1("DemandMode: %d\n", PortConfig->DemandMode);
1015 DPRINT1("MapBuffers: %d\n", PortConfig->MapBuffers);
1016 DPRINT1("NeedPhysicalAddresses: %d\n", PortConfig->NeedPhysicalAddresses);
1017 DPRINT1("TaggedQueuing: %d\n", PortConfig->TaggedQueuing);
1018 DPRINT1("AutoRequestSense: %d\n", PortConfig->AutoRequestSense);
1019 DPRINT1("MultipleRequestPerLu: %d\n", PortConfig->MultipleRequestPerLu);
1020 DPRINT1("ReceiveEvent: %d\n", PortConfig->ReceiveEvent);
1021 DPRINT1("RealModeInitialized: %d\n", PortConfig->RealModeInitialized);
1022 DPRINT1("BufferAccessScsiPortControlled: %d\n", PortConfig->BufferAccessScsiPortControlled);
1023 DPRINT1("MaximumNumberOfTargets: %d\n", PortConfig->MaximumNumberOfTargets);
1024 DPRINT1("SlotNumber: %d\n", PortConfig->SlotNumber);
1025 DPRINT1("BusInterruptLevel2: %x\n", PortConfig->BusInterruptLevel2);
1026 DPRINT1("BusInterruptVector2: %x\n", PortConfig->BusInterruptVector2);
1027 DPRINT1("InterruptMode2: %x\n", PortConfig->InterruptMode2);
1028 DPRINT1("DmaChannel2: %d\n", PortConfig->DmaChannel2);
1029 DPRINT1("DmaPort2: %d\n", PortConfig->DmaPort2);
1030 DPRINT1("DmaWidth2: %d\n", PortConfig->DmaWidth2);
1031 DPRINT1("DmaSpeed2: %d\n", PortConfig->DmaSpeed2);
1032 DPRINT1("DeviceExtensionSize: %d\n", PortConfig->DeviceExtensionSize);
1033 DPRINT1("SpecificLuExtensionSize: %d\n", PortConfig->SpecificLuExtensionSize);
1034 DPRINT1("SrbExtensionSize: %d\n", PortConfig->SrbExtensionSize);
1035
1036 #endif
1037
1038 if (DeviceExtension->VirtualAddress == NULL && DeviceExtension->SrbExtensionSize)
1039 {
1040 ScsiPortGetUncachedExtension(&DeviceExtension->MiniPortDeviceExtension,
1041 PortConfig,
1042 0);
1043 }
1044
1045 /* Register an interrupt handler for this device */
1046 MappedIrq = HalGetInterruptVector(PortConfig->AdapterInterfaceType,
1047 PortConfig->SystemIoBusNumber,
1048 PortConfig->BusInterruptLevel,
1049 #if 1
1050 /*
1051 * FIXME:
1052 * Something is wrong in our interrupt conecting code.
1053 * The promise Ultra100TX driver returns 0 for BusInterruptVector
1054 * and a nonzero value for BusInterruptLevel. The driver does only
1055 * work with this fix.
1056 */
1057 PortConfig->BusInterruptLevel,
1058 #else
1059 PortConfig->BusInterruptVector,
1060 #endif
1061 &Dirql,
1062 &Affinity);
1063 DPRINT("AdapterInterfaceType %x, SystemIoBusNumber %x, BusInterruptLevel %x, BusInterruptVector %x\n",
1064 PortConfig->AdapterInterfaceType, PortConfig->SystemIoBusNumber,
1065 PortConfig->BusInterruptLevel, PortConfig->BusInterruptVector);
1066 Status = IoConnectInterrupt(&DeviceExtension->Interrupt,
1067 ScsiPortIsr,
1068 DeviceExtension,
1069 NULL,
1070 MappedIrq,
1071 Dirql,
1072 Dirql,
1073 PortConfig->InterruptMode,
1074 TRUE,
1075 Affinity,
1076 FALSE);
1077 if (!NT_SUCCESS(Status))
1078 {
1079 DbgPrint("Could not connect interrupt %d\n",
1080 PortConfig->BusInterruptVector);
1081 goto ByeBye;
1082 }
1083
1084 if (!(HwInitializationData->HwInitialize)(&DeviceExtension->MiniPortDeviceExtension))
1085 {
1086 DbgPrint("HwInitialize() failed!");
1087 Status = STATUS_UNSUCCESSFUL;
1088 goto ByeBye;
1089 }
1090
1091 /* Initialize port capabilities */
1092 DeviceExtension->PortCapabilities = ExAllocatePool(NonPagedPool,
1093 sizeof(IO_SCSI_CAPABILITIES));
1094 if (DeviceExtension->PortCapabilities == NULL)
1095 {
1096 DbgPrint("Failed to allocate port capabilities!\n");
1097 Status = STATUS_INSUFFICIENT_RESOURCES;
1098 goto ByeBye;
1099 }
1100
1101 PortCapabilities = DeviceExtension->PortCapabilities;
1102 PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
1103 if (PortConfig->ScatterGather == FALSE ||
1104 PortConfig->NumberOfPhysicalBreaks >= (0x100000000LL >> PAGE_SHIFT) ||
1105 PortConfig->MaximumTransferLength < PortConfig->NumberOfPhysicalBreaks * PAGE_SIZE)
1106 {
1107 PortCapabilities->MaximumTransferLength =
1108 PortConfig->MaximumTransferLength;
1109 }
1110 else
1111 {
1112 PortCapabilities->MaximumTransferLength =
1113 PortConfig->NumberOfPhysicalBreaks * PAGE_SIZE;
1114 }
1115
1116 PortCapabilities->MaximumPhysicalPages =
1117 PortCapabilities->MaximumTransferLength / PAGE_SIZE;
1118 PortCapabilities->SupportedAsynchronousEvents = 0; /* FIXME */
1119 PortCapabilities->AlignmentMask =
1120 PortConfig->AlignmentMask;
1121 PortCapabilities->TaggedQueuing =
1122 PortConfig->TaggedQueuing;
1123 PortCapabilities->AdapterScansDown =
1124 PortConfig->AdapterScansDown;
1125 PortCapabilities->AdapterUsesPio = TRUE; /* FIXME */
1126
1127 /* Scan the adapter for devices */
1128 SpiScanAdapter (DeviceExtension);
1129
1130 /* Build the registry device map */
1131 SpiBuildDeviceMap (DeviceExtension,
1132 (PUNICODE_STRING)Argument2);
1133
1134 /* Create the dos device link */
1135 swprintf(DosNameBuffer,
1136 L"\\??\\Scsi%lu:",
1137 SystemConfig->ScsiPortCount);
1138 RtlInitUnicodeString(&DosDeviceName,
1139 DosNameBuffer);
1140 IoCreateSymbolicLink(&DosDeviceName,
1141 &DeviceName);
1142
1143 /* Update the system configuration info */
1144 if (PortConfig->AtdiskPrimaryClaimed == TRUE)
1145 SystemConfig->AtDiskPrimaryAddressClaimed = TRUE;
1146 if (PortConfig->AtdiskSecondaryClaimed == TRUE)
1147 SystemConfig->AtDiskSecondaryAddressClaimed = TRUE;
1148
1149 SystemConfig->ScsiPortCount++;
1150 PortDeviceObject = NULL;
1151 DeviceFound = TRUE;
1152 }
1153 else
1154 {
1155 DPRINT("HwFindAdapter() Result: %lu\n", Result);
1156
1157 ExFreePool (PortConfig);
1158 IoDeleteDevice (PortDeviceObject);
1159 PortDeviceObject = NULL;
1160 }
1161
1162 DPRINT("Bus: %lu MaxBus: %lu\n", BusNumber, MaxBus);
1163 if (BusNumber >= MaxBus)
1164 {
1165 DPRINT("Scanned all buses!\n");
1166 Status = STATUS_SUCCESS;
1167 goto ByeBye;
1168 }
1169
1170 if (Again == FALSE)
1171 {
1172 BusNumber++;
1173 SlotNumber.u.AsULONG = 0;
1174 }
1175 }
1176
1177 ByeBye:
1178 /* Clean up the mess */
1179 if (PortDeviceObject != NULL)
1180 {
1181 DPRINT("Delete device: %p\n", PortDeviceObject);
1182
1183 DeviceExtension = PortDeviceObject->DeviceExtension;
1184
1185 if (DeviceExtension->PortCapabilities != NULL)
1186 {
1187 IoDisconnectInterrupt (DeviceExtension->Interrupt);
1188 ExFreePool (DeviceExtension->PortCapabilities);
1189 }
1190
1191 if (DeviceExtension->PortConfig != NULL)
1192 {
1193 ExFreePool (DeviceExtension->PortConfig);
1194 }
1195
1196 IoDeleteDevice (PortDeviceObject);
1197 }
1198
1199 DPRINT("ScsiPortInitialize() done!\n");
1200
1201 return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS;
1202 }
1203
1204
1205 /*
1206 * @unimplemented
1207 */
1208 VOID STDCALL
1209 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
1210 IN PSCSI_REQUEST_BLOCK Srb,
1211 IN ULONG LogicalAddress,
1212 IN ULONG Length)
1213 {
1214 DPRINT1("ScsiPortIoMapTransfer()\n");
1215 UNIMPLEMENTED;
1216 }
1217
1218
1219 /*
1220 * @unimplemented
1221 */
1222 VOID STDCALL
1223 ScsiPortLogError(IN PVOID HwDeviceExtension,
1224 IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
1225 IN UCHAR PathId,
1226 IN UCHAR TargetId,
1227 IN UCHAR Lun,
1228 IN ULONG ErrorCode,
1229 IN ULONG UniqueId)
1230 {
1231 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1232
1233 DPRINT1("ScsiPortLogError() called\n");
1234 DPRINT1("Srb %x, PathId %d, TargetId %d, Lun %d, ErrorCode %x, UniqueId %x\n",
1235 Srb, PathId, TargetId, Lun, ErrorCode, UniqueId);
1236
1237 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1238 SCSI_PORT_DEVICE_EXTENSION,
1239 MiniPortDeviceExtension);
1240
1241
1242 DPRINT("ScsiPortLogError() done\n");
1243 }
1244
1245
1246 /*
1247 * @implemented
1248 */
1249 VOID STDCALL
1250 ScsiPortMoveMemory(OUT PVOID Destination,
1251 IN PVOID Source,
1252 IN ULONG Length)
1253 {
1254 RtlMoveMemory(Destination,
1255 Source,
1256 Length);
1257 }
1258
1259
1260 /*
1261 * @implemented
1262 */
1263 VOID
1264 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType,
1265 IN PVOID HwDeviceExtension,
1266 ...)
1267 {
1268 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1269 va_list ap;
1270
1271 DPRINT("ScsiPortNotification() called\n");
1272
1273 DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
1274 SCSI_PORT_DEVICE_EXTENSION,
1275 MiniPortDeviceExtension);
1276
1277 DPRINT("DeviceExtension %p\n", DeviceExtension);
1278
1279 va_start(ap, HwDeviceExtension);
1280
1281 switch (NotificationType)
1282 {
1283 case RequestComplete:
1284 {
1285 PSCSI_REQUEST_BLOCK Srb;
1286
1287 Srb = (PSCSI_REQUEST_BLOCK) va_arg (ap, PSCSI_REQUEST_BLOCK);
1288
1289 DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
1290 DeviceExtension->Flags |= IRP_FLAG_COMPLETE;
1291 Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
1292 }
1293 break;
1294
1295 case NextRequest:
1296 DPRINT("Notify: NextRequest\n");
1297 DeviceExtension->Flags |= IRP_FLAG_NEXT;
1298 break;
1299
1300 case NextLuRequest:
1301 {
1302 UCHAR PathId;
1303 UCHAR TargetId;
1304 UCHAR Lun;
1305 PSCSI_PORT_LUN_EXTENSION LunExtension;
1306
1307 PathId = (UCHAR) va_arg (ap, int);
1308 TargetId = (UCHAR) va_arg (ap, int);
1309 Lun = (UCHAR) va_arg (ap, int);
1310
1311 DPRINT ("Notify: NextLuRequest(PathId %u TargetId %u Lun %u)\n",
1312 PathId, TargetId, Lun);
1313
1314 LunExtension = SpiGetLunExtension(DeviceExtension,
1315 PathId,
1316 TargetId,
1317 Lun);
1318 if (LunExtension)
1319 {
1320 DeviceExtension->Flags |= IRP_FLAG_NEXT_LU;
1321 LunExtension->Flags |= IRP_FLAG_NEXT_LU;
1322 }
1323 }
1324 break;
1325
1326 case ResetDetected:
1327 DPRINT1("Notify: ResetDetected\n");
1328 /* FIXME: ??? */
1329 break;
1330
1331 default:
1332 DPRINT1 ("Unsupported notification %lu\n", NotificationType);
1333 break;
1334 }
1335 if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
1336 {
1337 IoRequestDpc(DeviceExtension->DeviceObject,
1338 NULL,
1339 DeviceExtension);
1340 }
1341 else
1342 {
1343 SpiProcessRequests(DeviceExtension, NULL);
1344 }
1345
1346 va_end(ap);
1347 }
1348
1349
1350 /*
1351 * @implemented
1352 */
1353 ULONG STDCALL
1354 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
1355 IN ULONG BusDataType,
1356 IN ULONG SystemIoBusNumber,
1357 IN ULONG SlotNumber,
1358 IN PVOID Buffer,
1359 IN ULONG Offset,
1360 IN ULONG Length)
1361 {
1362 DPRINT("ScsiPortSetBusDataByOffset()\n");
1363 return(HalSetBusDataByOffset(BusDataType,
1364 SystemIoBusNumber,
1365 SlotNumber,
1366 Buffer,
1367 Offset,
1368 Length));
1369 }
1370
1371
1372 /*
1373 * @implemented
1374 */
1375 BOOLEAN STDCALL
1376 ScsiPortValidateRange(IN PVOID HwDeviceExtension,
1377 IN INTERFACE_TYPE BusType,
1378 IN ULONG SystemIoBusNumber,
1379 IN SCSI_PHYSICAL_ADDRESS IoAddress,
1380 IN ULONG NumberOfBytes,
1381 IN BOOLEAN InIoSpace)
1382 {
1383 DPRINT("ScsiPortValidateRange()\n");
1384 return(TRUE);
1385 }
1386
1387
1388 /* INTERNAL FUNCTIONS ********************************************************/
1389
1390
1391 static BOOLEAN
1392 SpiGetPciConfigData (IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
1393 IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
1394 IN ULONG BusNumber,
1395 IN OUT PPCI_SLOT_NUMBER NextSlotNumber)
1396 {
1397 PCI_COMMON_CONFIG PciConfig;
1398 PCI_SLOT_NUMBER SlotNumber;
1399 ULONG DataSize;
1400 ULONG DeviceNumber;
1401 ULONG FunctionNumber;
1402 CHAR VendorIdString[8];
1403 CHAR DeviceIdString[8];
1404 ULONG i;
1405 ULONG RangeLength;
1406
1407 DPRINT ("SpiGetPciConfiguration() called\n");
1408
1409 if (NextSlotNumber->u.bits.FunctionNumber >= PCI_MAX_FUNCTION)
1410 {
1411 NextSlotNumber->u.bits.FunctionNumber = 0;
1412 NextSlotNumber->u.bits.DeviceNumber++;
1413 }
1414
1415 if (NextSlotNumber->u.bits.DeviceNumber >= PCI_MAX_DEVICES)
1416 {
1417 NextSlotNumber->u.bits.DeviceNumber = 0;
1418 return FALSE;
1419 }
1420
1421 for (DeviceNumber = NextSlotNumber->u.bits.DeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
1422 {
1423 SlotNumber.u.bits.DeviceNumber = DeviceNumber;
1424
1425 for (FunctionNumber = NextSlotNumber->u.bits.FunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
1426 {
1427 SlotNumber.u.bits.FunctionNumber = FunctionNumber;
1428
1429 DataSize = HalGetBusData (PCIConfiguration,
1430 BusNumber,
1431 SlotNumber.u.AsULONG,
1432 &PciConfig,
1433 PCI_COMMON_HDR_LENGTH);
1434 if (DataSize != PCI_COMMON_HDR_LENGTH)
1435 {
1436 if (FunctionNumber == 0)
1437 {
1438 break;
1439 }
1440 else
1441 {
1442 continue;
1443 }
1444 }
1445
1446 sprintf (VendorIdString, "%04hx", PciConfig.VendorID);
1447 sprintf (DeviceIdString, "%04hx", PciConfig.DeviceID);
1448
1449 if (!_strnicmp(VendorIdString, HwInitializationData->VendorId, HwInitializationData->VendorIdLength) &&
1450 !_strnicmp(DeviceIdString, HwInitializationData->DeviceId, HwInitializationData->DeviceIdLength))
1451 {
1452 DPRINT ("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1453 PciConfig.VendorID,
1454 PciConfig.DeviceID,
1455 BusNumber,
1456 SlotNumber.u.bits.DeviceNumber,
1457 SlotNumber.u.bits.FunctionNumber);
1458
1459 PortConfig->BusInterruptLevel =
1460 PortConfig->BusInterruptVector = PciConfig.u.type0.InterruptLine;
1461 PortConfig->SlotNumber = SlotNumber.u.AsULONG;
1462
1463 /* Initialize access ranges */
1464 if (PortConfig->NumberOfAccessRanges > 0)
1465 {
1466 if (PortConfig->NumberOfAccessRanges > PCI_TYPE0_ADDRESSES)
1467 PortConfig->NumberOfAccessRanges = PCI_TYPE0_ADDRESSES;
1468
1469 for (i = 0; i < PortConfig->NumberOfAccessRanges; i++)
1470 {
1471 (*PortConfig->AccessRanges)[i].RangeStart.QuadPart =
1472 PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_ADDRESS_MASK;
1473 if ((*PortConfig->AccessRanges)[i].RangeStart.QuadPart != 0)
1474 {
1475 RangeLength = (ULONG)-1;
1476 HalSetBusDataByOffset (PCIConfiguration,
1477 BusNumber,
1478 SlotNumber.u.AsULONG,
1479 (PVOID)&RangeLength,
1480 0x10 + (i * sizeof(ULONG)),
1481 sizeof(ULONG));
1482
1483 HalGetBusDataByOffset (PCIConfiguration,
1484 BusNumber,
1485 SlotNumber.u.AsULONG,
1486 (PVOID)&RangeLength,
1487 0x10 + (i * sizeof(ULONG)),
1488 sizeof(ULONG));
1489
1490 HalSetBusDataByOffset (PCIConfiguration,
1491 BusNumber,
1492 SlotNumber.u.AsULONG,
1493 (PVOID)&PciConfig.u.type0.BaseAddresses[i],
1494 0x10 + (i * sizeof(ULONG)),
1495 sizeof(ULONG));
1496 if (RangeLength != 0)
1497 {
1498 (*PortConfig->AccessRanges)[i].RangeLength =
1499 -(RangeLength & PCI_ADDRESS_IO_ADDRESS_MASK);
1500 (*PortConfig->AccessRanges)[i].RangeInMemory =
1501 !(PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_SPACE);
1502
1503 DPRINT("RangeStart 0x%lX RangeLength 0x%lX RangeInMemory %s\n",
1504 PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_ADDRESS_MASK,
1505 -(RangeLength & PCI_ADDRESS_IO_ADDRESS_MASK),
1506 (PciConfig.u.type0.BaseAddresses[i] & PCI_ADDRESS_IO_SPACE)?"FALSE":"TRUE");
1507 }
1508 }
1509 }
1510 }
1511
1512 NextSlotNumber->u.bits.DeviceNumber = DeviceNumber;
1513 NextSlotNumber->u.bits.FunctionNumber = FunctionNumber;
1514
1515 PortConfig->SlotNumber = NextSlotNumber->u.AsULONG;
1516
1517 NextSlotNumber->u.bits.FunctionNumber += 1;
1518
1519 return TRUE;
1520 }
1521
1522
1523 if (FunctionNumber == 0 && !(PciConfig.HeaderType & PCI_MULTIFUNCTION))
1524 {
1525 break;
1526 }
1527 }
1528 NextSlotNumber->u.bits.FunctionNumber = 0;
1529 }
1530
1531 DPRINT ("No device found\n");
1532
1533 return FALSE;
1534 }
1535
1536
1537
1538 /**********************************************************************
1539 * NAME INTERNAL
1540 * ScsiPortCreateClose
1541 *
1542 * DESCRIPTION
1543 * Answer requests for Create/Close calls: a null operation.
1544 *
1545 * RUN LEVEL
1546 * PASSIVE_LEVEL
1547 *
1548 * ARGUMENTS
1549 * DeviceObject
1550 * Pointer to a device object.
1551 *
1552 * Irp
1553 * Pointer to an IRP.
1554 *
1555 * RETURN VALUE
1556 * Status.
1557 */
1558
1559 static NTSTATUS STDCALL
1560 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
1561 IN PIRP Irp)
1562 {
1563 DPRINT("ScsiPortCreateClose()\n");
1564
1565 Irp->IoStatus.Status = STATUS_SUCCESS;
1566 Irp->IoStatus.Information = FILE_OPENED;
1567
1568 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1569
1570 return(STATUS_SUCCESS);
1571 }
1572
1573
1574 /**********************************************************************
1575 * NAME INTERNAL
1576 * ScsiPortDispatchScsi
1577 *
1578 * DESCRIPTION
1579 * Answer requests for SCSI calls
1580 *
1581 * RUN LEVEL
1582 * PASSIVE_LEVEL
1583 *
1584 * ARGUMENTS
1585 * Standard dispatch arguments
1586 *
1587 * RETURNS
1588 * NTSTATUS
1589 */
1590
1591 static NTSTATUS STDCALL
1592 ScsiPortDispatchScsi(IN PDEVICE_OBJECT DeviceObject,
1593 IN PIRP Irp)
1594 {
1595 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1596 PSCSI_PORT_LUN_EXTENSION LunExtension;
1597 PIO_STACK_LOCATION Stack;
1598 PSCSI_REQUEST_BLOCK Srb;
1599 NTSTATUS Status = STATUS_SUCCESS;
1600 ULONG DataSize = 0;
1601
1602 DPRINT("ScsiPortDispatchScsi(DeviceObject %p Irp %p)\n",
1603 DeviceObject, Irp);
1604
1605 DeviceExtension = DeviceObject->DeviceExtension;
1606 Stack = IoGetCurrentIrpStackLocation(Irp);
1607
1608 Srb = Stack->Parameters.Scsi.Srb;
1609 if (Srb == NULL)
1610 {
1611 Status = STATUS_UNSUCCESSFUL;
1612
1613 Irp->IoStatus.Status = Status;
1614 Irp->IoStatus.Information = 0;
1615
1616 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1617
1618 return(Status);
1619 }
1620
1621 DPRINT("Srb: %p\n", Srb);
1622 DPRINT("Srb->Function: %lu\n", Srb->Function);
1623 DPRINT("PathId: %lu TargetId: %lu Lun: %lu\n", Srb->PathId, Srb->TargetId, Srb->Lun);
1624
1625 LunExtension = SpiGetLunExtension(DeviceExtension,
1626 Srb->PathId,
1627 Srb->TargetId,
1628 Srb->Lun);
1629 if (LunExtension == NULL)
1630 {
1631 Status = STATUS_NO_SUCH_DEVICE;
1632
1633 Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
1634 Irp->IoStatus.Status = Status;
1635 Irp->IoStatus.Information = 0;
1636
1637 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1638
1639 return(Status);
1640 }
1641
1642 switch (Srb->Function)
1643 {
1644 case SRB_FUNCTION_EXECUTE_SCSI:
1645 case SRB_FUNCTION_IO_CONTROL:
1646 IoMarkIrpPending(Irp);
1647 Srb->OriginalRequest = LunExtension;
1648 Irp->Tail.Overlay.DriverContext[3] = Srb;
1649 SpiProcessRequests(DeviceExtension, Irp);
1650 return(STATUS_PENDING);
1651
1652 case SRB_FUNCTION_SHUTDOWN:
1653 case SRB_FUNCTION_FLUSH:
1654 if (DeviceExtension->PortConfig->CachesData == TRUE)
1655 {
1656 IoMarkIrpPending(Irp);
1657 Srb->OriginalRequest = LunExtension;
1658 Irp->Tail.Overlay.DriverContext[3] = Srb;
1659 SpiProcessRequests(DeviceExtension, Irp);
1660 return(STATUS_PENDING);
1661 }
1662 break;
1663
1664 case SRB_FUNCTION_CLAIM_DEVICE:
1665 DPRINT (" SRB_FUNCTION_CLAIM_DEVICE\n");
1666
1667 /* Reference device object and keep the device object */
1668 ObReferenceObject(DeviceObject);
1669 LunExtension->DeviceObject = DeviceObject;
1670 LunExtension->DeviceClaimed = TRUE;
1671 Srb->DataBuffer = DeviceObject;
1672 break;
1673
1674 case SRB_FUNCTION_RELEASE_DEVICE:
1675 DPRINT (" SRB_FUNCTION_RELEASE_DEVICE\n");
1676 DPRINT ("PathId: %lu TargetId: %lu Lun: %lu\n",
1677 Srb->PathId, Srb->TargetId, Srb->Lun);
1678
1679 /* Dereference device object and clear the device object */
1680 ObDereferenceObject(LunExtension->DeviceObject);
1681 LunExtension->DeviceObject = NULL;
1682 LunExtension->DeviceClaimed = FALSE;
1683 break;
1684
1685 default:
1686 DPRINT1("SRB function not implemented (Function %lu)\n", Srb->Function);
1687 Status = STATUS_NOT_IMPLEMENTED;
1688 break;
1689 }
1690
1691 Irp->IoStatus.Status = Status;
1692 Irp->IoStatus.Information = DataSize;
1693
1694 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1695
1696 return(Status);
1697 }
1698
1699
1700 /**********************************************************************
1701 * NAME INTERNAL
1702 * ScsiPortDeviceControl
1703 *
1704 * DESCRIPTION
1705 * Answer requests for device control calls
1706 *
1707 * RUN LEVEL
1708 * PASSIVE_LEVEL
1709 *
1710 * ARGUMENTS
1711 * Standard dispatch arguments
1712 *
1713 * RETURNS
1714 * NTSTATUS
1715 */
1716
1717 static NTSTATUS STDCALL
1718 ScsiPortDeviceControl(IN PDEVICE_OBJECT DeviceObject,
1719 IN PIRP Irp)
1720 {
1721 PIO_STACK_LOCATION Stack;
1722 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1723 NTSTATUS Status = STATUS_SUCCESS;
1724
1725 DPRINT("ScsiPortDeviceControl()\n");
1726
1727 Irp->IoStatus.Information = 0;
1728
1729
1730 Stack = IoGetCurrentIrpStackLocation(Irp);
1731 DeviceExtension = DeviceObject->DeviceExtension;
1732
1733 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
1734 {
1735 case IOCTL_SCSI_GET_DUMP_POINTERS:
1736 {
1737 PDUMP_POINTERS DumpPointers;
1738 DPRINT(" IOCTL_SCSI_GET_DUMP_POINTERS\n");
1739 DumpPointers = (PDUMP_POINTERS)Irp->AssociatedIrp.SystemBuffer;
1740 DumpPointers->DeviceObject = DeviceObject;
1741
1742 Irp->IoStatus.Information = sizeof(DUMP_POINTERS);
1743 }
1744 break;
1745
1746 case IOCTL_SCSI_GET_CAPABILITIES:
1747 {
1748 DPRINT(" IOCTL_SCSI_GET_CAPABILITIES\n");
1749
1750 *((PIO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer) =
1751 DeviceExtension->PortCapabilities;
1752
1753 Irp->IoStatus.Information = sizeof(PIO_SCSI_CAPABILITIES);
1754 }
1755 break;
1756
1757 case IOCTL_SCSI_GET_INQUIRY_DATA:
1758 {
1759 DPRINT(" IOCTL_SCSI_GET_INQUIRY_DATA\n");
1760
1761 /* Copy inquiry data to the port device extension */
1762 Irp->IoStatus.Information =
1763 SpiGetInquiryData(DeviceExtension,
1764 Irp->AssociatedIrp.SystemBuffer);
1765 DPRINT("Inquiry data size: %lu\n", Irp->IoStatus.Information);
1766 }
1767 break;
1768
1769 case IOCTL_SCSI_PASS_THROUGH:
1770 DPRINT(" IOCTL_SCSI_PASS_THROUGH\n");
1771 Status = STATUS_NOT_IMPLEMENTED;
1772 break;
1773
1774 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
1775 DPRINT(" IOCTL_SCSI_PASS_THROUGH_DIRECT\n");
1776 Status = STATUS_NOT_IMPLEMENTED;
1777 break;
1778
1779 case IOCTL_SCSI_MINIPORT:
1780 DPRINT(" IOCTL_SCSI_MINIPORT\n");
1781 DPRINT(" Signature: %.8s\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->Signature);
1782 DPRINT(" ControlCode: 0x%lX\n", ((PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer)->ControlCode);
1783 return SpiScsiMiniport(DeviceObject, Irp);
1784
1785 default:
1786 DPRINT1(" unknown ioctl code: 0x%lX\n",
1787 Stack->Parameters.DeviceIoControl.IoControlCode);
1788 Status = STATUS_INVALID_DEVICE_REQUEST;
1789 break;
1790 }
1791
1792 Irp->IoStatus.Status = Status;
1793 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1794
1795 return Status;
1796 }
1797
1798 static NTSTATUS STDCALL
1799 SpiCompletion(IN PDEVICE_OBJECT DeviceObject,
1800 IN PIRP Irp,
1801 IN PVOID Context)
1802 {
1803 PSCSI_REQUEST_BLOCK Srb;
1804
1805 DPRINT("SpiCompletion(DeviceObject %x, Irp %x, Context %x)\n",
1806 DeviceObject, Irp, Context);
1807
1808 Srb = (PSCSI_REQUEST_BLOCK)Context;
1809 Irp->IoStatus.Information = 0;
1810
1811 switch (SRB_STATUS(Srb->SrbStatus))
1812 {
1813 case SRB_STATUS_SUCCESS:
1814 Irp->IoStatus.Status = STATUS_SUCCESS;
1815 Irp->IoStatus.Information = Srb->DataTransferLength;
1816 break;
1817
1818 case SRB_STATUS_INVALID_PATH_ID:
1819 case SRB_STATUS_INVALID_TARGET_ID:
1820 case SRB_STATUS_INVALID_LUN:
1821 case SRB_STATUS_NO_HBA:
1822 Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
1823 break;
1824
1825 case SRB_STATUS_NO_DEVICE:
1826 Irp->IoStatus.Status = STATUS_DEVICE_NOT_CONNECTED;
1827 break;
1828
1829 case SRB_STATUS_BUSY:
1830 Irp->IoStatus.Status = STATUS_DEVICE_BUSY;
1831 break;
1832
1833 case SRB_STATUS_DATA_OVERRUN:
1834 Irp->IoStatus.Status = STATUS_DATA_OVERRUN;
1835 Irp->IoStatus.Information = Srb->DataTransferLength;
1836 break;
1837
1838 case SRB_STATUS_INVALID_REQUEST:
1839 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
1840 break;
1841
1842 default:
1843 Irp->IoStatus.Status = STATUS_IO_DEVICE_ERROR;
1844 break;
1845 }
1846
1847 ExFreePool(Srb);
1848
1849 if (Irp->PendingReturned)
1850 {
1851 IoMarkIrpPending (Irp);
1852 }
1853 return Irp->IoStatus.Status;
1854 }
1855
1856 static NTSTATUS
1857 SpiScsiMiniport(IN PDEVICE_OBJECT DeviceObject,
1858 IN PIRP Irp)
1859 {
1860 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1861 PSRB_IO_CONTROL SrbIoControl;
1862 PIO_STACK_LOCATION IrpStack;
1863 PSCSI_REQUEST_BLOCK Srb;
1864 PSCSI_PORT_LUN_EXTENSION LunExtension;
1865
1866 DPRINT("SpiScsiMiniport(DeviceObject %x, Irp %x)\n",
1867 DeviceObject, Irp);
1868
1869 DeviceExtension = DeviceObject->DeviceExtension;
1870 SrbIoControl = (PSRB_IO_CONTROL)Irp->AssociatedIrp.SystemBuffer;
1871
1872 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1873 if (IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SRB_IO_CONTROL))
1874 {
1875 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
1876 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1877 return STATUS_INVALID_PARAMETER;
1878 }
1879 if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SRB_IO_CONTROL) + SrbIoControl->Length)
1880 {
1881 Irp->IoStatus.Information = sizeof(SRB_IO_CONTROL) + SrbIoControl->Length;
1882 Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
1883 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1884 return STATUS_BUFFER_TOO_SMALL;
1885 }
1886 if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
1887 {
1888 Irp->IoStatus.Status = STATUS_NO_SUCH_DEVICE;
1889 Irp->IoStatus.Information = 0;
1890 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1891 return STATUS_NO_SUCH_DEVICE;
1892 }
1893
1894 Srb = ExAllocatePool(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK));
1895 if (Srb == NULL)
1896 {
1897 Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
1898 IoCompleteRequest(Irp, IO_NO_INCREMENT);
1899 return STATUS_INSUFFICIENT_RESOURCES;
1900 }
1901 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
1902 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
1903 Srb->OriginalRequest = Irp;
1904 Srb->Function = SRB_FUNCTION_IO_CONTROL;
1905 Srb->DataBuffer = (PVOID)SrbIoControl;
1906 Srb->DataTransferLength = sizeof(SRB_IO_CONTROL) + SrbIoControl->Length;
1907
1908 /* We using the first extension from the list. The miniport driver is responsible to find the correct device. */
1909 LunExtension = CONTAINING_RECORD(DeviceExtension->LunExtensionListHead.Flink,
1910 SCSI_PORT_LUN_EXTENSION,
1911 List);
1912 Srb->PathId = LunExtension->PathId;
1913 Srb->TargetId = LunExtension->TargetId;
1914 Srb->Lun = LunExtension->Lun;
1915
1916 IrpStack = IoGetNextIrpStackLocation(Irp);
1917
1918 IrpStack->MajorFunction = IRP_MJ_SCSI;
1919 IrpStack->Parameters.Scsi.Srb = Srb;
1920
1921 IoSetCompletionRoutine(Irp,
1922 SpiCompletion,
1923 Srb,
1924 TRUE,
1925 TRUE,
1926 TRUE);
1927
1928 return IoCallDriver(DeviceObject, Irp);
1929 }
1930
1931 static VOID
1932 SpiAllocateSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1933 PSCSI_REQUEST_BLOCK Srb)
1934 {
1935 ULONG index;
1936
1937 DPRINT("SpiAllocateSrbExtension\n");
1938
1939 DPRINT("DeviceExtension->VirtualAddress %x, DeviceExtension->SrbExtensionSize %x\n",
1940 DeviceExtension->VirtualAddress, DeviceExtension->SrbExtensionSize);
1941
1942 Srb->SrbExtension = NULL;
1943 if (DeviceExtension->VirtualAddress != NULL &&
1944 DeviceExtension->SrbExtensionSize > 0)
1945 {
1946 index = RtlFindClearBitsAndSet(&DeviceExtension->SrbExtensionAllocMap, 1, 0);
1947 if (index != 0xffffffff)
1948 {
1949 DeviceExtension->CurrentSrbExtensions++;
1950 Srb->SrbExtension = (PVOID)((ULONG_PTR)DeviceExtension->VirtualAddress + index * DeviceExtension->SrbExtensionSize);
1951 }
1952 }
1953 DPRINT("%x\n", Srb->SrbExtension);
1954 }
1955
1956 static VOID
1957 SpiFreeSrbExtension(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1958 PSCSI_REQUEST_BLOCK Srb)
1959 {
1960 ULONG index;
1961
1962 if (DeviceExtension->VirtualAddress != NULL &&
1963 DeviceExtension->SrbExtensionSize > 0 &&
1964 Srb->SrbExtension != NULL)
1965 {
1966 index = ((ULONG_PTR)Srb->SrbExtension - (ULONG_PTR)DeviceExtension->VirtualAddress) / DeviceExtension->SrbExtensionSize;
1967 RtlClearBits(&DeviceExtension->SrbExtensionAllocMap, index, 1);
1968 DeviceExtension->CurrentSrbExtensions--;
1969 }
1970 Srb->SrbExtension = NULL;
1971 }
1972
1973
1974 static BOOLEAN STDCALL
1975 ScsiPortStartPacket(IN OUT PVOID Context)
1976 {
1977 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1978 PSCSI_REQUEST_BLOCK Srb;
1979 PIRP Irp;
1980 PIO_STACK_LOCATION IrpStack;
1981
1982 DPRINT("ScsiPortStartPacket(Context %x) called\n", Context);
1983
1984 Srb = (PSCSI_REQUEST_BLOCK)Context;
1985 Irp = (PIRP)Srb->OriginalRequest;
1986 IrpStack = IoGetCurrentIrpStackLocation(Irp);
1987 DeviceExtension = IrpStack->DeviceObject->DeviceExtension;
1988
1989 return(DeviceExtension->HwStartIo(&DeviceExtension->MiniPortDeviceExtension,
1990 Srb));
1991 }
1992
1993
1994 static PSCSI_PORT_LUN_EXTENSION
1995 SpiAllocateLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1996 IN UCHAR PathId,
1997 IN UCHAR TargetId,
1998 IN UCHAR Lun)
1999 {
2000 PSCSI_PORT_LUN_EXTENSION LunExtension;
2001 ULONG LunExtensionSize;
2002
2003 DPRINT("SpiAllocateLunExtension (%p %u %u %u)\n",
2004 DeviceExtension, PathId, TargetId, Lun);
2005
2006 LunExtensionSize =
2007 sizeof(SCSI_PORT_LUN_EXTENSION) + DeviceExtension->LunExtensionSize;
2008 DPRINT("LunExtensionSize %lu\n", LunExtensionSize);
2009
2010 LunExtension = ExAllocatePool(NonPagedPool,
2011 LunExtensionSize);
2012 if (LunExtension == NULL)
2013 {
2014 return NULL;
2015 }
2016
2017 RtlZeroMemory(LunExtension,
2018 LunExtensionSize);
2019
2020 InsertTailList(&DeviceExtension->LunExtensionListHead,
2021 &LunExtension->List);
2022
2023 LunExtension->PathId = PathId;
2024 LunExtension->TargetId = TargetId;
2025 LunExtension->Lun = Lun;
2026
2027 LunExtension->PendingIrpCount = 0;
2028 LunExtension->ActiveIrpCount = 0;
2029
2030 LunExtension->NextIrp = NULL;
2031
2032 return LunExtension;
2033 }
2034
2035
2036 static VOID
2037 SpiRemoveLunExtension (IN PSCSI_PORT_LUN_EXTENSION LunExtension)
2038 {
2039 DPRINT("SpiRemoveLunExtension(%p) called\n",
2040 LunExtension);
2041
2042 if (LunExtension == NULL)
2043 return;
2044
2045 RemoveEntryList (&LunExtension->List);
2046
2047
2048 /* Release LUN extersion data */
2049
2050
2051 ExFreePool (LunExtension);
2052
2053 return;
2054 }
2055
2056
2057 static PSCSI_PORT_LUN_EXTENSION
2058 SpiGetLunExtension (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2059 IN UCHAR PathId,
2060 IN UCHAR TargetId,
2061 IN UCHAR Lun)
2062 {
2063 PSCSI_PORT_LUN_EXTENSION LunExtension;
2064 PLIST_ENTRY Entry;
2065
2066 DPRINT("SpiGetLunExtension(%p %u %u %u) called\n",
2067 DeviceExtension, PathId, TargetId, Lun);
2068
2069 if (IsListEmpty(&DeviceExtension->LunExtensionListHead))
2070 return NULL;
2071
2072 Entry = DeviceExtension->LunExtensionListHead.Flink;
2073 while (Entry != &DeviceExtension->LunExtensionListHead)
2074 {
2075 LunExtension = CONTAINING_RECORD(Entry,
2076 SCSI_PORT_LUN_EXTENSION,
2077 List);
2078 if (LunExtension->PathId == PathId &&
2079 LunExtension->TargetId == TargetId &&
2080 LunExtension->Lun == Lun)
2081 {
2082 return LunExtension;
2083 }
2084
2085 Entry = Entry->Flink;
2086 }
2087
2088 return NULL;
2089 }
2090
2091
2092 static NTSTATUS
2093 SpiSendInquiry (IN PDEVICE_OBJECT DeviceObject,
2094 IN OUT PSCSI_REQUEST_BLOCK Srb,
2095 IN OUT PIO_STATUS_BLOCK IoStatusBlock,
2096 IN OUT PKEVENT Event)
2097 {
2098 PIO_STACK_LOCATION IrpStack;
2099 PIRP Irp;
2100 NTSTATUS Status;
2101
2102 DPRINT ("SpiSendInquiry() called\n");
2103
2104
2105 KeInitializeEvent (Event,
2106 NotificationEvent,
2107 FALSE);
2108
2109 Irp = IoBuildDeviceIoControlRequest (IOCTL_SCSI_EXECUTE_OUT,
2110 DeviceObject,
2111 NULL,
2112 0,
2113 Srb->DataBuffer,
2114 Srb->DataTransferLength,
2115 TRUE,
2116 Event,
2117 IoStatusBlock);
2118 if (Irp == NULL)
2119 {
2120 DPRINT("IoBuildDeviceIoControlRequest() failed\n");
2121 return STATUS_INSUFFICIENT_RESOURCES;
2122 }
2123
2124 /* Attach Srb to the Irp */
2125 IrpStack = IoGetNextIrpStackLocation (Irp);
2126 IrpStack->Parameters.Scsi.Srb = Srb;
2127 Srb->OriginalRequest = Irp;
2128
2129 /* Call the driver */
2130 Status = IoCallDriver (DeviceObject,
2131 Irp);
2132
2133 return Status;
2134 }
2135
2136 static VOID
2137 SpiScanAdapter (IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
2138 {
2139 PSCSI_REQUEST_BLOCK Srb;
2140 PCDB Cdb;
2141 ULONG Bus;
2142 ULONG Target;
2143 PSCSI_PORT_SCAN_ADAPTER ScanDataArray;
2144 PSCSI_PORT_SCAN_ADAPTER ScanData;
2145 ULONG i;
2146 ULONG MaxCount;
2147 ULONG WaitCount;
2148 ULONG ActiveCount;
2149 PVOID* EventArray;
2150 PKWAIT_BLOCK WaitBlockArray;
2151
2152 DPRINT ("SpiScanAdapter() called\n");
2153
2154 MaxCount = DeviceExtension->PortConfig->NumberOfBuses *
2155 DeviceExtension->PortConfig->MaximumNumberOfTargets;
2156
2157 ScanDataArray = ExAllocatePool(NonPagedPool, MaxCount * (sizeof(SCSI_PORT_SCAN_ADAPTER) + sizeof(PVOID) + sizeof(KWAIT_BLOCK)));
2158 if (ScanDataArray == NULL)
2159 {
2160 return;
2161 }
2162 EventArray = (PVOID*)((PUCHAR)ScanDataArray + MaxCount * sizeof(SCSI_PORT_SCAN_ADAPTER));
2163 WaitBlockArray = (PKWAIT_BLOCK)((PUCHAR)EventArray + MaxCount * sizeof(PVOID));
2164
2165 for (Bus = 0; Bus < DeviceExtension->PortConfig->NumberOfBuses; Bus++)
2166 {
2167 for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
2168 {
2169 ScanData = &ScanDataArray[Bus * DeviceExtension->PortConfig->MaximumNumberOfTargets + Target];
2170 ScanData->Bus = Bus;
2171 ScanData->Target = Target;
2172 ScanData->Lun = 0;
2173 ScanData->Active = FALSE;
2174 }
2175 }
2176 do
2177 {
2178 ActiveCount = 0;
2179 WaitCount = 0;
2180 for (i = 0; i < MaxCount; i++)
2181 {
2182 ScanData = &ScanDataArray[i];
2183 Srb = &ScanData->Srb;
2184 if (ScanData->Active)
2185 {
2186 if (ScanData->Status == STATUS_PENDING &&
2187 0 == KeReadStateEvent(&ScanData->Event))
2188 {
2189 ActiveCount++;
2190 continue;
2191 }
2192 else
2193 {
2194 ScanData->Status = ScanData->IoStatusBlock.Status;
2195 }
2196 ScanData->Active = FALSE;
2197 DPRINT ("Target %lu Lun %lu\n", ScanData->Target, ScanData->Lun);
2198 DPRINT ("Status %lx Srb.SrbStatus %x\n", ScanData->Status, Srb->SrbStatus);
2199 DPRINT ("DeviceTypeQualifier %x\n", ((PINQUIRYDATA)Srb->DataBuffer)->DeviceTypeQualifier);
2200
2201 if (NT_SUCCESS(ScanData->Status) &&
2202 (Srb->SrbStatus == SRB_STATUS_SUCCESS ||
2203 (Srb->SrbStatus == SRB_STATUS_DATA_OVERRUN &&
2204 /*
2205 * FIXME:
2206 * The NT 4.0 driver from an inic950 based scsi controller
2207 * returns only 4 byte of inquiry data, but the device name
2208 * is visible on NT 4.0. We must implement an other way
2209 * to get the complete inquiry data.
2210 */
2211 Srb->DataTransferLength >= /*INQUIRYDATABUFFERSIZE*/4)) &&
2212 ((PINQUIRYDATA)Srb->DataBuffer)->DeviceTypeQualifier == 0)
2213 {
2214 /* Copy inquiry data */
2215 RtlCopyMemory (&ScanData->LunExtension->InquiryData,
2216 Srb->DataBuffer,
2217 min(sizeof(INQUIRYDATA), Srb->DataTransferLength));
2218 ScanData->Lun++;
2219 }
2220 else
2221 {
2222 SpiRemoveLunExtension (ScanData->LunExtension);
2223 ScanData->Lun = SCSI_MAXIMUM_LOGICAL_UNITS;
2224 }
2225 }
2226 if (ScanData->Lun >= SCSI_MAXIMUM_LOGICAL_UNITS)
2227 {
2228 continue;
2229 }
2230 RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
2231 Srb->SrbFlags = SRB_FLAGS_DATA_IN;
2232 Srb->DataBuffer = ScanData->DataBuffer;
2233 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
2234 Srb->DataTransferLength = 255; //256;
2235 Srb->CdbLength = 6;
2236 Srb->Lun = ScanData->Lun;
2237 Srb->PathId = ScanData->Bus;
2238 Srb->TargetId = ScanData->Target;
2239 Srb->SrbStatus = SRB_STATUS_SUCCESS;
2240 Srb->TimeOutValue = 2;
2241 Cdb = (PCDB) &Srb->Cdb;
2242
2243 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
2244 Cdb->CDB6INQUIRY.AllocationLength = 255;
2245 Cdb->CDB6INQUIRY.LogicalUnitNumber = ScanData->Lun;
2246
2247 RtlZeroMemory(Srb->DataBuffer, 256);
2248
2249 ScanData->LunExtension = SpiAllocateLunExtension (DeviceExtension,
2250 ScanData->Bus,
2251 ScanData->Target,
2252 ScanData->Lun);
2253 if (ScanData->LunExtension == NULL)
2254 {
2255 DPRINT1("Failed to allocate the LUN extension!\n");
2256 ScanData->Lun = SCSI_MAXIMUM_LOGICAL_UNITS;
2257 continue;
2258 }
2259 ScanData->Status = SpiSendInquiry (DeviceExtension->DeviceObject,
2260 Srb,
2261 &ScanData->IoStatusBlock,
2262 &ScanData->Event);
2263 ScanData->Active = TRUE;
2264 ActiveCount++;
2265 if (ScanData->Status == STATUS_PENDING)
2266 {
2267 EventArray[WaitCount] = &ScanData->Event;
2268 WaitCount++;
2269 }
2270 }
2271 if (WaitCount > 0 && WaitCount == ActiveCount)
2272 {
2273 KeWaitForMultipleObjects(WaitCount,
2274 EventArray,
2275 WaitAny,
2276 Executive,
2277 KernelMode,
2278 FALSE,
2279 NULL,
2280 WaitBlockArray);
2281 }
2282 }
2283 while (ActiveCount > 0);
2284
2285 ExFreePool(ScanDataArray);
2286
2287 DPRINT ("SpiScanAdapter() done\n");
2288 }
2289
2290
2291 static ULONG
2292 SpiGetInquiryData(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2293 OUT PSCSI_ADAPTER_BUS_INFO AdapterBusInfo)
2294 {
2295 PSCSI_PORT_LUN_EXTENSION LunExtension;
2296 PSCSI_INQUIRY_DATA UnitInfo, PrevUnit;
2297 ULONG Bus;
2298 ULONG Target;
2299 ULONG Lun;
2300 ULONG UnitCount;
2301
2302 DPRINT("SpiGetInquiryData() called\n");
2303
2304 /* Copy inquiry data to the port device extension */
2305 AdapterBusInfo->NumberOfBuses = DeviceExtension->PortConfig->NumberOfBuses;
2306
2307 UnitInfo = (PSCSI_INQUIRY_DATA)
2308 ((PUCHAR)AdapterBusInfo + sizeof(SCSI_ADAPTER_BUS_INFO) +
2309 (sizeof(SCSI_BUS_DATA) * (AdapterBusInfo->NumberOfBuses - 1)));
2310
2311 for (Bus = 0; Bus < AdapterBusInfo->NumberOfBuses; Bus++)
2312 {
2313 AdapterBusInfo->BusData[Bus].InitiatorBusId =
2314 DeviceExtension->PortConfig->InitiatorBusId[Bus];
2315 AdapterBusInfo->BusData[Bus].InquiryDataOffset =
2316 (ULONG)((PUCHAR)UnitInfo - (PUCHAR)AdapterBusInfo);
2317
2318 PrevUnit = NULL;
2319 UnitCount = 0;
2320
2321 for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
2322 {
2323 for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
2324 {
2325 LunExtension = SpiGetLunExtension(DeviceExtension,
2326 Bus,
2327 Target,
2328 Lun);
2329 if (LunExtension != NULL)
2330 {
2331 DPRINT("(Bus %lu Target %lu Lun %lu)\n",
2332 Bus, Target, Lun);
2333 RtlZeroMemory(UnitInfo, sizeof(*UnitInfo));
2334 UnitInfo->PathId = Bus;
2335 UnitInfo->TargetId = Target;
2336 UnitInfo->Lun = Lun;
2337 UnitInfo->InquiryDataLength = INQUIRYDATABUFFERSIZE;
2338 RtlCopyMemory (&UnitInfo->InquiryData,
2339 &LunExtension->InquiryData,
2340 INQUIRYDATABUFFERSIZE);
2341 if (PrevUnit != NULL)
2342 {
2343 PrevUnit->NextInquiryDataOffset =
2344 (ULONG)((ULONG_PTR)UnitInfo-(ULONG_PTR)AdapterBusInfo);
2345 }
2346 PrevUnit = UnitInfo;
2347 UnitInfo = (PSCSI_INQUIRY_DATA)((PUCHAR)UnitInfo + sizeof(SCSI_INQUIRY_DATA)+INQUIRYDATABUFFERSIZE-1);
2348 UnitCount++;
2349 }
2350 }
2351 }
2352 DPRINT("UnitCount: %lu\n", UnitCount);
2353 AdapterBusInfo->BusData[Bus].NumberOfLogicalUnits = UnitCount;
2354 if (UnitCount == 0)
2355 {
2356 AdapterBusInfo->BusData[Bus].InquiryDataOffset = 0;
2357 }
2358 }
2359
2360 DPRINT("Data size: %lu\n", (ULONG)UnitInfo - (ULONG)AdapterBusInfo);
2361
2362 return (ULONG)((PUCHAR)UnitInfo-(PUCHAR)AdapterBusInfo);
2363 }
2364
2365
2366 static BOOLEAN STDCALL
2367 ScsiPortIsr(IN PKINTERRUPT Interrupt,
2368 IN PVOID ServiceContext)
2369 {
2370 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2371
2372 DPRINT("ScsiPortIsr() called!\n");
2373
2374 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
2375
2376 return DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension);
2377 }
2378
2379
2380 // ScsiPortDpc
2381 // DESCRIPTION:
2382 //
2383 // RUN LEVEL:
2384 //
2385 // ARGUMENTS:
2386 // IN PKDPC Dpc
2387 // IN PDEVICE_OBJECT DpcDeviceObject
2388 // IN PIRP DpcIrp
2389 // IN PVOID DpcContext
2390 //
2391 static VOID STDCALL
2392 ScsiPortDpc(IN PKDPC Dpc,
2393 IN PDEVICE_OBJECT DpcDeviceObject,
2394 IN PIRP DpcIrp,
2395 IN PVOID DpcContext)
2396 {
2397 PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2398
2399 DPRINT("ScsiPortDpc(Dpc %p DpcDeviceObject %p DpcIrp %p DpcContext %p)\n",
2400 Dpc, DpcDeviceObject, DpcIrp, DpcContext);
2401
2402 DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DpcContext;
2403
2404 SpiProcessRequests(DeviceExtension, NULL);
2405
2406 DPRINT("ScsiPortDpc() done\n");
2407 }
2408
2409
2410 // ScsiPortIoTimer
2411 // DESCRIPTION:
2412 // This function handles timeouts and other time delayed processing
2413 //
2414 // RUN LEVEL:
2415 //
2416 // ARGUMENTS:
2417 // IN PDEVICE_OBJECT DeviceObject Device object registered with timer
2418 // IN PVOID Context the Controller extension for the
2419 // controller the device is on
2420 //
2421 static VOID STDCALL
2422 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
2423 PVOID Context)
2424 {
2425 DPRINT1("ScsiPortIoTimer()\n");
2426 }
2427
2428
2429 static PSCSI_REQUEST_BLOCK
2430 ScsiPortInitSenseRequestSrb(PSCSI_REQUEST_BLOCK OriginalSrb)
2431 {
2432 PSCSI_REQUEST_BLOCK Srb;
2433 ULONG Length;
2434 PCDB Cdb;
2435
2436 Length = sizeof(SCSI_REQUEST_BLOCK) + sizeof(SENSE_DATA) + 32;
2437 Srb = ExAllocatePoolWithTag(NonPagedPool,
2438 Length,
2439 TAG('S', 'S', 'r', 'b'));
2440 if (Srb == NULL)
2441 {
2442 return NULL;
2443 }
2444
2445 RtlZeroMemory(Srb, Length);
2446
2447 Srb->PathId = OriginalSrb->PathId;
2448 Srb->TargetId = OriginalSrb->TargetId;
2449 Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
2450 Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
2451 Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2452 Srb->OriginalRequest = OriginalSrb->OriginalRequest;
2453
2454 Srb->TimeOutValue = 4;
2455
2456 Srb->CdbLength = 6;
2457 /* The DataBuffer must be located in contiguous physical memory if
2458 * the miniport driver uses dma for the sense info. The size of
2459 * the sense data is 18 byte. If the buffer starts at a 32 byte
2460 * boundary than is the buffer always in one memory page.
2461 */
2462 Srb->DataBuffer = (PVOID)ROUND_UP((ULONG_PTR)(Srb + 1), 32);
2463 Srb->DataTransferLength = sizeof(SENSE_DATA);
2464
2465 Cdb = (PCDB)Srb->Cdb;
2466 Cdb->CDB6INQUIRY.OperationCode = SCSIOP_REQUEST_SENSE;
2467 Cdb->CDB6INQUIRY.AllocationLength = sizeof(SENSE_DATA);
2468
2469 return(Srb);
2470 }
2471
2472 /**********************************************************************
2473 * NAME INTERNAL
2474 * SpiBuildDeviceMap
2475 *
2476 * DESCRIPTION
2477 * Builds the registry device map of all device which are attached
2478 * to the given SCSI HBA port. The device map is located at:
2479 * \Registry\Machine\DeviceMap\Scsi
2480 *
2481 * RUN LEVEL
2482 * PASSIVE_LEVEL
2483 *
2484 * ARGUMENTS
2485 * DeviceExtension
2486 * ...
2487 *
2488 * RegistryPath
2489 * Name of registry driver service key.
2490 *
2491 * RETURNS
2492 * NTSTATUS
2493 */
2494
2495 static NTSTATUS
2496 SpiBuildDeviceMap (PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2497 PUNICODE_STRING RegistryPath)
2498 {
2499 PSCSI_PORT_LUN_EXTENSION LunExtension;
2500 OBJECT_ATTRIBUTES ObjectAttributes;
2501 UNICODE_STRING KeyName =
2502 RTL_CONSTANT_STRING(L"\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi");
2503 UNICODE_STRING ValueName;
2504 WCHAR NameBuffer[64];
2505 ULONG Disposition;
2506 HANDLE ScsiKey;
2507 HANDLE ScsiPortKey = NULL;
2508 HANDLE ScsiBusKey = NULL;
2509 HANDLE ScsiInitiatorKey = NULL;
2510 HANDLE ScsiTargetKey = NULL;
2511 HANDLE ScsiLunKey = NULL;
2512 ULONG BusNumber;
2513 ULONG Target;
2514 ULONG CurrentTarget;
2515 ULONG Lun;
2516 PWCHAR DriverName;
2517 ULONG UlongData;
2518 PWCHAR TypeName;
2519 NTSTATUS Status;
2520
2521 DPRINT("SpiBuildDeviceMap() called\n");
2522
2523 if (DeviceExtension == NULL || RegistryPath == NULL)
2524 {
2525 DPRINT1("Invalid parameter\n");
2526 return(STATUS_INVALID_PARAMETER);
2527 }
2528
2529 /* Open or create the 'Scsi' subkey */
2530 InitializeObjectAttributes(&ObjectAttributes,
2531 &KeyName,
2532 OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
2533 0,
2534 NULL);
2535 Status = ZwCreateKey(&ScsiKey,
2536 KEY_ALL_ACCESS,
2537 &ObjectAttributes,
2538 0,
2539 NULL,
2540 REG_OPTION_VOLATILE,
2541 &Disposition);
2542 if (!NT_SUCCESS(Status))
2543 {
2544 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2545 return(Status);
2546 }
2547
2548 /* Create new 'Scsi Port X' subkey */
2549 DPRINT("Scsi Port %lu\n",
2550 DeviceExtension->PortNumber);
2551
2552 swprintf(NameBuffer,
2553 L"Scsi Port %lu",
2554 DeviceExtension->PortNumber);
2555 RtlInitUnicodeString(&KeyName,
2556 NameBuffer);
2557 InitializeObjectAttributes(&ObjectAttributes,
2558 &KeyName,
2559 0,
2560 ScsiKey,
2561 NULL);
2562 Status = ZwCreateKey(&ScsiPortKey,
2563 KEY_ALL_ACCESS,
2564 &ObjectAttributes,
2565 0,
2566 NULL,
2567 REG_OPTION_VOLATILE,
2568 &Disposition);
2569 ZwClose(ScsiKey);
2570 if (!NT_SUCCESS(Status))
2571 {
2572 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2573 return(Status);
2574 }
2575
2576 /*
2577 * Create port-specific values
2578 */
2579
2580 /* Set 'DMA Enabled' (REG_DWORD) value */
2581 UlongData = (ULONG)!DeviceExtension->PortCapabilities->AdapterUsesPio;
2582 DPRINT(" DMA Enabled = %s\n", (UlongData) ? "TRUE" : "FALSE");
2583 RtlInitUnicodeString(&ValueName,
2584 L"DMA Enabled");
2585 Status = ZwSetValueKey(ScsiPortKey,
2586 &ValueName,
2587 0,
2588 REG_DWORD,
2589 &UlongData,
2590 sizeof(ULONG));
2591 if (!NT_SUCCESS(Status))
2592 {
2593 DPRINT("ZwSetValueKey('DMA Enabled') failed (Status %lx)\n", Status);
2594 ZwClose(ScsiPortKey);
2595 return(Status);
2596 }
2597
2598 /* Set 'Driver' (REG_SZ) value */
2599 DriverName = wcsrchr(RegistryPath->Buffer, L'\\') + 1;
2600 RtlInitUnicodeString(&ValueName,
2601 L"Driver");
2602 Status = ZwSetValueKey(ScsiPortKey,
2603 &ValueName,
2604 0,
2605 REG_SZ,
2606 DriverName,
2607 (wcslen(DriverName) + 1) * sizeof(WCHAR));
2608 if (!NT_SUCCESS(Status))
2609 {
2610 DPRINT("ZwSetValueKey('Driver') failed (Status %lx)\n", Status);
2611 ZwClose(ScsiPortKey);
2612 return(Status);
2613 }
2614
2615 /* Set 'Interrupt' (REG_DWORD) value (NT4 only) */
2616 UlongData = (ULONG)DeviceExtension->PortConfig->BusInterruptLevel;
2617 DPRINT(" Interrupt = %lu\n", UlongData);
2618 RtlInitUnicodeString(&ValueName,
2619 L"Interrupt");
2620 Status = ZwSetValueKey(ScsiPortKey,
2621 &ValueName,
2622 0,
2623 REG_DWORD,
2624 &UlongData,
2625 sizeof(ULONG));
2626 if (!NT_SUCCESS(Status))
2627 {
2628 DPRINT("ZwSetValueKey('Interrupt') failed (Status %lx)\n", Status);
2629 ZwClose(ScsiPortKey);
2630 return(Status);
2631 }
2632
2633 /* Set 'IOAddress' (REG_DWORD) value (NT4 only) */
2634 UlongData = ScsiPortConvertPhysicalAddressToUlong((*DeviceExtension->PortConfig->AccessRanges)[0].RangeStart);
2635 DPRINT(" IOAddress = %lx\n", UlongData);
2636 RtlInitUnicodeString(&ValueName,
2637 L"IOAddress");
2638 Status = ZwSetValueKey(ScsiPortKey,
2639 &ValueName,
2640 0,
2641 REG_DWORD,
2642 &UlongData,
2643 sizeof(ULONG));
2644 if (!NT_SUCCESS(Status))
2645 {
2646 DPRINT("ZwSetValueKey('IOAddress') failed (Status %lx)\n", Status);
2647 ZwClose(ScsiPortKey);
2648 return(Status);
2649 }
2650
2651 /* Enumerate buses */
2652 for (BusNumber = 0; BusNumber < DeviceExtension->PortConfig->NumberOfBuses; BusNumber++)
2653 {
2654 /* Create 'Scsi Bus X' key */
2655 DPRINT(" Scsi Bus %lu\n", BusNumber);
2656 swprintf(NameBuffer,
2657 L"Scsi Bus %lu",
2658 BusNumber);
2659 RtlInitUnicodeString(&KeyName,
2660 NameBuffer);
2661 InitializeObjectAttributes(&ObjectAttributes,
2662 &KeyName,
2663 0,
2664 ScsiPortKey,
2665 NULL);
2666 Status = ZwCreateKey(&ScsiBusKey,
2667 KEY_ALL_ACCESS,
2668 &ObjectAttributes,
2669 0,
2670 NULL,
2671 REG_OPTION_VOLATILE,
2672 &Disposition);
2673 if (!NT_SUCCESS(Status))
2674 {
2675 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2676 goto ByeBye;
2677 }
2678
2679 /* Create 'Initiator Id X' key */
2680 DPRINT(" Initiator Id %u\n",
2681 DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
2682 swprintf(NameBuffer,
2683 L"Initiator Id %u",
2684 (unsigned int)(UCHAR)DeviceExtension->PortConfig->InitiatorBusId[BusNumber]);
2685 RtlInitUnicodeString(&KeyName,
2686 NameBuffer);
2687 InitializeObjectAttributes(&ObjectAttributes,
2688 &KeyName,
2689 0,
2690 ScsiBusKey,
2691 NULL);
2692 Status = ZwCreateKey(&ScsiInitiatorKey,
2693 KEY_ALL_ACCESS,
2694 &ObjectAttributes,
2695 0,
2696 NULL,
2697 REG_OPTION_VOLATILE,
2698 &Disposition);
2699 if (!NT_SUCCESS(Status))
2700 {
2701 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2702 goto ByeBye;
2703 }
2704
2705 /* FIXME: Are there any initiator values (??) */
2706
2707 ZwClose(ScsiInitiatorKey);
2708 ScsiInitiatorKey = NULL;
2709
2710
2711 /* Enumerate targets */
2712 CurrentTarget = (ULONG)-1;
2713 ScsiTargetKey = NULL;
2714 for (Target = 0; Target < DeviceExtension->PortConfig->MaximumNumberOfTargets; Target++)
2715 {
2716 for (Lun = 0; Lun < SCSI_MAXIMUM_LOGICAL_UNITS; Lun++)
2717 {
2718 LunExtension = SpiGetLunExtension(DeviceExtension,
2719 BusNumber,
2720 Target,
2721 Lun);
2722 if (LunExtension != NULL)
2723 {
2724 if (Target != CurrentTarget)
2725 {
2726 /* Close old target key */
2727 if (ScsiTargetKey != NULL)
2728 {
2729 ZwClose(ScsiTargetKey);
2730 ScsiTargetKey = NULL;
2731 }
2732
2733 /* Create 'Target Id X' key */
2734 DPRINT(" Target Id %lu\n", Target);
2735 swprintf(NameBuffer,
2736 L"Target Id %lu",
2737 Target);
2738 RtlInitUnicodeString(&KeyName,
2739 NameBuffer);
2740 InitializeObjectAttributes(&ObjectAttributes,
2741 &KeyName,
2742 0,
2743 ScsiBusKey,
2744 NULL);
2745 Status = ZwCreateKey(&ScsiTargetKey,
2746 KEY_ALL_ACCESS,
2747 &ObjectAttributes,
2748 0,
2749 NULL,
2750 REG_OPTION_VOLATILE,
2751 &Disposition);
2752 if (!NT_SUCCESS(Status))
2753 {
2754 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2755 goto ByeBye;
2756 }
2757
2758 CurrentTarget = Target;
2759 }
2760
2761 /* Create 'Logical Unit Id X' key */
2762 DPRINT(" Logical Unit Id %lu\n", Lun);
2763 swprintf(NameBuffer,
2764 L"Logical Unit Id %lu",
2765 Lun);
2766 RtlInitUnicodeString(&KeyName,
2767 NameBuffer);
2768 InitializeObjectAttributes(&ObjectAttributes,
2769 &KeyName,
2770 0,
2771 ScsiTargetKey,
2772 NULL);
2773 Status = ZwCreateKey(&ScsiLunKey,
2774 KEY_ALL_ACCESS,
2775 &ObjectAttributes,
2776 0,
2777 NULL,
2778 REG_OPTION_VOLATILE,
2779 &Disposition);
2780 if (!NT_SUCCESS(Status))
2781 {
2782 DPRINT("ZwCreateKey() failed (Status %lx)\n", Status);
2783 goto ByeBye;
2784 }
2785
2786 /* Set 'Identifier' (REG_SZ) value */
2787 swprintf(NameBuffer,
2788 L"%.8S%.16S%.4S",
2789 LunExtension->InquiryData.VendorId,
2790 LunExtension->InquiryData.ProductId,
2791 LunExtension->InquiryData.ProductRevisionLevel);
2792 DPRINT(" Identifier = '%S'\n", NameBuffer);
2793 RtlInitUnicodeString(&ValueName,
2794 L"Identifier");
2795 Status = ZwSetValueKey(ScsiLunKey,
2796 &ValueName,
2797 0,
2798 REG_SZ,
2799 NameBuffer,
2800 (wcslen(NameBuffer) + 1) * sizeof(WCHAR));
2801 if (!NT_SUCCESS(Status))
2802 {
2803 DPRINT("ZwSetValueKey('Identifier') failed (Status %lx)\n", Status);
2804 goto ByeBye;
2805 }
2806
2807 /* Set 'Type' (REG_SZ) value */
2808 switch (LunExtension->InquiryData.DeviceType)
2809 {
2810 case 0:
2811 TypeName = L"DiskPeripheral";
2812 break;
2813 case 1:
2814 TypeName = L"TapePeripheral";
2815 break;
2816 case 2:
2817 TypeName = L"PrinterPeripheral";
2818 break;
2819 case 4:
2820 TypeName = L"WormPeripheral";
2821 break;
2822 case 5:
2823 TypeName = L"CdRomPeripheral";
2824 break;
2825 case 6:
2826 TypeName = L"ScannerPeripheral";
2827 break;
2828 case 7:
2829 TypeName = L"OpticalDiskPeripheral";
2830 break;
2831 case 8:
2832 TypeName = L"MediumChangerPeripheral";
2833 break;
2834 case 9:
2835 TypeName = L"CommunicationPeripheral";
2836 break;
2837 default:
2838 TypeName = L"OtherPeripheral";
2839 break;
2840 }
2841 DPRINT(" Type = '%S'\n", TypeName);
2842 RtlInitUnicodeString(&ValueName,
2843 L"Type");
2844 Status = ZwSetValueKey(ScsiLunKey,
2845 &ValueName,
2846 0,
2847 REG_SZ,
2848 TypeName,
2849 (wcslen(TypeName) + 1) * sizeof(WCHAR));
2850 if (!NT_SUCCESS(Status))
2851 {
2852 DPRINT("ZwSetValueKey('Type') failed (Status %lx)\n", Status);
2853 goto ByeBye;
2854 }
2855
2856 ZwClose(ScsiLunKey);
2857 ScsiLunKey = NULL;
2858 }
2859 }
2860
2861 /* Close old target key */
2862 if (ScsiTargetKey != NULL)
2863 {
2864 ZwClose(ScsiTargetKey);
2865 ScsiTargetKey = NULL;
2866 }
2867 }
2868
2869 ZwClose(ScsiBusKey);
2870 ScsiBusKey = NULL;
2871 }
2872
2873 ByeBye:
2874 if (ScsiLunKey != NULL)
2875 ZwClose (ScsiLunKey);
2876
2877 if (ScsiInitiatorKey != NULL)
2878 ZwClose (ScsiInitiatorKey);
2879
2880 if (ScsiTargetKey != NULL)
2881 ZwClose (ScsiTargetKey);
2882
2883 if (ScsiBusKey != NULL)
2884 ZwClose (ScsiBusKey);
2885
2886 if (ScsiPortKey != NULL)
2887 ZwClose (ScsiPortKey);
2888
2889 DPRINT("SpiBuildDeviceMap() done\n");
2890
2891 return Status;
2892 }
2893
2894 static VOID
2895 SpiRemoveActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2896 PIRP Irp,
2897 PIRP PrevIrp)
2898 {
2899 PSCSI_PORT_LUN_EXTENSION LunExtension;
2900 PIRP CurrentIrp;
2901 LunExtension = Irp->Tail.Overlay.DriverContext[2];
2902 InterlockedDecrement((PLONG)&LunExtension->ActiveIrpCount);
2903 InterlockedDecrement((PLONG)&DeviceExtension->ActiveIrpCount);
2904 if (PrevIrp)
2905 {
2906 InterlockedExchangePointer(&PrevIrp->Tail.Overlay.DriverContext[0],
2907 Irp->Tail.Overlay.DriverContext[0]);
2908 }
2909 else
2910 {
2911 InterlockedExchangePointer(&DeviceExtension->NextIrp,
2912 Irp->Tail.Overlay.DriverContext[0]);
2913 }
2914 if (LunExtension->NextIrp == Irp)
2915 {
2916 InterlockedExchangePointer(&LunExtension->NextIrp,
2917 Irp->Tail.Overlay.DriverContext[1]);
2918 return;
2919 }
2920 else
2921 {
2922 CurrentIrp = LunExtension->NextIrp;
2923 while (CurrentIrp)
2924 {
2925 if (CurrentIrp->Tail.Overlay.DriverContext[1] == Irp)
2926 {
2927 InterlockedExchangePointer(&CurrentIrp->Tail.Overlay.DriverContext[1],
2928 Irp->Tail.Overlay.DriverContext[1]);
2929 return;
2930 }
2931 CurrentIrp = CurrentIrp->Tail.Overlay.DriverContext[1];
2932 }
2933 KEBUGCHECK(0);
2934 }
2935 }
2936
2937 static VOID
2938 SpiAddActiveIrp(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2939 PIRP Irp)
2940 {
2941 PSCSI_PORT_LUN_EXTENSION LunExtension;
2942 PSCSI_REQUEST_BLOCK Srb;
2943 LunExtension = Irp->Tail.Overlay.DriverContext[2];
2944 Srb = Irp->Tail.Overlay.DriverContext[3];
2945 Irp->Tail.Overlay.DriverContext[0] = (PVOID)DeviceExtension->NextIrp;
2946 InterlockedExchangePointer(&DeviceExtension->NextIrp, Irp);
2947 Irp->Tail.Overlay.DriverContext[1] = (PVOID)LunExtension->NextIrp;
2948 InterlockedExchangePointer(&LunExtension->NextIrp, Irp);
2949 }
2950
2951 static VOID
2952 SpiProcessRequests(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2953 IN PIRP NextIrp)
2954 {
2955 /*
2956 * Using of some fields from Srb and Irp while processing requests:
2957 *
2958 * NextIrp on entry:
2959 * Srb->OriginalRequest -> LunExtension
2960 * Irp->Tail.Overlay.DriverContext[3] -> original Srb
2961 * IoStack->Parameters.Scsi.Srb -> original Srb
2962 *
2963 * Irp is within the pending irp list:
2964 * Srb->OriginalRequest -> LunExtension
2965 * Irp->Tail.Overlay.DriverContext[0] and DriverContext[1] -> ListEntry for queue
2966 * Irp->Tail.Overlay.DriverContext[2] -> sort key (from Srb->QueueSortKey)
2967 * Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
2968 * IoStack->Parameters.Scsi.Srb -> original Srb
2969 *
2970 * Irp is within the active irp list or while other processing:
2971 * Srb->OriginalRequest -> Irp
2972 * Irp->Tail.Overlay.DriverContext[0] -> next irp, DeviceExtension->NextIrp is head.
2973 * Irp->Tail.Overlay.DriverContext[1] -> next irp, LunExtension->NextIrp is head.
2974 * Irp->Tail.Overlay.DriverContext[2] -> LunExtension
2975 * Irp->Tail.Overlay.DriverContext[3] -> current Srb (original or sense request)
2976 * IoStack->Parameters.Scsi.Srb -> original Srb
2977 */
2978 PIO_STACK_LOCATION IrpStack;
2979 PSCSI_PORT_LUN_EXTENSION LunExtension;
2980 PLIST_ENTRY ListEntry;
2981 KIRQL oldIrql;
2982 PIRP Irp;
2983 LIST_ENTRY NextIrpListHead;
2984 LIST_ENTRY CompleteIrpListHead;
2985 PSCSI_REQUEST_BLOCK Srb;
2986 PSCSI_REQUEST_BLOCK OriginalSrb;
2987 PIRP PrevIrp;
2988
2989 DPRINT("SpiProcessRequests() called\n");
2990
2991 InitializeListHead(&NextIrpListHead);
2992 InitializeListHead(&CompleteIrpListHead);
2993
2994 KeAcquireSpinLock(&DeviceExtension->Lock, &oldIrql);
2995
2996 if (NextIrp)
2997 {
2998 Srb = NextIrp->Tail.Overlay.DriverContext[3];
2999 /*
3000 * FIXME:
3001 * Is this the right place to set this flag ?
3002 */
3003 NextIrp->Tail.Overlay.DriverContext[2] = (PVOID)Srb->QueueSortKey;
3004 LunExtension = Srb->OriginalRequest;
3005
3006 ListEntry = DeviceExtension->PendingIrpListHead.Flink;
3007 while (ListEntry != &DeviceExtension->PendingIrpListHead)
3008 {
3009 Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
3010 if ((ULONG)Irp->Tail.Overlay.DriverContext[2] > Srb->QueueSortKey)
3011 {
3012 break;
3013 }
3014 ListEntry = ListEntry->Flink;
3015 }
3016 InsertTailList(ListEntry, (PLIST_ENTRY)&NextIrp->Tail.Overlay.DriverContext[0]);
3017 DeviceExtension->PendingIrpCount++;
3018 LunExtension->PendingIrpCount++;
3019 }
3020
3021 while (DeviceExtension->Flags & IRP_FLAG_COMPLETE ||
3022 (((DeviceExtension->SrbExtensionSize == 0 || DeviceExtension->CurrentSrbExtensions < DeviceExtension->MaxSrbExtensions) &&
3023 DeviceExtension->PendingIrpCount > 0 &&
3024 (DeviceExtension->Flags & (IRP_FLAG_NEXT|IRP_FLAG_NEXT_LU) || DeviceExtension->NextIrp == NULL))))
3025 {
3026 DPRINT ("RequestComplete %d, NextRequest %d, NextLuRequest %d, PendingIrpCount %d, ActiveIrpCount %d\n",
3027 DeviceExtension->Flags & IRP_FLAG_COMPLETE ? 1 : 0,
3028 DeviceExtension->Flags & IRP_FLAG_NEXT ? 1 : 0,
3029 DeviceExtension->Flags & IRP_FLAG_NEXT_LU ? 1 : 0,
3030 DeviceExtension->PendingIrpCount,
3031 DeviceExtension->ActiveIrpCount);
3032
3033
3034 if (DeviceExtension->Flags & IRP_FLAG_COMPLETE)
3035 {
3036 DeviceExtension->Flags &= ~IRP_FLAG_COMPLETE;
3037 PrevIrp = NULL;
3038 Irp = DeviceExtension->NextIrp;
3039 while (Irp)
3040 {
3041 NextIrp = (PIRP)Irp->Tail.Overlay.DriverContext[0];
3042 Srb = Irp->Tail.Overlay.DriverContext[3];
3043 if (!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE))
3044 {
3045 BOOLEAN CompleteThisRequest;
3046 LunExtension = Irp->Tail.Overlay.DriverContext[2];
3047 IrpStack = IoGetCurrentIrpStackLocation(Irp);
3048 OriginalSrb = IrpStack->Parameters.Scsi.Srb;
3049
3050 if (Srb->SrbStatus == SRB_STATUS_BUSY)
3051 {
3052 CompleteThisRequest = FALSE;
3053 Irp->Tail.Overlay.DriverContext[3] = Srb;
3054
3055 SpiRemoveActiveIrp(DeviceExtension, Irp, PrevIrp);
3056 SpiFreeSrbExtension(DeviceExtension, OriginalSrb);
3057
3058 Srb->OriginalRequest = LunExtension;
3059 Irp->Tail.Overlay.DriverContext[2] = 0;
3060
3061 InsertHeadList(&DeviceExtension->PendingIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
3062 DeviceExtension->PendingIrpCount++;
3063 LunExtension->PendingIrpCount++;
3064 Irp = NextIrp;
3065 continue;
3066 }
3067
3068 if (OriginalSrb != Srb)
3069 {
3070 SENSE_DATA* SenseInfoBuffer;
3071
3072 SenseInfoBuffer = Srb->DataBuffer;
3073
3074 DPRINT("Got sense data!\n");
3075
3076 DPRINT("Valid: %x\n", SenseInfoBuffer->Valid);
3077 DPRINT("ErrorCode: %x\n", SenseInfoBuffer->ErrorCode);
3078 DPRINT("SenseKey: %x\n", SenseInfoBuffer->SenseKey);
3079 DPRINT("SenseCode: %x\n", SenseInfoBuffer->AdditionalSenseCode);
3080
3081 /* Copy sense data */
3082 RtlCopyMemory(OriginalSrb->SenseInfoBuffer,
3083 SenseInfoBuffer,
3084 sizeof(SENSE_DATA));
3085 OriginalSrb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
3086 OriginalSrb->SrbExtension = Srb->SrbExtension;
3087 ExFreePool(Srb);
3088 CompleteThisRequest = TRUE;
3089 }
3090 else if (SRB_STATUS(Srb->SrbStatus) != SRB_STATUS_SUCCESS &&
3091 Srb->ScsiStatus == SCSISTAT_CHECK_CONDITION &&
3092 Srb->SenseInfoBuffer != NULL &&
3093 Srb->SenseInfoBufferLength >= sizeof(SENSE_DATA) &&
3094 !(Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID))
3095 {
3096 DPRINT("SCSIOP_REQUEST_SENSE required!\n");
3097
3098 Srb = ScsiPortInitSenseRequestSrb(OriginalSrb);
3099
3100 if (Srb)
3101 {
3102 CompleteThisRequest = FALSE;
3103 Irp->Tail.Overlay.DriverContext[3] = Srb;
3104 SpiRemoveActiveIrp(DeviceExtension, Irp, PrevIrp);
3105 SpiFreeSrbExtension(DeviceExtension, OriginalSrb);
3106
3107 Srb->OriginalRequest = LunExtension;
3108 Irp->Tail.Overlay.DriverContext[2] = 0;
3109
3110 InsertHeadList(&DeviceExtension->PendingIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
3111 DeviceExtension->PendingIrpCount++;
3112 LunExtension->PendingIrpCount++;
3113 Irp = NextIrp;
3114 continue;
3115 }
3116 else
3117 {
3118 CompleteThisRequest = TRUE;
3119 }
3120 }
3121 else
3122 {
3123 DPRINT("Complete Request\n");
3124 CompleteThisRequest = TRUE;
3125 }
3126 if (CompleteThisRequest)
3127 {
3128 SpiRemoveActiveIrp(DeviceExtension, Irp, PrevIrp);
3129 InsertHeadList(&CompleteIrpListHead, (PLIST_ENTRY)&Irp->Tail.Overlay.DriverContext[0]);
3130 SpiFreeSrbExtension(DeviceExtension, OriginalSrb);
3131 }
3132 else
3133 {
3134 PrevIrp = Irp;
3135 }
3136 Irp = NextIrp;
3137 continue;
3138 }
3139 PrevIrp = Irp;
3140 Irp = NextIrp;
3141 }
3142 }
3143 if (!IsListEmpty(&CompleteIrpListHead))
3144 {
3145 KeReleaseSpinLockFromDpcLevel(&DeviceExtension->Lock);
3146 while (!IsListEmpty(&CompleteIrpListHead))
3147 {
3148 ListEntry = RemoveTailList(&CompleteIrpListHead);
3149 Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.DriverContext[0]);
3150 IoCompleteRequest(Irp, IO_NO_INCREMENT);
3151 }
3152 KeAcquireSpinLockAtDpcLevel(&DeviceExtension->Lock);