CLOCK.ASM
上传用户:xiaogehua
上传日期:2007-01-08
资源大小:1183k
文件大小:13k
源码类别:

操作系统开发

开发平台:

Asm

  1. ;    File              : $CLOCK.ASM$
  2. ;
  3. ;    Description       :
  4. ;
  5. ;    Original Author   : DIGITAL RESEARCH
  6. ;
  7. ;    Last Edited By    : $CALDERA$
  8. ;
  9. ;-----------------------------------------------------------------------;
  10. ;    Copyright Work of Caldera, Inc. All Rights Reserved.
  11. ;      
  12. ;    THIS WORK IS A COPYRIGHT WORK AND CONTAINS CONFIDENTIAL,
  13. ;    PROPRIETARY AND TRADE SECRET INFORMATION OF CALDERA, INC.
  14. ;    ACCESS TO THIS WORK IS RESTRICTED TO (I) CALDERA, INC. EMPLOYEES
  15. ;    WHO HAVE A NEED TO KNOW TO PERFORM TASKS WITHIN THE SCOPE OF
  16. ;    THEIR ASSIGNMENTS AND (II) ENTITIES OTHER THAN CALDERA, INC. WHO
  17. ;    HAVE ACCEPTED THE CALDERA OPENDOS SOURCE LICENSE OR OTHER CALDERA LICENSE
  18. ;    AGREEMENTS. EXCEPT UNDER THE EXPRESS TERMS OF THE CALDERA LICENSE
  19. ;    AGREEMENT NO PART OF THIS WORK MAY BE USED, PRACTICED, PERFORMED,
  20. ;    COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED, ABRIDGED,
  21. ;    CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, RECAST,
  22. ;    TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF
  23. ;    CALDERA, INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT
  24. ;    AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO CRIMINAL AND
  25. ;    CIVIL LIABILITY.
  26. ;-----------------------------------------------------------------------;
  27. ;
  28. ;    *** Current Edit History ***
  29. ;    *** End of Current Edit History ***
  30. ;
  31. ;    $Log$
  32. ;    CLOCK.ASM 1.12 93/07/22 19:43:10
  33. ;    switch over to REQUEST.EQU
  34. ;    ENDLOG
  35. include BIOSGRPS.EQU
  36. include DRMACROS.EQU ; standard DR macros
  37. include IBMROS.EQU ; ROM BIOS equates
  38. include REQUEST.EQU ; request header equates
  39. include DRIVER.EQU ; device driver equates
  40. page
  41. CGROUP group CODE, RCODE, RESUMECODE, ICODE
  42. CG equ offset CGROUP
  43. TIME struc
  44. DAYS dw ?
  45. MINUTES db ?
  46. HOURS db ?
  47. HUNDREDTHS db ?
  48. SECONDS db ?
  49. TIME ends
  50. Assume CS:CGROUP, DS:CGROUP, ES:Nothing, SS:Nothing
  51. CODE segment 'CODE'
  52. extrn endbios:word ; for device driver INIT function
  53. extrn daycount:word
  54. ; There are 1193180/65536 ticks per second, or 0E90Bh/10000h ticks per 5/100th.
  55. CONVERSION_FACTOR equ 0E90Bh
  56. CODE ends
  57. RCODE segment 'RCODE'
  58. extrn DataSegment:word
  59. monlen db 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  60. Public ClockTable
  61. ClockTable:
  62. db 9 ; Last supported function
  63. dw CG:dd_init ; 0-initialize driver
  64. dw CG:dd_error ; 1-media change check (disks only)
  65. dw CG:dd_error ; 2-build BPB (disks only)
  66. dw CG:dd_error ; 3-IOCTL string input
  67. dw CG:dd_input ; 4-input
  68. dw CG:dd_error ; 5-nondestructive input (char only)
  69. dw CG:dd_error ; 6-input status (char only)
  70. dw CG:dd_error ; 7-input flush
  71. dw CG:dd_output ; 8-output
  72. dw CG:dd_output ; 9-output with verify
  73. page
  74. driver proc near
  75. dd_error: ; used for all unsupported driver functions
  76. ;--------
  77. mov ax,RHS_ERROR+3 ; "invalid command" error
  78. ret
  79. dd_input: ; 4-input
  80. ;--------
  81. les di,es:RH4_BUFFER[bx] ; ES:DI -> requested date/time buffer
  82. call read_system_ticks ; read system tick counter
  83. mov ax,daycount ; AX = date
  84. stosw ; return date
  85. push dx ; save low word of ticks
  86. mov ax,5
  87. mul cx ; multiply high word of ticks by 5
  88. xchg ax,cx ; save result in CX
  89. pop dx
  90. mov ax,5
  91. mul dx ; multiply low word of tick by 5
  92. add dx,cx ;  and add in high word
  93. mov bx,CONVERSION_FACTOR
  94. div bx ; convert to centi-secs
  95. push ax ; save high word of result
  96. xor ax,ax
  97. div bx ; divide remainder
  98. pop dx ; recover high word of result
  99. ;  giving us time in centi-secs
  100. mov bx,60*100 ; BX = centi-secs/minute
  101. div bx ; AX = # minutes
  102. push dx ; save centi-secs remainder
  103. cwd ; DX = 0
  104. mov bx,60+(256*100) ; BL = minutes/hour,BH = centi-secs/sec
  105. div bl ; AL = hours, AH = minutes remainder
  106. xchg al,ah
  107. stosw ; return minutes then hours
  108. pop ax ; recover centi-secs remainder
  109. div bh ; AL = secs, AH = centi-secs remainder
  110. xchg al,ah
  111. stosw ; return centi-secs then secs
  112. sub ax,ax
  113. ret
  114. page
  115. dd_output: ; 8-output
  116. ;---------
  117. les si,es:RH4_BUFFER[bx]
  118. ; First we'll convert the date & set the RTC if present:
  119. mov ax,es:DAYS[si] ; # of days since 1/1/1980
  120. mov daycount,ax
  121. mov dx,1980 ; get initial year
  122. output1:
  123. mov cx,365 ; assumed year size
  124. test dl,3 ; test for leap years
  125.  jnz output2 ; skip if not a leap year
  126. inc cx ; leap years have 366 days
  127. output2:
  128. cmp ax,cx ; more days than this year?
  129.  jb output3 ; skip if less - same year
  130. sub ax,cx ; else date in future year
  131. inc dx ; subtract from total, next year
  132. jmps output1 ; check again
  133. output3: ; DX = binary year, AX = day in year
  134. sub bx,bx ; start with January
  135. sub cx,cx ; CH = 0
  136. output4:
  137. mov cl,cs:monlen[bx] ; CX = # of days in next month
  138. cmp cl,28 ; is it february ?
  139.  jne output5
  140. test dl,3 ; is it a leap year ?
  141.  jnz output5
  142. inc cx ; leap years have 29 days in february
  143. output5:
  144. cmp ax,cx ; remaining day count >= month length?
  145.  jb output6 ; skip if right month found
  146. sub ax,cx ; else subtract days in that month
  147. inc bx ; move on to next month
  148. jmps output4 ; repeat until month found
  149. output6: ; DX = binary year
  150. inc ax ; AX = day-1    =>  convert to day
  151. inc bx ; BX = month-1  =>  convert to month
  152. mov ah,bl ; high byte is month
  153. call bin2bcd ; convert to month
  154. xchg ax,dx ; DL, DH = day, month of date
  155. ; AX = binary year
  156. mov bl,100
  157. div bl ; AL = century, AH = year
  158. xchg al,ah ; AH = century, AL = year
  159. call bin2bcd ; convert AL, AH from binary to BCD
  160. xchg ax,cx ; CL, CH = year, century for date
  161. mov ah,5 ; set real time clock date
  162. int RTC_INT ;    on AT, XT-286, PS/2, etc.
  163. ; Now we'll convert the time & set the RTC if present
  164. ; mov ah,es:HOURS[si]
  165. ; mov al,es:MINUTES[si] ; get binary hours & minutes
  166. mov ax,es:word ptr MINUTES[si]
  167. call bin2bcd ; convert to BCD values
  168. xchg ax,cx ; CH, CL = hh:mm in BCD
  169. mov ah,es:SECONDS[si]
  170. mov al,0 ; get binary seconds & no daylight saving
  171. call bin2bcd ; convert to BCD values
  172. xchg ax,dx ; DH, DL = ss.000 in BCD
  173. mov ah,3 ; set real time clock time
  174. int RTC_INT ;    on AT, XT-286, PS/2, etc.
  175. mov al,100
  176. mul es:SECONDS[si] ; AX = seconds in hundredths
  177. xchg ax,dx ; save in DX
  178. mov al,es:HUNDREDTHS[si]
  179. cbw ; AX = hundredths
  180. add ax,dx ; AX = secs and hundredths in 1/100ths
  181. cwd ; make the a dword
  182. mov bx,5
  183. div bx ; AX = secs and hundredths in 5/100ths
  184. xchg ax,bx ; save in BX
  185. mov al,60 ; convert hours into minutes
  186. mul es:HOURS[si] ; AX = hours in mins
  187. xchg ax,dx
  188. mov al,es:MINUTES[si]
  189. cbw ; AX = minutes value
  190. add ax,dx ; AX = hours and mins in mins
  191. mov dx,60*20
  192. mul dx ; DX:AX = hours and mins in 5/100ths
  193. add ax,bx
  194. adc dx,0 ; DX:AX = total in 5/100ths
  195. mov bx,CONVERSION_FACTOR ; load up our magic value
  196. push dx ; save high word
  197. mul bx ; DX = low word result
  198. mov cx,dx ;  save for later
  199. pop ax ; recover high word
  200. mul bx ; DX:AX = result from high word
  201. add ax,cx ; add low and high word results
  202. adc dx,0 ;  together in DX:AX
  203. xchg ax,dx ; DX = low word of result
  204. xchg ax,cx ; CX = high word of result
  205. mov ah,1 ; set system timer
  206. int RTC_INT ; CX = high word, DX = low word
  207. sub ax,ax ; return successfully when done
  208. ret
  209. Public read_system_ticks
  210. read_system_ticks:
  211. ;-----------------
  212. mov ah,0 ; read system tick counter
  213. int RTC_INT
  214. test al,al ; have we passed midnight ?
  215.  jz read_st10 ; if so a new day has dawned
  216. inc daycount
  217. read_st10:
  218. ret
  219. bin2bcd: ; convert AL and AH to BCD values
  220. ;-------
  221. call bin2bcd1 ; swap AL, AH, convert to BCD
  222. ; call bin2bcd1
  223. ; ret
  224. bin2bcd1:
  225. push cx
  226. mov ch,ah ; save AH in scratch register
  227. aam ; AL = AL % 10; AH = AL/10;
  228. mov cl,4
  229. shl ah,cl ; shift tens into high nibble
  230. or ah,al ; combine the nibbles
  231. mov al,ch ; restore the high byte into low byte
  232. pop cx
  233. ret
  234. driver endp
  235. RCODE ends ; end of device driver code
  236. RESUMECODE segment 'RESUMECODE'
  237. ; If the system ROM BIOS supports RESUME mode then it will call Int 6C
  238. ; when returning from sleep mode. We take this over and reset the clock
  239. ; based upon the RTC value. To save space we only relocate the code if
  240. ; required.
  241. ;
  242. Public ResumeHandler
  243. ResumeHandler proc far
  244. sti
  245. mov ax,cs:DataSegment ; we have been asleep and are being
  246. mov ds,ax ;  woken by the BIOS
  247. mov es,ax ; lets re-read the RTC before
  248. call set_clock ;  we return to them
  249. clc
  250. ret 2
  251. ResumeHandler endp
  252. set_monlen db 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  253. set_clock:
  254. ;---------
  255. ; We may also be called after a RESUME when we have to reset the time.
  256. mov ah,2 ; read real time clock
  257. xor cx,cx
  258. xor dx,dx ; assume it won't work
  259. stc
  260. int RTC_INT ; CH = hours, CL = mins, DH = secs
  261.  jc set_clock40 ; (all in BCD remember)
  262. xchg al,dh ; AL = secs
  263. call bcd2bin ; AL = secs in binary
  264. cmp al,59
  265.  ja set_clock40 ; reject invalid seconds
  266. mov ah,100
  267. mul ah ; AX = seconds in hundredths
  268. cwd ; make it a dword
  269. mov bx,5
  270. div bx ; AX = secs and hundredths in 5/100ths
  271. xchg ax,bx ; save in BX
  272. mov al,ch ; AL = hours in BCD
  273. call bcd2bin ; AL = hours in binary
  274. cmp al,23
  275.  ja set_clock40 ; reject invalid hours
  276. mov ah,60 ; convert hours into minutes
  277. mul ah ; AX = hours in mins
  278. xchg ax,dx ; save in DX
  279. mov al,cl ; AL = mins in BCD
  280. call bcd2bin ; AL = mins in binary
  281. cmp al,59
  282.  je set_clock40 ; reject invalid mins
  283. cbw ; AX = minutes value
  284. add ax,dx ; AX = hours and mins in mins
  285. mov dx,60*20
  286. mul dx ; DX:AX = hours and mins in 5/100ths
  287. add ax,bx
  288. adc dx,0 ; DX:AX = total in 5/100ths
  289. mov bx,CONVERSION_FACTOR ; load up our magic value
  290. push dx ; save high word
  291. mul bx ; DX = low word result
  292. mov cx,dx ;  save for later
  293. pop ax ; recover high word
  294. mul bx ; DX:AX = result from high word
  295. add ax,cx ; add low and high word results
  296. adc dx,0 ;  together in DX:AX
  297. xchg ax,dx ; DX = low word of result
  298. xchg ax,cx ; CX = high word of result
  299. mov ah,1 ; set system timer
  300. int RTC_INT ; CX = high word, DX = low word
  301. set_clock40:
  302. mov ah,4 ; read RTC (if present)
  303. int RTC_INT ; validate date - CMOS may be corrupt
  304. cmp cx,1980h ; Too low?
  305.  jb set_clock45 ; Yes so skip
  306. cmp cx,2099h ; Too high ?
  307.  ja set_clock45 ; Yes so skip
  308. cmp dx,0101h ; Too low?
  309.  jb set_clock45 ; Yes so skip
  310. cmp dx,3112h ; Too high ?
  311.  jbe set_clock50 ; No its okay so scram
  312. set_clock45:
  313.     mov cx,1980h        ; assume the year 1980
  314. mov dx,0101h ; assume 1st of January of that year
  315. set_clock50:
  316. xchg ax,cx ; AL, AH = year, century in BCD
  317. call bcd2bin ; convert values to binary
  318. xchg ax,cx
  319. xchg ax,dx ; AL, AH = day, month in BCD
  320. call bcd2bin ; convert values to binary
  321. xchg ax,dx
  322. mov daycount,0 ; zero the daycount in case of RESUME
  323.     mov ax,19*256 + 80      ; assume 1980 
  324. set_clock55:
  325. cmp ax,cx ; same year?
  326.  je set_clock65
  327. mov bx,365 ; assume 365 days in that year
  328. test al,3 ; test for leap year
  329.  jnz set_clock60 ; (this works til 2400 A.D.)
  330. inc bx ; add FEB 29 if divisible by four
  331. set_clock60:
  332. add daycount,bx ; add days in previous year to total
  333. inc al ; next year
  334. cmp al,100 ; end of century?
  335.  jb set_clock55 ; skip if same century
  336. mov al,0 ; continue with XX00
  337. inc ah ;   ...next century
  338. jmps set_clock55 ; check year again
  339. set_clock65: ; same year by now
  340. xchg ax,cx ; CX = year
  341. sub dx,0101h ; make month, day 0 relative
  342. sub bx,bx ; assume January
  343. sub ax,ax ; AH = 0
  344. set_clock70:
  345. cmp dh,bl ; does current month match?
  346.  je set_clock80 ; skip if it does
  347. mov al,cs:set_monlen[bx] ; get length of that month
  348. cmp al,28 ; is it february ?
  349.  jne set_clock75
  350. test cl,3 ; is it a leap year ?
  351.  jnz set_clock75
  352. inc ax ; leap year, 29 days in february
  353. set_clock75:
  354. add daycount,ax ; add it to total day count
  355. inc bx ; move on to next month
  356. jmps set_clock70
  357. set_clock80:
  358. mov al,dl ; get days in that month
  359. add daycount,ax ; add them to day count
  360. ret
  361. bcd2bin:
  362. ;-------
  363. ; entry: AL, AH = BCD values
  364. ; AL, AH = binary equivalents
  365. call bcd2bin1 ; swap AL, AH, convert AL to binary
  366. ; call bcd2bin1 ; swap AL, AH, convert AL to binary
  367. ; ret
  368. bcd2bin1: ; convert BCD to binary
  369. xchg al,ah ; swap the two values
  370. push bx
  371. mov bl,0 ; start off without tens
  372. bcd2bin2:
  373. cmp al,10h ; check if more tens
  374.  jb bcd2bin3 ; all tens done
  375. sub al,10h ; else subtract 10 in BCD
  376. add bl,10 ; ...and add it in binary
  377. jmps bcd2bin2 ; repeat for all tens
  378. bcd2bin3: ; AL = ones, BL = tens
  379. add al,bl ; AL = binary value
  380. pop bx ; restore BX
  381. ret
  382. RESUMECODE ends
  383. ICODE segment 'ICODE' ; initialization code
  384. Assume CS:CGROUP, DS:CGROUP
  385. dd_init: ; 0-initialize driver
  386. ;-------
  387. call set_clock ; set elapsed ticks
  388. les bx,REQUEST[bp] ; ES:BX -> request header
  389. mov ax,endbios
  390. mov es:RH0_RESIDENT[bx],ax ; set end of device driver
  391. mov es:RH0_RESIDENT+2[bx],ds
  392. sub ax,ax ; initialization succeeded
  393. ret ; (BIOS init always does...)
  394. ICODE ends
  395. end