www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1995/05/26/08:19:49

Original-Received: by NeXT.Mailer (1.118.3)
PP-warning: Illegal Received field on preceding line
From: Timothy "J." Wood <bungi AT omnigroup DOT com>
Date: Fri, 26 May 95 04:07:59 -0700
To: djgpp AT sun DOT soe DOT clarkson DOT edu
Subject: Keyboard interrupt handler brokenness
Reply-To: tjw AT omnigroup DOT com

  I'm just starting my DOS hacking (having lived most of my life in  
Unix) and I've just written my first DJGPP interrupt handler.  This  
does some simple keyboard operations -- detecting key down and up  
and is pieced together from various pieces of examples that I've  
found laying around.

  Amazingly, it works.  Well, mostly.  Two problems.  As written  
below, eventually the keyboard will start beeping.  Presumably it's  
input buffer it filled.  In fact, when I hit escape, a bunch of  
stuff is printed out; the contents of the full buffer, I assume.

  If I uncommend the real mode handler calls in main(), the beeping  
doesn't happen, but if you type fast enough, the program will issue  
the message 'Unsupported INT 0xd' followed a keypress or two later  
by a segmentation fault.

  Anyway, the code follows.  If you have any suggestions about what  
might be going wrong, that would be much appreciated.  I've tweaked  
it every which way I can find, and I'm reading through a stacks of  
documentation I have and trying other tweaks, but this is probably  
something obvious to someone who's programmed DOS for more than a  
couple hours :)

-tim

/* key.c */
/* I'm compiling on a sparc.20 running NEXTSTEP with the following:

/usr/local/lib/djgpp/bin/gcc -Wall -B/usr/local/lib/djgpp/bin/  
-nostdinc -I/usr/local/lib/djgpp/include -O1 -c key.c

/usr/local/lib/djgpp/bin/ld -nostartfiles  
-L/usr/local/lib/djgpp/lib /usr/local/lib/djgpp/lib/crt0.o key.o  
-lpc -lc -o key

  My compiler flags will probably differ from anyone compiling
  under DOS so the above is only a suggestion of what might work
  for you.

*/

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <go32.h>
#include <dos.h>
#include <dpmi.h>
#include <pc.h>

#define KEY_INT 0x09

_go32_dpmi_seginfo oldirq_rm;
_go32_dpmi_registers rm_regs;
_go32_dpmi_seginfo rm_si;
_go32_dpmi_seginfo oldirq_pm;
_go32_dpmi_seginfo pm_si;

unsigned char key = 0;

static inline void _disable()
{
	asm __volatile__ (
		"cli"
	);
}
static inline void _enable()
{
	asm __volatile__ (
		"sti"
	);
}

static inline unsigned char inb(unsigned short port)
{
    unsigned char               data;

    asm volatile(
	"inb %1,%0"
	: "=a"(data)
	: "d"(port));

    return (data);
}

static inline void outb(unsigned short port, unsigned char data)
{
    asm volatile(
    	"outb %1,%0"
	:
	: "d" (port), "a" (data));
}

#define KEY_BUFFER 0x60
#define KEY_CONTROL 0x61
#define INT_CONTROL 0x20

static void key_intr(_go32_dpmi_registers *reg)
{
    unsigned char control;

    /* get the key */
    key = inb(KEY_BUFFER);

    /* reset the keyboard controller */
    control = inb(KEY_CONTROL);
    control |= 0x80; /* The code I saw used 0x82 here, but my docs  
say to use 0x80, why? */
    outb(KEY_CONTROL, control);
    control &= 0x7f;
    outb(KEY_CONTROL, control);

    /* ack the interrupt */
    outb(INT_CONTROL, 0x20);

    _enable();
}

static void install_rm_interrupt()
{
    int                         ret;

    rm_si.pm_offset = (int)key_intr;
    ret = _go32_dpmi_allocate_real_mode_callback_iret(&rm_si, &rm_regs);
    if (ret != 0) {
	printf("cannot allocate real mode callback, error=%04x\n", ret);
	exit(1);
    }

    _disable();
    _go32_dpmi_get_real_mode_interrupt_vector(KEY_INT, &oldirq_rm);
    _go32_dpmi_set_real_mode_interrupt_vector(KEY_INT, &rm_si);
    _enable();
}

static void cleanup_rm_interrupt()
{
    _disable();
    _go32_dpmi_set_real_mode_interrupt_vector(KEY_INT, &oldirq_rm);
    _go32_dpmi_free_real_mode_callback(&rm_si);
    _enable();
}

static void install_pm_interrupt()
{
    _disable();
    _go32_dpmi_get_protected_mode_interrupt_vector(KEY_INT, &oldirq_pm);
    pm_si.pm_offset = (int)key_intr;
    pm_si.pm_selector = _go32_my_cs();
    _go32_dpmi_chain_protected_mode_interrupt_vector(KEY_INT, &pm_si);
    _enable();
}

static void cleanup_pm_interrupt()
{
    _disable();
    _go32_dpmi_set_protected_mode_interrupt_vector(KEY_INT, &oldirq_pm);
    _enable();
}

void main(int argc, char *argv[])
{
    unsigned char               oldKey = 0;

    /*install_rm_interrupt();*/
    install_pm_interrupt();

    printf("Interrupt handlers installed\n");

    while (1) {
	if (oldKey != key) {
	    printf("key = %d\n", key);
	    if (key == 1) {
		break;
	    }
	    oldKey = key;
	}
    }

    /*cleanup_rm_interrupt();*/
    cleanup_pm_interrupt();
}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019