This is the past DOS era of the compilation of source code, although has passed, but for the study of the assembly is still helpful, assembly language is just a basic programmer language, most people can grasp, not necessarily in-depth research.
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 the "done" status.
;
; Ray Duncan
; Laboratory Microsystems Inc.
; April 1985
Code segment Public ' CODE '
Driver proc Far
Assume Cs:code,ds:code,es:code
ORG 0
Max_cmd equ 15; MS-DOS command code maximum
; This is for MS-DOS 3.x
; And 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; attribute Word
; bit 15=1 for character devices
DW Strat;d evice "strategy" entry point
DW Intr;d evice "Interrupt" entry point
DB ' DRIVER '; char device name, 8 char, or
; If block device, No. of units
; In the followed by
; 7 don ' t care bytes
; Interpretation of attributes Word:
;
; Bit significance
;
; =1 for character drivers
; =1 If driver can handle IOCTL
; =1 if block device & NON-IBM format
; 12 0
; One 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-by driver
;
RH_PTR DD? ; Pointer to request header
; Passed to Strat by BDOs
Ident 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; Ten = return current output status
DW Outp_flush; one = Flush output buffers
DW IOCTL_OUTP; = I/O control output
DW Dev_open; Device open (MS-DOS 3.x)
DW Dev_close; = Device Close (MS-DOS 3.x)
DW Rem_media; MB = removeable Media (MS-DOS 3.x)
Page
;
; MS-DOS REQUEST Header structure definition
;
; The 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
Reserve DB 8 dup (?) ; Reserved area
; End of "Static" portion
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
;
; Status Word is interpreted as follows:
;
; Bit (s) significance
; 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
; Ten Write fault
; One Read fault
; General failure
; 13-14 Reserved
; Invalid Disk Change (MS-DOS 3.x)
Page
; Device Driver "strategy routine"
; Each time a request is made to this device, the BDOs
; The 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 the Request Header
mov word ptr cs:[rh_ptr],bx
mov word ptr cs:[rh_ptr+2],es
RET; Back to BDOs
Strat ENDP
Page
; Device Driver "Interrupt routine"
; This entry's called by the BDOs immediately
; The call to the "strategy routine", which saved the long
; Address to 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.
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 Exit
Done: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 IS
; Placed into the 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 is a NOP for character devices.
;
; This routine is called the 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 + 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 is a NOP for character devices.
;
; This routine was called by MS-DOS when media-changed the code is
; Returned by Media Check routine, or if not sure the code is returned
; And there are no dirty buffers.
;
; Build BPB call receives pointer to One-sector buffer in
; Field of Request Header (offset 14). If "Non-ibm-format" bit
; In attribute word is zero, the buffer contains the 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 is 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 the set in Device Header is word.
;
; Called with:
;
; Request Header + byte Media descriptor BYTE from DPB
; Request Header + DWORD Transfer Address
; Request Header + WORD byte/sector count
; Request Header + WORD starting Sector No. (Block Dev.)
;
; Returns The return Status Word set appropriately, and
; Request Header + 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 + byte Media descriptor BYTE from DPB
; Request Header + DWORD Transfer Address
; Request Header + WORD byte/sector count
; Request Header + WORD starting Sector No. (Block Dev.)
;
; Returns The return Status Word set appropriately, and
; Request Header + WORD actual bytes or sectors transferred
Input:
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 was read is returned
; At Request Header + 13. This character isn't removed from
; The Input Buffer. This is 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 would 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 + byte Media descriptor BYTE from DPB
; Request Header + DWORD Transfer Address
; Request Header + WORD byte/sector count
; Request Header + WORD starting Sector No. (Block Dev.)
;
; Returns The return Status Word set appropriately, and
; Request Header + WORD actual bytes or sectors transferred
Output:
JMP Done
Page
;
; Function 9 Write with Verify to Device
;
; Called with
;
; Request Header + byte Media descriptor BYTE from DPB
; Request Header + DWORD Transfer Address
; Request Header + WORD byte/sector count
; Request Header + WORD starting Sector No. (Block Dev.)
;
; Returns The return Status Word set appropriately, and
; Request Header + WORD actual bytes or sectors transferred
Outp_vfy:
JMP Done
Page
;
; Function Ten 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 One Flush Output buffers
;
; Character devices only.
;
; Terminate pending requests. The output buffer, if any,
; is emptied.
Outp_flush:
JMP Done
Page
;
; Function I/O control Write
;
; Only called if IOCTL the bit in Device Header is the word is set.
;
; Called with
;
; Request Header + byte Media descriptor BYTE from DPB
; Request Header + DWORD Transfer Address
; Request Header + WORD byte/sector count
; Request Header + WORD starting Sector No. (Block Dev.)
;
; Returns The return Status Word set appropriately, and
; Request Header + WORD actual bytes or sectors transferred
;
; No error check is performed on IOCTL calls.
IOCTL_OUTP:
JMP Done
Page
;
; Function Device Open
;
; MS-DOS version 3.0 and above only.
; Only called if OPEN/CLOSE/RM bit sets in Attribute word.
; May is used to manage the local buffering. Reference Count
; Are incremented keeping track of number of open files on
; The device. On character devices can is used to send
; Device initialization string, which can is set by IOCTL
; Write. Note that CON AUX and PRN devices are always open.
;
; Returns The return Status of Word set to ' done '.
;
Dev_open:
JMP Done
Page
;
; Function Device Close
;
; MS-DOS version 3.0 and above only.
; Only called if OPEN/CLOSE/RM bit sets in Attribute word.
; May is used to manage the local buffering. Reference Count
; are 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 is used to send device post-i/o
; String such as a form feed, which can is set by IOCTL
; Write. Note that CON AUX and PRN devices are never closed.
;
; Returns The return Status of Word set to ' done '.
;
Dev_close:
JMP Done
Page
;
; Function 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 of 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 the driver is loaded. It is responsible for
; Initializing the hardware, setting up any necessary
; Interrupt vectors, and it must return to the address
; Of the the memory after the driver to the BDOs.
; If It is a blocks device driver, Init must also return the
; Address to 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 is called by the
; initialization function.
;
; In this example, INIT returns it own address to the DOS as
; The start of free memory after the driver and so this memory
; occupied by INIT would be reclaimed after the it is finished
; With its work.
;
; Called with:
;
; Request Header + DWORD Pointer to the character after the "="
; On the CONFIG. SYS line that loaded
; Driver This information are read only.
; BYTE Drive letter for a
; Block Driver (0=a 1=b etc)
; (MS-DOS 3.x only)
;
; Returns:
;
; Request Header + BYTE number of units (block devices only)
; + DWORD Address of the memory above driver
; + 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 usable memory addr.
mov word ptr es:[di. Address],offset Init
mov word ptr es:[di. Address+2],cs
JMP Done
Intr ENDP
Driver ENDP
Code ends
End