1 /*++
2 
3 Copyright (c) 2002-2016 Alexandr A. Telyatnikov (Alter)
4 
5 Module Name:
6     id_probe.cpp
7 
8 Abstract:
9     This module scans PCI and ISA buses for IDE controllers
10     and determines their Busmaster DMA capabilities
11 
12 Author:
13     Alexander A. Telyatnikov (Alter)
14 
15 Environment:
16     kernel mode only
17 
18 Notes:
19 
20     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 Revision History:
32 
33     Some parts of hardware-specific code were taken from FreeBSD 4.3-6.1 ATA driver by
34          S�ren Schmidt, Copyright (c) 1998-2007
35 
36     Some parts of device detection code were taken from from standard ATAPI.SYS from NT4 DDK by
37          Mike Glass (MGlass)
38          Chuck Park (ChuckP)
39 
40     Device search/init algorithm is completly rewritten by
41          Alter, Copyright (c) 2002-2004
42 
43     Fixes for Native/Compatible modes of onboard IDE controller by
44          Vitaliy Vorobyov, deathsoft@yandex.ru (c) 2004
45 
46 Licence:
47     GPLv2
48 
49 --*/
50 
51 #include "stdafx.h"
52 
53 PBUSMASTER_CONTROLLER_INFORMATION BMList = NULL;
54 ULONG         BMListLen = 0;
55 ULONG         IsaCount = 0;
56 ULONG         MCACount = 0;
57 
58 BOOLEAN FirstMasterOk = FALSE;
59 // This is our own resource check,
60 // ReactOS allows to allocate same I/O range for both PCI and ISA controllers
61 BOOLEAN AtdiskPrimaryClaimed = FALSE;
62 BOOLEAN AtdiskSecondaryClaimed = FALSE;
63 
64 #ifndef UNIATA_CORE
65 
66 UCHAR         pciBuffer[256];
67 ULONG         maxPciBus = 16;
68 
69 PDRIVER_OBJECT SavedDriverObject = NULL;
70 
71 // local routines
72 
73 ULONG
74 NTAPI
75 UniataEnumBusMasterController__(
76 /*    IN PVOID HwDeviceExtension,
77     IN PVOID Context,
78     IN PVOID BusInformation,
79     IN PCHAR ArgumentString,
80     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
81     OUT PBOOLEAN Again*/
82     );
83 
84 VOID
85 NTAPI
86 AtapiDoNothing(VOID)
87 {
88     return;
89 } // end AtapiDoNothing()
90 
91 #endif //UNIATA_CORE
92 
93 USHORT
94 NTAPI
95 UniataEnableIoPCI(
96     IN  ULONG                  busNumber,
97     IN  ULONG                  slotNumber,
98  IN OUT PPCI_COMMON_CONFIG     pciData
99     )
100 {
101     ULONG i;
102     ULONG busDataRead;
103     USHORT CmdOrig;
104 
105     // Enable Busmastering, IO-space and Mem-space
106     // Note: write to CONFIG *may* cause controller to interrupt (not handled yet)
107     // even if no bits are updated. Was observed on ICH7
108     KdPrint2((PRINT_PREFIX "Enabling Mem/Io spaces and busmastering...\n"));
109     KdPrint2((PRINT_PREFIX "Initial pciData.Command = %#x\n", pciData->Command));
110     for(i=0; i<3; i++) {
111         CmdOrig = pciData->Command;
112         switch(i) {
113         case 0:
114             KdPrint2((PRINT_PREFIX "PCI_ENABLE_IO_SPACE\n"));
115             pciData->Command |= PCI_ENABLE_IO_SPACE;
116             break;
117         case 1:
118             KdPrint2((PRINT_PREFIX "PCI_ENABLE_MEMORY_SPACE\n"));
119             pciData->Command |= PCI_ENABLE_MEMORY_SPACE;
120             break;
121         case 2:
122             KdPrint2((PRINT_PREFIX "PCI_ENABLE_BUS_MASTER\n"));
123             pciData->Command |= PCI_ENABLE_BUS_MASTER;
124             break;
125         }
126         if(CmdOrig == pciData->Command) {
127             continue;
128         }
129         HalSetBusDataByOffset(  PCIConfiguration, busNumber, slotNumber,
130                                 &(pciData->Command),
131                                 offsetof(PCI_COMMON_CONFIG, Command),
132                                 sizeof(pciData->Command));
133 
134         // reread config space
135         busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotNumber,
136                                     pciData, PCI_COMMON_HDR_LENGTH);
137         if(busDataRead < PCI_COMMON_HDR_LENGTH) {
138             KdPrint2((PRINT_PREFIX "HalGetBusData() failed %#x\n", busDataRead));
139             break;
140         }
141         KdPrint2((PRINT_PREFIX "New pciData.Command = %#x\n", pciData->Command));
142     }
143     KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData->u.type0.InterruptLine));
144     KdPrint2((PRINT_PREFIX "Final pciData.Command = %#x\n", pciData->Command));
145     return pciData->Command;
146 } // end UniataEnableIoPCI()
147 
148 /*
149     Get PCI address by ConfigInfo and RID
150 */
151 ULONGIO_PTR
152 NTAPI
153 AtapiGetIoRange(
154     IN PVOID HwDeviceExtension,
155     IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
156     IN PPCI_COMMON_CONFIG pciData,
157     IN ULONG SystemIoBusNumber,
158     IN ULONG rid,   //range id
159     IN ULONG offset,
160     IN ULONG length
161     )
162 {
163     ULONGIO_PTR io_start = 0;
164     KdPrint2((PRINT_PREFIX "  AtapiGetIoRange:\n"));
165 
166     if(ConfigInfo->NumberOfAccessRanges <= rid)
167         return 0;
168 
169     KdPrint2((PRINT_PREFIX "  AtapiGetIoRange: rid %#x, start %#x, offs %#x, len %#x, mem %#x\n",
170         rid,
171         ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[rid].RangeStart),
172         offset,
173         length,
174         (*ConfigInfo->AccessRanges)[rid].RangeInMemory
175         ));
176 
177     if(!(*ConfigInfo->AccessRanges)[rid].RangeInMemory) {
178         io_start = (pciData->u.type0.BaseAddresses[rid] & ~0x07/*PCI_ADDRESS_IOMASK*/) + offset;
179         // if(pciData->u.type0.BaseAddresses[rid] != 0) ;)
180         if(io_start > offset) {
181             if(/*(WinVer_Id() <= WinVer_NT) &&*/ offset && rid == 4) {
182                 // MS atapi.sys does so for BusMaster controllers
183                 (*ConfigInfo->AccessRanges)[rid+1].RangeStart =
184                     ScsiPortConvertUlongToPhysicalAddress(io_start);
185                 (*ConfigInfo->AccessRanges)[rid+1].RangeLength = length;
186             } else {
187                 (*ConfigInfo->AccessRanges)[rid].RangeStart =
188                     ScsiPortConvertUlongToPhysicalAddress(io_start);
189                 (*ConfigInfo->AccessRanges)[rid].RangeLength = length;
190             }
191             if((pciData->u.type0.BaseAddresses[rid] & PCI_ADDRESS_IO_SPACE)) {
192                 (*ConfigInfo->AccessRanges)[rid].RangeInMemory = FALSE;
193             } else {
194                 KdPrint2((PRINT_PREFIX "  AtapiGetIoRange: adjust mem 0 -> 1\n"));
195                 (*ConfigInfo->AccessRanges)[rid].RangeInMemory = TRUE;
196             }
197         } else {
198             io_start = 0;
199         }
200     }
201 
202     if((*ConfigInfo->AccessRanges)[rid].RangeInMemory) {
203         if(offset) {
204             KdPrint2((PRINT_PREFIX "  AtapiGetIoRange: can't map memory range with offset\n"));
205             return 0;
206         }
207         io_start =
208             // Get the system physical address for this IO range.
209             ((ULONG_PTR)ScsiPortGetDeviceBase(HwDeviceExtension,
210                         PCIBus /*ConfigInfo->AdapterInterfaceType*/,
211                         SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/,
212                         ScsiPortConvertUlongToPhysicalAddress(
213                             (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[rid].RangeStart) &
214                             ~0x07/*PCI_ADDRESS_IOMASK*/) + offset
215                                                              ),
216                         length,
217                         (BOOLEAN)!(*ConfigInfo->AccessRanges)[rid].RangeInMemory)
218                                );
219 
220         KdPrint2((PRINT_PREFIX "  AtapiGetIoRange: %#x\n", io_start));
221    //     if(io_start > offset) {
222             return io_start;
223    //     }
224     }
225 
226     KdPrint2((PRINT_PREFIX "  AtapiGetIoRange: (2) %#x\n", io_start));
227     return io_start;
228 
229 } // end AtapiGetIoRange()
230 
231 #ifndef UNIATA_CORE
232 
233 /*
234     Do nothing, but build list of supported IDE controllers
235     It is a hack, ScsiPort architecture assumes, that DriverEntry
236     can support only KNOWN Vendor/Device combinations.
237     Thus, we build list here. Later we pretend that always knew
238     about found devices.
239 
240     We shall initiate ISA device init, but callback will use
241     Hal routines directly in order to scan PCI bus.
242 */
243 VOID
244 NTAPI
245 UniataEnumBusMasterController(
246     IN PVOID DriverObject,
247     PVOID Argument2
248     )
249 {
250     UniataEnumBusMasterController__();
251 
252 } // end UniataEnumBusMasterController()
253 
254 BOOLEAN
255 NTAPI
256 UniataCheckPCISubclass(
257     BOOLEAN known,
258     ULONG   RaidFlags,
259     UCHAR   SubClass
260     )
261 {
262     if(known) {
263         if((RaidFlags & UNIATA_RAID_CONTROLLER) &&
264             SkipRaids) {
265             KdPrint2((PRINT_PREFIX "Skip RAID\n"));
266             return FALSE;
267         }
268         return TRUE;
269     }
270     KdPrint2((PRINT_PREFIX "unknown\n"));
271 
272     switch(SubClass) {
273     case PCI_DEV_SUBCLASS_RAID:
274         if(SkipRaids) {
275             KdPrint2((PRINT_PREFIX "Skip RAID (2)\n"));
276             return FALSE;
277         }
278         break;
279     case PCI_DEV_SUBCLASS_IDE:
280     case PCI_DEV_SUBCLASS_ATA:
281         break;
282     case PCI_DEV_SUBCLASS_SATA:
283         break;
284     default:
285         KdPrint2((PRINT_PREFIX "Subclass not supported\n"));
286         return FALSE;
287     }
288     return TRUE;
289 } // end UniataCheckPCISubclass()
290 
291 static CONST ULONG StdIsaPorts[] = {IO_WD1, IO_WD1 + ATA_ALTOFFSET, IO_WD2, IO_WD2 + ATA_ALTOFFSET, 0, 0};
292 
293 /*
294     Device initializaton callback
295     Builds PCI device list using Hal routines (not ScsiPort wrappers)
296 */
297 ULONG
298 NTAPI
299 UniataEnumBusMasterController__(
300     )
301 {
302 //    PHW_DEVICE_EXTENSION  deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
303 //    PVOID HwDeviceExtension;
304     PHW_DEVICE_EXTENSION  deviceExtension = NULL;
305     PCHAR PciDevMap = NULL;
306     PCI_SLOT_NUMBER       slotData;
307     PCI_COMMON_CONFIG     pciData;
308     ULONG                 busNumber;
309     ULONG                 slotNumber;
310     ULONG                 funcNumber;
311     BOOLEAN               no_buses = FALSE;
312     BOOLEAN               no_ranges = FALSE;
313     BOOLEAN               non_isa = TRUE;
314     ULONG                 busDataRead;
315 //    BOOLEAN               SimplexOnly;
316 
317     UCHAR                 vendorString[5];
318     UCHAR                 deviceString[5];
319     PUCHAR                vendorStrPtr;
320     PUCHAR                deviceStrPtr;
321 
322     UCHAR   BaseClass;                  // (ro)
323     UCHAR   SubClass;                   // (ro)
324     ULONG   VendorID;
325     ULONG   DeviceID;
326     ULONG   dev_id;
327 
328     USHORT  SubVendorID;
329     USHORT  SubSystemID;
330 
331     ULONG   i;
332     ULONG   pass=0;
333 
334     ULONG   RaidFlags;
335 
336     BOOLEAN found;
337     BOOLEAN known;
338     BOOLEAN NeedPciAltInit;
339     BOOLEAN NonZeroSubId = 0;
340 
341     UCHAR IrqForCompat = 10;
342 
343     vendorStrPtr = vendorString;
344     deviceStrPtr = deviceString;
345     slotData.u.AsULONG = 0;
346 
347     KdPrint2((PRINT_PREFIX "UniataEnumBusMasterController__: maxPciBus=%d\n", maxPciBus));
348     if(!maxPciBus) {
349         return(SP_RETURN_NOT_FOUND);
350     }
351     /*HwDeviceExtension =*/
352     deviceExtension = (PHW_DEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(HW_DEVICE_EXTENSION));
353     if(!deviceExtension) {
354         KdPrint2((PRINT_PREFIX "!deviceExtension\n"));
355         return(SP_RETURN_NOT_FOUND);
356     }
357     RtlZeroMemory(deviceExtension, sizeof(HW_DEVICE_EXTENSION));
358     PciDevMap = (PCHAR)ExAllocatePool(NonPagedPool, maxPciBus*PCI_MAX_DEVICES);
359     if(!PciDevMap) {
360         KdPrint2((PRINT_PREFIX "!PciDevMap\n"));
361         goto exit;
362     }
363     RtlZeroMemory(PciDevMap, maxPciBus*PCI_MAX_DEVICES);
364 
365     for(pass=0; pass<3; pass++) {
366         KdPrint2((PRINT_PREFIX "  pass %d\n", pass));
367         no_buses = FALSE;
368         for(busNumber=0 ;busNumber<maxPciBus && !no_buses; busNumber++) {
369             for(slotNumber=0; slotNumber<PCI_MAX_DEVICES  && !no_buses; slotNumber++) {
370             NeedPciAltInit = FALSE;
371             for(funcNumber=0; funcNumber<PCI_MAX_FUNCTION && !no_buses; funcNumber++) {
372 
373                 if(pass) {
374                     // use cached device presence map from the 1st pass
375                     if(PciDevMap[busNumber*PCI_MAX_DEVICES + slotNumber] & (1 << funcNumber)) {
376                         // ok
377                     } else {
378                         continue;
379                     }
380                 }
381 //                KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x\n",busNumber,slotNumber,funcNumber));
382                 slotData.u.bits.DeviceNumber   = slotNumber;
383                 slotData.u.bits.FunctionNumber = funcNumber;
384 
385                 busDataRead = HalGetBusData
386                               //ScsiPortGetBusData
387                                            (
388                                             //HwDeviceExtension,
389                                             PCIConfiguration, busNumber, slotData.u.AsULONG,
390                                             &pciData, PCI_COMMON_HDR_LENGTH);
391                 // no more buses
392                 if(!busDataRead) {
393                     no_buses = TRUE; // break all nested bus scan loops and continue with next pass
394                     maxPciBus = busNumber;
395                     break;
396                 }
397                 // indicate that system has PCI bus(es)
398                 hasPCI = TRUE;
399 
400                 // no device in this slot
401                 if(busDataRead == 2) {
402                     NeedPciAltInit = TRUE;
403                     continue;
404                 }
405 
406                 if(busDataRead < (ULONG)PCI_COMMON_HDR_LENGTH) {
407                     NeedPciAltInit = TRUE;
408                     continue;
409                 }
410 
411                 VendorID  = pciData.VendorID;
412                 DeviceID  = pciData.DeviceID;
413                 BaseClass = pciData.BaseClass;
414                 SubClass  = pciData.SubClass;
415                 dev_id = VendorID | (DeviceID << 16);
416 
417                 SubVendorID = pciData.u.type0.SubVendorID;
418                 SubSystemID = pciData.u.type0.SubSystemID;
419 
420                 if(SubVendorID && SubSystemID) {
421                   NonZeroSubId = 1;
422                 }
423 
424                 KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X, SubVen/Sys %4.4x/%4.4x\n", dev_id, BaseClass, SubClass, SubVendorID, SubSystemID));
425 
426                 // check for (g_opt_VirtualMachine == VM_AUTO) is performed inside each
427                 // VM check for debug purposes
428                 // Do not optimize :)
429                 if((VendorID == 0x80ee && DeviceID == 0xcafe) ||
430                    (VendorID == 0x80ee && DeviceID == 0xbeef)) {
431                     KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - VirtualBox Guest Service\n",busNumber,slotNumber,funcNumber));
432                     if(g_opt_VirtualMachine == VM_AUTO) {
433                         g_opt_VirtualMachine = VM_VBOX;
434                     }
435                 } else
436                 if((VendorID == 0x15ad) ||
437                    (SubVendorID == 0x15ad && SubSystemID == 0x1976)) {
438                     KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - VMWare\n",busNumber,slotNumber,funcNumber));
439                     if(g_opt_VirtualMachine == VM_AUTO) {
440                         g_opt_VirtualMachine = VM_VMWARE;
441                     }
442                 } else
443                 if(SubVendorID == 0x1af4 && SubSystemID == 0x1100) {
444                     KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - QEmu\n",busNumber,slotNumber,funcNumber));
445                     if(g_opt_VirtualMachine == VM_AUTO) {
446                         g_opt_VirtualMachine = VM_QEMU;
447                     }
448                 } else
449                 if(VendorID == 0x1234 && DeviceID == 0x1111) {
450                     KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - Bochs\n",busNumber,slotNumber,funcNumber));
451                     if(g_opt_VirtualMachine == VM_AUTO) {
452                         g_opt_VirtualMachine = VM_BOCHS;
453                     }
454 /*                } else
455                 if(pass>0 && !NonZeroSubId &&
456                    VendorID == 0x8086 &&
457                      (DeviceID == 0x7010 ||
458                       DeviceID == 0x1230)) {
459                     KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - Bochs PIIX emulation\n",busNumber,slotNumber,funcNumber));
460                     if(g_opt_VirtualMachine == VM_AUTO) {
461                         g_opt_VirtualMachine = VM_BOCHS;
462                     }*/
463                 }
464 
465                 if(BaseClass != PCI_DEV_CLASS_STORAGE) {
466                     continue;
467                 }
468 
469                 KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x\n",busNumber,slotNumber,funcNumber));
470                 KdPrint2((PRINT_PREFIX "Storage Class\n"));
471                 KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X, ProgIf %2.2X\n", dev_id, BaseClass, SubClass, pciData.ProgIf ));
472                 // look for known chipsets
473                 found = FALSE;
474                 known = FALSE;
475 
476                 if(pciData.u.type0.InterruptPin == 14 ||
477                    pciData.u.type0.InterruptPin == 15 ||
478                    pciData.u.type0.InterruptLine == 14 ||
479                    pciData.u.type0.InterruptLine == 15) {
480                     KdPrint2((PRINT_PREFIX "(!) InterruptPin = %#x\n", pciData.u.type0.InterruptPin));
481                     KdPrint2((PRINT_PREFIX "(!) InterruptLine = %#x\n", pciData.u.type0.InterruptLine));
482                 }
483 
484                 if(deviceExtension) {
485                     deviceExtension->slotNumber = slotData.u.AsULONG;
486                     deviceExtension->SystemIoBusNumber = busNumber;
487                     deviceExtension->DevID = dev_id;
488                     deviceExtension->RevID = pciData.RevisionID;
489                     deviceExtension->AdapterInterfaceType = PCIBus;
490                 }
491 
492                 found = (BOOLEAN)AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"Include", 0);
493                 if(!found) {
494                     KdPrint2((PRINT_PREFIX "No force include, check exclude\n"));
495                     found = !AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"Exclude", 0);
496                     if(!found) {
497                         KdPrint2((PRINT_PREFIX "Device excluded\n"));
498                         continue;
499                     }
500                 }
501 
502                 //known = UniataChipDetect(HwDeviceExtension, NULL, -1, ConfigInfo, &SimplexOnly);
503                 i = Ata_is_dev_listed((PBUSMASTER_CONTROLLER_INFORMATION_BASE)&BusMasterAdapters[0], VendorID, DeviceID, 0, NUM_BUSMASTER_ADAPTERS);
504 
505                 known = (i != BMLIST_TERMINATOR);
506                 if(known) {
507                     deviceExtension->FullDevName = BusMasterAdapters[i].FullDevName;
508                     RaidFlags = BusMasterAdapters[i].RaidFlags;
509                 } else {
510                     deviceExtension->FullDevName = "Unknown Storage";
511                     RaidFlags = 0;
512                 }
513                 found = UniataCheckPCISubclass(known, RaidFlags, SubClass);
514                 if(!found) {
515                     KdPrint2((PRINT_PREFIX "Subclass not supported\n"));
516                     continue;
517                 }
518 
519                 switch(dev_id) {
520                 /* additional checks for some supported chipsets */
521                 case 0xc6931080:
522                     if (SubClass != PCI_DEV_SUBCLASS_IDE)
523                         found = FALSE;
524                     break;
525 
526                 /* unknown chipsets, try generic DMA if it seems possible */
527                 default:
528                     KdPrint2((PRINT_PREFIX "Default device\n"));
529                     if(Ata_is_supported_dev(&pciData) ||
530                        Ata_is_ahci_dev(&pciData))
531                         found = TRUE;
532                     break;
533                 }
534 
535                 if(!found) {
536                     continue;
537                 }
538 
539                 KdPrint2((PRINT_PREFIX "found, pass %d\n", pass));
540 
541                 KdPrint2((PRINT_PREFIX "InterruptPin = %#x\n", pciData.u.type0.InterruptPin));
542                 KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData.u.type0.InterruptLine));
543 
544                 if(!pass && known) {
545                     UniataEnableIoPCI(busNumber, slotData.u.AsULONG, &pciData);
546                 }
547                 // validate Mem/Io ranges
548                 no_ranges = TRUE;
549                 non_isa = TRUE;
550                 for(i=0; i<PCI_TYPE0_ADDRESSES; i++) {
551                     if(pciData.u.type0.BaseAddresses[i] & ~0x7) {
552                         no_ranges = FALSE;
553                         //break;
554                         KdPrint2((PRINT_PREFIX "Range %d = %#x\n", i, pciData.u.type0.BaseAddresses[i]));
555                         if(i<4) {
556                             if(StdIsaPorts[i] == (pciData.u.type0.BaseAddresses[i] & ~0x7)) {
557                                 non_isa = FALSE;
558                             }
559                         }
560                     }
561                 }
562                 if(no_ranges) {
563                     KdPrint2((PRINT_PREFIX "No PCI Mem/Io ranges found on device, skip it\n"));
564                     continue;
565                 }
566                 if(!non_isa) {
567                     KdPrint2((PRINT_PREFIX "standard ISA ranges on PCI, special case ?\n"));
568                 }
569 
570                 if(pass) {
571                     // fill list of detected devices
572                     // it'll be used for further init
573                     KdPrint2((PRINT_PREFIX "found suitable device\n"));
574                     PBUSMASTER_CONTROLLER_INFORMATION newBMListPtr = BMList+BMListLen;
575 
576                     if(pass == 1) {
577                         if(!IsMasterDev(&pciData)) {
578                             continue;
579                         }
580                         if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"NativePCIMode", 0)) {
581                             KdPrint2((PRINT_PREFIX "try switch to native mode\n"));
582 
583                             IrqForCompat = (UCHAR)AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"NativePCIModeIRQ", 0xff);
584                             KdPrint2((PRINT_PREFIX "IrqForCompat = %#x\n", IrqForCompat));
585                             if((IrqForCompat & 0xffffff00) /*||
586                                (IrqForCompat & 0xff) > 31*/ ||
587                                (IrqForCompat == 0xff)) {
588                                 IrqForCompat = 0x0b;
589                                 KdPrint2((PRINT_PREFIX "default to IRQ 11\n"));
590                             }
591 
592                             //ChangePciConfig1(0x09, a | PCI_IDE_PROGIF_NATIVE_ALL); // ProgIf
593                             pciData.ProgIf |= PCI_IDE_PROGIF_NATIVE_ALL;
594                             HalSetBusDataByOffset(  PCIConfiguration, busNumber, slotData.u.AsULONG,
595                                                     &(pciData.ProgIf),
596                                                     offsetof(PCI_COMMON_CONFIG, ProgIf),
597                                                     sizeof(pciData.ProgIf));
598 
599                             // reread config space
600                             busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotData.u.AsULONG,
601                                                         &pciData, PCI_COMMON_HDR_LENGTH);
602                             // check if the device have switched to Native Mode
603                             if(IsMasterDev(&pciData)) {
604                                 KdPrint2((PRINT_PREFIX "Can't switch to native mode\n"));
605                             } else {
606                                 KdPrint2((PRINT_PREFIX "switched to native mode\n"));
607                                 KdPrint2((PRINT_PREFIX "InterruptPin = %#x\n", pciData.u.type0.InterruptPin));
608                                 KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData.u.type0.InterruptLine));
609                                 // check if IRQ is assigned to device
610                                 if(!(pciData.u.type0.InterruptLine) ||
611                                     (pciData.u.type0.InterruptLine == 0xff)) {
612                                     KdPrint2((PRINT_PREFIX "assign interrupt for device\n"));
613                                     pciData.u.type0.InterruptLine = IrqForCompat;
614                                     HalSetBusDataByOffset(  PCIConfiguration, busNumber, slotData.u.AsULONG,
615                                                             &(pciData.u.type0.InterruptLine),
616                                                             offsetof(PCI_COMMON_CONFIG, u.type0.InterruptLine),
617                                                             sizeof(pciData.u.type0.InterruptLine));
618                                 } else {
619                                     KdPrint2((PRINT_PREFIX "Auto-assigned interrupt line %#x\n",
620                                         pciData.u.type0.InterruptLine));
621                                     IrqForCompat = pciData.u.type0.InterruptLine;
622                                 }
623                                 KdPrint2((PRINT_PREFIX "reread config space\n"));
624                                 // reread config space
625                                 busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotData.u.AsULONG,
626                                                             &pciData, PCI_COMMON_HDR_LENGTH);
627                                 KdPrint2((PRINT_PREFIX "busDataRead = %#x\n", busDataRead));
628                                 KdPrint2((PRINT_PREFIX "reread InterruptLine = %#x\n", pciData.u.type0.InterruptLine));
629                                 // check if we have successfully assigned IRQ to device
630                                 if((pciData.u.type0.InterruptLine != IrqForCompat) ||
631                                    (pciData.u.type0.InterruptLine == 0xff) ||
632                                    !pciData.u.type0.InterruptLine) {
633                                     KdPrint2((PRINT_PREFIX "can't assign interrupt for device, revert to compat mode\n"));
634                                     pciData.u.type0.InterruptLine = 0xff;
635                                     KdPrint2((PRINT_PREFIX "set IntrLine to 0xff\n"));
636                                     HalSetBusDataByOffset(  PCIConfiguration, busNumber, slotData.u.AsULONG,
637                                                             &(pciData.u.type0.InterruptLine),
638                                                             offsetof(PCI_COMMON_CONFIG, u.type0.InterruptLine),
639                                                             sizeof(pciData.u.type0.InterruptLine));
640                                     KdPrint2((PRINT_PREFIX "clear PCI_IDE_PROGIF_NATIVE_ALL\n"));
641                                     pciData.ProgIf &= ~PCI_IDE_PROGIF_NATIVE_ALL;
642                                     HalSetBusDataByOffset(  PCIConfiguration, busNumber, slotData.u.AsULONG,
643                                                             &(pciData.ProgIf),
644                                                             offsetof(PCI_COMMON_CONFIG, ProgIf),
645                                                             sizeof(pciData.ProgIf));
646                                     // reread config space
647                                     KdPrint2((PRINT_PREFIX "reread config space on revert\n"));
648                                     busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotData.u.AsULONG,
649                                                                 &pciData, PCI_COMMON_HDR_LENGTH);
650                                 } else {
651                                     KdPrint2((PRINT_PREFIX "Assigned interrupt %#x for device\n", IrqForCompat));
652                                     KdPrint2((PRINT_PREFIX "continue detection on next round\n"));
653                                     continue;
654                                 }
655                             }
656                         }
657                     } else
658                     if(pass == 2) {
659                         if(IsMasterDev(&pciData)) {
660                             continue;
661                         }
662                     }
663 
664 /*                        if(known) {
665                         RtlCopyMemory(newBMListPtr, (PVOID)&(BusMasterAdapters[i]), sizeof(BUSMASTER_CONTROLLER_INFORMATION));
666                     } else {*/
667                     sprintf((PCHAR)vendorStrPtr, "%4.4lx", VendorID);
668                     sprintf((PCHAR)deviceStrPtr, "%4.4lx", DeviceID);
669 
670                     RtlCopyMemory(&(newBMListPtr->VendorIdStr), (PCHAR)vendorStrPtr, 4);
671                     RtlCopyMemory(&(newBMListPtr->DeviceIdStr), (PCHAR)deviceStrPtr, 4);
672 
673                     newBMListPtr->nVendorId = VendorID;
674                     newBMListPtr->VendorId = (PCHAR)&(newBMListPtr->VendorIdStr);
675                     newBMListPtr->VendorIdLength = 4;
676                     newBMListPtr->nDeviceId = DeviceID;
677                     newBMListPtr->DeviceId = (PCHAR)&(newBMListPtr->DeviceIdStr);
678                     newBMListPtr->DeviceIdLength = 4;
679 
680                     newBMListPtr->RaidFlags = RaidFlags;
681 //                        }
682                     newBMListPtr->slotNumber = slotData.u.AsULONG;
683                     newBMListPtr->MasterDev = IsMasterDev(&pciData) ? 1 : 0;
684                     newBMListPtr->busNumber = busNumber;
685 
686                     newBMListPtr->NeedAltInit = NeedPciAltInit;
687                     newBMListPtr->Known = known;
688 
689                     if(!non_isa) {
690                         KdPrint2((PRINT_PREFIX "* ISA ranges on PCI, special case !\n"));
691                         // Do not fail init after unseccessfull call of UniataClaimLegacyPCIIDE()
692                         // some SMP HALs fails to reallocate IO range
693                         newBMListPtr->ChanInitOk |= 0x40;
694                     }
695 
696                     KdPrint2((PRINT_PREFIX "Add to BMList, AltInit %d\n", NeedPciAltInit));
697                 } else {
698                     KdPrint2((PRINT_PREFIX "count: BMListLen++\n"));
699                     PciDevMap[busNumber*PCI_MAX_DEVICES + slotNumber] |= (1 << funcNumber);
700                 }
701 
702                 BMListLen++;
703 
704             } // Function
705             } // Slot
706             if(!hasPCI) {
707                 break;
708             }
709         }
710         if(!pass) {
711              if(!BMListLen)
712                  break;
713              BMList = (PBUSMASTER_CONTROLLER_INFORMATION)ExAllocatePool(NonPagedPool,
714                                          (BMListLen+1)*sizeof(BUSMASTER_CONTROLLER_INFORMATION));
715              if(!BMList) {
716                  BMListLen=0;
717                  break;
718              }
719              RtlZeroMemory(BMList, (BMListLen+1)*sizeof(BUSMASTER_CONTROLLER_INFORMATION));
720              no_buses = FALSE;
721              BMListLen=0;
722         }
723     }
724 exit:
725     KdPrint2((PRINT_PREFIX "  BMListLen=%x\n", BMListLen));
726     if(deviceExtension) {
727         ExFreePool(deviceExtension);
728     }
729     if(PciDevMap) {
730         ExFreePool(PciDevMap);
731     }
732     return(SP_RETURN_NOT_FOUND);
733 } // end UniataEnumBusMasterController__()
734 
735 
736 /*
737     Wrapper for read PCI config space
738 */
739 ULONG
740 NTAPI
741 ScsiPortGetBusDataByOffset(
742     IN PVOID  HwDeviceExtension,
743     IN BUS_DATA_TYPE  BusDataType,
744     IN ULONG  BusNumber,
745     IN ULONG  SlotNumber,
746     IN PVOID  Buffer,
747     IN ULONG  Offset,
748     IN ULONG  Length
749     )
750 {
751     UCHAR tmp[256];
752     ULONG busDataRead;
753 
754     if(Offset+Length > 256)
755         return 0;
756 
757     busDataRead = HalGetBusData(
758         //ScsiPortGetBusData(HwDeviceExtension,
759                                      BusDataType,
760                                      BusNumber,
761                                      SlotNumber,
762                                      &tmp,
763                                      Offset+Length);
764     if(busDataRead < Offset+Length) {
765         if(busDataRead < Offset)
766             return 0;
767         return (Offset+Length-busDataRead);
768     }
769     RtlCopyMemory(Buffer, tmp+Offset, Length);
770     return Length;
771 } // end ScsiPortGetBusDataByOffset()
772 
773 /*
774     Looks for devices from list on specified bus(es)/slot(s)
775     returnts its index in list.
776     If no matching record found, -1 is returned
777 */
778 ULONG
779 NTAPI
780 AtapiFindListedDev(
781     IN PBUSMASTER_CONTROLLER_INFORMATION_BASE BusMasterAdapters,
782     IN ULONG     lim,
783     IN PVOID  HwDeviceExtension,
784     IN ULONG  BusNumber,
785     IN ULONG  SlotNumber,
786     OUT PCI_SLOT_NUMBER* _slotData // optional
787     )
788 {
789     PCI_SLOT_NUMBER       slotData;
790     PCI_COMMON_CONFIG     pciData;
791     ULONG                 busDataRead;
792 
793     ULONG busNumber;
794     ULONG slotNumber;
795     ULONG funcNumber;
796 
797     ULONG busNumber2;
798     ULONG slotNumber2;
799 
800     ULONG i;
801 
802     KdPrint2((PRINT_PREFIX "AtapiFindListedDev: lim=%x, Bus=%x, Slot=%x\n", lim, BusNumber, SlotNumber));
803 
804     // set start/end bus
805     if(BusNumber == PCIBUSNUM_NOT_SPECIFIED) {
806         busNumber  = 0;
807         busNumber2 = maxPciBus;
808     } else {
809         busNumber  = BusNumber;
810         busNumber2 = BusNumber+1;
811     }
812     // set start/end slot
813     if(SlotNumber == PCISLOTNUM_NOT_SPECIFIED) {
814         slotNumber  = 0;
815         slotNumber2 = PCI_MAX_DEVICES;
816     } else {
817         slotNumber  = SlotNumber;
818         slotNumber2 = SlotNumber+1;
819     }
820     slotData.u.AsULONG = 0;
821 
822     KdPrint2((PRINT_PREFIX " scanning range Bus %x-%x, Slot %x-%x\n", busNumber, busNumber2-1, slotNumber, slotNumber2-1));
823 
824     for(            ; busNumber  < busNumber2       ; busNumber++ ) {
825     for(            ; slotNumber < slotNumber2      ; slotNumber++) {
826     for(funcNumber=0; funcNumber < PCI_MAX_FUNCTION ; funcNumber++) {
827 
828         slotData.u.bits.DeviceNumber   = slotNumber;
829         slotData.u.bits.FunctionNumber = funcNumber;
830 
831         busDataRead = HalGetBusData(
832             //ScsiPortGetBusData(HwDeviceExtension,
833                                     PCIConfiguration, busNumber, slotData.u.AsULONG,
834                                     &pciData, PCI_COMMON_HDR_LENGTH);
835         // no more buses (this should not happen)
836         if(!busDataRead) {
837             continue;
838         }
839         // no device in this slot
840         if(busDataRead == 2)
841             continue;
842 
843         if(busDataRead < (ULONG)PCI_COMMON_HDR_LENGTH)
844             continue;
845 /*
846         KdPrint2((PRINT_PREFIX "AtapiFindListedDev: b:s:f(%x:%x:%x) %4.4x/%4.4x/%2.2x\n",
847                   busNumber, slotNumber, funcNumber,
848                   pciData.VendorID, pciData.DeviceID, pciData.RevisionID));
849                   */
850         i = Ata_is_dev_listed(BusMasterAdapters, pciData.VendorID, pciData.DeviceID, pciData.RevisionID, lim);
851         if(i != BMLIST_TERMINATOR) {
852             if(_slotData)
853                 *_slotData = slotData;
854             KdPrint2((PRINT_PREFIX "AtapiFindListedDev: found\n"));
855             KdPrint2((PRINT_PREFIX "AtapiFindListedDev: b:s:f(%x:%x:%x) %4.4x/%4.4x/%2.2x\n",
856                       busNumber, slotNumber, funcNumber,
857                       pciData.VendorID, pciData.DeviceID, pciData.RevisionID));
858             return i;
859         }
860 
861     }}}
862     return -1;
863 } // end AtapiFindListedDev()
864 
865 /*
866     Looks for device with specified Device/Vendor and Revision
867     on specified Bus/Slot
868 */
869 ULONG
870 NTAPI
871 AtapiFindDev(
872     IN PVOID  HwDeviceExtension,
873     IN BUS_DATA_TYPE  BusDataType,
874     IN ULONG  BusNumber,
875     IN ULONG  SlotNumber,
876     IN ULONG  dev_id,
877     IN ULONG  RevID
878     )
879 {
880     PCI_COMMON_CONFIG     pciData;
881     ULONG                 funcNumber;
882     ULONG                 busDataRead;
883 
884     ULONG   VendorID;
885     ULONG   DeviceID;
886     PCI_SLOT_NUMBER       slotData;
887 
888     slotData.u.AsULONG = SlotNumber;
889     // walk through all Function Numbers
890     for(funcNumber = 0; funcNumber < PCI_MAX_FUNCTION; funcNumber++) {
891 
892         slotData.u.bits.FunctionNumber = funcNumber;
893         if(slotData.u.AsULONG == SlotNumber)
894             continue;
895 
896         busDataRead = HalGetBusData(
897             //busDataRead = ScsiPortGetBusData(HwDeviceExtension,
898                                          PCIConfiguration,
899                                          BusNumber,
900                                          slotData.u.AsULONG,
901                                          &pciData,
902                                          PCI_COMMON_HDR_LENGTH);
903 
904         if (busDataRead < (ULONG)PCI_COMMON_HDR_LENGTH) {
905             continue;
906         }
907 
908         VendorID  = pciData.VendorID;
909         DeviceID  = pciData.DeviceID;
910 
911         if(dev_id != (VendorID | (DeviceID << 16)) )
912             continue;
913         if(RevID >= pciData.RevisionID)
914             return 1;
915     }
916     return 0;
917 } // end AtapiFindDev()
918 
919 #endif //UNIATA_CORE
920 
921 
922 ULONG
923 NTAPI
924 UniataFindCompatBusMasterController1(
925     IN PVOID HwDeviceExtension,
926     IN PVOID Context,
927     IN PVOID BusInformation,
928     IN PCHAR ArgumentString,
929     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
930     OUT PBOOLEAN Again
931     )
932 {
933     return UniataFindBusMasterController(
934         HwDeviceExtension,
935         UlongToPtr(0x00000000),
936         BusInformation,
937         ArgumentString,
938         ConfigInfo,
939         Again
940         );
941 } // end UniataFindCompatBusMasterController1()
942 
943 ULONG
944 NTAPI
945 UniataFindCompatBusMasterController2(
946     IN PVOID HwDeviceExtension,
947     IN PVOID Context,
948     IN PVOID BusInformation,
949     IN PCHAR ArgumentString,
950     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
951     OUT PBOOLEAN Again
952     )
953 {
954     return UniataFindBusMasterController(
955         HwDeviceExtension,
956         UlongToPtr(0x80000000),
957         BusInformation,
958         ArgumentString,
959         ConfigInfo,
960         Again
961         );
962 } // end UniataFindCompatBusMasterController2()
963 
964 /*++
965 
966 Routine Description:
967 
968     This function is called by the OS-specific port driver after
969     the necessary storage has been allocated, to gather information
970     about the adapter's configuration.
971 
972 Arguments:
973 
974     HwDeviceExtension - HBA miniport driver's adapter data storage
975     Context - Address of adapter count
976     BusInformation -
977     ArgumentString - Used to determine whether driver is client of ntldr or crash dump utility.
978     ConfigInfo - Configuration information structure describing HBA
979     Again - Indicates search for adapters to continue
980 
981 Return Value:
982 
983     ULONG
984 
985 --*/
986 ULONG
987 NTAPI
988 UniataFindBusMasterController(
989     IN PVOID HwDeviceExtension,
990     IN PVOID Context,
991     IN PVOID BusInformation,
992     IN PCHAR ArgumentString,
993     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
994     OUT PBOOLEAN Again
995     )
996 {
997     PHW_DEVICE_EXTENSION  deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
998     PHW_CHANNEL           chan = NULL;
999 #ifndef UNIATA_CORE
1000     // this buffer must be global for UNIATA_CORE build
1001     PCI_COMMON_CONFIG     pciData;
1002 #endif //UNIATA_CORE
1003     ULONG                 slotNumber;
1004     ULONG                 busDataRead;
1005     ULONG                 SystemIoBusNumber;
1006 /*
1007     UCHAR                 vendorString[5];
1008     UCHAR                 deviceString[5];
1009 
1010     PUCHAR                vendorStrPtr;
1011     PUCHAR                deviceStrPtr;
1012 */
1013     UCHAR   BaseClass;
1014     UCHAR   SubClass;
1015     ULONG   VendorID;
1016     ULONG   DeviceID;
1017     ULONG   RevID;
1018     ULONG   dev_id;
1019     PCI_SLOT_NUMBER       slotData;
1020 
1021     ULONG   i;
1022     ULONG   channel;
1023     ULONG   c = 0;
1024     PUCHAR  ioSpace;
1025     UCHAR   statusByte;
1026     ULONG   bm_offset;
1027 
1028 //    UCHAR   tmp8;
1029 //    ULONG   irq;
1030 
1031     BOOLEAN found = FALSE;
1032     BOOLEAN MasterDev;
1033     BOOLEAN simplexOnly = FALSE;
1034 #ifndef UNIATA_CORE
1035 #ifdef UNIATA_INIT_ON_PROBE
1036     BOOLEAN skip_find_dev = FALSE;
1037 #endif
1038 #endif
1039     BOOLEAN AltInit = FALSE;
1040 
1041     SCSI_PHYSICAL_ADDRESS IoBasePort1;
1042     SCSI_PHYSICAL_ADDRESS IoBasePort2;
1043 
1044     PIDE_BUSMASTER_REGISTERS BaseIoAddressBM_0 = NULL;
1045     PIDE_REGISTERS_1 BaseIoAddress1[IDE_MAX_CHAN];
1046     PIDE_REGISTERS_2 BaseIoAddress2[IDE_MAX_CHAN];
1047 
1048     RtlZeroMemory(&BaseIoAddress1, sizeof(BaseIoAddress1));
1049     RtlZeroMemory(&BaseIoAddress2, sizeof(BaseIoAddress2));
1050 
1051     NTSTATUS status;
1052     PPORT_CONFIGURATION_INFORMATION_COMMON _ConfigInfo =
1053         (PPORT_CONFIGURATION_INFORMATION_COMMON)ConfigInfo;
1054 
1055     if(!WinVer_WDM_Model) {
1056         *Again = FALSE;
1057     } else {
1058         *Again = TRUE;
1059     }
1060 
1061     KdPrint2((PRINT_PREFIX "UniataFindBusMasterController: Context=%x, BMListLen=%d\n", Context, BMListLen));
1062 
1063     KdPrint2((PRINT_PREFIX "ConfigInfo->Length %x\n", ConfigInfo->Length));
1064 
1065     if(ForceSimplex) {
1066         KdPrint2((PRINT_PREFIX "ForceSimplex (1)\n"));
1067         simplexOnly = TRUE;
1068     }
1069 
1070     if(ConfigInfo->AdapterInterfaceType == Isa) {
1071         KdPrint2((PRINT_PREFIX "AdapterInterfaceType: Isa\n"));
1072     }
1073     if(InDriverEntry) {
1074         i = PtrToUlong(Context);
1075         if(i & 0x80000000) {
1076             AltInit = TRUE;
1077         }
1078         i &= ~0x80000000;
1079         channel = BMList[i].channel;
1080     } else {
1081         channel = 0;
1082         for(i=0; i<BMListLen; i++) {
1083             if(BMList[i].slotNumber == ConfigInfo->SlotNumber &&
1084                BMList[i].busNumber  == ConfigInfo->SystemIoBusNumber) {
1085                 break;
1086             }
1087         }
1088         if(i >= BMListLen) {
1089             KdPrint2((PRINT_PREFIX "unexpected device arrival\n"));
1090             i = PtrToUlong(Context);
1091             if(FirstMasterOk) {
1092                 channel = 1;
1093             }
1094             i &= ~0x80000000;
1095             if(i >= BMListLen) {
1096                 KdPrint2((PRINT_PREFIX " => SP_RETURN_NOT_FOUND\n"));
1097                 goto exit_notfound;
1098             }
1099         }
1100         BMList[i].channel = (UCHAR)channel;
1101     }
1102 
1103     bm_offset = channel ? ATA_BM_OFFSET1 : 0;
1104 
1105     KdPrint2((PRINT_PREFIX "bm_offset %x, channel %x \n", bm_offset, channel));
1106 
1107     if (!deviceExtension) {
1108         KdPrint2((PRINT_PREFIX "!deviceExtension => SP_RETURN_ERROR\n"));
1109         return SP_RETURN_ERROR;
1110     }
1111     RtlZeroMemory(deviceExtension, sizeof(HW_DEVICE_EXTENSION));
1112 /*
1113     vendorStrPtr = vendorString;
1114     deviceStrPtr = deviceString;
1115 */
1116     slotNumber = BMList[i].slotNumber;
1117     SystemIoBusNumber = BMList[i].busNumber;
1118 
1119 
1120     KdPrint2((PRINT_PREFIX "AdapterInterfaceType=%#x\n",ConfigInfo->AdapterInterfaceType));
1121     KdPrint2((PRINT_PREFIX "IoBusNumber=%#x\n",ConfigInfo->SystemIoBusNumber));
1122     KdPrint2((PRINT_PREFIX "slotNumber=%#x\n",slotNumber));
1123 
1124     // this buffer must be global and already filled for UNIATA_CORE build
1125     busDataRead = HalGetBusData(
1126         //busDataRead = ScsiPortGetBusData(HwDeviceExtension,
1127                                      PCIConfiguration,
1128                                      SystemIoBusNumber,
1129                                      slotNumber,
1130                                      &pciData,
1131                                      PCI_COMMON_HDR_LENGTH);
1132 
1133 #ifndef UNIATA_CORE
1134     if (busDataRead < (ULONG)PCI_COMMON_HDR_LENGTH) {
1135         KdPrint2((PRINT_PREFIX "busDataRead < PCI_COMMON_HDR_LENGTH => SP_RETURN_ERROR\n"));
1136         goto exit_error;
1137     }
1138 
1139     KdPrint2((PRINT_PREFIX "busDataRead\n"));
1140     if (pciData.VendorID == PCI_INVALID_VENDORID) {
1141         KdPrint2((PRINT_PREFIX "PCI_INVALID_VENDORID\n"));
1142         goto exit_error;
1143     }
1144 #endif //UNIATA_CORE
1145 
1146     VendorID  = pciData.VendorID;
1147     DeviceID  = pciData.DeviceID;
1148     BaseClass = pciData.BaseClass;
1149     SubClass  = pciData.SubClass;
1150     RevID     = pciData.RevisionID;
1151     dev_id = VendorID | (DeviceID << 16);
1152     slotData.u.AsULONG = slotNumber;
1153     KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
1154 
1155     deviceExtension->slotNumber = slotNumber;
1156     deviceExtension->SystemIoBusNumber = SystemIoBusNumber;
1157     deviceExtension->DevID = dev_id;
1158     deviceExtension->RevID = RevID;
1159     deviceExtension->NumberChannels = IDE_DEFAULT_MAX_CHAN; // default
1160     deviceExtension->NumberLuns = IDE_MAX_LUN_PER_CHAN; // default
1161     deviceExtension->DevIndex = i;
1162 
1163     _snprintf(deviceExtension->Signature, sizeof(deviceExtension->Signature),
1164               "UATA%8.8x/%1.1x@%8.8x", dev_id, channel, slotNumber);
1165 
1166     if(BaseClass != PCI_DEV_CLASS_STORAGE) {
1167         KdPrint2((PRINT_PREFIX "BaseClass != PCI_DEV_CLASS_STORAGE => SP_RETURN_NOT_FOUND\n"));
1168         goto exit_notfound;
1169     }
1170 
1171     KdPrint2((PRINT_PREFIX "Storage Class\n"));
1172 
1173     // look for known chipsets
1174     if(VendorID != BMList[i].nVendorId ||
1175        DeviceID != BMList[i].nDeviceId) {
1176         KdPrint2((PRINT_PREFIX "device not suitable\n"));
1177         goto exit_notfound;
1178     }
1179 
1180     found = UniataCheckPCISubclass(BMList[i].Known, BMList[i].RaidFlags, SubClass);
1181     if(!found) {
1182         KdPrint2((PRINT_PREFIX "Subclass not supported\n"));
1183         goto exit_notfound;
1184     }
1185 
1186     ConfigInfo->AlignmentMask = 0x00000003;
1187 
1188     MasterDev = IsMasterDev(&pciData);
1189 
1190     if(MasterDev) {
1191         KdPrint2((PRINT_PREFIX "MasterDev (1)\n"));
1192         deviceExtension->MasterDev = TRUE;
1193         KdPrint2((PRINT_PREFIX "Check exclude\n"));
1194         if(AtapiRegCheckDevValue(deviceExtension, channel, DEVNUM_NOT_SPECIFIED, L"Exclude", 0)) {
1195             KdPrint2((PRINT_PREFIX "Device excluded\n"));
1196             goto exit_notfound;
1197         }
1198     }
1199 
1200     status = UniataChipDetect(HwDeviceExtension, &pciData, i, ConfigInfo, &simplexOnly);
1201     switch(status) {
1202     case STATUS_SUCCESS:
1203         found = TRUE;
1204         break;
1205     case STATUS_NOT_FOUND:
1206         found = FALSE;
1207         break;
1208     default:
1209         KdPrint2((PRINT_PREFIX "FAILED => SP_RETURN_ERROR\n"));
1210         goto exit_error;
1211     }
1212     KdPrint2((PRINT_PREFIX "ForceSimplex = %d\n", simplexOnly));
1213     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (0)", deviceExtension->HwFlags));
1214     switch(dev_id) {
1215     /* additional checks for some supported chipsets */
1216     case 0xc6931080:
1217         if (SubClass != PCI_DEV_SUBCLASS_IDE) {
1218             KdPrint2((PRINT_PREFIX "0xc6931080, SubClass != PCI_DEV_SUBCLASS_IDE => found = FALSE\n"));
1219             found = FALSE;
1220         } else {
1221             found = FALSE;
1222         }
1223         break;
1224 
1225     /* unknown chipsets, try generic DMA if it seems possible */
1226     default:
1227         if (found)
1228             break;
1229         KdPrint2((PRINT_PREFIX "Default device\n"));
1230         if(Ata_is_supported_dev(&pciData)) {
1231             KdPrint2((PRINT_PREFIX "Ata_is_supported_dev\n"));
1232             found = TRUE;
1233         } else
1234         if(deviceExtension->HwFlags & UNIATA_AHCI) {
1235             KdPrint2((PRINT_PREFIX "AHCI candidate\n"));
1236             found = TRUE;
1237         } else {
1238             KdPrint2((PRINT_PREFIX "!Ata_is_supported_dev => found = FALSE\n"));
1239             found = FALSE;
1240         }
1241         deviceExtension->UnknownDev = TRUE;
1242         break;
1243     }
1244 
1245     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (1)", deviceExtension->HwFlags));
1246     if(!found) {
1247         KdPrint2((PRINT_PREFIX "!found => SP_RETURN_NOT_FOUND\n"));
1248         goto exit_notfound;
1249     }
1250 
1251     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (2)", deviceExtension->HwFlags));
1252     KdPrint2((PRINT_PREFIX "found suitable device\n"));
1253 
1254     /***********************************************************/
1255     /***********************************************************/
1256     /***********************************************************/
1257 
1258     deviceExtension->UseDpc = TRUE;
1259 #ifndef UNIATA_CORE
1260     if (g_Dump) {
1261         deviceExtension->DriverMustPoll = TRUE;
1262         deviceExtension->UseDpc = FALSE;
1263         deviceExtension->simplexOnly = TRUE;
1264         deviceExtension->HwFlags |= UNIATA_NO_DPC;
1265     }
1266 #endif //UNIATA_CORE
1267     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (3)", deviceExtension->HwFlags));
1268     if(deviceExtension->HwFlags & UNIATA_NO_DPC) {
1269         /* CMD 649, ROSB SWK33, ICH4 */
1270         KdPrint2((PRINT_PREFIX "UniataFindBusMasterController: UNIATA_NO_DPC (0)\n"));
1271         deviceExtension->UseDpc = FALSE;
1272     }
1273 
1274     if(MasterDev) {
1275         if((WinVer_Id() <= WinVer_NT) && AltInit && FirstMasterOk) {
1276             // this is the 2nd attempt to init this controller by OUR driver
1277             KdPrint2((PRINT_PREFIX "Skip primary/secondary claiming checks\n"));
1278         } else {
1279             if((channel==0) && ConfigInfo->AtdiskPrimaryClaimed) {
1280                 KdPrint2((PRINT_PREFIX "Error: Primary channel already claimed by another driver\n"));
1281                 goto exit_notfound;
1282             }
1283             if((channel==1) && ConfigInfo->AtdiskSecondaryClaimed) {
1284                 KdPrint2((PRINT_PREFIX "Error: Secondary channel already claimed by another driver\n"));
1285                 goto exit_notfound;
1286             }
1287         }
1288     }
1289     if(deviceExtension->HwFlags & UNIATA_AHCI) {
1290         KdPrint2((PRINT_PREFIX "  AHCI registers layout\n"));
1291     } else
1292     if(deviceExtension->AltRegMap) {
1293         KdPrint2((PRINT_PREFIX "  Non-standard registers layout\n"));
1294         if(deviceExtension->HwFlags & UNIATA_SATA) {
1295             KdPrint2((PRINT_PREFIX "UNIATA_SATA -> IsBusMaster == TRUE\n"));
1296             if(!deviceExtension->BusMaster) {
1297                 deviceExtension->BusMaster = DMA_MODE_BM;
1298             }
1299         }
1300     } else {
1301         deviceExtension->BusMaster = DMA_MODE_NONE;
1302 
1303         if(WinVer_WDM_Model && !deviceExtension->UnknownDev) {
1304             UniataEnableIoPCI(ConfigInfo->SystemIoBusNumber, slotData.u.AsULONG, &pciData);
1305         }
1306         // validate Mem/Io ranges
1307         //no_ranges = TRUE;
1308         {
1309             ULONG j;
1310             for(j=0; j<PCI_TYPE0_ADDRESSES; j++) {
1311                 if(pciData.u.type0.BaseAddresses[j] & ~0x7) {
1312                     //no_ranges = FALSE;
1313                     //break;
1314                     KdPrint2((PRINT_PREFIX "Range %d = %#x\n", j, pciData.u.type0.BaseAddresses[j]));
1315                 }
1316             }
1317         }
1318 
1319         if(IsBusMaster(&pciData)) {
1320 
1321             KdPrint2((PRINT_PREFIX "IsBusMaster == TRUE\n"));
1322             BaseIoAddressBM_0 = (PIDE_BUSMASTER_REGISTERS)
1323                 (AtapiGetIoRange(HwDeviceExtension, ConfigInfo, &pciData, SystemIoBusNumber,
1324                                 4, bm_offset, MasterDev ? 0x08 : 0x10/*ATA_BMIOSIZE*/)/* - bm_offset*/); //range id
1325             if(BaseIoAddressBM_0) {
1326                 UniataInitMapBM(deviceExtension,
1327                                 BaseIoAddressBM_0,
1328                                 (*ConfigInfo->AccessRanges)[4].RangeInMemory ? TRUE : FALSE);
1329                 deviceExtension->BusMaster = DMA_MODE_BM;
1330                 deviceExtension->BaseIoAddressBM_0.Addr  = (ULONGIO_PTR)BaseIoAddressBM_0;
1331                 if((*ConfigInfo->AccessRanges)[4].RangeInMemory) {
1332                     deviceExtension->BaseIoAddressBM_0.MemIo = TRUE;
1333                 }
1334             }
1335             KdPrint2((PRINT_PREFIX "  BusMasterAddress (base): %#x\n", BaseIoAddressBM_0));
1336         }
1337 
1338         if(!deviceExtension->BusMaster) {
1339             KdPrint2((PRINT_PREFIX "  !BusMasterAddress -> PIO4\n"));
1340             deviceExtension->MaxTransferMode = ATA_PIO4;
1341         }
1342 
1343         if(deviceExtension->BusMaster && !MasterDev) {
1344             KdPrint2((PRINT_PREFIX "IsBusMaster == TRUE && !MasterDev\n"));
1345             statusByte = AtapiReadPort1(&(deviceExtension->chan[0]), IDX_BM_Status);
1346             KdPrint2((PRINT_PREFIX "  BM statusByte = %x\n", statusByte));
1347             if(statusByte == IDE_STATUS_WRONG) {
1348                 KdPrint2((PRINT_PREFIX "  invalid port ?\n"));
1349                 deviceExtension->BusMaster = DMA_MODE_NONE;
1350 /*
1351                 if(BaseIoAddressBM_0) {
1352                     ScsiPortFreeDeviceBase(HwDeviceExtension,
1353                                            BaseIoAddressBM_0);
1354                     BaseIoAddressBM_0 = NULL;
1355                 }
1356 */
1357             } else
1358             if(statusByte & BM_STATUS_SIMPLEX_ONLY) {
1359                 KdPrint2((PRINT_PREFIX "  BM_STATUS => simplexOnly\n"));
1360                 simplexOnly = TRUE;
1361             }
1362         }
1363     }
1364 
1365     /*
1366      * the Cypress chip is a mess, it contains two ATA functions, but
1367      * both channels are visible on the first one.
1368      * simply ignore the second function for now, as the right
1369      * solution (ignoring the second channel on the first function)
1370      * doesn't work with the crappy ATA interrupt setup on the alpha.
1371      */
1372     if (dev_id == 0xc6931080 && slotData.u.bits.FunctionNumber > 1) {
1373         KdPrint2((PRINT_PREFIX "dev_id == 0xc6931080 && FunctionNumber > 1 => exit_findbm\n"));
1374         goto exit_findbm;
1375     }
1376 
1377     /* do extra chipset specific setups */
1378     AtapiReadChipConfig(HwDeviceExtension, i, CHAN_NOT_SPECIFIED);
1379     AtapiChipInit(HwDeviceExtension, i, CHAN_NOT_SPECIFIED_CHECK_CABLE);
1380 
1381     simplexOnly |= deviceExtension->simplexOnly;
1382     deviceExtension->simplexOnly |= simplexOnly;
1383 
1384     KdPrint2((PRINT_PREFIX "simplexOnly = %d (2)", simplexOnly));
1385 
1386     //TODO: fix hang with UseDpc=TRUE in Simplex mode
1387     //deviceExtension->UseDpc = TRUE;
1388     if(simplexOnly) {
1389         KdPrint2((PRINT_PREFIX "simplexOnly => UseDpc = FALSE\n"));
1390         deviceExtension->UseDpc = FALSE;
1391     }
1392 
1393     if(simplexOnly && MasterDev) {
1394         if(deviceExtension->NumberChannels < IDE_DEFAULT_MAX_CHAN) {
1395             KdPrint2((PRINT_PREFIX "set NumberChannels = %d\n", IDE_DEFAULT_MAX_CHAN));
1396             deviceExtension->NumberChannels = IDE_DEFAULT_MAX_CHAN;
1397             if(BaseIoAddressBM_0) {
1398                 UniataInitMapBM(deviceExtension,
1399                                 BaseIoAddressBM_0,
1400                                 (*ConfigInfo->AccessRanges)[4].RangeInMemory ? TRUE : FALSE);
1401             }
1402         }
1403     }
1404     if((channel > 0) &&
1405        (deviceExtension->NumberChannels > 1)) {
1406         KdPrint2((PRINT_PREFIX "Error: channel > 0 && NumberChannels > 1\n"));
1407         goto exit_findbm;
1408     }
1409 
1410     // Indicate number of buses.
1411     ConfigInfo->NumberOfBuses = (UCHAR)(deviceExtension->NumberChannels);
1412     if(!ConfigInfo->InitiatorBusId[0]) {
1413         ConfigInfo->InitiatorBusId[0] = (CHAR)(IoGetConfigurationInformation()->ScsiPortCount);
1414         KdPrint2((PRINT_PREFIX "set ConfigInfo->InitiatorBusId[0] = %#x\n", ConfigInfo->InitiatorBusId[0]));
1415     }
1416     // Indicate four devices can be attached to the adapter
1417     ConfigInfo->MaximumNumberOfTargets = (UCHAR)(deviceExtension->NumberLuns);
1418 
1419     if (MasterDev) {
1420         KdPrint2((PRINT_PREFIX "MasterDev (2)\n"));
1421 /*
1422         if((WinVer_Id() > WinVer_NT) ||
1423            (deviceExtension->NumberChannels > 1)) {
1424 
1425             KdPrint2((PRINT_PREFIX "2 channels & 2 irq for 1 controller Win 2000+\n"));
1426 
1427             if (ConfigInfo->AdapterInterfaceType == MicroChannel) {
1428                 ConfigInfo->InterruptMode2 =
1429                 ConfigInfo->InterruptMode = LevelSensitive;
1430             } else {
1431                 ConfigInfo->InterruptMode2 =
1432                 ConfigInfo->InterruptMode = Latched;
1433             }
1434             ConfigInfo->BusInterruptLevel = 14;
1435             ConfigInfo->BusInterruptLevel2 = 15;
1436         } else*/
1437         if(simplexOnly) {
1438 
1439             KdPrint2((PRINT_PREFIX "2 channels & 2 irq for 1 controller\n"));
1440 
1441             if (ConfigInfo->AdapterInterfaceType == MicroChannel) {
1442                 ConfigInfo->InterruptMode2 =
1443                 ConfigInfo->InterruptMode = LevelSensitive;
1444             } else {
1445                 ConfigInfo->InterruptMode2 =
1446                 ConfigInfo->InterruptMode = Latched;
1447             }
1448             ConfigInfo->BusInterruptLevel = 14;
1449             ConfigInfo->BusInterruptLevel2 = 15;
1450         } else {
1451             KdPrint2((PRINT_PREFIX "1 channels & 1 irq for 1 controller\n"));
1452             if (ConfigInfo->AdapterInterfaceType == MicroChannel) {
1453                 ConfigInfo->InterruptMode = LevelSensitive;
1454             } else {
1455                 ConfigInfo->InterruptMode = Latched;
1456             }
1457             ConfigInfo->BusInterruptLevel = (channel == 0 ? 14 : 15);
1458         }
1459     } else {
1460         KdPrint2((PRINT_PREFIX "!MasterDev\n"));
1461         ConfigInfo->SlotNumber = slotNumber;
1462         ConfigInfo->SystemIoBusNumber = SystemIoBusNumber;
1463         ConfigInfo->InterruptMode = LevelSensitive;
1464 
1465         /* primary and secondary channels share the same interrupt */
1466         if(!ConfigInfo->BusInterruptVector ||
1467             (ConfigInfo->BusInterruptVector != pciData.u.type0.InterruptLine)) {
1468             KdPrint2((PRINT_PREFIX "patch irq line = %#x\n", pciData.u.type0.InterruptLine));
1469             ConfigInfo->BusInterruptVector = pciData.u.type0.InterruptLine;  // set default value
1470             if(!ConfigInfo->BusInterruptVector) {
1471                 KdPrint2((PRINT_PREFIX "patch irq line (2) = 10\n"));
1472                 ConfigInfo->BusInterruptVector = 10;
1473             }
1474         }
1475     }
1476     ConfigInfo->MultipleRequestPerLu = TRUE;
1477     ConfigInfo->AutoRequestSense     = TRUE;
1478     ConfigInfo->TaggedQueuing        = TRUE;
1479 
1480     if((WinVer_Id() >= WinVer_NT) ||
1481        (ConfigInfo->Length >= sizeof(_ConfigInfo->comm) + sizeof(_ConfigInfo->nt4))) {
1482         KdPrint2((PRINT_PREFIX "update ConfigInfo->nt4\n"));
1483         _ConfigInfo->nt4.DeviceExtensionSize         = sizeof(HW_DEVICE_EXTENSION);
1484         _ConfigInfo->nt4.SpecificLuExtensionSize     = sizeof(HW_LU_EXTENSION);
1485         //if(deviceExtension->HwFlags & UNIATA_AHCI) {
1486            _ConfigInfo->nt4.SrbExtensionSize            = sizeof(ATA_REQ);
1487         //} else {
1488         //   _ConfigInfo->nt4.SrbExtensionSize            = FIELD_OFFSET(ATA_REQ, dma_tab) + sizeof(BM_DMA_ENTRY)*ATA_DMA_ENTRIES;
1489         //}
1490         KdPrint2((PRINT_PREFIX "using AtaReq sz %x\n", _ConfigInfo->nt4.SrbExtensionSize));
1491     }
1492     if((WinVer_Id() > WinVer_2k) ||
1493        (ConfigInfo->Length >= sizeof(_ConfigInfo->comm) + sizeof(_ConfigInfo->nt4) + sizeof(_ConfigInfo->w2k))) {
1494         KdPrint2((PRINT_PREFIX "update ConfigInfo->w2k: 64bit %d\n",
1495             deviceExtension->Host64));
1496 #ifdef USE_OWN_DMA
1497         // We need not set Dma64BitAddresses since we perform address translation manually.
1498 #else
1499         _ConfigInfo->w2k.Dma64BitAddresses           = deviceExtension->Host64;
1500 #endif //USE_OWN_DMA
1501         _ConfigInfo->w2k.ResetTargetSupported        = TRUE;
1502         _ConfigInfo->w2k.MaximumNumberOfLogicalUnits = (UCHAR)deviceExtension->NumberLuns;
1503     }
1504 
1505     // Save the Interrupe Mode for later use
1506     deviceExtension->InterruptMode      = ConfigInfo->InterruptMode;
1507     deviceExtension->BusInterruptLevel  = ConfigInfo->BusInterruptLevel;
1508     deviceExtension->BusInterruptVector = ConfigInfo->BusInterruptVector;
1509     deviceExtension->Channel            = channel;
1510     deviceExtension->DevIndex           = i;
1511     deviceExtension->OrigAdapterInterfaceType
1512                                         = ConfigInfo->AdapterInterfaceType;
1513     deviceExtension->AlignmentMask      = ConfigInfo->AlignmentMask;
1514     deviceExtension->AdapterInterfaceType = PCIBus;
1515 
1516     KdPrint2((PRINT_PREFIX "chan[%d] InterruptMode: %d, Level %d, Level2 %d, Vector %d, Vector2 %d\n",
1517         channel,
1518         ConfigInfo->InterruptMode,
1519         ConfigInfo->BusInterruptLevel,
1520         ConfigInfo->BusInterruptLevel2,
1521         ConfigInfo->BusInterruptVector,
1522         ConfigInfo->BusInterruptVector2
1523         ));
1524 
1525     found = FALSE;
1526 
1527     if(deviceExtension->BusMaster) {
1528 
1529         KdPrint2((PRINT_PREFIX "Reconstruct ConfigInfo\n"));
1530 #ifdef USE_OWN_DMA
1531         ConfigInfo->NeedPhysicalAddresses = FALSE;
1532 #else
1533         ConfigInfo->NeedPhysicalAddresses = TRUE;
1534 #endif //USE_OWN_DMA
1535         if(!MasterDev) {
1536 //#ifdef USE_OWN_DMA
1537 //            KdPrint2((PRINT_PREFIX "!MasterDev, own DMA\n"));
1538 //#else
1539             KdPrint2((PRINT_PREFIX "set Dma32BitAddresses\n"));
1540             ConfigInfo->Dma32BitAddresses = TRUE;
1541 //#endif //USE_OWN_DMA
1542         }
1543 
1544         // thanks to Vitaliy Vorobyov aka deathsoft@yandex.ru for
1545         // better solution:
1546 
1547         if(AltInit) {
1548             // I'm sorry, I have to do this
1549             // when Win doesn't
1550 
1551             if(ConfigInfo->AdapterInterfaceType == Isa /*&&
1552 //               InDriverEntry*/) {
1553                 KdPrint2((PRINT_PREFIX "AdapterInterfaceType Isa => PCIBus\n"));
1554                 ConfigInfo->AdapterInterfaceType = PCIBus;
1555             }
1556             if(ConfigInfo->AdapterInterfaceType == PCIBus /*&&
1557 //               InDriverEntry*/) {
1558                 KdPrint2((PRINT_PREFIX "AdapterInterfaceType PCIBus, update address\n"));
1559                 ConfigInfo->SlotNumber = slotNumber;
1560                 ConfigInfo->SystemIoBusNumber = SystemIoBusNumber;
1561             }
1562         }
1563 
1564 #ifndef USE_OWN_DMA
1565         ConfigInfo->Master        = TRUE;
1566         ConfigInfo->DmaWidth      = Width16Bits;
1567 #endif //USE_OWN_DMA
1568         ConfigInfo->ScatterGather = TRUE;
1569     }
1570     ConfigInfo->MapBuffers = TRUE; // Need for PIO and OWN_DMA
1571     ConfigInfo->CachesData = TRUE;
1572 
1573     KdPrint2((PRINT_PREFIX "BMList[i].channel %#x, NumberChannels %#x, channel %#x\n",BMList[i].channel, deviceExtension->NumberChannels, channel));
1574 
1575     for (; channel < (BMList[i].channel + deviceExtension->NumberChannels); channel++, c++) {
1576 
1577         KdPrint2((PRINT_PREFIX "de %#x, Channel %#x\n",deviceExtension, channel));
1578         //PrintNtConsole("de %#x, Channel %#x, nchan %#x\n",deviceExtension, channel, deviceExtension->NumberChannels);
1579         chan = &deviceExtension->chan[c];
1580 
1581         KdPrint2((PRINT_PREFIX "chan = %#x\n", chan));
1582         //PrintNtConsole("chan = %#x, c=%#x\n", chan, c);
1583         AtapiSetupLunPtrs(chan, deviceExtension, c);
1584 
1585         /* do extra channel-specific setups */
1586         AtapiReadChipConfig(HwDeviceExtension, i, channel);
1587         //AtapiChipInit(HwDeviceExtension, i, channel);
1588         if(deviceExtension->HwFlags & UNIATA_AHCI) {
1589             KdPrint2((PRINT_PREFIX "  No more setup for AHCI channel\n"));
1590         } else
1591         if(deviceExtension->AltRegMap) {
1592             KdPrint2((PRINT_PREFIX "  Non-standard registers layout\n"));
1593         } else {
1594             // Check if the range specified is not used by another driver
1595             if(MasterDev) {
1596                 KdPrint2((PRINT_PREFIX "set AccessRanges\n"));
1597                 (*ConfigInfo->AccessRanges)[channel * 2 + 0].RangeStart =
1598                     ScsiPortConvertUlongToPhysicalAddress(channel ? IO_WD2 : IO_WD1);
1599                 (*ConfigInfo->AccessRanges)[channel * 2 + 0].RangeLength = ATA_IOSIZE;
1600 
1601                 (*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeStart =
1602                     ScsiPortConvertUlongToPhysicalAddress((channel ? IO_WD2 : IO_WD1) + ATA_ALTOFFSET);
1603                 (*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeLength = ATA_ALTIOSIZE;
1604             } else
1605             if(AltInit &&
1606                !(*ConfigInfo->AccessRanges)[channel * 2 + 0].RangeStart.QuadPart &&
1607                !(*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeStart.QuadPart) {
1608                 KdPrint2((PRINT_PREFIX "cheat ScsiPort, sync real PCI and ConfigInfo IO ranges\n"));
1609                 AtapiGetIoRange(HwDeviceExtension, ConfigInfo, &pciData, SystemIoBusNumber,
1610                         channel * 2 + 0, 0, ATA_IOSIZE);
1611                 AtapiGetIoRange(HwDeviceExtension, ConfigInfo, &pciData, SystemIoBusNumber,
1612                         channel * 2 + 1, 0, ATA_ALTIOSIZE);
1613             }
1614 
1615             IoBasePort1 = (*ConfigInfo->AccessRanges)[channel * 2 + 0].RangeStart;
1616             IoBasePort2 = (*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeStart;
1617 
1618             if(!MasterDev) {
1619                 if(!IoBasePort1.QuadPart || !IoBasePort2.QuadPart) {
1620                     KdPrint2((PRINT_PREFIX "ScsiPortValidateRange failed (1)\n"));
1621                     continue;
1622                 }
1623             }
1624 
1625             if(!ScsiPortValidateRange(HwDeviceExtension,
1626                                       PCIBus /*ConfigInfo->AdapterInterfaceType*/,
1627                                       SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/,
1628                                       IoBasePort1,
1629                                       ATA_IOSIZE,
1630                                       TRUE) ) {
1631                 KdPrint2((PRINT_PREFIX "ScsiPortValidateRange failed (1)\n"));
1632                 continue;
1633             }
1634 
1635             if(!ScsiPortValidateRange(HwDeviceExtension,
1636                                       PCIBus /*ConfigInfo->AdapterInterfaceType*/,
1637                                       SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/,
1638                                       IoBasePort2,
1639                                       ATA_ALTIOSIZE,
1640                                       TRUE) ) {
1641                 KdPrint2((PRINT_PREFIX "ScsiPortValidateRange failed (2)\n"));
1642                 continue;
1643             }
1644 
1645             KdPrint2((PRINT_PREFIX "Getting IO ranges\n"));
1646 
1647             // Ok, translate adresses to io-space
1648             if(ScsiPortConvertPhysicalAddressToUlong(IoBasePort2)) {
1649                 if(!(MasterDev /* || USE_16_BIT */)) {
1650                     KdPrint2((PRINT_PREFIX "!MasterDev mode\n"));
1651                     IoBasePort2 = ScsiPortConvertUlongToPhysicalAddress(
1652                                       ScsiPortConvertPhysicalAddressToUlong(IoBasePort2) + 2);
1653                 }
1654             } else {
1655                 KdPrint2((PRINT_PREFIX "use relative IoBasePort2\n"));
1656                 IoBasePort2 = ScsiPortConvertUlongToPhysicalAddress(
1657                                   ScsiPortConvertPhysicalAddressToUlong(IoBasePort1) + ATA_PCCARD_ALTOFFSET);
1658             }
1659 
1660             // Get the system physical address for this IO range.
1661             ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
1662                                             MasterDev ? ConfigInfo->AdapterInterfaceType : PCIBus /*ConfigInfo->AdapterInterfaceType*/,
1663                                             MasterDev ? ConfigInfo->SystemIoBusNumber : SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/,
1664                                             IoBasePort1,
1665                                             ATA_IOSIZE,
1666                                             TRUE);
1667             KdPrint2((PRINT_PREFIX "IO range 1 %#x\n",ioSpace));
1668 
1669             // Check if ioSpace accessible.
1670             if (!ioSpace) {
1671                 KdPrint2((PRINT_PREFIX "!ioSpace\n"));
1672                 continue;
1673             }
1674 /*
1675             if(deviceExtension->BusMaster) {
1676                 KdPrint2((PRINT_PREFIX "set BusMaster io-range in DO\n"));
1677                 // bm_offset already includes (channel ? ATA_BM_OFFSET1 : 0)
1678                 deviceExtension->BaseIoAddressBM[c] = (PIDE_BUSMASTER_REGISTERS)
1679                     ((ULONG)(deviceExtension->BaseIoAddressBM_0) + bm_offset + (c ? ATA_BM_OFFSET1 : 0));
1680             }
1681 */
1682             //deviceExtension->BaseIoAddress1[c] = (PIDE_REGISTERS_1)(ioSpace);
1683             BaseIoAddress1[c] = (PIDE_REGISTERS_1)(ioSpace);
1684 
1685             // Get the system physical address for the second IO range.
1686             ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
1687                                             MasterDev ? ConfigInfo->AdapterInterfaceType : PCIBus /*ConfigInfo->AdapterInterfaceType*/,
1688                                             MasterDev ? ConfigInfo->SystemIoBusNumber : SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/,
1689                                             IoBasePort2,
1690                                             ATA_ALTIOSIZE,
1691                                             TRUE);
1692             KdPrint2((PRINT_PREFIX "IO range 2 %#x\n",ioSpace));
1693 
1694             BaseIoAddress2[c] = (PIDE_REGISTERS_2)(ioSpace);
1695             if(!ioSpace) {
1696                 // Release all allocated resources
1697                 KdPrint2((PRINT_PREFIX "!deviceExtension->BaseIoAddress2\n"));
1698                 //ioSpace = (PUCHAR)BaseIoAddress1[c];
1699     //            goto free_iospace_1;
1700                 found = FALSE;
1701                 goto exit_findbm;
1702             }
1703             UniataInitMapBase(chan, BaseIoAddress1[c], BaseIoAddress2[c]);
1704         }
1705         //ioSpace = (PUCHAR)(deviceExtension->BaseIoAddress1[c]);
1706 
1707         DbgDumpRegTranslation(chan, IDX_IO1);
1708         DbgDumpRegTranslation(chan, IDX_IO2);
1709         DbgDumpRegTranslation(chan, IDX_BM_IO);
1710         DbgDumpRegTranslation(chan, IDX_SATA_IO);
1711 
1712         if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
1713 #ifdef _DEBUG
1714             UniataDumpATARegs(chan);
1715 #endif
1716 
1717 #ifndef UNIATA_CORE
1718 #ifdef UNIATA_INIT_ON_PROBE
1719 //        if(deviceExtension->HwFlags & UNIATA_SATA) {
1720 //#endif //UNIATA_INIT_ON_PROBE
1721             KdPrint2((PRINT_PREFIX "Check drive 0\n"));
1722             // Check master.
1723             SelectDrive(chan, 0);
1724             AtapiStallExecution(10);
1725             GetBaseStatus(chan, statusByte);
1726             skip_find_dev = FALSE;
1727             if(!(deviceExtension->HwFlags & UNIATA_NO_SLAVE) && (deviceExtension->NumberLuns > 1)) {
1728                 if ((statusByte & 0xf8) == 0xf8 ||
1729                     (statusByte == 0xa5)) {
1730                     // Check slave.
1731                     KdPrint2((PRINT_PREFIX "Check drive 1\n"));
1732                     SelectDrive(chan, 1);
1733                     AtapiStallExecution(1);
1734                     GetBaseStatus(chan, statusByte);
1735                     if ((statusByte & 0xf8) == 0xf8 ||
1736                         (statusByte == 0xa5)) {
1737                         // No controller at this base address.
1738                         KdPrint2((PRINT_PREFIX "Empty channel\n"));
1739                         skip_find_dev = TRUE;
1740                     }
1741                 }
1742             }
1743 
1744             // Search for devices on this controller.
1745             if (!skip_find_dev &&
1746                 FindDevices(HwDeviceExtension,
1747                         0,
1748                         c)) {
1749                 KdPrint2((PRINT_PREFIX "Found some devices\n"));
1750                 found = TRUE;
1751             } else {
1752                 KdPrint2((PRINT_PREFIX "no devices\n"));
1753     /*            KeBugCheckEx(0xc000000e,
1754                              ScsiPortConvertPhysicalAddressToUlong(IoBasePort1),
1755                              ScsiPortConvertPhysicalAddressToUlong(IoBasePort2),
1756                              (ULONG)(deviceExtension->BaseIoAddressBM[c]), skip_find_dev);*/
1757             }
1758 //#ifdef UNIATA_INIT_ON_PROBE
1759 //        }
1760 #else //UNIATA_INIT_ON_PROBE
1761             KdPrint2((PRINT_PREFIX "clean IDE intr 0\n"));
1762 
1763             SelectDrive(chan, 0);
1764             AtapiStallExecution(10);
1765             GetBaseStatus(chan, statusByte);
1766 
1767             if(!(deviceExtension->HwFlags & UNIATA_NO_SLAVE) && (deviceExtension->NumberLuns > 1)) {
1768                 KdPrint2((PRINT_PREFIX "clean IDE intr 1\n"));
1769 
1770                 SelectDrive(chan, 1);
1771                 AtapiStallExecution(1);
1772                 GetBaseStatus(chan, statusByte);
1773 
1774                 SelectDrive(chan, 0);
1775             }
1776 
1777             statusByte = GetDmaStatus(deviceExtension, c);
1778             KdPrint2((PRINT_PREFIX "  DMA status %#x\n", statusByte));
1779             if(statusByte & BM_STATUS_INTR) {
1780                 // bullshit, we have DMA interrupt, but had never initiate DMA operation
1781                 KdPrint2((PRINT_PREFIX "  clear unexpected DMA intr\n"));
1782                 AtapiDmaDone(deviceExtension, 0, c, NULL);
1783                 GetBaseStatus(chan, statusByte);
1784             }
1785 
1786 #endif //UNIATA_INIT_ON_PROBE
1787         }
1788         found = TRUE;
1789 
1790         chan->PrimaryAddress = FALSE;
1791         // Claim primary or secondary ATA IO range.
1792         if (MasterDev) {
1793             KdPrint2((PRINT_PREFIX "claim Compatible controller\n"));
1794             if (channel == 0) {
1795                 KdPrint2((PRINT_PREFIX "claim Primary\n"));
1796                 AtdiskPrimaryClaimed =
1797                 ConfigInfo->AtdiskPrimaryClaimed = TRUE;
1798                 chan->PrimaryAddress = TRUE;
1799 
1800                 FirstMasterOk = TRUE;
1801 
1802             } else
1803             if (channel == 1) {
1804                 KdPrint2((PRINT_PREFIX "claim Secondary\n"));
1805                 AtdiskSecondaryClaimed =
1806                 ConfigInfo->AtdiskSecondaryClaimed = TRUE;
1807 
1808                 FirstMasterOk = TRUE;
1809             }
1810         } else {
1811             if(chan->RegTranslation[IDX_IO1].Addr == IO_WD1 &&
1812                !chan->RegTranslation[IDX_IO1].MemIo) {
1813                 KdPrint2((PRINT_PREFIX "claim Primary (PCI over ISA range)\n"));
1814                 AtdiskPrimaryClaimed =
1815                 ConfigInfo->AtdiskPrimaryClaimed = TRUE;
1816             }
1817             if(chan->RegTranslation[IDX_IO1].Addr == IO_WD2 &&
1818                !chan->RegTranslation[IDX_IO1].MemIo) {
1819                 KdPrint2((PRINT_PREFIX "claim Secondary (PCI over ISA range)\n"));
1820                 AtdiskSecondaryClaimed =
1821                 ConfigInfo->AtdiskSecondaryClaimed = TRUE;
1822             }
1823         }
1824 
1825         AtapiDmaAlloc(HwDeviceExtension, ConfigInfo, c);
1826 #else //UNIATA_CORE
1827         }
1828         found = TRUE;
1829 #endif //UNIATA_CORE
1830     } // end for(channel)
1831 
1832 exit_findbm:
1833 
1834 #ifndef UNIATA_CORE
1835     if(!found) {
1836         KdPrint2((PRINT_PREFIX "exit: !found\n"));
1837         if(BaseIoAddress1[0])
1838             ScsiPortFreeDeviceBase(HwDeviceExtension,
1839                                    BaseIoAddress1[0]);
1840         if(BaseIoAddress2[0])
1841             ScsiPortFreeDeviceBase(HwDeviceExtension,
1842                                    BaseIoAddress2[0]);
1843 
1844         if(BaseIoAddress1[1])
1845             ScsiPortFreeDeviceBase(HwDeviceExtension,
1846                                    BaseIoAddress1[1]);
1847         if(BaseIoAddress2[1])
1848             ScsiPortFreeDeviceBase(HwDeviceExtension,
1849                                    BaseIoAddress2[1]);
1850 
1851         if(BaseIoAddressBM_0)
1852             ScsiPortFreeDeviceBase(HwDeviceExtension,
1853                                    BaseIoAddressBM_0);
1854 
1855         if(deviceExtension->BaseIoAHCI_0.Addr) {
1856             ScsiPortFreeDeviceBase(HwDeviceExtension,
1857                                    deviceExtension->BaseIoAHCI_0.pAddr);
1858         }
1859 
1860         KdPrint2((PRINT_PREFIX "return SP_RETURN_NOT_FOUND\n"));
1861         goto exit_notfound;
1862     } else {
1863 
1864         KdPrint2((PRINT_PREFIX "exit: init spinlock\n"));
1865         //KeInitializeSpinLock(&(deviceExtension->DpcSpinLock));
1866         deviceExtension->ActiveDpcChan =
1867         deviceExtension->FirstDpcChan = CHAN_NOT_SPECIFIED;
1868 
1869         BMList[i].Isr2Enable = FALSE;
1870 
1871         KdPrint2((PRINT_PREFIX "MasterDev=%#x, NumberChannels=%#x, Isr2DevObj=%#x\n",
1872             MasterDev, deviceExtension->NumberChannels, BMList[i].Isr2DevObj));
1873 
1874         // ConnectIntr2 should be moved to HwInitialize
1875         status = UniataConnectIntr2(HwDeviceExtension);
1876 
1877         KdPrint2((PRINT_PREFIX "MasterDev=%#x, NumberChannels=%#x, Isr2DevObj=%#x\n",
1878             MasterDev, deviceExtension->NumberChannels, BMList[i].Isr2DevObj));
1879 
1880         if(/*WinVer_WDM_Model &&*/ MasterDev) {
1881             KdPrint2((PRINT_PREFIX "do not tell system, that we know about PCI IO ranges\n"));
1882 /*            if(BaseIoAddressBM_0) {
1883                 ScsiPortFreeDeviceBase(HwDeviceExtension,
1884                                        BaseIoAddressBM_0);
1885             }*/
1886             (*ConfigInfo->AccessRanges)[4].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
1887             (*ConfigInfo->AccessRanges)[4].RangeLength = 0;
1888             (*ConfigInfo->AccessRanges)[5].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
1889             (*ConfigInfo->AccessRanges)[5].RangeLength = 0;
1890         }
1891 
1892         if(!NT_SUCCESS(status)) {
1893             KdPrint2((PRINT_PREFIX "failed\n"));
1894             found = FALSE;
1895             goto exit_findbm;
1896         }
1897 
1898         KdPrint2((PRINT_PREFIX "final chan[%d] InterruptMode: %d, Level %d, Level2 %d, Vector %d, Vector2 %d\n",
1899             channel,
1900             ConfigInfo->InterruptMode,
1901             ConfigInfo->BusInterruptLevel,
1902             ConfigInfo->BusInterruptLevel2,
1903             ConfigInfo->BusInterruptVector,
1904             ConfigInfo->BusInterruptVector2
1905             ));
1906 
1907 
1908     }
1909 #endif //UNIATA_CORE
1910 
1911     KdPrint2((PRINT_PREFIX "return SP_RETURN_FOUND\n"));
1912     //PrintNtConsole("return SP_RETURN_FOUND, de %#x, c0.lun0 %#x\n", deviceExtension, deviceExtension->chan[0].lun[0]);
1913 
1914     if(MasterDev) {
1915         KdPrint2((PRINT_PREFIX "Attempt %d of MasterDev ok\n", AltInit));
1916         FirstMasterOk = TRUE;
1917     }
1918 
1919     ConfigInfo->NumberOfBuses++; // add virtual channel for communication port
1920     return SP_RETURN_FOUND;
1921 
1922 exit_error:
1923     UniataFreeLunExt(deviceExtension);
1924     return SP_RETURN_ERROR;
1925 
1926 exit_notfound:
1927     UniataFreeLunExt(deviceExtension);
1928     return SP_RETURN_NOT_FOUND;
1929 
1930 } // end UniataFindBusMasterController()
1931 
1932 #ifndef UNIATA_CORE
1933 
1934 /*
1935    This is for claiming PCI Busmaster in compatible mode under WDM OSes
1936 */
1937 NTSTATUS
1938 NTAPI
1939 UniataClaimLegacyPCIIDE(
1940     ULONG i
1941     )
1942 {
1943     NTSTATUS status;
1944     PCM_RESOURCE_LIST resourceList = NULL;
1945     UNICODE_STRING devname;
1946 
1947     KdPrint2((PRINT_PREFIX "UniataClaimLegacyPCIIDE:\n"));
1948 
1949     if(BMList[i].PciIdeDevObj) {
1950         KdPrint2((PRINT_PREFIX "Already initialized\n"));
1951         return STATUS_UNSUCCESSFUL;
1952     }
1953 
1954     RtlInitUnicodeString(&devname, L"\\Device\\uniata_PCIIDE");
1955     status = IoCreateDevice(SavedDriverObject, sizeof(PCIIDE_DEVICE_EXTENSION),
1956                             /*NULL*/ &devname, FILE_DEVICE_UNKNOWN,
1957                             0, FALSE, &(BMList[i].PciIdeDevObj));
1958 
1959     if(!NT_SUCCESS(status)) {
1960         KdPrint2((PRINT_PREFIX "IoCreateDevice failed %#x\n", status));
1961         return status;
1962     }
1963 
1964     resourceList = (PCM_RESOURCE_LIST) ExAllocatePool(PagedPool,
1965                                 sizeof(CM_RESOURCE_LIST));
1966 
1967     if (!resourceList) {
1968         KdPrint2((PRINT_PREFIX "!resourceList\n"));
1969         status = STATUS_INSUFFICIENT_RESOURCES;
1970 del_do:
1971         IoDeleteDevice(BMList[i].PciIdeDevObj);
1972         BMList[i].PciIdeDevObj          = NULL;
1973         return status;
1974     }
1975 
1976     RtlZeroMemory(
1977         resourceList,
1978         sizeof(CM_RESOURCE_LIST));
1979 
1980     // IoReportDetectedDevice() should be used for WDM OSes
1981 
1982     // TODO: check if resourceList is actually used inside HalAssignSlotResources()
1983     // Note: with empty resourceList call to HalAssignSlotResources() fails on some HW
1984     // e.g. Intel ICH4, but works with non-empty.
1985 
1986     resourceList->Count = 1;
1987     resourceList->List[0].InterfaceType = PCIBus;
1988     resourceList->List[0].BusNumber = BMList[i].busNumber;
1989     // we do not report IO ranges since they are used/claimed by ISA part(s)
1990     resourceList->List[0].PartialResourceList.Count = 0;
1991 
1992     RtlInitUnicodeString(&devname, L"PCIIDE");
1993     status = HalAssignSlotResources(&SavedRegPath,
1994                                     &devname,
1995                                     SavedDriverObject,
1996                                     BMList[i].PciIdeDevObj,
1997                                     PCIBus,
1998                                     BMList[i].busNumber,
1999                                     BMList[i].slotNumber,
2000                                     &resourceList);
2001 
2002     if (!NT_SUCCESS(status)) {
2003         KdPrint2((PRINT_PREFIX "HalAssignSlotResources failed %#x\n", status));
2004         // this is always deallocated inside HalAssignSlotResources() implementation
2005         //ExFreePool(resourceList);
2006         goto del_do;
2007     }
2008 
2009     KdPrint2((PRINT_PREFIX "ok %#x\n", status));
2010     BMList[i].ChanInitOk |= 0x80;
2011 
2012     return status;
2013 } // end UniataClaimLegacyPCIIDE()
2014 
2015 
2016 /*++
2017 
2018 Routine Description:
2019 
2020     This function is called to initialize 2nd device object for
2021     multichannel controllers.
2022 
2023 Arguments:
2024 
2025     HwDeviceExtension - HBA miniport driver's adapter data storage
2026 
2027 Return Value:
2028 
2029     ULONG
2030 
2031 --*/
2032 NTSTATUS
2033 NTAPI
2034 UniataConnectIntr2(
2035     IN PVOID HwDeviceExtension
2036     )
2037 {
2038     PHW_DEVICE_EXTENSION  deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2039     ULONG i = deviceExtension->DevIndex;
2040     NTSTATUS status;
2041     PISR2_DEVICE_EXTENSION Isr2DevExt;
2042     WCHAR devname_str[33];
2043     UNICODE_STRING devname;
2044 
2045     KdPrint2((PRINT_PREFIX "Init ISR:\n"));
2046 
2047     /*
2048       We MUST register 2nd ISR for multichannel controllers even for UP systems.
2049       This is needed for cases when
2050       multichannel controller generate interrupt while we are still in its ISR for
2051       other channle's interrupt. New interrupt must be detected and queued for
2052       further processing. If we do not do this, system will not route this
2053       interrupt to main ISR (since it is busy) and we shall get to infinite loop
2054       looking for interrupt handler.
2055     */
2056 
2057     if(!deviceExtension->MasterDev && (deviceExtension->NumberChannels > 1) &&   // do not touch MasterDev
2058        !deviceExtension->simplexOnly && /*                        // this is unnecessary on simplex controllers
2059        !BMList[i].Isr2DevObj*/                                    // handle re-init under w2k+
2060        /*!ForceSimplex*/
2061        /*(CPU_num > 1) &&  // unnecessary for UP systems*/
2062        TRUE) {
2063         // Ok, continue...
2064         KdPrint2((PRINT_PREFIX "Multichannel native mode, go...\n"));
2065 #ifndef UNIATA_USE_XXableInterrupts
2066         // If we raise IRQL to TIMER value, other interrupt cannot occure on the same CPU
2067 /*        if(KeNumberProcessors < 2) {
2068             KdPrint2((PRINT_PREFIX "Unnecessary (?), UP machine\n"));
2069             //return STATUS_SUCCESS;
2070         }*/
2071 #endif //UNIATA_USE_XXableInterrupts
2072     } else {
2073         KdPrint2((PRINT_PREFIX "Unnecessary\n"));
2074         return STATUS_SUCCESS;
2075     }
2076 
2077     if(BMList[i].Isr2DevObj) {
2078         KdPrint2((PRINT_PREFIX "Already initialized [%d] %#x\n", i, BMList[i].Isr2DevObj));
2079         return STATUS_SUCCESS;
2080     }
2081 
2082     KdPrint2((PRINT_PREFIX "Create DO\n"));
2083 
2084     devname.Length =
2085         _snwprintf(devname_str, sizeof(devname_str)/sizeof(WCHAR)-1,
2086               L"\\Device\\uniata%d_2ch", i);
2087     devname_str[devname.Length] = 0;
2088     devname.Length *= sizeof(WCHAR);
2089     devname.MaximumLength = devname.Length;
2090     devname.Buffer = devname_str;
2091 
2092     KdPrint2((PRINT_PREFIX "DO name:  len(%d, %d), %S\n", devname.Length, devname.MaximumLength, devname.Buffer));
2093 
2094     status = IoCreateDevice(SavedDriverObject, sizeof(ISR2_DEVICE_EXTENSION),
2095                             /*NULL*/ &devname, FILE_DEVICE_UNKNOWN,
2096                             0, FALSE, &(BMList[i].Isr2DevObj));
2097 
2098     if(!NT_SUCCESS(status)) {
2099         KdPrint2((PRINT_PREFIX "IoCreateDevice failed %#x\n", status));
2100         return status;
2101     }
2102 
2103     KdPrint2((PRINT_PREFIX "HalGetInterruptVector\n"));
2104     KdPrint2((PRINT_PREFIX "  OrigAdapterInterfaceType=%d\n", deviceExtension->OrigAdapterInterfaceType));
2105     KdPrint2((PRINT_PREFIX "  SystemIoBusNumber=%d\n", deviceExtension->SystemIoBusNumber));
2106     KdPrint2((PRINT_PREFIX "  BusInterruptLevel=%d\n", deviceExtension->BusInterruptLevel));
2107     KdPrint2((PRINT_PREFIX "  BusInterruptVector=%d\n", deviceExtension->BusInterruptVector));
2108     BMList[i].Isr2Vector = HalGetInterruptVector(
2109         deviceExtension->OrigAdapterInterfaceType,
2110         deviceExtension->SystemIoBusNumber,
2111         deviceExtension->BusInterruptLevel,
2112         deviceExtension->BusInterruptVector,
2113         &(BMList[i].Isr2Irql),
2114         &(BMList[i].Isr2Affinity));
2115 
2116     Isr2DevExt = (PISR2_DEVICE_EXTENSION)(BMList[i].Isr2DevObj->DeviceExtension);
2117     Isr2DevExt->HwDeviceExtension = deviceExtension;
2118     Isr2DevExt->DevIndex = i;
2119 
2120     KdPrint2((PRINT_PREFIX "isr2_de %#x\n", Isr2DevExt));
2121     KdPrint2((PRINT_PREFIX "isr2_vector %#x\n", BMList[i].Isr2Vector));
2122     KdPrint2((PRINT_PREFIX "isr2_irql %#x\n", BMList[i].Isr2Irql));
2123     KdPrint2((PRINT_PREFIX "isr2_affinity %#x\n", BMList[i].Isr2Affinity));
2124 
2125 //            deviceExtension->QueueNewIrql = BMList[i].Isr2Irql;
2126 
2127     KdPrint2((PRINT_PREFIX "IoConnectInterrupt\n"));
2128     status = IoConnectInterrupt(
2129         &(BMList[i].Isr2InterruptObject),
2130         AtapiInterrupt2,
2131         Isr2DevExt,
2132         NULL,
2133         BMList[i].Isr2Vector,
2134         BMList[i].Isr2Irql,
2135         BMList[i].Isr2Irql,
2136         (KINTERRUPT_MODE)(deviceExtension->InterruptMode),
2137         TRUE,
2138         BMList[i].Isr2Affinity,
2139         FALSE);
2140 
2141     if(!NT_SUCCESS(status)) {
2142         KdPrint2((PRINT_PREFIX "IoConnectInterrupt failed\n"));
2143         IoDeleteDevice(BMList[i].Isr2DevObj);
2144         BMList[i].Isr2DevObj          = NULL;
2145         BMList[i].Isr2InterruptObject = NULL;
2146         return status;
2147     }
2148 
2149     //deviceExtension->Isr2DevObj = BMList[i].Isr2DevObj;
2150 
2151     return status;
2152 } // end UniataConnectIntr2()
2153 
2154 NTSTATUS
2155 NTAPI
2156 UniataDisconnectIntr2(
2157     IN PVOID HwDeviceExtension
2158     )
2159 {
2160     PHW_DEVICE_EXTENSION  deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2161     ULONG i = deviceExtension->DevIndex;
2162 //    NTSTATUS status;
2163 
2164     KdPrint2((PRINT_PREFIX "Deinit ISR:\n"));
2165 
2166     if(!BMList[i].Isr2DevObj) {
2167         KdPrint2((PRINT_PREFIX "Already uninitialized %#x\n"));
2168         return STATUS_SUCCESS;
2169     }
2170 
2171     IoDisconnectInterrupt(BMList[i].Isr2InterruptObject);
2172 
2173     BMList[i].Isr2InterruptObject = NULL;
2174 
2175     IoDeleteDevice(BMList[i].Isr2DevObj);
2176 
2177     BMList[i].Isr2DevObj          = NULL;
2178     //deviceExtension->Isr2DevObj   = NULL;
2179 
2180     return STATUS_SUCCESS;
2181 } // end UniataDisconnectIntr2()
2182 
2183 #endif //UNIATA_CORE
2184 
2185 BOOLEAN
2186 NTAPI
2187 AtapiCheckIOInterference(
2188     IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
2189     ULONG portBase) {
2190     // check if Primary/Secondary Master IDE claimed
2191     if((portBase == IO_WD1) &&
2192        (ConfigInfo->AtdiskPrimaryClaimed || AtdiskPrimaryClaimed)) {
2193         KdPrint2((PRINT_PREFIX "AtapiCheckIOInterference: AtdiskPrimaryClaimed\n"));
2194         return TRUE;
2195     } else
2196     if((portBase == IO_WD2) &&
2197        (ConfigInfo->AtdiskSecondaryClaimed || AtdiskSecondaryClaimed)) {
2198         KdPrint2((PRINT_PREFIX "AtapiCheckIOInterference: AtdiskSecondaryClaimed\n"));
2199         return TRUE;
2200     }
2201     return FALSE;
2202 } // end AtapiCheckIOInterference()
2203 
2204 /*++
2205 
2206 Routine Description:
2207 
2208     This function is called by the OS-specific port driver after
2209     the necessary storage has been allocated, to gather information
2210     about the adapter's configuration.
2211 
2212 Arguments:
2213 
2214     HwDeviceExtension - HBA miniport driver's adapter data storage
2215     Context - Address of adapter count
2216     ArgumentString - Used to determine whether driver is client of ntldr or crash dump utility.
2217     ConfigInfo - Configuration information structure describing HBA
2218     Again - Indicates search for adapters to continue
2219 
2220 Return Value:
2221 
2222     ULONG
2223 
2224 --*/
2225 ULONG
2226 NTAPI
2227 AtapiFindIsaController(
2228     IN PVOID HwDeviceExtension,
2229     IN PVOID Context,
2230     IN PVOID BusInformation,
2231     IN PCHAR ArgumentString,
2232     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
2233     OUT PBOOLEAN Again
2234     )
2235 {
2236     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2237     PHW_CHANNEL          chan;
2238     PULONG               adapterCount    = (PULONG)Context;
2239     PUCHAR               ioSpace = NULL;
2240     ULONG                i;
2241     ULONG                irq=0;
2242     ULONG                portBase=0;
2243     ULONG                retryCount;
2244 //    BOOLEAN              atapiOnly;
2245     UCHAR                statusByte, statusByte2;
2246     BOOLEAN              preConfig = FALSE;
2247     //
2248     PIDE_REGISTERS_1 BaseIoAddress1;
2249     PIDE_REGISTERS_2 BaseIoAddress2 = NULL;
2250 
2251     // The following table specifies the ports to be checked when searching for
2252     // an IDE controller.  A zero entry terminates the search.
2253     static CONST ULONG AdapterAddresses[5] = {IO_WD1, IO_WD2, IO_WD1-8, IO_WD2-8, 0};
2254 //    CONST UCHAR Channels[5] = {0, 1, 0, 1, 0};
2255 
2256     // The following table specifies interrupt levels corresponding to the
2257     // port addresses in the previous table.
2258     static CONST ULONG InterruptLevels[5] = {14, 15, 11, 10, 0};
2259 
2260     KdPrint2((PRINT_PREFIX "AtapiFindIsaController (ISA):\n"));
2261 
2262     if (!deviceExtension) {
2263         return SP_RETURN_ERROR;
2264     }
2265     RtlZeroMemory(deviceExtension, sizeof(HW_DEVICE_EXTENSION));
2266 
2267     KdPrint2((PRINT_PREFIX "  assume max PIO4\n"));
2268     deviceExtension->MaxTransferMode = ATA_PIO4;
2269     deviceExtension->NumberChannels = 1;
2270     deviceExtension->NumberLuns = IDE_MAX_LUN_PER_CHAN; // default
2271 
2272     if(!UniataAllocateLunExt(deviceExtension, UNIATA_ALLOCATE_NEW_LUNS)) {
2273         goto exit_error;
2274     }
2275 
2276     chan = &(deviceExtension->chan[0]);
2277     AtapiSetupLunPtrs(chan, deviceExtension, 0);
2278 
2279     deviceExtension->AdapterInterfaceType =
2280     deviceExtension->OrigAdapterInterfaceType
2281                                         = ConfigInfo->AdapterInterfaceType;
2282 
2283 #ifndef UNIATA_CORE
2284 
2285     /* do extra chipset specific setups */
2286     AtapiReadChipConfig(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
2287     AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
2288 
2289     // Check to see if this is a special configuration environment.
2290     portBase = irq = 0;
2291     if (ArgumentString) {
2292 
2293         irq = AtapiParseArgumentString(ArgumentString, "Interrupt");
2294         if (irq ) {
2295 
2296             // Both parameters must be present to proceed
2297             portBase = AtapiParseArgumentString(ArgumentString, "BaseAddress");
2298             if (!portBase) {
2299 
2300                 // Try a default search for the part.
2301                 irq = 0;
2302             }
2303         }
2304     }
2305 
2306 #endif //UNIATA_CORE
2307 /*
2308     for(i=0; i<2; i++) {
2309         if((*ConfigInfo->AccessRanges)[i].RangeStart) {
2310             KdPrint2((PRINT_PREFIX "  IoRange[%d], start %#x, len %#x, mem %#x\n",
2311                 i,
2312                 ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[i].RangeStart),
2313                 (*ConfigInfo->AccessRanges)[i].RangeLength,
2314                 (*ConfigInfo->AccessRanges)[i].RangeInMemory
2315                 ));
2316         }
2317     }
2318 */
2319 //    if((*ConfigInfo->AccessRanges)[0].RangeStart) {
2320         portBase = ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart);
2321 //    }
2322     if(portBase) {
2323         if(!AtapiCheckIOInterference(ConfigInfo, portBase)) {
2324             ioSpace =  (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
2325                                              ConfigInfo->AdapterInterfaceType,
2326                                              ConfigInfo->SystemIoBusNumber,
2327                                              (*ConfigInfo->AccessRanges)[0].RangeStart,
2328                                              (*ConfigInfo->AccessRanges)[0].RangeLength,
2329                                              (BOOLEAN) !((*ConfigInfo->AccessRanges)[0].RangeInMemory));
2330         } else {
2331             // do not touch resources, just fail later inside loop on next call to
2332             // AtapiCheckIOInterference()
2333         }
2334         *Again = FALSE;
2335         // Since we have pre-configured information we only need to go through this loop once
2336         preConfig = TRUE;
2337         KdPrint2((PRINT_PREFIX "  preconfig, portBase=%x, len=%x\n", portBase, (*ConfigInfo->AccessRanges)[0].RangeLength));
2338     }
2339 
2340     // Scan through the adapter address looking for adapters.
2341 #ifndef UNIATA_CORE
2342     while (AdapterAddresses[*adapterCount] != 0) {
2343 #else
2344     do {
2345 #endif //UNIATA_CORE
2346 
2347         retryCount = 4;
2348         deviceExtension->DevIndex = (*adapterCount); // this is used inside AtapiRegCheckDevValue()
2349         KdPrint2((PRINT_PREFIX "AtapiFindIsaController: adapterCount=%d\n", *adapterCount));
2350 
2351         for (i = 0; i < deviceExtension->NumberLuns; i++) {
2352             // Zero device fields to ensure that if earlier devices were found,
2353             // but not claimed, the fields are cleared.
2354             deviceExtension->lun[i].DeviceFlags &= ~(DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT | DFLAGS_TAPE_DEVICE);
2355         }
2356         // Get the system physical address for this IO range.
2357 
2358         // Check if configInfo has the default information
2359         // if not, we go and find ourselves
2360         if (preConfig == FALSE) {
2361 
2362             ULONG portBase_reg = 0;
2363             ULONG irq_reg = 0;
2364 
2365             if (!portBase) {
2366                 portBase = AdapterAddresses[*adapterCount];
2367                 KdPrint2((PRINT_PREFIX "portBase[%d]=%x\n", *adapterCount, portBase));
2368             } else {
2369                 KdPrint2((PRINT_PREFIX "portBase=%x\n", portBase));
2370             }
2371 
2372             portBase_reg = AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PortBase", 0);
2373             irq_reg      = AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"Irq", 0);
2374             if(portBase_reg && irq_reg) {
2375                 KdPrint2((PRINT_PREFIX "use registry settings portBase=%x, irq=%d\n", portBase_reg, irq_reg));
2376                 portBase = portBase_reg;
2377                 irq = irq_reg;
2378             }
2379             // check if Primary/Secondary Master IDE claimed
2380             if(AtapiCheckIOInterference(ConfigInfo, portBase)) {
2381                 goto next_adapter;
2382             }
2383             ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
2384                                             ConfigInfo->AdapterInterfaceType,
2385                                             ConfigInfo->SystemIoBusNumber,
2386                                             ScsiPortConvertUlongToPhysicalAddress(portBase),
2387                                             ATA_IOSIZE,
2388                                             TRUE);
2389 
2390         } else {
2391             KdPrint2((PRINT_PREFIX "preconfig portBase=%x\n", portBase));
2392             // Check if Primary/Secondary Master IDE claimed
2393             // We can also get here from preConfig branc with conflicting portBase
2394             //   (and thus, w/o ioSpace allocated)
2395             if(AtapiCheckIOInterference(ConfigInfo, portBase)) {
2396                 goto not_found;
2397             }
2398         }
2399         BaseIoAddress1 = (PIDE_REGISTERS_1)ioSpace;
2400 next_adapter:
2401         // Update the adapter count.
2402         (*adapterCount)++;
2403 
2404         // Check if ioSpace accessible.
2405         if (!ioSpace) {
2406             KdPrint2((PRINT_PREFIX "AtapiFindIsaController: !ioSpace\n"));
2407             portBase = 0;
2408             continue;
2409         }
2410 
2411         // Get the system physical address for the second IO range.
2412         if (BaseIoAddress1) {
2413             if(preConfig &&
2414                !ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[1].RangeStart)) {
2415                 KdPrint2((PRINT_PREFIX "AtapiFindIsaController: PCMCIA ?\n"));
2416                 ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
2417                                                 ConfigInfo->AdapterInterfaceType,
2418                                                 ConfigInfo->SystemIoBusNumber,
2419                                                 ScsiPortConvertUlongToPhysicalAddress((ULONGIO_PTR)BaseIoAddress1 + 0x0E),
2420                                                 ATA_ALTIOSIZE,
2421                                                 TRUE);
2422             } else {
2423                 ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
2424                                                 ConfigInfo->AdapterInterfaceType,
2425                                                 ConfigInfo->SystemIoBusNumber,
2426                                                 ScsiPortConvertUlongToPhysicalAddress((ULONGIO_PTR)BaseIoAddress1 + ATA_ALTOFFSET),
2427                                                 ATA_ALTIOSIZE,
2428                                                 TRUE);
2429             }
2430         }
2431         BaseIoAddress2 = (PIDE_REGISTERS_2)ioSpace;
2432         KdPrint2((PRINT_PREFIX "  BaseIoAddress1=%x\n", BaseIoAddress1));
2433         KdPrint2((PRINT_PREFIX "  BaseIoAddress2=%x\n", BaseIoAddress2));
2434         if(!irq) {
2435             KdPrint2((PRINT_PREFIX "  expected InterruptLevel=%x\n", InterruptLevels[*adapterCount - 1]));
2436         }
2437 
2438         UniataInitMapBase(chan, BaseIoAddress1, BaseIoAddress2);
2439         UniataInitMapBM(deviceExtension, 0, FALSE);
2440 
2441 #ifdef _DEBUG
2442         UniataDumpATARegs(chan);
2443 #endif
2444 
2445         // Select master.
2446         SelectDrive(chan, 0);
2447 
2448         statusByte = AtapiReadPort1(chan, IDX_IO1_i_Status);
2449         statusByte2 = AtapiReadPort1(chan, IDX_IO2_AltStatus);
2450         if((statusByte ^ statusByte2) & ~IDE_STATUS_INDEX) {
2451             KdPrint2((PRINT_PREFIX "AtapiFindIsaController: Status %x vs AltStatus %x missmatch, abort init ?\n", statusByte, statusByte2));
2452 
2453             if(BaseIoAddress2) {
2454                 ScsiPortFreeDeviceBase(HwDeviceExtension,
2455                                        (PCHAR)BaseIoAddress2);
2456                 BaseIoAddress2 = NULL;
2457             }
2458             BaseIoAddress2 = (PIDE_REGISTERS_2)((ULONGIO_PTR)BaseIoAddress1 + 0x0E);
2459             KdPrint2((PRINT_PREFIX "  try BaseIoAddress2=%x\n", BaseIoAddress2));
2460             ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
2461                                             ConfigInfo->AdapterInterfaceType,
2462                                             ConfigInfo->SystemIoBusNumber,
2463                                             ScsiPortConvertUlongToPhysicalAddress((ULONGIO_PTR)BaseIoAddress2),
2464                                             ATA_ALTIOSIZE,
2465                                             TRUE);
2466             if(!ioSpace) {
2467                 BaseIoAddress2 = NULL;
2468                 KdPrint2((PRINT_PREFIX "    abort (0)\n"));
2469                 goto not_found;
2470             }
2471             UniataInitMapBase(chan, BaseIoAddress1, BaseIoAddress2);
2472             statusByte = AtapiReadPort1(chan, IDX_IO1_i_Status);
2473             statusByte2 = AtapiReadPort1(chan, IDX_IO2_AltStatus);
2474             if((statusByte ^ statusByte2) & ~IDE_STATUS_INDEX) {
2475                 KdPrint2((PRINT_PREFIX "    abort: Status %x vs AltStatus %x missmatch\n", statusByte, statusByte2));
2476                 goto not_found;
2477             }
2478         }
2479 
2480 retryIdentifier:
2481 
2482         // Select master.
2483         SelectDrive(chan, 0);
2484 
2485         // Check if card at this address.
2486         AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, 0xAA);
2487         statusByte = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
2488 
2489         // Check if indentifier can be read back.
2490         if (AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) != 0xAA ||
2491             statusByte == IDE_STATUS_WRONG) {
2492 
2493             KdPrint2((PRINT_PREFIX "AtapiFindIsaController: Identifier read back from Master (%#x)\n",
2494                         statusByte));
2495 
2496             statusByte = AtapiReadPort1(chan, IDX_IO2_AltStatus);
2497 
2498             if (statusByte != IDE_STATUS_WRONG && (statusByte & IDE_STATUS_BUSY)) {
2499 
2500                 i = 0;
2501 
2502                 // Could be the TEAC in a thinkpad. Their dos driver puts it in a sleep-mode that
2503                 // warm boots don't clear.
2504                 do {
2505                     AtapiStallExecution(1000);
2506                     statusByte = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Status);
2507                     KdPrint2((PRINT_PREFIX
2508                                 "AtapiFindIsaController: First access to status %#x\n",
2509                                 statusByte));
2510                 } while ((statusByte & IDE_STATUS_BUSY) && ++i < 10);
2511 
2512                 if (retryCount-- && (!(statusByte & IDE_STATUS_BUSY))) {
2513                     goto retryIdentifier;
2514                 }
2515             }
2516 
2517             // Select slave.
2518             SelectDrive(chan, 1);
2519             statusByte = AtapiReadPort1(chan, IDX_IO2_AltStatus);
2520 
2521             // See if slave is present.
2522             AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, 0xAA);
2523 
2524             if (AtapiReadPort1(chan, IDX_IO1_i_CylinderLow) != 0xAA ||
2525                 statusByte == IDE_STATUS_WRONG) {
2526 
2527                 KdPrint2((PRINT_PREFIX
2528                             "AtapiFindIsaController: Identifier read back from Slave (%#x)\n",
2529                             statusByte));
2530                 goto not_found;
2531             }
2532         }
2533 
2534         // Fill in the access array information only if default params are not in there.
2535         if (preConfig == FALSE) {
2536 
2537             // An adapter has been found request another call, only if we didn't get preconfigured info.
2538             *Again = TRUE;
2539 
2540             if (portBase) {
2541                 (*ConfigInfo->AccessRanges)[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(portBase);
2542             } else {
2543                 (*ConfigInfo->AccessRanges)[0].RangeStart =
2544                     ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount - 1]);
2545             }
2546 
2547             (*ConfigInfo->AccessRanges)[0].RangeLength = ATA_IOSIZE;
2548             (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
2549 
2550             if(BaseIoAddress2) {
2551                 if(hasPCI) {
2552                     (*ConfigInfo->AccessRanges)[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress((ULONG_PTR)BaseIoAddress2);
2553                     (*ConfigInfo->AccessRanges)[1].RangeLength = ATA_ALTIOSIZE;
2554                     (*ConfigInfo->AccessRanges)[1].RangeInMemory = FALSE;
2555                 } else {
2556                     // NT4 and NT3.51 on ISA-only hardware definitly fail floppy.sys load
2557                     // when this range is claimed by other driver.
2558                     // However, floppy should use only 0x3f0-3f5,3f7
2559                     if((ULONGIO_PTR)BaseIoAddress2 >= 0x3f0 && (ULONGIO_PTR)BaseIoAddress2 <= 0x3f7) {
2560                         KdPrint2((PRINT_PREFIX "!!! Possible AltStatus vs Floppy IO range interference !!!\n"));
2561                     }
2562                     KdPrint2((PRINT_PREFIX "Do not expose to OS on old ISA\n"));
2563                     (*ConfigInfo->AccessRanges)[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
2564                     (*ConfigInfo->AccessRanges)[1].RangeLength = 0;
2565                 }
2566             }
2567 
2568             // Indicate the interrupt level corresponding to this IO range.
2569             if (irq) {
2570                 ConfigInfo->BusInterruptLevel = irq;
2571             } else {
2572                 ConfigInfo->BusInterruptLevel = InterruptLevels[*adapterCount - 1];
2573             }
2574 
2575             if (ConfigInfo->AdapterInterfaceType == MicroChannel) {
2576                 ConfigInfo->InterruptMode = LevelSensitive;
2577             } else {
2578                 ConfigInfo->InterruptMode = Latched;
2579             }
2580         }
2581 
2582         ConfigInfo->NumberOfBuses = 1;
2583         ConfigInfo->MaximumNumberOfTargets = IDE_MAX_LUN_PER_CHAN;
2584 
2585         // Indicate maximum transfer length is 64k.
2586         ConfigInfo->MaximumTransferLength = 0x10000;
2587         deviceExtension->MaximumDmaTransferLength = ConfigInfo->MaximumTransferLength;
2588 
2589         KdPrint2((PRINT_PREFIX "de %#x, Channel ???\n", deviceExtension));
2590         //PrintNtConsole("de %#x, Channel %#x, nchan %#x\n",deviceExtension, channel, deviceExtension->NumberChannels);
2591 
2592         KdPrint2((PRINT_PREFIX "chan = %#x\n", chan));
2593         //PrintNtConsole("chan = %#x, c=%#x\n", chan, c);
2594 /*
2595         // should be already set up in AtapiSetupLunPtrs(chan, deviceExtension, 0);
2596 
2597         chan->DeviceExtension = deviceExtension;
2598         chan->lChannel        = 0;
2599         chan->lun[0] = &(deviceExtension->lun[0]);
2600         chan->lun[1] = &(deviceExtension->lun[1]);*/
2601 
2602         /* do extra channel-specific setups */
2603         AtapiReadChipConfig(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, 0);
2604         AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, 0);
2605 
2606         KdPrint2((PRINT_PREFIX
2607                    "AtapiFindIsaController: Found IDE at %#x\n",
2608                    BaseIoAddress1));
2609 
2610         // For Daytona, the atdisk driver gets the first shot at the
2611         // primary and secondary controllers.
2612         if (preConfig == FALSE) {
2613 
2614             if (*adapterCount - 1 < 2) {
2615 
2616                 // Determine whether this driver is being initialized by the
2617                 // system or as a crash dump driver.
2618                 if (g_Dump) {
2619 #ifndef UNIATA_CORE
2620                     deviceExtension->DriverMustPoll = TRUE;
2621 #endif //UNIATA_CORE
2622                 } else {
2623                     deviceExtension->DriverMustPoll = FALSE;
2624                 }
2625 
2626             } else {
2627                 //atapiOnly = FALSE;
2628             }
2629 
2630         } else {
2631 
2632             //atapiOnly = FALSE;
2633             deviceExtension->DriverMustPoll = FALSE;
2634 
2635         }// preConfig check
2636 
2637         // Save the Interrupe Mode for later use
2638         deviceExtension->InterruptMode = ConfigInfo->InterruptMode;
2639         deviceExtension->BusInterruptLevel = ConfigInfo->BusInterruptLevel;
2640         deviceExtension->BusInterruptVector = ConfigInfo->BusInterruptVector;
2641 
2642         KdPrint2((PRINT_PREFIX
2643                    "AtapiFindIsaController: look for devices\n"));
2644         // Search for devices on this controller.
2645         if (FindDevices(HwDeviceExtension,
2646                         0,
2647                         0 /* Channel */)) {
2648 
2649             KdPrint2((PRINT_PREFIX
2650                        "AtapiFindIsaController: detected\n"));
2651             // Claim primary or secondary ATA IO range.
2652             if (portBase) {
2653                 switch (portBase) {
2654                 case IO_WD2:
2655                     ConfigInfo->AtdiskSecondaryClaimed = TRUE;
2656                     chan->PrimaryAddress = FALSE;
2657                     break;
2658                 case IO_WD1:
2659                     ConfigInfo->AtdiskPrimaryClaimed = TRUE;
2660                     chan->PrimaryAddress = TRUE;
2661                     break;
2662                 default:
2663                     break;
2664                 }
2665             } else {
2666                 if (*adapterCount == 1) {
2667                     ConfigInfo->AtdiskPrimaryClaimed = TRUE;
2668                     chan->PrimaryAddress = TRUE;
2669                 } else if (*adapterCount == 2) {
2670                     ConfigInfo->AtdiskSecondaryClaimed = TRUE;
2671                     chan->PrimaryAddress = FALSE;
2672                 }
2673             }
2674 
2675             if(deviceExtension->AdapterInterfaceType == Isa) {
2676                 IsaCount++;
2677             } else
2678             if(deviceExtension->AdapterInterfaceType == MicroChannel) {
2679                 MCACount++;
2680             }
2681 
2682             ConfigInfo->NumberOfBuses++; // add virtual channel for communication port
2683             KdPrint2((PRINT_PREFIX
2684                        "AtapiFindIsaController: return SP_RETURN_FOUND\n"));
2685             return(SP_RETURN_FOUND);
2686         } else {
2687 not_found:
2688             // No controller at this base address.
2689             if(BaseIoAddress1) {
2690                 ScsiPortFreeDeviceBase(HwDeviceExtension,
2691                                        (PCHAR)BaseIoAddress1);
2692                 BaseIoAddress1 = NULL;
2693             }
2694             if(BaseIoAddress2) {
2695                 ScsiPortFreeDeviceBase(HwDeviceExtension,
2696                                        (PCHAR)BaseIoAddress2);
2697                 BaseIoAddress2 = NULL;
2698             }
2699             for(i=0; i<2; i++) {
2700                 KdPrint2((PRINT_PREFIX
2701                            "AtapiFindIsaController: cleanup AccessRanges %d\n", i));
2702                 (*ConfigInfo->AccessRanges)[i].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
2703                 (*ConfigInfo->AccessRanges)[i].RangeLength = 0;
2704                 (*ConfigInfo->AccessRanges)[i].RangeInMemory = FALSE;
2705             }
2706             irq = 0;
2707             portBase = 0;
2708         }
2709 #ifndef UNIATA_CORE
2710     }
2711 #else
2712     } while(FALSE);
2713 #endif //UNIATA_CORE
2714 
2715     // The entire table has been searched and no adapters have been found.
2716     // There is no need to call again and the device base can now be freed.
2717     // Clear the adapter count for the next bus.
2718     *Again = FALSE;
2719     *(adapterCount) = 0;
2720 
2721     KdPrint2((PRINT_PREFIX
2722                "AtapiFindIsaController: return SP_RETURN_NOT_FOUND\n"));
2723     UniataFreeLunExt(deviceExtension);
2724     return(SP_RETURN_NOT_FOUND);
2725 
2726 exit_error:
2727     UniataFreeLunExt(deviceExtension);
2728     return SP_RETURN_ERROR;
2729 
2730 } // end AtapiFindIsaController()
2731 
2732 /*
2733     Do nothing, but parse ScsiPort ArgumentString and setup global variables.
2734 */
2735 
2736 ULONG
2737 NTAPI
2738 AtapiReadArgumentString(
2739     IN PVOID HwDeviceExtension,
2740     IN PVOID Context,
2741     IN PVOID BusInformation,
2742     IN PCHAR ArgumentString,
2743     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
2744     OUT PBOOLEAN Again
2745     )
2746 {
2747 #ifndef __REACTOS__
2748     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2749 #endif
2750 
2751     if (AtapiParseArgumentString(ArgumentString, "dump") == 1) {
2752         KdPrint2((PRINT_PREFIX
2753                    "AtapiReadArgumentString: Crash dump\n"));
2754         //atapiOnly = FALSE;
2755         g_Dump = TRUE;
2756     }
2757     return(SP_RETURN_NOT_FOUND);
2758 } // end AtapiReadArgumentString()
2759 
2760 ULONG
2761 NTAPI
2762 UniataAnybodyHome(
2763     IN PVOID   HwDeviceExtension,
2764     IN ULONG   lChannel,
2765     IN ULONG   deviceNumber
2766     )
2767 {
2768     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2769     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
2770     //ULONG                ldev = GET_LDEV2(lChannel, deviceNumber, 0);
2771     PHW_LU_EXTENSION     LunExt = chan->lun[deviceNumber];
2772 
2773     SATA_SSTATUS_REG     SStatus;
2774     UCHAR                signatureLow;
2775     UCHAR                signatureHigh;
2776 
2777     if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
2778         KdPrint2((PRINT_PREFIX "  hidden\n"));
2779         UniataForgetDevice(LunExt);
2780         return ATA_AT_HOME_NOBODY;
2781     }
2782     if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
2783 
2784         SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, deviceNumber);
2785         KdPrint2((PRINT_PREFIX "SStatus %x\n", SStatus.Reg));
2786         if(SStatus.DET <= SStatus_DET_Dev_NoPhy) {
2787             KdPrint2((PRINT_PREFIX "  SATA DET <= SStatus_DET_Dev_NoPhy\n"));
2788             return ATA_AT_HOME_NOBODY;
2789         }
2790         if(SStatus.SPD < SStatus_SPD_Gen1) {
2791             KdPrint2((PRINT_PREFIX "  SATA SPD < SStatus_SPD_Gen1\n"));
2792             return ATA_AT_HOME_NOBODY;
2793         }
2794         if(SStatus.IPM == SStatus_IPM_NoDev) {
2795             KdPrint2((PRINT_PREFIX "  SATA IPN == SStatus_IPM_NoDev\n"));
2796             return ATA_AT_HOME_NOBODY;
2797         }
2798         if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
2799             // Select the device for legacy.
2800             goto legacy_select;
2801         }
2802 
2803     } else {
2804 legacy_select:
2805         // Select the device.
2806         SelectDrive(chan, deviceNumber);
2807         AtapiStallExecution(5);
2808     }
2809 
2810     if((deviceExtension->HwFlags & UNIATA_AHCI) &&
2811        UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
2812         KdPrint2((PRINT_PREFIX "  AHCI check\n"));
2813         ULONG SIG = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_SIG);
2814         signatureLow = (UCHAR)(SIG >> 16);
2815         signatureHigh = (UCHAR)(SIG >> 24);
2816     } else {
2817         signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
2818         signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
2819     }
2820 
2821     if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
2822         KdPrint2((PRINT_PREFIX "  ATAPI at home\n"));
2823         return ATA_AT_HOME_ATAPI;
2824     }
2825     if(deviceExtension->HwFlags & UNIATA_AHCI) {
2826         KdPrint2((PRINT_PREFIX "  AHCI HDD at home\n"));
2827         return ATA_AT_HOME_HDD;
2828     }
2829     if(g_opt_VirtualMachine > VM_NONE /*== VM_BOCHS ||
2830        g_opt_VirtualMachine == VM_VBOX*/) {
2831         GetStatus(chan, signatureLow);
2832         if(!signatureLow) {
2833             KdPrint2((PRINT_PREFIX "  0-status VM - not present\n"));
2834             UniataForgetDevice(LunExt);
2835             return ATA_AT_HOME_NOBODY;
2836         }
2837     }
2838 
2839     AtapiStallExecution(10);
2840 
2841     AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0x55);
2842     AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0x55);
2843     AtapiStallExecution(5);
2844     signatureLow = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
2845     if(signatureLow != 0x55) {
2846         if(signatureLow == 0xff || signatureLow == 0) {
2847             KdPrint2((PRINT_PREFIX "  nobody home! %#x != 0x55\n", signatureLow));
2848             UniataForgetDevice(LunExt);
2849             return ATA_AT_HOME_NOBODY;
2850         }
2851         // another chance
2852         signatureLow = AtapiReadPort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh);
2853         signatureLow += 2;
2854         AtapiWritePort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh, signatureLow);
2855         AtapiStallExecution(5);
2856         signatureHigh = AtapiReadPort1(chan, IDX_ATAPI_IO1_o_ByteCountHigh);
2857         if(signatureLow != signatureHigh) {
2858             KdPrint2((PRINT_PREFIX "  nobody home! last chance failed %#x != %#x\n", signatureLow, signatureHigh));
2859             UniataForgetDevice(LunExt);
2860             return ATA_AT_HOME_NOBODY;
2861         }
2862         return ATA_AT_HOME_XXX;
2863     }
2864 
2865     AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0xAA);
2866     AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0xAA);
2867     AtapiStallExecution(5);
2868     signatureLow = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
2869     if(signatureLow != 0xAA) {
2870         KdPrint2((PRINT_PREFIX "  nobody home! %#x != 0xAA\n", signatureLow));
2871         UniataForgetDevice(LunExt);
2872         return ATA_AT_HOME_NOBODY;
2873     }
2874 
2875     KdPrint2((PRINT_PREFIX "  HDD at home\n"));
2876     return ATA_AT_HOME_HDD;
2877 } // end UniataAnybodyHome()
2878 
2879 ULONG
2880 NTAPI
2881 CheckDevice(
2882     IN PVOID   HwDeviceExtension,
2883     IN ULONG   lChannel,
2884     IN ULONG   deviceNumber,
2885     IN BOOLEAN ResetDev
2886     )
2887 {
2888     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
2889     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
2890     //ULONG                ldev = GET_LDEV2(lChannel, deviceNumber, 0);
2891     PHW_LU_EXTENSION     LunExt;
2892 
2893     UCHAR                signatureLow,
2894                          signatureHigh;
2895     UCHAR                statusByte;
2896     ULONG                RetVal=0;
2897     ULONG                waitCount = g_opt_WaitBusyResetCount;
2898     ULONG                at_home = 0;
2899 
2900     KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x\n",
2901                deviceNumber));
2902 
2903     if(deviceNumber >= chan->NumberLuns) {
2904         return 0;
2905     }
2906     if(deviceExtension->HwFlags & UNIATA_AHCI) {
2907         if(!(at_home = UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber))) {
2908             return 0;
2909         }
2910     }
2911     LunExt = chan->lun[deviceNumber];
2912 
2913     if(ResetDev) {
2914         LunExt->PowerState = 0;
2915     }
2916 
2917     if((deviceExtension->HwFlags & UNIATA_SATA) &&
2918         !UniataIsSATARangeAvailable(deviceExtension, lChannel) &&
2919         deviceNumber) {
2920         KdPrint2((PRINT_PREFIX "  SATA w/o i/o registers, check slave presence\n"));
2921         SelectDrive(chan, deviceNumber & 0x01);
2922         statusByte = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_DriveSelect);
2923         KdPrint2((PRINT_PREFIX "  DriveSelect: %#x\n", statusByte));
2924         if((statusByte & IDE_DRIVE_MASK) != IDE_DRIVE_SELECT_2) {
2925             KdPrint2((PRINT_PREFIX "CheckDevice: (no dev)\n"));
2926             UniataForgetDevice(LunExt);
2927             return 0;
2928         }
2929     }
2930 
2931     if(ResetDev && (deviceExtension->HwFlags & UNIATA_AHCI)) {
2932         KdPrint2((PRINT_PREFIX "CheckDevice: reset AHCI dev\n"));
2933         if(UniataAhciSoftReset(HwDeviceExtension, chan->lChannel, deviceNumber) == (ULONG)(-1)) {
2934             KdPrint2((PRINT_PREFIX "CheckDevice: (no dev)\n"));
2935             UniataForgetDevice(LunExt);
2936             return 0;
2937         }
2938     } else
2939     if(ResetDev) {
2940         KdPrint2((PRINT_PREFIX "CheckDevice: reset dev\n"));
2941 
2942         // Reset device
2943         AtapiSoftReset(chan, deviceNumber);
2944 
2945         if(!(at_home = UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber))) {
2946             //KdPrint2((PRINT_PREFIX "CheckDevice: nobody at home 1\n"));
2947             return 0;
2948         }
2949         statusByte = WaitOnBusy(chan);
2950 
2951         if((statusByte | IDE_STATUS_BUSY) == IDE_STATUS_WRONG) {
2952             KdPrint2((PRINT_PREFIX
2953                         "CheckDevice: bad status %x\n", statusByte));
2954         } else
2955         if(statusByte != IDE_STATUS_WRONG && (statusByte & IDE_STATUS_BUSY)) {
2956             // Perform hard-reset.
2957             KdPrint2((PRINT_PREFIX
2958                         "CheckDevice: BUSY\n"));
2959 
2960             AtapiHardReset(chan, FALSE, 500 * 1000);
2961 /*
2962             AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_RESET_CONTROLLER );
2963             chan->last_devsel = -1;
2964             AtapiStallExecution(500 * 1000);
2965             AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_REENABLE_CONTROLLER);
2966 */
2967             SelectDrive(chan, deviceNumber & 0x01);
2968 
2969             do {
2970                 // Wait for Busy to drop.
2971                 AtapiStallExecution(100);
2972                 GetStatus(chan, statusByte);
2973 
2974             } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
2975 
2976             GetBaseStatus(chan, statusByte);
2977             KdPrint2((PRINT_PREFIX
2978                         "CheckDevice: status after hard reset %x\n", statusByte));
2979         }
2980 
2981         if((statusByte | IDE_STATUS_BUSY) == IDE_STATUS_WRONG) {
2982             KdPrint2((PRINT_PREFIX
2983                         "CheckDevice: no dev ?\n"));
2984             UniataForgetDevice(LunExt);
2985             return 0;
2986         } else
2987         if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
2988         //if(deviceExtension->HwFlags & UNIATA_SATA) {
2989             KdPrint2((PRINT_PREFIX
2990                         "CheckDevice: try enable SATA Phy\n"));
2991             statusByte = UniataSataPhyEnable(HwDeviceExtension, lChannel, deviceNumber);
2992             if(statusByte == IDE_STATUS_WRONG) {
2993                 KdPrint2((PRINT_PREFIX "CheckDevice: status %#x (no dev)\n", statusByte));
2994                 UniataForgetDevice(LunExt);
2995                 return 0;
2996             }
2997         }
2998     }
2999 
3000     if(deviceExtension->HwFlags & UNIATA_AHCI) {
3001         RetVal = LunExt->DeviceFlags;
3002         signatureLow = signatureHigh = 0; // make GCC happy
3003     } else {
3004         // Select the device.
3005         SelectDrive(chan, deviceNumber);
3006 
3007         if(!(at_home = UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber))) {
3008             //KdPrint2((PRINT_PREFIX "CheckDevice: nobody at home 2\n"));
3009             return 0;
3010         }
3011 
3012         statusByte = WaitOnBaseBusyLong(chan);
3013 
3014         GetBaseStatus(chan, statusByte);
3015         if(deviceExtension->HwFlags & UNIATA_SATA) {
3016             UniataSataClearErr(HwDeviceExtension, lChannel, UNIATA_SATA_IGNORE_CONNECT, deviceNumber);
3017         }
3018 
3019         KdPrint2((PRINT_PREFIX "CheckDevice: status %#x\n", statusByte));
3020         if(((statusByte | IDE_STATUS_BUSY) == IDE_STATUS_WRONG) ||
3021             (statusByte & IDE_STATUS_BUSY)) {
3022             KdPrint2((PRINT_PREFIX "CheckDevice: busy => return\n"));
3023             UniataForgetDevice(LunExt);
3024             return 0;
3025         }
3026 
3027         signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
3028         signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
3029     }
3030 
3031     // set default costs
3032     LunExt->RwSwitchCost  = REORDER_COST_SWITCH_RW_HDD;
3033     LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_HDD;
3034     LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_HDD;
3035     LunExt->AtapiReadyWaitDelay = 0;
3036 
3037     if(deviceExtension->HwFlags & UNIATA_AHCI) {
3038         if(RetVal & DFLAGS_DEVICE_PRESENT) {
3039             if(IssueIdentify(HwDeviceExtension,
3040                               deviceNumber,
3041                               lChannel,
3042                               (RetVal & DFLAGS_ATAPI_DEVICE) ? IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY,
3043                               FALSE)) {
3044                 // OK
3045                 KdPrint2((PRINT_PREFIX "CheckDevice: detected AHCI Device %#x\n",
3046                            deviceNumber));
3047             } else {
3048                 //RetVal &= ~DFLAGS_ATAPI_DEVICE;
3049                 //LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE;
3050 
3051                 UniataForgetDevice(LunExt);
3052                 RetVal = 0;
3053             }
3054         }
3055     } else
3056     if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
3057 
3058         KdPrint2((PRINT_PREFIX "CheckDevice: ATAPI signature found\n"));
3059         // ATAPI signature found.
3060         // Issue the ATAPI identify command if this
3061         // is not for the crash dump utility.
3062 try_atapi:
3063         if (!g_Dump) {
3064 
3065             // Issue ATAPI packet identify command.
3066             if (IssueIdentify(HwDeviceExtension,
3067                               deviceNumber,
3068                               lChannel,
3069                               IDE_COMMAND_ATAPI_IDENTIFY, FALSE)) {
3070 
3071                 // Indicate ATAPI device.
3072                 KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x is ATAPI\n",
3073                            deviceNumber));
3074 
3075                 RetVal = DFLAGS_DEVICE_PRESENT | DFLAGS_ATAPI_DEVICE;
3076                 LunExt->DeviceFlags |= (DFLAGS_DEVICE_PRESENT | DFLAGS_ATAPI_DEVICE);
3077 
3078                 // some ATAPI devices doesn't work with DPC on CMD-649
3079                 // and probably some other controllers
3080                 if(deviceExtension->HwFlags & UNIATA_NO_DPC_ATAPI) {
3081                     /* CMD 649, ROSB SWK33, ICH4 */
3082                     KdPrint2((PRINT_PREFIX "CheckDevice: UNIATA_NO_DPC_ATAPI\n"));
3083                     deviceExtension->UseDpc = FALSE;
3084                 }
3085 
3086                 GetStatus(chan, statusByte);
3087                 if (statusByte & IDE_STATUS_ERROR) {
3088                     AtapiSoftReset(chan, deviceNumber);
3089                 }
3090 
3091             } else {
3092 forget_device:
3093                 // Indicate no working device.
3094                 KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x not responding\n",
3095                            deviceNumber));
3096 
3097                 UniataForgetDevice(LunExt);
3098                 RetVal = 0;
3099             }
3100             GetBaseStatus(chan, statusByte);
3101 
3102         }
3103 
3104     } else {
3105 
3106         KdPrint2((PRINT_PREFIX "CheckDevice: IDE device check\n"));
3107         // Issue IDE Identify. If an Atapi device is actually present, the signature
3108         // will be asserted, and the drive will be recognized as such.
3109         if(deviceExtension->DWordIO) {
3110             KdPrint2((PRINT_PREFIX "  try 32bit IO\n"));
3111             LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
3112         }
3113         if (IssueIdentify(HwDeviceExtension,
3114                           deviceNumber,
3115                           lChannel,
3116                           IDE_COMMAND_IDENTIFY, FALSE)) {
3117 
3118             // IDE drive found.
3119             KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x is IDE\n",
3120                        deviceNumber));
3121 
3122             // Indicate IDE - not ATAPI device.
3123             RetVal = DFLAGS_DEVICE_PRESENT;
3124             LunExt->DeviceFlags |= DFLAGS_DEVICE_PRESENT;
3125             LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE;
3126         } else
3127         if(g_opt_VirtualMachine <= VM_NONE) {
3128             // This can be ATAPI on broken hardware
3129             GetBaseStatus(chan, statusByte);
3130             if(!at_home && UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
3131                 KdPrint2((PRINT_PREFIX "CheckDevice: nobody at home post IDE\n"));
3132                 goto forget_device;
3133             }
3134             KdPrint2((PRINT_PREFIX "CheckDevice: try ATAPI %#x, status %#x\n",
3135                        deviceNumber, statusByte));
3136             goto try_atapi;
3137         } else {
3138             KdPrint2((PRINT_PREFIX "CheckDevice: VM Device %#x not present\n",
3139                        deviceNumber));
3140         }
3141         GetBaseStatus(chan, statusByte);
3142     }
3143     KdPrint2((PRINT_PREFIX "CheckDevice: check status: %sfound\n", RetVal ? "" : "not "));
3144     return RetVal;
3145 } // end CheckDevice()
3146 
3147 
3148 /*++
3149 
3150 Routine Description:
3151 
3152     This routine is called from AtapiFindXxxController to identify
3153     devices attached to an IDE controller.
3154 
3155 Arguments:
3156 
3157     HwDeviceExtension - HBA miniport driver's adapter data storage
3158     AtapiOnly - Indicates that routine should return TRUE only if
3159         an ATAPI device is attached to the controller.
3160 
3161 Return Value:
3162 
3163     TRUE - True if devices found.
3164 
3165 --*/
3166 BOOLEAN
3167 NTAPI
3168 FindDevices(
3169     IN PVOID HwDeviceExtension,
3170     IN ULONG   Flags,
3171     IN ULONG   Channel
3172     )
3173 {
3174     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
3175     PHW_CHANNEL          chan = &(deviceExtension->chan[Channel]);
3176     PHW_LU_EXTENSION     LunExt;
3177     BOOLEAN              deviceResponded = FALSE,
3178                          skipSetParameters = FALSE;
3179     ULONG                waitCount = 10000;
3180     //ULONG                deviceNumber;
3181     ULONG                i;
3182     UCHAR                statusByte;
3183     ULONG                max_ldev;
3184     BOOLEAN              AtapiOnly = FALSE;
3185 
3186     KdPrint2((PRINT_PREFIX "FindDevices:\n"));
3187 
3188     // Disable interrupts
3189     AtapiDisableInterrupts(deviceExtension, Channel);
3190 //    AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_DISABLE_INTERRUPTS | IDE_DC_A_4BIT );
3191 
3192     // Clear expecting interrupt flag and current SRB field.
3193     UniataExpectChannelInterrupt(chan, FALSE);
3194 //    chan->CurrentSrb = NULL;
3195 //    max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : IDE_MAX_LUN_PER_CHAN;
3196     max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : deviceExtension->NumberLuns;
3197     KdPrint2((PRINT_PREFIX "  max_ldev %d\n", max_ldev));
3198 
3199     // Search for devices.
3200     for (i = 0; i < max_ldev; i++) {
3201         //AtapiDisableInterrupts(deviceExtension, Channel);
3202         if(Flags & UNIATA_FIND_DEV_UNHIDE) {
3203             chan->lun[i]->DeviceFlags &= ~DFLAGS_HIDDEN;
3204         }
3205         deviceResponded |=
3206             (CheckDevice(HwDeviceExtension, Channel, i, TRUE) != 0);
3207         //AtapiEnableInterrupts(deviceExtension, Channel);
3208     }
3209 
3210     if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
3211         AtapiEnableInterrupts(deviceExtension, Channel);
3212         KdPrint2((PRINT_PREFIX
3213                    "FindDevices: returning %d (AHCI)\n",
3214                    deviceResponded));
3215         return deviceResponded;
3216     }
3217 
3218     for (i = 0; i < max_ldev; i++) {
3219         LunExt = chan->lun[i];
3220 
3221         if ((  LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) &&
3222              !(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) &&
3223              !(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) && deviceResponded) {
3224 
3225             // This hideous hack is to deal with ESDI devices that return
3226             // garbage geometry in the IDENTIFY data.
3227             // This is ONLY for the crashdump environment as
3228             // these are ESDI devices.
3229             if (LunExt->IdentifyData.SectorsPerTrack == 0x35 &&
3230                 LunExt->IdentifyData.NumberOfHeads == 0x07) {
3231 
3232                 KdPrint2((PRINT_PREFIX "FindDevices: Found nasty Compaq ESDI!\n"));
3233 
3234                 // Change these values to something reasonable.
3235                 LunExt->IdentifyData.SectorsPerTrack = 0x34;
3236                 LunExt->IdentifyData.NumberOfHeads = 0x0E;
3237             }
3238 
3239             if (LunExt->IdentifyData.SectorsPerTrack == 0x35 &&
3240                 LunExt->IdentifyData.NumberOfHeads == 0x0F) {
3241 
3242                 KdPrint2((PRINT_PREFIX "FindDevices: Found nasty Compaq ESDI!\n"));
3243 
3244                 // Change these values to something reasonable.
3245                 LunExt->IdentifyData.SectorsPerTrack = 0x34;
3246                 LunExt->IdentifyData.NumberOfHeads = 0x0F;
3247             }
3248 
3249 
3250             if (LunExt->IdentifyData.SectorsPerTrack == 0x36 &&
3251                 LunExt->IdentifyData.NumberOfHeads == 0x07) {
3252 
3253                 KdPrint2((PRINT_PREFIX "FindDevices: Found nasty UltraStor ESDI!\n"));
3254 
3255                 // Change these values to something reasonable.
3256                 LunExt->IdentifyData.SectorsPerTrack = 0x3F;
3257                 LunExt->IdentifyData.NumberOfHeads = 0x10;
3258                 skipSetParameters = TRUE;
3259             }
3260 
3261 
3262             if (skipSetParameters)
3263                 continue;
3264 
3265             statusByte = WaitOnBusy(chan);
3266 
3267             // Select the device.
3268             SelectDrive(chan, i & 0x01);
3269             GetStatus(chan, statusByte);
3270 
3271             if (statusByte & IDE_STATUS_ERROR) {
3272 
3273                 // Reset the device.
3274                 KdPrint2((PRINT_PREFIX
3275                             "FindDevices: Resetting controller before SetDriveParameters.\n"));
3276 
3277                 AtapiHardReset(chan, FALSE, 500 * 1000);
3278 /*
3279                 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_RESET_CONTROLLER );
3280                 chan->last_devsel = -1;
3281                 AtapiStallExecution(500 * 1000);
3282                 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_REENABLE_CONTROLLER);
3283 */
3284                 SelectDrive(chan, i & 0x01);
3285 
3286                 do {
3287                     // Wait for Busy to drop.
3288                     AtapiStallExecution(100);
3289                     GetStatus(chan, statusByte);
3290 
3291                 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
3292             }
3293 
3294             statusByte = WaitOnBusy(chan);
3295 
3296             KdPrint2((PRINT_PREFIX
3297                         "FindDevices: Status before SetDriveParameters: (%#x) (%#x)\n",
3298                         statusByte,
3299                         AtapiReadPort1(chan, IDX_IO1_i_DriveSelect)));
3300 
3301             GetBaseStatus(chan, statusByte);
3302 
3303             // Use the IDENTIFY data to set drive parameters.
3304             if (!SetDriveParameters(HwDeviceExtension,i,Channel)) {
3305 
3306                 KdPrint2((PRINT_PREFIX
3307                            "FindDevices: Set drive parameters for device %d failed\n",
3308                            i));
3309                 // Don't use this device as writes could cause corruption.
3310                 LunExt->DeviceFlags &= ~DFLAGS_DEVICE_PRESENT;
3311                 UniataForgetDevice(LunExt);
3312                 continue;
3313 
3314             }
3315             if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
3316 
3317                 // Pick up ALL IDE removable drives that conform to Yosemite V0.2...
3318                 AtapiOnly = FALSE;
3319             }
3320 
3321             // Indicate that a device was found.
3322             if (!AtapiOnly) {
3323                 deviceResponded = TRUE;
3324             }
3325         }
3326     }
3327 
3328 /*    // Reset the controller. This is a feeble attempt to leave the ESDI
3329     // controllers in a state that ATDISK driver will recognize them.
3330     // The problem in ATDISK has to do with timings as it is not reproducible
3331     // in debug. The reset should restore the controller to its poweron state
3332     // and give the system enough time to settle.
3333     if (!deviceResponded) {
3334 
3335         AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_RESET_CONTROLLER );
3336         AtapiStallExecution(50 * 1000);
3337         AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_REENABLE_CONTROLLER);
3338     }
3339 */
3340     if(deviceResponded) {
3341         for (i = 0; i < max_ldev; i++) {
3342             LunExt = chan->lun[i];
3343 
3344             KdPrint2((PRINT_PREFIX
3345                        "FindDevices: select %d dev to clear INTR\n", i));
3346             SelectDrive(chan, i);
3347             GetBaseStatus(chan, statusByte);
3348             KdPrint2((PRINT_PREFIX
3349                        "FindDevices: statusByte=%#x\n", statusByte));
3350         }
3351         for (i = 0; i < max_ldev; i++) {
3352             LunExt = chan->lun[i];
3353 
3354             if(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) {
3355                 // Make sure some device (master is preferred) is selected on exit.
3356                 KdPrint2((PRINT_PREFIX
3357                            "FindDevices: select %d dev on exit\n", i));
3358                 SelectDrive(chan, i);
3359                 break;
3360             }
3361         }
3362     }
3363 
3364     GetBaseStatus(chan, statusByte);
3365     // Enable interrupts
3366     AtapiEnableInterrupts(deviceExtension, Channel);
3367 //    AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_A_4BIT );
3368     GetBaseStatus(chan, statusByte);
3369 
3370     KdPrint2((PRINT_PREFIX
3371                "FindDevices: returning %d\n",
3372                deviceResponded));
3373 
3374     return deviceResponded;
3375 
3376 } // end FindDevices()
3377