[comp.sys.ibm.pc] Turbo C timer interrupt handler

ngeow@bucsb.UUCP (Yee Kwong Ngeow) (04/24/89)

Hi..

  I am trying to do some mutittasking on a PS2 Model 70. I am in
the process of writting an efficient  multi user BBS, so I need
to know how to change the timer interrupt of the PC to switch
between program, using time quantumn method (round robin
scheduling.) 

  What I really need to know is can I modify the timer interrupt
vector so that every fraction of a second (I presume 1/60th) 
the OS calls the handler, which switches the running process
and returns?       

  I am currently using Turbo C. Is there anyway to do it using this
compiler?

  Feel free to be technical. I have taken the OS course :-) 

Thanks in advance,
Kwong 

osh@cbnewsh.ATT.COM (david.a.oshinsky) (04/25/89)

The following program demonstrates how to handle timer interrupts
from Turbo C.
			Hope this helps,
			David Oshinsky
			AT&T Bell Laboratories
			Holmdel, NJ
		phone:	(201)949-0037
		uucp:	att!houxs!osh

------------------------- Cut here --------------------------
/* 8253 timer test program for Turbo C 1.5/2.0.		   */
/* Author:  David Oshinsky, 11/14/88.			   */

/* This program demonstrates how to use counter 0 in the   */
/* 8253 chip to provide "real-time clock" functions on the */
/* IBM PC or PC/AT.					   */

/* SOME QUICK INFO ON PC INTERRUPTS:			   */
/* The interrupt lines INT2 through INT7 appear on the PC  */
/* bus.  INT0 and INT1 appear only on the motherboard.     */
/* Interrupt line usage is as follows:			   */
/*	INT0 is used by counter 0 of the 8253 programmable */
/*		interval timer chip			   */
/*	INT1 is used by the keyboard			   */
/*	INT5 is used by the hard disk controller	   */
/*	INT6 is used by the floppy disk controller	   */

/* The above is not completely accurate when applied to	   */
/* the PC/AT; however, the timer interrupt uses INT0 on	   */
/* both the PC and PC/AT.  (This program works on both the */
/* PC and the PC/AT.)					   */

/* The 8259 Peripheral Interrupt Controller (PIC) chip	   */
/* maps the INTx line to interrupt number x+8 (this is	   */
/* programmable, set by MS-DOS).  Hence, the timer	   */
/* interrupt is number 8.				   */

#include <dos.h>

#define ZERO_FLAG	0x040
#define CONTROL_C	3
#define MS_PER_TICK	53	/* milliseconds per IBM PC clock tick */

unsigned long count;
unsigned ticks;
void interrupt timer(), interrupt (*old_handler)();

main()
{
	union REGS sreg, rreg;

	/* time starts at zero */
	count = 0;
	ticks = 0;

	/* initializations related to MS-DOS call to read keyboard */
	sreg.x.dx = 0xff;
	sreg.h.ah = 0x06;
	
	printf("\nTo stop the timer test program, type CTRL-C.");
	printf("\nTo display time since starting the program, hit any key.");
	printf("\nThe time is accurate to roughly the nearest 1 msec.\n\n");
	
	/* Save the address of the current timer interrupt handler */
	old_handler = getvect(8);

	/* Call "timer" function when timer interrupt occurs. */
	setvect(8, timer);
	
	/* Set up 8259 PIC chip to allow INT0 interrupt. */
	outportb(0x21, inportb(0x21) & 0xfe);
	
	/* issue command to 8253:  counter 0, binary counter, rate generator */
	/* (mode 2), load least significant byte of counter followed by      */
	/* most significant byte					     */
	outportb(0x43, 0x34);
	
	/* Timer is set for 0x4cd * 813.8 ns = 1 ms (LSB followed by MSB). */
	outportb(0x40, 0xcd); /* least significant byte of timer count */
	outportb(0x40, 0x04); /* most significant byte of timer count  */
	
	while (1) {
		/* wait for keystroke */
		while ( 1 ) {
			intdos(&sreg, &rreg);
			if ( ! (rreg.x.flags & ZERO_FLAG) )
				break;
	    	}
	
		/* stop the program if ctrl-C */
		if ( (rreg.x.ax & 0xff) == CONTROL_C ) {
			/* NOTE:  the following code MUST be executed before  */
			/* returning to MS-DOS in order to allow proper	      */
			/* operation of programs which use the 8253 timer.    */
	
			/* restore 8253 to original state set during PC boot  */
			/* NOTE:  this program leaves 8259 mask register with */
			/* least significant bit clear (i.e., INT0 enabled).  */
			outportb(0x43, 0x34);
			outportb(0x40, 0);
			outportb(0x40, 0);
	
			/* restore original interrupt vector for number 8 */
			setvect(8, old_handler);
	
			printf("Timer test program returning to MS-DOS.\n");
			exit(0);
		}
		else
			printf("TIME = %lu MSEC.\n",count);
	}
}
	
/* timer interrupt service routine (interrupt number 8) */
void interrupt
timer()
{
	count++;
	
	/* chain to the MS-DOS timer handler approx. 18 times per second */
	if (++ticks == MS_PER_TICK) {
		old_handler();
		ticks = 0;
	}
	
	/* issue end-of-interrupt command to 8259 PIC chip */
	outportb(0x20, 0x20);
}