Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: bitmaster am 11. October 2005, 22:54
-
Hallo. Ich programmiere seit einiger Zeit ein eigenes OS. Schaut euch es mal auf meiner Webseite unter http://www.osm-page.de an. Wie ihr dort seht ist es erst in der Alpha-Version. Aber die Beta-Version ist so gut wie fertig. Also könnte ich sie auf meiner Webseite setzten. Würde mir nicht der Maustreiber den ich unbedingt haben will ein Problem bereiten. Ich möchte nämlich einen Maustreiber für Seriell und PS/2 schreiben. Aber mein Problem ist das ich so gut wie keine Daten über die Maustreiber-entwicklung habe. Ich weis dass der IRQ für COM1 vier, für COM2 drei und für PS/2 zwölf ist. Ich habe auch herausgefunden, dass der IRQ12 der int 74h ist. Wenn ich jetzt den int 74h meinen eigenen Code zuweise müsste dieser doch ausgeführt werden sobald ich etwas mit der PS/2-Maus mache (sie z.B. bewege). Tut er aber nicht. Dann habe ich herausgefunden dass ich die PS/2-Maus erst aktivieren muss. Aber meine Frage ist wie. Wie muss ich die PS/2-Maus aktivieren. Wenn ich dies getan habe führt sie dann automatisch den IRQ12 also int 74h aus? Welche Ports muss ich für den Datenaustausch (Daten der Maus empfangen und durch z.B. drücken senden) ansprechen? Die PS/2 nutzt doch auch den Tastaturcontroller oder? Aber wie weise ich der Maus meinen IRQ-Handler zu? Was muss in den IRQ-Handler rein und wie teste ich ob es sich um eine PS/2-Maus oder einer seriellen handelt. Ich finde einfach keine Infos darüber. Hoffentlich könnt Ihr mir helfen. Ich bitte so um Hilfe.
Danke!!!
-
Wießt du das Beta test version und Alpha endgültige version heißt??????
mfg,
Kyoko12
-
Ãhm Kyoko, wo haste denn den stuss her? Alpha kommt grundsätzlich vor Beta... und ist damit definitiv keine fertige Version
-
@Topic:
Es gab mal das OS StormOS (Wird im nächsten Lowlevel vorgestellt), wo es auch einen Maustreiber gab. Da die Website inzwischen verschwunden ist, poste ich einfach mal den kompletten Code (inkl. russischer Kommentare). Interssant sind hier erstmal die Funktionen CheckPS2 und InitMouse.
typedef struct {
unsigned char LButton;
unsigned char RButton;
short X;
short Y;
unsigned char Moved;
unsigned char Pressed;
} TMouse;
TMouse Mouse;
#define KEYB_CTRL 0x64
#define KEYB_BUF 0x60
// naudojami ekrano dydio nustatymai, kad nereik� kviesti ekrano objekto
unsigned short sWidth, sHeight;
/**
* �ungiama PS2 pel�
* @param Width ekrano ilgis
* @param Height ekrano auk�is
*/
void InitMouse(unsigned short Width, unsigned short Height) {
CheckPS2();
outportb(KEYB_CTRL, 0xA8); //�ungiame PS2 pel� bendravim�
CheckPS2();
outportb(KEYB_CTRL, 0xD4);
CheckPS2();
outportb(KEYB_BUF, 0xF4); // �ungiame duomen siuntim�
CheckPS2();
sWidth = Width;
sHeight = Height;
// nustatome koordinates ties ekrano viduriu
Mouse.X = sWidth / 2;
Mouse.Y = sHeight / 2;
Mouse.Moved = 0;
Mouse.Pressed = 0;
}
/**
* I�augomas ekrano buferis pelei ir nupie�ama pati pel�
*/
void InitMouseGFX() {
GetMouseBuffer(Mouse.X, Mouse.Y);
DrawMouse(Mouse.X, Mouse.Y);
}
/**
* Patikriname Input Buffer Flag, Output Buffer Flag ir MOBF
*/
void CheckPS2() {
unsigned long i = 0xFFFF;
while((inportb(KEYB_CTRL) & 0x3) && i) {
inportb(KEYB_BUF);
i--;
}
}
/**
* Klaviatros jungties skaitymas
* @return pel� "Scan" kodas
*/
char ReadMouse() {
unsigned long i;
char Status, Byte = 0;
for(i = 0; i < 0xFFFF; i++) {
Status = inportb(KEYB_CTRL);
if(Status & 0x01) {
Byte = inportb(KEYB_BUF);
if(!(Status & 0xC0))
return Byte;
}
}
return Byte;
}
void IRQ12() {
Mouse.Pressed = 0;
Mouse.Moved = 0;
char Buf[3];
// skaitome tris pel� siun�amus baitus
Buf[0] = ReadMouse();
Buf[1] = ReadMouse();
Buf[2] = ReadMouse();
// ar buvo paspaustas pel�, kuris nors vienas mygtukas
// �a�me tada status�
if(Buf[0] & 1) {
Mouse.LButton = 1;
Mouse.Pressed = 1;
}
if((Buf[0] & 2) >> 1) {
Mouse.RButton = 1;
Mouse.Pressed = 1;
}
if(Buf[1] + Buf[2]) {
PutMouseBuffer(Mouse.X, Mouse.Y);
Mouse.X += Buf[1];
Mouse.Y -= Buf[2];
Mouse.Moved = 1;
// tikriname ar po naujo pel� pajudinimo nebuvo perengtos ekrano ribos
// X a�je
if(Mouse.X >= sWidth)
Mouse.X = sWidth - 1;
if(Mouse.X < 0)
Mouse.X = 0;
// Y a�je
if(Mouse.Y >= sHeight) Mouse.Y = sHeight - 1;
if(Mouse.Y < 0) Mouse.Y = 0;
GetMouseBuffer(Mouse.X, Mouse.Y);
DrawMouse(Mouse.X, Mouse.Y);
}
}
-
Kyoko12: Stuss
N00B: genau
DarkThing: Danke, aber ich kann kein russisch. Kannst du den Code erkähren? C ist auch nicht so meine Stärke. Wäre schön wenn das Assembler wäre. Aber ich versuche es mal in Assembler zu übersetzen. Vielen Dank!
-
Das ist allerdings auch kein Russisch^^ Russisch wird zu allermeist in Kyrillischen Buchstaben geschrieben. Und selbst wenn man es in Lateinischen Buchstaben umschreibt ist Russisch anders
-
InitMouse proc near
call CheckPS2
mov al,0A8h
out 64h,al
call CheckPS2
mov al,0D4h
out 64h,al
call CheckPS2
mov al,0F4h
out 60h,al
call CheckPS2
?
InitMouse endp
So, den rest habe ich nicht verstanden bzw. kann ich nicht übersetzten. Kannst du (könnt ihr) mir helfen? Hast du (habt ihr) eine Doku wo erklährt wird was z.B. A8h, D4h und F4h bewirken? Ich wäre sehr dankbar. Danke!!!
-
Die Funktion ReadMouse liefert (denk ich) ein Byte Daten von der Maus - Ãhnlich wie beim Keyboardtreiber "in 0x60". Die Funktion IRQ12 ist einfach der IRQ-Handler, der in der IDT eingetragen werden muss. Dort werden 3 Bytes mit Hilfe von ReadMouse geholt und die neue Position errechnet.
Ansonsten gibts noch hier ein paar Tuts über Maustreiber:
http://www.nondot.org/sabre/os/articles/HumanInterfaceDevices/
-
Danke. Aber jetzt weis ich auch nicht mehr wie vorher. In dem Link wird nur der int 33h beschrieben. Der ist aber kein Treiber sondern ein int der den vorhandenen Treiber nutzt. Ich muss so einen aber selber schreiben. Also meine Frage ist erst einmal: Wie bringe ich die Maus dazu (wenn ich sie z.B. bewege, drücke) den IRQ12-Handler (int 74h) anzuspringen? Mehr möchte ich erst mal gar nicht wissen. Wie aktiviere ich die Maus und mache ihr klar das sie den int 74h anspringen soll? Dann könnte ich ja einfach eine Adresse den IRQ12 (int 74h) zuweise die z.B. eine Meldung ausgibt und den EOI (end of interrupt) also mov al,20h out A0,al out 20,al sendet. Dann würde ich doch immer wenn ich die Maus benutze eine Meldung bekommen. Somit könnte ich erst einmal testen ob das bis dahin funktioniert und dann später die richtigen Sachen den IRQ12 zuweisen. Kann doch so gemacht werden oder? Also wie bringe ich die Maus dazu den IRQ12 anzuspringen? Danke!!!
edit: Ach ja, alles in Assembler bitte. Danke
-
Du musst die Adresse des Handlers genau wie bei allen anderen Interrupt-Handlern (Exceptions, Timer, Keyboard, ...) an der richtigen Position in die IDT eintragen. Anschließend kannst du die Maus initialisieren (mit InitMouse). Das ist eigentlich schon alles.
Tutorials zur IDT gibts in Lowlevel, auf www.osdever.net , usw.
-
bitmasters OS arbeitet im Realmode, daher verwendet er keine IDT, sondern die IVT.
-
Ja genau ich arbeite im Real-Mode und nutze deswegen die IVT. Aber wenn ich die Maus mit initmouse initialisiere und in der IVT an Adresse 74h*4 meine routine schicke führt der PC sie nicht aus wenn ich die Maus beispielsweise bewege. Warum? Ist das initmouse überhaubt richtig wie ich das weiter oben in ASM übersetzt habe? Sagen wir mal es würde funktionieren, hat keine eine Doku die dies erklährt? Ich möchte auch wissen was das bedeutet und nicht einfach Code kopieren und sagen ja es funst. Bitte um Hilfe. Ich weis nicht mehr weiter. :cry:
-
Ich wusste doch das ich was dazu schon mal gesehen habe
http://www.osdever.net/documents.php?cat=8&sort=1
vielleicht hilfts. Schickes os mal so am rande. In welchem Grafik Modus arbeitest du?
-
Ich wusste doch das ich was dazu schon mal gesehen habe
http://www.osdever.net/documents.php?cat=8&sort=1
vielleicht hilfts.
danke, aber dort wird nicht beschrieben wie ich die PS/2-Maus aktiviere und sie somit zum IRQ12 zwinge.Schickes os mal so am rande. In welchem Grafik Modus arbeitest du?
Machst du dich lustig oder ist das ernst? Ich arbeite nicht im Grafikmodus sondern im Textmodus. Modus 3 heißt er.
-
Machst du dich lustig oder ist das ernst? Ich arbeite nicht im Grafikmodus sondern im Textmodus. Modus 3 heißt er.
Nein mach ich nicht, aber ich frage weil ich gerne wüsste wie du den Hintergrund färbst.
-
Zum Färben des Hintergrundes gibts ein paar Bits im Attribut Byte im Textmodus. Ich glaube das wird auch in einem Magazin hier auf der Seite erklärt.
-
Machst du dich lustig oder ist das ernst? Ich arbeite nicht im Grafikmodus sondern im Textmodus. Modus 3 heißt er.
Nein mach ich nicht, aber ich frage weil ich gerne wüsste wie du den Hintergrund färbst.
Mach ein neues Thema darüber auf und ich werde dir zeigen wie ich das mache. Hier möchte ich dir das nicht erklären, weil es dann vielleicht nur noch darum geht und nicht um die Maus. Bitte um Verständnis.
-
hi,
C++ ist zwar nicht mein Spezialgebiet (Pascal und asm sind besser :D ), aber so ungefähr müsste es stimmen:
Loop:
mov dx,KEYB_CTRL ; wenn KEYB_CTRL ne Variable ist, dann [KEYB_CTRL] schreiben
in al,dx
and al,0x03
and eax,[i] ; zwecks verständlichkeit drin, könnte man weglassen
cmp eax,0 ; könnte man ebenfalls weglassen
jz Ende:
mov dx,KEYB_BUF
in al,dx
dec [i]
jmp Loop
Ende:
...
i dd 0
Aber ich bin mir nicht sicher, wie man einmal das "&" und dann das "&&" übersetzt, in meinen Augen ist in diesem Fall das beides ein AND (wobei ich && bei Vergleichen kenne).
probiers einfach mal aus.
cu,
stefan2005
-
EDIT: Argh, hatte einen kleinen Fehler
[global checkPS2]
checkPS2:
push ecx
push edx
mov ecx, 0xFFFF
mov dx, KEYB_CTRL
check:
in al, dx
and al, 0x3
cmp al, 0
jnz check_ok
loop check
jmp check_failed
check_ok:
mov dx, KEYB_BUF
in al, dx
check_failed:
pop edx
pop ecx
ret
Ich habe den Code nicht getestet, sollte aber funktionieren.
Kompilier doch einfach den Code mit "gcc -S -o ps2.asm ps2.c" und sieh dir das Ergebniss an^^
-
Aber ich bin mir nicht sicher, wie man einmal das "&" und dann das "&&" übersetzt, in meinen Augen ist in diesem Fall das beides ein AND (wobei ich && bei Vergleichen kenne).
Ein && ist ein boolesches and. Das heißt, dass es nur true liefert wenn zwei Variablen/Werte auch true sind.
Ein normales & bedeutet bitweises and. Da werden also die zwei Werte/Vars binär geandet.
-
Also ich habe jetzt die maus so aktiviert:
;gebe IRQ12 also int 74h eine Adresse
;für einen Code der eine Meldung ausgibt
;und mit iret zurückspringt
call InitMouse ;rufe die Funktion auf
;beende
InitMouse proc near
call CheckPS2
mov al,0A8h
out 64h,al
call CheckPS2
mov al,0D4h
out 64h,al
call CheckPS2
mov al,0F4h
out 60h,al
call CheckPS2
ret
InitMouse endp
CheckPS2 proc near
mov dx,0FFFFh
next:
in al,64h
and al,03h
jz done
or dx,dx
jz done
in al,60h
dec dx
jmp next
done:
ret
CheckPS2 endp
Also ich übergebe dem IRQ12 (int 74h) die Adresse meines Codes der folgenes macht:
Alle Register auf den Stack schreibt. Dann das ds zum cs macht und eine Meldung ausgiebt. Nun den EOI (end of interrupt) mit folgendem Code sendet:
mov al,20h
out 0A0h,al
out 20h,al
jetzt holt er alle Register vom Stack und springt mit iret zurück.
Dann aktiviere ich die Maus mit dem Code den ich gepostet habe und ende. Wenn ich jetzt unter einem Real-Mode OS (z.B. DOS oder meins) die Schose laufen lasse passiert erstmal nicht solange bis das Programm endet. Dann mache ich nicht und er gibt die meldung aus die er eigentlich erst ausgeben soll wenn ich etwas mit der Maus mache sie z.B. bewege. Und nun bleibt das OS hängen. Das verstehe ich nicht. Er führt also den IRQ12 aus und tut dann garnichts mehr. Warum? Normalerweise sollte er mir immer die Meldung ausgeben (also den IRQ12 ausführen) wenn ich die Maus bewege und drücke. Das soll nämlich nur ein Test sein ob er auch den IRQ12 ausführt wenn ich es will. Später könnte ich dann ja immer noch den Code für die Meldung mit dem richtigen Code für die Maus (Daten lesen etc.) ersetzten. Aber wie ich sehe funktioniert nicht einmal dies. Könnt Ihr mir weiterhelfen?
Danke!!!
-
Hat keiner von euch ne Ahnung? Dann poste ich mal meinen Code:
mouse.asm => mouse.filexor ah,ah
mov si,offset filename
int 60h
mov ah,05h
mov si,offset filename
mov bx,1000h
mov dx,2000h
int 60h
mov ax,2000h
mov ds,ax
mov es,ax
push 2000h
push 1000h
retf
filename db "mouse.sys",00h
mouse2.asm -> mouse.sys
org 1000h
xor ah,ah
mov si,offset msg
int 60h
mov ax,2174h
mov dx,cs
mov bx,offset MouseOffset
int 60h
call InitMouse
mov ah,04h
int 60h
InitMouse proc near
call CheckPS2
mov al,0A8h
out 64h,al
call CheckPS2
mov al,0D4h
out 64h,al
call CheckPS2
mov al,0F4h
out 60h,al
call CheckPS2
ret
InitMouse endp
CheckPS2 proc near
mov dx,0FFFFh
next:
in al,64h
and al,03h
jz done
or dx,dx
jz done
in al,60h
dec dx
jmp next
done:
ret
CheckPS2 endp
MouseOffset:
push ax
push si
push ds
mov ax,cs
mov ds,ax
xor ah,ah
mov si,offset msg
int 60h
mov al,20h
out 0A0h,al
out 20h,al
pop ds
pop si
pop ax
iret
msg db 0Dh,0Ah,"mouse",00h
Warum funst der Code nicht? Er soll bei jeder bewegung der Mouse die Meldung mouse ausgeben. Hilfe!!!
Danke!!!
-
Also ich verstehe das nicht. Einige von euch haben doch ein OS mit Mausfunktion. Kann mir nicht jemand Helfen. Mein OS ist bereit für die Beta-Version abgesehen von dem Maustreiber. Ich würde meine Beta-Version gerne fertig bekommen aber mit Maustreiber. Kann denn keiner von euch mir helfen? Folgendes Dokument habe ich auf meiner Festplatte: http://www.prakinf.tu-ilmenau.de/~albrecht/alfred/f0157.htm Dort wird gesagt wenn ich A8h an den Port 64h sende wird die Zusatzeinheit (das müsste die Maus sein) aktiviert. Aber ich verstehe immer noch nicht wie ich die Maus dazu bringe den IRQ12 (int 74h) anzuspringen wenn ich sie gebrauche. Könnt ihr mir nicht helfen?
Danke!!!
-
Ich habs ich habs ich haaaaabs. Es funst. Jetzt ruft er entlich den IRQ12 auf wenn ich die maus benutze. Ich hatte vergessen (und wusste nicht das ich das muss) in al,60h in der IRQ12 Routine zu schreiben. Erst dann kann er weiter machen. Ich bin so froh. Aber ich bin ja noch nicht am Ziel. Jetzt muss ich noch die meldung im IRQ12 mit den richtigen Funktionen ersetzten. Woher weis ich wann die linke/rechte/das Rad gedrückt wurde und die maus in welcher Richtung?
Danke!!!
PS: Ich bin so froh ;-)
-
hi,
wenn der IRQ12 aufgerufen wird, dann musst du mittels IN 3 mal ein Byte vom Port einlesen.
Das erste Byte enthält Informationen über die Maustasten (Bit 1 = linke Maustaste, Bit 2 = rechte, Bit 3 = mittlere, glaub ich, notfalls durch ausprobieren rauskriegen :), wenn Bit gesetzt, dann ist die Maustaste gedrückt )
Das zweite Byte gibt als signed int 8 die Veränderung auf der X-Achse
und das dritte die veränderung auf der y-Achse an.
(hab vor paar minuten selbst erst meinen Maustreiber vollendet :D)
mfg,
Stefan2005
-
(hab vor paar minuten selbst erst meinen Maustreiber vollendet :D)
Das ist ja cool. Vielen dank ich werde das morgen ausprobieren, weil ich jetzt schlafen gehe.
PS: nochmals vielen dank
-
Habe herrausgefunden das mein Programm nicht auf allen PCs funktioniert. Ich weis aber nicht warum. Ich habe gelesen das es im Kontroller-Register 2 Bits gibt die dafür zuständig sind IRQs aufzurufen. Meine Fragen sind: Sind die vielleicht bei der Maus nicht bei allen PCs standartmäßig gesetzt? Und wie setze ich diese? Folgendes habe ich nämlich im Internet gefunden:
Kontroll-Register:
- XLAT _EN2 _EN - SYS INT2 INT
INT
bei neuen Daten von der Tastatur wird Interrupt 1 ausgelöst
INT2
bei neuen Daten von der Maus wird Interrupt 12 ausgelöst
Schonmal danke!!!
-
Also irgendwie funst die Schose nicht so richtig. Beim VMware läufts ganz gut, unter Bochs gar nicht, 1. PC läuft auch nicht und beim 2. PC läuft es aber nicht so wie bei vmware. Das heißt unter VMware läufts noch am besten. Aber was mache ich falsch? Hier mein Code:
call CheckPS2
;hiermit aktiviere ich die Maus, fehlt da was?
;dies befindet sich außerhalb der IRQ12 Routine
;wird also nur einmal aufgerufen, ist das richtig?
mov al,0A8h
out 64h,al
call CheckPS2
mov al,0D4h
out 64h,al
call CheckPS2
mov al,0F4h
out 60h,al
call CheckPS2
;ende
CheckPS2:
mov dx,0FFFFh
next:
in al,64h
and al,03h
jz done
or dx,dx
jz done
in al,60h
dec dx
jmp next
done:
ret
;folgender Code ist in der IRQ12 Routine
push ax ;Register sichern
push si
push ds
push es
mov ax,cs ;für meldung muss ds gleich cs sein
mov ds,ax
mov es,ax
in al,64h
test al,20h
jz exit ;wenn nicht für Maus dann ende
in al,60h
test al,00000001b ;linke taste gedrückt?
jz nicht_linke
xor ah,ah
mov si,offset linke
int 60h ;dies gibt einfach nur die meldung linke aus (int 60h von mein os)
jmp weiter
nicht_linke:
test al,00000010b ;rechte taste gedrückt?
jz nicht_rechte
xor ah,ah
mov si,offset rechte ;meldung rechte
int 60h
jmp weiter
nicht_rechte:
test al,00000100b ;mittlere taste gedrückt?
jz weiter
xor ah,ah
mov si,offset mitte ;meldung mitte
int 60h
weiter: ;der rest x und y bewegung der maus, für später
in al,60h
in al,60h
;
xor ah,ah
mov si,offset msg ;eine meldung ausgeben, wenn nur diese
int 60h ;ausgegeben wird dann wurde keine taste gedrückt
;
exit:
mov al,20h ;sende EOI (end of interrupt)
out 0A0h,al ;schalte slave frei
out 20h,al ;schalte master frei
pop es
pop ds
pop si
pop ax
iret ;zurück
Der Code soll folgendes bewirken. Er soll die PS/2-Maus aktivieren (nur einmal also außerhalb von der IRQ12-Routine). In der Routine soll er prüfen welche taste gedrückt wurde und dann die jeweilige Meldung ausgeben + msg-Meldung. Wenn keine Taste gedrückt wurde dann soll er nur die msg-Meldung ausgeben. Die letzten beiden Parameter für x und y Achse (Verschiebung der maus) werden erst einmal nicht berücksichtigt. Zum Schluss der EOI und zurück. Der Code soll einfach nur ausgeben welche Taste gedrückt wurde (stört euch nicht an den int 60h das ist einfach der int von meinem os und ah = Null bedeutet Meldung ausgeben. Das alles funktioniert unter VMware genau so. Aber und Bochs funst nichts und unter einem PC von mir auch nicht. Der andere PC funktioniert damit fast er gibt nur beim verschieben auch die Meldungen für recht, links, mittel aus obwohl ich keine Taste drücke. Was ist an diesem Code falsch? Ist das aktivieren der Maus richtig? Was muss ich ändern?
Danke!!!
PS: stefan2005 du sagtest du hast deinen Maustreiber fertig könntest du mir vielleicht sagen wie du die Maus aktiviert hast und was du im IRQ12 stehen hast? Danke!!!
-
hi,
klar, ist jedoch Delphi Code, sollte aber leicht zu verstehen sein, da viel Assembler drin vorkommt.
procedure InitMouse;
var InByte : Byte;
begin
kbCmd($A8);
kbRead;
kbCmd($20);
InByte := kbRead OR $3;
kbCmd($60);
If Inb($E9) = $E9 then kbWrite(InByte); // Für Bochs
kbCmd($D4);
kbWrite($F4);
kbRead;
end;
procedure kbWrite(Cmd: Byte);
asm
@Init:
pushad
mov dl,al
mov ecx,$ffff
@kw_loop1:
in al,$64
test al,$20
jz @kw_ok1
loop @kw_loop1
mov ah,1
jmp @kw_exit
@kw_ok1:
in al,$60
mov ecx,$ffff
@kw_loop:
in al,$64
test al,2
jz @kw_ok
loop @kw_loop
mov ah,1
jmp @kw_exit
@kw_ok:
mov al,dl
out $60,al
mov ecx,$ffff
@kw_loop3:
in al,$64
test al,2
jz @kw_ok3
loop @kw_loop3
mov ah,1
jmp @kw_exit
@kw_ok3:
mov ah,8
@kw_loop4:
mov ecx,$ffff
@kw_loop5:
in al,$64
test al,1
jnz @kw_ok4
loop @kw_loop5
dec ah
jnz @kw_loop4
@kw_ok4:
xor ah,ah
@kw_exit:
popad
end;
function kbRead: Byte;
asm
@Init:
push ecx
push edx
mov ecx,$ffff
@kr_loop:
in al,$64
test al,1
jnz @kr_ready
loop @kr_loop
mov ah,1
jmp @kr_exit
@kr_ready:
push ecx
mov ecx,32
@kr_delay:
loop @kr_delay
pop ecx
in al,$60
xor ah,ah
@kr_exit:
pop edx
pop ecx
end;
procedure kbCmd(Cmd: Byte);
asm
@Init:
mov ecx,$ffff
push eax
@c_wait:
in al,$64
test al,2
jz @c_send
loop @c_wait
jmp @c_error
@c_send:
pop eax
out $64,al
mov ecx,$ffff
@c_accept:
in al,$64
test al,2
jz @c_ok
loop @c_accept
@c_error:
mov ah,1
jmp @c_exit
@c_ok:
xor ah,ah
@c_exit:
end;
procedure IRQ12_ASM; assembler;
asm
pushad
call IRQ12
popad
iretd
end;
mfg,
stefan
-
Habe ich gerade unter Bochs und VMware getestet. Dort funktioniert es. Auch wenn ich den Code nicht ganz verstehe. Werde gleich mal meine PCs testen. Aber der Code kommt mir so bekannt vor. Der hat ziemlich viel änlichkeit mit folgendem Code:
kb_read:
push ecx edx
mov ecx,0xffff
kr_loop:
in al,0x64
test al,1
jnz kr_ready
loop kr_loop
mov ah,1
jmp kr_exit
kr_ready:
push ecx
mov ecx,32
kr_delay:
loop kr_delay
pop ecx
in al,0x60
xor ah,ah
kr_exit:
pop edx ecx
ret
kb_write:
push ecx edx
mov dl,al
mov ecx,0xffff
kw_loop1:
in al,0x64
test al,0x20
jz kw_ok1
loop kw_loop1
mov ah,1
jmp kw_exit
kw_ok1:
in al,0x60
mov ecx,0xffff
kw_loop:
in al,0x64
test al,2
jz kw_ok
loop kw_loop
mov ah,1
jmp kw_exit
kw_ok:
mov al,dl
out 0x60,al
mov ecx,0xffff
kw_loop3:
in al,0x64
test al,2
jz kw_ok3
loop kw_loop3
mov ah,1
jmp kw_exit
kw_ok3:
mov ah,8
kw_loop4:
mov ecx,0xffff
kw_loop5:
in al,0x64
test al,1
jnz kw_ok4
loop kw_loop5
dec ah
jnz kw_loop4
kw_ok4:
xor ah,ah
kw_exit:
pop edx ecx
ret
kb_cmd:
mov ecx,0xffff
c_wait:
in al,0x64
test al,2
jz c_send
loop c_wait
jmp c_error
c_send:
mov al,bl
out 0x64,al
mov ecx,0xffff
c_accept:
in al,0x64
test al,2
jz c_ok
loop c_accept
c_error:
mov ah,1
jmp c_exit
c_ok:
xor ah,ah
c_exit:
ret
setmouse: ; set mousepicture -pointer
; ps2 mouse enable
mov [0xf200],dword mousepointer
cli
mov bl,0xa8 ; enable mouse cmd
call kb_cmd
call kb_read ; read status
mov bl,0x20 ; get command byte
call kb_cmd
call kb_read
or al,3 ; enable interrupt
mov bl,0x60 ; write command
push eax
call kb_cmd
pop eax
call kb_write
mov bl,0xd4 ; for mouse
call kb_cmd
mov al,0xf4 ; enable mouse device
call kb_write
call kb_read ; read status return
Was soll die Zeile in der "für Bochs" steht bedeuten? Brauch Bochs eine extra Einladung?
-
hi,
in der Tat, ich hab mir das initialisieren der Maus ein wenig einfacher gemacht :)
das für Bochs heißt, dass diese zeile nur ausgeführt wird, wenn das OS auf Bochs läuft -> bei meiner Bochs Version würde es ohne dieser zeile nicht laufen. Mit dieser Zeile würde es zwar in Bochs laufen, aber nicht mehr auf nem echten PC :D
mfg,
stefan2005
-
Also bei mir läuft es überall ohne diese Zeile, auch in Bochs. Ist Bochs 2.2.1, wie das bei anderen Versionen ist weis ich nicht. Aber ich lasse diese Zeile weck. Vielen dank noch. Ach ja wenn ich die drei in al,60h in der IRQ12 Routine laufen lasse muss ich etwas berücksichtigen? Vielleicht vorher irgendwie prüfen ob die Daten überhaupt schon da sind?
Danke!!!
-
Ich kenn mich jetzt nich so mit der Maus aus, aber ich denke nicht, das du noch Abfragen musst, ob die Daten da sind, da der IRQ ja nur aufgerufen werden sollte, wenn welche da sind.
-
hi,
ja, wenn das erste Bit im Port $64 (KEYBOARD CONTROL) gesetzt ist, dann kann man vom port $60 das Byte einlesen.
mfg,
stefan
-
Ich kenn mich jetzt nich so mit der Maus aus, aber ich denke nicht, das du noch Abfragen musst, ob die Daten da sind, da der IRQ ja nur aufgerufen werden sollte, wenn welche da sind.
Ja, aber ich meine wenn ich mit in al,60h den ersten Parameter lade und da die CPU viel schneller ist als die Peripherie ob direkt schon der zweite da ist oder ob ich erst warten (prüfen) muss bis er da ist und diesen dann laden und danach den letzten.
-
hi,
ja, wenn das erste Bit im Port $64 (KEYBOARD CONTROL) gesetzt ist, dann kann man vom port $60 das Byte einlesen.
mfg,
stefan
OK.
Danke!!!
PS: Melde mich bald wieder. ;-)
-
So da bin ich wieder. Ich habe den Code zum aktivieren der PS/2-Maus noch etwas optimiert und in meinem OS integriert. Alles funktioniert wunderbar. Der erste Parameter der Maus gibt ja an welche Taste gedrückt oder nicht gedrückt wurde. Das funktioniert auch wunderbar. Jetzt habe ich aber eine Frage wie das mit dem zweiten und dritten Parameter funktioniert. Die sollen ja die Bewegung der Maus beinhalten (zweiter = x-Achse und dritter = y-Achse). Aber was genau beinhalten sie dann? Die zahlen gehen doch von -128 bis +128 oder? Ich habe mir die mal ausgeben lassen. Wenn ich die Maus ein ganz kleines Stück nach rechts bewege bekommt der zweite Parameter eine 1 und der dritte eine Null. Wenn ich die Maus ein ganz kleines Stück nach links bewege bekommt der zweite Parameter eine 255 (das müssten dann eine -1 sein oder?) und der dritte eine Null. Aber was sagt die 1 mir dann? Muss ich diese an meinen Video-Modus anpassen? Wie mache ich das am besten?
Danke!!!
-
Die beiden Parameter geben wohl an, wie weit/schnell die Maus bewegt wurde (und natürlich auch die Richtung). Du könntest erstmal die Werte direkt zu deiner Mauszeiger-Position addieren oder von ihr subtrahieren. Dann sollte man den Mauszeiger schon richtig bewegen können. Später kann man dann ja noch die Geschwindigkeit anpassen.