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