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

Obsah / Ovladače / CMOS / Globální funkce ovladače paměti CMOS

Zdrojový kód: DRIVERS\SYSTEM\CMOS.ASM


Globální funkce ovladače paměti CMOS

Globální funkce ovladače paměti CMOS se provádějí s implicitním ovladačem paměti CMOS, jehož popisovač je uchován v proměnné CMOSDevice.


; -----------------------------------------------------------------------------
;               CMOS global function: Read byte from CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EDX = index of byte (0 to 127)
; OUTPUT:	EAX = read byte (0 to 255, 0 on error)
;		CY = invalid index (EAX = 0)
; NOTES:	It locks fast spin-lock of device interface.
; NOTES:	It takes aprox. 4 us.
; -----------------------------------------------------------------------------

CMOSGetByte:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_GetByte ; read byte
		pop	ebx		; pop EBX
		ret

Funkce CMOSGetByte načte bajt z paměti CMOS. Na vstupu funkce obsahuje registr EDX index bajtu v rozsahu 0 až 127. Na výstupu funkce je v registru EAX navrácen načtený bajt v rozsahu 0 až 255. V případě chyby (zadán neplatný index bajtu) je navrácen příznak CY a obsah registru EAX je nulový. Funkce trvá přibližně 4 mikrosekundy. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;                CMOS global function: Write byte to CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	AL = data
;		EDX = index of data (0 to 127)
; OUTPUT:	CY = invalid index
; -----------------------------------------------------------------------------

CMOSSetByte:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_SetByte ; write byte
		pop	ebx		; pop EBX
		ret

Funkce CMOSSetByte uloží bajt do paměti CMOS. Na vstupu funkce obsahuje registr AL bajt k zápisu a registr EDX index bajtu v rozsahu 0 až 127. V případě chyby (zadán neplatný index bajtu) je navrácen příznak CY. Funkce trvá přibližně 4 mikrosekundy. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;               CMOS global function: Read data from CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EAX = data buffer
;		ECX = number of bytes (0 to 128)
;		EDX = start index (0 to 127)
; OUTPUT:	CY = invalid parameters (no data read)
; -----------------------------------------------------------------------------

CMOSGetData:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_GetData ; read data
		pop	ebx		; pop EBX
		ret

Funkce CMOSGetData načte data z paměti CMOS. Na vstupu funkce obsahuje registr EAX ukazatel na datový buffer (do kterého se data mají načíst), ECX počet bajtů k načtení v rozsahu 0 až 128 a EDX počáteční index dat v rozsahu 0 až 127. V případě chyby (zadán neplatný index nebo neplatný počet bajtů) je navrácen příznak CY a obsah bufferu zůstane nezměněn. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;                CMOS global function: Write data to CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EAX = data buffer
;		ECX = number of bytes (0 to 128)
;		EDX = start index (0 to 127)
; OUTPUT:	CY = invalid parameters (no data writen)
; -----------------------------------------------------------------------------

CMOSSetData:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_SetData ; write data
		pop	ebx		; pop EBX
		ret

Funkce CMOSSetData uloží data do paměti CMOS. Na vstupu funkce obsahuje registr EAX ukazatel na datový buffer (ze kterého se data mají uložit), ECX počet bajtů k uložení v rozsahu 0 až 128 a EDX počáteční index dat v rozsahu 0 až 127. V případě chyby (zadán neplatný index nebo neplatný počet bajtů) je navrácen příznak CY a žádná data nejsou zapsána. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;            CMOS global function: Read date and time from CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EDX = pointer to DATETIME buffer
; OUTPUT:	CY = time update is in progress (try again later) or DATETIME
;			entries are not	in valid range
; NOTES:	Time update flag can be set up to 2 ms.
;		Values are loaded into buffer even on error state.
;		It takes aprox. 40 us.
;		On some PC's day of week may be invalid (-> Sunday).
; -----------------------------------------------------------------------------

CMOSGetTime:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_GetTime ; read date and time
		pop	ebx		; pop EBX
		ret

Funkce CMOSGetTime načte datum a čas z paměti CMOS. Na vstupu funkce obsahuje registr EDX ukazatel na buffer DATETIME, do kterého se má datum a čas načíst. Jsou-li údaje v CMOS neplatné nebo pokud probíhá update cyklus času je navrácen příznak chyby CY. I v případě navrácené chyby jsou údaje z paměti CMOS načteny. Update cyklus znamená, že probíhá inkrementace času hodin a je potřeba čekat na jeho dokončení. Doba čekání se může pohybovat až do 2 milisekund. Položka dne v týdnu může být u některých PC neplatná a proto je sice načítána, ale není kontrolována na platnost. Je-li potřeba časový údaj načíst přesně, je třeba opakovaným čtením synchronizovat okamžik, kdy se zvýší údaj sekund. Funkce trvá typicky zhruba 40 mikrosekund. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;            CMOS global function: Write date and time to CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EDX = pointer to DATETIME buffer
; OUTPUT:	CY = error (currently not used, allways NC)
; NOTES:	It takes aprox. 50 us.
;		Next time increment begins 0.5 sec later.
; -----------------------------------------------------------------------------

CMOSSetTime:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_SetTime ; write date and time
		pop	ebx		; pop EBX
		ret

Funkce CMOSSetTime je funkce pro zápis aktuálního data a času do paměti CMOS. Na vstupu funkce obsahuje registr EDX ukazatel na buffer DATETIME, obsahující aktuální datum a čas (včetně dne v týdnu). V případě chyby funkce navrací příznak CY. První inkrementace času nastane 0,5 sekundy po zápisu času - při přesné synchronizaci času je proto potřeba čas nastavit v době za 0,5 sekundy po uběhnutí požadovaného času. Funkce trvá typicky zhruba 50 mikrosekund. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;               CMOS global function: Read alarm from CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EDX = pointer to DATETIME buffer
; OUTPUT:	EAX = flags (ALARM_ENABLED, ...)
;		CY = error
; NOTES:	It takes aprox. 20 us.
;		Unused entries (or on error) are initialized to 0:00:00 1/1/1
; -----------------------------------------------------------------------------

CMOSGetAlarm:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_GetAlrm ; read alarm
		pop	ebx		; pop EBX
		ret

Funkce CMOSGetAlarm je funkce pro načtení času alarmu z paměti CMOS. Na vstupu funkce obsahuje registr EDX ukazatel na buffer DATETIME, do kterého bude čas alarmu načten. Na výstupu funkce jsou v registru EAX navráceny příznaky (ALARM_ENABLED, ...). V případě chyby funkce vrací příznak CY. Nepoužité položky struktury jsou inicializovány na údaj 0:00:00 1/1/1. Funkce trvá typicky 20 mikrosekund. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;               CMOS global function: Write alarm to CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EAX = flags (ALARM_ENABLED, ...)
;		EDX = pointer to DATETIME buffer
; OUTPUT:	CY = error
; NOTES:	It takes aprox. 20 us.
; -----------------------------------------------------------------------------

CMOSSetAlarm:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_SetAlrm ; write alarm
		pop	ebx		; pop EBX
		ret

Funkce CMOSSetAlarm je funkce pro zápis času alarmu do paměti CMOS. Na vstupu funkce obsahuje registr EAX příznaky (ALARM_ENABLED,...) a registr EDX ukazatel na buffer DATETIME, obsahující čas alarmu. V případě chyby funkce navrací příznak CY. Funkce trvá typicky zhruba 20 mikrosekund. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;           CMOS global function: Get periodic interrupt rate (IRQ 8)
; -----------------------------------------------------------------------------
; OUTPUT:	CY = error
;		EAX = periodic interrupt rate (CMOS_RATE_NONE,...)
; NOTES:	It takes aprox. 8 us.
; -----------------------------------------------------------------------------

CMOSGetRate:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_GetRate ; get interrupt rate
		pop	ebx		; pop EBX
		ret

Funkce CMOSGetRate je funkce pro zjištění rychlosti periodického přerušení. Na výstupu funkce navrací v registru EAX rychlost přerušení - hodnotu CMOS_RATE_NONE, CMOS_RATE_8K atd. V případě chyby funkce navrací příznak CY. Funkce trvá typicky zhruba 8 mikrosekund.


; -----------------------------------------------------------------------------
;           CMOS global function: Set periodic interrupt rate (IRQ 8)
; -----------------------------------------------------------------------------
; INPUT:	EAX = periodic interrupt rate (CMOS_RATE_NONE,...)
; OUTPUT:	CY = error, invalid rate selection
; NOTES:	It takes aprox. 12 us.
; -----------------------------------------------------------------------------

CMOSSetRate:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_SetRate ; set interrupt rate
		pop	ebx		; pop EBX
		ret

Funkce CMOSSetRate je funkce pro nastavení rychlosti periodického přerušení. Na vstupu funkce obsahuje registr EAX rychlost přerušení (hodnota CMOS_RATE_NONE, CMOS_RATE_8K atd.). V případě chybného argumentu navrací funkce příznak chyby CY. CMOS_RATE_NONE přerušení zakáže, ostatní hodnoty přerušení povolí. Funkce trvá typicky zhruba 12 mikrosekund.


; -----------------------------------------------------------------------------
;                 CMOS global function: Acknowledge interrupt
; -----------------------------------------------------------------------------
; OUTPUT:	CY = error (currently not used, allways NC)
; NOTES:	It takes aprox. 4 us.
;		It reads status register C.
; -----------------------------------------------------------------------------

CMOSAckInt:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_AckInt ; acknowledge interrupt
		pop	ebx		; pop EBX
		ret

Funkce CMOSAckInt je funkce pro potvrzení periodického přerušení. Funkce je volána z obsluhy periodického přerušení. Informuje řadič hodin reálného času o zpracování přerušení, čímž umožní aktivaci příštího přerušení. Potvrzení přerušení se provádí čtením stavového registru C hodin reálného času. Funkce trvá typicky zhruba 4 mikrosekundy.


; -----------------------------------------------------------------------------
;                      CMOS global function: Reassert NMI
; -----------------------------------------------------------------------------

CMOSNextNMI:	push	ebx		; push EBX
		mov	ebx,[CMOSDevice] ; EBX <- current CMOS device
		DEVFNCLOCKC DEVCMOS_NextNMI ; get IRQ channel info
		pop	ebx		; pop EBX
		ret

Funkce CMOSNextNMI je funkce k reaktivaci dalšího nemaskovatelného přerušení po obsloužení nemaskovatelného přerušení. Funkce zajistí uzamknutí ovladače pomocí rychlého zámku.


; -----------------------------------------------------------------------------
;                    CMOS global function: Read CMOS time
; -----------------------------------------------------------------------------
; OUTPUT:	EDX:EAX = absolute time (100-nanoseconds from 1/1/1 CE 0:00)
;		CY = error (EDX:EAX = 0)
; NOTES:	Function takes normaly 40 us but it can take up to 10 ms.
; -----------------------------------------------------------------------------

; ------------- Push registers

GetCMOSTime:	push	ebx		; push EBX
		push	ecx		; push ECX
		push	esi		; push ESI
		push	ebp		; push EBP
		mov	ebp,esp		; EBP <- local variables
		sub	esp,DATETIME_size ; buffer for date-time structure

; ------------- Read date and time from CMOS (wait 256 * 40 = 10240 us)

		xor	ecx,ecx		; ECX <- 0
		mov	ch,1		; ECX <- 256, max. attempts (= 10 ms)
		xor	esi,esi		; ESI <- 0, old value - time
		xor	ebx,ebx		; EBX <- 0, old value - date
GetCMOSTime2:	mov	edx,esp		; EDX <- DATETIME buffer in stack
		call	CMOSGetTime	; read date and time
		jc	GetCMOSTime6	; error

; ------------- Check old value if it has been changed

		cmp	esi,[ebp-DATETIME_size+DATETIME_Time] ; check time
		jne	GetCMOSTime4	; change, try again
		cmp	ebx,[ebp-DATETIME_size+DATETIME_Date] ; check date
		jne	GetCMOSTime4	; change, try again

; ------------- Convert system time to absolute time
		
		mov	ebx,esp		; EBX <- DATETIME buffer in stack
		call	DateTimeToAbs	; convert date-time to absolute time
		clc			; clear error flag
		jmp	short GetCMOSTime8

; ------------- Next attempt

GetCMOSTime4:	mov	esi,[ebp-DATETIME_size+DATETIME_Time] ; ESI <- get time
		mov	ebx,[ebp-DATETIME_size+DATETIME_Date] ; EBX <- get date
GetCMOSTime6:	loop	GetCMOSTime2	; next attempt

; ------------- Error

		xor	eax,eax		; EAX <- 0
		xor	edx,edx		; EDX <- 0
		stc			; set error flag

; ------------- Pop registers

GetCMOSTime8:	mov	esp,ebp		; EPS <- return stack
		pop	ebp		; pop EBP
		pop	esi		; pop ESI
		pop	ecx		; pop ECX
		pop	ebx		; pop EBX
		ret

Funkce GetCMOSTime je funkce k načtení aktuálního času z paměti CMOS. Navrátí v registrech EDX:EAX aktuální čas v absolutním formátu (tj. počet 100-nsec od 0:00:00 1.1.1). V případě chyby (položky data a času jsou v paměti CMOS v neplatném tvaru) je navrácen příznak CY a obsah registrů EDX:EAX je nulový. Funkce zajistí čekání na ukončení aktualizace hodin a může trvat od 40 mikrosekund do 10 milisekund. Jsou používány funkce ovladače paměti CMOS, které si samy zajistí uzamknutí zámku ovladače. Proto může být funkce volána s povoleným přerušením, má-li být povolena obsluha přerušení během průběhu funkce.

Funkce opakovaně načítá čas pomocí funkce CMOSGetTime, dokud není načten bez chyby nebo není proveden dostatečný počet pokusů (=256) odpovídající zhruba 10 ms. V případě úspěšného načtení času (tj. položky v CMOS jsou platné a neprobíhá aktualizace času) je čas porovnán z předešlou hodnotou. Čas je považován za platný pouze v případě, že je 2x načten stejný údaj. V tom případě se zkonvertuje na absolutní formát.


; -----------------------------------------------------------------------------
;                    CMOS global function: Write CMOS time
; -----------------------------------------------------------------------------
; INPUT:	EDX:EAX = absolute time (100-nanoseconds from 1/1/1 CE 0:00)
; OUTPUT:	CY = error
; NOTES:	Function takes aprox. 50 us.
;		Next time increment begins 0.5 sec later.
; -----------------------------------------------------------------------------

; ------------- Push registers

SetCMOSTime:	push	ebx		; push EBX
		push	edx		; push EDX
		push	ebp		; push EBP
		mov	ebp,esp		; EBP <- local variables
		sub	esp,DATETIME_size ; buffer for date-time structure

; ------------- Convert absolute time to DATETIME

		mov	ebx,esp		; EBX <- DATETIME buffer in stack
		call	AbsToDateTime	; convert absolute time to date-time

; ------------- Write date and time to CMOS memory

		mov	edx,esp		; EDX <- DATETIME buffer in stack
		call	CMOSSetTime	; write date and time to CMOS memory

; ------------- Pop registers

		mov	esp,ebp		; EPS <- return stack
		pop	ebp		; pop EBP
		pop	edx		; pop EDX
		pop	ebx		; pop EBX
		ret

Funkce SetCMOSTime je funkce k zápisu aktuálního času do paměti CMOS. Na vstupu obsahují registry EDX:EAX aktuální čas v absolutním formátu (tj. počet 100-nsec od 0:00:00 1.1.1). V případě chyby je navrácen příznak CY. Funkce trvá přibližně 50 mikrosekund. První inkrementace času nastane 0,5 sekundy po zápisu času - při přesné synchronizaci času je proto potřeba čas nastavit v době za 0,5 sekundy po uběhnutí požadovaného času.


; -----------------------------------------------------------------------------
;                    CMOS global function: Read CMOS alarm
; -----------------------------------------------------------------------------
; OUTPUT:	EDX:EAX = absolute time (100-nanoseconds from 1/1/1 CE 0:00)
; 		ECX = flags (ALARM_ENABLED, ...)
;		CY = error (EDX:EAX = 0)
; NOTES:	It takes aprox. 20 us.
; -----------------------------------------------------------------------------

; ------------- Push registers

GetCMOSAlarm:	push	ebx		; push EBX
		push	ebp		; push EBP
		mov	ebp,esp		; EBP <- local variables
		sub	esp,DATETIME_size ; buffer for date-time structure

; ------------- Read alarm from CMOS

		mov	edx,esp		; EDX <- DATETIME buffer in stack
		call	CMOSGetAlarm	; read alarm
		xchg	eax,ecx		; ECX <- flags

; ------------- Convert system time to absolute time

		mov	ebx,esp		; EBX <- DATETIME buffer in stack
		pushf			; push flags (CY = error)
		call	DateTimeToAbs	; convert date-time to absolute time
		popf			; pop flags (CY = error)

; ------------- Pop registers

		mov	esp,ebp		; EPS <- return stack
		pop	ebp		; pop EBP
		pop	ebx		; pop EBX
		ret

Funkce GetCMOSAlarm je funkce k načtení alarmu z paměti CMOS. Navrátí v registrech EDX:EAX čas alarmu v absolutním formátu (tj. počet 100-nsec od 0:00:00 1.1.1). V registru ECX jsou navráceny příznaky (ALARM_ENABLED, ...). V případě chyby funkce vrací příznak CY a čas EDX:EAX = 0. Funkce trvá přibližně 20 mikrosekund.


; -----------------------------------------------------------------------------
;                    CMOS global function: Write CMOS alarm
; -----------------------------------------------------------------------------
; INPUT:	EDX:EAX = absolute time (100-nanoseconds from 1/1/1 CE 0:00)
; 		ECX = flags (ALARM_ENABLED, ...)
; OUTPUT:	CY = error
; NOTES:	Function takes aprox. 20 us.
; -----------------------------------------------------------------------------

; ------------- Push registers

SetCMOSAlarm:	push	ebx		; push EBX
		push	edx		; push EDX
		push	ebp		; push EBP
		mov	ebp,esp		; EBP <- local variables
		sub	esp,DATETIME_size ; buffer for date-time structure

; ------------- Convert absolute time to DATETIME

		mov	ebx,esp		; EBX <- DATETIME buffer in stack
		call	AbsToDateTime	; convert absolute time to date-time

; ------------- Write alarm to CMOS memory

		xchg	eax,ecx		; EAX <- flags, ECX <- time LOW
		mov	edx,esp		; EDX <- DATETIME buffer in stack
		call	CMOSSetAlarm	; write alarm to CMOS memory
		xchg	eax,ecx		; return EAX and ECX

; ------------- Pop registers

		mov	esp,ebp		; EPS <- return stack
		pop	ebp		; pop EBP
		pop	edx		; pop EDX
		pop	ebx		; pop EBX
		ret

Funkce SetCMOSAlarm je funkce k zápisu alarmu do paměti CMOS. Na vstupu obsahují registry EDX:EAX čas alarmu v absolutním formátu (tj. počet 100-nsec od 0:00:00 1.1.1). Registr ECX obsahuje příznaky (ALARM_ENABLED,...). V případě chyby je navrácen příznak CY. Funkce trvá přibližně 20 mikrosekund.


Obsah / Ovladače / CMOS / Globální funkce ovladače paměti CMOS