ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

id_probe.cpp
Go to the documentation of this file.
00001 /*++
00002 
00003 Copyright (c) 2002-2011 Alexandr A. Telyatnikov (Alter)
00004 
00005 Module Name:
00006     id_probe.cpp
00007 
00008 Abstract:
00009     This module scans PCI and ISA buses for IDE controllers
00010     and determines their Busmaster DMA capabilities
00011 
00012 Author:
00013     Alexander A. Telyatnikov (Alter)
00014 
00015 Environment:
00016     kernel mode only
00017 
00018 Notes:
00019 
00020     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00021     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00022     OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00023     IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00024     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00025     NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00026     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00027     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00028     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00029     THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 
00031 Revision History:
00032 
00033     Some parts of hardware-specific code were taken from FreeBSD 4.3-6.1 ATA driver by
00034          Søren Schmidt, Copyright (c) 1998-2007
00035 
00036     Some parts of device detection code were taken from from standard ATAPI.SYS from NT4 DDK by
00037          Mike Glass (MGlass)
00038          Chuck Park (ChuckP)
00039 
00040     Device search/init algorithm is completly rewritten by
00041          Alter, Copyright (c) 2002-2004
00042 
00043     Fixes for Native/Compatible modes of onboard IDE controller by
00044          Vitaliy Vorobyov, deathsoft@yandex.ru (c) 2004
00045 
00046 --*/
00047 
00048 #include "stdafx.h"
00049 
00050 PBUSMASTER_CONTROLLER_INFORMATION BMList = NULL;
00051 ULONG         BMListLen = 0;
00052 ULONG         IsaCount = 0;
00053 ULONG         MCACount = 0;
00054 
00055 BOOLEAN FirstMasterOk = FALSE;
00056 
00057 #ifndef UNIATA_CORE
00058 
00059 UCHAR         pciBuffer[256];
00060 ULONG         maxPciBus = 16;
00061 
00062 PDRIVER_OBJECT SavedDriverObject = NULL;
00063 
00064 // local routines 
00065 
00066 ULONG
00067 NTAPI
00068 UniataEnumBusMasterController__(
00069 /*    IN PVOID HwDeviceExtension,
00070     IN PVOID Context,
00071     IN PVOID BusInformation,
00072     IN PCHAR ArgumentString,
00073     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
00074     OUT PBOOLEAN Again*/
00075     );
00076 
00077 VOID
00078 NTAPI
00079 AtapiDoNothing(VOID)
00080 {
00081     return;
00082 } // end AtapiDoNothing()
00083 
00084 #endif //UNIATA_CORE
00085 
00086 /*
00087     Get PCI address by ConfigInfo and RID
00088 */
00089 ULONG
00090 NTAPI
00091 AtapiGetIoRange(
00092     IN PVOID HwDeviceExtension,
00093     IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
00094     IN PPCI_COMMON_CONFIG pciData,
00095     IN ULONG SystemIoBusNumber,
00096     IN ULONG rid,   //range id
00097     IN ULONG offset,
00098     IN ULONG length
00099     )
00100 {
00101     ULONGIO_PTR io_start = 0;
00102     KdPrint2((PRINT_PREFIX "  AtapiGetIoRange:\n"));
00103 
00104     if(ConfigInfo->NumberOfAccessRanges <= rid)
00105         return 0;
00106 
00107     KdPrint2((PRINT_PREFIX "  AtapiGetIoRange: rid %#x, start %#x, offs %#x, len %#x, mem %#x\n",
00108         rid,
00109         ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[rid].RangeStart),
00110         offset,
00111         length,
00112         (*ConfigInfo->AccessRanges)[rid].RangeInMemory
00113         ));
00114 
00115     if((*ConfigInfo->AccessRanges)[rid].RangeInMemory) {
00116         io_start =
00117             // Get the system physical address for this IO range.
00118             ((ULONG_PTR)ScsiPortGetDeviceBase(HwDeviceExtension,
00119                         PCIBus /*ConfigInfo->AdapterInterfaceType*/,
00120                         SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/,
00121                         ScsiPortConvertUlongToPhysicalAddress(
00122                             (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[rid].RangeStart) &
00123                             ~0x07/*PCI_ADDRESS_IOMASK*/) + offset
00124                                                              ),
00125                         length,
00126                         (BOOLEAN)!(*ConfigInfo->AccessRanges)[rid].RangeInMemory)
00127                                );
00128 
00129         KdPrint2((PRINT_PREFIX "  AtapiGetIoRange: %#x\n", io_start));
00130    //     if(io_start > offset) {
00131             return io_start;
00132    //     }
00133     }
00134 
00135     io_start = (pciData->u.type0.BaseAddresses[rid] & ~0x07/*PCI_ADDRESS_IOMASK*/) + offset;
00136     // if(pciData->u.type0.BaseAddresses[rid] != 0) ;)
00137     if(io_start > offset) {
00138         if(/*(WinVer_Id() <= WinVer_NT) &&*/ offset && rid == 4) {
00139             // MS atapi.sys does so for BusMaster controllers
00140             (*ConfigInfo->AccessRanges)[rid+1].RangeStart =
00141                 ScsiPortConvertUlongToPhysicalAddress(io_start);
00142             (*ConfigInfo->AccessRanges)[rid+1].RangeLength = length;
00143         } else {
00144             (*ConfigInfo->AccessRanges)[rid].RangeStart =
00145                 ScsiPortConvertUlongToPhysicalAddress(io_start);
00146             (*ConfigInfo->AccessRanges)[rid].RangeLength = length;
00147         }
00148         if((pciData->u.type0.BaseAddresses[rid] & PCI_ADDRESS_IO_SPACE)) {
00149             (*ConfigInfo->AccessRanges)[rid].RangeInMemory = FALSE;
00150         } else {
00151             (*ConfigInfo->AccessRanges)[rid].RangeInMemory = TRUE;
00152         }
00153     } else {
00154         io_start = 0;
00155     }
00156     KdPrint2((PRINT_PREFIX "  AtapiGetIoRange: (2) %#x\n", io_start));
00157     return io_start;
00158 
00159 } // end AtapiGetIoRange()
00160 
00161 #ifndef UNIATA_CORE
00162 
00163 /*
00164     Do nothing, but build list of supported IDE controllers
00165     It is a hack, ScsiPort architecture assumes, that DriverEntry
00166     can support only KNOWN Vendor/Device combinations.
00167     Thus, we build list here. Later will pretend that always knew
00168     about found devices.
00169 
00170     We shall initiate ISA device init, but callback will use
00171     Hal routines directly in order to scan PCI bus.
00172 */
00173 VOID
00174 NTAPI
00175 UniataEnumBusMasterController(
00176     IN PVOID DriverObject,
00177     PVOID Argument2
00178     )
00179 {
00180     UniataEnumBusMasterController__();
00181 
00182 } // end UniataEnumBusMasterController()
00183 
00184 BOOLEAN
00185 NTAPI
00186 UniataCheckPCISubclass(
00187     BOOLEAN known,
00188     ULONG   RaidFlags,
00189     UCHAR   SubClass
00190     )
00191 {
00192     if(known) {
00193         if((RaidFlags & UNIATA_RAID_CONTROLLER) &&
00194             SkipRaids) {
00195             KdPrint2((PRINT_PREFIX "Skip RAID\n"));
00196             return FALSE;
00197         }
00198         return TRUE;
00199     }
00200     KdPrint2((PRINT_PREFIX "unknown\n"));
00201 
00202     switch(SubClass) {
00203     case PCI_DEV_SUBCLASS_RAID:
00204         if(SkipRaids) {
00205             KdPrint2((PRINT_PREFIX "Skip RAID (2)\n"));
00206             return FALSE;
00207         }
00208         break;
00209     case PCI_DEV_SUBCLASS_IDE:
00210     case PCI_DEV_SUBCLASS_ATA:
00211         break;
00212     case PCI_DEV_SUBCLASS_SATA:
00213         break;
00214     default:
00215         KdPrint2((PRINT_PREFIX "Subclass not supported\n"));
00216         return FALSE;
00217     }
00218     return TRUE;
00219 } // end UniataCheckPCISubclass()
00220 
00221 /*
00222     Device initializaton callback
00223     Builds PCI device list using Hal routines (not ScsiPort wrappers)
00224 */
00225 ULONG
00226 NTAPI
00227 UniataEnumBusMasterController__(
00228     )
00229 {
00230 //    PHW_DEVICE_EXTENSION  deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
00231     PVOID HwDeviceExtension;
00232     PHW_DEVICE_EXTENSION  deviceExtension = NULL;
00233     PCI_SLOT_NUMBER       slotData;
00234     PCI_COMMON_CONFIG     pciData;
00235     ULONG                 busNumber;
00236     ULONG                 slotNumber;
00237     ULONG                 funcNumber;
00238     BOOLEAN               no_buses = FALSE;
00239     BOOLEAN               no_ranges = FALSE;
00240     ULONG                 busDataRead;
00241 //    BOOLEAN               SimplexOnly;
00242 
00243     UCHAR                 vendorString[5];
00244     UCHAR                 deviceString[5];
00245     PUCHAR                vendorStrPtr;
00246     PUCHAR                deviceStrPtr;
00247 
00248     UCHAR   BaseClass;                  // (ro)
00249     UCHAR   SubClass;                   // (ro)
00250     ULONG   VendorID;
00251     ULONG   DeviceID;
00252     ULONG   dev_id;
00253 
00254     USHORT  SubVendorID;
00255     USHORT  SubSystemID;
00256 
00257     ULONG   i;
00258     ULONG   pass=0;
00259 
00260     ULONG   RaidFlags;
00261 
00262     BOOLEAN found;
00263     BOOLEAN known;
00264     BOOLEAN NeedPciAltInit;
00265 
00266     UCHAR IrqForCompat = 10;
00267 
00268     vendorStrPtr = vendorString;
00269     deviceStrPtr = deviceString;
00270     slotData.u.AsULONG = 0;
00271 
00272     HwDeviceExtension =
00273     deviceExtension = (PHW_DEVICE_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(HW_DEVICE_EXTENSION));
00274     if(!deviceExtension) {
00275         return(SP_RETURN_NOT_FOUND);
00276     }
00277     RtlZeroMemory(deviceExtension, sizeof(HW_DEVICE_EXTENSION));
00278 
00279     for(pass=0; pass<3; pass++) {
00280         for(busNumber=0 ;busNumber<maxPciBus && !no_buses; busNumber++) {
00281             for(slotNumber=0; slotNumber<PCI_MAX_DEVICES  && !no_buses; slotNumber++) {
00282             NeedPciAltInit = FALSE;
00283             for(funcNumber=0; funcNumber<PCI_MAX_FUNCTION && !no_buses; funcNumber++) {
00284 
00285 //                KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x\n",busNumber,slotNumber,funcNumber));
00286                 slotData.u.bits.DeviceNumber   = slotNumber;
00287                 slotData.u.bits.FunctionNumber = funcNumber;
00288 
00289                 busDataRead = HalGetBusData
00290                               //ScsiPortGetBusData
00291                                            (
00292                                             //HwDeviceExtension,
00293                                             PCIConfiguration, busNumber, slotData.u.AsULONG,
00294                                             &pciData, PCI_COMMON_HDR_LENGTH);
00295                 // no more buses
00296                 if(!busDataRead) {
00297                     no_buses = TRUE;
00298                     maxPciBus = busNumber;
00299                     break;
00300                 }
00301                 // no device in this slot
00302                 if(busDataRead == 2) {
00303                     NeedPciAltInit = TRUE;
00304                     continue;
00305                 }
00306 
00307                 if(busDataRead < (ULONG)PCI_COMMON_HDR_LENGTH) {
00308                     NeedPciAltInit = TRUE;
00309                     continue;
00310                 }
00311 
00312                 VendorID  = pciData.VendorID;
00313                 DeviceID  = pciData.DeviceID;
00314                 BaseClass = pciData.BaseClass;
00315                 SubClass  = pciData.SubClass;
00316                 dev_id = VendorID | (DeviceID << 16);
00317 
00318                 SubVendorID = pciData.u.type0.SubVendorID;
00319                 SubSystemID = pciData.u.type0.SubSystemID;
00320 
00321 
00322                 //KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
00323 
00324                 if(VendorID == 0x80ee && DeviceID == 0xcafe) {
00325                     KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - VirtualBox Guest Service\n",busNumber,slotNumber,funcNumber));
00326                     if(g_opt_VirtualMachine == VM_AUTO) {
00327                         g_opt_VirtualMachine = VM_VBOX;
00328                     }
00329                     //continue;
00330                 } else
00331                 if((VendorID == 0x15ad) ||
00332                    (SubVendorID == 0x15ad && SubSystemID == 0x1976)) {
00333                     KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - VMWare\n",busNumber,slotNumber,funcNumber));
00334                     if(g_opt_VirtualMachine == VM_AUTO) {
00335                         g_opt_VirtualMachine = VM_VMWARE;
00336                     }
00337                     //g_opt_VirtualBox = TRUE;
00338                 } else
00339                 if(SubVendorID == 0x1af4 && SubSystemID == 0x1100) {
00340                     KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x - QEmu\n",busNumber,slotNumber,funcNumber));
00341                     if(g_opt_VirtualMachine == VM_AUTO) {
00342                         g_opt_VirtualMachine = VM_QEMU;
00343                     }
00344                 }
00345 
00346 
00347                 if(BaseClass != PCI_DEV_CLASS_STORAGE) {
00348                     continue;
00349                 }
00350 
00351                 KdPrint2((PRINT_PREFIX "-- BusID: %#x:%#x:%#x\n",busNumber,slotNumber,funcNumber));
00352                 KdPrint2((PRINT_PREFIX "Storage Class\n"));
00353                 KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
00354                 // look for known chipsets
00355                 found = FALSE;
00356                 known = FALSE;
00357 
00358                 if(deviceExtension) {
00359                     deviceExtension->slotNumber = slotData.u.AsULONG;
00360                     deviceExtension->SystemIoBusNumber = busNumber;
00361                     deviceExtension->DevID = dev_id;
00362                     deviceExtension->RevID = pciData.RevisionID;
00363                     deviceExtension->AdapterInterfaceType = PCIBus;
00364                 }
00365 
00366                 found = (BOOLEAN)AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"Include", 0);
00367                 if(!found) {
00368                     KdPrint2((PRINT_PREFIX "No force include, check exclude\n"));
00369                     found = !AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"Exclude", 0);
00370                     if(!found) {
00371                         KdPrint2((PRINT_PREFIX "Device excluded\n"));
00372                         continue;
00373                     }
00374                 }
00375 
00376                 //known = UniataChipDetect(HwDeviceExtension, NULL, -1, ConfigInfo, &SimplexOnly);
00377                 i = Ata_is_dev_listed((PBUSMASTER_CONTROLLER_INFORMATION)&BusMasterAdapters[0], VendorID, DeviceID, 0, NUM_BUSMASTER_ADAPTERS);
00378 
00379                 known = (i != BMLIST_TERMINATOR);
00380                 if(known) {
00381                     deviceExtension->FullDevName = BusMasterAdapters[i].FullDevName;
00382                     RaidFlags = BusMasterAdapters[i].RaidFlags;
00383                 } else {
00384                     deviceExtension->FullDevName = "Unknown Storage";
00385                     RaidFlags = 0;
00386                 }
00387                 found = UniataCheckPCISubclass(known, RaidFlags, SubClass);
00388                 if(!found) {
00389                     KdPrint2((PRINT_PREFIX "Subclass not supported\n"));
00390                     continue;
00391                 }
00392 
00393                 switch(dev_id) {
00394                 /* additional checks for some supported chipsets */
00395                 case 0xc6931080:
00396                     if (SubClass != PCI_DEV_SUBCLASS_IDE)
00397                         found = FALSE;
00398                     break;
00399 
00400                 /* unknown chipsets, try generic DMA if it seems possible */
00401                 default:
00402                     KdPrint2((PRINT_PREFIX "Default device\n"));
00403                     if(Ata_is_supported_dev(&pciData) ||
00404                        Ata_is_ahci_dev(&pciData))
00405                         found = TRUE;
00406                     break;
00407                 }
00408 
00409                 if(found) {
00410 
00411                     KdPrint2((PRINT_PREFIX "found, pass %d\n", pass));
00412 
00413                     KdPrint2((PRINT_PREFIX "InterruptPin = %#x\n", pciData.u.type0.InterruptPin));
00414                     KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData.u.type0.InterruptLine));
00415 
00416                     if(!pass && known) {
00417                         // Enable Busmastering, IO-space and Mem-space
00418                         KdPrint2((PRINT_PREFIX "Enabling Mem/Io spaces and busmastering...\n"));
00419                         KdPrint2((PRINT_PREFIX "Initial pciData.Command = %#x\n", pciData.Command));
00420                         for(i=0; i<3; i++) {
00421                             switch(i) {
00422                             case 0:
00423                                 KdPrint2((PRINT_PREFIX "PCI_ENABLE_IO_SPACE\n"));
00424                                 pciData.Command |= PCI_ENABLE_IO_SPACE;
00425                                 break;
00426                             case 1:
00427                                 KdPrint2((PRINT_PREFIX "PCI_ENABLE_MEMORY_SPACE\n"));
00428                                 pciData.Command |= PCI_ENABLE_MEMORY_SPACE;
00429                                 break;
00430                             case 2:
00431                                 KdPrint2((PRINT_PREFIX "PCI_ENABLE_BUS_MASTER\n"));
00432                                 pciData.Command |= PCI_ENABLE_BUS_MASTER;
00433                                 break;
00434                             }
00435                             HalSetBusDataByOffset(  PCIConfiguration, busNumber, slotData.u.AsULONG,
00436                                                     &(pciData.Command),
00437                                                     offsetof(PCI_COMMON_CONFIG, Command),
00438                                                     sizeof(pciData.Command));
00439                             KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData.u.type0.InterruptLine));
00440 
00441                             // reread config space
00442                             busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotData.u.AsULONG,
00443                                                         &pciData, PCI_COMMON_HDR_LENGTH);
00444                             KdPrint2((PRINT_PREFIX "New pciData.Command = %#x\n", pciData.Command));
00445                         }
00446                         KdPrint2((PRINT_PREFIX "Final pciData.Command = %#x\n", pciData.Command));
00447                     }
00448                     // validate Mem/Io ranges
00449                     no_ranges = TRUE;
00450                     for(i=0; i<PCI_TYPE0_ADDRESSES; i++) {
00451                         if(pciData.u.type0.BaseAddresses[i] & ~0x7) {
00452                             no_ranges = FALSE;
00453                             //break;
00454                             KdPrint2((PRINT_PREFIX "Range %d = %#x\n", i, pciData.u.type0.BaseAddresses[i]));
00455                         }
00456                     }
00457                     if(no_ranges) {
00458                         KdPrint2((PRINT_PREFIX "No PCI Mem/Io ranges found on device, skip it\n"));
00459                         continue;
00460                     }
00461 
00462                     if(pass) {
00463                         // fill list of detected devices
00464                         // it'll be used for further init
00465                         KdPrint2((PRINT_PREFIX "found suitable device\n"));
00466                         PBUSMASTER_CONTROLLER_INFORMATION newBMListPtr = BMList+BMListLen;
00467 
00468                         if(pass == 1) {
00469                             if(!IsMasterDev(&pciData)) {
00470                                 continue;
00471                             }
00472                             if(AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"NativePCIMode", 0)) {
00473                                 KdPrint2((PRINT_PREFIX "try switch to native mode\n"));
00474 
00475                                 IrqForCompat = (UCHAR)AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"NativePCIModeIRQ", 0xff);
00476                                 KdPrint2((PRINT_PREFIX "IrqForCompat = %#x\n", IrqForCompat));
00477                                 if((IrqForCompat & 0xffffff00) /*||
00478                                    (IrqForCompat & 0xff) > 31*/ ||
00479                                    (IrqForCompat == 0xff)) {
00480                                     IrqForCompat = 0x0b;
00481                                     KdPrint2((PRINT_PREFIX "default to IRQ 11\n"));
00482                                 }
00483 
00484                                 //ChangePciConfig1(0x09, a | PCI_IDE_PROGIF_NATIVE_ALL); // ProgIf
00485                                 pciData.ProgIf |= PCI_IDE_PROGIF_NATIVE_ALL;
00486                                 HalSetBusDataByOffset(  PCIConfiguration, busNumber, slotData.u.AsULONG,
00487                                                         &(pciData.ProgIf),
00488                                                         offsetof(PCI_COMMON_CONFIG, ProgIf),
00489                                                         sizeof(pciData.ProgIf));
00490 
00491                                 // reread config space
00492                                 busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotData.u.AsULONG,
00493                                                             &pciData, PCI_COMMON_HDR_LENGTH);
00494                                 // check if the device have switched to Native Mode
00495                                 if(IsMasterDev(&pciData)) {
00496                                     KdPrint2((PRINT_PREFIX "Can't switch to native mode\n"));
00497                                 } else {
00498                                     KdPrint2((PRINT_PREFIX "switched to native mode\n"));
00499                                     KdPrint2((PRINT_PREFIX "InterruptPin = %#x\n", pciData.u.type0.InterruptPin));
00500                                     KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData.u.type0.InterruptLine));
00501                                     // check if IRQ is assigned to device
00502                                     if(!(pciData.u.type0.InterruptLine) ||
00503                                         (pciData.u.type0.InterruptLine == 0xff)) {
00504                                         KdPrint2((PRINT_PREFIX "assign interrupt for device\n"));
00505                                         pciData.u.type0.InterruptLine = IrqForCompat;
00506                                         HalSetBusDataByOffset(  PCIConfiguration, busNumber, slotData.u.AsULONG,
00507                                                                 &(pciData.u.type0.InterruptLine),
00508                                                                 offsetof(PCI_COMMON_CONFIG, u.type0.InterruptLine),
00509                                                                 sizeof(pciData.u.type0.InterruptLine));
00510                                     } else {
00511                                         KdPrint2((PRINT_PREFIX "Auto-assigned interrupt line %#x\n",
00512                                             pciData.u.type0.InterruptLine));
00513                                         IrqForCompat = pciData.u.type0.InterruptLine;
00514                                     }
00515                                     KdPrint2((PRINT_PREFIX "reread config space\n"));
00516                                     // reread config space
00517                                     busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotData.u.AsULONG,
00518                                                                 &pciData, PCI_COMMON_HDR_LENGTH);
00519                                     KdPrint2((PRINT_PREFIX "busDataRead = %#x\n", busDataRead));
00520                                     KdPrint2((PRINT_PREFIX "reread InterruptLine = %#x\n", pciData.u.type0.InterruptLine));
00521                                     // check if we have successfully assigned IRQ to device
00522                                     if((pciData.u.type0.InterruptLine != IrqForCompat) ||
00523                                        (pciData.u.type0.InterruptLine == 0xff) ||
00524                                        !pciData.u.type0.InterruptLine) {
00525                                         KdPrint2((PRINT_PREFIX "can't assign interrupt for device, revert to compat mode\n"));
00526                                         pciData.u.type0.InterruptLine = 0xff;
00527                                         KdPrint2((PRINT_PREFIX "set IntrLine to 0xff\n"));
00528                                         HalSetBusDataByOffset(  PCIConfiguration, busNumber, slotData.u.AsULONG,
00529                                                                 &(pciData.u.type0.InterruptLine),
00530                                                                 offsetof(PCI_COMMON_CONFIG, u.type0.InterruptLine),
00531                                                                 sizeof(pciData.u.type0.InterruptLine));
00532                                         KdPrint2((PRINT_PREFIX "clear PCI_IDE_PROGIF_NATIVE_ALL\n"));
00533                                         pciData.ProgIf &= ~PCI_IDE_PROGIF_NATIVE_ALL;
00534                                         HalSetBusDataByOffset(  PCIConfiguration, busNumber, slotData.u.AsULONG,
00535                                                                 &(pciData.ProgIf),
00536                                                                 offsetof(PCI_COMMON_CONFIG, ProgIf),
00537                                                                 sizeof(pciData.ProgIf));
00538                                         // reread config space
00539                                         KdPrint2((PRINT_PREFIX "reread config space on revert\n"));
00540                                         busDataRead = HalGetBusData(PCIConfiguration, busNumber, slotData.u.AsULONG,
00541                                                                     &pciData, PCI_COMMON_HDR_LENGTH);
00542                                     } else {
00543                                         KdPrint2((PRINT_PREFIX "Assigned interrupt %#x for device\n", IrqForCompat));
00544                                         KdPrint2((PRINT_PREFIX "continue detection on next round\n"));
00545                                         continue;
00546                                     }
00547                                 }
00548                             }
00549                         } else
00550                         if(pass == 2) {
00551                             if(IsMasterDev(&pciData))
00552                                 continue;
00553                         }
00554 
00555 /*                        if(known) {
00556                             RtlCopyMemory(newBMListPtr, (PVOID)&(BusMasterAdapters[i]), sizeof(BUSMASTER_CONTROLLER_INFORMATION));
00557                         } else {*/
00558                         sprintf((PCHAR)vendorStrPtr, "%4.4lx", VendorID);
00559                         sprintf((PCHAR)deviceStrPtr, "%4.4lx", DeviceID);
00560 
00561                         RtlCopyMemory(&(newBMListPtr->VendorIdStr), (PCHAR)vendorStrPtr, 4);
00562                         RtlCopyMemory(&(newBMListPtr->DeviceIdStr), (PCHAR)deviceStrPtr, 4);
00563 
00564                         newBMListPtr->nVendorId = VendorID;
00565                         newBMListPtr->VendorId = (PCHAR)&(newBMListPtr->VendorIdStr);
00566                         newBMListPtr->VendorIdLength = 4;
00567                         newBMListPtr->nDeviceId = DeviceID;
00568                         newBMListPtr->DeviceId = (PCHAR)&(newBMListPtr->DeviceIdStr);
00569                         newBMListPtr->DeviceIdLength = 4;
00570 
00571                         newBMListPtr->RaidFlags = RaidFlags;
00572 //                        }
00573                         newBMListPtr->slotNumber = slotData.u.AsULONG;
00574                         newBMListPtr->MasterDev = IsMasterDev(&pciData) ? 1 : 0;
00575                         newBMListPtr->busNumber = busNumber;
00576 
00577                         newBMListPtr->NeedAltInit = NeedPciAltInit;
00578                         newBMListPtr->Known = known;
00579 
00580                         KdPrint2((PRINT_PREFIX "Add to BMList, AltInit %d\n", NeedPciAltInit));
00581                     } else {
00582                         KdPrint2((PRINT_PREFIX "count: BMListLen++\n"));
00583                     }
00584 
00585                     BMListLen++;
00586                 }
00587             }
00588             }
00589         }
00590         if(!pass) {
00591              if(!BMListLen)
00592                  break;
00593              BMList = (PBUSMASTER_CONTROLLER_INFORMATION)ExAllocatePool(NonPagedPool,
00594                                          (BMListLen+1)*sizeof(BUSMASTER_CONTROLLER_INFORMATION));
00595              if(!BMList) {
00596                  BMListLen=0;
00597                  break;
00598              }
00599              RtlZeroMemory(BMList, (BMListLen+1)*sizeof(BUSMASTER_CONTROLLER_INFORMATION));
00600              no_buses = FALSE;
00601              BMListLen=0;
00602         }
00603     }
00604     KdPrint2((PRINT_PREFIX "  BMListLen=%x\n", BMListLen));
00605     if(deviceExtension) {
00606         ExFreePool(deviceExtension);
00607     }
00608     return(SP_RETURN_NOT_FOUND);
00609 } // end UniataEnumBusMasterController__()
00610 
00611 
00612 /*
00613     Wrapper for read PCI config space
00614 */
00615 ULONG
00616 NTAPI
00617 ScsiPortGetBusDataByOffset(
00618     IN PVOID  HwDeviceExtension,
00619     IN BUS_DATA_TYPE  BusDataType,
00620     IN ULONG  BusNumber,
00621     IN ULONG  SlotNumber,
00622     IN PVOID  Buffer,
00623     IN ULONG  Offset,
00624     IN ULONG  Length
00625     )
00626 {
00627     UCHAR tmp[256];
00628     ULONG busDataRead;
00629 
00630     if(Offset+Length > 256)
00631         return 0;
00632 
00633     busDataRead = HalGetBusData(
00634         //ScsiPortGetBusData(HwDeviceExtension,
00635                                      BusDataType,
00636                                      BusNumber,
00637                                      SlotNumber,
00638                                      &tmp,
00639                                      Offset+Length);
00640     if(busDataRead < Offset+Length) {
00641         if(busDataRead < Offset)
00642             return 0;
00643         return (Offset+Length-busDataRead);
00644     }
00645     RtlCopyMemory(Buffer, tmp+Offset, Length);
00646     return Length;
00647 } // end ScsiPortGetBusDataByOffset()
00648 
00649 /*
00650     Looks for devices from list on specified bus(es)/slot(s)
00651     returnts its index in list.
00652     If no matching record found, -1 is returned
00653 */
00654 ULONG
00655 NTAPI
00656 AtapiFindListedDev(
00657     PBUSMASTER_CONTROLLER_INFORMATION BusMasterAdapters,
00658     ULONG     lim,
00659     IN PVOID  HwDeviceExtension,
00660     IN ULONG  BusNumber,
00661     IN ULONG  SlotNumber,
00662     OUT PCI_SLOT_NUMBER* _slotData // optional
00663     )
00664 {
00665     PCI_SLOT_NUMBER       slotData;
00666     PCI_COMMON_CONFIG     pciData;
00667     ULONG                 busDataRead;
00668 
00669     ULONG busNumber;
00670     ULONG slotNumber;
00671     ULONG funcNumber;
00672 
00673     ULONG busNumber2;
00674     ULONG slotNumber2;
00675 
00676     ULONG i;
00677 
00678     KdPrint2((PRINT_PREFIX "AtapiFindListedDev: lim=%x, Bus=%x, Slot=%x\n", lim, BusNumber, SlotNumber));
00679 
00680     // set start/end bus
00681     if(BusNumber == PCIBUSNUM_NOT_SPECIFIED) {
00682         busNumber  = 0;
00683         busNumber2 = maxPciBus;
00684     } else {
00685         busNumber  = BusNumber;
00686         busNumber2 = BusNumber+1;
00687     }
00688     // set start/end slot
00689     if(SlotNumber == PCISLOTNUM_NOT_SPECIFIED) {
00690         slotNumber  = 0;
00691         slotNumber2 = PCI_MAX_DEVICES;
00692     } else {
00693         slotNumber  = SlotNumber;
00694         slotNumber2 = SlotNumber+1;
00695     }
00696     slotData.u.AsULONG = 0;
00697 
00698     KdPrint2((PRINT_PREFIX " scanning range Bus %x-%x, Slot %x-%x\n", busNumber, busNumber2-1, slotNumber, slotNumber2-1));
00699 
00700     for(            ; busNumber  < busNumber2       ; busNumber++ ) {
00701     for(            ; slotNumber < slotNumber2      ; slotNumber++) {
00702     for(funcNumber=0; funcNumber < PCI_MAX_FUNCTION ; funcNumber++) {
00703 
00704         slotData.u.bits.DeviceNumber   = slotNumber;
00705         slotData.u.bits.FunctionNumber = funcNumber;
00706 
00707         busDataRead = HalGetBusData(
00708             //ScsiPortGetBusData(HwDeviceExtension,
00709                                     PCIConfiguration, busNumber, slotData.u.AsULONG, 
00710                                     &pciData, PCI_COMMON_HDR_LENGTH);
00711         // no more buses (this should not happen)
00712         if(!busDataRead) {
00713             continue;
00714         }
00715         // no device in this slot
00716         if(busDataRead == 2)
00717             continue;
00718 
00719         if(busDataRead < (ULONG)PCI_COMMON_HDR_LENGTH)
00720             continue;
00721 /*
00722         KdPrint2((PRINT_PREFIX "AtapiFindListedDev: b:s:f(%x:%x:%x) %4.4x/%4.4x/%2.2x\n",
00723                   busNumber, slotNumber, funcNumber,
00724                   pciData.VendorID, pciData.DeviceID, pciData.RevisionID));
00725                   */
00726         i = Ata_is_dev_listed(BusMasterAdapters, pciData.VendorID, pciData.DeviceID, pciData.RevisionID, lim);
00727         if(i != BMLIST_TERMINATOR) {
00728             if(_slotData)
00729                 *_slotData = slotData;
00730             KdPrint2((PRINT_PREFIX "AtapiFindListedDev: found\n"));
00731             KdPrint2((PRINT_PREFIX "AtapiFindListedDev: b:s:f(%x:%x:%x) %4.4x/%4.4x/%2.2x\n",
00732                       busNumber, slotNumber, funcNumber,
00733                       pciData.VendorID, pciData.DeviceID, pciData.RevisionID));
00734             return i;
00735         }
00736 
00737     }}}
00738     return -1;
00739 } // end AtapiFindListedDev()
00740 
00741 /*
00742     Looks for device with specified Device/Vendor and Revision
00743     on specified Bus/Slot
00744 */
00745 ULONG
00746 NTAPI
00747 AtapiFindDev(
00748     IN PVOID  HwDeviceExtension,
00749     IN BUS_DATA_TYPE  BusDataType,
00750     IN ULONG  BusNumber,
00751     IN ULONG  SlotNumber,
00752     IN ULONG  dev_id,
00753     IN ULONG  RevID
00754     )
00755 {
00756     PCI_COMMON_CONFIG     pciData;
00757     ULONG                 funcNumber;
00758     ULONG                 busDataRead;
00759 
00760     ULONG   VendorID;
00761     ULONG   DeviceID;
00762     PCI_SLOT_NUMBER       slotData;
00763 
00764     slotData.u.AsULONG = SlotNumber;
00765     // walk through all Function Numbers
00766     for(funcNumber = 0; funcNumber < PCI_MAX_FUNCTION; funcNumber++) {
00767 
00768         slotData.u.bits.FunctionNumber = funcNumber;
00769         if(slotData.u.AsULONG == SlotNumber)
00770             continue;
00771 
00772         busDataRead = HalGetBusData(
00773             //busDataRead = ScsiPortGetBusData(HwDeviceExtension,
00774                                          PCIConfiguration,
00775                                          BusNumber,
00776                                          slotData.u.AsULONG,
00777                                          &pciData,
00778                                          PCI_COMMON_HDR_LENGTH);
00779 
00780         if (busDataRead < (ULONG)PCI_COMMON_HDR_LENGTH) {
00781             continue;
00782         }
00783 
00784         VendorID  = pciData.VendorID;
00785         DeviceID  = pciData.DeviceID;
00786 
00787         if(dev_id != (VendorID | (DeviceID << 16)) )
00788             continue;
00789         if(RevID >= pciData.RevisionID)
00790             return 1;
00791     }
00792     return 0;
00793 } // end AtapiFindDev()
00794 
00795 #endif //UNIATA_CORE
00796 
00797 
00798 ULONG
00799 NTAPI
00800 UniataFindCompatBusMasterController1(
00801     IN PVOID HwDeviceExtension,
00802     IN PVOID Context,
00803     IN PVOID BusInformation,
00804     IN PCHAR ArgumentString,
00805     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
00806     OUT PBOOLEAN Again
00807     )
00808 {
00809     return UniataFindBusMasterController(
00810         HwDeviceExtension,
00811         (PVOID)0x00000000,
00812         BusInformation,
00813         ArgumentString,
00814         ConfigInfo,
00815         Again
00816         );
00817 } // end UniataFindCompatBusMasterController1()
00818 
00819 ULONG
00820 NTAPI
00821 UniataFindCompatBusMasterController2(
00822     IN PVOID HwDeviceExtension,
00823     IN PVOID Context,
00824     IN PVOID BusInformation,
00825     IN PCHAR ArgumentString,
00826     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
00827     OUT PBOOLEAN Again
00828     )
00829 {
00830     return UniataFindBusMasterController(
00831         HwDeviceExtension,
00832         (PVOID)0x80000000,
00833         BusInformation,
00834         ArgumentString,
00835         ConfigInfo,
00836         Again
00837         );
00838 } // end UniataFindCompatBusMasterController2()
00839 
00840 BOOLEAN
00841 NTAPI
00842 UniataAllocateLunExt(
00843     PHW_DEVICE_EXTENSION  deviceExtension,
00844     ULONG NewNumberChannels
00845     )
00846 {
00847     PHW_LU_EXTENSION old_luns = NULL;
00848     PHW_CHANNEL old_chans = NULL;
00849 
00850     KdPrint2((PRINT_PREFIX "allocate Luns for %d channels\n", deviceExtension->NumberChannels));
00851 
00852     old_luns = deviceExtension->lun;
00853     old_chans = deviceExtension->chan;
00854 
00855     if(old_luns || old_chans) {
00856         if(NewNumberChannels == UNIATA_ALLOCATE_NEW_LUNS) {
00857             KdPrint2((PRINT_PREFIX "already allocated!\n"));
00858             return FALSE;
00859         }
00860     }
00861 
00862     if(!deviceExtension->NumberLuns) {
00863         KdPrint2((PRINT_PREFIX "default NumberLuns=2\n"));
00864         deviceExtension->NumberLuns = 2;
00865     }
00866 
00867     deviceExtension->lun = (PHW_LU_EXTENSION)ExAllocatePool(NonPagedPool, sizeof(HW_LU_EXTENSION) * (deviceExtension->NumberChannels+1) * deviceExtension->NumberLuns);
00868     if (!deviceExtension->lun) {
00869         KdPrint2((PRINT_PREFIX "!deviceExtension->lun => SP_RETURN_ERROR\n"));
00870         return FALSE;
00871     }
00872     RtlZeroMemory(deviceExtension->lun, sizeof(HW_LU_EXTENSION) * (deviceExtension->NumberChannels+1) * deviceExtension->NumberLuns);
00873     
00874     deviceExtension->chan = (PHW_CHANNEL)ExAllocatePool(NonPagedPool, sizeof(HW_CHANNEL) * (deviceExtension->NumberChannels+1));
00875     if (!deviceExtension->chan) {
00876         ExFreePool(deviceExtension->lun);
00877         deviceExtension->lun = NULL;
00878         KdPrint2((PRINT_PREFIX "!deviceExtension->chan => SP_RETURN_ERROR\n"));
00879         return FALSE;
00880     }
00881     RtlZeroMemory(deviceExtension->chan, sizeof(HW_CHANNEL) * (deviceExtension->NumberChannels+1));
00882     return TRUE;
00883 } // end UniataAllocateLunExt()
00884 
00885 
00886 /*++
00887 
00888 Routine Description:
00889 
00890     This function is called by the OS-specific port driver after
00891     the necessary storage has been allocated, to gather information
00892     about the adapter's configuration.
00893 
00894 Arguments:
00895 
00896     HwDeviceExtension - HBA miniport driver's adapter data storage
00897     Context - Address of adapter count
00898     BusInformation -
00899     ArgumentString - Used to determine whether driver is client of ntldr or crash dump utility.
00900     ConfigInfo - Configuration information structure describing HBA
00901     Again - Indicates search for adapters to continue
00902 
00903 Return Value:
00904 
00905     ULONG
00906 
00907 --*/
00908 ULONG
00909 NTAPI
00910 UniataFindBusMasterController(
00911     IN PVOID HwDeviceExtension,
00912     IN PVOID Context,
00913     IN PVOID BusInformation,
00914     IN PCHAR ArgumentString,
00915     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
00916     OUT PBOOLEAN Again
00917     )
00918 {
00919     PHW_DEVICE_EXTENSION  deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
00920     PHW_CHANNEL           chan = NULL;
00921 #ifndef UNIATA_CORE
00922     // this buffer must be global for UNIATA_CORE build
00923     PCI_COMMON_CONFIG     pciData;
00924 #endif //UNIATA_CORE
00925     ULONG                 slotNumber;
00926     ULONG                 busDataRead;
00927     ULONG                 SystemIoBusNumber;
00928 
00929     UCHAR                 vendorString[5];
00930     UCHAR                 deviceString[5];
00931     PUCHAR                vendorStrPtr;
00932     PUCHAR                deviceStrPtr;
00933 
00934     UCHAR   BaseClass;
00935     UCHAR   SubClass;
00936     ULONG   VendorID;
00937     ULONG   DeviceID;
00938     ULONG   RevID;
00939     ULONG   dev_id;
00940     PCI_SLOT_NUMBER       slotData;
00941 
00942     ULONG   i;
00943     ULONG   channel;
00944     ULONG   c = 0;
00945     PUCHAR  ioSpace;
00946     UCHAR   statusByte;
00947     ULONG   bm_offset;
00948 
00949 //    UCHAR   tmp8;
00950 //    ULONG   irq;
00951 
00952     BOOLEAN found = FALSE;
00953     BOOLEAN MasterDev;
00954     BOOLEAN simplexOnly = FALSE;
00955 #ifndef UNIATA_CORE
00956 #ifdef UNIATA_INIT_ON_PROBE
00957     BOOLEAN skip_find_dev = FALSE;
00958 #endif
00959 #endif
00960     BOOLEAN AltInit = FALSE;
00961 
00962     SCSI_PHYSICAL_ADDRESS IoBasePort1;
00963     SCSI_PHYSICAL_ADDRESS IoBasePort2;
00964 
00965     PIDE_BUSMASTER_REGISTERS BaseIoAddressBM_0 = NULL;
00966     PIDE_REGISTERS_1 BaseIoAddress1[IDE_MAX_CHAN];
00967     PIDE_REGISTERS_2 BaseIoAddress2[IDE_MAX_CHAN];
00968 
00969     RtlZeroMemory(&BaseIoAddress1, sizeof(BaseIoAddress1));
00970     RtlZeroMemory(&BaseIoAddress2, sizeof(BaseIoAddress2));
00971 
00972     NTSTATUS status;
00973     PPORT_CONFIGURATION_INFORMATION_COMMON _ConfigInfo =
00974         (PPORT_CONFIGURATION_INFORMATION_COMMON)ConfigInfo;
00975 
00976     if(!WinVer_WDM_Model) {
00977         *Again = FALSE;
00978     } else {
00979         *Again = TRUE;
00980     }
00981 
00982     KdPrint2((PRINT_PREFIX "UniataFindBusMasterController: Context=%x, BMListLen=%d\n", Context, BMListLen));
00983 
00984     KdPrint2((PRINT_PREFIX "ConfigInfo->Length %x\n", ConfigInfo->Length));
00985 
00986     if(ForceSimplex) {
00987         KdPrint2((PRINT_PREFIX "ForceSimplex (1)\n"));
00988         simplexOnly = TRUE;
00989     }
00990 
00991     if(ConfigInfo->AdapterInterfaceType == Isa) {
00992         KdPrint2((PRINT_PREFIX "AdapterInterfaceType: Isa\n"));
00993     }
00994     if(InDriverEntry) {
00995         i = (ULONG)Context;
00996         if(i & 0x80000000) {
00997             AltInit = TRUE;
00998         }
00999         i &= ~0x80000000;
01000         channel = BMList[i].channel;
01001     } else {
01002         channel = 0;
01003         for(i=0; i<BMListLen; i++) {
01004             if(BMList[i].slotNumber == ConfigInfo->SlotNumber &&
01005                BMList[i].busNumber  == ConfigInfo->SystemIoBusNumber) {
01006                 break;
01007             }
01008         }
01009         if(i >= BMListLen) {
01010             KdPrint2((PRINT_PREFIX "unexpected device arrival\n"));
01011             i = (ULONG)Context;
01012             if(FirstMasterOk) {
01013                 channel = 1;
01014             }
01015             i &= ~0x80000000;
01016             if(i >= BMListLen) {
01017                 KdPrint2((PRINT_PREFIX " => SP_RETURN_NOT_FOUND\n"));
01018                 goto exit_notfound;
01019             }
01020         }
01021         BMList[i].channel = (UCHAR)channel;
01022     }
01023 
01024     bm_offset = channel ? ATA_BM_OFFSET1 : 0;
01025 
01026     KdPrint2((PRINT_PREFIX "bm_offset %x, channel %x \n", bm_offset, channel));
01027 
01028     if (!deviceExtension) {
01029         KdPrint2((PRINT_PREFIX "!deviceExtension => SP_RETURN_ERROR\n"));
01030         return SP_RETURN_ERROR;
01031     }
01032     RtlZeroMemory(deviceExtension, sizeof(HW_DEVICE_EXTENSION));
01033 
01034     vendorStrPtr = vendorString;
01035     deviceStrPtr = deviceString;
01036 
01037     slotNumber = BMList[i].slotNumber;
01038     SystemIoBusNumber = BMList[i].busNumber;
01039 
01040 
01041     KdPrint2((PRINT_PREFIX "AdapterInterfaceType=%#x\n",ConfigInfo->AdapterInterfaceType));
01042     KdPrint2((PRINT_PREFIX "IoBusNumber=%#x\n",ConfigInfo->SystemIoBusNumber));
01043     KdPrint2((PRINT_PREFIX "slotNumber=%#x\n",slotNumber));
01044 
01045     // this buffer must be global and already filled for UNIATA_CORE build
01046     busDataRead = HalGetBusData(
01047         //busDataRead = ScsiPortGetBusData(HwDeviceExtension,
01048                                      PCIConfiguration,
01049                                      SystemIoBusNumber,
01050                                      slotNumber,
01051                                      &pciData,
01052                                      PCI_COMMON_HDR_LENGTH);
01053 
01054 #ifndef UNIATA_CORE
01055     if (busDataRead < (ULONG)PCI_COMMON_HDR_LENGTH) {
01056         KdPrint2((PRINT_PREFIX "busDataRead < PCI_COMMON_HDR_LENGTH => SP_RETURN_ERROR\n"));
01057         goto exit_error;
01058     }
01059 
01060     KdPrint2((PRINT_PREFIX "busDataRead\n"));
01061     if (pciData.VendorID == PCI_INVALID_VENDORID) {
01062         KdPrint2((PRINT_PREFIX "PCI_INVALID_VENDORID\n"));
01063         goto exit_error;
01064     }
01065 #endif //UNIATA_CORE
01066 
01067     VendorID  = pciData.VendorID;
01068     DeviceID  = pciData.DeviceID;
01069     BaseClass = pciData.BaseClass;
01070     SubClass  = pciData.SubClass;
01071     RevID     = pciData.RevisionID;
01072     dev_id = VendorID | (DeviceID << 16);
01073     slotData.u.AsULONG = slotNumber;
01074     KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
01075 
01076     deviceExtension->slotNumber = slotNumber;
01077     deviceExtension->SystemIoBusNumber = SystemIoBusNumber;
01078     deviceExtension->DevID = dev_id;
01079     deviceExtension->RevID = RevID;
01080     deviceExtension->NumberChannels = IDE_DEFAULT_MAX_CHAN; // default
01081     deviceExtension->NumberLuns = IDE_MAX_LUN_PER_CHAN; // default
01082     deviceExtension->DevIndex = i;
01083 
01084     _snprintf(deviceExtension->Signature, sizeof(deviceExtension->Signature),
01085               "UATA%8.8x/%1.1x@%8.8x", dev_id, channel, slotNumber);
01086 
01087     if(BaseClass != PCI_DEV_CLASS_STORAGE) {
01088         KdPrint2((PRINT_PREFIX "BaseClass != PCI_DEV_CLASS_STORAGE => SP_RETURN_NOT_FOUND\n"));
01089         goto exit_notfound;
01090     }
01091 
01092     KdPrint2((PRINT_PREFIX "Storage Class\n"));
01093 
01094     // look for known chipsets
01095     if(VendorID != BMList[i].nVendorId ||
01096        DeviceID != BMList[i].nDeviceId) {
01097         KdPrint2((PRINT_PREFIX "device not suitable\n"));
01098         goto exit_notfound;
01099     }
01100 
01101     found = UniataCheckPCISubclass(BMList[i].Known, BMList[i].RaidFlags, SubClass);
01102     if(!found) {
01103         KdPrint2((PRINT_PREFIX "Subclass not supported\n"));
01104         goto exit_notfound;
01105     }
01106 
01107     ConfigInfo->AlignmentMask = 0x00000003;
01108 
01109     MasterDev = IsMasterDev(&pciData);
01110 
01111     if(MasterDev) {
01112         KdPrint2((PRINT_PREFIX "MasterDev (1)\n"));
01113         deviceExtension->MasterDev = TRUE;
01114     }
01115 
01116     status = UniataChipDetect(HwDeviceExtension, &pciData, i, ConfigInfo, &simplexOnly);
01117     switch(status) {
01118     case STATUS_SUCCESS:
01119         found = TRUE;
01120         break;
01121     case STATUS_NOT_FOUND:
01122         found = FALSE;
01123         break;
01124     default:
01125         KdPrint2((PRINT_PREFIX "FAILED => SP_RETURN_ERROR\n"));
01126         goto exit_error;
01127     }
01128     KdPrint2((PRINT_PREFIX "ForceSimplex = %d\n", simplexOnly));
01129     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (0)", deviceExtension->HwFlags));
01130     switch(dev_id) {
01131     /* additional checks for some supported chipsets */
01132     case 0xc6931080:
01133         if (SubClass != PCI_DEV_SUBCLASS_IDE) {
01134             KdPrint2((PRINT_PREFIX "0xc6931080, SubClass != PCI_DEV_SUBCLASS_IDE => found = FALSE\n"));
01135             found = FALSE;
01136         } else {
01137             found = FALSE;
01138         }
01139         break;
01140 
01141     /* unknown chipsets, try generic DMA if it seems possible */
01142     default:
01143         if (found)
01144             break;
01145         KdPrint2((PRINT_PREFIX "Default device\n"));
01146         if(Ata_is_supported_dev(&pciData)) {
01147             KdPrint2((PRINT_PREFIX "Ata_is_supported_dev\n"));
01148             found = TRUE;
01149         } else
01150         if(deviceExtension->HwFlags & UNIATA_AHCI) {
01151             KdPrint2((PRINT_PREFIX "AHCI candidate\n"));
01152             found = TRUE;
01153         } else {
01154             KdPrint2((PRINT_PREFIX "!Ata_is_supported_dev => found = FALSE\n"));
01155             found = FALSE;
01156         }
01157         deviceExtension->UnknownDev = TRUE;
01158         break;
01159     }
01160 
01161     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (1)", deviceExtension->HwFlags));
01162     if(!found) {
01163         KdPrint2((PRINT_PREFIX "!found => SP_RETURN_NOT_FOUND\n"));
01164         goto exit_notfound;
01165     }
01166 
01167     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (2)", deviceExtension->HwFlags));
01168     KdPrint2((PRINT_PREFIX "found suitable device\n"));
01169 
01170     /***********************************************************/
01171     /***********************************************************/
01172     /***********************************************************/
01173 
01174     deviceExtension->UseDpc = TRUE;
01175     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (3)", deviceExtension->HwFlags));
01176     if(deviceExtension->HwFlags & UNIATA_NO_DPC) {
01177         /* CMD 649, ROSB SWK33, ICH4 */
01178         KdPrint2((PRINT_PREFIX "UniataFindBusMasterController: UNIATA_NO_DPC (0)\n"));
01179         deviceExtension->UseDpc = FALSE;
01180     }
01181 
01182     if(MasterDev) {
01183         if((WinVer_Id() <= WinVer_NT) && AltInit && FirstMasterOk) {
01184             // this is the 2nd attempt to init this controller by OUR driver
01185             KdPrint2((PRINT_PREFIX "Skip primary/secondary claiming checks\n"));
01186         } else {
01187             if((channel==0) && ConfigInfo->AtdiskPrimaryClaimed) {
01188                 KdPrint2((PRINT_PREFIX "Error: Primary channel already claimed by another driver\n"));
01189                 goto exit_notfound;
01190             }
01191             if((channel==1) && ConfigInfo->AtdiskSecondaryClaimed) {
01192                 KdPrint2((PRINT_PREFIX "Error: Secondary channel already claimed by another driver\n"));
01193                 goto exit_notfound;
01194             }
01195         }
01196     }
01197     if(deviceExtension->AltRegMap) {
01198         KdPrint2((PRINT_PREFIX "  Non-standard registers layout\n"));
01199         if(deviceExtension->HwFlags & UNIATA_SATA) {
01200             KdPrint2((PRINT_PREFIX "UNIATA_SATA -> IsBusMaster == TRUE\n"));
01201             deviceExtension->BusMaster = TRUE;
01202         }
01203     } else {
01204         deviceExtension->BusMaster = FALSE;
01205 
01206         if(WinVer_WDM_Model && !deviceExtension->UnknownDev) {
01207             ULONG i;
01208             // Enable Busmastering, IO-space and Mem-space
01209             KdPrint2((PRINT_PREFIX "Enabling Mem/Io spaces and busmastering...\n"));
01210             KdPrint2((PRINT_PREFIX "Initial pciData.Command = %#x\n", pciData.Command));
01211             for(i=0; i<3; i++) {
01212                 switch(i) {
01213                 case 0:
01214                     KdPrint2((PRINT_PREFIX "PCI_ENABLE_IO_SPACE\n"));
01215                     pciData.Command |= PCI_ENABLE_IO_SPACE;
01216                     break;
01217                 case 1:
01218                     KdPrint2((PRINT_PREFIX "PCI_ENABLE_MEMORY_SPACE\n"));
01219                     pciData.Command |= PCI_ENABLE_MEMORY_SPACE;
01220                     break;
01221                 case 2:
01222                     KdPrint2((PRINT_PREFIX "PCI_ENABLE_BUS_MASTER\n"));
01223                     pciData.Command |= PCI_ENABLE_BUS_MASTER;
01224                     break;
01225                 }
01226                 HalSetBusDataByOffset(  PCIConfiguration, SystemIoBusNumber, slotData.u.AsULONG, 
01227                                         &(pciData.Command),
01228                                         offsetof(PCI_COMMON_CONFIG, Command),
01229                                         sizeof(pciData.Command));
01230                 KdPrint2((PRINT_PREFIX "InterruptLine = %#x\n", pciData.u.type0.InterruptLine));
01231 
01232                 // reread config space
01233                 busDataRead = HalGetBusData(PCIConfiguration, SystemIoBusNumber, slotData.u.AsULONG, 
01234                                             &pciData, PCI_COMMON_HDR_LENGTH);
01235                 KdPrint2((PRINT_PREFIX "New pciData.Command = %#x\n", pciData.Command));
01236             }
01237             KdPrint2((PRINT_PREFIX "Final pciData.Command = %#x\n", pciData.Command));
01238         }
01239         // validate Mem/Io ranges
01240         //no_ranges = TRUE;
01241         {
01242             ULONG i;
01243             for(i=0; i<PCI_TYPE0_ADDRESSES; i++) {
01244                 if(pciData.u.type0.BaseAddresses[i] & ~0x7) {
01245                     //no_ranges = FALSE;
01246                     //break;
01247                     KdPrint2((PRINT_PREFIX "Range %d = %#x\n", i, pciData.u.type0.BaseAddresses[i]));
01248                 }
01249             }
01250         }
01251 
01252         if(IsBusMaster(&pciData)) {
01253 
01254             KdPrint2((PRINT_PREFIX "IsBusMaster == TRUE\n"));
01255             BaseIoAddressBM_0 = (PIDE_BUSMASTER_REGISTERS)
01256                 (AtapiGetIoRange(HwDeviceExtension, ConfigInfo, &pciData, SystemIoBusNumber,
01257                                 4, bm_offset, MasterDev ? 0x08 : 0x10/*ATA_BMIOSIZE*/)/* - bm_offset*/); //range id
01258             if(BaseIoAddressBM_0) {
01259                 UniataInitMapBM(deviceExtension,
01260                                 BaseIoAddressBM_0,
01261                                 (*ConfigInfo->AccessRanges)[4].RangeInMemory ? TRUE : FALSE);
01262                 deviceExtension->BusMaster = TRUE;
01263                 deviceExtension->BaseIoAddressBM_0.Addr  = (ULONGIO_PTR)BaseIoAddressBM_0;
01264                 if((*ConfigInfo->AccessRanges)[4].RangeInMemory) {
01265                     deviceExtension->BaseIoAddressBM_0.MemIo = TRUE;
01266                 }
01267             }
01268             KdPrint2((PRINT_PREFIX "  BusMasterAddress (base): %#x\n", BaseIoAddressBM_0));
01269         }
01270 
01271         if(!deviceExtension->BusMaster) {
01272             KdPrint2((PRINT_PREFIX "  !BusMasterAddress -> PIO4\n"));
01273             deviceExtension->MaxTransferMode = ATA_PIO4;
01274         }
01275 
01276         if(deviceExtension->BusMaster && !MasterDev) {
01277             KdPrint2((PRINT_PREFIX "IsBusMaster == TRUE && !MasterDev\n"));
01278             statusByte = AtapiReadPort1(&(deviceExtension->chan[0]), IDX_BM_Status);
01279             KdPrint2((PRINT_PREFIX "  BM statusByte = %x\n", statusByte));
01280             if(statusByte == 0xff) {
01281                 KdPrint2((PRINT_PREFIX "  invalid port ?\n"));
01282 /*
01283                 if(BaseIoAddressBM_0) {
01284                     ScsiPortFreeDeviceBase(HwDeviceExtension,
01285                                            BaseIoAddressBM_0);
01286                     BaseIoAddressBM_0 = NULL;
01287                 }
01288 */
01289             } else
01290             if(statusByte & BM_STATUS_SIMPLEX_ONLY) {
01291                 KdPrint2((PRINT_PREFIX "  BM_STATUS => simplexOnly\n"));
01292                 simplexOnly = TRUE;
01293             }
01294         }
01295     }
01296 
01297     /*
01298      * the Cypress chip is a mess, it contains two ATA functions, but
01299      * both channels are visible on the first one.
01300      * simply ignore the second function for now, as the right
01301      * solution (ignoring the second channel on the first function)
01302      * doesn't work with the crappy ATA interrupt setup on the alpha.
01303      */
01304     if (dev_id == 0xc6931080 && slotData.u.bits.FunctionNumber > 1) {
01305         KdPrint2((PRINT_PREFIX "dev_id == 0xc6931080 && FunctionNumber > 1 => exit_findbm\n"));
01306         goto exit_findbm;
01307     }
01308 
01309     /* do extra chipset specific setups */
01310     AtapiReadChipConfig(HwDeviceExtension, i, CHAN_NOT_SPECIFIED);
01311     AtapiChipInit(HwDeviceExtension, i, CHAN_NOT_SPECIFIED_CHECK_CABLE);
01312 
01313     simplexOnly |= deviceExtension->simplexOnly;
01314     deviceExtension->simplexOnly |= simplexOnly;
01315 
01316     KdPrint2((PRINT_PREFIX "simplexOnly = %d (2)", simplexOnly));
01317 
01318     //TODO: fix hang with UseDpn=TRUE in Simplex mode
01319     //deviceExtension->UseDpc = TRUE;
01320     if(simplexOnly) {
01321         KdPrint2((PRINT_PREFIX "simplexOnly => UseDpc = FALSE\n"));
01322         deviceExtension->UseDpc = FALSE;
01323     }
01324 
01325     if(simplexOnly && MasterDev) {
01326         if(deviceExtension->NumberChannels < IDE_DEFAULT_MAX_CHAN) {
01327             KdPrint2((PRINT_PREFIX "set NumberChannels = %d\n", IDE_DEFAULT_MAX_CHAN));
01328             deviceExtension->NumberChannels = IDE_DEFAULT_MAX_CHAN;
01329             if(BaseIoAddressBM_0) {
01330                 UniataInitMapBM(deviceExtension,
01331                                 BaseIoAddressBM_0,
01332                                 (*ConfigInfo->AccessRanges)[4].RangeInMemory ? TRUE : FALSE);
01333             }
01334         }
01335     }
01336     if((channel > 0) &&
01337        (deviceExtension->NumberChannels > 1)) {
01338         KdPrint2((PRINT_PREFIX "Error: channel > 0 && NumberChannels > 1\n"));
01339         goto exit_findbm;
01340     }
01341 
01342     // Indicate number of buses.
01343     ConfigInfo->NumberOfBuses = (UCHAR)(deviceExtension->NumberChannels);
01344     if(!ConfigInfo->InitiatorBusId[0]) {
01345         ConfigInfo->InitiatorBusId[0] = (CHAR)(IoGetConfigurationInformation()->ScsiPortCount);
01346         KdPrint2((PRINT_PREFIX "set ConfigInfo->InitiatorBusId[0] = %#x\n", ConfigInfo->InitiatorBusId[0]));
01347     }
01348     // Indicate four devices can be attached to the adapter
01349     ConfigInfo->MaximumNumberOfTargets = (UCHAR)(deviceExtension->NumberLuns);
01350 
01351     if (MasterDev) {
01352         KdPrint2((PRINT_PREFIX "MasterDev (2)\n"));
01353 /*
01354         if((WinVer_Id() > WinVer_NT) ||
01355            (deviceExtension->NumberChannels > 1)) {
01356 
01357             KdPrint2((PRINT_PREFIX "2 channels & 2 irq for 1 controller Win 2000+\n"));
01358 
01359             if (ConfigInfo->AdapterInterfaceType == MicroChannel) {
01360                 ConfigInfo->InterruptMode2 =
01361                 ConfigInfo->InterruptMode = LevelSensitive;
01362             } else {
01363                 ConfigInfo->InterruptMode2 =
01364                 ConfigInfo->InterruptMode = Latched;
01365             }
01366             ConfigInfo->BusInterruptLevel = 14;
01367             ConfigInfo->BusInterruptLevel2 = 15;
01368         } else*/
01369         if(simplexOnly) {
01370 
01371             KdPrint2((PRINT_PREFIX "2 channels & 2 irq for 1 controller\n"));
01372 
01373             if (ConfigInfo->AdapterInterfaceType == MicroChannel) {
01374                 ConfigInfo->InterruptMode2 =
01375                 ConfigInfo->InterruptMode = LevelSensitive;
01376             } else {
01377                 ConfigInfo->InterruptMode2 =
01378                 ConfigInfo->InterruptMode = Latched;
01379             }
01380             ConfigInfo->BusInterruptLevel = 14;
01381             ConfigInfo->BusInterruptLevel2 = 15;
01382         } else {
01383             KdPrint2((PRINT_PREFIX "1 channels & 1 irq for 1 controller\n"));
01384             if (ConfigInfo->AdapterInterfaceType == MicroChannel) {
01385                 ConfigInfo->InterruptMode = LevelSensitive;
01386             } else {
01387                 ConfigInfo->InterruptMode = Latched;
01388             }
01389             ConfigInfo->BusInterruptLevel = (channel == 0 ? 14 : 15);
01390         }
01391     } else {
01392         KdPrint2((PRINT_PREFIX "!MasterDev\n"));
01393         ConfigInfo->SlotNumber = slotNumber;
01394         ConfigInfo->SystemIoBusNumber = SystemIoBusNumber;
01395 
01396         /* primary and secondary channels share the same interrupt */
01397         if(!ConfigInfo->BusInterruptVector ||
01398             (ConfigInfo->BusInterruptVector != pciData.u.type0.InterruptLine)) {
01399             KdPrint2((PRINT_PREFIX "patch irq line = %#x\n", pciData.u.type0.InterruptLine));
01400             ConfigInfo->BusInterruptVector = pciData.u.type0.InterruptLine;  // set default value
01401             if(!ConfigInfo->BusInterruptVector) {
01402                 KdPrint2((PRINT_PREFIX "patch irq line (2) = 10\n"));
01403                 ConfigInfo->BusInterruptVector = 10;
01404             }
01405         }
01406     }
01407     ConfigInfo->MultipleRequestPerLu = TRUE;
01408     ConfigInfo->AutoRequestSense     = TRUE;
01409     ConfigInfo->TaggedQueuing        = TRUE;
01410 
01411     if((WinVer_Id() >= WinVer_NT) ||
01412        (ConfigInfo->Length >= sizeof(_ConfigInfo->comm) + sizeof(_ConfigInfo->nt4))) {
01413         KdPrint2((PRINT_PREFIX "update ConfigInfo->nt4\n"));
01414         _ConfigInfo->nt4.DeviceExtensionSize         = sizeof(HW_DEVICE_EXTENSION);
01415         _ConfigInfo->nt4.SpecificLuExtensionSize     = sizeof(HW_LU_EXTENSION);
01416         _ConfigInfo->nt4.SrbExtensionSize            = sizeof(ATA_REQ);
01417     }
01418     if((WinVer_Id() > WinVer_2k) ||
01419        (ConfigInfo->Length >= sizeof(_ConfigInfo->comm) + sizeof(_ConfigInfo->nt4) + sizeof(_ConfigInfo->w2k))) {
01420         KdPrint2((PRINT_PREFIX "update ConfigInfo->w2k\n"));
01421         _ConfigInfo->w2k.Dma64BitAddresses           = 0;
01422         _ConfigInfo->w2k.ResetTargetSupported        = TRUE;
01423         _ConfigInfo->w2k.MaximumNumberOfLogicalUnits = (UCHAR)deviceExtension->NumberLuns;
01424     }
01425 
01426     // Save the Interrupe Mode for later use
01427     deviceExtension->InterruptMode      = ConfigInfo->InterruptMode;
01428     deviceExtension->BusInterruptLevel  = ConfigInfo->BusInterruptLevel;
01429     deviceExtension->BusInterruptVector = ConfigInfo->BusInterruptVector;
01430     deviceExtension->Channel            = channel;
01431     deviceExtension->DevIndex           = i;
01432     deviceExtension->OrigAdapterInterfaceType
01433                                         = ConfigInfo->AdapterInterfaceType;
01434     deviceExtension->AlignmentMask      = ConfigInfo->AlignmentMask;
01435     deviceExtension->AdapterInterfaceType = PCIBus;
01436 
01437     found = FALSE;
01438 
01439     if(deviceExtension->BusMaster) {
01440 
01441         KdPrint2((PRINT_PREFIX "Reconstruct ConfigInfo\n"));
01442         ConfigInfo->MapBuffers = TRUE;
01443 #ifdef USE_OWN_DMA
01444         ConfigInfo->NeedPhysicalAddresses = FALSE;
01445 #else
01446         ConfigInfo->NeedPhysicalAddresses = TRUE;
01447 #endif //USE_OWN_DMA
01448         if(!MasterDev) {
01449             KdPrint2((PRINT_PREFIX "set Dma32BitAddresses\n"));
01450             ConfigInfo->Dma32BitAddresses = TRUE;
01451         }
01452 
01453         // thanks to Vitaliy Vorobyov aka deathsoft@yandex.ru for
01454         // better solution:
01455 
01456         if(AltInit) {
01457             // I'm sorry, I have to do this
01458             // when Win doesn't 
01459 
01460             if(ConfigInfo->AdapterInterfaceType == Isa /*&&
01461 //               InDriverEntry*/) {
01462                 KdPrint2((PRINT_PREFIX "AdapterInterfaceType Isa => PCIBus\n"));
01463                 ConfigInfo->AdapterInterfaceType = PCIBus;
01464             }
01465             if(ConfigInfo->AdapterInterfaceType == PCIBus /*&&
01466 //               InDriverEntry*/) {
01467                 KdPrint2((PRINT_PREFIX "AdapterInterfaceType PCIBus, update address\n"));
01468                 ConfigInfo->SlotNumber = slotNumber;
01469                 ConfigInfo->SystemIoBusNumber = SystemIoBusNumber;
01470             }
01471         }
01472 
01473 #ifndef USE_OWN_DMA
01474         ConfigInfo->Master        = TRUE;
01475         ConfigInfo->DmaWidth      = Width16Bits;
01476 #endif //USE_OWN_DMA
01477         ConfigInfo->CachesData    = TRUE;
01478         ConfigInfo->ScatterGather = TRUE;
01479     }
01480 
01481     // Note: now we can support only 4 channels !!!
01482     // in order to add support for multichannel controllers we must rewrite
01483     // io-range claiming algorithm
01484 
01485     KdPrint2((PRINT_PREFIX "BMList[i].channel %#x, NumberChannels %#x, channel %#x\n",BMList[i].channel, deviceExtension->NumberChannels, channel));
01486 
01487     for (; channel < (BMList[i].channel + deviceExtension->NumberChannels); channel++, c++) {
01488 
01489         KdPrint2((PRINT_PREFIX "de %#x, Channel %#x\n",deviceExtension, channel));
01490         //PrintNtConsole("de %#x, Channel %#x, nchan %#x\n",deviceExtension, channel, deviceExtension->NumberChannels);
01491         chan = &deviceExtension->chan[c];
01492 
01493         KdPrint2((PRINT_PREFIX "chan = %#x\n", chan));
01494         //PrintNtConsole("chan = %#x, c=%#x\n", chan, c);
01495         AtapiSetupLunPtrs(chan, deviceExtension, c);
01496 
01497         /* do extra channel-specific setups */
01498         AtapiReadChipConfig(HwDeviceExtension, i, channel);
01499         //AtapiChipInit(HwDeviceExtension, i, channel);
01500         if(deviceExtension->HwFlags & UNIATA_AHCI) {
01501             KdPrint2((PRINT_PREFIX "  No more setup for AHCI channel\n"));
01502         } else
01503         if(deviceExtension->AltRegMap) {
01504             KdPrint2((PRINT_PREFIX "  Non-standard registers layout\n"));
01505         } else {
01506             // Check if the range specified is not used by another driver
01507             if(MasterDev) {
01508                 KdPrint2((PRINT_PREFIX "set AccessRanges\n"));
01509                 (*ConfigInfo->AccessRanges)[channel * 2 + 0].RangeStart =
01510                     ScsiPortConvertUlongToPhysicalAddress(channel ? IO_WD2 : IO_WD1);
01511                 (*ConfigInfo->AccessRanges)[channel * 2 + 0].RangeLength = ATA_IOSIZE;
01512 
01513                 (*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeStart =
01514                     ScsiPortConvertUlongToPhysicalAddress((channel ? IO_WD2 : IO_WD1) + ATA_ALTOFFSET);
01515                 (*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeLength = ATA_ALTIOSIZE;
01516 
01517                 // do not claim 2nd BM io-range for Secondary channel of
01518                 // Compatible-mode controllers
01519                 if(/*(WinVer_Id() <= WinVer_NT) &&*/ !c && channel == 1) {
01520                     KdPrint2((PRINT_PREFIX "cheat ScsiPort for 2nd channel, BM io-range\n"));
01521                     (*ConfigInfo->AccessRanges)[4].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
01522                     (*ConfigInfo->AccessRanges)[4].RangeLength = 0;
01523                 }
01524             } else
01525             if(AltInit &&
01526                !(*ConfigInfo->AccessRanges)[channel * 2 + 0].RangeStart.QuadPart &&
01527                !(*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeStart.QuadPart) {
01528                 KdPrint2((PRINT_PREFIX "cheat ScsiPort, sync real PCI and ConfigInfo IO ranges\n"));
01529                 AtapiGetIoRange(HwDeviceExtension, ConfigInfo, &pciData, SystemIoBusNumber,
01530                         channel * 2 + 0, 0, ATA_IOSIZE);
01531                 AtapiGetIoRange(HwDeviceExtension, ConfigInfo, &pciData, SystemIoBusNumber,
01532                         channel * 2 + 1, 0, ATA_ALTIOSIZE);
01533             }
01534 
01535             IoBasePort1 = (*ConfigInfo->AccessRanges)[channel * 2 + 0].RangeStart;
01536             IoBasePort2 = (*ConfigInfo->AccessRanges)[channel * 2 + 1].RangeStart;
01537 
01538             if(!MasterDev) {
01539                 if(!IoBasePort1.QuadPart || !IoBasePort2.QuadPart) {
01540                     KdPrint2((PRINT_PREFIX "ScsiPortValidateRange failed (1)\n"));
01541                     continue;
01542                 }
01543             }
01544 
01545             if(!ScsiPortValidateRange(HwDeviceExtension,
01546                                       PCIBus /*ConfigInfo->AdapterInterfaceType*/,
01547                                       SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/,
01548                                       IoBasePort1,
01549                                       ATA_IOSIZE,
01550                                       TRUE) ) {
01551                 KdPrint2((PRINT_PREFIX "ScsiPortValidateRange failed (1)\n"));
01552                 continue;
01553             }
01554 
01555             if(!ScsiPortValidateRange(HwDeviceExtension,
01556                                       PCIBus /*ConfigInfo->AdapterInterfaceType*/,
01557                                       SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/,
01558                                       IoBasePort2,
01559                                       ATA_ALTIOSIZE,
01560                                       TRUE) ) {
01561                 KdPrint2((PRINT_PREFIX "ScsiPortValidateRange failed (2)\n"));
01562                 continue;
01563             }
01564 
01565             KdPrint2((PRINT_PREFIX "Getting IO ranges\n"));
01566 
01567             // Ok, translate adresses to io-space
01568             if(ScsiPortConvertPhysicalAddressToUlong(IoBasePort2)) {
01569                 if(!(MasterDev /* || USE_16_BIT */)) {
01570                     KdPrint2((PRINT_PREFIX "!MasterDev mode\n"));
01571                     IoBasePort2 = ScsiPortConvertUlongToPhysicalAddress(
01572                                       ScsiPortConvertPhysicalAddressToUlong(IoBasePort2) + 2);
01573                 }
01574             } else {
01575                 KdPrint2((PRINT_PREFIX "use relative IoBasePort2\n"));
01576                 IoBasePort2 = ScsiPortConvertUlongToPhysicalAddress(
01577                                   ScsiPortConvertPhysicalAddressToUlong(IoBasePort1) + ATA_PCCARD_ALTOFFSET);
01578             }
01579 
01580             // Get the system physical address for this IO range.
01581             ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
01582                                             PCIBus /*ConfigInfo->AdapterInterfaceType*/,
01583                                             SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/,
01584                                             IoBasePort1,
01585                                             ATA_IOSIZE,
01586                                             TRUE);
01587             KdPrint2((PRINT_PREFIX "IO range 1 %#x\n",ioSpace));
01588 
01589             // Check if ioSpace accessible.
01590             if (!ioSpace) {
01591                 KdPrint2((PRINT_PREFIX "!ioSpace\n"));
01592                 continue;
01593             }
01594 /*
01595             if(deviceExtension->BusMaster) {
01596                 KdPrint2((PRINT_PREFIX "set BusMaster io-range in DO\n"));
01597                 // bm_offset already includes (channel ? ATA_BM_OFFSET1 : 0)
01598                 deviceExtension->BaseIoAddressBM[c] = (PIDE_BUSMASTER_REGISTERS)
01599                     ((ULONG)(deviceExtension->BaseIoAddressBM_0) + bm_offset + (c ? ATA_BM_OFFSET1 : 0));
01600             }
01601 */
01602             //deviceExtension->BaseIoAddress1[c] = (PIDE_REGISTERS_1)(ioSpace);
01603             BaseIoAddress1[c] = (PIDE_REGISTERS_1)(ioSpace);
01604 
01605             // Get the system physical address for the second IO range.
01606             ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
01607                                             PCIBus /*ConfigInfo->AdapterInterfaceType*/,
01608                                             SystemIoBusNumber /*ConfigInfo->SystemIoBusNumber*/,
01609                                             IoBasePort2,
01610                                             ATA_ALTIOSIZE,
01611                                             TRUE);
01612             KdPrint2((PRINT_PREFIX "IO range 2 %#x\n",ioSpace));
01613 
01614             BaseIoAddress2[c] = (PIDE_REGISTERS_2)(ioSpace);
01615             if(!ioSpace) {
01616                 // Release all allocated resources
01617                 KdPrint2((PRINT_PREFIX "!deviceExtension->BaseIoAddress2\n"));
01618                 //ioSpace = (PUCHAR)BaseIoAddress1[c];
01619     //            goto free_iospace_1;
01620                 found = FALSE;
01621                 goto exit_findbm;
01622             }
01623             UniataInitMapBase(chan, BaseIoAddress1[c], BaseIoAddress2[c]);
01624         }
01625         //ioSpace = (PUCHAR)(deviceExtension->BaseIoAddress1[c]);
01626 
01627         KdPrint2((PRINT_PREFIX "IDX_IO1 %x->%x(%s)\n",
01628           IDX_IO1,
01629           chan->RegTranslation[IDX_IO1].Addr,
01630           chan->RegTranslation[IDX_IO1].MemIo ? "mem" : "io"));
01631 
01632         KdPrint2((PRINT_PREFIX "IDX_IO2 %x->%x(%s)\n",
01633           IDX_IO2,
01634           chan->RegTranslation[IDX_IO2].Addr,
01635           chan->RegTranslation[IDX_IO2].MemIo ? "mem" : "io"));
01636 
01637         KdPrint2((PRINT_PREFIX "IDX_BM_IO %x->%x(%s)\n",
01638           IDX_BM_IO,
01639           chan->RegTranslation[IDX_BM_IO].Addr,
01640           chan->RegTranslation[IDX_BM_IO].MemIo ? "mem" : "io"));
01641 
01642         KdPrint2((PRINT_PREFIX "IDX_SATA_IO %x->%x(%s)\n",
01643           IDX_SATA_IO,
01644           chan->RegTranslation[IDX_SATA_IO].Addr,
01645           chan->RegTranslation[IDX_SATA_IO].MemIo ? "mem" : "io"));
01646 
01647         if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
01648             UniataDumpATARegs(chan);
01649 
01650 #ifndef UNIATA_CORE
01651 #ifdef UNIATA_INIT_ON_PROBE
01652 //        if(deviceExtension->HwFlags & UNIATA_SATA) {
01653 //#endif //UNIATA_INIT_ON_PROBE
01654             KdPrint2((PRINT_PREFIX "Check drive 0\n"));
01655             // Check master.
01656             SelectDrive(chan, 0);
01657             AtapiStallExecution(10);
01658             GetBaseStatus(chan, statusByte);
01659             skip_find_dev = FALSE;
01660             if(!(deviceExtension->HwFlags & UNIATA_NO_SLAVE)) {
01661                 if ((statusByte & 0xf8) == 0xf8 ||
01662                     (statusByte == 0xa5)) {
01663                     // Check slave.
01664                     KdPrint2((PRINT_PREFIX "Check drive 1\n"));
01665                     SelectDrive(chan, 1);
01666                     AtapiStallExecution(1);
01667                     GetBaseStatus(chan, statusByte);
01668                     if ((statusByte & 0xf8) == 0xf8 ||
01669                         (statusByte == 0xa5)) {
01670                         // No controller at this base address.
01671                         KdPrint2((PRINT_PREFIX "Empty channel\n"));
01672                         skip_find_dev = TRUE;
01673                     }
01674                 }
01675             }
01676 
01677             // Search for devices on this controller.
01678             if (!skip_find_dev &&
01679                 FindDevices(HwDeviceExtension,
01680                         0,
01681                         c)) {
01682                 KdPrint2((PRINT_PREFIX "Found some devices\n"));
01683                 found = TRUE;
01684             } else {
01685                 KdPrint2((PRINT_PREFIX "no devices\n"));
01686     /*            KeBugCheckEx(0xc000000e,
01687                              ScsiPortConvertPhysicalAddressToUlong(IoBasePort1),
01688                              ScsiPortConvertPhysicalAddressToUlong(IoBasePort2),
01689                              (ULONG)(deviceExtension->BaseIoAddressBM[c]), skip_find_dev);*/
01690             }
01691 //#ifdef UNIATA_INIT_ON_PROBE
01692 //        }
01693 #endif //UNIATA_INIT_ON_PROBE
01694         }
01695         found = TRUE;
01696 
01697         chan->PrimaryAddress = FALSE;
01698         // Claim primary or secondary ATA IO range.
01699         if (MasterDev) {
01700             KdPrint2((PRINT_PREFIX "claim Compatible controller\n"));
01701             if (channel == 0) {
01702                 KdPrint2((PRINT_PREFIX "claim Primary\n"));
01703                 ConfigInfo->AtdiskPrimaryClaimed = TRUE;
01704                 chan->PrimaryAddress = TRUE;
01705 
01706                 FirstMasterOk = TRUE;
01707 
01708             } else
01709             if (channel == 1) {
01710                 KdPrint2((PRINT_PREFIX "claim Secondary\n"));
01711                 ConfigInfo->AtdiskSecondaryClaimed = TRUE;
01712 
01713                 FirstMasterOk = TRUE;
01714             }
01715         }
01716 
01717         AtapiDmaAlloc(HwDeviceExtension, ConfigInfo, c);
01718 #else //UNIATA_CORE
01719         }
01720         found = TRUE;
01721 #endif //UNIATA_CORE
01722     } // end for(channel)
01723 
01724 exit_findbm:
01725 
01726 #ifndef UNIATA_CORE
01727     if(!found) {
01728         KdPrint2((PRINT_PREFIX "exit: !found\n"));
01729         if(BaseIoAddress1[0])
01730             ScsiPortFreeDeviceBase(HwDeviceExtension,
01731                                    BaseIoAddress1[0]);
01732         if(BaseIoAddress2[0])
01733             ScsiPortFreeDeviceBase(HwDeviceExtension,
01734                                    BaseIoAddress2[0]);
01735 
01736         if(BaseIoAddress1[1])
01737             ScsiPortFreeDeviceBase(HwDeviceExtension,
01738                                    BaseIoAddress1[1]);
01739         if(BaseIoAddress2[1])
01740             ScsiPortFreeDeviceBase(HwDeviceExtension,
01741                                    BaseIoAddress2[1]);
01742 
01743         if(BaseIoAddressBM_0)
01744             ScsiPortFreeDeviceBase(HwDeviceExtension,
01745                                    BaseIoAddressBM_0);
01746 
01747         KdPrint2((PRINT_PREFIX "return SP_RETURN_NOT_FOUND\n"));
01748         goto exit_notfound;
01749     } else {
01750 
01751         KdPrint2((PRINT_PREFIX "exit: init spinlock\n"));
01752         //KeInitializeSpinLock(&(deviceExtension->DpcSpinLock));
01753         deviceExtension->ActiveDpcChan =
01754         deviceExtension->FirstDpcChan = -1;
01755 
01756         BMList[i].Isr2Enable = FALSE;
01757 
01758         KdPrint2((PRINT_PREFIX "MasterDev=%#x, NumberChannels=%#x, Isr2DevObj=%#x\n",
01759             MasterDev, deviceExtension->NumberChannels, BMList[i].Isr2DevObj));
01760 
01761         // ConnectIntr2 should be moved to HwInitialize
01762         status = UniataConnectIntr2(HwDeviceExtension);
01763 
01764         KdPrint2((PRINT_PREFIX "MasterDev=%#x, NumberChannels=%#x, Isr2DevObj=%#x\n",
01765             MasterDev, deviceExtension->NumberChannels, BMList[i].Isr2DevObj));
01766 
01767         if(WinVer_WDM_Model && MasterDev) {
01768             KdPrint2((PRINT_PREFIX "do not tell system, that we know about this:\n"));
01769             if(BaseIoAddressBM_0) {
01770                 ScsiPortFreeDeviceBase(HwDeviceExtension,
01771                                        BaseIoAddressBM_0);
01772             }
01773             (*ConfigInfo->AccessRanges)[4].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
01774             (*ConfigInfo->AccessRanges)[4].RangeLength = 0;
01775             (*ConfigInfo->AccessRanges)[5].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0);
01776             (*ConfigInfo->AccessRanges)[5].RangeLength = 0;
01777         }
01778 
01779         if(!NT_SUCCESS(status)) {
01780             KdPrint2((PRINT_PREFIX "failed\n"));
01781             found = FALSE;
01782             goto exit_findbm;
01783         }
01784     }
01785 #endif //UNIATA_CORE
01786 
01787     KdPrint2((PRINT_PREFIX "return SP_RETURN_FOUND\n"));
01788     //PrintNtConsole("return SP_RETURN_FOUND, de %#x, c0.lun0 %#x\n", deviceExtension, deviceExtension->chan[0].lun[0]);
01789 
01790     if(MasterDev) {
01791         KdPrint2((PRINT_PREFIX "Attempt %d of MasterDev ok\n", AltInit));
01792         FirstMasterOk = TRUE;
01793     }
01794 
01795     ConfigInfo->NumberOfBuses++; // add virtual channel for communication port
01796     return SP_RETURN_FOUND;
01797 
01798 exit_error:
01799     if (deviceExtension->lun) ExFreePool(deviceExtension->lun);
01800     if (deviceExtension->chan) ExFreePool(deviceExtension->chan);
01801     return SP_RETURN_ERROR;
01802     
01803 exit_notfound:
01804     ExFreePool(deviceExtension->lun);
01805     ExFreePool(deviceExtension->chan);
01806     return SP_RETURN_NOT_FOUND;
01807 
01808 } // end UniataFindBusMasterController()
01809 
01810 #ifndef UNIATA_CORE
01811 
01812 /*
01813    This is for claiming PCI Busmaster in compatible mode under WDM OSes
01814 */
01815 ULONG
01816 NTAPI
01817 UniataFindFakeBusMasterController(
01818     IN PVOID HwDeviceExtension,
01819     IN PVOID Context,
01820     IN PVOID BusInformation,
01821     IN PCHAR ArgumentString,
01822     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
01823     OUT PBOOLEAN Again
01824     )
01825 {
01826     PHW_DEVICE_EXTENSION  deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
01827     //PHW_CHANNEL           chan = NULL;
01828     // this buffer must be global for UNIATA_CORE build
01829     PCI_COMMON_CONFIG     pciData;
01830 
01831     ULONG                 slotNumber;
01832     ULONG                 busDataRead;
01833     ULONG                 SystemIoBusNumber;
01834 
01835     UCHAR                 vendorString[5];
01836     UCHAR                 deviceString[5];
01837     PUCHAR                vendorStrPtr;
01838     PUCHAR                deviceStrPtr;
01839 
01840     UCHAR   BaseClass;
01841     UCHAR   SubClass;
01842     ULONG   VendorID;
01843     ULONG   DeviceID;
01844     ULONG   RevID;
01845     ULONG   dev_id;
01846     PCI_SLOT_NUMBER       slotData;
01847 
01848     ULONG   i;
01849 //    PUCHAR  ioSpace;
01850 //    UCHAR   statusByte;
01851 
01852 //    UCHAR   tmp8;
01853 //    ULONG   irq;
01854 
01855     BOOLEAN found = FALSE;
01856     BOOLEAN MasterDev;
01857     BOOLEAN simplexOnly = FALSE;
01858     //BOOLEAN skip_find_dev = FALSE;
01859     //BOOLEAN AltInit = FALSE;
01860 
01861     PIDE_BUSMASTER_REGISTERS BaseIoAddressBM_0 = NULL;
01862 
01863     NTSTATUS status;
01864     PPORT_CONFIGURATION_INFORMATION_COMMON _ConfigInfo =
01865         (PPORT_CONFIGURATION_INFORMATION_COMMON)ConfigInfo;
01866 
01867     *Again = FALSE;
01868 
01869     if(InDriverEntry) {
01870         i = (ULONG)Context;
01871     } else {
01872         for(i=0; i<BMListLen; i++) {
01873             if(BMList[i].slotNumber == ConfigInfo->SlotNumber &&
01874                BMList[i].busNumber  == ConfigInfo->SystemIoBusNumber) {
01875                 break;
01876             }
01877         }
01878         if(i >= BMListLen) {
01879             KdPrint2((PRINT_PREFIX "unexpected device arrival => SP_RETURN_NOT_FOUND\n"));
01880             goto exit_notfound;
01881         }
01882     }
01883 
01884     KdPrint2((PRINT_PREFIX "UniataFindFakeBusMasterController (WDM)\n"));
01885 
01886     if (!deviceExtension) {
01887         KdPrint2((PRINT_PREFIX "!deviceExtension => SP_RETURN_ERROR\n"));
01888         return SP_RETURN_ERROR;
01889     }
01890     RtlZeroMemory(deviceExtension, sizeof(HW_DEVICE_EXTENSION));
01891 
01892     vendorStrPtr = vendorString;
01893     deviceStrPtr = deviceString;
01894 
01895     slotNumber = BMList[i].slotNumber;
01896     SystemIoBusNumber = BMList[i].busNumber;
01897 
01898     KdPrint2((PRINT_PREFIX "AdapterInterfaceType=%#x\n",ConfigInfo->AdapterInterfaceType));
01899     KdPrint2((PRINT_PREFIX "IoBusNumber=%#x\n",ConfigInfo->SystemIoBusNumber));
01900     KdPrint2((PRINT_PREFIX "slotNumber=%#x\n",slotNumber));
01901 
01902     // this buffer must be global and already filled for UNIATA_CORE build
01903     busDataRead = HalGetBusData(
01904         //busDataRead = ScsiPortGetBusData(HwDeviceExtension,
01905                                      PCIConfiguration,
01906                                      SystemIoBusNumber,
01907                                      slotNumber,
01908                                      &pciData,
01909                                      PCI_COMMON_HDR_LENGTH);
01910 
01911     if (busDataRead < PCI_COMMON_HDR_LENGTH) {
01912         KdPrint2((PRINT_PREFIX "busDataRead < PCI_COMMON_HDR_LENGTH => SP_RETURN_ERROR\n"));
01913         goto exit_error;
01914     }
01915 
01916     KdPrint2((PRINT_PREFIX "busDataRead\n"));
01917     if (pciData.VendorID == PCI_INVALID_VENDORID) {
01918         KdPrint2((PRINT_PREFIX "PCI_INVALID_VENDORID\n"));
01919         goto exit_error;
01920     }
01921 
01922     VendorID  = pciData.VendorID;
01923     DeviceID  = pciData.DeviceID;
01924     BaseClass = pciData.BaseClass;
01925     SubClass  = pciData.SubClass;
01926     RevID     = pciData.RevisionID;
01927     dev_id = VendorID | (DeviceID << 16);
01928     slotData.u.AsULONG = slotNumber;
01929     KdPrint2((PRINT_PREFIX "DevId = %8.8X Class = %4.4X/%4.4X\n", dev_id, BaseClass, SubClass ));
01930 
01931     deviceExtension->slotNumber = slotNumber;
01932     deviceExtension->SystemIoBusNumber = SystemIoBusNumber;
01933     deviceExtension->DevID = dev_id;
01934     deviceExtension->RevID = RevID;
01935     deviceExtension->NumberChannels = IDE_DEFAULT_MAX_CHAN; // default
01936     deviceExtension->NumberLuns = IDE_MAX_LUN_PER_CHAN; // default
01937     deviceExtension->DevIndex = i;
01938 
01939     _snprintf(deviceExtension->Signature, sizeof(deviceExtension->Signature),
01940               "UATA%8.8x/%1.1x@%8.8x", dev_id, 0xff, slotNumber);
01941 
01942     if(BaseClass != PCI_DEV_CLASS_STORAGE) {
01943         KdPrint2((PRINT_PREFIX "BaseClass != PCI_DEV_CLASS_STORAGE => SP_RETURN_NOT_FOUND\n"));
01944         goto exit_notfound;
01945     }
01946 
01947     KdPrint2((PRINT_PREFIX "Storage Class\n"));
01948 
01949     // look for known chipsets
01950     if(VendorID != BMList[i].nVendorId ||
01951        DeviceID != BMList[i].nDeviceId) {
01952         KdPrint2((PRINT_PREFIX "device not suitable\n"));
01953         goto exit_notfound;
01954     }
01955 
01956     if((BMList[i].RaidFlags & UNIATA_RAID_CONTROLLER) &&
01957         SkipRaids) {
01958         KdPrint2((PRINT_PREFIX "RAID support disabled\n"));
01959         goto exit_notfound;
01960     }
01961 
01962     if(!UniataCheckPCISubclass(FALSE, BMList[i].RaidFlags, SubClass)) {
01963         KdPrint2((PRINT_PREFIX "Subclass not supported\n"));
01964         goto exit_notfound;
01965     }
01966 
01967     ConfigInfo->AlignmentMask = 0x00000003;
01968 
01969     status = UniataChipDetect(HwDeviceExtension, &pciData, i, ConfigInfo, &simplexOnly);
01970     switch(status) {
01971     case STATUS_SUCCESS:
01972         found = TRUE;
01973         break;
01974     case STATUS_NOT_FOUND:
01975         found = FALSE;
01976         break;
01977     default:
01978         KdPrint2((PRINT_PREFIX "FAILED => SP_RETURN_ERROR\n"));
01979         goto exit_error;
01980     }
01981     KdPrint2((PRINT_PREFIX "ForceSimplex = %d\n", simplexOnly));
01982     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (0)", deviceExtension->HwFlags));
01983     switch(dev_id) {
01984     /* additional checks for some supported chipsets */
01985     case 0xc6931080:
01986         if (SubClass != PCI_DEV_SUBCLASS_IDE) {
01987             KdPrint2((PRINT_PREFIX "0xc6931080, SubClass != PCI_DEV_SUBCLASS_IDE => found = FALSE\n"));
01988             found = FALSE;
01989         } else {
01990             found = FALSE;
01991         }
01992         break;
01993 
01994     /* unknown chipsets, try generic DMA if it seems possible */
01995     default:
01996         if (found)
01997             break;
01998         KdPrint2((PRINT_PREFIX "Default device\n"));
01999         if(Ata_is_supported_dev(&pciData)) {
02000             KdPrint2((PRINT_PREFIX "Ata_is_supported_dev\n"));
02001             found = TRUE;
02002         } else {
02003             KdPrint2((PRINT_PREFIX "!Ata_is_supported_dev => found = FALSE\n"));
02004             found = FALSE;
02005         }
02006         deviceExtension->UnknownDev = TRUE;
02007         break;
02008     }
02009 
02010     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (1)", deviceExtension->HwFlags));
02011     if(!found) {
02012         KdPrint2((PRINT_PREFIX "!found => SP_RETURN_NOT_FOUND\n"));
02013         goto exit_notfound;
02014     }
02015 
02016     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (2)", deviceExtension->HwFlags));
02017     KdPrint2((PRINT_PREFIX "found suitable device\n"));
02018 
02019     /***********************************************************/
02020     /***********************************************************/
02021     /***********************************************************/
02022 
02023     deviceExtension->UseDpc = TRUE;
02024     KdPrint2((PRINT_PREFIX "HwFlags = %x\n (3)", deviceExtension->HwFlags));
02025     if(deviceExtension->HwFlags & UNIATA_NO_DPC) {
02026         /* CMD 649, ROSB SWK33, ICH4 */
02027         KdPrint2((PRINT_PREFIX "UniataFindBusMasterController: UNIATA_NO_DPC (0)\n"));
02028         deviceExtension->UseDpc = FALSE;
02029     }
02030 
02031     MasterDev = IsMasterDev(&pciData);
02032 
02033     if(MasterDev) {
02034         KdPrint2((PRINT_PREFIX "MasterDev\n"));
02035         deviceExtension->MasterDev = TRUE;
02036         deviceExtension->NumberChannels = 1;
02037     } else {
02038         KdPrint2((PRINT_PREFIX "!MasterDev => SP_RETURN_NOT_FOUND\n"));
02039         goto exit_notfound;
02040     }
02041 
02042     if(deviceExtension->AltRegMap) {
02043         KdPrint2((PRINT_PREFIX "  Non-standard registers layout => SP_RETURN_NOT_FOUND\n"));
02044         goto exit_notfound;
02045     }
02046     if(IsBusMaster(&pciData)) {
02047         KdPrint2((PRINT_PREFIX "  !BusMaster => SP_RETURN_NOT_FOUND\n"));
02048         goto exit_notfound;
02049     }
02050 
02051     KdPrint2((PRINT_PREFIX "IsBusMaster == TRUE\n"));
02052     BaseIoAddressBM_0 = (PIDE_BUSMASTER_REGISTERS)
02053         (AtapiGetIoRange(HwDeviceExtension, ConfigInfo, &pciData, SystemIoBusNumber,
02054                         4, 0, 0x10/*ATA_BMIOSIZE*/)/* - bm_offset*/); //range id
02055     if(BaseIoAddressBM_0) {
02056         UniataInitMapBM(deviceExtension,
02057                         BaseIoAddressBM_0,
02058                         (*ConfigInfo->AccessRanges)[4].RangeInMemory ? TRUE : FALSE);
02059         deviceExtension->BusMaster = TRUE;
02060         deviceExtension->BaseIoAddressBM_0.Addr  = (ULONGIO_PTR)BaseIoAddressBM_0;
02061         if((*ConfigInfo->AccessRanges)[4].RangeInMemory) {
02062             deviceExtension->BaseIoAddressBM_0.MemIo = TRUE;
02063         }
02064     }
02065     KdPrint2((PRINT_PREFIX "  BusMasterAddress (base): %#x\n", BaseIoAddressBM_0));
02066 
02067     /*
02068      * the Cypress chip is a mess, it contains two ATA functions, but 
02069      * both channels are visible on the first one.
02070      * simply ignore the second function for now, as the right
02071      * solution (ignoring the second channel on the first function)
02072      * doesn't work with the crappy ATA interrupt setup on the alpha.
02073      */
02074     if (dev_id == 0xc6931080 && slotData.u.bits.FunctionNumber > 1) {
02075         KdPrint2((PRINT_PREFIX "dev_id == 0xc6931080 && FunctionNumber > 1 => exit_findbm\n"));
02076         goto exit_findbm;
02077     }
02078 
02079     // Indicate number of buses.
02080     ConfigInfo->NumberOfBuses = 0;
02081     if(!ConfigInfo->InitiatorBusId[0]) {
02082         ConfigInfo->InitiatorBusId[0] = (CHAR)(IoGetConfigurationInformation()->ScsiPortCount);
02083         KdPrint2((PRINT_PREFIX "set ConfigInfo->InitiatorBusId[0] = %#x\n", ConfigInfo->InitiatorBusId[0]));
02084     }
02085     // Indicate four devices can be attached to the adapter
02086     ConfigInfo->MaximumNumberOfTargets = 0;
02087 
02088     ConfigInfo->MultipleRequestPerLu = FALSE;
02089     ConfigInfo->AutoRequestSense     = FALSE;
02090     ConfigInfo->TaggedQueuing        = FALSE;
02091 
02092     if((WinVer_Id() >= WinVer_NT) ||
02093        (ConfigInfo->Length >= sizeof(_ConfigInfo->comm) + sizeof(_ConfigInfo->nt4))) {
02094         _ConfigInfo->nt4.DeviceExtensionSize         = sizeof(HW_DEVICE_EXTENSION);
02095         _ConfigInfo->nt4.SpecificLuExtensionSize     = sizeof(HW_LU_EXTENSION);    
02096         _ConfigInfo->nt4.SrbExtensionSize            = sizeof(ATA_REQ);            
02097     }
02098     if((WinVer_Id() > WinVer_2k) ||
02099        (ConfigInfo->Length >= sizeof(_ConfigInfo->comm) + sizeof(_ConfigInfo->nt4) + sizeof(_ConfigInfo->w2k))) {
02100         _ConfigInfo->w2k.Dma64BitAddresses           = 0;
02101         _ConfigInfo->w2k.ResetTargetSupported        = FALSE;
02102         _ConfigInfo->w2k.MaximumNumberOfLogicalUnits = 0;
02103     }
02104 
02105     // Save the Interrupe Mode for later use
02106     deviceExtension->InterruptMode      = ConfigInfo->InterruptMode;
02107     deviceExtension->BusInterruptLevel  = ConfigInfo->BusInterruptLevel;
02108     deviceExtension->BusInterruptVector = ConfigInfo->BusInterruptVector;
02109     deviceExtension->Channel            = 0;
02110     deviceExtension->DevIndex           = i;
02111     deviceExtension->OrigAdapterInterfaceType
02112                                         = ConfigInfo->AdapterInterfaceType;
02113     deviceExtension->AlignmentMask      = ConfigInfo->AlignmentMask;
02114     deviceExtension->AdapterInterfaceType = PCIBus;
02115 
02116     KdPrint2((PRINT_PREFIX "Reconstruct ConfigInfo\n"));
02117     ConfigInfo->MapBuffers = TRUE;
02118 #ifdef USE_OWN_DMA
02119     ConfigInfo->NeedPhysicalAddresses = FALSE;
02120 #else
02121     ConfigInfo->NeedPhysicalAddresses = TRUE;
02122 #endif //USE_OWN_DMA
02123 
02124 exit_findbm:
02125 
02126     KdPrint2((PRINT_PREFIX "return SP_RETURN_FOUND\n"));
02127     //PrintNtConsole("return SP_RETURN_FOUND, de %#x, c0.lun0 %#x\n", deviceExtension, deviceExtension->chan[0].lun[0]);
02128 
02129     return SP_RETURN_FOUND;
02130     
02131 exit_error:
02132     if (deviceExtension->lun) ExFreePool(deviceExtension->lun);
02133     if (deviceExtension->chan) ExFreePool(deviceExtension->chan);
02134     return SP_RETURN_ERROR;
02135     
02136 exit_notfound:
02137     ExFreePool(deviceExtension->lun);
02138     ExFreePool(deviceExtension->chan);
02139     return SP_RETURN_NOT_FOUND;
02140 
02141 } // end UniataFindFakeBusMasterController()
02142 
02143 
02144 /*++
02145 
02146 Routine Description:
02147 
02148     This function is called to initialize 2nd device object for
02149     multichannel controllers.
02150 
02151 Arguments:
02152 
02153     HwDeviceExtension - HBA miniport driver's adapter data storage
02154 
02155 Return Value:
02156 
02157     ULONG
02158 
02159 --*/
02160 NTSTATUS
02161 NTAPI
02162 UniataConnectIntr2(
02163     IN PVOID HwDeviceExtension
02164     )
02165 {
02166     PHW_DEVICE_EXTENSION  deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
02167     ULONG i = deviceExtension->DevIndex;
02168     NTSTATUS status;
02169     PISR2_DEVICE_EXTENSION Isr2DevExt;
02170     WCHAR devname_str[32];
02171     UNICODE_STRING devname;
02172 
02173     KdPrint2((PRINT_PREFIX "Init ISR:\n"));
02174 
02175     if(BMList[i].Isr2DevObj) {
02176         KdPrint2((PRINT_PREFIX "Already initialized %#x\n", BMList[i].Isr2DevObj));
02177         return STATUS_SUCCESS;
02178     }
02179 
02180     if(!deviceExtension->MasterDev && (deviceExtension->NumberChannels > 1) &&   // do not touch MasterDev
02181        !deviceExtension->simplexOnly && /*                        // this is unnecessary on simplex controllers
02182        !BMList[i].Isr2DevObj*/                                    // handle re-init under w2k+
02184        TRUE) {
02185         // Ok, continue...
02186         KdPrint2((PRINT_PREFIX "Multichannel native mode, go...\n"));
02187     } else {
02188         KdPrint2((PRINT_PREFIX "Unnecessary\n"));
02189         return STATUS_SUCCESS;
02190     }
02191 
02192     KdPrint2((PRINT_PREFIX "Create DO\n"));
02193 
02194     devname.Length = 
02195         _snwprintf(devname_str, sizeof(devname_str)/sizeof(WCHAR),
02196               L"\\Device\\uniata%d_2ch", i);
02197     devname.Length *= sizeof(WCHAR);
02198     devname.MaximumLength = devname.Length;
02199     devname.Buffer = devname_str;
02200 
02201     KdPrint2((PRINT_PREFIX "DO name:  len(%d, %d), %S\n", devname.Length, devname.MaximumLength, devname.Buffer));
02202 
02203     status = IoCreateDevice(SavedDriverObject, sizeof(ISR2_DEVICE_EXTENSION),
02204                             /*NULL*/ &devname, FILE_DEVICE_UNKNOWN,
02205                             0, FALSE, &(BMList[i].Isr2DevObj));
02206 
02207     if(!NT_SUCCESS(status)) {
02208         KdPrint2((PRINT_PREFIX "IoCreateDevice failed %#x\n"));
02209         return status;
02210     }
02211 
02212     KdPrint2((PRINT_PREFIX "HalGetInterruptVector\n"));
02213     KdPrint2((PRINT_PREFIX "  OrigAdapterInterfaceType=%d\n", deviceExtension->OrigAdapterInterfaceType));
02214     KdPrint2((PRINT_PREFIX "  SystemIoBusNumber=%d\n", deviceExtension->SystemIoBusNumber));
02215     KdPrint2((PRINT_PREFIX "  BusInterruptLevel=%d\n", deviceExtension->BusInterruptLevel));
02216     KdPrint2((PRINT_PREFIX "  BusInterruptVector=%d\n", deviceExtension->BusInterruptVector));
02217     BMList[i].Isr2Vector = HalGetInterruptVector(
02218         deviceExtension->OrigAdapterInterfaceType,
02219         deviceExtension->SystemIoBusNumber,
02220         deviceExtension->BusInterruptLevel,
02221         deviceExtension->BusInterruptVector,
02222         &(BMList[i].Isr2Irql),
02223         &(BMList[i].Isr2Affinity));
02224 
02225     Isr2DevExt = (PISR2_DEVICE_EXTENSION)(BMList[i].Isr2DevObj->DeviceExtension);
02226     Isr2DevExt->HwDeviceExtension = deviceExtension;
02227     Isr2DevExt->DevIndex = i;
02228 
02229     KdPrint2((PRINT_PREFIX "isr2_de %#x\n", Isr2DevExt));
02230     KdPrint2((PRINT_PREFIX "isr2_vector %#x\n", BMList[i].Isr2Vector));
02231     KdPrint2((PRINT_PREFIX "isr2_irql %#x\n", BMList[i].Isr2Irql));
02232     KdPrint2((PRINT_PREFIX "isr2_affinity %#x\n", BMList[i].Isr2Affinity));
02233 
02234 //            deviceExtension->QueueNewIrql = BMList[i].Isr2Irql;
02235 
02236     KdPrint2((PRINT_PREFIX "IoConnectInterrupt\n"));
02237     status = IoConnectInterrupt(
02238         &(BMList[i].Isr2InterruptObject),
02239         AtapiInterrupt2,
02240         Isr2DevExt,
02241         NULL,
02242         BMList[i].Isr2Vector,
02243         BMList[i].Isr2Irql,
02244         BMList[i].Isr2Irql,
02245         (KINTERRUPT_MODE)(deviceExtension->InterruptMode),
02246         TRUE,
02247         BMList[i].Isr2Affinity,
02248         FALSE);
02249 
02250     if(!NT_SUCCESS(status)) {
02251         KdPrint2((PRINT_PREFIX "IoConnectInterrupt failed\n"));
02252         IoDeleteDevice(BMList[i].Isr2DevObj);
02253         BMList[i].Isr2DevObj          = NULL;
02254         BMList[i].Isr2InterruptObject = NULL;
02255         return status;
02256     }
02257 
02258     //deviceExtension->Isr2DevObj = BMList[i].Isr2DevObj;
02259 
02260     return status;
02261 } // end UniataConnectIntr2()
02262 
02263 NTSTATUS
02264 NTAPI
02265 UniataDisconnectIntr2(
02266     IN PVOID HwDeviceExtension
02267     )
02268 {
02269     PHW_DEVICE_EXTENSION  deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
02270     ULONG i = deviceExtension->DevIndex;
02271 //    NTSTATUS status;
02272 
02273     KdPrint2((PRINT_PREFIX "Deinit ISR:\n"));
02274 
02275     if(!BMList[i].Isr2DevObj) {
02276         KdPrint2((PRINT_PREFIX "Already uninitialized %#x\n"));
02277         return STATUS_SUCCESS;
02278     }
02279 
02280     IoDisconnectInterrupt(BMList[i].Isr2InterruptObject);
02281 
02282     BMList[i].Isr2InterruptObject = NULL;
02283 
02284     IoDeleteDevice(BMList[i].Isr2DevObj);
02285 
02286     BMList[i].Isr2DevObj          = NULL;
02287     //deviceExtension->Isr2DevObj   = NULL;
02288 
02289     return STATUS_SUCCESS;
02290 } // end UniataDisconnectIntr2()
02291 
02292 #endif //UNIATA_CORE
02293 
02294 /*++
02295 
02296 Routine Description:
02297 
02298     This function is called by the OS-specific port driver after
02299     the necessary storage has been allocated, to gather information
02300     about the adapter's configuration.
02301 
02302 Arguments:
02303 
02304     HwDeviceExtension - HBA miniport driver's adapter data storage
02305     Context - Address of adapter count
02306     ArgumentString - Used to determine whether driver is client of ntldr or crash dump utility.
02307     ConfigInfo - Configuration information structure describing HBA
02308     Again - Indicates search for adapters to continue
02309 
02310 Return Value:
02311 
02312     ULONG
02313 
02314 --*/
02315 ULONG
02316 NTAPI
02317 AtapiFindController(
02318     IN PVOID HwDeviceExtension,
02319     IN PVOID Context,
02320     IN PVOID BusInformation,
02321     IN PCHAR ArgumentString,
02322     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
02323     OUT PBOOLEAN Again
02324     )
02325 {
02326     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
02327     PHW_CHANNEL          chan;
02328     PULONG               adapterCount    = (PULONG)Context;
02329     PUCHAR               ioSpace = NULL;
02330     ULONG                i;
02331     ULONG                irq=0;
02332     ULONG                portBase;
02333     ULONG                retryCount;
02334     BOOLEAN              atapiOnly;
02335     UCHAR                statusByte;
02336     BOOLEAN              preConfig = FALSE;
02337     //
02338     PIDE_REGISTERS_1 BaseIoAddress1;
02339     PIDE_REGISTERS_2 BaseIoAddress2 = NULL;
02340 
02341     // The following table specifies the ports to be checked when searching for
02342     // an IDE controller.  A zero entry terminates the search.
02343     static CONST ULONG AdapterAddresses[5] = {IO_WD1, IO_WD2, IO_WD1-8, IO_WD2-8, 0};
02344 //    CONST UCHAR Channels[5] = {0, 1, 0, 1, 0};
02345 
02346     // The following table specifies interrupt levels corresponding to the
02347     // port addresses in the previous table.
02348     static CONST ULONG InterruptLevels[5] = {14, 15, 11, 10, 0};
02349 
02350     KdPrint2((PRINT_PREFIX "AtapiFindController:\n"));
02351 
02352     if (!deviceExtension) {
02353         return SP_RETURN_ERROR;
02354     }
02355     RtlZeroMemory(deviceExtension, sizeof(HW_DEVICE_EXTENSION));
02356 
02357     KdPrint2((PRINT_PREFIX "  assume max PIO4\n"));
02358     deviceExtension->MaxTransferMode = ATA_PIO4;
02359     deviceExtension->NumberChannels = 1;
02360     deviceExtension->NumberLuns = IDE_MAX_LUN_PER_CHAN; // default
02361 
02362     if(!UniataAllocateLunExt(deviceExtension, UNIATA_ALLOCATE_NEW_LUNS)) {
02363         goto exit_error;
02364     }
02365 
02366     chan = &(deviceExtension->chan[0]);
02367 
02368     deviceExtension->AdapterInterfaceType =
02369     deviceExtension->OrigAdapterInterfaceType
02370                                         = ConfigInfo->AdapterInterfaceType;
02371 
02372 #ifndef UNIATA_CORE
02373 
02374     /* do extra chipset specific setups */
02375     AtapiReadChipConfig(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
02376     AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, CHAN_NOT_SPECIFIED);
02377 
02378     // Check to see if this is a special configuration environment.
02379     portBase = irq = 0;
02380     if (ArgumentString) {
02381 
02382         irq = AtapiParseArgumentString(ArgumentString, "Interrupt");
02383         if (irq ) {
02384 
02385             // Both parameters must be present to proceed
02386             portBase = AtapiParseArgumentString(ArgumentString, "BaseAddress");
02387             if (!portBase) {
02388 
02389                 // Try a default search for the part.
02390                 irq = 0;
02391             }
02392         }
02393     }
02394 
02395 #endif //UNIATA_CORE
02396 
02397 
02398     // Scan though the adapter address looking for adapters.
02399     if (ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart) != 0) {
02400         ioSpace =  (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
02401                                          ConfigInfo->AdapterInterfaceType,
02402                                          ConfigInfo->SystemIoBusNumber,
02403                                          (*ConfigInfo->AccessRanges)[0].RangeStart,
02404                                          (*ConfigInfo->AccessRanges)[0].RangeLength,
02405                                          (BOOLEAN) !((*ConfigInfo->AccessRanges)[0].RangeInMemory));
02406         *Again = FALSE;
02407         // Since we have pre-configured information we only need to go through this loop once
02408         preConfig = TRUE;
02409         portBase = ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[0].RangeStart);
02410         KdPrint2((PRINT_PREFIX "  preconfig, portBase=%x\n", portBase));
02411     }
02412 
02413 #ifndef UNIATA_CORE
02414     while (AdapterAddresses[*adapterCount] != 0) {
02415 #else
02416     do {
02417 #endif //UNIATA_CORE
02418 
02419         retryCount = 4;
02420         deviceExtension->DevIndex = (*adapterCount);
02421 
02422         portBase = AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"PortBase", portBase);
02423         irq      = AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"Irq", irq);
02424         
02425         for (i = 0; i < 4; i++) {
02426             // Zero device fields to ensure that if earlier devices were found,
02427             // but not claimed, the fields are cleared.
02428             deviceExtension->lun[i].DeviceFlags &= ~(DFLAGS_ATAPI_DEVICE | DFLAGS_DEVICE_PRESENT | DFLAGS_TAPE_DEVICE);
02429         }
02430         // Get the system physical address for this IO range.
02431 
02432         // Check if configInfo has the default information
02433         // if not, we go and find ourselves
02434         if (preConfig == FALSE) {
02435 
02436             if (portBase) {
02437                 ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
02438                                                 ConfigInfo->AdapterInterfaceType,
02439                                                 ConfigInfo->SystemIoBusNumber,
02440                                                 ScsiPortConvertUlongToPhysicalAddress(portBase),
02441                                                 8,
02442                                                 TRUE);
02443             } else {
02444                 ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
02445                                                 ConfigInfo->AdapterInterfaceType,
02446                                                 ConfigInfo->SystemIoBusNumber,
02447                                                 ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount]),
02448                                                 8,
02449                                                 TRUE);
02450             }
02451 
02452         } 
02453         BaseIoAddress1 = (PIDE_REGISTERS_1)ioSpace;
02454 
02455         // Update the adapter count.
02456         (*adapterCount)++;
02457 
02458         // Check if ioSpace accessible.
02459         if (!ioSpace) {
02460             KdPrint2((PRINT_PREFIX "AtapiFindController: !ioSpace\n"));
02461             continue;
02462         }
02463         // check if Primary/Secondary Master IDE claimed
02464         if((ioSpace == (PUCHAR)IO_WD1) &&
02465            (ConfigInfo->AtdiskPrimaryClaimed)) {
02466             KdPrint2((PRINT_PREFIX "AtapiFindController: AtdiskPrimaryClaimed\n"));
02467             goto not_found;
02468         } else
02469         if((ioSpace == (PUCHAR)IO_WD2) &&
02470            (ConfigInfo->AtdiskSecondaryClaimed)) {
02471             KdPrint2((PRINT_PREFIX "AtapiFindController: AtdiskSecondaryClaimed\n"));
02472             goto not_found;
02473         }
02474 
02475         // Get the system physical address for the second IO range.
02476         if (BaseIoAddress1) {
02477             if(preConfig && 
02478                !ScsiPortConvertPhysicalAddressToUlong((*ConfigInfo->AccessRanges)[1].RangeStart)) {
02479                 KdPrint2((PRINT_PREFIX "AtapiFindController: PCMCIA ?\n"));
02480                 ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
02481                                                 ConfigInfo->AdapterInterfaceType,
02482                                                 ConfigInfo->SystemIoBusNumber,
02483                                                 ScsiPortConvertUlongToPhysicalAddress((ULONGIO_PTR)BaseIoAddress1 + 0x0E),
02484                                                 ATA_ALTIOSIZE,
02485                                                 TRUE);
02486             } else {
02487                 ioSpace = (PUCHAR)ScsiPortGetDeviceBase(HwDeviceExtension,
02488                                                 ConfigInfo->AdapterInterfaceType,
02489                                                 ConfigInfo->SystemIoBusNumber,
02490                                                 ScsiPortConvertUlongToPhysicalAddress((ULONGIO_PTR)BaseIoAddress1 + ATA_ALTOFFSET),
02491                                                 ATA_ALTIOSIZE,
02492                                                 TRUE);
02493             }
02494         }
02495         BaseIoAddress2 = (PIDE_REGISTERS_2)ioSpace;
02496         KdPrint2((PRINT_PREFIX "  BaseIoAddress1=%x\n", BaseIoAddress1));
02497         KdPrint2((PRINT_PREFIX "  BaseIoAddress2=%x\n", BaseIoAddress2));
02498 
02499         UniataInitMapBase(chan, BaseIoAddress1, BaseIoAddress2);
02500         UniataInitMapBM(deviceExtension, 0, FALSE);
02501 
02502 retryIdentifier:
02503 
02504         // Select master.
02505         SelectDrive(chan, 0);
02506 
02507         // Check if card at this address.
02508         AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, 0xAA);
02509 
02510         // Check if indentifier can be read back.
02511         if ((statusByte = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow)) != 0xAA) {
02512 
02513             KdPrint2((PRINT_PREFIX "AtapiFindController: Identifier read back from Master (%#x)\n",
02514                         statusByte));
02515 
02516             statusByte = AtapiReadPort1(chan, IDX_IO2_AltStatus);
02517 
02518             if (statusByte & IDE_STATUS_BUSY) {
02519 
02520                 i = 0;
02521 
02522                 // Could be the TEAC in a thinkpad. Their dos driver puts it in a sleep-mode that
02523                 // warm boots don't clear.
02524                 do {
02525                     AtapiStallExecution(1000);
02526                     statusByte = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_Status);
02527                     KdPrint2((PRINT_PREFIX
02528                                 "AtapiFindController: First access to status %#x\n",
02529                                 statusByte));
02530                 } while ((statusByte & IDE_STATUS_BUSY) && ++i < 10);
02531 
02532                 if (retryCount-- && (!(statusByte & IDE_STATUS_BUSY))) {
02533                     goto retryIdentifier;
02534                 }
02535             }
02536 
02537             // Select slave.
02538             SelectDrive(chan, 1);
02539 
02540             // See if slave is present.
02541             AtapiWritePort1(chan, IDX_IO1_o_CylinderLow, 0xAA);
02542 
02543             if ((statusByte = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow)) != 0xAA) {
02544 
02545                 KdPrint2((PRINT_PREFIX
02546                             "AtapiFindController: Identifier read back from Slave (%#x)\n",
02547                             statusByte));
02548 not_found:
02549                 // No controller at this base address.
02550                 if(BaseIoAddress1) {
02551                     ScsiPortFreeDeviceBase(HwDeviceExtension,
02552                                            (PCHAR)BaseIoAddress1);
02553                     BaseIoAddress1 = NULL;
02554                 }
02555                 if(BaseIoAddress2) {
02556                     ScsiPortFreeDeviceBase(HwDeviceExtension,
02557                                            (PCHAR)BaseIoAddress2);
02558                     BaseIoAddress2 = NULL;
02559                 }
02560                 continue;
02561             }
02562         }
02563 
02564         // Fill in the access array information only if default params are not in there.
02565         if (preConfig == FALSE) {
02566 
02567             // An adapter has been found request another call, only if we didn't get preconfigured info.
02568             *Again = TRUE;
02569 
02570             if (portBase) {
02571                 (*ConfigInfo->AccessRanges)[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(portBase);
02572             } else {
02573                 (*ConfigInfo->AccessRanges)[0].RangeStart =
02574                     ScsiPortConvertUlongToPhysicalAddress(AdapterAddresses[*adapterCount - 1]);
02575             }
02576 
02577             (*ConfigInfo->AccessRanges)[0].RangeLength = 8;
02578             (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
02579 
02580             // Indicate the interrupt level corresponding to this IO range.
02581             if (irq) {
02582                 ConfigInfo->BusInterruptLevel = irq;
02583             } else {
02584                 ConfigInfo->BusInterruptLevel = InterruptLevels[*adapterCount - 1];
02585             }
02586 
02587             if (ConfigInfo->AdapterInterfaceType == MicroChannel) {
02588                 ConfigInfo->InterruptMode = LevelSensitive;
02589             } else {
02590                 ConfigInfo->InterruptMode = Latched;
02591             }
02592         }
02593 
02594         ConfigInfo->NumberOfBuses = 1;
02595         ConfigInfo->MaximumNumberOfTargets = IDE_MAX_LUN_PER_CHAN;
02596 
02597         // Indicate maximum transfer length is 64k.
02598         ConfigInfo->MaximumTransferLength = 0x10000;
02599         deviceExtension->MaximumDmaTransferLength = ConfigInfo->MaximumTransferLength;
02600 
02601         KdPrint2((PRINT_PREFIX "de %#x, Channel ???\n", deviceExtension));
02602         //PrintNtConsole("de %#x, Channel %#x, nchan %#x\n",deviceExtension, channel, deviceExtension->NumberChannels);
02603 
02604         KdPrint2((PRINT_PREFIX "chan = %#x\n", chan));
02605         //PrintNtConsole("chan = %#x, c=%#x\n", chan, c);
02606         chan->DeviceExtension = deviceExtension;
02607         chan->lChannel        = 0;
02608         chan->lun[0] = &(deviceExtension->lun[0]);
02609         chan->lun[1] = &(deviceExtension->lun[1]);
02610 
02611         /* do extra channel-specific setups */
02612         AtapiReadChipConfig(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, 0);
02613         AtapiChipInit(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, 0);
02614 
02615         KdPrint2((PRINT_PREFIX
02616                    "AtapiFindController: Found IDE at %#x\n",
02617                    BaseIoAddress1));
02618 
02619         // For Daytona, the atdisk driver gets the first shot at the
02620         // primary and secondary controllers.
02621         if (preConfig == FALSE) {
02622 
02623             if (*adapterCount - 1 < 2) {
02624 
02625                 // Determine whether this driver is being initialized by the
02626                 // system or as a crash dump driver.
02627                 if (ArgumentString) {
02628 
02629 #ifndef UNIATA_CORE
02630                     if (AtapiParseArgumentString(ArgumentString, "dump") == 1) {
02631                         KdPrint2((PRINT_PREFIX
02632                                    "AtapiFindController: Crash dump\n"));
02633                         atapiOnly = FALSE;
02634                         deviceExtension->DriverMustPoll = TRUE;
02635                     } else {
02636                         KdPrint2((PRINT_PREFIX
02637                                    "AtapiFindController: Atapi Only\n"));
02638                         atapiOnly = TRUE;
02639                         deviceExtension->DriverMustPoll = FALSE;
02640                     }
02641 #endif //UNIATA_CORE
02642                 } else {
02643 
02644                     KdPrint2((PRINT_PREFIX
02645                                "AtapiFindController: Atapi Only (2)\n"));
02646                     atapiOnly = TRUE;
02647                     deviceExtension->DriverMustPoll = FALSE;
02648                 }
02649 
02650             } else {
02651                 atapiOnly = FALSE;
02652             }
02653 
02654         } else {
02655 
02656             atapiOnly = FALSE;
02657             deviceExtension->DriverMustPoll = FALSE;
02658 
02659         }// preConfig check
02660 
02661         // Save the Interrupe Mode for later use
02662         deviceExtension->InterruptMode = ConfigInfo->InterruptMode;
02663 
02664         KdPrint2((PRINT_PREFIX
02665                    "AtapiFindController: look for devices\n"));
02666         // Search for devices on this controller.
02667         if (FindDevices(HwDeviceExtension,
02668                         0,
02669                         0 /* Channel */)) {
02670 
02671             KdPrint2((PRINT_PREFIX
02672                        "AtapiFindController: detected\n"));
02673             // Claim primary or secondary ATA IO range.
02674             if (portBase) {
02675                 switch (portBase) {
02676                 case IO_WD2:
02677                     ConfigInfo->AtdiskSecondaryClaimed = TRUE;
02678                     chan->PrimaryAddress = FALSE;
02679                     break;
02680                 case IO_WD1:
02681                     ConfigInfo->AtdiskPrimaryClaimed = TRUE;
02682                     chan->PrimaryAddress = TRUE;
02683                     break;
02684                 default:
02685                     break;
02686                 }
02687             } else {
02688                 if (*adapterCount == 1) {
02689                     ConfigInfo->AtdiskPrimaryClaimed = TRUE;
02690                     chan->PrimaryAddress = TRUE;
02691                 } else if (*adapterCount == 2) {
02692                     ConfigInfo->AtdiskSecondaryClaimed = TRUE;
02693                     chan->PrimaryAddress = FALSE;
02694                 }
02695             }
02696 
02697             if(deviceExtension->AdapterInterfaceType == Isa) {
02698                 IsaCount++;
02699             } else
02700             if(deviceExtension->AdapterInterfaceType == MicroChannel) {
02701                 MCACount++;
02702             }
02703 
02704             KdPrint2((PRINT_PREFIX 
02705                        "AtapiFindController: return SP_RETURN_FOUND\n"));
02706             return(SP_RETURN_FOUND);
02707         }
02708 #ifndef UNIATA_CORE
02709     }
02710 #else
02711     } while(FALSE);
02712 #endif //UNIATA_CORE
02713 
02714     // The entire table has been searched and no adapters have been found.
02715     // There is no need to call again and the device base can now be freed.
02716     // Clear the adapter count for the next bus.
02717     *Again = FALSE;
02718     *(adapterCount) = 0;
02719 
02720     KdPrint2((PRINT_PREFIX
02721                "AtapiFindController: return SP_RETURN_NOT_FOUND\n"));
02722     ExFreePool(deviceExtension->lun);
02723     ExFreePool(deviceExtension->chan);
02724     return(SP_RETURN_NOT_FOUND);
02725 
02726 exit_error:
02727     if (deviceExtension->lun) ExFreePool(deviceExtension->lun);
02728     if (deviceExtension->chan) ExFreePool(deviceExtension->chan);
02729     return SP_RETURN_ERROR;
02730     
02731 } // end AtapiFindController()
02732 
02733 BOOLEAN
02734 NTAPI
02735 UniataAnybodyHome(
02736     IN PVOID   HwDeviceExtension,
02737     IN ULONG   lChannel,
02738     IN ULONG   deviceNumber
02739     )
02740 {
02741     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
02742     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
02743     //ULONG                ldev = GET_LDEV2(lChannel, deviceNumber, 0);
02744     PHW_LU_EXTENSION     LunExt = chan->lun[deviceNumber];
02745 
02746     SATA_SSTATUS_REG     SStatus;
02747     UCHAR                signatureLow;
02748     UCHAR                signatureHigh;
02749 
02750     if(LunExt->DeviceFlags & DFLAGS_HIDDEN) {
02751         KdPrint2((PRINT_PREFIX "  hidden\n"));
02752         UniataForgetDevice(LunExt);
02753         return FALSE;
02754     }
02755     // Select the device.
02756     SelectDrive(chan, deviceNumber);
02757 
02758     signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
02759     signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
02760 
02761     if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
02762         KdPrint2((PRINT_PREFIX "  ATAPI at home\n", signatureLow));
02763         return TRUE;
02764     }
02765 
02766     if(!UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
02767         AtapiStallExecution(10);
02768 
02769         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0x55);
02770         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0x55);
02771         AtapiStallExecution(5);
02772         signatureLow = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
02773         if(signatureLow != 0x55) {
02774             KdPrint2((PRINT_PREFIX "  nobody home! %#x != 0x55\n", signatureLow));
02775             UniataForgetDevice(LunExt);
02776             return FALSE;
02777         }
02778 
02779         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0xAA);
02780         AtapiWritePort1(chan, IDX_IO1_o_BlockNumber, 0xAA);
02781         AtapiStallExecution(5);
02782         signatureLow = AtapiReadPort1(chan, IDX_IO1_i_BlockNumber);
02783         if(signatureLow != 0xAA) {
02784             KdPrint2((PRINT_PREFIX "  nobody home! %#x != 0xAA\n", signatureLow));
02785             UniataForgetDevice(LunExt);
02786             return FALSE;
02787         }
02788     } else {
02789 
02790         SStatus.Reg = UniataSataReadPort4(chan, IDX_SATA_SStatus, deviceNumber);
02791         KdPrint2((PRINT_PREFIX "SStatus %x\n", SStatus.Reg));
02792         if(SStatus.DET <= SStatus_DET_Dev_NoPhy) {
02793             KdPrint2((PRINT_PREFIX "  SATA DET <= SStatus_DET_Dev_NoPhy\n"));
02794             return FALSE;
02795         }
02796         if(SStatus.SPD < SStatus_SPD_Gen1) {
02797             KdPrint2((PRINT_PREFIX "  SATA SPD < SStatus_SPD_Gen1\n"));
02798             return FALSE;
02799         }
02800         if(SStatus.IPM == SStatus_IPM_NoDev) {
02801             KdPrint2((PRINT_PREFIX "  SATA IPN == SStatus_IPM_NoDev\n"));
02802             return FALSE;
02803         }
02804     }
02805 
02806     return TRUE;
02807 } // end UniataAnybodyHome()
02808 
02809 ULONG
02810 NTAPI
02811 CheckDevice(
02812     IN PVOID   HwDeviceExtension,
02813     IN ULONG   lChannel,
02814     IN ULONG   deviceNumber,
02815     IN BOOLEAN ResetDev
02816     )
02817 {
02818     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
02819     PHW_CHANNEL          chan = &(deviceExtension->chan[lChannel]);
02820     //ULONG                ldev = GET_LDEV2(lChannel, deviceNumber, 0);
02821     PHW_LU_EXTENSION     LunExt;
02822 
02823     UCHAR                signatureLow,
02824                          signatureHigh;
02825     UCHAR                statusByte;
02826     ULONG                RetVal=0;
02827     ULONG                waitCount = 10000;
02828 
02829     KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x\n",
02830                deviceNumber));
02831 
02832     if(deviceNumber > chan->NumberLuns) {
02833         return 0;
02834     }
02835 
02836     LunExt = chan->lun[deviceNumber];
02837 
02838     if(ResetDev && (deviceExtension->HwFlags & UNIATA_AHCI)) {
02839         KdPrint2((PRINT_PREFIX "CheckDevice: reset AHCI dev\n"));
02840         if(UniataAhciSoftReset(HwDeviceExtension, chan->lChannel, deviceNumber) == (ULONG)(-1)) {
02841             KdPrint2((PRINT_PREFIX "CheckDevice: (no dev)\n"));
02842             UniataForgetDevice(LunExt);
02843             return 0;
02844         }
02845     } else
02846     if(ResetDev) {
02847         KdPrint2((PRINT_PREFIX "CheckDevice: reset dev\n"));
02848 
02849         // Reset device
02850         AtapiSoftReset(chan, deviceNumber);
02851 
02852         if(!UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
02853             return 0;
02854         }
02855         statusByte = WaitOnBusy(chan);
02856 
02857         if((statusByte | IDE_STATUS_BUSY) == 0xff) {
02858             KdPrint2((PRINT_PREFIX
02859                         "CheckDevice: bad status %x\n", statusByte));
02860         } else
02861         if(statusByte != 0xff && (statusByte & IDE_STATUS_BUSY)) {
02862             // Perform hard-reset.
02863             KdPrint2((PRINT_PREFIX
02864                         "CheckDevice: BUSY\n"));
02865 
02866             AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_RESET_CONTROLLER );
02867             AtapiStallExecution(500 * 1000);
02868             AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_REENABLE_CONTROLLER);
02869             SelectDrive(chan, deviceNumber & 0x01);
02870 
02871             do {
02872                 // Wait for Busy to drop.
02873                 AtapiStallExecution(100);
02874                 GetStatus(chan, statusByte);
02875 
02876             } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
02877 
02878             GetBaseStatus(chan, statusByte);
02879             KdPrint2((PRINT_PREFIX
02880                         "CheckDevice: status after hard reset %x\n", statusByte));
02881         }
02882 
02883         if((statusByte | IDE_STATUS_BUSY) == 0xff) {
02884             KdPrint2((PRINT_PREFIX 
02885                         "CheckDevice: no dev ?\n"));
02886         } else
02887         if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
02888         //if(deviceExtension->HwFlags & UNIATA_SATA) {
02889             KdPrint2((PRINT_PREFIX
02890                         "CheckDevice: try enable SATA Phy\n"));
02891             statusByte = UniataSataPhyEnable(HwDeviceExtension, lChannel, deviceNumber);
02892             if(statusByte == 0xff) {
02893                 KdPrint2((PRINT_PREFIX "CheckDevice: status %#x (no dev)\n", statusByte));
02894                 UniataForgetDevice(LunExt);
02895                 return 0;
02896             }
02897         }
02898     }
02899 
02900     if(deviceExtension->HwFlags & UNIATA_AHCI) {
02901         RetVal = LunExt->DeviceFlags;
02902         signatureLow = signatureHigh = 0; // make GCC happy
02903     } else {
02904         // Select the device.
02905         SelectDrive(chan, deviceNumber);
02906 
02907         if(!UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
02908             return 0;
02909         }
02910 
02911         statusByte = WaitOnBaseBusyLong(chan);
02912 
02913         GetBaseStatus(chan, statusByte);
02914         if(deviceExtension->HwFlags & UNIATA_SATA) {
02915             UniataSataClearErr(HwDeviceExtension, lChannel, UNIATA_SATA_IGNORE_CONNECT, deviceNumber);
02916         }
02917 
02918         KdPrint2((PRINT_PREFIX "CheckDevice: status %#x\n", statusByte));
02919         if(((statusByte | IDE_STATUS_BUSY) == 0xff) ||
02920             (statusByte & IDE_STATUS_BUSY)) {
02921             KdPrint2((PRINT_PREFIX "CheckDevice: busy => return\n"));
02922             UniataForgetDevice(LunExt);
02923             return 0;
02924         }
02925 
02926         signatureLow = AtapiReadPort1(chan, IDX_IO1_i_CylinderLow);
02927         signatureHigh = AtapiReadPort1(chan, IDX_IO1_i_CylinderHigh);
02928     }
02929 
02930     // set default costs
02931     LunExt->RwSwitchCost  = REORDER_COST_SWITCH_RW_HDD;
02932     LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_HDD;
02933     LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_HDD;
02934 
02935     if(deviceExtension->HwFlags & UNIATA_AHCI) {
02936         if(RetVal & DFLAGS_DEVICE_PRESENT) {
02937             if(IssueIdentify(HwDeviceExtension,
02938                               deviceNumber,
02939                               lChannel,
02940                               (RetVal & DFLAGS_ATAPI_DEVICE) ? IDE_COMMAND_ATAPI_IDENTIFY : IDE_COMMAND_IDENTIFY,
02941                               FALSE)) {
02942                 // OK
02943                 KdPrint2((PRINT_PREFIX "CheckDevice: detected AHCI Device %#x\n",
02944                            deviceNumber));
02945             } else {
02946                 RetVal &= ~DFLAGS_ATAPI_DEVICE;
02947                 LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE;
02948             }
02949         }
02950     } else
02951     if (signatureLow == ATAPI_MAGIC_LSB && signatureHigh == ATAPI_MAGIC_MSB) {
02952 
02953         KdPrint2((PRINT_PREFIX "CheckDevice: ATAPI signature found\n"));
02954         // ATAPI signature found.
02955         // Issue the ATAPI identify command if this
02956         // is not for the crash dump utility.
02957 
02958         if (!deviceExtension->DriverMustPoll) {
02959 
02960             // Issue ATAPI packet identify command.
02961             if (IssueIdentify(HwDeviceExtension,
02962                               deviceNumber,
02963                               lChannel,
02964                               IDE_COMMAND_ATAPI_IDENTIFY, FALSE)) {
02965 
02966                 // Indicate ATAPI device.
02967                 KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x is ATAPI\n",
02968                            deviceNumber));
02969 
02970                 RetVal = DFLAGS_DEVICE_PRESENT | DFLAGS_ATAPI_DEVICE;
02971                 LunExt->DeviceFlags |= (DFLAGS_DEVICE_PRESENT | DFLAGS_ATAPI_DEVICE);
02972 
02973                 // some ATAPI devices doesn't work with DPC on CMD-649
02974                 // and probably some other controllers
02975                 if(deviceExtension->HwFlags & UNIATA_NO_DPC_ATAPI) {
02976                     /* CMD 649, ROSB SWK33, ICH4 */
02977                     KdPrint2((PRINT_PREFIX "CheckDevice: UNIATA_NO_DPC_ATAPI\n"));
02978                     deviceExtension->UseDpc = FALSE;
02979                 }
02980 
02981                 GetStatus(chan, statusByte);
02982                 if (statusByte & IDE_STATUS_ERROR) {
02983                     AtapiSoftReset(chan, deviceNumber);
02984                 }
02985 
02986             } else {
02987 
02988                 // Indicate no working device.
02989                 KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x not responding\n",
02990                            deviceNumber));
02991 
02992                 UniataForgetDevice(LunExt);
02993                 RetVal = 0;
02994             }
02995             GetBaseStatus(chan, statusByte);
02996 
02997         }
02998 
02999     } else {
03000 
03001         KdPrint2((PRINT_PREFIX "CheckDevice: IDE device check\n"));
03002         // Issue IDE Identify. If an Atapi device is actually present, the signature
03003         // will be asserted, and the drive will be recognized as such.
03004         if(deviceExtension->DWordIO) {
03005             KdPrint2((PRINT_PREFIX "  try 32bit IO\n"));
03006             LunExt->DeviceFlags |= DFLAGS_DWORDIO_ENABLED;
03007         }
03008         if (IssueIdentify(HwDeviceExtension,
03009                           deviceNumber,
03010                           lChannel,
03011                           IDE_COMMAND_IDENTIFY, FALSE)) {
03012 
03013             // IDE drive found.
03014             KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x is IDE\n",
03015                        deviceNumber));
03016 
03017             // Indicate IDE - not ATAPI device.
03018             RetVal = DFLAGS_DEVICE_PRESENT;
03019             LunExt->DeviceFlags |= DFLAGS_DEVICE_PRESENT;
03020             LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE;
03021         }
03022         GetBaseStatus(chan, statusByte);
03023     }
03024     KdPrint2((PRINT_PREFIX "CheckDevice: check status: %sfound\n", RetVal ? "" : "not "));
03025     return RetVal;
03026 } // end CheckDevice()
03027 
03028 
03029 /*++
03030 
03031 Routine Description:
03032 
03033     This routine is called from AtapiFindController to identify
03034     devices attached to an IDE controller.
03035 
03036 Arguments:
03037 
03038     HwDeviceExtension - HBA miniport driver's adapter data storage
03039     AtapiOnly - Indicates that routine should return TRUE only if
03040         an ATAPI device is attached to the controller.
03041 
03042 Return Value:
03043 
03044     TRUE - True if devices found.
03045 
03046 --*/
03047 BOOLEAN
03048 NTAPI
03049 FindDevices(
03050     IN PVOID HwDeviceExtension,
03051     IN ULONG   Flags,
03052     IN ULONG   Channel
03053     )
03054 {
03055     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
03056     PHW_CHANNEL          chan = &(deviceExtension->chan[Channel]);
03057     PHW_LU_EXTENSION     LunExt;
03058     BOOLEAN              deviceResponded = FALSE,
03059                          skipSetParameters = FALSE;
03060     ULONG                waitCount = 10000;
03061     //ULONG                deviceNumber;
03062     ULONG                i;
03063     UCHAR                statusByte;
03064     ULONG                max_ldev;
03065     BOOLEAN              AtapiOnly = FALSE;
03066 
03067     KdPrint2((PRINT_PREFIX "FindDevices:\n"));
03068 
03069     // Disable interrupts
03070     AtapiDisableInterrupts(deviceExtension, Channel);
03071 //    AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_DISABLE_INTERRUPTS | IDE_DC_A_4BIT );
03072 
03073     // Clear expecting interrupt flag and current SRB field.
03074     chan->ExpectingInterrupt = FALSE;
03075 //    chan->CurrentSrb = NULL;
03076 //    max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : IDE_MAX_LUN_PER_CHAN;
03077     max_ldev = (chan->ChannelCtrlFlags & CTRFLAGS_NO_SLAVE) ? 1 : deviceExtension->NumberLuns;
03078     KdPrint2((PRINT_PREFIX "  max_ldev %d\n", max_ldev));
03079 
03080     // Search for devices.
03081     for (i = 0; i < max_ldev; i++) {
03082         //AtapiDisableInterrupts(deviceExtension, Channel);
03083         if(Flags & UNIATA_FIND_DEV_UNHIDE) {
03084             chan->lun[i]->DeviceFlags &= ~DFLAGS_HIDDEN;
03085         }
03086         deviceResponded |= 
03087             (CheckDevice(HwDeviceExtension, Channel, i, TRUE) != 0);
03088         //AtapiEnableInterrupts(deviceExtension, Channel);
03089     }
03090 
03091     if(chan->DeviceExtension->HwFlags & UNIATA_AHCI) {
03092         AtapiEnableInterrupts(deviceExtension, Channel);
03093         KdPrint2((PRINT_PREFIX
03094                    "FindDevices: returning %d (AHCI)\n",
03095                    deviceResponded));
03096         return deviceResponded;
03097     }
03098 
03099     for (i = 0; i < max_ldev; i++) {
03100         LunExt = chan->lun[i];
03101 
03102         if ((  LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) &&
03103              !(LunExt->DeviceFlags & DFLAGS_LBA_ENABLED) &&
03104              !(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) && deviceResponded) {
03105 
03106             // This hideous hack is to deal with ESDI devices that return
03107             // garbage geometry in the IDENTIFY data.
03108             // This is ONLY for the crashdump environment as
03109             // these are ESDI devices.
03110             if (LunExt->IdentifyData.SectorsPerTrack ==
03111                     0x35 &&
03112                 LunExt->IdentifyData.NumberOfHeads ==
03113                     0x07) {
03114 
03115                 KdPrint2((PRINT_PREFIX 
03116                            "FindDevices: Found nasty Compaq ESDI!\n"));
03117 
03118                 // Change these values to something reasonable.
03119                 LunExt->IdentifyData.SectorsPerTrack =
03120                     0x34;
03121                 LunExt->IdentifyData.NumberOfHeads =
03122                     0x0E;
03123             }
03124 
03125             if (LunExt->IdentifyData.SectorsPerTrack ==
03126                     0x35 &&
03127                 LunExt->IdentifyData.NumberOfHeads ==
03128                     0x0F) {
03129 
03130                 KdPrint2((PRINT_PREFIX 
03131                            "FindDevices: Found nasty Compaq ESDI!\n"));
03132 
03133                 // Change these values to something reasonable.
03134                 LunExt->IdentifyData.SectorsPerTrack =
03135                     0x34;
03136                 LunExt->IdentifyData.NumberOfHeads =
03137                     0x0F;
03138             }
03139 
03140 
03141             if (LunExt->IdentifyData.SectorsPerTrack ==
03142                     0x36 &&
03143                 LunExt->IdentifyData.NumberOfHeads ==
03144                     0x07) {
03145 
03146                 KdPrint2((PRINT_PREFIX "FindDevices: Found nasty UltraStor ESDI!\n"));
03147 
03148                 // Change these values to something reasonable.
03149                 LunExt->IdentifyData.SectorsPerTrack =
03150                     0x3F;
03151                 LunExt->IdentifyData.NumberOfHeads =
03152                     0x10;
03153                 skipSetParameters = TRUE;
03154             }
03155 
03156 
03157             if (skipSetParameters)
03158                 continue;
03159 
03160             statusByte = WaitOnBusy(chan);
03161 
03162             // Select the device.
03163             SelectDrive(chan, i & 0x01);
03164             GetStatus(chan, statusByte);
03165 
03166             if (statusByte & IDE_STATUS_ERROR) {
03167 
03168                 // Reset the device.
03169                 KdPrint2((PRINT_PREFIX
03170                             "FindDevices: Resetting controller before SetDriveParameters.\n"));
03171 
03172                 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_RESET_CONTROLLER );
03173                 AtapiStallExecution(500 * 1000);
03174                 AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_REENABLE_CONTROLLER);
03175                 SelectDrive(chan, i & 0x01);
03176 
03177                 do {
03178                     // Wait for Busy to drop.
03179                     AtapiStallExecution(100);
03180                     GetStatus(chan, statusByte);
03181 
03182                 } while ((statusByte & IDE_STATUS_BUSY) && waitCount--);
03183             }
03184 
03185             statusByte = WaitOnBusy(chan);
03186 
03187             KdPrint2((PRINT_PREFIX
03188                         "FindDevices: Status before SetDriveParameters: (%#x) (%#x)\n",
03189                         statusByte,
03190                         AtapiReadPort1(chan, IDX_IO1_i_DriveSelect)));
03191 
03192             GetBaseStatus(chan, statusByte);
03193 
03194             // Use the IDENTIFY data to set drive parameters.
03195             if (!SetDriveParameters(HwDeviceExtension,i,Channel)) {
03196 
03197                 KdPrint2((PRINT_PREFIX
03198                            "FindDevices: Set drive parameters for device %d failed\n",
03199                            i));
03200                 // Don't use this device as writes could cause corruption.
03201                 LunExt->DeviceFlags &= ~DFLAGS_DEVICE_PRESENT;
03202                 UniataForgetDevice(LunExt);
03203                 continue;
03204 
03205             }
03206             if (LunExt->DeviceFlags & DFLAGS_REMOVABLE_DRIVE) {
03207 
03208                 // Pick up ALL IDE removable drives that conform to Yosemite V0.2...
03209                 AtapiOnly = FALSE;
03210             }
03211 
03212             // Indicate that a device was found.
03213             if (!AtapiOnly) {
03214                 deviceResponded = TRUE;
03215             }
03216         }
03217     }
03218 
03219 /*    // Reset the controller. This is a feeble attempt to leave the ESDI
03220     // controllers in a state that ATDISK driver will recognize them.
03221     // The problem in ATDISK has to do with timings as it is not reproducible
03222     // in debug. The reset should restore the controller to its poweron state
03223     // and give the system enough time to settle.
03224     if (!deviceResponded) {
03225 
03226         AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_RESET_CONTROLLER );
03227         AtapiStallExecution(50 * 1000);
03228         AtapiWritePort1(chan, IDX_IO2_o_Control,IDE_DC_REENABLE_CONTROLLER);
03229     }
03230 */
03231     if(deviceResponded) {
03232         for (i = 0; i < max_ldev; i++) {
03233             LunExt = chan->lun[i];
03234 
03235             KdPrint2((PRINT_PREFIX 
03236                        "FindDevices: select %d dev to clear INTR\n", i));
03237             SelectDrive(chan, i);
03238             GetBaseStatus(chan, statusByte);
03239             KdPrint2((PRINT_PREFIX 
03240                        "FindDevices: statusByte=%#x\n", statusByte));
03241         }
03242         for (i = 0; i < max_ldev; i++) {
03243             LunExt = chan->lun[i];
03244 
03245             if(LunExt->DeviceFlags & DFLAGS_DEVICE_PRESENT) {
03246                 // Make sure some device (master is preferred) is selected on exit.
03247                 KdPrint2((PRINT_PREFIX 
03248                            "FindDevices: select %d dev on exit\n", i));
03249                 SelectDrive(chan, i);
03250                 break;
03251             }
03252         }
03253     }
03254 
03255     GetBaseStatus(chan, statusByte);
03256     // Enable interrupts
03257     AtapiEnableInterrupts(deviceExtension, Channel);
03258 //    AtapiWritePort1(chan, IDX_IO2_o_Control, IDE_DC_A_4BIT );
03259     GetBaseStatus(chan, statusByte);
03260 
03261     KdPrint2((PRINT_PREFIX
03262                "FindDevices: returning %d\n",
03263                deviceResponded));
03264 
03265     return deviceResponded;
03266 
03267 } // end FindDevices()

Generated on Sat May 26 2012 04:26:57 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.