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