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

📄 diskmain.cpp

📁 Microsoft WinCE 6.0 BSP FINAL release source code for use with the i.MX27ADS TO2 WCE600_FINAL_MX27_S
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    }

    DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: SetDiskInfo-\r\n")));
    return dwError;
}

// ----------------------------------------------------------------------------
// Function: GetDeviceInfo
//     IOCTL_DISK_DEVICE_INFO
//
// Parameters:
//     pIOReq -
// ----------------------------------------------------------------------------

DWORD
CDisk::GetDeviceInfo(
    PIOREQ pIOReq
    )
{
    PSTORAGEDEVICEINFO psdi = (PSTORAGEDEVICEINFO)pIOReq->pInBuf;
    HKEY hKey;

    DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: GetDeviceInfo+\r\n")));
    if ((pIOReq->dwInBufSize == 0) || (pIOReq->pInBuf == NULL)) {
        return ERROR_INVALID_PARAMETER;
    }

	if (pIOReq->dwInBufSize < sizeof(STORAGEDEVICEINFO)) {
        return ERROR_INSUFFICIENT_BUFFER;
    }

    if (pIOReq->pBytesReturned) {
        *(pIOReq->pBytesReturned) = sizeof(STORAGEDEVICEINFO);
    }

    psdi->dwDeviceClass = 0;
    psdi->dwDeviceType = 0;
    psdi->dwDeviceFlags = 0;

    PTSTR szProfile = psdi->szProfile;

    wcscpy(szProfile, L"Default");

    if (ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, m_szDeviceKey, 0, 0, &hKey)) {
        hKey = NULL;
    }

    if (IsAtapiDevice() && IsCDRomDevice()) {

        psdi->dwDeviceClass = STORAGE_DEVICE_CLASS_MULTIMEDIA;
        psdi->dwDeviceType |= STORAGE_DEVICE_TYPE_REMOVABLE_MEDIA;
        psdi->dwDeviceType |= STORAGE_DEVICE_TYPE_ATAPI;
        psdi->dwDeviceType |= STORAGE_DEVICE_TYPE_PCIIDE;
        psdi->dwDeviceFlags |= STORAGE_DEVICE_FLAG_MEDIASENSE;
        psdi->dwDeviceFlags |= STORAGE_DEVICE_FLAG_READONLY;

        if (!hKey || !AtaGetRegistryString(hKey, REG_VALUE_CDPROFILE, &szProfile, sizeof(psdi->szProfile))) {
            wcscpy(psdi->szProfile, REG_VALUE_CDPROFILE);
        }

    }
    else {

        psdi->dwDeviceClass = STORAGE_DEVICE_CLASS_BLOCK;
        psdi->dwDeviceType |= STORAGE_DEVICE_TYPE_PCIIDE;
        psdi->dwDeviceType |= STORAGE_DEVICE_TYPE_ATA;
        psdi->dwDeviceFlags |= STORAGE_DEVICE_FLAG_READWRITE;

        if (!hKey || !AtaGetRegistryString(hKey, REG_VALUE_HDPROFILE, &szProfile, sizeof(psdi->szProfile))) {
            wcscpy(psdi->szProfile, REG_VALUE_HDPROFILE);
        }

    }

    DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: GetDeviceInfo-\r\n")));
    return ERROR_SUCCESS;
}

// ----------------------------------------------------------------------------
// Function: GetDiskName
//     Implement IOCTL_DISK_GETNAME
//
// Parameters:
//     pIOReq -
// ----------------------------------------------------------------------------

DWORD
CDisk::GetDiskName(
    PIOREQ pIOReq
    )
{
    static PTCHAR szDefaultDiscDrive = (_T("External Volume"));
    PTCHAR szDiskName = NULL;
    DWORD dwSize;

    DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: GetDiskName+\r\n")));
//    DEBUGMSG(ZONE_IOCTL, (_T("Ata!GeDisktName\r\n")));

    if ((pIOReq->pBytesReturned == NULL) || (pIOReq->dwOutBufSize == 0) || (pIOReq->pOutBuf == NULL)) {
        return ERROR_INVALID_PARAMETER;
    }

    *(pIOReq->pBytesReturned) = 0;

    if (m_szDiskName) {
        if (wcslen(m_szDiskName)) {
            szDiskName = m_szDiskName;
        }
        else {
            return ERROR_NOT_SUPPORTED;
        }
    }
    else {
        szDiskName = szDefaultDiscDrive;
    }

    dwSize = (wcslen(szDiskName) + 1) * sizeof(TCHAR);

    if (pIOReq->dwOutBufSize < dwSize) {
        return ERROR_INSUFFICIENT_BUFFER;
    }

    wcscpy((PTCHAR) pIOReq->pOutBuf, szDiskName);

    *(pIOReq->pBytesReturned) = dwSize;

    DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: GetDiskName-\r\n")));
    return ERROR_SUCCESS;
}

// ----------------------------------------------------------------------------
// Function: ReadWriteDisk
//     Implement ATA/ATAPI-6 R3B 8.34 (READ SECTOR(S)) and 8.62 (WRITE SECTOR(S)).
//     Implement ATA/ATAPI-6 R3B 9.5 (PIO data-in command protocol) and 9.6
//     (PIO data-out command protocol).
//     This function reads from/writes to an ATA device.
//
// Parameters:
//     pIOReq -
//     fRead -
//
// Notes:
//     READ SECTOR(S) and WRITE SECTOR(S) can transfer up to 256 sectors; however,
//     every transfer is segmented, as per the PIO data-in/out protocol.  A segment
//     of a multiple-block transfer is called a "DRQ data block" and is the length
//     of a sector; see ATA/ATAPI-6 R3B 9.5 and 9.6 for more information.
// ----------------------------------------------------------------------------

DWORD
CDisk::ReadWriteDisk(
    PIOREQ pIOReq,
    BOOL fRead
    )
{
	SG_BUF SafeBufferList[MAX_SG_BUF] = {0};
	PUCHAR saveoldptrs[MAX_SG_BUF];
    PVOID  ptemp = 0;
	unsigned int i, mappedptrs = 0;

    DWORD dwError = ERROR_SUCCESS; // result

    PSG_REQ pSgReq = (PSG_REQ) pIOReq->pInBuf; // scatter/gather request
    PSG_BUF pSgBuf;                            // scatter/gather buffer

    BYTE bStatus; // device Status register

	DWORD dwIntrCount, dwBufferCount;

    BYTE bCmd = fRead ? m_bReadCommand : m_bWriteCommand; // command

    DWORD dwCurBufNum;           // current scatter/gather buffer
    DWORD dwCurBufPos;           // current position in current scatter/gather buffer
    PBYTE pBuffer;               // pointer to current address of current scatter/gather buffer
    DWORD dwCurDoubleBufPos;     // current position in current double buffer
    DWORD dwCurDoubleBufLen;     // length of current double buffer (for reads)
    PBYTE pDoubleBuffer;         // pointer to current address of double buffer
    DWORD dwCurByte;             // current byte (to increment current sector of transfer) of "global" transfer
    DWORD dwCurSec;              // current sector of "global" transfer
    DWORD dwCurDRQDataBlockByte; // current byte of current DRQ data block transfer
    BOOL fWriteComplete;         // to facilitate PIO data-out protocol, flag transfer complete


    DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: ReadWriteDisk+(sr_start:%d, sr_num_sec:%d, start: %d)\r\n"), pSgReq->sr_start, pSgReq->sr_num_sec, GetTickCount()));
    
    // validate arguments
    if ((pSgReq == NULL) || (pIOReq->dwInBufSize < sizeof(SG_REQ))) {
        return ERROR_INVALID_PARAMETER;
    }
    if ((pSgReq->sr_num_sec == 0) || (pSgReq->sr_num_sg == 0) || (pSgReq->sr_num_sg > MAX_SG_BUF)) {
        return  ERROR_INVALID_PARAMETER;
    }
    if ((pSgReq->sr_start + pSgReq->sr_num_sec) > m_DiskInfo.di_total_sectors) {
        return ERROR_SECTOR_NOT_FOUND;
    }

    // Make a safe copy of the caller's SG_BUF array
    if (0 == CeSafeCopyMemory((LPVOID)SafeBufferList, (LPVOID)(pSgReq->sr_sglist), (sizeof(SG_BUF) * pSgReq->sr_num_sg))) {
        return ERROR_INVALID_PARAMETER;
    }

    // Validate and map embedded sb_bufs
    for (i = 0; i < pSgReq->sr_num_sg; i++) {
        if (
            (SafeBufferList[i].sb_len == 0) ||
            (SafeBufferList[i].sb_buf == NULL)
        ) {
            dwError = ERROR_INVALID_PARAMETER;
            goto exit;
        }

        if (FAILED(CeOpenCallerBuffer(
                    &ptemp,
                    SafeBufferList[i].sb_buf,
                    SafeBufferList[i].sb_len,
                    fRead ? ARG_O_PTR : ARG_I_PTR,
                    FALSE)))
        {
            dwError = ERROR_INVALID_PARAMETER;
			DEBUGMSG(ZONE_ERROR, (TEXT("Ata!CDisk::ReadWriteDisk> CeOpenCallerBuffer(pDestMarshalled=0x%08x,pSrcUnmarshalled=0x%08x) failed!\r\n"),ptemp,SafeBufferList[i].sb_buf));
            goto exit;
        }
        saveoldptrs[i] = SafeBufferList[i].sb_buf;
        SafeBufferList[i].sb_buf = (PUCHAR)ptemp;			
        mappedptrs = i + 1 ;
    }

    // do we have to allocate the double buffer?
    if (NULL == m_rgbDoubleBuffer) {
        DEBUGMSG(ZONE_INIT, (TEXT(
            "Ata!CDisk::ReadWriteDisk> Allocating double buffer [first use]: %d\r\n"
            ), m_pPort->m_pDskReg[m_dwDeviceId]->dwDoubleBufferSize));
        m_rgbDoubleBuffer = (PBYTE)LocalAlloc(LPTR, m_pPort->m_pDskReg[m_dwDeviceId]->dwDoubleBufferSize);
        if (NULL == m_rgbDoubleBuffer) {
            DEBUGMSG(ZONE_ERROR, (TEXT(
                "Ata!CDisk::ReadWriteDisk> Failed to allocate double buffer\r\n"
                )));
            dwError = ERROR_OUTOFMEMORY;
            goto exit;
        }
    }

    // clear interrupt, if set
    // TODO: Is this necessary?
    // GetBaseStatus();
    GetBaseStatus();

    // initialize "global" transfer state
    dwCurSec = pSgReq->sr_start;
    dwCurByte = 0;

    // fetch first scatter/gather buffer
    dwCurBufNum = 0;
    dwCurBufPos = 0;
	pSgBuf = &(SafeBufferList[dwCurBufNum]);
    //pSgBuf = &(pSgReq->sr_sglist[0]);
    // map nested pointer and test for security violation
    pBuffer = (PBYTE)pSgBuf->sb_buf;
    if (pSgBuf->sb_buf != NULL && pBuffer == NULL) {
        // security violation
        DEBUGMSG(ZONE_ERROR, (TEXT(
            "Ata!CDisk::ReadWriteDisk> Failed to map pointer to caller\r\n"
            )));
        dwError = ERROR_INVALID_PARAMETER;
        goto exit;
    }

    // is this a read or a write?
    if (fRead) {

        if (pIOReq->pBytesReturned){
		  *(pIOReq->pBytesReturned) = 0;
		}
        // --------------------------------------------------------------------
        // ATA/ATAPI-6 R3B 9.5 (PIO data-in protocol)
        // --------------------------------------------------------------------

        // Host_Idle
        // ---------
        // issue command
PIO_Data_In_Read_Command:;
		//DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: ReadWriteDisk+(PIO_Data_In_Read_Command)\r\n")));
        // determine size of transfer
        if ((((pSgReq->sr_start + pSgReq->sr_num_sec) - dwCurSec) * m_DiskInfo.di_bytes_per_sect) > m_pPort->m_pDskReg[m_dwDeviceId]->dwDoubleBufferSize) {
            dwCurDoubleBufLen = m_pPort->m_pDskReg[m_dwDeviceId]->dwDoubleBufferSize;
        }
        else {
            dwCurDoubleBufLen = ((pSgReq->sr_start + pSgReq->sr_num_sec) - dwCurSec) * m_DiskInfo.di_bytes_per_sect;
        }
		dwIntrCount = 0;
		dwBufferCount = 0;
        // issue command
        if (!SendIOCommand(dwCurSec, dwCurDoubleBufLen / m_DiskInfo.di_bytes_per_sect, bCmd)) {
            DEBUGMSG(ZONE_ERROR, (_T(
                "Ata!CDisk::ReadWriteDisk> Failed to issue read/write command\r\n"
                )));
            dwError = fRead ? ERROR_READ_FAULT : ERROR_WRITE_FAULT;
            goto exit;
        }

        // initialize double buffer for read
        pDoubleBuffer = m_rgbDoubleBuffer;
        dwCurDoubleBufPos = 0;

        // INTRQ_Wait
        // ----------
        // wait for interrupt if nIEN=0 (i.e., if interrupt enabled)
HPIOI_INTRQ_Wait:;
        // if nIEN=1 (interrupt enabled), wait for interrupt
        if (m_fInterruptSupported) {
			DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: ReadWriteDisk+(INTRQ: %d, %d)\r\n"), dwIntrCount,dwCurDoubleBufLen));
			if((dwIntrCount < dwCurDoubleBufLen) && (dwIntrCount < m_DiskInfo.di_bytes_per_sect * m_Id.MaximumBlockTransfer)) 
			{
				if(dwBufferCount >= m_DiskInfo.di_bytes_per_sect && dwBufferCount < dwCurDoubleBufLen)
				{
				  goto HPIOI_Transfer_Data_Setup;                             // DRQ data block transfer not complete
				}
				goto HPIOI_Check_Status;                          // DRQ data block transferred, nIEN=1
			}
			dwIntrCount = 0;
            if (!WaitForInterrupt(m_dwDiskIoTimeOut) || (CheckIntrState() == ATA_INTR_ERROR)) {
                DEBUGMSG(ZONE_IO|ZONE_WARNING, (_T(
                    "Ata!CDisk::ReadWriteDisk> Failed to wait for interrupt (m_dwDeviceId=%d)\r\n"
                    ), m_dwDeviceId));
                dwError = ERROR_READ_FAULT;
                goto exit;
            }
        }

        // Check_Status
        // ------------
        // if BSY=0 and DRQ=0, transition to Host_Idle
        // if BSY=1, re-enter this state
        // if BSY=0 and DRQ=1, transition to Transfer_Data
HPIOI_Check_Status:;
		//DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: ReadWriteDisk+(HPIOI_Check_Status)\r\n")));
        bStatus = GetAltStatus();                                  // read Status register
        if ((!(bStatus & 0x80)) && (!(bStatus & 0x08))) goto exit; // BSY=0, DRQ=0
        if (bStatus & 0x80) goto HPIOI_Check_Status;               // BSY=1
        if ((!(bStatus & 0x80)) && (bStatus & 0x08)) goto HPIOI_Transfer_Data_Setup; // BSY=0, DRQ=1
        DEBUGCHK(FALSE);
        goto exit;

        // Transfer_Data
        // -------------
        // if read Data register, DRQ data block transfer not complete, re-enter this state
        // if raad Data register, all data for command transferred, transition to Host_Idle
        // if read Data register, DRQ data block transferred, all data for command not transferred,
        //     and nIEN=1, transition to Check_Status
        // if read Data register, DRQ data block transferred, all data for command not transferred,
        //     and nIEN=0, transition to INTRQ_Wait
HPIOI_Transfer_Data_Setup:;
		//DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: ReadWriteDisk+(HPIOI_Transfer_Data_Setup)\r\n")));
        dwCurDRQDataBlockByte = 0;                      // reset DRQ data block
HPIOI_Transfer_Data:;
		//DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: ReadWriteDisk+(HPIOI_Transfer_Data)\r\n")));
        if (m_f16Bit) {
            *((PWORD)pDoubleBuffer) = ReadWord();       // read 16-bit Data register
            pDoubleBuffer++;
            dwCurDRQDataBlockByte += 1;                 // increment DRQ data block
			dwIntrCount += 2;
			dwBufferCount += 2;
        }
        else {
            *((PBYTE)pDoubleBuffer) = (BYTE)ReadByte(); // read 8-bit Data register
			dwIntrCount ++;
			dwBufferCount ++;
        }
        pDoubleBuffer++;
        dwCurDRQDataBlockByte += 1;                     // increment DRQ data block
        // is DRQ data block transferred?
        if (dwCurDRQDataBlockByte == m_pPort->m_pDskReg[m_dwDeviceId]->dwDrqDataBlockSize) {
            dwCurDoubleBufPos += m_pPort->m_pDskReg[m_dwDeviceId]->dwDrqDataBlockSize;
            // has all data for command been transferred?
            if (dwCurDoubleBufPos == dwCurDoubleBufLen) goto HPIOI_Empty_Double_Buffer;
            // DRQ data block transferred, all data for command not transferred
            goto HPIOI_INTRQ_Wait;
        }
        // DRQ data block transfer not complete
        goto HPIOI_Transfer_Data;

HPIOI_Empty_Double_Buffer:;
		//DEBUGMSG(ZONE_FUNC, (TEXT("CDisk: ReadWr

⌨️ 快捷键说明

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