home *** CD-ROM | disk | FTP | other *** search
/ Sound Sensations! / sound_sensations.iso / cmf / drivers / driver.asm next >
Assembly Source File  |  1985-03-15  |  10KB  |  294 lines

  1.  
  2. ;--------------------------------------------------------------------
  3. ; DRIVER.SYS    (a character device driver)
  4. ;        Copyright (c) 1985 by Dan Rollins
  5. ;
  6. ; Simple device driver illustrates the fundamental structures and
  7. ; actions of a DOS 2.0 installable device driver.
  8. ;
  9. ; Creates TESTDEV, an input and output character device (pseudo-device).
  10. ;
  11. ; To install: Assemble, link, then process with:
  12. ;        exe2bin driver driver.sys
  13. ;          Then add this line to your CONFIG.SYS file:
  14. ;         device=driver.sys
  15. ;          Then reboot DOS and copy a file to TESTDEV
  16.  
  17. ;=======================================================================
  18. ;---- equates for character device drivers ----
  19. ;=======================================================================
  20.  
  21. ;-- equates for the data structures used by this driver
  22.  
  23. ;-- offsets from the start of the Request Header
  24. RH_LEN         equ 0     ;byte
  25. RH_UNIT_CODE     equ 1     ;byte
  26. RH_CMD_CODE     equ 2     ;byte
  27. RH_STATUS     equ 3     ;word
  28.  
  29. ;--- Request Header offsets for fields when the INIT function is executed
  30. IN_UNIT_COUNT     equ 13  ;byte
  31. IN_END_ADDR     equ 14  ;dword
  32. IN_BPB_PTR     equ 18  ;dword
  33.  
  34. ;--- Request Header offsets for fields for INPUT or OUTPUT functions
  35. IO_MEDIA_DESC     equ 13  ;byte
  36. IO_TRANS_ADDR     equ 14  ;dword
  37. IO_DATA_COUNT     equ 18  ;word
  38. IO_START_SECTOR  equ 20  ;word
  39.  
  40. ;--- equates for the bit-flags used in the attribute field of the device header
  41.  
  42. CHAR_DEVICE     equ 8000h   ;bit 15: 1 for character device, 0 block device
  43. IOCTL         equ 4000h   ;bit 14: 1 if IOCTL system calls are supported
  44. NON_IBM_FORMAT     equ 2000h   ;bit 13: 1 if block device is non-IBM format
  45.                  ;bits 12 to 4 are reserved
  46. CLOCK         equ 8         ;bit 3: 1 if this is the CLOCK$ device
  47. NUL         equ 4         ;bit 2: 1 if this is the NUL device
  48. STO         equ 2         ;bit 1: 1 if this is the Standard Output device
  49. STI         equ 1         ;bit 0: 1 if this is the Standard Input device
  50.  
  51. ;--- equates for the bit-flags used in the status record for each command
  52.  
  53. ERR_FLAG     equ 8000h   ;bit 15: 1 if error occurred (see below)
  54.                  ;bits 14 to 10 reserved
  55. BUSY         equ 0200h   ;bit 9: 1 if device is busy
  56. DONE         equ 0100h   ;bit 8: set to 1 before exiting to caller
  57. ;--- the following values occupy bits 7 thru 0 when an error occurs --
  58. WRITE_PROTECT     equ  0
  59. UNKNOWN_UNIT     equ  1
  60. DEV_NOT_READY     equ  2
  61. UNKNOWN_CMD     equ  3    ;<-- this is the only error used by this device ---
  62. CRC_ERROR     equ  4
  63. BAD_LEN      equ  5
  64. SEEK_ERROR     equ  6
  65. UNKNOWN_MEDIA     equ  7
  66. SECTOR_NOT_FND     equ  8
  67. OUT_OF_PAPER     equ  9
  68. WRITE_FAULT     equ  0ah
  69. READ_FAULT     equ  0bh
  70. GENERAL_FAILURE  equ  0ch
  71.  
  72. ;===============================================================
  73. ;----------- data and code of the file begins here -------------
  74. ;===============================================================
  75.  
  76. dev_seg  segment
  77. test_dev proc  far
  78.      assume cs:dev_seg, ds:dev_seg, es:dev_seg
  79.  
  80. ;------------------------------
  81. ; The following lines are the device header that must exist for
  82. ;  every device.  This file has only one device, and it works with
  83. ;  character I/O.
  84.  
  85. header:         ;label for the start of this device driver
  86.  
  87. next_dev_ptr        dd    -1         ;this is the last (only) device defined
  88. dev_attribute        dw     CHAR_DEVICE
  89. strategy_ptr        dw     strategy    ;the proc that sets up for the functions
  90. interrupt_ptr        dw     interrupt   ;the proc that handles function calls
  91. device_name        db     'TESTDEV '  ;8-byte string of device name
  92.  
  93. request_ptr        dd    ?   ;STRATEGY stores ES:BX request header pointer here
  94.                 ;INTERRUPT retrieves it
  95.  
  96. ; this table is used to jump to the procedure that is indicated
  97. ; by DOS in the command code (third byte of the request header)
  98.  
  99. fn_table dw  init_fn          ;  0: initialization procedure
  100.      dw  media_check_fn   ;  1: media check procedure
  101.      dw  build_bpb_fn     ;  2: build Bios Parameter Block
  102.      dw  ioctl_in_fn      ;  3: IOCTL Input
  103.      dw  input_fn          ;  4: read from device
  104.      dw  nd_input_fn      ;  5: Non-Destructive, no-wait read
  105.      dw  input_status_fn  ;  6: return status of input device
  106.      dw  input_flush_fn   ;  7: flush (clear) the input buffer
  107.      dw  output_fn          ;  8: write to device
  108.      dw  output_verify_fn ;  9: write and verify
  109.      dw  output_status_fn ; 10: return status of output device
  110.      dw  output_flush_fn  ; 11: flush (clear) the output buffer
  111.      dw  ioctl_out_fn     ; 12: IOCTL Output
  112.  
  113. ;The following messages are displayed by TESTDEV when DOS
  114. ;makes a request.
  115.  
  116. CR     equ     0dh
  117. LF     equ     0ah
  118. fn0_msg  db 'Initializing TESTDEV Driver ',CR,LF,'$'
  119. fn4_msg  db 'Input request : $'
  120. fn8_msg  db 'Output request : $'
  121. crlf     db CR,LF,'$'
  122.  
  123. ;=============================================================
  124. ; STRATEGY procedure
  125. ; Just saves the request header pointer for the INTERRUPT procedure
  126.  
  127. strategy proc far
  128.      assume cs:dev_seg
  129.      mov     cs:word ptr request_ptr,bx
  130.      mov     cs:word ptr request_ptr+2,es
  131.      ret                       ;FAR return to DOS
  132. strategy endp
  133.  
  134. ;=============================================================
  135. ; INTERRUPT procedure
  136. ; Processes the command indicated in the request header.
  137.  
  138. interrupt proc far
  139.      assume cs:dev_seg, ds:nothing, es:nothing
  140.      push     ds            ;preserve all registers
  141.      push     es
  142.      push     ax
  143.      push     bx
  144.      push     cx
  145.      push     dx
  146.      push     di
  147.      push     si
  148.  
  149.      push     cs
  150.      pop     ds        ;DS addresses the program data area
  151.      les     bx,request_ptr ;get the pointer saved by STRATEGY
  152.      mov     ah,0
  153.      mov     al,es:[bx+RH_CMD_CODE]  ;fetch the command
  154.      mov     di,ax
  155.      shl     di,1             ; * 2 to point to jump vector
  156.      jmp     fn_table[di]         ;invoke that function procedure
  157.  
  158. ;--- all command jumps except INIT, INPUT, and OUTPUT will end up here ----
  159.  
  160. nd_input_fn:         ;requests for any of these commands
  161. media_check_fn:      ; will result in an error message
  162. build_bpb_fn:
  163. ioctl_in_fn:
  164. input_status_fn:
  165. input_flush_fn:
  166. output_verify_fn:
  167. output_status_fn:
  168. output_flush_fn:
  169. ioctl_out_fn:
  170.  
  171. error_exit:
  172.      or     word ptr es:[bx+RH_STATUS],ERR_FLAG     ;set the ERROR_FLAG
  173.      or     word ptr es:[bx+RH_STATUS],UNKNOWN_CMD  ;identify the error
  174.  
  175. ;--- service request has been handled.
  176. ;--- Set the "done flag" and return to DOS.
  177.  
  178. common_exit:
  179.      or     word ptr es:[bx+RH_STATUS],DONE  ;always indicate completion
  180.      pop     si                  ; by setting the DONE bit
  181.      pop     di
  182.      pop     dx
  183.      pop     cx
  184.      pop     bx
  185.      pop     ax
  186.      pop     es
  187.      pop     ds
  188.      ret                   ;FAR return
  189.  
  190. ;--------------------------
  191. ; INTERRUPT procedure function calls
  192. ; Only three types of requests are handled by TESTDEV.    All other
  193. ;  requests are routed through the ERROR_EXIT.
  194.  
  195. ;-------------------------------------------------------------------------
  196. ; INPUT_FN
  197. ; Reads (waits for) 1 character from the keyboard, and displays it,
  198. ; then returns it (within the I/O structure) to DOS.
  199.  
  200. input_fn proc near
  201.      mov     ch,0
  202.      mov     cl,es:[bx+IO_DATA_COUNT]  ;get number of bytes
  203.      jcxz     if_exit     ;if no bytes, just exit
  204. if_10:
  205.      mov     dx,offset fn4_msg     ;"Input request: "
  206.      mov     ah,9               ;DOS print string service
  207.      int     21H
  208.  
  209.      mov     ah,0      ;ROM-BIOS AWAIT_KEY function
  210.      int     16H      ;get AL = ASCII character, AH = scan code
  211.  
  212.      mov     word ptr es:[bx+IO_DATA_COUNT],1 ;store the character count
  213.  
  214.      push     ds
  215.      lds     di,es:[bx+IO_TRANS_ADDR]    ;get SEG:OFF of destination
  216.      mov     [di],al             ;store byte in destination
  217.      pop     ds
  218.  
  219.      mov     dl,al
  220.      mov     ah,2         ;display the character
  221.      int     21H
  222.  
  223.      mov     dx,offset crlf  ;start a new line
  224.      mov     ah,9         ;invoke DOS print string service
  225.      int     21h
  226.      loop     if_10         ;do again, for multi-byte requests
  227. if_exit:
  228.      jmp     common_exit
  229. input_fn endp
  230.  
  231. ;--------------------------------------------------------------------
  232. ; OUTPUT_FN  sends the character passed to it from DOS out to the
  233. ; standard output device.
  234.  
  235. output_fn proc near
  236.      mov     ch,0
  237.      mov     cl,es:[bx+IO_DATA_COUNT]  ;get number of bytes
  238.      jcxz     of_exit     ;if no bytes, just exit
  239. of_10:
  240.      mov     dx,offset fn8_msg     ;"Output request :"
  241.      mov     ah,9               ;DOS print string service
  242.      int     21H
  243.  
  244.      push     ds
  245.      lds     si,es:[bx+IO_TRANS_ADDR] ;get SEG:OFF of data
  246.      mov     dl,[si]          ;retrieve the character
  247.      pop     ds              ;unstack or die
  248.  
  249.      mov     ah,2        ;display the character
  250.      int     21H
  251.  
  252.      mov     dx,offset crlf  ;print new line characters
  253.      mov     ah,9         ;DOS print string service
  254.      int     21H
  255.      loop     of_10         ;get next (if multi-byte request)
  256. of_exit:
  257.      jmp     common_exit
  258. output_fn endp
  259.  
  260. ;-------------------------,
  261. ; INIT_FN procedure
  262. ; Passes the end-of-driver address back to DOS.
  263. ; Note that the address of this procedure is passed back to DOS as the
  264. ;  address of the end of the driver.  After one invocation, INIT_FN
  265. ;  is never called again; thus, it doesn't need to be saved with the
  266. ;  rest of the function procedures.
  267.  
  268. init_fn  proc  near
  269.      mov     dx,offset fn0_msg     ;"Initializing TESTDEV"
  270.      mov     ah,9               ;DOS print string service
  271.      int     21H
  272.  
  273. ;-- debugging tool:
  274. ;-- store the address so the code can be examined with DEBUG ---
  275.      push     ds
  276.      mov     ax,0
  277.      mov     ds,ax
  278.      mov     word ptr ds:[04f0h],offset interrupt
  279.      mov     word ptr ds:[04f2h],cs
  280.      pop     ds
  281. ;-- header address (offset,segment) is stored at address 0000:04F0
  282. ;-- which is known as the "intra-application communication area"
  283.  
  284. ;-- specify the end of this driver and exit to DOS -------
  285.      mov     word ptr es:[bx+IN_END_ADDR],offset init_fn
  286.      mov     word ptr es:[bx+IN_END_ADDR+2],cs
  287.      jmp     common_exit
  288. init_fn  endp
  289.  
  290. interrupt endp
  291. test_dev  endp
  292. dev_seg   ends
  293.       end       header   ;must specify for EXE2BIN
  294.