Mail Archives: djgpp/1997/01/29/18:00:01
This is a multi-part message in MIME format.
--------------22C7C356429
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
John:
Attached is my timerIsr subsystem built using Watcom 10.6 (I haven't
ported it to djgpp yet). It has a preprocessor directive for "C_386"
that if defined, is the code for a bi-modal approach to the RTC (i.e.,
real and protected mode handlers) - if not defined, it is the code for a
real-mode only treatment of the RTC. I would think that this would be
relatively easy to port to djgpp (the bi-modal approach may not be
necessary).
Hope this helps...
Mark
--------------22C7C356429
Content-Type: text/plain; charset=us-ascii; name="Timerisr.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="Timerisr.c"
/* ---------------------------------------------------------------------------
*
* FILENAME
* timerIsr.c
*
* DESCRIPTION
* Provide timer ISR hook for timer subsystem.
*
* MODIFICATION HISTORY
* DATE ENGINEER REVISION COMMENTS
* 5/25/95 M.S. Teel 0 Original
* 1/5/96 M.S. Teel 0 Added 286/386
* support.
*
* ROUTINES INCLUDED
* int timerIsrInit (void)
* static void interrupt systemRtcIsr (void)
* void timerIsrExit (void)
* unsigned long getSystemTick (void)
*
* --------------------------------------------------------------------------
*/
/* ... OS include files
*/
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <i86.h>
#include <string.h>
/* ... System include files
*/
#include <dtiDefs.h>
#include <event.h>
#include <video.h>
/* ... Library include files
*/
/* ... Local include files
*/
/* ... global memory declarations
*/
/* ... global memory referenced
*/
/* ... static (local) memory declarations
*/
#define RTC_VECTOR 0x70
#define PERIODIC_INT_BIT 0x40
#define UPDATE_INT_BIT 0x10
#ifdef C_386
static short oldProtectedSegment;
static unsigned int oldProtectedOffset;
static unsigned int oldRealSegment;
static unsigned int oldRealOffset;
static void interrupt systemRtcIsr (void);
static unsigned short lastMilliSecondTime;
static unsigned long systemTick;
extern void __interrupt __far realRtcIsr (void);
extern unsigned short __far interruptCount;
extern void timerIsrExit
(
void
);
#define D32RealSeg(P) ((((DWORD) (P)) >> 4) & 0xFFFF)
#define D32RealOff(P) (((DWORD) (P)) & 0xF)
typedef unsigned int WORD;
typedef unsigned long DWORD;
static void *realMemAlloc
(
DWORD size
)
{
union REGS r;
r.x.eax = 0x0100; /* DPMI allocate DOS memory */
r.x.ebx = (size + 15) >> 4; /* Number of paragraphs requested */
int386 (0x31, &r, &r);
if (r.x.cflag)
return ((DWORD) 0); /* Failed */
return (void *) ((r.x.eax & 0xFFFF) << 4);
}
/* ---------------------------------------------------------------------------------
*
*
FUNCTION: int timerIsrInit (void)
*
* DESCRIPTION: Save old handler and install ours.
*
* ASSUMPTIONS
* None.
* ---------------------------------------------------------------------------------
*/
static void startTimerIsr
(
EVENT_ID eventToFree
)
{
union REGS r;
unsigned char x;
void *lowp;
eventDelete (eventToFree);
/* ... Save the starting real-mode and protected-mode handler addresses
*/
r.x.eax = 0x0204; /* DPMI get protected mode vector */
r.h.bl = RTC_VECTOR;
int386 (0x31, &r, &r);
oldProtectedSegment = (WORD) r.x.ecx;
oldProtectedOffset = r.x.edx;
r.x.eax = 0x0200; /* DPMI get real mode vector */
r.h.bl = RTC_VECTOR;
int386 (0x31, &r, &r);
oldRealSegment = (WORD) r.x.ecx;
oldRealOffset = (WORD) r.x.edx;
/* ... Allocate 128 bytes of DOS memory for the real-mode handler,
... which must of course be less than 128 bytes long. Then copy
... the real-mode handler into that segment.
*/
if (!(lowp = realMemAlloc (128)))
{
generateMessage ("Couldn't get low memory!", TRUE, TRUE);
return;
}
_fmemcpy ((void __far *) lowp, (void __far *) realRtcIsr, 128);
/* ... Install the new handlers. The memory touched by the protected mode
... handler needs to be locked, in case we are running under VMM
... or an external DPMI host.
*/
r.x.eax = 0x0205; /* DPMI set protected mode vector */
r.x.ebx = (DWORD) RTC_VECTOR;
r.x.ecx = (DWORD) FP_SEG(systemRtcIsr);
r.x.edx = FP_OFF(systemRtcIsr);
int386 (0x31, &r, &r);
r.x.eax = 0x0600; /* DPMI lock linear region */
r.x.ebx = ((DWORD) systemRtcIsr) >> 16;
r.x.ecx = ((DWORD) systemRtcIsr) & 0xFFFF;
r.x.esi = 0;
r.x.edi = 256; /* lock 256 bytes */
int386 (0x31, &r, &r);
r.x.eax = 0x0201; /* DPMI set real mode vector */
r.x.ebx = (DWORD) RTC_VECTOR;
r.x.ecx = D32RealSeg(lowp); /* CX:DX == real mode &handler */
r.x.edx = D32RealOff(lowp);
int386 (0x31, &r, &r);
/* ... now let's enable IRQ 8 (RTC)
*/
interruptDisable ();
outp (0x70,0x0C); /* access Register C */
inp (0x71); /* read Register C */
outp (0xA0,0x60);
x = inp (0xA1); /* read IMR */
x &= 0xFE; /* clear enable IRQ0 */
outp (0xA1,x);
outp (0xA0,0x60);
outp (0x70,0x0a); /* access register C */
if (!(inp (0x71) & 0x80)) /* is IRQ Flag set ? */
{
outp (0x70,0x0C); /* access Register C */
inp (0x71); /* read/clear IRQ Flag */
outp (0x70,0x0b); /* access Register B */
x = inp (0x71); /* clear interrupt */
x |= PERIODIC_INT_BIT; /* turn on the PIE bit */
x &= ~UPDATE_INT_BIT; /* turn off update interrupt */
outp (0x70,0x0b); /* access register B */
outp (0x71,x); /* set the PIE bit */
}
interruptEnable();
return;
}
/* -----------------------------------------------------------------------------
*
*
* FUNCTION: static void interrupt systemRtcIsr (void)
*
* DESCRIPTION: Our RTC ISR.
*
* ASSUMPTIONS
* None.
* ------------------------------------------------------------------------------
*/
static void interrupt systemRtcIsr
(
void
)
{
unsigned short milliSeconds;
/* ... normalize 976 us to 1 ms
*/
milliSeconds = (++interruptCount * 125) >> 7;
/* ... update it
*/
if (milliSeconds != lastMilliSecondTime)
{
systemTick ++;
lastMilliSecondTime = milliSeconds;
}
/* ... reset the interrupt for the next time
*/
outp (0x70,0x0C); /* access Register C */
inp (0x71); /* clear interrupt */
outp (0xA0,0x20); /* send end-of-INT signal to slave 8259 */
outp (0x20,0x20); /* send end-of-INT signal to master 8259 */
return;
}
/* ---------------------------------------------------------------------------------
*
*
FUNCTION: void timerIsrExit (void)
*
* DESCRIPTION: Reset RTC ISR to old vector contents.
*
* ASSUMPTIONS
* None.
* ---------------------------------------------------------------------------------
*/
void timerIsrExit
(
void
)
{
union REGS regs;
struct SREGS srii;
segread (&srii);
/* ...set the real mode RTC interrupt
*/
regs.w.ax = 0x0201;
regs.h.bl = RTC_VECTOR;
regs.w.cx = oldRealSegment;
regs.w.dx = oldRealOffset;
int386x(0x31,®s,®s,&srii);
/* ...Restore the protected mode ISR
*/
regs.w.ax = 0x0205;
regs.h.bl = RTC_VECTOR;
regs.w.cx = oldProtectedSegment;
regs.x.edx = oldProtectedOffset;
int386x(0x31,®s,®s,&srii);
return;
}
#else /* ifdef C_386 */
typedef void interrupt far (*INTRPTR)(void);
static void interrupt far (*originalIsr)(void);
static unsigned short interruptCount;
static unsigned short lastMilliSecondTime;
static unsigned long systemTick;
extern void timerIsrExit
(
void
);
static void far *getvect
(
unsigned char intNo
)
{
union REGS r;
struct SREGS s;
void far *retPtr;
segread (&s);
r.h.ah = 0x35;
r.h.al = intNo;
int86x (0x21, &r, &r, &s);
retPtr = (void far *)MK_FP(s.es,r.w.bx);
return retPtr;
}
static void setvect
(
unsigned char intNo,
void far *handler
)
{
union REGS r;
struct SREGS s;
memset (&s, 0, sizeof (struct SREGS));
r.h.ah = 0x25;
r.h.al = intNo;
s.ds = FP_SEG((INTRPTR)(handler));
r.w.dx = FP_OFF((INTRPTR)(handler));
int86x (0x21, &r, &r, &s);
return;
}
/* ---------------------------------------------------------------------------------
*
*
FUNCTION: static void interrupt systemRtcIsr (void)
*
* DESCRIPTION: Our RTC ISR.
*
* ASSUMPTIONS
* None.
* ---------------------------------------------------------------------------------
*/
void interrupt far systemRtcIsr
(
void
)
{
unsigned short milliSecondTime;
/* ... normalize 976 us to 1 ms
*/
milliSecondTime = (++interruptCount * 125) >> 7;
/* ... If a millisecond has changed update it
*/
if (milliSecondTime != lastMilliSecondTime)
{
systemTick += 1;
lastMilliSecondTime = milliSecondTime;
}
/* ... reset the interrupt for the next time
*/
outp (0x70,0x0C); /* access Register C */
inp (0x71); /* clear interrupt */
outp (0xA0,0x20); /* send end-of-INT signal to slave 8259 */
outp (0x20,0x20); /* send end-of-INT signal to master 8259 */
/* ... call the "real" handler
(*originalIsr) ();
*/
return;
}
void systemRtcIsrTemp
(
void
)
{
unsigned char x;
interruptDisable ();
outp (0x70,0x0C); /* access Register C */
inp (0x71); /* read Register C */
outp (0xA0,0x60);
x = inp (0xA1); /* read IMR */
x &= 0xFE; /* clear enable IRQ0 */
outp (0xA1,x);
outp (0xA0,0x60);
outp (0x70,0x0a); /* access register A */
if (!(inp (0x71) & 0x80)) /* is IRQ Flag set ? */
{
outp (0x70,0x0C); /* access Register C */
inp (0x71); /* read/clear IRQ Flag */
outp (0x70,0x0b); /* access Register B */
x = inp (0x71); /* clear interrupt */
x |= PERIODIC_INT_BIT; /* turn on the PIE bit */
x &= ~UPDATE_INT_BIT; /* turn off update interrupt */
outp (0x70,0x0b); /* access register B */
outp (0x71,x); /* set the PIE bit */
}
interruptEnable ();
return;
}
/* ---------------------------------------------------------------------------------
*
*
FUNCTION: void startTimerIsr (void)
*
* DESCRIPTION: Save old handler and install ours.
*
* ASSUMPTIONS
* None.
* ---------------------------------------------------------------------------------
*/
static void startTimerIsr
(
EVENT_ID eventToFree
)
{
unsigned char x;
void far *tempIsr;
eventDelete (generalEventList, eventToFree);
tempIsr = getvect (RTC_VECTOR);
if (tempIsr == systemRtcIsr)
{
/* ... we have already installed it!
*/
return;
}
else
originalIsr = tempIsr;
systemTick = 0L;
interruptCount = 0;
setvect (RTC_VECTOR, systemRtcIsr);
/* ... now let's enable IRQ 8 (RTC)
*/
interruptDisable ();
outp (0x70,0x0C); /* access Register C */
inp (0x71); /* read Register C */
outp (0xA0,0x60);
x = inp (0xA1); /* read IMR */
x &= 0xFE; /* clear enable IRQ0 */
outp (0xA1,x);
outp (0xA0,0x60);
outp (0x70,0x0a); /* access register A */
if (!(inp (0x71) & 0x80)) /* is IRQ Flag set ? */
{
outp (0x70,0x0C); /* access Register C */
inp (0x71); /* read/clear IRQ Flag */
outp (0x70,0x0b); /* access Register B */
x = inp (0x71); /* clear interrupt */
x |= PERIODIC_INT_BIT; /* turn on the PIE bit */
x &= ~UPDATE_INT_BIT; /* turn off update interrupt */
outp (0x70,0x0b); /* access register B */
outp (0x71,x); /* set the PIE bit */
}
interruptEnable ();
return;
}
/* ---------------------------------------------------------------------------------
*
*
FUNCTION: void timerIsrExit (void)
*
* DESCRIPTION: Reset RTC ISR to old vector contents.
*
* ASSUMPTIONS
* None.
* ---------------------------------------------------------------------------------
*/
void timerIsrExit
(
void
)
{
setvect (RTC_VECTOR, originalIsr);
return;
}
#endif /* ifdef C_386 */
/* ...Now do the timer interrupt initialization
*/
int timerIsrInit()
{
EVENT_ID eventId;
/* ... Now initialize the system tick and interruptCount
*/
systemTick = 0;
interruptCount = 0;
if ((eventId =
eventCreate (generalEventList, NULL, startTimerIsr, 0)) == NULL)
return ERROR;
/* ... give him the eventId as his parameter
*/
eventCreate (generalEventList, eventId, startTimerIsr, eventId);
eventRaise (generalEventList, eventId);
return OK;
}
/* ---------------------------------------------------------------------------------
*
*
FUNCTION: unsigned long getSystemTick (void)
*
* DESCRIPTION: Return current value of system tick counter.
*
* ASSUMPTIONS
* None.
* ---------------------------------------------------------------------------------
*/
unsigned long getSystemTick
(
void
)
{
return systemTick;
}
--------------22C7C356429--
- Raw text -