Home | History | Annotate | Line # | Download | only in vsa
smg.c revision 1.11
      1 /*	$NetBSD: smg.c,v 1.11 1999/01/11 21:54:23 drochner Exp $ */
      2 /*
      3  * Copyright (c) 1998 Ludd, University of Lule}, Sweden.
      4  * All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *	This product includes software developed at Ludd, University of
     17  *	Lule}, Sweden and its contributors.
     18  * 4. The name of the author may not be used to endorse or promote products
     19  *    derived from this software without specific prior written permission
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/param.h>
     34 #include <sys/device.h>
     35 #include <sys/systm.h>
     36 #include <sys/time.h>
     37 #include <sys/malloc.h>
     38 #include <sys/conf.h>
     39 #include <sys/kernel.h>
     40 
     41 #include <dev/cons.h>
     42 
     43 #include <dev/wscons/wsdisplayvar.h>
     44 #include <dev/wscons/wsconsio.h>
     45 #include <dev/wscons/wscons_callbacks.h>
     46 
     47 #include <machine/vsbus.h>
     48 #include <machine/sid.h>
     49 
     50 #include "lkc.h"
     51 
     52 #define SM_COLS		128	/* char width of screen */
     53 #define SM_ROWS		57	/* rows of char on screen */
     54 #define SM_CHEIGHT	15	/* lines a char consists of */
     55 #define SM_NEXTROW	(SM_COLS * SM_CHEIGHT)
     56 
     57 static	int smg_match __P((struct device *, struct cfdata *, void *));
     58 static	void smg_attach __P((struct device *, struct device *, void *));
     59 
     60 struct	smg_softc {
     61 	struct	device ss_dev;
     62 };
     63 
     64 struct cfattach smg_ca = {
     65 	sizeof(struct smg_softc), smg_match, smg_attach,
     66 };
     67 
     68 static void	smg_cursor __P((void *, int, int, int));
     69 unsigned int	smg_mapchar __P((void *, int));
     70 static void	smg_putchar __P((void *, int, int, u_int, long));
     71 static void	smg_copycols __P((void *, int, int, int,int));
     72 static void	smg_erasecols __P((void *, int, int, int, long));
     73 static void	smg_copyrows __P((void *, int, int, int));
     74 static void	smg_eraserows __P((void *, int, int, long));
     75 static int	smg_alloc_attr __P((void *, int, int, int, long *));
     76 
     77 const struct wsdisplay_emulops smg_emulops = {
     78 	smg_cursor,
     79 	smg_mapchar,
     80 	smg_putchar,
     81 	smg_copycols,
     82 	smg_erasecols,
     83 	smg_copyrows,
     84 	smg_eraserows,
     85 	smg_alloc_attr
     86 };
     87 
     88 const struct wsscreen_descr smg_stdscreen = {
     89 	"128x57", SM_COLS, SM_ROWS,
     90 	&smg_emulops,
     91 	8, SM_CHEIGHT,
     92 	WSSCREEN_UNDERLINE|WSSCREEN_REVERSE,
     93 };
     94 
     95 const struct wsscreen_descr *_smg_scrlist[] = {
     96 	&smg_stdscreen,
     97 };
     98 
     99 const struct wsscreen_list smg_screenlist = {
    100 	sizeof(_smg_scrlist) / sizeof(struct wsscreen_descr *),
    101 	_smg_scrlist,
    102 };
    103 
    104 extern char q_font[];
    105 #define QCHAR(c) (c < 32 ? 32 : (c > 127 ? c - 66 : c - 32))
    106 #define QFONT(c,line)	q_font[QCHAR(c) * 15 + line]
    107 #define	SM_ADDR(row, col, line) \
    108 	sm_addr[col + (row * SM_CHEIGHT * SM_COLS) + line * SM_COLS]
    109 
    110 
    111 static int	smg_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
    112 static int	smg_mmap __P((void *, off_t, int));
    113 static int	smg_alloc_screen __P((void *, const struct wsscreen_descr *,
    114 				      void **, int *, int *, long *));
    115 static void	smg_free_screen __P((void *, void *));
    116 static void	smg_show_screen __P((void *, void *));
    117 static void	smg_crsr_blink __P((void *));
    118 
    119 const struct wsdisplay_accessops smg_accessops = {
    120 	smg_ioctl,
    121 	smg_mmap,
    122 	smg_alloc_screen,
    123 	smg_free_screen,
    124 	smg_show_screen,
    125 	0 /* load_font */
    126 };
    127 
    128 struct	smg_screen {
    129 	int	ss_curx;
    130 	int	ss_cury;
    131 	u_char	ss_image[SM_ROWS][SM_COLS];	/* Image of current screen */
    132 	u_char	ss_attr[SM_ROWS][SM_COLS];	/* Reversed etc... */
    133 };
    134 
    135 static	struct smg_screen smg_conscreen;
    136 static	struct smg_screen *curscr;
    137 
    138 int
    139 smg_match(parent, match, aux)
    140 	struct device *parent;
    141 	struct cfdata *match;
    142 	void *aux;
    143 {
    144 	struct	vsbus_attach_args *va = aux;
    145 
    146 	if (va->va_type != inr_vf)
    147 		return 0;
    148 #ifdef DIAGNOSTIC
    149 	if (sm_addr == 0)
    150 		panic("smg: inconsistency in smg address mapping");
    151 #endif
    152 	return 1;
    153 }
    154 
    155 void
    156 smg_attach(parent, self, aux)
    157 	struct device *parent, *self;
    158 	void *aux;
    159 {
    160 	struct wsemuldisplaydev_attach_args aa;
    161 
    162 	printf("\n");
    163 	curscr = &smg_conscreen;
    164 	aa.console = !(vax_confdata & 0x20);
    165 	aa.scrdata = &smg_screenlist;
    166 	aa.accessops = &smg_accessops;
    167 	timeout(smg_crsr_blink, 0, hz/2);
    168 
    169 	config_found(self, &aa, wsemuldisplaydevprint);
    170 }
    171 
    172 static	u_char *cursor;
    173 static	int cur_on;
    174 
    175 static void
    176 smg_crsr_blink(arg)
    177 	void *arg;
    178 {
    179 	if (cur_on)
    180 		*cursor ^= 255;
    181 	timeout(smg_crsr_blink, 0, hz/2);
    182 }
    183 
    184 void
    185 smg_cursor(id, on, row, col)
    186 	void *id;
    187 	int on, row, col;
    188 {
    189 	struct smg_screen *ss = id;
    190 
    191 	if (ss == curscr) {
    192 		SM_ADDR(ss->ss_cury, ss->ss_curx, 14) =
    193 		    QFONT(ss->ss_image[ss->ss_cury][ss->ss_curx], 14);
    194 		cursor = &SM_ADDR(row, col, 14);
    195 		if ((cur_on = on))
    196 			*cursor ^= 255;
    197 	}
    198 	ss->ss_curx = col;
    199 	ss->ss_cury = row;
    200 }
    201 
    202 unsigned int
    203 smg_mapchar(id, uni)
    204 	void *id;
    205 	int uni;
    206 {
    207 	if (uni < 256)
    208 		return (uni);
    209 	return (0);
    210 }
    211 
    212 static void
    213 smg_putchar(id, row, col, c, attr)
    214 	void *id;
    215 	int row, col;
    216 	u_int c;
    217 	long attr;
    218 {
    219 	struct smg_screen *ss = id;
    220 	int i;
    221 
    222 	c &= 0xff;
    223 
    224 	ss->ss_image[row][col] = c;
    225 	ss->ss_attr[row][col] = attr;
    226 	if (ss != curscr)
    227 		return;
    228 	for (i = 0; i < 15; i++) {
    229 		unsigned char ch = QFONT(c, i);
    230 
    231 		SM_ADDR(row, col, i) = (attr & WSATTR_REVERSE ? ~ch : ch);
    232 
    233 	}
    234 	if (attr & WSATTR_UNDERLINE)
    235 		SM_ADDR(row, col, 14) ^= SM_ADDR(row, col, 14);
    236 }
    237 
    238 /*
    239  * copies columns inside a row.
    240  */
    241 static void
    242 smg_copycols(id, row, srccol, dstcol, ncols)
    243 	void *id;
    244 	int row, srccol, dstcol, ncols;
    245 {
    246 	struct smg_screen *ss = id;
    247 	int i;
    248 
    249 	bcopy(&ss->ss_image[row][srccol], &ss->ss_image[row][dstcol], ncols);
    250 	bcopy(&ss->ss_attr[row][srccol], &ss->ss_attr[row][dstcol], ncols);
    251 	if (ss != curscr)
    252 		return;
    253 	for (i = 0; i < SM_CHEIGHT; i++)
    254 		bcopy(&SM_ADDR(row,srccol, i), &SM_ADDR(row, dstcol, i),ncols);
    255 }
    256 
    257 /*
    258  * Erases a bunch of chars inside one row.
    259  */
    260 static void
    261 smg_erasecols(id, row, startcol, ncols, fillattr)
    262 	void *id;
    263 	int row, startcol, ncols;
    264 	long fillattr;
    265 {
    266 	struct smg_screen *ss = id;
    267 	int i;
    268 
    269 	bzero(&ss->ss_image[row][startcol], ncols);
    270 	bzero(&ss->ss_attr[row][startcol], ncols);
    271 	if (ss != curscr)
    272 		return;
    273 	for (i = 0; i < SM_CHEIGHT; i++)
    274 		bzero(&SM_ADDR(row, startcol, i), ncols);
    275 }
    276 
    277 static void
    278 smg_copyrows(id, srcrow, dstrow, nrows)
    279 	void *id;
    280 	int srcrow, dstrow, nrows;
    281 {
    282 	struct smg_screen *ss = id;
    283 	int frows;
    284 
    285 	bcopy(&ss->ss_image[srcrow][0], &ss->ss_image[dstrow][0],
    286 	    nrows * SM_COLS);
    287 	bcopy(&ss->ss_attr[srcrow][0], &ss->ss_attr[dstrow][0],
    288 	    nrows * SM_COLS);
    289 	if (ss != curscr)
    290 		return;
    291 	if (nrows > 25) {
    292 		frows = nrows >> 1;
    293 		if (srcrow > dstrow) {
    294 			bcopy(&sm_addr[(srcrow * SM_NEXTROW)],
    295 			    &sm_addr[(dstrow * SM_NEXTROW)],
    296 			    frows * SM_NEXTROW);
    297 			bcopy(&sm_addr[((srcrow + frows) * SM_NEXTROW)],
    298 			    &sm_addr[((dstrow + frows) * SM_NEXTROW)],
    299 			    (nrows - frows) * SM_NEXTROW);
    300 		} else {
    301 			bcopy(&sm_addr[((srcrow + frows) * SM_NEXTROW)],
    302 			    &sm_addr[((dstrow + frows) * SM_NEXTROW)],
    303 			    (nrows - frows) * SM_NEXTROW);
    304 			bcopy(&sm_addr[(srcrow * SM_NEXTROW)],
    305 			    &sm_addr[(dstrow * SM_NEXTROW)],
    306 			    frows * SM_NEXTROW);
    307 		}
    308 	} else
    309 		bcopy(&sm_addr[(srcrow * SM_NEXTROW)],
    310 		    &sm_addr[(dstrow * SM_NEXTROW)], nrows * SM_NEXTROW);
    311 }
    312 
    313 static void
    314 smg_eraserows(id, startrow, nrows, fillattr)
    315 	void *id;
    316 	int startrow, nrows;
    317 	long fillattr;
    318 {
    319 	struct smg_screen *ss = id;
    320 	int frows;
    321 
    322 	bzero(&ss->ss_image[startrow][0], nrows * SM_COLS);
    323 	bzero(&ss->ss_attr[startrow][0], nrows * SM_COLS);
    324 	if (ss != curscr)
    325 		return;
    326 	if (nrows > 25) {
    327 		frows = nrows >> 1;
    328 		bzero(&sm_addr[(startrow * SM_NEXTROW)], frows * SM_NEXTROW);
    329 		bzero(&sm_addr[((startrow + frows) * SM_NEXTROW)],
    330 		    (nrows - frows) * SM_NEXTROW);
    331 	} else
    332 		bzero(&sm_addr[(startrow * SM_NEXTROW)], nrows * SM_NEXTROW);
    333 }
    334 
    335 static int
    336 smg_alloc_attr(id, fg, bg, flags, attrp)
    337 	void *id;
    338 	int fg, bg;
    339 	int flags;
    340 	long *attrp;
    341 {
    342 	*attrp = flags;
    343 	return 0;
    344 }
    345 
    346 int
    347 smg_ioctl(v, cmd, data, flag, p)
    348 	void *v;
    349 	u_long cmd;
    350 	caddr_t data;
    351 	int flag;
    352 	struct proc *p;
    353 {
    354 	struct wsdisplay_fbinfo fb;
    355 
    356 	switch (cmd) {
    357 	case WSDISPLAYIO_GTYPE:
    358 		*(u_int *)data = WSDISPLAY_TYPE_PM_MONO;
    359 		break;
    360 
    361 	case WSDISPLAYIO_GINFO:
    362 		fb.height = 864;
    363 		fb.width = 1024;
    364 		return copyout(&fb, data, sizeof(struct wsdisplay_fbinfo));
    365 
    366 
    367 	default:
    368 		return -1;
    369 	}
    370 	return 0;
    371 }
    372 
    373 static int
    374 smg_mmap(v, offset, prot)
    375 	void *v;
    376 	off_t offset;
    377 	int prot;
    378 {
    379 	if (offset >= SMSIZE || offset < 0)
    380 		return -1;
    381 	return (SMADDR + offset) >> CLSHIFT;
    382 }
    383 
    384 int
    385 smg_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
    386 	void *v;
    387 	const struct wsscreen_descr *type;
    388 	void **cookiep;
    389 	int *curxp, *curyp;
    390 	long *defattrp;
    391 {
    392 	*cookiep = malloc(sizeof(struct smg_screen), M_DEVBUF, M_WAITOK);
    393 	bzero(*cookiep, sizeof(struct smg_screen));
    394 	*curxp = *curyp = *defattrp = 0;
    395 	return 0;
    396 }
    397 
    398 void
    399 smg_free_screen(v, cookie)
    400 	void *v;
    401 	void *cookie;
    402 {
    403 }
    404 
    405 void
    406 smg_show_screen(v, cookie)
    407 	void *v;
    408 	void *cookie;
    409 {
    410 	struct smg_screen *ss = cookie;
    411 	int row, col, line;
    412 
    413 	if (ss == curscr)
    414 		return;
    415 
    416 	for (row = 0; row < SM_ROWS; row++)
    417 		for (line = 0; line < SM_CHEIGHT; line++) {
    418 			for (col = 0; col < SM_COLS; col++) {
    419 				u_char s, c = ss->ss_image[row][col];
    420 
    421 				if (c < 32)
    422 					c = 32;
    423 				s = QFONT(c, line);
    424 				if (ss->ss_attr[row][col] & WSATTR_REVERSE)
    425 					s ^= 255;
    426 				SM_ADDR(row, col, line) = s;
    427 			}
    428 			if (ss->ss_attr[row][col] & WSATTR_UNDERLINE)
    429 				SM_ADDR(row, col, line) = 255;
    430 		}
    431 	cursor = &sm_addr[(ss->ss_cury * SM_CHEIGHT * SM_COLS) + ss->ss_curx +
    432 	    ((SM_CHEIGHT - 1) * SM_COLS)];
    433 	curscr = ss;
    434 }
    435 
    436 cons_decl(smg);
    437 
    438 #define WSCONSOLEMAJOR 68
    439 
    440 void
    441 smgcninit(cndev)
    442 	struct	consdev *cndev;
    443 {
    444 	extern void lkccninit __P((struct consdev *));
    445 	extern int lkccngetc __P((dev_t));
    446 	/* Clear screen */
    447 	memset(sm_addr, 0, 128*864);
    448 
    449 	curscr = &smg_conscreen;
    450 	wsdisplay_cnattach(&smg_stdscreen, &smg_conscreen, 0, 0, 0);
    451 	cn_tab->cn_dev = makedev(WSCONSOLEMAJOR, 0);
    452 #if NLKC
    453 	lkccninit(cndev);
    454 	wsdisplay_set_cons_kbd(lkccngetc, nullcnpollc);
    455 #endif
    456 }
    457 
    458 int smgprobe(void);
    459 int
    460 smgprobe()
    461 {
    462 	switch (vax_boardtype) {
    463 	case VAX_BTYP_410:
    464 	case VAX_BTYP_420:
    465 	case VAX_BTYP_43:
    466 		if (vax_confdata & 0x20) /* doesn't use graphics console */
    467 			break;
    468 		if (sm_addr == 0) /* Haven't mapped graphic area */
    469 			break;
    470 
    471 		return 1;
    472 
    473 	default:
    474 		break;
    475 	}
    476 	return 0;
    477 }
    478