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