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

📄 pm.c

📁 uboot在arm处理器s3c2410的移植代码
💻 C
📖 第 1 页 / 共 4 页
字号:
{    PMSREGS     sregs;    ulong       linAddr;    ulong       DSBaseAddr;    /* Get the base address for the default DS selector */    PM_segread(&sregs);    DSBaseAddr = DPMI_getSelectorBase(sregs.ds);    if ((base < 0x100000) && (DSBaseAddr == 0)) {	/* DS is zero based, so we can directly access the first 1Mb of	 * system memory (like under DOS4GW).	 */	return (void*)base;	}    /* Map the memory to a linear address using DPMI function 0x800 */    if ((linAddr = DPMI_mapPhysicalToLinear(base,limit)) == 0xFFFFFFFF) {	if (base >= 0x100000)	    return NULL;	/* If the linear address mapping fails but we are trying to	 * map an area in the first 1Mb of system memory, then we must	 * be running under a Windows or OS/2 DOS box. Under these	 * environments we can use the segment wrap around as a fallback	 * measure, as this does work properly.	 */	linAddr = base;	}    /* Now expand the default DS selector to 4Gb so we can access it */    if (!DPMI_setSelectorLimit(sregs.ds,0xFFFFFFFFUL))	return NULL;    /* Finally enable caching for the page tables that we just mapped in,     * since DOS4GW and PMODE/W create the page table entries without     * caching enabled which hurts the performance of the linear framebuffer     * as it disables write combining on Pentium Pro and above processors.     *     * For those processors cache disabling is better handled through the     * MTRR registers anyway (we can write combine a region but disable     * caching) so that MMIO register regions do not screw up.     */    if (DSBaseAddr == 0)	PM_adjustPageTables(linAddr,limit,isCached);    /* Now return the base address of the memory into the default DS */    return (void*)(linAddr - DSBaseAddr);}#if defined(PM386)/* Some DOS extender implementations do not directly support calling a * real mode procedure from protected mode. However we can simulate what * we need temporarily hooking the INT 6Ah vector with a small real mode * stub that will call our real mode code for us. */static uchar int6AHandler[] = {    0x00,0x00,0x00,0x00,        /*  __PMODE_callReal variable           */    0xFB,                       /*  sti                                 */    0x2E,0xFF,0x1E,0x00,0x00,   /*  call    [cs:__PMODE_callReal]       */    0xCF,                       /*  iretf                               */    };static uchar *crPtr = NULL; /* Pointer to of int 6A handler         */static uint crRSeg,crROff;  /* Real mode seg:offset of handler      */void PMAPI PM_callRealMode(uint seg,uint off, RMREGS *in,    RMSREGS *sregs){    uchar   *p;    uint    oldSeg,oldOff;    if (!crPtr) {	/* Allocate and copy the memory block only once */	crPtr = PM_allocRealSeg(sizeof(int6AHandler), &crRSeg, &crROff);	memcpy(crPtr,int6AHandler,sizeof(int6AHandler));	}    PM_setWord(crPtr,off);              /* Plug in address to call  */    PM_setWord(crPtr+2,seg);    p = PM_mapRealPointer(0,0x6A * 4);    oldOff = PM_getWord(p);             /* Save old handler address */    oldSeg = PM_getWord(p+2);    PM_setWord(p,crROff+4);             /* Hook 6A handler          */    PM_setWord(p+2,crRSeg);    PM_int86x(0x6A, in, in, sregs);     /* Call real mode code      */    PM_setWord(p,oldOff);               /* Restore old handler      */    PM_setWord(p+2,oldSeg);}#endif  /* PM386 */#endif  /* !REALMODE *//****************************************************************************REMARKS:Allocates a block of locked, physically contiguous memory. The memorymay be required to be below the 16Meg boundary.****************************************************************************/void * PMAPI PM_allocLockedMem(    uint size,    ulong *physAddr,    ibool contiguous,    ibool below16Meg){    uchar           *p,*roundedP;    uint            r_seg,r_off;    uint            roundedSize = (size + 4 + 0xFFF) & ~0xFFF;    PM_lockHandle   lh; /* Unused in DOS */#ifndef REALMODE    VXD_regs        regs;    /* If we have connected to our helper VxD in a Windows DOS box, use the     * helper VxD services to allocate the memory that we need.     */    if (VXD_version) {	memset(&regs,0,sizeof(regs));	regs.eax = API_NUM(PMHELP_ALLOCLOCKED);	regs.ebx = size;	regs.ecx = (ulong)physAddr;	regs.edx = contiguous | (below16Meg << 8);	_PM_VxDCall(&regs,_PM_VXD_off,_PM_VXD_sel);	return (void*)regs.eax;	}    /* If the memory is not contiguous, we simply need to allocate it     * using regular memory allocation services, and lock it down     * in memory.     *     * For contiguous memory blocks, the only way to guarantee contiguous physical     * memory addresses under DOS is to allocate the memory below the     * 1Meg boundary as real mode memory.     *     * Note that we must page align the memory block, and we also must     * keep track of the non-aligned pointer so we can properly free     * it later. Hence we actually allocate 4 bytes more than the     * size rounded up to the next 4K boundary.     */    if (!contiguous)	p = PM_malloc(roundedSize);    else#endif	p = PM_allocRealSeg(roundedSize,&r_seg,&r_off);    if (p == NULL)	return NULL;    roundedP = (void*)(((ulong)p + 0xFFF) & ~0xFFF);    *((ulong*)(roundedP + size)) = (ulong)p;    PM_lockDataPages(roundedP,size,&lh);    if ((*physAddr = PM_getPhysicalAddr(roundedP)) == 0xFFFFFFFF) {	PM_freeLockedMem(roundedP,size,contiguous);	return NULL;	}    /* Disable caching for the memory since it is probably a DMA buffer */#ifndef REALMODE    PM_adjustPageTables((ulong)roundedP,size-1,false);#endif    return roundedP;}/****************************************************************************REMARKS:Free a block of locked memory.****************************************************************************/void PMAPI PM_freeLockedMem(void *p,uint size,ibool contiguous){#ifndef REALMODE    VXD_regs        regs;    PM_lockHandle   lh; /* Unused in DOS */    if (!p)	return;    if (VXD_version) {	memset(&regs,0,sizeof(regs));	regs.eax = API_NUM(PMHELP_FREELOCKED);	regs.ebx = (ulong)p;	regs.ecx = size;	regs.edx = contiguous;	_PM_VxDCall(&regs,_PM_VXD_off,_PM_VXD_sel);	return;	}    PM_unlockDataPages(p,size,&lh);    if (!contiguous)	free(*((void**)((uchar*)p + size)));    else#endif	PM_freeRealSeg(*((void**)((char*)p + size)));}#ifndef REALMODE/****************************************************************************REMARKS:Allocates a new block of pages for the page block manager.****************************************************************************/static pageblock *PM_addNewPageBlock(void){    int         i,size;    pageblock   *newBlock;    char        *p,*next;    /* Allocate memory for the new page block, and add to head of list */    size = PAGES_PER_BLOCK * PM_PAGE_SIZE + (PM_PAGE_SIZE-1) + sizeof(pageblock);    if ((newBlock = PM_malloc(size)) == NULL)	return NULL;    newBlock->prev = NULL;    newBlock->next = pageBlocks;    if (pageBlocks)	pageBlocks->prev = newBlock;    pageBlocks = newBlock;    /* Initialise the page aligned free list for the page block */    newBlock->freeCount = PAGES_PER_BLOCK;    newBlock->freeList = p = (char*)(((ulong)(newBlock + 1) + (PM_PAGE_SIZE-1)) & ~(PM_PAGE_SIZE-1));    newBlock->freeListStart = newBlock->freeList;    newBlock->freeListEnd = p + (PAGES_PER_BLOCK-1) * PM_PAGE_SIZE;    for (i = 0; i < PAGES_PER_BLOCK; i++,p = next)	FREELIST_NEXT(p) = next = p + PM_PAGE_SIZE;    FREELIST_NEXT(p - PM_PAGE_SIZE) = NULL;    return newBlock;}#endif/****************************************************************************REMARKS:Allocates a page aligned and page sized block of memory****************************************************************************/void * PMAPI PM_allocPage(    ibool locked){#ifndef REALMODE    VXD_regs        regs;    pageblock       *block;    void            *p;    PM_lockHandle   lh; /* Unused in DOS */    /* Call the helper VxD for this service if we are running in a DOS box */    if (VXD_version) {	memset(&regs,0,sizeof(regs));	regs.eax = API_NUM(PMHELP_ALLOCPAGE);	regs.ebx = locked;	_PM_VxDCall(&regs,_PM_VXD_off,_PM_VXD_sel);	return (void*)regs.eax;	}    /* Scan the block list looking for any free blocks. Allocate a new     * page block if no free blocks are found.     */    for (block = pageBlocks; block != NULL; block = block->next) {	if (block->freeCount)	    break;	}    if (block == NULL && (block = PM_addNewPageBlock()) == NULL)	return NULL;    block->freeCount--;    p = block->freeList;    block->freeList = FREELIST_NEXT(p);    if (locked)	PM_lockDataPages(p,PM_PAGE_SIZE,&lh);    return p;#else    return NULL;#endif}/****************************************************************************REMARKS:Free a page aligned and page sized block of memory****************************************************************************/void PMAPI PM_freePage(    void *p){#ifndef REALMODE    VXD_regs    regs;    pageblock   *block;    /* Call the helper VxD for this service if we are running in a DOS box */    if (VXD_version) {	memset(&regs,0,sizeof(regs));	regs.eax = API_NUM(PMHELP_FREEPAGE);	regs.ebx = (ulong)p;	_PM_VxDCall(&regs,_PM_VXD_off,_PM_VXD_sel);	return;	}    /* First find the page block that this page belongs to */    for (block = pageBlocks; block != NULL; block = block->next) {	if (p >= block->freeListStart && p <= block->freeListEnd)	    break;	}    CHECK(block != NULL);    /* Now free the block by adding it to the free list */    FREELIST_NEXT(p) = block->freeList;    block->freeList = p;    if (++block->freeCount == PAGES_PER_BLOCK) {	/* If all pages in the page block are now free, free the entire	 * page block itself.	 */	if (block == pageBlocks) {	    /* Delete from head */	    pageBlocks = block->next;	    if (block->next)		block->next->prev = NULL;	    }	else {	    /* Delete from middle of list */	    CHECK(block->prev != NULL);	    block->prev->next = block->next;	    if (block->next)		block->next->prev = block->prev;	    }	PM_free(block);	}#else    (void)p;#endif}/*-------------------------------------------------------------------------*//* DOS Real Mode support.                                                  *//*-------------------------------------------------------------------------*/#ifdef REALMODE#ifndef MK_FP#define MK_FP(s,o)  ( (void far *)( ((ulong)(s) << 16) + \		    (ulong)(o) ))#endifvoid * PMAPI PM_mapRealPointer(uint r_seg,uint r_off){ return MK_FP(r_seg,r_off); }void * PMAPI PM_getBIOSPointer(void){    return MK_FP(0x40,0);}void * PMAPI PM_getA0000Pointer(void){    return MK_FP(0xA000,0);}void * PMAPI PM_mapPhysicalAddr(ulong base,ulong limit,ibool isCached){    uint sel = base >> 4;    uint off = base & 0xF;    limit = limit;    return MK_FP(sel,off);}void PMAPI PM_freePhysicalAddr(void *ptr,ulong limit){ ptr = ptr; }ulong PMAPI PM_getPhysicalAddr(void *p){    return ((((ulong)p >> 16) << 4) + (ushort)p);}ibool PMAPI PM_getPhysicalAddrRange(void *p,ulong length,ulong *physAddress){ return false; }void * PMAPI PM_mapToProcess(void *base,ulong limit){ return (void*)base; }void * PMAPI PM_allocRealSeg(uint size,uint *r_seg,uint *r_off){    /* Call malloc() to allocate the memory for us */    void *p = PM_malloc(size);    *r_seg = FP_SEG(p);    *r_off = FP_OFF(p);    return p;}void PMAPI PM_freeRealSeg(void *mem){    if (mem) PM_free(mem);}int PMAPI PM_int86(int intno, RMREGS *in, RMREGS *out){    return PM_int386(intno,in,out);}int PMAPI PM_int86x(int intno, RMREGS *in, RMREGS *out,    RMSREGS *sregs){    return PM_int386x(intno,in,out,sregs);}void PMAPI PM_availableMemory(ulong *physical,ulong *total){    PMREGS regs;    regs.h.ah = 0x48;    regs.x.bx = 0xFFFF;    PM_int86(0x21,&regs,&regs);    *physical = *total = regs.x.bx * 16UL;}#endif/*-------------------------------------------------------------------------*//* Phar Lap TNT DOS Extender support.                                      *//*-------------------------------------------------------------------------*/#ifdef TNT#include <pldos32.h>#include <pharlap.h>#include <hw386.h>static uchar *zeroPtr = NULL;void * PMAPI PM_getBIOSPointer(void){    if (!zeroPtr)	zeroPtr = PM_mapPhysicalAddr(0,0xFFFFF,true);    return (void*)(zeroPtr + 0x400);}void * PMAPI PM_getA0000Pointer(void){    static void *bankPtr;    if (!bankPtr)	bankPtr = PM_mapPhysicalAddr(0xA0000,0xFFFF,true);    return bankPtr;}void * PMAPI PM_mapPhysicalAddr(ulong base,ulong limit,ibool isCached){    CONFIG_INF  config;    ULONG       offset;    int         err;    ulong       baseAddr,baseOfs,newLimit;    VXD_regs    regs;    /* If we have connected to our helper VxD in a Windows DOS box, use     * the helper VxD services to map memory instead of the DPMI services.     * We do this because the helper VxD can properly disable caching     * where necessary, which we can only do directly here if we are     * running at ring 0 (ie: under real DOS).     */    if (VXD_version == -1)	PM_init();    if (VXD_version) {	memset(&regs,0,sizeof(regs));	regs.eax = API_NUM(PMHELP_MAPPHYS);	regs.ebx = base;	regs.ecx = limit;	regs.edx = isCached;	_PM_VxDCall(&regs,_PM_VXD_off,_PM_VXD_sel);	return (void*)regs.eax;	}    /* Round the physical address to a 4Kb boundary and the limit to a     * 4Kb-1 boundary before passing the values to TNT. If we round the     * physical address, then we also add an extra offset into the address     * that we return.     */    baseOfs = base & 4095;    baseAddr = base & ~4095;    newLimit = ((limit+baseOfs+1+4095) & ~4095)-1;    _dx_config_inf(&config, (UCHAR*)&config);    err = _dx_map_phys(config.c_ds_sel,baseAddr,(newLimit + 4095) / 4096,&offset);    if (err == 130) {	/* If the TNT function failed, we are running in a DPMI environment	 * and this function does not work. However we know how to handle	 * DPMI properly, so we use our generic DPMI functions to do	 * what the TNT runtime libraries can't.	 */	return DPMI_mapPhysicalAddr(base,limit,isCached);	}    if (err == 0)	return (void*)(offset + baseOfs);    return NULL;}void PMAPI PM_freePhysicalAddr(void *ptr,ulong limit){}ulong PMAPI PM_getPhysicalAddr(void *p){ return 0xFFFFFFFFUL; }ibool PMAPI PM_getPhysicalAddrRange(void *p,ulong length,ulong *physAddress){ return false; }void * PMAPI PM_mapToProcess(void *base,ulong limit){ return (void*)base; }void * PMAPI PM_mapRealPointer(uint r_seg,uint r_off){    if (!zeroPtr)	zeroPtr = PM_mapPhysicalAddr(0,0xFFFFF);    return (void*)(zeroPtr + MK_PHYS(r_seg,r_off));}void * PMAPI PM_allocRealSeg(uint size,uint *r_seg,uint *r_off){    USHORT  addr,t;    void    *p;    if (_dx_real_alloc((size + 0xF) >> 4,&addr,&t) != 0)	return 0;    *r_seg = addr;                  /* Real mode segment address    */    *r_off = 0;                     /* Real mode segment offset     */    p = PM_mapRealPointer(*r_seg,*r_off);    _PM_addRealModeBlock(p,addr);    return p;}void PMAPI PM_freeRealSeg(void *mem){    if (mem) _dx_real_free(_PM_findRealModeBlock(mem));}#define INDPMI(reg)     rmregs.reg = regs->reg#define OUTDPMI(reg)    regs->reg = rmregs.regvoid PMAPI DPMI_int86(int intno, DPMI_regs *regs){    SWI_REGS    rmregs;    memset(&rmregs, 0, sizeof(rmregs));    INDPMI(eax); INDPMI(ebx); INDPMI(ecx); INDPMI(edx); INDPMI(esi); INDPMI(edi);    _dx_real_int(intno,&rmregs);    OUTDPMI(eax); OUTDPMI(ebx); OUTDPMI(ecx); OUTDPMI(edx); OUTDPMI(esi); OUTDPMI(edi);    regs->flags = rmregs.flags;}#define IN(reg)     rmregs.reg = in->e.reg#define OUT(reg)    out->e.reg = rmregs.regint PMAPI PM_int86(int intno, RMREGS *in, RMREGS *out){    SWI_REGS    rmregs;    memset(&rmregs, 0, sizeof(rmregs));    IN(eax); IN(ebx); IN(ecx); IN(edx); IN(esi); IN(edi);    _dx_real_int(intno,&rmregs);    OUT(eax); OUT(ebx); OUT(ecx); OUT(edx); OUT(esi); OUT(edi);    out->x.cflag = rmregs.flags & 0x1;    return out->x.ax;}int PMAPI PM_int86x(int intno, RMREGS *in, RMREGS *out,    RMSREGS *sregs){    SWI_REGS    rmregs;    memset(&rmregs, 0, sizeof(rmregs));    IN(eax); IN(ebx); IN(ecx); IN(edx); IN(esi); IN(edi);    rmregs.es = sregs->es;    rmregs.ds = sregs->ds;    _dx_real_int(intno,&rmregs);    OUT(eax); OUT(ebx); OUT(ecx); OUT(edx); OUT(esi); OUT(edi);    sregs->es = rmregs.es;

⌨️ 快捷键说明

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