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