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