TITLE PREFERS.SYS - Sample Device Driver PAGE 60,132 ;=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=* ; P R E F E R S . S Y S ; By George W. Seaton -- Assemble with Borland's TASM ; ; This module is an example of a simple "character" device driver. ; It does not "drive" any particular device; instead, it sets up ; certain BIOS parameters for the video and keyboard, according ; to the user's personal preferences. For the author's AT-clone ; with an EGA color video, these preferences include: ; ; - Turning off the NumLock state. ; - Setting the EGA video to 43-line mode. ; - Turning OFF the video blink bit. ; ; After its initial installation, users can use the driver (i.e., ; by writing to the device) to toggle these parameters. ;================================================================ ; Assembler setup commands ;================================================================ CSEG Segment byte public "CODE" Assume CS:CSEG,DS:CSEG,ES:CSEG Org 00H ;<============ NOTE! PREFERS: ;================================================================ ; D R I V E R H E A D E R B L O C K ; ; Bytes 0000h-0011h of the driver M-U-S-T be set up as follows: ;================================================================ DW 0FFFFh ;+0: Offset of next Device (if any) DW 0FFFFh ;+2: Segment of next Device (if any) ;---------------------------------------------------------------- DW 8000h ;+4: Device Attribute Word ; (Bit 15 SET for "Character" device) ;---------------------------------------------------------------- DW Offset STRAT ;+6: Offset of "Strategy" routine DW Offset INTRPT ;+8: Offset of "Interrupt" routine ;---------------------------------------------------------------- DB 'I_PREFER' ;+0Ah..+11h = Name of Driver ; (padded with spaces, as required) ;================================================================ PAGE ;================================================================ ; S T R A T E G Y R O U T I N E ; ; Called by DOS to save the pointer (in ES:BX) to the Device ; Driver Request Header. ;---------------------------------------------------------------- STRAT: MOV CS:[HDROFS],BX ;Save offset of Request Header MOV CS:[HDRSEG],ES ;Save segment of Request Header RETF ;Return to DOS ;================================================================ ; Local Data Storage... ;---------------------------------------------------------------- HEADER LABEL DWORD ;Allow for DD reference HDROFS DW 0000 ;Seqment storage HDRSEG DW 0000 ;Offset storage TOGGLE DB 01 ;Storage for current toggle states ; 01 = EGA Blink Bit ON ;================================================================ PAGE ;================================================================ ; I N T E R R U P T P R O C E D U R E ; ; Called by DOS to process a driver request, as defined in the ; Request Header. The Request Header is found at the address ; previously passed to the Strategy Routine. ; ; Request Header format: ; +00 = NUMB Number of bytes in Request Header (byte) ; +01 = UNIT Unit Number of this request (byte) (BLOCK) ; +02 = CMMD Request Command Code (byte) ; +03 = STAT Returned Status (word) ; +05 = RESRVED Reserved by DOS (8 bytes) ; +0D = MEDIA Media Descriptor (byte) ; +0E = ADDR Data Transfer Address (word:word) ; +12 = COUNT Byte or sector count (word) ; +14 = SECT Starting sector value (BLOCK DEVICE) ;================================================================ ; I _ P R E F E R I N T E R R U P T L O G I C ;---------------------------------------------------------------- INTRPT: PUSH AX ;Save the entry registers... PUSH BX PUSH CX PUSH DX PUSH ES PUSH DI PUSH SI ;---------------------------------------------------------------- ; Retrieve the address of the Request Header and get the CMMD. ;---------------------------------------------------------------- PUSH CS POP DS LES BX,CS:[HEADER] ;ES:BX = [HDRSEG:HDROFS] MOV AL,ES:[BX+02] ;CMMD = HDRSEG:[HDROFS+2] ;---------------------------------------------------------------- ; If CMMD IS "Write" or "Write with Verify", go to the "WRITE" ; logic. ;---------------------------------------------------------------- CMP AL,08h ;If CMMD = "WRITE" then... JZ WRITE ;...WRITE CMP AL,09h ;If CMMD = "WRITEV" then... JZ WRITE ;...WRITE ;---------------------------------------------------------------- ; If CMMD IS "INIT," go to the Initialization logic. ;---------------------------------------------------------------- CMP AL,00 ;If CMMD = "INIT" then... JMP INIT ;...INITIALIZE ;---------------------------------------------------------------- PAGE ;---------------------------------------------------------------- ; For any other CMMD, return an error code in the STATUS ; parameter and return to DOS. ;---------------------------------------------------------------- BADRTN: MOV Word Ptr ES:[BX+03],8103h JMP RETURN ;Return NOP ;---------------------------------------------------------------- ; Return through here when done ;---------------------------------------------------------------- GUDRTN: MOV Word Ptr ES:[BX+03],0100h ;---------------------------------------------------------------- ; Restore registers and return to DOS ;---------------------------------------------------------------- RETURN: POP SI ;Restore the entry registers... POP DI POP ES POP DX POP CX POP BX POP AX RETF ;Return (Far) ;================================================================ PAGE ;================================================================ ; W R I T E P R O C E D U R E ; ; Retrieve the "output message" for the driver. This should be ; one character, where... ; ; ... N or n toggles the NumLock state (Initially OFF) ; ... L or l toggles the EGA 43-line mode (Initially ON) ; ... B or b toggles the EGA video blink state (Initially OFF) ;================================================================ WRITE: LDS SI,ES:[BX+0Eh] ;DS:SI = ADDR LODSB ;AL = DS:[SI] = [ADDR] = "x" PUSH CS ;Move CS... POP DS ;...into DS ;---------------------------------------------------------------- ; For [N,L,B]: Go to the appropriate "toggle" logic. ; (Otherwise, ignore the character.) ;---------------------------------------------------------------- AND AL,5Fh ;Make letter upper case CMP AL,4Eh ;If (AL = 'N') then... JNE NotNum CALL NUMLCK ;...CALL NUMLCK JMP GUDRTN NotNum: CMP AL,4Ch ;If (AL = 'L') then... JNE NotLine CALL EGA43 ;...CALL EGA43 JMP GUDRTN NotLine: CMP AL,42h ;If (AL = 'B') then... JNE BADRTN CALL BLINK ;...CALL BLINK JMP GUDRTN ;================================================================ PAGE ;================================================================ ; NUMLCK: Toggles the NumLock State for the keyboard. ;---------------------------------------------------------------- NUMLCK PROC NEAR PUSH AX ;Save the... PUSH ES ;...entry registers MOV AX,0040h ;Set DS to... MOV ES,AX ;...0040 (BIOS segment) MOV AL,Byte Ptr ES:[0017h] ;Get the keyboard state TEST AL,20h ;Test the NumLock bit JNZ NumOFF ; NumON: OR AL,20h ;If OFF, turn it ON JMP NumSet NumOFF: AND AL,0DFh ;If ON, turn it OFF NumSet: MOV Byte Ptr ES:[0017h],AL ;Put it back POP ES ;Restore the... POP AX ;...entry registers RET ;Return to the caller NUMLCK ENDP ;================================================================ ; BLINK: Toggles the EGA/VGA Blink Bit ;---------------------------------------------------------------- BLINK PROC NEAR PUSH AX ;Save the... PUSH BX PUSH DS ;...entry registers PUSH CS POP DS MOV AL,[TOGGLE] ;Get the current toggle word TEST AL,01 ;Test the Blink state bit JNZ BlkOff BlkOn: MOV BL,01 ;Turn ON if currently OFF OR AL,01 JMP BlkSet BlkOff: MOV BL,00 ;Turn OFF if currently ON AND AL,0FEh BlkSet: MOV [TOGGLE],AL MOV AX,1003h INT 10h POP DS ;Restore the... POP BX POP AX ;...entry registers RET BLINK ENDP ;================================================================ PAGE ;================================================================ ; EGA43: Toggles the 43-line mode for the EGA video. ; (Also, sets up a block cursor, "fixes" the EGA cursor ; emulation, and selects the EGA BIOS "Print Screen" ;---------------------------------------------------------------- EGA43 PROC NEAR PUSH AX ;Save the... PUSH BX PUSH CX PUSH ES ;...entry registers ;---------------------------------------------------------------- ; If the current BIOS screen lines count (less one) at 0040:0084 ; is NOT 42, then go set up the 43-line mode. Otherwise, restore ; the 25-line mode ;---------------------------------------------------------------- MOV AX,0040h ;Set DS to... MOV ES,AX ;...0040 (BIOS segment) MOV AL,Byte Ptr ES:[0084h] ;IF (0040:0084 <> 42) then... CMP AL,42 JNE GoTo43 ;...GoTo43 ;---------------------------------------------------------------- ; Select the 8x14 font and adjust the screen lines (to 25). ;---------------------------------------------------------------- GoTo25: MOV AX,1111h MOV BL,00 INT 10h ;---------------------------------------------------------------- ; Turn the EGA cursor emulation logic back on and set up a block ; cursor. Then return. ;---------------------------------------------------------------- AND Byte Ptr ES:[0087h],0FEh JMP SetCur ;---------------------------------------------------------------- ; Select the 8x8 character font and adjust the screen lines ;---------------------------------------------------------------- GoTo43: MOV AX,1112h ;Load the 8x8 font & recalculate MOV BL,00 ;RAM block 0 INT 10h ;BIOS Video Service ;---------------------------------------------------------------- ; Select the alternate (EGA BIOS) Print Screen function ;---------------------------------------------------------------- MOV BL,20h MOV AH,12h INT 10h ;---------------------------------------------------------------- ; Turn off the buggy EGA cursor emulation and set up a block ; cursor. Then return. ;---------------------------------------------------------------- OR Byte Ptr ES:[0087h],01 SetCur: MOV CX,0007h ;CH = Scan top; CL = Scan bottom MOV AH,01 ;"Set Cursor Size" INT 10h POP ES ;Restore the... POP CX POP BX POP AX ;...entry registers RET EGA43 ENDP ;================================================================ RUNSIZ EQU $-PREFERS DB (0100H-RUNSIZ) DUP(00) ;================================================================ PAGE ;================================================================ ; I N I T I A L I Z A T I O N L O G I C ;================================================================ ; This logic is invoked when DOS installs the driver. (CMMD = 0). ; The initialization steps include: ; ; 1. Reseting the keyboard NumLock state. ; 2. Setting the EGA video into 43-line mode ; 3. Turning off the EGA blink bit ; 4. Displaying the "I'm here!" message on the video screen. ; ; When done, the logic tells DOS where the "expendable" part of ; the driver (the initialization logic itsef) begins. DOS will ; then release the memory AFTER that address for its own use. ;---------------------------------------------------------------- INIT LABEL NEAR PUSH AX ;Save registers PUSH BX ; PUSH CX ; PUSH DX ; PUSH ES ; ;---------------------------------------------------------------- ; Call the mainline procedures to set the initial preferences. ;---------------------------------------------------------------- CALL NUMLCK ;Turn OFF the NumLock State CALL EGA43 ;Turn ON the EGA 43-line mode CALL BLINK ;Turn OFF the EGA Blink bit ;---------------------------------------------------------------- ; Announce the installation of the driver. ;---------------------------------------------------------------- LEA DX,IMHERE ;DX = Offset(IMHERE) MOV AH,09h ;"Display string" INT 21h ;DOS service ;---------------------------------------------------------------- PAGE ;---------------------------------------------------------------- ; Release the initialization logic and return. ;---------------------------------------------------------------- POP ES ;Restore the key entry registers POP DX ; POP CX ; POP BX ; LEA AX,INIT ;AX = Offset(INIT) MOV Word Ptr ES:[BX+0Eh],AX ;"ADDR" = AX MOV Word Ptr ES:[BX+10h],CS ;"ADDR+2" = CS POP AX ;Restore AX JMP GUDRTN ;Return ;================================================================ IMHERE LABEL NEAR DB 0Dh,0Ah,'PREFERS.SYS Preferences Driver Installed.' DB 0Dh,0Ah DB 'Write N, L, or B to I_Prefer to change',0Dh,0Ah,'$' CSEG ENDS END PREFERS ;=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*