From e54d4d15c4765407b26fe9d9080b60a5a76fad10 Mon Sep 17 00:00:00 2001 From: Ove Kaaven Date: Sat, 22 May 1999 10:40:15 +0000 Subject: [PATCH] Added MZ_Current() (returns current LPDOSTASK) and DOSVM_Wait() (DOSVM idle message loop), and fields hConInput and hConOutput. --- include/dosexe.h | 4 +- loader/dos/dosvm.c | 210 ++++++++++++++++++++++---------------------- loader/dos/module.c | 41 ++++++--- 3 files changed, 140 insertions(+), 115 deletions(-) diff --git a/include/dosexe.h b/include/dosexe.h index 1ca0ab7ad52..5e86bae8c27 100644 --- a/include/dosexe.h +++ b/include/dosexe.h @@ -30,7 +30,7 @@ typedef struct _DOSTASK { HMODULE16 hModule; char mm_name[128]; int mm_fd; - HANDLE hReadPipe,hXPipe; + HANDLE hReadPipe,hXPipe,hConInput,hConOutput; int read_pipe,write_pipe; pid_t task; int sig_sent; @@ -67,7 +67,9 @@ extern BOOL MZ_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmdline, LPCSTR LPSECURITY_ATTRIBUTES psa, LPSECURITY_ATTRIBUTES tsa, BOOL inherit, LPSTARTUPINFOA startup, LPPROCESS_INFORMATION info ); +extern LPDOSTASK MZ_Current( void ); extern int DOSVM_Enter( PCONTEXT context ); +extern void DOSVM_Wait( int read_pipe, HANDLE hObject ); extern void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,void*), void *data ); extern void DOSVM_PIC_ioport_out( WORD port, BYTE val ); extern void DOSVM_SetTimer( unsigned ticks ); diff --git a/loader/dos/dosvm.c b/loader/dos/dosvm.c index c50ca2489b2..65d8d8a5d93 100644 --- a/loader/dos/dosvm.c +++ b/loader/dos/dosvm.c @@ -167,12 +167,10 @@ static void DOSVM_SendQueuedEvents(PCONTEXT context, LPDOSTASK lpDosTask) void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,void*), void *data) { - TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); - NE_MODULE *pModule = NE_GetPtr( pTask->hModule ); + LPDOSTASK lpDosTask = MZ_Current(); LPDOSEVENT event, cur, prev; - GlobalUnlock16( GetCurrentTask() ); - if (pModule && pModule->lpDosTask) { + if (lpDosTask) { event = malloc(sizeof(DOSEVENT)); if (!event) { ERR_(int)("out of memory allocating event entry\n"); @@ -183,20 +181,20 @@ void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,v /* insert event into linked list, in order *after* * all earlier events of higher or equal priority */ - cur = pModule->lpDosTask->pending; prev = NULL; + cur = lpDosTask->pending; prev = NULL; while (cur && cur->priority<=priority) { prev = cur; cur = cur->next; } event->next = cur; if (prev) prev->next = event; - else pModule->lpDosTask->pending = event; + else lpDosTask->pending = event; /* get dosmod's attention to the new event, except for irq==0 where we already have it */ - if (irq && !pModule->lpDosTask->sig_sent) { + if (irq && !lpDosTask->sig_sent) { TRACE_(int)("new event queued, signalling dosmod\n"); - kill(pModule->lpDosTask->task,SIGUSR2); - pModule->lpDosTask->sig_sent++; + kill(lpDosTask->task,SIGUSR2); + lpDosTask->sig_sent++; } else { TRACE_(int)("new event queued\n"); } @@ -222,6 +220,7 @@ static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig, CV; #undef CP if (fnINSTR_EmulateInstruction) ret=fnINSTR_EmulateInstruction(&sigcontext); + else ERR_(module)("fnINSTR_EmulateInstruction is not initialized!\n"); #define CP(x,y) VM86->regs.x = y##_sig(&sigcontext) CV; #undef CP @@ -334,24 +333,53 @@ void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg) } } +void DOSVM_Wait( int read_pipe, HANDLE hObject ) +{ + LPDOSTASK lpDosTask = MZ_Current(); + MSG msg; + DWORD waitret; + BOOL got_msg = FALSE; + + do { + /* check for messages (waste time before the response check below) */ + while (PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) { + /* got a message */ + DOSVM_ProcessMessage(lpDosTask,&msg); + /* we don't need a TranslateMessage here */ + DispatchMessageA(&msg); + got_msg = TRUE; + } + if (read_pipe == -1) { + if (got_msg) break; + } else { + fd_set readfds; + struct timeval timeout={0,0}; + /* quick check for response from dosmod + * (faster than doing the full blocking wait, if data already available) */ + FD_ZERO(&readfds); FD_SET(read_pipe,&readfds); + if (select(read_pipe+1,&readfds,NULL,NULL,&timeout)>0) + break; + } + /* check for data from win32 console device */ + + /* nothing yet, block while waiting for something to do */ + waitret=MsgWaitForMultipleObjects(1,&hObject,FALSE,INFINITE,QS_ALLINPUT); + if (waitret==(DWORD)-1) { + ERR_(module)("dosvm wait error=%ld\n",GetLastError()); + } + if (read_pipe != -1) { + if (waitret==WAIT_OBJECT_0) break; + } + } while (TRUE); +} + int DOSVM_Enter( PCONTEXT context ) { - TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); - NE_MODULE *pModule = NE_GetPtr( pTask->hModule ); - LPDOSTASK lpDosTask; + LPDOSTASK lpDosTask = MZ_Current(); struct vm86plus_struct VM86; int stat,len,sig; - DWORD waitret; - MSG msg; - fd_set readfds; - struct timeval timeout={0,0}; - GlobalUnlock16( GetCurrentTask() ); - if (!pModule) { - ERR_(module)("No task is currently active!\n"); - return -1; - } - if (!(lpDosTask=pModule->lpDosTask)) { + if (!lpDosTask) { /* MZ_CreateProcess or MZ_AllocDPMITask should have been called first */ ERR_(module)("dosmod has not been initialized!"); return -1; @@ -390,25 +418,8 @@ int DOSVM_Enter( PCONTEXT context ) ERR_(module)("dosmod sync lost, errno=%d\n",errno); return -1; } - do { - /* check for messages (waste time before the response check below) */ - while (PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) { - /* got a message */ - DOSVM_ProcessMessage(lpDosTask,&msg); - /* we don't need a TranslateMessage here */ - DispatchMessageA(&msg); - } - /* quick check for response from dosmod - * (faster than doing the full blocking wait, if data already available) */ - FD_ZERO(&readfds); FD_SET(lpDosTask->read_pipe,&readfds); - if (select(lpDosTask->read_pipe+1,&readfds,NULL,NULL,&timeout)>0) - break; - /* nothing yet, block while waiting for something to do */ - waitret=MsgWaitForMultipleObjects(1,&(lpDosTask->hReadPipe),FALSE,INFINITE,QS_ALLINPUT); - if (waitret==(DWORD)-1) { - ERR_(module)("dosvm wait error=%ld\n",GetLastError()); - } - } while (waitret!=WAIT_OBJECT_0); + /* wait for response, doing other things in the meantime */ + DOSVM_Wait(lpDosTask->read_pipe, lpDosTask->hReadPipe); /* read response */ while (1) { if ((len=read(lpDosTask->read_pipe,&stat,sizeof(stat)))==sizeof(stat)) break; @@ -453,29 +464,27 @@ int DOSVM_Enter( PCONTEXT context ) void DOSVM_PIC_ioport_out( WORD port, BYTE val) { - TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); - NE_MODULE *pModule = NE_GetPtr( pTask->hModule ); + LPDOSTASK lpDosTask = MZ_Current(); LPDOSEVENT event; - GlobalUnlock16( GetCurrentTask() ); - if (pModule && pModule->lpDosTask) { + if (lpDosTask) { if ((port==0x20) && (val==0x20)) { - if (pModule->lpDosTask->current) { + if (lpDosTask->current) { /* EOI (End Of Interrupt) */ TRACE_(int)("received EOI for current IRQ, clearing\n"); - event = pModule->lpDosTask->current; - pModule->lpDosTask->current = event->next; + event = lpDosTask->current; + lpDosTask->current = event->next; if (event->relay) - (*event->relay)(pModule->lpDosTask,NULL,event->data); + (*event->relay)(lpDosTask,NULL,event->data); free(event); - if (pModule->lpDosTask->pending && - !pModule->lpDosTask->sig_sent) { + if (lpDosTask->pending && + !lpDosTask->sig_sent) { /* another event is pending, which we should probably * be able to process now, so tell dosmod about it */ TRACE_(int)("another event pending, signalling dosmod\n"); - kill(pModule->lpDosTask->task,SIGUSR2); - pModule->lpDosTask->sig_sent++; + kill(lpDosTask->task,SIGUSR2); + lpDosTask->sig_sent++; } } else { WARN_(int)("EOI without active IRQ\n"); @@ -488,65 +497,59 @@ void DOSVM_PIC_ioport_out( WORD port, BYTE val) void DOSVM_SetTimer( unsigned ticks ) { - TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); - NE_MODULE *pModule = NE_GetPtr( pTask->hModule ); - int stat=DOSMOD_SET_TIMER; - struct timeval tim; + LPDOSTASK lpDosTask = MZ_Current(); + int stat=DOSMOD_SET_TIMER; + struct timeval tim; - GlobalUnlock16( GetCurrentTask() ); - if (pModule&&pModule->lpDosTask) { - /* the PC clocks ticks at 1193180 Hz */ - tim.tv_sec=0; - tim.tv_usec=((unsigned long long)ticks*1000000)/1193180; - /* sanity check */ - if (!tim.tv_usec) tim.tv_usec=1; + if (lpDosTask) { + /* the PC clocks ticks at 1193180 Hz */ + tim.tv_sec=0; + tim.tv_usec=((unsigned long long)ticks*1000000)/1193180; + /* sanity check */ + if (!tim.tv_usec) tim.tv_usec=1; - if (write(pModule->lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { - ERR_(module)("dosmod sync lost, errno=%d\n",errno); - return; + if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { + ERR_(module)("dosmod sync lost, errno=%d\n",errno); + return; + } + if (write(lpDosTask->write_pipe,&tim,sizeof(tim))!=sizeof(tim)) { + ERR_(module)("dosmod sync lost, errno=%d\n",errno); + return; + } + /* there's no return */ } - if (write(pModule->lpDosTask->write_pipe,&tim,sizeof(tim))!=sizeof(tim)) { - ERR_(module)("dosmod sync lost, errno=%d\n",errno); - return; - } - /* there's no return */ - } } unsigned DOSVM_GetTimer( void ) { - TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); - NE_MODULE *pModule = NE_GetPtr( pTask->hModule ); - int stat=DOSMOD_GET_TIMER; - struct timeval tim; + LPDOSTASK lpDosTask = MZ_Current(); + int stat=DOSMOD_GET_TIMER; + struct timeval tim; - GlobalUnlock16( GetCurrentTask() ); - if (pModule&&pModule->lpDosTask) { - if (write(pModule->lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { - ERR_(module)("dosmod sync lost, errno=%d\n",errno); - return 0; + if (lpDosTask) { + if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) { + ERR_(module)("dosmod sync lost, errno=%d\n",errno); + return 0; + } + /* read response */ + while (1) { + if (read(lpDosTask->read_pipe,&tim,sizeof(tim))==sizeof(tim)) break; + if ((errno==EINTR)||(errno==EAGAIN)) continue; + ERR_(module)("dosmod sync lost, errno=%d\n",errno); + return 0; + } + return ((unsigned long long)tim.tv_usec*1193180)/1000000; } - /* read response */ - while (1) { - if (read(pModule->lpDosTask->read_pipe,&tim,sizeof(tim))==sizeof(tim)) break; - if ((errno==EINTR)||(errno==EAGAIN)) continue; - ERR_(module)("dosmod sync lost, errno=%d\n",errno); - return 0; - } - return ((unsigned long long)tim.tv_usec*1193180)/1000000; - } - return 0; + return 0; } void DOSVM_SetSystemData( int id, void *data ) { - TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); - NE_MODULE *pModule = NE_GetPtr( pTask->hModule ); + LPDOSTASK lpDosTask = MZ_Current(); DOSSYSTEM *sys, *prev; - GlobalUnlock16( GetCurrentTask() ); - if (pModule && pModule->lpDosTask) { - sys = pModule->lpDosTask->sys; + if (lpDosTask) { + sys = lpDosTask->sys; prev = NULL; while (sys && (sys->id != id)) { prev = sys; @@ -561,20 +564,18 @@ void DOSVM_SetSystemData( int id, void *data ) sys->data = data; sys->next = NULL; if (prev) prev->next = sys; - else pModule->lpDosTask->sys = sys; + else lpDosTask->sys = sys; } } else free(data); } void* DOSVM_GetSystemData( int id ) { - TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); - NE_MODULE *pModule = NE_GetPtr( pTask->hModule ); + LPDOSTASK lpDosTask = MZ_Current(); DOSSYSTEM *sys; - GlobalUnlock16( GetCurrentTask() ); - if (pModule && pModule->lpDosTask) { - sys = pModule->lpDosTask->sys; + if (lpDosTask) { + sys = lpDosTask->sys; while (sys && (sys->id != id)) sys = sys->next; if (sys) @@ -591,11 +592,12 @@ int DOSVM_Enter( PCONTEXT context ) return -1; } +void DOSVM_Wait( int read_pipe, HANDLE hObject) {} void DOSVM_PIC_ioport_out( WORD port, BYTE val) {} void DOSVM_SetTimer( unsigned ticks ) {} unsigned DOSVM_GetTimer( void ) { return 0; } void DOSVM_SetSystemData( int id, void *data ) { free(data); } void* DOSVM_GetSystemData( int id ) { return NULL; } -void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,void*), void *data) { /* EMPTY */ } +void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,PCONTEXT,void*), void *data) {} #endif diff --git a/loader/dos/module.c b/loader/dos/module.c index 64aea5d650c..404b3aaf2bb 100644 --- a/loader/dos/module.c +++ b/loader/dos/module.c @@ -182,7 +182,7 @@ static BOOL MZ_InitMemory( LPDOSTASK lpDosTask, NE_MODULE *pModule ) { int x; - if (lpDosTask->img_ofs) return TRUE; /* already allocated */ + if (lpDosTask->img) return TRUE; /* already allocated */ /* allocate 1MB+64K shared memory */ lpDosTask->img_ofs=START_OFFSET; @@ -330,7 +330,7 @@ static void MZ_InitTimer( LPDOSTASK lpDosTask, int ver ) int func; struct timeval tim; - /* start dosmod timer at 55Hz */ + /* start dosmod timer at 55ms (18.2Hz) */ func=DOSMOD_SET_TIMER; tim.tv_sec=0; tim.tv_usec=54925; write(lpDosTask->write_pipe,&func,sizeof(func)); @@ -370,14 +370,17 @@ BOOL MZ_InitTask( LPDOSTASK lpDosTask ) lpDosTask->write_pipe=write_fd[1]; - /* if we have a mapping file, use it */ - fname=lpDosTask->mm_name; farg=NULL; - if (!fname[0]) { - /* otherwise, map our own memory image */ - sprintf(fproc,"/proc/%d/mem",getpid()); - sprintf(arg,"%ld",(unsigned long)lpDosTask->img); - fname=fproc; farg=arg; - } + lpDosTask->hConInput=GetStdHandle(STD_INPUT_HANDLE); + lpDosTask->hConOutput=GetStdHandle(STD_OUTPUT_HANDLE); + + /* if we have a mapping file, use it */ + fname=lpDosTask->mm_name; farg=NULL; + if (!fname[0]) { + /* otherwise, map our own memory image */ + sprintf(fproc,"/proc/%d/mem",getpid()); + sprintf(arg,"%ld",(unsigned long)lpDosTask->img); + fname=fproc; farg=arg; + } TRACE(module,"Loading DOS VM support module (hmodule=%04x)\n",lpDosTask->hModule); if ((child=fork())<0) { @@ -541,6 +544,19 @@ void MZ_KillModule( LPDOSTASK lpDosTask ) #endif } +LPDOSTASK MZ_Current( void ) +{ + TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() ); + NE_MODULE *pModule = pTask ? NE_GetPtr( pTask->hModule ) : NULL; + + GlobalUnlock16( GetCurrentTask() ); + + if (pModule) + return pModule->lpDosTask; + + return NULL; +} + #else /* !MZ_SUPPORTED */ BOOL MZ_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmdline, LPCSTR env, @@ -553,4 +569,9 @@ BOOL MZ_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmdline, LPCSTR env, return FALSE; } +LPDOSTASK *MZ_Current( void ) +{ + return NULL; +} + #endif