home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PROGRAMS / UTILS / DOS_HELP / ADVMSDOS.ZIP / DRIVER.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-06-19  |  11.6 KB  |  478 lines

  1.         name    driver
  2.         page    55,132
  3.         title   'DRIVER --- installable driver template'
  4.  
  5. ;
  6. ; This is a "template" for a MS-DOS installable device driver.
  7. ;
  8. ; The actual driver subroutines are stubs only and have
  9. ; no effect but to return a non-error "Done" status.
  10. ; Copyright 1985 Ray Duncan
  11. ;
  12. ; To assemble, link, and convert this program into 
  13. ; a BIN file, follow these steps:
  14. ;
  15. ;    C>MASM DRIVER;
  16. ;     C>LINK DRIVER;
  17. ;    C>EXE2BIN DRIVER.EXE DRIVER.BIN
  18. ;    C>DEL DRIVER.EXE
  19. ;
  20. ; Ignore the message "Warning: no stack segment" from the Linker.
  21. ;
  22. ; Then add the line:
  23. ;
  24. ;    DEVICE=DRIVER.BIN
  25. ;
  26. ; to your CONFIG.SYS file.  Note that the logical name in the
  27. ; device header can't be the same as the filename, or you will
  28. ; not be able to delete or copy the file after the system is loaded.
  29. ;
  30.  
  31. code    segment public 'CODE'
  32.  
  33. driver  proc    far
  34.  
  35.         assume  cs:code,ds:code,es:code
  36.  
  37.         org     0
  38.  
  39.  
  40. Max_Cmd equ     16              ; MS-DOS command code maximum
  41.                                 ; this is 16 for MS-DOS 3.x
  42.                                 ; and 12 for MS-DOS 2.x 
  43.  
  44.  
  45. cr      equ     0dh             ; ASCII carriage return
  46. lf      equ     0ah             ; ASCII line feed
  47. eom     equ     '$'             ; end of message signal
  48.  
  49.  
  50.         page
  51. ;
  52. ; Device Driver Header
  53. ;
  54. Header  dd      -1              ; link to next device, -1=end of list
  55.  
  56.         dw      8000h           ; Device Attribute word
  57.                 ; bit 15 =1 for character devices
  58.                 ; bit 14 =1 if driver can handle IOCTL
  59.                 ; bit 13 =1 if block device & non-IBM format
  60.                 ; bit 12 =0
  61.                 ; bit 11 =1 if OPEN/CLOSE/RM supported (DOS 3.x)
  62.                 ; bit 10 =0        
  63.                 ; bit 9  =0
  64.                 ; bit 8  =0
  65.                 ; bit 7  =0
  66.                 ; bit 6  =0
  67.                 ; bit 5  =0
  68.                 ; bit 4  =0
  69.                 ; bit 3  =1 if CLOCK device
  70.                 ; bit 2  =1 if NUL device
  71.                 ; bit 1  =1 if Standard Output
  72.                 ; bit 0  =1 if Standard Input
  73.  
  74.         dw      Strat           ; device "Strategy" entry point
  75.  
  76.         dw      Intr            ; device "Interrupt" entry point
  77.  
  78.         db      'DRVR    '      ; character device name, 8 char, or if block
  79.                                 ; device, no. of units in first byte followed 
  80.                 ; by 7 don't care bytes.
  81.  
  82.  
  83. ;
  84. ; Double-word pointer to Request Header
  85. ; Passed to Strategy Routine by MS-DOS
  86. ;
  87.  
  88. RH_Ptr  dd      ?
  89.     page
  90. ;
  91. ; MS-DOS Command Codes dispatch table.
  92. ; The "Interrupt" routine uses this table and the 
  93. ; Command Code supplied in the Request Header to 
  94. ; transfer to the appropriate driver subroutine.
  95.  
  96. Dispatch:
  97.         dw      Init            ;  0 = initialize driver
  98.         dw      Media_Chk       ;  1 = media check on block device
  99.         dw      Build_Bpb       ;  2 = build BIOS parameter block
  100.         dw      IOCTL_Rd           ;  3 = I/O control read 
  101.         dw      Read               ;  4 = read from device
  102.         dw      ND_Read            ;  5 = non-destructive Read 
  103.         dw      Inp_Stat        ;  6 = return current input status
  104.         dw      Inp_Flush       ;  7 = flush device input buffers
  105.         dw      Write              ;  8 = write to device
  106.         dw      Write_Vfy       ;  9 = write with verify
  107.         dw      Outp_Stat       ; 10 = return current output status
  108.         dw      Outp_Flush      ; 11 = flush output buffers
  109.         dw      IOCTL_Wrt          ; 12 = I/O control write 
  110.         dw      Dev_Open        ; 13 = device open       (MS-DOS 3.X)
  111.         dw      Dev_Close       ; 14 = device close      (MS-DOS 3.X)
  112.         dw      Rem_Media       ; 15 = removeable media  (MS-DOS 3.X)
  113.     dw    Out_Busy    ; 16 = output until busy (MS-DOS 3.X)    
  114.         page
  115. ; MS-DOS Request Header structure definition
  116. ;
  117. ; The first 13 bytes of all Request Headers are the same
  118. ; and are referred to as the "Static" part of the Header.
  119. ; The number and meaning of the following bytes varies.
  120. ; In this "Struc" definition we show the Request Header
  121. ; contents for Read and Write calls.
  122. ;
  123. Request struc                   ; request header template structure
  124.         
  125.                                 ; beginning of "Static" portion
  126.  
  127. Rlength db      ?               ; length of request header
  128.  
  129. Unit    db      ?               ; unit number for this request
  130.  
  131. Command db      ?               ; request header's command code
  132.  
  133. Status  dw      ?               ; driver's return status word
  134.                 ; bit  15    = Error
  135.                 ; bits 10-14 = Reserved
  136.                 ; bit  9     = Busy
  137.                 ; bit  8     = Done
  138.                 ; bits 0-7   = Error code if bit 15=1
  139.  
  140. Reserve db      8 dup (?)       ; reserved area
  141.  
  142.                                 ; end of "Static" portion, the remainder in
  143.                 ; this example is for Read and Write functions
  144.  
  145. Media   db      ?               ; Media Descriptor byte
  146.  
  147. Address dd      ?               ; memory address for transfer
  148.  
  149. Count   dw      ?               ; byte/sector count value
  150.  
  151. Sector  dw      ?               ; starting sector value
  152.  
  153. Request ends                    ; end of request header template
  154.         page
  155.  
  156. ; Device Driver "Strategy Routine"
  157.  
  158. ; Each time a request is made for this device, MS-DOS
  159. ; first calls the "Strategy routine",  then immediately 
  160. ; calls the "Interrupt routine".  
  161.  
  162. ; The Strategy routine is passed the address of the
  163. ; Request Header in ES:BX, which it saves in a local
  164. ; variable and then returns to MS-DOS.
  165.  
  166. Strat   proc    far     
  167.                                 ; save address of Request Header
  168.         mov     word ptr cs:[RH_Ptr],bx
  169.         mov     word ptr cs:[RH_Ptr+2],es
  170.  
  171.         ret                     ; back to MS-DOS
  172.  
  173. Strat   endp
  174.  
  175.         page
  176.  
  177.  
  178. ; Device Driver "Interrupt Routine"
  179.  
  180. ; This entry point is called by MS-DOS immediately after 
  181. ; the call to the "Strategy Routine", which saved the long
  182. ; address of the Request Header in the local variable "RH_Ptr".
  183.  
  184. ; The "Interrupt Routine" uses the Command Code passed in
  185. ; the Request Header to transfer to the appropriate device
  186. ; handling routine.  Each command code routine is responsible
  187. ; for putting any necessary information into the Request
  188. ; Header, then performs a Near Return with AX = Status.
  189.  
  190. Intr    proc  far
  191.  
  192.         push    ax              ; save general registers 
  193.         push    bx
  194.         push    cx
  195.         push    dx
  196.         push    ds
  197.         push    es
  198.         push    di
  199.         push    si
  200.         push    bp
  201.  
  202.         push    cs              ; make local data addressable
  203.         pop     ds
  204.  
  205.         les     di,[RH_Ptr]     ; let ES:DI = Request Header
  206.  
  207.                                 ; get BX = Command Code
  208.         mov     bl,es:[di.Command]
  209.         xor     bh,bh
  210.         cmp     bx,Max_Cmd      ; make sure it's legal
  211.     jle    Intr1        ; jump, function code is ok
  212.     mov    ax,8003h    ; set Error bit and "Unknown Command" code
  213.     jmp    Intr2
  214.  
  215. Intr1:    shl     bx,1            ; form index to Dispatch table
  216.                                 ; and branch to driver routine
  217.         call    word ptr [bx+Dispatch]
  218.                 ; should return AX = status
  219.  
  220.     les    di,[RH_Ptr]    ; restore ES:DI = addr of Request Header
  221.  
  222. Intr2:    or    ax,0100h    ; merge Done bit into status, and
  223.                 ; store into Request Header
  224.         mov     es:[di.Status],ax
  225.  
  226.         pop     bp              ;restore general registers
  227.         pop     si
  228.         pop     di
  229.         pop     es
  230.         pop     ds
  231.         pop     dx
  232.         pop     cx
  233.         pop     bx
  234.         pop     ax
  235.         ret                     ; back to MS-DOS
  236.  
  237.         page
  238.  
  239. ;
  240. ; Command Code subroutines called by Interrupt Routine
  241. ;
  242. ; These routines are called with ES:DI pointing to the
  243. ; Request Header.  
  244. ;
  245. ; They should return AX = 0 if function was completed
  246. ; successfully, or AX = 8000H + Error code if function failed.
  247. ;
  248.  
  249. Media_Chk proc    near        ; Function 1 = Media Check
  250.     
  251.     xor    ax,ax
  252.     ret
  253.  
  254. Media_Chk endp
  255.  
  256.  
  257. Build_Bpb proc     near        ; Function 2 = Build BPB
  258.  
  259.     xor    ax,ax
  260.     ret
  261.  
  262. Build_Bpb endp
  263.  
  264.  
  265. IOCTL_Rd proc    near        ;Function 3 = I/O Control Read
  266.  
  267.     xor    ax,ax
  268.     ret
  269.  
  270. IOCTL_Rd endp
  271.  
  272.  
  273. Read     proc    near         ; Function 4 = Read
  274.  
  275.     xor    ax,ax
  276.     ret
  277.  
  278. Read    endp
  279.  
  280.  
  281. ND_Read proc    near        ; Function 5 = Non-Destructive Read
  282.  
  283.     xor    ax,ax
  284.     ret
  285.  
  286. ND_Read endp
  287.  
  288.  
  289. Inp_Stat proc    near        ; Function 6 = Input Status
  290.  
  291.     xor    ax,ax
  292.     ret
  293.  
  294. Inp_Stat endp
  295.  
  296.  
  297. Inp_Flush proc    near        ; Function 7 = Flush Input Buffers
  298.  
  299.     xor    ax,ax
  300.     ret
  301.  
  302. Inp_Flush endp
  303.  
  304.  
  305. Write     proc    near        ; Function 8 = Write
  306.  
  307.     xor    ax,ax
  308.     ret
  309.  
  310. Write    endp
  311.  
  312.  
  313. Write_Vfy proc    near        ; Function 9 = Write with Verify
  314.  
  315.     xor    ax,ax
  316.     ret
  317.  
  318. Write_Vfy endp
  319.  
  320.  
  321. Outp_Stat proc    near        ; Function 10 = Output Status
  322.  
  323.     xor    ax,ax
  324.     ret
  325.  
  326. Outp_Stat endp
  327.  
  328.  
  329. Outp_Flush proc    near        ; Function 11 = Flush Output Buffers
  330.  
  331.     xor    ax,ax
  332.     ret
  333.  
  334. Outp_Flush endp
  335.  
  336.  
  337. IOCTL_Wrt proc    near        ; Function 12 = I/O Control Write
  338.  
  339.     xor    ax,ax
  340.     ret
  341.  
  342. IOCTL_Wrt endp
  343.  
  344.  
  345. Dev_Open proc    near        ; Function 13 = Device Open
  346.  
  347.     xor    ax,ax
  348.     ret
  349.  
  350. Dev_Open endp
  351.     
  352.  
  353. Dev_Close proc    near        ; Function 14 = Device Close
  354.  
  355.     xor    ax,ax
  356.     ret
  357.  
  358. Dev_Close endp
  359.  
  360.  
  361. Rem_Media proc    near        ; Function 15 = Removable Media
  362.  
  363.     xor    ax,ax
  364.     ret
  365.  
  366. Rem_Media endp
  367.  
  368.  
  369. Out_Busy proc    near        ; Function 16 = Output Until Busy
  370.  
  371.     xor    ax,ax
  372.     ret
  373.  
  374. Out_Busy endp         
  375.         page
  376.  
  377. ; This Initialization code for the driver is called only
  378. ; once when the driver is loaded.  It is responsible for
  379. ; initializing the hardware, setting up any necessary 
  380. ; interrupt vectors, and it must return the address
  381. ; of the first free memory after the driver to MS-DOS.
  382. ; If it is a block device driver, Init must also return the 
  383. ; address of the Bios Parameter Block pointer array; if all 
  384. ; units are the same, all pointers can point to the same BPB.
  385. ; Only MS-DOS services 01-0CH and 30H can be called by the 
  386. ; Initialization function. 
  387. ;
  388. ; In this example, Init returns its own address to the DOS as 
  389. ; the start of free memory after the driver, so that the memory 
  390. ; occupied by INIT will be reclaimed after it is finished 
  391. ; with its work.  
  392.  
  393. Init    proc    near        ; Function 0 = Initialize Driver
  394.  
  395.         push    es              ; save address of Request Header 
  396.         push    di
  397.  
  398.     mov    ax,cs        ; convert load address to ASCII
  399.     mov    bx,offset DHaddr
  400.     call    hexasc
  401.  
  402.         mov     ah,9            ; print sign-on message and
  403.         mov     dx,offset Ident ; the load address of driver
  404.         int     21h
  405.  
  406.         pop     di              ; restore Request Header addr
  407.         pop     es
  408.  
  409.                                 ; set first usable memory addr.
  410.         mov     word ptr es:[di.Address],offset Init
  411.         mov     word ptr es:[di.Address+2],cs
  412.  
  413.     xor    ax,ax        ; Return status 
  414.     ret
  415.  
  416. Init    endp
  417.  
  418.  
  419. Ident   db      cr,lf,lf
  420.         db      'Example Device Driver 1.0'
  421.         db      cr,lf
  422.         db      'Device Header at '
  423. DHaddr    db    'XXXX:0000'
  424.         db      cr,lf,lf,eom
  425.  
  426.  
  427. Intr    endp
  428.  
  429.     page
  430.  
  431. ; HEXASC --- converts a binary 16-bit number into
  432. ;            a "hexadecimal" ASCII string.
  433. ;
  434. ; Call with     AX    = value to convert
  435. ;        DS:BX = address to store 4-character string
  436. ;
  437. ; Returns    AX, BX destroyed, other registers preserved
  438.  
  439. hexasc    proc    near
  440.  
  441.     push    cx    ; save registers 
  442.     push    dx
  443.  
  444.     mov    dx,4    ; initialize character counter
  445.  
  446. hexasc1:
  447.     mov    cx,4    ; isolate next four bits
  448.     rol    ax,cl
  449.     mov    cx,ax
  450.     and    cx,0fh
  451.     add    cx,'0'    ; convert to ASCII 
  452.     cmp    cx,'9'    ; is it 0-9?
  453.     jbe    hexasc2    ; yes, jump
  454.             ; add fudge factor for A-F
  455.     add    cx,'A'-'9'-1
  456.  
  457. hexasc2:        ; store this character
  458.     mov    [bx],cl
  459.     inc    bx    ; bump string pointer
  460.  
  461.     dec    dx    ; count characters converted
  462.     jnz    hexasc1 ; loop, not four yet
  463.  
  464.     pop    dx    ; restore registers
  465.     pop    cx
  466.     ret        ; back to caller
  467.  
  468. hexasc    endp
  469.  
  470.  
  471. Driver  endp
  472.  
  473. code    ends
  474.         
  475.         end
  476.