554 lines
No EOL
10 KiB
NASM
554 lines
No EOL
10 KiB
NASM
;Driver della tastiera per NXOS
|
||
;------------------------------
|
||
;Written by: MaX and Alb‚ - 2001
|
||
;
|
||
;Questo driver sostituisce le routine dell'int 16h del bios.
|
||
;Controlla anche se particolari combinazioni di tasti sono state premute:
|
||
;
|
||
;CTRL+C o CTRL+Del --> Termina il processo visibile
|
||
;CTRL+N --> Rende visibile il processo successivo
|
||
|
||
;Prossima funzione da implementare: GetString
|
||
|
||
|
||
org 0h
|
||
|
||
InstallDriver:
|
||
cli
|
||
xor ax,ax
|
||
mov es,ax
|
||
mov ax,offset Int25h
|
||
mov word ptr es:[25h*4],ax
|
||
mov ax,cs
|
||
mov word ptr es:[(25h*4)+2],ax
|
||
|
||
mov ax,word ptr es:[09h*4]
|
||
mov word ptr cs:[OldInt09h],ax
|
||
mov ax,word ptr es:[09h*4+2]
|
||
mov word ptr cs:[OldInt09h+2],ax
|
||
|
||
mov ax,offset Int09h
|
||
mov word ptr es:[09h*4],ax
|
||
mov ax,cs
|
||
mov word ptr es:[09h*4+2],ax
|
||
|
||
mov ah,02h
|
||
mov bl,1
|
||
int 20h
|
||
|
||
;==============================================================================
|
||
|
||
Int25h:
|
||
cmp ah,00h
|
||
je Int25h_00h
|
||
cmp ah,01h
|
||
je Int25h_01h
|
||
cmp ah,02h
|
||
je Int25h_02h
|
||
cmp ah,03h
|
||
je Int25h_03h
|
||
cmp ah,04h
|
||
je Int25h_04h
|
||
cmp ah,05h
|
||
je Int25h_05h
|
||
cmp ah,06h
|
||
je Int25h_06h
|
||
cmp ah,07h
|
||
je Int25h_07h
|
||
iret
|
||
Int25h_00h:
|
||
call GetKey
|
||
iret
|
||
Int25h_01h:
|
||
call TestKey
|
||
retf 2 ;Attenzione qui: uso "retf 2" invece di "iret", perchè iret
|
||
;ripristina lo stato dei
|
||
;flags, mentre io voglio che il flag Z sia settato dalla
|
||
;procedura "TestKey"
|
||
Int25h_02h:
|
||
call GetStatus
|
||
iret
|
||
Int25h_03h:
|
||
call SetAutoRpt
|
||
iret
|
||
Int25h_04h:
|
||
call EndKeyboardDriver
|
||
iret
|
||
Int25h_05h:
|
||
call StoreKey
|
||
iret
|
||
Int25h_06h:
|
||
call GetKeyWithEcho
|
||
iret
|
||
Int25h_07h:
|
||
call GetStringWithEcho
|
||
iret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
EndKeyboardDriver:
|
||
xor ax,ax
|
||
mov es,ax
|
||
mov ax,word ptr cs:[OldInt09h]
|
||
mov es:[09h*4],ax
|
||
mov ax,word ptr cs:[OldInt09h+2]
|
||
mov es:[09h*4+2],ax
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
GetKey:
|
||
;prende il codice del tasto premuto dal buffer di tastiera e lo retituisce in AX
|
||
;Output: al=ascii-code ah=scan-code
|
||
push cx
|
||
push si
|
||
|
||
GetKey1:
|
||
mov ah,03h
|
||
int 20h
|
||
cmp si,cx
|
||
je GetKey2 ;se il processo Š quello visibile, allora legge il tasto
|
||
mov ah,05h ;altrimenti passa al processo successivo
|
||
int 20h
|
||
jmp GetKey1
|
||
|
||
GetKey2:
|
||
Call TestKey
|
||
jz GetKey1
|
||
|
||
cli
|
||
push ds
|
||
mov ax,40h
|
||
mov ds,ax
|
||
mov si,word ptr ds:[HeadPtr] ;carica in bx l'indirizzo del prossimo carattere
|
||
mov ax,ds:[si] ;preleva il carattere e lo mette in ax
|
||
inc si
|
||
inc si
|
||
cmp si,ds:[82h] ;check for overflow
|
||
jnz GetKey_End
|
||
mov si,ds:[80h] ;ripristina il valore originale di HeadPtr
|
||
|
||
GetKey_End:
|
||
mov word ptr ds:[HeadPtr],si
|
||
pop ds
|
||
|
||
pop si
|
||
pop cx
|
||
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
TestKey:
|
||
;verifica se e' disponibile un carattere nel buffer
|
||
; ZF=1 il carattere non e' disponibile
|
||
; ZF=0 il carattere e' disponibile
|
||
; se il car. e' disponibile allora al= ascii-code ah=scan-code
|
||
; il carattere non viene rimosso dal buffer
|
||
|
||
push ds
|
||
push bx
|
||
|
||
TestKey1:
|
||
mov ah,03h
|
||
int 20h
|
||
cmp si,cx
|
||
je TestKey2
|
||
mov ah,05h
|
||
int 20h
|
||
jmp TestKey1
|
||
|
||
TestKey2:
|
||
mov ax, 40h
|
||
mov ds, ax
|
||
cli ;regione critica
|
||
mov bx, word ptr ds:[HeadPtr]
|
||
mov ax, ds:[bx] ;mette il carattere letto dal buffer in ax
|
||
cmp bx, word ptr ds:[TailPtr] ;ZF=1, se il buffer e' vuoto
|
||
pop bx
|
||
pop ds
|
||
sti ;Bisogna ricordarsi di risettare l'interrupt flag, perchŠ
|
||
;da TestKey non esco con un "iret" ma con "retf 2" (quindi
|
||
;non viene risettato il valore originale dei flags)
|
||
ret
|
||
|
||
;----------------------------------------------------------------------------------
|
||
|
||
GetStringWithEcho:
|
||
;Input: DS:[SI] --> buffer in cui memorizzare la stringa
|
||
;Output CX=numero di caratteri della stringa.
|
||
;La stringa finisce quando viene premuto CR (#13) (cioŠ Enter). Il carattere
|
||
;CR non viene memorizzato nel buffer
|
||
;I caratteri premuti vengono visualizzati sul video.
|
||
|
||
push ax
|
||
push si
|
||
|
||
xor cx,cx
|
||
|
||
GetString1:
|
||
call GetKey
|
||
cmp al,13
|
||
je GetString_End
|
||
cmp al,8
|
||
je GetString_DelPressed
|
||
mov byte ptr ds:[si],al
|
||
inc si
|
||
inc cx
|
||
mov ah,00h
|
||
int 24h
|
||
jmp GetString1
|
||
|
||
GetString_DelPressed:
|
||
test cx,cx
|
||
jz GetString1
|
||
|
||
dec si
|
||
dec cx
|
||
mov al,' '
|
||
mov byte ptr ds:[si],al
|
||
|
||
mov ah,05h
|
||
int 24h
|
||
sub dl,1
|
||
push dx
|
||
mov ah,06h
|
||
int 24h
|
||
|
||
mov al,' '
|
||
mov ah,00h
|
||
int 24h
|
||
|
||
pop dx
|
||
mov ah,06h
|
||
int 24h
|
||
|
||
jmp GetString1
|
||
|
||
GetString_End:
|
||
|
||
pop si
|
||
pop ax
|
||
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
GetKeyWithEcho:
|
||
;output AL=ascii code, AH=scan code
|
||
|
||
call GetKey
|
||
push ax
|
||
mov ah,00h
|
||
int 24h
|
||
pop ax
|
||
|
||
ret
|
||
|
||
;------------------------------------------------------------------------------
|
||
|
||
;patch dell'interrupt 09h
|
||
;Questo Š necessario per determinare la pressione di certe combinazioni di tasti
|
||
;(es CTRL+C --> termina il processo visibile...ecc.)
|
||
|
||
;Per maggiori informazioni, consultate il capitolo 20 del libro
|
||
;"The Art of Assembly Language".
|
||
|
||
Int09h:
|
||
cli
|
||
push ax
|
||
push cx
|
||
push ds
|
||
|
||
|
||
mov ax,40h
|
||
mov ds,ax
|
||
; mov al,0adh
|
||
; call SetCmd ;disabilita temporaneamente la tastiera
|
||
|
||
cli
|
||
; xor cx,cx
|
||
|
||
Int09h_Wait4Data:
|
||
; in al,64h
|
||
; test al,10b
|
||
; loopnz Int09h_Wait4Data
|
||
|
||
mov al,byte ptr ds:[17h]
|
||
test al,100b
|
||
jz OrigInt09h
|
||
|
||
and al,11111011b
|
||
mov byte ptr ds:[17h],al
|
||
|
||
in al,60h
|
||
cmp al,2eh ;guarda se Š stata premuta una C (per il CTRL+C)
|
||
je Int09h_CtrlC
|
||
cmp al,53h ;controlla se Š premuto Del
|
||
je Int09h_CtrlC
|
||
|
||
cmp al,31h ;controlla se Š premuto il tasto 'N'
|
||
je Int09h_CtrlN
|
||
|
||
; jmp OrigInt09h ;altrimenti salta all'interrupt originale
|
||
|
||
mov al,20h
|
||
out 20h,al
|
||
|
||
pop ds
|
||
pop cx
|
||
pop ax
|
||
|
||
iret
|
||
|
||
|
||
Int09h_CheckCtrlC:
|
||
|
||
; mov al,byte ptr ds:[17h]
|
||
; test al,100b ;controlla se Š premuto CTRL
|
||
; jnz Int09h_CtrlC
|
||
|
||
; jmp OrigInt09h
|
||
|
||
Int09h_CheckCtrlN:
|
||
; mov al,byte ptr ds:[17h]
|
||
; test al,100b
|
||
; jnz Int09h_CtrlN
|
||
|
||
; jmp OrigInt09h
|
||
|
||
Int09h_CtrlC:
|
||
;CTRL+C o CTRL+Del sono stati premuti
|
||
; mov al,0aeh ;riabilita la tastiera
|
||
; call SetCmd
|
||
|
||
mov al,20h ;segnale di fine interrupt
|
||
out 20h,al
|
||
|
||
pop ds
|
||
pop cx
|
||
pop ax
|
||
|
||
mov ah,02h ;termina il processo corrente
|
||
mov bl,0
|
||
int 20h
|
||
|
||
Int09h_CtrlN:
|
||
mov ah,06h ;controlla qual'Š il processo successivo
|
||
int 20h
|
||
|
||
mov ah,02h ;setta visibile il processo successivo
|
||
int 24h
|
||
|
||
; mov al,0aeh ;riabilita la tastiera
|
||
; call SetCmd
|
||
|
||
mov al,20h ;segnale di fine interrupt
|
||
out 20h,al
|
||
|
||
pop ds
|
||
pop cx
|
||
pop ax
|
||
iret
|
||
|
||
OrigInt09h:
|
||
; mov al,0aeh ;riabilita la tastiera
|
||
; call SetCmd
|
||
|
||
; mov al,20h
|
||
; out 20h,al
|
||
|
||
pop ds
|
||
pop cx
|
||
pop ax
|
||
|
||
jmp dword ptr cs:[OldInt09h] ;salta all'int 09h originale
|
||
|
||
|
||
;--------------------------------------
|
||
|
||
SetCmd:
|
||
;Questa procedura manda un comando al microcontroller della tastiera
|
||
;INPUT AL:comando da mandare
|
||
push cx
|
||
cli
|
||
xor cx,cx
|
||
|
||
push ax
|
||
|
||
SetCmd_Wait4Empty:
|
||
in al,64h
|
||
test al,10b
|
||
loopnz SetCmd_Wait4Empty
|
||
|
||
pop ax
|
||
out 64h,al
|
||
|
||
sti
|
||
pop cx
|
||
ret
|
||
|
||
;---------------------------------------------------------------------------------
|
||
|
||
;preleva lo stato dei tasti modificatori
|
||
;NON TESTATO!!
|
||
|
||
GetStatus:
|
||
|
||
push ds
|
||
mov ax, 40h
|
||
mov ds, ax
|
||
mov al, byte ptr ds:[KbdFlags1] ;mette in al lo stato dei tasti modificatori
|
||
pop ds
|
||
|
||
ret
|
||
|
||
;----------------------------------------------
|
||
|
||
;setta il rapporto di autoripetizione
|
||
;bh=0, 1, 2, or 3 (delay in 1/4 sec before autorepeat starts)
|
||
;and bl=0..1Fh (repeat rate, about 2:1 to 30:1 (chars:sec).
|
||
|
||
;BH=0 --> 250 ms
|
||
;BH=1 --> 500 ms
|
||
;BH=2 --> 750 ms
|
||
;Bh=3 --> 1 second
|
||
|
||
;BL=0 --> 30 rpts/sec
|
||
;BL=1 --> 26 rpts/sec
|
||
;...
|
||
;BL=1fh --> 2 rpts /sec
|
||
|
||
SetAutoRpt:
|
||
|
||
push ax
|
||
push cx
|
||
push bx
|
||
|
||
mov al, 0ADh ;Disable kbd for now.
|
||
call SetCmd
|
||
and bh, 11b ;Force into proper range.
|
||
mov cl, 5
|
||
shl bh, cl ;Move to final position.
|
||
and bl, 1Fh ;Force into proper range.
|
||
or bh, bl ;8042 command data byte.
|
||
mov al, 0F3h ;8042 set repeat rate cmd.
|
||
call SendCmd ;Send the command to 8042.
|
||
mov al, bh ;Get parameter byte
|
||
call SendCmd ;Send parameter to the 8042.
|
||
mov al, 0AEh ;Reenable keyboard.
|
||
call SetCmd
|
||
mov al, 0F4h ;Restart kbd scanning.
|
||
call SendCmd
|
||
|
||
pop bx
|
||
pop cx
|
||
pop ax
|
||
|
||
ret
|
||
|
||
;----------------------------------------------
|
||
|
||
|
||
; memorizza il carattere in CX nel buffer
|
||
; CH=scan-code CL=ascii-code
|
||
|
||
;NON TESTATO!
|
||
|
||
StoreKey:
|
||
|
||
push ds
|
||
push bx
|
||
mov ax, 40h
|
||
mov ds, ax
|
||
cli ;regione critica
|
||
mov bx, word ptr ds:[TailPtr] ;indirizzo di memorizzazione tasto
|
||
push bx ;salva l'inidirizzo nello stack
|
||
mov [bx], cx ;memorizza
|
||
inc word PTR ds:[TailPtr] ;incrementa il puntatore di coda
|
||
cmp bx, word ptr ds:[HeadPtr] ;sono stati sovrascritti dati?
|
||
jne StoreOkay ;se non salta, se si continua
|
||
pop word ptr cs:[TailPtr] ;riprende il vecchio indirizzo e ignora
|
||
sub sp, 2 ;sistema lo stack
|
||
StoreOkay:
|
||
add sp, 2 ;rimuove dati dallo stack
|
||
pop bx
|
||
pop ds
|
||
|
||
ret
|
||
|
||
;-------------------------------------------------
|
||
|
||
; Spedisce un comando o un dato alla
|
||
; keyboard data port (port 60h).
|
||
|
||
SendCmd:
|
||
push ds
|
||
push bx
|
||
push cx
|
||
mov cx, 40h
|
||
mov ds, cx
|
||
mov bx, ax ;Salva il dato
|
||
mov bh, 3
|
||
RetryLp:
|
||
cli
|
||
|
||
; cancella il flag del registro KbdFlags4
|
||
; flags: Cancella errori , riconoscimento accettato, rispedisci flags
|
||
|
||
and byte ptr ds:[KbdFlags4], 4fh
|
||
|
||
;aspetta finche' l'8042 processa il comando corrente
|
||
|
||
xor cx, cx
|
||
|
||
SendCmd_Wait4Empty:
|
||
in al, 64h ;legge lo stato del registro
|
||
test al, 10b ;Input buffer pieno?
|
||
loopnz SendCmd_Wait4Empty ;aspetta finche' e' vuoto
|
||
|
||
|
||
; Ok spedisci i dato alla porta 60h
|
||
|
||
mov al, bl
|
||
out 60h, al
|
||
sti
|
||
|
||
; Wait for the arrival of an acknowledgement from the keyboard ISR:
|
||
|
||
xor cx, cx
|
||
Wait4Ack:
|
||
test byte ptr ds:[KbdFlags4], 10 ;Acknowledge received bit.
|
||
jnz GotAck
|
||
loop Wait4Ack
|
||
|
||
dec bh
|
||
jne RetryLp
|
||
|
||
; If the operation failed after 3 retries, set the error bit and quit.
|
||
|
||
or byte ptr ds:[KbdFlags4], 80h ;Set error bit.
|
||
|
||
GotAck:
|
||
pop cx
|
||
pop bx
|
||
pop ds
|
||
ret
|
||
|
||
;--------------------------------------
|
||
|
||
; variabili BIOS
|
||
|
||
KbdFlags1 equ 17h ; variabile che contiene lo stato dei tasti modificatori
|
||
KbdFlags2 equ 18h ; altra variabile " " " " " "
|
||
AltKpd equ 19h
|
||
HeadPtr equ 1ah ; puntatore alla testa del buffer
|
||
TailPtr equ 1ch ; puntatore alla coda del buffer
|
||
Buffer equ 1eh ; buffer
|
||
EndBuf equ 3eh
|
||
KbdFlags3 equ 96h ; miscellaneos keyboard flags
|
||
KbdFlags4 equ 97h ; " " " "
|
||
|
||
;variabili driver
|
||
|
||
OldInt09h dd ? |