Keyboard interrupt handler for own kernel (C)

2019-05-18 00:11发布

问题:

I am writing a tiny OS as part of an assigment for school,but I got stuck when it comes to get keyboard input (press a key -> display it on screen). I am using the Bare Bones tutorial from osdev.org (gcc cross-compiler, GRUB bootloader, ld linker) and since I am in protected mode I can not use BIOS interrupts for input, that's why I have to write my own interrupt handler (?) but I'm not sure how to do that even after I read some osdev articles and forum discussions. Very similar problem (http://forum.osdev.org/viewtopic.php?f=1&t=9746) except that I don't know how to "set up the interrupts".

#if !defined(__cplusplus)
#include <stdbool.h> /* C doesn't have booleans by default. */
#endif
#include <stddef.h>
#include <stdint.h>
#define INT_DISABLE 0
#define INT_ENABLE  0x200
#define PIC1 0x20
#define PIC2 0xA0

#define ICW1 0x11
#define ICW4 0x01

void outb( unsigned short port, unsigned char val )
{
   asm volatile("outb %0, %1" : : "a"(val), "Nd"(port) );
}

static __inline unsigned char inb (unsigned short int port)
{
  unsigned char _v;

  __asm__ __volatile__ ("inb %w1,%0":"=a" (_v):"Nd" (port));
  return _v;
}

void init_pics(int pic1, int pic2)
{
   /* send ICW1 */
   outb(PIC1, ICW1);
   outb(PIC2, ICW1);

   /* send ICW2 */
   outb(PIC1 + 1, pic1);   
   outb(PIC2 + 1, pic2);   

   /* send ICW3 */
   outb(PIC1 + 1, 4);   
   outb(PIC2 + 1, 2);

   /* send ICW4 */
   outb(PIC1 + 1, ICW4);
   outb(PIC2 + 1, ICW4);

   /* disable all IRQs */
   outb(PIC1 + 1, 0xFF);
}

/*irrelevant code*/


#if defined(__cplusplus)
extern "C" /* Use C linkage for kernel_main. */
#endif
void kernel_main()
{
    terminal_initialize();

    char c;     
    init_pics(0x20, 0x28);
    c = inb(0x60);
    terminal_putchar(c);
}

This is printing me a white box.If I try listening to port 0x64 I get some different character. I don't expect this to work, because I don't have the interrupt. I think it should be something like

void _interrupt button_pressed()
{
/*code*/
}

if(button_pressed)
{
    c = inb(0x60);
    //code to translate the char to ASCII
    terminal_putchar(asciiChar);
}

Any help is appreciated. Thanks

回答1:

If there is someone interested how I solved the problem, here is the solution

char c = 0;
init_pics(0x20, 0x28);
do
{

if(inb(0x60)!=c) //PORT FROM WHICH WE READ
{
    c = inb(0x60);
    if(c>0)
        {

            terminal_putinput(c); //print on screen

        }
    }


}
while(c!=1); // 1= ESCAPE

c variable contains the code of the pressed button. Creating a translation array by associating to each code, the corresponding ASCII code, I can print the letter/number which is written on button.

The buttons code can be found here: http://www.nondot.org/sabre/os/files/HCI/keyboard.txt

The ASCII here: http://www.ascii-code.com/