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

📄 cdio.cpp

📁 这是运行在windows ce 4.2 版本下的关于硬盘加载的驱动程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
 }


//---------------------------------------------------------------------------   
//
//  Function: AtapiLoadMedia
//
//  synopsis: Process a IOCTL_CDROM_LOAD_MEDIA/IOCTL_CDROM_EJECT_MEDIA request
//
//  ENTRY
//      Nothing    
//  EXIT
//      Extended error set on failure
//
//-----------------------------------------------------------------------------


DWORD CDisk::AtapiLoadMedia(BOOL bEject)
{
    ATAPI_COMMAND_PACKET    CmdPkt;
    SGX_BUF SgBuf;
    DWORD dwRet;
    DWORD dwError = ERROR_SUCCESS;

    DEBUGMSG(ZONE_IOCTL, (TEXT("ATAPI:ATAPILoadMedia - Entered. Load=%s\r\n"), bEject ? L"TRUE": L"FALSE"));
    memset((void *)&CmdPkt, 0, sizeof(CmdPkt));
    CmdPkt.Opcode = ATAPI_PACKET_CMD_START_STOP;                     
    CmdPkt.Byte_4 = bEject ? 2 : 3;
    
    SgBuf.sb_len = 0;
    SgBuf.sb_buf = NULL;
 
    if (AtapiSendCommand(&CmdPkt)) {
        if (!AtapiReceiveData(&SgBuf, 0, &dwRet)) {
            DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("ATAPI::LoadMedia failed on receive\r\n")));
            dwError = ERROR_READ_FAULT;
        }
        if (!bEject) {
            Sleep(5000);
            AtapiIsUnitReadyEx();
        }
    } else {
       return ERROR_GEN_FAILURE;
    }    
    return dwError;
}

DWORD CDisk::AtapiStartDisc()
{
    ATAPI_COMMAND_PACKET    CmdPkt;
    SGX_BUF SgBuf;
    DWORD dwRet;
    DWORD dwError = ERROR_SUCCESS;

    DEBUGMSG(ZONE_CDROM, (TEXT("ATAPI:AtapiStartDisc - Entered.\r\n")));
    memset((void *)&CmdPkt, 0, sizeof(CmdPkt));
    CmdPkt.Opcode = ATAPI_PACKET_CMD_START_STOP;                     
    CmdPkt.Byte_4 = 1;
    
    SgBuf.sb_len = 0;
    SgBuf.sb_buf = NULL;
 
    if (AtapiSendCommand(&CmdPkt)) {
        if (!AtapiReceiveData(&SgBuf, 1, &dwRet)) {
            DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("ATAPI::LoadMedia failed on receive\r\n")));
            dwError = ERROR_READ_FAULT;
        }
    } else {
       return ERROR_GEN_FAILURE;
    }    
    return dwError;
}

DWORD CDisk::AtapiReadQChannel(PIOREQ pIOReq)
{
    ATAPI_COMMAND_PACKET    CmdPkt;
    SGX_BUF SgBuf;
    DWORD dwRet;
    DWORD dwError = ERROR_SUCCESS;
    CDROM_SUB_Q_DATA_FORMAT *pcsqdf = (CDROM_SUB_Q_DATA_FORMAT *)pIOReq->pInBuf;
    SUB_Q_CHANNEL_DATA sqcd;
    DWORD dwDataSize = 0;

    if (!pcsqdf || !pIOReq->pOutBuf || (sizeof(CDROM_SUB_Q_DATA_FORMAT) != pIOReq->dwInBufSize)) {
        return ERROR_BAD_ARGUMENTS;
    }
    switch( pcsqdf->Format) {
        case IOCTL_CDROM_CURRENT_POSITION:
            dwDataSize = sizeof(SUB_Q_CURRENT_POSITION);
            break;
        case IOCTL_CDROM_MEDIA_CATALOG:
            dwDataSize = sizeof(SUB_Q_MEDIA_CATALOG_NUMBER);
            break;
        case IOCTL_CDROM_TRACK_ISRC:
            dwDataSize = sizeof(SUB_Q_TRACK_ISRC);
            break;
        default:
            dwError = ERROR_BAD_FORMAT;
    }
    if (pIOReq->dwOutBufSize < dwDataSize) {
        dwError = ERROR_BAD_ARGUMENTS;
    }    

    if (dwError == ERROR_SUCCESS) {
        memset((void *)&CmdPkt, 0, sizeof(CmdPkt));
        CmdPkt.Opcode = ATAPI_PACKET_CMD_READ_SUB_CHAN;
            CmdPkt.Byte_1 = 0x00;
            CmdPkt.Byte_2 = 0x40;               // Header + data required
            CmdPkt.Byte_3 = (BYTE)(pcsqdf->Format);                  
            CmdPkt.Byte_8 = (BYTE)dwDataSize;         
        
        SgBuf.sb_len = dwDataSize;
        SgBuf.sb_buf = (PBYTE) &sqcd;

        if (AtapiSendCommand(&CmdPkt)) {
            if (!AtapiReceiveData(&SgBuf, 1, &dwRet)) {
                DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("ATAPI::ReadQChannel failed on receive\r\n")));
                dwError = ERROR_READ_FAULT;
            } else {
                memcpy( pIOReq->pOutBuf, (LPBYTE)&sqcd, dwDataSize);
            }
        } else {
            DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("ATAPI::ReadQChannel failed on SendCommand\r\n")));
            dwError = ERROR_GEN_FAILURE;
        }    
    }    

    return dwError;
}

//---------------------------------------------------------------------------   
//
//  Function: AtapiGetToc
//
//  synopsis: Gets the table of contents from the media
//
//  ENTRY
//      Nothing    
//  EXIT
//      Extended error set on failure
//
//-----------------------------------------------------------------------------
BOOL CDisk::AtapiGetToc(CDROM_TOC * pTOC)
{
    ATAPI_COMMAND_PACKET    CmdPkt;
    SGX_BUF SgBuf;
    DWORD dwRet;
    BOOL fRet = TRUE;

    memset((void *)&CmdPkt, 0, sizeof(CmdPkt));
    CmdPkt.Opcode = ATAPI_PACKET_CMD_READ_TOC;
    CmdPkt.Byte_1 = 0x02;           // Use MSF Address Format 
    CmdPkt.Byte_7 = (BYTE)((sizeof(CDROM_TOC)>> 8) &0x0FF);    //3
    CmdPkt.Byte_8 = (BYTE)(sizeof(CDROM_TOC) &0x0FF);          // 24
    
    SgBuf.sb_len = sizeof(CDROM_TOC);
    SgBuf.sb_buf = (PBYTE) pTOC;

    if (AtapiSendCommand(&CmdPkt)) {
        if (!AtapiReceiveData(&SgBuf, 1, &dwRet)) {
            DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("ATAPI::GetToc failed on receive\r\n")));
            fRet = FALSE;
        } else {
            WORD wTOCDataLen = (MAKEWORD(pTOC->Length[1], pTOC->Length[0]) - 2);
    
            //
            //      Minus 4 for the the entire header
            //
    
            if (wTOCDataLen != (dwRet - 4))
            {
                DEBUGMSG(ZONE_ERROR, (TEXT("ATAPI:AtapiGetToc - Bad Length in TOC Header = %d, Expecting = %d\r\n"), wTOCDataLen, dwRet - 4));
                fRet = FALSE;
            }
    
            if ((wTOCDataLen % sizeof(TRACK_DATA)) != 0)
            {
                DEBUGMSG( ZONE_ERROR, (TEXT("ATAPI:AtapiGetToc - Data length  = %d which is not a multiple of CDREADTOC_MSFINFO size\r\n"), wTOCDataLen));
                fRet = FALSE;
            }
        }
    } else {
         DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("ATAPI::GetToc failed on SendCommand\r\n")));
        fRet = FALSE;
    }    

    return fRet;
}

//---------------------------------------------------------------------------
//
//      Function: AtapiGetDiscInfo
//
//      Synopsis: implements CDROM_IOCTL_DISC_INFO - Get Disc Information
//
//              This function returns the TOC (table of contents) information
//              from the Q-channel in the lead-in track of the disc, which
//              indicates the starting and ending tracks and the start of
//              the lead-out track.
//
//              The first and last track number are binary values, not BCD.
//
//              It is recommended that the information from the TOC be read
//              in and cached on drive initialization so that when this function
//              is called, there is not need to interrupt drive play to get this
//              information.  Note that the first and last track numbers do not
//              include the lead-in and lead-out tracks of the session.
//
//              The SessionIndex is used to get TOC information from disks
//              with more than one recorded session.  Sessions are the same
//              as OrangeBook Volumes.  The first session has a SessionIndex
//              of zero, and the second session has a SessionIndex of one.
//              A SessionIndex of DISC_INFO_LAST_SESSION (-1) requests the disc
//              info for the last session recorded on the disc.
//
//              The LogicStartAddr is the logical sector address of the first
//              data sector of the first track in this session.
//
//              For standard Redbook and Yellowbook CD-ROMs, zero (0) is the
//              only valid SessionIndex value.  In this case, LogicStartAddr
//              should be returned as zero (0).
//
//              Note: The LogicStartAddr is normally used to locate the first
//              sector of the Volume Recognition Sequence for the indicated
//              session. The Volume Recognition Sequence for the session is
//              expected to start at Sector (LogicStartAddr + 16).
//
//      ENTRY
//              IOCTL Packet format specified by CDROM_DISCINFO structure.
//              Reserved - Reserved Zero
//              SessionIndex - Set to desired session number to query.
//              SessionIndex = 0 indicates a query for the first session
//              SessionIndex = 0xFFFFFFFF indicates a query for the last
//              session on the disc
//
//      EXIT
//              Success
//                      Returns NO_ERROR
//                      CDROM_DISCINFO structure filled in for indicated session
//
//                      If SessionIndex was passed in as 0xFFFFFFFF, it may be
//                      modified to contain the index of the last session on the
//                      disc.  Because not all device drivers must scan through
//                      all the sessions on the disc, this update may or may not
//                      actually take place.
//
//              Failure
//                      Returns an extended error code.
//                      ERROR_UNKNOWN_COMMAND - The command is not supported
//                      ERROR_INVALID_PARAMETER - The session number is invalid
//                      Other Extended Errors may also be returned
//-----------------------------------------------------------------------------

DWORD CDisk::AtapiGetDiscInfo(PIOREQ pIOReq)
{
// TODO: Support multiple sessions
    CDROM_DISCINFO *pDiscInfo = (CDROM_DISCINFO *)pIOReq->pOutBuf;
    CDROM_TOC Toc;
    DWORD dwError = ERROR_SUCCESS;

    return ERROR_SUCCESS; // Bypass for now !!!

    if ((pDiscInfo == NULL) || 
        (pIOReq->dwOutBufSize< sizeof(CDROM_DISCINFO))) {
        return(ERROR_INVALID_PARAMETER);
    }    
    if (AtapiGetToc(&Toc)) {

        TRACK_DATA *pTrack = &(Toc.TrackData[0]);
    
        WORD wStartTrack = 0, wLastTrack = 0;
        // Find the first & last track of the requested session using the LeadOutTrack to detect
        // the session changes
        WORD wTrackIndex;

        //
        //      The size or the array is the indicated size minus two bytes. One byte
        //      for the first track number and one for the last
        //
    
        WORD wTOCDataLen = (MAKEWORD(Toc.Length[1], Toc.Length[0]) - 2);
        
        // If there is already a TOC buffer alloacted then see if it is big enough to hold the
        // newly read TOC, else allocate a buffer to cache the TOC track info here
    
        WORD wTrackCount = wTOCDataLen/sizeof(TRACK_DATA);
    
        for (wTrackIndex = 0; wTrackIndex < wTrackCount; wTrackIndex++) {
            if (pTrack[wTrackIndex].TrackNumber == 0xaa) { // CDATAPI_SESSION_LEADOUT_TRACK = 0xaa
                break;
            } else {
                if( pTrack[wTrackIndex].TrackNumber < wStartTrack)
                {
                    wStartTrack = pTrack[wTrackIndex].TrackNumber;
                    wStartTrack = wTrackIndex;
                }
                if( pTrack[wTrackIndex].TrackNumber > wLastTrack)
                {
                    wLastTrack = pTrack[wTrackIndex].TrackNumber;
                }                        
            }
        }
    
        if (wTrackIndex == wTrackCount)  {
            dwError = ERROR_IO_DEVICE;
            return FALSE;
        }
    
        pDiscInfo->FirstTrack = pTrack[wStartTrack].TrackNumber;
        pDiscInfo->LastTrack =  pTrack[wLastTrack].TrackNumber;
    
        pDiscInfo->LogicStartAddr = CDROM_MSFCOMP_TO_LBA(pTrack[wStartTrack].Address[1], pTrack[wStartTrack].Address[2], pTrack[wStartTrack].Address[3]);
    
        pDiscInfo->LeadOutTrackAddr.msf_Frame = pTrack[wTrackIndex].Address[3];
        pDiscInfo->LeadOutTrackAddr.msf_Second = pTrack[wTrackIndex].Address[2];
        pDiscInfo->LeadOutTrackAddr.msf_Minute = pTrack[wTrackIndex].Address[1];
        pDiscInfo->LeadOutTrackAddr.msf_Filler = 0;
        
        pDiscInfo->FirstSession = 1;
        pDiscInfo->LastSession = 1;
        pDiscInfo->RetSession = 1;
     
    }
    return dwError;
}


BOOL CDisk::AtapiDetectDVD()
{
    CDMODE_SENSE_INFO SenseInfo;
    ATAPI_COMMAND_PACKET    CmdPkt;
    SGX_BUF SgBuf;
    DWORD dwRet;

   
    memset(&CmdPkt, 0, sizeof(ATAPI_COMMAND_PACKET));
    CmdPkt.Opcode = ATAPI_PACKET_CMD_MODE_SENSE;        
    CmdPkt.Byte_2 = 0x2a;                      // Get the mech status page
    CmdPkt.Byte_7 = 2;                      // Say 512 bytes, expect only 18
    
    SgBuf.sb_len = sizeof(CDMODE_SENSE_INFO);
    SgBuf.sb_buf = (PBYTE) &SenseInfo;
    
    if (AtapiSendCommand(&CmdPkt)) {
        if (!AtapiReceiveData(&SgBuf, 1, &dwRet)) {
            DEBUGMSG( ZONE_ERROR|ZONE_CDROM, (TEXT("AtaGetSenseInfo Failed!!!\r\n")));
            return FALSE;
        }
    } else {
         return FALSE;
    }
    return (SenseInfo.cap.cdvdc_readbits & READCAPS_DVD);
}

void CDisk::AtapiDumpSenseData()
{
    CD_SENSE_DATA SenseData;
    if (AtapiGetSenseInfo(&SenseData)) {
        DEBUGMSG( ZONE_CDROM | ZONE_ERROR, (TEXT("Sense Info\r\n")));
        DEBUGMSG( ZONE_CDROM | ZONE_ERROR, (TEXT("   Error Code = 0x%2.2X, Segment Number = %d, Sense Key = 0x%2.2X\r\n"), SenseData.sd_ErrCode, SenseData.sd_SegNum, SenseData.sd_ILI_Key));
        DEBUGMSG( ZONE_CDROM | ZONE_ERROR, (TEXT("   Information = 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X\r\n"), SenseData.sd_Info[0], SenseData.sd_Info[1], SenseData.sd_Info[2], SenseData.sd_Info[3]));
        DEBUGMSG( ZONE_CDROM | ZONE_ERROR, (TEXT("   Additional Sense Length = %d\r\n"), SenseData.sd_Length));
        DEBUGMSG( ZONE_CDROM | ZONE_ERROR, (TEXT("   Command Specific Information = 0x%2.2X 0x%2.2X 0x%2.2X 0x%2.2X\r\n"),SenseData.sd_CmdInfo[0], SenseData.sd_CmdInfo[1], SenseData.sd_CmdInfo[2], SenseData.sd_CmdInfo[3]));
        DEBUGMSG( ZONE_CDROM | ZONE_ERROR, (TEXT("   ASC = 0x%2.2X, ASCQ = 0x%2.2X, FRUC = 0x%2.2X\r\n"), SenseData.sd_SenseCode, SenseData.sd_Qualifier, SenseData.sd_UnitCode));
        DEBUGMSG( ZONE_CDROM | ZONE_ERROR, (TEXT("   Sense Key Specfic = 0x%2.2X 0x%2.2X 0x%2.2X\r\n"), SenseData.sd_Key1, SenseData.sd_Key2, SenseData.sd_Key3));
    } else {
        DEBUGMSG( ZONE_CDROM | ZONE_ERROR, (TEXT(" Unable to get CD Sense info\r\n")));
    }
}

⌨️ 快捷键说明

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