/* $Header:screen_conf.c 12.0$ */
/* $ACIS:screen_conf.c 12.0$ */
/* $Source: /ibm/acis/usr/sys/standatr/RCS/screen_conf.c,v $ */

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

/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION 1986,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */

#include "sa.h"

int screen_lines;	/* So someone can find out */

#include "param.h"
#include "errno.h"
#include "uio.h"
#include "../machine/led.h"

#include "screen_conf.h"
#include "consdefs.h"

/* Common routines for table */
int screen_probe();			/* Generic screen probe routine */
int nulldev();				/* Returns False (0) */
int nodev();				/* Returns NODEV */


#include "mono.h"
#if NMONO > 0

int mono_probe();
int mono_screen_init();
int mono_screen_putc();
int mono_screen_print();
int mono_pos_cursor();
#define mono_pos_loc nodev
int mono_screen_blank();
int mono_screen_move();
#define mono_screen_restore nodev
#else
#define mono_probe nulldev
#define mono_screen_init nodev
#define mono_screen_putc nodev
#define mono_screen_print nodev
#define mono_pos_cursor nodev
#define mono_pos_loc nodev
#define mono_screen_blank nodev
#define mono_screen_move nodev
#define mono_screen_restore nodev
#endif NMONO

#include "ega.h"
#if NEGA > 0
int ega_probe();
int ega_screen_init();
int ega_screen_putc();
#define ega_screen_print nodev
int ega_pos_cursor();
#define ega_pos_loc nodev
int ega_screen_blank();
int ega_screen_move();
int ega_fgbg();
#define ega_screen_restore nodev
#else
#define ega_probe nulldev
#define ega_screen_init nodev
#define ega_screen_putc nodev
#define ega_screen_print nodev
#define ega_pos_cursor nodev
#define ega_pos_loc nodev
#define ega_screen_blank nodev
#define ega_screen_move nodev
#define ega_fgbg nodev
#define ega_screen_restore nodev
#endif NEGA

#include "vga.h"
#include "pcbios.h"
#if ( (NVGA > 0) && (NPCBIOS > 0) )
int vga_probe();
int vga_screen_init();
int vga_sa_screen_putc();
int vga_pos_cursor();
#define vga_pos_loc nodev
int vga_sa_screen_blank();
int vga_screen_move();
int vga_screen_print();
int vga_sa_color_table();
int vga_screen_restore();
#else
#define vga_probe nulldev
#define vga_screen_init nodev
#define vga_sa_screen_putc nodev
#define vga_screen_print nodev
#define vga_pos_cursor nodev
#define vga_pos_loc nodev
#define vga_sa_screen_blank nodev
#define vga_screen_move nodev
#define vga_sa_color_table nodev
#define vga_screen_restore nodev
#endif ( (NVGA > 0) && (NPCBIOS > 0) )

#include "ibmvbarmmmdxiv.h"
#if  (NIBMVBARMMMDXIV > 0) 
int ibm8514_probe();
int ibm8514_screen_init();
int ibm8514_screen_putc();
int ibm8514_pos_cursor();
#define ibm8514_pos_loc nodev
int ibm8514_screen_blank();
int ibm8514_screen_move();
int ibm8514_screen_print();
int ibm8514_color_table();
int ibm8514_screen_restore();
#else
#define ibm8514_probe nulldev
#define ibm8514_screen_init nodev
#define ibm8514_screen_putc nodev
#define ibm8514_screen_print nodev
#define ibm8514_pos_cursor nodev
#define ibm8514_pos_loc nodev
#define ibm8514_screen_blank nodev
#define ibm8514_screen_move nodev
#define ibm8514_color_table nodev
#define ibm8514_screen_restore nodev
#endif (NIBMVBARMMMDXIV > 0) 

#include "aed.h"
#if NAED > 0
int aed_probe();
int aed_screen_init();
int aed_screen_putc();
int aed_screen_print();
int apav_init();
int apav_pos_loc();
int apav_load_loc();
#define aed_init_loc nodev
#define aed_pos_loc  nodev
#define aed_load_loc nodev
#define aed_pos_cursor nodev
#define aed_screen_blank nodev
#define aed_screen_move nodev
#define aed_screen_restore nodev
#else
#define aed_probe nulldev
#define aed_screen_init nodev
#define aed_screen_putc nodev
#define aed_screen_print nodev
#define aed_pos_cursor nodev
#define aed_init_loc nodev
#define aed_pos_loc nodev
#define aed_load_loc nodev
#define aed_screen_blank nodev
#define aed_screen_move nodev
#define aed_screen_restore nodev
#endif NAED

#include "apaeight.h"
#if NAPAEIGHT > 0
int apa8_probe();
int apa8_screen_init();
int apa8_screen_putc();
int apa8_pos_cursor();
int apa8_screen_blank();
int apa8_screen_move();
#define apa8_init_loc nodev
#define apa8_pos_loc nodev
#define apa8_load_loc nodev
#define apa8_screen_print nulldev
#define apa8_screen_restore nodev
#else
#define apa8_probe nulldev
#define apa8_screen_init nodev
#define apa8_screen_putc nodev
#define apa8_screen_print nodev
#define apa8_pos_cursor nodev
#define apa8_screen_blank nodev
#define apa8_screen_move nodev
#define apa8_init_loc nodev
#define apa8_pos_loc nodev
#define apa8_load_loc nodev
#define apa8_screen_restore nodev
#endif NAPAEIGHT


#include "apasixteen.h"
#if NAPASIXTEEN > 0
int apa16_probe();
int apa16_screen_init();
int apa16_screen_putc();
int apa16_pos_cursor();
int apa16_screen_blank();
int apa16_screen_move();
#define apa16_init_loc nodev
#define apa16_pos_loc nodev
#define apa16_load_loc nodev
#define apa16_screen_print nodev
#define apa16_screen_restore nodev
#else
#define apa16_probe nulldev
#define apa16_screen_init nodev
#define apa16_screen_putc nodev
#define apa16_screen_print nodev
#define apa16_pos_cursor nodev
#define apa16_screen_blank nodev
#define apa16_screen_move nodev
#define apa16_init_loc nodev
#define apa16_pos_loc nodev
#define apa16_load_loc nodev
#define apa16_screen_restore nodev
#endif NAPASIXTEEN

#include "apaeightc.h"
#if NAPAEIGHTC > 0
int apa8C_probe();
int apa8C_screen_init();
int apa8C_screen_putc();
int apa8C_pos_cursor();
int apa8C_screen_blank();
int apa8C_screen_move();
#define apa8C_init_loc nodev
#define apa8C_pos_loc nodev
#define apa8C_load_loc nodev
#define apa8C_screen_print nulldev
#define apa8C_screen_restore nodev
#else
#define apa8C_probe nulldev
#define apa8C_screen_init nodev
#define apa8C_screen_putc nodev
#define apa8C_pos_cursor nodev
#define apa8C_pos_loc nodev
#define apa8C_screen_blank nodev
#define apa8C_screen_move nodev
#define apa8C_init_loc nodev
#define apa8C_pos_loc nodev
#define apa8C_load_loc nodev
#define apa8C_screen_print nulldev
#define apa8C_screen_restore nodev
#endif NAPAEIGHTC

/*  Console screen switch table to support different heads */
#ifndef ATR_NEW
/*  ATR version will replace the rwaddr with the window offset */
#endif ATR_NEW

struct screen_sw screen_sw[] = {
/*  ENTRY	NAME		PROBE
	INIT				PUTC				POS_CUR
	BLANK				MOVE				PRINT
	RWADDR				LINES, WIDTH, VBITS, HBITS,  FLAGS
	DEF_OUTE			INIT_LOC			POS_LOC
	LOAD_LOC			FG_BG		SCREEN_ADDR
*/
{ /* 0 */	"aed",          aed_probe,
	aed_screen_init,	aed_screen_putc,	aed_pos_cursor,
	aed_screen_blank,	aed_screen_move,	aed_screen_print,
	C (0x0a4020 + MEM_BASE),		53,	80,	800,	1024,	0,
	E_STDOUTPUT,		aed_init_loc,		aed_pos_loc,
	aed_load_loc,		nulldev,	C ( 0x000A4020 + MEM_BASE),
	aed_screen_restore,
},

{ /* 1 */	"apa16",        apa16_probe,
	apa16_screen_init,	apa16_screen_putc,	apa16_pos_cursor,
	apa16_screen_blank,	apa16_screen_move,	apa16_screen_print,
	C 0xf4d80000,		33,	80,	768,	1024,	0,
	E_IBMOUTPUT,		apa16_init_loc, 	apa16_pos_loc,
	apa16_load_loc, 	nulldev,	C ( 0x00D80000 + MEM_BASE),
	apa16_screen_restore,
},

{ /* 2 */	"apa8c",        apa8C_probe,
	apa8C_screen_init,	apa8C_screen_putc,	apa8C_pos_cursor,
	apa8C_screen_blank,	apa8C_screen_move,	apa8C_screen_print,
	C 0xf4d20000,		32,	80,	512,	720,	0,
	E_IBMOUTPUT,		apa8C_init_loc, 	apa8C_pos_loc,
	apa8C_load_loc, 	nulldev,	C ( 0x00D20000 + MEM_BASE),
	apa8C_screen_restore,
},

{ /* 3 */	"apa8",         apa8_probe,
	apa8_screen_init,	apa8_screen_putc,	apa8_pos_cursor,
	apa8_screen_blank,	apa8_screen_move,	apa8_screen_print,
	C 0xf4d00000,		32,	80,	512,	720,	0,
	E_IBMOUTPUT,		apa8_init_loc,		apa8_pos_loc,
	apa8_load_loc,		nulldev,	C ( 0x00D00000 + MEM_BASE),
	apa8_screen_restore,
},

{ /* 4 */	"ega",          ega_probe,
	ega_screen_init,	ega_screen_putc,	ega_pos_cursor,
	ega_screen_blank,	ega_screen_move,	ega_screen_print,
	C 0xf40b8000,		25,	80,	350,	640,	0,
	E_IBMOUTPUT,		nulldev,		nulldev,
	nulldev,		ega_fgbg,	C ( 0x000B8000 + MEM_BASE),
	ega_screen_restore,
},
{ /* 5 */	"monochrome",   mono_probe,
	mono_screen_init,	mono_screen_putc,	mono_pos_cursor,
	mono_screen_blank,	mono_screen_move,	mono_screen_print,
	C 0xf40b0000,		25,	80,	25,	80,	0,
	E_IBMOUTPUT,		nulldev,		nulldev,
	nulldev,		nulldev,	C ( 0x000b0000 + MEM_BASE),
	mono_screen_restore,
},

{ /* 6 */	"vga       ",   vga_probe,
	vga_screen_init,	vga_sa_screen_putc,	vga_pos_cursor,
	vga_sa_screen_blank,	vga_screen_move,	vga_screen_print,
	C 0xf40b8000,		25,	80,	350,	640,	0,
	E_IBMOUTPUT,		nulldev,		nulldev,
	nulldev,		vga_sa_color_table,	C ( 0x000B8000 + MEM_BASE),
	vga_screen_restore,
},

{ /* 7 */	"ibm8514   ",	ibm8514_probe,
	ibm8514_screen_init,	ibm8514_screen_putc,	ibm8514_pos_cursor,
	ibm8514_screen_blank,	ibm8514_screen_move,	ibm8514_screen_print,
	C 0x000046e8,		42,	80,	768,	1024,	0,
	E_IBMOUTPUT,		nulldev,		nulldev,
	nulldev,		ibm8514_color_table,	C ( 0x000046e8),
	ibm8514_screen_restore,
},

{ /* 8 */	"DUMMY",        nulldev,
	nulldev,			nulldev,		nulldev,
	nulldev,			nulldev,		nulldev,
	C 0x00000000,		0,	0,	0,	0,	0,
	0,					nulldev,		nulldev,
	nulldev,		nulldev,	C 0x00000000,
	nulldev,
},

};

/* number of entries in screen_sw table */
int NSCREEN = sizeof (screen_sw) / sizeof (screen_sw[0]);

int stdie_open(), stdoe_open(), stde_close(), stde_read(), stde_write(), stde_ioctl(), stde_rint(), stde_putc(), stde_put_status(), stde_select();
int ibme_open(), ibme_close(), ibme_write(), ibme_ioctl(), ibme_putc(), ibme_put_status();
int buf_open(), buf_close(), buf_write(), buf_ioctl(), buf_putc(),
buf_select(), buf_getc();


struct emulsw emulsw[] =
{
	/*	Open		Close		Read		Write
		Ioctl		rint		putc		select
		putstatus */
/* 0 */ {
		stdie_open,	stde_close,	nulldev,	nulldev,
		nulldev,	nulldev,	nulldev,	nulldev,
		nulldev
	},
/* 1 */ {
		stdoe_open,	stde_close,	nulldev,	nulldev,
		nulldev,	nulldev,	stde_putc,	nulldev,
		stde_put_status
	},
/* 2 */ {
		ibme_open,	ibme_close,	nulldev,	nulldev,
		nulldev,	nulldev,	ibme_putc,	nulldev,
		ibme_put_status
	},
};


extern SCREEN_INFO cons_info;
extern struct tty cons;

int NEMUL = sizeof (emulsw) / sizeof (emulsw[0]);

screen_init(si)
register SCREEN_INFO *si;
{
/*	register */ int i;
	register char *rwaddr;
	struct	tty	*tp	= &cons;
	dev_t	dev;
	short poll;

EDEBUG (0x01, aed_pr ("IN screen_init\n"));

/* As this is called only at boot time, initialize all screens present for
 * use both as kernel and user devices. Override will come at the user's
 * discretion.
 */

	WS = NO_ENTRY;
	for (i = 0; i < NSCREEN; i++) {
#ifdef ATR
#ifdef IBMRTPC
		if (cpu == CPU_ATR) {
			screen_sw[i].rwaddr = (char *) ((int) screen_sw[i].rwaddr & 0x00ffffff);
			screen_sw[i].addr = (char *) ((int) screen_sw[i].addr & 0x00ffffff);
		}
#endif
#endif
		if (screen_sw[i].init && (screen_sw[i].init != nodev) &&
			((rwaddr = screen_sw[i].rwaddr) != 0)) {
			if ((*screen_sw[i].probe)(rwaddr))
				{
				screen_sw[i].flags |= CONSDEV_PRESENT;
/*				if (!(screen_sw[i].flags & CONSDEV_KERNEL)) */
					{
EDEBUG (0x01, aed_pr ("init %d\n", i));
/*					if (!(screen_sw[i].flags & CONSDEV_OPEN)) */
						{
						(*screen_sw[i].init)();
						screen_sw[i].flags |= CONSDEV_INIT;
						screen_sw[i].flags |= CONSDEV_BOTH;
						screen_sw[i].screenx =
						 screen_sw[i].screeny = 0;
						 /* init for switch */
						if (WS == NO_ENTRY) WS = i;
						}
					}
				}
		}
	}
	/*
	 * if we haven't made a choice, or if our choice does not exist then
	 * look for any alive screen.
	 */
	if (WS == NO_ENTRY ||
		((screen_sw[WS].flags & CONSDEV_ALIVE) == 0)) {
		WS = NO_ENTRY;	  /* just in case */
		for (i = 0; i < NSCREEN; i++)
			if (((screen_sw[i].flags & CONSDEV_ALIVE) == CONSDEV_ALIVE) &&
					(!(screen_sw[i].flags & CONSDEV_OPEN)) )
				{
				WS = i;
				break;
				}
	}
/*
 * loop thru the other screens and print message for the screen we are
 * going to use just in case the user is looking at the wrong one.
 */
	(*emulsw[si->oute.emulator].e_close)(tp, si); /* close screen for now */
	for (i = 0; i < NSCREEN; i++) {
		if (i != WS && ((screen_sw[i].flags & CONSDEV_ALIVE) == CONSDEV_ALIVE))
			{
			register int save = WS;
			WS = i;
/* Set the window for the message to the screen */
#ifdef ATR
			set_128_window(screen_addr(WS));
#endif ATR
			sichars(CE_DEFAULT, si);
			(*emulsw[si->oute.emulator].e_open)(dev, tp, si,
					SCREEN_SWITCH_RELOAD);
			put_status(0,"Console is screen ");
			put_status(18,screen_sw[save].name);
			(*emulsw[si->oute.emulator].e_close)(tp, si);
			WS = save;
			}
	}
/* Reset the window for the active screen */
#ifdef ATR
	set_128_window(screen_addr(WS));
#endif ATR
	sichars(CE_DEFAULT, si);
	(*emulsw[si->oute.emulator].e_open)(dev, tp, si, SCREEN_SWITCH_RELOAD);

	 /* init for switch */
	if (WS == NO_ENTRY) {
		DISPLAY(LED_NO_SCREEN); 	  /* no screen on system! */
		hard_delay(1000);
		WS = CONS_DUMMY; /* keep going anyway */
		screen_sw[CONS_DUMMY].flags |= CONSDEV_ALIVE;
	}

	si->screen_inited = 1;
EDEBUG (0x01, aed_pr ("WS %d\n", WS));
	init_kbd();			/* initialize the keyboard */
}

#define TEST_PAT 0x65

screen_probe(rwaddr)
register char *rwaddr;
{
	PUT_PC1B(*rwaddr, TEST_PAT);
	hard_delay(3);
	return (GET_PC1B(*rwaddr) == TEST_PAT);
}



#define SPLRETURN(r) { return(r); }
/*
 * switch to screen "n" or to next screen (if n < 0)
 */
switch_screen(n)
register int n;
{
	register struct tty *tp = &cons;
	register SCREEN_INFO *si = &cons_info;
	register int i;
	register int j;
	register int save = WS;

	if (n >= NSCREEN)
		SPLRETURN (-1); 	  /* can't do it */
	if (n == SCREEN_SWITCH || n == SCREEN_SWITCH_RELOAD
		|| n == SCREEN_SEARCH)	/* select next */
		{
		for (j = WS, i = 0; i < NSCREEN; ++i)
			{
			if (++j >= NSCREEN)
				j = 0;
			if (((screen_sw[j].flags & CONSDEV_ALIVE) == CONSDEV_ALIVE) &&
				(!(screen_sw[j].flags & CONSDEV_OPEN)))
				{
				if (n == SCREEN_SWITCH_RELOAD)
					screen_sw[j].flags &= ~CONSDEV_INIT;
				break;
				}
			}
		}	/* end select next */
	else if (n < 0) /* Not a valid request	*/
		 { SPLRETURN (-1);	}
	else	/* explicit screen switch */
		 {
		if (((screen_sw[n].flags & CONSDEV_ALIVE) == CONSDEV_ALIVE) &&
				(!(screen_sw[n].flags & CONSDEV_OPEN))	)
			j = n;
		else
			SPLRETURN (-1);
		}
	if ((n == SCREEN_SEARCH) && (j == save))
		SPLRETURN (-1); /* next screen is the same as the present */


	if (WS != j)
		{
		put_status(0,"Switched to screen ");
		put_status(19,screen_sw[j].name);
		WS = j; /* WS points to the next alive screen */
		}

#ifdef ATR
	if (cpu == CPU_ATR)
		set_128_window(screen_addr(j));
#endif ATR

	/*
	 * screen_init can be cleared to force an init which (might) force
	 * a micro-code reload
	 */
	if ((screen_sw[WS].flags & CONSDEV_INIT) == 0) {
		(*screen_sw[WS].init)();
		screen_sw[WS].flags |= CONSDEV_INIT;
	}

	/* Start default ouput emulator over with new screen */
	if ((save != WS) /* going to a new screen */
	/* test:	|| (!(screen_sw[WS].flags & CONSDEV_INIT)) */
					)	/* don't reopen if init */
		 {
		(*emulsw[si->oute.emulator].e_close)(tp, si);
		si->oute.emulator = screen_sw[WS].def_oute;
		(*emulsw[si->oute.emulator].e_open)(tp->t_dev, tp, si, n);
		put_status(0,"                                                                                "); /* clear status line on new screen */
		screen_lines = SCREEN_LENGTH - 1;
		}

	SPLRETURN (WS);
}


/*
 * put up a status indicator from the keyboard
 * don't attempt it if the device is not initialized
 */
put_status(pos, str)
register int pos;
register char *str;
{
register SCREEN_INFO *si = &cons_info;

EDEBUG (0x40, printf("put_status: si (%x) WS (%d) oute (%d)\n", si, WS, si->oute.emulator));
EDEBUG (0x40, printf("call: (%x)\n", emulsw[si->oute.emulator].e_putstatus));
	if (screen_sw[WS].flags & CONSDEV_INIT)
		(*emulsw[si->oute.emulator].e_putstatus)(si, pos, str);
EDEBUG (0x40, printf("put_status: done\r\n"));
}

/*
 * print the current screen (if possible)
 */
print_screen(flag)
register int flag;
{
	register SCREEN_INFO *si = &cons_info;
	extern int print_log;		/* if we are logging on printer */

	if (flag) {
		print_log = !print_log;
		return;
	}
	(*screen_sw[WS].printscreen)(si, flag);
}

/*
 * reset the screen (by forcing a microcode reload etc. next time it is used
 * mainly used to reload aed microcode.
 */

reset_screen(n)
{
	screen_sw[n].flags &= ~CONSDEV_INIT;
}

/*
 * call each screen restore to redraw their screen.
 * it's called screen_redraw so it doesn't conflict
 * with the debugger screen_restore (which only works for
 * the mono, sigh..).
 */
screen_redraw()
{
	int i;

	for (i = 0; i < NSCREEN; i++) {
		if (screen_sw[i].flags & CONSDEV_PRESENT) {
			(*screen_sw[i].restore)();
		}
	}
}

sichars (unit, si)
register int unit;
register SCREEN_INFO *si;
{
	si->ine.unit = si->oute.unit = si->mse.unit = 0;
	si->ine.rsel = si->oute.rsel = si->mse.rsel = 0;
	si->ine.flag = si->oute.flag = si->mse.flag = 0;
	si->ine.intr_reason = si->oute.intr_reason = si->mse.intr_reason = 0;
	si->mse.emulator = E_MSINPUT;

	/* Set to emulators determined by symbolic minor device on console */
	switch (unit) {
/* #ifdef notdef */
	case CE_WM:
		si->ine.emulator = E_STDINPUT;
		si->oute.emulator = E_WMOUTPUT;
		break;
 /* #endif */
	case CE_DEFAULT:
	default:
		si->ine.emulator = E_STDINPUT;
		si->oute.emulator = screen_sw[WS].def_oute;
		break;
	}
}
/********* end	"../machinecons/screen_conf.c"  *************/

struct	tty	cons;
struct	screen_info	cons_info;
int screen_inited;

int debug = 0;
int edebug = 0;
int _noputchar = 0;		/* flag to suppress output */
int (*alt_putchar)();

 /*
  * high level interface - a newline implies a cr/lf
  * _putchar treates lf as a single function character.
  */
putchar(c)
	register int c;
{
	struct	screen_info	*si	= &cons_info;

	if (alt_putchar)
		return((*alt_putchar)(c));
	if (!screen_inited)
		sa_screen_init(si);

	if (!_noputchar) {
		if (c == '\n')
			(*emulsw[si->oute.emulator].e_putc)('\r', si);
		(*emulsw[si->oute.emulator].e_putc)(c, si);
	}
	return (c);
}

sa_screen_init(si)
struct	screen_info	*si;
{
/*
 * displaying of "Console is..." message is done in ../machinecons/screen_conf.c
 */
	struct	tty	*tp	= &cons;
	dev_t	dev;
	int	i;

	screen_init(si);

	screen_inited = 1;
	screen_lines = SCREEN_LENGTH - 1;
}

_putchar(c)
	register int c;
{
	struct	screen_info	*si	= &cons_info;

	if (!screen_inited)
		sa_screen_init(si);
	(*emulsw[si->oute.emulator].e_putc)(c, si);
	return (c);
}

int nulldev()
{
}

int nodev()
{
}

aed_pr()	/* define later if debug output needed */
{
}

save_screen(from,to,length)
char *from, *to;
{
#ifdef IBMRTPC
	bcopy(from,to,length);
#endif IBMRTPC
}
screen_restore(from,to,length)
char *from, *to;
{
#ifdef IBMRTPC
	bcopy(from,to,length);
#endif IBMRTPC
}
