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