;SCCSID = @(#)bvsbufs.asm	6.2 91/02/11
	PAGE	58,132
	TITLE	BvsBufs.Asm -- Base Video Subsystem Buffer Routines
; ****************************************************************************
; *									     *
; *			  IBM/Microsoft Confidential			     *
; *									     *
; *		    Copyright (c) IBM Corporation  1987, 1990		     *
; *		    Copyright (c) Microsoft Corp.  1987, 1990		     *
; *			      All Rights Reserved			     *
; *									     *
; ****************************************************************************

;/********************** START OF SPECIFICATIONS ************************/
;/*									*/
;/* SOURCE FILE NAME:	BvsBufs.Asm					*/
;/*									*/
;/* DESCRIPTIVE NAME:	Bvs Buffer and Config Routines			*/
;/*									*/
;/* COPYRIGHT:	na							*/
;/*									*/
;/* STATUS:	na							*/
;/*									*/
;/* NOTES:	Executes on level 3 - Protect Mode ONLY 		*/
;/*									*/
;/*    DEPENDENCIES:	None						*/
;/*									*/
;/*    RESTRICTIONS:	None						*/
;/*									*/
;/*    PATCH LABEL:	na						*/
;/*									*/
;/* ENTRY POINTS: BvsGetPhysBuf, BvsGetBuf, BvsShowBuf, BvsGetConfig	*/
;/*									*/
;/* EXTERNAL REFERENCES: None						*/
;/************************ END OF SPECIFICATIONS ************************/

	.xlist
	INCLUDE bvscb.inc		;BVS Data Structures
	INCLUDE bvsparms.inc		;BVS Paramter Equates
	INCLUDE bvsextrn.inc		;BVS external definitions	;@T52
	INCLUDE error2.inc		;System error equates
	INCLUDE infoseg.inc		;System Info Segments
	INCLUDE struc.inc		;Structured Macros
	.list

	.386p			;@D549

	extrn	AllVDH:NEAR		;Common VDH call routine in BVSMAIN
	extrn	AllBuffer:NEAR		;Common VDH call routine in BvsSubs
	extrn	WndwConfig:WORD 	;VIO windowable config data	;@T45

BVSGSEG SEGMENT WORD PUBLIC 'FAR_DATA' USE16  ;@@A,@D549                ;@T52
BVSGSEG ENDS				;@@A

BVS3SEG SEGMENT BYTE PUBLIC 'CODE' USE16        ;@D549
	ASSUME	CS:BVS3SEG

;/*********************** START OF SPECIFICATIONS ***********************/
;/*									*/
;/* SUBROUTINE NAME:  BvsGetPhysBuf					*/
;/*									*/
;/* DESCRIPTIVE NAME:  Base Video Subsystem Get Physical Buffer 	*/
;/*									*/
;/* FUNCTION:  Returns the address and attributes of the Physical Video */
;/*	       Buffer (PVB) for the Base Video Subsystem		*/
;/*									*/
;/* NOTES:  Executes on Level 3 					*/
;/*									*/
;/* ENTRY POINT:  BvsGetPhysBuf 					*/
;/*   LINKAGE:	Call BvsGetPhysBuf from BvsMain 			*/
;/*									*/
;/* INPUT:  StackFrame and Registers (see BVSMAIN) with:		*/
;/*	parmn	= Offset of PhysBuf control block			*/
;/*	parmnm1 = Selector of PhysBuf control block			*/
;/*									*/
;/* EXIT-NORMAL:  AX = 0						*/
;/*		  Selectors to data block				*/
;/*									*/
;/* EXIT-ERROR: ERROR_VIO_IN_BG 					*/
;/*									*/
;/* EFFECTS:  None							*/
;/*									*/
;/* INTERNAL REFERENCES:  PPBVSCB, BVSCBsg				*/
;/*   ROUTINES:  None							*/
;/*									*/
;/* EXTERNAL REFERENCES:  None						*/
;/*   ROUTINES:  GetPhysBuf in VDH					*/
;/*									*/
;/************************ END OF SPECIFICATIONS ************************/

;Begin BvsGetPhysBuf
;    Preset return code to ERROR_VIO_IN_BG
;    If in the foreground
;	 Call GetPhysBuf in the VDH to allocate the selector(s)
;    Endif
;End BvsGetPhysBuf

BvsGetPhysBuf PROC NEAR
	PUBLIC	BvsGetPhysBuf
	push	ds

	mov	ax,ERROR_VIO_IN_BG	;Preset error
	mov	ds,es:bvsi_gdtsel					;@T52
	mov	dl,[bx].SIS_CurScrnGrp
	.if	<dl eq <byte ptr es:bvsi_sgnum>> ;Session in foreground ;@T52

	    mov     [bp].vp_flags,vp_f_physical ;Force flag to be set off
	    mov     ax,[bp].p_offset
	    mov     [bp].vp_offset,ax
	    mov     ax,[bp].p_selector
	    mov     [bp].vp_selector,ax ;Set the PhysBuf pointer

	    mov     di,fn_GetPhysBuf
	    Call    AllVDH

	.endif

	pop	ds			;Restore BVSCB selector
	.if	<zero ax>		;Successful GetPhysBuf
	    .if     <BIT [bx].bvs_flags nand bvs_f_avio> and		 ;@B30
	    .if     <BIT [bx].bvs_flags nand bvs_f_window>		 ;@B30
		and	[bx].bvs_flags,NOT bvs_f_wrtthru ;End Write Thru
	    .endif							 ;@B30
	.endif
	RET				;Return to BvsMain
BvsGetPhysBuf ENDP

;/*********************** START OF SPECIFICATIONS ***********************/
;/*									*/
;/* SUBROUTINE NAME:  BvsGetBuf 					*/
;/*									*/
;/* DESCRIPTIVE NAME:  Base Video Subsystem Get Logical Buffer		*/
;/*									*/
;/* FUNCTION:	Returns the address of the Logical Video buffer for	*/
;/*		the current screen group using the Base Video Subsystem.*/
;/*		It also marks the LVBsg for write thru in foreground.	*/
;/*									*/
;/* NOTES:  Executes on Level 3 					*/
;/*									*/
;/* ENTRY POINT:  BvsGetBuf						*/
;/*   LINKAGE:	Call BvsGetBuf from BvsMain				*/
;/*									*/
;/* INPUT:  StackFrame and Registers (see BVSMAIN) with:		*/
;/*	parmn	= Offset of LVB length					*/
;/*	parmnm1 = Selector of LVB length				*/
;/*	parmnm2 = Offset of LVB ptr					*/
;/*	parmnm3 = Selector of LVB ptr					*/
;/*									*/
;/* EXIT-NORMAL:  AX = 0						*/
;/*		  LVBsg selector/offset in data block			*/
;/*		  LVBsg length in length area				*/
;/*									*/
;/* EXIT-ERROR: Invalid ptr to Parameter Block				*/
;/*		Invalid ptr to Length					*/
;/*		ERROR_VIO_MODE						*/
;/*									*/
;/* EFFECTS:  None							*/
;/*									*/
;/* INTERNAL REFERENCES:  PPBVSCB, BVSCBsg				*/
;/*   ROUTINES: None							*/
;/*									*/
;/* EXTERNAL REFERENCES:  None						*/
;/*   ROUTINES: GetMode in VDH, BufferUpdate in VDH			*/
;/*									*/
;/************************ END OF SPECIFICATIONS ************************/

;Begin BvsGetBuf
;    Call BufferUpdate in VDH to synchronize LVB with PVB
;    If no error
;	 Return the LVB selector and length to the user's data area
;	 Set return code to zero
;    Endif
;End BvsGetBuf

BvsGetBuf PROC	NEAR
	PUBLIC	BvsGetBuf

	mov	ax,ERROR_VIO_MODE
	test	[bx].bvs_type,mode_f_graphics
	.if	<z>			;Non-graphics mode?
	    sub     ax,ax
	    mov     cx,es:bvsi_lvbsel					;@T52
	    .if     <BIT [bx].bvs_flags nand bvs_f_wrtthru> and ;@B1
	    push    ds			;@C4;@B1
	    mov     ds,es:bvsi_gdtsel	;@C4;@B1			;@T52
	    mov     dl,[bx].SIS_CurScrnGrp ;@C4;@B1
	    pop     ds			;@C4;@B1
	    .if     <dl eq <byte ptr es:bvsi_sgnum>> ;@C4;@B1		;@T52
		mov	[bp].vp_parmlength,6
		mov	[bp].vp_flags,vp_f_full+vp_f_physical ;Full buffer
		mov	[bp].vp_sr_lvbsel,cx ;Set the LVB selector
		mov	di,fn_SaveEnv	;Sync LVB with PVB
		Call	AllVDH
	    .endif			;@C4

	    .if     <zero ax>
		les	di,dword ptr [bp].gb_offset ;Get ptr to LVB ptr
		stosw			;Store offset of buffer (=0)
		mov	es:[di],cx	;Store the selector of the buffer

		les	di,dword ptr [bp].p_offset ;Get ptr to length

		mov	ax,[bx].bvs_rows	;ax = rows	;B790152
		mul	[bx].bvs_cols		;ax = row * col ;B790152
		xor	cx,cx					;B790152
		mov	cl,byte ptr [bx].bvs_attrbytes		;B790152
		inc	cx					;B790152
		mul	cx	;ax = row * col * cell_size	;B790152

	;;;;;;;;mov	ax,word ptr [bx].bvs_bufsize		;B790152
		stosw			;Store length of buffer

		or	[bx].bvs_flags,bvs_f_wrtthru ;Set wrtthru flag
		sub	ax,ax		;Set good return code
	    .endif
	.endif
	ret				;Return to caller
BvsGetBuf ENDP

;/*********************** START OF SPECIFICATIONS ***********************/
;/*									*/
;/* SUBROUTINE NAME:  BvsShowBuf					*/
;/*									*/
;/* DESCRIPTIVE NAME:  Base Video Subsystem Show Logical Buffer 	*/
;/*									*/
;/* FUNCTION:  Copies the current LVBsg to the PVB for the Base Video	*/
;/*	       Subsystem						*/
;/*									*/
;/* NOTES:  Executes on Level 3 					*/
;/*									*/
;/* ENTRY POINT:  BvsShowBuf						*/
;/*   LINKAGE:	Call BvsShowBuf from BvsMain				*/
;/*									*/
;/* INPUT:  StackFrame and Registers (see BVSMAIN) with:		*/
;/*	parmn	= Length of updated data				*/
;/*	parmnm1 = Offset into LVBsg of updated data			*/
;/*									*/
;/* EXIT-NORMAL:  AX = 0						*/
;/*									*/
;/* EXIT-ERROR: None							*/
;/*									*/
;/* INPUT:  None							*/
;/*									*/
;/* EXIT-NORMAL:  AX = 0						*/
;/*									*/
;/* EXIT-ERROR:  None							*/
;/*									*/
;/* EFFECTS:  None							*/
;/*									*/
;/* INTERNAL REFERENCES:  PPBVSCB, BVSCBsg, LVBsg			*/
;/*   ROUTINES: None							*/
;/*									*/
;/* EXTERNAL REFERENCES:  None						*/
;/*   ROUTINES: GetMode and BufferUpdate in VDH 			*/
;/*									*/
;/************************ END OF SPECIFICATIONS ************************/

;Begin BvsShowBuf
;    Limit parameters to the LVB (using current mode data)
;    Call BufferUpdate in VDH to update the screen from the LVB
;End BvsShowBuf

BvsShowBuf PROC NEAR
	PUBLIC	BvsShowBuf

	push	ds			; check if foreground ;@C8
	mov	ds,es:bvsi_gdtsel	;@C8				;@T52
	mov	dl,[bx].SIS_CurScrnGrp	;@C8;B704999
	pop	ds			;@C8

	sub	ax,ax			;Preset good return code ;B704999
	.if	<BIT [bx].bvs_flags AND bvs_f_wrtthru> or ;GetBuf performed ;@TB5;@C8;B704999
	.if	<BIT [bx].bvs_type AND mode_f_graphics> ;Graphics ;B704999
	    .if     <dl eq <byte ptr es:bvsi_sgnum>> or ; FG process? ;@C8;@@TB5;B704999;@T52
	    push    ds			;@TB5
	    push    BVSGSEG		;@TB5
	    pop     ds			;@TB5
	    mov     cx,ds:bvsg_maxbase	;@TB5				;@T52
	    pop     ds			;@TB5
	    .if     <<byte ptr es:bvsi_sgnum> a cl> ; VIO/AVIO SG? ;@TB5,@T52,@T49
;@T49	    .if     <dl eq 1>		; Shell FG? ;@TB5;B704999

		mov	dx,es:bvsi_lvbsel				;@T52
		mov	[bp].vp_selector,dx ;Set the string address
		mov	ax,[bp].sb_offset
		and	ax,0FFFEh	; mask out odd bit ;@C8
		mov	[bp].vp_offset,ax

		xor	cx,cx						;B790216
		mov	cl,byte ptr [bx].bvs_attrbytes			;B790216
		inc	cx		     ; CX = cell size		;B790216
		xor	dx,dx						;B790216
		div	cx		     ; AX = Align offset	;B790216
					     ; (Convert to cells)	;B790216
		mov	dx,[bp].sb_length    ;@T8			;B790216
		.if	<dx ne 65535>	;@B44				;B790216
		    inc     dx		;inc if odd length; @C8 ;@B44	;B790216
		.endif			;@B44				;B790216
		and	dx,NOT 1	     ;mask off odd bit ;@B51	;B790216

;;;B790216	shr	ax,1		;Convert to cells
;;;B790216	push	ax		;@T8
;;;B790216	mov	ax,[bx].bvs_rows ;@T8
;;;B790216	sub	dx,dx		;@T8
;;;B790216	mul	[bx].bvs_cols	;@T8
;;;B790216	shl	ax,1		;LVB size for 1 attr. 80x25 ;@T8
;;;B790216	mov	cx,ax		;@T8
;;;B790216	mov	dx,[bp].sb_length ;@T8
;;;B790216
;;;B790216	.if	<dx ne 65535>	;@B44
;;;B790216	    inc     dx		;inc in case of odd length; @C8 ;@B44
;;;B790216	.endif			;@B44
;;;B790216
;;;B790216	and	dx,NOT 1	;mask off odd bit ;@B51
;;;B790216
;;;B790216	pop	ax		;@T8
;;;B790216	.if	<cx b <word ptr [bx].bvs_bufsize>> ;3 byte attr len? ;@T8
;;;B790216	    shr     ax,1	;Align offset ;@T8
;;;B790216;@C19     shr     dx,1	;Adjust length ;@T8
;;;B790216	.endif			;@T8
		mov	[bp].vp_repeatlength,dx ;Set the length ;@T8
		sub	dx,dx		;@T8
		div	[bx].bvs_cols	;Compute row and col from offset

		mov	[bp].vp_startrow,ax
		mov	[bp].vp_startcol,dx ;Set the row and column

		mov	[bp].vp_index,sx_WriteCellStr ;Set the subroutine index
		jmp	AllBuffer	;Return to caller via AllBuffer ;B704999
	    .endif
	.endif				;@C8
	ret				;Return to caller
BvsShowBuf ENDP

;/*********************** START OF SPECIFICATIONS ***********************/
;/*									*/
;/* SUBROUTINE NAME:  BvsGetConfig					*/
;/*									*/
;/* DESCRIPTIVE NAME:  Base Video Subsystem Get Video Configuration	*/
;/*									*/
;/* FUNCTION:  Returns the current video configuration			*/
;/*									*/
;/* NOTES:  Executes on Level 3 					*/
;/*									*/
;/* ENTRY POINT:  BvsGetConfig						*/
;/*   LINKAGE:	Call BvsGetConfig from BvsMain				*/
;/*									*/
;/* INPUT:  StackFrame and Registers (see BVSMAIN) with:		*/
;/*	parmn	= Offset of font ptr return area			*/
;/*	parmnm1 = Selector of font ptr return area			*/
;/*	parmnm2 = Adapter number (0=Current, 1=Primary, 2=Secondary)	*/
;/*									*/
;/* EXIT-NORMAL:  AX = 0						*/
;/*									*/
;/* EXIT-ERROR: None							*/
;/*									*/
;/* INPUT:  None							*/
;/*									*/
;/* EXIT-NORMAL:  AX = 0						*/
;/*									*/
;/* EXIT-ERROR:  ERROR_VIO_PARMS					*/
;/*									*/
;/* EFFECTS:  None							*/
;/*									*/
;/* INTERNAL REFERENCES:  PPBVSCB, BVSCBsg, LVBsg			*/
;/*   ROUTINES:  None							*/
;/*									*/
;/* EXTERNAL REFERENCES:  None						*/
;/*   ROUTINES:  None							*/
;/*									*/
;/************************ END OF SPECIFICATIONS ************************/

;Begin BvsGetConfig
;    Preset return code to ERROR_VIO_INVALID_PARMS
;    If the requested configuration is valid
;	 Call ReturnConfigInfo in the VDH
;	 If the return code is zero
;	     Place the config number in the user's data
;	 Endif
;    Endif
;End BvsGetConfig

BvsGetConfig PROC NEAR
	PUBLIC	BvsGetConfig

	mov	ax,ERROR_VIO_INVALID_PARMS ;Preset error
	mov	dx,[bp].gc_confignum
	.if	<dx be [bx].bvs_numconfigs> near ;Valid config number	;@T45
	    push    [bx].bvs_curconfig
	    .if     <nonzero dx>	;Not a default request
		mov	[bx].bvs_curconfig,dx ;Change current config
	    .endif

	    .if     <[bx].bvs_curconfig eq bx> near ;Windowed session ;@@A ;@B49
		push	ds		;@@A
		push	BVSGSEG 	;@@A
		pop	ds		;@@A
		les	di,dword ptr [bp].p_offset			;@T45
		push	di						;@T45
		mov	cx,es:[di].cf_length				;@T45
		mov	ax,ERROR_VIO_INVALID_LENGTH			;@T45
		.if	<cx a 1>
		    mov     si,offset WndwConfig			;@T45
		    mov     ax,cx					;@T45
		    .if     <al a <size configdata>>			;@T45
			mov	al,cf_confignum 			;@T45
		    .endif						;@T45

		    push    di						;@T45
		    sub     al,size cf_length				;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_adapter				;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_display				;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_memory				;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_confignum			;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_version				;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_flags				;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_envsize				;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_fullsize 			;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_partsize 			;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_adapteroff			;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_displayoff			;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_lemadapterdata			;@B49
		    .if     <ns>					;@B49
			movsw						;@B49
		    .endif						;@B49

		    sub     al,size cf_emadapters			;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
		    .endif						;@T45

		    sub     al,size cf_lemdisplaydata			;@B49
		    .if     <ns>					;@B49
			movsw						;@B49
		    .endif						;@B49

		    sub     al,size cf_emdisplays			;@T45
		    .if     <ns>					;@T45
			movsw						;@T45
		    .endif						;@T45

		    mov     ax,di					;@T45
		    pop     di						;@T45
		    sub     ax,di					;@T45
		    .if     <al a 2>	;More than just a length request;@T45
			stosw		;Update length in Mode data	;@T45
		    .endif						;@T45

		    sub     ax,ax	;Set good return code		;@T45
		.endif							;@T45
		pop	si						;@T45
		pop	ds						;@T45
	    .else							;@T45
		les	si,dword ptr [bp].p_offset
		mov	cx,es:[si].cf_length ;Get config data length
		mov	[bp].vp_offset,si
		mov	[bp].vp_selector,es ;Set the config data pointer

		mov	di,fn_GetConfig
		Call	AllVDH
	    .endif							;@T45
	    .if     <zero ax>		;No error
		.if	<cx ne 2> and	;@S25
		.if	<es:[si].cf_length ae cf_confignum+2> ;Enough room ;@S25
		    mov     dx,[bx].bvs_curconfig
		    mov     es:[si].cf_confignum,dx ;Update config number
		.endif
	    .endif

	    pop     [bx].bvs_curconfig
	.endif
	ret				;Return to caller
BvsGetConfig ENDP

BVS3SEG ENDS
	END

;@@A = 12/02/88 STJ, Return shell's config for windows, P2813
;@T8 = 12/22/88 TPL, Setup the correct row, column and count for AVIO, P3311
;@@B = 01/18/89 CJJ, Commented out because was clearing error codes
;@C4 = 02/08/89 CJJ, For GetBuf check if session is in foreground and if so
;		     SaveEnv otherwise just return LVB,  PTR 3813
;@C8 = 03/07/89 CJJ, If wrtthru flag not on or not foreground session
;  PTR 700456	     then just return, mask out odd bit for odd offsets and
;		     add 1 to length for odd lengths since moves are based on
;		     words - if even the 1 is masked out when divided by 2
;@TB5 = 03/24/89 TLB, Add check for screen group 1 and writethru flag set
;		       PTR B783228
;@B1 = 04/20/89 WKB, Bypass LVB/PVB sync if it has already been done ,B701124
;@C19 05/01/89	CJJ, Don't adjust length for WriteCellStr, HM00550
;B704999 = 07/20/89 STJ, Let BVH validate support of graphics ShowBuf
;@S25 = 08/18/89 STJ, Use 1.0 length as default for GetXXXX calls, B706860
;@T45 = 08/31/89 TPL, Don't load other BVHs when starting VIO Wndw, B707495
;@D549 = 11/02/89 CJJ, 2.0 UNIQUE - Support rangeless sessions, DCR 549
;@B30 = 12/01/89 WKB, Allow VIOSHOWBUF updates in WINDOW and AVIO, B787183
;@T52 = 01/16/90 TPL, 2.0 UNIQUE - DCR 704 work
;@B44 = 02/12/90 WKB, Don't increment length when eq 65535, B787909
;@B49 = 03/16/90 WKB, Correct GetConfig for windowed processes, B712006
;@B51 = 04/03/90 WKB, Mask off odd bit for vioshowbuf, B788869
;@T49 = 05/18/90 TPL, Should allow VIO/AVIO to showbuf in BG, SM89548
;B790152 = 07/31/90 WKB, Return correct number of bytes in LVB, B790152
;B790216 = 08/23/90 WKB, Changes from Takumi(MS)
;B790219 = 08/23/90 WKB, Changes from Takumi(MS)
