home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1986 / 03 / weislst2.mar < prev    next >
Text File  |  1986-03-31  |  9KB  |  235 lines

  1. ;---------------------------------------------------;
  2. ; Weissman/Dr. Dobbs Submission.  Listing 2:        ;
  3. ; AT timer handler.                                 ;
  4. ;---------------------------------------------------;
  5.  
  6. ;---------------------------------------------------;
  7. ; Memory-resident handler for the 1024              ;
  8. ; tick/sec. realtime clock in the IBM AT:           ;
  9. ;                                                   ;
  10. ; Enables INT 70, the clock interrupt, and          ;
  11. ; counts the ticks at the 1k rate.  The range is    ;
  12. ; 2**32 div 2**10, or 2**22 seconds.  Long enough.  ;
  13. ;                                                   ;
  14. ; Sets up the usual INT 1A (Get/set time of day)    ;
  15. ; to handle get/set of the hi-resolution timing     ;
  16. ; data via special codes in AH register.            ;
  17. ;                                                   ;
  18. ; With AH=10h, caller recieves current time in 1k   ;
  19. ;              ticks.                               ;
  20. ;              CX returns high 16 bits, DX the low. ;
  21. ;      AH=11h  allows user to set the 32-bit count. ;
  22. ;              CX=High count to set, DX is low.     ;
  23. ;                                                   ;
  24. ; 10/1/85 Written by Gregg Weissman                 ;
  25. ;         E-X-E Software Systems                    ;
  26. ;         Released to the public domain.            ;
  27. ;---------------------------------------------------;
  28.  
  29. CODE    segment
  30. assume cs:CODE,ds:CODE,es:CODE,ss:CODE
  31.  
  32.         ;-------------------------------------------;
  33.         ; Conserve memory space: maintain variables ;
  34.         ; in the unused areas of the program prefix.;
  35.         ;-------------------------------------------;
  36.  
  37.         org 5ch
  38.  
  39. I1AJMP  dd      ?                       ; Vector to usual 1A int.
  40. I70JMP  dd      ?                       ; Ditto the INT 70.
  41. TIMELO  dw      ?                       ; low 16 bits of time.
  42. TIMEHI  dw      ?                       ; Hi  16 bits of time.
  43.  
  44.         org 100h                        ; Start of .COM program
  45.  
  46. BEGIN:  jmp     short START             ; Jump around handlers.
  47.  
  48.  
  49.         ;-------------------------------------------;
  50.         ; Handle the Get/Set time-of-day INT 1A:    ;
  51.         ; As mentioned, AH=10h Returns time,        ;
  52.         ;               AH=11h Sets time            ;
  53.         ; Illegal values  >11h  return Carry status ;
  54.         ;-------------------------------------------;
  55.  
  56. INT_1A  proc far
  57. assume ds:nothing,es:nothing,ss:nothing
  58.  
  59.         cmp     ah,10h                  ; See if it's our range of cmnd vals.
  60.         jb      NOPE_1A                 ; If less than, assume BIOS int 1a.
  61.         sub     ah,10h                  ; Remove special code "bias" of 10h
  62.         je      GET_TIME                ;  and branch if equal to "Get" cmnd.
  63.         dec     ah                      ; See if "Set" cmns.
  64.         jne     BAD_CMD_1A              ; If not, branch to error.
  65.  
  66.         ;-- set time: cx,dx
  67.  
  68.         mov     TIMEHI,cx
  69.         mov     TIMELO,dx
  70.         iret
  71.  
  72. GET_TIME:
  73.  
  74.         mov     cx,TIMEHI               ; Obtain the number of times the 1024
  75.         mov     dx,TIMELO               ; tick per sec. interrupt has occurred.
  76.         iret
  77.  
  78. BAD_CMD_1A:
  79.  
  80.         stc
  81.         ret     2                       ; Return an error flag.
  82.  
  83. NOPE_1A:
  84.  
  85.         jmp     I1AJMP                  ; Continue to BIOS handler via vector.
  86.  
  87. INT_1A  endp
  88.  
  89.  
  90.         ;-------------------------------------------;
  91.         ; Handle the 1024 ticks/second realtime     ;
  92.         ; clock interrupt:  maintain 32-bit count.  ;
  93.         ;-------------------------------------------;
  94.         ; Still assume ds, etc. nothing in effect.  ;
  95.         ;-------------------------------------------;
  96.  
  97. INT_70  proc far
  98.  
  99.         push    ax
  100.         push    ds
  101.         mov     ax,cs
  102.         mov     ds,ax
  103.  
  104. assume ds:CODE
  105.  
  106.         inc     TIMELO                  ; Bump low counter.
  107.         jne     CONT_70                 ; Continue if count not wrapped around
  108.         inc     TIMEHI                  ; Bump high counter.
  109.  
  110. CONT_70:
  111.  
  112.         pushf                           ; Simulate INT nn
  113.         call    I70JMP                  ; Call the realtime clock handler,
  114.                                         ;   to let BIOS handle user-event-wait.
  115.         call    ENABLE_INT              ; And return here so we can re-init
  116.         pop     ds                      ;   the timer: BIOS turns it off.
  117.         pop     ax
  118.         iret
  119.  
  120. INT_70  endp
  121.  
  122.         ;-----------------------------------------;
  123.         ; This routine enables the "PIE", or      ;
  124.         ; periodic interrupt event.  It is called ;
  125.         ; when the system initializes, and after  ;
  126.         ; each tick, in case BIOS turned it off.  ;
  127.         ;-----------------------------------------;
  128.         ;   This communicates with the CMOS       ;
  129.         ;   module via ports 70h & 71h.  The      ;
  130.         ;   "JMP $+2" is for a delay between      ;
  131.         ;   port accesses, allowing the device    ;
  132.         ;   time to settle down.  The 80286 is    ;
  133.         ;   too fast.                             ;
  134.         ;-----------------------------------------;
  135.  
  136. ENABLE_INT      proc near
  137.  
  138.         cli                                     ; Prevent interruption.
  139.         mov     al,0bh                          ; First, identify the reg.
  140.         out     70h,al                          ; we want (0b is the one).
  141.         jmp     $+2                             ; Just a long NOP.
  142.         in      al,71h
  143.         or      al,01000000b                    ; This bit is int. enable
  144.         mov     ah,al                           ; Save value: we need al
  145.         mov     al,0bh                          ; Address the register again.
  146.         out     70h,al
  147.         jmp     $+2                             ; NOP
  148.         mov     al,ah                           ; Get back the desired value.
  149.         out     71h,al                          ; Now stored in CMOS & ready.
  150.         in      al,0a1h                         ; Int. control chip register.
  151.         and     al,0feh                         ; Bit 0 is another int. enable
  152.         out     0a1h,al                         ;  now set to allow interrupt.
  153.         mov     al,20h                          ; Send "End of interrupt" for
  154.         out     0a0h,al                         ;  good measure.
  155.         out     020h,al                         ;  ditto controller chip 1.
  156.         sti
  157.         ret
  158.  
  159. ENABLE_INT      endp
  160.  
  161.  
  162.         ;-------------------------------------------;
  163.         ; Initialize the interrupt handlers and     ;
  164.         ; the interrupt generator itself.  Leave    ;
  165.         ; behind the resident code.                 ;
  166.         ;-------------------------------------------;
  167.         ; We leave out amenities like DOS version   ;
  168.         ; test and check for an actual AT.          ;
  169.         ;-------------------------------------------;
  170.  
  171. START:
  172. assume ds:CODE,es:CODE,ss:CODE
  173.  
  174.  
  175.         mov     ah,10h                  ; First check to see if already
  176.         clc                             ; resident,
  177.         mov     cx,1234h                ; by constructing an unlikely
  178.         mov     dx,cx                   ; time value of 12341234h
  179.         int     1ah                     ; See if we get the time back.
  180.         cmp     cx,dx                   ; If cx=1234=dx, not present.
  181.         je      NOT_THERE
  182.         mov     dx,offset ALREADY       ; Tell the user it's in already
  183.         mov     ah,9                    ; using DOS print function.
  184.         int     21h
  185.         mov     ax,4c01h                ; Terminate with errorlevel 1
  186.         int     21h
  187.  
  188. NOT_THERE:
  189.  
  190.         mov     ax,3570h                ; Get the current vectors
  191.         int     21h                     ; from DOS.
  192.         mov     word ptr I70JMP,bx      ; Save in prefix are variables.
  193.         mov     word ptr I70JMP+2,es
  194.         mov     ax,351ah                ; Got the 70, now get 1A
  195.         int     21h
  196.         mov     word ptr I1AJMP,bx
  197.         mov     word ptr I1AJMP+2,es
  198.  
  199.         push    cs                      ; Restore es for form's sake
  200.         pop     es
  201.  
  202.         mov     THIS_SEG,cs
  203.  
  204.         cli
  205.         mov     dx,offset INT_1a        ; Set interrupt vectors to our handlers
  206.         mov     ax,251ah
  207.         int     21h
  208.         mov     dx,offset INT_70        ; Ditto for int 70.
  209.         mov     ax,2570h
  210.         int     21h
  211.         mov     dx,offset HELLO         ; Print a message
  212.         mov     ah,9
  213.         int     21h
  214.  
  215.         call    ENABLE_INT              ; Start the timer.
  216.  
  217.         mov     dx,offset START+15      ; Set terminate address in
  218.         mov     cl,4                    ;  paragraphs, rounding up &
  219.         shr     dx,cl                   ;  dividing by 16.
  220.  
  221.  
  222.         mov     TIMELO,0                ; Clear the current time.
  223.         mov     TIMEHI,0
  224.  
  225.         mov     ax,3100h                ; Terminate & stay put.
  226.         int     21h                     ; End.
  227.  
  228.         ;-- Messages for the user:
  229.  
  230. HELLO   db      'Hi-resolution AT timer now loaded.',13,10,'$'
  231. ALREADY db      'The resident timer handler is already installed.',13,10,'$'
  232.  
  233. CODE    ends
  234. end     BEGIN
  235.