[comp.os.minix] EGA bug fix

hubble@cae780.UUCP (04/13/87)

The EGA problem, as I mentioned in my earlier posting, was with the way the
EGA treats the video origin.  I have changed the way MINIX does it's screen
scrolling to cure the problem.  Two routines were added to klib88.s:

        1)  _scr_up   Scroll page zero up one line
        2)  _scr_dn   Scroll page zero down one line

These are brute force assembly routines that simply move all characters in
the video ram page zero up or down one line as required.  One would expect
this to be slower than just changing the video origin register; however,
I was able to notice no performance degradation.  There must be enough
overhead elsewhere that this gets lost in the noise.

Then, the terminal driver, tty.c, was modified to call these new assembly
routines.  I have included the complete new routine to replace the existing
routine:
 
       1)  scroll_screen   Modified to call scr_up and scr_dn for scrolling

I have tagged the source for all three routines on the end of this message.
The changes work on my clone EGA and I believe they should also work on
all CGA's and Mono graphic adapters.  However, I do not have the hardware
to test that belief.

A couple of other points:
       1)  Since the EGA does not suffer from "snow", the wait for vertical
           retrace in the _vid_copy routine of klib88.s can be deleted.
           This improves performance but would break on normal CGA's.
       2)  As far as I could tell, the variable tty_struct[n].tty_org was
           never initialized.  This seemed to have no effect, but I 
           initialized it in tty_init for good measure.

Source of the three routines follow:

----------------------------------------------------------------------------

Add the following routines (_scr_up and _scr_dn) to kernel/MINIX/klib88.s.
Don't forget to add their names to one of the ".globl" statements near the
beginning of the file.

----------------------------------------------------------------------------


|*===========================================================================*
|*				scr_up  				     *
|*===========================================================================*
| This routine scrolls the screen up one line on an EGA display 
| 
| The call is:
|     scr_up(org)
| where
|     'org'       is the video segment origin of the desired page

_scr_up:
	push bp			| we need bp to access the parameters
	mov bp,sp		| set bp to sp for indexing
	push si			| save the registers
	push di			| save di
	push cx			| save cx
	push es			| save es
	push ds			| save ds
	mov si,#160		| si = pointer to data to be copied
	mov di,#0		| di = offset within video ram
	mov cx,#1920		| cx = word count for copy loop

	pushf			| copying may now start; save flags
	cli			| interrupts just get in the way: disable them
	mov ax,4(bp)
	mov es,ax		| load es now: int routines may ruin it
	mov ds,ax

	rep			| this is the copy loop
	movw			| ditto

	popf			| restore flags
	pop ds			| restore ds
	pop es			| restore es
	pop cx			| restore cx
	pop di			| restore di
	pop si			| restore si
	pop bp			| restore bp
	ret			| return to caller

|*===========================================================================*
|*				  scr_dn				     *
|*===========================================================================*
| This routine scrolls the screen down one line on an EGA display 
| 
| The call is:
|     scr_dn(org)
| where
|     'org'       is the video segment origin of the desired page

_scr_dn:
	push bp			| we need bp to access the parameters
	mov bp,sp		| set bp to sp for indexing
	push si			| save the registers
	push di			| save di
	push cx			| save cx
	push es			| save es
	push ds			| save ds
	mov si,#3838		| si = pointer to data to be copied
	mov di,#3998		| di = offset within video ram
	mov cx,#1920		| cx = word count for copy loop

	pushf			| copying may now start; save flags
	cli			| interrupts just get in the way: disable them
	mov ax,4(bp)
	mov es,ax		| load es now: int routines may ruin it
	mov ds,ax

	std
	rep			| this is the copy loop
	movw			| ditto

	popf			| restore flags
	pop ds			| restore ds
	pop es			| restore es
	pop cx			| restore cx
	pop di			| restore di
	pop si			| restore si
	pop bp			| restore bp
	ret			| return to caller

----------------------------------------------------------------------------

Replace the existing scroll_screen routine (in kernel/tty.c) with the
following one:

----------------------------------------------------------------------------


/*===========================================================================*
 *				scroll_screen				     *
 *===========================================================================*/
PRIVATE scroll_screen(tp, dir)
register struct tty_struct *tp;	/* pointer to tty struct */
int dir;			/* GO_FORWARD or GO_BACKWARD */
{
  if (dir == GO_FORWARD)
       {
	scr_up(vid_base);
	vid_copy(NIL_PTR, vid_base, tp->tty_org + 2*(SCR_LINES-1)*LINE_WIDTH,
          LINE_WIDTH);
       }
  else
       {
	scr_dn(vid_base);
	vid_copy(NIL_PTR, vid_base, tp->tty_org, LINE_WIDTH);
       }
}

----------------------------------------------------------------------------

I hope this helps solve other's EGA problems.


                                                  Good Luck!
                                                  Larry R. Hubble
                                         {hplabs, tektronix}!hubble@cae780