Autor Thema: Keyboard Controller  (Gelesen 7240 mal)

bscreator

  • Gast
Gespeichert
« am: 08. February 2010, 17:16 »
Hallo,

ich hab ein Problem mit meinem Keyboard Controller.
Ich versuche, einen Keyboard Self Test mit
mov al,0xAA
out 0x64,al
in al,0x60
Im Register AL steht jedoch anstatt 0x55 (für successful) noch die 0xAA.

Mach ich irgendwas falsch ?

Viele Grüße,
bsc

Cool-Andy

  • Gast
Gespeichert
« Antwort #1 am: 08. February 2010, 17:49 »
Ich bin mir nicht sicher, aber musst du 0x60 nicht erst leeren, bevor du in 0x64 schreiben kannst?

Also:
in al, 0x60
mov al, 0xAA
out 0x64, al
in al, 0x60

Ich hoffe es war richtig, was ich gesagt habe!  8-)

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 08. February 2010, 18:29 »
Außerdem solltest du mit dem Lesen warten, bis der KBC was in den Ausgabepuffer geschrieben hat.
Dieser Text wird unter jedem Beitrag angezeigt.

bscreator

  • Gast
Gespeichert
« Antwort #3 am: 08. February 2010, 19:17 »
Also leeren kann man den KBC mit dem Auslesen des Ports 0x60 nicht!
Warten bringt auch nichts.
Hab das Auslesen und vergleichen mit 0x55 schon in eine Endlosschleife gepackt, aber da würd der Assembler wahrscheinlich die ganze Nacht durchlaufen.

rizor

  • Beiträge: 521
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 08. February 2010, 19:43 »
War es nicht so, dass du bei dem Selftest eine gewisse Zeit warten musst?
Errinnere mich da eine eine Warte-Funktion
Programmiertechnik:
Vermeide in Assembler zu programmieren wann immer es geht.

bscreator

  • Gast
Gespeichert
« Antwort #5 am: 09. February 2010, 16:12 »
Naja,
im Grunde gehts mir nur darum, ohne Verwendung der Interrupts von der Tastatur lesen zu können.
Kennt ihr da noch nen anderen Weg außer über die Ports ?

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 09. February 2010, 17:22 »
Nein, es gibt keinen anderen Weg. I/O-Ports sind dazu da, um mit Geräten zu kommunizieren.
Dieser Text wird unter jedem Beitrag angezeigt.

bscreator

  • Gast
Gespeichert
« Antwort #7 am: 10. February 2010, 13:26 »
OK,
kennt ihr dann einen kleinen Codeabschnitt, mit dem man eine Taste unter Verwendung von Ports von der Tastatur liest ?

Vielen Dank,
bsc

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #8 am: 10. February 2010, 13:56 »
#define KBD_DATA 0x60
#define KBD_CTRL 0x64

#define KBD_OBF 0x01 // output buffer full

/* scancode in zeichen umwandeln, gibt 0 zurück, wenn der scancode kein zeichen ist */
char keyb_decode(unsigned char code);

char keyb_read_char()
{
char c;

do {
while (!(inb(KBD_CTRL) & KBD_OBF));
c = keyb_decode(inb(KBD_DATA));
} while (c == 0);

return c;
}
« Letzte Änderung: 11. February 2010, 13:48 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

bscreator

  • Gast
Gespeichert
« Antwort #9 am: 10. February 2010, 17:37 »
Dann müsst das ganze in Assembler ungefähr so aussehen, oder ?
start:
in al,0x64      ;lese von Command-Port
mov ah,0x01
cmp al,ah     
jne start       ;wenn Input-Buffer leer

read:           
in al,0x60     ;lese von Data-Port
mov ah,0x00
cmp ah,al
je read

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 10. February 2010, 21:06 »
Hi,

nicht ganz. Änderungen sind mit Pfeilen markiert.

start:
in al,0x64      ;lese von Command-Port
mov ah,0x01
test al,ah      ; <------------ test statt cmp, weil du nur ein bit testen willst
jz start       ;wenn Output-Buffer leer <----- edit: muss hier natürlich auch jz heißen

read:           
in al,0x60     ;lese von Data-Port
;<--------------- und hier jetzt den Scancode (al) verarbeiten. das mit keyb_decode ist vielleicht zu verwirrend gewesen. das hätte ich da nicht einfügen sollen.
« Letzte Änderung: 11. February 2010, 13:49 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

bscreator

  • Gast
Gespeichert
« Antwort #11 am: 11. February 2010, 11:40 »
Hi  PorkChicken,

habs jetzt mal so ausprobiert, also die getkey-Methode vom StupidOS-Kernel
getkey:
mov ah, 0 ; Funktion 0
int 016h ; Ausführen
ret

durch diese getkey-Methode
getkey:
in al,0x64
mov ah,0x01
test al,ah
jne getkey
in al,0x60
ret
ersetzt.

Aber das einzige, was Bochs dann macht, ist eine Endlosschleife, bzw. es wartet nicht auf einen Tastendruck, sondern es startet den Bootloader und den Kernel immer wieder.

Wenn du aber die Zeile jne getkey durch je getkey ersetzt, dann funktioniert es komischerweise

Habt ihr ne Ahnung, warum ?


« Letzte Änderung: 11. February 2010, 11:46 von bscreator »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 11. February 2010, 12:24 »
Weil "je" ja das gleiche ist wie "jz". Und "jz" ist hier natürlich der richtige Sprung.

Das heißt er springt solange immer wieder zu "getkey", wie das Bit 1 (also OBF) null ist. Er wartet also, bis es gesetzt ist, was ja auch dem Sinn des OBF-Flags entspricht.
« Letzte Änderung: 11. February 2010, 13:50 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

bscreator

  • Gast
Gespeichert
« Antwort #13 am: 11. February 2010, 12:29 »
OK,
das heißt also, dass es bei Bochs "je" heißen muss.
Wenn ich das ganze aber dann unter REALEN Bedingungen, sprich den Rechner neu starten und von Floppy booten lass, testen möchte, muss es "jne" heißen, oder ?
« Letzte Änderung: 11. February 2010, 12:37 von bscreator »

Jidder

  • Administrator
  • Beiträge: 1 625
    • Profil anzeigen
Gespeichert
« Antwort #14 am: 11. February 2010, 13:48 »
Unter Bochs und realem PC muss der selbe Code funktionieren. Ich verstehe nicht, wie du darauf kommst, dass es jne sein sollte.

Ich muss bei meinen Posts allerdings auch ein Detail richtig stellen: Das was ich in meinen vorherigen Posts fälschlicherweise als Input Buffer bezeichnet habe, ist der Output Buffer. Wir lesen ja den Keyboard Controller aus. Im Wiki stehts natürlich richtig.
« Letzte Änderung: 11. February 2010, 13:52 von PorkChicken »
Dieser Text wird unter jedem Beitrag angezeigt.

bscreator

  • Gast
Gespeichert
« Antwort #15 am: 11. February 2010, 14:33 »
Du meinst
;Warten bis der Eingabepuffer leer ist
wait1:
in   al, 0x64
test al, 00000010b
jne  wait1
 
;Befehl 0xD1 zum schreiben des Inputports an den KBC senden
mov  al, 0xD1
out  0x64, al
 
;Wieder warten bis der Eingabepuffer leer ist
wait2:
in   al, 0x64
test al, 00000010b
jne  wait2
 
;Den neuen Wert für den Inputport über Port 0x60 senden
mov  al, 0xFE
out  0x60, al

Zitat
Unter Bochs und realem PC muss der selbe Code funktionieren.
Sorry, aber da muss ich Dir widersprechen. Hab schon etliche Ereignisse gehabt, wo der Code zwar unter Bochs, aber nicht beim REALEN PC-Reset funktioniert hat.


XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #16 am: 11. February 2010, 16:45 »
Wenn Code zwar unter bochs, aber nicht auf einer echten Maschine funktioniert, dann heißt das trotzdem, dass der Code, der auf echter Hardware läuft, auch auf bochs geht (zumindest gehen sollte).

Bei jz vs. jnz ist es aber so, dass sich beide Codes gegenseitig ausschließen würden. Und das ist ja was anderes. PorkChicken hat sich da wohl einfach vertan, als er dein cmp mit jne übernommen hat. Bei test müsste es eben je/jz sein -- das hat er ja jetzt auch in seinem entsprechenden Code korrigiert.

Und, nein, PorkChicken meinte nicht den Inportport, sondern den Inputbuffer vs. Outputbuffer (Inputbuffer zum Senden von Befehlen, Outputbuffer zum Lesen von Scancodes).
« Letzte Änderung: 11. February 2010, 16:48 von XanClic »

bscreator

  • Gast
Gespeichert
« Antwort #17 am: 11. February 2010, 19:59 »
Zitat
(zumindest gehen sollte)
Das mein ich

Zitat
jz vs. jnz ist es aber so, dass sich beide Codes gegenseitig ausschließen würden
Da hast du allerdings auch wieder recht.

OK. Das Verarbeiten von Scan-Codes funktioniert.
Aber wie kann ich Zeichen auslesen, sprich ASCII-Codes ?

XanClic

  • Beiträge: 261
    • Profil anzeigen
    • github
Gespeichert
« Antwort #18 am: 11. February 2010, 20:12 »
Zitat von: bscreator
Zitat
(zumindest gehen sollte)
Das mein ich
Ich dachte, du meinst das erste (also dass Code, der auf bochs geht, auf echter Hardware nicht geht). Denn normalerweise läuft jeder Code, der auf echter Hardware geht, auch auf bochs (wobei ich da mal Probleme mit so einem Bit in cr4 hatte)...

Zitat von: bscreator
Aber wie kann ich Zeichen auslesen, sprich ASCII-Codes ?
Das ist die Funktion, die PorkChicken anfangs als keyb_decode() bezeichnet hat. Zur Liste der Scancodes siehe z. B. http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html (aus dem Wiki).

bscreator

  • Gast
Gespeichert
« Antwort #19 am: 11. February 2010, 21:00 »
1. Dann muss ich jetzt für jeden Buchstaben den Hex-Code manuell auswerten, oder ?
Also:
falls Scancode==0x1e, dann Ausgabe 'A'
falls Scancode==0x30, dann Ausgabe 'B'
...

2. Konnte man Tasten auch schon beim 8086 mit Hilfe von Ports auslesen, oder erst ab dem 80286 ?

 

Einloggen