/* * (C) Copyright 1992, ..., 2007 the "DOSEMU-Development-Team". * * for details see file COPYING.DOSEMU in the DOSEMU distribution */ /* * Robert Sanders, started 3/1/93 * * Hans Lermen, moved 'mapping' to generic mapping drivers, 2000/02/02 * */ #include #include #include #include "memory.h" #include "emu.h" #include "hma.h" #include "mapping.h" #include "bios.h" #include "utilities.h" #include "dos2linux.h" #include "cpu-emu.h" #define HMAAREA 0x100000 unsigned char *ext_mem_base = NULL; void HMA_MAP(int HMA) { void *ipc_return; /* Note: MAPPING_HMA is magic, dont be confused by src==dst==HMAAREA here */ off_t src = HMA ? HMAAREA : 0; x_printf("Entering HMA_MAP with HMA=%d\n", HMA); if (munmap_mapping(MAPPING_HMA, &mem_base[HMAAREA], HMASIZE) < 0) { x_printf("HMA: Detaching HMAAREA unsuccessful: %s\n", strerror(errno)); leavedos(48); } x_printf("HMA: detached at %#x\n", HMAAREA); ipc_return = alias_mapping(MAPPING_HMA, HMAAREA, HMASIZE, PROT_READ | PROT_WRITE | PROT_EXEC, LOWMEM(src)); if (ipc_return == MAP_FAILED) { x_printf("HMA: Mapping HMA to HMAAREA %#x unsuccessful: %s\n", HMAAREA, strerror(errno)); leavedos(47); } x_printf("HMA: mapped to %p\n", ipc_return); } void set_a20(int enableHMA) { if (a20 == enableHMA) { g_printf("WARNING: redundant %s of A20!\n", enableHMA ? "enabling" : "disabling"); return; } /* to turn the A20 on, one must unmap the "wrapped" low page, and * map in the real HMA memory. to turn it off, one must unmap the HMA * and make FFFF:xxxx addresses wrap to the low page. */ HMA_MAP(enableHMA); a20 = enableHMA; } void HMA_init(void) { /* initially, no HMA */ HMA_MAP(0); a20 = 0; if (config.ext_mem) { ext_mem_base = mmap_mapping(MAPPING_EXTMEM | MAPPING_SCRATCH, (void*)-1, EXTMEM_SIZE, PROT_READ | PROT_WRITE, 0); x_printf("Ext.Mem of size 0x%x at %p\n", EXTMEM_SIZE, ext_mem_base); memcheck_addtype('x', "Extended memory (HMA+XMS)"); memcheck_reserve('x', LOWMEM_SIZE, HMASIZE + EXTMEM_SIZE); } } void hma_exit(void) { } void extmem_copy(unsigned dst, unsigned src, unsigned len) { unsigned slen, dlen, clen, copied = 0; unsigned s, d, edge = LOWMEM_SIZE + HMASIZE; unsigned char *ps = NULL; while ((clen = len - copied) > 0) { slen = clen; s = src + copied; if (s >= edge) ps = &ext_mem_base[s - edge]; else if (s + slen > edge) slen = edge - s; dlen = clen; d = dst + copied; if (d < edge && d + dlen > edge) dlen = edge - d; clen = min(slen, dlen); x_printf("INT15: copy 0x%x bytes from %#x to %#x%s\n", clen, s, d, clen != len ? " (split)" : ""); if (d < edge) { if (s < edge) memmove_dos2dos(d, s, clen); else memcpy_2dos(d, ps, clen); e_invalidate(d, clen); } else { unsigned char *pd = &ext_mem_base[d - edge]; if (s < edge) memcpy_2unix(pd, s, clen); else memmove(pd, ps, clen); } copied += clen; } }