home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / sysutil / parint.asm < prev    next >
Assembly Source File  |  1994-03-05  |  7KB  |  234 lines

  1.     page    60,132
  2. comment    *  PARINT.COM - (C) 1984 by David G Hunter.
  3.        This program may be freely copied but may not be sold for profit.
  4.  
  5.        (Necessary modifications for the early model (1981) IBM PC
  6.            made by Lawrence B. Afrin, 12/30/84.  These modifications
  7.        are documented at the appropriate point in this program.
  8.        Modifications are Copyright (c) 1984 by Lawrence B. Afrin.
  9.        Along with Mr. Hunter's code, these modifications may be
  10.        freely copied but may not be sold for profit.)
  11.  
  12.        PARINT.COM detects parity errors, logs them on the printer if
  13.        possible, beeps, and returns to program execution.  The system does
  14.        not halt when this program is resident.  Parity error checking is
  15.        terminated after first error is detected.  The error message
  16.        includes the time of the event.  If the printer is not available,
  17.        errors are logged to the screen.
  18. *
  19. ;***************** Addresses of Interrupt handlers *******************
  20.  
  21. Book    segment    at 0h        ;this is where the interrupt address books is
  22.     org    2h*4        ;
  23. Int_2    label    dword        ;address of NMI handler
  24. Book    ends
  25.  
  26. ;***************** Beginning of PARINT Instructions *******************
  27. cseg    segment
  28.     assume    cs:cseg
  29.     org    100h
  30.  
  31. Start:    jmp    newvec ;install new NMI handler in RAM
  32.  
  33.  
  34. ;************************** NMI handler ********************************
  35.  
  36. newint    proc    near        ;new interrupt handler
  37.     assume    ds:cseg, es:cseg
  38.     sti            ;this flag was cleared when interrupt was issued
  39.     jmp    go        ;jump over more data
  40.  
  41. go:    push    cx
  42.     push    ds
  43.     pushf
  44.     push    dx
  45.     push    bx
  46.     push    ax
  47.     pushf
  48.     mov    al, 00h
  49.     out    0A0h, al    ;turn off parity checking for now
  50.     xor    cx, cx    ;cx=error flag: cx=1 if parity OK
  51.     in    al,62h    ;get data in port C
  52.  
  53. ; - - find origin of NMI - - - - - -
  54.     test    al, 40h
  55.     jz    mother
  56.     mov    dx, offset par2 ;if bit 6 set, error is on expansion board
  57.     jmp    out        ; print message and exit
  58.  
  59. mother:    test    al, 80h
  60.     jz    other
  61.     mov    dx, offset par1 ;if bit 7 set, error is on main board
  62.     jmp    out        ;print message and exit
  63.  
  64. other:    or    cx, 1h    ;If neither bit set, no parity error occurred,
  65.     mov    al, 80h    ;so set parity OK flag
  66.     out    0A0h, al    ;turn parity checking back on
  67.     jmp    noprt        ;Don't print message if not parity error
  68.  
  69. ; - - print error message and exit.  Type of exit depends on type of error --
  70. out:    mov    ax,cs        ;establish proper data segment to
  71.     mov    ds,ax        ; allow access to messages
  72.     call    whatime    ;get time of error
  73.     mov    bx, device1
  74.     cmp    bx,0004    ;if output is to printer, make sure it's ready
  75.     jne    f1
  76.     call    testprt
  77. f1:    call    print
  78.     mov    dx, offset time ;"time of error" message
  79.     call    print
  80.     mov    dx, offset paroff
  81.     call    print
  82.  
  83. noprt:    popf
  84.     pop    ax
  85.     pop    bx
  86.     pop    dx
  87.     popf
  88.     pop    ds
  89.     test    cx, 1h    ;special exit if parity OK
  90.     jnz    oth
  91.     pop    cx
  92.     iret            ;message printed; let execution continue
  93.  
  94. ;     If no parity error, turn control over to pre-existing NMI handler.
  95. ; This is done by restoring DS and jumping to the instruction that
  96. ; specifies the address of the old interrupt routine.  This unusual exit
  97. ; is necessary because otherwise, once DS was restored, the address of the
  98. ; old interrupt routine would not be accessible.
  99.  
  100. oth:    cli
  101.     pop    cx
  102.     jmp    GetOut
  103.  
  104. newint    endp
  105.  
  106.  
  107. ;**************************** SUBROUTINES ******************************
  108.  
  109. Testprt    proc    near
  110.     push    dx
  111.     push    ax
  112.     xor    dx,dx        ;print # 0
  113.     mov    ah,2
  114.     int    17h        ;read printer status
  115.     test    ah,00101001b    ;error bits
  116.     jz    aok
  117.     mov    bx, device2    ;if not ok, try other device
  118. aok:    pop    ax
  119.     pop    dx
  120.     ret
  121. testprt    endp
  122.  
  123. Print    proc    near ;output to file named in bx; if error try another file
  124.     push    cx
  125.     mov    cx,34        ;34 characters to print
  126.     mov    ah,40h    ;DOS function call
  127.     int    21h
  128.     pop    cx
  129.     ret
  130. print    endp
  131.  
  132. Whatime    proc    near        ;what time is it?  put result in hour/min
  133.     push    cx
  134.     push    dx
  135.     mov    ah,2Ch    ;DOS time
  136.     int    21h
  137.     mov    al,ch        ;hours (0-23)
  138.     call    convt        ;put tens in ah, ones in al
  139.     mov    hour,"00"
  140.     add    hour,ax
  141.     mov    al,cl
  142.     call    convt        ;do same for minutes (0-59)
  143.     mov    min,"00"
  144.     add    min,ax
  145.     pop    dx
  146.     pop    cx
  147.     ret
  148. Whatime    endp
  149.  
  150. Convt    proc    near        ;convert number (<100) to ASCII.  Number is in
  151.                 ;al.  result: tens in ah, ones in al.
  152.     xor    ah,ah        ;input is less than 100 anyway, so clear it
  153.     push    cx
  154.     mov    cl,10
  155.     div    cl        ;divide ax by 10
  156.     pop    cx
  157. little:    ret
  158. Convt    endp
  159.  
  160. ;------------------------------- DATA ----------------------------------
  161.  
  162. GetOut:    nop
  163. Instruc    db    0EAh        ;this is the jump-immediate instruction!
  164.                 ;it jumps to the address stored in oldint
  165. Oldint    dd    ?        ;address of old interrupt 2 routine -
  166. Device1    dw    0004        ;printer
  167. Device2    dw    0001        ;standard output device
  168. par1    db    0Dh,0Ah,"Parity Error: Main Board     ",07h,0Dh,0Ah
  169. par2    db    0Dh,0Ah,"Parity Error: Expansion Board",07h,0Dh,0Ah
  170. time    db    "    TIME:  "
  171. hour    dw    "00"
  172.     db    ":"
  173. min    dw    "00"
  174.     db    "                ",0Dh,0Ah
  175. paroff    db    "PARITY CHECKING NOW DISABLED   ",0Dh,0Ah,0Ah
  176.  
  177. ;---------------------------- MAIN PROGRAM -----------------------------
  178.  
  179. ;************************* INSTALL NMI HANDLER **************************
  180.  
  181. Newvec    proc    near
  182.     jmp    past
  183.  
  184. loaded    db    0Dh,0Ah,"PARITY ERROR INTERCEPTOR v2.00 by David Hunter IS NOW"
  185.     db    " INSTALLED",0Dh,0Ah,"$"
  186.  
  187. past:    mov    dx, offset loaded
  188.     mov    ah,9
  189.     int    21h
  190.     assume    ds:Book    ;interrupt address book area
  191.     push    ds        ;save old ds for future use
  192.     mov    ax,Book
  193.     mov    ds,ax
  194.  
  195. ; NOTE: The following modifications and their associated documentation
  196. ; are Copyright (c) 1984 by Lawrence B. Afrin.  Further copyright
  197. ; information is included in this program's header comment block.
  198. ;
  199. ;       The following two instructions have been removed from David
  200. ; Hunter's version by Lawrence B. Afrin because Mr. Afrin found that
  201. ; on the original model of the IBM PC (and possibly later models, too),
  202. ; these instructions cause the machine to go into the Twilight Zone
  203. ; later on when NMI interrupts are re-enabled.  For some reason in the
  204. ; early IBM PC models, when NMI interrupts are re-enabled after having
  205. ; been disabled, the reenabling operation causes the system to signal
  206. ; an NMI interrupt.  At the point in this program at which that occurs,
  207. ; the program is not ready to handle that interrupt and consequently
  208. ; dies.  Therefore, by preventing the initial disabling of NMI
  209. ; interrupts, the problem is take care of.  -- LBA, 12/30/84
  210.  
  211. ;    mov    al, 00h
  212. ;    out    0A0h, al     ;turn off parity checking
  213.     mov    ax,int_2    ;get the address
  214.     mov    oldint,ax    ;save it for some future use
  215.     mov    ax,int_2[2]    ;second part of double word
  216.     mov    oldint[2],ax
  217.     mov    int_2, offset newint    ;now load the new address
  218.     mov    int_2[2],cs        ;cs is ds in com program
  219.     mov    al, 80h
  220. ;
  221. ; NOTE: It is at the following instruction that the early model PC would
  222. ; ordinarily enter the Twilight Zone if the NMI-disabling instructions
  223. ; noted above were to be left in the program.  Because those instructions
  224. ; were removed, the following instruction, which re-enables an already
  225. ; enabled NMI mask, has no effect on the machine and does not cause a
  226. ; spurious NMI interrupt.
  227. ;
  228.     out    0A0h, al        ;turn parity checking back on
  229.     mov    dx, offset newvec    ;leave new interrupt routine resident
  230.     int    27h            ;don't need "newvec" or beyond
  231. newvec    endp
  232. cseg    ends
  233.     end    start
  234.