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

Obsah / Ovladače / CMOS / Funkce interface ovladače paměti CMOS

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


Funkce interface ovladače paměti CMOS


CMOSDevice:	dd	CMOSDev			; current CMOS device descr.

%define		CMOSDevVendor  DefaultVendor

CMOSDev:	DEVICECMOS 0,DEV_STATIC,1,0,0,CMOSDev

CMOSDevRes1:	DEVRESOURCE CMOSDevResN,CMOSDevRes0,CMOS_BASE,CMOS_BASE+1, \
		 DEVRES_PORT,DEVRES_STATIC,CMOSDevRes1Name

CMOSDevResN:	DEVRESOURCE CMOSDevRes0,CMOSDevRes1,CMOS_IRQ,CMOS_IRQ, \
		 DEVRES_IRQ,DEVRES_STATIC,CMOSDevRes2Name

CMOSDevName:	CTEXTDATA 'cmos'
CMOSDevShort:	CTEXTDATA 'CMOS MC146818'

CMOSDevRes1Name:CTEXTDATA 'ctrl'
CMOSDevRes2Name:CTEXTDATA 'irq'

CMOSDevFull:	LANGTEXTSTR CMOSDevFullEN,LANG_ENGLISH,SUBLANG_DEFAULT,2
 		LANGTEXTSTR CMOSDevFullCZ,LANG_CZECH,  SUBLANG_DEFAULT,0

CMOSDevFullEN:	CTEXTDATA 'CMOS memory MC146818'
CMOSDevFullCZ:	CTEXTDATA 'Pam',0c4h,9bh,0c5h,0a5h,' CMOS MC146818'

CMOSDevInt:	dd	DEV_GEN_ID
		dd	DEV_CMOS_ID
		dd	DEV_NUL_ID

CMOSDev je struktura popisovače standardního ovladače paměti CMOS. V proměnné CMOSDevice je uložen ukazatel na aktuální ovladač paměti CMOS - při instalaci nového ovladače je tento ukazatel přepsán novým ukazatelem.


; -----------------------------------------------------------------------------
;                           Install CMOS device
; -----------------------------------------------------------------------------
; OUTPUT:	CY = error
; -----------------------------------------------------------------------------

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

CMOSInstall:	push	ebx		; push EBX
		push	ecx		; push ECX

; ------------- Register CMOS device

		mov	ebx,CMOSDev	; 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 CMOSInstall nainstaluje standardní ovladač paměti CMOS - zaregistruje ovladač do systému. V případě chyby je navrácen příznak chyby CY.


; -----------------------------------------------------------------------------
;                           Uninstall CMOS device
; -----------------------------------------------------------------------------
; OUTPUT:	CY = error
; -----------------------------------------------------------------------------

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

CMOSUninstall:	push	ebx		; push EBX

; ------------- Unregister CMOS device

		mov	ebx,CMOSDev	; EBX <- device descriptor
		call	DevUnregister	; unregister device

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

		pop	ebx		; pop EBX
		ret

Funkce CMOSUninstall odinstaluje standardní ovladač paměti CMOS - 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 CMOS device
; -----------------------------------------------------------------------------
; INPUT:	EBX = device descriptor DEVCMOS
; OUTPUT:	CY = error
; -----------------------------------------------------------------------------

CMOSDevInit:	clc			; clear error flag
		ret

Funkce CMOSDevInit inicializuje ovladač paměti CMOS. U současné verze ovladače nepoužito.


; -----------------------------------------------------------------------------
;                   Driver function: Deinitialize CMOS device
; -----------------------------------------------------------------------------
; INPUT:	EBX = device descriptor DEVCMOS
; OUTPUT:	CY = error
; -----------------------------------------------------------------------------

CMOSDevDeinit:	clc			; clear error flag
		ret

Funkce CMOSDevDeinit deinicializuje ovladač paměti CMOS. U současné verze ovladače nepoužito.


; -----------------------------------------------------------------------------
;                 Driver function: Read byte from CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EBX = device descriptor DEVCMOS
;		EDX = index of byte (0 to 127)
; OUTPUT:	EAX = read byte (0 to 255, 0 on error)
;		CY = invalid index (EAX = 0)
; NOTES:	It takes aprox. 4 us.
; -----------------------------------------------------------------------------

; ------------- Check index of the byte

CMOSDevGetByte:	xor	eax,eax		; EAX <- 0
		cmp	edx,128		; check index of byte
		cmc			; CY = invalid index
		jc	CMOSDevGetByte4	; invalid index

; ------------- Read data

		GET_CMOS dl		; AL <- read CMOS byte
		clc			; clear error flag
CMOSDevGetByte4:ret

Funkce CMOSDevGetByte načte bajt z paměti CMOS. Na vstupu funkce obsahuje registr EBX ukazatel na popisovač zařízení DEVCMOS. Registr EDX obsahuje 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.


; -----------------------------------------------------------------------------
;                 Driver function: Write byte to CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	AL = data
;		EBX = device descriptor DEVCMOS
;		EDX = index of data (0 to 127)
;		CY = invalid index
; NOTES:	It takes aprox. 4 us.
; -----------------------------------------------------------------------------

; ------------- Check index of the byte

CMOSDevSetByte:	cmp	edx,128		; check index of byte
		cmc			; CY = invalid index
		jc	CMOSDevSetByte4	; invalid index

; ------------- Write byte

		xchg	eax,edx		; AL <- index of data
		out	CMOS_INDEX,al	; set index of the byte
		SHORT_DELAY		; short delay
		xchg	eax,edx		; AL <- byte to write to CMOS
		out	CMOS_DATA,al	; write byte into CMOS
CMOSDevSetByte4:ret

Funkce CMOSDevSetByte uloží bajt do paměti CMOS. Na vstupu funkce obsahuje registr AL bajt k zápisu, registr EBX ukazatel na popisovač zařízení DEVCMOS 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.


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

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

CMOSDevGetData:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX
		push	edi		; push EDI
		xchg	eax,edi		; EDI <- data buffer

; ------------- Check start index

		cmp	edx,128		; check start index
		cmc			; CY = invalid index
		jc	CMOSDevGetData8	; invalid index

; ------------- Check number of bytes

		mov	eax,edx		; EAX <- start index
		add	eax,ecx		; EAX <- end index
		jc	CMOSDevGetData8	; invalid number of bytes
		cmp	eax,129		; check end index
		cmc			; CY = invalid number of bytes
		jc	CMOSDevGetData8	; invalid number of bytes
		
; ------------- Read data from CMOS

		jecxz	CMOSDevGetData8	; no data to read (here is NC)
		cld			; set direction UP
CMOSDevGetData4:GET_CMOS dl		; AL <- read CMOS byte
		inc	edx		; increase index of byte
		stosb			; store byte
		loop	CMOSDevGetData4	; get next byte
		clc			; clear erro flag

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

CMOSDevGetData8:pop	edi		; pop EDI
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

Funkce CMOSDevGetData 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), EBX ukazatel na popisovač zařízení DEVCMOS, 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.


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

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

CMOSDevSetData:	push	eax		; push EAX
		push	ecx		; push ECX
		push	edx		; push EDX
		push	esi		; push ESI
		xchg	eax,esi		; ESI <- data buffer

; ------------- Check start index

		cmp	edx,128		; check start index
		cmc			; CY = invalid index
		jc	CMOSDevSetData8	; invalid index

; ------------- Check number of bytes

		mov	eax,edx		; EAX <- start index
		add	eax,ecx		; EAX <- end index
		jc	CMOSDevSetData8	; invalid number of bytes
		cmp	eax,129		; check end index
		cmc			; CY = invalid number of bytes
		jc	CMOSDevSetData8	; invalid number of bytes
		
; ------------- Write data to CMOS

		jecxz	CMOSDevSetData8	; no data to write (here is NC)
		cld			; set direction UP
CMOSDevSetData4:mov	al,dl		; AL <- index of data
		out	CMOS_INDEX,al	; set index of the byte
		SHORT_DELAY		; short delay
		lodsb			; AL <- load byte
		inc	edx		; increase index of byte
		out	CMOS_DATA,al	; write byte into CMOS
		loop	CMOSDevSetData4	; get next byte
		clc			; clear erro flag

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

CMOSDevSetData8:pop	esi		; pop ESI
		pop	edx		; pop EDX
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

Funkce CMOSDevSetData uloží data do paměti CMOS. Na vstupu funkce obsahuje registr EAX ukazatel na datový buffer (ze kterého se data mají uložit), EBX ukazatel na popisovač zařízení DEVCMOS, 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.


; -----------------------------------------------------------------------------
;              Driver function: Read date and time from CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EBX = device descriptor DEVCMOS
;		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 (replaced with Sunday).
; -----------------------------------------------------------------------------

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

CMOSDevGetTime:	push	eax		; push EAX
		push	esi		; push ESI
		push	edi		; push EDI

; ------------- Prepare registers

		mov	edi,edx		; EDI <- DATETIME buffer
		cld			; set direction UP

; ------------- Clear nanoseconds

		xor	eax,eax		; EAX <- 0
		stosd			; clear nanoseconds
		xchg	eax,esi		; ESI <- 0, index of register
		push	edi		; push buffer address

; ------------- Get "time update" flag on start of transmission

		GET_CMOS CMOS_STATUS_A	; read status register A
		shl	eax,16+3	; save "time update" flag

; ------------- Get "BIN mode" flag (-> bit 31)

		GET_CMOS CMOS_STATUS_B	; read status register B
		ror	eax,3		; roll BIN flag into bit 31

; ------------- Read seconds (index CMOS_SEC = 0)

		call	CMOSReadBCD	; read data

; ------------- Read minutes (index CMOS_MIN = 2)

		inc	esi		; icrease index of register
		call	CMOSReadBCD	; read data

; ------------- Read hours (index CMOS_HOUR = 4)

		inc	esi		; icrease index of register
		call	CMOSReadBCD	; read data

; ------------- Read day of week (index CMOS_DAYWEEK = 6)

		inc	esi		; icrease index of register
		call	CMOSReadBCD	; read data
		dec	al		; correction
		jz	CMOSDevGetTime1	; it is Sunday
		cmp	al,7		; check day of week
		jb	CMOSDevGetTime2	; day of week is OK
CMOSDevGetTime1:mov	al,7		; set to Sunday
CMOSDevGetTime2:dec	edi		; return buffer pointer
		stosb			; store day of week

; ------------- Read day in month (index CMOS_DAY = 7)

		call	CMOSReadBCD	; read data

; ------------- Read month (index CMOS_MONTH = 8)

		call	CMOSReadBCD	; read data

; ------------- Read year (index CMOS_YEAR = 9)

		call	CMOSReadBCD	; read data
		mov	ah,0		; AX = year
		cmp	al,80		; year 1980 or more
		jae	CMOSDevGetTime4	; it is year 1980 or more
		add	al,100		; century correction
CMOSDevGetTime4:add	ax,1900		; add century
		dec	edi		; return buffer pointer
		stosw			; store year

; ------------- Check seconds

		pop	esi		; ESI <- start of time
		lodsb			; load seconds
		cmp	al,59		; check seconds
		ja	CMOSDevGetTime6	; invalid entry

; ------------- Check minutes

		lodsb			; load minutes
		cmp	al,59		; check minutes
		ja	CMOSDevGetTime6	; invalid entry

; ------------- Check hours

		lodsb			; load hours
		cmp	al,23		; check hours
		ja	CMOSDevGetTime6	; invalid entry

; ------------- Check day in month

		inc	esi		; skip day of week
		lodsb			; load day in month
		cmp	al,1		; check day in month minimal
		jb	CMOSDevGetTime6	; invalid entry
		cmp	al,31		; check day in month maximal
		ja	CMOSDevGetTime6	; invalid entry

; ------------- Check month

		lodsb			; load month
		cmp	al,1		; check month minimal
		jb	CMOSDevGetTime6	; invalid entry
		cmp	al,12		; check month maximal
		ja	CMOSDevGetTime6	; invalid entry

; ------------- Get and check "time update" flag on end of transmission
; This second check is NOT necessary - after setting UIP flag we have 244 us.

		GET_CMOS CMOS_STATUS_A	; read status register A
		and	eax,(RTC_UIP << 16) + RTC_UIP ; check time update flag
		jz	CMOSDevGetTime8	; time update is not in progress

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

CMOSDevGetTime6:stc			; set error flag
CMOSDevGetTime8:pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	eax		; pop EAX
		ret

Funkce CMOSDevGetTime načte datum a čas z paměti CMOS. Na vstupu funkce obsahuje registr EBX ukazatel na popisovač zařízení DEVCMOS a 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 načte z CMOS nejdříve příznak aktualizace času (stavový registr A), dále příznak binárního módu položek (stavový registr B) a nakonec všechny potřebné položky data a času. Během načítání automaticky převádí položky z kódu BCD na BIN, je-li to potřebné. Den v týdnu převede z formátu CMOS (1=neděle...7=sobota) na formát DATETIME (1=pondělí..7=neděle). K roku přičte století - buď 1900 (pro 80 až 99) nebo 2000 (pro 00 až 79). Následuje kontrola rozsahů položek. U data není ověřena platnost data ale pouze platnost rozsahu položek. Den v týdnu není kontrolován (může mít u některých PC neplatnou hodnotu, ale k výpočtu data není zapotřebí). Nakonec se znovu načte stavový registr A a ověří se zda neprobíhá aktualizace času. Pokud na začátku nebo na konci funkce probíhala aktualizace času, je navrácen příznak chyby. Podle dokumentace řadiče paměti CMOS není tato druhá kontrola na konci funkce nutná, protože aktualizace času začíná nejdříve až 244 mikrosekund od zapnutí příznaku aktualizace, takže funkce by měla mít dostatek času k načtení platných údajů.


; -----------------------------------------------------------------------------
;              Driver function: Write date and time to CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EBX = device descriptor DEVCMOS
;		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.
; -----------------------------------------------------------------------------

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

CMOSDevSetTime:	push	eax		; push EAX
		push	edx		; push EDX
		push	esi		; push ESI
		push	edi		; push EDI

; ------------- Prepare registers

		mov	esi,edx		; ESI <- DATETIME buffer
		cld			; set direction UP
		lodsd			; skip nanoseconds
		xor	edi,edi		; EDI <- 0, index of data

; ------------- Set RTC_SET flag (=abort update cycle)

		GET_CMOS CMOS_STATUS_B	; read status register B
		mov	dl,al		; DL <- save register B
		or	al,RTC_SET	; set RTC_SET flag
		out	CMOS_DATA,al	; write byte into CMOS

; ------------- Reset stage divider

		GET_CMOS CMOS_STATUS_A	; read status register A
		mov	dh,al		; DH <- save register A
		or	al,70h		; set RESET divider flag
		out	CMOS_DATA,al	; write byte into CMOS

; ------------- Write seconds (index CMOS_SEC = 0)

        	lodsb			; load seconds
		call	CMOSWriteBCD	; write data

; ------------- Write minutes

        	lodsb			; load minutes
		inc	edi		; icrease index of register
		call	CMOSWriteBCD	; write data

; ------------- Write hours

        	lodsb			; load hours
		inc	edi		; icrease index of register
		call	CMOSWriteBCD	; write data

; ------------- Write day of week

        	lodsb			; load day of week
		inc	eax		; correction
		cmp	al,8		; Sunday?
		jb	CMOSDevSetTime2	; no
		mov	al,1		; AL <- 1, Sunday
CMOSDevSetTime2:inc	edi		; icrease index of register
		call	CMOSWriteBCD	; write data

; ------------- Write day in month

        	lodsb			; load day in month
		call	CMOSWriteBCD	; write data

; ------------- Write month

        	lodsb			; load month
		call	CMOSWriteBCD	; write data

; ------------- Write year

        	lodsw			; load year
		sub	ax,1900		; year correction
		cmp	al,99		; maximal value
		jbe	CMOSDevSetTime4	; value is OK
		sub	al,100		; century correction
CMOSDevSetTime4:call	CMOSWriteBCD	; write data

; ------------- Return status register B

		mov	al,CMOS_STATUS_B ; AL <- index of status reg. B
		out	CMOS_INDEX,al	; set index of the byte
		SHORT_DELAY		; short delay
		xchg	eax,edx		; AL <- byte to write to CMOS
		out	CMOS_DATA,al	; write byte into CMOS

; ------------- Return status register A

		mov	al,CMOS_STATUS_A ; AL <- index of status reg. A
		out	CMOS_INDEX,al	; set index of the byte
		SHORT_DELAY		; short delay
		xchg	al,ah		; AL <- byte to write to CMOS
		out	CMOS_DATA,al	; write byte into CMOS

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

		pop	edi		; pop EDI
		pop	esi		; pop ESI
		pop	edx		; pop EDX
		pop	eax		; pop EAX
		clc			; clear error flag
		ret

Funkce CMOSDevSetTime je funkce pro zápis aktuálního data a času do paměti CMOS. Na vstupu funkce obsahuje registr EBX ukazatel na popisovač zařízení DEVCMOS a 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 (v současné verzi driveru je vždy NC). 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 nejdříve nastaví ve stavovém registru B příznakový bit RTC_SET. Tím aktivuje režim nastavování času a zakáže tak automatickou aktualizaci času. Dále pomocí registru A resetuje 22-stupňovou předděličku. To zajistí, že první posun času začne 0,5 sekundy po ukončení zápisu. Následuje zápis jednotlivých položek času. Položky jsou automaticky převáděny do kódu BCD, je-li to potřeba. Den v týdnu je převeden z formátu DATETIME (1=pondělí..7=neděle) na formát CMOS (1=neděle..7=sobota). Rok je zapsán jako offset od 1900 příp. 2000. Na závěr funkce je navrácen původní obsah registru B - tím se povolí automatická aktualizace hodin - a původní obsah registru A - tím se uvolní blokování předděličky a čítání času se rozběhne.


; -----------------------------------------------------------------------------
;                   Driver function: Read alarm from CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EBX = device descriptor DEVCMOS
;		EDX = pointer to DATETIME buffer
; OUTPUT:	EAX = flags (ALARM_ENABLED, ...)
;		CY = error (currently always NC)
; NOTES:	It takes aprox. 20 us.
;		Unused entries are initialized to 0:00:00 1/1/1
; -----------------------------------------------------------------------------

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

CMOSDevGetAlrm:	push	ecx		; push ECX
		push	edi		; push EDI

; ------------- Initialize DATETIME buffer (-> ECX = 0)

		cld			; set direction UP
		mov	edi,edx		; EDI <- DATETIME buffer
		xor	eax,eax		; EAX <- 0
		mov	ecx,DATETIME_size/4 ; ECX <- size of the buffer
		rep	stosd		; clear DATETIME buffer
		mov	edi,edx		; EDI <- DATETIME buffer
		stosd			; skip nanoseconds
		inc	eax		; EAX <- 1
		mov	byte [edi-4+DATETIME_WDay],6 ; Saturday
		mov	[edi-4+DATETIME_Day],al ; day in month
		mov	[edi-4+DATETIME_Month],al ; month
		mov	[edi-4+DATETIME_Year],al ; year

; ------------- Get "BIN mode" flag (-> bit 31), check "alarm enabled" flag

		GET_CMOS CMOS_STATUS_B	; read status register B
		test	al,RTC_AIE	; alarm interrupt enabled?
		jz	CMOSDevGetAlrm2	; alarm not enabled
		or	cl,ALARM_ENABLED ; set "alarm enabled" flag
CMOSDevGetAlrm2:ror	eax,3		; roll BIN flag into bit 31

; ------------- Read seconds

		mov	ax,ALARM_USE_SEC*256 + CMOS_ALARM_SEC ; index+flag
		call	CMOSReadAlarm	; read data

; ------------- Read minutes

		mov	ax,ALARM_USE_MIN*256 + CMOS_ALARM_MIN ; index+flag
		call	CMOSReadAlarm	; read data

; ------------- Read hours

		mov	ax,ALARM_USE_HOUR*256 + CMOS_ALARM_HOUR ; index+flag
		call	CMOSReadAlarm	; read data

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

		xchg	eax,ecx		; EAX <- flags
		clc			; clear error flag
		pop	edi		; pop EDI
		pop	ecx		; pop ECX
		ret

Funkce CMOSDevGetAlrm je funkce pro načtení času alarmu z paměti CMOS. Na vstupu funkce obsahuje registr EBX popisovač zařízení DEVCMOS a 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 (v současné verzi driveru je vždy NC). Nepoužité položky struktury jsou inicializovány na údaj 0:00:00 1/1/1. Funkce trvá typicky 20 mikrosekund.

Na začátku funkce se nejdříve inicializuje buffer DATETIME na implicitní položky. Ze stavového registru B se načte příznak binárního formátu dat a příznak povolení alarmu. Do bufferu se načtou jednotlivé položky. Je-li potřeba, jsou automaticky převedené z kódu BCD na BIN. Je-li položka v platném stavu, je nastaven příslušný příznakový bit navrácených příznaků.


; -----------------------------------------------------------------------------
;                Driver function: Write alarm to CMOS memory
; -----------------------------------------------------------------------------
; INPUT:	EAX = flags (ALARM_ENABLED, ...)
;		EBX = device descriptor DEVCMOS
;		EDX = pointer to DATETIME buffer
; OUTPUT:	CY = error (currently not used, allways NC)
; NOTES:	It takes aprox. 20 us.
; -----------------------------------------------------------------------------

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

CMOSDevSetAlrm:	push	eax		; push EAX
		push	ecx		; push ECX
		push	esi		; push ESI

; ------------- Prepare registers

		xchg	eax,ecx		; ECX <- flags
		mov	esi,edx		; ESI <- DATETIME buffer
		cld			; set direction UP
		lodsd			; skip nanoseconds

; ------------- Get "BIN mode" flag (-> bit 31), clear "alarm enabled" flag

		GET_CMOS CMOS_STATUS_B	; read status register B
		mov	ch,al		; CH <- save status byte
		test	al,RTC_AIE	; was interrupt enabled?
		jz	CMOSDevSetAlrm2	; interrupt was not enabled
		and	al,~RTC_AIE	; clear alarm enabled flag
		out	CMOS_DATA,al	; set new alarm enabled flag
CMOSDevSetAlrm2:ror	eax,3		; roll BIN flag into bit 31

; ------------- Write seconds

		mov	ax,ALARM_USE_SEC*256 + CMOS_ALARM_SEC ; index + flag
		call	CMOSWriteAlarm	; write data

; ------------- Write minutes

		mov	ax,ALARM_USE_MIN*256 + CMOS_ALARM_MIN ; index + flag
		call	CMOSWriteAlarm	; write data

; ------------- Write hours

		mov	ax,ALARM_USE_HOUR*256 + CMOS_ALARM_HOUR ; index + flag
		call	CMOSWriteAlarm	; write data

; ------------- Alarm enable

		test	cl,ALARM_ENABLED ; check flag
		jz	CMOSDevSetAlrm4	; alarm is not enabled
		mov	al,CMOS_STATUS_B ; AL <- index of status register B
		out	CMOS_INDEX,al	; set index of the byte
		SHORT_DELAY		; short delay
		mov	al,ch		; AL <- old value
		or	al,RTC_AIE	; set alarm enabled flag
		out	CMOS_DATA,al	; set new alarm enabled flag

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

CMOSDevSetAlrm4:clc			; clear error flag
		pop	esi		; pop ESI
		pop	ecx		; pop ECX
		pop	eax		; pop EAX
		ret

Funkce CMOSDevSetAlrm je funkce pro zápis času alarmu do paměti CMOS. Na vstupu funkce obsahuje registr EAX příznaky (ALARM_ENABLED,...), EBX popisovač zařízení DEVCMOS a registr EDX ukazatel na buffer DATETIME, obsahující čas alarmu. V případě chyby funkce navrací příznak CY (v současné verzi driveru je vždy NC). Funkce trvá typicky zhruba 20 mikrosekund.

Na začátku funkce je ze stavového registru B načten příznak binárního módu dat. Pokud bylo přerušení povoleno, je nejdříve zakázáno, aby nenastalo přerušení během provádění zápisu. Dále jsou zapsány položky alarmu. Je-li potřeba, jsou položky automaticky převedeny na formát BCD. Pro neplatné položky je uložena hodnota indikující neplatnost položky. Na závěr je alarm povolen, pokud bylo povolení požadováno.


; -----------------------------------------------------------------------------
;             Driver function: Get periodic interrupt rate (IRQ 8)
; -----------------------------------------------------------------------------
; INPUT:	EBX = device descriptor DEVCMOS
; OUTPUT:	CY = error (currently not used, allways NC)
;		EAX = periodic interrupt rate (CMOS_RATE_NONE,...)
; NOTES:	It takes aprox. 8 us.
; -----------------------------------------------------------------------------

; ------------- Check if periodic interrupt is enabled

CMOSDevGetRate:	GET_CMOS CMOS_STATUS_B	; read status register B
		and	eax,RTC_PIE	; is periodic interrupt enabled?
		jz	CMOSDevGetRate9	; periodic interrupt is disabled

; ------------- Get periodic interrupt rate

		GET_CMOS CMOS_STATUS_A	; read status register A
		and	al,0fh		; mask rate selection bits
CMOSDevGetRate9:ret

Funkce CMOSDevGetRate je funkce pro zjištění rychlosti periodického přerušení. Na vstupu funkce obsahuje registr EBX popisovač ovladače paměti CMOS. 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 (v současné verzi driveru je vždy NC). Funkce trvá typicky zhruba 8 mikrosekund.


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

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

CMOSDevSetRate:	push	eax		; push EAX

; ------------- Check rate selection value

		cmp	eax,CMOS_RATE_MAX+1 ; check rate selection
		cmc			; CY = error flag
		jc	CMOSDevSetRate9	; invalid rate selection

; ------------- Check if periodic interrupt is enabled

		or	eax,eax		; should be disabled?
		jz	CMOSDevSetRate6	; disable periodic interrupt

; ------------- Set periodic interrupt rate

		mov	ah,al		; AH <- save rate selection
		GET_CMOS CMOS_STATUS_A	; read status register A
		and	al,~0fh		; clear rate selection bits
		or	al,ah		; set rate selection bits
		SHORT_DELAY		; short delay
		out	CMOS_DATA,al	; write byte to CMOS

; ------------- Enable periodic interrupt (it returns NC)

		mov	ah,RTC_PIE	; enable periodic interrupt

; ------------- Set periodic interrupt (AH=PIE bit, it returns NC)

CMOSDevSetRate6:GET_CMOS CMOS_STATUS_B	; read status register B
		and	al,~RTC_PIE	; disable periodic interrupt
		or	al,ah		; set periodic interrupt bit
		SHORT_DELAY		; short delay
		out	CMOS_DATA,al	; write byte to CMOS

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

CMOSDevSetRate9:pop	eax		; pop EAX
		ret

Funkce CMOSDevSetRate 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.), EBX popisovač ovladače paměti CMOS. 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.


; -----------------------------------------------------------------------------
;                   Driver function: Acknowledge interrupt
; -----------------------------------------------------------------------------
; INPUT:	EBX = device descriptor DEVCMOS
; OUTPUT:	CY = error (currently not used, allways NC)
; NOTES:	It takes aprox. 4 us.
;		It reads status register C.
; -----------------------------------------------------------------------------

CMOSDevAckInt:	push	eax		; push EAX
		GET_CMOS CMOS_STATUS_C	; read status register C
		clc			; clear error flag
		pop	eax		; pop EAX
		ret

Funkce CMOSDevAckInt 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. Na vstupu funkce obsahuje registr EBX popisovač ovladače paměti CMOS. Funkce trvá typicky zhruba 4 mikrosekundy.


; -----------------------------------------------------------------------------
;                     Driver function: Reassert NMI
; -----------------------------------------------------------------------------
; INPUT:	EBX = device descriptor DEVCMOS
; -----------------------------------------------------------------------------

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

CMOSDevNextNMI:	push	eax		; push EAX

; ------------- Disable NMI

		mov	al,B7 + CMOS_REG_DEF ; AL <- NMI disabled
		out	CMOS_INDEX,al	; disable NMI
		in	al,CMOS_DATA	; ...dummy

; ------------- Enable NMI

		mov	al,CMOS_REG_DEF	; AL <- NMI enabled
		out	CMOS_INDEX,al	; enable NMI
		in	al,CMOS_DATA	; ...dummy

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

		pop	eax		; pop EAX
		ret

Funkce CMOSDevNextNMI je funkce k reaktivaci dalšího nemaskovatelného přerušení po obsloužení nemaskovatelného přerušení. Na vstupu funkce obsahuje registr EBX popisovač zařízení DEVCMOS.


Obsah / Ovladače / CMOS / Funkce interface ovladače paměti CMOS