Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: bscreator 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
-
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-)
-
Außerdem solltest du mit dem Lesen warten, bis der KBC was in den Ausgabepuffer geschrieben hat.
-
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.
-
War es nicht so, dass du bei dem Selftest eine gewisse Zeit warten musst?
Errinnere mich da eine eine Warte-Funktion
-
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 ?
-
Nein, es gibt keinen anderen Weg. I/O-Ports sind dazu da, um mit Geräten zu kommunizieren.
-
OK,
kennt ihr dann einen kleinen Codeabschnitt, mit dem man eine Taste unter Verwendung von Ports von der Tastatur liest ?
Vielen Dank,
bsc
-
#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;
}
-
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
-
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.
-
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 ?
-
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.
-
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 ?
-
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.
-
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
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.
-
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).
-
(zumindest gehen sollte)
Das mein ich
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 ?
-
(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)...
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).
-
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 ?
-
Normalerweise macht man so eine Auswertung eher mit einem Array (wo man dann den Scancode als Index verwendet und dass dann den ASCII-Code zurückliefert) als mit vielen If-Abfragen.
Und das mit den Ports: Wie willst du die denn sonst auslesen? :?
-
Normalerweise macht man so eine Auswertung eher mit einem Array (wo man dann den Scancode als Index verwendet und dass dann den ASCII-Code zurückliefert) als mit vielen If-Abfragen.
Ist schon klar. Was ich damit sagen wollte ist, dass es aber keine einfache mathematische Formel gibt, um vom Scancode auf den ASCII-Wert zu schließen,oder ?
Und das mit den Ports frag ich, weil auf
http://lowlevel.brainsware.org/wiki/index.php/Keyboard_Controller
folgendes drinsteht :
"Der KBC wurde mit dem AT System (286) eingeführt. "
Also: Wie einen KBC auslesen, wenns den erst ab dem 286 gibt ?
-
Normalerweise macht man so eine Auswertung eher mit einem Array (wo man dann den Scancode als Index verwendet und dass dann den ASCII-Code zurückliefert) als mit vielen If-Abfragen.
Ist schon klar. Was ich damit sagen wollte ist, dass es aber keine einfache mathematische Formel gibt, um vom Scancode auf den ASCII-Wert zu schließen,oder ?
Soweit ich weiß, nicht, aber ich wäre dankbar, wenn du mir eine solche liefern könntest. :wink:
Und das mit den Ports frag ich, weil auf
http://lowlevel.brainsware.org/wiki/index.php/Keyboard_Controller
folgendes drinsteht :
"Der KBC wurde mit dem AT System (286) eingeführt. "
Also: Wie einen KBC auslesen, wenns den erst ab dem 286 gibt ?
1. Was heißt "erst"? Hast du noch einen 8086 oder 80186 zu Hause rumliegen?
2. Dann gabs vorher wohl andere Standards (oder vielleicht ja auch gar keinen), ich bin mir aber ziemlich sicher, dass das dann auch über Ports funktionierte. Und wenn da nichts dokumentiert ist, muss man eben das BIOS nehmen (ein 8086 oder 80186 kommt ja noch gar nicht in den PM, deshalb ist das BIOS ja immer verfügbar).
-
Damals hast du glaube ich mit der Tastatur direkt geredet und erst mit PS/2 kam dann der Controller dazu, mit dem man dann auch ne Maus ansprechen konnte. Wenn mein Protected-Mode OS macht, ist das aber sowieso egal, denn den gibts ja schließlich erst mit dem 386iger (zumindest in der 32Bit Variante des PM).
-
Damals hast du glaube ich mit der Tastatur direkt geredet
Ähm, das versteh ich nicht richtig.
Jetzt kommuniziere ich doch auch mit der Tastatur direkt und nicht über den ab dem 286 eingeführten Keyboard Controller, oder ?
Was heißt "erst"? Hast du noch einen 8086 oder 80186 zu Hause rumliegen?
Hab zuhause noch nen 8086 und der ist mein absolutes Sahnetörtchen. :-D
Noch ne Frage:
Die Interrupts vom BIOS werden wohl auch über Ports kommunizieren. Wie kann ich mit der Tastatur DIREKT kommunizieren ?
Gruss,
bsc
-
Noch ne Frage:
Die Interrupts vom BIOS werden wohl auch über Ports kommunizieren. Wie kann ich mit der Tastatur DIREKT kommunizieren ?
Guck dich mal im Linux-Kernel um, die haben Tastaturtreiber für XT-Tastaturen und ähnliches drin, aber die laufen _alle_ über einen Fremdanschluss, d.h. Parallelport oder so. Die Tastatur kannst du über den normalen Anschluss nicht direkt ansprechen.
Der XT (8086/8088) nutzt übrigens einen anderen Tastaturstandard, in dem man der Tastatur nichts senden kann. Also elektrisch gibt die Tastatur den Takt und die Daten vor und der Rechner muss es nehmen oder es lassen. Ab dem AT (80286) kam dann das AT-Tastaturprotokoll dazu und dort kann man der Tastatur auch Befehle schicken (z.B. LEDs an/aus), und um das vernünftig hinzukriegen, gibt es den KBC. Die Tastatur gibt übrigens trotzdem den Takt vor. :-) Aus dem Grund funktionieren XT-Tastaturen nicht mit einem modernen PC (und in der Übergangsphase gab es Jumper oder DIP-Schalter zum Umschalten).
Mit der PS/2-Baureihe hat IBM dann den PS/2-Anschluss eingeführt, der sich aber elektrisch und protokolltechnisch nicht vom AT-Tastaturanschluss unterscheidet, nur der Controller auf PC-Seite wurde erweitert/ersetzt und der kann jetzt zusätzlich auch Mäuse ansprechen. Für die Tastatur blieb alles beim alten.
Wie man eine XT-Tastatur ohne BIOS anspricht, weiß ich nicht, es gibt aber gute elektrische Beschreibungen (für Mikrocontroller oder so) im Internet...
So, ich hoffe, nicht genervt zu haben.
Gruß,
Svenska
-
Der XT (8086/8088) nutzt übrigens einen anderen Tastaturstandard, in dem man der Tastatur nichts senden kann.
Dann ist man aber über die BIOS-Interrupts flexibler (da diese sowohl für XT, als auch für AT-Tastaturen funktionieren), oder ?
-
Wenn du ein Realmode OS baust ist es sowieso nicht ungeschickt die BIOS-Interrupts zu nehmen. Bei einem Protected Mode OS findest du (wahrscheinlich) eh keine Uralttastatur und willst sowieso keine BIOS-Interrupts nehmen (abgesehen von VESA BIOS Extensions vielleicht).