pmdos.c

来自「适合KS8695X」· C语言 代码 · 共 1,638 行 · 第 1/4 页

C
1,638
字号
    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,&regs,&regs);
}

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,&regs,&regs);
}

#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, &regs, &regs, &sregs);
    return 1;
}

void PMAPI PM_restoreMouseHandler(void)
{
    RMREGS  regs;

    if (_PM_mouseHandler) {
	regs.x.ax = 33;
	PM_int86(0x33, &regs, &regs);
	PM_freeRealSeg(mousePtr);
	_DPMI_freeCallback(mouseRMCB);
	_PM_mouseHandler = NULL;
	}
}

#endif

static 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 DOS4GW
static uchar ctrlHandler[] = {
    0x00,0x00,0x00,0x00,            /*  ctrlBFlag                       */
    0x66,0x2E,0xC7,0x06,0x00,0x00,
    0x01,0x00,0x00,0x00,            /*  mov     [cs:ctrlBFlag],1        */
    0xCF,                           /*  iretf                           */
    };
#endif

void 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 DOS4GW
static 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                           */
    };
#endif

void 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 + =
减小字号Ctrl + -
显示快捷键?