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