📄 pmdos.c
字号:
void PMAPI PM_getPMvect(int intno, PMFARPTR *isr){ PMREGS regs; regs.x.ax = 0x204; regs.h.bl = intno; PM_int386(0x31,®s,®s); isr->sel = regs.x.cx; isr->off = regs.e.edx;}void PMAPI PM_setPMvect(int intno, PM_intHandler isr){ PMSREGS sregs; PMREGS regs; PM_saveDS(); regs.x.ax = 0x205; /* Set protected mode vector */ regs.h.bl = intno; PM_segread(&sregs); regs.x.cx = sregs.cs; regs.e.edx = (uint)isr; PM_int386(0x31,®s,®s);}void PMAPI PM_restorePMvect(int intno, PMFARPTR isr){ PMREGS regs; regs.x.ax = 0x205; regs.h.bl = intno; regs.x.cx = isr.sel; regs.e.edx = isr.off; PM_int386(0x31,®s,®s);}#endif/*-------------------------------------------------------------------------*//* Watcom C/C++ with Rational DOS/4GW support. *//*-------------------------------------------------------------------------*/#ifdef DOS4GW#define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */#define MOUSE_SUPPORTED /* DOS4GW directly supports mouse *//* We use the normal DOS services to save and restore interrupts handlers * for Watcom C++, because using the direct DPMI functions does not * appear to work properly. At least if we use the DPMI functions, we * dont get the auto-passup feature that we need to correctly trap * real and protected mode interrupts without installing Bi-model * interrupt handlers. */void PMAPI PM_getPMvect(int intno, PMFARPTR *isr){ PMREGS regs; PMSREGS sregs; PM_segread(&sregs); regs.h.ah = 0x35; regs.h.al = intno; PM_int386x(0x21,®s,®s,&sregs); isr->sel = sregs.es; isr->off = regs.e.ebx;}void PMAPI PM_setPMvect(int intno, PM_intHandler isr){ PMREGS regs; PMSREGS sregs; PM_saveDS(); PM_segread(&sregs); regs.h.ah = 0x25; regs.h.al = intno; sregs.ds = sregs.cs; regs.e.edx = (uint)isr; PM_int386x(0x21,®s,®s,&sregs);}void PMAPI PM_restorePMvect(int intno, PMFARPTR isr){ PMREGS regs; PMSREGS sregs; PM_segread(&sregs); regs.h.ah = 0x25; regs.h.al = intno; sregs.ds = isr.sel; regs.e.edx = isr.off; PM_int386x(0x21,®s,®s,&sregs);}int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh){ lockPMHandlers(); /* Ensure our handlers are locked */ _PM_mouseHandler = mh; _PM_setMouseHandler(_PM_mouseMask = mask); return 1;}void PMAPI PM_restoreMouseHandler(void){ PMREGS regs; if (_PM_mouseHandler) { regs.x.ax = 33; PM_int386(0x33, ®s, ®s); _PM_mouseHandler = NULL; }}#endif/*-------------------------------------------------------------------------*//* DJGPP port of GNU C++ support. *//*-------------------------------------------------------------------------*/#ifdef DJGPP#define GENERIC_DPMI32 /* Use generic 32 bit DPMI routines */void PMAPI PM_getPMvect(int intno, PMFARPTR *isr){ PMREGS regs; regs.x.ax = 0x204; regs.h.bl = intno; PM_int386(0x31,®s,®s); isr->sel = regs.x.cx; isr->off = regs.e.edx;}void PMAPI PM_setPMvect(int intno, PM_intHandler isr){ PMSREGS sregs; PMREGS regs; PM_saveDS(); regs.x.ax = 0x205; /* Set protected mode vector */ regs.h.bl = intno; PM_segread(&sregs); regs.x.cx = sregs.cs; regs.e.edx = (uint)isr; PM_int386(0x31,®s,®s);}void PMAPI PM_restorePMvect(int intno, PMFARPTR isr){ PMREGS regs; regs.x.ax = 0x205; regs.h.bl = intno; regs.x.cx = isr.sel; regs.e.edx = isr.off; PM_int386(0x31,®s,®s);}#endif/*-------------------------------------------------------------------------*//* Generic 32 bit DPMI routines *//*-------------------------------------------------------------------------*/#if defined(GENERIC_DPMI32)static long prevRealBreak; /* Previous real mode break handler */static long prevRealCtrlC; /* Previous real mode CtrlC handler */static long prevRealCritical; /* Prev real mode critical handler */#ifndef MOUSE_SUPPORTED/* The following real mode routine is used to call a 32 bit protected * mode FAR function from real mode. We use this for passing up control * from the real mode mouse callback to our protected mode code. */static long mouseRMCB; /* Mouse real mode callback address */static uchar *mousePtr;static char mouseRegs[0x32]; /* Real mode regs for mouse callback */static uchar mouseHandler[] = { 0x00,0x00,0x00,0x00, /* _realRMCB */ 0x2E,0xFF,0x1E,0x00,0x00, /* call [cs:_realRMCB] */ 0xCB, /* retf */ };int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh){ RMREGS regs; RMSREGS sregs; uint rseg,roff; lockPMHandlers(); /* Ensure our handlers are locked */ /* Copy the real mode handler to real mode memory */ if ((mousePtr = PM_allocRealSeg(sizeof(mouseHandler),&rseg,&roff)) == NULL) return 0; memcpy(mousePtr,mouseHandler,sizeof(mouseHandler)); if (!_DPMI_allocateCallback(_PM_mousePMCB, mouseRegs, &mouseRMCB)) PM_fatalError("Unable to allocate real mode callback!\n"); PM_setLong(mousePtr,mouseRMCB); /* Install the real mode mouse handler */ _PM_mouseHandler = mh; sregs.es = rseg; regs.x.dx = roff+4; regs.x.cx = _PM_mouseMask = mask; regs.x.ax = 0xC; PM_int86x(0x33, ®s, ®s, &sregs); return 1;}void PMAPI PM_restoreMouseHandler(void){ RMREGS regs; if (_PM_mouseHandler) { regs.x.ax = 33; PM_int86(0x33, ®s, ®s); PM_freeRealSeg(mousePtr); _DPMI_freeCallback(mouseRMCB); _PM_mouseHandler = NULL; }}#endifstatic void getISR(int intno, PMFARPTR *pmisr, long *realisr){ PM_getPMvect(intno,pmisr); _PM_getRMvect(intno,realisr);}static void restoreISR(int intno, PMFARPTR pmisr, long realisr){ _PM_setRMvect(intno,realisr); PM_restorePMvect(intno,pmisr);}static void setISR(int intno, void (* PMAPI pmisr)()){ lockPMHandlers(); /* Ensure our handlers are locked */ PM_setPMvect(intno,pmisr);}void PMAPI PM_setTimerHandler(PM_intHandler th){ getISR(0x8, &_PM_prevTimer, &_PM_prevRealTimer); _PM_timerHandler = th; setISR(0x8, _PM_timerISR);}void PMAPI PM_restoreTimerHandler(void){ if (_PM_timerHandler) { restoreISR(0x8, _PM_prevTimer, _PM_prevRealTimer); _PM_timerHandler = NULL; }}ibool PMAPI PM_setRealTimeClockHandler(PM_intHandler th,int frequency){ /* Save the old CMOS real time clock values */ _PM_oldCMOSRegA = _PM_readCMOS(0x0A); _PM_oldCMOSRegB = _PM_readCMOS(0x0B); /* Set the real time clock interrupt handler */ getISR(0x70, &_PM_prevRTC, &_PM_prevRealRTC); _PM_rtcHandler = th; setISR(0x70, _PM_rtcISR); /* Program the real time clock default frequency */ PM_setRealTimeClockFrequency(frequency); /* Unmask IRQ8 in the PIC2 */ _PM_oldRTCPIC2 = PM_inpb(0xA1); PM_outpb(0xA1,_PM_oldRTCPIC2 & 0xFE); return true;}void PMAPI PM_restoreRealTimeClockHandler(void){ if (_PM_rtcHandler) { /* Restore CMOS registers and mask RTC clock */ _PM_writeCMOS(0x0A,_PM_oldCMOSRegA); _PM_writeCMOS(0x0B,_PM_oldCMOSRegB); PM_outpb(0xA1,(PM_inpb(0xA1) & 0xFE) | (_PM_oldRTCPIC2 & ~0xFE)); /* Restore the interrupt vector */ restoreISR(0x70, _PM_prevRTC, _PM_prevRealRTC); _PM_rtcHandler = NULL; }}PM_IRQHandle PMAPI PM_setIRQHandler( int IRQ, PM_irqHandler ih){ int thunkSize,PICmask,chainPrevious; ulong offsetAdjust; _PM_IRQHandle *handle; thunkSize = (ulong)_PM_irqISRTemplateEnd - (ulong)_PM_irqISRTemplate; if ((handle = PM_malloc(sizeof(_PM_IRQHandle) + thunkSize)) == NULL) return NULL; handle->IRQ = IRQ; handle->prevPIC = PM_inpb(0x21); handle->prevPIC2 = PM_inpb(0xA1); if (IRQ < 8) { handle->IRQVect = (IRQ + 8); PICmask = (1 << IRQ); chainPrevious = ((handle->prevPIC & PICmask) == 0); } else { handle->IRQVect = (0x60 + IRQ + 8); PICmask = ((1 << IRQ) | 0x4); chainPrevious = ((handle->prevPIC2 & (PICmask >> 8)) == 0); } /* Copy and setup the assembler thunk */ offsetAdjust = (ulong)handle->thunk - (ulong)_PM_irqISRTemplate; memcpy(handle->thunk,_PM_irqISRTemplate,thunkSize); *((ulong*)&handle->thunk[2]) = offsetAdjust; *((ulong*)&handle->thunk[11+0]) = (ulong)ih; if (chainPrevious) { *((ulong*)&handle->thunk[11+4]) = handle->prevHandler.off; *((ulong*)&handle->thunk[11+8]) = handle->prevHandler.sel; } else { *((ulong*)&handle->thunk[11+4]) = 0; *((ulong*)&handle->thunk[11+8]) = 0; } *((ulong*)&handle->thunk[11+12]) = IRQ; /* Set the real time clock interrupt handler */ getISR(handle->IRQVect, &handle->prevHandler, &handle->prevRealhandler); setISR(handle->IRQVect, (PM_intHandler)handle->thunk); /* Unmask the IRQ in the PIC */ PM_outpb(0xA1,handle->prevPIC2 & ~(PICmask >> 8)); PM_outpb(0x21,handle->prevPIC & ~PICmask); return handle;}void PMAPI PM_restoreIRQHandler( PM_IRQHandle irqHandle){ int PICmask; _PM_IRQHandle *handle = irqHandle; /* Restore PIC mask for the interrupt */ if (handle->IRQ < 8) PICmask = (1 << handle->IRQ); else PICmask = ((1 << handle->IRQ) | 0x4); PM_outpb(0xA1,(PM_inpb(0xA1) & ~(PICmask >> 8)) | (handle->prevPIC2 & (PICmask >> 8))); PM_outpb(0x21,(PM_inpb(0x21) & ~PICmask) | (handle->prevPIC & PICmask)); /* Restore the interrupt vector */ restoreISR(handle->IRQVect, handle->prevHandler, handle->prevRealhandler); /* Finally free the thunk */ PM_free(handle);}void PMAPI PM_setKeyHandler(PM_intHandler kh){ getISR(0x9, &_PM_prevKey, &_PM_prevRealKey); _PM_keyHandler = kh; setISR(0x9, _PM_keyISR);}void PMAPI PM_restoreKeyHandler(void){ if (_PM_keyHandler) { restoreISR(0x9, _PM_prevKey, _PM_prevRealKey); _PM_keyHandler = NULL; }}void PMAPI PM_setKey15Handler(PM_key15Handler kh){ getISR(0x15, &_PM_prevKey15, &_PM_prevRealKey15); _PM_key15Handler = kh; setISR(0x15, _PM_key15ISR);}void PMAPI PM_restoreKey15Handler(void){ if (_PM_key15Handler) { restoreISR(0x15, _PM_prevKey15, _PM_prevRealKey15); _PM_key15Handler = NULL; }}/* Real mode Ctrl-C and Ctrl-Break handler. This handler simply sets a * flag in the real mode code segment and exit. We save the location * of this flag in real mode memory so that both the real mode and * protected mode code will be modifying the same flags. */#ifndef DOS4GWstatic uchar ctrlHandler[] = { 0x00,0x00,0x00,0x00, /* ctrlBFlag */ 0x66,0x2E,0xC7,0x06,0x00,0x00, 0x01,0x00,0x00,0x00, /* mov [cs:ctrlBFlag],1 */ 0xCF, /* iretf */ };#endifvoid PMAPI PM_installAltBreakHandler(PM_breakHandler bh){#ifndef DOS4GW uint rseg,roff;#else static int ctrlCFlag,ctrlBFlag; _PM_ctrlCPtr = (uchar*)&ctrlCFlag; _PM_ctrlBPtr = (uchar*)&ctrlBFlag;#endif getISR(0x1B, &_PM_prevBreak, &prevRealBreak); getISR(0x23, &_PM_prevCtrlC, &prevRealCtrlC); _PM_breakHandler = bh; setISR(0x1B, _PM_breakISR); setISR(0x23, _PM_ctrlCISR);#ifndef DOS4GW /* Hook the real mode vectors for these handlers, as these are not * normally reflected by the DPMI server up to protected mode */ _PM_ctrlBPtr = PM_allocRealSeg(sizeof(ctrlHandler)*2, &rseg, &roff); memcpy(_PM_ctrlBPtr,ctrlHandler,sizeof(ctrlHandler)); memcpy(_PM_ctrlBPtr+sizeof(ctrlHandler),ctrlHandler,sizeof(ctrlHandler)); _PM_ctrlCPtr = _PM_ctrlBPtr + sizeof(ctrlHandler); _PM_setRMvect(0x1B,((long)rseg << 16) | (roff+4)); _PM_setRMvect(0x23,((long)rseg << 16) | (roff+sizeof(ctrlHandler)+4));#endif}void PMAPI PM_installBreakHandler(void){ PM_installAltBreakHandler(NULL);}void PMAPI PM_restoreBreakHandler(void){ if (_PM_prevBreak.sel) { restoreISR(0x1B, _PM_prevBreak, prevRealBreak); restoreISR(0x23, _PM_prevCtrlC, prevRealCtrlC); _PM_prevBreak.sel = 0; _PM_breakHandler = NULL;#ifndef DOS4GW PM_freeRealSeg(_PM_ctrlBPtr);#endif }}/* Real mode Critical Error handler. This handler simply saves the AX and * DI values in the real mode code segment and exits. We save the location * of this flag in real mode memory so that both the real mode and * protected mode code will be modifying the same flags. */#ifndef DOS4GWstatic uchar criticalHandler[] = { 0x00,0x00, /* axCode */ 0x00,0x00, /* diCode */ 0x2E,0xA3,0x00,0x00, /* mov [cs:axCode],ax */ 0x2E,0x89,0x3E,0x02,0x00, /* mov [cs:diCode],di */ 0xB8,0x03,0x00, /* mov ax,3 */ 0xCF, /* iretf */ };#endifvoid PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch){#ifndef DOS4GW uint rseg,roff;#else static short critBuf[2]; _PM_critPtr = (uchar*)critBuf;#endif getISR(0x24, &_PM_prevCritical, &prevRealCritical); _PM_critHandler = ch; setISR(0x24, _PM_criticalISR);#ifndef DOS4GW /* Hook the real mode vector, as this is not normally reflected by the * DPMI server up to protected mode. */ _PM_critPtr = PM_allocRealSeg(sizeof(criticalHandler)*2, &rseg, &roff); memcpy(_PM_critPtr,criticalHandler,sizeof(criticalHandler)); _PM_setRMvect(0x24,((long)rseg << 16) | (roff+4));#endif}void PMAPI PM_installCriticalHandler(void){ PM_installAltCriticalHandler(NULL);}void PMAPI PM_restoreCriticalHandler(void){ if (_PM_prevCritical.sel) { restoreISR(0x24, _PM_prevCritical, prevRealCritical); PM_freeRealSeg(_PM_critPtr); _PM_prevCritical.sel = 0; _PM_critHandler = NULL; }}int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh){ PMSREGS sregs; PM_segread(&sregs); return DPMI_lockLinearPages((uint)p + DPMI_getSelectorBase(sregs.ds),len);}int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh){ PMSREGS sregs; PM_segread(&sregs); return DPMI_unlockLinearPages((uint)p + DPMI_getSelectorBase(sregs.ds),len);}int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh){ PMSREGS sregs; PM_segread(&sregs); return DPMI_lockLinearPages((uint)p + DPMI_getSelectorBase(sregs.cs),len);}int PMAPI PM_unlockCodePages(void (*p)(),uint len,PM_lockHandle *lh){ PMSREGS sregs; PM_segread(&sregs); return DPMI_unlockLinearPages((uint)p + DPMI_getSelectorBase(sregs.cs),len);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -