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