Page 60,132


;****************************************************************
;*								*
;*	EMILY is a character-oriented device driver.		*
;*								*
;*	All block-oriented functions in EMILY simply set the	*
;*	DONE status flag and exit.				*
;*								*
;*	The basic request-header structure used in all		*
;*	request-headers is called the Request_Header_Preamble.	*
;*	All request-headers begin with a 13-byte area		*
;*	corresponding to the Request_Header_Preamble.		*
;*								*
;*	Assembled using Microsoft MASM 1.25.			*
;*								*
;****************************************************************



;--------------------------------------------------------------------
;
; Request-header structure type 1
;
;    Used by services 6, 7, 10, and 11
;
;--------------------------------------------------------------------
Request_Header_Preamble    STRUC

Header_Length		   DB (?)	   ; Length in bytes
Unit_Code		   DB (?)	   ; Unit code
Command_Code		   DB (?)	   ; Command code
Status_Code		   DW (?)	   ; Status of the request
PCDOS_Reserved		   DB 8 Dup (?)    ; Reserved area for PC DOS

Request_Header_Preamble    Ends
;--------------------------------------------------------------------



;--------------------------------------------------------------------
;
; Request-header structure type 2
;
;    Used by service 0	(Init)
;
;--------------------------------------------------------------------
Request_Header_Init	   STRUC

			   DB  13 dup(?)   ; Area for Request_Header_Preamble

Init_Unit_Count 	   DB (?)	   ; Number of units
Init_Ending_Program_Addr   DD (?)	   ; Stay resident address
Init_Bios_Param_Block_Addr DD (?)	   ; Doesn't apply to char. devices
Init_Byte_Drive_Number	   DB (?)

Request_Header_Init	   Ends
;--------------------------------------------------------------------



;--------------------------------------------------------------------
;
; Request-header structure type 3
;
;    Used by service 1	(Media Check - doesn't apply to char. devices)
;
;--------------------------------------------------------------------
Request_Header_Media	   STRUC

			   DB  13 dup(?)   ; Area for Request_Header_Preamble

Media_Media_Descriptor	   DB (?)	   ; Define media type
Media_Byte_return	   DB (?)	   ; Indicate media status
Media_Vol_Id_Addr	   DD (?)	   ; Previous Vol ID pointer

Request_Header_Media	   Ends
;--------------------------------------------------------------------



;--------------------------------------------------------------------
;
; Request-header structure type 4
;
;    Used by service 2	(BUILD BPB - doesn't apply to char. devices)
;
;--------------------------------------------------------------------
Request_Header_BPB	   STRUC

			   DB  13 dup(?)   ; Area for Request_Header_Preamble

BPB_Media_Descriptor	   DB (?)	   ; Define media type
BPB_Data_Transfer_Address  DD (?)	   ; I/O buffer
BPB_Bios_Param_Block_Addr  DD (?)	   ; Pointer to BPB

Request_Header_BPB	   Ends
;--------------------------------------------------------------------



;--------------------------------------------------------------------
;
; Request-header structure type 5
;
;    Used by service 3, 4, 8, 9, and 12 (Input or Output)
;
;--------------------------------------------------------------------
Request_Header_IO	   STRUC

			   DB  13 dup(?)   ; Area for Request_Header_Preamble

IO_Media_Descriptor	   DB (?)	   ; Define media type
IO_Data_Transfer_Address   DD (?)	   ; I/O buffer
IO_Byte_Counter 	   DW (?)	   ; Number of bytes transferred
IO_Starting_Sector	   DW (?)	   ; Not used in char. devices
IO_Vol_Id_Addr		   DD (?)	   ; Pointer to Vol ID

Request_Header_IO	   Ends
;--------------------------------------------------------------------



;--------------------------------------------------------------------
;
; Request-header structure type 6
;
;    Used by service 5	(Non Destructive Input No Wait)
;
;--------------------------------------------------------------------
Request_Header_Non_Dest    STRUC

			   DB  13 dup(?)   ; Area for Request_Header_Preamble
Non_Dest_Read_Byte	   DB (?)	   ; Byte read from device

Request_Header_Non_Dest    Ends
;--------------------------------------------------------------------





Page
;****************************************************************
;*								*
;*	Beginning of EMILY					*
;*								*
;****************************************************************

CSEG	Segment Para Public 'CODE'
	Assume CS:CSEG,DS:Nothing,ES:Nothing,SS:Nothing
;
;	The source code begins here
;
		Org  0000H
Device_Driver	Proc Far
;
;	Here is the device header
;
Next_Device	DD	-1	; Setting this field to -1
				; . indicates that there is
				; . only one driver in this
				; . device-driver program.

Attribute	DW	0C000H	; Turn bits 14 and 15 on, all
				; . others off. Bit 15 = 1 for
				; . a character device. Bit 14 = 1
				; . if device supports the IOCTL
				; . function.

Strategy	DW Offset Strategy_Routine
				; Tells PC-DOS the offset address
				; . of the Strategy routine.
				; . The segment address is assumed
				; . to be the value in the CS
				; . register.


Interrupt	DW Offset Interrupt_Routine
				; Tells PC-DOS the offset address
				; . of the Interrupt routine.
				; . Like the Strategy routine, the
				; . segment address is assumed to
				; . be in the CS register.


Device_Name	DB "EMILY   "   ; The name of this particular device
				; . driver is EMILY. Name must be
				; . 8 characters, so 3 blanks added.


Request_Header		Label Word

Request_Header_Offset	DW (?)	; Here is where the pointer
Request_Header_Segment	DW (?)	; . is defined


;
; Here is the jump table of command modules
;
Device_Functions	Label Word

		DW Offset Initialize_Driver_Command	;command-code = 0
		DW Offset Media_Check_Command		;command-code = 1
		DW Offset Build_BPB_Command		;command-code = 2
		DW Offset IOCTL_Input_Command		;command-code = 3
		DW Offset Read_Input_Command		;command-code = 4
		DW Offset Non_Destruct_Input_Command	;command-code = 5
		DW Offset Input_Status_Command		;command-code = 6
		DW Offset Input_Flush_Command		;command-code = 7
		DW Offset Write_Output_Command		;command-code = 8
		DW Offset Write_Verify_Command		;command-code = 9
		DW Offset Output_Status_Command 	;command-code = 10
		DW Offset Output_Flush_Command		;command-code = 11
		DW Offset IOCTL_Output_Command		;command-code = 12
		DW Offset Device_Open_Command		;command-code = 13
		DW Offset Device_Close_Command		;command-code = 14
		DW Offset Removable_Media_Command	;command-code = 15


;
; Here is the strategy routine
;
Strategy_Routine Proc Far

	Mov	Word Ptr CS:Request_Header_Offset,BX

	Mov	Word Ptr CS:Request_Header_Segment,ES

	Ret

Strategy_Routine Endp


;
; Here is the interrupt routine
;
Interrupt_Routine Proc Far

INRT01:
	Push	AX			; Save the registers
	Push	BX			; . and flags
	Push	CX			; .
	Push	DX			; .
	Push	SI			; .
	Push	DI			; .
	Push	DS			; .
	Push	ES			; .
	Pushf				; ..End
INRT02:
	Push	CS			; Set DS equal to CS
	Pop	DS			; ..End

	Mov	BX,Word Ptr CS:Request_Header_Offset
	Mov	ES,Word Ptr CS:Request_Header_Segment
					; Get the address of the
					; . request header into
					; . ES:[BX]

	Mov	Word Ptr ES:[BX].Status_Code,0000H
					; Clear the status word

	Mov	DX,0000H		; Calculate the index into
	Mov	DL,Byte Ptr ES:[BX].Command_Code
	Shl	DX,1			; . the jump table and put
	Mov	DI,DX			; . it into DI

	Cmp	DI,0024D		; Compare for an invalid
	Jbe	INRT03			; command
;
; Here is the error routine for an illegal command
;
	Or	Byte Ptr ES:[BX].Status_Code+1,80H
					; Set the error bit
	Mov	Byte Ptr ES:[BX].Status_Code,03H
					; Set the error byte
	Jmp	Short INRT90

INRT03:
	Mov	SI,Word Ptr CS:Device_Functions[DI]
					; Get the offset address
					; . of the appropriate
					; . command

	Call	SI			; This is a near call to
					; . the command
INRT90:
	Popf				; Restore the registers
	Pop	ES			; . and flags
	Pop	DS			; .
	Pop	DI			; .
	Pop	SI			; .
	Pop	DX			; .
	Pop	CX			; .
	Pop	BX			; .
	Pop	AX			; ..End

	Ret

Interrupt_Routine Endp

;
; Here is the initialization command
;
Initialize_Driver_Command Proc Near

	Mov	AX,Offset End_Of_the_Program

	Mov	Word Ptr ES:[BX].Init_Ending_Program_Addr,AX

	Mov	Word Ptr ES:[BX+2].Init_Ending_Program_Addr,CS

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Initialize_Driver_Command Endp

;
; Here is the media check command
;
Media_Check_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Media_Check_Command Endp

;
; Here is the construct Bios Parameter Block command
;
Build_BPB_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Build_BPB_Command Endp

;
; Here is the IOCTL input command
;
IOCTL_Input_Command Proc Near

	Lds	DI,ES:[BX].IO_Data_Transfer_Address

	Mov	Byte Ptr DS:[DI],'E'

	Mov	Word Ptr ES:[BX].IO_Byte_Counter,0001H

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

IOCTL_Input_Command Endp

;
; Here is the read input command
;
Read_Input_Command Proc Near

	Mov	Word Ptr ES:[BX].IO_Byte_Counter,0000H

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Read_Input_Command Endp

;
; Here is the non-destructive input command
;
Non_Destruct_Input_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0200H
					; Set the busy bit

	Mov	Word Ptr ES:[BX].Non_Dest_Read_Byte,0000H

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Non_Destruct_Input_Command Endp

;
; Here is the input status command
;
Input_Status_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Input_Status_Command Endp


;
; Here is the flush input command
;
Input_Flush_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Input_Flush_Command Endp

;
; Here is the write output command
;
Write_Output_Command Proc Near

	Mov	Word Ptr ES:[BX].IO_Byte_Counter,0000H

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Write_Output_Command Endp


;
; Here is the write verify command
;
Write_Verify_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Write_Verify_Command Endp


;
; Here is the output status command
;
Output_Status_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Output_Status_Command Endp


;
; Here is the flush the output command
;
Output_Flush_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Output_Flush_Command Endp


;
; Here is the IOCTL output command
;
IOCTL_Output_Command Proc Near

	Mov	Word Ptr ES:[BX].IO_Byte_Counter,0000H

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

IOCTL_Output_Command Endp

;
; Here is the device open command
;
Device_Open_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Device_Open_Command Endp


;
; Here is the device close command
;
Device_Close_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Device_Close_Command Endp


;
; Here is the removable media command
;
Removable_Media_Command Proc Near

	Or	Word Ptr ES:[BX].Status_Code,0100H
					; Set the finished bit

	Ret

Removable_Media_Command Endp


Device_Driver Endp


End_of_the_Program	Equ $		; The assembler sets the
					; . variable to the last
					; . valid address in the
					; . program

CSEG	Ends
	End	Device_Driver
