pmdos.c

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

C
1,638
字号
/****************************************************************************
*
*                   SciTech OS Portability Manager Library
*
*  ========================================================================
*
*    The contents of this file are subject to the SciTech MGL Public
*    License Version 1.0 (the "License"); you may not use this file
*    except in compliance with the License. You may obtain a copy of
*    the License at http://www.scitechsoft.com/mgl-license.txt
*
*    Software distributed under the License is distributed on an
*    "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
*    implied. See the License for the specific language governing
*    rights and limitations under the License.
*
*    The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
*
*    The Initial Developer of the Original Code is SciTech Software, Inc.
*    All Rights Reserved.
*
*  ========================================================================
*
* Language:     ANSI C
* Environment:  16/32 bit DOS
*
* Description:  Implementation for the OS Portability Manager Library, which
*               contains functions to implement OS specific services in a
*               generic, cross platform API. Porting the OS Portability
*               Manager library is the first step to porting any SciTech
*               products to a new platform.
*
****************************************************************************/

#include "pmapi.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>

/*--------------------------- Global variables ----------------------------*/

#ifndef REALMODE
static int  globalDataStart;
#endif

PM_criticalHandler  _VARAPI _PM_critHandler = NULL;
PM_breakHandler     _VARAPI _PM_breakHandler = NULL;
PM_intHandler       _VARAPI _PM_timerHandler = NULL;
PM_intHandler       _VARAPI _PM_rtcHandler = NULL;
PM_intHandler       _VARAPI _PM_keyHandler = NULL;
PM_key15Handler     _VARAPI _PM_key15Handler = NULL;
PM_mouseHandler     _VARAPI _PM_mouseHandler = NULL;
PM_intHandler       _VARAPI _PM_int10Handler = NULL;
int                 _VARAPI _PM_mouseMask;

uchar *     _VARAPI _PM_ctrlCPtr;               /* Location of Ctrl-C flag      */
uchar *     _VARAPI _PM_ctrlBPtr;               /* Location of Ctrl-Break flag  */
uchar *     _VARAPI _PM_critPtr;                /* Location of Critical error Bf*/
PMFARPTR    _VARAPI _PM_prevTimer = PMNULL;     /* Previous timer handler       */
PMFARPTR    _VARAPI _PM_prevRTC = PMNULL;       /* Previous RTC handler         */
PMFARPTR    _VARAPI _PM_prevKey = PMNULL;       /* Previous key handler         */
PMFARPTR    _VARAPI _PM_prevKey15 = PMNULL;     /* Previous key15 handler       */
PMFARPTR    _VARAPI _PM_prevBreak = PMNULL;     /* Previous break handler       */
PMFARPTR    _VARAPI _PM_prevCtrlC = PMNULL;     /* Previous CtrlC handler       */
PMFARPTR    _VARAPI _PM_prevCritical = PMNULL;  /* Previous critical handler    */
long        _VARAPI _PM_prevRealTimer;          /* Previous real mode timer     */
long        _VARAPI _PM_prevRealRTC;            /* Previous real mode RTC       */
long        _VARAPI _PM_prevRealKey;            /* Previous real mode key       */
long        _VARAPI _PM_prevRealKey15;          /* Previous real mode key15     */
long        _VARAPI _PM_prevRealInt10;          /* Previous real mode int 10h   */
static uchar        _PM_oldCMOSRegA;            /* CMOS register A contents     */
static uchar        _PM_oldCMOSRegB;            /* CMOS register B contents     */
static uchar        _PM_oldRTCPIC2;             /* Mask value for RTC IRQ8      */

/* Structure to maintain information about hardware interrupt handlers,
 * include a copy of the hardware IRQ assembler thunk (one for each
 * hooked interrupt handler).
 */

typedef struct {
    uchar       IRQ;
    uchar       IRQVect;
    uchar       prevPIC;
    uchar       prevPIC2;
    PMFARPTR    prevHandler;
    long        prevRealhandler;
    uchar       thunk[1];
    /* IRQ assembler thunk follows ... */
    } _PM_IRQHandle;

/*----------------------------- Implementation ----------------------------*/

/* Globals for locking interrupt handlers in _pmdos.asm */

#ifndef REALMODE
extern int  _VARAPI _PM_pmdosDataStart;
extern int  _VARAPI _PM_pmdosDataEnd;
extern int  _VARAPI _PM_DMADataStart;
extern int  _VARAPI _PM_DMADataEnd;
void _ASMAPI _PM_pmdosCodeStart(void);
void _ASMAPI _PM_pmdosCodeEnd(void);
void _ASMAPI _PM_DMACodeStart(void);
void _ASMAPI _PM_DMACodeEnd(void);
#endif

/* Protected mode interrupt handlers, also called by PM callbacks below */

void _ASMAPI _PM_timerISR(void);
void _ASMAPI _PM_rtcISR(void);
void _ASMAPI _PM_irqISRTemplate(void);
void _ASMAPI _PM_irqISRTemplateEnd(void);
void _ASMAPI _PM_keyISR(void);
void _ASMAPI _PM_key15ISR(void);
void _ASMAPI _PM_breakISR(void);
void _ASMAPI _PM_ctrlCISR(void);
void _ASMAPI _PM_criticalISR(void);
void _ASMAPI _PM_mouseISR(void);
void _ASMAPI _PM_int10PMCB(void);

/* Protected mode DPMI callback handlers */

void _ASMAPI _PM_mousePMCB(void);

/* Routine to install a mouse handler function */

void _ASMAPI _PM_setMouseHandler(int mask);

/* Routine to allocate DPMI real mode callback routines */

ibool _ASMAPI _DPMI_allocateCallback(void (_ASMAPI *pmcode)(),void *rmregs,long *RMCB);
void _ASMAPI _DPMI_freeCallback(long RMCB);

/* DPMI helper functions in PMLITE.C */

ulong   PMAPI DPMI_mapPhysicalToLinear(ulong physAddr,ulong limit);
int     PMAPI DPMI_setSelectorBase(ushort sel,ulong linAddr);
ulong   PMAPI DPMI_getSelectorBase(ushort sel);
int     PMAPI DPMI_setSelectorLimit(ushort sel,ulong limit);
uint    PMAPI DPMI_createSelector(ulong base,ulong limit);
void    PMAPI DPMI_freeSelector(uint sel);
int     PMAPI DPMI_lockLinearPages(ulong linear,ulong len);
int     PMAPI DPMI_unlockLinearPages(ulong linear,ulong len);

/* Functions to read and write CMOS registers */

uchar   PMAPI _PM_readCMOS(int index);
void    PMAPI _PM_writeCMOS(int index,uchar value);

/*-------------------------------------------------------------------------*/
/* Generic routines common to all environments                             */
/*-------------------------------------------------------------------------*/

void PMAPI PM_resetMouseDriver(int hardReset)
{
    RMREGS          regs;
    PM_mouseHandler oldHandler = _PM_mouseHandler;

    PM_restoreMouseHandler();
    regs.x.ax = hardReset ? 0 : 33;
    PM_int86(0x33, &regs, &regs);
    if (oldHandler)
	PM_setMouseHandler(_PM_mouseMask, oldHandler);
}

void PMAPI PM_setRealTimeClockFrequency(int frequency)
{
    static short convert[] = {
	8192,
	4096,
	2048,
	1024,
	512,
	256,
	128,
	64,
	32,
	16,
	8,
	4,
	2,
	-1,
	};
    int i;

    /* First clear any pending RTC timeout if not cleared */
    _PM_readCMOS(0x0C);
    if (frequency == 0) {
	/* Disable RTC timout */
	_PM_writeCMOS(0x0A,_PM_oldCMOSRegA);
	_PM_writeCMOS(0x0B,_PM_oldCMOSRegB & 0x0F);
	}
    else {
	/* Convert frequency value to RTC clock indexes */
	for (i = 0; convert[i] != -1; i++) {
	    if (convert[i] == frequency)
		break;
	    }

	/* Set RTC timout value and enable timeout */
	_PM_writeCMOS(0x0A,0x20 | (i+3));
	_PM_writeCMOS(0x0B,(_PM_oldCMOSRegB & 0x0F) | 0x40);
	}
}

#ifndef REALMODE

static void PMAPI lockPMHandlers(void)
{
    static int      locked = 0;
    int             stat;
    PM_lockHandle   lh; /* Unused in DOS */

    /* Lock all of the code and data used by our protected mode interrupt
     * handling routines, so that it will continue to work correctly
     * under real mode.
     */
    if (!locked) {
	PM_saveDS();
	stat  = !PM_lockDataPages(&globalDataStart-2048,4096,&lh);
	stat |= !PM_lockDataPages(&_PM_pmdosDataStart,(int)&_PM_pmdosDataEnd - (int)&_PM_pmdosDataStart,&lh);
	stat |= !PM_lockCodePages((__codePtr)_PM_pmdosCodeStart,(int)_PM_pmdosCodeEnd-(int)_PM_pmdosCodeStart,&lh);
	stat |= !PM_lockDataPages(&_PM_DMADataStart,(int)&_PM_DMADataEnd - (int)&_PM_DMADataStart,&lh);
	stat |= !PM_lockCodePages((__codePtr)_PM_DMACodeStart,(int)_PM_DMACodeEnd-(int)_PM_DMACodeStart,&lh);
	if (stat) {
	    printf("Page locking services failed - interrupt handling not safe!\n");
	    exit(1);
	    }
	locked = 1;
	}
}

#endif

/*-------------------------------------------------------------------------*/
/* DOS Real Mode support.                                                  */
/*-------------------------------------------------------------------------*/

#ifdef REALMODE

#ifndef MK_FP
#define MK_FP(s,o)  ( (void far *)( ((ulong)(s) << 16) + \
		    (ulong)(o) ))
#endif

int PMAPI PM_setMouseHandler(int mask, PM_mouseHandler mh)
{
    PM_saveDS();
    _PM_mouseHandler = mh;
    _PM_setMouseHandler(_PM_mouseMask = mask);
    return 1;
}

void PMAPI PM_restoreMouseHandler(void)
{
    union REGS      regs;

    if (_PM_mouseHandler) {
	regs.x.ax = 33;
	int86(0x33, &regs, &regs);
	_PM_mouseHandler = NULL;
	}
}

void PMAPI PM_setTimerHandler(PM_intHandler th)
{
    _PM_getRMvect(0x8, (long*)&_PM_prevTimer);
    _PM_timerHandler = th;
    _PM_setRMvect(0x8, (long)_PM_timerISR);
}

void PMAPI PM_restoreTimerHandler(void)
{
    if (_PM_timerHandler) {
	_PM_setRMvect(0x8, (long)_PM_prevTimer);
	_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 */
    _PM_getRMvect(0x70, (long*)&_PM_prevRTC);
    _PM_rtcHandler = th;
    _PM_setRMvect(0x70, (long)_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 */
	_PM_setRMvect(0x70, (long)_PM_prevRTC);
	_PM_rtcHandler = NULL;
	}
}

void PMAPI PM_setKeyHandler(PM_intHandler kh)
{
    _PM_getRMvect(0x9, (long*)&_PM_prevKey);
    _PM_keyHandler = kh;
    _PM_setRMvect(0x9, (long)_PM_keyISR);
}

void PMAPI PM_restoreKeyHandler(void)
{
    if (_PM_keyHandler) {
	_PM_setRMvect(0x9, (long)_PM_prevKey);
	_PM_keyHandler = NULL;
	}
}

void PMAPI PM_setKey15Handler(PM_key15Handler kh)
{
    _PM_getRMvect(0x15, (long*)&_PM_prevKey15);
    _PM_key15Handler = kh;
    _PM_setRMvect(0x15, (long)_PM_key15ISR);
}

void PMAPI PM_restoreKey15Handler(void)
{
    if (_PM_key15Handler) {
	_PM_setRMvect(0x15, (long)_PM_prevKey15);
	_PM_key15Handler = NULL;
	}
}

void PMAPI PM_installAltBreakHandler(PM_breakHandler bh)
{
    static int  ctrlCFlag,ctrlBFlag;

    _PM_ctrlCPtr = (uchar*)&ctrlCFlag;
    _PM_ctrlBPtr = (uchar*)&ctrlBFlag;
    _PM_getRMvect(0x1B, (long*)&_PM_prevBreak);
    _PM_getRMvect(0x23, (long*)&_PM_prevCtrlC);
    _PM_breakHandler = bh;
    _PM_setRMvect(0x1B, (long)_PM_breakISR);
    _PM_setRMvect(0x23, (long)_PM_ctrlCISR);
}

void PMAPI PM_installBreakHandler(void)
{
    PM_installAltBreakHandler(NULL);
}

void PMAPI PM_restoreBreakHandler(void)
{
    if (_PM_prevBreak) {
	_PM_setRMvect(0x1B, (long)_PM_prevBreak);
	_PM_setRMvect(0x23, (long)_PM_prevCtrlC);
	_PM_prevBreak = NULL;
	_PM_breakHandler = NULL;
	}
}

void PMAPI PM_installAltCriticalHandler(PM_criticalHandler ch)
{
    static  short critBuf[2];

    _PM_critPtr = (uchar*)critBuf;
    _PM_getRMvect(0x24, (long*)&_PM_prevCritical);
    _PM_critHandler = ch;
    _PM_setRMvect(0x24, (long)_PM_criticalISR);
}

void PMAPI PM_installCriticalHandler(void)
{
    PM_installAltCriticalHandler(NULL);
}

void PMAPI PM_restoreCriticalHandler(void)
{
    if (_PM_prevCritical) {
	_PM_setRMvect(0x24, (long)_PM_prevCritical);
	_PM_prevCritical = NULL;
	_PM_critHandler = NULL;
	}
}

int PMAPI PM_lockDataPages(void *p,uint len,PM_lockHandle *lh)
{
    p = p;  len = len;      /* Do nothing for real mode */
    return 1;
}

int PMAPI PM_unlockDataPages(void *p,uint len,PM_lockHandle *lh)
{
    p = p;  len = len;      /* Do nothing for real mode */
    return 1;
}

int PMAPI PM_lockCodePages(void (*p)(),uint len,PM_lockHandle *lh)
{
    p = p;  len = len;      /* Do nothing for real mode */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?