]>
wirehaze git hosting - MS-DOS.git/blob - v4.0/src/BIOS/MSCLOCK.ASM
1 TITLE MSCLOCK
- DOS
3.3
2 ;----------------------------------------------------------------
4 ; CLOCK DEVICE DRIVER :
7 ; This file contains the Clock Device Driver. :
9 ; The routines in this files are: :
13 ; TIM$WRIT Set the current time :
14 ; TIM$READ Read the current time :
15 ; Time_To_Ticks Convert time to corresponding :
16 ; number of clock ticks :
18 ; The clock ticks at the rate of: :
20 ; 1193180/65536 ticks/second (about 18.2 ticks per second):
21 ; See each routine for information on the use. :
23 ;----------------------------------------------------------------
27 INCLUDE MSGROUP
.INC ;DEFINE CODE SEGMENT
32 ; DAYCNT is the number of days since 1-1-80.
33 ; Each time the clock is read it is necessary to check if another day has
34 ; passed. The ROM only returns the day rollover once so if it is missed
35 ; the time will be off by a day.
37 EXTRN DAYCNT
:WORD ;MSDATA
39 ;;Rev 3.30 Modification ------------------------------------------------
40 ; variables for real time clock setting
42 HaveCMOSClock db 0 ;set by MSINIT.
48 month_tab db 31,28,31,30,31,30,31,31,30,31,30,31
50 ; The following are indirect intra-segment call addresses. The
51 ;procedures are defined in MSINIT for relocation. MSINIT will set these
52 ;address when the relocation is done.
54 BinToBCD dw 0 ;should point to Bin_To_BCD proc in MSINIT
56 DaycntToDay dw 0 ;should point to Daycnt_to_day in MSINIT
58 ;********************************************************************
59 ; Indirect call address of TIME_TO_TICKS procedure.
60 ;This will be used by the relocatable portable suspend/resume code.
63 TimeToTicks dw Time_To_Ticks
65 ;;End of Modification ------------------------------------------------
67 ;--------------------------------------------------------------------
69 ; Settime sets the current time
71 ; On entry ES:[DI] has the current time:
73 ; number of days since 1-1-80 (WORD)
74 ; minutes (0-59) (BYTE)
76 ; hundredths of seconds (0-99) (BYTE)
77 ; seconds (0-59) (BYTE)
79 ; Each number has been checked for the correct range.
84 mov AX,WORD PTR ES:[DI]
85 push AX ;DAYCNT. We need to set this at the very
86 ; end to avoid tick windows.
87 ;;Rev 3.30 Modification
90 mov al,es:[di+3] ;get binary hours
91 call BinToBCD
;convert to BCD
92 mov ch,al ;CH = BCD hours
93 mov al,es:[di+2] ;get binary minutes
94 call BinToBCD
;convert to BCD
95 mov cl,al ;CL = BCD minutes
96 mov al,es:[di+5] ;get binary seconds
97 call BinToBCD
;convert to BCD
98 mov dh,al ;DH = BCD seconds
99 mov dl,0 ;DL = 0 (ST) or 1 (DST)
101 mov ah,03h ;set RTC time
102 int 1
Ah ;call rom bios clock routine
105 ;;End of Modification
107 mov CX,WORD PTR ES:[DI+2]
108 mov DX,WORD PTR ES:[DI+4]
109 ;;Rev 3.30 Modification
110 call time_to_ticks
; convert time to ticks
111 ;CX:DX now has time in ticks
113 mov AH, 1 ; command is set time in clock
114 int 1
Ah ; call rom-bios clock routines
117 ;CMOS clock -------------------------------------
120 call DaycntToDay
; convert to BCD format
122 mov AH,05h ; set RTC date
123 int 1
Ah ; call rom-bios clock routines
125 ;------------------------------------------------
130 ;;End of Modification
135 ; convert time to ticks
136 ; input : time in CX and DX
137 ; ticks returned in CX:DX
140 TIME_TO_TICKS PROC
NEAR
142 ; first convert from Hour,min,sec,hund. to
143 ; total number of 100th of seconds
145 mul CH ;Hours to minutes
147 add AX,CX ;Total minutes
149 mov BX,DX ;Get out of the way of the multiply
150 mul CX ;Convert to 1/100 sec
153 mul BH ;Convert seconds to 1/100 sec
154 add CX,AX ;Combine seconds with hours and min.
155 adc DX,0 ;Ripple carry
157 add CX,BX ;Combine 1/100 sec
160 ;;Rev 3.30 Modification
161 ;DX:CX IS TIME IN 1/100 SEC
163 XCHG AX,CX ;NOW TIME IS IN CX:AX
165 MUL BX ;MULTIPLY LOW HALF
167 XCHG AX,DX ;CX->AX, AX->DX, DX->CX
168 MUL BX ;MULTIPLY HIGH HALF
169 ADD AX,CX ;COMBINE OVERLAPPING PRODUCTS
171 XCHG AX,DX ;AX:DX=TIME*59659
173 DIV BL ;DIVIDE HIGH HALF BY 5
176 MOV AL,AH ;REMAINDER OF DIVIDE-BY-5
178 XCHG AX,DX ;USE IT TO EXTEND LOW HALF
179 DIV BX ;DIVDE LOW HALF BY 5
181 ; CX:DX is now number of ticks in time
184 ;;End of Modification
188 ; Gettime reads date and time
189 ; and returns the following information:
191 ; ES:[DI] =count of days since 1-1-80
195 ; ES:[DI+5]=hundredths of seconds
200 xor AH, AH ; set command to read clock
201 int 1
Ah ; call rom-bios to get time
203 or al,al ; check for a new day
204 jz noroll1
; if al=0 then don't reset day count
205 INC [DAYCNT
] ; CATCH ROLLOVE
210 ; we now need to convert the time in tick to the time in 100th of
211 ; seconds. The relation between tick and seconds is:
217 ; To get to 100th of second we need to multiply by 100. The equation is:
219 ; Ticks from clock * 65536 * 100
220 ; --------------------------------- = time in 100th of seconds
223 ; Fortunately this fromula simplifies to:
225 ; Ticks from clock * 5 * 65,536
226 ; --------------------------------- = time in 100th of seconds
229 ; The calculation is done by first multipling tick by 5. Next we divide by
230 ; 59,659. In this division we multiply by 65,536 by shifting the dividend
231 ; my 16 bits to the left.
233 ; start with ticks in CX:DX
246 ; now have ticks * 5 in DX:AX
247 ; we now need to multiply by 65,536 and divide by 59659 d.
249 mov CX,59659 ; get divisor
251 ; DX now has remainder
252 ; AX has high word of final quotient
253 mov BX,AX ; put high work if safe place
254 xor AX,AX ; this is the multiply by 65536
255 div CX ; BX:AX now has time in 100th of seconds
258 ;Rounding based on the remainder may be added here
259 ;The result in BX:AX is time in 1/100 second.
261 mov CX,200 ;Extract 1/100's
262 ;Division by 200 is necessary to ensure no overflow--max result
263 ;is number of seconds in a day/2 = 43200.
265 cmp DL,100 ;Remainder over 100?
267 sub DL,100 ;Keep 1/100's less than 100
269 cmc ;If we subtracted 100, carry is now set
270 mov BL,DL ;Save 1/100's
271 ;To compensate for dividing by 200 instead of 100, we now multiply
272 ;by two, shifting a one in if the remainder had exceeded 100.
276 mov CX,60 ;Divide out seconds
278 mov BH,DL ;Save the seconds
279 div CL ;Break into hours and minutes
282 ;Time is now in AX:BX (hours, minutes, seconds, 1/100 sec)