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

📄 diskmain.cpp

📁 Ep93XX TionProV2 BSP
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        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, 
                    (
                        TEXT("ATAPI:ReadWriteDMA Failed Retrying\r\n")
                    )
                );
                AbortDMA();
                m_fWriteBug1Failure = TRUE;
                bRetryUsingPIO      = TRUE;
                dwError             = ERROR_WRITE_FAULT;
                break;
            }
            else if (ulWaitReturn == DMAWAIT_ERROR_WRITE_2)
            {
                DEBUGMSG
                ( 
                    ZONE_ERROR, 
                    (
                        TEXT("ATAPI:ReadWriteDMA 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:ReadWriteDMA 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:ReadWriteDma Failed Not Retrying \r\n")
                    )
                );
                bRetryUsingPIO      = TRUE;
                AbortDMA();
                dwError     = fRead ? ERROR_READ_FAULT : ERROR_WRITE_FAULT;
                break;
            }
        } //end for

        if(dwError != ERROR_SUCCESS)
        {
            break;
        }

        
        dwStartSector       += dwSectorsToTransfer;
        dwStartBufferNum    = dwEndBufferNum;
        dwNumSectors        -= dwSectorsToTransfer;        
    }  //end while  

    if (ERROR_SUCCESS != dwError) 
    {
        //
        // Reset the controller and try in PIO mode.
        //


        //
        // Reset the device and issue commands to set up the dma mode
        // again.
        //
        // AtapiSoftReset();
        // WaitForInterrupt(50);
        // SetBestTransferMode();

        if(bRetryUsingPIO)
        {
            dwError = ReadWriteDisk(pIOReq, fRead);
            DEBUGMSG( ZONE_WARNING, (TEXT("CDisk::ReadWriteDiskDMA using PIO for the transfer.\r\n")));
        }
    }

    pSgReq->sr_status = dwError;
    
    DEBUGMSG( ZONE_DMA, (TEXT("-CDisk::ReadWriteDiskDMA\r\n")));
    
    return dwError;
}

/*------------------------------------------------------------------------------------------*/
DWORD CDisk::GetStorageId(PIOREQ pIOReq)
{
    DWORD dwError = ERROR_SUCCESS;
    DWORD dwBytesLeft;
    PBYTE pDstOffset;
    PSTORAGE_IDENTIFICATION pStorageId = (PSTORAGE_IDENTIFICATION)pIOReq->pOutBuf;
    if (!pStorageId || (pIOReq->dwOutBufSize < sizeof(STORAGE_IDENTIFICATION)) || !pIOReq->pBytesReturned) 
        return ERROR_INVALID_PARAMETER;
    pStorageId->dwSize = sizeof(STORAGE_IDENTIFICATION);
    pStorageId->dwFlags = 0;  // can be or of {MANUFACTUREID,SERIALNUM}_INVALID

    dwBytesLeft = pIOReq->dwOutBufSize - sizeof(STORAGE_IDENTIFICATION);
    pDstOffset = (PBYTE)(pStorageId + 1);
    
    pStorageId->dwManufactureIDOffset = pDstOffset - (PBYTE)pStorageId;

    SetLastError(ERROR_SUCCESS);    // TODO: Once ATAParseIdString is changed we can modify this
    if (!ATAParseIdString((PBYTE)m_Id.ModelNumber, sizeof(m_Id.ModelNumber), &(pStorageId->dwManufactureIDOffset), &pDstOffset, &dwBytesLeft))
        pStorageId->dwFlags |= MANUFACTUREID_INVALID;
        
    pStorageId->dwSerialNumOffset = pDstOffset - (PBYTE)pStorageId;
    
    if (!ATAParseIdString((PBYTE)m_Id.SerialNumber, sizeof(m_Id.SerialNumber), &(pStorageId->dwSerialNumOffset), &pDstOffset, &dwBytesLeft))
        pStorageId->dwFlags |= SERIALNUM_INVALID;
    
    pStorageId->dwSize = pDstOffset - (PBYTE)pStorageId;    // required size

    *(pIOReq->pBytesReturned)= min(pStorageId->dwSize, pIOReq->dwOutBufSize);       // bytes written
    
    // ATAParseIdString sets the error value
    dwError = GetLastError(); 
        
    return dwError;
}

//****************************************************************************
// GetDriveIdentifyData
//****************************************************************************
// Allows test programs to get the drive information data.
// 
//
DWORD CDisk::GetDriveIdentifyData(IDENTIFY_DATA *pId)
{
    memcpy((void *)pId, (void *) &m_Id, sizeof(IDENTIFY_DATA));
    return ERROR_SUCCESS; 
}


#define NUM_SECTORS         1
unsigned short usReadBuffer[NUM_SECTORS*(BYTES_PER_SECTOR>>1)]; 
unsigned short usWriteBuffer[NUM_SECTORS*(BYTES_PER_SECTOR>>1)]; 

//****************************************************************************
// TestDisk
//****************************************************************************
// Routine to test the disk read and write routines.
// 
//
DWORD CDisk::TestDisk(void)
{
    IOREQ sIOReqWrite,sIOReqRead;
    SG_REQ sSgReqWrite,sSgReqRead;
    int i;
    DWORD dwError;

    sIOReqWrite.pInBuf = (PUCHAR)&sSgReqWrite;
    sIOReqRead.pInBuf  = (PUCHAR)&sSgReqRead;

    //
    // Required to make the ReadWriteDiskDma Call.
    //
    sIOReqWrite.dwInBufSize = sizeof(SG_REQ);
    sIOReqRead.dwInBufSize  = sizeof(SG_REQ);


    for(i = 0; i<(NUM_SECTORS * (BYTES_PER_SECTOR>>1)) ; i++)
    {
        usWriteBuffer[i] = (i<<16) | i ;
    }

    //
    // Write the boot sector with a pattern.
    //
    sSgReqWrite.sr_start    = 1;
    sSgReqWrite.sr_num_sec  = NUM_SECTORS;
    sSgReqWrite.sr_num_sg   = 1;
    
    sSgReqWrite.sr_sglist[0].sb_len = BYTES_PER_SECTOR * NUM_SECTORS;
    sSgReqWrite.sr_sglist[0].sb_buf = (PUCHAR)&usWriteBuffer;

    dwError = ReadWriteDiskDMA(&sIOReqWrite, FALSE);

    if(dwError != ERROR_SUCCESS)
    {
        DEBUGMSG
        ( 
            ZONE_DMA, 
            (
                TEXT("ATAPI:TestDisk Write Failed.\r\n")
            )
        );

        return dwError;
    }

    //
    // Read back the pattern.
    //
    sSgReqRead.sr_start    = 1;
    sSgReqRead.sr_num_sec  = NUM_SECTORS;
    sSgReqRead.sr_num_sg   = 1;
    
    sSgReqRead.sr_sglist[0].sb_len = BYTES_PER_SECTOR * NUM_SECTORS;
    sSgReqRead.sr_sglist[0].sb_buf = (PUCHAR)&usReadBuffer;
    dwError = ReadWriteDiskDMA(&sIOReqRead, TRUE);

    if(dwError != ERROR_SUCCESS)
    {
        DEBUGMSG
        ( 
            ZONE_DMA, 
            (
                TEXT("ATAPI:TestDisk Read Failed.\r\n")
            )
        );

        return dwError;
    }

    //
    // Print out the debug information.
    //
    for(i = 0 ; i < (NUM_SECTORS * (BYTES_PER_SECTOR>>1)); i+=8)
    {
        NKDbgPrintfW
        (
            L"0x%04x 0x%04x 0x%04x 0x%04x "
            L"0x%04x 0x%04x 0x%04x 0x%04x\r\n"
            ,
            usReadBuffer[i + 0], usReadBuffer[i + 1], 
            usReadBuffer[i + 2], usReadBuffer[i + 3],
            usReadBuffer[i + 4], usReadBuffer[i + 5], 
            usReadBuffer[i + 6], usReadBuffer[i + 7]
        );
    }

    return dwError;
}


⌨️ 快捷键说明

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