3 Copyright (c) 2002-2008 Alexandr A. Telyatnikov (Alter)
9 This module scans PCI and ISA buses for IDE controllers
10 and determines their Busmaster DMA capabilities
13 Alexander A. Telyatnikov (Alter)
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.
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
36 Some parts of device detection code were taken from from standard ATAPI.SYS from NT4 DDK by
40 Device search/init algorithm is completly rewritten by
41 Alter, Copyright (c) 2002-2004
43 Fixes for Native/Compatible modes of onboard IDE controller by
44 Vitaliy Vorobyov, deathsoft@yandex.ru (c) 2004
50 PBUSMASTER_CONTROLLER_INFORMATION BMList
= NULL
;
55 BOOLEAN FirstMasterOk
= FALSE
;
62 PDRIVER_OBJECT SavedDriverObject
= NULL
;
67 UniataEnumBusMasterController__(
68 /* IN PVOID HwDeviceExtension,
70 IN PVOID BusInformation,
71 IN PCHAR ArgumentString,
72 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
81 } // end AtapiDoNothing()
86 Get PCI address by ConfigInfo and RID
90 IN PVOID HwDeviceExtension
,
91 IN PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
92 IN PPCI_COMMON_CONFIG pciData
,
93 IN ULONG SystemIoBusNumber
,
94 IN ULONG rid
, //range id
100 KdPrint2((PRINT_PREFIX
" AtapiGetIoRange:\n"));
102 if(ConfigInfo
->NumberOfAccessRanges
<= rid
)
105 KdPrint2((PRINT_PREFIX
" AtapiGetIoRange: rid %#x, start %#x, offs %#x, len %#x, mem %#x\n",
107 ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo
->AccessRanges
)[rid
].RangeStart
),
110 (*ConfigInfo
->AccessRanges
)[rid
].RangeInMemory
113 if((*ConfigInfo
->AccessRanges
)[rid
].RangeInMemory
) {
115 // Get the system physical address for this IO range.
116 ((ULONG
)ScsiPortGetDeviceBase(HwDeviceExtension
,
117 PCIBus
/*ConfigInfo->AdapterInterfaceType*/,
118 SystemIoBusNumber
/*ConfigInfo->SystemIoBusNumber*/,
119 ScsiPortConvertUlongToPhysicalAddress(
120 (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo
->AccessRanges
)[rid
].RangeStart
) &
121 ~0x07/*PCI_ADDRESS_IOMASK*/) + offset
124 (BOOLEAN
)!(*ConfigInfo
->AccessRanges
)[rid
].RangeInMemory
)
127 KdPrint2((PRINT_PREFIX
" AtapiGetIoRange: %#x\n", io_start
));
128 // if(io_start > offset) {
133 io_start
= (pciData
->u
.type0
.BaseAddresses
[rid
] & ~0x07/*PCI_ADDRESS_IOMASK*/) + offset
;
134 // if(pciData->u.type0.BaseAddresses[rid] != 0) ;)
135 if(io_start
> offset
) {
136 if(/*(WinVer_Id() <= WinVer_NT) &&*/ offset
&& rid
== 4) {
137 // MS atapi.sys does so for BusMaster controllers
138 (*ConfigInfo
->AccessRanges
)[rid
+1].RangeStart
=
139 ScsiPortConvertUlongToPhysicalAddress(io_start
);
140 (*ConfigInfo
->AccessRanges
)[rid
+1].RangeLength
= length
;
142 (*ConfigInfo
->AccessRanges
)[rid
].RangeStart
=
143 ScsiPortConvertUlongToPhysicalAddress(io_start
);
144 (*ConfigInfo
->AccessRanges
)[rid
].RangeLength
= length
;
149 KdPrint2((PRINT_PREFIX
" AtapiGetIoRange: (2) %#x\n", io_start
));
152 } // end AtapiGetIoRange()
157 Do nothing, but build list of supported IDE controllers
158 It is a hack, ScsiPort architecture assumes, that DriverEntry
159 can support only KNOWN Vendor/Device combinations.
160 Thus, we build list here. Later will pretend that always knew
163 We shall initiate ISA device init, but callback will use
164 Hal routines directly in order to scan PCI bus.
167 UniataEnumBusMasterController(
168 IN PVOID DriverObject
,
172 UniataEnumBusMasterController__();
174 } // end UniataEnumBusMasterController()
177 UniataCheckPCISubclass(
184 if((RaidFlags
& UNIATA_RAID_CONTROLLER
) &&
186 KdPrint2((PRINT_PREFIX
"Skip RAID\n"));
191 KdPrint2((PRINT_PREFIX
"unknown\n"));
194 case PCI_DEV_SUBCLASS_RAID
:
196 KdPrint2((PRINT_PREFIX
"Skip RAID (2)\n"));
200 case PCI_DEV_SUBCLASS_IDE
:
201 case PCI_DEV_SUBCLASS_ATA
:
202 case PCI_DEV_SUBCLASS_SATA
:
205 KdPrint2((PRINT_PREFIX
"Subclass not supported\n"));
209 } // end UniataCheckPCISubclass()
212 Device initializaton callback
213 Builds PCI device list using Hal routines (not ScsiPort wrappers)
216 UniataEnumBusMasterController__(
219 // PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
220 PVOID HwDeviceExtension
;
221 PHW_DEVICE_EXTENSION deviceExtension
= NULL
;
222 PCI_SLOT_NUMBER slotData
;
223 PCI_COMMON_CONFIG pciData
;
227 BOOLEAN no_buses
= FALSE
;
228 BOOLEAN no_ranges
= FALSE
;
230 // BOOLEAN SimplexOnly;
232 UCHAR vendorString
[5];
233 UCHAR deviceString
[5];
237 UCHAR BaseClass
; // (ro)
238 UCHAR SubClass
; // (ro)
251 UCHAR IrqForCompat
= 10;
253 vendorStrPtr
= vendorString
;
254 deviceStrPtr
= deviceString
;
255 slotData
.u
.AsULONG
= 0;
258 deviceExtension
= (PHW_DEVICE_EXTENSION
)ExAllocatePool(NonPagedPool
, sizeof(HW_DEVICE_EXTENSION
));
259 if(!deviceExtension
) {
260 return(SP_RETURN_NOT_FOUND
);
262 RtlZeroMemory(deviceExtension
, sizeof(HW_DEVICE_EXTENSION
));
264 for(pass
=0; pass
<3; pass
++) {
265 for(busNumber
=0 ;busNumber
<maxPciBus
&& !no_buses
; busNumber
++) {
266 for(slotNumber
=0; slotNumber
<PCI_MAX_DEVICES
&& !no_buses
; slotNumber
++) {
267 for(funcNumber
=0; funcNumber
<PCI_MAX_FUNCTION
&& !no_buses
; funcNumber
++) {
269 // KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x\n",busNumber,slotNumber,funcNumber));
270 slotData
.u
.bits
.DeviceNumber
= slotNumber
;
271 slotData
.u
.bits
.FunctionNumber
= funcNumber
;
273 busDataRead
= HalGetBusData
277 PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
278 &pciData
, PCI_COMMON_HDR_LENGTH
);
282 maxPciBus
= busNumber
;
285 // no device in this slot
289 if(busDataRead
< (ULONG
)PCI_COMMON_HDR_LENGTH
)
292 VendorID
= pciData
.VendorID
;
293 DeviceID
= pciData
.DeviceID
;
294 BaseClass
= pciData
.BaseClass
;
295 SubClass
= pciData
.SubClass
;
296 dev_id
= VendorID
| (DeviceID
<< 16);
297 //KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
299 if(BaseClass
!= PCI_DEV_CLASS_STORAGE
)
302 KdPrint2((PRINT_PREFIX
"Storage Class\n"));
303 KdPrint2((PRINT_PREFIX
"DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id
, BaseClass
, SubClass
));
304 // look for known chipsets
308 if(deviceExtension
) {
309 deviceExtension
->slotNumber
= slotData
.u
.AsULONG
;
310 deviceExtension
->SystemIoBusNumber
= busNumber
;
311 deviceExtension
->DevID
= dev_id
;
312 deviceExtension
->RevID
= pciData
.RevisionID
;
313 deviceExtension
->AdapterInterfaceType
= PCIBus
;
316 found
= (BOOLEAN
)AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"Include", 0);
318 KdPrint2((PRINT_PREFIX
"No force include, check exclude\n"));
319 found
= !AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"Exclude", 0);
321 KdPrint2((PRINT_PREFIX
"Device excluded\n"));
326 //known = UniataChipDetect(HwDeviceExtension, NULL, -1, ConfigInfo, &SimplexOnly);
327 i
= Ata_is_dev_listed((PBUSMASTER_CONTROLLER_INFORMATION
)&BusMasterAdapters
[0], VendorID
, DeviceID
, 0, NUM_BUSMASTER_ADAPTERS
);
329 known
= (i
!= BMLIST_TERMINATOR
);
331 deviceExtension
->FullDevName
= BusMasterAdapters
[i
].FullDevName
;
332 RaidFlags
= BusMasterAdapters
[i
].RaidFlags
;
334 deviceExtension
->FullDevName
= "Unknown Storage";
337 found
= UniataCheckPCISubclass(known
, RaidFlags
, SubClass
);
339 KdPrint2((PRINT_PREFIX
"Subclass not supported\n"));
344 /* additional checks for some supported chipsets */
346 if (SubClass
!= PCI_DEV_SUBCLASS_IDE
)
350 /* unknown chipsets, try generic DMA if it seems possible */
352 KdPrint2((PRINT_PREFIX
"Default device\n"));
353 if(Ata_is_supported_dev(&pciData
))
360 KdPrint2((PRINT_PREFIX
"found, pass %d\n", pass
));
362 KdPrint2((PRINT_PREFIX
"InterruptPin = %#x\n", pciData
.u
.type0
.InterruptPin
));
363 KdPrint2((PRINT_PREFIX
"InterruptLine = %#x\n", pciData
.u
.type0
.InterruptLine
));
366 // Enable Busmastering, IO-space and Mem-space
367 KdPrint2((PRINT_PREFIX
"Enabling Mem/Io spaces and busmastering...\n"));
368 KdPrint2((PRINT_PREFIX
"Initial pciData.Command = %#x\n", pciData
.Command
));
372 KdPrint2((PRINT_PREFIX
"PCI_ENABLE_IO_SPACE\n"));
373 pciData
.Command
|= PCI_ENABLE_IO_SPACE
;
376 KdPrint2((PRINT_PREFIX
"PCI_ENABLE_MEMORY_SPACE\n"));
377 pciData
.Command
|= PCI_ENABLE_MEMORY_SPACE
;
380 KdPrint2((PRINT_PREFIX
"PCI_ENABLE_BUS_MASTER\n"));
381 pciData
.Command
|= PCI_ENABLE_BUS_MASTER
;
384 HalSetBusDataByOffset( PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
386 offsetof(PCI_COMMON_CONFIG
, Command
),
387 sizeof(pciData
.Command
));
388 KdPrint2((PRINT_PREFIX
"InterruptLine = %#x\n", pciData
.u
.type0
.InterruptLine
));
390 // reread config space
391 busDataRead
= HalGetBusData(PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
392 &pciData
, PCI_COMMON_HDR_LENGTH
);
393 KdPrint2((PRINT_PREFIX
"New pciData.Command = %#x\n", pciData
.Command
));
395 KdPrint2((PRINT_PREFIX
"Final pciData.Command = %#x\n", pciData
.Command
));
397 // validate Mem/Io ranges
399 for(i
=0; i
<PCI_TYPE0_ADDRESSES
; i
++) {
400 if(pciData
.u
.type0
.BaseAddresses
[i
] & ~0x7) {
403 KdPrint2((PRINT_PREFIX
"Range %d = %#x\n", i
, pciData
.u
.type0
.BaseAddresses
[i
]));
407 KdPrint2((PRINT_PREFIX
"No PCI Mem/Io ranges found on device, skip it\n"));
412 // fill list of detected devices
413 // it'll be used for further init
414 KdPrint2((PRINT_PREFIX
"found suitable device\n"));
415 PBUSMASTER_CONTROLLER_INFORMATION newBMListPtr
= BMList
+BMListLen
;
418 if(!IsMasterDev(&pciData
)) {
421 if(AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"NativePCIMode", 0)) {
422 KdPrint2((PRINT_PREFIX
"try switch to native mode\n"));
424 IrqForCompat
= (UCHAR
)AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"NativePCIModeIRQ", 0xff);
425 KdPrint2((PRINT_PREFIX
"IrqForCompat = %#x\n", IrqForCompat
));
426 if((IrqForCompat
& 0xffffff00) /*||
427 (IrqForCompat & 0xff) > 31*/ ||
428 (IrqForCompat
== 0xff)) {
430 KdPrint2((PRINT_PREFIX
"default to IRQ 11\n"));
433 //ChangePciConfig1(0x09, a | PCI_IDE_PROGIF_NATIVE_ALL); // ProgIf
434 pciData
.ProgIf
|= PCI_IDE_PROGIF_NATIVE_ALL
;
435 HalSetBusDataByOffset( PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
437 offsetof(PCI_COMMON_CONFIG
, ProgIf
),
438 sizeof(pciData
.ProgIf
));
440 // reread config space
441 busDataRead
= HalGetBusData(PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
442 &pciData
, PCI_COMMON_HDR_LENGTH
);
443 // check if the device have switched to Native Mode
444 if(IsMasterDev(&pciData
)) {
445 KdPrint2((PRINT_PREFIX
"Can't switch to native mode\n"));
447 KdPrint2((PRINT_PREFIX
"switched to native mode\n"));
448 KdPrint2((PRINT_PREFIX
"InterruptPin = %#x\n", pciData
.u
.type0
.InterruptPin
));
449 KdPrint2((PRINT_PREFIX
"InterruptLine = %#x\n", pciData
.u
.type0
.InterruptLine
));
450 // check if IRQ is assigned to device
451 if(!(pciData
.u
.type0
.InterruptLine
) ||
452 (pciData
.u
.type0
.InterruptLine
== 0xff)) {
453 KdPrint2((PRINT_PREFIX
"assign interrupt for device\n"));
454 pciData
.u
.type0
.InterruptLine
= IrqForCompat
;
455 HalSetBusDataByOffset( PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
456 &(pciData
.u
.type0
.InterruptLine
),
457 offsetof(PCI_COMMON_CONFIG
, u
.type0
.InterruptLine
),
458 sizeof(pciData
.u
.type0
.InterruptLine
));
460 KdPrint2((PRINT_PREFIX
"Auto-assigned interrupt line %#x\n",
461 pciData
.u
.type0
.InterruptLine
));
462 IrqForCompat
= pciData
.u
.type0
.InterruptLine
;
464 KdPrint2((PRINT_PREFIX
"reread config space\n"));
465 // reread config space
466 busDataRead
= HalGetBusData(PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
467 &pciData
, PCI_COMMON_HDR_LENGTH
);
468 KdPrint2((PRINT_PREFIX
"busDataRead = %#x\n", busDataRead
));
469 KdPrint2((PRINT_PREFIX
"reread InterruptLine = %#x\n", pciData
.u
.type0
.InterruptLine
));
470 // check if we have successfully assigned IRQ to device
471 if((pciData
.u
.type0
.InterruptLine
!= IrqForCompat
) ||
472 (pciData
.u
.type0
.InterruptLine
== 0xff) ||
473 !pciData
.u
.type0
.InterruptLine
) {
474 KdPrint2((PRINT_PREFIX
"can't assign interrupt for device, revert to compat mode\n"));
475 pciData
.u
.type0
.InterruptLine
= 0xff;
476 KdPrint2((PRINT_PREFIX
"set IntrLine to 0xff\n"));
477 HalSetBusDataByOffset( PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
478 &(pciData
.u
.type0
.InterruptLine
),
479 offsetof(PCI_COMMON_CONFIG
, u
.type0
.InterruptLine
),
480 sizeof(pciData
.u
.type0
.InterruptLine
));
481 KdPrint2((PRINT_PREFIX
"clear PCI_IDE_PROGIF_NATIVE_ALL\n"));
482 pciData
.ProgIf
&= ~PCI_IDE_PROGIF_NATIVE_ALL
;
483 HalSetBusDataByOffset( PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
485 offsetof(PCI_COMMON_CONFIG
, ProgIf
),
486 sizeof(pciData
.ProgIf
));
487 // reread config space
488 KdPrint2((PRINT_PREFIX
"reread config space on revert\n"));
489 busDataRead
= HalGetBusData(PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
490 &pciData
, PCI_COMMON_HDR_LENGTH
);
492 KdPrint2((PRINT_PREFIX
"Assigned interrupt %#x for device\n", IrqForCompat
));
493 KdPrint2((PRINT_PREFIX
"continue detection on next round\n"));
500 if(IsMasterDev(&pciData
))
505 RtlCopyMemory(newBMListPtr, (PVOID)&(BusMasterAdapters[i]), sizeof(BUSMASTER_CONTROLLER_INFORMATION));
507 sprintf((PCHAR
)vendorStrPtr
, "%4.4x", VendorID
);
508 sprintf((PCHAR
)deviceStrPtr
, "%4.4x", DeviceID
);
510 RtlCopyMemory(&(newBMListPtr
->VendorIdStr
), (PCHAR
)vendorStrPtr
, 4);
511 RtlCopyMemory(&(newBMListPtr
->DeviceIdStr
), (PCHAR
)deviceStrPtr
, 4);
513 newBMListPtr
->nVendorId
= VendorID
;
514 newBMListPtr
->VendorId
= (PCHAR
)&(newBMListPtr
->VendorIdStr
);
515 newBMListPtr
->VendorIdLength
= 4;
516 newBMListPtr
->nDeviceId
= DeviceID
;
517 newBMListPtr
->DeviceId
= (PCHAR
)&(newBMListPtr
->DeviceIdStr
);
518 newBMListPtr
->DeviceIdLength
= 4;
520 newBMListPtr
->RaidFlags
= RaidFlags
;
522 newBMListPtr
->slotNumber
= slotData
.u
.AsULONG
;
523 newBMListPtr
->MasterDev
= IsMasterDev(&pciData
) ? 1 : 0;
524 newBMListPtr
->busNumber
= busNumber
;
526 newBMListPtr
->Known
= known
;
528 KdPrint2((PRINT_PREFIX
"Add to BMList\n"));
530 KdPrint2((PRINT_PREFIX
"count: BMListLen++\n"));
541 BMList
= (PBUSMASTER_CONTROLLER_INFORMATION
)ExAllocatePool(NonPagedPool
,
542 (BMListLen
+1)*sizeof(BUSMASTER_CONTROLLER_INFORMATION
));
547 RtlZeroMemory(BMList
, (BMListLen
+1)*sizeof(BUSMASTER_CONTROLLER_INFORMATION
));
552 KdPrint2((PRINT_PREFIX
" BMListLen=%x\n", BMListLen
));
553 if(deviceExtension
) {
554 ExFreePool(deviceExtension
);
556 return(SP_RETURN_NOT_FOUND
);
557 } // end UniataEnumBusMasterController__()
561 Wrapper for read PCI config space
564 ScsiPortGetBusDataByOffset(
565 IN PVOID HwDeviceExtension
,
566 IN BUS_DATA_TYPE BusDataType
,
577 if(Offset
+Length
> 256)
580 busDataRead
= HalGetBusData(
581 //ScsiPortGetBusData(HwDeviceExtension,
587 if(busDataRead
< Offset
+Length
) {
588 if(busDataRead
< Offset
)
590 return (Offset
+Length
-busDataRead
);
592 RtlCopyMemory(Buffer
, tmp
+Offset
, Length
);
594 } // end ScsiPortGetBusDataByOffset()
597 Looks for devices from list on specified bus(es)/slot(s)
598 returnts its index in list.
599 If no matching record found, -1 is returned
603 PBUSMASTER_CONTROLLER_INFORMATION BusMasterAdapters
,
605 IN PVOID HwDeviceExtension
,
608 OUT PCI_SLOT_NUMBER
* _slotData
// optional
611 PCI_SLOT_NUMBER slotData
;
612 PCI_COMMON_CONFIG pciData
;
625 if(BusNumber
== PCIBUSNUM_NOT_SPECIFIED
) {
627 busNumber2
= maxPciBus
;
629 busNumber
= BusNumber
;
630 busNumber2
= BusNumber
+1;
632 // set start/end slot
633 if(SlotNumber
== PCISLOTNUM_NOT_SPECIFIED
) {
635 slotNumber2
= PCI_MAX_DEVICES
;
637 slotNumber
= SlotNumber
;
638 slotNumber2
= SlotNumber
+1;
640 slotData
.u
.AsULONG
= 0;
642 for( ; busNumber
< busNumber2
; busNumber
++ ) {
643 for( ; slotNumber
< slotNumber2
; slotNumber
++) {
644 for(funcNumber
=0; funcNumber
< PCI_MAX_FUNCTION
; funcNumber
++) {
646 slotData
.u
.bits
.DeviceNumber
= slotNumber
;
647 slotData
.u
.bits
.FunctionNumber
= funcNumber
;
649 busDataRead
= HalGetBusData(
650 //ScsiPortGetBusData(HwDeviceExtension,
651 PCIConfiguration
, busNumber
, slotData
.u
.AsULONG
,
652 &pciData
, PCI_COMMON_HDR_LENGTH
);
653 // no more buses (this should not happen)
657 // no device in this slot
661 if(busDataRead
< (ULONG
)PCI_COMMON_HDR_LENGTH
)
664 i
= Ata_is_dev_listed(BusMasterAdapters
, pciData
.VendorID
, pciData
.DeviceID
, pciData
.RevisionID
, lim
);
665 if(i
!= BMLIST_TERMINATOR
) {
667 *_slotData
= slotData
;
673 } // end AtapiFindListedDev()
676 Looks for device with specified Device/Vendor and Revision
677 on specified Bus/Slot
681 IN PVOID HwDeviceExtension
,
682 IN BUS_DATA_TYPE BusDataType
,
689 PCI_COMMON_CONFIG pciData
;
695 PCI_SLOT_NUMBER slotData
;
697 slotData
.u
.AsULONG
= SlotNumber
;
698 // walk through all Function Numbers
699 for(funcNumber
= 0; funcNumber
< PCI_MAX_FUNCTION
; funcNumber
++) {
701 slotData
.u
.bits
.FunctionNumber
= funcNumber
;
702 if(slotData
.u
.AsULONG
== SlotNumber
)
705 busDataRead
= HalGetBusData(
706 //busDataRead = ScsiPortGetBusData(HwDeviceExtension,
711 PCI_COMMON_HDR_LENGTH
);
713 if (busDataRead
< (ULONG
)PCI_COMMON_HDR_LENGTH
) {
717 VendorID
= pciData
.VendorID
;
718 DeviceID
= pciData
.DeviceID
;
720 if(dev_id
!= (VendorID
| (DeviceID
<< 16)) )
722 if(RevID
>= pciData
.RevisionID
)
726 } // end AtapiFindDev()
732 UniataFindCompatBusMasterController1(
733 IN PVOID HwDeviceExtension
,
735 IN PVOID BusInformation
,
736 IN PCHAR ArgumentString
,
737 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
741 return UniataFindBusMasterController(
749 } // end UniataFindCompatBusMasterController1()
752 UniataFindCompatBusMasterController2(
753 IN PVOID HwDeviceExtension
,
755 IN PVOID BusInformation
,
756 IN PCHAR ArgumentString
,
757 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
761 return UniataFindBusMasterController(
769 } // end UniataFindCompatBusMasterController2()
772 UniataAllocateLunExt(
773 PHW_DEVICE_EXTENSION deviceExtension
,
774 ULONG NewNumberChannels
777 PHW_LU_EXTENSION old_luns
= NULL
;
778 PHW_CHANNEL old_chans
= NULL
;
780 KdPrint2((PRINT_PREFIX
"allocate Luns for %d channels\n", deviceExtension
->NumberChannels
));
782 old_luns
= deviceExtension
->lun
;
783 old_chans
= deviceExtension
->chan
;
785 if(old_luns
|| old_chans
) {
786 if(NewNumberChannels
== UNIATA_ALLOCATE_NEW_LUNS
) {
787 KdPrint2((PRINT_PREFIX
"already allocated!\n"));
792 deviceExtension
->lun
= (PHW_LU_EXTENSION
)ExAllocatePool(NonPagedPool
, sizeof(HW_LU_EXTENSION
) * (deviceExtension
->NumberChannels
+1) * IDE_MAX_LUN_PER_CHAN
);
793 if (!deviceExtension
->lun
) {
794 KdPrint2((PRINT_PREFIX
"!deviceExtension->lun => SP_RETURN_ERROR\n"));
797 RtlZeroMemory(deviceExtension
->lun
, sizeof(HW_LU_EXTENSION
) * (deviceExtension
->NumberChannels
+1) * IDE_MAX_LUN_PER_CHAN
);
799 deviceExtension
->chan
= (PHW_CHANNEL
)ExAllocatePool(NonPagedPool
, sizeof(HW_CHANNEL
) * (deviceExtension
->NumberChannels
+1));
800 if (!deviceExtension
->chan
) {
801 KdPrint2((PRINT_PREFIX
"!deviceExtension->chan => SP_RETURN_ERROR\n"));
804 RtlZeroMemory(deviceExtension
->chan
, sizeof(HW_CHANNEL
) * (deviceExtension
->NumberChannels
+1));
806 } // end UniataAllocateLunExt()
813 This function is called by the OS-specific port driver after
814 the necessary storage has been allocated, to gather information
815 about the adapter's configuration.
819 HwDeviceExtension - HBA miniport driver's adapter data storage
820 Context - Address of adapter count
822 ArgumentString - Used to determine whether driver is client of ntldr or crash dump utility.
823 ConfigInfo - Configuration information structure describing HBA
824 Again - Indicates search for adapters to continue
832 UniataFindBusMasterController(
833 IN PVOID HwDeviceExtension
,
835 IN PVOID BusInformation
,
836 IN PCHAR ArgumentString
,
837 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
841 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
842 PHW_CHANNEL chan
= NULL
;
844 // this buffer must be global for UNIATA_CORE build
845 PCI_COMMON_CONFIG pciData
;
849 ULONG SystemIoBusNumber
;
851 UCHAR vendorString
[5];
852 UCHAR deviceString
[5];
862 PCI_SLOT_NUMBER slotData
;
874 BOOLEAN found
= FALSE
;
876 BOOLEAN simplexOnly
= FALSE
;
877 BOOLEAN skip_find_dev
= FALSE
;
878 BOOLEAN AltInit
= FALSE
;
880 SCSI_PHYSICAL_ADDRESS IoBasePort1
;
881 SCSI_PHYSICAL_ADDRESS IoBasePort2
;
883 PIDE_BUSMASTER_REGISTERS BaseIoAddressBM_0
= NULL
;
884 PIDE_REGISTERS_1 BaseIoAddress1
[IDE_MAX_CHAN
];
885 PIDE_REGISTERS_2 BaseIoAddress2
[IDE_MAX_CHAN
];
887 RtlZeroMemory(&BaseIoAddress1
, sizeof(BaseIoAddress1
));
888 RtlZeroMemory(&BaseIoAddress2
, sizeof(BaseIoAddress2
));
891 PPORT_CONFIGURATION_INFORMATION_COMMON _ConfigInfo
=
892 (PPORT_CONFIGURATION_INFORMATION_COMMON
)ConfigInfo
;
894 if(!WinVer_WDM_Model
) {
900 KdPrint2((PRINT_PREFIX
"UniataFindBusMasterController: Context=%x, BMListLen=%d\n", Context
, BMListLen
));
902 KdPrint2((PRINT_PREFIX
"ConfigInfo->Length %x\n", ConfigInfo
->Length
));
905 KdPrint2((PRINT_PREFIX
"ForceSimplex (1)\n"));
909 if(ConfigInfo
->AdapterInterfaceType
== Isa
) {
910 KdPrint2((PRINT_PREFIX
"AdapterInterfaceType: Isa\n"));
918 channel
= BMList
[i
].channel
;
921 for(i
=0; i
<BMListLen
; i
++) {
922 if(BMList
[i
].slotNumber
== ConfigInfo
->SlotNumber
&&
923 BMList
[i
].busNumber
== ConfigInfo
->SystemIoBusNumber
) {
928 KdPrint2((PRINT_PREFIX
"unexpected device arrival\n"));
935 KdPrint2((PRINT_PREFIX
" => SP_RETURN_NOT_FOUND\n"));
939 BMList
[i
].channel
= (UCHAR
)channel
;
942 bm_offset
= channel
? ATA_BM_OFFSET1
: 0;
944 KdPrint2((PRINT_PREFIX
"bm_offset %x, channel %x \n", bm_offset
, channel
));
946 if (!deviceExtension
) {
947 KdPrint2((PRINT_PREFIX
"!deviceExtension => SP_RETURN_ERROR\n"));
948 return SP_RETURN_ERROR
;
951 RtlZeroMemory(deviceExtension
, sizeof(HW_DEVICE_EXTENSION
));
953 vendorStrPtr
= vendorString
;
954 deviceStrPtr
= deviceString
;
956 slotNumber
= BMList
[i
].slotNumber
;
957 SystemIoBusNumber
= BMList
[i
].busNumber
;
960 KdPrint2((PRINT_PREFIX
"AdapterInterfaceType=%#x\n",ConfigInfo
->AdapterInterfaceType
));
961 KdPrint2((PRINT_PREFIX
"IoBusNumber=%#x\n",ConfigInfo
->SystemIoBusNumber
));
962 KdPrint2((PRINT_PREFIX
"slotNumber=%#x\n",slotNumber
));
964 // this buffer must be global and already filled for UNIATA_CORE build
965 busDataRead
= HalGetBusData(
966 //busDataRead = ScsiPortGetBusData(HwDeviceExtension,
971 PCI_COMMON_HDR_LENGTH
);
974 if (busDataRead
< (ULONG
)PCI_COMMON_HDR_LENGTH
) {
975 KdPrint2((PRINT_PREFIX
"busDataRead < PCI_COMMON_HDR_LENGTH => SP_RETURN_ERROR\n"));
979 KdPrint2((PRINT_PREFIX
"busDataRead\n"));
980 if (pciData
.VendorID
== PCI_INVALID_VENDORID
) {
981 KdPrint2((PRINT_PREFIX
"PCI_INVALID_VENDORID\n"));
986 VendorID
= pciData
.VendorID
;
987 DeviceID
= pciData
.DeviceID
;
988 BaseClass
= pciData
.BaseClass
;
989 SubClass
= pciData
.SubClass
;
990 RevID
= pciData
.RevisionID
;
991 dev_id
= VendorID
| (DeviceID
<< 16);
992 slotData
.u
.AsULONG
= slotNumber
;
993 KdPrint2((PRINT_PREFIX
"DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id
, BaseClass
, SubClass
));
995 deviceExtension
->slotNumber
= slotNumber
;
996 deviceExtension
->SystemIoBusNumber
= SystemIoBusNumber
;
997 deviceExtension
->DevID
= dev_id
;
998 deviceExtension
->RevID
= RevID
;
999 deviceExtension
->NumberChannels
= 2; // default
1000 deviceExtension
->DevIndex
= i
;
1002 _snprintf(deviceExtension
->Signature
, sizeof(deviceExtension
->Signature
),
1003 "UATA%8.8x/%1.1x@%8.8x", dev_id
, channel
, slotNumber
);
1005 if(BaseClass
!= PCI_DEV_CLASS_STORAGE
) {
1006 KdPrint2((PRINT_PREFIX
"BaseClass != PCI_DEV_CLASS_STORAGE => SP_RETURN_NOT_FOUND\n"));
1010 KdPrint2((PRINT_PREFIX
"Storage Class\n"));
1012 // look for known chipsets
1013 if(VendorID
!= BMList
[i
].nVendorId
||
1014 DeviceID
!= BMList
[i
].nDeviceId
) {
1015 KdPrint2((PRINT_PREFIX
"device not suitable\n"));
1019 found
= UniataCheckPCISubclass(BMList
[i
].Known
, BMList
[i
].RaidFlags
, SubClass
);
1021 KdPrint2((PRINT_PREFIX
"Subclass not supported\n"));
1025 ConfigInfo
->AlignmentMask
= 0x00000003;
1027 found
= UniataChipDetect(HwDeviceExtension
, &pciData
, i
, ConfigInfo
, &simplexOnly
);
1028 KdPrint2((PRINT_PREFIX
"ForceSimplex = %d\n", simplexOnly
));
1029 KdPrint2((PRINT_PREFIX
"HwFlags = %x\n (0)", deviceExtension
->HwFlags
));
1031 /* additional checks for some supported chipsets */
1033 if (SubClass
!= PCI_DEV_SUBCLASS_IDE
) {
1034 KdPrint2((PRINT_PREFIX
"0xc6931080, SubClass != PCI_DEV_SUBCLASS_IDE => found = FALSE\n"));
1041 /* unknown chipsets, try generic DMA if it seems possible */
1045 KdPrint2((PRINT_PREFIX
"Default device\n"));
1046 if(!Ata_is_supported_dev(&pciData
)) {
1047 KdPrint2((PRINT_PREFIX
"!Ata_is_supported_dev => found = FALSE\n"));
1050 KdPrint2((PRINT_PREFIX
"Ata_is_supported_dev\n"));
1053 deviceExtension
->UnknownDev
= TRUE
;
1057 KdPrint2((PRINT_PREFIX
"HwFlags = %x\n (1)", deviceExtension
->HwFlags
));
1059 KdPrint2((PRINT_PREFIX
"!found => SP_RETURN_NOT_FOUND\n"));
1063 KdPrint2((PRINT_PREFIX
"HwFlags = %x\n (2)", deviceExtension
->HwFlags
));
1064 KdPrint2((PRINT_PREFIX
"found suitable device\n"));
1066 /***********************************************************/
1067 /***********************************************************/
1068 /***********************************************************/
1070 deviceExtension
->UseDpc
= TRUE
;
1071 KdPrint2((PRINT_PREFIX
"HwFlags = %x\n (3)", deviceExtension
->HwFlags
));
1072 if(deviceExtension
->HwFlags
& UNIATA_NO_DPC
) {
1073 /* CMD 649, ROSB SWK33, ICH4 */
1074 KdPrint2((PRINT_PREFIX
"UniataFindBusMasterController: UNIATA_NO_DPC (0)\n"));
1075 deviceExtension
->UseDpc
= FALSE
;
1078 MasterDev
= IsMasterDev(&pciData
);
1081 KdPrint2((PRINT_PREFIX
"MasterDev (1)\n"));
1082 deviceExtension
->MasterDev
= TRUE
;
1083 deviceExtension
->NumberChannels
= 1;
1087 if((WinVer_Id() <= WinVer_NT
) && AltInit
&& FirstMasterOk
) {
1088 // this is the 2nd attempt to init this controller by OUR driver
1089 KdPrint2((PRINT_PREFIX
"Skip primary/secondary claiming checks\n"));
1091 if((channel
==0) && ConfigInfo
->AtdiskPrimaryClaimed
) {
1092 KdPrint2((PRINT_PREFIX
"Error: Primary channel already claimed by another driver\n"));
1095 if((channel
==1) && ConfigInfo
->AtdiskSecondaryClaimed
) {
1096 KdPrint2((PRINT_PREFIX
"Error: Secondary channel already claimed by another driver\n"));
1101 if(deviceExtension
->AltRegMap
) {
1102 KdPrint2((PRINT_PREFIX
" Non-standard registers layout\n"));
1103 if(deviceExtension
->HwFlags
& UNIATA_SATA
) {
1104 KdPrint2((PRINT_PREFIX
"UNIATA_SATA -> IsBusMaster == TRUE\n"));
1105 deviceExtension
->BusMaster
= TRUE
;
1108 deviceExtension
->BusMaster
= FALSE
;
1110 if(WinVer_WDM_Model
&& !deviceExtension
->UnknownDev
) {
1112 // Enable Busmastering, IO-space and Mem-space
1113 KdPrint2((PRINT_PREFIX
"Enabling Mem/Io spaces and busmastering...\n"));
1114 KdPrint2((PRINT_PREFIX
"Initial pciData.Command = %#x\n", pciData
.Command
));
1115 for(i
=0; i
<3; i
++) {
1118 KdPrint2((PRINT_PREFIX
"PCI_ENABLE_IO_SPACE\n"));
1119 pciData
.Command
|= PCI_ENABLE_IO_SPACE
;
1122 KdPrint2((PRINT_PREFIX
"PCI_ENABLE_MEMORY_SPACE\n"));
1123 pciData
.Command
|= PCI_ENABLE_MEMORY_SPACE
;
1126 KdPrint2((PRINT_PREFIX
"PCI_ENABLE_BUS_MASTER\n"));
1127 pciData
.Command
|= PCI_ENABLE_BUS_MASTER
;
1130 HalSetBusDataByOffset( PCIConfiguration
, SystemIoBusNumber
, slotData
.u
.AsULONG
,
1132 offsetof(PCI_COMMON_CONFIG
, Command
),
1133 sizeof(pciData
.Command
));
1134 KdPrint2((PRINT_PREFIX
"InterruptLine = %#x\n", pciData
.u
.type0
.InterruptLine
));
1136 // reread config space
1137 busDataRead
= HalGetBusData(PCIConfiguration
, SystemIoBusNumber
, slotData
.u
.AsULONG
,
1138 &pciData
, PCI_COMMON_HDR_LENGTH
);
1139 KdPrint2((PRINT_PREFIX
"New pciData.Command = %#x\n", pciData
.Command
));
1141 KdPrint2((PRINT_PREFIX
"Final pciData.Command = %#x\n", pciData
.Command
));
1143 // validate Mem/Io ranges
1147 for(i
=0; i
<PCI_TYPE0_ADDRESSES
; i
++) {
1148 if(pciData
.u
.type0
.BaseAddresses
[i
] & ~0x7) {
1149 //no_ranges = FALSE;
1151 KdPrint2((PRINT_PREFIX
"Range %d = %#x\n", i
, pciData
.u
.type0
.BaseAddresses
[i
]));
1156 if(IsBusMaster(&pciData
)) {
1158 KdPrint2((PRINT_PREFIX
"IsBusMaster == TRUE\n"));
1159 BaseIoAddressBM_0
= (PIDE_BUSMASTER_REGISTERS
)
1160 (AtapiGetIoRange(HwDeviceExtension
, ConfigInfo
, &pciData
, SystemIoBusNumber
,
1161 4, bm_offset
, MasterDev
? 0x08 : 0x10/*ATA_BMIOSIZE*/)/* - bm_offset*/); //range id
1162 if(BaseIoAddressBM_0
) {
1163 UniataInitMapBM(deviceExtension
,
1165 (*ConfigInfo
->AccessRanges
)[4].RangeInMemory
? TRUE
: FALSE
);
1166 deviceExtension
->BusMaster
= TRUE
;
1167 deviceExtension
->BaseIoAddressBM_0
.Addr
= (ULONG
)BaseIoAddressBM_0
;
1168 if((*ConfigInfo
->AccessRanges
)[4].RangeInMemory
) {
1169 deviceExtension
->BaseIoAddressBM_0
.MemIo
= TRUE
;
1172 KdPrint2((PRINT_PREFIX
" BusMasterAddress (base): %#x\n", BaseIoAddressBM_0
));
1175 if(!deviceExtension
->BusMaster
) {
1176 KdPrint2((PRINT_PREFIX
" !BusMasterAddress -> PIO4\n"));
1177 deviceExtension
->MaxTransferMode
= ATA_PIO4
;
1180 if(deviceExtension
->BusMaster
&& !MasterDev
) {
1181 KdPrint2((PRINT_PREFIX
"IsBusMaster == TRUE && !MasterDev\n"));
1182 statusByte
= AtapiReadPort1(&(deviceExtension
->chan
[0]), IDX_BM_Status
);
1183 KdPrint2((PRINT_PREFIX
" statusByte = %x\n", statusByte
));
1184 if(statusByte
== 0xff) {
1185 KdPrint2((PRINT_PREFIX
" invalid port ?\n"));
1187 if(BaseIoAddressBM_0) {
1188 ScsiPortFreeDeviceBase(HwDeviceExtension,
1190 BaseIoAddressBM_0 = NULL;
1194 if(statusByte
& BM_STATUS_SIMPLEX_ONLY
) {
1195 KdPrint2((PRINT_PREFIX
" BM_STATUS => simplexOnly\n"));
1202 * the Cypress chip is a mess, it contains two ATA functions, but
1203 * both channels are visible on the first one.
1204 * simply ignore the second function for now, as the right
1205 * solution (ignoring the second channel on the first function)
1206 * doesn't work with the crappy ATA interrupt setup on the alpha.
1208 if (dev_id
== 0xc6931080 && slotData
.u
.bits
.FunctionNumber
> 1) {
1209 KdPrint2((PRINT_PREFIX
"dev_id == 0xc6931080 && FunctionNumber > 1 => exit_findbm\n"));
1213 /* do extra chipset specific setups */
1214 AtapiReadChipConfig(HwDeviceExtension
, i
, CHAN_NOT_SPECIFIED
);
1215 AtapiChipInit(HwDeviceExtension
, i
, CHAN_NOT_SPECIFIED_CHECK_CABLE
);
1217 simplexOnly
|= deviceExtension
->simplexOnly
;
1218 deviceExtension
->simplexOnly
|= simplexOnly
;
1220 KdPrint2((PRINT_PREFIX
"simplexOnly = %d (2)", simplexOnly
));
1222 //TODO: fix hang with UseDpn=TRUE in Simplex mode
1223 //deviceExtension->UseDpc = TRUE;
1225 KdPrint2((PRINT_PREFIX
"simplexOnly => UseDpc = FALSE\n"));
1226 deviceExtension
->UseDpc
= FALSE
;
1229 if(simplexOnly
|| !MasterDev
/*|| (WinVer_Id() > WinVer_NT)*/) {
1230 if(deviceExtension
->NumberChannels
< 2) {
1231 KdPrint2((PRINT_PREFIX
"set NumberChannels = 2\n"));
1232 deviceExtension
->NumberChannels
= 2;
1233 if(BaseIoAddressBM_0
) {
1234 UniataInitMapBM(deviceExtension
,
1236 (*ConfigInfo
->AccessRanges
)[4].RangeInMemory
? TRUE
: FALSE
);
1241 (deviceExtension
->NumberChannels
> 1)) {
1242 KdPrint2((PRINT_PREFIX
"Error: channel > 0 && NumberChannels > 1\n"));
1246 // Indicate number of buses.
1247 ConfigInfo
->NumberOfBuses
= (UCHAR
)(deviceExtension
->NumberChannels
);
1248 if(!ConfigInfo
->InitiatorBusId
[0]) {
1249 ConfigInfo
->InitiatorBusId
[0] = (CHAR
)(IoGetConfigurationInformation()->ScsiPortCount
);
1250 KdPrint2((PRINT_PREFIX
"set ConfigInfo->InitiatorBusId[0] = %#x\n", ConfigInfo
->InitiatorBusId
[0]));
1252 // Indicate four devices can be attached to the adapter
1253 ConfigInfo
->MaximumNumberOfTargets
= (UCHAR
)(/*deviceExtension->NumberChannels **/ 2);
1256 KdPrint2((PRINT_PREFIX
"MasterDev (2)\n"));
1258 if((WinVer_Id() > WinVer_NT) ||
1259 (deviceExtension->NumberChannels > 1)) {
1261 KdPrint2((PRINT_PREFIX "2 channels & 2 irq for 1 controller Win 2000+\n"));
1263 if (ConfigInfo->AdapterInterfaceType == MicroChannel) {
1264 ConfigInfo->InterruptMode2 =
1265 ConfigInfo->InterruptMode = LevelSensitive;
1267 ConfigInfo->InterruptMode2 =
1268 ConfigInfo->InterruptMode = Latched;
1270 ConfigInfo->BusInterruptLevel = 14;
1271 ConfigInfo->BusInterruptLevel2 = 15;
1275 KdPrint2((PRINT_PREFIX
"2 channels & 2 irq for 1 controller\n"));
1277 if (ConfigInfo
->AdapterInterfaceType
== MicroChannel
) {
1278 ConfigInfo
->InterruptMode2
=
1279 ConfigInfo
->InterruptMode
= LevelSensitive
;
1281 ConfigInfo
->InterruptMode2
=
1282 ConfigInfo
->InterruptMode
= Latched
;
1284 ConfigInfo
->BusInterruptLevel
= 14;
1285 ConfigInfo
->BusInterruptLevel2
= 15;
1287 KdPrint2((PRINT_PREFIX
"1 channels & 1 irq for 1 controller\n"));
1288 if (ConfigInfo
->AdapterInterfaceType
== MicroChannel
) {
1289 ConfigInfo
->InterruptMode
= LevelSensitive
;
1291 ConfigInfo
->InterruptMode
= Latched
;
1293 ConfigInfo
->BusInterruptLevel
= (channel
== 0 ? 14 : 15);
1296 KdPrint2((PRINT_PREFIX
"!MasterDev\n"));
1297 ConfigInfo
->SlotNumber
= slotNumber
;
1298 ConfigInfo
->SystemIoBusNumber
= SystemIoBusNumber
;
1300 /* primary and secondary channels share the same interrupt */
1301 if(!ConfigInfo
->BusInterruptVector
||
1302 (ConfigInfo
->BusInterruptVector
!= pciData
.u
.type0
.InterruptLine
)) {
1303 KdPrint2((PRINT_PREFIX
"patch irq line = %#x\n", pciData
.u
.type0
.InterruptLine
));
1304 ConfigInfo
->BusInterruptVector
= pciData
.u
.type0
.InterruptLine
; // set default value
1305 if(!ConfigInfo
->BusInterruptVector
) {
1306 KdPrint2((PRINT_PREFIX
"patch irq line (2) = 10\n"));
1307 ConfigInfo
->BusInterruptVector
= 10;
1311 ConfigInfo
->MultipleRequestPerLu
= TRUE
;
1312 ConfigInfo
->AutoRequestSense
= TRUE
;
1313 ConfigInfo
->TaggedQueuing
= TRUE
;
1315 if((WinVer_Id() >= WinVer_NT
) ||
1316 (ConfigInfo
->Length
>= sizeof(_ConfigInfo
->comm
) + sizeof(_ConfigInfo
->nt4
))) {
1317 KdPrint2((PRINT_PREFIX
"update ConfigInfo->nt4\n"));
1318 _ConfigInfo
->nt4
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
1319 _ConfigInfo
->nt4
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
1320 _ConfigInfo
->nt4
.SrbExtensionSize
= sizeof(ATA_REQ
);
1322 if((WinVer_Id() > WinVer_2k
) ||
1323 (ConfigInfo
->Length
>= sizeof(_ConfigInfo
->comm
) + sizeof(_ConfigInfo
->nt4
) + sizeof(_ConfigInfo
->w2k
))) {
1324 KdPrint2((PRINT_PREFIX
"update ConfigInfo->w2k\n"));
1325 _ConfigInfo
->w2k
.Dma64BitAddresses
= 0;
1326 _ConfigInfo
->w2k
.ResetTargetSupported
= TRUE
;
1327 _ConfigInfo
->w2k
.MaximumNumberOfLogicalUnits
= 2;
1330 // Save the Interrupe Mode for later use
1331 deviceExtension
->InterruptMode
= ConfigInfo
->InterruptMode
;
1332 deviceExtension
->BusInterruptLevel
= ConfigInfo
->BusInterruptLevel
;
1333 deviceExtension
->BusInterruptVector
= ConfigInfo
->BusInterruptVector
;
1334 deviceExtension
->Channel
= channel
;
1335 deviceExtension
->DevIndex
= i
;
1336 deviceExtension
->OrigAdapterInterfaceType
1337 = ConfigInfo
->AdapterInterfaceType
;
1338 deviceExtension
->AlignmentMask
= ConfigInfo
->AlignmentMask
;
1339 deviceExtension
->AdapterInterfaceType
= PCIBus
;
1343 if(deviceExtension
->BusMaster
) {
1345 KdPrint2((PRINT_PREFIX
"Reconstruct ConfigInfo\n"));
1346 ConfigInfo
->MapBuffers
= TRUE
;
1348 ConfigInfo
->NeedPhysicalAddresses
= FALSE
;
1350 ConfigInfo
->NeedPhysicalAddresses
= TRUE
;
1351 #endif //USE_OWN_DMA
1353 KdPrint2((PRINT_PREFIX
"set Dma32BitAddresses\n"));
1354 ConfigInfo
->Dma32BitAddresses
= TRUE
;
1357 // thanks to Vitaliy Vorobyov aka deathsoft@yandex.ru for
1361 // I'm sorry, I have to do this
1364 if(ConfigInfo
->AdapterInterfaceType
== Isa
/*&&
1365 // InDriverEntry*/) {
1366 KdPrint2((PRINT_PREFIX
"AdapterInterfaceType Isa => PCIBus\n"));
1367 ConfigInfo
->AdapterInterfaceType
= PCIBus
;
1369 if(ConfigInfo
->AdapterInterfaceType
== PCIBus
/*&&
1370 // InDriverEntry*/) {
1371 KdPrint2((PRINT_PREFIX
"AdapterInterfaceType PCIBus, update address\n"));
1372 ConfigInfo
->SlotNumber
= slotNumber
;
1373 ConfigInfo
->SystemIoBusNumber
= SystemIoBusNumber
;
1378 ConfigInfo
->Master
= TRUE
;
1379 ConfigInfo
->DmaWidth
= Width16Bits
;
1380 #endif //USE_OWN_DMA
1381 ConfigInfo
->CachesData
= TRUE
;
1382 ConfigInfo
->ScatterGather
= TRUE
;
1385 // Note: now we can support only 4 channels !!!
1386 // in order to add support for multichannel controllers we must rewrite
1387 // io-range claiming algorithm
1389 KdPrint2((PRINT_PREFIX
"BMList[i].channel %#x, NumberChannels %#x, channel %#x\n",BMList
[i
].channel
, deviceExtension
->NumberChannels
, channel
));
1391 for (; channel
< (BMList
[i
].channel
+ deviceExtension
->NumberChannels
); channel
++, c
++) {
1393 KdPrint2((PRINT_PREFIX
"de %#x, Channel %#x\n",deviceExtension
, channel
));
1394 //PrintNtConsole("de %#x, Channel %#x, nchan %#x\n",deviceExtension, channel, deviceExtension->NumberChannels);
1395 chan
= &deviceExtension
->chan
[c
];
1397 KdPrint2((PRINT_PREFIX
"chan = %#x\n", chan
));
1398 //PrintNtConsole("chan = %#x, c=%#x\n", chan, c);
1399 AtapiSetupLunPtrs(chan
, deviceExtension
, c
);
1401 /* do extra channel-specific setups */
1402 AtapiReadChipConfig(HwDeviceExtension
, i
, channel
);
1403 //AtapiChipInit(HwDeviceExtension, i, channel);
1404 if(deviceExtension
->AltRegMap
) {
1405 KdPrint2((PRINT_PREFIX
" Non-standard registers layout\n"));
1407 // Check if the range specified is not used by another driver
1409 KdPrint2((PRINT_PREFIX
"set AccessRanges\n"));
1410 (*ConfigInfo
->AccessRanges
)[channel
* 2 + 0].RangeStart
=
1411 ScsiPortConvertUlongToPhysicalAddress(channel
? IO_WD2
: IO_WD1
);
1412 (*ConfigInfo
->AccessRanges
)[channel
* 2 + 0].RangeLength
= ATA_IOSIZE
;
1414 (*ConfigInfo
->AccessRanges
)[channel
* 2 + 1].RangeStart
=
1415 ScsiPortConvertUlongToPhysicalAddress((channel
? IO_WD2
: IO_WD1
) + ATA_ALTOFFSET
);
1416 (*ConfigInfo
->AccessRanges
)[channel
* 2 + 1].RangeLength
= ATA_ALTIOSIZE
;
1418 // do not claim 2nd BM io-range for Secondary channel of
1419 // Compatible-mode controllers
1420 if(/*(WinVer_Id() <= WinVer_NT) &&*/ !c
&& channel
== 1) {
1421 KdPrint2((PRINT_PREFIX
"cheat ScsiPort for 2nd channel, BM io-range\n"));
1422 (*ConfigInfo
->AccessRanges
)[4].RangeStart
= ScsiPortConvertUlongToPhysicalAddress(0);
1423 (*ConfigInfo
->AccessRanges
)[4].RangeLength
= 0;
1427 IoBasePort1
= (*ConfigInfo
->AccessRanges
)[channel
* 2 + 0].RangeStart
;
1428 IoBasePort2
= (*ConfigInfo
->AccessRanges
)[channel
* 2 + 1].RangeStart
;
1431 if(!IoBasePort1
.QuadPart
|| !IoBasePort2
.QuadPart
) {
1432 KdPrint2((PRINT_PREFIX
"ScsiPortValidateRange failed (1)\n"));
1437 if(!ScsiPortValidateRange(HwDeviceExtension
,
1438 PCIBus
/*ConfigInfo->AdapterInterfaceType*/,
1439 SystemIoBusNumber
/*ConfigInfo->SystemIoBusNumber*/,
1443 KdPrint2((PRINT_PREFIX
"ScsiPortValidateRange failed (1)\n"));
1447 if(!ScsiPortValidateRange(HwDeviceExtension
,
1448 PCIBus
/*ConfigInfo->AdapterInterfaceType*/,
1449 SystemIoBusNumber
/*ConfigInfo->SystemIoBusNumber*/,
1453 KdPrint2((PRINT_PREFIX
"ScsiPortValidateRange failed (2)\n"));
1457 KdPrint2((PRINT_PREFIX
"Getting IO ranges\n"));
1459 // Ok, translate adresses to io-space
1460 if(ScsiPortConvertPhysicalAddressToUlong(IoBasePort2
)) {
1461 if(!(MasterDev
/* || USE_16_BIT */)) {
1462 KdPrint2((PRINT_PREFIX
"!MasterDev mode\n"));
1463 IoBasePort2
= ScsiPortConvertUlongToPhysicalAddress(
1464 ScsiPortConvertPhysicalAddressToUlong(IoBasePort2
) + 2);
1467 KdPrint2((PRINT_PREFIX
"use relative IoBasePort2\n"));
1468 IoBasePort2
= ScsiPortConvertUlongToPhysicalAddress(
1469 ScsiPortConvertPhysicalAddressToUlong(IoBasePort1
) + ATA_PCCARD_ALTOFFSET
);
1472 // Get the system physical address for this IO range.
1473 ioSpace
= (PUCHAR
)ScsiPortGetDeviceBase(HwDeviceExtension
,
1474 PCIBus
/*ConfigInfo->AdapterInterfaceType*/,
1475 SystemIoBusNumber
/*ConfigInfo->SystemIoBusNumber*/,
1479 KdPrint2((PRINT_PREFIX
"IO range 1 %#x\n",ioSpace
));
1481 // Check if ioSpace accessible.
1483 KdPrint2((PRINT_PREFIX
"!ioSpace\n"));
1487 if(deviceExtension->BusMaster) {
1488 KdPrint2((PRINT_PREFIX "set BusMaster io-range in DO\n"));
1489 // bm_offset already includes (channel ? ATA_BM_OFFSET1 : 0)
1490 deviceExtension->BaseIoAddressBM[c] = (PIDE_BUSMASTER_REGISTERS)
1491 ((ULONG)(deviceExtension->BaseIoAddressBM_0) + bm_offset + (c ? ATA_BM_OFFSET1 : 0));
1494 //deviceExtension->BaseIoAddress1[c] = (PIDE_REGISTERS_1)(ioSpace);
1495 BaseIoAddress1
[c
] = (PIDE_REGISTERS_1
)(ioSpace
);
1497 // Get the system physical address for the second IO range.
1498 ioSpace
= (PUCHAR
)ScsiPortGetDeviceBase(HwDeviceExtension
,
1499 PCIBus
/*ConfigInfo->AdapterInterfaceType*/,
1500 SystemIoBusNumber
/*ConfigInfo->SystemIoBusNumber*/,
1504 KdPrint2((PRINT_PREFIX
"IO range 2 %#x\n",ioSpace
));
1506 BaseIoAddress2
[c
] = (PIDE_REGISTERS_2
)(ioSpace
);
1508 // Release all allocated resources
1509 KdPrint2((PRINT_PREFIX
"!deviceExtension->BaseIoAddress2\n"));
1510 //ioSpace = (PUCHAR)BaseIoAddress1[c];
1511 // goto free_iospace_1;
1515 UniataInitMapBase(chan
, BaseIoAddress1
[c
], BaseIoAddress2
[c
]);
1517 //ioSpace = (PUCHAR)(deviceExtension->BaseIoAddress1[c]);
1519 KdPrint2((PRINT_PREFIX
"IDX_IO1 %x->%x(%s)\n",
1521 chan
->RegTranslation
[IDX_IO1
].Addr
,
1522 chan
->RegTranslation
[IDX_IO1
].MemIo
? "mem" : "io"));
1524 KdPrint2((PRINT_PREFIX
"IDX_IO2 %x->%x(%s)\n",
1526 chan
->RegTranslation
[IDX_IO2
].Addr
,
1527 chan
->RegTranslation
[IDX_IO2
].MemIo
? "mem" : "io"));
1529 KdPrint2((PRINT_PREFIX
"IDX_BM_IO %x->%x(%s)\n",
1531 chan
->RegTranslation
[IDX_BM_IO
].Addr
,
1532 chan
->RegTranslation
[IDX_BM_IO
].MemIo
? "mem" : "io"));
1534 KdPrint2((PRINT_PREFIX
"IDX_SATA_IO %x->%x(%s)\n",
1536 chan
->RegTranslation
[IDX_SATA_IO
].Addr
,
1537 chan
->RegTranslation
[IDX_SATA_IO
].MemIo
? "mem" : "io"));
1539 UniataDumpATARegs(chan
);
1542 #ifdef UNIATA_INIT_ON_PROBE
1543 // if(deviceExtension->HwFlags & UNIATA_SATA) {
1544 //#endif //UNIATA_INIT_ON_PROBE
1545 KdPrint2((PRINT_PREFIX
"Check drive 0\n"));
1547 SelectDrive(chan
, 0);
1548 AtapiStallExecution(10);
1549 GetBaseStatus(chan
, statusByte
);
1550 skip_find_dev
= FALSE
;
1551 if(!(deviceExtension
->HwFlags
& UNIATA_NO_SLAVE
)) {
1552 if ((statusByte
& 0xf8) == 0xf8 ||
1553 (statusByte
== 0xa5)) {
1555 KdPrint2((PRINT_PREFIX
"Check drive 1\n"));
1556 SelectDrive(chan
, 1);
1557 AtapiStallExecution(1);
1558 GetBaseStatus(chan
, statusByte
);
1559 if ((statusByte
& 0xf8) == 0xf8 ||
1560 (statusByte
== 0xa5)) {
1561 // No controller at this base address.
1562 KdPrint2((PRINT_PREFIX
"Empty channel\n"));
1563 skip_find_dev
= TRUE
;
1568 // Search for devices on this controller.
1569 if (!skip_find_dev
&&
1570 FindDevices(HwDeviceExtension
,
1573 KdPrint2((PRINT_PREFIX
"Found some devices\n"));
1576 KdPrint2((PRINT_PREFIX
"no devices\n"));
1577 /* KeBugCheckEx(0xc000000e,
1578 ScsiPortConvertPhysicalAddressToUlong(IoBasePort1),
1579 ScsiPortConvertPhysicalAddressToUlong(IoBasePort2),
1580 (ULONG)(deviceExtension->BaseIoAddressBM[c]), skip_find_dev);*/
1582 //#ifdef UNIATA_INIT_ON_PROBE
1584 #endif //UNIATA_INIT_ON_PROBE
1587 chan
->PrimaryAddress
= FALSE
;
1588 // Claim primary or secondary ATA IO range.
1590 KdPrint2((PRINT_PREFIX
"claim Compatible controller\n"));
1592 KdPrint2((PRINT_PREFIX
"claim Primary\n"));
1593 ConfigInfo
->AtdiskPrimaryClaimed
= TRUE
;
1594 chan
->PrimaryAddress
= TRUE
;
1596 FirstMasterOk
= TRUE
;
1600 KdPrint2((PRINT_PREFIX
"claim Secondary\n"));
1601 ConfigInfo
->AtdiskSecondaryClaimed
= TRUE
;
1603 FirstMasterOk
= TRUE
;
1607 AtapiDmaAlloc(HwDeviceExtension
, ConfigInfo
, c
);
1610 #endif //UNIATA_CORE
1611 } // end for(channel)
1617 KdPrint2((PRINT_PREFIX
"exit: !found\n"));
1618 if(BaseIoAddress1
[0])
1619 ScsiPortFreeDeviceBase(HwDeviceExtension
,
1621 if(BaseIoAddress2
[0])
1622 ScsiPortFreeDeviceBase(HwDeviceExtension
,
1625 if(BaseIoAddress1
[1])
1626 ScsiPortFreeDeviceBase(HwDeviceExtension
,
1628 if(BaseIoAddress2
[1])
1629 ScsiPortFreeDeviceBase(HwDeviceExtension
,
1632 if(BaseIoAddressBM_0
)
1633 ScsiPortFreeDeviceBase(HwDeviceExtension
,
1636 KdPrint2((PRINT_PREFIX
"return SP_RETURN_NOT_FOUND\n"));
1640 KdPrint2((PRINT_PREFIX
"exit: init spinlock\n"));
1641 //KeInitializeSpinLock(&(deviceExtension->DpcSpinLock));
1642 deviceExtension
->ActiveDpcChan
=
1643 deviceExtension
->FirstDpcChan
= -1;
1645 BMList
[i
].Isr2Enable
= FALSE
;
1647 KdPrint2((PRINT_PREFIX
"MasterDev=%#x, NumberChannels=%#x, Isr2DevObj=%#x\n",
1648 MasterDev
, deviceExtension
->NumberChannels
, BMList
[i
].Isr2DevObj
));
1650 // ConnectIntr2 should be moved to HwInitialize
1651 status
= UniataConnectIntr2(HwDeviceExtension
);
1653 KdPrint2((PRINT_PREFIX
"MasterDev=%#x, NumberChannels=%#x, Isr2DevObj=%#x\n",
1654 MasterDev
, deviceExtension
->NumberChannels
, BMList
[i
].Isr2DevObj
));
1656 if(WinVer_WDM_Model
&& MasterDev
) {
1657 KdPrint2((PRINT_PREFIX
"do not tell system, that we know about this:\n"));
1658 if(BaseIoAddressBM_0
) {
1659 ScsiPortFreeDeviceBase(HwDeviceExtension
,
1662 (*ConfigInfo
->AccessRanges
)[4].RangeStart
= ScsiPortConvertUlongToPhysicalAddress(0);
1663 (*ConfigInfo
->AccessRanges
)[4].RangeLength
= 0;
1664 (*ConfigInfo
->AccessRanges
)[5].RangeStart
= ScsiPortConvertUlongToPhysicalAddress(0);
1665 (*ConfigInfo
->AccessRanges
)[5].RangeLength
= 0;
1668 if(!NT_SUCCESS(status
)) {
1669 KdPrint2((PRINT_PREFIX
"failed\n"));
1674 #endif //UNIATA_CORE
1676 KdPrint2((PRINT_PREFIX
"return SP_RETURN_FOUND\n"));
1677 //PrintNtConsole("return SP_RETURN_FOUND, de %#x, c0.lun0 %#x\n", deviceExtension, deviceExtension->chan[0].lun[0]);
1680 KdPrint2((PRINT_PREFIX
"Attempt %d of MasterDev ok\n", AltInit
));
1681 FirstMasterOk
= TRUE
;
1684 ConfigInfo
->NumberOfBuses
++; // add virtual channel for communication port
1685 return SP_RETURN_FOUND
;
1688 if (deviceExtension
->lun
) ExFreePool(deviceExtension
->lun
);
1689 if (deviceExtension
->chan
) ExFreePool(deviceExtension
->chan
);
1690 return SP_RETURN_ERROR
;
1693 ExFreePool(deviceExtension
->lun
);
1694 ExFreePool(deviceExtension
->chan
);
1695 return SP_RETURN_NOT_FOUND
;
1697 } // end UniataFindBusMasterController()
1702 This is for claiming PCI Busmaster in compatible mode under WDM OSes
1705 UniataFindFakeBusMasterController(
1706 IN PVOID HwDeviceExtension
,
1708 IN PVOID BusInformation
,
1709 IN PCHAR ArgumentString
,
1710 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
1714 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
1715 PHW_CHANNEL chan
= NULL
;
1716 // this buffer must be global for UNIATA_CORE build
1717 PCI_COMMON_CONFIG pciData
;
1721 ULONG SystemIoBusNumber
;
1723 UCHAR vendorString
[5];
1724 UCHAR deviceString
[5];
1725 PUCHAR vendorStrPtr
;
1726 PUCHAR deviceStrPtr
;
1734 PCI_SLOT_NUMBER slotData
;
1738 // UCHAR statusByte;
1743 BOOLEAN found
= FALSE
;
1745 BOOLEAN simplexOnly
= FALSE
;
1746 BOOLEAN skip_find_dev
= FALSE
;
1747 BOOLEAN AltInit
= FALSE
;
1749 PIDE_BUSMASTER_REGISTERS BaseIoAddressBM_0
= NULL
;
1752 PPORT_CONFIGURATION_INFORMATION_COMMON _ConfigInfo
=
1753 (PPORT_CONFIGURATION_INFORMATION_COMMON
)ConfigInfo
;
1760 for(i
=0; i
<BMListLen
; i
++) {
1761 if(BMList
[i
].slotNumber
== ConfigInfo
->SlotNumber
&&
1762 BMList
[i
].busNumber
== ConfigInfo
->SystemIoBusNumber
) {
1766 if(i
>= BMListLen
) {
1767 KdPrint2((PRINT_PREFIX
"unexpected device arrival => SP_RETURN_NOT_FOUND\n"));
1772 KdPrint2((PRINT_PREFIX
"UniataFindFakeBusMasterController (WDM)\n"));
1774 if (!deviceExtension
) {
1775 KdPrint2((PRINT_PREFIX
"!deviceExtension => SP_RETURN_ERROR\n"));
1776 return SP_RETURN_ERROR
;
1779 RtlZeroMemory(deviceExtension
, sizeof(HW_DEVICE_EXTENSION
));
1781 vendorStrPtr
= vendorString
;
1782 deviceStrPtr
= deviceString
;
1784 slotNumber
= BMList
[i
].slotNumber
;
1785 SystemIoBusNumber
= BMList
[i
].busNumber
;
1787 KdPrint2((PRINT_PREFIX
"AdapterInterfaceType=%#x\n",ConfigInfo
->AdapterInterfaceType
));
1788 KdPrint2((PRINT_PREFIX
"IoBusNumber=%#x\n",ConfigInfo
->SystemIoBusNumber
));
1789 KdPrint2((PRINT_PREFIX
"slotNumber=%#x\n",slotNumber
));
1791 // this buffer must be global and already filled for UNIATA_CORE build
1792 busDataRead
= HalGetBusData(
1793 //busDataRead = ScsiPortGetBusData(HwDeviceExtension,
1798 PCI_COMMON_HDR_LENGTH
);
1800 if (busDataRead
< PCI_COMMON_HDR_LENGTH
) {
1801 KdPrint2((PRINT_PREFIX
"busDataRead < PCI_COMMON_HDR_LENGTH => SP_RETURN_ERROR\n"));
1805 KdPrint2((PRINT_PREFIX
"busDataRead\n"));
1806 if (pciData
.VendorID
== PCI_INVALID_VENDORID
) {
1807 KdPrint2((PRINT_PREFIX
"PCI_INVALID_VENDORID\n"));
1811 VendorID
= pciData
.VendorID
;
1812 DeviceID
= pciData
.DeviceID
;
1813 BaseClass
= pciData
.BaseClass
;
1814 SubClass
= pciData
.SubClass
;
1815 RevID
= pciData
.RevisionID
;
1816 dev_id
= VendorID
| (DeviceID
<< 16);
1817 slotData
.u
.AsULONG
= slotNumber
;
1818 KdPrint2((PRINT_PREFIX
"DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id
, BaseClass
, SubClass
));
1820 deviceExtension
->slotNumber
= slotNumber
;
1821 deviceExtension
->SystemIoBusNumber
= SystemIoBusNumber
;
1822 deviceExtension
->DevID
= dev_id
;
1823 deviceExtension
->RevID
= RevID
;
1824 deviceExtension
->NumberChannels
= 2; // default
1825 deviceExtension
->DevIndex
= i
;
1827 _snprintf(deviceExtension
->Signature
, sizeof(deviceExtension
->Signature
),
1828 "UATA%8.8x/%1.1x@%8.8x", dev_id
, 0xff, slotNumber
);
1830 if(BaseClass
!= PCI_DEV_CLASS_STORAGE
) {
1831 KdPrint2((PRINT_PREFIX
"BaseClass != PCI_DEV_CLASS_STORAGE => SP_RETURN_NOT_FOUND\n"));
1835 KdPrint2((PRINT_PREFIX
"Storage Class\n"));
1837 // look for known chipsets
1838 if(VendorID
!= BMList
[i
].nVendorId
||
1839 DeviceID
!= BMList
[i
].nDeviceId
) {
1840 KdPrint2((PRINT_PREFIX
"device not suitable\n"));
1844 if((BMList
[i
].RaidFlags
& UNIATA_RAID_CONTROLLER
) &&
1846 KdPrint2((PRINT_PREFIX
"RAID support disabled\n"));
1851 case PCI_DEV_SUBCLASS_IDE
:
1852 case PCI_DEV_SUBCLASS_RAID
:
1853 case PCI_DEV_SUBCLASS_ATA
:
1854 case PCI_DEV_SUBCLASS_SATA
:
1858 KdPrint2((PRINT_PREFIX
"Subclass not supported\n"));
1862 ConfigInfo
->AlignmentMask
= 0x00000003;
1864 found
= UniataChipDetect(HwDeviceExtension
, &pciData
, i
, ConfigInfo
, &simplexOnly
);
1865 KdPrint2((PRINT_PREFIX
"ForceSimplex = %d\n", simplexOnly
));
1866 KdPrint2((PRINT_PREFIX
"HwFlags = %x\n (0)", deviceExtension
->HwFlags
));
1868 /* additional checks for some supported chipsets */
1870 if (SubClass
!= PCI_DEV_SUBCLASS_IDE
) {
1871 KdPrint2((PRINT_PREFIX
"0xc6931080, SubClass != PCI_DEV_SUBCLASS_IDE => found = FALSE\n"));
1878 /* unknown chipsets, try generic DMA if it seems possible */
1882 KdPrint2((PRINT_PREFIX
"Default device\n"));
1883 if(!Ata_is_supported_dev(&pciData
)) {
1884 KdPrint2((PRINT_PREFIX
"!Ata_is_supported_dev => found = FALSE\n"));
1887 KdPrint2((PRINT_PREFIX
"Ata_is_supported_dev\n"));
1890 deviceExtension
->UnknownDev
= TRUE
;
1894 KdPrint2((PRINT_PREFIX
"HwFlags = %x\n (1)", deviceExtension
->HwFlags
));
1896 KdPrint2((PRINT_PREFIX
"!found => SP_RETURN_NOT_FOUND\n"));
1900 KdPrint2((PRINT_PREFIX
"HwFlags = %x\n (2)", deviceExtension
->HwFlags
));
1901 KdPrint2((PRINT_PREFIX
"found suitable device\n"));
1903 /***********************************************************/
1904 /***********************************************************/
1905 /***********************************************************/
1907 deviceExtension
->UseDpc
= TRUE
;
1908 KdPrint2((PRINT_PREFIX
"HwFlags = %x\n (3)", deviceExtension
->HwFlags
));
1909 if(deviceExtension
->HwFlags
& UNIATA_NO_DPC
) {
1910 /* CMD 649, ROSB SWK33, ICH4 */
1911 KdPrint2((PRINT_PREFIX
"UniataFindBusMasterController: UNIATA_NO_DPC (0)\n"));
1912 deviceExtension
->UseDpc
= FALSE
;
1915 MasterDev
= IsMasterDev(&pciData
);
1918 KdPrint2((PRINT_PREFIX
"MasterDev\n"));
1919 deviceExtension
->MasterDev
= TRUE
;
1920 deviceExtension
->NumberChannels
= 1;
1922 KdPrint2((PRINT_PREFIX
"!MasterDev => SP_RETURN_NOT_FOUND\n"));
1926 if(deviceExtension
->AltRegMap
) {
1927 KdPrint2((PRINT_PREFIX
" Non-standard registers layout => SP_RETURN_NOT_FOUND\n"));
1930 if(IsBusMaster(&pciData
)) {
1931 KdPrint2((PRINT_PREFIX
" !BusMaster => SP_RETURN_NOT_FOUND\n"));
1935 KdPrint2((PRINT_PREFIX
"IsBusMaster == TRUE\n"));
1936 BaseIoAddressBM_0
= (PIDE_BUSMASTER_REGISTERS
)
1937 (AtapiGetIoRange(HwDeviceExtension
, ConfigInfo
, &pciData
, SystemIoBusNumber
,
1938 4, 0, 0x10/*ATA_BMIOSIZE*/)/* - bm_offset*/); //range id
1939 if(BaseIoAddressBM_0
) {
1940 UniataInitMapBM(deviceExtension
,
1942 (*ConfigInfo
->AccessRanges
)[4].RangeInMemory
? TRUE
: FALSE
);
1943 deviceExtension
->BusMaster
= TRUE
;
1944 deviceExtension
->BaseIoAddressBM_0
.Addr
= (ULONG
)BaseIoAddressBM_0
;
1945 if((*ConfigInfo
->AccessRanges
)[4].RangeInMemory
) {
1946 deviceExtension
->BaseIoAddressBM_0
.MemIo
= TRUE
;
1949 KdPrint2((PRINT_PREFIX
" BusMasterAddress (base): %#x\n", BaseIoAddressBM_0
));
1952 * the Cypress chip is a mess, it contains two ATA functions, but
1953 * both channels are visible on the first one.
1954 * simply ignore the second function for now, as the right
1955 * solution (ignoring the second channel on the first function)
1956 * doesn't work with the crappy ATA interrupt setup on the alpha.
1958 if (dev_id
== 0xc6931080 && slotData
.u
.bits
.FunctionNumber
> 1) {
1959 KdPrint2((PRINT_PREFIX
"dev_id == 0xc6931080 && FunctionNumber > 1 => exit_findbm\n"));
1963 // Indicate number of buses.
1964 ConfigInfo
->NumberOfBuses
= 0;
1965 if(!ConfigInfo
->InitiatorBusId
[0]) {
1966 ConfigInfo
->InitiatorBusId
[0] = (CHAR
)(IoGetConfigurationInformation()->ScsiPortCount
);
1967 KdPrint2((PRINT_PREFIX
"set ConfigInfo->InitiatorBusId[0] = %#x\n", ConfigInfo
->InitiatorBusId
[0]));
1969 // Indicate four devices can be attached to the adapter
1970 ConfigInfo
->MaximumNumberOfTargets
= 0;
1972 ConfigInfo
->MultipleRequestPerLu
= FALSE
;
1973 ConfigInfo
->AutoRequestSense
= FALSE
;
1974 ConfigInfo
->TaggedQueuing
= FALSE
;
1976 if((WinVer_Id() >= WinVer_NT
) ||
1977 (ConfigInfo
->Length
>= sizeof(_ConfigInfo
->comm
) + sizeof(_ConfigInfo
->nt4
))) {
1978 _ConfigInfo
->nt4
.DeviceExtensionSize
= sizeof(HW_DEVICE_EXTENSION
);
1979 _ConfigInfo
->nt4
.SpecificLuExtensionSize
= sizeof(HW_LU_EXTENSION
);
1980 _ConfigInfo
->nt4
.SrbExtensionSize
= sizeof(ATA_REQ
);
1982 if((WinVer_Id() > WinVer_2k
) ||
1983 (ConfigInfo
->Length
>= sizeof(_ConfigInfo
->comm
) + sizeof(_ConfigInfo
->nt4
) + sizeof(_ConfigInfo
->w2k
))) {
1984 _ConfigInfo
->w2k
.Dma64BitAddresses
= 0;
1985 _ConfigInfo
->w2k
.ResetTargetSupported
= FALSE
;
1986 _ConfigInfo
->w2k
.MaximumNumberOfLogicalUnits
= 0;
1989 // Save the Interrupe Mode for later use
1990 deviceExtension
->InterruptMode
= ConfigInfo
->InterruptMode
;
1991 deviceExtension
->BusInterruptLevel
= ConfigInfo
->BusInterruptLevel
;
1992 deviceExtension
->BusInterruptVector
= ConfigInfo
->BusInterruptVector
;
1993 deviceExtension
->Channel
= 0;
1994 deviceExtension
->DevIndex
= i
;
1995 deviceExtension
->OrigAdapterInterfaceType
1996 = ConfigInfo
->AdapterInterfaceType
;
1997 deviceExtension
->AlignmentMask
= ConfigInfo
->AlignmentMask
;
1998 deviceExtension
->AdapterInterfaceType
= PCIBus
;
2000 KdPrint2((PRINT_PREFIX
"Reconstruct ConfigInfo\n"));
2001 ConfigInfo
->MapBuffers
= TRUE
;
2003 ConfigInfo
->NeedPhysicalAddresses
= FALSE
;
2005 ConfigInfo
->NeedPhysicalAddresses
= TRUE
;
2006 #endif //USE_OWN_DMA
2010 KdPrint2((PRINT_PREFIX
"return SP_RETURN_FOUND\n"));
2011 //PrintNtConsole("return SP_RETURN_FOUND, de %#x, c0.lun0 %#x\n", deviceExtension, deviceExtension->chan[0].lun[0]);
2013 return SP_RETURN_FOUND
;
2016 if (deviceExtension
->lun
) ExFreePool(deviceExtension
->lun
);
2017 if (deviceExtension
->chan
) ExFreePool(deviceExtension
->chan
);
2018 return SP_RETURN_ERROR
;
2021 ExFreePool(deviceExtension
->lun
);
2022 ExFreePool(deviceExtension
->chan
);
2023 return SP_RETURN_NOT_FOUND
;
2025 } // end UniataFindFakeBusMasterController()
2030 Routine Description:
2032 This function is called to initialize 2nd device object for
2033 multichannel controllers.
2037 HwDeviceExtension - HBA miniport driver's adapter data storage
2046 IN PVOID HwDeviceExtension
2049 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2050 ULONG i
= deviceExtension
->DevIndex
;
2052 PISR2_DEVICE_EXTENSION Isr2DevExt
;
2053 WCHAR devname_str
[32];
2054 UNICODE_STRING devname
;
2056 KdPrint2((PRINT_PREFIX
"Init ISR:\n"));
2058 if(BMList
[i
].Isr2DevObj
) {
2059 KdPrint2((PRINT_PREFIX
"Already initialized %#x\n", BMList
[i
].Isr2DevObj
));
2060 return STATUS_SUCCESS
;
2063 if(!deviceExtension
->MasterDev
&& (deviceExtension
->NumberChannels
> 1) && // do not touch MasterDev
2064 !deviceExtension
->simplexOnly
&& /* // this is unnecessary on simplex controllers
2065 !BMList[i].Isr2DevObj*/ // handle re-init under w2k+
2069 KdPrint2((PRINT_PREFIX
"Multichannel native mode, go...\n"));
2071 KdPrint2((PRINT_PREFIX
"Unnecessary\n"));
2072 return STATUS_SUCCESS
;
2075 KdPrint2((PRINT_PREFIX
"Create DO\n"));
2078 _snwprintf(devname_str
, sizeof(devname_str
)/sizeof(WCHAR
),
2079 L
"\\Device\\uniata%d_2ch", i
);
2080 devname
.Length
*= sizeof(WCHAR
);
2081 devname
.MaximumLength
= devname
.Length
;
2082 devname
.Buffer
= devname_str
;
2084 KdPrint2((PRINT_PREFIX
"DO name: len(%d, %d), %S\n", devname
.Length
, devname
.MaximumLength
, devname
.Buffer
));
2086 status
= IoCreateDevice(SavedDriverObject
, sizeof(ISR2_DEVICE_EXTENSION
),
2087 /*NULL*/ &devname
, FILE_DEVICE_UNKNOWN
,
2088 0, FALSE
, &(BMList
[i
].Isr2DevObj
));
2090 if(!NT_SUCCESS(status
)) {
2091 KdPrint2((PRINT_PREFIX
"IoCreateDevice failed %#x\n"));
2095 KdPrint2((PRINT_PREFIX
"HalGetInterruptVector\n"));
2096 KdPrint2((PRINT_PREFIX
" OrigAdapterInterfaceType=%d\n", deviceExtension
->OrigAdapterInterfaceType
));
2097 KdPrint2((PRINT_PREFIX
" SystemIoBusNumber=%d\n", deviceExtension
->SystemIoBusNumber
));
2098 KdPrint2((PRINT_PREFIX
" BusInterruptLevel=%d\n", deviceExtension
->BusInterruptLevel
));
2099 KdPrint2((PRINT_PREFIX
" BusInterruptVector=%d\n", deviceExtension
->BusInterruptVector
));
2100 BMList
[i
].Isr2Vector
= HalGetInterruptVector(
2101 deviceExtension
->OrigAdapterInterfaceType
,
2102 deviceExtension
->SystemIoBusNumber
,
2103 deviceExtension
->BusInterruptLevel
,
2104 deviceExtension
->BusInterruptVector
,
2105 &(BMList
[i
].Isr2Irql
),
2106 &(BMList
[i
].Isr2Affinity
));
2108 Isr2DevExt
= (PISR2_DEVICE_EXTENSION
)(BMList
[i
].Isr2DevObj
->DeviceExtension
);
2109 Isr2DevExt
->HwDeviceExtension
= deviceExtension
;
2110 Isr2DevExt
->DevIndex
= i
;
2112 KdPrint2((PRINT_PREFIX
"isr2_de %#x\n", Isr2DevExt
));
2113 KdPrint2((PRINT_PREFIX
"isr2_vector %#x\n", BMList
[i
].Isr2Vector
));
2114 KdPrint2((PRINT_PREFIX
"isr2_irql %#x\n", BMList
[i
].Isr2Irql
));
2115 KdPrint2((PRINT_PREFIX
"isr2_affinity %#x\n", BMList
[i
].Isr2Affinity
));
2117 // deviceExtension->QueueNewIrql = BMList[i].Isr2Irql;
2119 KdPrint2((PRINT_PREFIX
"IoConnectInterrupt\n"));
2120 status
= IoConnectInterrupt(
2121 &(BMList
[i
].Isr2InterruptObject
),
2125 BMList
[i
].Isr2Vector
,
2128 (KINTERRUPT_MODE
)(deviceExtension
->InterruptMode
),
2130 BMList
[i
].Isr2Affinity
,
2133 if(!NT_SUCCESS(status
)) {
2134 KdPrint2((PRINT_PREFIX
"IoConnectInterrupt failed\n"));
2135 IoDeleteDevice(BMList
[i
].Isr2DevObj
);
2136 BMList
[i
].Isr2DevObj
= NULL
;
2137 BMList
[i
].Isr2InterruptObject
= NULL
;
2141 //deviceExtension->Isr2DevObj = BMList[i].Isr2DevObj;
2144 } // end UniataConnectIntr2()
2147 UniataDisconnectIntr2(
2148 IN PVOID HwDeviceExtension
2151 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2152 ULONG i
= deviceExtension
->DevIndex
;
2155 KdPrint2((PRINT_PREFIX
"Deinit ISR:\n"));
2157 if(!BMList
[i
].Isr2DevObj
) {
2158 KdPrint2((PRINT_PREFIX
"Already uninitialized %#x\n"));
2159 return STATUS_SUCCESS
;
2162 IoDisconnectInterrupt(BMList
[i
].Isr2InterruptObject
);
2164 BMList
[i
].Isr2InterruptObject
= NULL
;
2166 IoDeleteDevice(BMList
[i
].Isr2DevObj
);
2168 BMList
[i
].Isr2DevObj
= NULL
;
2169 //deviceExtension->Isr2DevObj = NULL;
2171 return STATUS_SUCCESS
;
2172 } // end UniataDisconnectIntr2()
2174 #endif //UNIATA_CORE
2178 Routine Description:
2180 This function is called by the OS-specific port driver after
2181 the necessary storage has been allocated, to gather information
2182 about the adapter's configuration.
2186 HwDeviceExtension - HBA miniport driver's adapter data storage
2187 Context - Address of adapter count
2188 ArgumentString - Used to determine whether driver is client of ntldr or crash dump utility.
2189 ConfigInfo - Configuration information structure describing HBA
2190 Again - Indicates search for adapters to continue
2198 AtapiFindController(
2199 IN PVOID HwDeviceExtension
,
2201 IN PVOID BusInformation
,
2202 IN PCHAR ArgumentString
,
2203 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
,
2207 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2209 PULONG adapterCount
= (PULONG
)Context
;
2217 BOOLEAN preConfig
= FALSE
;
2219 PIDE_REGISTERS_1 BaseIoAddress1
;
2220 PIDE_REGISTERS_2 BaseIoAddress2
;
2222 // The following table specifies the ports to be checked when searching for
2223 // an IDE controller. A zero entry terminates the search.
2224 static CONST ULONG AdapterAddresses
[5] = {IO_WD1
, IO_WD2
, IO_WD1
-8, IO_WD2
-8, 0};
2225 // CONST UCHAR Channels[5] = {0, 1, 0, 1, 0};
2227 // The following table specifies interrupt levels corresponding to the
2228 // port addresses in the previous table.
2229 static CONST ULONG InterruptLevels
[5] = {14, 15, 11, 10, 0};
2231 KdPrint2((PRINT_PREFIX
"AtapiFindController:\n"));
2233 if (!deviceExtension
) {
2234 return SP_RETURN_ERROR
;
2236 RtlZeroMemory(deviceExtension
, sizeof(HW_DEVICE_EXTENSION
));
2238 KdPrint2((PRINT_PREFIX
" assume max PIO4\n"));
2239 deviceExtension
->MaxTransferMode
= ATA_PIO4
;
2240 deviceExtension
->NumberChannels
= 1;
2242 if(!UniataAllocateLunExt(deviceExtension
, UNIATA_ALLOCATE_NEW_LUNS
)) {
2246 chan
= &(deviceExtension
->chan
[0]);
2248 deviceExtension
->AdapterInterfaceType
=
2249 deviceExtension
->OrigAdapterInterfaceType
2250 = ConfigInfo
->AdapterInterfaceType
;
2254 /* do extra chipset specific setups */
2255 AtapiReadChipConfig(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2256 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, CHAN_NOT_SPECIFIED
);
2258 // Check to see if this is a special configuration environment.
2260 if (ArgumentString
) {
2262 irq
= AtapiParseArgumentString(ArgumentString
, "Interrupt");
2265 // Both parameters must be present to proceed
2266 portBase
= AtapiParseArgumentString(ArgumentString
, "BaseAddress");
2269 // Try a default search for the part.
2275 #endif //UNIATA_CORE
2278 // Scan though the adapter address looking for adapters.
2279 if (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo
->AccessRanges
)[0].RangeStart
) != 0) {
2280 ioSpace
= (PUCHAR
)ScsiPortGetDeviceBase(HwDeviceExtension
,
2281 ConfigInfo
->AdapterInterfaceType
,
2282 ConfigInfo
->SystemIoBusNumber
,
2283 (*ConfigInfo
->AccessRanges
)[0].RangeStart
,
2284 (*ConfigInfo
->AccessRanges
)[0].RangeLength
,
2285 (BOOLEAN
) !((*ConfigInfo
->AccessRanges
)[0].RangeInMemory
));
2287 // Since we have pre-configured information we only need to go through this loop once
2289 portBase
= ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo
->AccessRanges
)[0].RangeStart
);
2290 KdPrint2((PRINT_PREFIX
" preconfig, portBase=%x\n", portBase
));
2294 while (AdapterAddresses
[*adapterCount
] != 0) {
2297 #endif //UNIATA_CORE
2300 deviceExtension
->DevIndex
= (*adapterCount
);
2302 portBase
= AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"PortBase", portBase
);
2303 irq
= AtapiRegCheckDevValue(deviceExtension
, CHAN_NOT_SPECIFIED
, DEVNUM_NOT_SPECIFIED
, L
"Irq", irq
);
2305 for (i
= 0; i
< 4; i
++) {
2306 // Zero device fields to ensure that if earlier devices were found,
2307 // but not claimed, the fields are cleared.
2308 deviceExtension
->lun
[i
].DeviceFlags
&= ~(DFLAGS_ATAPI_DEVICE
| DFLAGS_DEVICE_PRESENT
| DFLAGS_TAPE_DEVICE
);
2310 // Get the system physical address for this IO range.
2312 // Check if configInfo has the default information
2313 // if not, we go and find ourselves
2314 if (preConfig
== FALSE
) {
2317 ioSpace
= (PUCHAR
)ScsiPortGetDeviceBase(HwDeviceExtension
,
2318 ConfigInfo
->AdapterInterfaceType
,
2319 ConfigInfo
->SystemIoBusNumber
,
2320 ScsiPortConvertUlongToPhysicalAddress(portBase
),
2324 ioSpace
= (PUCHAR
)ScsiPortGetDeviceBase(HwDeviceExtension
,
2325 ConfigInfo
->AdapterInterfaceType
,
2326 ConfigInfo
->SystemIoBusNumber
,
2327 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses
[*adapterCount
]),
2333 BaseIoAddress1
= (PIDE_REGISTERS_1
)ioSpace
;
2335 // Update the adapter count.
2338 // Check if ioSpace accessible.
2340 KdPrint2((PRINT_PREFIX
"AtapiFindController: !ioSpace\n"));
2343 // check if Primary/Secondary Master IDE claimed
2344 if((ioSpace
== (PUCHAR
)IO_WD1
) &&
2345 (ConfigInfo
->AtdiskPrimaryClaimed
)) {
2346 KdPrint2((PRINT_PREFIX
"AtapiFindController: AtdiskPrimaryClaimed\n"));
2349 if((ioSpace
== (PUCHAR
)IO_WD2
) &&
2350 (ConfigInfo
->AtdiskSecondaryClaimed
)) {
2351 KdPrint2((PRINT_PREFIX
"AtapiFindController: AtdiskSecondaryClaimed\n"));
2355 // Get the system physical address for the second IO range.
2356 if (BaseIoAddress1
) {
2358 !ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo
->AccessRanges
)[1].RangeStart
)) {
2359 KdPrint2((PRINT_PREFIX
"AtapiFindController: PCMCIA ?\n"));
2360 ioSpace
= (PUCHAR
)ScsiPortGetDeviceBase(HwDeviceExtension
,
2361 ConfigInfo
->AdapterInterfaceType
,
2362 ConfigInfo
->SystemIoBusNumber
,
2363 ScsiPortConvertUlongToPhysicalAddress((ULONG
)BaseIoAddress1
+ 0x0E),
2367 ioSpace
= (PUCHAR
)ScsiPortGetDeviceBase(HwDeviceExtension
,
2368 ConfigInfo
->AdapterInterfaceType
,
2369 ConfigInfo
->SystemIoBusNumber
,
2370 ScsiPortConvertUlongToPhysicalAddress((ULONG
)BaseIoAddress1
+ ATA_ALTOFFSET
),
2375 BaseIoAddress2
= (PIDE_REGISTERS_2
)ioSpace
;
2376 KdPrint2((PRINT_PREFIX
" BaseIoAddress1=%x\n", BaseIoAddress1
));
2377 KdPrint2((PRINT_PREFIX
" BaseIoAddress2=%x\n", BaseIoAddress2
));
2379 UniataInitMapBase(chan
, BaseIoAddress1
, BaseIoAddress2
);
2380 UniataInitMapBM(deviceExtension
, 0, FALSE
);
2385 SelectDrive(chan
, 0);
2387 // Check if card at this address.
2388 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, 0xAA);
2390 // Check if indentifier can be read back.
2391 if ((statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
)) != 0xAA) {
2393 KdPrint2((PRINT_PREFIX
"AtapiFindController: Identifier read back from Master (%#x)\n",
2396 statusByte
= AtapiReadPort1(chan
, IDX_IO2_AltStatus
);
2398 if (statusByte
& IDE_STATUS_BUSY
) {
2402 // Could be the TEAC in a thinkpad. Their dos driver puts it in a sleep-mode that
2403 // warm boots don't clear.
2405 AtapiStallExecution(1000);
2406 statusByte
= AtapiReadPort1(chan
, IDX_ATAPI_IO1_i_Status
);
2407 KdPrint2((PRINT_PREFIX
2408 "AtapiFindController: First access to status %#x\n",
2410 } while ((statusByte
& IDE_STATUS_BUSY
) && ++i
< 10);
2412 if (retryCount
-- && (!(statusByte
& IDE_STATUS_BUSY
))) {
2413 goto retryIdentifier
;
2418 SelectDrive(chan
, 1);
2420 // See if slave is present.
2421 AtapiWritePort1(chan
, IDX_IO1_o_CylinderLow
, 0xAA);
2423 if ((statusByte
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
)) != 0xAA) {
2425 KdPrint2((PRINT_PREFIX
2426 "AtapiFindController: Identifier read back from Slave (%#x)\n",
2429 // No controller at this base address.
2430 if(BaseIoAddress1
) {
2431 ScsiPortFreeDeviceBase(HwDeviceExtension
,
2432 (PCHAR
)BaseIoAddress1
);
2433 BaseIoAddress1
= NULL
;
2435 if(BaseIoAddress2
) {
2436 ScsiPortFreeDeviceBase(HwDeviceExtension
,
2437 (PCHAR
)BaseIoAddress2
);
2438 BaseIoAddress2
= NULL
;
2444 // Fill in the access array information only if default params are not in there.
2445 if (preConfig
== FALSE
) {
2447 // An adapter has been found request another call, only if we didn't get preconfigured info.
2451 (*ConfigInfo
->AccessRanges
)[0].RangeStart
= ScsiPortConvertUlongToPhysicalAddress(portBase
);
2453 (*ConfigInfo
->AccessRanges
)[0].RangeStart
=
2454 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses
[*adapterCount
- 1]);
2457 (*ConfigInfo
->AccessRanges
)[0].RangeLength
= 8;
2458 (*ConfigInfo
->AccessRanges
)[0].RangeInMemory
= FALSE
;
2460 // Indicate the interrupt level corresponding to this IO range.
2462 ConfigInfo
->BusInterruptLevel
= irq
;
2464 ConfigInfo
->BusInterruptLevel
= InterruptLevels
[*adapterCount
- 1];
2467 if (ConfigInfo
->AdapterInterfaceType
== MicroChannel
) {
2468 ConfigInfo
->InterruptMode
= LevelSensitive
;
2470 ConfigInfo
->InterruptMode
= Latched
;
2474 ConfigInfo
->NumberOfBuses
= 1;
2475 ConfigInfo
->MaximumNumberOfTargets
= 2;
2477 // Indicate maximum transfer length is 64k.
2478 ConfigInfo
->MaximumTransferLength
= 0x10000;
2479 deviceExtension
->MaximumDmaTransferLength
= ConfigInfo
->MaximumTransferLength
;
2481 KdPrint2((PRINT_PREFIX
"de %#x, Channel ???\n", deviceExtension
));
2482 //PrintNtConsole("de %#x, Channel %#x, nchan %#x\n",deviceExtension, channel, deviceExtension->NumberChannels);
2484 KdPrint2((PRINT_PREFIX
"chan = %#x\n", chan
));
2485 //PrintNtConsole("chan = %#x, c=%#x\n", chan, c);
2486 chan
->DeviceExtension
= deviceExtension
;
2488 chan
->lun
[0] = &(deviceExtension
->lun
[0]);
2489 chan
->lun
[1] = &(deviceExtension
->lun
[1]);
2491 /* do extra channel-specific setups */
2492 AtapiReadChipConfig(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, 0);
2493 AtapiChipInit(HwDeviceExtension
, DEVNUM_NOT_SPECIFIED
, 0);
2495 KdPrint2((PRINT_PREFIX
2496 "AtapiFindController: Found IDE at %#x\n",
2499 // For Daytona, the atdisk driver gets the first shot at the
2500 // primary and secondary controllers.
2501 if (preConfig
== FALSE
) {
2503 if (*adapterCount
- 1 < 2) {
2505 // Determine whether this driver is being initialized by the
2506 // system or as a crash dump driver.
2507 if (ArgumentString
) {
2510 if (AtapiParseArgumentString(ArgumentString
, "dump") == 1) {
2511 KdPrint2((PRINT_PREFIX
2512 "AtapiFindController: Crash dump\n"));
2514 deviceExtension
->DriverMustPoll
= TRUE
;
2516 KdPrint2((PRINT_PREFIX
2517 "AtapiFindController: Atapi Only\n"));
2519 deviceExtension
->DriverMustPoll
= FALSE
;
2521 #endif //UNIATA_CORE
2524 KdPrint2((PRINT_PREFIX
2525 "AtapiFindController: Atapi Only (2)\n"));
2527 deviceExtension
->DriverMustPoll
= FALSE
;
2537 deviceExtension
->DriverMustPoll
= FALSE
;
2541 // Save the Interrupe Mode for later use
2542 deviceExtension
->InterruptMode
= ConfigInfo
->InterruptMode
;
2544 KdPrint2((PRINT_PREFIX
2545 "AtapiFindController: look for devices\n"));
2546 // Search for devices on this controller.
2547 if (FindDevices(HwDeviceExtension
,
2551 KdPrint2((PRINT_PREFIX
2552 "AtapiFindController: detected\n"));
2553 // Claim primary or secondary ATA IO range.
2557 ConfigInfo
->AtdiskSecondaryClaimed
= TRUE
;
2558 chan
->PrimaryAddress
= FALSE
;
2561 ConfigInfo
->AtdiskPrimaryClaimed
= TRUE
;
2562 chan
->PrimaryAddress
= TRUE
;
2568 if (*adapterCount
== 1) {
2569 ConfigInfo
->AtdiskPrimaryClaimed
= TRUE
;
2570 chan
->PrimaryAddress
= TRUE
;
2571 } else if (*adapterCount
== 2) {
2572 ConfigInfo
->AtdiskSecondaryClaimed
= TRUE
;
2573 chan
->PrimaryAddress
= FALSE
;
2577 if(deviceExtension
->AdapterInterfaceType
== Isa
) {
2580 if(deviceExtension
->AdapterInterfaceType
== MicroChannel
) {
2584 KdPrint2((PRINT_PREFIX
2585 "AtapiFindController: return SP_RETURN_FOUND\n"));
2586 return(SP_RETURN_FOUND
);
2592 #endif //UNIATA_CORE
2594 // The entire table has been searched and no adapters have been found.
2595 // There is no need to call again and the device base can now be freed.
2596 // Clear the adapter count for the next bus.
2598 *(adapterCount
) = 0;
2600 KdPrint2((PRINT_PREFIX
2601 "AtapiFindController: return SP_RETURN_NOT_FOUND\n"));
2602 ExFreePool(deviceExtension
->lun
);
2603 ExFreePool(deviceExtension
->chan
);
2604 return(SP_RETURN_NOT_FOUND
);
2607 if (deviceExtension
->lun
) ExFreePool(deviceExtension
->lun
);
2608 if (deviceExtension
->chan
) ExFreePool(deviceExtension
->chan
);
2609 return SP_RETURN_ERROR
;
2611 } // end AtapiFindController()
2615 IN PVOID HwDeviceExtension
,
2617 IN ULONG deviceNumber
2620 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2621 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2622 ULONG ldev
= GET_LDEV2(lChannel
, deviceNumber
, 0);
2623 PHW_LU_EXTENSION LunExt
= &(deviceExtension
->lun
[ldev
]);
2625 SATA_SSTATUS_REG SStatus
;
2627 UCHAR signatureHigh
;
2629 if(LunExt
->DeviceFlags
& DFLAGS_HIDDEN
) {
2630 KdPrint2((PRINT_PREFIX
" hidden\n"));
2631 UniataForgetDevice(LunExt
);
2634 // Select the device.
2635 SelectDrive(chan
, deviceNumber
);
2637 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
2638 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
2640 if (signatureLow
== ATAPI_MAGIC_LSB
&& signatureHigh
== ATAPI_MAGIC_MSB
) {
2641 KdPrint2((PRINT_PREFIX
" ATAPI at home\n", signatureLow
));
2645 if(!UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
2646 AtapiStallExecution(10);
2648 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, 0x55);
2649 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, 0x55);
2650 AtapiStallExecution(5);
2651 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
2652 if(signatureLow
!= 0x55) {
2653 KdPrint2((PRINT_PREFIX
" nobody home! %#x != 0x55\n", signatureLow
));
2654 UniataForgetDevice(LunExt
);
2658 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, 0xAA);
2659 AtapiWritePort1(chan
, IDX_IO1_o_BlockNumber
, 0xAA);
2660 AtapiStallExecution(5);
2661 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_BlockNumber
);
2662 if(signatureLow
!= 0xAA) {
2663 KdPrint2((PRINT_PREFIX
" nobody home! %#x != 0xAA\n", signatureLow
));
2664 UniataForgetDevice(LunExt
);
2669 SStatus
.Reg
= AtapiReadPort4(chan
, IDX_SATA_SStatus
);
2670 KdPrint2((PRINT_PREFIX
"SStatus %x\n", SStatus
.Reg
));
2671 if(SStatus
.DET
<= SStatus_DET_Dev_NoPhy
) {
2672 KdPrint2((PRINT_PREFIX
" SATA DET <= SStatus_DET_Dev_NoPhy\n"));
2675 if(SStatus
.SPD
< SStatus_SPD_Gen1
) {
2676 KdPrint2((PRINT_PREFIX
" SATA SPD < SStatus_SPD_Gen1\n"));
2679 if(SStatus
.IPM
== SStatus_IPM_NoDev
) {
2680 KdPrint2((PRINT_PREFIX
" SATA IPN == SStatus_IPM_NoDev\n"));
2686 } // end UniataAnybodyHome()
2690 IN PVOID HwDeviceExtension
,
2692 IN ULONG deviceNumber
,
2696 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2697 PHW_CHANNEL chan
= &(deviceExtension
->chan
[lChannel
]);
2698 ULONG ldev
= GET_LDEV2(lChannel
, deviceNumber
, 0);
2699 PHW_LU_EXTENSION LunExt
= &(deviceExtension
->lun
[ldev
]);
2706 KdPrint2((PRINT_PREFIX
"CheckDevice: Device %#x\n",
2709 KdPrint2((PRINT_PREFIX
"CheckDevice: reset dev\n"));
2712 AtapiSoftReset(chan
, deviceNumber
);
2714 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, deviceNumber
)) {
2717 statusByte
= WaitOnBusy(chan
);
2719 if((statusByte
| IDE_STATUS_BUSY
) == 0xff) {
2720 KdPrint2((PRINT_PREFIX
2721 "CheckDevice: bad status %x\n", statusByte
));
2723 if(statusByte
!= 0xff && (statusByte
& IDE_STATUS_BUSY
)) {
2724 // Perform hard-reset.
2725 KdPrint2((PRINT_PREFIX
2726 "CheckDevice: BUSY\n"));
2727 GetBaseStatus(chan
, statusByte
);
2730 if((statusByte
| IDE_STATUS_BUSY
) == 0xff) {
2731 KdPrint2((PRINT_PREFIX
2732 "CheckDevice: no dev ?\n"));
2734 if(UniataIsSATARangeAvailable(deviceExtension
, lChannel
)) {
2735 //if(deviceExtension->HwFlags & UNIATA_SATA) {
2736 KdPrint2((PRINT_PREFIX
2737 "CheckDevice: try enable SATA Phy\n"));
2738 statusByte
= UniataSataPhyEnable(HwDeviceExtension
, lChannel
);
2739 if(statusByte
== 0xff) {
2740 KdPrint2((PRINT_PREFIX
"CheckDevice: status %#x (no dev)\n", statusByte
));
2741 UniataForgetDevice(LunExt
);
2746 // Select the device.
2747 SelectDrive(chan
, deviceNumber
);
2749 if(!UniataAnybodyHome(HwDeviceExtension
, lChannel
, deviceNumber
)) {
2753 statusByte
= WaitOnBaseBusyLong(chan
);
2755 GetBaseStatus(chan
, statusByte
);
2756 if(deviceExtension
->HwFlags
& UNIATA_SATA
) {
2757 UniataSataClearErr(HwDeviceExtension
, lChannel
, UNIATA_SATA_IGNORE_CONNECT
);
2760 KdPrint2((PRINT_PREFIX
"CheckDevice: status %#x\n", statusByte
));
2761 if(((statusByte
| IDE_STATUS_BUSY
) == 0xff) ||
2762 (statusByte
& IDE_STATUS_BUSY
)) {
2763 KdPrint2((PRINT_PREFIX
"CheckDevice: busy => return\n"));
2764 UniataForgetDevice(LunExt
);
2768 // set default costs
2769 LunExt
->RwSwitchCost
= REORDER_COST_SWITCH_RW_HDD
;
2770 LunExt
->RwSwitchMCost
= REORDER_MCOST_SWITCH_RW_HDD
;
2771 LunExt
->SeekBackMCost
= REORDER_MCOST_SEEK_BACK_HDD
;
2773 signatureLow
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderLow
);
2774 signatureHigh
= AtapiReadPort1(chan
, IDX_IO1_i_CylinderHigh
);
2776 if (signatureLow
== ATAPI_MAGIC_LSB
&& signatureHigh
== ATAPI_MAGIC_MSB
) {
2778 KdPrint2((PRINT_PREFIX
"CheckDevice: ATAPI signature found\n"));
2779 // ATAPI signature found.
2780 // Issue the ATAPI identify command if this
2781 // is not for the crash dump utility.
2783 if (!deviceExtension
->DriverMustPoll
) {
2785 // Issue ATAPI packet identify command.
2786 if (IssueIdentify(HwDeviceExtension
,
2789 IDE_COMMAND_ATAPI_IDENTIFY
, FALSE
)) {
2791 // Indicate ATAPI device.
2792 KdPrint2((PRINT_PREFIX
"CheckDevice: Device %#x is ATAPI\n",
2795 RetVal
= DFLAGS_DEVICE_PRESENT
| DFLAGS_ATAPI_DEVICE
;
2796 LunExt
->DeviceFlags
|= (DFLAGS_DEVICE_PRESENT
| DFLAGS_ATAPI_DEVICE
);
2798 // some ATAPI devices doesn't work with DPC on CMD-649
2799 // and probably some other controllers
2800 if(deviceExtension
->HwFlags
& UNIATA_NO_DPC_ATAPI
) {
2801 /* CMD 649, ROSB SWK33, ICH4 */
2802 KdPrint2((PRINT_PREFIX
"CheckDevice: UNIATA_NO_DPC_ATAPI\n"));
2803 deviceExtension
->UseDpc
= FALSE
;
2806 GetStatus(chan
, statusByte
);
2807 if (statusByte
& IDE_STATUS_ERROR
) {
2808 AtapiSoftReset(chan
, deviceNumber
);
2813 // Indicate no working device.
2814 KdPrint2((PRINT_PREFIX
"CheckDevice: Device %#x not responding\n",
2817 UniataForgetDevice(LunExt
);
2820 GetBaseStatus(chan
, statusByte
);
2826 KdPrint2((PRINT_PREFIX
"CheckDevice: IDE device check\n"));
2827 // Issue IDE Identify. If an Atapi device is actually present, the signature
2828 // will be asserted, and the drive will be recognized as such.
2829 if(deviceExtension
->DWordIO
) {
2830 KdPrint2((PRINT_PREFIX
" try 32bit IO\n"));
2831 LunExt
->DeviceFlags
|= DFLAGS_DWORDIO_ENABLED
;
2833 if (IssueIdentify(HwDeviceExtension
,
2836 IDE_COMMAND_IDENTIFY
, FALSE
)) {
2839 KdPrint2((PRINT_PREFIX
"CheckDevice: Device %#x is IDE\n",
2842 // Indicate IDE - not ATAPI device.
2843 RetVal
= DFLAGS_DEVICE_PRESENT
;
2844 LunExt
->DeviceFlags
|= DFLAGS_DEVICE_PRESENT
;
2845 LunExt
->DeviceFlags
&= ~DFLAGS_ATAPI_DEVICE
;
2847 GetBaseStatus(chan
, statusByte
);
2849 KdPrint2((PRINT_PREFIX
"CheckDevice: check status: %sfound\n", RetVal
? "" : "not "));
2851 } // end CheckDevice()
2856 Routine Description:
2858 This routine is called from AtapiFindController to identify
2859 devices attached to an IDE controller.
2863 HwDeviceExtension - HBA miniport driver's adapter data storage
2864 AtapiOnly - Indicates that routine should return TRUE only if
2865 an ATAPI device is attached to the controller.
2869 TRUE - True if devices found.
2874 IN PVOID HwDeviceExtension
,
2879 PHW_DEVICE_EXTENSION deviceExtension
= (PHW_DEVICE_EXTENSION
)HwDeviceExtension
;
2880 PHW_CHANNEL chan
= &(deviceExtension
->chan
[Channel
]);
2881 PHW_LU_EXTENSION LunExt
;
2882 BOOLEAN deviceResponded
= FALSE
,
2883 skipSetParameters
= FALSE
;
2884 ULONG waitCount
= 10000;
2885 //ULONG deviceNumber;
2890 BOOLEAN AtapiOnly
= FALSE
;
2892 KdPrint2((PRINT_PREFIX
"FindDevices:\n"));
2894 // Disable interrupts
2895 AtapiDisableInterrupts(deviceExtension
, Channel
);
2896 // AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_DISABLE_INTERRUPTS | IDE_DC_A_4BIT );
2898 // Clear expecting interrupt flag and current SRB field.
2899 chan
->ExpectingInterrupt
= FALSE
;
2900 // chan->CurrentSrb = NULL;
2901 max_ldev
= (chan
->ChannelCtrlFlags
& CTRFLAGS_NO_SLAVE
) ? 1 : 2;
2902 KdPrint2((PRINT_PREFIX
" max_ldev %d\n", max_ldev
));
2904 // Search for devices.
2905 for (i
= 0; i
< max_ldev
; i
++) {
2906 AtapiDisableInterrupts(deviceExtension
, Channel
);
2907 if(Flags
& UNIATA_FIND_DEV_UNHIDE
) {
2908 ldev
= GET_LDEV2(Channel
, i
, 0);
2909 deviceExtension
->lun
[ldev
].DeviceFlags
&= ~DFLAGS_HIDDEN
;
2912 (CheckDevice(HwDeviceExtension
, Channel
, i
, TRUE
) != 0);
2913 AtapiEnableInterrupts(deviceExtension
, Channel
);
2916 for (i
= 0; i
< max_ldev
; i
++) {
2917 ldev
= GET_LDEV2(Channel
, i
, 0);
2918 LunExt
= &(deviceExtension
->lun
[ldev
]);
2920 if (( LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
) &&
2921 !(LunExt
->DeviceFlags
& DFLAGS_LBA_ENABLED
) &&
2922 !(LunExt
->DeviceFlags
& DFLAGS_ATAPI_DEVICE
) && deviceResponded
) {
2924 // This hideous hack is to deal with ESDI devices that return
2925 // garbage geometry in the IDENTIFY data.
2926 // This is ONLY for the crashdump environment as
2927 // these are ESDI devices.
2928 if (LunExt
->IdentifyData
.SectorsPerTrack
==
2930 LunExt
->IdentifyData
.NumberOfHeads
==
2933 KdPrint2((PRINT_PREFIX
2934 "FindDevices: Found nasty Compaq ESDI!\n"));
2936 // Change these values to something reasonable.
2937 LunExt
->IdentifyData
.SectorsPerTrack
=
2939 LunExt
->IdentifyData
.NumberOfHeads
=
2943 if (LunExt
->IdentifyData
.SectorsPerTrack
==
2945 LunExt
->IdentifyData
.NumberOfHeads
==
2948 KdPrint2((PRINT_PREFIX
2949 "FindDevices: Found nasty Compaq ESDI!\n"));
2951 // Change these values to something reasonable.
2952 LunExt
->IdentifyData
.SectorsPerTrack
=
2954 LunExt
->IdentifyData
.NumberOfHeads
=
2959 if (LunExt
->IdentifyData
.SectorsPerTrack
==
2961 LunExt
->IdentifyData
.NumberOfHeads
==
2964 KdPrint2((PRINT_PREFIX
"FindDevices: Found nasty UltraStor ESDI!\n"));
2966 // Change these values to something reasonable.
2967 LunExt
->IdentifyData
.SectorsPerTrack
=
2969 LunExt
->IdentifyData
.NumberOfHeads
=
2971 skipSetParameters
= TRUE
;
2975 if (skipSetParameters
)
2978 statusByte
= WaitOnBusy(chan
);
2980 // Select the device.
2981 SelectDrive(chan
, i
& 0x01);
2982 GetStatus(chan
, statusByte
);
2984 if (statusByte
& IDE_STATUS_ERROR
) {
2986 // Reset the device.
2987 KdPrint2((PRINT_PREFIX
2988 "FindDevices: Resetting controller before SetDriveParameters.\n"));
2990 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_RESET_CONTROLLER
);
2991 AtapiStallExecution(500 * 1000);
2992 AtapiWritePort1(chan
, IDX_IO2_o_Control
, IDE_DC_REENABLE_CONTROLLER
);
2993 SelectDrive(chan
, i
& 0x01);
2996 // Wait for Busy to drop.
2997 AtapiStallExecution(100);
2998 GetStatus(chan
, statusByte
);
3000 } while ((statusByte
& IDE_STATUS_BUSY
) && waitCount
--);
3003 statusByte
= WaitOnBusy(chan
);
3005 KdPrint2((PRINT_PREFIX
3006 "FindDevices: Status before SetDriveParameters: (%#x) (%#x)\n",
3008 AtapiReadPort1(chan
, IDX_IO1_i_DriveSelect
)));
3010 GetBaseStatus(chan
, statusByte
);
3012 // Use the IDENTIFY data to set drive parameters.
3013 if (!SetDriveParameters(HwDeviceExtension
,i
,Channel
)) {
3015 KdPrint2((PRINT_PREFIX
3016 "FindDevices: Set drive parameters for device %d failed\n",
3018 // Don't use this device as writes could cause corruption.
3019 LunExt
->DeviceFlags
&= ~DFLAGS_DEVICE_PRESENT
;
3020 UniataForgetDevice(&(deviceExtension
->lun
[ldev
]));
3024 if (LunExt
->DeviceFlags
& DFLAGS_REMOVABLE_DRIVE
) {
3026 // Pick up ALL IDE removable drives that conform to Yosemite V0.2...
3030 // Indicate that a device was found.
3032 deviceResponded
= TRUE
;
3037 /* // Reset the controller. This is a feeble attempt to leave the ESDI
3038 // controllers in a state that ATDISK driver will recognize them.
3039 // The problem in ATDISK has to do with timings as it is not reproducible
3040 // in debug. The reset should restore the controller to its poweron state
3041 // and give the system enough time to settle.
3042 if (!deviceResponded) {
3044 AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_RESET_CONTROLLER );
3045 AtapiStallExecution(50 * 1000);
3046 AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_REENABLE_CONTROLLER);
3049 if(deviceResponded
) {
3050 for (i
= 0; i
< max_ldev
; i
++) {
3051 ldev
= GET_LDEV2(Channel
, i
, 0);
3052 LunExt
= &(deviceExtension
->lun
[ldev
]);
3054 KdPrint2((PRINT_PREFIX
3055 "FindDevices: select %d dev to clear INTR\n", i
));
3056 SelectDrive(chan
, i
);
3057 GetBaseStatus(chan
, statusByte
);
3058 KdPrint2((PRINT_PREFIX
3059 "FindDevices: statusByte=%#x\n", statusByte
));
3061 for (i
= 0; i
< max_ldev
; i
++) {
3062 ldev
= GET_LDEV2(Channel
, i
, 0);
3063 LunExt
= &(deviceExtension
->lun
[ldev
]);
3065 if(LunExt
->DeviceFlags
& DFLAGS_DEVICE_PRESENT
) {
3066 // Make sure some device (master is preferred) is selected on exit.
3067 KdPrint2((PRINT_PREFIX
3068 "FindDevices: select %d dev on exit\n", i
));
3069 SelectDrive(chan
, i
);
3075 GetBaseStatus(chan
, statusByte
);
3076 // Enable interrupts
3077 AtapiEnableInterrupts(deviceExtension
, Channel
);
3078 // AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_A_4BIT );
3079 GetBaseStatus(chan
, statusByte
);
3081 KdPrint2((PRINT_PREFIX
3082 "FindDevices: returning %d\n",
3085 return deviceResponded
;
3087 } // end FindDevices()