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

📄 diskio.c

📁 WinCE下的ATADISK驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
    (TEXT("ATADISK:ATAInitController writing to ATA_REG_DRV_CTRL\r\n")));

        ATA_WRITE_UCHAR(pDisk->d_Flags, (UCHAR*)pDisk->d_pATARegAlt + ATA_REG_DRV_CTRL,
                         ATA_CTRL_ENABLE_INTR);
        if (ATAWaitForDisk(
                pDisk,
                WAIT_TIME_LONG,
                WAIT_TYPE_READY) != CERR_SUCCESS) {
            ret = FALSE;
        }
    } except (GetExceptionCode() == STATUS_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        DEBUGMSG(ZONE_IO|ZONE_ERROR, (TEXT("ATADISK:ATAInitController - exception!\r\n")));
        ret = FALSE;
    }
DEBUGMSG(ZONE_INIT, (TEXT("ATADISK:ATAInitController done\r\n")));
    return ret;
}   // ATAInitController

//
// Function to open the driver key specified by the active key
//
// The caller is responsible for closing the returned HKEY
//
HKEY
OpenDriverKey(
    LPTSTR ActiveKey
    )
{
    TCHAR DevKey[256];
    HKEY hDevKey;
    HKEY hActive;
    DWORD ValType;
    DWORD ValLen;
    DWORD status;

    //
    // Get the device key from active device registry key
    //
    status = RegOpenKeyEx(
                HKEY_LOCAL_MACHINE,
                ActiveKey,
                0,
                0,
                &hActive);
    if (status) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR,
            (TEXT("ATADISK:OpenDriverKey RegOpenKeyEx(HLM\\%s) returned %d!!!\r\n"),
                  ActiveKey, status));
        return NULL;
    }

    hDevKey = NULL;

    ValLen = sizeof(DevKey);
    status = RegQueryValueEx(
                hActive,
                DEVLOAD_DEVKEY_VALNAME,
                NULL,
                &ValType,
                (PUCHAR)DevKey,
                &ValLen);
    if (status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR,
            (TEXT("ATADISK:OpenDriverKey - RegQueryValueEx(%s) returned %d\r\n"),
                  DEVLOAD_DEVKEY_VALNAME, status));
        goto odk_fail;
    }

    //
    // Get the geometry values from the device key
    //
    status = RegOpenKeyEx(
                HKEY_LOCAL_MACHINE,
                DevKey,
                0,
                0,
                &hDevKey);
    if (status) {
        hDevKey = NULL;
        DEBUGMSG(ZONE_INIT|ZONE_ERROR,
            (TEXT("ATADISK:OpenDriverKey RegOpenKeyEx(HLM\\%s) returned %d!!!\r\n"),
                  DevKey, status));
    }

odk_fail:
    RegCloseKey(hActive);
    return hDevKey;
}   // OpenDriverKey

//
// Function to retrieve the folder name value from the driver key. The folder name is
// used by FATFS to name this disk volume.
//
BOOL
GetFolderName(
    PDISK pDisk,
    LPWSTR FolderName,
    DWORD cBytes,
    DWORD * pcBytes
    )
{
    HKEY DriverKey;
    DWORD ValType;
    DWORD status;
    TCHAR szName[MAX_PATH];
    DWORD dwSize;

    DriverKey = OpenDriverKey(pDisk->d_ActivePath);
    if (DriverKey) {
        dwSize = sizeof(szName);
        status = RegQueryValueEx(
                    DriverKey,
                    TEXT("Folder"),
                    NULL,
                    &ValType,
                    (LPBYTE)szName,
                    &dwSize);
        if ((status != ERROR_SUCCESS) || (dwSize > cBytes)){
            DEBUGMSG(ZONE_INIT|ZONE_ERROR,
                (TEXT("ATADISK:GetFolderName - RegQueryValueEx(Folder) returned %d\r\n"),
                      status));
            *pcBytes = 0;
        } else {
            DEBUGMSG(ZONE_INIT|ZONE_ERROR,
                (TEXT("ATADISK:GetFolderName - FolderName = %s, length = %d\r\n"),
                 FolderName, *pcBytes));
           *pcBytes = (wcslen(szName)+1)*sizeof(WCHAR);
           wcscpy( (LPWSTR)FolderName, szName);
        }
        RegCloseKey(DriverKey);
        if (status || (*pcBytes == 0)) {
            SetLastError( ERROR_NOT_FOUND);
            return FALSE;
        }
        return TRUE;
    }
    return FALSE;
}   // GetFolderName

//
// Function to get the C:H:S values for the disk specified by the ActiveKey.
//
// NOTE: Only one such set of values will be allowed per system since the active
// key is dynamic. The CHS values must be stored in the device key.
//
// NOTE2: C:H:S => Cylinders:Heads:Sectors per track
//
BOOL
GetGeometry(
    HKEY hDevKey,
    WORD * Cylinders,
    WORD * Heads,
    WORD * Sectors
    )
{
    DWORD ValType;
    DWORD ValLen;
    DWORD status;
    DWORD dwtmp;

    ValLen = sizeof(dwtmp);
    status = RegQueryValueEx(
                hDevKey,
                TEXT("Cylinders"),
                NULL,
                &ValType,
                (PUCHAR)&dwtmp,
                &ValLen);
    if (status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR,
            (TEXT("ATADISK:GetGeometry - RegQueryValueEx(Cylinders) returned %d\r\n"),
                  status));
        return FALSE;
    }
    *Cylinders = (WORD)dwtmp;

    ValLen = sizeof(dwtmp);
    status = RegQueryValueEx(
                hDevKey,
                TEXT("Heads"),
                NULL,
                &ValType,
                (PUCHAR)&dwtmp,
                &ValLen);
    if (status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR,
            (TEXT("ATADISK:GetGeometry - RegQueryValueEx(Heads) returned %d\r\n"),
                  status));
        return FALSE;
    }
    *Heads = (WORD)dwtmp;

    ValLen = sizeof(dwtmp);
    status = RegQueryValueEx(
                hDevKey,
                TEXT("Sectors"),
                NULL,
                &ValType,
                (PUCHAR)&dwtmp,
                &ValLen);
    if (status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR,
            (TEXT("ATADISK:GetGeometry - RegQueryValueEx(Sectors) returned %d\r\n"),
                  status));
        return FALSE;
    }
    *Sectors = (WORD)dwtmp;
    return TRUE;
}   // GetGeometry

static BOOL
ParseATAIdString(
    CHAR *str, int len, DWORD *pdwOffset, CHAR **ppDest, DWORD *pcBytesLeft
    )
{
    UCHAR *p;
    DWORD cCopied;
    CHAR *pDest;
    
    // check validity (spec says ASCII, I assumed printable)
    for (p = str; p < &str[len]; ++p)
        if (*p < 0x20 || *p > 0x7F) {
            *pdwOffset = 0;
            return FALSE;
        }

    // find the last non-pad character
    for (p = &str[len]; p > str && p[-1] == ' '; --p)
        ;
    cCopied = p - str;

    // special case - empty string implies not present
    if (cCopied == 0) {
        *pdwOffset = 0;
        return TRUE;
    }
    ++cCopied; // this is a byte count so add a terminating null

    // always increment *ppDest because it counts the bytes that we want,
    // not just the bytes that we've actually written.
    pDest = *ppDest;
    *ppDest += cCopied;

    // if there has already been an error, then we needn't continue further
    if (GetLastError() != ERROR_SUCCESS)
        return TRUE;

    // make sure there's enough space to copy into
    if (cCopied > *pcBytesLeft) {
        SetLastError(ERROR_INSUFFICIENT_BUFFER);
        cCopied = *pcBytesLeft;
    }
    __try {
        if (cCopied) {
            memcpy(pDest, str, cCopied-1);
            pDest[cCopied-1] = '\0';
        }
    } __except (EXCEPTION_EXECUTE_HANDLER) {
        SetLastError(ERROR_INVALID_PARAMETER);
    };

    *pcBytesLeft -= cCopied;
    return TRUE;
}

BOOL
GetStorageID(
    PDISK pDisk,
    PSTORAGE_IDENTIFICATION psid,
    DWORD cBytes,
    DWORD * pcBytes
    )
{
    IDENTIFY_DATA sAtaId;
    PCHAR pDstOffset;
    DWORD cRemaining;

    memset( &sAtaId, 0, sizeof(IDENTIFY_DATA));
    
    if (cBytes < sizeof(*psid)) {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    } else
        // initialize the error status in case there are no errors
        SetLastError(ERROR_SUCCESS);

    __try {
        psid->dwSize = sizeof(*psid);
        psid->dwFlags = 0;  // can be or of {MANUFACTUREID,SERIALNUM}_INVALID
        psid->dwManufactureIDOffset = psid->dwSerialNumOffset = 0;
    } __except (EXCEPTION_EXECUTE_HANDLER) {
        SetLastError(ERROR_INVALID_PARAMETER);
        return FALSE;
    }
    if (ATAIssueIdentify(pDisk, &sAtaId) == FALSE) {
        // leave the error code alone
        return FALSE;
    }

    cRemaining = cBytes - sizeof(*psid);
    pDstOffset = (PCHAR)(psid + 1);

// This macro is only used here; I think it's clearer than the expansion.
#define PARSESTRING(nSrcField,nOffField,nFlagPfx)                                  \
    if (1) {                                                                       \
        psid->nOffField = pDstOffset - (PCHAR)psid;                                \
        if (ParseATAIdString((PCHAR)sAtaId.nSrcField, sizeof(sAtaId.nSrcField),    \
                             &psid->nOffField, &pDstOffset, &cRemaining) == FALSE) \
            psid->dwFlags |= nFlagPfx ## _INVALID;                                 \
    } else

    PARSESTRING(ModelNumber, dwManufactureIDOffset, MANUFACTUREID);
    PARSESTRING(SerialNumber, dwSerialNumOffset, SERIALNUM);
    psid->dwSize = pDstOffset - (PCHAR)psid;    // required size

    *pcBytes = min(psid->dwSize, cBytes);       // bytes written

    return (GetLastError() == ERROR_SUCCESS);
}

//
// Function to check if the advertised LBA mode capability needs to be ignored.
//
// NOTE: Only one such set of value can be allowed per system since the active
// key is dynamic. The CHSMode value must be stored in the device key.
//
// NOTE2: C:H:S => Cylinders:Heads:Sectors per track
//        LBA => Logical Block Address
//
BOOL
UseCHSMode(
    HKEY hDevKey
    )
{
    DWORD ValType;
    DWORD ValLen;
    DWORD status;
    DWORD dwtmp;

    ValLen = sizeof(dwtmp);
    status = RegQueryValueEx(
                hDevKey,
                TEXT("CHSMode"),
                NULL,
                &ValType,
                (PUCHAR)&dwtmp,
                &ValLen);
    if (status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR,
            (TEXT("ATADISK:UseCHSMode - RegQueryValueEx(CHSMode) returned %d\r\n"),
                  status));
        return FALSE;
    }

    return dwtmp == 1 ? TRUE : FALSE;
}   // UseCHSMode

//
// InitDisk
//
DWORD InitDisk(
    PDISK pDisk,
    LPTSTR ActiveKey
    )
{
    IDENTIFY_DATA Id;
    HKEY DriverKey;

    memset( &Id, 0, sizeof(IDENTIFY_DATA));


    if (ATAInitController(pDisk) == FALSE) {
        return 1;
    }
    if (ATAIssueIdentify(pDisk, &Id) == FALSE) {
        return 2;
    }

    DriverKey = OpenDriverKey(ActiveKey);

    //
    // If the identify data block is not reliable, then get the values
    // from the registry.
    //
    if (DriverKey && ((Id.TranslationFieldsValid & 1) == 0)) {
        DEBUGMSG(ZONE_INIT,
            (TEXT("ATADISK:InitDisk - Getting C:H:S from registry\r\n")));
        GetGeometry(
            DriverKey,
            &(Id.NumberOfCylinders),
            &(Id.NumberOfHeads),
            &(Id.SectorsPerTrack));
        DEBUGMSG(ZONE_INIT,
            (TEXT("ATADISK:InitDisk - C:H:S = %d:%d:%d\r\n"),
            Id.NumberOfCylinders, Id.NumberOfHeads, Id.SectorsPerTrack));
    }

    pDisk->d_fLBAMode       = TRUE;
    pDisk->d_DiskInfo.di_total_sectors = Id.TotalUserAddressableSectors;
    pDisk->d_DiskInfo.di_bytes_per_sect = BYTES_PER_SECTOR; // Start with 512, then go with SetInfo changes
    pDisk->d_DiskInfo.di_cylinders = Id.NumberOfCylinders;
    pDisk->d_DiskInfo.di_heads = Id.NumberOfHeads;
    pDisk->d_DiskInfo.di_sectors = Id.SectorsPerTrack;
    pDisk->d_DiskInfo.di_flags = DISK_INFO_FLAG_MBR;

    if (DriverKey) {
        if (UseCHSMode(DriverKey)) {
            pDisk->d_fLBAMode = FALSE;
        }
        RegCloseKey(DriverKey);
    }
    return 0;
}   // Initdisk

⌨️ 快捷键说明

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