#include "sys/param.h"#include "sys/mmu.h"#include "sys/types.h"#include "sys/inode.h"#include "saio.h"long bmcolor = 0;	/* white (0) or black (-1) background */char *bmscrn;		/* pointer to screen */long icon[] = {  0xF0F0F0F0, 0x0F0F0F0F, 0xF0F0F0F0, 0x0F0F0F0F,		 0xF0F0F0F0, 0x0F0F0F0F, 0xF0F0F0F0, 0x0F0F0F0F,		 0xF0F0F0F0, 0x0F0F0F0F, 0xF0F0F0F0, 0x0F0F0F0F,		 0xF0F0F0F0, 0x0F0F0F0F, 0xF0F0F0F0, 0x0F0F0F0F,		 0xF0F0F0F0, 0x0F0F0F0F, 0xF0F0F0F0, 0x0F0F0F0F,		 0xF0F0F0F0, 0x0F0F0F0F, 0xF0F0F0F0, 0x0F0F0F0F,		 0xF0F0F0F0, 0x0F0F0F0F, 0xF0F0F0F0, 0x0F0F0F0F,		 0xF0F0F0F0, 0x0F0F0F0F, 0xF0F0F0F0, 0x0F0F0F0F,};/* Standalone console interface *//* * Copyright 1984 UniSoft Corporation * Use of this material is subject to your disclosure agreement with * AT&T, Western Electric and UniSoft Corporation. * * Console Interface * getlocal checks the COPS interrupt flag register looking for a pending * character code.  If it finds one then it takes the appropriate action. * Only when a down keycode for a transitable character is hit does it * return the ascii value, otherwise it returns zero. * getchar calls getlocal until it returns a character. * getchar echos, getlocal does not. */#include "sys/cops.h"#include "sys/keyboard.h"#include "sys/bmfont.h"int	consinit;coinit(){	register struct device_e *p = COPSADDR;	p->e_pcr = 9;	p->e_acr = 1;	p->e_ier = 0x7F;/* 	printf("pcr=%x, acr=%x, ddra=%x, ddrb=%x, ier=%x, irb=%x\n",		p->e_pcr & 0xFF, p->e_acr & 0xFF, p->e_ddra & 0xFF,		p->e_ddrb & 0xFF, p->e_ifr & 0xFF, p->e_irb & 0xFF); */	consinit = 1;}char *co_cvtab = ToLA;		/* pointer to appropriate conv table */	/* This proceedure is used to send commands to the Keyboard COPS	 * (ie. `enable keyboard')	 */int keytype;			/* type of keyboard */getlocal(){	register struct device_e *p = COPSADDR;	register char i;	static int state;	/* State for muli-byte COPS sequences */	if (!consinit)		coinit();	i = p->e_ifr;	if ((i & FCA1) == 0) {		/* printf("%x ",i & 0xFF); */		return 0;	}	i = p->e_ira & 0xFF;	if (!state) {			/* IDLE LOOP */		if (!i) {			/* printf("Mouse state:"); */			state = 2;	/* mouse data follows */		} else if (i == 0x80) {			state = -1;		} else if ((i & 0x7F) > 0x1F) {			return keycode(i);		} /* else			printf("Plug code x%x\n",i); */	} else {		if (state == -1) {			state = 0;			if (i <= 0xDF) {	/* i is new keyboard ID code */				keytype = i;			} else if (i <= 0xEF) {		/* read clock data */				printf(" CLOCK READ\n");				state = 5;			} else {				if ((i & 0xFF) == 0xFB)					rom_mon(icon,"RESTART",0);				/* printf(" ??? [%x] ???\n",i); */			}		} else {			/* printf(" %2.2x",i&0xFF); */			if (--state == 0)				/* printf("\n") */ ;		}	}	return 0;}#define COLOCKFLG 1#define COCTRLFLG 2#define COSHFTFLG 4keycode(c)	register int c;{	register int i;	static char coctrl, colock, coshft;/* printf("cointr[%x]\n",c&0xFF); */	if (c & 0x80) {				/* key went down */		c &= 0x7F;			/* knock out high bit */		if (c < Lck) {		/* it is really a character */			if ((i=co_cvtab[c]) == Imp) {	/* cvt keycode to char*/				printf("Got invalid down-keycode `x%x'\n",c);				return 0;			}			if (coctrl) i &= 0x1F;			return i;		} else if (c > Lck) {				if (c == Sft) coshft = 1; 	/* Shift key */			else coctrl = 1;		/* Command key */		} else			colock = 1;			/* Alpha lock */	} else {				/* key went up */		c &= 0x7F;		if (c > Lck) {			if (c == Cmd) coctrl = 0;	/* ctrl key */			else coshft = 0;		/* shift key */		} else			colock = 0;			/* Alpha lock */	}/* Some shift key changed so we must reset the conversion table */	co_cvtab = coshft ? ToUA		/* uppercase everything */			: (colock ? ToCC	/* uppercase alpha only */			: ToLA);		/* lowercase ascii */	return 0;}/* * Adm3a emulator * Called with each character destined for the console. * Processes control sequences and keeps track of terminal state. * Calls into bitmap.c actually do the I/O */short maxrow = 33;short maxcol = 81;short adm_row = 22;short adm_col = 0;		/* cursor location (0-maxrow, 0-maxcol) */short row_ofs = 4, col_ofs =4;	/* row and column offsets */short winscrl = 8;		/* lines to scroll each time *//* This routine interprets the characters destined for the console and * performs like a Lear Adm3a.  It is implemented in terms of primitives * defined in bitmap.c */adm_putc (c)	register char c;{	static int flag;		/* in cursor relocation sequence */	char *bminit();			/* one time screen initialization */	if (!bmscrn) bminit();;	c &= 0x7F;	if (flag) {			/* process cursor relocation */		flag++;			/* setup to pick up next character */		if (flag == 2) {			if (c != '=') goto reset;		} else if (flag == 3) {			if ((c -= ' ') >= 0 && c <= maxrow) adm_row = c;		} else {			if ((c -= ' ') >= 0 && c <= maxcol) {				adm_col = c;			}		reset:			flag = 0;			bminvert(adm_row+row_ofs,adm_col+col_ofs);		}		return;	}	if (c >= ' ') {		c &= 0x7F;		bmputc(adm_row+row_ofs,adm_col+col_ofs,c);		adm_advance();	} else {		bminvert (adm_row+row_ofs, adm_col+col_ofs);		if (c == 8) {		/* Backspace */			if (adm_col > 0) adm_col--;		} else if (c == 13) {	/* Carriage return */			adm_col = 0;		} else if (c == 10) {	/* Line feed */			if (adm_row++ >= maxrow) {				if (row_ofs > 0)					bmwin(winscrl,row_ofs-1,row_ofs+maxrow+1,col_ofs-1,col_ofs+maxcol+1);				else					bmwin(winscrl,row_ofs,row_ofs+maxrow,col_ofs,col_ofs+maxcol);				adm_row -= winscrl;			}		} else if (c == 26) {	/* ^Z means clear screen and home */			adm_clear();		} else if (c == 12) {	/* ^L is non-destructive space */			adm_advance();		} else if (c == 11) {	/* ^K is up a line, same column */			if (adm_row > 0) {				adm_row--;			}		} else if (c == 30) {	/* ^^ is home */			adm_row = 0;			adm_col = 0;		} else if (c == 0x1B) {	/* Escape character */			flag = 1;			return;		}	}	bminvert(adm_row+row_ofs,adm_col+col_ofs);}adm_advance(){	if (adm_col++ >= maxcol) {		/* wraps around */		adm_col = 0;		if (adm_row++ >= maxrow) {	/* on last line */			if (row_ofs > 0)				bmwin(winscrl,row_ofs-1,row_ofs+maxrow+1,col_ofs-1,col_ofs+maxcol+1);			else				bmwin(winscrl,row_ofs,row_ofs+maxrow,col_ofs,col_ofs+maxcol);			adm_row -= winscrl;		}	}}adm_clear(){	if (row_ofs)		bmwin(0,row_ofs-1,row_ofs+maxrow+1,col_ofs-1,col_ofs+maxcol+1);	else		bmwin(0,row_ofs,row_ofs+maxrow,col_ofs,col_ofs+maxcol);	adm_row = adm_col = 0;}/* * Bitmap Display Driver * * The screen is 720 by 364 raster units.  A comfortable pixel size is * 9 by 10 giving 80 columns (9 wide) and 36 lines (10 deep).  The * extra 4 raster rows are unused.  Unfortunately this arrangement is * very expensive in processor time since pixels lie across byte boundaries. * * For the time being the pixel size used will be 8 by 9 providing a * screen area of 90 columns, and 40 lines. * * This is the low level display driver intended to simplify the task * of writing higher level screen emulators by simulating just the common * aspects of all crts in the following functions: * *	bminit ()		clears entire display *	bminvert (row, col)	invert character at row, column *	bmputc (r, c, char)	put the character at row, column *	bmwin (cmd, t, b, l, r) modifies window (top,bot,left,right); *				cmd == 1 means scroll up a line *				cmd == 0 means clear that area */#define BPL	90#define V_RESO	9#define H_RESO	8/* Note: since the last four words must be black (-1) to prevent the * retrace lines from showing we get away with one loop (0 - 363). * If a white screen is used the low bit of the last word written must * be a one so the loop below will have to change. */char *bminit ()		/* one time screen initialization */{/* register short i = ((720 * 364) >> 5) -1;/* amount of screen in longs */	register long *p;	p = (long *)(TOTMEM - 0x8000);	/* setup logical screen address */	bmscrn = (char *)p;/* So we fit in the space left by the boot rom */	VIDADDR = ((long)p + MEMSTART) >> 15;/*****	do {		*p++ = -1;	} while (--i != -1);*****/	if (winscrl != 1)		bmwin(0,row_ofs+adm_row-1,row_ofs+maxrow+1,col_ofs-1,col_ofs+maxcol+1);	else		bmwin(0,row_ofs-1,row_ofs+maxrow+1,col_ofs-1,col_ofs+maxcol+1);	bminvert(row_ofs,col_ofs);	return bmscrn;}/* Modify a section of the display * Currently supported commands are 0 for clear, and 1 for scroll up. */bmwin (cmd, tr, br, lc, rc)	short cmd, br, lc, rc;	register short tr;{	register short wrap, j, i;	short cols, rows;	register char *pc, *ec;	if (!(pc = bmscrn))		pc = bminit();/* Calculate number of logical lines to operate on */	rows = br - tr + 1;/* Calculate number of columns (bytes) accross screen */	cols = rc - lc + 1;/* Wrap is an offset to be added to scan line pointers at the end of * each line to bring them around to the start of the next line. * It is the number of columns not being scrolled (usually zero) */	wrap = BPL - cols;		/* wrap around offset *//* Pc points at the upper area of the screen (ie, that will receive the  * scroll data. */	pc += tr * (short)(BPL * V_RESO) + lc;/* I is the number of scan lines to operate on.  ie. the number of scan * lines in the window minus the number of lines to scroll. */	i = (short)(rows - cmd) * (short)(V_RESO) - 1; /* scan lines *//* Here we do the scrolling if it is indicated */	if (cmd) {			/* scroll command lines *//* Ec is is set to point at the first line to scroll up */		ec = pc + cmd * ((short)(BPL) * (short)(V_RESO));		do {			/* scroll scan line at a time */			j = cols - 1;		/* column counter */			do *pc++ = *ec++;	/* optimizes to dbra loop */			while (--j != -1);			pc += wrap;		/* skip to next scan line */			ec += wrap;		} while (--i != -1);		i = (short)(V_RESO) * cmd - 1;	/* reset for clear */	}	tr = bmcolor;	do {			/* clear */		j = cols - 1;		do *pc++ = tr;		while (--j != -1);		pc += wrap;	} while (--i != -1);	return;}bminvert (r, c)			/* reverse video char under cursor */	register short r, c;{	register char *p = bmscrn;	register short i;	if (!p)		p = bminit();	p += (r * (BPL * V_RESO)) + c;	i = V_RESO - 1;	do {		*p = ~*p;		p += BPL;		/* 1 scan line */	} while (--i != -1);}		bmputc (r, c, k)			/* draw a char at location r, c */	register short r, c;	char k;{	register char *p = bmscrn;	register char *f = &bmfont[0];	register short i;	if (!p)		p = bminit();	p += (r * (BPL * V_RESO)) + c;	f += (k - ' ') << 3;	i = FONTVERT - 1;		/* bytes in font table for one char */	if (bmcolor) {		do {			*p = ~*f++;	/* should probably reverse font table*/			p += BPL;	/* 1 scan line == 90 bytes */		} while (--i != -1);	} else {		do {			*p = *f++;			p += BPL;	/* 1 scan line == 90 bytes */		} while (--i != -1);	}	*p = bmcolor;			/* blank row under cursor */}