| Zeile 1: | Zeile 1: | ||
| − | Der '''Keyboard-Controller''' oder auch '''KBC''' ist ein Baustein auf dem Mainboard und dient (unter anderem) der Tastaturansteuerung. | + | Der '''Keyboard-Controller''' oder auch '''KBC''' ist ein Baustein auf dem Mainboard und dient (unter anderem) der Tastaturansteuerung. Ursprünglich von IBM entwickelt, wurde der Keyboard-Controller in seiner Funktion stark erweitert, wodurch sich heutzutage viele Aufgaben über selbigen erledigen lassen. |
| − | Der KBC wurde mit dem AT System ( | + | Der KBC wurde mit dem AT-System (i286) eingeführt. Im Vorgängersystem XT wurde für vergleichbare Aufgaben das Programmable Peripheral Interface (PPI) genutzt. |
== Funktionen des KBC == | == Funktionen des KBC == | ||
*Ansteuerung eines oder zweier Auxiliary Port(s) (Tastatur, Maus) | *Ansteuerung eines oder zweier Auxiliary Port(s) (Tastatur, Maus) | ||
| − | * | + | *Ein-/ausschalten der 21. Adressleitung ([[A20-Gate]]) |
| − | *CPU-Reset auslösen, also | + | *CPU-Reset auslösen, also Neustart des Systems |
*Zusammen mit dem [[Programmable Interval Timer | PIT]] den [[Systemlautsprecher]] ansteuern. | *Zusammen mit dem [[Programmable Interval Timer | PIT]] den [[Systemlautsprecher]] ansteuern. | ||
| − | *Information ob das System eine Monochrom- oder Farbgrafikkarte benutzt (Irrelevant | + | *Information darüber, ob das System eine Monochrom- oder Farbgrafikkarte benutzt (Irrelevant, da Farbgrafik bereits mit XT-Systemen als Standard eingeführt wurde!) |
| − | <br> | + | <br /> |
== Kommunikationswege == | == Kommunikationswege == | ||
| − | <br> | + | <br /> |
http://img441.imageshack.us/img441/636/kbclogic20071105bt5.png | http://img441.imageshack.us/img441/636/kbclogic20071105bt5.png | ||
| − | <br> | + | <br /> |
| − | <br> | + | <br /> |
| − | Normalerweise wird der erste Auxiliary Port (PSAUX0*) für eine Tastatur verwendet und an den zweiten (PSAUX1*) | + | Normalerweise wird der erste Auxiliary Port (PSAUX0*) für eine Tastatur verwendet und an den zweiten (PSAUX1*) eine Maus oder ein anderes Zeigegerät angeschlossen. Technisch unterscheiden sich die beiden Ports nicht. Daher kann man dort beliebige Gerätekombinationen anschließen, solange das BIOS nicht mit einer Fehlermeldung stoppt, weil es bestimmte Geräte an bestimmten Ports erwartet. Beliebige Gerätekombinationen werden z. B. von Linux unterstützt, nicht jedoch von Windows.<br /> |
| − | (*Anmerkung zu PSAUX0 und PSAUX1: Diese Begriffe habe ich mir | + | (*Anmerkung zu PSAUX0 und PSAUX1: Diese Begriffe habe ich mir „ausgedacht“, da ich keine vernünftige offizielle Bezeichnung kenne. Man wird diese Begriffe also in keiner anderen Referenz finden, außer es wurde hier abgeschrieben.) |
| − | <br> | + | <br /> |
== USB Legacy Support == | == USB Legacy Support == | ||
| − | Diese von vielen Mainboards bereitgestellte Funktion simuliert angeschlossene USB-Geräte wie Maus und Tastatur als PS/2 Geräte.<br> | + | Diese von vielen Mainboards bereitgestellte Funktion simuliert angeschlossene USB-Geräte wie Maus und Tastatur als PS/2-Geräte.<br /> |
| − | <br> | + | <br /> |
| − | Dies hat für Programmierer Vor- und Nachteile. Einerseits muss man für die Unterstützung solcher Eingabegeräte keine eigenen USB Treiber programmieren. Andererseits | + | Dies hat für Programmierer Vor- und Nachteile. Einerseits muss man für die Unterstützung solcher Eingabegeräte keine eigenen USB-Treiber programmieren. Andererseits können damit folgende Probleme auftreten:<br /> |
| − | *Auf manchen Systemen | + | *Auf manchen Systemen läuft IMMER eine Abstraktionsschicht mit, auch wenn keine USB-Geräte angeschlossen sind. Dies kann zur Folge haben, dass die Intellimaus-Extension nicht funktioniert. Oder dass man nicht, wie weiter oben beschrieben, beliebige Geräte an einen PSAUX-Port anschließen kann (werden nicht erkannt). |
| − | *Das [[SMM|SMM BIOS]], über welches die USB zu PS/2 Abstraktion stattfindet, | + | *Das [[SMM|SMM-BIOS]], über welches die USB-zu-PS/2-Abstraktion stattfindet, unterstützt nicht immer den Betrieb über 32-Bit-[[Protected Mode|Protected-Mode]]. Die Benutzung erweiterter Speichertechniken oder des [[Long Mode]] kann das System daher zum Absturz bringen! |
| − | <br> | + | <br /> |
| − | Diese Probleme sind nicht mehr vorhanden wenn der Legacy-Modus ausgeschaltet wurde. Dies geschieht während der Initialisierung des USB-Hostcontrollers. | + | Diese Probleme sind nicht mehr vorhanden, wenn der Legacy-Modus ausgeschaltet wurde. Dies geschieht während der Initialisierung des USB-Hostcontrollers. |
== Programmieren des KBC == | == Programmieren des KBC == | ||
| − | Programmiert wird der KBC über die | + | Programmiert wird der KBC über die zwei Ports 0x60 und 0x64. Dabei werden auf den Ports nur Bytes gesendet und empfangen.<br /> |
| − | <br> | + | <br /> |
| − | Über den Port 0x64 kann man das Statusregister auslesen und KBC-Befehle senden.<br> | + | Über den Port 0x64 kann man das Statusregister auslesen und KBC-Befehle senden.<br /> |
| − | <br> | + | <br /> |
| − | Der Port 0x60 dient als Ein-/Ausgabe Puffer. Parameter oder Rückgabewerte für einen Befehl werden über diesen Port geschrieben bzw. gelesen. Wenn keine Befehlsparameter erwartet werden und man auf den Port 0x60 schreibt, wird direkt an PSAUX0 weitergeleitet.<br> | + | Der Port 0x60 dient als Ein-/Ausgabe-Puffer. Parameter oder Rückgabewerte für einen Befehl werden über diesen Port geschrieben bzw. gelesen. Wenn keine Befehlsparameter erwartet werden und man auf den Port 0x60 schreibt, wird direkt an PSAUX0 weitergeleitet.<br /> |
*Vor dem Schreiben auf Port 0x60 oder 0x64 muss der Eingabepuffer leer sein. (Port[0x64].Bit[1] == 0) | *Vor dem Schreiben auf Port 0x60 oder 0x64 muss der Eingabepuffer leer sein. (Port[0x64].Bit[1] == 0) | ||
| Zeile 49: | Zeile 49: | ||
=== Statusregister === | === Statusregister === | ||
| − | + | Wird vom Port 0x64 gelesen und ist folgendermaßen aufgebaut: | |
<pre> | <pre> | ||
Bit 76543210 | Bit 76543210 | ||
| − | │││││││└─ Status des Ausgabepuffers (KBC -> CPU) : | + | │││││││└─ Status des Ausgabepuffers (KBC -> CPU): 0=leer; 1=voll (es kann von Port 0x60 gelesen werden) |
| − | ││││││└── Status des Eingabepuffers (KBC <- CPU) : | + | ││││││└── Status des Eingabepuffers (KBC <- CPU): 0=leer (Schreiben auf 0x60 oder 0x64 möglich); 1=voll |
│││││└─── 1=Erfolgreicher Selbsttest (Wie Controller_Command_Byte.Bit[3]; sollte immer 1 sein) | │││││└─── 1=Erfolgreicher Selbsttest (Wie Controller_Command_Byte.Bit[3]; sollte immer 1 sein) | ||
| − | ││││└──── zuletzt benutzter Port : 0=0x60; | + | ││││└──── zuletzt benutzter Port: 0=0x60; 1=0x61 oder 0x64? |
| − | │││└───── Tastatursperre : 0=Tastatur gesperrt; 1=Tastatur nicht gesperrt | + | │││└───── Tastatursperre: 0=Tastatur gesperrt; 1=Tastatur nicht gesperrt |
││└────── PSAUX? | ││└────── PSAUX? | ||
| − | │└─────── Timeout : 1=Tastatur oder PSAUX-Gerät | + | │└─────── Timeout: 1=Tastatur oder PSAUX-Gerät reagiert nicht? |
| − | └──────── Paritätsfehler : 1=Beim letzten Byte | + | └──────── Paritätsfehler: 1=Beim letzten gesendeten/empfangenen Byte trat ein Paritätsfehler auf |
</pre> | </pre> | ||
| − | <br> | + | <br /> |
=== Input Port P1 === | === Input Port P1 === | ||
| − | Nur aus Vollständigkeitsgründen hier aufgeführt | + | Nur aus Vollständigkeitsgründen hier aufgeführt! Wie man auf einem kurzen Blick erkennen kann, sind diese Werte heute nicht mehr relevant. Gelesen wird er über den KBC-Befehl 0xC0. |
| − | |||
<pre> | <pre> | ||
Bit 76543210 | Bit 76543210 | ||
| Zeile 74: | Zeile 73: | ||
│││└───── Speicher auf dem Mainboard: 0= 512 KB, 1= 256 KB | │││└───── Speicher auf dem Mainboard: 0= 512 KB, 1= 256 KB | ||
│││ | │││ | ||
| − | ││└────── Manufacturing jumper 0= installed, 1= not installed | + | ││└────── Manufacturing jumper 0=installed, 1=not installed |
││ with jumper the BIOS runs an infinite diagnostic loop | ││ with jumper the BIOS runs an infinite diagnostic loop | ||
│└─────── Grafikkarte: 0=Color Graphics Adapter (CGA), 1=Monochrome Display Adapter (MDA) | │└─────── Grafikkarte: 0=Color Graphics Adapter (CGA), 1=Monochrome Display Adapter (MDA) | ||
| − | │ Kleiner | + | │ Kleiner Tipp: CGA wurde mit den XT-System eingeführt. ;) |
| − | └──────── Tastatursperre : 0=Tastatur gesperrt; | + | └──────── Tastatursperre: 0=Tastatur gesperrt; 1=Tastatur nicht gesperrt |
</pre> | </pre> | ||
| − | <br> | + | <br /> |
=== Outputport === | === Outputport === | ||
| − | + | Wird mit dem KBC-Befehl 0xD0 ausgelesen und per 0xD1 geschrieben: | |
| − | |||
<pre> | <pre> | ||
Bit 76543210 | Bit 76543210 | ||
| Zeile 96: | Zeile 94: | ||
└──────── ? Keyboard data out | └──────── ? Keyboard data out | ||
</pre> | </pre> | ||
| − | <br> | + | <br /> |
=== Controller Command Byte === | === Controller Command Byte === | ||
| − | + | Wird mit dem KBC-Befehl 0x20 ausgelesen und per 0x60 geschrieben: | |
| − | |||
<pre> | <pre> | ||
Bit 76543210 | Bit 76543210 | ||
| − | │││││││└─ 1=Erzeuge einen | + | │││││││└─ 1=Erzeuge einen IRQ 1, wenn PSAUX0 Daten auf Port 0x60 ausgibt |
| − | ││││││└── 1=Erzeuge einen | + | ││││││└── 1=Erzeuge einen IRQ 12, wenn PSAUX1 Daten auf Port 0x60 ausgibt |
│││││└─── 1=Erfolgreicher Selbsttest (Wie Statusregister.Bit[3]; sollte immer 1 sein) | │││││└─── 1=Erfolgreicher Selbsttest (Wie Statusregister.Bit[3]; sollte immer 1 sein) | ||
││││└──── AT : 1=Tastatursperre Ignorieren (Statusregister Bit4 immer 1) | ││││└──── AT : 1=Tastatursperre Ignorieren (Statusregister Bit4 immer 1) | ||
| Zeile 115: | Zeile 112: | ||
└──────── 0 (reserviert) | └──────── 0 (reserviert) | ||
</pre> | </pre> | ||
| − | <br> | + | <br /> |
| − | <nowiki>*KBC Scancode-Übersetzung: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html#translationtable</nowiki> | + | <nowiki>*KBC-Scancode-Übersetzung: http://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html#translationtable</nowiki> |
=== KBC-Befehle === | === KBC-Befehle === | ||
| − | + | Müssen auf Port 0x64 ausgegeben werden (bevor man auf Port 0x64 schreibt, muss der Ausgabepuffer leer sein (Port[0x64].Bit[1]==0) und die Tastatur darf sich nicht mehr im Resetmodus befinden (Port[0x64].Bit[2]==1)) | |
<pre> | <pre> | ||
0xAA Tastatur-Selbsttest. Sollte 0x55 auf Port 0x60 zurückgeben. | 0xAA Tastatur-Selbsttest. Sollte 0x55 auf Port 0x60 zurückgeben. | ||
| Zeile 154: | Zeile 151: | ||
</pre> | </pre> | ||
| − | <br> | + | <br /> |
=== Tastatur-Befehle === | === Tastatur-Befehle === | ||
| − | + | Werden auf Port 0x60 ausgegeben (bevor man auf Port 0x60 schreibt, muss der Ausgabepuffer leer sein (Port[0x64].Bit[1]==0) und die Tastatur darf sich nicht mehr im Resetmodus befinden (Port[0x64].Bit[2]==1)) | |
<pre> | <pre> | ||
0xED Setzen der LEDs auf der Tastatur. Ein zweites Byte wird über Port 0x60 gesendet: | 0xED Setzen der LEDs auf der Tastatur. Ein zweites Byte wird über Port 0x60 gesendet: | ||
| Zeile 167: | Zeile 164: | ||
└┴┴┴┴──── 0 | └┴┴┴┴──── 0 | ||
| − | 0xEE Dieser Befehl ist zum | + | 0xEE Dieser Befehl ist zum Testen der Tastatur. Die Tastatur sollte mit 0xEE antworten. |
| − | 0xF0 Auswählen des Scancodes. Als Parameter den Scancode 1, 2( | + | 0xF0 Auswählen des Scancodes. Als Parameter den Scancode 1, 2 (Standard) oder 3 an Port 0x60 senden. |
| − | Mit dem Wert 0 als Parameter kann man den aktuellen Scancode auslesen | + | Mit dem Wert 0 als Parameter kann man den aktuellen Scancode von Port 0x60 auslesen |
| − | 0xF2 Diesen Befehl sendet man zum | + | 0xF2 Diesen Befehl sendet man zum Identifizieren der Tastatur. Es gibt folgende Rückgabewerte: |
| − | XT Tastatur : Timeout (leider NICHT Port[0x64].Bit[6]=1, sondern selbst zu messender Zweitwert) | + | XT-Tastatur : Timeout (leider NICHT Port[0x64].Bit[6]=1, sondern selbst zu messender Zweitwert) |
| − | AT Tastatur : Rückgabewert 0xFA | + | AT-Tastatur : Rückgabewert 0xFA |
| − | MF II Tastatur : Rückgabewert 0xFA 0xAB 0x41 | + | MF-II-Tastatur : Rückgabewert 0xFA 0xAB 0x41 |
0xF3 Setzen der Wiederholrate für gedrückte Tasten. Ein zweites Byte wird über Port 0x60 gesendet: | 0xF3 Setzen der Wiederholrate für gedrückte Tasten. Ein zweites Byte wird über Port 0x60 gesendet: | ||
| Zeile 194: | Zeile 191: | ||
│││ 11111 : 2 | │││ 11111 : 2 | ||
│││ | │││ | ||
| − | │└┴────── Wartezeit bevor eine gehaltene Taste wiederholt wird. | + | │└┴────── Wartezeit, bevor eine gehaltene Taste wiederholt wird. |
│ 00 : 250 ms | │ 00 : 250 ms | ||
│ 01 : 500 ms | │ 01 : 500 ms | ||
| Zeile 208: | Zeile 205: | ||
0xF5 Tastatur deaktivieren und Standardwerte setzen. Der Puffer wird gelöscht, | 0xF5 Tastatur deaktivieren und Standardwerte setzen. Der Puffer wird gelöscht, | ||
die LEDs werden abgeschaltet, Wiederholrate und Wartezeit werden auf | die LEDs werden abgeschaltet, Wiederholrate und Wartezeit werden auf | ||
| − | Standardwerte | + | Standardwerte zurückgesetzt und die Tastatur wird deaktiviert (es werden |
keine Tastenanschläge mehr übertragen) | keine Tastenanschläge mehr übertragen) | ||
| Zeile 216: | Zeile 213: | ||
für die Nutzung mit der CPU gedacht. | für die Nutzung mit der CPU gedacht. | ||
| − | 0xFF Tastatur-Reset und | + | 0xFF Tastatur-Reset und Selbsttest. Rückgabe 0xAA, wenn Test erfolgreich, sonst |
0xFC | 0xFC | ||
| Zeile 233: | Zeile 230: | ||
Bevor man die Tastatur benutzt, ist es ratsam, sie erst einmal in einen bekannten, | Bevor man die Tastatur benutzt, ist es ratsam, sie erst einmal in einen bekannten, | ||
sauberen Zustand zu bringen. Im | sauberen Zustand zu bringen. Im | ||
| − | [http://git.tyndur.org/?p=tyndur.git;a=blob;f=src/modules/kbc/keyboard.c Tastaturtreiber von | + | [http://git.tyndur.org/?p=tyndur.git;a=blob;f=src/modules/kbc/keyboard.c Tastaturtreiber von týndur] |
| − | hat sich nach einigem | + | hat sich nach einigem Herumexperimentieren mit verschiedenen Emulatoren die |
folgende einfache Initialisierung bewährt: | folgende einfache Initialisierung bewährt: | ||
| − | * Solange das Bit 0 im Statusregister (Puffer voll) gesetzt ist Bytes aus dem Datenregister lesen. Das hilft, wenn schon vor der Initialisierung des Treibers irgendwelche Tasten betätigt wurde, da der KBC dann keine weiteren Zeichen sendet, bis der Puffer geleert (ausgelesen wurde). Das tritt zum Beispiel im Zusammenhang mit GRUB oft auf, wenn der Benutzer die Taste zu lange gedrückt hält. | + | * Solange das Bit 0 im Statusregister (Puffer voll) gesetzt ist, Bytes aus dem Datenregister lesen. Das hilft, wenn schon vor der Initialisierung des Treibers irgendwelche Tasten betätigt wurde, da der KBC dann keine weiteren Zeichen sendet, bis der Puffer geleert (ausgelesen wurde). Das tritt zum Beispiel im Zusammenhang mit GRUB oft auf, wenn der Benutzer die Taste zu lange gedrückt hält. |
* Tastatur mit Befehl 0xF4 aktivieren. Andere Kombinationen wurden auch getestet, haben aber Probleme bereitet, unter anderem war Zeitweise ein Reset der Tastatur drin, was dazu geführt hat, dass diese unter gewissen Emulatoren überhaupt nicht mehr funktionierte. | * Tastatur mit Befehl 0xF4 aktivieren. Andere Kombinationen wurden auch getestet, haben aber Probleme bereitet, unter anderem war Zeitweise ein Reset der Tastatur drin, was dazu geführt hat, dass diese unter gewissen Emulatoren überhaupt nicht mehr funktionierte. | ||
| Zeile 270: | Zeile 267: | ||
Routine zur Behandlung der Tastatur-IRQs vor der oben angegebenen | Routine zur Behandlung der Tastatur-IRQs vor der oben angegebenen | ||
Initialisierung erfolgt, da sich sonst möglicherweise üble [[Race_Condition|Race-Conditions]] | Initialisierung erfolgt, da sich sonst möglicherweise üble [[Race_Condition|Race-Conditions]] | ||
| − | ergeben, also konkret wenn der Puffer bereits geleert wurde und noch vor dem | + | ergeben, also konkret, wenn der Puffer bereits geleert wurde und noch vor dem |
Registrieren der IRQ-Routine eine Taste gedrückt wird, dann ist der Puffer | Registrieren der IRQ-Routine eine Taste gedrückt wird, dann ist der Puffer | ||
der Tastatur voll, und sie schickt somit auch keine IRQs mehr, bis er geleert | der Tastatur voll, und sie schickt somit auch keine IRQs mehr, bis er geleert | ||
| Zeile 276: | Zeile 273: | ||
=== IRQ-Handler === | === IRQ-Handler === | ||
| − | Nun sind wir also bereit Tastendrücke von der Tastatur einzulesen. Im Folgenden wird genauer darauf eingegangen, wie wir die Tastendrücke, die wir | + | Nun sind wir also bereit, Tastendrücke von der Tastatur einzulesen. Im Folgenden wird genauer darauf eingegangen, wie wir die Tastendrücke, die wir |
| − | vom | + | vom Controller über einen IRQ signalisiert erhalten, verarbeiten können. |
Der erste und wichtigste Schritt in unserer IRQ-Behandlungsroutine ist es, | Der erste und wichtigste Schritt in unserer IRQ-Behandlungsroutine ist es, | ||
| Zeile 289: | Zeile 286: | ||
der uns angibt um welche Taste es sich handelt. Dieser Scancode hat überhaupt | der uns angibt um welche Taste es sich handelt. Dieser Scancode hat überhaupt | ||
nichts mit irgendwelchen Zeichen zu tun, er gibt uns nur, an welche Taste | nichts mit irgendwelchen Zeichen zu tun, er gibt uns nur, an welche Taste | ||
| − | gedrückt oder gelöst wurde | + | gedrückt oder gelöst wurde und muss von uns manuell mit einer Scancode-Tabelle |
in die korrespondierenden Zeichen umgewandelt werden. Dabei muss man sich | in die korrespondierenden Zeichen umgewandelt werden. Dabei muss man sich | ||
bewusst sein, dass für die Tastatur eine Steuertaste, wie zum Beispiel die | bewusst sein, dass für die Tastatur eine Steuertaste, wie zum Beispiel die | ||
| − | Umschalttaste oder Capslock, genau das | + | Umschalttaste oder Capslock, genau das selbe ist wie beispielsweise ein „a“. |
| − | Wird beispielsweise [Umschalt]+[a] gedrückt, um ein großes | + | Wird beispielsweise [Umschalt]+[a] gedrückt, um ein großes „a“ zu erhalten, schickt |
uns der Tastaturcontroller 2 Bytes, eines Umschalttaste gedrückt und ein anderes | uns der Tastaturcontroller 2 Bytes, eines Umschalttaste gedrückt und ein anderes | ||
| − | + | „a“ gedrückt. Es ist also Aufgabe des Treibers, diese Tasten entsprechend zu | |
interpretieren. | interpretieren. | ||
Um das Ganze noch komplizierter zu machen, gibt es noch so genannte ''Extented | Um das Ganze noch komplizierter zu machen, gibt es noch so genannte ''Extented | ||
| − | Scancodes'', davon gibt es zwei verschiedene Sorten. Diese werden mit E0 | + | Scancodes'', davon gibt es zwei verschiedene Sorten. Diese werden mit E0 und E1 |
| − | bezeichnet, und bestehen aus | + | bezeichnet, und bestehen aus zwei respektive drei Bytes. Das erste Byte eines |
E0-Scancodes hat überraschenderweise den Wert 0xE0, während das zweite Byte beinhaltet, um | E0-Scancodes hat überraschenderweise den Wert 0xE0, während das zweite Byte beinhaltet, um | ||
welchen e0-Scancode es sich genau handelt. E1-Scancodes bestehen aus 3 Bytes, | welchen e0-Scancode es sich genau handelt. E1-Scancodes bestehen aus 3 Bytes, | ||
| − | das | + | das erste hat den Wert 0xE1, während die folgenden zwei Bytes zu einem |
Scancode-Wert kombiniert werden. Dabei muss beachtet werden, dass bei den | Scancode-Wert kombiniert werden. Dabei muss beachtet werden, dass bei den | ||
| − | Extended-Scancodes das Bit 8 des | + | Extended-Scancodes das Bit 8 des zweiten und dritten Bytes darüber Aufschluss gibt, ob es |
sich um eine gedrückte oder eine gelöste Taste handelt. Die einzelnen Bytes der | sich um eine gedrückte oder eine gelöste Taste handelt. Die einzelnen Bytes der | ||
E0-Scancodes werden mit unterschiedlichen IRQs gesendet, man muss sich den | E0-Scancodes werden mit unterschiedlichen IRQs gesendet, man muss sich den | ||
aktuellen Zustand im Code also irgendwie merken. Bei Extended Scancodes | aktuellen Zustand im Code also irgendwie merken. Bei Extended Scancodes | ||
| − | gibt es noch eine weitere Stolperfalle und zwar sind das die so genannten '' | + | gibt es noch eine weitere Stolperfalle und zwar sind das die so genannten ''„fake |
| − | + | shifts“'' [http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html#ss1.6 vgl.] | |
So, nun wissen wir also, mit welchem Scancode wir es zu tun haben. Als nächstes | So, nun wissen wir also, mit welchem Scancode wir es zu tun haben. Als nächstes | ||
| Zeile 319: | Zeile 316: | ||
Auch hier wieder ein kleiner Codeabschnitt, der zeigt wie man den IRQ-Handler | Auch hier wieder ein kleiner Codeabschnitt, der zeigt wie man den IRQ-Handler | ||
| − | umsetzen könnte (aus | + | umsetzen könnte (aus týndur übernommen, BSD-Lizenz): |
<c> | <c> | ||
/** | /** | ||
| Zeile 389: | Zeile 386: | ||
Dieses Codestück unternimmt genau die oben beschriebenen Schritte. Die Funktion | Dieses Codestück unternimmt genau die oben beschriebenen Schritte. Die Funktion | ||
| − | + | „translate_scancode“ übersetzt, wie oben im Kommentar angegeben, die Scancodes | |
in interne Keycodes der Code dazu findet sich ebenfalls im | in interne Keycodes der Code dazu findet sich ebenfalls im | ||
[http://git.tyndur.org/?p=tyndur.git;a=blob;f=src/modules/kbc/sc2kc.c tyndur-Repository]. | [http://git.tyndur.org/?p=tyndur.git;a=blob;f=src/modules/kbc/sc2kc.c tyndur-Repository]. | ||
| Zeile 398: | Zeile 395: | ||
== Beispiele zur Benutzung der KBC Funktionen == | == Beispiele zur Benutzung der KBC Funktionen == | ||
| − | === CPU- | + | === CPU-Reset === |
| − | Der CPU-Reset wird ausgelöst indem der Wert 0xFE in | + | Der CPU-Reset wird ausgelöst, indem der Wert 0xFE in den Outputport geschrieben wird. |
<asm> | <asm> | ||
| − | ;Warten bis der Eingabepuffer leer ist | + | ;Warten, bis der Eingabepuffer leer ist |
wait1: | wait1: | ||
in al, 0x64 | in al, 0x64 | ||
| Zeile 407: | Zeile 404: | ||
jne wait1 | jne wait1 | ||
| − | ;Befehl 0xD1 zum | + | ;Befehl 0xD1 zum Schreiben des Inputports an den KBC senden |
mov al, 0xD1 | mov al, 0xD1 | ||
out 0x64, al | out 0x64, al | ||
| − | ;Wieder warten bis der Eingabepuffer leer ist | + | ;Wieder warten, bis der Eingabepuffer leer ist |
wait2: | wait2: | ||
in al, 0x64 | in al, 0x64 | ||
| Zeile 425: | Zeile 422: | ||
* http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html | * http://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html | ||
| − | [[ | + | [[Kategorie:Tutorials]] |