diff options
| author | 2024-04-25 21:24:10 +0100 | |
|---|---|---|
| committer | 2024-04-25 22:32:27 +0000 | |
| commit | 2d04cacc5322951f187bb17e017c12920ac8ebe2 (patch) | |
| tree | 80ee017efa878dfd5344b44249e6a241f2a7f6e2 /v4.0/src/BIOS/MSCLOCK.ASM | |
| parent | Merge pull request #430 from jpbaltazar/typoptbr (diff) | |
| download | ms-dos-main.tar.gz ms-dos-main.tar.xz ms-dos-main.zip | |
Diffstat (limited to 'v4.0/src/BIOS/MSCLOCK.ASM')
| -rw-r--r-- | v4.0/src/BIOS/MSCLOCK.ASM | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/v4.0/src/BIOS/MSCLOCK.ASM b/v4.0/src/BIOS/MSCLOCK.ASM new file mode 100644 index 0000000..5d66d03 --- /dev/null +++ b/v4.0/src/BIOS/MSCLOCK.ASM | |||
| @@ -0,0 +1,296 @@ | |||
| 1 | TITLE MSCLOCK - DOS 3.3 | ||
| 2 | ;---------------------------------------------------------------- | ||
| 3 | ; : | ||
| 4 | ; CLOCK DEVICE DRIVER : | ||
| 5 | ; : | ||
| 6 | ; : | ||
| 7 | ; This file contains the Clock Device Driver. : | ||
| 8 | ; : | ||
| 9 | ; The routines in this files are: : | ||
| 10 | ; : | ||
| 11 | ; routine function : | ||
| 12 | ; ------- -------- : | ||
| 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 : | ||
| 17 | ; : | ||
| 18 | ; The clock ticks at the rate of: : | ||
| 19 | ; : | ||
| 20 | ; 1193180/65536 ticks/second (about 18.2 ticks per second): | ||
| 21 | ; See each routine for information on the use. : | ||
| 22 | ; : | ||
| 23 | ;---------------------------------------------------------------- | ||
| 24 | |||
| 25 | |||
| 26 | itest=0 | ||
| 27 | INCLUDE MSGROUP.INC ;DEFINE CODE SEGMENT | ||
| 28 | INCLUDE MSMACRO.INC | ||
| 29 | |||
| 30 | EXTRN EXIT:NEAR | ||
| 31 | ; | ||
| 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. | ||
| 36 | ; | ||
| 37 | EXTRN DAYCNT:WORD ;MSDATA | ||
| 38 | |||
| 39 | ;;Rev 3.30 Modification ------------------------------------------------ | ||
| 40 | ; variables for real time clock setting | ||
| 41 | public HaveCMOSClock | ||
| 42 | HaveCMOSClock db 0 ;set by MSINIT. | ||
| 43 | public base_century | ||
| 44 | base_century db 19 | ||
| 45 | public base_year | ||
| 46 | base_year db 80 | ||
| 47 | public month_tab | ||
| 48 | month_tab db 31,28,31,30,31,30,31,31,30,31,30,31 | ||
| 49 | |||
| 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. | ||
| 53 | public BinToBCD | ||
| 54 | BinToBCD dw 0 ;should point to Bin_To_BCD proc in MSINIT | ||
| 55 | public DaycntToDay | ||
| 56 | DaycntToDay dw 0 ;should point to Daycnt_to_day in MSINIT | ||
| 57 | |||
| 58 | ;******************************************************************** | ||
| 59 | ; Indirect call address of TIME_TO_TICKS procedure. | ||
| 60 | ;This will be used by the relocatable portable suspend/resume code. | ||
| 61 | |||
| 62 | public TimeToTicks | ||
| 63 | TimeToTicks dw Time_To_Ticks | ||
| 64 | |||
| 65 | ;;End of Modification ------------------------------------------------ | ||
| 66 | |||
| 67 | ;-------------------------------------------------------------------- | ||
| 68 | ; | ||
| 69 | ; Settime sets the current time | ||
| 70 | ; | ||
| 71 | ; On entry ES:[DI] has the current time: | ||
| 72 | ; | ||
| 73 | ; number of days since 1-1-80 (WORD) | ||
| 74 | ; minutes (0-59) (BYTE) | ||
| 75 | ; hours (0-23) (BYTE) | ||
| 76 | ; hundredths of seconds (0-99) (BYTE) | ||
| 77 | ; seconds (0-59) (BYTE) | ||
| 78 | ; | ||
| 79 | ; Each number has been checked for the correct range. | ||
| 80 | ; | ||
| 81 | PUBLIC TIM$WRIT | ||
| 82 | TIM$WRIT PROC NEAR | ||
| 83 | ASSUME DS:CODE | ||
| 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 | ||
| 88 | cmp HaveCMOSClock, 0 | ||
| 89 | je No_CMOS_1 | ||
| 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) | ||
| 100 | cli ;turn off timer | ||
| 101 | mov ah,03h ;set RTC time | ||
| 102 | int 1Ah ;call rom bios clock routine | ||
| 103 | sti | ||
| 104 | |||
| 105 | ;;End of Modification | ||
| 106 | No_CMOS_1: | ||
| 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 | ||
| 112 | cli ; Turn off timer | ||
| 113 | mov AH, 1 ; command is set time in clock | ||
| 114 | int 1Ah ; call rom-bios clock routines | ||
| 115 | pop [DAYCNT] | ||
| 116 | sti | ||
| 117 | ;CMOS clock ------------------------------------- | ||
| 118 | cmp HaveCMOSClock, 0 | ||
| 119 | je No_CMOS_2 | ||
| 120 | call DaycntToDay ; convert to BCD format | ||
| 121 | cli ; Turn off timer | ||
| 122 | mov AH,05h ; set RTC date | ||
| 123 | int 1Ah ; call rom-bios clock routines | ||
| 124 | sti | ||
| 125 | ;------------------------------------------------ | ||
| 126 | |||
| 127 | No_CMOS_2: | ||
| 128 | jmp EXIT | ||
| 129 | TIM$WRIT ENDP | ||
| 130 | ;;End of Modification | ||
| 131 | |||
| 132 | |||
| 133 | |||
| 134 | ; | ||
| 135 | ; convert time to ticks | ||
| 136 | ; input : time in CX and DX | ||
| 137 | ; ticks returned in CX:DX | ||
| 138 | ; | ||
| 139 | public time_to_ticks | ||
| 140 | TIME_TO_TICKS PROC NEAR | ||
| 141 | |||
| 142 | ; first convert from Hour,min,sec,hund. to | ||
| 143 | ; total number of 100th of seconds | ||
| 144 | mov AL,60 | ||
| 145 | mul CH ;Hours to minutes | ||
| 146 | mov CH,0 | ||
| 147 | add AX,CX ;Total minutes | ||
| 148 | mov CX,6000 ;60*100 | ||
| 149 | mov BX,DX ;Get out of the way of the multiply | ||
| 150 | mul CX ;Convert to 1/100 sec | ||
| 151 | mov CX,AX | ||
| 152 | mov AL,100 | ||
| 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 | ||
| 156 | mov BH,0 | ||
| 157 | add CX,BX ;Combine 1/100 sec | ||
| 158 | adc DX,0 | ||
| 159 | |||
| 160 | ;;Rev 3.30 Modification | ||
| 161 | ;DX:CX IS TIME IN 1/100 SEC | ||
| 162 | XCHG AX,DX | ||
| 163 | XCHG AX,CX ;NOW TIME IS IN CX:AX | ||
| 164 | MOV BX,59659 | ||
| 165 | MUL BX ;MULTIPLY LOW HALF | ||
| 166 | XCHG DX,CX | ||
| 167 | XCHG AX,DX ;CX->AX, AX->DX, DX->CX | ||
| 168 | MUL BX ;MULTIPLY HIGH HALF | ||
| 169 | ADD AX,CX ;COMBINE OVERLAPPING PRODUCTS | ||
| 170 | ADC DX,0 | ||
| 171 | XCHG AX,DX ;AX:DX=TIME*59659 | ||
| 172 | MOV BX,5 | ||
| 173 | DIV BL ;DIVIDE HIGH HALF BY 5 | ||
| 174 | MOV CL,AL | ||
| 175 | MOV CH,0 | ||
| 176 | MOV AL,AH ;REMAINDER OF DIVIDE-BY-5 | ||
| 177 | CBW | ||
| 178 | XCHG AX,DX ;USE IT TO EXTEND LOW HALF | ||
| 179 | DIV BX ;DIVDE LOW HALF BY 5 | ||
| 180 | MOV DX,AX | ||
| 181 | ; CX:DX is now number of ticks in time | ||
| 182 | ret | ||
| 183 | TIME_TO_TICKS ENDP | ||
| 184 | ;;End of Modification | ||
| 185 | |||
| 186 | |||
| 187 | ; | ||
| 188 | ; Gettime reads date and time | ||
| 189 | ; and returns the following information: | ||
| 190 | ; | ||
| 191 | ; ES:[DI] =count of days since 1-1-80 | ||
| 192 | ; ES:[DI+2]=hours | ||
| 193 | ; ES:[DI+3]=minutes | ||
| 194 | ; ES:[DI+4]=seconds | ||
| 195 | ; ES:[DI+5]=hundredths of seconds | ||
| 196 | ; | ||
| 197 | PUBLIC TIM$READ | ||
| 198 | TIM$READ PROC NEAR | ||
| 199 | ; read the clock | ||
| 200 | xor AH, AH ; set command to read clock | ||
| 201 | int 1Ah ; call rom-bios to get time | ||
| 202 | |||
| 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 | ||
| 206 | noroll1: | ||
| 207 | MOV SI,[DAYCNT] | ||
| 208 | |||
| 209 | ; | ||
| 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: | ||
| 212 | ; | ||
| 213 | ; 65536 seconds | ||
| 214 | ; ---------------- | ||
| 215 | ; 1,193,180 tick | ||
| 216 | ; | ||
| 217 | ; To get to 100th of second we need to multiply by 100. The equation is: | ||
| 218 | ; | ||
| 219 | ; Ticks from clock * 65536 * 100 | ||
| 220 | ; --------------------------------- = time in 100th of seconds | ||
| 221 | ; 1,193,180 | ||
| 222 | ; | ||
| 223 | ; Fortunately this fromula simplifies to: | ||
| 224 | ; | ||
| 225 | ; Ticks from clock * 5 * 65,536 | ||
| 226 | ; --------------------------------- = time in 100th of seconds | ||
| 227 | ; 59,659 | ||
| 228 | ; | ||
| 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. | ||
| 232 | ; | ||
| 233 | ; start with ticks in CX:DX | ||
| 234 | ; multiply by 5 | ||
| 235 | MOV AX,CX | ||
| 236 | MOV BX,DX | ||
| 237 | SHL DX,1 | ||
| 238 | RCL CX,1 ;TIMES 2 | ||
| 239 | SHL DX,1 | ||
| 240 | RCL CX,1 ;TIMES 4 | ||
| 241 | ADD DX,BX | ||
| 242 | ADC AX,CX ;TIMES 5 | ||
| 243 | XCHG AX,DX | ||
| 244 | |||
| 245 | |||
| 246 | ; now have ticks * 5 in DX:AX | ||
| 247 | ; we now need to multiply by 65,536 and divide by 59659 d. | ||
| 248 | |||
| 249 | mov CX,59659 ; get divisor | ||
| 250 | div CX | ||
| 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 | ||
| 256 | |||
| 257 | ; | ||
| 258 | ;Rounding based on the remainder may be added here | ||
| 259 | ;The result in BX:AX is time in 1/100 second. | ||
| 260 | mov DX,BX | ||
| 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. | ||
| 264 | div CX | ||
| 265 | cmp DL,100 ;Remainder over 100? | ||
| 266 | jb NOADJ | ||
| 267 | sub DL,100 ;Keep 1/100's less than 100 | ||
| 268 | NOADJ: | ||
| 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. | ||
| 273 | rcl AX,1 | ||
| 274 | mov DL,0 | ||
| 275 | rcl DX,1 | ||
| 276 | mov CX,60 ;Divide out seconds | ||
| 277 | div CX | ||
| 278 | mov BH,DL ;Save the seconds | ||
| 279 | div CL ;Break into hours and minutes | ||
| 280 | xchg AL,AH | ||
| 281 | |||
| 282 | ;Time is now in AX:BX (hours, minutes, seconds, 1/100 sec) | ||
| 283 | |||
| 284 | push AX | ||
| 285 | MOV AX,SI ; DAYCNT | ||
| 286 | stosw | ||
| 287 | pop AX | ||
| 288 | stosw | ||
| 289 | mov AX,BX | ||
| 290 | stosw | ||
| 291 | jmp EXIT | ||
| 292 | |||
| 293 | TIM$READ ENDP | ||
| 294 | CODE ENDS | ||
| 295 | END | ||
| 296 | \ No newline at end of file | ||