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_dma.cpp
Go to the documentation of this file.
00001 /*++
00002 
00003 Copyright (c) 2002-2011 Alexander A. Telyatnikov (Alter)
00004 
00005 Module Name:
00006     id_dma.cpp
00007 
00008 Abstract:
00009     This is the miniport driver for ATAPI IDE controllers
00010     With Busmaster DMA support
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     This module is a port from FreeBSD 4.3-6.1 ATA driver (ata-dma.c, ata-chipset.c) by
00034          Søren Schmidt, Copyright (c) 1998-2008
00035 
00036     Changed defaulting-to-generic-PIO/DMA policy
00037     Added PIO settings for VIA
00038     Optimized VIA/AMD/nVidia init part
00039     Optimized Promise TX2 init part
00040     Optimized Intel init part
00041          by Alex A. Telyatnikov (Alter) (c) 2002-2007
00042 
00043 
00044 --*/
00045 
00046 #include "stdafx.h"
00047 
00048 static const ULONG valid_udma[7] = {0,0,2,0,4,5,6};
00049 
00050 static const CHAR retry_Wdma[MAX_RETRIES+1] = {2, 2, 2,-1,-1,-1};
00051 static const CHAR retry_Udma[MAX_RETRIES+1] = {6, 2,-1,-1,-1,-1};
00052 
00053 PHYSICAL_ADDRESS ph4gb = {{0xFFFFFFFF, 0}};
00054 
00055 VOID
00056 NTAPI
00057 cyrix_timing (
00058     IN PHW_DEVICE_EXTENSION deviceExtension,
00059     IN ULONG dev,               // physical device number (0-3)
00060     IN CHAR  mode
00061     );
00062 
00063 VOID
00064 NTAPI
00065 promise_timing (
00066     IN PHW_DEVICE_EXTENSION deviceExtension,
00067     IN ULONG dev,               // physical device number (0-3)
00068     IN CHAR  mode
00069     );
00070 
00071 VOID
00072 NTAPI
00073 hpt_timing (
00074     IN PHW_DEVICE_EXTENSION deviceExtension,
00075     IN ULONG dev,               // physical device number (0-3)
00076     IN CHAR  mode
00077     );
00078 
00079 VOID
00080 NTAPI
00081 via82c_timing (
00082     IN PHW_DEVICE_EXTENSION deviceExtension,
00083     IN ULONG dev,               // physical device number (0-3)
00084     IN CHAR  mode
00085     );
00086 
00087 ULONG
00088 NTAPI
00089 hpt_cable80(
00090     IN PHW_DEVICE_EXTENSION deviceExtension,
00091     IN ULONG channel            // physical channel number (0-1)
00092     );
00093 
00094 #define ATAPI_DEVICE(de, ldev)    (de->lun[ldev].DeviceFlags & DFLAGS_ATAPI_DEVICE)
00095 
00096 ULONG
00097 NTAPI
00098 AtapiVirtToPhysAddr_(
00099     IN PVOID HwDeviceExtension,
00100     IN PSCSI_REQUEST_BLOCK Srb,
00101     IN PUCHAR data,
00102     IN PULONG count,
00103    OUT PULONG ph_addru
00104     )
00105 {
00106     PHYSICAL_ADDRESS ph_addr;
00107     ULONG addr;
00108 
00109     ph_addr = MmGetPhysicalAddress(data);
00110     if(!ph_addru && ph_addr.HighPart) {
00111         // do so until we add 64bit address support
00112         // or some workaround
00113         *count = 0;
00114         return -1;
00115     }
00116 
00117     (*ph_addru) = ph_addr.HighPart;
00118     //addr = ScsiPortConvertPhysicalAddressToUlong(ph_addr);
00119     addr = ph_addr.LowPart;
00120     if(!addr && !ph_addr.HighPart) {
00121         *count = 0;
00122         return 0;
00123     }
00124     if(!Srb) {
00125         *count = sizeof(BM_DMA_ENTRY)*ATA_DMA_ENTRIES;
00126     } else {
00127         *count = PAGE_SIZE - (addr & (PAGE_SIZE-1));
00128     }
00129     return addr;
00130 } // end AtapiVirtToPhysAddr_()
00131 
00132 VOID
00133 NTAPI
00134 AtapiDmaAlloc(
00135     IN PVOID HwDeviceExtension,
00136     IN PPORT_CONFIGURATION_INFORMATION ConfigInfo,
00137     IN ULONG lChannel          // logical channel,
00138     )
00139 {
00140 #ifdef USE_OWN_DMA
00141     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
00142     PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
00143     ULONG c = lChannel;
00144     ULONG i;
00145     ULONG ph_addru;
00146 
00147     deviceExtension->chan[c].CopyDmaBuffer = FALSE;
00148 
00149     if(!deviceExtension->Host64 && (WinVer_Id() > WinVer_NT)) {
00150         KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: allocate tmp buffers below 4Gb\n"));
00151         chan->DB_PRD = MmAllocateContiguousMemory(sizeof(((PATA_REQ)NULL)->dma_tab), ph4gb);
00152         if(chan->DB_PRD) {
00153             chan->DB_PRD_PhAddr = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)(chan->DB_PRD), &i, &ph_addru);
00154             if(!chan->DB_PRD_PhAddr || !i || ((LONG)(chan->DB_PRD_PhAddr) == -1)) {
00155                 KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: No DB PRD BASE\n" ));
00156                 chan->DB_PRD = NULL;
00157                 chan->DB_PRD_PhAddr = 0;
00158                 return;
00159             }
00160             if(ph_addru) {
00161                 KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: No DB PRD below 4Gb\n" ));
00162                 goto err_1;
00163             }
00164         }
00165         chan->DB_IO = MmAllocateContiguousMemory(deviceExtension->MaximumDmaTransferLength, ph4gb);
00166         if(chan->DB_IO) {
00167             chan->DB_IO_PhAddr = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)(chan->DB_IO), &i, &ph_addru);
00168             if(!chan->DB_IO_PhAddr || !i || ((LONG)(chan->DB_IO_PhAddr) == -1)) {
00169                 KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: No DB IO BASE\n" ));
00170 err_1:
00171                 MmFreeContiguousMemory(chan->DB_PRD);
00172                 chan->DB_PRD = NULL;
00173                 chan->DB_PRD_PhAddr = 0;
00174                 chan->DB_IO = NULL;
00175                 chan->DB_IO_PhAddr = 0;
00176                 return;
00177             }
00178             if(ph_addru) {
00179                 KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: No DB IO below 4Gb\n" ));
00180                 MmFreeContiguousMemory(chan->DB_IO);
00181                 goto err_1;
00182             }
00183         }
00184     }
00185 
00186 
00187     if(deviceExtension->HwFlags & UNIATA_AHCI) {
00188         KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: AHCI\n" ));
00189         if(chan->AhciCtlBlock) {
00190             KdPrint2((PRINT_PREFIX "  already initialized %x\n", chan->AhciCtlBlock));
00191             return;
00192         }
00193         // Need 1K-byte alignment
00194         chan->AhciCtlBlock0 = (PIDE_AHCI_CHANNEL_CTL_BLOCK)MmAllocateContiguousMemory(
00195                 sizeof(IDE_AHCI_CHANNEL_CTL_BLOCK)+AHCI_CLB_ALIGNEMENT_MASK,
00196                 ph4gb);
00197         if(chan->AhciCtlBlock0) {
00198             union {
00199                 PUCHAR AhciCtlBlock;
00200                 ULONGLONG AhciCtlBlock64;
00201             };
00202             AhciCtlBlock64 = 0;
00203             AhciCtlBlock = (PUCHAR)chan->AhciCtlBlock0;
00204 
00205             KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: CLP BASE %I64x\n", AhciCtlBlock64));
00206 
00207             AhciCtlBlock64 += AHCI_CLB_ALIGNEMENT_MASK;
00208             AhciCtlBlock64 &= ~AHCI_CLB_ALIGNEMENT_MASK;
00209 
00210             KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: CLP BASE 1k-aligned %I64x\n", AhciCtlBlock64));
00211 
00212             chan->AhciCtlBlock = (PIDE_AHCI_CHANNEL_CTL_BLOCK)AhciCtlBlock;
00213 
00214             chan->AHCI_CTL_PhAddr = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)(chan->AhciCtlBlock), &i, &ph_addru);
00215             KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: CLP Phys BASE %I64x\n", chan->AHCI_CTL_PhAddr));
00216             if(!chan->AHCI_CTL_PhAddr || !i || ((LONG)(chan->AHCI_CTL_PhAddr) == -1)) {
00217                 KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: No AHCI CLP BASE\n" ));
00218                 chan->AhciCtlBlock = NULL;
00219                 chan->AHCI_CTL_PhAddr = 0;
00220                 return;
00221             }
00222             if(ph_addru) {
00223                 KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: No AHCI CLP below 4Gb\n" ));
00224                 MmFreeContiguousMemory(chan->AhciCtlBlock0);
00225                 chan->AhciCtlBlock = NULL;
00226                 chan->AHCI_CTL_PhAddr = 0;
00227                 return;
00228             }
00229         } else {
00230             KdPrint2((PRINT_PREFIX "AtapiDmaAlloc: Can't alloc AHCI CLP\n"));
00231         }
00232     }
00233 #endif //USE_OWN_DMA
00234     return;
00235 } // end AtapiDmaAlloc()
00236 
00237 BOOLEAN
00238 NTAPI
00239 AtapiDmaSetup(
00240     IN PVOID HwDeviceExtension,
00241     IN ULONG DeviceNumber,
00242     IN ULONG lChannel,          // logical channel,
00243     IN PSCSI_REQUEST_BLOCK Srb,
00244     IN PUCHAR data,
00245     IN ULONG count
00246     )
00247 {
00248     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
00249     ULONG dma_count, dma_base, dma_baseu;
00250     ULONG i;
00251     PHW_CHANNEL chan = &(deviceExtension->chan[lChannel]);
00252     PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
00253     BOOLEAN use_DB_IO = FALSE;
00254     BOOLEAN use_AHCI = (deviceExtension->HwFlags & UNIATA_AHCI) ? TRUE : FALSE;
00255     ULONG orig_count = count;
00256     ULONG max_entries = use_AHCI ? ATA_AHCI_DMA_ENTRIES : ATA_DMA_ENTRIES;
00257 
00258     AtaReq->Flags &= ~REQ_FLAG_DMA_OPERATION;
00259 
00260     KdPrint2((PRINT_PREFIX "AtapiDmaSetup: mode %#x, data %x, count %x, lCh %x, dev %x\n",
00261         chan->lun[DeviceNumber]->TransferMode,
00262         data, count, lChannel, DeviceNumber ));
00263     if(chan->lun[DeviceNumber]->TransferMode < ATA_DMA) {
00264         KdPrint2((PRINT_PREFIX "AtapiDmaSetup: Not DMA mode, assume this is just preparation\n" ));
00265         //return FALSE;
00266     }
00267     //KdPrint2((PRINT_PREFIX "  checkpoint 1\n" ));
00268     if(!count) {
00269         KdPrint2((PRINT_PREFIX "AtapiDmaSetup: count=0\n" ));
00270         return FALSE;
00271     }
00272     //KdPrint2((PRINT_PREFIX "  checkpoint 2\n" ));
00273     if(count > deviceExtension->MaximumDmaTransferLength) {
00274         KdPrint2((PRINT_PREFIX "AtapiDmaSetup: deviceExtension->MaximumDmaTransferLength > count\n" ));
00275         return FALSE;
00276     }
00277     //KdPrint2((PRINT_PREFIX "  checkpoint 3\n" ));
00278     if((ULONG)data & deviceExtension->AlignmentMask) {
00279         KdPrint2((PRINT_PREFIX "AtapiDmaSetup: unaligned data: %#x (%#x)\n", data, deviceExtension->AlignmentMask));
00280         return FALSE;
00281     }
00282 
00283     //KdPrint2((PRINT_PREFIX "  checkpoint 4\n" ));
00284     if(use_AHCI) {
00285         KdPrint2((PRINT_PREFIX "  get Phys(AHCI_CMD=%x)\n", &(AtaReq->ahci.ahci_cmd_ptr->prd_tab) ));
00286         dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)&(AtaReq->ahci.ahci_cmd_ptr->prd_tab), &i, &dma_baseu);
00287         AtaReq->ahci.ahci_base64 = NULL; // clear before setup
00288     } else {
00289         KdPrint2((PRINT_PREFIX "  get Phys(PRD=%x)\n", &(AtaReq->dma_tab) ));
00290         dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, NULL, (PUCHAR)&(AtaReq->dma_tab) /*chan->dma_tab*/, &i, &dma_baseu);
00291     }
00292     if(dma_baseu) {
00293         KdPrint2((PRINT_PREFIX "AtapiDmaSetup: SRB built-in PRD above 4Gb: %8.8x%8.8x\n", dma_baseu, dma_base));
00294         if(!deviceExtension->Host64) {
00295             dma_base = chan->DB_PRD_PhAddr;
00296             AtaReq->Flags |= REQ_FLAG_DMA_DBUF_PRD;
00297             i = 1;
00298         }
00299     } else
00300     if(!dma_base || !i || ((LONG)(dma_base) == -1)) {
00301         KdPrint2((PRINT_PREFIX "AtapiDmaSetup: No BASE\n" ));
00302         return FALSE;
00303     }
00304     AtaReq->ata.dma_base = dma_base; // aliased to ahci_base64
00305 
00306     KdPrint2((PRINT_PREFIX "  get Phys(data=%x)\n", data ));
00307     dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, Srb, data, &dma_count, &dma_baseu);
00308     if(dma_baseu) {
00309         KdPrint2((PRINT_PREFIX "AtapiDmaSetup: 1st block of buffer above 4Gb: %8.8x%8.8x\n", dma_baseu, dma_base));
00310         if(!deviceExtension->Host64) {
00311 retry_DB_IO:
00312             use_DB_IO = TRUE;
00313             dma_base = chan->DB_IO_PhAddr;
00314             data = (PUCHAR)(chan->DB_IO);
00315         } else {
00316             AtaReq->ahci.ahci_base64 = (ULONGLONG)dma_base | ((ULONGLONG)dma_baseu << 32);
00317         }
00318     } else
00319     if(!dma_count || ((LONG)(dma_base) == -1)) {
00320         KdPrint2((PRINT_PREFIX "AtapiDmaSetup: No 1st block\n" ));
00321         //AtaReq->dma_base = NULL;
00322         AtaReq->ahci.ahci_base64 = NULL;
00323         return FALSE;
00324     }
00325 
00326     dma_count = min(count, (PAGE_SIZE - ((ULONG)data & PAGE_MASK)));
00327     data += dma_count;
00328     count -= dma_count;
00329     i = 0;
00330 
00331     while (count) {
00332         if(use_AHCI) {
00333             AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].base   = dma_base;
00334             AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].baseu  = dma_baseu;
00335             AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC    = ((dma_count-1) & 0x3fffff);
00336         } else {
00337             AtaReq->dma_tab[i].base  = dma_base;
00338             AtaReq->dma_tab[i].count = (dma_count & 0xffff);
00339         }
00340         i++; 
00341         if (i >= max_entries) {
00342             KdPrint2((PRINT_PREFIX "too many segments in DMA table\n" ));
00343             //AtaReq->dma_base = NULL;
00344             AtaReq->ahci.ahci_base64 = NULL;
00345             return FALSE;
00346         }
00347         KdPrint2((PRINT_PREFIX "  get Phys(data[n]=%x)\n", data ));
00348         dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, Srb, data, &dma_count, &dma_baseu);
00349         if(dma_baseu) {
00350             KdPrint2((PRINT_PREFIX "AtapiDmaSetup: block of buffer above 4Gb: %8.8x%8.8x\n", dma_baseu, dma_base));
00351             if(!deviceExtension->Host64) {
00352                 if(use_DB_IO) {
00353                     KdPrint2((PRINT_PREFIX "AtapiDmaSetup: *ERROR* special buffer above 4Gb: %8.8x%8.8x\n", dma_baseu, dma_base));
00354                     return FALSE;
00355                 }
00356                 count = orig_count;
00357                 goto retry_DB_IO;
00358             }
00359         } else
00360         if(!dma_count || !dma_base || ((LONG)(dma_base) == -1)) {
00361             //AtaReq->dma_base = NULL;
00362             AtaReq->ahci.ahci_base64 = 0;
00363             KdPrint2((PRINT_PREFIX "AtapiDmaSetup: No NEXT block\n" ));
00364             return FALSE;
00365         }
00366 
00367         dma_count = min(count, PAGE_SIZE);
00368         data += min(count, PAGE_SIZE);
00369         count -= min(count, PAGE_SIZE);
00370     }
00371     KdPrint2((PRINT_PREFIX "  set TERM\n" ));
00372     if(use_AHCI) {
00373         AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].base   = dma_base;
00374         AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].baseu  = dma_baseu;
00375         AtaReq->ahci.ahci_cmd_ptr->prd_tab[i].DBC    = ((dma_count-1) & 0x3fffff);
00376     } else {
00377         AtaReq->dma_tab[i].base = dma_base;
00378         AtaReq->dma_tab[i].count = (dma_count & 0xffff) | ATA_DMA_EOT;
00379     }
00380     AtaReq->dma_entries = i;
00381 
00382     if(use_DB_IO) {
00383         AtaReq->Flags |= REQ_FLAG_DMA_DBUF;
00384     }
00385     AtaReq->Flags |= REQ_FLAG_DMA_OPERATION;
00386 
00387     KdPrint2((PRINT_PREFIX "AtapiDmaSetup: OK\n" ));
00388     return TRUE;
00389 
00390 } // end AtapiDmaSetup()
00391 
00392 BOOLEAN
00393 NTAPI
00394 AtapiDmaPioSync(
00395     PVOID  HwDeviceExtension,
00396     PSCSI_REQUEST_BLOCK Srb,
00397     PUCHAR data,
00398     ULONG  count
00399     )
00400 {
00401 #ifndef USE_OWN_DMA
00402     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
00403     ULONG dma_base;
00404     PUCHAR DmaBuffer;
00405     ULONG dma_count;
00406     ULONG len;
00407     PATA_REQ AtaReq;
00408 
00409     // This must never be called after DMA operation !!!
00410     KdPrint2((PRINT_PREFIX "AtapiDmaPioSync: data %#x, len %#x\n", data, count));
00411 
00412     if(!Srb) {
00413         KdPrint2((PRINT_PREFIX "AtapiDmaPioSync: !Srb\n" ));
00414         return FALSE;
00415     }
00416 
00417     AtaReq = (PATA_REQ)(Srb->SrbExtension);
00418 
00419     // do nothing on PCI (This can be changed. We cannot guarantee,
00420     // that CommonBuffer will always point to User's buffer,
00421     // however, this usually happens on PCI-32)
00422     if(deviceExtension->OrigAdapterInterfaceType == PCIBus) {
00423         return TRUE;
00424     }
00425     // do nothing for DMA
00426     if(AtaReq->Flags & REQ_FLAG_DMA_OPERATION) {
00427         return TRUE;
00428     }
00429 
00430     if(!data) {
00431         KdPrint2((PRINT_PREFIX "AtapiDmaPioSync: !data\n" ));
00432         return FALSE;
00433     }
00434 
00435     while(count) {
00436         dma_base = AtapiVirtToPhysAddr(HwDeviceExtension, Srb, data, &dma_count);
00437         if(!dma_base) {
00438             KdPrint2((PRINT_PREFIX "AtapiDmaPioSync: !dma_base for data %#x\n", data));
00439             return FALSE;
00440         }
00441         DmaBuffer = (PUCHAR)ScsiPortGetVirtualAddress(HwDeviceExtension,
00442                                                       ScsiPortConvertUlongToPhysicalAddress(dma_base));
00443         if(!DmaBuffer) {
00444             KdPrint2((PRINT_PREFIX "AtapiDmaPioSync: !DmaBuffer for dma_base %#x\n", dma_base));
00445             return FALSE;
00446         }
00447         len = min(dma_count, count);
00448         memcpy(DmaBuffer, data, len);
00449         count -= len;
00450         data += len;
00451     }
00452 #endif //USE_OWN_DMA
00453 
00454     return TRUE;
00455 } // end AtapiDmaPioSync()
00456 
00457 BOOLEAN
00458 NTAPI
00459 AtapiDmaDBSync(
00460     PHW_CHANNEL chan,
00461     PSCSI_REQUEST_BLOCK Srb
00462     )
00463 {
00464     PATA_REQ AtaReq;
00465 
00466     AtaReq = (PATA_REQ)(Srb->SrbExtension);
00467     if((Srb->SrbFlags & SRB_FLAGS_DATA_IN) &&
00468        (AtaReq->Flags & REQ_FLAG_DMA_DBUF)) {
00469         KdPrint2((PRINT_PREFIX "  AtapiDmaDBSync is issued.\n"));
00470         ASSERT(FALSE);
00471         KdPrint2((PRINT_PREFIX "  DBUF (Read)\n"));
00472         RtlCopyMemory(AtaReq->DataBuffer, chan->DB_IO,
00473                               Srb->DataTransferLength);
00474     }
00475     return TRUE;
00476 } // end AtapiDmaDBSync()
00477 
00478 VOID
00479 NTAPI
00480 AtapiDmaStart(
00481     IN PVOID HwDeviceExtension,
00482     IN ULONG DeviceNumber,
00483     IN ULONG lChannel,          // logical channel,
00484     IN PSCSI_REQUEST_BLOCK Srb
00485     )
00486 {
00487     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
00488     //PIDE_BUSMASTER_REGISTERS BaseIoAddressBM = deviceExtension->BaseIoAddressBM[lChannel];
00489     PATA_REQ AtaReq = (PATA_REQ)(Srb->SrbExtension);
00490     PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
00491 
00492     ULONG VendorID =  deviceExtension->DevID        & 0xffff;
00493     ULONG ChipType  = deviceExtension->HwFlags & CHIPTYPE_MASK;
00494 
00495     KdPrint2((PRINT_PREFIX "AtapiDmaStart: %s on %#x:%#x\n",
00496         (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? "read" : "write",
00497         lChannel, DeviceNumber ));
00498 
00499     if(!AtaReq->ata.dma_base) {
00500         KdPrint2((PRINT_PREFIX "AtapiDmaStart: *** !AtaReq->ata.dma_base\n"));
00501         return;
00502     }
00503     if(AtaReq->Flags & REQ_FLAG_DMA_DBUF_PRD) {
00504         KdPrint2((PRINT_PREFIX "  DBUF_PRD\n"));
00505         ASSERT(FALSE);
00506         if(deviceExtension->HwFlags & UNIATA_AHCI) {
00507             RtlCopyMemory(chan->DB_PRD, AtaReq->ahci.ahci_cmd_ptr, sizeof(AtaReq->ahci_cmd0));
00508         } else {
00509             RtlCopyMemory(chan->DB_PRD, &(AtaReq->dma_tab), sizeof(AtaReq->dma_tab));
00510         }
00511     }
00512     if(!(Srb->SrbFlags & SRB_FLAGS_DATA_IN) &&
00513        (AtaReq->Flags & REQ_FLAG_DMA_DBUF)) {
00514         KdPrint2((PRINT_PREFIX "  DBUF (Write)\n"));
00515         ASSERT(FALSE);
00516         RtlCopyMemory(chan->DB_IO, AtaReq->DataBuffer,
00517                               Srb->DataTransferLength);
00518     }
00519 
00520     // set flag
00521     chan->ChannelCtrlFlags |= CTRFLAGS_DMA_ACTIVE;
00522 
00523     switch(VendorID) {
00524     case ATA_PROMISE_ID:
00525         if(ChipType == PRNEW) {
00526             ULONG Channel = deviceExtension->Channel + lChannel;
00527             if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) {
00528                 AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
00529                       AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) |
00530                           (Channel ? 0x08 : 0x02));
00531                 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),(Channel ? 0x24 : 0x20),
00532                       ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x05000000 : 0x06000000) | (Srb->DataTransferLength >> 1)
00533                       );
00534             }
00535 /*
00536         } else
00537         if(deviceExtension->MemIo) {
00538             // begin transaction
00539             AtapiWritePort4(chan,
00540                  IDX_BM_Command,
00541                  (AtapiReadPort4(chan,
00542                      IDX_BM_Command) & ~0x000000c0) |
00543                      ((Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x00000080 : 0x000000c0) );
00544             return;
00545 */
00546         }
00547         break;
00548     }
00549 
00550     // set pointer to Pointer Table
00551     AtapiWritePort4(chan, IDX_BM_PRD_Table,
00552           AtaReq->ata.dma_base
00553           );
00554     // set transfer direction
00555     AtapiWritePort1(chan, IDX_BM_Command,
00556           (Srb->SrbFlags & SRB_FLAGS_DATA_IN) ? BM_COMMAND_READ : BM_COMMAND_WRITE);
00557     // clear Error & Intr bits (writeing 1 clears bits)
00558     // set DMA capability bit
00559     AtapiWritePort1(chan, IDX_BM_Status,
00560          AtapiReadPort1(chan, IDX_BM_Status) |
00561              (BM_STATUS_INTR | BM_STATUS_ERR) /*|
00562              (DeviceNumber ? BM_STATUS_DRIVE_1_DMA : BM_STATUS_DRIVE_0_DMA)*/);
00563     // begin transaction
00564     AtapiWritePort1(chan, IDX_BM_Command,
00565          AtapiReadPort1(chan, IDX_BM_Command) |
00566              BM_COMMAND_START_STOP);
00567     return;
00568 
00569 } // end AtapiDmaStart()
00570 
00571 UCHAR
00572 NTAPI
00573 AtapiDmaDone(
00574     IN PVOID HwDeviceExtension,
00575     IN ULONG DeviceNumber,
00576     IN ULONG lChannel,          // logical channel,
00577     IN PSCSI_REQUEST_BLOCK Srb
00578     )
00579 {
00580     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
00581     //PIDE_BUSMASTER_REGISTERS BaseIoAddressBM = deviceExtension->BaseIoAddressBM[lChannel];
00582     PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
00583     UCHAR dma_status;
00584 
00585     ULONG VendorID =  deviceExtension->DevID        & 0xffff;
00586     ULONG ChipType  = deviceExtension->HwFlags & CHIPTYPE_MASK;
00587 
00588     KdPrint2((PRINT_PREFIX "AtapiDmaDone: dev %d\n", DeviceNumber));
00589 
00590     if(deviceExtension->HwFlags & UNIATA_AHCI) {
00591         KdPrint2((PRINT_PREFIX "  ACHTUNG! should not be called for AHCI!\n"));
00592         return 0xff;
00593     }
00594 
00595     switch(VendorID) {
00596     case ATA_PROMISE_ID:
00597         if(ChipType == PRNEW) {
00598             ULONG Channel = deviceExtension->Channel + lChannel;
00599             if(chan->ChannelCtrlFlags & CTRFLAGS_LBA48) {
00600                 AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11,
00601                       AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),0x11) &
00602                           ~(Channel ? 0x08 : 0x02));
00603                 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),(Channel ? 0x24 : 0x20),
00604                       0
00605                       );
00606             }
00607 /*
00608         } else
00609         if(deviceExtension->MemIo) {
00610             // end transaction
00611             AtapiWritePort4(chan,
00612                  IDX_BM_Command,
00613                  (AtapiReadPort4(chan,
00614                      IDX_BM_Command) & ~0x00000080) );
00615             // clear flag
00616             chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_ACTIVE;
00617             return 0;
00618 */
00619         }
00620         break;
00621     }
00622 
00623     // get status
00624     dma_status = AtapiReadPort1(chan, IDX_BM_Status) & BM_STATUS_MASK;
00625     // end transaction
00626     AtapiWritePort1(chan, IDX_BM_Command,
00627          AtapiReadPort1(chan, IDX_BM_Command) &
00628              ~BM_COMMAND_START_STOP);
00629     // clear interrupt and error status
00630     AtapiWritePort1(chan, IDX_BM_Status, BM_STATUS_ERR | BM_STATUS_INTR);
00631     // clear flag
00632     chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_ACTIVE;
00633 
00634     return dma_status;
00635 
00636 } // end AtapiDmaDone()
00637 
00638 VOID
00639 NTAPI
00640 AtapiDmaReinit(
00641     IN PHW_DEVICE_EXTENSION deviceExtension,
00642     IN PHW_LU_EXTENSION LunExt,
00643     IN PATA_REQ AtaReq
00644     )
00645 {
00646     SCHAR apiomode;
00647 
00648     apiomode = (CHAR)AtaPioMode(&(LunExt->IdentifyData));
00649 
00650     if(!(AtaReq->Flags & REQ_FLAG_DMA_OPERATION)) {
00651         KdPrint2((PRINT_PREFIX
00652                     "AtapiDmaReinit: !(AtaReq->Flags & REQ_FLAG_DMA_OPERATION), fall to PIO on Device %d\n", LunExt->Lun));
00653         goto limit_pio;
00654     }
00655     if(deviceExtension->HwFlags & UNIATA_AHCI) {
00656         if(!AtaReq->ahci.ahci_base64) {
00657             KdPrint2((PRINT_PREFIX
00658                         "AtapiDmaReinit: no AHCI PRD, fall to PIO on Device %d\n", LunExt->Lun));
00659             goto limit_pio;
00660         }
00661     } else
00662     if(!AtaReq->ata.dma_base) {
00663         KdPrint2((PRINT_PREFIX
00664                     "AtapiDmaReinit: no PRD, fall to PIO on Device %d\n", LunExt->Lun));
00665         goto limit_pio;
00666     }
00667 
00668     if((deviceExtension->HbaCtrlFlags & HBAFLAGS_DMA_DISABLED_LBA48) &&
00669        (AtaReq->lba >= (LONGLONG)ATA_MAX_LBA28) &&
00670        (LunExt->TransferMode > ATA_PIO5) ) {
00671         KdPrint2((PRINT_PREFIX
00672                     "AtapiDmaReinit: FORCE_DOWNRATE on Device %d for LBA48\n", LunExt->Lun));
00673         goto limit_lba48;
00674     }
00675 
00676 
00677     if(AtaReq->Flags & REQ_FLAG_FORCE_DOWNRATE) {
00678         KdPrint2((PRINT_PREFIX
00679                     "AtapiDmaReinit: FORCE_DOWNRATE on Device %d\n", LunExt->Lun));
00680         if(AtaReq->lba >= (LONGLONG)ATA_MAX_LBA28) {
00681 limit_lba48:
00682             LunExt->DeviceFlags |= REQ_FLAG_FORCE_DOWNRATE_LBA48;
00683 limit_pio:
00684             // do not make extra work if we already use PIO
00685             if(/*LunExt->TransferMode >= ATA_DMA*/
00686                (LunExt->TransferMode > ATA_PIO5) && (LunExt->TransferMode != ATA_PIO0+apiomode)
00687                ) {
00688                 KdPrint2((PRINT_PREFIX 
00689                             "AtapiDmaReinit: set PIO mode on Device %d (%x -> %x)\n", LunExt->Lun, LunExt->TransferMode, ATA_PIO0+apiomode));
00690                 AtapiDmaInit(deviceExtension, LunExt->Lun, LunExt->chan->lChannel,
00691                              apiomode,
00692                              -1,
00693                              -1 );
00694             } else
00695             if(LunExt->LimitedTransferMode < LunExt->TransferMode) {
00696                 KdPrint2((PRINT_PREFIX 
00697                             "AtapiDmaReinit: set PIO mode on Device %d (%x -> %x) (2)\n", LunExt->Lun, LunExt->TransferMode, LunExt->LimitedTransferMode));
00698                 AtapiDmaInit(deviceExtension, LunExt->Lun, LunExt->chan->lChannel,
00699                              LunExt->LimitedTransferMode-ATA_PIO0, 
00700                              -1,
00701                              -1 );
00702             }
00703 
00704         } else {
00705             KdPrint2((PRINT_PREFIX
00706                         "AtapiDmaReinit: set MAX mode on Device %d\n", LunExt->Lun));
00707             AtapiDmaInit(deviceExtension, LunExt->Lun, LunExt->chan->lChannel,
00708                          apiomode,
00709                          min( retry_Wdma[AtaReq->retry],
00710                               (CHAR)AtaWmode(&(LunExt->IdentifyData)) ),
00711                          min( retry_Udma[AtaReq->retry],
00712                               (CHAR)AtaUmode(&(LunExt->IdentifyData)) ) );
00713         }
00714 //            LunExt->DeviceFlags &= ~DFLAGS_FORCE_DOWNRATE;
00715     } else
00716     if(
00717         (LunExt->LimitedTransferMode >
00718          LunExt->TransferMode) ||
00719          (LunExt->DeviceFlags & DFLAGS_REINIT_DMA)) {
00720         // restore IO mode
00721         KdPrint2((PRINT_PREFIX
00722                     "AtapiDmaReinit: restore IO mode on Device %d\n", LunExt->Lun));
00723         AtapiDmaInit__(deviceExtension, LunExt);
00724     }
00725 } // end AtapiDmaReinit()
00726 
00727 VOID
00728 NTAPI
00729 AtapiDmaInit__(
00730     IN PHW_DEVICE_EXTENSION deviceExtension,
00731     IN PHW_LU_EXTENSION LunExt
00732     )
00733 {
00734     if(LunExt->IdentifyData.SupportDma) {
00735         KdPrint2((PRINT_PREFIX
00736                     "AtapiDmaInit__: Set (U)DMA on Device %d\n", LunExt->Lun));
00737 /*        for(i=AtaUmode(&(LunExt->IdentifyData)); i>=0; i--) {
00738             AtapiDmaInit(deviceExtension, ldev & 1, ldev >> 1,
00739                          (CHAR)AtaPioMode(&(LunExt->IdentifyData)),
00740                          (CHAR)AtaWmode(&(LunExt->IdentifyData)),
00741                          UDMA_MODE0+(CHAR)i );
00742         }
00743         for(i=AtaWmode(&(LunExt->IdentifyData)); i>=0; i--) {
00744             AtapiDmaInit(deviceExtension, ldev & 1, ldev >> 1,
00745                          (CHAR)AtaPioMode(&(LunExt->IdentifyData)),
00746                          (CHAR)AtaWmode(&(LunExt->IdentifyData)),
00747                          UDMA_MODE0+(CHAR)i );
00748         }*/
00749         AtapiDmaInit(deviceExtension, LunExt->Lun, LunExt->chan->lChannel,
00750                      (CHAR)AtaPioMode(&(LunExt->IdentifyData)),
00751                      (CHAR)AtaWmode(&(LunExt->IdentifyData)),
00752                      (CHAR)AtaUmode(&(LunExt->IdentifyData)) );
00753     } else {
00754         KdPrint2((PRINT_PREFIX
00755                     "AtapiDmaInit__: Set PIO on Device %d\n", LunExt->Lun));
00756         AtapiDmaInit(deviceExtension, LunExt->Lun, LunExt->chan->lChannel,
00757                      (CHAR)AtaPioMode(&(LunExt->IdentifyData)), -1, -1);
00758     }
00759 } // end AtapiDmaInit__()
00760 
00761 BOOLEAN
00762 NTAPI
00763 AtaSetTransferMode(
00764     IN PHW_DEVICE_EXTENSION deviceExtension,
00765     IN ULONG DeviceNumber,
00766     IN ULONG lChannel,          // logical channel,
00767     IN PHW_LU_EXTENSION LunExt,
00768     IN ULONG mode
00769     )
00770 {
00771     KdPrint3((PRINT_PREFIX 
00772                 "AtaSetTransferMode: Set %#x on Device %d/%d\n", mode, lChannel, DeviceNumber));
00773     LONG statusByte = 0;
00774     CHAR apiomode;
00775 
00776     statusByte = AtaCommand(deviceExtension, DeviceNumber, lChannel,
00777                         IDE_COMMAND_SET_FEATURES, 0, 0, 0,
00778                         (UCHAR)((mode > ATA_UDMA6) ? ATA_UDMA6 : mode), ATA_C_F_SETXFER, ATA_WAIT_BASE_READY);
00779     if(statusByte & IDE_STATUS_ERROR) {
00780         KdPrint3((PRINT_PREFIX "  wait ready after error\n"));
00781         if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) {
00782             AtapiStallExecution(10);
00783         } else {
00784             AtapiStallExecution(100);
00785         }
00786         apiomode = (CHAR)AtaPioMode(&(LunExt->IdentifyData));
00787         if(  (apiomode > 0) &&
00788              ((CHAR)AtaWmode(&(LunExt->IdentifyData))   > 0) &&
00789              ((CHAR)AtaUmode(&(LunExt->IdentifyData))   > 0)
00790           ) {
00791             return FALSE;
00792         }
00793         if(mode > ATA_PIO2) {
00794             return FALSE;
00795         }
00796         KdPrint3((PRINT_PREFIX "  assume that drive doesn't support mode swithing using PIO%d\n", apiomode));
00797         mode = ATA_PIO0 + apiomode;
00798     }
00799     //if(mode <= ATA_UDMA6) {
00800         LunExt->TransferMode = (UCHAR)mode;
00801     //}
00802     return TRUE;
00803 } // end AtaSetTransferMode()
00804 
00805 VOID
00806 NTAPI
00807 AtapiDmaInit(
00808     IN PVOID HwDeviceExtension,
00809     IN ULONG DeviceNumber,
00810     IN ULONG lChannel,          // logical channel,
00811                                // is always 0 except simplex-only controllers
00812     IN SCHAR apiomode,
00813     IN SCHAR wdmamode,
00814     IN SCHAR udmamode
00815     )
00816 {
00817     PHW_DEVICE_EXTENSION deviceExtension = (PHW_DEVICE_EXTENSION)HwDeviceExtension;
00818     ULONG Channel = deviceExtension->Channel + lChannel;
00819     PHW_CHANNEL chan = &deviceExtension->chan[lChannel];
00820     //LONG statusByte = 0;
00821     ULONG dev = Channel*2 + DeviceNumber;       // for non-SATA/AHCI only!
00822     ULONG ldev = lChannel*2 + DeviceNumber;     // for non-SATA/AHCI only!
00823     ULONG slotNumber = deviceExtension->slotNumber;
00824     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
00825     LONG i;
00826     PHW_LU_EXTENSION LunExt = chan->lun[DeviceNumber];
00827 
00828     ULONG VendorID  =  deviceExtension->DevID        & 0xffff;
00829     //ULONG DeviceID  = (deviceExtension->DevID >> 16) & 0xffff;
00830     //ULONG RevID     =  deviceExtension->RevID;
00831     ULONG ChipType  = deviceExtension->HwFlags & CHIPTYPE_MASK;
00832     ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
00833 
00834     LONG statusByte = 0;
00835 
00836     //UCHAR *reg_val = NULL;
00837 
00838     LunExt->DeviceFlags &= ~DFLAGS_REINIT_DMA;
00839     /* set our most pessimistic default mode */
00840     LunExt->TransferMode = ATA_PIO;
00841 //    if(!deviceExtension->BaseIoAddressBM[lChannel]) {
00842     if(!deviceExtension->BusMaster) {
00843         KdPrint2((PRINT_PREFIX "  !deviceExtension->BusMaster: NO DMA\n"));
00844         wdmamode = udmamode = -1;
00845     }
00846 
00847     // Limit transfer mode (controller limitation)
00848     if((LONG)deviceExtension->MaxTransferMode >= ATA_UDMA) {
00849         KdPrint2((PRINT_PREFIX "AtapiDmaInit: deviceExtension->MaxTransferMode >= ATA_UDMA\n"));
00850         udmamode = min( udmamode, (CHAR)(deviceExtension->MaxTransferMode - ATA_UDMA));
00851     } else
00852     if((LONG)deviceExtension->MaxTransferMode >= ATA_WDMA) {
00853         KdPrint2((PRINT_PREFIX "AtapiDmaInit: deviceExtension->MaxTransferMode >= ATA_WDMA\n"));
00854         udmamode = -1;
00855         wdmamode = min( wdmamode, (CHAR)(deviceExtension->MaxTransferMode - ATA_WDMA));
00856     } else
00857     if((LONG)deviceExtension->MaxTransferMode >= ATA_PIO0) {
00858         KdPrint2((PRINT_PREFIX "AtapiDmaInit: NO DMA\n"));
00859         wdmamode = udmamode = -1;
00860         apiomode = min( apiomode, (CHAR)(deviceExtension->MaxTransferMode - ATA_PIO0));
00861     } else {
00862         KdPrint2((PRINT_PREFIX "AtapiDmaInit: PIO0\n"));
00863         wdmamode = udmamode = -1;
00864         apiomode = 0;
00865     }
00866     // Limit transfer mode (device limitation)
00867     KdPrint2((PRINT_PREFIX "AtapiDmaInit: LunExt->LimitedTransferMode %#x\n", LunExt->LimitedTransferMode));
00868     if((LONG)LunExt->LimitedTransferMode >= ATA_UDMA) {
00869         KdPrint2((PRINT_PREFIX "AtapiDmaInit: LunExt->MaxTransferMode >= ATA_UDMA   =>   %#x\n",
00870          min( udmamode, (CHAR)(LunExt->LimitedTransferMode - ATA_UDMA))
00871                 ));
00872         udmamode = min( udmamode, (CHAR)(LunExt->LimitedTransferMode - ATA_UDMA));
00873     } else
00874     if((LONG)LunExt->LimitedTransferMode >= ATA_WDMA) {
00875         KdPrint2((PRINT_PREFIX "AtapiDmaInit: LunExt->MaxTransferMode >= ATA_WDMA   =>   %#x\n",
00876          min( wdmamode, (CHAR)(LunExt->LimitedTransferMode - ATA_WDMA))
00877                 ));
00878         udmamode = -1;
00879         wdmamode = min( wdmamode, (CHAR)(LunExt->LimitedTransferMode - ATA_WDMA));
00880     } else
00881     if((LONG)LunExt->LimitedTransferMode >= ATA_PIO0) {
00882         KdPrint2((PRINT_PREFIX "AtapiDmaInit: lun NO DMA\n"));
00883         wdmamode = udmamode = -1;
00884         apiomode = min( apiomode, (CHAR)(LunExt->LimitedTransferMode - ATA_PIO0));
00885     } else {
00886         KdPrint2((PRINT_PREFIX "AtapiDmaInit: lun PIO0\n"));
00887         wdmamode = udmamode = -1;
00888         apiomode = 0;
00889     }
00890 
00891     SelectDrive(chan, DeviceNumber);
00892     GetStatus(chan, statusByte);
00893     // we can see here IDE_STATUS_ERROR status after previous operation
00894     if(statusByte & IDE_STATUS_ERROR) {
00895         KdPrint2((PRINT_PREFIX "IDE_STATUS_ERROR detected on entry, statusByte = %#x\n", statusByte));
00896         //GetBaseStatus(chan, statusByte);
00897     }
00898     if(statusByte && UniataIsIdle(deviceExtension, statusByte & ~IDE_STATUS_ERROR) != IDE_STATUS_IDLE) {
00899         KdPrint2((PRINT_PREFIX "Can't setup transfer mode: statusByte = %#x\n", statusByte));
00900         return;
00901     }
00902 
00903     if(deviceExtension->UnknownDev) {
00904         KdPrint2((PRINT_PREFIX "Unknown chip, omit Vendor/Dev checks\n"));
00905         goto try_generic_dma;
00906     }
00907 
00908     if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) {
00909     //if(ChipFlags & UNIATA_SATA) {
00910         /****************/
00911         /* SATA Generic */
00912         /****************/
00913         UCHAR ModeByte;
00914 
00915         KdPrint2((PRINT_PREFIX "SATA Generic\n"));
00916         if(udmamode > 5) {
00917             if(LunExt->IdentifyData.SataCapabilities != 0x0000 &&
00918                LunExt->IdentifyData.SataCapabilities != 0xffff) {
00919                 //udmamode = min(udmamode, 6);
00920                 KdPrint2((PRINT_PREFIX "LunExt->LimitedTransferMode %x, LunExt->OrigTransferMode %x\n",
00921                     LunExt->LimitedTransferMode, LunExt->OrigTransferMode));
00922                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, min(LunExt->LimitedTransferMode, LunExt->OrigTransferMode))) {
00923                     return;
00924                 }
00925                 udmamode = min(udmamode, 5);
00926 
00927             } else {
00928                 KdPrint2((PRINT_PREFIX "SATA -> PATA adapter ?\n"));
00929                 if (udmamode > 2 && !LunExt->IdentifyData.HwResCableId) {
00930                     KdPrint2((PRINT_PREFIX "AtapiDmaInit: DMA limited to UDMA33, non-ATA66 compliant cable\n"));
00931                     udmamode = 2;
00932                     apiomode = min( apiomode, (CHAR)(LunExt->LimitedTransferMode - ATA_PIO0));
00933                 } else {
00934                     udmamode = min(udmamode, 5);
00935                 }
00936             }
00937         }
00938         if(udmamode >= 0) {
00939             ModeByte = ATA_UDMA0 + udmamode;
00940         } else
00941         if(wdmamode >= 0) {
00942             ModeByte = ATA_WDMA0 + wdmamode;
00943         } else
00944         if(apiomode >= 0) {
00945             ModeByte = ATA_PIO0  + apiomode;
00946         } else {
00947             ModeByte = ATA_PIO;
00948         }
00949 
00950         AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ModeByte);
00951         return;
00952     }
00953     if(udmamode > 2 && !LunExt->IdentifyData.HwResCableId) {
00954         KdPrint2((PRINT_PREFIX "AtapiDmaInit: DMA limited to UDMA33, non-ATA66 compliant cable\n"));
00955         udmamode = 2;
00956         apiomode = min( apiomode, (CHAR)(LunExt->LimitedTransferMode - ATA_PIO));
00957     }
00958 
00959     KdPrint2((PRINT_PREFIX "Setup chip a:w:u=%d:%d:%d\n",
00960         apiomode,
00961         wdmamode,
00962         udmamode));
00963 
00964     switch(VendorID) {
00965     case ATA_ACARD_ID: {
00966         /*********/
00967         /* Acard */
00968         /*********/
00969         static const USHORT reg4a = 0xa6;
00970         UCHAR  reg = 0x40 + (UCHAR)dev;
00971 
00972         if(ChipType == ATPOLD) {
00973             /* Old Acard 850 */
00974             static const USHORT reg4x = 0x0301;
00975 
00976             for(i=udmamode; i>=0; i--) {
00977                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA + i)) {
00978 set_old_acard:
00979                     ChangePciConfig1(0x54, a | (0x01 << dev) | ((i+1) << (dev*2)));
00980                     SetPciConfig1(0x4a, reg4a);
00981                     SetPciConfig2(reg,  reg4x);
00982                     return;
00983                 }
00984 
00985             }
00986             if (wdmamode >= 2 && apiomode >= 4) {
00987                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA2)) {
00988                     goto set_old_acard;
00989                 }
00990             }
00991         } else {
00992             /* New Acard 86X */
00993             static const UCHAR reg4x = 0x31;
00994 
00995             for(i=udmamode; i>=0; i--) {
00996                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA + i)) {
00997 set_new_acard:
00998                     ChangePciConfig2(0x44, (a & ~(0x000f << (dev * 4))) | ((i+1) << (dev*4)));
00999                     SetPciConfig1(0x4a, reg4a);
01000                     SetPciConfig1(reg,  reg4x);
01001                     return;
01002                 }
01003 
01004             }
01005             if (wdmamode >= 2 && apiomode >= 4) {
01006                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA2)) {
01007                     goto set_new_acard;
01008                 }
01009             }
01010         }
01011         /* Use GENERIC PIO */
01012         break; }
01013     case ATA_ACER_LABS_ID: {
01014         /************************/
01015         /* Acer Labs Inc. (ALI) */
01016         /************************/
01017         static const UCHAR ali_udma[] = {0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x0f};
01018         static const ULONG ali_pio[]  =
01019                 { 0x006d0003, 0x00580002, 0x00440001, 0x00330001,
01020                   0x00310001, 0x00440001};
01021         /* the older Aladdin doesn't support ATAPI DMA on both master & slave */
01022         if ((ChipFlags & ALIOLD) &&
01023             (udmamode >= 0 || wdmamode >= 0)) {
01024             if(ATAPI_DEVICE(deviceExtension, lChannel*2) &&
01025                ATAPI_DEVICE(deviceExtension, lChannel*2 + 1)) {
01026                 // 2 devices on this channel - NO DMA
01027                 chan->MaxTransferMode =
01028                     min(chan->MaxTransferMode, ATA_PIO4);
01029                 udmamode = wdmamode = -1;
01030                 break;
01031             }
01032         }
01033         for(i=udmamode; i>=0; i--) {
01034             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01035                 ULONG word54;
01036 
01037                 GetPciConfig4(0x54, word54);
01038                 word54 &= ~(0x000f000f << (dev * 4));
01039                 word54 |= (((ali_udma[i]<<16) | 5) << (dev * 4));
01040                 SetPciConfig4(0x54, word54);
01041                 ChangePciConfig1(0x53, a | 0x03);
01042                 SetPciConfig4(0x58 + (Channel<<2), 0x00310001);
01043                 return;
01044             }
01045         }
01046         /* make sure eventual UDMA mode from the BIOS is disabled */
01047         ChangePciConfig2(0x56, a & ~(0x0008 << (dev * 4)) );
01048         if (wdmamode >= 2 && apiomode >= 4) {
01049             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA2)) {
01050                 ChangePciConfig1(0x53, a | 0x03);
01051                 chan->ChannelCtrlFlags |= CTRFLAGS_DMA_RO;
01052                 return;
01053             }
01054         }
01055         ChangePciConfig1(0x53, (a & ~0x01) | 0x02);
01056 
01057         for(i=apiomode; i>=0; i--) {
01058             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + i)) {
01059                 ChangePciConfig4(0x54, a & ~(0x0008000f << (dev * 4)));
01060                 SetPciConfig4(0x58 + (Channel<<2), ali_pio[i]);
01061                 return;
01062             }
01063         }
01064         return;
01065         break; }
01066     case ATA_AMD_ID:
01067     case ATA_NVIDIA_ID:
01068     case ATA_VIA_ID: {
01069         /********************/
01070         /* AMD, nVidia, VIA */
01071         /********************/
01072         if((VendorID == ATA_VIA_ID) &&
01073            (ChipFlags & VIASATA) &&
01074            (Channel == 0)) {
01075             AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_SA150);
01076             return;
01077         }
01078 
01079         static const UCHAR via_modes[5][7] = {
01080             { 0xc2, 0xc1, 0xc0, 0x00, 0x00, 0x00, 0x00 },        /* ATA33 and New Chips */
01081             { 0xee, 0xec, 0xea, 0xe9, 0xe8, 0x00, 0x00 },        /* ATA66 */
01082             { 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0, 0x00 },        /* ATA100 */
01083             { 0xf7, 0xf7, 0xf6, 0xf4, 0xf2, 0xf1, 0xf0 },        /* VIA ATA133 */
01084             { 0xc2, 0xc1, 0xc0, 0xc4, 0xc5, 0xc6, 0xc7 }};       /* AMD/nVIDIA */
01085     static const UCHAR via_pio[] =
01086             { 0xa8, 0x65, 0x42, 0x22, 0x20, 0x42, 0x22, 0x20,
01087               0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
01088         const UCHAR *reg_val = NULL;
01089         UCHAR reg = 0x53-(UCHAR)dev;
01090 
01091         reg_val = &via_modes[ChipType][0];
01092 
01093         if(VendorID == ATA_NVIDIA_ID)
01094             reg += 0x10;
01095 
01096         for(i = udmamode; i>=0; i--) {
01097             SetPciConfig1(reg-0x08, via_pio[8+i]);
01098             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01099                 SetPciConfig1(reg, (UCHAR)reg_val[i]);
01100                 return;
01101             }
01102         }
01103         if(!(ChipFlags & VIABAR)) {
01104         /* This chip can't do WDMA. */
01105             for(i = wdmamode; i>=0; i--) {
01106                 SetPciConfig1(reg-0x08, via_pio[5+i]);
01107                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01108                     SetPciConfig1(reg, 0x8b);
01109                     return;
01110                 }
01111             }
01112         }
01113         /* set PIO mode timings */
01114         AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01115         if((apiomode >= 0) && (ChipType != VIA133)) {
01116             SetPciConfig1(reg-0x08, via_pio[apiomode]);
01117         }
01118         via82c_timing(deviceExtension, dev, ATA_PIO0 + apiomode);
01119         AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01120         return;
01121 
01122         break; }
01123     case ATA_CYRIX_ID: {
01124         /*********/
01125         /* Cyrix */
01126         /*********/
01127         ULONG cyr_piotiming[] =
01128             { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 };
01129         ULONG cyr_wdmatiming[] = { 0x00077771, 0x00012121, 0x00002020 };
01130         ULONG cyr_udmatiming[] = { 0x00921250, 0x00911140, 0x00911030 };
01131         ULONG mode_reg = 0x24+(dev << 3);
01132 
01133         if(apiomode >= 4)
01134             apiomode = 4;
01135         for(i=udmamode; i>=0; i--) {
01136             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01137                 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_udmatiming[udmamode]);
01138                 return;
01139             }
01140         }
01141         for(i=wdmamode; i>=0; i--) {
01142             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01143                 AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_wdmatiming[wdmamode]);
01144                 return;
01145             }
01146         }
01147         if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
01148             AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_piotiming[apiomode]);
01149             return;
01150         }
01151         return;
01152 
01153         break; }
01154     case ATA_NATIONAL_ID: {
01155         /************/
01156         /* National */
01157         /************/
01158         ULONG nat_piotiming[] =
01159            { 0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010,
01160               0x00803020, 0x20102010, 0x00100010,
01161               0x00100010, 0x00100010, 0x00100010 };
01162         ULONG nat_dmatiming[] = { 0x80077771, 0x80012121, 0x80002020 };
01163         ULONG nat_udmatiming[] = { 0x80921250, 0x80911140, 0x80911030 };
01164 
01165         if(apiomode >= 4)
01166             apiomode = 4;
01167         for(i=udmamode; i>=0; i--) {
01168             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01169                 SetPciConfig4(0x44 + (dev * 8), nat_udmatiming[i]);
01170                 SetPciConfig4(0x40 + (dev * 8), nat_piotiming[i+8]);
01171                 return;
01172             }
01173         }
01174         for(i=wdmamode; i>=0; i--) {
01175             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01176                 SetPciConfig4(0x44 + (dev * 8), nat_dmatiming[i]);
01177                 SetPciConfig4(0x40 + (dev * 8), nat_piotiming[i+5]);
01178                 return;
01179             }
01180         }
01181         if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
01182             ChangePciConfig4(0x44 + (dev * 8), a | 0x80000000);
01183             SetPciConfig4(0x40 + (dev * 8), nat_piotiming[apiomode]);
01184             return;
01185         }
01186         /* Use GENERIC PIO */
01187         break; }
01188     case ATA_CYPRESS_ID:
01189         /***********/
01190         /* Cypress */
01191         /***********/
01192         if (wdmamode >= 2 && apiomode >= 4) {
01193             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA2)) {
01194                 SetPciConfig2(Channel ? 0x4e:0x4c, 0x2020);
01195                 return;
01196             }
01197         }
01198         /* Use GENERIC PIO */
01199         break;
01200     case ATA_MARVELL_ID:
01201         /***********/
01202         /* Marvell */
01203         /***********/
01204         for(i=udmamode; i>=0; i--) {
01205             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01206                 return;
01207             }
01208         }
01209         for(i=wdmamode; i>=0; i--) {
01210             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01211                 return;
01212             }
01213         }
01214         /* try generic DMA, use hpt_timing() */
01215         if (wdmamode >= 0 && apiomode >= 4) {
01216             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_DMA)) {
01217                 return;
01218             }
01219         }
01220         AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01221         return;
01222         break;
01223     case ATA_NETCELL_ID:
01224         /***********/
01225         /* NetCell */
01226         /***********/
01227         if (wdmamode >= 2 && apiomode >= 4) {
01228             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA2)) {
01229                 return;
01230             }
01231         }
01232         /* Use GENERIC PIO */
01233         break;
01234     case ATA_HIGHPOINT_ID: {
01235         /********************/
01236         /* High Point (HPT) */
01237         /********************/
01238         for(i=udmamode; i>=0; i--) {
01239             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01240                 hpt_timing(deviceExtension, dev, (UCHAR)(ATA_UDMA + i));       // ???
01241                 return;
01242             }
01243         }
01244 
01245         for(i=wdmamode; i>=0; i--) {
01246             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01247                 hpt_timing(deviceExtension, dev, (UCHAR)(ATA_WDMA0+i));
01248                 return;
01249             }
01250         }
01251         /* try generic DMA, use hpt_timing() */
01252         if (wdmamode >= 0 && apiomode >= 4) {
01253             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_DMA)) {
01254                 return;
01255             }
01256         }
01257         AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01258         hpt_timing(deviceExtension, dev, ATA_PIO0 + apiomode);
01259         return;
01260         break; }
01261     case ATA_INTEL_ID: {
01262         /*********/
01263         /* Intel */
01264         /*********/
01265 
01266         BOOLEAN udma_ok = FALSE;
01267         ULONG  idx = 0;
01268         ULONG  reg40;
01269         UCHAR  reg44;
01270         USHORT reg48;
01271         USHORT reg4a;
01272         USHORT reg54;
01273         ULONG  mask40 = 0;
01274         ULONG  new40  = 0;
01275         UCHAR  mask44 = 0;
01276         UCHAR  new44  = 0;
01277         UCHAR  intel_timings[] = { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23,
01278                                0x23, 0x23, 0x23, 0x23, 0x23, 0x23 };
01279 
01280         if(deviceExtension->DevID == ATA_I82371FB) {
01281             if (wdmamode >= 2 && apiomode >= 4) {
01282                 ULONG word40;
01283 
01284                 GetPciConfig4(0x40, word40);
01285                 word40 >>= Channel * 16;
01286 
01287                 /* Check for timing config usable for DMA on controller */
01288                 if (!((word40 & 0x3300) == 0x2300 &&
01289                       ((word40 >> ((!(DeviceNumber & 1)) ? 0 : 4)) & 1) == 1)) {
01290                     udmamode = wdmamode = -1;
01291                     break;
01292                 }
01293 
01294                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA2)) {
01295                     return;
01296                 }
01297             }
01298             break;
01299         }
01300 
01301         if(deviceExtension->DevID == ATA_ISCH) {
01302             ULONG tim;
01303             GetPciConfig4(0x80 + dev*4, tim);
01304 
01305             for(i=udmamode; i>=0; i--) {
01306                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01307                     tim |= (0x1 << 31);
01308                     tim &= ~(0x7 << 16);
01309                     tim |= (i << 16);
01310 
01311                     idx = i+8;
01312                     udma_ok = TRUE;
01313                     apiomode = ATA_PIO4;
01314                     break;
01315                 }
01316             }
01317             if(!udma_ok) {
01318                 for(i=wdmamode; i>=0; i--) {
01319                     if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01320                         tim &= ~(0x1 << 31);
01321                         tim &= ~(0x3 << 8);
01322                         tim |= (i << 8);
01323 
01324                         idx = i+5;
01325                         udma_ok = TRUE;
01326                         apiomode = (i == 0) ? ATA_PIO0 :
01327                             (i == 1) ? ATA_PIO3 : ATA_PIO4;
01328                         break;
01329                     }
01330                 }
01331             }
01332             if(!udma_ok) {
01333                 AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01334                 idx = apiomode;
01335             }
01336             tim &= ~(0x7);
01337             tim |= (apiomode & 0x7);
01338             SetPciConfig4(0x80 + dev*4, tim);
01339 
01340             break;
01341         }
01342 
01343         GetPciConfig2(0x48, reg48);
01344         if(!(ChipFlags & ICH4_FIX)) {
01345             GetPciConfig2(0x4a, reg4a);
01346         }
01347         GetPciConfig2(0x54, reg54);
01348 //        if(udmamode >= 0) {
01349             // enable the write buffer to be used in a split (ping/pong) manner.
01350             reg54 |= 0x400;
01351 //        } else {
01352 //            reg54 &= ~0x400;
01353 //        }
01354 
01355 //        reg40 &= ~0x00ff00ff;
01356 //        reg40 |= 0x40774077;
01357 
01358         for(i=udmamode; i>=0; i--) {
01359             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01360 
01361             /* Set UDMA reference clock (33/66/133MHz). */
01362                 SetPciConfig1(0x48, reg48 | (0x0001 << dev));
01363                 if(!(ChipFlags & ICH4_FIX)) {
01364                     SetPciConfig2(0x4a, (reg4a & ~(0x3 << (dev<<2))) |
01365                                         (0x01 + !(i & 0x01))  );
01366                 }
01367                 if(i >= 3) {
01368                     reg54 |= (0x1 << dev);
01369                 } else {
01370                     reg54 &= ~(0x1 << dev);
01371                 }
01372                 if(i >= 5) {
01373                     reg54 |= (0x1000 << dev);
01374                 } else {
01375                     reg54 &= ~(0x1000 << dev);
01376                 }
01377                 SetPciConfig2(0x54, reg54);
01378 
01379                 udma_ok = TRUE;
01380                 idx = i+8;
01381                 if(ChipFlags & ICH4_FIX) {
01382                     return;
01383                 }
01384                 break;
01385             }
01386         }
01387 
01388         if(!udma_ok) {
01389             SetPciConfig1(0x48, reg48 & ~(0x0001 << dev));
01390             if(!(ChipFlags & ICH4_FIX)) {
01391                 SetPciConfig2(0x4a, (reg4a & ~(0x3 << (dev << 2)))  );
01392             }
01393             SetPciConfig2(0x54, reg54 & ~(0x1001 << dev));
01394             for(i=wdmamode; i>=0; i--) {
01395                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01396                     udma_ok = TRUE;
01397                     idx = i+5;
01398                     if(ChipFlags & ICH4_FIX) {
01399                         return;
01400                     }
01401                     break;
01402                 }
01403             }
01404         }
01405 
01406         if(!udma_ok) {
01407             AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01408             idx = apiomode;
01409         }
01410 
01411         GetPciConfig4(0x40, reg40);
01412         GetPciConfig1(0x44, reg44);
01413 
01414     /* Allow PIO/WDMA timing controls. */
01415         reg40 &= ~0x00ff00ff;
01416         reg40 |= ~0x40774077;
01417     /* Set PIO/WDMA timings. */
01418         if(!(DeviceNumber & 1)) {
01419             mask40 |= 0x00003300;
01420             new40 = ((USHORT)(intel_timings[idx]) << 8);
01421         } else {
01422             mask44 = 0x0f;
01423             new44 = ((intel_timings[idx] & 0x30) >> 2) |
01424                      (intel_timings[idx] & 0x03);
01425         }
01426 
01427         if (Channel) {
01428             mask40 <<= 16;
01429             new40 <<= 16;
01430             mask44 <<= 4;
01431             new44 <<= 4;
01432         }
01433 
01434         SetPciConfig4(0x40, (reg40 & ~mask40) | new40);
01435         SetPciConfig1(0x44, (reg44 & ~mask44) | new44);
01436 
01437         return;
01438         break; }
01439     case ATA_PROMISE_ID:
01440         /***********/
01441         /* Promise */
01442         /***********/
01443         if(ChipType < PRTX) {
01444             if (ATAPI_DEVICE(deviceExtension, ldev)) {
01445                 udmamode =
01446                 wdmamode = -1;
01447             }
01448         }
01449         for(i=udmamode; i>=0; i--) {
01450             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01451                 promise_timing(deviceExtension, dev, (UCHAR)(ATA_UDMA + i));       // ???
01452                 return;
01453             }
01454         }
01455 
01456         for(i=wdmamode; i>=0; i--) {
01457             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01458                 promise_timing(deviceExtension, dev, (UCHAR)(ATA_WDMA0+i));
01459                 return;
01460             }
01461         }
01462         /* try generic DMA, use hpt_timing() */
01463         if (wdmamode >= 0 && apiomode >= 4) {
01464             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_DMA)) {
01465                 return;
01466             }
01467         }
01468         AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01469         promise_timing(deviceExtension, dev, ATA_PIO0 + apiomode);
01470         return;
01471         break;
01472     case ATA_ATI_ID:
01473 
01474         KdPrint2((PRINT_PREFIX "ATI\n"));
01475         if(ChipType == SIIMIO) {
01476             goto l_ATA_SILICON_IMAGE_ID;
01477         }
01478         //goto ATA_SERVERWORKS_ID;
01479         // FALL THROUGH
01480 
01481         //break; }
01482 
01483     case ATA_SERVERWORKS_ID: {
01484         /***************/
01485         /* ServerWorks */
01486         /***************/
01487 //        static const ULONG udma_modes[] = { 0x70, 0x21, 0x20 };
01488         static const ULONG sw_dma_modes[] = { 0x70, 0x21, 0x20 };
01489         static const ULONG sw_pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20, 0x34, 0x22, 0x20,
01490                                               0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
01491         USHORT reg56;
01492         ULONG  reg44;
01493         ULONG  reg40;
01494         ULONG  offset = dev ^ 0x01;
01495         ULONG  bit_offset = offset * 8;
01496 
01497         for(i=udmamode; i>=0; i--) {
01498             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01499                 GetPciConfig2(0x56, reg56);
01500                 reg56 &= ~(0xf << (dev * 4));
01501                 reg56 |= ((USHORT)i << (dev * 4));
01502                 SetPciConfig2(0x56, reg56);
01503                 ChangePciConfig1(0x54, a | (0x01 << dev));
01504                 // 44
01505                 GetPciConfig4(0x44, reg44);
01506                 reg44 = (reg44 & ~(0xff << bit_offset)) |
01507                              (sw_dma_modes[2] << bit_offset);
01508                 SetPciConfig4(0x44, reg44);
01509                 // 40
01510                 GetPciConfig4(0x40, reg40);
01511                 reg40 = (reg40 & ~(0xff << bit_offset)) |
01512                              (sw_pio_modes[8+i] << bit_offset);
01513                 SetPciConfig4(0x40, reg40);
01514                 return;
01515             }
01516         }
01517 
01518         for(i=wdmamode; i>=0; i--) {
01519             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01520 
01521                 ChangePciConfig1(0x54, a & ~(0x01 << dev));
01522                 // 44
01523                 GetPciConfig4(0x44, reg44);
01524                 reg44 = (reg44 & ~(0xff << bit_offset)) |
01525                              (sw_dma_modes[wdmamode] << bit_offset);
01526                 SetPciConfig4(0x44, reg44);
01527                 // 40
01528                 GetPciConfig4(0x40, reg40);
01529                 reg40 = (reg40 & ~(0xff << bit_offset)) |
01530                              (sw_pio_modes[5+i] << bit_offset);
01531                 SetPciConfig4(0x40, reg40);
01532                 return;
01533             }
01534         }
01535         AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01536 //        SetPciConfig4(0x44, sw_pio_modes[apiomode]);
01537         if(VendorID == ATA_ATI_ID) {
01538             // special case for ATI
01539             // Seems, that PATA ATI are just re-brended ServerWorks
01540             USHORT reg4a;
01541             // 4a
01542             GetPciConfig2(0x4a, reg4a);
01543             reg4a = (reg4a & ~(0xf << (dev*4))) |
01544                            (apiomode << (dev*4));
01545             SetPciConfig2(0x4a, reg4a);
01546         }
01547 
01548         // 40
01549         GetPciConfig4(0x40, reg40);
01550         reg40 = (reg40 & ~(0xff << bit_offset)) |
01551                        (sw_pio_modes[apiomode] << bit_offset);
01552         SetPciConfig4(0x40, reg40);
01553         return;
01554         break; }
01555     case ATA_SILICON_IMAGE_ID: {
01556 l_ATA_SILICON_IMAGE_ID:
01557         /********************/
01558         /* SiliconImage/CMD */
01559         /********************/
01560         if(ChipType == SIIMIO) {
01561 
01562             static const UCHAR sil_modes[7] =
01563                 { 0xf, 0xb, 0x7, 0x5, 0x3, 0x2, 0x1 };
01564             static const USHORT sil_wdma_modes[3] =
01565                 { 0x2208, 0x10c2, 0x10c1 };
01566             static const USHORT sil_pio_modes[6] =
01567                 { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1, 0x10c1 };
01568 
01569             UCHAR ureg = 0xac + ((UCHAR)DeviceNumber * 0x02) + ((UCHAR)Channel * 0x10);
01570             UCHAR uval;
01571             UCHAR mreg = Channel ? 0x84 : 0x80;
01572             UCHAR mask = DeviceNumber ? 0x30 : 0x03;
01573             UCHAR mode;
01574 
01575             GetPciConfig1(ureg, uval);
01576             GetPciConfig1(mreg, mode);
01577 
01578             /* enable UDMA mode */
01579             for(i = udmamode; i>=0; i--) {
01580 
01581                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01582                     SetPciConfig1(mreg, mode | mask);
01583                     SetPciConfig1(ureg, (uval & 0x3f) | sil_modes[i]);
01584                     return;
01585                 }
01586             }
01587             /* enable WDMA mode */
01588             for(i = wdmamode; i>=0; i--) {
01589 
01590                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01591                     SetPciConfig1(mreg, mode | (mask & 0x22));
01592                     SetPciConfig2(ureg - 0x4, sil_wdma_modes[i]);
01593                     return;
01594                 }
01595             }
01596             /* restore PIO mode */
01597             AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01598 
01599             SetPciConfig1(mreg, mode | (mask & 0x11));
01600             SetPciConfig2(ureg - 0x8, sil_pio_modes[apiomode]);
01601             return;
01602 
01603         } else {
01604 
01605             static const UCHAR cmd_modes[2][6] = {
01606                 { 0x31, 0x21, 0x011, 0x25, 0x15, 0x05 },
01607                 { 0xc2, 0x82, 0x042, 0x8a, 0x4a, 0x0a } };
01608             static const UCHAR cmd_wdma_modes[] = { 0x87, 0x32, 0x3f };
01609             static const UCHAR cmd_pio_modes[] = { 0xa9, 0x57, 0x44, 0x32, 0x3f };
01610             ULONG treg = 0x54 + ((dev < 3) ? (dev << 1) : 7);
01611 
01612             udmamode = min(udmamode, 5);
01613             /* enable UDMA mode */
01614             for(i = udmamode; i>=0; i--) {
01615                 UCHAR umode;
01616 
01617                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01618                     GetPciConfig1(Channel ? 0x7b : 0x73, umode);
01619                     umode &= ~(!(DeviceNumber & 1) ? 0x35 : 0xca);
01620                     umode |= ( cmd_modes[DeviceNumber & 1][i]);
01621                     SetPciConfig1(Channel ? 0x7b : 0x73, umode);
01622                     return;
01623                 }
01624             }
01625             /* make sure eventual UDMA mode from the BIOS is disabled */
01626             ChangePciConfig1(Channel ? 0x7b : 0x73, a & ~(!(DeviceNumber & 1) ? 0x35 : 0xca));
01627 
01628             for(i = wdmamode; i>=0; i--) {
01629 
01630                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01631                     SetPciConfig1(treg, cmd_wdma_modes[i]);
01632                     ChangePciConfig1(Channel ? 0x7b : 0x73, a & ~(!(DeviceNumber & 1) ? 0x35 : 0xca));
01633                     return;
01634                 }
01635             }
01636             /* set PIO mode timings */
01637             AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01638 
01639             SetPciConfig1(treg, cmd_pio_modes[apiomode]);
01640             ChangePciConfig1(Channel ? 0x7b : 0x73, a & ~(!(DeviceNumber & 1) ? 0x35 : 0xca));
01641             return;
01642 
01643         }
01644         return;
01645         break; }
01646     case ATA_SIS_ID: {
01647         /*******/
01648         /* SiS */
01649         /*******/
01650         PULONG sis_modes = NULL;
01651         static const ULONG sis_modes_new133[] =
01652                 { 0x28269008, 0x0c266008, 0x04263008, 0x0c0a3008, 0x05093008,
01653                   0x22196008, 0x0c0a3008, 0x05093008, 0x050939fc, 0x050936ac,
01654                   0x0509347c, 0x0509325c, 0x0509323c, 0x0509322c, 0x0509321c};
01655         static const ULONG sis_modes_old133[] =
01656                 { 0x00cb, 0x0067, 0x0044, 0x0033, 0x0031, 0x0044, 0x0033, 0x0031,
01657                   0x8f31, 0x8a31, 0x8731, 0x8531, 0x8331, 0x8231, 0x8131 };
01658         static const ULONG sis_modes_old[] =
01659                 { 0x0c0b, 0x0607, 0x0404, 0x0303, 0x0301, 0x0404, 0x0303, 0x0301,
01660                   0xf301, 0xd301, 0xb301, 0xa301, 0x9301, 0x8301 };
01661         static const ULONG sis_modes_new100[] =
01662                 { 0x00cb, 0x0067, 0x0044, 0x0033, 0x0031, 0x0044, 0x0033, 0x0031,
01663                   0x8b31, 0x8731, 0x8531, 0x8431, 0x8231, 0x8131 };
01664 
01665         ULONG reg = 0;
01666         UCHAR reg57;
01667         ULONG reg_size = 0;
01668         ULONG offs;
01669 
01670         switch(ChipType) {
01671         case SIS133NEW:
01672             sis_modes = (PULONG)(&sis_modes_new133[0]);
01673             reg_size = 4;
01674             GetPciConfig1(0x57, reg57);
01675             reg = (reg57 & 0x40 ? 0x70 : 0x40) + (dev * 4);
01676             break;
01677         case SIS133OLD:
01678             sis_modes = (PULONG)(&sis_modes_old133[0]);
01679             reg_size = 2;
01680             reg = 0x40 + (dev * 2);
01681             break;
01682         case SIS100NEW:
01683             sis_modes = (PULONG)(&sis_modes_new100[0]);
01684             reg_size = 2;
01685             reg = 0x40 + (dev * 2);
01686             break;
01687         case SIS100OLD:
01688         case SIS66:
01689         case SIS33:
01690             sis_modes = (PULONG)(&sis_modes_old[0]);
01691             reg_size = 2;
01692             reg = 0x40 + (dev * 2);
01693             break;
01694         }
01695 
01696         offs = 5+3;
01697         for(i=udmamode; i>=0; i--) {
01698             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01699                 if(reg_size == 4) {
01700                     SetPciConfig4(reg, sis_modes[offs+i]);
01701                 } else {
01702                     SetPciConfig2(reg, (USHORT)sis_modes[offs+i]);
01703                 }
01704                 return;
01705             }
01706         }
01707 
01708         offs = 5;
01709         for(i=wdmamode; i>=0; i--) {
01710             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01711                 if(reg_size == 4) {
01712                     SetPciConfig4(reg, sis_modes[offs+i]);
01713                 } else {
01714                     SetPciConfig2(reg, (USHORT)sis_modes[offs+i]);
01715                 }
01716                 return;
01717             }
01718         }
01719         AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01720         if(reg_size == 4) {
01721             SetPciConfig4(reg, sis_modes[apiomode]);
01722         } else {
01723             SetPciConfig2(reg, (USHORT)sis_modes[apiomode]);
01724         }
01725         return;
01726         break; }
01727     case 0x16ca:
01728         /* Cenatek Rocket Drive controller */
01729         if (wdmamode >= 0 &&
01730             (AtapiReadPort1(chan, IDX_BM_Status) &
01731              (DeviceNumber ? BM_STATUS_DRIVE_1_DMA : BM_STATUS_DRIVE_0_DMA))) {
01732             AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + wdmamode);
01733         } else {
01734             AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01735         }
01736         return;
01737     case ATA_ITE_ID: {       /* ITE IDE controller */
01738 
01739         if(ChipType == ITE_33) {
01740             int a_speed = 3 << (dev * 4);
01741             int u_flag  = 1 << dev;
01742             int u_speed = 0;
01743             int pio     = 1;
01744             UCHAR  reg48, reg4a;
01745             USHORT drive_enables;
01746             ULONG  drive_timing;
01747 
01748             GetPciConfig1(0x48, reg48);
01749             GetPciConfig1(0x4a, reg4a);
01750 
01751             /*
01752              * Setting the DMA cycle time to 2 or 3 PCI clocks (60 and 91 nsec
01753              * at 33 MHz PCI clock) seems to cause BadCRC errors during DMA
01754              * transfers on some drives, even though both numbers meet the minimum
01755              * ATAPI-4 spec of 73 and 54 nsec for UDMA 1 and 2 respectively.
01756              * So the faster times are just commented out here. The good news is
01757              * that the slower cycle time has very little affect on transfer
01758              * performance.
01759              */
01760 
01761             for(i=udmamode; i>=0; i--) {
01762                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01763                     SetPciConfig1(0x48, reg48 | u_flag);
01764                     reg4a &= ~a_speed;
01765                     SetPciConfig1(0x4a, reg4a | u_speed);
01766                     pio = 4;
01767                     goto setup_drive_ite;
01768                 }
01769             }
01770 
01771             for(i=wdmamode; i>=0; i--) {
01772                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01773                     SetPciConfig1(0x48, reg48 & ~u_flag);
01774                     SetPciConfig1(0x4a, reg4a & ~a_speed);
01775                     pio = 3;
01776                     return;
01777                 }
01778             }
01779             AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01780             SetPciConfig1(0x48, reg48 & ~u_flag);
01781             SetPciConfig1(0x4a, reg4a & ~a_speed);
01782 
01783             pio = apiomode;
01784 
01785 setup_drive_ite:
01786 
01787             GetPciConfig2(0x40, drive_enables);
01788             GetPciConfig4(0x44, drive_timing);
01789 
01790             /*
01791              * FIX! The DIOR/DIOW pulse width and recovery times in port 0x44
01792              * are being left at the default values of 8 PCI clocks (242 nsec
01793              * for a 33 MHz clock). These can be safely shortened at higher
01794              * PIO modes. The DIOR/DIOW pulse width and recovery times only
01795              * apply to PIO modes, not to the DMA modes.
01796              */
01797 
01798             /*
01799              * Enable port 0x44. The IT8172G spec is confused; it calls
01800              * this register the "Slave IDE Timing Register", but in fact,
01801              * it controls timing for both master and slave drives.
01802              */
01803             drive_enables |= 0x4000;
01804 
01805             drive_enables &= (0xc000 | (0x06 << (DeviceNumber*4)));
01806             if (pio > 1) {
01807             /* enable prefetch and IORDY sample-point */
01808                 drive_enables |= (0x06 << (DeviceNumber*4));
01809             }
01810 
01811             SetPciConfig2(0x40, drive_enables);
01812         } else
01813         if(ChipType == ITE_133) {
01814             static const UCHAR udmatiming[] =
01815                 { 0x44, 0x42, 0x31, 0x21, 0x11, 0xa2, 0x91 };
01816             static const UCHAR chtiming[] =
01817                 { 0xaa, 0xa3, 0xa1, 0x33, 0x31, 0x88, 0x32, 0x31 };
01818             ULONG offset = (Channel<<2) + DeviceNumber;
01819             UCHAR reg54;
01820 
01821             for(i=udmamode; i>=0; i--) {
01822                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01823                     ChangePciConfig1(0x50, a & ~(1 << (dev + 3)) );
01824                     SetPciConfig1(0x56 + offset, udmatiming[i]);
01825                     return;
01826                 }
01827             }
01828 
01829             for(i=wdmamode; i>=0; i--) {
01830                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01831 
01832                     ChangePciConfig1(0x50, a | (1 << (dev + 3)) );
01833                     GetPciConfig1(0x54 + offset, reg54);
01834                     if(reg54 < chtiming[i+5]) {
01835                         SetPciConfig1(0x54 + offset, chtiming[i+5]);
01836                     }
01837                     return;
01838                 }
01839             }
01840             AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01841             ChangePciConfig1(0x50, a | (1 << (dev + 3)) );
01842             GetPciConfig1(0x54 + offset, reg54);
01843             if(reg54 < chtiming[apiomode]) {
01844                 SetPciConfig1(0x54 + offset, chtiming[apiomode]);
01845             }
01846             return;
01847         } else
01848         if(ChipType == ITE_133_NEW) {
01849             //static const USHORT reg54_timings[] = { 0x0000, 0x0000, 0x0001, 0x0001, 0x0001, 0x1001, 0x1001 };
01850             static const UCHAR udmatiming[] =
01851                 { 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10  };
01852             static const UCHAR timings[] =
01853                 { 0x00, 0x00, 0x10, 0x21, 0x23, 0x10, 0x21, 0x23,
01854                0x23, 0x23, 0x23, 0x23, 0x23, 0x02, 0x02 };
01855             BOOLEAN udma_ok = FALSE;
01856             BOOLEAN ok = FALSE;
01857             UCHAR timing = 0;
01858 
01859             WCHAR reg40;
01860             UCHAR reg44;
01861             USHORT reg4a;
01862             USHORT reg54;
01863             USHORT mask40=0, new40=0;
01864             UCHAR mask44=0, new44=0;
01865 
01866             GetPciConfig2(0x40, reg40);
01867             GetPciConfig1(0x44, reg44);
01868             GetPciConfig2(0x4a, reg4a);
01869             GetPciConfig2(0x54, reg54);
01870 
01871             if(!(reg54 & (0x10 << dev))) {
01872                 // 80-pin check
01873                 udmamode = min(udmamode, 2);
01874             }
01875 
01876             for(i=udmamode; i>=0; i--) {
01877                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01878                     ChangePciConfig1(0x48, a | (1 << dev) );
01879                     ChangePciConfig2(0x4a,
01880                              (a & ~(0x3 << (dev*4))) |
01881                              (udmatiming[i] << (dev*4)) );
01882                     ok=TRUE;
01883                     udma_ok=TRUE;
01884                     timing = timings[i+8];
01885                     break;
01886                 }
01887             }
01888              
01889             for(i=wdmamode; !ok && i>=0; i--) {
01890                 if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01891 
01892                     ok=TRUE;
01893                     timing = timings[i+5];
01894                     break;
01895                 }
01896             }
01897 
01898             if(!ok) {
01899                 AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01900                 timing = timings[apiomode];
01901             }
01902 
01903             if(!udma_ok) {
01904                 ChangePciConfig1(0x48, a & ~(1 << dev) );
01905                 ChangePciConfig2(0x4a, a & ~(0x3 << (dev << 2)) );
01906             }
01907             if (udma_ok && udmamode >= ATA_UDMA2) {
01908                 reg54 |= (0x1 << dev);
01909             } else {
01910                 reg54 &= ~(0x1 << dev);
01911             }
01912             if (udma_ok && udmamode >= ATA_UDMA5) {
01913                 reg54 |= (0x1000 << dev);
01914             } else {
01915                 reg54 &= ~(0x1000 << dev);
01916             }
01917             SetPciConfig2(0x54, reg54 );
01918 
01919             reg40 &= 0xff00;
01920             reg40 |= 0x4033;
01921 
01922             if(!(ldev & 1)) {
01923                 reg40 |= (ATAPI_DEVICE(deviceExtension, ldev) ? 0x04 : 0x00);
01924                 mask40 = 0x3300;
01925                 new40 = timing << 8;
01926             } else {
01927                 reg40 |= (ATAPI_DEVICE(deviceExtension, ldev) ? 0x40 : 0x00);
01928                 mask44 = 0x0f;
01929                 new44 = ((timing & 0x30) >> 2) |
01930                         (timing & 0x03);
01931             }
01932             SetPciConfig2(0x40, (reg40 & ~mask40) | new40);
01933             SetPciConfig1(0x44, (reg44 & ~mask44) | new44);
01934             return;
01935         }
01936 
01937         return;
01938         break; }
01939     case 0x3388:
01940         /* HiNT Corp. VXPro II EIDE */
01941         if (wdmamode >= 0 &&
01942             (AtapiReadPort1(chan, IDX_BM_Status) &
01943              (DeviceNumber ? BM_STATUS_DRIVE_1_DMA : BM_STATUS_DRIVE_0_DMA))) {
01944             AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_DMA);
01945         } else {
01946             AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode);
01947         }
01948         return;
01949     case ATA_JMICRON_ID: {
01950 
01951         UCHAR reg40;
01952         GetPciConfig1(0x40, reg40);
01953 
01954         if(reg40 & 0x08) {
01955             // 80-pin check
01956             udmamode = min(udmamode, 2);
01957         }
01958     /* Nothing to do to setup mode, the controller snoop SET_FEATURE cmd. */
01959         if(apiomode >= 4)
01960             apiomode = 4;
01961         for(i=udmamode; i>=0; i--) {
01962             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
01963                 return;
01964             }
01965         }
01966         for(i=wdmamode; i>=0; i--) {
01967             if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
01968                 return;
01969             }
01970         }
01971         if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
01972             return;
01973         }
01974         return;
01975         break; }
01976     }
01977 
01978 try_generic_dma:
01979 
01980     /* unknown controller chip */
01981 
01982     /* better not try generic DMA on ATAPI devices it almost never works */
01983     if (ATAPI_DEVICE(deviceExtension, ldev)) {
01984         KdPrint2((PRINT_PREFIX "ATAPI on unknown controller -> PIO\n"));
01985         udmamode =
01986         wdmamode = -1;
01987     }
01988 
01989     /* if controller says its setup for DMA take the easy way out */
01990     /* the downside is we dont know what DMA mode we are in */
01991     if ((udmamode >= 0 || /*wdmamode > 1*/ wdmamode >= 0) &&
01992          /*deviceExtension->BaseIoAddressBM[lChannel]*/ deviceExtension->BusMaster &&
01993         (GetDmaStatus(deviceExtension, lChannel) &
01994          (!(ldev & 1) ?
01995           BM_STATUS_DRIVE_0_DMA : BM_STATUS_DRIVE_1_DMA))) {
01996 //        LunExt->TransferMode = ATA_DMA;
01997 //        return;
01998         KdPrint2((PRINT_PREFIX "try DMA on unknown controller\n"));
01999         if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_DMA)) {
02000             return;
02001         }
02002     }
02003 
02004 #if 0
02005     /* well, we have no support for this, but try anyways */
02006     if ((wdmamode >= 0 && apiomode >= 4) && deviceExtension->BaseIoAddressBM[lChannel]) {
02007         if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_DMA/* + wdmamode*/)) {
02008             return;
02009         }
02010     }
02011 #endif
02012 
02013     KdPrint2((PRINT_PREFIX "try PIO%d on unknown controller\n", apiomode));
02014     if(!AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
02015         KdPrint2((PRINT_PREFIX "fall to PIO on unknown controller\n"));
02016         LunExt->TransferMode = ATA_PIO;
02017     }
02018     return;
02019 } // end AtapiDmaInit()
02020 
02021 
02022 VOID
02023 NTAPI
02024 cyrix_timing(
02025     IN PHW_DEVICE_EXTENSION deviceExtension,
02026     IN ULONG dev,               // physical device number (0-3)
02027     IN CHAR  mode
02028     )
02029 {
02030 //    ASSERT(dev/2 >= deviceExtension->Channel);
02031 //    PHW_CHANNEL chan = &(deviceExtension->chan[dev/2-deviceExtension->Channel]);
02032     ULONG reg20 = 0x0000e132;
02033     ULONG reg24 = 0x00017771;
02034 
02035     if(mode == ATA_PIO5)
02036         mode = ATA_PIO4;
02037 
02038     switch (mode) {
02039     case ATA_PIO0:        reg20 = 0x0000e132; break;
02040     case ATA_PIO1:        reg20 = 0x00018121; break;
02041     case ATA_PIO2:        reg20 = 0x00024020; break;
02042     case ATA_PIO3:        reg20 = 0x00032010; break;
02043     case ATA_PIO4:
02044     case ATA_PIO5:        reg20 = 0x00040010; break;
02045     case ATA_WDMA2:       reg24 = 0x00002020; break;
02046     case ATA_UDMA2:       reg24 = 0x00911030; break;
02047     }
02048     AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),(dev*8) + 0x20, reg20);
02049     AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0),(dev*8) + 0x24, reg24);
02050 } // cyrix_timing()
02051 
02052 VOID
02053 NTAPI
02054 promise_timing(
02055     IN PHW_DEVICE_EXTENSION deviceExtension,
02056     IN ULONG dev,               // physical device number (0-3)
02057     IN CHAR  mode
02058     )
02059 {
02060     PVOID HwDeviceExtension = (PVOID)deviceExtension;
02061     ULONG slotNumber = deviceExtension->slotNumber;
02062     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
02063 
02064     ULONG ChipType  = deviceExtension->HwFlags & CHIPTYPE_MASK;
02065     //ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
02066 
02067     ULONG timing = 0;
02068 
02069     if(mode == ATA_PIO5)
02070         mode = ATA_PIO4;
02071 
02072     switch(ChipType) {
02073     case PROLD:
02074         switch (mode) {
02075         default:
02076         case ATA_PIO0:  timing = 0x004ff329; break;
02077         case ATA_PIO1:  timing = 0x004fec25; break;
02078         case ATA_PIO2:  timing = 0x004fe823; break;
02079         case ATA_PIO3:  timing = 0x004fe622; break;
02080         case ATA_PIO4:  timing = 0x004fe421; break;
02081         case ATA_WDMA0: timing = 0x004567f3; break;
02082         case ATA_WDMA1: timing = 0x004467f3; break;
02083         case ATA_WDMA2: timing = 0x004367f3; break;
02084         case ATA_UDMA0: timing = 0x004367f3; break;
02085         case ATA_UDMA1: timing = 0x004247f3; break;
02086         case ATA_UDMA2: timing = 0x004127f3; break;
02087         }
02088         break;
02089 
02090     case PRNEW:
02091         switch (mode) {
02092         default:
02093         case ATA_PIO0:  timing = 0x004fff2f; break;
02094         case ATA_PIO1:  timing = 0x004ff82a; break;
02095         case ATA_PIO2:  timing = 0x004ff026; break;
02096         case ATA_PIO3:  timing = 0x004fec24; break;
02097         case ATA_PIO4:  timing = 0x004fe822; break;
02098         case ATA_WDMA0: timing = 0x004acef6; break;
02099         case ATA_WDMA1: timing = 0x0048cef6; break;
02100         case ATA_WDMA2: timing = 0x0046cef6; break;
02101         case ATA_UDMA0: timing = 0x0046cef6; break;
02102         case ATA_UDMA1: timing = 0x00448ef6; break;
02103         case ATA_UDMA2: timing = 0x00436ef6; break;
02104         case ATA_UDMA3: timing = 0x00424ef6; break;
02105         case ATA_UDMA4: timing = 0x004127f3; break;
02106         case ATA_UDMA5: timing = 0x004127f3; break;
02107         }
02108         break;
02109     default:
02110         return;
02111     }
02112     SetPciConfig4(0x60 + (dev<<2), timing);
02113 } // end promise_timing()
02114 
02115 
02116 VOID
02117 NTAPI
02118 hpt_timing(
02119     IN PHW_DEVICE_EXTENSION deviceExtension,
02120     IN ULONG dev,               // physical device number (0-3)
02121     IN CHAR  mode
02122     )
02123 {
02124     PVOID HwDeviceExtension = (PVOID)deviceExtension;
02125     ULONG slotNumber = deviceExtension->slotNumber;
02126     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
02127 
02128     ULONG ChipType  = deviceExtension->HwFlags & CHIPTYPE_MASK;
02129     //ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK;
02130 
02131     ULONG timing = 0;
02132 
02133     if(mode == ATA_PIO5)
02134         mode = ATA_PIO4;
02135 
02136     switch(ChipType) {
02137     case HPT374:
02138 
02139         switch (mode) {                                                /* HPT374 */
02140         case ATA_PIO0:  timing = 0x0ac1f48a; break;
02141         case ATA_PIO1:  timing = 0x0ac1f465; break;
02142         case ATA_PIO2:  timing = 0x0a81f454; break;
02143         case ATA_PIO3:  timing = 0x0a81f443; break;
02144         case ATA_PIO4:  timing = 0x0a81f442; break;
02145         case ATA_WDMA0: timing = 0x228082ea; break;
02146         case ATA_WDMA1: timing = 0x22808254; break;
02147         case ATA_WDMA2: timing = 0x22808242; break;
02148         case ATA_UDMA0: timing = 0x121882ea; break;
02149         case ATA_UDMA1: timing = 0x12148254; break;
02150         case ATA_UDMA2: timing = 0x120c8242; break;
02151         case ATA_UDMA3: timing = 0x128c8242; break;
02152         case ATA_UDMA4: timing = 0x12ac8242; break;
02153         case ATA_UDMA5: timing = 0x12848242; break;
02154         case ATA_UDMA6: timing = 0x12808242; break;
02155         default:        timing = 0x0d029d5e;
02156         }
02157         break;
02158 
02159     case HPT372:
02160 
02161         switch (mode) {                                                /* HPT372 */
02162         case ATA_PIO0:  timing = 0x0d029d5e; break;
02163         case ATA_PIO1:  timing = 0x0d029d26; break;
02164         case ATA_PIO2:  timing = 0x0c829ca6; break;
02165         case ATA_PIO3:  timing = 0x0c829c84; break;
02166         case ATA_PIO4:  timing = 0x0c829c62; break;
02167         case ATA_WDMA0: timing = 0x2c82922e; break;
02168         case ATA_WDMA1: timing = 0x2c829266; break;
02169         case ATA_WDMA2: timing = 0x2c829262; break;
02170         case ATA_UDMA0: timing = 0x1c829c62; break;
02171         case ATA_UDMA1: timing = 0x1c9a9c62; break;
02172         case ATA_UDMA2: timing = 0x1c929c62; break;
02173         case ATA_UDMA3: timing = 0x1c8e9c62; break;
02174         case ATA_UDMA4: timing = 0x1c8a9c62; break;
02175         case ATA_UDMA5: timing = 0x1c8a9c62; break;
02176         case ATA_UDMA6: timing = 0x1c869c62; break;
02177         default:        timing = 0x0d029d5e;
02178         }
02179         break;
02180 
02181     case HPT370:
02182 
02183         switch (mode) {                                                /* HPT370 */
02184         case ATA_PIO0:  timing = 0x06914e57; break;
02185         case ATA_PIO1:  timing = 0x06914e43; break;
02186         case ATA_PIO2:  timing = 0x06514e33; break;
02187         case ATA_PIO3:  timing = 0x06514e22; break;
02188         case ATA_PIO4:  timing = 0x06514e21; break;
02189         case ATA_WDMA0: timing = 0x26514e97; break;
02190         case ATA_WDMA1: timing = 0x26514e33; break;
02191         case ATA_WDMA2: timing = 0x26514e21; break;
02192         case ATA_UDMA0: timing = 0x16514e31; break;
02193         case ATA_UDMA1: timing = 0x164d4e31; break;
02194         case ATA_UDMA2: timing = 0x16494e31; break;
02195         case ATA_UDMA3: timing = 0x166d4e31; break;
02196         case ATA_UDMA4: timing = 0x16454e31; break;
02197         case ATA_UDMA5: timing = 0x16454e31; break;
02198         default:        timing = 0x06514e57;
02199         }
02200 
02201     case HPT366: {
02202         UCHAR reg41;
02203 
02204         GetPciConfig1(0x41 + (dev << 2), reg41);
02205 
02206         switch (reg41) {
02207         case 0x85:        /* 25Mhz */
02208             switch (mode) {
02209             case ATA_PIO0:        timing = 0x40d08585; break;
02210             case ATA_PIO1:        timing = 0x40d08572; break;
02211             case ATA_PIO2:        timing = 0x40ca8542; break;
02212             case ATA_PIO3:        timing = 0x40ca8532; break;
02213             case ATA_PIO4:        timing = 0x40ca8521; break;
02214             case ATA_WDMA2:       timing = 0x20ca8521; break;
02215             case ATA_UDMA2:       timing = 0x10cf8521; break;
02216             case ATA_UDMA4:       timing = 0x10c98521; break;
02217             default:              timing = 0x01208585;
02218             }
02219             break;
02220         default:
02221         case 0xa7:        /* 33MHz */
02222             switch (mode) {
02223             case ATA_PIO0:        timing = 0x40d0a7aa; break;
02224             case ATA_PIO1:        timing = 0x40d0a7a3; break;
02225             case ATA_PIO2:        timing = 0x40d0a753; break;
02226             case ATA_PIO3:        timing = 0x40c8a742; break;
02227             case ATA_PIO4:        timing = 0x40c8a731; break;
02228             case ATA_WDMA0:       timing = 0x20c8a797; break;
02229             case ATA_WDMA1:       timing = 0x20c8a732; break;
02230             case ATA_WDMA2:       timing = 0x20c8a731; break;
02231             case ATA_UDMA0:       timing = 0x10c8a731; break;
02232             case ATA_UDMA1:       timing = 0x10cba731; break;
02233             case ATA_UDMA2:       timing = 0x10caa731; break;
02234             case ATA_UDMA3:       timing = 0x10cfa731; break;
02235             case ATA_UDMA4:       timing = 0x10c9a731; break;
02236             default:              timing = 0x0120a7a7;
02237             }
02238             break;
02239         case 0xd9:        /* 40Mhz */
02240             switch (mode) {
02241             case ATA_PIO0:        timing = 0x4018d9d9; break;
02242             case ATA_PIO1:        timing = 0x4010d9c7; break;
02243             case ATA_PIO2:        timing = 0x4010d997; break;
02244             case ATA_PIO3:        timing = 0x4010d974; break;
02245             case ATA_PIO4:        timing = 0x4008d963; break;
02246             case ATA_WDMA2:       timing = 0x2008d943; break;
02247             case ATA_UDMA2:       timing = 0x100bd943; break;
02248             case ATA_UDMA4:       timing = 0x100fd943; break;
02249             default:              timing = 0x0120d9d9;
02250             }
02251         }
02252         break; }
02253     }
02254 
02255     SetPciConfig4(0x40 + (dev<<2), timing);
02256 } // end hpt_timing()
02257 
02258 
02259 #define FIT(v,min,max) (((v)>(max)?(max):(v))<(min)?(min):(v))
02260 
02261 VOID
02262 NTAPI
02263 via82c_timing(
02264     IN PHW_DEVICE_EXTENSION deviceExtension,
02265     IN ULONG dev,               // physical device number (0-3)
02266     IN CHAR  mode
02267     )
02268 {
02269     PVOID HwDeviceExtension = (PVOID)deviceExtension;
02270     ULONG slotNumber = deviceExtension->slotNumber;
02271     ULONG SystemIoBusNumber = deviceExtension->SystemIoBusNumber;
02272 
02273     USHORT T = 1000 / /* PciBusClockMHz()*/ 33;
02274 
02275     USHORT setup   = 0;
02276     USHORT active  = 0;
02277     USHORT recover = 0;
02278     USHORT cycle   = 0;
02279 
02280     UCHAR t;
02281 
02282     switch(mode) {
02283     default:
02284     case ATA_PIO0:  setup = 70; active = 165; recover = 150; cycle = 600; break;
02285     case ATA_PIO1:  setup = 50; active = 125; recover = 100; cycle = 383; break;
02286     case ATA_PIO2:  setup = 30; active = 100; recover = 90;  cycle = 240; break;
02287     case ATA_PIO3:  setup = 30; active = 80;  recover = 70;  cycle = 180; break;
02288     case ATA_PIO4:  setup = 25; active = 70;  recover = 25;  cycle = 120; break;
02289     case ATA_PIO5:  setup = 20; active = 50;  recover = 30;  cycle = 100; break;
02290     }
02291 
02292     setup   = (setup  -1)/(T+1);
02293     active  = (active -1)/(T+1);
02294     recover = (recover-1)/(T+1);
02295     cycle   = (cycle  -1)/(T+1);
02296 
02297     if (active + recover < cycle) {
02298         active += (cycle - (active + recover)) / 2;
02299         recover = cycle - active;
02300     }
02301 
02302     // Newer chips dislike this:
02303     if(
02304         deviceExtension->MaxTransferMode < ATA_UDMA6) {
02305         /* PIO address setup */
02306         GetPciConfig1(0x4c, t);
02307         t = (t & ~(3 << ((3 - dev) << 1))) | (FIT(setup - 1, 0, 3) << ((3 - dev) << 1));
02308         SetPciConfig1(0x4c, t);
02309     }
02310 
02311     /* PIO active & recover */
02312     SetPciConfig1(0x4b-dev, (FIT(active - 1, 0, 0xf) << 4) | FIT(recover - 1, 0, 0xf) );
02313 } // end via82c_timing()
02314 

Generated on Sun May 27 2012 04:28:24 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.