1 /*
2  * PROJECT:     ReactOS Storage Stack / SCSIPORT storage port library
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Main and exported functions
5  * COPYRIGHT:   Eric Kohl (eric.kohl@reactos.org)
6  *              Aleksey Bragin (aleksey@reactos.org)
7  */
8 
9 /* INCLUDES *****************************************************************/
10 
11 #include "scsiport.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 ULONG InternalDebugLevel = 0x00;
17 
18 #undef ScsiPortMoveMemory
19 
20 /* GLOBALS *******************************************************************/
21 
22 static BOOLEAN
23 SpiGetPciConfigData(IN PDRIVER_OBJECT DriverObject,
24                     IN PDEVICE_OBJECT DeviceObject,
25                     IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
26                     IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
27                     IN PUNICODE_STRING RegistryPath,
28                     IN ULONG BusNumber,
29                     IN OUT PPCI_SLOT_NUMBER NextSlotNumber);
30 
31 static NTSTATUS NTAPI
32 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
33             IN PIRP Irp);
34 
35 static VOID NTAPI
36 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
37         PVOID Context);
38 
39 VOID NTAPI
40 SpiMiniportTimerDpc(IN struct _KDPC *Dpc,
41                     IN PVOID DeviceObject,
42                     IN PVOID SystemArgument1,
43                     IN PVOID SystemArgument2);
44 
45 static NTSTATUS
46 SpiCreatePortConfig(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
47                     PHW_INITIALIZATION_DATA HwInitData,
48                     PCONFIGURATION_INFO InternalConfigInfo,
49                     PPORT_CONFIGURATION_INFORMATION ConfigInfo,
50                     BOOLEAN FirstCall);
51 
52 NTSTATUS NTAPI
53 SpQueryDeviceCallout(IN PVOID  Context,
54                      IN PUNICODE_STRING  PathName,
55                      IN INTERFACE_TYPE  BusType,
56                      IN ULONG  BusNumber,
57                      IN PKEY_VALUE_FULL_INFORMATION  *BusInformation,
58                      IN CONFIGURATION_TYPE  ControllerType,
59                      IN ULONG  ControllerNumber,
60                      IN PKEY_VALUE_FULL_INFORMATION  *ControllerInformation,
61                      IN CONFIGURATION_TYPE  PeripheralType,
62                      IN ULONG  PeripheralNumber,
63                      IN PKEY_VALUE_FULL_INFORMATION  *PeripheralInformation);
64 
65 static VOID
66 SpiParseDeviceInfo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
67                    IN HANDLE Key,
68                    IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
69                    IN PCONFIGURATION_INFO InternalConfigInfo,
70                    IN PUCHAR Buffer);
71 
72 static VOID
73 SpiResourceToConfig(IN PHW_INITIALIZATION_DATA HwInitializationData,
74                     IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor,
75                     IN PPORT_CONFIGURATION_INFORMATION PortConfig);
76 
77 static PCM_RESOURCE_LIST
78 SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
79                     PPORT_CONFIGURATION_INFORMATION PortConfig);
80 
81 static NTSTATUS
82 SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCachedSize);
83 
84 NTHALAPI ULONG NTAPI HalGetBusData(BUS_DATA_TYPE, ULONG, ULONG, PVOID, ULONG);
85 NTHALAPI ULONG NTAPI HalGetInterruptVector(INTERFACE_TYPE, ULONG, ULONG, ULONG, PKIRQL, PKAFFINITY);
86 NTHALAPI NTSTATUS NTAPI HalAssignSlotResources(PUNICODE_STRING, PUNICODE_STRING, PDRIVER_OBJECT, PDEVICE_OBJECT, INTERFACE_TYPE, ULONG, ULONG, PCM_RESOURCE_LIST *);
87 
88 /* FUNCTIONS *****************************************************************/
89 
90 /**********************************************************************
91  * NAME                         EXPORTED
92  *  DriverEntry
93  *
94  * DESCRIPTION
95  *  This function initializes the driver.
96  *
97  * RUN LEVEL
98  *  PASSIVE_LEVEL
99  *
100  * ARGUMENTS
101  *  DriverObject
102  *      System allocated Driver Object for this driver.
103  *
104  *  RegistryPath
105  *      Name of registry driver service key.
106  *
107  * RETURN VALUE
108  *  Status.
109  */
110 
111 NTSTATUS NTAPI
112 DriverEntry(IN PDRIVER_OBJECT DriverObject,
113         IN PUNICODE_STRING RegistryPath)
114 {
115     DPRINT("ScsiPort Driver %s\n", VERSION);
116     return(STATUS_SUCCESS);
117 }
118 
119 
120 /**********************************************************************
121  * NAME                         EXPORTED
122  *  ScsiDebugPrint
123  *
124  * DESCRIPTION
125  *  Prints debugging messages.
126  *
127  * RUN LEVEL
128  *  PASSIVE_LEVEL
129  *
130  * ARGUMENTS
131  *  DebugPrintLevel
132  *      Debug level of the given message.
133  *
134  *  DebugMessage
135  *      Pointer to printf()-compatible format string.
136  *
137  *  ...
138         Additional output data (see printf()).
139  *
140  * RETURN VALUE
141  *  None.
142  *
143  * @implemented
144  */
145 
146 VOID
147 ScsiDebugPrint(IN ULONG DebugPrintLevel,
148            IN PCHAR DebugMessage,
149            ...)
150 {
151     char Buffer[256];
152     va_list ap;
153 
154     if (DebugPrintLevel > InternalDebugLevel)
155         return;
156 
157     va_start(ap, DebugMessage);
158     vsprintf(Buffer, DebugMessage, ap);
159     va_end(ap);
160 
161     DbgPrint(Buffer);
162 }
163 
164 /* An internal helper function for ScsiPortCompleteRequest */
165 VOID
166 NTAPI
167 SpiCompleteRequest(IN PVOID HwDeviceExtension,
168                    IN PSCSI_REQUEST_BLOCK_INFO SrbInfo,
169                    IN UCHAR SrbStatus)
170 {
171     PSCSI_REQUEST_BLOCK Srb;
172 
173     /* Get current SRB */
174     Srb = SrbInfo->Srb;
175 
176     /* Return if there is no SRB or it is not active */
177     if (!Srb || !(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE)) return;
178 
179     /* Set status */
180     Srb->SrbStatus = SrbStatus;
181 
182     /* Set data transfered to 0 */
183     Srb->DataTransferLength = 0;
184 
185     /* Notify */
186     ScsiPortNotification(RequestComplete,
187                          HwDeviceExtension,
188                          Srb);
189 }
190 
191 /*
192  * @unimplemented
193  */
194 VOID NTAPI
195 ScsiPortCompleteRequest(IN PVOID HwDeviceExtension,
196                         IN UCHAR PathId,
197                         IN UCHAR TargetId,
198                         IN UCHAR Lun,
199                         IN UCHAR SrbStatus)
200 {
201     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
202     PSCSI_PORT_LUN_EXTENSION LunExtension;
203     PSCSI_REQUEST_BLOCK_INFO SrbInfo;
204     PLIST_ENTRY ListEntry;
205     ULONG BusNumber;
206     ULONG Target;
207 
208     DPRINT("ScsiPortCompleteRequest() called\n");
209 
210     DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
211                                         SCSI_PORT_DEVICE_EXTENSION,
212                                         MiniPortDeviceExtension);
213 
214     /* Go through all buses */
215     for (BusNumber = 0; BusNumber < 8; BusNumber++)
216     {
217         /* Go through all targets */
218         for (Target = 0; Target < DeviceExtension->MaxTargedIds; Target++)
219         {
220             /* Get logical unit list head */
221             LunExtension = DeviceExtension->LunExtensionList[Target % 8];
222 
223             /* Go through all logical units */
224             while (LunExtension)
225             {
226                 /* Now match what caller asked with what we are at now */
227                 if ((PathId == SP_UNTAGGED || PathId == LunExtension->PathId) &&
228                     (TargetId == SP_UNTAGGED || TargetId == LunExtension->TargetId) &&
229                     (Lun == SP_UNTAGGED || Lun == LunExtension->Lun))
230                 {
231                     /* Yes, that's what caller asked for. Complete abort requests */
232                     if (LunExtension->CompletedAbortRequests)
233                     {
234                         /* TODO: Save SrbStatus in this request */
235                         DPRINT1("Completing abort request without setting SrbStatus!\n");
236 
237                         /* Issue a notification request */
238                         ScsiPortNotification(RequestComplete,
239                                              HwDeviceExtension,
240                                              LunExtension->CompletedAbortRequests);
241                     }
242 
243                     /* Complete the request using our helper */
244                     SpiCompleteRequest(HwDeviceExtension,
245                                        &LunExtension->SrbInfo,
246                                        SrbStatus);
247 
248                     /* Go through the queue and complete everything there too */
249                     ListEntry = LunExtension->SrbInfo.Requests.Flink;
250                     while (ListEntry != &LunExtension->SrbInfo.Requests)
251                     {
252                         /* Get the actual SRB info entry */
253                         SrbInfo = CONTAINING_RECORD(ListEntry,
254                                                     SCSI_REQUEST_BLOCK_INFO,
255                                                     Requests);
256 
257                         /* Complete it */
258                         SpiCompleteRequest(HwDeviceExtension,
259                                            SrbInfo,
260                                            SrbStatus);
261 
262                         /* Advance to the next request in queue */
263                         ListEntry = SrbInfo->Requests.Flink;
264                     }
265                 }
266 
267                 /* Advance to the next one */
268                 LunExtension = LunExtension->Next;
269             }
270         }
271     }
272 }
273 
274 /*
275  * @unimplemented
276  */
277 VOID NTAPI
278 ScsiPortFlushDma(IN PVOID HwDeviceExtension)
279 {
280   DPRINT("ScsiPortFlushDma()\n");
281   UNIMPLEMENTED;
282 }
283 
284 
285 /*
286  * @implemented
287  */
288 VOID NTAPI
289 ScsiPortFreeDeviceBase(IN PVOID HwDeviceExtension,
290                IN PVOID MappedAddress)
291 {
292     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
293     PMAPPED_ADDRESS NextMa, LastMa;
294 
295     //DPRINT("ScsiPortFreeDeviceBase() called\n");
296 
297     DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
298                                         SCSI_PORT_DEVICE_EXTENSION,
299                                         MiniPortDeviceExtension);
300 
301     /* Initialize our pointers */
302     NextMa = DeviceExtension->MappedAddressList;
303     LastMa = NextMa;
304 
305     while (NextMa)
306     {
307         if (NextMa->MappedAddress == MappedAddress)
308         {
309             /* Unmap it first */
310             MmUnmapIoSpace(MappedAddress, NextMa->NumberOfBytes);
311 
312             /* Remove it from the list */
313             if (NextMa == DeviceExtension->MappedAddressList)
314             {
315                 /* Remove the first entry */
316                 DeviceExtension->MappedAddressList = NextMa->NextMappedAddress;
317             }
318             else
319             {
320                 LastMa->NextMappedAddress = NextMa->NextMappedAddress;
321             }
322 
323             /* Free the resources and quit */
324             ExFreePool(NextMa);
325 
326             return;
327         }
328         else
329         {
330             LastMa = NextMa;
331             NextMa = NextMa->NextMappedAddress;
332         }
333     }
334 }
335 
336 
337 /*
338  * @implemented
339  */
340 ULONG NTAPI
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     DPRINT("ScsiPortGetBusData()\n");
349 
350     if (Length)
351     {
352         /* If Length is non-zero, just forward the call to
353         HalGetBusData() function */
354         return HalGetBusData(BusDataType,
355                              SystemIoBusNumber,
356                              SlotNumber,
357                              Buffer,
358                              Length);
359     }
360 
361     /* We have a more complex case here */
362     UNIMPLEMENTED;
363     return 0;
364 }
365 
366 /*
367  * @implemented
368  */
369 ULONG NTAPI
370 ScsiPortSetBusDataByOffset(IN PVOID DeviceExtension,
371                            IN ULONG BusDataType,
372                            IN ULONG SystemIoBusNumber,
373                            IN ULONG SlotNumber,
374                            IN PVOID Buffer,
375                            IN ULONG Offset,
376                            IN ULONG Length)
377 {
378     DPRINT("ScsiPortSetBusDataByOffset()\n");
379     return HalSetBusDataByOffset(BusDataType,
380                                  SystemIoBusNumber,
381                                  SlotNumber,
382                                  Buffer,
383                                  Offset,
384                                  Length);
385 }
386 
387 /*
388  * @implemented
389  */
390 PVOID NTAPI
391 ScsiPortGetDeviceBase(IN PVOID HwDeviceExtension,
392               IN INTERFACE_TYPE BusType,
393               IN ULONG SystemIoBusNumber,
394               IN SCSI_PHYSICAL_ADDRESS IoAddress,
395               IN ULONG NumberOfBytes,
396               IN BOOLEAN InIoSpace)
397 {
398     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
399     PHYSICAL_ADDRESS TranslatedAddress;
400     PMAPPED_ADDRESS DeviceBase;
401     ULONG AddressSpace;
402     PVOID MappedAddress;
403 
404     //DPRINT ("ScsiPortGetDeviceBase() called\n");
405 
406     DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
407                                         SCSI_PORT_DEVICE_EXTENSION,
408                                         MiniPortDeviceExtension);
409 
410     AddressSpace = (ULONG)InIoSpace;
411     if (HalTranslateBusAddress(BusType,
412                                SystemIoBusNumber,
413                                IoAddress,
414                                &AddressSpace,
415                                &TranslatedAddress) == FALSE)
416     {
417         return NULL;
418     }
419 
420     /* i/o space */
421     if (AddressSpace != 0)
422         return((PVOID)(ULONG_PTR)TranslatedAddress.QuadPart);
423 
424     MappedAddress = MmMapIoSpace(TranslatedAddress,
425                                  NumberOfBytes,
426                                  FALSE);
427 
428     DeviceBase = ExAllocatePoolWithTag(NonPagedPool,
429                                 sizeof(MAPPED_ADDRESS), TAG_SCSIPORT);
430 
431     if (DeviceBase == NULL)
432         return MappedAddress;
433 
434     DeviceBase->MappedAddress = MappedAddress;
435     DeviceBase->NumberOfBytes = NumberOfBytes;
436     DeviceBase->IoAddress = IoAddress;
437     DeviceBase->BusNumber = SystemIoBusNumber;
438 
439     /* Link it to the Device Extension list */
440     DeviceBase->NextMappedAddress = DeviceExtension->MappedAddressList;
441     DeviceExtension->MappedAddressList = DeviceBase;
442 
443     return MappedAddress;
444 }
445 
446 /*
447  * @unimplemented
448  */
449 PVOID NTAPI
450 ScsiPortGetLogicalUnit(IN PVOID HwDeviceExtension,
451                IN UCHAR PathId,
452                IN UCHAR TargetId,
453                IN UCHAR Lun)
454 {
455     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
456     PSCSI_PORT_LUN_EXTENSION LunExtension;
457 
458     DPRINT("ScsiPortGetLogicalUnit() called\n");
459 
460     DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
461                                         SCSI_PORT_DEVICE_EXTENSION,
462                                         MiniPortDeviceExtension);
463 
464     /* Check the extension size */
465     if (!DeviceExtension->LunExtensionSize)
466     {
467         /* They didn't want one */
468         return NULL;
469     }
470 
471     LunExtension = SpiGetLunExtension(DeviceExtension,
472                                       PathId,
473                                       TargetId,
474                                       Lun);
475     /* Check that the logical unit exists */
476     if (!LunExtension)
477     {
478         /* Nope, return NULL */
479         return NULL;
480     }
481 
482     /* Return the logical unit miniport extension */
483     return (LunExtension + 1);
484 }
485 
486 
487 /*
488  * @implemented
489  */
490 SCSI_PHYSICAL_ADDRESS NTAPI
491 ScsiPortGetPhysicalAddress(IN PVOID HwDeviceExtension,
492                            IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
493                            IN PVOID VirtualAddress,
494                            OUT ULONG *Length)
495 {
496     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
497     SCSI_PHYSICAL_ADDRESS PhysicalAddress;
498     SIZE_T BufferLength = 0;
499     ULONG_PTR Offset;
500     PSCSI_SG_ADDRESS SGList;
501     PSCSI_REQUEST_BLOCK_INFO SrbInfo;
502 
503     DPRINT("ScsiPortGetPhysicalAddress(%p %p %p %p)\n",
504         HwDeviceExtension, Srb, VirtualAddress, Length);
505 
506     DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
507                                         SCSI_PORT_DEVICE_EXTENSION,
508                                         MiniPortDeviceExtension);
509 
510     if (Srb == NULL || Srb->SenseInfoBuffer == VirtualAddress)
511     {
512         /* Simply look it up in the allocated common buffer */
513         Offset = (PUCHAR)VirtualAddress - (PUCHAR)DeviceExtension->SrbExtensionBuffer;
514 
515         BufferLength = DeviceExtension->CommonBufferLength - Offset;
516         PhysicalAddress.QuadPart = DeviceExtension->PhysicalAddress.QuadPart + Offset;
517     }
518     else if (DeviceExtension->MapRegisters)
519     {
520         /* Scatter-gather list must be used */
521         SrbInfo = SpiGetSrbData(DeviceExtension,
522                                Srb->PathId,
523                                Srb->TargetId,
524                                Srb->Lun,
525                                Srb->QueueTag);
526 
527         SGList = SrbInfo->ScatterGather;
528 
529         /* Find needed item in the SG list */
530         Offset = (PCHAR)VirtualAddress - (PCHAR)Srb->DataBuffer;
531         while (Offset >= SGList->Length)
532         {
533             Offset -= SGList->Length;
534             SGList++;
535         }
536 
537         /* We're done, store length and physical address */
538         BufferLength = SGList->Length - Offset;
539         PhysicalAddress.QuadPart = SGList->PhysicalAddress.QuadPart + Offset;
540     }
541     else
542     {
543         /* Nothing */
544         PhysicalAddress.QuadPart = (LONGLONG)(SP_UNINITIALIZED_VALUE);
545     }
546 
547     *Length = (ULONG)BufferLength;
548     return PhysicalAddress;
549 }
550 
551 
552 /*
553  * @unimplemented
554  */
555 PSCSI_REQUEST_BLOCK NTAPI
556 ScsiPortGetSrb(IN PVOID DeviceExtension,
557            IN UCHAR PathId,
558            IN UCHAR TargetId,
559            IN UCHAR Lun,
560            IN LONG QueueTag)
561 {
562   DPRINT1("ScsiPortGetSrb() unimplemented\n");
563   UNIMPLEMENTED;
564   return NULL;
565 }
566 
567 
568 /*
569  * @implemented
570  */
571 PVOID NTAPI
572 ScsiPortGetUncachedExtension(IN PVOID HwDeviceExtension,
573                  IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
574                  IN ULONG NumberOfBytes)
575 {
576     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
577     DEVICE_DESCRIPTION DeviceDescription;
578     ULONG MapRegistersCount;
579     NTSTATUS Status;
580 
581     DPRINT("ScsiPortGetUncachedExtension(%p %p %lu)\n",
582         HwDeviceExtension, ConfigInfo, NumberOfBytes);
583 
584     DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
585                                         SCSI_PORT_DEVICE_EXTENSION,
586                                         MiniPortDeviceExtension);
587 
588     /* Check for allocated common DMA buffer */
589     if (DeviceExtension->SrbExtensionBuffer != NULL)
590     {
591         DPRINT1("The HBA has already got a common DMA buffer!\n");
592         return NULL;
593     }
594 
595     /* Check for DMA adapter object */
596     if (DeviceExtension->AdapterObject == NULL)
597     {
598         /* Initialize DMA adapter description */
599         RtlZeroMemory(&DeviceDescription, sizeof(DEVICE_DESCRIPTION));
600 
601         DeviceDescription.Version = DEVICE_DESCRIPTION_VERSION;
602         DeviceDescription.Master = ConfigInfo->Master;
603         DeviceDescription.ScatterGather = ConfigInfo->ScatterGather;
604         DeviceDescription.DemandMode = ConfigInfo->DemandMode;
605         DeviceDescription.Dma32BitAddresses = ConfigInfo->Dma32BitAddresses;
606         DeviceDescription.BusNumber = ConfigInfo->SystemIoBusNumber;
607         DeviceDescription.DmaChannel = ConfigInfo->DmaChannel;
608         DeviceDescription.InterfaceType = ConfigInfo->AdapterInterfaceType;
609         DeviceDescription.DmaWidth = ConfigInfo->DmaWidth;
610         DeviceDescription.DmaSpeed = ConfigInfo->DmaSpeed;
611         DeviceDescription.MaximumLength = ConfigInfo->MaximumTransferLength;
612         DeviceDescription.DmaPort = ConfigInfo->DmaPort;
613 
614         /* Get a DMA adapter object */
615         DeviceExtension->AdapterObject =
616             HalGetAdapter(&DeviceDescription, &MapRegistersCount);
617 
618         /* Fail in case of error */
619         if (DeviceExtension->AdapterObject == NULL)
620         {
621             DPRINT1("HalGetAdapter() failed\n");
622             return NULL;
623         }
624 
625         /* Set number of physical breaks */
626         if (ConfigInfo->NumberOfPhysicalBreaks != 0 &&
627             MapRegistersCount > ConfigInfo->NumberOfPhysicalBreaks)
628         {
629             DeviceExtension->PortCapabilities.MaximumPhysicalPages =
630                 ConfigInfo->NumberOfPhysicalBreaks;
631         }
632         else
633         {
634             DeviceExtension->PortCapabilities.MaximumPhysicalPages = MapRegistersCount;
635         }
636     }
637 
638     /* Update auto request sense feature */
639     DeviceExtension->SupportsAutoSense = ConfigInfo->AutoRequestSense;
640 
641     /* Update Srb extension size */
642     if (DeviceExtension->SrbExtensionSize != ConfigInfo->SrbExtensionSize)
643         DeviceExtension->SrbExtensionSize = ConfigInfo->SrbExtensionSize;
644 
645     /* Update Srb extension alloc flag */
646     if (ConfigInfo->AutoRequestSense || DeviceExtension->SrbExtensionSize)
647         DeviceExtension->NeedSrbExtensionAlloc = TRUE;
648 
649     /* Allocate a common DMA buffer */
650     Status = SpiAllocateCommonBuffer(DeviceExtension, NumberOfBytes);
651 
652     if (!NT_SUCCESS(Status))
653     {
654         DPRINT1("SpiAllocateCommonBuffer() failed with Status = 0x%08X!\n", Status);
655         return NULL;
656     }
657 
658     return DeviceExtension->NonCachedExtension;
659 }
660 
661 static NTSTATUS
662 SpiAllocateCommonBuffer(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension, ULONG NonCachedSize)
663 {
664     PVOID *SrbExtension, CommonBuffer;
665     ULONG CommonBufferLength, BufSize;
666 
667     /* If size is 0, set it to 16 */
668     if (!DeviceExtension->SrbExtensionSize)
669         DeviceExtension->SrbExtensionSize = 16;
670 
671     /* Calculate size */
672     BufSize = DeviceExtension->SrbExtensionSize;
673 
674     /* Add autosense data size if needed */
675     if (DeviceExtension->SupportsAutoSense)
676         BufSize += sizeof(SENSE_DATA);
677 
678 
679     /* Round it */
680     BufSize = (BufSize + sizeof(LONGLONG) - 1) & ~(sizeof(LONGLONG) - 1);
681 
682     /* Sum up into the total common buffer length, and round it to page size */
683     CommonBufferLength =
684         ROUND_TO_PAGES(NonCachedSize + BufSize * DeviceExtension->RequestsNumber);
685 
686     /* Allocate it */
687     if (!DeviceExtension->AdapterObject)
688     {
689         /* From nonpaged pool if there is no DMA */
690         CommonBuffer = ExAllocatePoolWithTag(NonPagedPool, CommonBufferLength, TAG_SCSIPORT);
691     }
692     else
693     {
694         /* Perform a full request since we have a DMA adapter*/
695         CommonBuffer = HalAllocateCommonBuffer(DeviceExtension->AdapterObject,
696             CommonBufferLength,
697             &DeviceExtension->PhysicalAddress,
698             FALSE );
699     }
700 
701     /* Fail in case of error */
702     if (!CommonBuffer)
703         return STATUS_INSUFFICIENT_RESOURCES;
704 
705     /* Zero it */
706     RtlZeroMemory(CommonBuffer, CommonBufferLength);
707 
708     /* Store its size in Device Extension */
709     DeviceExtension->CommonBufferLength = CommonBufferLength;
710 
711     /* SrbExtension buffer is located at the beginning of the buffer */
712     DeviceExtension->SrbExtensionBuffer = CommonBuffer;
713 
714     /* Non-cached extension buffer is located at the end of
715        the common buffer */
716     if (NonCachedSize)
717     {
718         CommonBufferLength -=  NonCachedSize;
719         DeviceExtension->NonCachedExtension = (PUCHAR)CommonBuffer + CommonBufferLength;
720     }
721     else
722     {
723         DeviceExtension->NonCachedExtension = NULL;
724     }
725 
726     if (DeviceExtension->NeedSrbExtensionAlloc)
727     {
728         /* Look up how many SRB data structures we need */
729         DeviceExtension->SrbDataCount = CommonBufferLength / BufSize;
730 
731         /* Initialize the free SRB extensions list */
732         SrbExtension = (PVOID *)CommonBuffer;
733         DeviceExtension->FreeSrbExtensions = SrbExtension;
734 
735         /* Fill the remaining pointers (if we have more than 1 SRB) */
736         while (CommonBufferLength >= 2 * BufSize)
737         {
738             *SrbExtension = (PVOID*)((PCHAR)SrbExtension + BufSize);
739             SrbExtension = *SrbExtension;
740 
741             CommonBufferLength -= BufSize;
742         }
743     }
744 
745     return STATUS_SUCCESS;
746 }
747 
748 
749 
750 /*
751  * @implemented
752  */
753 PVOID NTAPI
754 ScsiPortGetVirtualAddress(IN PVOID HwDeviceExtension,
755                           IN SCSI_PHYSICAL_ADDRESS PhysicalAddress)
756 {
757     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
758     ULONG Offset;
759 
760     DPRINT("ScsiPortGetVirtualAddress(%p %I64x)\n",
761         HwDeviceExtension, PhysicalAddress.QuadPart);
762 
763     DeviceExtension = CONTAINING_RECORD(HwDeviceExtension,
764                                         SCSI_PORT_DEVICE_EXTENSION,
765                                         MiniPortDeviceExtension);
766 
767     if (DeviceExtension->PhysicalAddress.QuadPart > PhysicalAddress.QuadPart)
768         return NULL;
769 
770     Offset = (ULONG)(PhysicalAddress.QuadPart - DeviceExtension->PhysicalAddress.QuadPart);
771 
772     if (Offset >= DeviceExtension->CommonBufferLength)
773         return NULL;
774 
775     return (PVOID)((ULONG_PTR)DeviceExtension->SrbExtensionBuffer + Offset);
776 }
777 
778 /**********************************************************************
779  * NAME                         EXPORTED
780  *  ScsiPortInitialize
781  *
782  * DESCRIPTION
783  *  Initializes SCSI port driver specific data.
784  *
785  * RUN LEVEL
786  *  PASSIVE_LEVEL
787  *
788  * ARGUMENTS
789  *  Argument1
790  *      Pointer to the miniport driver's driver object.
791  *
792  *  Argument2
793  *      Pointer to the miniport driver's registry path.
794  *
795  *  HwInitializationData
796  *      Pointer to port driver specific configuration data.
797  *
798  *  HwContext
799         Miniport driver specific context.
800  *
801  * RETURN VALUE
802  *  Status.
803  *
804  * @implemented
805  */
806 
807 ULONG NTAPI
808 ScsiPortInitialize(
809     IN PVOID Argument1,
810     IN PVOID Argument2,
811     IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
812     IN PVOID HwContext)
813 {
814     PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Argument1;
815     PUNICODE_STRING RegistryPath = (PUNICODE_STRING)Argument2;
816     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = NULL;
817     PCONFIGURATION_INFORMATION SystemConfig;
818     PPORT_CONFIGURATION_INFORMATION PortConfig;
819     PORT_CONFIGURATION_INFORMATION InitialPortConfig;
820     CONFIGURATION_INFO ConfigInfo;
821     ULONG DeviceExtensionSize;
822     ULONG PortConfigSize;
823     BOOLEAN Again;
824     BOOLEAN DeviceFound = FALSE;
825     BOOLEAN FirstConfigCall = TRUE;
826     ULONG Result;
827     NTSTATUS Status;
828     ULONG MaxBus;
829     PCI_SLOT_NUMBER SlotNumber;
830 
831     PDEVICE_OBJECT PortDeviceObject;
832     WCHAR NameBuffer[80];
833     UNICODE_STRING DeviceName;
834     WCHAR DosNameBuffer[80];
835     UNICODE_STRING DosDeviceName;
836     PIO_SCSI_CAPABILITIES PortCapabilities;
837 
838     PCM_RESOURCE_LIST ResourceList;
839     BOOLEAN Conflict;
840     SIZE_T BusConfigSize;
841 
842 
843     DPRINT ("ScsiPortInitialize() called!\n");
844 
845     /* Check params for validity */
846     if ((HwInitializationData->HwInitialize == NULL) ||
847         (HwInitializationData->HwStartIo == NULL) ||
848         (HwInitializationData->HwInterrupt == NULL) ||
849         (HwInitializationData->HwFindAdapter == NULL) ||
850         (HwInitializationData->HwResetBus == NULL))
851     {
852         return STATUS_INVALID_PARAMETER;
853     }
854 
855     /* Set handlers */
856     DriverObject->DriverStartIo = ScsiPortStartIo;
857     DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiPortCreateClose;
858     DriverObject->MajorFunction[IRP_MJ_CLOSE] = ScsiPortCreateClose;
859     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiPortDeviceControl;
860     DriverObject->MajorFunction[IRP_MJ_SCSI] = ScsiPortDispatchScsi;
861 
862     /* Obtain configuration information */
863     SystemConfig = IoGetConfigurationInformation();
864 
865     /* Zero the internal configuration info structure */
866     RtlZeroMemory(&ConfigInfo, sizeof(CONFIGURATION_INFO));
867 
868     /* Zero starting slot number */
869     SlotNumber.u.AsULONG = 0;
870 
871     /* Allocate space for access ranges */
872     if (HwInitializationData->NumberOfAccessRanges)
873     {
874         ConfigInfo.AccessRanges =
875             ExAllocatePoolWithTag(PagedPool,
876             HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE), TAG_SCSIPORT);
877 
878         /* Fail if failed */
879         if (ConfigInfo.AccessRanges == NULL)
880             return STATUS_INSUFFICIENT_RESOURCES;
881     }
882 
883     /* Open registry keys */
884     SpiInitOpenKeys(&ConfigInfo, (PUNICODE_STRING)Argument2);
885 
886     /* Last adapter number = not known */
887     ConfigInfo.LastAdapterNumber = SP_UNINITIALIZED_VALUE;
888 
889     /* Calculate sizes of DeviceExtension and PortConfig */
890     DeviceExtensionSize = sizeof(SCSI_PORT_DEVICE_EXTENSION) +
891         HwInitializationData->DeviceExtensionSize;
892 
893     MaxBus = (HwInitializationData->AdapterInterfaceType == PCIBus) ? 8 : 1;
894     DPRINT("MaxBus: %lu\n", MaxBus);
895 
896     while (TRUE)
897     {
898         /* Create a unicode device name */
899         swprintf(NameBuffer,
900                  L"\\Device\\ScsiPort%lu",
901                  SystemConfig->ScsiPortCount);
902         RtlInitUnicodeString(&DeviceName, NameBuffer);
903 
904         DPRINT("Creating device: %wZ\n", &DeviceName);
905 
906         /* Create the port device */
907         Status = IoCreateDevice(DriverObject,
908                                 DeviceExtensionSize,
909                                 &DeviceName,
910                                 FILE_DEVICE_CONTROLLER,
911                                 0,
912                                 FALSE,
913                                 &PortDeviceObject);
914 
915         if (!NT_SUCCESS(Status))
916         {
917             DPRINT1("IoCreateDevice call failed! (Status 0x%lX)\n", Status);
918             PortDeviceObject = NULL;
919             break;
920         }
921 
922         DPRINT ("Created device: %wZ (%p)\n", &DeviceName, PortDeviceObject);
923 
924         /* Set the buffering strategy here... */
925         PortDeviceObject->Flags |= DO_DIRECT_IO;
926         PortDeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT; /* FIXME: Is this really needed? */
927 
928         /* Fill Device Extension */
929         DeviceExtension = PortDeviceObject->DeviceExtension;
930         RtlZeroMemory(DeviceExtension, DeviceExtensionSize);
931         DeviceExtension->Length = DeviceExtensionSize;
932         DeviceExtension->DeviceObject = PortDeviceObject;
933         DeviceExtension->PortNumber = SystemConfig->ScsiPortCount;
934 
935         /* Driver's routines... */
936         DeviceExtension->HwInitialize = HwInitializationData->HwInitialize;
937         DeviceExtension->HwStartIo = HwInitializationData->HwStartIo;
938         DeviceExtension->HwInterrupt = HwInitializationData->HwInterrupt;
939         DeviceExtension->HwResetBus = HwInitializationData->HwResetBus;
940         DeviceExtension->HwDmaStarted = HwInitializationData->HwDmaStarted;
941 
942         /* Extensions sizes */
943         DeviceExtension->MiniPortExtensionSize = HwInitializationData->DeviceExtensionSize;
944         DeviceExtension->LunExtensionSize = HwInitializationData->SpecificLuExtensionSize;
945         DeviceExtension->SrbExtensionSize = HwInitializationData->SrbExtensionSize;
946 
947         /* Round Srb extension size to the quadword */
948         DeviceExtension->SrbExtensionSize =
949             ~(sizeof(LONGLONG) - 1) & (DeviceExtension->SrbExtensionSize +
950             sizeof(LONGLONG) - 1);
951 
952         /* Fill some numbers (bus count, lun count, etc) */
953         DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS;
954         DeviceExtension->RequestsNumber = 16;
955 
956         /* Initialize the spin lock in the controller extension */
957         KeInitializeSpinLock(&DeviceExtension->IrqLock);
958         KeInitializeSpinLock(&DeviceExtension->SpinLock);
959 
960         /* Initialize the DPC object */
961         IoInitializeDpcRequest(PortDeviceObject,
962                                ScsiPortDpcForIsr);
963 
964         /* Initialize the device timer */
965         DeviceExtension->TimerCount = -1;
966         IoInitializeTimer(PortDeviceObject,
967                           ScsiPortIoTimer,
968                           DeviceExtension);
969 
970         /* Initialize miniport timer */
971         KeInitializeTimer(&DeviceExtension->MiniportTimer);
972         KeInitializeDpc(&DeviceExtension->MiniportTimerDpc,
973                         SpiMiniportTimerDpc,
974                         PortDeviceObject);
975 
976 CreatePortConfig:
977 
978         Status = SpiCreatePortConfig(DeviceExtension,
979                                      HwInitializationData,
980                                      &ConfigInfo,
981                                      &InitialPortConfig,
982                                      FirstConfigCall);
983 
984         if (!NT_SUCCESS(Status))
985         {
986             DPRINT("SpiCreatePortConfig() failed with Status 0x%08X\n", Status);
987             break;
988         }
989 
990         /* Allocate and initialize port configuration info */
991         PortConfigSize = (sizeof(PORT_CONFIGURATION_INFORMATION) +
992                           HwInitializationData->NumberOfAccessRanges *
993                           sizeof(ACCESS_RANGE) + 7) & ~7;
994         DeviceExtension->PortConfig = ExAllocatePoolWithTag(NonPagedPool, PortConfigSize, TAG_SCSIPORT);
995 
996         /* Fail if failed */
997         if (DeviceExtension->PortConfig == NULL)
998         {
999             Status = STATUS_INSUFFICIENT_RESOURCES;
1000             break;
1001         }
1002 
1003         PortConfig = DeviceExtension->PortConfig;
1004 
1005         /* Copy information here */
1006         RtlCopyMemory(PortConfig,
1007                       &InitialPortConfig,
1008                       sizeof(PORT_CONFIGURATION_INFORMATION));
1009 
1010 
1011         /* Copy extension sizes into the PortConfig */
1012         PortConfig->SpecificLuExtensionSize = DeviceExtension->LunExtensionSize;
1013         PortConfig->SrbExtensionSize = DeviceExtension->SrbExtensionSize;
1014 
1015         /* Initialize Access ranges */
1016         if (HwInitializationData->NumberOfAccessRanges != 0)
1017         {
1018             PortConfig->AccessRanges = (PVOID)(PortConfig+1);
1019 
1020             /* Align to LONGLONG */
1021             PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) + 7);
1022             PortConfig->AccessRanges = (PVOID)((ULONG_PTR)(PortConfig->AccessRanges) & ~7);
1023 
1024             /* Copy the data */
1025             RtlCopyMemory(PortConfig->AccessRanges,
1026                           ConfigInfo.AccessRanges,
1027                           HwInitializationData->NumberOfAccessRanges * sizeof(ACCESS_RANGE));
1028         }
1029 
1030         /* Search for matching PCI device */
1031         if ((HwInitializationData->AdapterInterfaceType == PCIBus) &&
1032             (HwInitializationData->VendorIdLength > 0) &&
1033             (HwInitializationData->VendorId != NULL) &&
1034             (HwInitializationData->DeviceIdLength > 0) && (HwInitializationData->DeviceId != NULL))
1035         {
1036             PortConfig->BusInterruptLevel = 0;
1037 
1038             /* Get PCI device data */
1039             DPRINT(
1040                 "VendorId '%.*s'  DeviceId '%.*s'\n", HwInitializationData->VendorIdLength,
1041                 HwInitializationData->VendorId, HwInitializationData->DeviceIdLength,
1042                 HwInitializationData->DeviceId);
1043 
1044             if (!SpiGetPciConfigData(
1045                     DriverObject, PortDeviceObject, HwInitializationData, PortConfig, RegistryPath,
1046                     ConfigInfo.BusNumber, &SlotNumber))
1047             {
1048                 /* Continue to the next bus, nothing here */
1049                 ConfigInfo.BusNumber++;
1050                 DeviceExtension->PortConfig = NULL;
1051                 ExFreePool(PortConfig);
1052                 Again = FALSE;
1053                 goto CreatePortConfig;
1054             }
1055 
1056             if (!PortConfig->BusInterruptLevel)
1057             {
1058                 /* Bypass this slot, because no interrupt was assigned */
1059                 DeviceExtension->PortConfig = NULL;
1060                 ExFreePool(PortConfig);
1061                 goto CreatePortConfig;
1062             }
1063         }
1064         else
1065         {
1066             DPRINT("Non-pci bus\n");
1067         }
1068 
1069         /* Note: HwFindAdapter is called once for each bus */
1070         Again = FALSE;
1071         DPRINT("Calling HwFindAdapter() for Bus %lu\n", PortConfig->SystemIoBusNumber);
1072         Result = (HwInitializationData->HwFindAdapter)(
1073             &DeviceExtension->MiniPortDeviceExtension, HwContext, 0, /* BusInformation */
1074             ConfigInfo.Parameter,                                    /* ArgumentString */
1075             PortConfig, &Again);
1076 
1077         DPRINT("HwFindAdapter() Result: %lu  Again: %s\n", Result, (Again) ? "True" : "False");
1078 
1079         /* Free MapRegisterBase, it's not needed anymore */
1080         if (DeviceExtension->MapRegisterBase != NULL)
1081         {
1082             ExFreePool(DeviceExtension->MapRegisterBase);
1083             DeviceExtension->MapRegisterBase = NULL;
1084         }
1085 
1086         /* If result is nothing good... */
1087         if (Result != SP_RETURN_FOUND)
1088         {
1089             DPRINT("HwFindAdapter() Result: %lu\n", Result);
1090 
1091             if (Result == SP_RETURN_NOT_FOUND)
1092             {
1093                 /* We can continue on the next bus */
1094                 ConfigInfo.BusNumber++;
1095                 Again = FALSE;
1096 
1097                 DeviceExtension->PortConfig = NULL;
1098                 ExFreePool(PortConfig);
1099                 goto CreatePortConfig;
1100             }
1101 
1102             /* Otherwise, break */
1103             Status = STATUS_INTERNAL_ERROR;
1104             break;
1105         }
1106 
1107         DPRINT(
1108             "ScsiPortInitialize(): Found HBA! (%x), adapter Id %d\n",
1109             PortConfig->BusInterruptVector, PortConfig->InitiatorBusId[0]);
1110 
1111         /* If the SRB extension size was updated */
1112         if (!DeviceExtension->NonCachedExtension &&
1113             (PortConfig->SrbExtensionSize != DeviceExtension->SrbExtensionSize))
1114         {
1115             /* Set it (rounding to LONGLONG again) */
1116             DeviceExtension->SrbExtensionSize =
1117                 (PortConfig->SrbExtensionSize + sizeof(LONGLONG)) & ~(sizeof(LONGLONG) - 1);
1118         }
1119 
1120         /* The same with LUN extension size */
1121         if (PortConfig->SpecificLuExtensionSize != DeviceExtension->LunExtensionSize)
1122             DeviceExtension->LunExtensionSize = PortConfig->SpecificLuExtensionSize;
1123 
1124         if (!((HwInitializationData->AdapterInterfaceType == PCIBus) &&
1125               (HwInitializationData->VendorIdLength > 0) &&
1126               (HwInitializationData->VendorId != NULL) &&
1127               (HwInitializationData->DeviceIdLength > 0) &&
1128               (HwInitializationData->DeviceId != NULL)))
1129         {
1130             /* Construct a resource list */
1131             ResourceList = SpiConfigToResource(DeviceExtension, PortConfig);
1132 
1133             if (ResourceList)
1134             {
1135                 UNICODE_STRING UnicodeString;
1136                 RtlInitUnicodeString(&UnicodeString, L"ScsiAdapter");
1137                 DPRINT("Reporting resources\n");
1138                 Status = IoReportResourceUsage(&UnicodeString,
1139                                                DriverObject,
1140                                                NULL,
1141                                                0,
1142                                                PortDeviceObject,
1143                                                ResourceList,
1144                                                FIELD_OFFSET(CM_RESOURCE_LIST,
1145                                                 List[0].PartialResourceList.PartialDescriptors) +
1146                                                 ResourceList->List[0].PartialResourceList.Count *
1147                                                 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
1148                                                FALSE,
1149                                                &Conflict);
1150                 ExFreePool(ResourceList);
1151 
1152                 /* In case of a failure or a conflict, break */
1153                 if (Conflict || (!NT_SUCCESS(Status)))
1154                 {
1155                     if (Conflict)
1156                         Status = STATUS_CONFLICTING_ADDRESSES;
1157                     break;
1158                 }
1159             }
1160         }
1161 
1162         /* Reset the Conflict var */
1163         Conflict = FALSE;
1164 
1165         /* Copy all stuff which we ever need from PortConfig to the DeviceExtension */
1166         if (PortConfig->MaximumNumberOfTargets > SCSI_MAXIMUM_TARGETS_PER_BUS)
1167             DeviceExtension->MaxTargedIds = SCSI_MAXIMUM_TARGETS_PER_BUS;
1168         else
1169             DeviceExtension->MaxTargedIds = PortConfig->MaximumNumberOfTargets;
1170 
1171         DeviceExtension->BusNum = PortConfig->NumberOfBuses;
1172         DeviceExtension->CachesData = PortConfig->CachesData;
1173         DeviceExtension->ReceiveEvent = PortConfig->ReceiveEvent;
1174         DeviceExtension->SupportsTaggedQueuing = PortConfig->TaggedQueuing;
1175         DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu;
1176 
1177         /* If something was disabled via registry - apply it */
1178         if (ConfigInfo.DisableMultipleLun)
1179             DeviceExtension->MultipleReqsPerLun = PortConfig->MultipleRequestPerLu = FALSE;
1180 
1181         if (ConfigInfo.DisableTaggedQueueing)
1182             DeviceExtension->SupportsTaggedQueuing = PortConfig->MultipleRequestPerLu = FALSE;
1183 
1184         /* Check if we need to alloc SRB data */
1185         if (DeviceExtension->SupportsTaggedQueuing || DeviceExtension->MultipleReqsPerLun)
1186         {
1187             DeviceExtension->NeedSrbDataAlloc = TRUE;
1188         }
1189         else
1190         {
1191             DeviceExtension->NeedSrbDataAlloc = FALSE;
1192         }
1193 
1194         /* Get a pointer to the port capabilities */
1195         PortCapabilities = &DeviceExtension->PortCapabilities;
1196 
1197         /* Copy one field there */
1198         DeviceExtension->MapBuffers = PortConfig->MapBuffers;
1199         PortCapabilities->AdapterUsesPio = PortConfig->MapBuffers;
1200 
1201         if (DeviceExtension->AdapterObject == NULL &&
1202             (PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE || PortConfig->Master))
1203         {
1204             DPRINT1("DMA is not supported yet\n");
1205             ASSERT(FALSE);
1206         }
1207 
1208         if (DeviceExtension->SrbExtensionBuffer == NULL &&
1209             (DeviceExtension->SrbExtensionSize != 0 || PortConfig->AutoRequestSense))
1210         {
1211             DeviceExtension->SupportsAutoSense = PortConfig->AutoRequestSense;
1212             DeviceExtension->NeedSrbExtensionAlloc = TRUE;
1213 
1214             /* Allocate common buffer */
1215             Status = SpiAllocateCommonBuffer(DeviceExtension, 0);
1216 
1217             /* Check for failure */
1218             if (!NT_SUCCESS(Status))
1219                 break;
1220         }
1221 
1222         /* Allocate SrbData, if needed */
1223         if (DeviceExtension->NeedSrbDataAlloc)
1224         {
1225             ULONG Count;
1226             PSCSI_REQUEST_BLOCK_INFO SrbData;
1227 
1228             if (DeviceExtension->SrbDataCount != 0)
1229                 Count = DeviceExtension->SrbDataCount;
1230             else
1231                 Count = DeviceExtension->RequestsNumber * 2;
1232 
1233             /* Allocate the data */
1234             SrbData = ExAllocatePoolWithTag(
1235                 NonPagedPool, Count * sizeof(SCSI_REQUEST_BLOCK_INFO), TAG_SCSIPORT);
1236             if (SrbData == NULL)
1237                 return STATUS_INSUFFICIENT_RESOURCES;
1238 
1239             RtlZeroMemory(SrbData, Count * sizeof(SCSI_REQUEST_BLOCK_INFO));
1240 
1241             DeviceExtension->SrbInfo = SrbData;
1242             DeviceExtension->FreeSrbInfo = SrbData;
1243             DeviceExtension->SrbDataCount = Count;
1244 
1245             /* Link it to the list */
1246             while (Count > 0)
1247             {
1248                 SrbData->Requests.Flink = (PLIST_ENTRY)(SrbData + 1);
1249                 SrbData++;
1250                 Count--;
1251             }
1252 
1253             /* Mark the last entry of the list */
1254             SrbData--;
1255             SrbData->Requests.Flink = NULL;
1256         }
1257 
1258         /* Initialize port capabilities */
1259         PortCapabilities = &DeviceExtension->PortCapabilities;
1260         PortCapabilities->Length = sizeof(IO_SCSI_CAPABILITIES);
1261         PortCapabilities->MaximumTransferLength = PortConfig->MaximumTransferLength;
1262 
1263         if (PortConfig->ReceiveEvent)
1264             PortCapabilities->SupportedAsynchronousEvents |= SRBEV_SCSI_ASYNC_NOTIFICATION;
1265 
1266         PortCapabilities->TaggedQueuing = DeviceExtension->SupportsTaggedQueuing;
1267         PortCapabilities->AdapterScansDown = PortConfig->AdapterScansDown;
1268 
1269         if (PortConfig->AlignmentMask > PortDeviceObject->AlignmentRequirement)
1270             PortDeviceObject->AlignmentRequirement = PortConfig->AlignmentMask;
1271 
1272         PortCapabilities->AlignmentMask = PortDeviceObject->AlignmentRequirement;
1273 
1274         if (PortCapabilities->MaximumPhysicalPages == 0)
1275         {
1276             PortCapabilities->MaximumPhysicalPages =
1277                 BYTES_TO_PAGES(PortCapabilities->MaximumTransferLength);
1278 
1279             /* Apply miniport's limits */
1280             if (PortConfig->NumberOfPhysicalBreaks < PortCapabilities->MaximumPhysicalPages)
1281             {
1282                 PortCapabilities->MaximumPhysicalPages = PortConfig->NumberOfPhysicalBreaks;
1283             }
1284         }
1285 
1286         CallHWInitialize(DeviceExtension);
1287 
1288         /* Start our timer */
1289         IoStartTimer(PortDeviceObject);
1290 
1291         /* Initialize bus scanning information */
1292         BusConfigSize = FIELD_OFFSET(
1293             BUSES_CONFIGURATION_INFORMATION,
1294             BusScanInfo[DeviceExtension->PortConfig->NumberOfBuses]);
1295         DeviceExtension->BusesConfig =
1296             ExAllocatePoolWithTag(PagedPool, BusConfigSize, TAG_SCSIPORT);
1297         if (!DeviceExtension->BusesConfig)
1298         {
1299             DPRINT1("Out of resources!\n");
1300             Status = STATUS_INSUFFICIENT_RESOURCES;
1301             break;
1302         }
1303 
1304         /* Zero it */
1305         RtlZeroMemory(DeviceExtension->BusesConfig, BusConfigSize);
1306 
1307         /* Store number of buses there */
1308         DeviceExtension->BusesConfig->NumberOfBuses = (UCHAR)DeviceExtension->BusNum;
1309 
1310         /* Scan the adapter for devices */
1311         SpiScanAdapter(DeviceExtension);
1312 
1313         /* Build the registry device map */
1314         SpiBuildDeviceMap(DeviceExtension, (PUNICODE_STRING)Argument2);
1315 
1316         /* Create the dos device link */
1317         swprintf(DosNameBuffer, L"\\??\\Scsi%lu:", SystemConfig->ScsiPortCount);
1318         RtlInitUnicodeString(&DosDeviceName, DosNameBuffer);
1319         IoCreateSymbolicLink(&DosDeviceName, &DeviceName);
1320 
1321         /* Increase the port count */
1322         SystemConfig->ScsiPortCount++;
1323         FirstConfigCall = FALSE;
1324 
1325         /* Increase adapter number and bus number respectively */
1326         ConfigInfo.AdapterNumber++;
1327 
1328         if (!Again)
1329             ConfigInfo.BusNumber++;
1330 
1331         DPRINT("Bus: %lu  MaxBus: %lu\n", ConfigInfo.BusNumber, MaxBus);
1332 
1333         DeviceFound = TRUE;
1334     }
1335 
1336     /* Clean up the mess */
1337     SpiCleanupAfterInit(DeviceExtension);
1338 
1339     /* Close registry keys */
1340     if (ConfigInfo.ServiceKey != NULL)
1341         ZwClose(ConfigInfo.ServiceKey);
1342 
1343     if (ConfigInfo.DeviceKey != NULL)
1344         ZwClose(ConfigInfo.DeviceKey);
1345 
1346     if (ConfigInfo.BusKey != NULL)
1347         ZwClose(ConfigInfo.BusKey);
1348 
1349     if (ConfigInfo.AccessRanges != NULL)
1350         ExFreePool(ConfigInfo.AccessRanges);
1351 
1352     if (ConfigInfo.Parameter != NULL)
1353         ExFreePool(ConfigInfo.Parameter);
1354 
1355     DPRINT("ScsiPortInitialize() done, Status = 0x%08X, DeviceFound = %d!\n",
1356         Status, DeviceFound);
1357 
1358     return (DeviceFound == FALSE) ? Status : STATUS_SUCCESS;
1359 }
1360 
1361 /*
1362  * @unimplemented
1363  */
1364 VOID NTAPI
1365 ScsiPortIoMapTransfer(IN PVOID HwDeviceExtension,
1366               IN PSCSI_REQUEST_BLOCK Srb,
1367               IN PVOID LogicalAddress,
1368               IN ULONG Length)
1369 {
1370   DPRINT1("ScsiPortIoMapTransfer()\n");
1371   UNIMPLEMENTED;
1372 }
1373 
1374 /*
1375  * @unimplemented
1376  */
1377 VOID NTAPI
1378 ScsiPortLogError(IN PVOID HwDeviceExtension,
1379          IN PSCSI_REQUEST_BLOCK Srb OPTIONAL,
1380          IN UCHAR PathId,
1381          IN UCHAR TargetId,
1382          IN UCHAR Lun,
1383          IN ULONG ErrorCode,
1384          IN ULONG UniqueId)
1385 {
1386   //PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1387 
1388   DPRINT1("ScsiPortLogError() called\n");
1389   DPRINT1("PathId: 0x%02x  TargetId: 0x%02x  Lun: 0x%02x  ErrorCode: 0x%08lx  UniqueId: 0x%08lx\n",
1390           PathId, TargetId, Lun, ErrorCode, UniqueId);
1391 
1392   //DeviceExtension = CONTAINING_RECORD(HwDeviceExtension, SCSI_PORT_DEVICE_EXTENSION, MiniPortDeviceExtension);
1393 
1394 
1395   DPRINT("ScsiPortLogError() done\n");
1396 }
1397 
1398 /*
1399  * @implemented
1400  */
1401 VOID NTAPI
1402 ScsiPortMoveMemory(OUT PVOID Destination,
1403            IN PVOID Source,
1404            IN ULONG Length)
1405 {
1406   RtlMoveMemory(Destination,
1407         Source,
1408         Length);
1409 }
1410 
1411 
1412 /*
1413  * @implemented
1414  */
1415 VOID
1416 ScsiPortNotification(IN SCSI_NOTIFICATION_TYPE NotificationType, IN PVOID HwDeviceExtension, ...)
1417 {
1418     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
1419     va_list ap;
1420 
1421     DPRINT("ScsiPortNotification() called\n");
1422 
1423     DeviceExtension =
1424         CONTAINING_RECORD(HwDeviceExtension, SCSI_PORT_DEVICE_EXTENSION, MiniPortDeviceExtension);
1425 
1426     DPRINT("DeviceExtension %p\n", DeviceExtension);
1427 
1428     va_start(ap, HwDeviceExtension);
1429 
1430     switch (NotificationType)
1431     {
1432         case RequestComplete:
1433         {
1434             PSCSI_REQUEST_BLOCK Srb;
1435             PSCSI_REQUEST_BLOCK_INFO SrbData;
1436 
1437             Srb = (PSCSI_REQUEST_BLOCK)va_arg(ap, PSCSI_REQUEST_BLOCK);
1438 
1439             DPRINT("Notify: RequestComplete (Srb %p)\n", Srb);
1440 
1441             /* Make sure Srb is alright */
1442             ASSERT(Srb->SrbStatus != SRB_STATUS_PENDING);
1443             ASSERT(
1444                 Srb->Function != SRB_FUNCTION_EXECUTE_SCSI ||
1445                 Srb->SrbStatus != SRB_STATUS_SUCCESS || Srb->ScsiStatus == SCSISTAT_GOOD);
1446 
1447             if (!(Srb->SrbFlags & SRB_FLAGS_IS_ACTIVE))
1448             {
1449                 /* It's been already completed */
1450                 va_end(ap);
1451                 return;
1452             }
1453 
1454             /* It's not active anymore */
1455             Srb->SrbFlags &= ~SRB_FLAGS_IS_ACTIVE;
1456 
1457             if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND)
1458             {
1459                 /* TODO: Treat it specially */
1460                 ASSERT(FALSE);
1461             }
1462             else
1463             {
1464                 /* Get the SRB data */
1465                 SrbData = SpiGetSrbData(
1466                     DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun, Srb->QueueTag);
1467 
1468                 /* Make sure there are no CompletedRequests and there is a Srb */
1469                 ASSERT(SrbData->CompletedRequests == NULL && SrbData->Srb != NULL);
1470 
1471                 /* If it's a read/write request, make sure it has data inside it */
1472                 if ((Srb->SrbStatus == SRB_STATUS_SUCCESS) &&
1473                     ((Srb->Cdb[0] == SCSIOP_READ) || (Srb->Cdb[0] == SCSIOP_WRITE)))
1474                 {
1475                     ASSERT(Srb->DataTransferLength);
1476                 }
1477 
1478                 SrbData->CompletedRequests = DeviceExtension->InterruptData.CompletedRequests;
1479                 DeviceExtension->InterruptData.CompletedRequests = SrbData;
1480             }
1481         }
1482         break;
1483 
1484         case NextRequest:
1485             DPRINT("Notify: NextRequest\n");
1486             DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
1487             break;
1488 
1489         case NextLuRequest:
1490         {
1491             UCHAR PathId;
1492             UCHAR TargetId;
1493             UCHAR Lun;
1494             PSCSI_PORT_LUN_EXTENSION LunExtension;
1495 
1496             PathId = (UCHAR)va_arg(ap, int);
1497             TargetId = (UCHAR)va_arg(ap, int);
1498             Lun = (UCHAR)va_arg(ap, int);
1499 
1500             DPRINT(
1501                 "Notify: NextLuRequest(PathId %u  TargetId %u  Lun %u)\n", PathId, TargetId, Lun);
1502 
1503             /* Mark it in the flags field */
1504             DeviceExtension->InterruptData.Flags |= SCSI_PORT_NEXT_REQUEST_READY;
1505 
1506             /* Get the LUN extension */
1507             LunExtension = SpiGetLunExtension(DeviceExtension, PathId, TargetId, Lun);
1508 
1509             /* If returned LunExtension is NULL, break out */
1510             if (!LunExtension)
1511                 break;
1512 
1513             /* This request should not be processed if */
1514             if ((LunExtension->ReadyLun) || (LunExtension->SrbInfo.Srb))
1515             {
1516                 /* Nothing to do here */
1517                 break;
1518             }
1519 
1520             /* Add this LUN to the list */
1521             LunExtension->ReadyLun = DeviceExtension->InterruptData.ReadyLun;
1522             DeviceExtension->InterruptData.ReadyLun = LunExtension;
1523         }
1524         break;
1525 
1526         case ResetDetected:
1527             DPRINT("Notify: ResetDetected\n");
1528             /* Add RESET flags */
1529             DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET | SCSI_PORT_RESET_REPORTED;
1530             break;
1531 
1532         case CallDisableInterrupts:
1533             DPRINT1("UNIMPLEMENTED SCSI Notification called: CallDisableInterrupts!\n");
1534             break;
1535 
1536         case CallEnableInterrupts:
1537             DPRINT1("UNIMPLEMENTED SCSI Notification called: CallEnableInterrupts!\n");
1538             break;
1539 
1540         case RequestTimerCall:
1541             DPRINT("Notify: RequestTimerCall\n");
1542             DeviceExtension->InterruptData.Flags |= SCSI_PORT_TIMER_NEEDED;
1543             DeviceExtension->InterruptData.HwScsiTimer = (PHW_TIMER)va_arg(ap, PHW_TIMER);
1544             DeviceExtension->InterruptData.MiniportTimerValue = (ULONG)va_arg(ap, ULONG);
1545             break;
1546 
1547         case BusChangeDetected:
1548             DPRINT1("UNIMPLEMENTED SCSI Notification called: BusChangeDetected!\n");
1549             break;
1550 
1551         default:
1552             DPRINT1("Unsupported notification from WMI: %lu\n", NotificationType);
1553             break;
1554     }
1555 
1556     va_end(ap);
1557 
1558     /* Request a DPC after we're done with the interrupt */
1559     DeviceExtension->InterruptData.Flags |= SCSI_PORT_NOTIFICATION_NEEDED;
1560 }
1561 
1562 /*
1563  * @implemented
1564  */
1565 BOOLEAN NTAPI
1566 ScsiPortValidateRange(IN PVOID HwDeviceExtension,
1567               IN INTERFACE_TYPE BusType,
1568               IN ULONG SystemIoBusNumber,
1569               IN SCSI_PHYSICAL_ADDRESS IoAddress,
1570               IN ULONG NumberOfBytes,
1571               IN BOOLEAN InIoSpace)
1572 {
1573   DPRINT("ScsiPortValidateRange()\n");
1574   return(TRUE);
1575 }
1576 
1577 
1578 /* INTERNAL FUNCTIONS ********************************************************/
1579 
1580 static VOID
1581 SpiResourceToConfig(IN PHW_INITIALIZATION_DATA HwInitializationData,
1582                     IN PCM_FULL_RESOURCE_DESCRIPTOR ResourceDescriptor,
1583                     IN PPORT_CONFIGURATION_INFORMATION PortConfig)
1584 {
1585     PACCESS_RANGE AccessRange;
1586     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialData;
1587     ULONG RangeNumber;
1588     ULONG Index;
1589     ULONG Interrupt = 0;
1590     ULONG Dma = 0;
1591 
1592     RangeNumber = 0;
1593 
1594     /* Loop through all entries */
1595     for (Index = 0; Index < ResourceDescriptor->PartialResourceList.Count; Index++)
1596     {
1597         PartialData = &ResourceDescriptor->PartialResourceList.PartialDescriptors[Index];
1598 
1599         switch (PartialData->Type)
1600         {
1601         case CmResourceTypePort:
1602             /* Copy access ranges */
1603             if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
1604             {
1605                 AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);
1606 
1607                 AccessRange->RangeStart = PartialData->u.Port.Start;
1608                 AccessRange->RangeLength = PartialData->u.Port.Length;
1609 
1610                 AccessRange->RangeInMemory = FALSE;
1611                 RangeNumber++;
1612             }
1613             break;
1614 
1615         case CmResourceTypeMemory:
1616             /* Copy access ranges */
1617             if (RangeNumber < HwInitializationData->NumberOfAccessRanges)
1618             {
1619                 AccessRange = &((*(PortConfig->AccessRanges))[RangeNumber]);
1620 
1621                 AccessRange->RangeStart = PartialData->u.Memory.Start;
1622                 AccessRange->RangeLength = PartialData->u.Memory.Length;
1623 
1624                 AccessRange->RangeInMemory = TRUE;
1625                 RangeNumber++;
1626             }
1627             break;
1628 
1629         case CmResourceTypeInterrupt:
1630 
1631             if (Interrupt == 0)
1632             {
1633                 /* Copy interrupt data */
1634                 PortConfig->BusInterruptLevel = PartialData->u.Interrupt.Level;
1635                 PortConfig->BusInterruptVector = PartialData->u.Interrupt.Vector;
1636 
1637                 /* Set interrupt mode accordingly to the resource */
1638                 if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
1639                 {
1640                     PortConfig->InterruptMode = Latched;
1641                 }
1642                 else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
1643                 {
1644                     PortConfig->InterruptMode = LevelSensitive;
1645                 }
1646             }
1647             else if (Interrupt == 1)
1648             {
1649                 /* Copy interrupt data */
1650                 PortConfig->BusInterruptLevel2 = PartialData->u.Interrupt.Level;
1651                 PortConfig->BusInterruptVector2 = PartialData->u.Interrupt.Vector;
1652 
1653                 /* Set interrupt mode accordingly to the resource */
1654                 if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LATCHED)
1655                 {
1656                     PortConfig->InterruptMode2 = Latched;
1657                 }
1658                 else if (PartialData->Flags == CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE)
1659                 {
1660                     PortConfig->InterruptMode2 = LevelSensitive;
1661                 }
1662             }
1663 
1664             Interrupt++;
1665             break;
1666 
1667         case CmResourceTypeDma:
1668 
1669             if (Dma == 0)
1670             {
1671                 PortConfig->DmaChannel = PartialData->u.Dma.Channel;
1672                 PortConfig->DmaPort = PartialData->u.Dma.Port;
1673 
1674                 if (PartialData->Flags & CM_RESOURCE_DMA_8)
1675                     PortConfig->DmaWidth = Width8Bits;
1676                 else if ((PartialData->Flags & CM_RESOURCE_DMA_16) ||
1677                          (PartialData->Flags & CM_RESOURCE_DMA_8_AND_16)) //???
1678                     PortConfig->DmaWidth = Width16Bits;
1679                 else if (PartialData->Flags & CM_RESOURCE_DMA_32)
1680                     PortConfig->DmaWidth = Width32Bits;
1681             }
1682             else if (Dma == 1)
1683             {
1684                 PortConfig->DmaChannel2 = PartialData->u.Dma.Channel;
1685                 PortConfig->DmaPort2 = PartialData->u.Dma.Port;
1686 
1687                 if (PartialData->Flags & CM_RESOURCE_DMA_8)
1688                     PortConfig->DmaWidth2 = Width8Bits;
1689                 else if ((PartialData->Flags & CM_RESOURCE_DMA_16) ||
1690                          (PartialData->Flags & CM_RESOURCE_DMA_8_AND_16)) //???
1691                     PortConfig->DmaWidth2 = Width16Bits;
1692                 else if (PartialData->Flags & CM_RESOURCE_DMA_32)
1693                     PortConfig->DmaWidth2 = Width32Bits;
1694             }
1695             break;
1696         }
1697     }
1698 }
1699 
1700 static PCM_RESOURCE_LIST
1701 SpiConfigToResource(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
1702                     PPORT_CONFIGURATION_INFORMATION PortConfig)
1703 {
1704     PCONFIGURATION_INFORMATION ConfigInfo;
1705     PCM_RESOURCE_LIST ResourceList;
1706     PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
1707     PACCESS_RANGE AccessRange;
1708     ULONG ListLength = 0, i, FullSize;
1709     ULONG Interrupt, Dma;
1710 
1711     /* Get current Atdisk usage from the system */
1712     ConfigInfo = IoGetConfigurationInformation();
1713 
1714     if (PortConfig->AtdiskPrimaryClaimed)
1715         ConfigInfo->AtDiskPrimaryAddressClaimed = TRUE;
1716 
1717     if (PortConfig->AtdiskSecondaryClaimed)
1718         ConfigInfo->AtDiskSecondaryAddressClaimed = TRUE;
1719 
1720     /* Do we use DMA? */
1721     if (PortConfig->DmaChannel != SP_UNINITIALIZED_VALUE ||
1722         PortConfig->DmaPort != SP_UNINITIALIZED_VALUE)
1723     {
1724         Dma = 1;
1725 
1726         if (PortConfig->DmaChannel2 != SP_UNINITIALIZED_VALUE ||
1727             PortConfig->DmaPort2 != SP_UNINITIALIZED_VALUE)
1728             Dma++;
1729     }
1730     else
1731     {
1732         Dma = 0;
1733     }
1734     ListLength += Dma;
1735 
1736     /* How many interrupts to we have? */
1737     Interrupt = DeviceExtension->InterruptCount;
1738     ListLength += Interrupt;
1739 
1740     /* How many access ranges do we use? */
1741     AccessRange = &((*(PortConfig->AccessRanges))[0]);
1742     for (i = 0; i < PortConfig->NumberOfAccessRanges; i++)
1743     {
1744         if (AccessRange->RangeLength != 0)
1745             ListLength++;
1746 
1747         AccessRange++;
1748     }
1749 
1750     /* Allocate the resource list, since we know its size now */
1751     FullSize = sizeof(CM_RESOURCE_LIST) + (ListLength - 1) *
1752         sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
1753 
1754     ResourceList = (PCM_RESOURCE_LIST)ExAllocatePoolWithTag(PagedPool, FullSize, TAG_SCSIPORT);
1755 
1756     if (!ResourceList)
1757         return NULL;
1758 
1759     /* Zero it */
1760     RtlZeroMemory(ResourceList, FullSize);
1761 
1762     /* Initialize it */
1763     ResourceList->Count = 1;
1764     ResourceList->List[0].InterfaceType = PortConfig->AdapterInterfaceType;
1765     ResourceList->List[0].BusNumber = PortConfig->SystemIoBusNumber;
1766     ResourceList->List[0].PartialResourceList.Count = ListLength;
1767     ResourceDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
1768 
1769     /* Copy access ranges array over */
1770     for (i = 0; i < PortConfig->NumberOfAccessRanges; i++)
1771     {
1772         AccessRange = &((*(PortConfig->AccessRanges))[i]);
1773 
1774         /* If the range is empty - skip it */
1775         if (AccessRange->RangeLength == 0)
1776             continue;
1777 
1778         if (AccessRange->RangeInMemory)
1779         {
1780             ResourceDescriptor->Type = CmResourceTypeMemory;
1781             ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
1782         }
1783         else
1784         {
1785             ResourceDescriptor->Type = CmResourceTypePort;
1786             ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
1787         }
1788 
1789         ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1790 
1791         ResourceDescriptor->u.Memory.Start = AccessRange->RangeStart;
1792         ResourceDescriptor->u.Memory.Length = AccessRange->RangeLength;
1793 
1794         ResourceDescriptor++;
1795     }
1796 
1797     /* If we use interrupt(s), copy them */
1798     while (Interrupt)
1799     {
1800         ResourceDescriptor->Type = CmResourceTypeInterrupt;
1801 
1802         if (PortConfig->AdapterInterfaceType == MicroChannel ||
1803             ((Interrupt == 2) ? PortConfig->InterruptMode2 : PortConfig->InterruptMode) == LevelSensitive)
1804         {
1805             ResourceDescriptor->ShareDisposition = CmResourceShareShared;
1806             ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
1807         }
1808         else
1809         {
1810             ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1811             ResourceDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
1812         }
1813 
1814         ResourceDescriptor->u.Interrupt.Level = (Interrupt == 2) ? PortConfig->BusInterruptLevel2 : PortConfig->BusInterruptLevel;
1815         ResourceDescriptor->u.Interrupt.Vector = (Interrupt == 2) ? PortConfig->BusInterruptVector2 : PortConfig->BusInterruptVector;
1816         ResourceDescriptor->u.Interrupt.Affinity = 0;
1817 
1818         ResourceDescriptor++;
1819         Interrupt--;
1820     }
1821 
1822     /* Copy DMA data */
1823     while (Dma)
1824     {
1825         ResourceDescriptor->Type = CmResourceTypeDma;
1826         ResourceDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
1827         ResourceDescriptor->u.Dma.Channel = (Dma == 2) ? PortConfig->DmaChannel2 : PortConfig->DmaChannel;
1828         ResourceDescriptor->u.Dma.Port = (Dma == 2) ? PortConfig->DmaPort2 : PortConfig->DmaPort;
1829         ResourceDescriptor->Flags = 0;
1830 
1831         if (((Dma == 2) ? PortConfig->DmaWidth2 : PortConfig->DmaWidth) == Width8Bits)
1832             ResourceDescriptor->Flags |= CM_RESOURCE_DMA_8;
1833         else if (((Dma == 2) ? PortConfig->DmaWidth2 : PortConfig->DmaWidth) == Width16Bits)
1834             ResourceDescriptor->Flags |= CM_RESOURCE_DMA_16;
1835         else
1836             ResourceDescriptor->Flags |= CM_RESOURCE_DMA_32;
1837 
1838         if (((Dma == 2) ? PortConfig->DmaChannel2 : PortConfig->DmaChannel) == SP_UNINITIALIZED_VALUE)
1839             ResourceDescriptor->u.Dma.Channel = 0;
1840 
1841         if (((Dma == 2) ? PortConfig->DmaPort2 : PortConfig->DmaPort) == SP_UNINITIALIZED_VALUE)
1842             ResourceDescriptor->u.Dma.Port = 0;
1843 
1844         ResourceDescriptor++;
1845         Dma--;
1846     }
1847 
1848     return ResourceList;
1849 }
1850 
1851 
1852 static BOOLEAN
1853 SpiGetPciConfigData(IN PDRIVER_OBJECT DriverObject,
1854                     IN PDEVICE_OBJECT DeviceObject,
1855                     IN struct _HW_INITIALIZATION_DATA *HwInitializationData,
1856                     IN OUT PPORT_CONFIGURATION_INFORMATION PortConfig,
1857                     IN PUNICODE_STRING RegistryPath,
1858                     IN ULONG BusNumber,
1859                     IN OUT PPCI_SLOT_NUMBER NextSlotNumber)
1860 {
1861     PCI_COMMON_CONFIG PciConfig;
1862     PCI_SLOT_NUMBER SlotNumber;
1863     ULONG DataSize;
1864     ULONG DeviceNumber;
1865     ULONG FunctionNumber;
1866     CHAR VendorIdString[8];
1867     CHAR DeviceIdString[8];
1868     UNICODE_STRING UnicodeStr;
1869     PCM_RESOURCE_LIST ResourceList = NULL;
1870     NTSTATUS Status;
1871 
1872     DPRINT ("SpiGetPciConfiguration() called\n");
1873 
1874     SlotNumber.u.AsULONG = 0;
1875 
1876     /* Loop through all devices */
1877     for (DeviceNumber = NextSlotNumber->u.bits.DeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
1878     {
1879         SlotNumber.u.bits.DeviceNumber = DeviceNumber;
1880 
1881         /* Loop through all functions */
1882         for (FunctionNumber = NextSlotNumber->u.bits.FunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
1883         {
1884             SlotNumber.u.bits.FunctionNumber = FunctionNumber;
1885 
1886             /* Get PCI config bytes */
1887             DataSize = HalGetBusData(PCIConfiguration,
1888                                      BusNumber,
1889                                      SlotNumber.u.AsULONG,
1890                                      &PciConfig,
1891                                      sizeof(ULONG));
1892 
1893             /* If result of HalGetBusData is 0, then the bus is wrong */
1894             if (DataSize == 0)
1895                 return FALSE;
1896 
1897             /* Check if result is PCI_INVALID_VENDORID or too small */
1898             if ((DataSize < sizeof(ULONG)) ||
1899                 (PciConfig.VendorID == PCI_INVALID_VENDORID))
1900             {
1901                 /* Continue to try the next function */
1902                 continue;
1903             }
1904 
1905             sprintf (VendorIdString, "%04hx", PciConfig.VendorID);
1906             sprintf (DeviceIdString, "%04hx", PciConfig.DeviceID);
1907 
1908             if (_strnicmp(VendorIdString, HwInitializationData->VendorId, HwInitializationData->VendorIdLength) ||
1909                 _strnicmp(DeviceIdString, HwInitializationData->DeviceId, HwInitializationData->DeviceIdLength))
1910             {
1911                 /* It is not our device */
1912                 continue;
1913             }
1914 
1915             DPRINT("Found device 0x%04hx 0x%04hx at %1lu %2lu %1lu\n",
1916                    PciConfig.VendorID,
1917                    PciConfig.DeviceID,
1918                    BusNumber,
1919                    SlotNumber.u.bits.DeviceNumber,
1920                    SlotNumber.u.bits.FunctionNumber);
1921 
1922 
1923             RtlInitUnicodeString(&UnicodeStr, L"ScsiAdapter");
1924             Status = HalAssignSlotResources(RegistryPath,
1925                                             &UnicodeStr,
1926                                             DriverObject,
1927                                             DeviceObject,
1928                                             PCIBus,
1929                                             BusNumber,
1930                                             SlotNumber.u.AsULONG,
1931                                             &ResourceList);
1932 
1933             if (!NT_SUCCESS(Status))
1934                 break;
1935 
1936             /* Create configuration information */
1937             SpiResourceToConfig(HwInitializationData,
1938                                 ResourceList->List,
1939                                 PortConfig);
1940 
1941             /* Free the resource list */
1942             ExFreePool(ResourceList);
1943 
1944             /* Set dev & fn numbers */
1945             NextSlotNumber->u.bits.DeviceNumber = DeviceNumber;
1946             NextSlotNumber->u.bits.FunctionNumber = FunctionNumber + 1;
1947 
1948             /* Save the slot number */
1949             PortConfig->SlotNumber = SlotNumber.u.AsULONG;
1950 
1951             return TRUE;
1952         }
1953        NextSlotNumber->u.bits.FunctionNumber = 0;
1954     }
1955 
1956     NextSlotNumber->u.bits.DeviceNumber = 0;
1957     DPRINT ("No device found\n");
1958 
1959     return FALSE;
1960 }
1961 
1962 
1963 
1964 /**********************************************************************
1965  * NAME                         INTERNAL
1966  *  ScsiPortCreateClose
1967  *
1968  * DESCRIPTION
1969  *  Answer requests for Create/Close calls: a null operation.
1970  *
1971  * RUN LEVEL
1972  *  PASSIVE_LEVEL
1973  *
1974  * ARGUMENTS
1975  *  DeviceObject
1976  *      Pointer to a device object.
1977  *
1978  *  Irp
1979  *      Pointer to an IRP.
1980  *
1981  * RETURN VALUE
1982  *  Status.
1983  */
1984 
1985 static NTSTATUS NTAPI
1986 ScsiPortCreateClose(IN PDEVICE_OBJECT DeviceObject,
1987                    IN PIRP Irp)
1988 {
1989     DPRINT("ScsiPortCreateClose()\n");
1990 
1991     Irp->IoStatus.Status = STATUS_SUCCESS;
1992     IoCompleteRequest(Irp, IO_NO_INCREMENT);
1993 
1994     return STATUS_SUCCESS;
1995 }
1996 
1997 IO_ALLOCATION_ACTION
1998 NTAPI
1999 SpiAdapterControl(PDEVICE_OBJECT DeviceObject,
2000                   PIRP Irp,
2001                   PVOID MapRegisterBase,
2002                   PVOID Context)
2003 {
2004     PSCSI_REQUEST_BLOCK Srb;
2005     PSCSI_SG_ADDRESS ScatterGatherList;
2006     KIRQL CurrentIrql;
2007     PIO_STACK_LOCATION IrpStack;
2008     ULONG TotalLength = 0;
2009     PSCSI_REQUEST_BLOCK_INFO SrbInfo;
2010     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2011     PUCHAR DataVA;
2012     BOOLEAN WriteToDevice;
2013 
2014     /* Get pointers to SrbInfo and DeviceExtension */
2015     SrbInfo = (PSCSI_REQUEST_BLOCK_INFO)Context;
2016     DeviceExtension = DeviceObject->DeviceExtension;
2017 
2018     /* Get pointer to SRB */
2019     IrpStack = IoGetCurrentIrpStackLocation(Irp);
2020     Srb = (PSCSI_REQUEST_BLOCK)IrpStack->Parameters.Others.Argument1;
2021 
2022     /* Depending on the map registers number, we allocate
2023        either from NonPagedPool, or from our static list */
2024     if (SrbInfo->NumberOfMapRegisters > MAX_SG_LIST)
2025     {
2026         SrbInfo->ScatterGather = ExAllocatePoolWithTag(
2027             NonPagedPool, SrbInfo->NumberOfMapRegisters * sizeof(SCSI_SG_ADDRESS), TAG_SCSIPORT);
2028 
2029         if (SrbInfo->ScatterGather == NULL)
2030             ASSERT(FALSE);
2031 
2032         Srb->SrbFlags |= SRB_FLAGS_SGLIST_FROM_POOL;
2033     }
2034     else
2035     {
2036         SrbInfo->ScatterGather = SrbInfo->ScatterGatherList;
2037     }
2038 
2039     /* Use chosen SG list source */
2040     ScatterGatherList = SrbInfo->ScatterGather;
2041 
2042     /* Save map registers base */
2043     SrbInfo->BaseOfMapRegister = MapRegisterBase;
2044 
2045     /* Determine WriteToDevice flag */
2046     WriteToDevice = Srb->SrbFlags & SRB_FLAGS_DATA_OUT ? TRUE : FALSE;
2047 
2048     /* Get virtual address of the data buffer */
2049     DataVA = (PUCHAR)MmGetMdlVirtualAddress(Irp->MdlAddress) +
2050                 ((PCHAR)Srb->DataBuffer - SrbInfo->DataOffset);
2051 
2052     /* Build the actual SG list */
2053     while (TotalLength < Srb->DataTransferLength)
2054     {
2055         if (!ScatterGatherList)
2056             break;
2057 
2058         ScatterGatherList->Length = Srb->DataTransferLength - TotalLength;
2059         ScatterGatherList->PhysicalAddress = IoMapTransfer(DeviceExtension->AdapterObject,
2060                                                            Irp->MdlAddress,
2061                                                            MapRegisterBase,
2062                                                            DataVA + TotalLength,
2063                                                            &ScatterGatherList->Length,
2064                                                            WriteToDevice);
2065 
2066         TotalLength += ScatterGatherList->Length;
2067         ScatterGatherList++;
2068     }
2069 
2070     /* Schedule an active request */
2071     InterlockedIncrement(&DeviceExtension->ActiveRequestCounter );
2072     KeAcquireSpinLock(&DeviceExtension->SpinLock, &CurrentIrql);
2073     KeSynchronizeExecution(DeviceExtension->Interrupt[0],
2074                            ScsiPortStartPacket,
2075                            DeviceObject);
2076     KeReleaseSpinLock(&DeviceExtension->SpinLock, CurrentIrql);
2077 
2078     return DeallocateObjectKeepRegisters;
2079 }
2080 
2081 BOOLEAN
2082 NTAPI
2083 ScsiPortIsr(
2084     _In_ PKINTERRUPT Interrupt,
2085     _In_ PVOID ServiceContext)
2086 {
2087     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2088 
2089     DPRINT("ScsiPortIsr() called!\n");
2090 
2091     DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ServiceContext;
2092 
2093     /* If interrupts are disabled - we don't expect any */
2094     if (DeviceExtension->InterruptData.Flags & SCSI_PORT_DISABLE_INTERRUPTS)
2095         return FALSE;
2096 
2097     /* Call miniport's HwInterrupt routine */
2098     if (DeviceExtension->HwInterrupt(&DeviceExtension->MiniPortDeviceExtension) == FALSE)
2099     {
2100         /* This interrupt doesn't belong to us */
2101         return FALSE;
2102     }
2103 
2104     /* If flag of notification is set - queue a DPC */
2105     if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
2106     {
2107         IoRequestDpc(DeviceExtension->DeviceObject,
2108                      DeviceExtension->CurrentIrp,
2109                      DeviceExtension);
2110     }
2111 
2112     return TRUE;
2113 }
2114 
2115 BOOLEAN
2116 NTAPI
2117 SpiProcessTimeout(PVOID ServiceContext)
2118 {
2119     PDEVICE_OBJECT DeviceObject = (PDEVICE_OBJECT)ServiceContext;
2120     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
2121     ULONG Bus;
2122 
2123     DPRINT("SpiProcessTimeout() entered\n");
2124 
2125     DeviceExtension->TimerCount = -1;
2126 
2127     if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET)
2128     {
2129         DeviceExtension->InterruptData.Flags &= ~SCSI_PORT_RESET;
2130 
2131         if (DeviceExtension->InterruptData.Flags & SCSI_PORT_RESET_REQUEST)
2132         {
2133             DeviceExtension->InterruptData.Flags &=  ~SCSI_PORT_RESET_REQUEST;
2134             ScsiPortStartPacket(ServiceContext);
2135         }
2136 
2137         return FALSE;
2138     }
2139     else
2140     {
2141         DPRINT("Resetting the bus\n");
2142 
2143         for (Bus = 0; Bus < DeviceExtension->BusNum; Bus++)
2144         {
2145             DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension, Bus);
2146 
2147             /* Reset flags and set reset timeout to 4 seconds */
2148             DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET;
2149             DeviceExtension->TimerCount = 4;
2150         }
2151 
2152         /* If miniport requested - request a dpc for it */
2153         if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
2154             IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
2155     }
2156 
2157     return TRUE;
2158 }
2159 
2160 
2161 BOOLEAN
2162 NTAPI
2163 SpiResetBus(PVOID ServiceContext)
2164 {
2165     PRESETBUS_PARAMS ResetParams = (PRESETBUS_PARAMS)ServiceContext;
2166     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2167 
2168     /* Perform the bus reset */
2169     DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)ResetParams->DeviceExtension;
2170     DeviceExtension->HwResetBus(DeviceExtension->MiniPortDeviceExtension,
2171                                 ResetParams->PathId);
2172 
2173     /* Set flags and start the timer */
2174     DeviceExtension->InterruptData.Flags |= SCSI_PORT_RESET;
2175     DeviceExtension->TimerCount = 4;
2176 
2177     /* If miniport requested - give him a DPC */
2178     if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
2179         IoRequestDpc(DeviceExtension->DeviceObject, NULL, NULL);
2180 
2181     return TRUE;
2182 }
2183 
2184 //    ScsiPortIoTimer
2185 //  DESCRIPTION:
2186 //    This function handles timeouts and other time delayed processing
2187 //
2188 //  RUN LEVEL:
2189 //
2190 //  ARGUMENTS:
2191 //    IN  PDEVICE_OBJECT  DeviceObject  Device object registered with timer
2192 //    IN  PVOID           Context       the Controller extension for the
2193 //                                      controller the device is on
2194 //
2195 static VOID NTAPI
2196 ScsiPortIoTimer(PDEVICE_OBJECT DeviceObject,
2197                 PVOID Context)
2198 {
2199     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2200     PSCSI_PORT_LUN_EXTENSION LunExtension;
2201     ULONG Lun;
2202     PIRP Irp;
2203 
2204     DPRINT("ScsiPortIoTimer()\n");
2205 
2206     DeviceExtension = (PSCSI_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
2207 
2208     /* Protect with the spinlock */
2209     KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
2210 
2211     /* Check timeouts */
2212     if (DeviceExtension->TimerCount > 0)
2213     {
2214         /* Decrease the timeout counter */
2215         DeviceExtension->TimerCount--;
2216 
2217         if (DeviceExtension->TimerCount == 0)
2218         {
2219             /* Timeout, process it */
2220             if (KeSynchronizeExecution(DeviceExtension->Interrupt[0],
2221                                        SpiProcessTimeout,
2222                                        DeviceExtension->DeviceObject))
2223             {
2224                 DPRINT("Error happened during processing timeout, but nothing critical\n");
2225             }
2226         }
2227 
2228         KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
2229 
2230         /* We should exit now, since timeout is processed */
2231         return;
2232     }
2233 
2234     /* Per-Lun scanning of timeouts is needed... */
2235     for (Lun = 0; Lun < LUS_NUMBER; Lun++)
2236     {
2237         LunExtension = DeviceExtension->LunExtensionList[Lun];
2238 
2239         while (LunExtension)
2240         {
2241             if (LunExtension->Flags & LUNEX_BUSY)
2242             {
2243                 if (!(LunExtension->Flags &
2244                     (LUNEX_NEED_REQUEST_SENSE | LUNEX_FROZEN_QUEUE)))
2245                 {
2246                     DPRINT("Retrying busy request\n");
2247 
2248                     /* Clear flags, and retry busy request */
2249                     LunExtension->Flags &= ~(LUNEX_BUSY | LUNEX_FULL_QUEUE);
2250                     Irp = LunExtension->BusyRequest;
2251 
2252                     /* Clearing busy request */
2253                     LunExtension->BusyRequest = NULL;
2254 
2255                     KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
2256 
2257                     IoStartPacket(DeviceObject, Irp, (PULONG)NULL, NULL);
2258 
2259                     KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
2260                 }
2261             }
2262             else if (LunExtension->RequestTimeout == 0)
2263             {
2264                 RESETBUS_PARAMS ResetParams;
2265 
2266                 LunExtension->RequestTimeout = -1;
2267 
2268                 DPRINT("Request timed out, resetting bus\n");
2269 
2270                 /* Pass params to the bus reset routine */
2271                 ResetParams.PathId = LunExtension->PathId;
2272                 ResetParams.DeviceExtension = DeviceExtension;
2273 
2274                 if (!KeSynchronizeExecution(DeviceExtension->Interrupt[0],
2275                                             SpiResetBus,
2276                                             &ResetParams))
2277                 {
2278                     DPRINT1("Reset failed\n");
2279                 }
2280             }
2281             else if (LunExtension->RequestTimeout > 0)
2282             {
2283                 /* Decrement the timeout counter */
2284                 LunExtension->RequestTimeout--;
2285             }
2286 
2287             LunExtension = LunExtension->Next;
2288         }
2289     }
2290 
2291     /* Release the spinlock */
2292     KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
2293 }
2294 
2295 VOID
2296 NTAPI
2297 SpiMiniportTimerDpc(IN struct _KDPC *Dpc,
2298                     IN PVOID DeviceObject,
2299                     IN PVOID SystemArgument1,
2300                     IN PVOID SystemArgument2)
2301 {
2302     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension;
2303 
2304     DPRINT("Miniport timer DPC\n");
2305 
2306     DeviceExtension = ((PDEVICE_OBJECT)DeviceObject)->DeviceExtension;
2307 
2308     /* Acquire the spinlock */
2309     KeAcquireSpinLockAtDpcLevel(&DeviceExtension->SpinLock);
2310 
2311     /* Call the timer routine */
2312     if (DeviceExtension->HwScsiTimer != NULL)
2313     {
2314         DeviceExtension->HwScsiTimer(&DeviceExtension->MiniPortDeviceExtension);
2315     }
2316 
2317     /* Release the spinlock */
2318     KeReleaseSpinLockFromDpcLevel(&DeviceExtension->SpinLock);
2319 
2320     if (DeviceExtension->InterruptData.Flags & SCSI_PORT_NOTIFICATION_NEEDED)
2321     {
2322         ScsiPortDpcForIsr(NULL,
2323                           DeviceExtension->DeviceObject,
2324                           NULL,
2325                           NULL);
2326     }
2327 }
2328 
2329 static NTSTATUS
2330 SpiCreatePortConfig(PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2331                     PHW_INITIALIZATION_DATA HwInitData,
2332                     PCONFIGURATION_INFO InternalConfigInfo,
2333                     PPORT_CONFIGURATION_INFORMATION ConfigInfo,
2334                     BOOLEAN ZeroStruct)
2335 {
2336     UNICODE_STRING UnicodeString;
2337     OBJECT_ATTRIBUTES ObjectAttributes;
2338     PCONFIGURATION_INFORMATION DdkConfigInformation;
2339     HANDLE RootKey, Key;
2340     BOOLEAN Found;
2341     WCHAR DeviceBuffer[16];
2342     WCHAR StrBuffer[512];
2343     ULONG Bus;
2344     NTSTATUS Status;
2345 
2346     /* Zero out the struct if told so */
2347     if (ZeroStruct)
2348     {
2349         /* First zero the portconfig */
2350         RtlZeroMemory(ConfigInfo, sizeof(PORT_CONFIGURATION_INFORMATION));
2351 
2352         /* Then access ranges */
2353         RtlZeroMemory(InternalConfigInfo->AccessRanges,
2354                       HwInitData->NumberOfAccessRanges * sizeof(ACCESS_RANGE));
2355 
2356         /* Initialize the struct */
2357         ConfigInfo->Length = sizeof(PORT_CONFIGURATION_INFORMATION);
2358         ConfigInfo->AdapterInterfaceType = HwInitData->AdapterInterfaceType;
2359         ConfigInfo->InterruptMode = Latched;
2360         ConfigInfo->DmaChannel = SP_UNINITIALIZED_VALUE;
2361         ConfigInfo->DmaPort = SP_UNINITIALIZED_VALUE;
2362         ConfigInfo->DmaChannel2 = SP_UNINITIALIZED_VALUE;
2363         ConfigInfo->DmaPort2 = SP_UNINITIALIZED_VALUE;
2364         ConfigInfo->MaximumTransferLength = SP_UNINITIALIZED_VALUE;
2365         ConfigInfo->NumberOfAccessRanges = HwInitData->NumberOfAccessRanges;
2366         ConfigInfo->MaximumNumberOfTargets = 8;
2367 
2368         /* Store parameters */
2369         ConfigInfo->NeedPhysicalAddresses = HwInitData->NeedPhysicalAddresses;
2370         ConfigInfo->MapBuffers = HwInitData->MapBuffers;
2371         ConfigInfo->AutoRequestSense = HwInitData->AutoRequestSense;
2372         ConfigInfo->ReceiveEvent = HwInitData->ReceiveEvent;
2373         ConfigInfo->TaggedQueuing = HwInitData->TaggedQueuing;
2374         ConfigInfo->MultipleRequestPerLu = HwInitData->MultipleRequestPerLu;
2375 
2376         /* Get the disk usage */
2377         DdkConfigInformation = IoGetConfigurationInformation();
2378         ConfigInfo->AtdiskPrimaryClaimed = DdkConfigInformation->AtDiskPrimaryAddressClaimed;
2379         ConfigInfo->AtdiskSecondaryClaimed = DdkConfigInformation->AtDiskSecondaryAddressClaimed;
2380 
2381         /* Initiator bus id is not set */
2382         for (Bus = 0; Bus < 8; Bus++)
2383             ConfigInfo->InitiatorBusId[Bus] = (CCHAR)SP_UNINITIALIZED_VALUE;
2384     }
2385 
2386     ConfigInfo->NumberOfPhysicalBreaks = 17;
2387 
2388     /* Clear this information */
2389     InternalConfigInfo->DisableTaggedQueueing = FALSE;
2390     InternalConfigInfo->DisableMultipleLun = FALSE;
2391 
2392     /* Store Bus Number */
2393     ConfigInfo->SystemIoBusNumber = InternalConfigInfo->BusNumber;
2394 
2395 TryNextAd:
2396 
2397     if (ConfigInfo->AdapterInterfaceType == Internal)
2398     {
2399         /* Open registry key for HW database */
2400         InitializeObjectAttributes(&ObjectAttributes,
2401                                    DeviceExtension->DeviceObject->DriverObject->HardwareDatabase,
2402                                    OBJ_CASE_INSENSITIVE,
2403                                    NULL,
2404                                    NULL);
2405 
2406         Status = ZwOpenKey(&RootKey,
2407                            KEY_READ,
2408                            &ObjectAttributes);
2409 
2410         if (NT_SUCCESS(Status))
2411         {
2412             /* Create name for it */
2413             swprintf(StrBuffer, L"ScsiAdapter\\%lu",
2414                 InternalConfigInfo->AdapterNumber);
2415 
2416             RtlInitUnicodeString(&UnicodeString, StrBuffer);
2417 
2418             /* Open device key */
2419             InitializeObjectAttributes(&ObjectAttributes,
2420                                        &UnicodeString,
2421                                        OBJ_CASE_INSENSITIVE,
2422                                        RootKey,
2423                                        NULL);
2424 
2425             Status = ZwOpenKey(&Key,
2426                                KEY_READ,
2427                                &ObjectAttributes);
2428 
2429             ZwClose(RootKey);
2430 
2431             if (NT_SUCCESS(Status))
2432             {
2433                 if (InternalConfigInfo->LastAdapterNumber != InternalConfigInfo->AdapterNumber)
2434                 {
2435                     DPRINT("Hardware info found at %S\n", StrBuffer);
2436 
2437                     /* Parse it */
2438                     SpiParseDeviceInfo(DeviceExtension,
2439                                        Key,
2440                                        ConfigInfo,
2441                                        InternalConfigInfo,
2442                                        (PUCHAR)StrBuffer);
2443 
2444                      InternalConfigInfo->BusNumber = 0;
2445                 }
2446                 else
2447                 {
2448                     /* Try the next adapter */
2449                     InternalConfigInfo->AdapterNumber++;
2450                     goto TryNextAd;
2451                 }
2452             }
2453             else
2454             {
2455                 /* Info was not found, exit */
2456                 DPRINT1("ZwOpenKey() failed with Status=0x%08X\n", Status);
2457                 return STATUS_DEVICE_DOES_NOT_EXIST;
2458             }
2459         }
2460         else
2461         {
2462             DPRINT1("ZwOpenKey() failed with Status=0x%08X\n", Status);
2463         }
2464     }
2465 
2466     /* Look at device params */
2467     Key = NULL;
2468     if (InternalConfigInfo->Parameter)
2469     {
2470         ExFreePool(InternalConfigInfo->Parameter);
2471         InternalConfigInfo->Parameter = NULL;
2472     }
2473 
2474     if (InternalConfigInfo->ServiceKey != NULL)
2475     {
2476         swprintf(DeviceBuffer, L"Device%lu", InternalConfigInfo->AdapterNumber);
2477         RtlInitUnicodeString(&UnicodeString, DeviceBuffer);
2478 
2479         /* Open the service key */
2480         InitializeObjectAttributes(&ObjectAttributes,
2481                                    &UnicodeString,
2482                                    OBJ_CASE_INSENSITIVE,
2483                                    InternalConfigInfo->ServiceKey,
2484                                    NULL);
2485 
2486         Status = ZwOpenKey(&Key,
2487                            KEY_READ,
2488                            &ObjectAttributes);
2489     }
2490 
2491     /* Parse device key */
2492     if (InternalConfigInfo->DeviceKey != NULL)
2493     {
2494         SpiParseDeviceInfo(DeviceExtension,
2495                            InternalConfigInfo->DeviceKey,
2496                            ConfigInfo,
2497                            InternalConfigInfo,
2498                            (PUCHAR)StrBuffer);
2499     }
2500 
2501     /* Then parse hw info */
2502     if (Key != NULL)
2503     {
2504         if (InternalConfigInfo->LastAdapterNumber != InternalConfigInfo->AdapterNumber)
2505         {
2506             SpiParseDeviceInfo(DeviceExtension,
2507                                Key,
2508                                ConfigInfo,
2509                                InternalConfigInfo,
2510                                (PUCHAR)StrBuffer);
2511 
2512             /* Close the key */
2513             ZwClose(Key);
2514         }
2515         else
2516         {
2517             /* Adapter not found, go try the next one */
2518             InternalConfigInfo->AdapterNumber++;
2519 
2520             /* Close the key */
2521             ZwClose(Key);
2522 
2523             goto TryNextAd;
2524         }
2525     }
2526 
2527     /* Update the last adapter number */
2528     InternalConfigInfo->LastAdapterNumber = InternalConfigInfo->AdapterNumber;
2529 
2530     /* Do we have this kind of bus at all? */
2531     Found = FALSE;
2532     Status = IoQueryDeviceDescription(&HwInitData->AdapterInterfaceType,
2533                                       &InternalConfigInfo->BusNumber,
2534                                       NULL,
2535                                       NULL,
2536                                       NULL,
2537                                       NULL,
2538                                       SpQueryDeviceCallout,
2539                                       &Found);
2540 
2541     /* This bus was not found */
2542     if (!Found)
2543     {
2544         INTERFACE_TYPE InterfaceType = Eisa;
2545 
2546         /* Check for EISA */
2547         if (HwInitData->AdapterInterfaceType == Isa)
2548         {
2549             Status = IoQueryDeviceDescription(&InterfaceType,
2550                                               &InternalConfigInfo->BusNumber,
2551                                               NULL,
2552                                               NULL,
2553                                               NULL,
2554                                               NULL,
2555                                               SpQueryDeviceCallout,
2556                                               &Found);
2557 
2558             /* Return respectively */
2559             if (Found)
2560                 return STATUS_SUCCESS;
2561             else
2562                 return STATUS_DEVICE_DOES_NOT_EXIST;
2563         }
2564         else
2565         {
2566             return STATUS_DEVICE_DOES_NOT_EXIST;
2567         }
2568     }
2569     else
2570     {
2571         return STATUS_SUCCESS;
2572     }
2573 }
2574 
2575 static VOID
2576 SpiParseDeviceInfo(IN PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
2577                    IN HANDLE Key,
2578                    IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
2579                    IN PCONFIGURATION_INFO InternalConfigInfo,
2580                    IN PUCHAR Buffer)
2581 {
2582     PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
2583     PCM_FULL_RESOURCE_DESCRIPTOR FullResource;
2584     PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
2585     PCM_SCSI_DEVICE_DATA ScsiDeviceData;
2586     ULONG Length, Count, Dma = 0, Interrupt = 0;
2587     ULONG Index = 0, RangeCount = 0;
2588     UNICODE_STRING UnicodeString;
2589     ANSI_STRING AnsiString;
2590     NTSTATUS Status = STATUS_SUCCESS;
2591 
2592 
2593     KeyValueInformation = (PKEY_VALUE_FULL_INFORMATION) Buffer;
2594 
2595     /* Loop through all values in the device node */
2596     while(TRUE)
2597     {
2598         Status = ZwEnumerateValueKey(Key,
2599                                      Index,
2600                                      KeyValueFullInformation,
2601                                      Buffer,
2602                                      512,
2603                                      &Length);
2604 
2605         if (!NT_SUCCESS(Status))
2606             return;
2607 
2608         Index++;
2609 
2610         /* Length for DWORD is ok? */
2611         if (KeyValueInformation->Type == REG_DWORD &&
2612             KeyValueInformation->DataLength != sizeof(ULONG))
2613         {
2614             continue;
2615         }
2616 
2617         /* Get MaximumLogicalUnit */
2618         if (_wcsnicmp(KeyValueInformation->Name, L"MaximumLogicalUnit",
2619             KeyValueInformation->NameLength/2) == 0)
2620         {
2621 
2622             if (KeyValueInformation->Type != REG_DWORD)
2623             {
2624                 DPRINT("Bad data type for MaximumLogicalUnit\n");
2625                 continue;
2626             }
2627 
2628             DeviceExtension->MaxLunCount = *((PUCHAR)
2629                 (Buffer + KeyValueInformation->DataOffset));
2630 
2631             /* Check / reset if needed */
2632             if (DeviceExtension->MaxLunCount > SCSI_MAXIMUM_LOGICAL_UNITS)
2633                 DeviceExtension->MaxLunCount = SCSI_MAXIMUM_LOGICAL_UNITS;
2634 
2635             DPRINT("MaximumLogicalUnit = %d\n", DeviceExtension->MaxLunCount);
2636         }
2637 
2638         /* Get InitiatorTargetId */
2639         if (_wcsnicmp(KeyValueInformation->Name, L"InitiatorTargetId",
2640             KeyValueInformation->NameLength / 2) == 0)
2641         {
2642 
2643             if (KeyValueInformation->Type != REG_DWORD)
2644             {
2645                 DPRINT("Bad data type for InitiatorTargetId\n");
2646                 continue;
2647             }
2648 
2649             ConfigInfo->InitiatorBusId[0] = *((PUCHAR)
2650                 (Buffer + KeyValueInformation->DataOffset));
2651 
2652             /* Check / reset if needed */
2653             if (ConfigInfo->InitiatorBusId[0] > ConfigInfo->MaximumNumberOfTargets - 1)
2654                 ConfigInfo->InitiatorBusId[0] = (CCHAR)-1;
2655 
2656             DPRINT("InitiatorTargetId = %d\n", ConfigInfo->InitiatorBusId[0]);
2657         }
2658 
2659         /* Get ScsiDebug */
2660         if (_wcsnicmp(KeyValueInformation->Name, L"ScsiDebug",
2661             KeyValueInformation->NameLength/2) == 0)
2662         {
2663             DPRINT("ScsiDebug key not supported\n");
2664         }
2665 
2666         /* Check for a breakpoint */
2667         if (_wcsnicmp(KeyValueInformation->Name, L"BreakPointOnEntry",
2668             KeyValueInformation->NameLength/2) == 0)
2669         {
2670             DPRINT1("Breakpoint on entry requested!\n");
2671             DbgBreakPoint();
2672         }
2673 
2674         /* Get DisableSynchronousTransfers */
2675         if (_wcsnicmp(KeyValueInformation->Name, L"DisableSynchronousTransfers",
2676             KeyValueInformation->NameLength/2) == 0)
2677         {
2678             DeviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
2679             DPRINT("Synch transfers disabled\n");
2680         }
2681 
2682         /* Get DisableDisconnects */
2683         if (_wcsnicmp(KeyValueInformation->Name, L"DisableDisconnects",
2684             KeyValueInformation->NameLength/2) == 0)
2685         {
2686             DeviceExtension->SrbFlags |= SRB_FLAGS_DISABLE_DISCONNECT;
2687             DPRINT("Disconnects disabled\n");
2688         }
2689 
2690         /* Get DisableTaggedQueuing */
2691         if (_wcsnicmp(KeyValueInformation->Name, L"DisableTaggedQueuing",
2692             KeyValueInformation->NameLength/2) == 0)
2693         {
2694             InternalConfigInfo->DisableTaggedQueueing = TRUE;
2695             DPRINT("Tagged queueing disabled\n");
2696         }
2697 
2698         /* Get DisableMultipleRequests */
2699         if (_wcsnicmp(KeyValueInformation->Name, L"DisableMultipleRequests",
2700             KeyValueInformation->NameLength/2) == 0)
2701         {
2702             InternalConfigInfo->DisableMultipleLun = TRUE;
2703             DPRINT("Multiple requests disabled\n");
2704         }
2705 
2706         /* Get DriverParameters */
2707         if (_wcsnicmp(KeyValueInformation->Name, L"DriverParameters",
2708             KeyValueInformation->NameLength/2) == 0)
2709         {
2710             /* Skip if nothing */
2711             if (KeyValueInformation->DataLength == 0)
2712                 continue;
2713 
2714             /* If there was something previously allocated - free it */
2715             if (InternalConfigInfo->Parameter != NULL)
2716                 ExFreePool(InternalConfigInfo->Parameter);
2717 
2718             /* Allocate it */
2719             InternalConfigInfo->Parameter = ExAllocatePoolWithTag(NonPagedPool,
2720                                                            KeyValueInformation->DataLength, TAG_SCSIPORT);
2721 
2722             if (InternalConfigInfo->Parameter != NULL)
2723             {
2724                 if (KeyValueInformation->Type != REG_SZ)
2725                 {
2726                     /* Just copy */
2727                     RtlCopyMemory(
2728                         InternalConfigInfo->Parameter,
2729                         (PCCHAR)KeyValueInformation + KeyValueInformation->DataOffset,
2730                         KeyValueInformation->DataLength);
2731                 }
2732                 else
2733                 {
2734                     /* If it's a unicode string, convert it to ansi */
2735                     UnicodeString.Length = (USHORT)KeyValueInformation->DataLength;
2736                     UnicodeString.MaximumLength = (USHORT)KeyValueInformation->DataLength;
2737                     UnicodeString.Buffer =
2738                         (PWSTR)((PCCHAR)KeyValueInformation + KeyValueInformation->DataOffset);
2739 
2740                     AnsiString.Length = 0;
2741                     AnsiString.MaximumLength = (USHORT)KeyValueInformation->DataLength;
2742                     AnsiString.Buffer = (PCHAR)InternalConfigInfo->Parameter;
2743 
2744                     Status = RtlUnicodeStringToAnsiString(&AnsiString,
2745                                                           &UnicodeString,
2746                                                           FALSE);
2747 
2748                     /* In case of error, free the allocated space */
2749                     if (!NT_SUCCESS(Status))
2750                     {
2751                         ExFreePool(InternalConfigInfo->Parameter);
2752                         InternalConfigInfo->Parameter = NULL;
2753                     }
2754 
2755                 }
2756             }
2757 
2758             DPRINT("Found driver parameter\n");
2759         }
2760 
2761         /* Get MaximumSGList */
2762         if (_wcsnicmp(KeyValueInformation->Name, L"MaximumSGList",
2763             KeyValueInformation->NameLength/2) == 0)
2764         {
2765             if (KeyValueInformation->Type != REG_DWORD)
2766             {
2767                 DPRINT("Bad data type for MaximumSGList\n");
2768                 continue;
2769             }
2770 
2771             ConfigInfo->NumberOfPhysicalBreaks = *((PUCHAR)(Buffer + KeyValueInformation->DataOffset));
2772 
2773             /* Check / fix */
2774             if (ConfigInfo->NumberOfPhysicalBreaks > SCSI_MAXIMUM_PHYSICAL_BREAKS)
2775             {
2776                 ConfigInfo->NumberOfPhysicalBreaks = SCSI_MAXIMUM_PHYSICAL_BREAKS;
2777             }
2778             else if (ConfigInfo->NumberOfPhysicalBreaks < SCSI_MINIMUM_PHYSICAL_BREAKS)
2779             {
2780                 ConfigInfo->NumberOfPhysicalBreaks = SCSI_MINIMUM_PHYSICAL_BREAKS;
2781             }
2782 
2783             DPRINT("MaximumSGList = %d\n", ConfigInfo->NumberOfPhysicalBreaks);
2784         }
2785 
2786         /* Get NumberOfRequests */
2787         if (_wcsnicmp(KeyValueInformation->Name, L"NumberOfRequests",
2788             KeyValueInformation->NameLength/2) == 0)
2789         {
2790             if (KeyValueInformation->Type != REG_DWORD)
2791             {
2792                 DPRINT("NumberOfRequests has wrong data type\n");
2793                 continue;
2794             }
2795 
2796             DeviceExtension->RequestsNumber = *((PUCHAR)(Buffer + KeyValueInformation->DataOffset));
2797 
2798             /* Check / fix */
2799             if (DeviceExtension->RequestsNumber < 16)
2800             {
2801                 DeviceExtension->RequestsNumber = 16;
2802             }
2803             else if (DeviceExtension->RequestsNumber > 512)
2804             {
2805                 DeviceExtension->RequestsNumber = 512;
2806             }
2807 
2808             DPRINT("Number Of Requests = %d\n", DeviceExtension->RequestsNumber);
2809         }
2810 
2811         /* Get resource list */
2812         if (_wcsnicmp(KeyValueInformation->Name, L"ResourceList",
2813                 KeyValueInformation->NameLength/2) == 0 ||
2814             _wcsnicmp(KeyValueInformation->Name, L"Configuration Data",
2815                 KeyValueInformation->NameLength/2) == 0 )
2816         {
2817             if (KeyValueInformation->Type != REG_FULL_RESOURCE_DESCRIPTOR ||
2818                 KeyValueInformation->DataLength < sizeof(REG_FULL_RESOURCE_DESCRIPTOR))
2819             {
2820                 DPRINT("Bad data type for ResourceList\n");
2821                 continue;
2822             }
2823             else
2824             {
2825                 DPRINT("Found ResourceList\n");
2826             }
2827 
2828             FullResource = (PCM_FULL_RESOURCE_DESCRIPTOR)(Buffer + KeyValueInformation->DataOffset);
2829 
2830             /* Copy some info from it */
2831             InternalConfigInfo->BusNumber = FullResource->BusNumber;
2832             ConfigInfo->SystemIoBusNumber = FullResource->BusNumber;
2833 
2834             /* Loop through it */
2835             for (Count = 0; Count < FullResource->PartialResourceList.Count; Count++)
2836             {
2837                 /* Get partial descriptor */
2838                 PartialDescriptor =
2839                     &FullResource->PartialResourceList.PartialDescriptors[Count];
2840 
2841                 /* Check datalength */
2842                 if ((ULONG)((PCHAR)(PartialDescriptor + 1) -
2843                     (PCHAR)FullResource) > KeyValueInformation->DataLength)
2844                 {
2845                     DPRINT("Resource data is of incorrect size\n");
2846                     break;
2847                 }
2848 
2849                 switch (PartialDescriptor->Type)
2850                 {
2851                 case CmResourceTypePort:
2852                     if (RangeCount >= ConfigInfo->NumberOfAccessRanges)
2853                     {
2854                         DPRINT("Too many access ranges\n");
2855                         continue;
2856                     }
2857 
2858                     InternalConfigInfo->AccessRanges[RangeCount].RangeInMemory = FALSE;
2859                     InternalConfigInfo->AccessRanges[RangeCount].RangeStart = PartialDescriptor->u.Port.Start;
2860                     InternalConfigInfo->AccessRanges[RangeCount].RangeLength = PartialDescriptor->u.Port.Length;
2861                     RangeCount++;
2862 
2863                     break;
2864 
2865                 case CmResourceTypeMemory:
2866                     if (RangeCount >= ConfigInfo->NumberOfAccessRanges)
2867                     {
2868                         DPRINT("Too many access ranges\n");
2869                         continue;
2870                     }
2871 
2872                     InternalConfigInfo->AccessRanges[RangeCount].RangeInMemory = TRUE;
2873                     InternalConfigInfo->AccessRanges[RangeCount].RangeStart = PartialDescriptor->u.Memory.Start;
2874                     InternalConfigInfo->AccessRanges[RangeCount].RangeLength = PartialDescriptor->u.Memory.Length;
2875                     RangeCount++;
2876 
2877                     break;
2878 
2879                 case CmResourceTypeInterrupt:
2880 
2881                     if (Interrupt == 0)
2882                     {
2883                         ConfigInfo->BusInterruptLevel =
2884                             PartialDescriptor->u.Interrupt.Level;
2885 
2886                         ConfigInfo->BusInterruptVector =
2887                             PartialDescriptor->u.Interrupt.Vector;
2888 
2889                         ConfigInfo->InterruptMode = (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
2890                     }
2891                     else if (Interrupt == 1)
2892                     {
2893                         ConfigInfo->BusInterruptLevel2 =
2894                         PartialDescriptor->u.Interrupt.Level;
2895 
2896                         ConfigInfo->BusInterruptVector2 =
2897                         PartialDescriptor->u.Interrupt.Vector;
2898 
2899                         ConfigInfo->InterruptMode2 = (PartialDescriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ? Latched : LevelSensitive;
2900                     }
2901 
2902                     Interrupt++;
2903                     break;
2904 
2905                 case CmResourceTypeDma:
2906 
2907                     if (Dma == 0)
2908                     {
2909                         ConfigInfo->DmaChannel = PartialDescriptor->u.Dma.Channel;
2910                         ConfigInfo->DmaPort = PartialDescriptor->u.Dma.Port;
2911 
2912                         if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8)
2913                             ConfigInfo->DmaWidth = Width8Bits;
2914                         else if ((PartialDescriptor->Flags & CM_RESOURCE_DMA_16) ||
2915                                  (PartialDescriptor->Flags & CM_RESOURCE_DMA_8_AND_16)) //???
2916                             ConfigInfo->DmaWidth = Width16Bits;
2917                         else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32)
2918                             ConfigInfo->DmaWidth = Width32Bits;
2919                     }
2920                     else if (Dma == 1)
2921                     {
2922                         ConfigInfo->DmaChannel2 = PartialDescriptor->u.Dma.Channel;
2923                         ConfigInfo->DmaPort2 = PartialDescriptor->u.Dma.Port;
2924 
2925                         if (PartialDescriptor->Flags & CM_RESOURCE_DMA_8)
2926                             ConfigInfo->DmaWidth2 = Width8Bits;
2927                         else if ((PartialDescriptor->Flags & CM_RESOURCE_DMA_16) ||
2928                                  (PartialDescriptor->Flags & CM_RESOURCE_DMA_8_AND_16)) //???
2929                             ConfigInfo->DmaWidth2 = Width16Bits;
2930                         else if (PartialDescriptor->Flags & CM_RESOURCE_DMA_32)
2931                             ConfigInfo->DmaWidth2 = Width32Bits;
2932                     }
2933 
2934                     Dma++;
2935                     break;
2936 
2937                 case CmResourceTypeDeviceSpecific:
2938                     if (PartialDescriptor->u.DeviceSpecificData.DataSize <
2939                         sizeof(CM_SCSI_DEVICE_DATA) ||
2940                         (PCHAR) (PartialDescriptor + 1) - (PCHAR)FullResource +
2941                         PartialDescriptor->u.DeviceSpecificData.DataSize >
2942                         KeyValueInformation->DataLength)
2943                     {
2944                         DPRINT("Resource data length is incorrect");
2945                         break;
2946                     }
2947 
2948                     /* Set only one field from it */
2949                     ScsiDeviceData = (PCM_SCSI_DEVICE_DATA) (PartialDescriptor+1);
2950                     ConfigInfo->InitiatorBusId[0] = ScsiDeviceData->HostIdentifier;
2951                     break;
2952                 }
2953             }
2954         }
2955     }
2956 }
2957 
2958 NTSTATUS
2959 NTAPI
2960 SpQueryDeviceCallout(IN PVOID  Context,
2961                      IN PUNICODE_STRING  PathName,
2962                      IN INTERFACE_TYPE  BusType,
2963                      IN ULONG  BusNumber,
2964                      IN PKEY_VALUE_FULL_INFORMATION  *BusInformation,
2965                      IN CONFIGURATION_TYPE  ControllerType,
2966                      IN ULONG  ControllerNumber,
2967                      IN PKEY_VALUE_FULL_INFORMATION  *ControllerInformation,
2968                      IN CONFIGURATION_TYPE  PeripheralType,
2969                      IN ULONG  PeripheralNumber,
2970                      IN PKEY_VALUE_FULL_INFORMATION  *PeripheralInformation)
2971 {
2972     PBOOLEAN Found = (PBOOLEAN)Context;
2973     /* We just set our Found variable to TRUE */
2974 
2975     *Found = TRUE;
2976     return STATUS_SUCCESS;
2977 }
2978 
2979 IO_ALLOCATION_ACTION
2980 NTAPI
2981 ScsiPortAllocateAdapterChannel(IN PDEVICE_OBJECT DeviceObject,
2982                                IN PIRP Irp,
2983                                IN PVOID MapRegisterBase,
2984                                IN PVOID Context)
2985 {
2986     KIRQL Irql;
2987     PSCSI_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
2988 
2989     /* Guard access with the spinlock */
2990     KeAcquireSpinLock(&DeviceExtension->SpinLock, &Irql);
2991 
2992     /* Save MapRegisterBase we've got here */
2993     DeviceExtension->MapRegisterBase = MapRegisterBase;
2994 
2995     /* Start pending request */
2996     KeSynchronizeExecution(DeviceExtension->Interrupt[0],
2997         ScsiPortStartPacket, DeviceObject);
2998 
2999     /* Release spinlock we took */
3000     KeReleaseSpinLock(&DeviceExtension->SpinLock, Irql);
3001 
3002     return KeepObject;
3003 }
3004 
3005 #undef ScsiPortConvertPhysicalAddressToUlong
3006 /*
3007  * @implemented
3008  */
3009 ULONG NTAPI
3010 ScsiPortConvertPhysicalAddressToUlong(IN SCSI_PHYSICAL_ADDRESS Address)
3011 {
3012   DPRINT("ScsiPortConvertPhysicalAddressToUlong()\n");
3013   return(Address.u.LowPart);
3014 }
3015 
3016 /* EOF */
3017