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