Date: Tue, 30 May 95 13:08 MDT From: mat AT ardi DOT com (Mat Hostetter) To: djgpp AT sun DOT soe DOT clarkson DOT edu Subject: Re: Manually calling iret functions References: <9505301726 DOT AA00437 AT jasmine> > 1. A protected mode handler, which does the following: > a. Increases & checks the tick count. > b. Use _go32_dpmi... to call the old interrupt. > c. Do whatever the ISR is supposed to do. Back in our pre-DPMI days, Executor used to reprogram the clock and forward every 18.2 Hz. We have since abandoned this approach, and now we patch into the 1024 Hz clock. In the old days our handler would "ljmp" down the PM interrupt chain when it wanted to forward the tick, otherwise it would issue an "end-of-interrupt" command to the timer controller (our docs are shaky on that, though). Most approaches will eat flaming death if your interrupt handler gets paged out, which is a big problem for any djgpp app that tries to use interrupts. These days all of Executor's interrupt handlers are written in assembly. They and their data are carefully locked down with the appropriate DPMI call so they can't get paged out. Here are some relevant code snippets you might (or might not) find useful. -Mat /* This reprograms the clock to a specified Hz, which need not be an int. */ #define REPROGRAM_TIMER_0(ticks_per_sec) \ asm volatile ("movb $0x36,%%al\n\t" \ "outb %%al,$0x43\n\t" \ "jmp 1f\n" \ "1:\tjmp 1f\n" \ "1:\tjmp 1f\n" \ "1:\tmovb %0,%%al\n\t" \ "outb %%al,$0x40\n\t" \ "jmp 1f\n" \ "1:\tjmp 1f\n" \ "1:\tjmp 1f\n" \ "1:\tmovb %1,%%al\n\t" \ "outb %%al,$0x40\n\t" : : \ "g" ((unsigned) ((65532 / ((ticks_per_sec) / 18.2)) + 0.5) \ & 0xFF), \ "g" (((unsigned) ((65532 / ((ticks_per_sec) / 18.2)) + 0.5) \ \ >> 8) & 0xFF) \ : "eax") ... _go32_dpmi_get_protected_mode_interrupt_vector (8, &old_handler); ... [in the timer handler]: /* See if we should forward this tick to the normal 18.2 Hz handler. */ usecs_elapsed += MICROSECONDS_PER_TICK; if (usecs_elapsed >= (1000000 * 10 / 182)) { usecs_elapsed -= 1000000 * 10 / 182; asm volatile ("cli\n\t" "pushfl\n\t" "lcall %0" : : "m" (*&old_handler.pm_offset)); } else { /* Issue end-of-interrupt command. */ asm volatile ("cli\n\t" "outb %b0,$0x20" : : "a" (0x20)); }