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

📄 cdio.cpp

📁 Ep93XX TionProV2 BSP
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        wSectorSize = CDROM_RAW_SECTOR_SIZE;
    } 
    else 
    {
        wSectorSize = CDROM_SECTOR_SIZE;
    }


    // Process the SG buffers in blocks of MAX_CD_SECT_PER_COMMAND.  Each DMA request will have a new SG_BUF array 
    // which will be a subset of the original request, and may start/stop in the middle of the original buffer.
    while (dwNumSectors) 
    {

        dwSectorsToTransfer = (dwNumSectors > MAX_CD_SECT_PER_COMMAND) ? MAX_CD_SECT_PER_COMMAND : dwNumSectors;
    
        DWORD dwBufferLeft = dwSectorsToTransfer * wSectorSize;
        DWORD dwNumSg = 0;

        while (dwBufferLeft) 
        {
            DWORD dwCurBufferLen = pSgBuf[dwEndBufferNum].sb_len - dwEndBufferOffset;

            if (dwBufferLeft < dwCurBufferLen) 
            {
                // The buffer left for this block is less than the current SG buffer length
                CurBuffer[dwEndBufferNum - dwStartBufferNum].sb_buf = pSgBuf[dwEndBufferNum].sb_buf + dwEndBufferOffset;
                CurBuffer[dwEndBufferNum - dwStartBufferNum].sb_len = dwBufferLeft;
                dwEndBufferOffset += dwBufferLeft;
                dwBufferLeft = 0;
            } 
            else 
            {
                // The buffer left for this block is greater than or equal to the current SG buffer length.  Move on to the next SG buffer.
                CurBuffer[dwEndBufferNum - dwStartBufferNum].sb_buf = pSgBuf[dwEndBufferNum].sb_buf + dwEndBufferOffset;
                CurBuffer[dwEndBufferNum - dwStartBufferNum].sb_len = dwCurBufferLen;
                dwEndBufferOffset = 0;
                dwEndBufferNum++;
                dwBufferLeft -= dwCurBufferLen;
            }    
            dwNumSg++;
        }

        //WaitForInterrupt(0);

        ulNumRetries = 0;
        for(;;) 
        {
            if(ulNumRetries >= MAX_DMARETRYS)
            {
                dwError         = ERROR_READ_FAULT;
                bRetryUsingPIO  = TRUE;
                break;
            }


            if (!SetupDMA(CurBuffer, dwNumSg, ATA_CMD_READ_DMA)) 
            {
                dwError = ERROR_READ_FAULT;
                break;
            }    

            SetupCdRomRead( wSectorSize == CDROM_RAW_SECTOR_SIZE ? TRUE : FALSE, dwStartSector, dwSectorsToTransfer, &CmdPkt);

            wCount = (SHORT)((dwSectorsToTransfer * wSectorSize) >> 1);

            if (!AtapiSendCommand(&CmdPkt, wCount, IsReadDMASupported())) 
            {
                dwError     = ERROR_READ_FAULT;
                AbortDMA();
                break;
            }

            //
            // Wait for Busy to be cleared. DRQ and DMARQ are asserted.
            // Wait a maximium of 5 Second to spin up the drive.
            //
            WaitOnDMARQForCD(5000);

            //
            // Begin DMA always returns true 
            //
            BeginDMA(TRUE);
            ulWaitReturn = WaitForDmaInterrupt(DISK_IO_TIME_OUT);

            //
            // Dma Completed Successfully
            //
            if(ulWaitReturn == DMAWAIT_NOERROR )
            {
                EndDMA(); 
                WaitOnBusy(FALSE);

                // Fix for the bug #35612, copy from CDROM to HDD.
				// Change from dwSgCount to dwNumSg.
				CompleteDMA( (PSG_BUF)CurBuffer, dwNumSg, TRUE);

                break;
            }

            //
            // Hit EP931x hardware DMA bug.
            //
            else if(ulWaitReturn == DMAWAIT_ERROR_WRITE_1 )
            {
                DEBUGMSG
                ( 
                    ZONE_ERROR, 
                    (
                        TEXT("ATAPI:ReadCdRomDMA Failed Retrying\r\n")
                    )
                );
                AbortDMA();
                ulNumRetries++;
            }

            else if (ulWaitReturn == DMAWAIT_ERROR_WRITE_2)
            {
                DEBUGMSG
                ( 
                    ZONE_ERROR, 
                    (
                        TEXT("ATAPI:ReadCdRomDMA Failed, Switching to PIO\r\n")
                    )
                );
                AbortDMA();
                m_fWriteBug2Failure = TRUE;
                bRetryUsingPIO      = TRUE;
                dwError             = ERROR_WRITE_FAULT;
                break;
            }

            else if (ulWaitReturn == DMAWAIT_ERROR_READ_1)
            {  
                DEBUGMSG
                ( 
                    ZONE_ERROR, 
                    (
                        TEXT("ATAPI:ReadCdRomDMA Failed, Switching to PIO\r\n")
                    )
                );
                AbortDMA();
                m_fReadBug1Failure  = TRUE;
                bRetryUsingPIO      = TRUE;
                dwError             = ERROR_READ_FAULT ;
                break;
            }

            //
            // Other Error.
            //
            else
            {
                DEBUGMSG
                ( 
                    ZONE_ERROR, 
                    (
                        TEXT("ATAPI:ReadCdRomDMA Failed Not Retrying \r\n")
                    )
                );
                AbortDMA();
                bRetryUsingPIO  = TRUE;
                dwError         = ERROR_READ_FAULT;
                break;
            }
        }

        dwStartSector += dwSectorsToTransfer;
        dwStartBufferNum = dwEndBufferNum;
        dwNumSectors -= dwSectorsToTransfer;        

    }       


//ExitFailure:
    if (dwError != ERROR_SUCCESS) 
    {
        if(bRetryUsingPIO)
        {
            dwError = ReadCdRomPIO
            (
                bRawMode,
                dwLBAAddr, 
                dwTransferLength, 
                dwSgCount, 
                pSgBuf,
                pBytesRead
            );
        }
    }    
    else 
    {
        *pBytesRead = dwTransferLength * wSectorSize;
    }

    DEBUGMSG( ZONE_CDROM, (TEXT("-CDisk::ReadCdRomDMA\r\n")));

    return dwError;
}


//****************************************************************************
// CDisk::ReadCdRomPIO
//****************************************************************************
// Performs a CDROM PIO read.
// 
//
DWORD CDisk::ReadCdRomPIO
(
    BOOL        bRawMode,
    DWORD       dwLBAAddr, 
    DWORD       dwTransferLength, 
    DWORD       dwSgCount, 
    SGX_BUF     *pSgBuf,
    DWORD        *pBytesRead
)
{
    ATAPI_COMMAND_PACKET    CmdPkt; 
    WORD                    wSectorSize;
    DWORD                   dwError = ERROR_SUCCESS;

    if( bRawMode) 
    {
        wSectorSize = CDROM_RAW_SECTOR_SIZE;
    } 
    else 
    {
        wSectorSize = CDROM_SECTOR_SIZE;
    }

    SetupCdRomRead(bRawMode, dwLBAAddr, dwTransferLength, &CmdPkt);
    
    if (AtapiSendCommand(&CmdPkt, wSectorSize, IsReadDMASupported())) 
    {
        if (!AtapiReceiveData(pSgBuf, dwSgCount,pBytesRead)) 
        {
            dwError = ERROR_READ_FAULT;
        }
    }
    else 
    {
         dwError = ERROR_READ_FAULT;
    }
    return dwError;
}    


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
//---------------------------------------------------------------------------
//
//  Send command to ATA Device.
//
//---------------------------------------------------------------------------

BOOL CDisk::AtapiSendCommand(PATAPI_COMMAND_PACKET pCmdPkt, WORD wCount, BOOL fDMA)
{
    // Set the Drive/Head registers 
    SelectDevice();
    GetBaseStatus();

    SelectDevice();


    if (WaitOnBusy(FALSE))
    {  
        if (GetError() & ATA_STATUS_ERROR)
        {      
            return FALSE;
        }
    }

    //
    // Calls Interrupt done for the IDE interrupt.
    //
    if(m_fInterruptSupported && IsDRQTypeIRQ())
    {
        EnableInterrupt();
    }

    WriteSectorCount(0);
    
    WriteSectorNumber(0);


    // Set the byte tranfer count       
    if (wCount) 
    {
        WriteLowCount((BYTE)(0xff & wCount));
        WriteHighCount((BYTE)(0xff & (wCount >> 8)));    
    } 
    else 
    {
        WriteLowCount(0xFE);
        WriteHighCount(0xFF);    
    }

    
    // 
    // Set PIO or DMA Mode as specified in bFlags. 0 = PIO, 1 = DMA
    //
    WriteFeature(fDMA ? 0x1 : 0x0);

    WaitForDisc( WAIT_TYPE_NOT_BUSY, 200);


    //
    // Write ATAPI into  command register.  
    //
    SelectDevice();

    
    //
    // Atapi Packet Command 
    //
    WriteCommand(ATAPI_CMD_COMMAND); 

    WaitForDisc( WAIT_TYPE_NOT_BUSY, 200);


    //
    // Check how device is reporting CPU attention: DRQ or INTRQ?
    // INTRQ within 10 ms!!!
    //  
    if (m_fInterruptSupported && IsDRQTypeIRQ())
    {   
        //  ATA_INTR_CMD is expected
        //
        if (!WaitForInterrupt(DISK_IO_TIME_OUT))
        {
            DEBUGMSG( ZONE_IO | ZONE_CDROM, (TEXT("ATAPI:AtapiSendCommand - Wait for ATA_INTR_CMD Interrupt (DevId %x) \r\n"), m_dwDeviceId));
            return FALSE;  
        }   
    }

    // 
    // Device will assert DRQ  within (50us or 3ms) if no interrupt id used
    // Wait for not BSY and DRQ
    //            
    if (!WaitForDRQ())
    {
        DEBUGMSG( ZONE_IO | ZONE_CDROM, (TEXT("ATAPIPCI:AtapiSendCommand 1 - ATAWaitForDisc failed with: %x (DevId %x)\r\n"), GetError(), m_dwDeviceId));
        return FALSE;
    }

    //
    // This should clear the interrupt.
    //
    if(m_fInterruptSupported)
    {
        EnableInterrupt();
    }

    //        
    // Write the ATAPI Command Packet.
    //
    WriteWordBuffer( (LPWORD)pCmdPkt, GetPacketSize()/sizeof(WORD));



    return TRUE;
}


⌨️ 快捷键说明

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