Lowlevel
Lowlevel => OS-Design => Thema gestartet von: jo2105 am 15. November 2012, 22:17
-
Ich bins mal wieder :-D
Ich habe damit eingefangen einen kleinen Keyboard-Treiber zu programmieren. Wenn ich aber mein makefile ausführe kriege ich die Meldung "qemu: unsupported keyboard cmd=0xf4". (Ich starte dabei qemu mit qemu -kernel kernel)
Wahrscheinlich klappt das nicht, weil ich eine USB-Tastatur habe. Allerdings wird das ja normalerweise vom BIOS emuliert. Gibt es irgendeine Möglichkeit, dass ich das auch mit qemu hinkriege? Ich fände es blöd, wenn ich nach jedem Build er das GRUB-Image machen müsste.^^
-
Hallo,
Qemu emuliert eine PS/2-Tastatur, unabhängig davon, ob dein Host-Rechner nun eine USB-Tastatur oder einen Touchscreen hat. Die Fehlermeldung deutet darauf hin, dass dein Tastaturtreiber komische (unspezifizierte) Dinge mit der Tastatur macht.
Installier mal ein Windows im Qemu, schau dir den Gerätemanager an und vergleiche mit der Hardware des Computers, auf dem du Qemu gestartet hast. Da dürfte eigentlich nix übereinstimmen.
Gruß,
Svenska
-
Hallo,
Qemu emuliert eine PS/2-Tastatur, unabhängig davon, ob dein Host-Rechner nun eine USB-Tastatur oder einen Touchscreen hat. Die Fehlermeldung deutet darauf hin, dass dein Tastaturtreiber komische (unspezifizierte) Dinge mit der Tastatur macht.
Installier mal ein Windows im Qemu, schau dir den Gerätemanager an und vergleiche mit der Hardware des Computers, auf dem du Qemu gestartet hast. Da dürfte eigentlich nix übereinstimmen.
Gruß,
Svenska
Es ist schonmal gut zu wissen, dass es an mir liegt. Jetzt muss ich nur noch den Fehler finden...
-
Was genau muss man eigentlich machen, damit ein IRQ als behandelt gilt? Ich habe den Treiber nähmlich soweit wie es im Artikel beschrieben ist, allerdings empfange ich einmal den Scancode 0xFA und das wars. Danach passiert nichts mehr, außer man sendet einen IRQ mit int.
-
Was genau muss man eigentlich machen, damit ein IRQ als behandelt gilt? Ich habe den Treiber nähmlich soweit wie es im Artikel beschrieben ist, allerdings empfange ich einmal den Scancode 0xFA und das wars. Danach passiert nichts mehr, außer man sendet einen IRQ mit int.
Du musst ein EOI senden (End of Interrupt)
Hier: http://www.lowlevel.eu/wiki/PIC_Tutorial (http://www.lowlevel.eu/wiki/PIC_Tutorial) steht wie's geht
-
Hallo,
Es ist schonmal gut zu wissen, dass es an mir liegt. Jetzt muss ich nur noch den Fehler finden...
Faustregel: Der Emulator ist deutlich fehlerfreier als der OS-Programmierer. (Ausnahmen bestätigen die Regel.)
Was genau muss man eigentlich machen, damit ein IRQ als behandelt gilt?
Normalerweise muss man einen Interrupt immer zweimal bestätigen, einmal bei dem Gerät selbst (Tastatur: durch Lesen des Datenregisters) und einmal bei dem verarbeitenden Interrupt-Controller (PIC: durch EOI-Befehl an den/die richtigen Interrupt-Controller, weil es ja zwei gibt).
Gruß,
Svenska
-
Du musst ein EOI senden (End of Interrupt)
Hier: http://www.lowlevel.eu/wiki/PIC_Tutorial (http://www.lowlevel.eu/wiki/PIC_Tutorial) steht wie's geht
Ja so etwas ähnliches habe ich im IRQ Handler eingebaut. (So stands auch im Wiki):
if(cpu->intr >= 0x20 && cpu->intr <= 0x2f) {
kprintf("IRQ %x\n", cpu->intr);
if(cpu->intr == 0x21) kb_irq_handler(cpu->intr);
if(cpu->intr >= 0x28) {
outb(0xa0, 0x20);
}
outb(0x20, 0x20);
}
/e: Das hat mir weitergeholfen. :D http://forum.lowlevel.eu/index.php?topic=2999.msg35127#msg35127
-
Ich habe mal ein paar Fragen zu dieser Funktion aus dem Wiki:
void irq_handler(uint8_t irq) {
uint8_t scancode;
uint8_t keycode = 0;
int break_code = 1;
// Status-Variablen fuer das Behandeln von e0- und e1-Scancodes
static int e0_code = 1;
// Wird auf 1 gesetzt, sobald e1 gelesen wurde, und auf 2, sobald das erste
// Datenbyte gelesen wurde
static int e1_code = 0;
static uint16_t e1_prev = 0;
scancode = inb(0x60);
// Um einen Breakcode handelt es sich, wenn das oberste Bit gesetzt ist und
// es kein e0 oder e1 fuer einen Extended-scancode ist
if ((scancode & 0x80) &&
(e1_code || (scancode != 0xE1)) &&
(e0_code || (scancode != 0xE0)))
{
break_code = 0;
scancode &= ~0x80;
return;
}
if (e0_code) {
// Fake shift abfangen und ignorieren
if ((scancode == 0x2A) || (scancode == 0x36)) {
e0_code = 1;
return;
}
keycode = translate_scancode(1, scancode);
e0_code = 1;
} else if (e1_code == 2) {
// Fertiger e1-Scancode
// Zweiten Scancode in hoeherwertiges Byte packen
e1_prev |= ((uint16_t) scancode << 8);
keycode = translate_scancode(2, e1_prev);
e1_code = 0;
} else if (e1_code == 1) {
// Erstes Byte fuer e1-Scancode
e1_prev = scancode;
e1_code++;
} else if (scancode == 0xE0) {
// Anfang eines e0-Codes
e0_code = 0;
} else if (scancode == 0xE1) {
// Anfang eines e1-Codes
e1_code = 1;
} else {
// Normaler Scancode
keycode = translate_scancode(0, scancode);
}
// Zum Testen sollte folgendes verwendet werden:
kprintf("%c", keycode);
//Nach erfolgreichen Tests, könnte eine send_key_event Funtkion wie bei Týndur verwendet werden
}
1. Warum muss e0_code am Anfang auf 1 stehen? Bei mir werden dann nur Nullen als Keycode ausgegeben.
2. Warum wird bei der Breakcodesache die Funktion verlassen. Man will doch auch wissen wovon es der Breakcode ist.
3. Warum steht nach dem if(e0_code) e0_code = 1. Das ändert doch garnichts
4. Muss das if(scancode==0xE0) nicht nach oben? Ansonsten wird doch einfach die Funktion verlassen und beim nächsten Einstieg werden die Werte wieder auf den Standard gesetzt.
-
1. Warum muss e0_code am Anfang auf 1 stehen? Bei mir werden dann nur Nullen als Keycode ausgegeben.
2. Warum wird bei der Breakcodesache die Funktion verlassen. Man will doch auch wissen wovon es der Breakcode ist.
3. Warum steht nach dem if(e0_code) e0_code = 1. Das ändert doch garnichts
Jo, da hat wohl wer beim Abtippen ins Wiki unfug gemacht. Das Original stimmt mit dir in diesen Punkten überein:
http://git.tyndur.org/?p=tyndur.git;a=blob;f=src/modules/kbc/keyboard.c;h=4fdaadcd8fbc92e518e7788fb53157c1b806a9ec;hb=HEAD#l131
4. Muss das if(scancode==0xE0) nicht nach oben? Ansonsten wird doch einfach die Funktion verlassen und beim nächsten Einstieg werden die Werte wieder auf den Standard gesetzt.
Ich weiß nicht, ob sich das mit den obigen Punkten erledigt hat, aber zu dem Punkt, dass die Werte auf den Standard gesetzt werden: Die Variablen, die als static deklariert wurden, behalten ihre alten Werte zwischen den Funktionsaufrufen und werden nur einmal beim ersten Aufruf der Funktion initialisiert.
-
1. Warum muss e0_code am Anfang auf 1 stehen? Bei mir werden dann nur Nullen als Keycode ausgegeben.
2. Warum wird bei der Breakcodesache die Funktion verlassen. Man will doch auch wissen wovon es der Breakcode ist.
3. Warum steht nach dem if(e0_code) e0_code = 1. Das ändert doch garnichts
Jo, da hat wohl wer beim Abtippen ins Wiki unfug gemacht. Das Original stimmt mit dir in diesen Punkten überein:
http://git.tyndur.org/?p=tyndur.git;a=blob;f=src/modules/kbc/keyboard.c;h=4fdaadcd8fbc92e518e7788fb53157c1b806a9ec;hb=HEAD#l131
4. Muss das if(scancode==0xE0) nicht nach oben? Ansonsten wird doch einfach die Funktion verlassen und beim nächsten Einstieg werden die Werte wieder auf den Standard gesetzt.
Ah ok. So wie es in Tyndur ist, sieht meine Funktion auch aus.
Das mit dem static wusste ich noch gar nicht, gut zu wissen.
Ich weiß nicht, ob sich das mit den obigen Punkten erledigt hat, aber zu dem Punkt, dass die Werte auf den Standard gesetzt werden: Die Variablen, die als static deklariert wurden, behalten ihre alten Werte zwischen den Funktionsaufrufen und werden nur einmal beim ersten Aufruf der Funktion initialisiert.
-
Mal ganz von dem Interruptproblem abgesehen, ist 0xFA kein Scancode sondern ein ACK vom Keyboard auf einen vorangegangenen Befehl.
Die sollten immer nach den Befehlen aus dem Buffer genommen werden.