ioctl.asm

来自「Dos6.0」· 汇编 代码 · 共 1,204 行 · 第 1/2 页

ASM
1,204
字号
PAGE	,132
TITLE	ANSI Generic IOCTL Code

;******************************************************************************

;  Change Log:

;    Date    Who   #			  Description
;  --------  ---  ---  ------------------------------------------------------

;  06/29/90  MKS  C04  Bug#1150.  Video 7 Fastwrite VGA has problems if a
;		       Hercules mono board is the active display.

;******************************************************************************

;****************** START OF SPECIFICATIONS **************************

;  MODULE NAME: IOCTL.ASM

;  DESCRIPTIVE NAME: PERFORM THE GENERIC IOCTL CALL IN ANSI.SYS

;  FUNCTION: THE GENERIC DEVICE IOCTL IS USED TO SET AND GET THE
;	     MODE OF THE DISPLAY DEVICE ACCORDING TO PARAMETERS PASSED
;	     IN A BUFFER. ADDITIONALLY, THE CALL CAN TOGGLE THE
;	     USE OF THE INTENSITY BIT, AND CAN LOAD THE 8X8 CHARACTER
;	     SET, EFFECTIVELY GIVING MORE LINES PER SCREEN. THE
;	     AVAILABILITY OF THIS FUNCTION VARIES STRONGLY WITH HARDWARE
;	     ATTACHED.

;  ENTRY POINT: GENERIC_IOCTL

;  INPUT: LOCATION OF REQUEST PACKET STORED DURING STRATEGY CALL.

;  AT EXIT:
;     NORMAL: CARRY CLEAR - DEVICE CHARACTERISTICS SET

;     ERROR: CARRY SET - ERROR CODE IN AX.
;	     AX = 1  - INVALID FUNCTION. EXTENDED ERROR = 20
;	     AX = 10 - UNSUPPORTED FUNCTION ON CURRENT HARDWARE.
;			EXTENDED ERROR = 29
;	     AX = 12 - DISPLAY.SYS DOES NOT HAVE 8X8 RAM CHARACTER SET.
;			EXTENDED ERROR = 31

;  INTERNAL REFERENCES:

;     ROUTINES: GET_IOCTL - PERFORMS THE GET DEVICE CHARACTERISTICS
;		SET_IOCTL - PERFORMS THE SET DEVICE CHARACTERISTICS
;		GET_SEARCH - SEARCHES THE INTERNAL VIDEO TABLE FOR THE
;			     CURRENT MODE MATCH
;		SET_SEARCH - SEARCHES THE INTERNAL VIDEO TABEL FOR THE
;			     CURRENT MODE MATCH
;		SET_CURSOR_EMUL - SETS THE BIT THAT CONTROLS CURSOR EMULATION
;		INT10_COM - INTERRUPT 10H HANDLER TO KEEP CURRENT SCREEN SIZE
;		INT2F_COM - INTERRUPT 2FH INTERFACE TO GENERIC IOCTL
;		MAP_DOWN - PERFORMS CURSOR TYPE MAPPING FOR EGA WITH MONOCHROME
;		SET_VIDEO_MODE - SETS THE VIDEO MODE

;     DATA AREAS: SCAN_LINE_TABLE - HOLDS SCAN LINE INFORMATION FOR PS/2
;		  FUNC_INFO - BUFFER FOR PS/2 FUNCTIONALITY CALL.


;  EXTERNAL REFERENCES:

;     ROUTINES: INT 10H SERVICES

;     DATA AREAS: VIDEO_MODE_TABLE - INTERNAL TABLE FOR CHARACTERISTICS TO MODE
;				     MATCH-UPS

;  NOTES:

;  REVISION HISTORY:

;      Label: "DOS ANSI.SYS Device Driver"
;	      "Version 4.00 (C) Copyright 1988 Microsoft"
;	      "Licensed Material - Program Property of Microsoft"

;****************** END OF SPECIFICATIONS ****************************
;Modification history *********************************************************
; P1350 Codepage switching not working on EGA		   10/10/87 J.K.
; P1626 ANSI does not allow lines=43 with PS2,Monochrome	   10/15/87 J.K.
; p1774 Lines=43 after selecting cp 850 does not work	   10/20/87 J.K.
; p1740 MODE CON LINES command causes problem with PE2 w PS/210/24/87 J.K.
; p2167 Does'nt say EGA in medium resol. cannot do 43 lines  10/30/87 J.K.
; p2236 After esc [=0h, issuing INT10h,AH=fh returns mode=1. 11/3/87  J.K.
; p2305 With ANSI loaded, loading RDTE hangs the system	   11/06/87 J.K.
; P2617 Order dependecy problem with Display.sys		   11/23/87 J.K.
; p2716 HOT key of VITTORIA does not work properly	   12/03/87 J.K.
; d398  /L option for Enforcing the number of lines	   12/17/87 J.K.
; D425 For OS2 compatibiltiy box, /L option status query	   01/14/88 J.K.
; P5699 Moving selecting alternate print screen routine to only when it
; 10/26/88    is needed.  OEM EGA cards don't support the call it, so they
; K. Sayers   couldn't (shift) print screen at all when the alt. routine was
;	      invoked during initialization.
;******************************************************************************

INCLUDE		DEVSYM.INC
INCLUDE		ANSI.INC
INCLUDE		MULT.INC

PUBLIC		GENERIC_IOCTL
PUBLIC		SET_IOCTL
PUBLIC		GET_IOCTL
PUBLIC		SET_SEARCH
PUBLIC		GET_SEARCH
PUBLIC		SET_CURSOR_EMUL
PUBLIC		FUNC_INFO
PUBLIC		MAX_SCANS
PUBLIC		INT10_COM
PUBLIC		SET_MODE_HANDLER
PUBLIC		SET_CURSOR_HANDLER
PUBLIC		ROM_INT10
PUBLIC		INT2F_COM
PUBLIC		INT2F_HANDLER
PUBLIC		ROM_INT2F
PUBLIC		ABORT
PUBLIC		MAP_DOWN
PUBLIC		SET_VIDEO_MODE
PUBLIC		REQ_TXT_LENGTH
PUBLIC		GRAPHICS_FLAG
PUBLIC		DO_ROWS
PUBLIC		Display_Loaded_Before_Me

CODE		SEGMENT  PUBLIC  BYTE
		ASSUME CS:CODE,DS:CODE

EXTRN		PTRSAV:DWORD
EXTRN		NO_OPERATION:NEAR
EXTRN		ERR1:NEAR
EXTRN		VIDEO_MODE_TABLE:BYTE
EXTRN		MAX_VIDEO_TAB_NUM:ABS
EXTRN		HDWR_FLAG:WORD
EXTRN		SCAN_LINES:BYTE
EXTRN		SWITCH_L:Byte			;Defined in ANSI.ASM

IFDEF		JAPAN
EXTRN		row_adj:byte
ENDIF

SCAN_LINE_TABLE	LABEL	BYTE
		SCAN_LINE_STR <200,000000001B,0>	; 200 scan lines
		SCAN_LINE_STR <344,000000010B,1>	; 350 scan lines
		SCAN_LINE_STR <400,000000100B,2>	; 400 scan lines
SCANS_AVAILABLE	EQU	($ - SCAN_LINE_TABLE)/TYPE SCAN_LINE_STR

;This is used when ANSI calls Get_IOCTL, Set_IOCTL by itself.
In_Generic_IOCTL_flag	db	0
I_AM_IN_NOW		EQU	00000001b
SET_MODE_BY_DISPLAY	EQU	00000010b	;Display.sys calls Set mode INT 10h.
CALLED_BY_INT10COM	EQU	00000100b	;To prevent from calling set mode int 10h again.

INT10_V_Mode		db	0ffh		;Used by INT10_COM

My_IOCTL_Req_Packet	REQ_PCKT <0,0,0Eh,0,?,0,?,?,?,?,?>

FUNC_INFO		INFO_BLOCK <>		;data block for functionality call
ROM_INT10		DW	?		;segment and offset of original..
			DW	?		;interrupt 10h vector.
ROM_INT2F		DW	?		;segment and offset of original..
			DW	?		;interrupt 2Fh vector.
INTENSITY_FLAG		DW	OFF		;intensity flag initially off
REQ_TXT_LENGTH		DW	DEFAULT_LENGTH	;requested text screen length
SCAN_DESIRED		DB	0		;scan lines desired
MAX_SCANS		DB	0		;maximum scan line setting
GRAPHICS_FLAG		DB	TEXT_MODE	;flag for graphics mode
Display_Loaded_Before_Me db	0		;flag
ANSI_SetMode_Call_Flag	db	0		;Ansi is issuing INT10,AH=0.
ALT_PRT_SC_INVOKED	DB	FALSE		;indicates that have already set up alternat print screen routine



; PROCEDURE_NAME: GENERIC_IOCTL

; FUNCTION:
; TO GET OR SET DEVICE CHARACTERISTICS ACCORDING TO THE BUFFER PASSED
; IN THE REQUEST PACKET.

; AT ENTRY:

; AT EXIT:
;	NORMAL: CARRY CLEAR - DEVICE CHARACTERISTICS SET

;	ERROR: CARRY SET - ERROR CODE IN AL. (SEE MODULE DESCRIPTION ABOVE).

; NOTE: THIS PROC IS PERFORMED AS A JMP AS WITH THE OLD ANSI CALLS.



GENERIC_IOCTL:
	les	bx,[PTRSAV]			; establish addressability to request header
	mov	al,es:[bx].MINORFUNCTION
	les	di,es:[bx].GENERICIOCTL_PACKET	; point to request packet

	cmp	al,GET_FUNC			; is this get subfunction?
	jnz	gi_not_get

	call	GET_IOCTL			; yes...execute routine

	jmp	short gi_check_error

gi_not_get:
	cmp	al,SET_FUNC			; is this the set subfunction?
	jnz	gi_none

	call	SET_IOCTL			; yes....execute routine

gi_check_error:
	jnc	gi_done				; branch if no error
	or	ax,CMD_ERROR			; yes...set error bit in status

gi_done:
	or	ax,DONE				; add done bit to status
	jmp	ERR1				; return with status in ax

gi_none:
	jmp	NO_OPERATION			; call lower CON device


; PROCEDURE_NAME: GET_IOCTL

; FUNCTION:
; THIS PROCEDURE RETURNS DEVICE CHARACTERISTICS.

; AT ENTRY: ES:DI POINTS TO REQUEST BUFFER

; AT EXIT:
;	NORMAL: CARRY CLEAR - REQUEST BUFFER CONTAINS DEVICE CHARACTERISTICS

;	ERROR: CARRY SET - ERROR CONDITION IN AX



GET_IOCTL	PROC	NEAR

	cmp	es:[di].INFO_LEVEL,0		; check for valid info level
	jnz	gi_invalid
	cmp	es:[di].DATA_LENGTH,TYPE MODE_TABLE+1 ; and buffer size
	jge	gi_valid

gi_invalid:
	mov	ax,INVALID_FUNC			; not valid...unsupported
	stc					; function..set error flag and
	ret

gi_valid:
	mov	es:[di].INFO_LEVEL+1,0		; set reserved byte to 0.
	mov	ah,REQ_VID_MODE			; request current video mode
	int	10H
	and	al,VIDEO_MASK
	lea	si,VIDEO_MODE_TABLE		; point to resident video table
	call	GET_SEARCH			; perform search
	jnc	gi_supported			; found?

	mov	ax,NOT_SUPPORTED		; no....load unsupported function
	ret					; carry already set

gi_supported:
	push	di				;Save Request Buffer pointer
	mov	WORD PTR es:[di].DATA_LENGTH,(TYPE MODE_TABLE)+1 ;length of data is struc size
	inc	si				; skip mode value
	add	di,RP_FLAGS			; point to flag word

;	VGA,MCGA: VALUE RETURNED FROM FUNCTIONALITY CALL
;	EGA: VALUE LAST SET THROUGH IOCTL. DEFAULT IS BLINKING.
;	CGA,MONO: BLINKING

	cmp	al,7				; M004; Monochrome screen?
	mov	ax,OFF				; assume CGA,MONO 
						; (we always have blink).
	jz	gi_flags_done			; M004;

	cmp	HDWR_FLAG,MCGA_ACTIVE		; if we have an EGA or better
	jl	gi_flags_done

	test	HDWR_FLAG,VGA_ACTIVE		; VGA supported?
	jz	gi_as_intensity_flag

	push	es				; yes...prepare for
	push	di				; functionality call

	push	ds
	pop	es
	lea	di,FUNC_INFO			; point to data block
	mov	ah,FUNC_CALL			; load function number
	xor	bx,bx				; implementation type 0
	int	10H

	mov	INTENSITY_FLAG,OFF		; assume no intensity
	test	es:[di].MISC_INFO,INT_BIT	; is blink bit set?
	jnz	gi_intensity_is_fine		; if not no intensity

	inc	INTENSITY_FLAG			; we want intensity

gi_intensity_is_fine:
	pop	di				; restore registers
	pop	es

gi_as_intensity_flag:
	mov	ax,INTENSITY_FLAG		; write the control flag..

gi_flags_done:
	stosw					; write the control flag..
						; point to next field (display)
	mov	cx,(TYPE MODE_TABLE)-1		; load count
	rep	movsb				; transfer data from video table
						; to request packet
	sub	si,TYPE MODE_TABLE		; point back to start of mode data

ifdef JAPAN
	dec	di				; point to number of rows
	dec	di
ENDIF

	cmp	[si].D_MODE,TEXT_MODE		; if we are in text mode and
	jnz	gi_row_counted
	cmp	[si].SCR_ROWS,DEFAULT_LENGTH	; length <> 25 then we have an EGA or VGA
	jz	gi_row_counted

ifndef JAPAN
	dec	di				; point back to length entry in req packet
	dec	di
ENDIF
	push	ds
	mov	ax,ROM_BIOS			; load ROM BIOS data area segment
	mov	ds,ax
	mov	al,BYTE PTR ds:[NUM_ROWS]	; load current number of rows
	cbw
	inc	ax				; add 1 to row count
	mov	WORD PTR es:[di],ax		; and copy to request packet
	pop	ds

gi_row_counted:

ifdef JAPAN
	mov	al,row_adj
	xor	ah,ah
	sub	es:[di],ax			; support ESC[>1l
ENDIF

	xor	ax,ax				; no errors
	clc					; clear error flag
	pop	di				; Restore Request Buffer pointer
	ret					; return to calling module

GET_IOCTL	ENDP




; PROCEDURE_NAME: SET_IOCTL

; FUNCTION:
; THIS PROCEDURE SETS THE VIDEO MODE AND CHARACTER SET ACCORDING
; TO THE CHARACTERSTICS PROVIDED.

; AT ENTRY:
;	ES:[DI] POINTS TO REQUEST BUFFER

; AT EXIT:
;	NORMAL: CLEAR CARRY - VIDEO MODE SET

;	ERROR: CARRY SET - ERROR CONDITION IN AX



SET_IOCTL	PROC	NEAR

	or	In_Generic_IOCTL_Flag, I_AM_IN_NOW	; Signal GENERIC_IOCTL request being processed
	push	REQ_TXT_LENGTH			; save old value in case of error

	cmp	es:[di].INFO_LEVEL,0		; check for valid info level
	jnz	si_invalid
	cmp	es:[di].DATA_LENGTH,TYPE MODE_TABLE+1 ; ane buffer size
	jnz	si_invalid
	mov	ax,es:[di].RP_FLAGS		; test for invalid flags
	test	ax,INVALID_FLAGS
	jnz	si_invalid
	test	es:[di].RP_FLAGS,ON		; if intensity is requested and..
	jz	si_valid
	cmp	HDWR_FLAG,MCGA_ACTIVE		; hardware does not support it
	jge	si_valid

si_invalid:
	mov	ax,INVALID_FUNC			; not valid...unsupported..
	jmp	si_failed

si_valid:
	call	SET_SEARCH			; search table for match
	jnc	si_mode_valid

si_not_supp:
	jmp	si_not_supported

si_mode_valid:
	cmp	[si].D_MODE,TEXT_MODE		; is a text mode being requested?
	jz	si_do_text_mode

	call	SET_VIDEO_MODE
	jmp	si_end_ok	

si_do_text_mode:
	mov	ax,es:[di].RP_ROWS		; save new requested value.
	mov	REQ_TXT_LENGTH,ax

	cmp	ax,DEFAULT_LENGTH		; is it just 25 lines needed?
	jz	si_display_ok

	mov	ax,DISPLAY_CHECK
	int	2FH

	cmp	al,INSTALLED			; or is DISPLAY.SYS not there?
	jnz	si_display_ok

	mov	ax,CHECK_FOR_FONT
	int	2FH				; or if it is does it have the..
	jnc	si_display_ok

	mov	ax,NOT_AVAILABLE		; DISPLAY.SYS does not have the font
	jmp	si_failed
	
si_display_ok:
	cmp	[si].SCR_ROWS,UNOCCUPIED
	jz	si_is_vga
	test	HDWR_FLAG,VGA_ACTIVE
	jz	si_non_vga

si_is_vga:
	mov	ax,1A00h			;Get currently active adap.;C04
	int	10h				;VGA interrupt             ;C04
	mov	ax,REQ_TXT_LENGTH		; restore AX
	cmp	bl,7				;Q: non_vga adapter?	   ;C04
	jb	si_non_vga			;Yes so do other stuff	   ;C04

process_vga:
	mov	cl,3				; ax loaded with length requested
	shl	ax,cl				; mulitply by 8 to get scan lines
	lea	bx,SCAN_LINE_TABLE		; load bx with scan line table start
	mov	cx,SCANS_AVAILABLE		; total number of scan lines settings

pv_while:
	cmp	ax,[bx].NUM_LINES		; pointing at the right setting?
	jz	pv_found

	add	bx,TYPE SCAN_LINE_STR		; not this setting..point to next
	loop	pv_while
	
	jmp	short si_not_supp

pv_found:
	mov	dl,[bx].REP_1BH

	test	SCAN_LINES,dl			; does the hardware have it?
	jz	si_not_supp

	mov	cl,[bx].REP_12H			; yes, store value to set it
	mov	SCAN_DESIRED,cl

	cmp	REQ_TXT_LENGTH,DEFAULT_LENGTH	; 25 lines requested?
	jnz	pv_scan_ok

	mov	al,MAX_SCANS			; desired scan setting should be..
	mov	SCAN_DESIRED,AL			; the maximum.

pv_scan_ok:

; following added to overcome problems with rolling
; screens in QBX and WZMAIL.	Problem still exists when switching between
; mono and VGA screens when ANSI is loaded with /L.

	test	In_Generic_IOCTL_Flag,CALLED_BY_INT10COM
	jnz	si_set_mode_done

	mov	ah,ALT_SELECT			; set the appropriate number..
	mov	bl,SELECT_SCAN			; of scan lines..
	mov	al,SCAN_DESIRED
	int	10H

	jmp	short si_processed

si_non_vga:
	mov	ax,REQ_TXT_LENGTH
	cmp	ax,DEFAULT_LENGTH		; see if length requested..
	jz	si_cursor_emul			; is valid
	cmp	ax,[si].SCR_ROWS
	jnz	si_not_supported

si_cursor_emul:
	call	SET_CURSOR_EMUL

si_processed:
	call	SET_VIDEO_MODE

si_set_mode_done:
	call	DO_ROWS
	cmp	ALT_PRT_SC_INVOKED,FALSE	; If not set up already
	jnz	si_printscreen_ok
	cmp	es:[di].RP_ROWS,DEFAULT_LENGTH	; and needed because lines	(or 30?)
	jle	si_printscreen_ok
	cmp	HDWR_FLAG,MCGA_ACTIVE		; and if we have EGA or better then.. (supported)
	jl	si_printscreen_ok

	mov	ah,ALT_SELECT			; issue select alternate print..
	mov	BL,ALT_PRT_SC			; screen routine call..
	int	10H
	mov	ALT_PRT_SC_INVOKED,TRUE		; mark that it was done

si_printscreen_ok:
	call	SET_CURSOR_EMUL			; yes..ensure cursor emulation
						; is set accordingly.
	cmp	HDWR_FLAG,MCGA_ACTIVE		; for the EGA and better...
	jl	si_end_ok

	cmp	[si].V_MODE,7			; M004; and not monochrome
	jz	si_end_ok

	xor	bx,bx				; bx: 1=intensity on, 0: off
						; assume off
	test	es:[di].RP_FLAGS,ON		
	jz	si_intensity_ok

	inc	bx				; user wants intensity

si_intensity_ok:
	mov	INTENSITY_FLAG,bx
	mov	ax,BLINK_TOGGLE
	xor	bl,ON				; bl is opposite
						; of INTENSITY_FLAG
	int	10H

si_end_ok:
	and	In_Generic_IOCTL_Flag, NOT I_AM_IN_NOW	; Turn the flag off
	pop	ax				; forget old REQ_TXT_LENGTH
	xor	ax,ax				; clear error register
	clc					; clear error flag
	ret

si_not_supported:
	mov	ax,NOT_SUPPORTED

si_failed:
	and	In_Generic_IOCTL_Flag, NOT I_AM_IN_NOW	; Turn the flag off
	pop	REQ_TXT_LENGTH			; error...so restore old value.
	stc					; set error flag
	ret

SET_IOCTL	ENDP



; Procedure name: DO_ROWS
; Function:
;	Only called for TEXT_MODE.
;	If (REQ_TXT_LENGTH <> DEFAULT_LENGTH) &
;	(DISPLAY.SYS not loaded or CODEPAGE not active)
;	then
;	LOAD ROM 8X8 charater.


DO_ROWS		PROC	NEAR

	cmp	req_txt_length, DEFAULT_LENGTH
	je	dr_exit
	mov	ax,LOAD_8X8 			; load 8x8 ROM font
	xor	bl,bl
	int	10H				; M003;
	mov	ax,SET_BLOCK_0			; activate block = 0
	xor	bl,bl
	int	10H				; M003;
dr_exit:
	ret

DO_ROWS 	ENDP






; PROCEDURE_NAME: SET_SEARCH

; FUNCTION:
; THIS PROCEDURE SEARCHES THE RESIDENT VIDEO TABLE IN ATTEMPT TO
; FIND A MODE THAT MATCHES THE CHARACTERISTICS REQUESTED.

; AT ENTRY:

; AT EXIT:
;	NORMAL: CARRY CLEAR - SI POINTS TO APPLICABLE RECORD

;	ERROR: CARRY SET

; When INT10_V_Mode <> 0FFH, then assumes that the user
;	issuing INT10h, Set mode function call.	Unlike Generic IOCTL
;	set mode call, the user already has taken care of the video mode.
;	So, we also find the matching V_MODE.

; WARNING: TRASH CX

SET_SEARCH	PROC	NEAR

	lea	si,VIDEO_MODE_TABLE		; point to video table
	mov	cx,MAX_VIDEO_TAB_NUM 		; load counter, # of tables

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?