Hi, 16.04.2012 02:52, Bart Oldeman wrote: > I had a good look at your EMS patch and applied some of the more > innocent portions And you are working around of the lack of git: I would otherwise send it as a patch-set myself. :)
> -- but there is something wrong with the changed > msdos.c interface: from what I see: > > before: > the EMS page frame was unmapped (mapped to lowram), > > with your patch: > msdos.c reserves 4 EMS pages (=64k), and then maps pages 0-3 physical > to 0-3 logical EMS memory (instead of lowram). The problem is that > emm_allocate_handle can fail and return EMM_ERROR which is not checked > in msdos.c. This happens e.g. when you run the Turbo C++ 1.01 IDE and > shell out to DOS: all (8M of) EMS memory is allocated by Turbo C++ and > msdos.c can't allocate an extra 64K. > > could you explain? I think unmapping can be done by mapping 0-3 > physical to 0xffff (4 times) logical. Well, that would be a bit of a hack. Even though we all know how dosemu works, some other EMM may probably mark such a pages not-present, or, if you happened to have the real EMS board and XT (you don't!:)), there can probably be no physical ram in that region. Even more worrysome is that even if you are going to allocate a handle with 0 pages on it, some DOS program will eat all the handles before you do that, just like now it eats all the pages. It would be better to stay compatible with the EMS specs, and also there was the DOS port of msdos.c somewhere... :P Fortunately, there is a better way of solving this, also japheth have suggested it in the past. With the attached (completely untested) patch I hope the problem is no more. This patch is against svn, it adds the remaining bits of the previous one, plus the fix. The MSDOS_EATS_EMS define is only needed for the DOS port, doesn't seem to hurt, but you can decide removing it.
Index: src/include/memory.h =================================================================== --- src/include/memory.h (revision 2067) +++ src/include/memory.h (working copy) @@ -262,16 +262,9 @@ #define LOWMEM_READ_DWORD(addr) UNIX_READ_DWORD(LOWMEM(addr)) #define LOWMEM_WRITE_DWORD(addr, val) UNIX_WRITE_DWORD(LOWMEM(addr), val) -/* generic lowmem addresses are the ones below 1Mb, that are - * not in the EMS frame, hardware or video memory. We can _safely_ - * add lowmem_base to those. */ -#define IS_GENERIC_LOWMEM_ADDR(addr) \ - ((addr) <= 0x9fffc || ((addr) >= 0xf4000 && (addr) <= 0xffffc)) - static inline void *LINEAR2UNIX(unsigned int addr) { - return IS_GENERIC_LOWMEM_ADDR(addr) ? LOWMEM(addr) : - dosaddr_to_unixaddr(addr); + return dosaddr_to_unixaddr(addr); } #define READ_BYTE(addr) UNIX_READ_BYTE(LINEAR2UNIX(addr)) Index: src/include/emm.h =================================================================== --- src/include/emm.h (revision 2067) +++ src/include/emm.h (working copy) @@ -11,7 +11,6 @@ #define DOSEMU_EMS_DRIVER_VERSION 3 #define MAX_HANDLES 255 /* must fit in a byte */ -#define EMS_FRAME_SIZE (EMM_MAX_PHYS * EMM_PAGE_SIZE) /* this is in EMS pages, which MAX_EMS (defined in Makefile) is in K */ #define MAX_EMM (config.ems_size >> 4) #ifndef PAGE_SIZE @@ -21,16 +20,19 @@ #define EMM_UMA_MAX_PHYS 12 #define EMM_UMA_STD_PHYS 4 #define EMM_CNV_MAX_PHYS 24 -#define EMM_MAX_PHYS (EMM_UMA_MAX_PHYS + EMM_CNV_MAX_PHYS) +#define EMM_MAX_PHYS (EMM_UMA_MAX_PHYS + EMM_CNV_MAX_PHYS) #define EMM_MAX_SAVED_PHYS EMM_UMA_STD_PHYS #define NULL_HANDLE 0xffff #define NULL_PAGE 0xffff #define PAGE_MAP_SIZE(np) (sizeof(u_short) * 2 * (np)) #ifndef __ASSEMBLER__ -void emm_get_map_registers(char *ptr); -void emm_set_map_registers(char *ptr); -void emm_unmap_all(void); +/* export a few EMS functions to DPMI so it doesn't have to call interrupt */ +int emm_allocate_std_pages(int pages_needed); +int emm_save_handle_state(int handle); +int emm_restore_handle_state(int handle); +int emm_map_unmap_multi(const u_short *array, int handle, int map_len); +/* end of DPMI/EMS API */ void ems_init(void); void ems_reset(void); Index: src/dosext/dpmi/msdos.c =================================================================== --- src/dosext/dpmi/msdos.c (revision 2067) +++ src/dosext/dpmi/msdos.c (working copy) @@ -38,6 +38,10 @@ #include "doshelpers.h" #endif +#define MSDOS_EATS_EMS 0 +#if MSDOS_EATS_EMS +#define MSDOS_EMS_PAGES 4 +#endif #define TRANS_BUFFER_SEG EMM_SEGMENT #define EXEC_SEG (MSDOS_CLIENT.lowmem_seg + EXEC_Para_ADD) @@ -53,7 +57,35 @@ static int msdos_client_num = 0; static struct msdos_struct msdos_client[DPMI_MAX_CLIENTS]; +static int ems_handle_pri, ems_handle_bkp; +void msdos_setup(void) +{ +#if MSDOS_EATS_EMS + static const u_short ems_map_simple[MSDOS_EMS_PAGES * 2] = + { 0, 0, 1, 1, 2, 2, 3, 3 }; + ems_handle_pri = emm_allocate_std_pages(MSDOS_EMS_PAGES); +#else + ems_handle_pri = emm_allocate_std_pages(0); +#endif + ems_handle_bkp = emm_allocate_std_pages(0); + if (ems_handle_pri == -1 || ems_handle_bkp == -1) { + error("DPMI: unable to allocate EMM handles!\n"); + config.exitearly = 1; + return; + } +#if MSDOS_EATS_EMS + emm_save_handle_state(ems_handle_bkp); + emm_map_unmap_multi(ems_map_simple, ems_handle_pri, MSDOS_EMS_PAGES); + emm_save_handle_state(ems_handle_pri); + emm_restore_handle_state(ems_handle_bkp); +#else + /* dosemu-specific optimization to save 64K of EMS: we know that + * at this point we have a clean'n'good UMB mapping, so just use it. */ + emm_save_handle_state(ems_handle_pri); +#endif +} + void msdos_init(int is_32, unsigned short mseg, unsigned short psp) { unsigned short envp; @@ -138,15 +170,15 @@ if (MSDOS_CLIENT.ems_frame_mapped) return; MSDOS_CLIENT.ems_frame_mapped = 1; - emm_get_map_registers(MSDOS_CLIENT.ems_map_buffer); - emm_unmap_all(); + emm_save_handle_state(ems_handle_bkp); + emm_restore_handle_state(ems_handle_pri); } static void restore_ems_frame(void) { if (!MSDOS_CLIENT.ems_frame_mapped) return; - emm_set_map_registers(MSDOS_CLIENT.ems_map_buffer); + emm_restore_handle_state(ems_handle_bkp); MSDOS_CLIENT.ems_frame_mapped = 0; } Index: src/dosext/dpmi/dpmi.c =================================================================== --- src/dosext/dpmi/dpmi.c (revision 2067) +++ src/dosext/dpmi/dpmi.c (working copy) @@ -2958,6 +2958,9 @@ if (SetSelector(dpmi_sel32, DPMI_sel_code_start - mem_base, DPMI_SEL_OFF(DPMI_sel_code_end)-1, 1, MODIFY_LDT_CONTENTS_CODE, 0, 0, 0, 0)) goto err; + + if (config.pm_dos_api) + msdos_setup(); return; err: Index: src/dosext/dpmi/msdos.h =================================================================== --- src/dosext/dpmi/msdos.h (revision 2067) +++ src/dosext/dpmi/msdos.h (working copy) @@ -34,11 +34,11 @@ unsigned short user_psp_sel; unsigned short current_psp; unsigned short lowmem_seg; - char ems_map_buffer[PAGE_MAP_SIZE(EMM_UMA_STD_PHYS)]; int ems_frame_mapped; dpmi_pm_block mem_map[MSDOS_MAX_MEM_ALLOCS]; }; +extern void msdos_setup(void); extern void msdos_init(int is_32, unsigned short mseg, unsigned short psp); extern void msdos_done(void); Index: src/dosext/misc/emm.c =================================================================== --- src/dosext/misc/emm.c (revision 2067) +++ src/dosext/misc/emm.c (working copy) @@ -40,8 +40,8 @@ * In contrast to some of the comments (Yes, _I_ know the adage about that...) * we appear to be supporting EMS 4.0, not 3.2. The following EMS 4.0 * functions are not supported (yet): 0x4f (partial page map functions), - * 0x55 (map pages and jump), and 0x56 (map pages and call). OS handle - * support is missing, and raw page size is 16k (instead of 4k). Other than + * 0x55 (map pages and jump), and 0x56 (map pages and call), + * and raw page size is 16k (instead of 4k). Other than * that, EMS 4.0 support appears complete. * * /REMARK @@ -306,8 +306,7 @@ return addr; } -static int -emm_allocate_handle(int pages_needed) +static int emm_allocate_handle(int pages_needed) { int i, j; void *obj; @@ -351,8 +350,7 @@ return (EMM_ERROR); } -static boolean_t -emm_deallocate_handle(int handle) +static boolean_t emm_deallocate_handle(int handle) { int numpages, i; void *object; @@ -369,7 +367,8 @@ object = handle_info[handle].object; destroy_memory_object(object,numpages*EMM_PAGE_SIZE); handle_info[handle].numpages = 0; - handle_info[handle].active = 0; + if (handle_info[handle].active == 1) + handle_info[handle].active = 0; handle_info[handle].object = NULL; CLEAR_HANDLE_NAME(handle_info[i].name); handle_total--; @@ -398,13 +397,6 @@ PROT_READ | PROT_WRITE | PROT_EXEC, base); } -void emm_unmap_all() -{ - if (!config.ems_size) - return; - _do_unmap_page(PHYS_PAGE_ADDR(0), EMS_FRAME_SIZE); -} - static boolean_t __map_page(int physical_page) { @@ -446,7 +438,7 @@ base = PHYS_PAGE_ADDR(physical_page); _do_unmap_page(base, EMM_PAGE_SIZE); - + return (TRUE); } @@ -488,8 +480,11 @@ if (handle_info[handle].numpages <= logical_page) return (FALSE); +#if 0 +/* no need to unmap before mapping */ if (emm_map[physical_page].handle != NULL_HANDLE) unmap_page(physical_page); +#endif base = PHYS_PAGE_ADDR(physical_page); logical = handle_info[handle].object + logical_page * EMM_PAGE_SIZE; @@ -516,8 +511,7 @@ return (handle_info[handle].numpages); } -static int -emm_save_handle_state(int handle) +int emm_save_handle_state(int handle) { int i; @@ -535,8 +529,7 @@ return 0; } -static int -emm_restore_handle_state(int handle) +int emm_restore_handle_state(int handle) { int i; @@ -559,7 +552,7 @@ } static int -do_map_unmap(state_t * state, int handle, int physical_page, int logical_page) +do_map_unmap(int handle, int physical_page, int logical_page) { CHECK_OS_HANDLE(handle); @@ -568,15 +561,13 @@ (handle_info[handle].active == 0)) { E_printf("Invalid Handle handle=%x, active=%d\n", handle, handle_info[handle].active); - SETHIGH(&(state->eax), EMM_INV_HAN); - return (UNCHANGED); + return EMM_INV_HAN; } if ((physical_page < 0) || (physical_page >= phys_pages)) { - SETHIGH(&(state->eax), EMM_ILL_PHYS); E_printf("Invalid Physical Page physical_page=%x\n", physical_page); - return (UNCHANGED); + return EMM_ILL_PHYS; } if (logical_page == 0xffff) { @@ -585,17 +576,15 @@ } else { if (logical_page >= handle_info[handle].numpages) { - SETHIGH(&(state->eax), EMM_LOG_OUT_RAN); E_printf("Logical page too high logical_page=%d, numpages=%d\n", logical_page, handle_info[handle].numpages); - return (UNCHANGED); + return EMM_LOG_OUT_RAN; } E_printf("EMS: do_map_unmap is mapping\n"); map_page(handle, physical_page, logical_page); } - SETHIGH(&(state->eax), EMM_NO_ERR); - return (TRUE); + return EMM_NO_ERR; } static inline int @@ -621,10 +610,25 @@ SETHIGH(&(state->eax), EMM_NO_ERR); } +int emm_map_unmap_multi(const u_short *array, int handle, int map_len) +{ + char ret = EMM_NO_ERR; + int i, phys, log; + for (i = 0; i < map_len; i++) { + log = array[i * 2]; + phys = array[i * 2 + 1]; + Kdebug0((dbg_fd, "loop: 0x%x 0x%x \n", log, phys)); + ret = do_map_unmap(handle, phys, log); + if (ret != EMM_NO_ERR) + break; + } + return ret; +} + static void map_unmap_multiple(state_t * state) { - + char ret; Kdebug0((dbg_fd, "map_unmap_multiple %d called\n", (int) LOW(state->eax))); @@ -632,20 +636,14 @@ case MULT_LOGPHYS:{ /* 0 */ int handle = WORD(state->edx); int map_len = WORD(state->ecx); - int i = 0, phys, log; u_short *array = (u_short *) Addr(state, ds, esi); Kdebug0((dbg_fd, "...using mult_logphys method, " "handle %d, map_len %d, array @ %p\n", handle, map_len, array)); - for (i = 0; i < map_len; i++) { - log = *(u_short *) array++; - phys = *(u_short *) array++; - - Kdebug0((dbg_fd, "loop: 0x%x 0x%x \n", log, phys)); - do_map_unmap(state, handle, phys, log); - } + ret = emm_map_unmap_multi(array, handle, map_len); + SETHIGH(&(state->eax), ret); break; } @@ -654,14 +652,15 @@ int map_len = WORD(state->ecx); int i = 0, phys, log, seg; u_short *array = (u_short *) Addr(state, ds, esi); + u_short *array2 = malloc(PAGE_MAP_SIZE(map_len)); Kdebug0((dbg_fd, "...using mult_logseg method, " "handle %d, map_len %d, array @ %p\n", handle, map_len, array)); for (i = 0; i < map_len; i++) { - log = *(u_short *) array; - seg = *(u_short *) (array + 1); + log = array[i * 2]; + seg = array[i * 2 + 1]; phys = SEG_TO_PHYS(seg); @@ -669,17 +668,19 @@ log, seg, phys)); if (phys == -1) { + free(array2); SETHIGH(&(state->eax), EMM_ILL_PHYS); return; } else { - do_map_unmap(state, handle, phys, log); - SETHIGH(&(state->eax), EMM_NO_ERR); + array2[i * 2] = log; + array2[i * 2 + 1] = phys; } - array++; - array++; } + ret = emm_map_unmap_multi(array2, handle, map_len); + SETHIGH(&(state->eax), ret); + free(array2); break; } @@ -1212,7 +1213,7 @@ return (UNCHANGED); } } - else + else { Kdebug1((dbg_fd, "bios_emm: Get Hardware Info/Raw Pages - Denied\n")); SETHIGH(&(state->eax), 0xa4); @@ -1220,6 +1221,15 @@ } } +int emm_allocate_std_pages(int pages_needed) +{ + int handle = emm_allocate_handle(pages_needed); + if (handle == EMM_ERROR) + return EMM_ERROR; + handle_info[handle].active = 0xff; + return handle; +} + static int allocate_std_pages(state_t * state) { @@ -1229,7 +1239,7 @@ Kdebug1((dbg_fd, "bios_emm: Get Handle and Standard Allocate pages = 0x%x\n", pages_needed)); - if ((handle = emm_allocate_handle(pages_needed)) == EMM_ERROR) { + if ((handle = emm_allocate_std_pages(pages_needed)) == EMM_ERROR) { SETHIGH(&(state->eax), emm_error); return (UNCHANGED); } @@ -1241,7 +1251,7 @@ return 0; } -void emm_get_map_registers(char *ptr) +static void emm_get_map_registers(char *ptr) { u_short *buf = (u_short *)ptr; int i; @@ -1257,7 +1267,7 @@ } } -void emm_set_map_registers(char *ptr) +static void emm_set_map_registers(char *ptr) { u_short *buf = (u_short *)ptr; int i; @@ -1528,8 +1538,10 @@ int physical_page = LOW(state->eax); int logical_page = WORD(state->ebx); int handle = WORD(state->edx); + char ret; - do_map_unmap(state, handle, physical_page, logical_page); + ret = do_map_unmap(handle, physical_page, logical_page); + SETHIGH(&(state->eax), ret); break; } case DEALLOCATE_HANDLE:{ /* 0x45 */ @@ -1815,13 +1827,17 @@ handle_info[sh_base].active = 0; } - /* should set up OS handle here */ - handle_info[OS_HANDLE].numpages = 0; - handle_info[OS_HANDLE].object = 0; - handle_info[OS_HANDLE].active = 1; + /* set up OS handle here */ + handle_info[OS_HANDLE].numpages = config.ems_cnv_pages; + handle_info[OS_HANDLE].object = LOWMEM(cnv_start_seg << 4); + handle_info[OS_HANDLE].active = 0xff; for (j = 0; j < saved_phys_pages; j++) { handle_info[OS_HANDLE].saved_mappings_logical[j] = NULL_PAGE; } + for (sh_base = 0; sh_base < config.ems_cnv_pages; sh_base++) { + emm_map[sh_base + cnv_pages_start].handle = OS_HANDLE; + emm_map[sh_base + cnv_pages_start].logical_page = sh_base; + } handle_total = 1; SET_HANDLE_NAME(handle_info[OS_HANDLE].name, "SYSTEM "); Index: src/emu.c =================================================================== --- src/emu.c (revision 2067) +++ src/emu.c (working copy) @@ -453,8 +453,10 @@ loopstep_run_vm86(); } - sync(); - fprintf(stderr, "Not a good day to die!!!!!\n"); + if (fatalerr) { + sync(); + fprintf(stderr, "Not a good day to die!!!!!\n"); + } leavedos(99); return 0; /* just to make gcc happy */ } Index: src/base/init/memcheck.c =================================================================== --- src/base/init/memcheck.c (revision 2067) +++ src/base/init/memcheck.c (working copy) @@ -206,17 +206,17 @@ return &mem_base[addr]; map_char = mem_map[addr/GRAN_SIZE]; /* Not EMS, Hardware, or Video */ - if (map_char == 'E' || map_char == 'h' || map_char == 'v') +// if (map_char == 'E' || map_char == 'h' || map_char == 'v') return &mem_base[addr]; // FIXTHIS ! - return LOWMEM(addr); +// return LOWMEM(addr); } void *lowmemp(const void *ptr) { unsigned char map_char; uintptr_t addr = (unsigned char *)ptr - mem_base; - if (IS_GENERIC_LOWMEM_ADDR(addr)) - return LOWMEM(addr); +// if (IS_GENERIC_LOWMEM_ADDR(addr)) +// return LOWMEM(addr); if (addr >= MEM_SIZE) return (void *)ptr; map_char = mem_map[addr/GRAN_SIZE]; Index: src/arch/linux/debugger/dosdebug.c =================================================================== --- src/arch/linux/debugger/dosdebug.c (revision 2067) +++ src/arch/linux/debugger/dosdebug.c (working copy) @@ -190,7 +190,7 @@ if (n >0) { if ((p=strchr(buf,1))!=NULL) n=p-buf; write(1, buf, n); - if (p!=NULL) exit(0); +// if (p!=NULL) exit(0); } if (n == 0) exit(1);
------------------------------------------------------------------------------ For Developers, A Lot Can Happen In A Second. Boundary is the first to Know...and Tell You. Monitor Your Applications in Ultra-Fine Resolution. Try it FREE! http://p.sf.net/sfu/Boundary-d2dvs2
_______________________________________________ Dosemu-devel mailing list Dosemu-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/dosemu-devel