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