/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:ibm8514.c 12.0$ */
/* $ACIS:ibm8514.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/standatr/RCS/ibm8514.c,v $ */

#ifndef lint
static char *rcsid = "$Header:ibm8514.c 12.0$";
#endif

#include "ibmvbarmmmdxiv.h"
#if NIBMVBARMMMDXIV > 0
#include "screen_conf.h"
#include "consdefs.h"
#include "sa.h"

#include "../ca_atr/ibm8514.h"
#include "../ca_atr/pcif.h"
#include "../pc_code/vga.h"

extern struct screen_info cons_info;
extern struct postconfig post_config;

int ibm8514_screen_type = SCREEN_TYPE_NONE;
struct ibm8514_color ibm8514_color_array[IBM8514_MAX_COLORS];
static unsigned ibm8514_plane_mask;
static int ibm8514_x = 0;
static int ibm8514_y = 0;
static int ibm8514_cursor_state = 0;
static int ibm8514_init = 0;
static int ibm8514_fgbg;
static struct ibm8514_color ibm8514_mono_red = 
	{ IBM8514_COLOR_MASK, IBM8514_COLOR_MASK, 0 };
static struct ibm8514_color ibm8514_cursor_fg = 
	{ 0, IBM8514_COLOR_MASK, IBM8514_COLOR_MASK };
static struct ibm8514_color ibm8514_cursor_bg = 
	{ IBM8514_COLOR_MASK, 0, 0 };
static struct ibm8514_color ibm8514_mcursor_fg = 
	{ 0, 0, IBM8514_COLOR_MASK };
static struct ibm8514_color ibm8514_mcursor_bg = 
	{ IBM8514_COLOR_MASK, IBM8514_COLOR_MASK, 0 };

static int 	ibm8514_win;
static struct vga_params *ibm8514_pc;
static struct vga_params ibm8514_pc_fake;


#define	ibm8514_cursor_on()  (ibm8514_cursor_state = (ibm8514_cursor_state ? 1: \
	  (ibm8514_lo_cursor(ibm8514_x,ibm8514_y,IBM8514_CURSOR_MASK),1)))
#define	ibm8514_cursor_off()  (ibm8514_cursor_state = (!ibm8514_cursor_state ? 0: \
	  (ibm8514_lo_cursor(ibm8514_x,ibm8514_y,IBM8514_CURSOR_MASK),0)))

#ifdef KERNEL
#define LP_PUT(si, c) lp_put(si, c)
#define	PUT_STATUS(si, col, str) put_status(si, col, str)
#else  /* assume STANDALONE */
#define LP_PUT(si, c) lp_put(c)
#define	PUT_STATUS(si, col, str) put_status(col, str)
#endif KERNEL
extern	int	lpstatus;

/*
 * this array is for storing characters to be printed with print screen
 */
struct ibm8514_save_buf ibm8514_save_screen[IBM8514_MAX_COLUMN*IBM8514_MAX_ROW];
int  ibm8514_save_pos;    /* cursor location */

ibm8514_probe(offset)
	unsigned	offset;
{
	volatile unsigned *addr = (volatile unsigned *)(offset + pcif_io_hw);
	ibm8514_init = 0; /* paranoia */
	return((*addr & IBM8514_PROBE_OUT) != IBM8514_PROBE_OUT);
}

ibm8514_screen_init()
{
	int	old_window = get_512_window();
	int size,i;

	/*
	 * BIOSENT is the screen data area  for ALL screens
	 */
	ibm8514_win = get_pc_cb(BIOSENT);
	if (post_config.os_type != OLD_TYPE) {
		ibm8514_pc = (struct vga_params *)(set_512_window(ibm8514_win)+
			pcif_512_fw);
	} else {
		ibm8514_pc = &ibm8514_pc_fake;
		ibm8514_pc->write_status = VGA_WRITE_OK;
	}

	ibm8514_cursor_state = 1;
        ibm8514_x = 0;
	ibm8514_y = 0;
	ibm8514_save_pos = 0;
	bzero(ibm8514_color_array,sizeof(ibm8514_color_array));

	/*
	 * clear the screen buffer
	 */
	size = screen_sw[CONS_IBM8514].width*screen_sw[CONS_IBM8514].lines;
	for (i=0; i < size; i++) {
		ibm8514_save_screen[i].ch = ' ';
		ibm8514_save_screen[i].attr = 0;
		ibm8514_save_screen[i].fg = 0;
	    	ibm8514_save_screen[i].bg = 0;
	}
	ibm8514_screen_type = ibm8514_get_type();

	/*
	 * initialize the screen if we're in the foreground
	 */	
	if (ibm8514_pc->write_status == VGA_WRITE_OK) {
		ibm8514_fgbg = IBM8514_FOREGROUND;
		ibm8514_do_init();
	  	ibm8514_lo_cursor(ibm8514_x,ibm8514_y,IBM8514_CURSOR_MASK);
	} else {
		ibm8514_fgbg = IBM8514_BACKGROUND;
	}

	/*
	 * on startup we need to steal the console focus
	 * from the vga if we have a display...
	 */
	if (!(ibm8514_init++)) {
		if (ibm8514_screen_type != SCREEN_TYPE_NONE) {
			/* make sure the 8514 gets the default input focus */
			cons_info.which_screen = NO_ENTRY;
		}
	}
	set_512_window(old_window);
	return(0);
}

/*
 * check if the color in index "i" is null
 */
int
ibm8514_color_null(i)
	int i;
{

	if (ibm8514_color_array[i].red) {
		return(0);
	}
	if (ibm8514_color_array[i].blue) {
		return(0);
	}
	if (ibm8514_color_array[i].green) {
		return(0);
	}
	return(1);
}

ibm8514_do_init()
{
	int	cursor_fg,cursor_bg;
	struct ibm8514_color ibm8514_tmp_array[IBM8514_MAX_COLORS];
	int	i;

	ibm8514_screen_type = ibm8514_get_type();

	ibm8514_plane_mask = ibm8514_lo_init(ibm8514_screen_type,ibm8514_tmp_array);
	/*screen_sw[CONS_IBM8514].color_entries = ibm8514_plane_mask+1;*/
	if (ibm8514_screen_type != SCREEN_TYPE_COLOR) {
		ibm8514_set_color(ibm8514_screen_type,
				SCREEN_RED,&ibm8514_mono_red);
	}
	/* color the cursor */
	cursor_fg = ibm8514_plane_mask ^ IBM8514_CURSOR_MASK;
	cursor_bg = IBM8514_CURSOR_MASK;
	if (ibm8514_color_null(cursor_fg)) {
		if (ibm8514_screen_type != SCREEN_TYPE_COLOR) {
			ibm8514_color_array[cursor_fg] = ibm8514_mcursor_fg;
		} else {
			ibm8514_color_array[cursor_fg] = ibm8514_cursor_fg;
		}
	}
	if (ibm8514_color_null(cursor_bg)) {
		if (ibm8514_screen_type != SCREEN_TYPE_COLOR) {
			ibm8514_color_array[cursor_bg] = ibm8514_mcursor_bg;
		} else {
			ibm8514_color_array[cursor_bg] = ibm8514_cursor_bg;
		}
	}
	ibm8514_set_color(ibm8514_screen_type,cursor_fg,
				&ibm8514_color_array[cursor_fg]);
	ibm8514_set_color(ibm8514_screen_type,cursor_bg,
				&ibm8514_color_array[cursor_bg]);
	for (i=0; i < IBM8514_MAX_COLORS; i++) {
		if (ibm8514_color_null(i)) {
			ibm8514_color_array[i] = ibm8514_tmp_array[i];
		} else {
			ibm8514_set_color(ibm8514_screen_type,i,
						&ibm8514_color_array[i]);
		}
	}
#ifdef BLACK_ON_WHITE
	ibm8514_color_table(0,ibm8514_plane_mask,0,0,REVERSE_COLOR);
#endif
}

/*
 * restore the screen. do init puts the 8514 back into 
 */
ibm8514_screen_restore()
{
	register int i,y,x,width;
	int	size;

	ibm8514_fgbg = IBM8514_FOREGROUND;
	ibm8514_do_init();
	width = screen_sw[CONS_IBM8514].width;
	size = width*screen_sw[CONS_IBM8514].lines;
	x = 0; y=0;
	for (i=0; i < size; i++) {
		ibm8514_lo_putc(x,y,ibm8514_save_screen[i].ch,
			ibm8514_save_screen[i].attr,ibm8514_save_screen[i].fg,
						     ibm8514_save_screen[i].bg);
		if (++x >= width) {
			y++; x=0;
		}
	}
	if (ibm8514_cursor_state) {
	  ibm8514_lo_cursor(ibm8514_x,ibm8514_y,IBM8514_CURSOR_MASK);
	} 
	return(1);
}

ibm8514_get_type()
{
	/*
	 * find out the type of  display connected
	 */
	switch (INW(IBM8514_CONFIG) & IBM8514_DISPLAY_BITS) {
		case	IBM8514_COLOR1:
		case	IBM8514_COLOR2:
			return(SCREEN_TYPE_COLOR);
			/* break; */
		case	IBM8514_GRAY1:
		case	IBM8514_GRAY2:
		case	IBM8514_GRAY19:
			return(SCREEN_TYPE_MONO);
			/* break; */
		default:
			return(SCREEN_TYPE_NONE);
	}
}

ibm8514_screen_putc(ch,attr)
	char	ch;
	int	attr;
{
	unsigned int	fg_color = ibm8514_plane_mask;
	unsigned int	bg_color = 0;;
	int old_window = get_512_window();

	if (attr & REVERSE_VIDEO) {
		register unsigned	tmp_color = fg_color;
		fg_color = bg_color;
		bg_color = tmp_color;
		attr &= ~REVERSE_VIDEO;
	}
	fg_color &= ibm8514_plane_mask;
	bg_color &= ibm8514_plane_mask;
	ibm8514_save_screen[ibm8514_save_pos].ch = ch;
	ibm8514_save_screen[ibm8514_save_pos].bg = bg_color;
	ibm8514_save_screen[ibm8514_save_pos].fg = fg_color;
	ibm8514_save_screen[ibm8514_save_pos].attr = attr;

	set_512_window(ibm8514_win);
	if (ibm8514_pc->write_status == VGA_WRITE_OK) {
		if (!IBM8514_IN_FOREGROUND)  {
			screen_redraw();
		}
		ibm8514_fgbg = IBM8514_FOREGROUND;
		ibm8514_cursor_off();
		ibm8514_lo_putc(ibm8514_x,ibm8514_y,ch,attr,fg_color,bg_color);
	} else {
		ibm8514_fgbg = IBM8514_BACKGROUND;
		ibm8514_cursor_state = 0;
	}
	set_512_window(old_window);
	
}

ibm8514_pos_cursor(column,line)
	int	column,line;
{
	int old_window = get_512_window();
	set_512_window(ibm8514_win);
	if (ibm8514_pc->write_status == VGA_WRITE_OK) {
		if (!IBM8514_IN_FOREGROUND)  {
			screen_redraw();
		}
		ibm8514_fgbg = IBM8514_FOREGROUND;
		ibm8514_cursor_off();
		ibm8514_x = column;
		ibm8514_y = line;
		ibm8514_cursor_on();
	} else {
		ibm8514_fgbg = IBM8514_BACKGROUND;
		ibm8514_cursor_state = 1;
		ibm8514_x = column;
		ibm8514_y = line;
	}
	set_512_window(old_window);
 	ibm8514_save_pos = lp_pos_cursor(column,line,CONS_IBM8514);
}


ibm8514_screen_blank(attr,sline,scol,eline,ecol)
	int attr;   /* attribute of how to clear the screen */
	int sline,scol; /* The starting line and column */
	int eline,ecol; /* The ending line and column */
{
	unsigned fg_color = ibm8514_plane_mask;
	unsigned bg_color = 0;
	register int i;
	int	end = lp_pos_cursor(ecol,eline,CONS_IBM8514);
	int old_window = get_512_window();

	if (attr & REVERSE_VIDEO) {
		unsigned tmp_color = fg_color;
		fg_color = bg_color;
		bg_color = tmp_color;
	}
	fg_color &= ibm8514_plane_mask;
	bg_color &= ibm8514_plane_mask;
	for (i=lp_pos_cursor(scol,sline,CONS_IBM8514); i < end; i++) {
		ibm8514_save_screen[i].ch = ' ';
		ibm8514_save_screen[i].bg = bg_color;
		ibm8514_save_screen[i].fg = fg_color;
		ibm8514_save_screen[i].attr = attr;
	}
		
	set_512_window(ibm8514_win);
	if (ibm8514_pc->write_status == VGA_WRITE_OK) {
		if (!IBM8514_IN_FOREGROUND)  {
			screen_redraw();
		}
		ibm8514_fgbg = IBM8514_FOREGROUND;
		ibm8514_cursor_off();
		ibm8514_lo_blank(attr,sline,scol,eline,ecol,fg_color,bg_color);
	} else {
		ibm8514_fgbg = IBM8514_BACKGROUND;
		ibm8514_cursor_state = 0;
	}
	set_512_window(old_window);
}

ibm8514_screen_move(line_top,line_bottom,line_dest)
	int line_top,line_bottom,line_dest;
{
	register int width = screen_sw[CONS_IBM8514].width;
	int old_window = get_512_window();

	/*
	 * scroll the buffer first
	 */
	if ((line_dest > line_top) && (line_dest < line_bottom)) {
		register char *start,*end,*next;
		end = (char *)&ibm8514_save_screen[line_top*width];
		next = (char *)&ibm8514_save_screen[(line_dest+
				         (line_bottom-line_top)+1) * width -1];
		for (start = ((char *)&ibm8514_save_screen[
			(line_bottom+1)*width])-1; start >= end; start--,next--)
			*next = *start;
	} else {
		bcopy(&ibm8514_save_screen[line_top*width],&ibm8514_save_screen
			[line_dest*width],((line_bottom-line_top)+1)*width
				*sizeof(struct ibm8514_save_buf));
	}

	/* now do the real screen */
	set_512_window(ibm8514_win);
	if (ibm8514_pc->write_status == VGA_WRITE_OK) {
		if (!IBM8514_IN_FOREGROUND)  {
			screen_redraw();
		}
		ibm8514_fgbg = IBM8514_FOREGROUND;
		ibm8514_cursor_off();
		ibm8514_lo_move(line_top,line_bottom,line_dest);
	} else {
		ibm8514_fgbg = IBM8514_BACKGROUND;
		ibm8514_cursor_state = 0;
	}
	set_512_window(old_window);
}

ibm8514_color_table(attr,flag)
	int flag,attr;
{
	unsigned entry;
	unsigned FG = ibm8514_plane_mask;
	unsigned BG = 0;
	struct ibm8514_color *cp;

	switch (flag) {
	/* reverse the foreground and background color entries */
	case REVERSE_COLOR:
		{
		struct ibm8514_color tmp;
		FG  &= ibm8514_plane_mask;
		BG &= ibm8514_plane_mask;
		tmp = ibm8514_color_array[FG];
		ibm8514_color_array[FG] = ibm8514_color_array[BG];
		ibm8514_color_array[BG] = tmp;
		if (IBM8514_IN_FOREGROUND) {
			ibm8514_set_color(ibm8514_screen_type,FG,
						&ibm8514_color_array[FG]);
			ibm8514_set_color(ibm8514_screen_type,BG,
						&ibm8514_color_array[BG]);
		}
		return(0);
		}
	/* increment foreground or background color */
	case COLOR_FG_INC:
	case COLOR_BG_INC:
		if (flag == COLOR_BG_INC) {
			entry = BG;
		} else {
			entry = FG;
		}
		cp = &ibm8514_color_array[entry];
		cp->blue++;
		if (cp->blue > IBM8514_COLOR_MASK ) {
			cp->blue &= IBM8514_COLOR_MASK;
			cp->green++;
			if (cp->green >= IBM8514_COLOR_MASK) {
				cp->green &= IBM8514_COLOR_MASK;
				cp->red++;
				cp->red &= IBM8514_COLOR_MASK;
			}
		}
		if (IBM8514_IN_FOREGROUND) {
			ibm8514_set_color(ibm8514_screen_type,entry,cp);
		}
		break;
	/* increment foreground or background color */
	case COLOR_FG_DEC:
	case COLOR_BG_DEC:
		if (flag == COLOR_BG_DEC) {
			entry = BG;
		} else {
			entry = FG;
		}
		cp = &ibm8514_color_array[entry];
		cp->blue--;
		if (cp->blue < 0x0 ) {
			cp->blue &= IBM8514_COLOR_MASK;
			cp->green--;
			if (cp->green < 0x0) {
				cp->green &= IBM8514_COLOR_MASK;
				cp->red--;
				cp->red &= IBM8514_COLOR_MASK;
			}
		}
		if (IBM8514_IN_FOREGROUND) {
			ibm8514_set_color(ibm8514_screen_type,entry,cp);
		}
		break;
	/* don't handle anything else */
	default:
		return(-1);
	}
}

ibm8514_screen_print(si,flags)
register SCREEN_INFO *si;
{
	register int l, x;
	int	length = screen_sw[CONS_IBM8514].lines;
	int	width = screen_sw[CONS_IBM8514].width;

	for (l=0; l < length*width; l+=width) {
		for (x=0; x < width; x++) {
			if (LP_PUT(si,ibm8514_save_screen[x+l].ch)) {
				delay(250);
				goto done;
			}
		}
		LP_PUT(si,'\r');
		LP_PUT(si,'\n');
	}
	LP_PUT(si,'\f');
done:
	PUT_STATUS(si, 33, "         ");
	lpstatus = -1;
}
#endif
