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