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

📄 pm.c

📁 AT91RM9200-U-Boot at91rm9200u-boot移植源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
REMARKS:Maps a physical memory range to a linear memory range.****************************************************************************/ulong MapPhysicalToLinear(    ulong base,    ulong limit,    int *npages){    ulong   linear,length = limit+1;    int     i,ppage,flags;#if 0    ppage = base >> 12;    *npages = (length + (base & 0xFFF) + 4095) >> 12;    flags = PR_FIXED | PR_STATIC;    if (base == 0xA0000) {        /* We require the linear address to be aligned to a 64Kb boundary         * for mapping the banked framebuffer (so we can do efficient         * carry checking for bank changes in the assembler code). The only         * way to ensure this is to force the linear address to be aligned         * to a 4Mb boundary.         */        flags |= PR_4MEG;        }    if ((linear = (ulong)PageReserve(PR_SYSTEM,*npages,flags)) == (ulong)-1)        return 0;    if (!PageCommitPhys(linear >> 12,*npages,ppage,PC_INCR | PC_USER | PC_WRITEABLE))        return 0;#endif    return linear + (base & 0xFFF);}/****************************************************************************PARAMETERS:base        - Physical base address of the memory to map inlimit       - Limit of physical memory to region to map inisCached    - True if the memory should be cached, false if notRETURNS:Linear address of the newly mapped memory.REMARKS:This function maps physical memory to linear memory, which can then be usedto create a selector or used directly from 32-bit protected mode programs.This is better than DPMI 0x800, since it allows you to maps physicalmemory below 1Mb, which gets this memory out of the way of the Windows VxD'ssticky paws.NOTE:   If the memory is not expected to be cached, this function will        directly re-program the PCD (Page Cache Disable) bit in the        page tables. There does not appear to be a mechanism in the VMM        to control this bit via the regular interface.****************************************************************************/void * PMAPI PM_mapPhysicalAddr(    ulong base,    ulong limit,    ibool isCached){    ulong   linear,length = limit+1;    int     i,npages;    ulong   PDB,*pPDB;    /* Search table of existing mappings to see if we have already mapped     * a region of memory that will serve this purpose.     */    for (i = 0; i < numMappings; i++) {        if (maps[i].physical == base && maps[i].length == length && maps[i].isCached == isCached)            return (void*)maps[i].linear;        }    if (numMappings == MAX_MEMORY_MAPPINGS)        return NULL;    /* We did not find any previously mapped memory region, so map it in.     * Note that we do not use MapPhysToLinear, since this function appears     * to have problems mapping memory in the 1Mb physical address space.     * Hence we use PageReserve and PageCommitPhys.     */    if ((linear = MapPhysicalToLinear(base,limit,&npages)) == 0)        return NULL;    maps[numMappings].physical = base;    maps[numMappings].length = length;    maps[numMappings].linear = linear;    maps[numMappings].npages = npages;    maps[numMappings].isCached = isCached;    numMappings++;#if 0    /* Finally disable caching where necessary */    if (!isCached && (PDB = _PM_getPDB()) != 0) {        int     startPDB,endPDB,iPDB,startPage,endPage,start,end,iPage;        ulong   pageTable,*pPageTable;        if (PDB >= 0x100000)            pPDB = (ulong*)MapPhysicalToLinear(PDB,0xFFF,&npages);        else            pPDB = (ulong*)PDB;        if (pPDB) {            startPDB = (linear >> 22) & 0x3FF;            startPage = (linear >> 12) & 0x3FF;            endPDB = ((linear+limit) >> 22) & 0x3FF;            endPage = ((linear+limit) >> 12) & 0x3FF;            for (iPDB = startPDB; iPDB <= endPDB; iPDB++) {                pageTable = pPDB[iPDB] & ~0xFFF;                if (pageTable >= 0x100000)                    pPageTable = (ulong*)MapPhysicalToLinear(pageTable,0xFFF,&npages);                else                    pPageTable = (ulong*)pageTable;                start = (iPDB == startPDB) ? startPage : 0;                end = (iPDB == endPDB) ? endPage : 0x3FF;                for (iPage = start; iPage <= end; iPage++)                    pPageTable[iPage] |= 0x10;                PageFree((ulong)pPageTable,PR_STATIC);                }            PageFree((ulong)pPDB,PR_STATIC);            }        }#endif    return (void*)linear;}void PMAPI PM_freePhysicalAddr(void *ptr,ulong limit){    /* We never free the mappings */}void PMAPI PM_sleep(ulong milliseconds){    /* We never sleep in a VDD */}int PMAPI PM_getCOMPort(int port){    // TODO: Re-code this to determine real values using the Plug and Play    //       manager for the OS.    switch (port) {        case 0: return 0x3F8;        case 1: return 0x2F8;        }    return 0;}int PMAPI PM_getLPTPort(int port){    // TODO: Re-code this to determine real values using the Plug and Play    //       manager for the OS.    switch (port) {        case 0: return 0x3BC;        case 1: return 0x378;        case 2: return 0x278;        }    return 0;}ulong PMAPI PM_getPhysicalAddr(void *p){        // TODO: This function should find the physical address of a linear        //               address.        return 0xFFFFFFFFUL;}void PMAPI _PM_freeMemoryMappings(void){    int i;//    for (i = 0; i < numMappings; i++)//        PageFree(maps[i].linear,PR_STATIC);}void * PMAPI PM_mapRealPointer(uint r_seg,uint r_off){ return (void*)MK_PHYS(r_seg,r_off); }void * PMAPI PM_allocRealSeg(uint size,uint *r_seg,uint *r_off){ return NULL; }void PMAPI PM_freeRealSeg(void *mem){ }void PMAPI DPMI_int86(int intno, DPMI_regs *regs){    /* Unsed in VDDs */}/****************************************************************************REMARKS:Load the V86 registers in the client state, and save the original statebefore loading the registers.****************************************************************************/static void LoadV86Registers(    PCRF saveRegs,    RMREGS *in,    RMSREGS *sregs){    PCRF            pcrf;     // current client register frame    // get pointer to registers    pcrf = (PCRF)VDHQuerySysValue(CURRENT_VDM, VDHLSV_PCRF);    // Note: We could do VDHPushRegs instead but this should be safer as it    // doesn't rely on the VDM session having enough free stack space.    *saveRegs = *pcrf;        // save all registers    pcrf->crf_eax = in->e.eax;    // load new values    pcrf->crf_ebx = in->e.ebx;    pcrf->crf_ecx = in->e.ecx;    pcrf->crf_edx = in->e.edx;    pcrf->crf_esi = in->e.esi;    pcrf->crf_edi = in->e.edi;    pcrf->crf_es  = sregs->es;    pcrf->crf_ds  = sregs->ds;}/****************************************************************************REMARKS:Read the V86 registers from the client state and restore the original state.****************************************************************************/static void ReadV86Registers(    PCRF saveRegs,    RMREGS *out,    RMSREGS *sregs){    PCRF            pcrf;     // current client register frame    // get pointer to registers    pcrf = (PCRF)VDHQuerySysValue(CURRENT_VDM, VDHLSV_PCRF);    // read new register values    out->e.eax = pcrf->crf_eax;    out->e.ebx = pcrf->crf_ebx;    out->e.ecx = pcrf->crf_ecx;    out->e.edx = pcrf->crf_edx;    out->e.esi = pcrf->crf_esi;    out->e.edi = pcrf->crf_edi;    sregs->es  = pcrf->crf_es;    sregs->ds  = pcrf->crf_ds;    // restore original client registers    *pcrf = *saveRegs;}/****************************************************************************REMARKS: Used for far calls into V86 code****************************************************************************/VOID HOOKENTRY UserReturnHook(  PVOID pRefData,  PCRF pcrf ){    VDHPostEventSem(hevFarCallRet);}/****************************************************************************REMARKS: Used for calling BIOS interrupts****************************************************************************/VOID HOOKENTRY UserIRetHook(  PVOID pRefData,  PCRF pcrf ){    VDHPostEventSem(hevIRet);}/****************************************************************************REMARKS:Call a V86 real mode function with the specified register valuesloaded before the call. The call returns with a far ret.Must be called from within a DOS session context!****************************************************************************/void PMAPI PM_callRealMode(    uint seg,    uint off,    RMREGS *regs,    RMSREGS *sregs){    CRF   saveRegs;    FPFN  fnAddress;    ULONG rc;    TRACE("SDDHELP: Entering PM_callRealMode()\n");    LoadV86Registers(SSToDS(&saveRegs),regs,sregs);    // set up return hook for call    rc = VDHArmReturnHook(hhookUserReturnHook, VDHARH_CSEIP_HOOK);    VDHResetEventSem(hevFarCallRet);    // the address is a 16:32 pointer    OFFSETOF32(fnAddress)  = off;    SEGMENTOF32(fnAddress) = seg;    rc = VDHPushFarCall(fnAddress);    VDHYield(0);    // wait until the V86 call returns - our return hook posts the semaphore    rc = VDHWaitEventSem(hevFarCallRet, SEM_INDEFINITE_WAIT);    ReadV86Registers(SSToDS(&saveRegs),regs,sregs);    TRACE("SDDHELP: Exiting PM_callRealMode()\n");}/****************************************************************************REMARKS:Issue a V86 real mode interrupt with the specified register valuesloaded before the interrupt.Must be called from within a DOS session context!****************************************************************************/int PMAPI PM_int86(    int intno,    RMREGS *in,    RMREGS *out){    RMSREGS    sregs = {0};    CRF        saveRegs;    ushort     oldDisable;    ULONG      rc;    memset(SSToDS(&sregs), 0, sizeof(sregs));#if 0   // do we need this??    /* Disable pass-up to our VDD handler so we directly call BIOS */    TRACE("SDDHELP: Entering PM_int86()\n");    if (disableTSRFlag) {        oldDisable = *disableTSRFlag;        *disableTSRFlag = 0;        }#endif    LoadV86Registers(SSToDS(&saveRegs), in, SSToDS(&sregs));    VDHResetEventSem(hevIRet);    rc = VDHPushInt(intno);    // set up return hook for interrupt    rc = VDHArmReturnHook(hhookUserIRetHook, VDHARH_NORMAL_IRET);    VDHYield(0);    // wait until the V86 IRETs - our return hook posts the semaphore    rc = VDHWaitEventSem(hevIRet, 5000); //SEM_INDEFINITE_WAIT);    ReadV86Registers(SSToDS(&saveRegs), out, SSToDS(&sregs));#if 0    /* Re-enable pass-up to our VDD handler if previously enabled */    if (disableTSRFlag)        *disableTSRFlag = oldDisable;#endif    TRACE("SDDHELP: Exiting PM_int86()\n");    return out->x.ax;}/****************************************************************************REMARKS:Issue a V86 real mode interrupt with the specified register values

⌨️ 快捷键说明

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