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

ss_while:
	cmp	[si].V_MODE,UNOCCUPIED		; while we have valid entries
	jz	ss_not_found

	mov	al,INT10_V_Mode

	cmp	al,0ffh				; if not issued by Int10 set mode,
	jnz	ss_from_set_mode

	
	mov	al,es:[di].RP_MODE		; load register for compare.
	cmp	[si].D_MODE,al			; match?
	jnz	ss_end_while

	mov	ax,es:[di].RP_COLORS		; yes...prepare next field
	cmp	[si].COLORS,ax			; match?
	jnz	ss_end_while

	cmp	es:[di].RESERVED2,0		; yes, ensure reserved byte is zero
	jnz	ss_end_while

	cmp	es:[di].RP_MODE,GRAPHICS_MODE	; for graphics mode
	jnz	ss_not_graphic			; check the following:

	mov	ax,es:[di].RP_WIDTH		; screen width.
	cmp	[si].SCR_WIDTH,ax
	jnz	ss_end_while

	mov	ax,es:[di].RP_LENGTH		; screen length
	cmp	[si].SCR_LENGTH,ax
	jnz	ss_end_while			; ignore #rows and #coloumns

	jmp	short ss_found

ss_not_graphic:
	mov	ax,es:[di].RP_COLS		; the rows are matched
	cmp	[si].SCR_COLS,ax		; in the main routine
	jnz	ss_end_while

ss_found:
	clc
	jmp	short ss_done

ss_from_set_mode:
	cmp	[si].V_MODE,al			; if V_MODE = AL, we are ok
	jz	ss_found

ss_end_while:
	add	si,type MODE_TABLE		; then, this is not the correct entry.
	loop	ss_while			; Let's find the next entry.

ss_not_found:
	stc

ss_done:
	mov	INT10_V_Mode, 0FFh		; Done. Reset the value
	ret

SET_SEARCH	ENDP




; PROCEDURE_NAME: GET_SEARCH

; FUNCTION:
; THIS PROCEDURE SEARCHES THE VIDEO TABLE LOOKING FOR A MATCHING
; VIDEO MODE.

; AT ENTRY: DS:SI POINTS TO VIDEO TABLE
;		AL CONTAINS THE MODE REQUESTED

; AT EXIT:
;	NORMAL: CARRY CLEAR, DS:SI POINTS TO MATCHING RECORD

;	ERROR: CARRY SET

; WARNING: TRASH CX

GET_SEARCH	PROC	NEAR

	mov	cx,MAX_VIDEO_TAB_NUM		; # of total tables

gs_while:
	cmp	[si].V_MODE,UNOCCUPIED		; while we're not pointing to
	jz	gs_error
	cmp	[si].V_MODE,al			; the right mode and we are still
	jz	gs_got_it

	add	si,TYPE MODE_TABLE		; point to the next mode
	loop	gs_while

gs_error:
	stc					; no, set error flag
	ret

gs_got_it:
	clc
	ret

GET_SEARCH	ENDP



; PROCEDURE_NAME: SET_CURSOR_EMUL

; FUNCTION:
; THIS PROCEDURE SETS THE CURSOR EMULATION BIT OFF IN ROM BIOS. THIS
; IS TO PROVIDE A CURSOR ON THE EGA WITH THE 5154 LOADED WITH AN 8X8
; CHARACTER SET.

; AT ENTRY:

; AT EXIT:
;	NORMAL: CURSOR EMULATION BIT SET FOR APPLICABLE HARDWARE

;	ERROR: N/A



SET_CURSOR_EMUL PROC	NEAR

	test	HDWR_FLAG,E5154_ACTIVE		; EGA with 5154?
	jz	sce_done

	push	si
	push	ds				; yes..so..
	mov	ax,ROM_BIOS			; check cursor emulation..
	mov	ds,ax
	mov	si,CURSOR_FLAG
	mov	al,BYTE PTR [si]

	cmp	cs:REQ_TXT_LENGTH,DEFAULT_LENGTH; >25 lines req?
	jnz	sce_cursor_on

	and	al,TURN_OFF			; no....set it OFF

	jmp	short sce_cursor_ok

sce_cursor_on:
	or	al,TURN_ON			; yes...set it ON

sce_cursor_ok:
	mov	BYTE PTR [si],AL
	pop	ds
	pop	si

sce_done:
	ret					; return to calling module

SET_CURSOR_EMUL	ENDP




; PROCEDURE_NAME: INT10_COM

; FUNCTION:
; THIS IS THE INTERRUPT 10H HANDLER TO CAPTURE THE FOLLOWING FUNCTIONS:

;	AH=1H (SET CURSOR TYPE). CURSOR EMULATION IS PERFORMED IF WE HAVE
;		AND EGA WITH A 5151 MONITOR, AND 43 LINES IS REQUESTED.

;M002; What is bellow was modified. The /L option was removed. But ansi
;M002; will still do a GET_IOCTL/SET_IOCTL for the application.
;	AH=0H (SET MODE) SCREEN LENGTH IS MAINTAINED WHEN POSSIBLE. (IE. IN
;		TEXT MODES ONLY.)
;	AN004; Capturing Set Mode call and enforcing the # of Rows based on the
;		previous Set_IOCTL request lines was a design mistake.	ANSI cannot
;		covers the all the application program out there which use INT 10h
;		directly to make a full screen interface by their own way.
;		This part of logic has been taken out by the management decision.
;		Instead, for each set mdoe INT 10h function call, if it were not
;		issued by SET_IOCTL procedures itself, or by DISPLAY.SYS program,
;		then we assume that it was issued by an APPS, that usually does not
;		know the new ANSI GET_IOCTL/SET_IOCTL interfaces.
;		In this case, ANSI is going to call GET_IOCTL and SET_IOCTL function
;		call - This is not to lose the local data consistency in ANSI.

; AT ENTRY:

; AT EXIT:
;	NORMAL:

;	ERROR:



INT10_COM	PROC	NEAR

	sti 					; restore interrupts
	cmp	ah,SET_CURSOR_CALL
	jz	SET_CURSOR_HANDLER
	cmp	ah,SET_MODE
	jz	SET_MODE_HANDLER

	jmp	DWORD PTR cs:ROM_INT10		; no...pass it on.

SET_CURSOR_HANDLER:
	push	ax

	test	cs:HDWR_FLAG,E5151_ACTIVE	; do we have an EGA?
	jz	sch_goto_rom
	cmp	cs:REQ_TXT_LENGTH,DEFAULT_LENGTH
	jz	sch_goto_rom
	cmp	cs:GRAPHICS_FLAG,TEXT_MODE	; with 5151..so perform cursor mapping
	jnz	sch_goto_rom
	cmp	cl,8
	jl	sch_goto_rom

	mov	al,ch				; check for cursor..
	and	al,60h				; off emulation. J.K.

	cmp	al,20h
	jz	sch_goto_rom

	mov	al,ch				; start position for cursor
	call	MAP_DOWN
	mov	ch,al
	mov	al,cl				; end position for cursor
	call	MAP_DOWN
	mov	cl,al

sch_goto_rom:
	pop	ax
	jmp	DWORD PTR CS:ROM_INT10		; continue interrupt processing

SET_MODE_HANDLER:
	pushf					; prepare for IRET
	mov	cs:ANSI_SetMode_Call_Flag, 1	; Used by INT2F_COM
	call	DWORD PTR CS:ROM_INT10		; call INT10 routine
	mov	cs:ANSI_SetMode_Call_Flag, 0	; Reset it
	push	bp
	push	es
	push	ds
	push	si
	push	di
	push	dx
	push	cx
	push	bx
	push	ax
	push	cs
	pop	ds
	mov	ah,REQ_VID_MODE			; get current mode..
	pushf
	call	DWORD PTR ROM_INT10
	and	al,VIDEO_MASK			; mask bit 7 (refresh)
	test	In_Generic_IOCTL_Flag, (I_AM_IN_NOW + SET_MODE_BY_DISPLAY)	; Flag is on?
;If not (I_AM_IN_NOW or SET_MODE_BY_DISPLAY),

	jnz	smh_ioctl_done

;	cmp	SWITCH_L,0			;M002; No more /L
;	jnz	smh_ioctl_done			;M002; No more /L

	push	ax				;Save mode
	push	es
	push	cs
	pop	es
	mov	di,offset My_IOCTL_Req_Packet
	mov	INT10_V_Mode,al			;Save current mode for SET_SEARCH
	call	Get_IOCTL

	jc	smh_set_ioctl_done

	or	In_Generic_IOCTL_Flag, CALLED_BY_INT10COM ;Do not set mode INT 10h again. Already done.
	call	Set_IOCTL
	and	In_Generic_IOCTL_Flag, not CALLED_BY_INT10COM

smh_set_ioctl_done:

	pop	es
	pop	ax				;Restore mode
	mov	INT10_V_Mode,0FFh


smh_ioctl_done:

	lea	si,VIDEO_MODE_TABLE
	call	GET_SEARCH 			; look through table for mode selected.
	jc	smh_graphic_mode		; M001; if not found then
						; M001; assume graphic mode

	cmp	[si].D_MODE,TEXT_MODE		; text mode?
	jz	smh_text_mode

smh_graphic_mode:
	mov	GRAPHICS_FLAG,GRAPHICS_MODE	; no, set graphics flag
	jmp	short smh_flag_done

smh_text_mode:
	mov	GRAPHICS_FLAG,TEXT_MODE		; set TEXT MODE


smh_flag_done:

;	test	In_Generic_IOCTL_Flag, I_AM_IN_NOW
;	jnz	smh_l_done			; M002; No more /L
;	cmp	Graphics_Flag,TEXT_MODE		; M002; No more /L
;	jnz	smh_l_done			; M002; No more /L
;	cmp	SWITCH_L,1			; M002; No more /L
;	jnz	smh_l_done			; M002; No more /L

;	call	DO_ROWS				; M002; No more /L

smh_l_done:

;For each SET mode function int 10h function call, if it is not
;issued by ANSI GET_IOCTL and SET_IOCTL procedure themselves, we assume
;that the APPS, which usually does not know the ANSI GET_IOCTL/SET_IOCTL
;interfaces, intend to change the screen mode.	In this case, ANSI is
;kind enough to call GET_IOCTL and SET_IOCTL function call for themselves.

	pop	ax
	pop	bx
	pop	cx
	pop	dx
	pop	di
	pop	si
	pop	ds
	pop	es
	pop	bp
	iret

INT10_COM	ENDP




; PROCEDURE_NAME: INT2F_COM

; FUNCTION:
; THIS IS THE INTERRUPT 2FH HANDLER TO CAPTURE THE FOLLOWING FUNCTIONS:

;	ax=1A00H INSTALL REQUEST. ANSI WILL RETURN AL=FFH IF LOADED.

;	AH=1A01H THIS IS THE INT2FH INTERFACE TO THE GENERIC IOCTL.
;	NOTE: THE GET CHARACTERISTICS FUNCTION CALL WILL RETURN
;		THE REQ_TXT_LENGTH IN THE BUFFER AS OPPOSED TO
;		THE ACTUAL HARDWARE SCREEN_LENGTH
;	Ax=1A02h This is an information passing from DISPLAY.SYS about
;		the INT 10h, SET MODE call.

; AT ENTRY:

; AT EXIT:
;	NORMAL:

;	ERROR:



INT2F_COM	PROC	NEAR

	sti
	cmp	ah,multANSI			; is this for ANSI?
	jnz	ic_goto_rom
	cmp	al,DA_INFO_2F
	jle	INT2F_HANDLER

ic_goto_rom:
	jmp	DWORD PTR CS:ROM_INT2F		; no....jump to old INT2F

INT2F_HANDLER:

	cmp	al,INSTALL_CHECK
	jnz	ih_not_check

;	do install check

	mov	al,INSTALLED			; load value to indicate installed
	clc					; clear error flag.
	jmp	ih_iret

ih_not_check:
	cmp	al,DA_INFO_2F			; IOCTL or INFO passing?
	jbe	ih_valid
	jmp	ih_iret

ih_valid:
	push	bp
	push	ax				; s
	push	cx				; a
	push	dx				; v
	push	ds				; e	r
	push	es				;	e
	push	di				;	g
	push	si				;	s.
	push	bx
	push	ds				; load ES with DS (for call)
	pop	es
	mov	di,dx				; load DI with dx (for call)
	push	cs				; setup local addressability
	pop	ds

	cmp	al,IOCTL_2F			; IOCTL request
	jnz	ih_not_ioctl

	cmp	cl,GET_FUNC			; get function requested.
	jnz	ih_not_get

	call	GET_IOCTL

	jc	ih_set_flags			; if no error and
	cmp	HDWR_FLAG,E5151_ACTIVE		; >25 lines supported
	jl	ih_set_flags
	cmp	[si].D_MODE,TEXT_MODE		; this is a text mode then..
	jnz	ih_set_flags


;	cmp	SWITCH_L,1			; M002; No more /L
;	jz	ih_use_rtl			; M002; No more /L

	cmp	ANSI_SetMode_Call_Flag,1
	jnz	ih_use_rtl			; if not originated by ANSI thru AH=0, Int10
	cmp	Display_Loaded_Before_me,1	; or Display.sys not loaded before ANSI,
	jz	ih_get_ok

ih_use_rtl:
	mov	bx,REQ_TXT_LENGTH		; then use REQ_TXT_LENGTH instead..
	mov	es:[di].RP_ROWS,bx

ih_get_ok:
	clc
	jmp	short ih_set_flags

ih_not_get:
	cmp	cl,SET_FUNC
	jnz	ih_invalid

	call	SET_IOCTL			; set function requested.

	jmp	short ih_set_flags

;	invalid function

ih_invalid:
	mov	ax,INVALID_FUNC			; load error and...
	stc 					; set error flag.
	jmp	short ih_set_flags		; Info. passing

ih_not_ioctl:
	cmp	es:[di].DA_INFO_LEVEL,0		; 0 - DA_SETMODE_FLAG request
	jnz	ih_not_info


	cmp	es:[di].DA_SETMODE_FLAG,1
	jnz	ih_not_set

	or	In_Generic_IOCTL_Flag, SET_MODE_BY_DISPLAY	;Turn the flag on
	jmp	short ih_info_ok

ih_not_set:
	and	In_Generic_IOCTL_Flag, not SET_MODE_BY_DISPLAY	;Turn the flag off

	jmp	short ih_info_ok

ih_not_info:

	cmp	es:[di].DA_INFO_LEVEL,1		; 1 = DA_L_STATA query
	jnz	ih_info_ok

;	mov	al,cs:[SWITCH_L]		; M002; No more /L
	mov	al,OFF				; M002; No more /L

	mov	es:[di].DA_L_STATE, al

ih_info_ok:
	clc					; clear carry. There is no Error in DOS 4.00 for this call.

ih_set_flags:
	pop	bx				; restore all..
	pop	si
	pop	di				;	registers except..
	pop	es
	pop	ds				;	BP.
	pop	dx
	pop	cx
	push	ax				; save error condition
	mov	bp,sp				; setup frame pointer
	mov	ax,[bp+10]			; load stack flags
	jc	ih_error			; carry set???

	and	ax,NOT_CY			; no.. set carry off.
	mov	[bp+10],ax			; put back on stack.
	pop	ax				; remove error flag from stack
	pop	ax				; no error so bring back function call
	XCHG	ah,al				; exchange to show that ANSI present
	jmp	short ih_pop_bp

ih_error:
	or	ax,CY				; yes...set carry on.
	mov	[bp+10],ax			; put back on stack.
	pop	ax				; restore error flag
	pop	bp				; pop off saved value of ax (destroyed)

ih_pop_bp:
	pop	bp				; restore final register.
ih_iret:
ABORT:	iret

INT2F_COM	ENDP




; PROCEDURE_NAME: MAP_DOWN

; FUNCTION:
; THIS PROCEDURE MAPS THE CURSOR START (END) POSITION FROM A 14 PEL
; BOX SIZE TO AN 8 PEL BOX SIZE.

; AT ENTRY: AL HAS THE CURSOR START (END) TO BE MAPPED.

; AT EXIT:
;	NORMAL: AL CONTAINS THE MAPPED POSITION FOR CURSOR START (END)

;	ERROR: N/A



MAP_DOWN	PROC	NEAR

	push	bx
	xor	ah,ah 			; clear upper byte of cursor position
	mov	bl,EIGHT		; multiply by current box size.
	push	dx			;	al	x
	mul	bl			;	---- = ---
	pop	dx			;	14	8
	mov	bl,FOURTEEN
	div	bl			; divide by box size expected.
	pop	bx
	ret

MAP_DOWN	ENDP




; PROCEDURE_NAME: SET_VIDEO_MODE

; FUNCTION:
; THIS PROCEDURE SETS THE VIDEO MODE SPECIFIED IN DS:[SI].V_MODE.

; AT ENTRY: DS:SI.V_MODE CONTAINS MODE NUMBER

; AT EXIT:
;	NORMAL: MODE SET

;	ERROR: N/A



SET_VIDEO_MODE PROC	NEAR

	test	In_Generic_IOCTL_Flag,CALLED_BY_INT10COM
	jnz	svm_done

	mov	al,[si].V_MODE			; ..issue set mode

	test	HDWR_FLAG,LCD_ACTIVE
	jnz	svm_update_bios			; is this the LCD?
	test	HDWR_FLAG,VGA_ACTIVE		; or VGA? (done for BRECON card)
	jz	svm_update_done

svm_update_bios:
	push	ds				; yes...
	mov	bl,al				; save mode
	mov	ax,ROM_BIOS
	mov	ds,ax				; get equipment status flag..
	mov	ax,ds:[EQUIP_FLAG]
	and	ax,INIT_VID_MASK		; clear initial video bits..

	cmp	bl,MODE7			; are we setting mono?
	jz	svm_mono
	cmp	bl,MODE15
	jnz	svm_color

svm_mono:
	or	ax,LCD_MONO_MODE		; yes...set bits as mono
	jmp	short svm_update_it

svm_color:
	or	ax,LCD_COLOR_MODE		; no...set bits as color

svm_update_it:
	mov	ds:[EQUIP_FLAG],ax	 	; replace updated flag.
	mov	al,bl			 	; restore mode.
	pop	ds

svm_update_done:
	mov	ah,SET_MODE			; set mode
	int	10H

svm_done:
	ret

SET_VIDEO_MODE	ENDP

CODE		ENDS
		END
