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

📄 ide.c

📁 WinCE 3.0 BSP, 包含Inter SA1110, Intel_815E, Advantech_PCM9574 等
💻 C
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-2000  Microsoft Corporation

Module Name: ide.c

Abstract: Boot loader IDE/ATA access functions.

Functions:

    id_drive            - Locate/identify drive.
    lba_to_pchs         - Convert LBA address to Physical CHS.
    read_sector         - Read the contents of a disk sector.
    init_ide            - Initialize IDE drive.
    load_image_ide      - Load OS image from drive.
    OEMHDDPlatformInit  - Blcommon interface functions.
    OEMHDDPreDownload   -  "
    OEMHDDReadData      -  "
    OEMHDDLaunch        -  "

Notes:
    
     Assumptions:
     - only primary master drive is supported
     - FAT16
     - file op routines only work on a single file at a time 
     - kernel image is in the root directory with the bootloader image

--*/

#include <windows.h>
#include "bootarg.h"
#include "ide.h"
#include "fat.h"
#include "bldr.h"


// Global variables.
//
UCHAR g_bsect[SECTOR_SIZE];
ULONG g_sectorsread=0;
UCHAR g_bstartcounting=0;
STATUSBAR g_statbar;

// Function prototypes.
//
int create_statusbar(PSTATUSBAR pbar, ULONG sval, ULONG eval);
int update_statusbar(PSTATUSBAR pbar, ULONG cval);

// Externs.
//
extern FILEINFO g_fileinfo;

int id_drive(void)
{
    USHORT cnt=0;
    drv_id_hdr hdr;

    DEBUGMSG(ZONE_BOOTPROG, (TEXT("B6\r\n")));

    memset(&hdr, 0, sizeof(drv_id_hdr));

    // Denote drive of interest and get drive id information
    WAIT_IDE_BUSY;
    WAIT_IDE_NOT_DRDY;
    // TODO - compensate for other drive numbers.
    WRITE_IDE_UCHAR(IDE_DRVHD_REG, 0xA0);
    WRITE_IDE_UCHAR(IDE_CMD_REG, IDE_IDDRIVE_CMD);
    WAIT_IDE_BUSY;
    WAIT_IDE_NOT_DRQ;

    DEBUGMSG(ZONE_BOOTPROG, (TEXT("B7\r\n")));

    if(IS_IDE_ERROR)
    {
        RETAILMSG(1, (TEXT("ERROR: Drive ID failed.\r\n")));         
        return(-1);
    }
   
    DEBUGMSG(ZONE_BOOTPROG, (TEXT("B8\r\n")));

    // Read id info from IDE sector buffer
    for(cnt = 0 ; cnt < (sizeof(drv_id_hdr) / sizeof(USHORT)) ; cnt++)
        *((USHORT *)(&hdr) + cnt) = READ_IDE_USHORT(IDE_DATA_REG);

    // Save away P-CHS conversion information for the drive.
    g_drvparms.phy_cyls        = hdr.lcyls;
    g_drvparms.phy_heads       = hdr.lheads;
    g_drvparms.phy_sectspertrk = hdr.lsctptrk;

    DEBUGMSG(ZONE_INFO, (TEXT("lheads = 0x%x\r\n"), g_drvparms.phy_heads));
    DEBUGMSG(ZONE_INFO, (TEXT("lsctptrk = 0x%x\r\n"), g_drvparms.phy_sectspertrk));

    RETAILMSG(1, (TEXT("Loading image from hard drive...\r\n")));

    return(0);
}


int lba_to_pchs(ULONG lba, 
                USHORT *pc,
                UCHAR  *ph,
                UCHAR  *ps)
{
    USHORT temp = 0;

    // Make sure we know the drive geometry
    if (g_drvparms.phy_cyls  == 0 ||
        g_drvparms.phy_heads == 0 ||
        g_drvparms.phy_sectspertrk == 0)
        return(-1);

    if (pc == NULL || ph == NULL || ps == NULL)
        return(-1);

    // Do the math...
    *pc = (USHORT)(lba / (g_drvparms.phy_heads * g_drvparms.phy_sectspertrk));
    temp = (USHORT)(lba % (g_drvparms.phy_heads * g_drvparms.phy_sectspertrk));
    *ph = (UCHAR)(temp / g_drvparms.phy_sectspertrk);
    *ps = (UCHAR)(temp % g_drvparms.phy_sectspertrk) + 1;
   
    return(0); 
}


int read_sector(ULONG lba, unsigned char *pbuf)
{
    USHORT c = 0;
    UCHAR  h = 0;
    UCHAR  s = 0;
    USHORT i = 0;
    UCHAR *a = NULL;

    if (!pbuf)
        return(-1);

    // Convert LBA address to P-CHS for IDE controller
    if (lba_to_pchs(lba, &c, &h, &s))
        return(-1);

    DEBUGMSG(ZONE_INFO, (TEXT("INFO: Reading sector (P-CHS = 0x%x:0x%x:0x%x).\r\n"), c, h, s));

    // Program the IDE controller
    WAIT_IDE_BUSY;
    WRITE_IDE_UCHAR(IDE_CYLL_REG, (unsigned char)(c & 0x00ff));
    WRITE_IDE_UCHAR(IDE_CYLH_REG, (unsigned char)((c & 0xff00) >> 8));
    // TODO - future drive num compensate.
    WRITE_IDE_UCHAR(IDE_DRVHD_REG, (unsigned char)(h | 0xA0));
    WRITE_IDE_UCHAR(IDE_SECTNUM_REG, (UCHAR)s);
    WRITE_IDE_UCHAR(IDE_SECTCNT_REG, 1);

    // Make sure interrupt enable bit is off (we'll poll)
    _outp(0x3f6, 0x0a);
    
    WAIT_IDE_NOT_DRDY;

    WRITE_IDE_UCHAR(IDE_CMD_REG, IDE_RDSECT_CMD);

    WAIT_IDE_BUSY; 
    if (IS_IDE_ERROR)
    {
        RETAILMSG(1, (TEXT("ERROR: Sector read failed.\r\n")));
        return(-1);
    }
    WAIT_IDE_NOT_DRQ;

    // Copy sector buffer contents to callers buffer
    for(i=0 ; i < (SECTOR_SIZE / sizeof(USHORT)) ; i++)
       *((USHORT *)pbuf + i) = (USHORT)(READ_IDE_USHORT(IDE_DATA_REG)); 

    // Increment total number of sectors and update status bar
    if (g_bstartcounting)
    {
        ++g_sectorsread;
        update_statusbar(&g_statbar, g_sectorsread);
    }
 
    return(0);
}


int init_ide(void)
{

    // Get drive geometry info - needed for LBA -> P-CHS convertion
    if (id_drive())
        return(-1);

    return(0);
}


// TODO: Resolve with OEMHDDPreDownload.
int load_image_ide(unsigned char *pname, ULONG *pimgloc)
{
    int stat=0;
    IMGHDR imghdr;
    RECHDR rechdr;
    ULONG cnt = 0;

    DEBUGMSG(ZONE_BOOTPROG, (TEXT("B5\r\n")));

    //
    g_bstartcounting = 0;
    g_sectorsread = 0;

    // Initialize IDE
    if (init_ide())
    {
        RETAILMSG(1, (TEXT("ERROR: IDE device initialization failed.\r\n")));
        return(-1);
    }


    // Initialize FAT structs
    if (init_fat())
    {
        RETAILMSG(1, (TEXT("ERROR: FAT initialization failed.\r\n")));
        return(-1);
    }

    // Open image (finds starting LBA and size - inits structs for later ops)
    // Only read is supported
    if (file_open(pname))
    {
        RETAILMSG(1, (TEXT("ERROR: File open failed (%s)\r\n"), pname));
        return(-1);
    }

    // Display status bar
    create_statusbar(&g_statbar, 0, (g_fileinfo.fsize / SECTOR_SIZE) - 1);
    g_bstartcounting = 1;

    // Get image header
    stat = file_read((unsigned char *)&imghdr, sizeof(IMGHDR));
    if (stat == FAT_EOF)
    {
        RETAILMSG(1, (TEXT("ERROR: EOF reading image header.\r\n")));
        return(-1);
    }
    else if (stat)
    {
        RETAILMSG(1, (TEXT("ERROR: File read failed.\r\n")));
        return(-1);
    }

    // Determine jump address
    *pimgloc = imghdr.imgaddr;

    // Display image header
    DEBUGMSG(ZONE_INFO, (TEXT("Image Header:\r\n")));
    DEBUGMSG(ZONE_INFO, (TEXT("-------------------------------------------\r\n")));
    DEBUGMSG(ZONE_INFO, (TEXT("Sync Bytes    = '%c%c%c%c%c%c'\r\n"), imghdr.syncbytes[0], imghdr.syncbytes[1], imghdr.syncbytes[2], imghdr.syncbytes[3], imghdr.syncbytes[4], imghdr.syncbytes[5]));
    DEBUGMSG(ZONE_INFO, (TEXT("Image Address = 0x%x\r\n"), imghdr.imgaddr));
    DEBUGMSG(ZONE_INFO, (TEXT("Image Length  = 0x%x\r\n"), imghdr.imglen));

    do
    {
	// Get record header
        stat = file_read((unsigned char *)&rechdr, sizeof(RECHDR));
        if (stat == FAT_EOF)
        {
            RETAILMSG(1, (TEXT("ERROR: EOF reading record header.\r\n")));
            return(-1);
        }
        else if (stat)
        {
            RETAILMSG(1, (TEXT("ERROR: File read failed.\r\n")));
            return(-1);
        } 

        // Display Record Header
        DEBUGMSG(ZONE_INFO, (TEXT("Record Header:\r\n")));
        DEBUGMSG(ZONE_INFO, (TEXT("------------------------------------------\r\n")));
        DEBUGMSG(ZONE_INFO, (TEXT("Record Address  = 0x%x\r\n"), rechdr.recaddr));
        DEBUGMSG(ZONE_INFO, (TEXT("Record Length   = 0x%x\r\n"), rechdr.reclen));
        DEBUGMSG(ZONE_INFO, (TEXT("Record CheckSum = 0x%x\r\n"), rechdr.recchksum));

        // Last Header
        if (rechdr.recaddr == 0 && rechdr.recchksum == 0)
            break;

        stat = file_read((unsigned char *)rechdr.recaddr, rechdr.reclen);
        if (stat)
        {
            if (stat == EOF)
                RETAILMSG(1, (TEXT("ERROR: EOF reading data.\r\n")));
            else
                RETAILMSG(1, (TEXT("ERROR: File read failed.\r\n")));
            return(-1);
        } 

    }
    while(1);

    // Close file
    file_close();

    return(0);
}


BOOL OEMHDDPlatformInit(VOID)
{
    return(TRUE);
}


DWORD OEMHDDPreDownload(VOID)
{
    UCHAR pName[] = KIMAGE_NAME;

    //
    g_bstartcounting = 0;
    g_sectorsread = 0;

    // Initialize IDE
    if (init_ide())
    {
        RETAILMSG(1, (TEXT("ERROR: IDE device initialization failed.\r\n")));
        return(-1);
    }

    // Initialize FAT structs
    if (init_fat())
    {
        RETAILMSG(1, (TEXT("ERROR: FAT initialization failed.\r\n")));
        return(-1);
    }

    // Open image (finds starting LBA and size - inits structs for later ops)
    // Only read is supported
    if (file_open(pName))
    {
        RETAILMSG(1, (TEXT("ERROR: File open failed (%s).\r\n"), pName));
        return(-1);
    }

    // Display status bar
    create_statusbar(&g_statbar, 0, (g_fileinfo.fsize / SECTOR_SIZE) - 1);
    g_bstartcounting = 1;

    return(BL_DOWNLOAD);
}


BOOL OEMHDDReadData(DWORD cbData, LPBYTE pbData)
{
    int stat=0;

    stat = file_read((unsigned char *)pbData, cbData);
    if (stat == FAT_EOF)
    {
        RETAILMSG(1, (TEXT("ERROR: EOF reading record header.\r\n")));
        return(FALSE);
    }
    else if (stat)
    {
        RETAILMSG(1, (TEXT("ERROR: File read failed.\r\n")));
        return(FALSE);
    } 

    return(TRUE);
}


VOID OEMHDDLaunch(DWORD dwImageStart,
                  DWORD dwImageLength,
                  DWORD dwLaunchAddr,
                  const ROMHDR *pRomHdr)
{
    ((PFN_LAUNCH)(dwLaunchAddr))();

    // Should never be reached.
    SpinForever();
}

⌨️ 快捷键说明

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