home *** CD-ROM | disk | FTP | other *** search
- name driver
- page 55,132
- title 'DRIVER --- installable driver template'
-
- ;
- ; This is a "template" for a MS-DOS installable device driver.
- ;
- ; The actual driver subroutines are stubs only and have
- ; no effect but to return a non-error "Done" status.
- ;
- ; Copyright 1985 Ray Duncan
- ;
- ; To assemble, link, and convert this program into
- ; a BIN file, follow these steps:
- ;
- ; C>MASM DRIVER;
- ; C>LINK DRIVER;
- ; C>EXE2BIN DRIVER.EXE DRIVER.BIN
- ; C>DEL DRIVER.EXE
- ;
- ; Ignore the message "Warning: no stack segment" from the Linker.
- ;
- ; Then add the line:
- ;
- ; DEVICE=DRIVER.BIN
- ;
- ; to your CONFIG.SYS file. Note that the logical name in the
- ; device header can't be the same as the filename, or you will
- ; not be able to delete or copy the file after the system is loaded.
- ;
-
- code segment public 'CODE'
-
- driver proc far
-
- assume cs:code,ds:code,es:code
-
- org 0
-
-
- Max_Cmd equ 16 ; MS-DOS command code maximum
- ; this is 16 for MS-DOS 3.x
- ; and 12 for MS-DOS 2.x
-
-
- cr equ 0dh ; ASCII carriage return
- lf equ 0ah ; ASCII line feed
- eom equ '$' ; end of message signal
-
-
- page
- ;
- ; Device Driver Header
- ;
- Header dd -1 ; link to next device, -1=end of list
-
- dw 8000h ; Device Attribute word
- ; bit 15 =1 for character devices
- ; bit 14 =1 if driver can handle IOCTL
- ; bit 13 =1 if block device & non-IBM format
- ; bit 12 =0
- ; bit 11 =1 if OPEN/CLOSE/RM supported (DOS 3.x)
- ; bit 10 =0
- ; bit 9 =0
- ; bit 8 =0
- ; bit 7 =0
- ; bit 6 =0
- ; bit 5 =0
- ; bit 4 =0
- ; bit 3 =1 if CLOCK device
- ; bit 2 =1 if NUL device
- ; bit 1 =1 if Standard Output
- ; bit 0 =1 if Standard Input
-
- dw Strat ; device "Strategy" entry point
-
- dw Intr ; device "Interrupt" entry point
-
- db 'DRVR ' ; character device name, 8 char, or if block
- ; device, no. of units in first byte followed
- ; by 7 don't care bytes.
-
-
- ;
- ; Double-word pointer to Request Header
- ; Passed to Strategy Routine by MS-DOS
- ;
-
- RH_Ptr dd ?
- page
- ;
- ; MS-DOS Command Codes dispatch table.
- ; The "Interrupt" routine uses this table and the
- ; Command Code supplied in the Request Header to
- ; transfer to the appropriate driver subroutine.
-
- Dispatch:
- dw Init ; 0 = initialize driver
- dw Media_Chk ; 1 = media check on block device
- dw Build_Bpb ; 2 = build BIOS parameter block
- dw IOCTL_Rd ; 3 = I/O control read
- dw Read ; 4 = read from device
- dw ND_Read ; 5 = non-destructive Read
- dw Inp_Stat ; 6 = return current input status
- dw Inp_Flush ; 7 = flush device input buffers
- dw Write ; 8 = write to device
- dw Write_Vfy ; 9 = write with verify
- dw Outp_Stat ; 10 = return current output status
- dw Outp_Flush ; 11 = flush output buffers
- dw IOCTL_Wrt ; 12 = I/O control write
- dw Dev_Open ; 13 = device open (MS-DOS 3.X)
- dw Dev_Close ; 14 = device close (MS-DOS 3.X)
- dw Rem_Media ; 15 = removeable media (MS-DOS 3.X)
- dw Out_Busy ; 16 = output until busy (MS-DOS 3.X)
- page
- ;
- ; MS-DOS Request Header structure definition
- ;
- ; The first 13 bytes of all Request Headers are the same
- ; and are referred to as the "Static" part of the Header.
- ; The number and meaning of the following bytes varies.
- ; In this "Struc" definition we show the Request Header
- ; contents for Read and Write calls.
- ;
- Request struc ; request header template structure
-
- ; beginning of "Static" portion
-
- Rlength db ? ; length of request header
-
- Unit db ? ; unit number for this request
-
- Command db ? ; request header's command code
-
- Status dw ? ; driver's return status word
- ; bit 15 = Error
- ; bits 10-14 = Reserved
- ; bit 9 = Busy
- ; bit 8 = Done
- ; bits 0-7 = Error code if bit 15=1
-
- Reserve db 8 dup (?) ; reserved area
-
- ; end of "Static" portion, the remainder in
- ; this example is for Read and Write functions
-
- Media db ? ; Media Descriptor byte
-
- Address dd ? ; memory address for transfer
-
- Count dw ? ; byte/sector count value
-
- Sector dw ? ; starting sector value
-
- Request ends ; end of request header template
- page
-
- ; Device Driver "Strategy Routine"
-
- ; Each time a request is made for this device, MS-DOS
- ; first calls the "Strategy routine", then immediately
- ; calls the "Interrupt routine".
-
- ; The Strategy routine is passed the address of the
- ; Request Header in ES:BX, which it saves in a local
- ; variable and then returns to MS-DOS.
-
- Strat proc far
- ; save address of Request Header
- mov word ptr cs:[RH_Ptr],bx
- mov word ptr cs:[RH_Ptr+2],es
-
- ret ; back to MS-DOS
-
- Strat endp
-
- page
-
-
- ; Device Driver "Interrupt Routine"
-
- ; This entry point is called by MS-DOS immediately after
- ; the call to the "Strategy Routine", which saved the long
- ; address of the Request Header in the local variable "RH_Ptr".
-
- ; The "Interrupt Routine" uses the Command Code passed in
- ; the Request Header to transfer to the appropriate device
- ; handling routine. Each command code routine is responsible
- ; for putting any necessary information into the Request
- ; Header, then performs a Near Return with AX = Status.
-
- Intr proc far
-
- push ax ; save general registers
- push bx
- push cx
- push dx
- push ds
- push es
- push di
- push si
- push bp
-
- push cs ; make local data addressable
- pop ds
-
- les di,[RH_Ptr] ; let ES:DI = Request Header
-
- ; get BX = Command Code
- mov bl,es:[di.Command]
- xor bh,bh
- cmp bx,Max_Cmd ; make sure it's legal
- jle Intr1 ; jump, function code is ok
- mov ax,8003h ; set Error bit and "Unknown Command" code
- jmp Intr2
-
- Intr1: shl bx,1 ; form index to Dispatch table
- ; and branch to driver routine
- call word ptr [bx+Dispatch]
- ; should return AX = status
-
- les di,[RH_Ptr] ; restore ES:DI = addr of Request Header
-
- Intr2: or ax,0100h ; merge Done bit into status, and
- ; store into Request Header
- mov es:[di.Status],ax
-
- pop bp ;restore general registers
- pop si
- pop di
- pop es
- pop ds
- pop dx
- pop cx
- pop bx
- pop ax
- ret ; back to MS-DOS
-
- page
-
- ;
- ; Command Code subroutines called by Interrupt Routine
- ;
- ; These routines are called with ES:DI pointing to the
- ; Request Header.
- ;
- ; They should return AX = 0 if function was completed
- ; successfully, or AX = 8000H + Error code if function failed.
- ;
-
- Media_Chk proc near ; Function 1 = Media Check
-
- xor ax,ax
- ret
-
- Media_Chk endp
-
-
- Build_Bpb proc near ; Function 2 = Build BPB
-
- xor ax,ax
- ret
-
- Build_Bpb endp
-
-
- IOCTL_Rd proc near ;Function 3 = I/O Control Read
-
- xor ax,ax
- ret
-
- IOCTL_Rd endp
-
-
- Read proc near ; Function 4 = Read
-
- xor ax,ax
- ret
-
- Read endp
-
-
- ND_Read proc near ; Function 5 = Non-Destructive Read
-
- xor ax,ax
- ret
-
- ND_Read endp
-
-
- Inp_Stat proc near ; Function 6 = Input Status
-
- xor ax,ax
- ret
-
- Inp_Stat endp
-
-
- Inp_Flush proc near ; Function 7 = Flush Input Buffers
-
- xor ax,ax
- ret
-
- Inp_Flush endp
-
-
- Write proc near ; Function 8 = Write
-
- xor ax,ax
- ret
-
- Write endp
-
-
- Write_Vfy proc near ; Function 9 = Write with Verify
-
- xor ax,ax
- ret
-
- Write_Vfy endp
-
-
- Outp_Stat proc near ; Function 10 = Output Status
-
- xor ax,ax
- ret
-
- Outp_Stat endp
-
-
- Outp_Flush proc near ; Function 11 = Flush Output Buffers
-
- xor ax,ax
- ret
-
- Outp_Flush endp
-
-
- IOCTL_Wrt proc near ; Function 12 = I/O Control Write
-
- xor ax,ax
- ret
-
- IOCTL_Wrt endp
-
-
- Dev_Open proc near ; Function 13 = Device Open
-
- xor ax,ax
- ret
-
- Dev_Open endp
-
-
- Dev_Close proc near ; Function 14 = Device Close
-
- xor ax,ax
- ret
-
- Dev_Close endp
-
-
- Rem_Media proc near ; Function 15 = Removable Media
-
- xor ax,ax
- ret
-
- Rem_Media endp
-
-
- Out_Busy proc near ; Function 16 = Output Until Busy
-
- xor ax,ax
- ret
-
- Out_Busy endp
- page
-
- ; This Initialization code for the driver is called only
- ; once when the driver is loaded. It is responsible for
- ; initializing the hardware, setting up any necessary
- ; interrupt vectors, and it must return the address
- ; of the first free memory after the driver to MS-DOS.
- ; If it is a block device driver, Init must also return the
- ; address of the Bios Parameter Block pointer array; if all
- ; units are the same, all pointers can point to the same BPB.
- ; Only MS-DOS services 01-0CH and 30H can be called by the
- ; Initialization function.
- ;
- ; In this example, Init returns its own address to the DOS as
- ; the start of free memory after the driver, so that the memory
- ; occupied by INIT will be reclaimed after it is finished
- ; with its work.
-
- Init proc near ; Function 0 = Initialize Driver
-
- push es ; save address of Request Header
- push di
-
- mov ax,cs ; convert load address to ASCII
- mov bx,offset DHaddr
- call hexasc
-
- mov ah,9 ; print sign-on message and
- mov dx,offset Ident ; the load address of driver
- int 21h
-
- pop di ; restore Request Header addr
- pop es
-
- ; set first usable memory addr.
- mov word ptr es:[di.Address],offset Init
- mov word ptr es:[di.Address+2],cs
-
- xor ax,ax ; Return status
- ret
-
- Init endp
-
-
- Ident db cr,lf,lf
- db 'Example Device Driver 1.0'
- db cr,lf
- db 'Device Header at '
- DHaddr db 'XXXX:0000'
- db cr,lf,lf,eom
-
-
- Intr endp
-
- page
-
- ; HEXASC --- converts a binary 16-bit number into
- ; a "hexadecimal" ASCII string.
- ;
- ; Call with AX = value to convert
- ; DS:BX = address to store 4-character string
- ;
- ; Returns AX, BX destroyed, other registers preserved
-
- hexasc proc near
-
- push cx ; save registers
- push dx
-
- mov dx,4 ; initialize character counter
-
- hexasc1:
- mov cx,4 ; isolate next four bits
- rol ax,cl
- mov cx,ax
- and cx,0fh
- add cx,'0' ; convert to ASCII
- cmp cx,'9' ; is it 0-9?
- jbe hexasc2 ; yes, jump
- ; add fudge factor for A-F
- add cx,'A'-'9'-1
-
- hexasc2: ; store this character
- mov [bx],cl
- inc bx ; bump string pointer
-
- dec dx ; count characters converted
- jnz hexasc1 ; loop, not four yet
-
- pop dx ; restore registers
- pop cx
- ret ; back to caller
-
- hexasc endp
-
-
- Driver endp
-
- code ends
-
- end