⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 diskmain.cpp

📁 3sc2443的CF卡IDE源代码,肯定好用.
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> ATAPI device\r\n"
                )));
            *pfIsAtapi = TRUE;
        }
        // unknown
        else {
            DEBUGMSG(ZONE_INIT, (_T(
                "Atapi!CDisk::SendExecuteDeviceDiagnostic> Device 0 = Unknown device type (i.e., not ATA, not ATAPI)\r\n"
                )));
        }
    }

    return TRUE;
}

// ----------------------------------------------------------------------------
// Function: SendIdentifyDevice
//     Issue IDENTIFY_DEVICE or IDENTIFY_PACKET_DEVICE depending on whether
//     fIsAtapi is TRUE.  Implement PIO data-in command protocol as per
//     ATA/ATAPI-6 R3B 9.2.
//     Implement ATA/ATAPI-6 R3B 9.10 (Device diagnostic protocol)
//
// Parameters:
//     fIsAtapi - if device is ATAPI, send IDENTIFY PACKET DEVICE
//
// Notes:
//     After issuing a PIO data-in command, if BSY=0 and DRQ=0, then the device
//     failed to process the command.  However, there exist devices that
//     require additional time to return status via the Status register.  As
//     such, a delayed retry has been introduced to faciliate such devices,
//     even though their actions do not comply with the specification.
// ----------------------------------------------------------------------------

#define HPIOI1_CHECK_STATUS_RETRIES 10
BOOL
CDisk::SendIdentifyDevice(
    BOOL fIsAtapi
    )
{
    BOOL fResult = TRUE;
    DWORD dwRetries = 0;
    BYTE bStatus;               // Status register
    DWORD cbIdentifyDeviceData; // IDENTIFY DEVICE data size

    // Host Idle protocol

    // select correct device
    SelectDevice();

    // HI1:Check_Status
    // ----------------
HI1_Check_Status:;
    bStatus = GetAltStatus();
    if ((bStatus & ATA_STATUS_BUSY) || (bStatus & ATA_STATUS_DATA_REQ)) { // BSY=1 or DRQ=1
        Sleep(5);
        goto HI1_Check_Status;
    }

    // HI3:Write_Parameters
    // --------------------
    // no paramters

    // HI4:Write_Command

	*((UINT32 *)(m_pATAReg + ATA_CFG)) |= 0x40;
	
    __try {
        WriteCommand(fIsAtapi ? ATAPI_CMD_IDENTIFY : ATA_CMD_IDENTIFY);
    }
    __except(EXCEPTION_EXECUTE_HANDLER) {
        DEBUGMSG(ZONE_ERROR, (_T(
            "Atapi!CDisk::SendIdentifyDevice> Exception writing to Command register\r\n"
            )));
        fResult = FALSE;
        goto exit;
    }

    // PIO data-in command protocol

    // HPIOI1:Check_Status
    // -------------------
HPIOI1_Check_Status:;
    __try {
        bStatus = GetAltStatus();
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
        DEBUGMSG(ZONE_ERROR, (_T(
            "Atapi!CDisk::SendIdentifyDevice> Exception\r\n"
            )));
        fResult = FALSE;
        goto exit;
    }
    if (!(bStatus & (ATA_STATUS_BUSY|ATA_STATUS_DATA_REQ))) { // BSY=0 and DRQ=0
        // an error occurred
        if (dwRetries < HPIOI1_CHECK_STATUS_RETRIES) {
            dwRetries++;
            Sleep(5);
            goto HPIOI1_Check_Status;
         }
         fResult = FALSE;
         goto exit;
    }
    if (bStatus & ATA_STATUS_BUSY) { // BSY=1
        goto HPIOI1_Check_Status;
    }
    if (!(bStatus & ATA_STATUS_BUSY) && (bStatus & ATA_STATUS_DATA_REQ)) { // BSY=0 and DRQ=1
        goto HPIOI2_Transfer_Data;
    }

    // HPIOI2:Transfer_Data
    // --------------------
    // (IDENTIFY [ATAPI] DEVICE only returns a single DRQ data block)
HPIOI2_Transfer_Data:;
    cbIdentifyDeviceData = sizeof(IDENTIFY_DATA);
    DEBUGCHK(cbIdentifyDeviceData <= BYTES_PER_SECTOR);
    // read result of IDENTIFY DEVICE/IDENTIFY PACKET DEVICE
    if (m_f16Bit) {
    
        USHORT temp[sizeof(IDENTIFY_DATA)/2];    
        USHORT value;
        
        cbIdentifyDeviceData /= 2;
        ReadWordBuffer((PWORD)temp, cbIdentifyDeviceData);

        for (int i=0; i<cbIdentifyDeviceData ; i++)
        {
        	value = ((*(temp + i)& 0xff00) >> 8) & 0xff;
			value |= ((*(temp + i)& 0xff ) << 8) & 0xff00;
			
			*(((USHORT *)(&m_Id)) + i) = value;
		}
        	
    }
    else {
        ReadByteBuffer((PBYTE)&m_Id, cbIdentifyDeviceData);
    }
    // ignore extraneous data
    while (GetAltStatus() & ATA_STATUS_DATA_REQ ) {
        if (m_f16Bit) {
            ReadWord();
        }
        else {
            ReadByte();
        }
    }

	*((UINT32 *)(m_pATAReg + ATA_CFG)) &= ~(0x40);
    // Return to Host Idle protocol

exit:;
    return fResult;
}

// ----------------------------------------------------------------------------
// Function: Identify
//     This function initiates communication with the device.  If the
//     appropriate device is detected on the channel, then instruct the device
//     to execute a diagnostic.  Issue IDENTIFY DEVICE/IDENTIFY PACKET DEVICE.
//     Validate the IDENTIFY data.  Inspect IDENTIFY data (if ATA, determine
//     which read/write commands to use, store disk geometry, etc.)
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

BOOL
CDisk::Identify(
    )
{
    DWORD dwBlockSize = 0; // size of IDENTIFY DEVICE/IDENTIFY PACKET DEVICE information
    WORD wDevType = 0;     // command packet set implemented by device (e.g., direct-access, CD-ROM, etc.)
    DWORD dwCHS = 0;       // whether the registry specifies that the device is to use C/H/S mode
    BYTE bDiagnosticCode;  // SendExecuteDeviceDiagnostic argument
    BOOL fIsAtapi;         // SendExecuteDeviceDiagnostic argument


    TakeCS();

    // test for device present
    if (!IsDevicePresent()) {
        ReleaseCS();
        return FALSE;
    }

    // issue EXECUTE DEVICE DIAGNOSTIC; determine whether device is ATA or ATAPI
    // (ignore the result of this call, as old devices fail to respond correctly)

    SendExecuteDeviceDiagnostic(&bDiagnosticCode, &fIsAtapi);

    // try ATA device
    if (SendIdentifyDevice(FALSE)) { // fIsAtapi=FALSE
        m_fAtapiDevice = FALSE;
        // ALi IDE/ATA controller tweak for supporting a DMA-enabled ATAPI device
        if (2 == m_pPort->m_pDskReg[m_dwDeviceId]->dwDMA) { // 0=PIO, 1=DMA, 2=ATA DMA only
            m_fDMAActive = TRUE;
        }
    }
    else {
        // try ATAPI device
        if (SendIdentifyDevice(TRUE)) { // fIsAtapi=TRUE
            m_fAtapiDevice = TRUE;
        }
        else {
            DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
                "Atapi!CDisk::Identify> Device failed to respond to IDENTIFY DEVICE and IDENTIFY PACKET DEVICE\r\n"
                )));
            ReleaseCS();
            return FALSE;
        }
    }

    ReleaseCS();

    // validate IDENTIFY DEVICE/IDENTIFY PACKET DEVICE signature; any empty
    // channel may return invalid data

	RETAILMSG(1, (_T("### ATA-Disk Total Sector Size 0x%x\r\n"), m_Id.TotalUserAddressableSectors));            
	

    if ((m_Id.GeneralConfiguration == 0) || (m_Id.GeneralConfiguration == 0xffff) ||
        (m_Id.GeneralConfiguration == 0xff7f) ||
        (m_Id.GeneralConfiguration == 0x7fff) ||
       ((m_Id.GeneralConfiguration == m_Id.IntegrityWord) && (m_Id.NumberOfCurrentCylinders == m_Id.IntegrityWord))
    ) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR, (_T(
            "Atapi!CDisk::Identify> General configuration(%04X) not valid; device not present\r\n"
            ), m_Id.GeneralConfiguration));
        RETAILMSG(1, (_T(
            "Atapi!CDisk::Identify> General configuration(%04X) not valid; device not present\r\n"
            ), m_Id.GeneralConfiguration));            
        return FALSE;
    }

    // dump IDENTIFY DEVICE/IDENTIFY PACKET DEVICE data and supported transfer modes
    PIDENTIFY_DATA pId = &m_Id;
    DUMPIDENTIFY(pId);
    DUMPSUPPORTEDTRANSFERMODES(pId);

    // ATA/ATAPI-3 compatible devices store command packet set implemented by
    // device in bits 12-8 of word 0 of IDENTIFY DEVICE/IDENTIFY PACKET DEVICE
    // data (this information is retired in ATA/ATAPI-6)

    wDevType = (m_Id.GeneralConfiguration >> 8) & 0x1F;
    switch (wDevType) {
    case ATA_IDDEVICE_UNKNOWN:
        return FALSE;
    case ATA_IDDEVICE_CDROM:
        m_dwDeviceFlags |= DFLAGS_DEVICE_CDROM;
        break;
    case ATA_IDDEVICE_DISK:
        break;
    case ATA_IDDEVICE_OPTICAL_MEM:
        break;
    default:
        DEBUGMSG(ZONE_INIT, (_T("Atapi!CDisk::Identify> Assuming direct-access device (hard disk drive)\r\n")));
        break;
    }
    // this is redundant; but various routines use this information
    m_dwDeviceFlags |= DFLAGS_DEVICE_PRESENT;
    m_dwDeviceFlags |= (IsAtapiDevice()) ? DFLAGS_ATAPI_DEVICE : 0;
    m_dwDeviceFlags |= (IsRemoveableDevice()) ? DFLAGS_REMOVABLE_DRIVE : 0;

    // ATAPI devices use ATAPI read/write commands; ATA devices support
    // single- and multi-sector transfers; if this is an ATA device, then
    // select multi-sector transfers, if supported

    if (!IsAtapiDevice()) {

        // default to single-sector transfers
        m_bReadCommand = ATA_CMD_READ; m_bWriteCommand = ATA_CMD_WRITE;

        if (m_Id.MaximumBlockTransfer != 0) {

            // device supports multi-sector transfers; enable multi-sector
            // transfers; issue SET MULTIPLE MODE command
            SelectDevice();
            WriteSectorCount((BYTE)m_Id.MaximumBlockTransfer);
            WriteCommand(ATA_CMD_SET_MULTIPLE);

            if (!WaitOnBusy(FALSE) && (GetAltStatus() & ATA_STATUS_READY)) {
                m_bReadCommand = ATA_CMD_MULTIPLE_READ; m_bWriteCommand = ATA_CMD_MULTIPLE_WRITE;
                m_bSectorsPerBlock = m_Id.MaximumBlockTransfer;
            }
            else {
                DEBUGMSG(ZONE_INIT, (_T(
                    "Atapi!CDisk::Identify> (Warning) Failed to enable multi-sector transfers; using single-sector transfers\r\n"
                    )));
            }
        }
    }
    m_bDMAReadCommand = ATA_CMD_READ_DMA;
    m_bDMAWriteCommand = ATA_CMD_WRITE_DMA;

    m_fLBAMode = (m_Id.Capabilities & 0x0200) ? TRUE : FALSE;
    m_DiskInfo.di_flags = DISK_INFO_FLAG_MBR;                 // all ATA storage devices have an MBR
    m_DiskInfo.di_bytes_per_sect = BYTES_PER_SECTOR;          // start with 512, then go with SetInfo changes
    m_DiskInfo.di_cylinders = m_Id.NumberOfCylinders;
    m_DiskInfo.di_heads = m_Id.NumberOfHeads;
    m_DiskInfo.di_sectors = m_Id.SectorsPerTrack;
    if (m_fLBAMode) {
        m_DiskInfo.di_total_sectors = m_Id.TotalUserAddressableSectors;
        ConfigLBA48(); // set m_fUseLBA48 if applicable
    }
    else {
        m_DiskInfo.di_total_sectors= m_DiskInfo.di_cylinders*m_DiskInfo.di_heads*m_DiskInfo.di_sectors;
    }

    return TRUE;
}


// ----------------------------------------------------------------------------
// Function: ConfigLBA48
//     This is a helper function which is called after the IDENTIFY_DEVICE
//     command has been successfully executed.  It parses the results
//     of the IDENTIFY_DEVICE command to determine if 48-bit LBA is supported
//     by the device.
//
// Parameters:
//     None
// ----------------------------------------------------------------------------

void CDisk::ConfigLBA48(void)
{
    PIDENTIFY_DATA pId = (PIDENTIFY_DATA)&m_Id;

    // Word 87 (CommandSetFeatureDefault): 
    //         bit 14 is set and bit 15 is cleared if config data
    //         in word 86 (CommandSetFeatureEnabled2) is valid.
    // Note that this is only valid for non-ATAPI devices
    if ( !IsAtapiDevice() &&
         (pId->CommandSetFeatureDefault & (1 << 14)) &&
         !(pId->CommandSetFeatureDefault & (1 << 15)) &&
         (pId->CommandSetFeatureEnabled2 & (1 << 10)) )
   {
        DEBUGMSG(ZONE_INIT, (TEXT("Atapi!CDisk::Identify::ConfigLBA48> Device supports 48-bit LBA\r\n")));
        DEBUGMSG(ZONE_INIT, (TEXT("Atapi!CDisk::Identify::ConfigLBA48> Max LBA Address = 0x%08x%08x"),
                             pId->Reserved7[102-94] + (pId->Reserved7[103-94] << 16),
                             pId->Reserved7[100-94] + (pId->Reserved7[101-94] << 16)));

        m_fUseLBA48 = TRUE;

        // The CE file system currently supports a maximum of 32-bit sector addresses,
        // so we only use the lower DWORD of lMaxLBAAdress.
        // m_DiskInfo.di_total_sectors = pId->lMaxLBAAddress[0];
        m_DiskInfo.di_total_sectors = pId->Reserved7[100-94] + (pId->Reserved7[101-94] << 16) ;
        // CDisk::Identify has determined whether or not the device supports multi-sector transfers
        // Update read/write command to use [READ|WRITE] [SECTORS|MULTIPLE] EXT
        if (m_bReadCommand == ATA_CMD_READ) 
        {
            m_bReadCommand = ATA_CMD_READ_SECTOR_EXT;
            m_bWriteCommand = ATA_CMD_WRITE_SECTOR_EXT;
        }
        else // CDisk::Identify has determined that the devce supports multi-sector transfers
        {
            m_bReadCommand = ATA_CMD_READ_MULTIPLE_EXT;
            m_bWriteCommand = ATA_CMD_WRITE_MULTIPLE_EXT;
        }
        m_bDMAReadCommand = ATA_CMD_READ_DMA_EXT;
        m_bDMAWriteCommand = ATA_CMD_WRITE_DMA_EXT;
   }
   else  m_fUseLBA48 = FALSE;
}

// ----------------------------------------------------------------------------
// Function: ValidateSg
//     Map embedded pointers
//
// Parameters:
//     pSgReq -
//     InBufLen -
// ----------------------------------------------------------------------------

BOOL
CDisk::ValidateSg(
    PSG_REQ pSgReq,
    DWORD InBufLen
    )
{
    if (PSLGetCallerTrust() != OEM_CERTIFY_TRUST) {
        if (pSgReq && InBufLen >= (sizeof(SG_REQ) + sizeof(SG_BUF) * (pSgReq->sr_num_sg - 1))) {
            DWORD dwIndex;
            for (dwIndex = 0; dwIndex < pSgReq -> sr_num_sg; dwIndex++) {
                pSgReq->sr_sglist[dwIndex].sb_buf = (PUCHAR)MapCallerPtr((LPVOID)pSgReq->sr_sglist[dwIndex].sb_buf,pSgReq->sr_sglist[dwIndex].sb_len);
            }
        }
        else {
            return FALSE;
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -