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