home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_03_06 / 3n06059b < prev    next >
Text File  |  1992-04-08  |  8KB  |  215 lines

  1. ;-------------------------------------------------------------------------
  2. ; BOOT.SYS  Illustrates some DOS device driver tricks.
  3. ;-------------------------------------------------------------------------
  4. ; This simple device driver will reboot the PC whenever an NMI is
  5. ; intercepted.  This is convenient for folks with a Periscope breakout
  6. ; switch or an Atron probe.  The IBM Professional Debugger package also
  7. ; included an NMI card, but the switch is on the card and not so convenient.
  8. ;
  9. ; This device driver could also be useful to a handicapped person where
  10. ; hitting Ctrl-Alt-Del is a difficult or impossible task depending on
  11. ; their keyboard layout.
  12. ;
  13. ; Many times a device driver will want to hook some vectors during init
  14. ; time and then not accept any I/O requests after that.  All the work it
  15. ; does is in it's interrupt handler(s).  The problem with this is that
  16. ; after init, the device is left with a larger DD interrupt routine than
  17. ; is needed if all it's going to do is reject all requests.  By having the
  18. ; device's init code redirect the interrupt routine pointer in the device
  19. ; header to a shorter "mini" DD interrupt routine we can set the ending
  20. ; address of the device driver such that the larger initial interrupt
  21. ; routine is part of the code to be thrown away after initialization.
  22. ; This results results in smaller resident memory requirements for the
  23. ; device driver.
  24. ;
  25. ; By setting the symbol SAVE_MEMORY below to 0 or 1 the device driver can
  26. ; be built with or without the interrupt routine hack.  On my development
  27. ; system running DR-DOS 6.0, the trick saved a paragraph of resident memory.
  28. ; Other device drivers may save a bit more.
  29. ;
  30. ; Another trick used below has to do with the name of the device.  I always
  31. ; worry about character devices invading the name space that the DOS file
  32. ; system uses when writing a device like this one, which is never intended
  33. ; to do I/O.  By having blanks at the start of the device name in the
  34. ; device header, we lessen the possibility of some DOS app stumbling across
  35. ; this device driver by accident.
  36. ;
  37. ; Yet another trick used below is to place a '$' right after the device
  38. ; header.  This allows the string in the device header to be used to
  39. ; print the device name during initialization via Int 21 fn 9.
  40. ;-------------------------------------------------------------------------
  41. ; WARNING: This code WON'T WORK on systems that use NMI for normal system
  42. ;          operation, like the PCjr and PC convertable.
  43. ;-------------------------------------------------------------------------
  44. ; Tony Ingenoso
  45. ; 1323 SE 17th #274
  46. ; Ft. Lauderdale, FL 33316
  47. ;-------------------------------------------------------------------------
  48.  
  49. SAVE_MEMORY = 0
  50.  
  51. ;----------------------------------------------
  52. ; Device driver request header structure
  53. ;----------------------------------------------
  54. request_header struc
  55. len     db      ?
  56. unit    db      ?
  57. command db      ?
  58. status  dw      ?
  59. reserve db      8 dup (?)
  60. ;--- init specific ---
  61. nunits  db      ?
  62. endaddr dd      ?
  63. request_header ends
  64.  
  65. ;----------------------------------------------
  66. ;    Dummy segment where the BIOS lives
  67. ;----------------------------------------------
  68. bios    segment at 0FFFFH
  69.         assume  cs:bios
  70.         org     0
  71. boot    label   far             ; Jumping here reboots the PC
  72. bios    ends
  73.  
  74.  
  75. cseg    segment para public 'CODE'
  76.         assume  cs:cseg
  77.         org     0
  78. ;------------- DEVICE HEADER ------------------
  79.         dd      -1              ; Link to next device
  80.         dw      8000H           ; Character device
  81.         dw      offset strategy ;
  82. intaddr dw      offset interrupt; Initially point to large interrupt routine
  83. devname db      '    BOOT','$'  ; Blanks prevent stumbling on dev by accident
  84. ;----------------------------------------------
  85.  
  86. req_ptr label   dword                   ; Strat saves RQH pointer here
  87. rh_offset dw    ?
  88. rh_seg    dw    ?
  89.  
  90. ;----------------------------------------------
  91. ;           NMI trapper routine
  92. ;----------------------------------------------
  93. NMItrapper proc far
  94.         mov     ax, 0040H               ; Set BIOS reset flag
  95.         mov     ds, ax                  ;
  96.         mov     word ptr ds:[72H],1234H ; WARM
  97.         jmp     boot                    ; JMP FFFF:0000
  98. NMItrapper endp
  99.  
  100. ;----------------------------------------------
  101. ;           DD strat routine
  102. ;----------------------------------------------
  103. strategy proc far
  104.         mov     cs:rh_offset, bx        ;offset
  105.         mov     cs:rh_seg, es           ;segment
  106.         ret
  107. strategy endp
  108.  
  109. IF SAVE_MEMORY
  110. ;----------------------------------------------
  111. ; DD interrupt routine for post-INIT requests.
  112. ;----------------------------------------------
  113. ; Using this mini interrupt routine after init
  114. ; reduces the resident memory requirements of
  115. ; the device driver.
  116. ;----------------------------------------------
  117. mini_interrupt proc far
  118.         push    ds                      ;
  119.         push    si                      ;
  120.         lds     si, cs:req_ptr          ; DS:SI-->request header
  121.         mov     [si].status, 8103H      ; Status = Done + Error + Unk command
  122.         pop     si                      ;
  123.         pop     ds                      ;
  124.         ret                             ;
  125. mini_interrupt endp
  126.  
  127. THROW_AWAY_CODE label near
  128. ENDIF
  129.  
  130. ;----------------------------------------------
  131. ;    DD interrupt routine for INIT requests
  132. ;----------------------------------------------
  133. interrupt proc far
  134.         push    ds                      ; Save what gets whacked
  135.         push    si                      ;
  136.         push    ax                      ;
  137.         lds     si, cs:req_ptr          ; DS:SI-->request header
  138.         mov     al, ds:[si].command     ; AL == command code
  139.         cmp     al, 0                   ; Is it an init request?
  140.         jne     error                   ; All but INIT get error
  141.         call    initialize              ;
  142.         mov     ax, 0100H               ; Status = No error + Done
  143.         jmp     short exit              ;
  144. error:  mov     ax, 8103H               ; Error + Done + Unknown command
  145. exit:   mov     ds:[si].status, ax      ; Set status word in RQH.
  146.         pop     ax                      ; Restore
  147.         pop     si                      ;
  148.         pop     ds                      ;
  149.         ret
  150. interrupt endp
  151.  
  152. IF (SAVE_MEMORY EQ 0)
  153. THROW_AWAY_CODE label near
  154. ENDIF
  155. ;----------------------------------------------
  156. ;          Initialize the device
  157. ;----------------------------------------------
  158. initialize proc near
  159.         push    dx                      ; Save DX
  160.         push    cs                      ; DS==CS
  161.         pop     ds                      ;
  162.         assume  ds:cseg
  163.  
  164. IF SAVE_MEMORY
  165. ;
  166. ; Relocate the DD's interrupt routine to the "mini".
  167. ;
  168.         mov     word ptr intaddr, offset mini_interrupt
  169. ENDIF
  170.  
  171. ;
  172. ; Display the logo message
  173. ;
  174.         mov     ah, 09H                 ; Display the logo
  175.         mov     dx, offset logo         ;
  176.         int     21H                     ;
  177. ;
  178. ; Grab the NMI vector.
  179. ;
  180.         mov     ax, 2502H               ; NMI is Int 2
  181.         mov     dx, offset NMItrapper   ;
  182.         int     21H                     ;
  183. ;
  184. ; Show the name of the initializing device
  185. ;
  186.         mov     ah, 09H
  187.         mov     dx, offset devini1      ; Display "Device ["
  188.         int     21H
  189.         mov     dx, offset devname      ; Display the device name
  190.         int     21H
  191.         mov     dx, offset devini2      ; Display "] initialized."
  192.         int     21H
  193. ;
  194. ; Set the ending address.
  195. ;
  196.         lds     si, cs:req_ptr          ; Get RQH pointer back
  197.         assume  ds:nothing
  198.         mov     word ptr [si].endaddr, offset THROW_AWAY_CODE
  199.         mov     word ptr [si].endaddr+2, cs
  200.         pop     dx                      ; Restore DX
  201.         ret
  202. initialize endp
  203.  
  204. ;----------------------------------------------
  205. ;                 Messages
  206. ;----------------------------------------------
  207. logo    db      'BOOT V1.00, Reboot on NMI',13,10
  208.         db      'Tony Ingenoso, 1992',13,10,'$'
  209.  
  210. devini1 db      'Device [$'
  211. devini2 db      '] initialized.',13,10,'$'
  212.  
  213. cseg    ends
  214.         end
  215.