First commit

This commit is contained in:
Alberto Venturini 2014-01-27 10:02:18 +01:00
commit 7d6d50e432
50 changed files with 5737 additions and 0 deletions

554
KEYBOARD.ASM Normal file
View file

@ -0,0 +1,554 @@
;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 ?