Obsah / Ovladače / TIMER / Funkce interface ovladače časovače
Zdrojový kód:
DRIVERS\SYSTEM\TIMER.ASM
Funkce
interface ovladače časovače
TIMER_BASE EQU 40h ; TIMER base register
TIMER_CTRL EQU TIMER_BASE+3 ; TIMER control register
TIMERDevice: dd TIMERDev ; current TIMER device descr.
%define TIMERDevVendor DefaultVendor
align 8, db 0
TIMERDev: DEVICETIMER DEV_STATIC,1,0,0,TIMERDev
TIMERDevRes1: DEVRESOURCE TIMERDevResN,TIMERDevRes0,TIMER_BASE,TIMER_BASE+3, \
DEVRES_PORT,DEVRES_STATIC,TIMERDevRes1Name
TIMERDevResN: DEVRESOURCE TIMERDevRes0,TIMERDevRes1,TIMER_IRQ,TIMER_IRQ, \
DEVRES_IRQ,DEVRES_STATIC,TIMERDevRes2Name
TIMERDevName: CTEXTDATA 'timer'
TIMERDevShort: CTEXTDATA 'Timer 8254'
TIMERDevFull: LANGTEXTSTR TIMERDevFullEN,LANG_ENGLISH,SUBLANG_DEFAULT,2
LANGTEXTSTR TIMERDevFullCZ,LANG_CZECH, SUBLANG_DEFAULT,0
TIMERDevFullEN: CTEXTDATA 'Programmable interval timer Intel 8254'
TIMERDevFullCZ: CTEXTDATA 'Programovateln',0c3h,0bdh,' ',0c4h,8dh,'asova', \
0c4h,8dh,' Intel 8254'
TIMERDevInt: dd DEV_GEN_ID
dd DEV_TIMER_ID
dd DEV_NUL_ID
TIMERDevRes1Name:CTEXTDATA 'ctrl'
TIMERDevRes2Name:CTEXTDATA 'irq'
|
TIMER_BASE
je bázová adresa portů časovače. TIMER_CTRL
je adresa řídicího portu
TIMERDev
je struktura popisovače standardního ovladače časovače. V
proměnné TIMERDevice je uložen ukazatel na
aktuální ovladač časovače - při instalaci nového ovladače
je tento ukazatel přepsán novým ukazatelem.
; -----------------------------------------------------------------------------
; Install TIMER device
; -----------------------------------------------------------------------------
; OUTPUT: CY = error
; -----------------------------------------------------------------------------
; ------------- Push registers
TIMERInstall: push ebx ; push EBX
push ecx ; push ECX
; ------------- Register TIMER device
mov ebx,TIMERDev ; EBX <- device descriptor
xor ecx,ecx ; ECX <- 0, no parent device
call DevRegister ; register device
; ------------- Pop registers
pop ecx ; pop ECX
pop ebx ; pop EBX
ret
|
Funkce TIMERInstall
nainstaluje standardní ovladač časovače - zaregistruje
ovladač do systému. V případě chyby je navrácen příznak
chyby CY.
; -----------------------------------------------------------------------------
; Uninstall TIMER device
; -----------------------------------------------------------------------------
; OUTPUT: CY = error
; -----------------------------------------------------------------------------
; ------------- Push registers
TIMERUninstall: push ebx ; push EBX
; ------------- Unregister IRQ device
mov ebx,TIMERDev ; EBX <- device descriptor
call DevUnregister ; unregister device
; ------------- Pop registers
pop ebx ; pop EBX
ret
|
Funkce TIMERUninstall
odinstaluje standardní ovladač časovače - odregistruje
ovladač ze systému. V případě chyby je navrácen příznak
chyby CY. Funkce nezajistí instalaci náhradního ovladače
paměti CMOS.
; -----------------------------------------------------------------------------
; Driver function: Initialize TIMER device
; -----------------------------------------------------------------------------
; INPUT: EBX = device descriptor DEVTIMER
; OUTPUT: CY = error
; -----------------------------------------------------------------------------
TIMERDevInit: clc ; clear error flag
ret
|
Funkce TIMERDevInit
inicializuje ovladač časovače. U současné verze ovladače
nepoužito.
; -----------------------------------------------------------------------------
; Driver function: Deinitialize TIMER device
; -----------------------------------------------------------------------------
; INPUT: EBX = device descriptor DEVTIMER
; OUTPUT: CY = error
; -----------------------------------------------------------------------------
TIMERDevDeinit: clc ; clear error flag
ret
|
Funkce TIMERDevDeinit
deinicializuje ovladač časovače. U současné verze ovladače
nepoužito.
; -----------------------------------------------------------------------------
; Driver function: Initialize counter
; -----------------------------------------------------------------------------
; INPUT: EAX = timer mode (DEVTIM_MODE_CNT, ...)
; EBX = device descriptor DEVTIMER
; ECX = counter initial value (1 to 65536, 0 stands for 65536)
; EDX = counter index (0 to 2)
; OUTPUT: CY = error, invalid arguments
; NOTES: On mode DEVTIM_MODE_GEN value of 1 is illegal (not checked).
; It takes aprox. 7 us.
; -----------------------------------------------------------------------------
; ------------- Check arguments
TIMERDevSetMode:cmp eax,DEVTIM_MODE_MAX ; check mode
ja TIMERDevSetMod9 ; invalid mode
cmp ecx,65536 ; check maximal initial value
ja TIMERDevSetMod9 ; invalid initial value
cmp edx,2 ; check counter index
ja TIMERDevSetMod9 ; invalid counter index
; ------------- Push registers
push eax ; push EAX
push edx ; push EDX
; ------------- Prepare control word -> AL
shl eax,1 ; AL = timer mode << 1, BIN mode
or al,B5+B4 ; set 2-byte mode
mov ah,dl ; AH <- counter index
shl ah,6 ; AH <- shift to bits 6-7
or al,ah ; AH <- add counter index
; ------------- Set counter mode
out TIMER_CTRL,al ; set counter mode
SHORT_DELAY ; short delay
; ------------- Prepare counter port -> EDX (it sets NC)
TIMERDevSetMod4:add dl,TIMER_BASE ; EDX <- counter port
; ------------- Set initial value LOW
mov al,cl ; AL <- initial value LOW
out dx,al ; set initial value LOW
SHORT_DELAY ; short delay
; ------------- Set initial value HIGH
mov al,ch ; AL <- initial value HIGH
out dx,al ; set initial value HIGH
; ------------- Pop registers (here is NC)
pop edx ; pop EDX
pop eax ; pop EAX
ret
; ------------- Error
TIMERDevSetMod9:stc ; set error flag
ret
|
Funkce TIMERDevSetMode
je funkce pro inicializaci čítače časovače. Na vstupu funkce
obsahuje registr EAX požadovaný mód čítače
(DEVTIM_MODE_CNT, ...), EBX popisovač ovladače časovače,
registr ECX inicializační hodnotu čítače (v rozsahu 0 až
65536, přičemž hodnota 0 má význam hodnoty 65536) a registr
EDX index čítače (v rozsahu 0 až 2). Čítač je vždy
používán jako 16-bitový. V případě neplatného argumentu
navrátí funkce příznak chyby CY. V módu DEVTIM_MODE_GEN je
inicializační hodnota čítače 1 neplatná, ale není funkcí
kontrolována platnost. Nastavením nového módu čítače se
přeruší probíhající čítání a čítač se resetuje.
Funkce trvá typicky zhruba 7 mikrosekund.
; -----------------------------------------------------------------------------
; Driver function: Set new counter initial value
; -----------------------------------------------------------------------------
; INPUT: EBX = device descriptor DEVTIMER
; ECX = new counter init. value (1 to 65536, 0 stands for 65536)
; EDX = counter index (0 to 2)
; OUTPUT: CY = error, invalid arguments
; NOTES: On mode DEVTIM_MODE_GEN value of 1 is illegal (not checked).
; It takes aprox. 4 us.
; -----------------------------------------------------------------------------
; ------------- Check arguments
TIMERDevSetVal: cmp ecx,65536 ; check maximal initial value
ja TIMERDevSetMod9 ; invalid initial value
cmp edx,2 ; check counter index
ja TIMERDevSetMod9 ; invalid counter index
; ------------- Push registers
push eax ; push EAX
push edx ; push EDX
jmp short TIMERDevSetMod4
|
Funkce TIMERDevSetVal
je funkce k nastavení nové inicializační hodnoty čítače
bez nastavení módu čítače a tedy bez resetování čítače.
Nová inicializační hodnota čítače se uplatní zpravidla
při následujícím cyklu. Na vstupu funkce obsahuje registr EBX
popisovač ovladače časovače, registr ECX inicializační
hodnotu čítače (v rozsahu 0 až 65536, přičemž hodnota 0
má význam hodnoty 65536) a registr EDX index čítače (v
rozsahu 0 až 2). Čítač je vždy používán jako 16-bitový.
V případě neplatného argumentu navrátí funkce příznak
chyby CY. V módu DEVTIM_MODE_GEN je inicializační hodnota
čítače 1 neplatná, ale není funkcí kontrolována platnost.
Funkce trvá typicky zhruba 4 mikrosekundy.
; -----------------------------------------------------------------------------
; Driver function: Get counter current value
; -----------------------------------------------------------------------------
; INPUT: EBX = device descriptor DEVTIMER
; EDX = counter index (0 to 2)
; OUTPUT: EAX = current counter value (0 on error)
; CY = error, invalid arguments (EAX=0)
; NOTES: It takes aprox. 7 us.
; -----------------------------------------------------------------------------
; ------------- Check arguments
TIMERDevGetVal: cmp edx,2 ; check counter index
ja TIMERDevGetVal9 ; invalid counter index
; ------------- Push registers
push edx ; push EDX
; ------------- Prepare control word -> EAX
mov eax,edx ; EAX <- counter index
shl eax,6 ; EAX <- shift to bits 6-7
; ------------- Set counter latch command
out TIMER_CTRL,al ; set counter latch command
SHORT_DELAY ; short delay
; ------------- Prepare counter port -> EDX (it sets NC)
add dl,TIMER_BASE ; EDX <- counter port
; ------------- Get current value LOW
in al,dx ; AL <- get current value LOW
SHORT_DELAY ; short delay
mov ah,al ; AH <- current value LOW
; ------------- Get current value HIGH
in al,dx ; AL <- get current value HIGH
xchg al,ah ; AL <- value LOW, AH <- value HIGH
; ------------- Pop registers (here is NC)
pop edx ; pop EDX
ret
; ------------- Error
TIMERDevGetVal9:xor eax,eax ; EAX <- 0
stc ; set error flag
ret
|
Funkce TIMERDevGetVal
je funkce ke zjištění aktuální hodnoty čítače. Na vstupu
funkce obsahuje registr EBX popisovač ovladače časovače a
registr EDX index čítače (v rozsahu 0 až 2). Funkce vrací na
výstupu v registru EAX aktuální hodnotu čítače. Čítač je
vždy používán jako 16-bitový. V případě neplatného
argumentu navrátí funkce příznak chyby CY. Funkce trvá
typicky zhruba 7 mikrosekund.
; -----------------------------------------------------------------------------
; Driver function: Get counter output
; -----------------------------------------------------------------------------
; INPUT: EBX = device descriptor DEVTIMER
; EDX = counter index (0 to 2)
; OUTPUT: EAX = current counter output (0 or 1)
; CY = error, invalid arguments (EAX=0)
; NOTES: It takes aprox. 4 us.
; -----------------------------------------------------------------------------
; ------------- Check arguments
TIMERDevGetOut: cmp edx,2 ; check counter index
ja TIMERDevGetVal9 ; invalid counter index
; ------------- Push registers
push edx ; push EDX
; ------------- Set counter LATCH STATUS command
mov al,B1 ; AL <- prepare bit of COUNTER 0
xchg ecx,edx ; CL <- counter index
shl al,cl ; AL <- counter bit
xchg ecx,edx ; ECX, EDX <- return old value
or al,B7+B6+B5 ; prepare LATCH STATUS command
out TIMER_CTRL,al ; set LATCH STATUS command
SHORT_DELAY ; short delay
; ------------- Get current status
xor eax,eax ; EAX <- 0
add dl,TIMER_BASE ; EDX <- counter port
in al,dx ; AL <- get current status
or al,al ; check bit 7 (= OUT pin value)
sets al ; EAX <- 1 if OUT is "1", else 0
; ------------- Pop registers (here is NC)
pop edx ; pop EDX
ret
|
Funkce TIMERDevGetOut
je funkce ke zjištění stavu výstupu OUT čítače. Na vstupu
funkce obsahuje registr EBX popisovač ovladače časovače a
registr EDX index čítače (v rozsahu 0 až 2). Funkce vrací na
výstupu v registru EAX aktuální stav OUT čítače, hodnotu 0
nebo 1. V případě neplatného argumentu navrátí funkce
příznak chyby CY (EAX = 0). Funkce trvá typicky zhruba 4
mikrosekundy. Funkce je podporována pouze u řadiče 8254
(standardní řadič v PC-AT) ale ne u 8253 (řadič používaný
v PC-XT).
Obsah / Ovladače / TIMER / Funkce interface ovladače časovače