Tvůrce webu je i pro tebe! Postav třeba web. Bez grafika. Bez kodéra. Hned.
wz

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