Autor Thema: QEMU + Tastaturtreiber  (Gelesen 8816 mal)

jo2105

  • Beiträge: 58
    • Profil anzeigen
Gespeichert
« 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.^^

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #1 am: 15. November 2012, 23:26 »
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

jo2105

  • Beiträge: 58
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 16. November 2012, 07:07 »
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...

jo2105

  • Beiträge: 58
    • Profil anzeigen
Gespeichert
« Antwort #3 am: 16. November 2012, 17:53 »
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.

micha

  • Beiträge: 141
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 16. November 2012, 20:04 »
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 steht wie's geht

Svenska

  • Beiträge: 1 792
    • Profil anzeigen
Gespeichert
« Antwort #5 am: 16. November 2012, 20:31 »
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

jo2105

  • Beiträge: 58
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 17. November 2012, 13:33 »
Du musst ein EOI senden (End of Interrupt)
Hier: 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
« Letzte Änderung: 17. November 2012, 15:28 von jo2105 »

jo2105

  • Beiträge: 58
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 18. November 2012, 11:25 »
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.

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 18. November 2012, 16:58 »
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.
Dieser Text wird unter jedem Beitrag angezeigt.

jo2105

  • Beiträge: 58
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 18. November 2012, 17:51 »
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.

livinskull

  • Beiträge: 27
    • Profil anzeigen
    • Livinskulls site
Gespeichert
« Antwort #10 am: 20. November 2012, 14:48 »
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.


 

Einloggen