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

📄 diskmain.cpp

📁 EP9315开发板的Wince6.0的BSP包文件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
DWORD CDisk::ReadWriteDisk(PIOREQ pIOReq, BOOL fRead)
{
    DWORD dwError = ERROR_SUCCESS;
    PBYTE pBuffer;
    PSG_REQ pSgReq = (PSG_REQ)pIOReq->pInBuf;
    DWORD dwStartSector, dwNumSectors, dwSectorsToTransfer, dwSectorsPerBlock, dwSgLeft, dwSgLen;
    DWORD dwMaxPerBlock = m_bSectorsPerBlock;

    PSG_BUF pSgBuf;

 
    BYTE bCmd = fRead ? m_bReadCommand : m_bWriteCommand;

    //* * * CAMSDB040504 - Changed the debug port. (START)
    //DEBUGMSG( ZONE_IOCTL, (TEXT("ATAPI:ReadWriteDisk Entered\r\n")));
    //DEBUGMSG( 1, (TEXT("ATAPI:ReadWriteDisk Entered\r\n")));
    //* * * CAMSDB040504 - Changed the debug port. (START)
    
    //* * * Manual BREAK (START) * * *
    //DebugBreak(); 
    //* * * Manual BREAK (END) * * *

    if ((pSgReq == NULL) ||
       (pIOReq->dwInBufSize < sizeof(SG_REQ))) 
    {
        return ERROR_INVALID_PARAMETER;
    } 
    if ((pSgReq->sr_num_sec == 0) || 
       (pSgReq->sr_num_sg == 0)) 
    {
        return  ERROR_INVALID_PARAMETER;
    }       
    
    //
    // Gets the status and calls Interrupt Done.
    //
    EnableInterrupt();

    
    dwSgLeft = pSgReq->sr_num_sg;           //  The number of SG segments 
    dwNumSectors = pSgReq->sr_num_sec;
    dwStartSector = pSgReq->sr_start;   // Get the Start Sector 
    pSgBuf = &(pSgReq->sr_sglist[0]);

	dwSgLen = pSgBuf->sb_len;

	pBuffer=pSgBuf->sb_buf;// (LPBYTE)MapCallerPtr(pSgBuf->sb_buf,  pSgBuf->sb_len);

//    pBuffer = (PBYTE)MapPtrToProcess((LPVOID)pSgBuf->sb_buf, GetCallerProcess());

/*
	if( fRead )
		RETAILMSG( 1, (TEXT("ATAPI: READ StartSector=%ld NumSectors=%ld NumSg=%ld\r\n"), 
			 dwStartSector, dwNumSectors, dwSgLeft));
	else
		RETAILMSG( 1, (TEXT("ATAPI: WRITE StartSector=%ld NumSectors=%ld NumSg=%ld\r\n"),
			 dwStartSector, dwNumSectors, dwSgLeft));

	RETAILMSG( 1, (TEXT("ATAPI:ReadWriteDisk SG len %d\r\n"), dwSgLen));
*/    

    m_wNextByte = 0xFFFF;

    DEBUGMSG( ZONE_IO, (TEXT("ATAPI:ReadWriteDisk StartSector=%ld NumSectors=%ld NumSg=%ld\r\n"), dwStartSector, dwNumSectors, dwSgLeft));
    
    while(dwNumSectors) 
    {
        if (dwNumSectors > dwMaxPerBlock)    
            dwSectorsToTransfer = dwMaxPerBlock;
        //  The Maximal Number of Sectors per Command is 256.
//      if (dwNumSectors > MAX_SECT_PER_COMMAND)    
//          dwSectorsToTransfer = MAX_SECT_PER_COMMAND;
        else    
            dwSectorsToTransfer = dwNumSectors;

        dwNumSectors -= dwSectorsToTransfer;

        if (!SendIOCommand(dwStartSector,dwSectorsToTransfer, bCmd)) 
        {

            HardResetAndForcePIOMode();

            //
            // Interrupt gets set during atapi reset.
            // Gets the status and calls Interrupt Done.
            //
            EnableInterrupt();
            if (!SendIOCommand(dwStartSector,dwSectorsToTransfer, bCmd)) 
            {
                dwError = fRead ? ERROR_READ_FAULT : ERROR_WRITE_FAULT;

				//RETAILMSG( 1, (TEXT("ATAPI:ReadWriteDisk SendCommand Failed\r\n")));
                break;
            }
        }

        dwStartSector += dwSectorsToTransfer;

        //  The read command expects an interrupt before data transfer.
        //  The write command, on the other side, expects an interrupt after

//        dwSectorsPerBlock = dwMaxPerBlock;

        while(dwSectorsToTransfer && (dwSgLeft > 0)) 
        {
	        dwSectorsPerBlock = MIN( dwMaxPerBlock, dwSectorsToTransfer );
/*            
            if (dwSectorsPerBlock > dwSectorsToTransfer)
            {
                dwSectorsPerBlock = dwSectorsToTransfer;
            }
*/
            dwSectorsToTransfer -= dwSectorsPerBlock;
            
            if (fRead && m_fInterruptSupported) 
            {       
                if (!WaitForInterrupt(DISK_IO_TIME_OUT) || (CheckIntrState() == ATA_INTR_ERROR)) 
                {  
                    DEBUGMSG( ZONE_IO, (TEXT("ATAPI:ReadWrite- WaitforInterrupt failed (DevId %x) \r\n"),m_dwDeviceId));

					RETAILMSG( 1, (TEXT("ATAPI:ReadWriteDisk SendCommand Failed 22222\r\n")));
                    dwError = ERROR_READ_FAULT;
                    break;
                } 
            }   
            if (!WaitForDRQ()) 
            {
                DEBUGMSG( ZONE_IO, (TEXT("ATAPI:ReadWrite- WaitforDRQ failed (DevId %x) \r\n"),m_dwDeviceId));
                dwError = ERROR_READ_FAULT;

				//RETAILMSG( 1, (TEXT("ATAPI:ReadWriteDisk SendCommand Failed 333333\r\n")));
                break;
            }

            DWORD dwBytesPerBlock = dwSectorsPerBlock * m_DiskInfo.di_bytes_per_sect;

            while ((dwBytesPerBlock>0) && (dwSgLeft >0))
            {
                DWORD dwReadThisTime = MIN(dwSgLen, dwBytesPerBlock); //(dwSgLen < dwBytesPerBlock) ? dwSgLen : dwBytesPerBlock;

				//RETAILMSG( 1, (TEXT("ATAPI:get %d (len %d--%d)\r\n"), dwReadThisTime,dwSgLen,dwBytesPerBlock));

                dwSgLen -= dwReadThisTime;
                dwBytesPerBlock -= dwReadThisTime;

                fRead ?   ReadBuffer(pBuffer,dwReadThisTime) 
						: WriteBuffer(pBuffer,dwReadThisTime);
                    
                pBuffer += dwReadThisTime; //


                // Go to the next scatter/gather if no more space left

                if ((dwSgLen == 0) && ( --dwSgLeft > 0)) {

                    pSgBuf++;

				     pBuffer=pSgBuf->sb_buf;// (LPBYTE)MapCallerPtr(pSgBuf->sb_buf,  pSgBuf->sb_len);
//                    pBuffer = (PBYTE)MapPtrToProcess((LPVOID)pSgBuf->sb_buf, GetCallerProcess());
                    dwSgLen = pSgBuf->sb_len;

					//RETAILMSG( 1, (TEXT("ATAPI:ReadWriteDisk SG len %d\r\n"), dwSgLen));
                }
            }   

            if (fRead) {

                while (dwBytesPerBlock > 0)  {

                    (void) ReadWord();
                    dwBytesPerBlock-=2 ;            
                }
            }
                
        }

        if (ERROR_SUCCESS != dwError)
            break;

        //  In case of write command an interrupt is generated upon each block.
        //  We can either wait for the interrupt or simply ignore it.
        //  However this is danger because an interrupt is pending and blocks all
        //  other interrupts on the same or lower level.

        if ( !fRead && m_fInterruptSupported) {     
            if (!WaitForInterrupt(DISK_IO_TIME_OUT) || (CheckIntrState() == ATA_INTR_ERROR)) {  
                DEBUGMSG( ZONE_IO, (TEXT("ATAPI:ReadWrite- WaitforInterrupt failed (DevId %x) \r\n"),m_dwDeviceId));

				//RETAILMSG( 1, (TEXT("ATAPI:ReadWriteDisk SendCommand Failed 44444\r\n")));
                dwError = ERROR_WRITE_FAULT;
                break;
            } 
        }            
    }
    
    // if (ERROR_SUCCESS != dwError) 
    // {
        //
        // TODO TODO TODO - Reset Device and setup the dma again.
        //
        // ResetController();
        


        //if (!(m_Id.Capabilities & 0x0200) && m_fLBAMode) 
        //{
        //    m_fLBAMode = FALSE;
        //    dwError = ReadWriteDisk(pIOReq, fRead);
        //} 
        //else 
        //{
        //}   
    // }    

    pSgReq->sr_status = dwError;
    return dwError;

}

/*------------------------------------------------------------------------------------------*/

DWORD CDisk::ReadWriteDiskDMA(PIOREQ pIOReq, BOOL fRead)
{
    DWORD   dwError = ERROR_SUCCESS;
    PSG_REQ pSgReq = (PSG_REQ)pIOReq->pInBuf;
    DWORD   dwSectorsToTransfer;
    SG_BUF  CurBuffer[MAX_SG_BUF];
    BYTE    bCmd;
    BOOL    bRetryUsingPIO = FALSE;
    ULONG   ulWaitReturn;
    BOOL    bRet;
    

    DEBUGMSG( ZONE_DMA, (TEXT("+CDisk::ReadWriteDiskDMA\r\n")));

    if ((pSgReq == NULL) || (pIOReq->dwInBufSize < sizeof(SG_REQ))) 
    {
        return ERROR_INVALID_PARAMETER;
    }   
    if ((pSgReq->sr_num_sec == 0) || 
       (pSgReq->sr_num_sg == 0)) 
    {
        return ERROR_INVALID_PARAMETER;
    }       

    DEBUGMSG
    ( 
        ZONE_DMA, 
        (
            TEXT("ATAPI:ReadWriteDiskDMA StartSector=%ld NumSectors=%ld NumSg=%ld\r\n"), 
            pSgReq->sr_start, 
            pSgReq->sr_num_sec, 
            pSgReq->sr_num_sg
        )
    );    

    GetBaseStatus(); // Clear Interrupt if it is already set 

    DWORD dwStartBufferNum = 0, dwEndBufferNum = 0, dwEndBufferOffset = 0;
    DWORD dwNumSectors = pSgReq->sr_num_sec;
    DWORD dwStartSector = pSgReq->sr_start;

    // Process the SG buffers in blocks of MAX_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_SECT_PER_COMMAND) ? MAX_SECT_PER_COMMAND : dwNumSectors;
        
        dwSectorsToTransfer = (dwNumSectors > MAX_DMA_SECT_PER_COMMAND) ? 
                                MAX_DMA_SECT_PER_COMMAND : dwNumSectors; 

        DWORD dwBufferLeft = dwSectorsToTransfer * BYTES_PER_SECTOR;
        DWORD dwNumSg = 0;

        while (dwBufferLeft) 
        {
            DWORD dwCurBufferLen = pSgReq->sr_sglist[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 = pSgReq->sr_sglist[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 = pSgReq->sr_sglist[dwEndBufferNum].sb_buf + dwEndBufferOffset;
                CurBuffer[dwEndBufferNum - dwStartBufferNum].sb_len = dwCurBufferLen;
                dwEndBufferOffset = 0;
                dwEndBufferNum++;
                dwBufferLeft -= dwCurBufferLen;
            }    
            dwNumSg++;
        }
      
        bCmd = fRead ? ATA_CMD_READ_DMA : ATA_CMD_WRITE_DMA;

        for(;;) 
        {

            if( !SetupDMA(CurBuffer, dwNumSg, fRead)) 
            {
                dwError     = fRead ? ERROR_READ_FAULT : ERROR_WRITE_FAULT;
                break;
            }    

            if( !SendIOCommand(dwStartSector, dwSectorsToTransfer, bCmd)) 
            {
                dwError     = fRead ? ERROR_READ_FAULT : ERROR_WRITE_FAULT;
                AbortDMA();

                //
                // Segate drives get stuck in the busy after a incomplete
                // transfer.  Reset the drive and try in PIO mode.
                //
                // Seagate drives also do not respond to the device reset
                // command when busy.  Need to reset both devices.
                //
                HardResetAndForcePIOMode();

                
                bRetryUsingPIO      = TRUE;
                break;
            }

            bRet = WaitOnDMARQ(DISK_IO_TIME_OUT * 1000);
            if(!bRet)
            {
                DEBUGMSG
                ( 
                   ZONE_ERROR, 
                   (
                       L"WaitOnDMARQ Failed\r\n"
                   )
                );
                dwError = fRead ? ERROR_READ_FAULT : ERROR_WRITE_FAULT;
                AbortDMA();
                break;
            }

            //
            // Begin DMA always returns true 
            //
            BeginDMA(fRead);

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

                //Fix for CETK Storage_API #4010 failed in UDMA mode.
				CompleteDMA( CurBuffer, dwNumSg, fRead);

                break;
            }
            //
            // Hit EP931x hardware DMA bug.
            //
            else if(ulWaitReturn == DMAWAIT_ERROR_WRITE_1 )
            {
                DEBUGMSG
                ( 
                    ZONE_ERROR, 
             

⌨️ 快捷键说明

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