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