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.; ; Ray Duncan; Laboratory Microsystems Inc.; April 1985code segment public 'CODE'driver proc far assume cs:code,ds:code,es:code org 0Max_Cmd equ 15 ; MS-DOS command code maximum ; this is 15 for MS-DOS 3.x ; and 12 for MS-DOS 2.x cr equ 0dh ; ASCII carriage returnlf equ 0ah ; ASCII line feedeom equ '$' ; end of message signal page;; Device Driver Header;Header dd -1 ;link to next device,-1= end of list dw 8000h ;attribute word ;bit 15=1 for character devices dw Strat ;device "Strategy" entry point dw Intr ;device "Interrupt" entry point db 'DRIVER ' ;char device name, 8 char, or ;if block device, no. of units ;in first byte followed by ;7 don't care bytes ; Interpretation of Attribute word:; ; Bit Significance;; 15 =1 for character drivers; 14 =1 if driver can handle IOCTL; 13 =1 if block device & non-IBM format; 12 0; 11 open/close/RM supported (DOS 3.x); 10 0; 9 0; 8 0; 7 0; 6 0; 5 0; 4 0; 3 =1 if CLOCK device; 2 =1 if NUL device; 1 =1 if Standard Output; 0 =1 if Standard Input page;; local variables for use by driver;RH_Ptr dd ? ; pointer to request header ; passed to Strat by BDOSIdent db cr,lf,lf db 'LMI Example Device Driver 1.0' db cr,lf db 'Copyright (c) 1985 ' db 'Laboratory Microsystems Inc.' db cr,lf,lf,eom;; 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 = init driver into system dw Media_Chk ; 1 = media check on blk dev dw Build_Bpb ; 2 = build BIOS param block dw Ioctl_Inp ; 3 = I/O ctrl read from dev dw Input ; 4 = normal destructive read dw Nd_Input ; 5 = non-destructive read,no wait dw Inp_Stat ; 6 = return current input status dw Inp_Flush ; 7 = flush device input buffers dw Output ; 8 = normal output to device dw Outp_Vfy ; 9 = output with verify dw Outp_Stat ; 10 = return current output status dw Outp_Flush ; 11 = flush output buffers dw Ioctl_Outp ; 12 = I/O control output 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) 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" portionRlength db ? ; length of request headerUnit db ? ; unit number for this requestCommand db ? ; request header's command codeStatus dw ? ; driver's return status wordReserve db 8 dup (?) ; reserved area ; end of "Static" portion Media db ? ; media descriptor byteAddress dd ? ; memory address for transferCount dw ? ; byte/sector count valueSector dw ? ; starting sector valueRequest ends ; end of request header template;; Status word is interpreted as follows:;; Bit(s) Significance; 15 Error; 10-14 Reserved; 9 Busy; 8 Done; 0-7 Error code if bit 15=1; Predefined BDOS error codes are:; ; 0 Write protect violation; 1 Unknown unit; 2 Drive not ready; 3 Unknown command; 4 CRC error; 5 Bad drive request structure length; 6 Seek error; 7 Unknown media; 8 Sector not found; 9 Printer out of paper; 10 Write fault; 11 Read fault; 12 General failure ; 13-14 Reserved; 15 Invalid disk change (MS-DOS 3.x) page; Device Driver "Strategy Routine"; Each time a request is made for this device, the BDOS; first calls "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 the BDOS.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 BDOSStrat endp page; Device Driver "Interrupt Routine"; This entry point is called by the BDOS 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 any necessary return information into the Request Header,; then transfers to Error or Exit to set the Return Status code.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] ; ES:DI = Request Header ; get BX = Command Code mov bl,es:[di.Command] xor bh,bh cmp bx,Max_Cmd ; make sure its legal jg Unk_Command ; too big, exit with error code shl bx,1 ; form index to Dispatch table ; and branch to driver routine jmp word ptr [bx+Dispatch] page; General collection of exit points for the driver routines.Unk_Command: ; Come here if Command Code too big. mov al,3 ; Sets "Unknown Command" error ; code and "Done" bit.Error: ; Transfer here with AL = error code. mov ah,81h ; Sets "Error" and "Done" bits. jmp ExitDone: mov ah,1 ; Come here if I/O complete and ; no error, sets "Done" bit only.Exit: ; General purpose exit point. ; Transfer here with AX = ; Return Status word to be ; placed into Request Header. lds bx,cs:[RH_Ptr] ; set status mov ds:[bx.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 BDOS page; Function 1 Media Check; Block devices only. Should be a NOP for character devices.;; This routine is called first by BDOS for a block device transfer,; passing current media descriptor byte at Request Header + ;; Media Check routine sets status word and in addition passes back ; return byte at Request Header + 14 as follows:; -1 Media has been changed; 0 Don't know if media changed; 1 Media has not been changed;; If driver can return 1 or -1, performance is improved because; MS-DOS does not need to reread the FAT for each directory access.Media_Chk: jmp Done page;; Function 2 Build BIOS Parameter Block; ; Block devices only. Should be a NOP for character devices.;; This routine is called by MS-DOS when Media-Changed code is; returned by Media Check routine, or if Not Sure code is returned; and there are no dirty buffers.; ; Build BPB call receives pointer to one-sector buffer in Address; Field of Request Header (offset 14). If "Non-IBM-Format" bit ; in attribute word is zero, the buffer contains the first sector; of the FAT including the media identification byte and should not ; be altered by the driver. If the "Non-IBM-Format" bit is set, ; the buffer may be used as scratch space.;; The Build BPB routine sets status and returns a DWORD pointer to ; the new Bios Parameter Block at Request Header + 18.;Build_Bpb: jmp Done page;; Function 3 I/O Control Read ; ; Only called if IOCTL bit set in Device Header Attribute word.;; Called with:;; Request Header + 13 BYTE Media descriptor byte from DPB; Request Header + 14 DWORD Transfer address; Request Header + 18 WORD byte/sector count; Request Header + 20 WORD starting sector no. (block dev.);; Returns the Return Status word set appropriately, and; Request Header + 18 WORD actual bytes or sectors transferred; ; No error check is performed on IOCTL I/O calls.Ioctl_Inp: jmp Done page;; Function 4 Read from Device;; Called with;; Request Header + 13 BYTE Media descriptor byte from DPB; Request Header + 14 DWORD Transfer address; Request Header + 18 WORD byte/sector count; Request Header + 20 WORD starting sector no. (block dev.);; Returns the Return Status word set appropriately, and; Request Header + 18 WORD actual bytes or sectors transferredInput: jmp Done page;; Function 5 Non-destructive Read from Device; ; Character devices only.;; If Input Status request returns Busy bit=0 (characters ; waiting), ; the next character that would be read is returned ; at Request Header + 13. This character is not removed from; the Input Buffer. This basically provides the capability to ; "look-ahead" by one character. Nd_Input: jmp Done page;; Function 6 Input Status; ; Character devices only.;; Sets the Returned Status word:; Done bit = 1; Busy bit = 1 read request would go to physical device; = 0 characters already in device buffer, read request; would return quickly.;; MS-DOS assumes all character devices have type-ahead buffer.; If device does not have type-ahead buffer, should always; return Busy bit=0 so MS-DOS will not hang.Inp_Stat: jmp Done page;; Function 7 Flush Input Buffers; ; Character devices only.;; Terminate all pending requests, i.e. the Input buffer is; emptied.Inp_Flush: jmp Done page;; Function 8 Write to Device; ; Called with;; Request Header + 13 BYTE Media descriptor byte from DPB; Request Header + 14 DWORD Transfer address; Request Header + 18 WORD byte/sector count; Request Header + 20 WORD starting sector no. (block dev.);; Returns the Return Status word set appropriately, and; Request Header + 18 WORD actual bytes or sectors transferredOutput: jmp Done page;; Function 9 Write with Verify to Device; ; Called with;; Request Header + 13 BYTE Media descriptor byte from DPB; Request Header + 14 DWORD Transfer address; Request Header + 18 WORD byte/sector count; Request Header + 20 WORD starting sector no. (block dev.);; Returns the Return Status word set appropriately, and; Request Header + 18 WORD actual bytes or sectors transferredOutp_Vfy: jmp Done page;; Function 10 Output Status;; Character devices only.;; Sets the Returned Status word:; Done bit = 1; Busy bit = 1 write request would wait for completion of; current request; = 0 device idle, write request would start immediately.;Outp_Stat: jmp Done page;; Function 11 Flush Output Buffers; ; Character devices only.;; Terminate pending requests. The output buffer, if any,; is emptied.Outp_Flush: jmp Done page;; Function 12 I/O Control Write ; ; Only called if IOCTL bit in Device Header Attribute word is set.;; Called with;; Request Header + 13 BYTE Media descriptor byte from DPB; Request Header + 14 DWORD Transfer address; Request Header + 18 WORD byte/sector count; Request Header + 20 WORD starting sector no. (block dev.);; Returns the Return Status word set appropriately, and; Request Header + 18 WORD actual bytes or sectors transferred;; No error check is performed on IOCTL calls.Ioctl_Outp: jmp Done page;; Function 13 Device Open;; MS-DOS version 3.0 and above only.; Only called if OPEN/CLOSE/RM bit set in Attribute word.; May be used to manage local buffering. Reference count; is incremented keeping track of number of open files on; the device. On character devices can be used to send; device initialization string, which can be set by IOCTL ; Write. Note that CON AUX and PRN devices are always open.;; Returns the Return Status word set to "Done".;Dev_Open: jmp Done page;; Function 14 Device Close;; MS-DOS version 3.0 and above only.; Only called if OPEN/CLOSE/RM bit set in Attribute word.; May be used to manage local buffering. Reference count; is decremented keeping track of number of open files on; the device; when count reaches zero all files have been closed ; and the driver should flush buffers as user may change disks.; On character devices can be used to send device post-I/O; string such as a form feed, which can be set by IOCTL ; Write. Note that CON AUX and PRN devices are never closed.;; Returns the Return Status word set to "Done".;Dev_Close: jmp Done page;; Function 15 Removeable Media;; MS-DOS version 3.0 and above only.; Only called if OPEN/CLOSE/RM bit set in Attribute word; and device type is block.;; Returns the Return Status word set to "Done" and ; Busy bit = 1 if media is non-removable. ; = 0 if media is removable.;Rem_Media: jmp Done 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 the BDOS.; 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. ;; Called with:;; Request Header + 18 DWORD pointer to the character after the "="; on the CONFIG.SYS line that loaded ; driver; this information is read only.; 22 BYTE drive letter for first unit of a ; block driver (0=A 1=B etc); (MS-DOS 3.x only) ;; Returns:; ; Request Header + 13 BYTE Number of units (block devices only); + 14 DWORD address of first free memory above driver; + 18 DWORD BPB pointer array (block devices only) ;Init: ; Function 0 ; initialize device driver push es ; push Request Header addr push di mov ah,9 ; print sign-on message mov dx,offset Ident 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 jmp DoneIntr endpDriver endpcode ends end  
|