Home | History | Annotate | Line # | Download | only in hpc
bicons.c revision 1.1
      1 /*	$NetBSD: bicons.c,v 1.1 2001/02/09 19:43:23 uch Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1999-2001
      5  *         Shin Takemura and PocketBSD Project. All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the PocketBSD project
     18  *	and its contributors.
     19  * 4. Neither the name of the project nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  */
     36 
     37 #define HALF_FONT
     38 
     39 #include <sys/param.h>
     40 #include <sys/device.h>
     41 #include <sys/systm.h>
     42 #include <sys/conf.h>
     43 #include <dev/cons.h>
     44 
     45 #include <machine/bootinfo.h>
     46 #include <machine/bus.h>
     47 #include <machine/platid.h>
     48 #include <machine/stdarg.h>
     49 
     50 #include <dev/hpc/biconsvar.h>
     51 #include <dev/hpc/bicons.h>
     52 extern u_int8_t font_clR8x8_data[];
     53 extern u_int8_t font_clB8x8_data[];
     54 #define FONT_HEIGHT	8
     55 #define FONT_WIDTH	1
     56 
     57 static void put_oxel_D2_M2L_3(u_int8_t *, u_int8_t, u_int8_t);
     58 static void put_oxel_D2_M2L_3x2(u_int8_t *, u_int8_t, u_int8_t);
     59 static void put_oxel_D2_M2L_0(u_int8_t *, u_int8_t, u_int8_t);
     60 static void put_oxel_D2_M2L_0x2(u_int8_t *, u_int8_t, u_int8_t);
     61 static void put_oxel_D4_M2L_F(u_int8_t *, u_int8_t, u_int8_t);
     62 static void put_oxel_D4_M2L_Fx2(u_int8_t *, u_int8_t, u_int8_t);
     63 static void put_oxel_D4_M2L_0(u_int8_t *, u_int8_t, u_int8_t);
     64 static void put_oxel_D4_M2L_0x2(u_int8_t *, u_int8_t, u_int8_t);
     65 static void put_oxel_D8_00(u_int8_t *, u_int8_t, u_int8_t);
     66 static void put_oxel_D8_FF(u_int8_t *, u_int8_t, u_int8_t);
     67 static void put_oxel_D16_0000(u_int8_t *, u_int8_t, u_int8_t);
     68 static void put_oxel_D16_FFFF(u_int8_t *, u_int8_t, u_int8_t);
     69 
     70 struct {
     71 	int type;
     72 	char *name;
     73 	void (*func)(u_int8_t *, u_int8_t, u_int8_t);
     74 	u_int8_t clear_byte;
     75 	int16_t oxel_bytes;
     76 } fb_table[] = {
     77 	{ BIFB_D2_M2L_3,	BIFBN_D2_M2L_3,
     78 	  put_oxel_D2_M2L_3,	0,	2	},
     79 	{ BIFB_D2_M2L_3x2,	BIFBN_D2_M2L_3x2,
     80 	  put_oxel_D2_M2L_3x2,	0,	1	},
     81 	{ BIFB_D2_M2L_0,	BIFBN_D2_M2L_0,
     82 	  put_oxel_D2_M2L_0,	0xff,	2	},
     83 	{ BIFB_D2_M2L_0x2,	BIFBN_D2_M2L_0x2,
     84 	  put_oxel_D2_M2L_0x2,	0xff,	1	},
     85 	{ BIFB_D4_M2L_F,	BIFBN_D4_M2L_F,
     86 	  put_oxel_D4_M2L_F,	0x00,	4	},
     87 	{ BIFB_D4_M2L_Fx2,	BIFBN_D4_M2L_Fx2,
     88 	  put_oxel_D4_M2L_Fx2,	0x00,	2	},
     89 	{ BIFB_D4_M2L_0,	BIFBN_D4_M2L_0,
     90 	  put_oxel_D4_M2L_0,	0xff,	4	},
     91 	{ BIFB_D4_M2L_0x2,	BIFBN_D4_M2L_0x2,
     92 	  put_oxel_D4_M2L_0x2,	0xff,	2	},
     93 	{ BIFB_D8_00,		BIFBN_D8_00,
     94 	  put_oxel_D8_00,	0xff,	8	},
     95 	{ BIFB_D8_FF,		BIFBN_D8_FF,
     96 	  put_oxel_D8_FF,	0x00,	8	},
     97 	{ BIFB_D16_0000,	BIFBN_D16_0000,
     98 	  put_oxel_D16_0000,	0xff,	16	},
     99 	{ BIFB_D16_FFFF,	BIFBN_D16_FFFF,
    100 	  put_oxel_D16_FFFF,	0x00,	16	},
    101 };
    102 #define FB_TABLE_SIZE (sizeof(fb_table)/sizeof(*fb_table))
    103 
    104 static u_int8_t	*fb_vram;
    105 static int16_t	fb_line_bytes;
    106 static u_int8_t	fb_clear_byte;
    107 int16_t	bicons_ypixel;
    108 int16_t	bicons_xpixel;
    109 #ifdef HALF_FONT
    110 static int16_t	fb_oxel_bytes	= 1;
    111 int16_t	bicons_width	= 80;
    112 void	(*fb_put_oxel)(u_int8_t *, u_int8_t, u_int8_t) = put_oxel_D2_M2L_3x2;
    113 #else /* HALF_FONT */
    114 static int16_t	fb_oxel_bytes	= 2;
    115 int16_t	bicons_width	= 40;
    116 void	(*fb_put_oxel)(u_int8_t *, u_int8_t, u_int8_t) = put_oxel_D2_M2L_3;
    117 #endif /* HALF_FONT */
    118 int16_t bicons_height;
    119 static int16_t curs_x;
    120 static int16_t curs_y;
    121 
    122 cdev_decl(biconsdev);
    123 
    124 static int bicons_priority;
    125 void biconscninit(struct consdev *);
    126 void biconscnprobe(struct consdev *);
    127 void biconscnputc(dev_t, int);
    128 int biconscngetc(dev_t);	/* harmless place holder */
    129 
    130 static void draw_char(int, int, int);
    131 static void clear(int, int);
    132 static void scroll(int, int, int);
    133 static void bicons_puts(char *);
    134 static void bicons_printf(const char *, ...) __attribute__((__unused__));
    135 
    136 void
    137 biconscninit(struct consdev *cndev)
    138 {
    139 	int fb_index = -1;
    140 
    141 	for (fb_index = 0; fb_index < FB_TABLE_SIZE; fb_index++)
    142 		if (fb_table[fb_index].type == bootinfo->fb_type)
    143 			break;
    144 
    145 	if (FB_TABLE_SIZE <= fb_index || fb_index == -1) {
    146 		/*
    147 		 *  Unknown frame buffer type, but what can I do ?
    148 		 */
    149 		fb_index = 0;
    150 	}
    151 
    152 	fb_vram = (u_int8_t *)bootinfo->fb_addr;
    153 	fb_line_bytes = bootinfo->fb_line_bytes;
    154 	bicons_xpixel = bootinfo->fb_width;
    155 	bicons_ypixel = bootinfo->fb_height;
    156 
    157 	fb_put_oxel = fb_table[fb_index].func;
    158 	fb_clear_byte = fb_table[fb_index].clear_byte;
    159 	fb_oxel_bytes = fb_table[fb_index].oxel_bytes;
    160 
    161 	bicons_width = bicons_xpixel / (8 * FONT_WIDTH);
    162 	bicons_height = bicons_ypixel / FONT_HEIGHT;
    163 	clear(0, bicons_ypixel);
    164 
    165 	curs_x = 0;
    166 	curs_y = 0;
    167 
    168 	bicons_puts("builtin console type = ");
    169 	bicons_puts(fb_table[fb_index].name);
    170 	bicons_puts("\n");
    171 }
    172 
    173 void
    174 biconscnprobe(struct consdev *cndev)
    175 {
    176 	int maj;
    177 
    178 	/* locate the major number */
    179 	for (maj = 0; maj < nchrdev; maj++)
    180 		if (cdevsw[maj].d_open == biconsdevopen)
    181 			break;
    182 
    183 	cndev->cn_dev = makedev(maj, 0);
    184 	cndev->cn_pri = bicons_priority;
    185 }
    186 
    187 void
    188 bicons_set_priority(int priority)
    189 {
    190 	bicons_priority = priority;
    191 }
    192 
    193 int
    194 biconscngetc(dev_t dev)
    195 {
    196 	printf("no input method. reboot me.\n");
    197 	while (1)
    198 		;
    199 	/* NOTREACHED */
    200 }
    201 
    202 void
    203 biconscnputc(dev_t dev, int c)
    204 {
    205 	int line_feed = 0;
    206 
    207 	switch (c) {
    208 	case 0x08: /* back space */
    209 		if (--curs_x < 0) {
    210 			curs_x = 0;
    211 		}
    212 		/* erase character ar cursor position */
    213 		draw_char(curs_x, curs_y, ' ');
    214 		break;
    215 	case '\r':
    216 		curs_x = 0;
    217 		break;
    218 	case '\n':
    219 		curs_x = 0;
    220 		line_feed = 1;
    221 		break;
    222 	default:
    223 		draw_char(curs_x, curs_y, c);
    224 		if (bicons_width <= ++curs_x) {
    225 			curs_x = 0;
    226 			line_feed = 1;
    227 		}
    228 	}
    229 
    230 	if (line_feed) {
    231 		if (bicons_height <= ++curs_y) {
    232 			/* scroll up */
    233 			scroll(FONT_HEIGHT, (bicons_height - 1) * FONT_HEIGHT,
    234 			       - FONT_HEIGHT);
    235 			clear((bicons_height - 1) * FONT_HEIGHT, FONT_HEIGHT);
    236 			curs_y--;
    237 		}
    238 	}
    239 }
    240 
    241 void
    242 bicons_puts(char *s)
    243 {
    244 	while (*s)
    245 		biconscnputc(NULL, *s++);
    246 }
    247 
    248 
    249 void
    250 bicons_putn(const char *s, int n)
    251 {
    252 	while (0 < n--)
    253 		biconscnputc(NULL, *s++);
    254 }
    255 
    256 void
    257 #ifdef __STDC__
    258 bicons_printf(const char *fmt, ...)
    259 #else
    260 bicons_printf(fmt, va_alist)
    261 	char *fmt;
    262 	va_dcl
    263 #endif
    264 {
    265 	va_list ap;
    266 	char buf[0x100];
    267 
    268 	va_start(ap, fmt);
    269 	vsnprintf(buf, sizeof(buf), fmt, ap);
    270 	va_end(ap);
    271 	bicons_puts(buf);
    272 }
    273 
    274 static void
    275 draw_char(int x, int y, int c)
    276 {
    277 	int i;
    278 	u_int8_t *p;
    279 
    280 	if (!fb_vram)
    281 		return;
    282 
    283 	p = &fb_vram[(y * FONT_HEIGHT * fb_line_bytes) +
    284 		    x * FONT_WIDTH * fb_oxel_bytes];
    285 	for (i = 0; i < FONT_HEIGHT; i++) {
    286 		(*fb_put_oxel)(p, font_clR8x8_data
    287 			       [FONT_WIDTH * (FONT_HEIGHT * c + i)], 0xff);
    288 		p += (fb_line_bytes);
    289 	}
    290 }
    291 
    292 static void
    293 clear(int y, int height)
    294 {
    295 	u_int8_t *p;
    296 
    297 	if (!fb_vram)
    298 		return;
    299 
    300 	p = &fb_vram[y * fb_line_bytes];
    301 
    302 	while (0 < height--) {
    303 		memset(p, fb_clear_byte,
    304 		       bicons_width * fb_oxel_bytes * FONT_WIDTH);
    305 		p += fb_line_bytes;
    306 	}
    307 }
    308 
    309 static void
    310 scroll(int y, int height, int d)
    311 {
    312 	u_int8_t *from, *to;
    313 
    314 	if (!fb_vram)
    315 		return;
    316 
    317 	if (d < 0) {
    318 		from = &fb_vram[y * fb_line_bytes];
    319 		to = from + d * fb_line_bytes;
    320 		while (0 < height--) {
    321 			memcpy(to, from, bicons_width * fb_oxel_bytes);
    322 			from += fb_line_bytes;
    323 			to += fb_line_bytes;
    324 		}
    325 	} else {
    326 		from = &fb_vram[(y + height - 1) * fb_line_bytes];
    327 		to = from + d * fb_line_bytes;
    328 		while (0 < height--) {
    329 			memcpy(to, from, bicons_xpixel * fb_oxel_bytes / 8);
    330 			from -= fb_line_bytes;
    331 			to -= fb_line_bytes;
    332 		}
    333 	}
    334 }
    335 
    336 /*=============================================================================
    337  *
    338  *	D2_M2L_3
    339  *
    340  */
    341 static void
    342 put_oxel_D2_M2L_3(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    343 {
    344 #if 1
    345 	u_int16_t *addr = (u_int16_t *)xaddr;
    346 	static u_int16_t map0[] = {
    347 		0x0000, 0x0300, 0x0c00, 0x0f00, 0x3000, 0x3300, 0x3c00, 0x3f00,
    348 		0xc000, 0xc300, 0xcc00, 0xcf00, 0xf000, 0xf300, 0xfc00, 0xff00,
    349 	};
    350 	static u_int16_t map1[] = {
    351 		0x0000, 0x0003, 0x000c, 0x000f, 0x0030, 0x0033, 0x003c, 0x003f,
    352 		0x00c0, 0x00c3, 0x00cc, 0x00cf, 0x00f0, 0x00f3, 0x00fc, 0x00ff,
    353 	};
    354 	*addr = (map1[data >> 4] | map0[data & 0x0f]);
    355 #else
    356 	static u_int8_t map[] = {
    357 		0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f,
    358 		0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff,
    359 	};
    360 	u_int8_t *addr = xaddr;
    361 
    362 	*addr++ = (map[(data >> 4) & 0x0f] & map[(mask >> 4) & 0x0f]) |
    363 		(*addr & ~map[(mask >> 4) & 0x0f]);
    364 	*addr   = (map[(data >> 0) & 0x0f] & map[(mask >> 0) & 0x0f]) |
    365 		(*addr & ~map[(mask >> 0) & 0x0f]);
    366 #endif
    367 }
    368 
    369 /*=============================================================================
    370  *
    371  *	D2_M2L_3x2
    372  *
    373  */
    374 static void
    375 put_oxel_D2_M2L_3x2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    376 {
    377 	register u_int8_t odd = (data & 0xaa);
    378 	register u_int8_t even = (data & 0x55);
    379 
    380 	*xaddr = (odd | (even << 1)) | ((odd >> 1) & even);
    381 }
    382 
    383 /*=============================================================================
    384  *
    385  *	D2_M2L_0
    386  *
    387  */
    388 static void
    389 put_oxel_D2_M2L_0(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    390 {
    391 #if 1
    392 	u_int16_t *addr = (u_int16_t *)xaddr;
    393 	static u_int16_t map0[] = {
    394 		0xff00, 0xfc00, 0xf300, 0xf000, 0xcf00, 0xcc00, 0xc300, 0xc000,
    395 		0x3f00, 0x3c00, 0x3300, 0x3000, 0x0f00, 0x0c00, 0x0300, 0x0000,
    396 	};
    397 	static u_int16_t map1[] = {
    398 		0x00ff, 0x00fc, 0x00f3, 0x00f0, 0x00cf, 0x00cc, 0x00c3, 0x00c0,
    399 		0x003f, 0x003c, 0x0033, 0x0030, 0x000f, 0x000c, 0x0003, 0x0000,
    400 	};
    401 	*addr = (map1[data >> 4] | map0[data & 0x0f]);
    402 #else
    403 	static u_int8_t map[] = {
    404 		0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f,
    405 		0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff,
    406 	};
    407 	u_int8_t *addr = xaddr;
    408 
    409 	*addr++ = (~(map[(data >> 4) & 0x0f] & map[(mask >> 4) & 0x0f])) |
    410 		(*addr & ~map[(mask >> 4) & 0x0f]);
    411 	*addr   = (~(map[(data >> 0) & 0x0f] & map[(mask >> 0) & 0x0f])) |
    412 		(*addr & ~map[(mask >> 0) & 0x0f]);
    413 #endif
    414 }
    415 
    416 /*=============================================================================
    417  *
    418  *	D2_M2L_0x2
    419  *
    420  */
    421 static void
    422 put_oxel_D2_M2L_0x2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    423 {
    424 	register u_int8_t odd = (data & 0xaa);
    425 	register u_int8_t even = (data & 0x55);
    426 
    427 	*xaddr = ~((odd | (even << 1)) | ((odd >> 1) & even));
    428 }
    429 
    430 /*=============================================================================
    431  *
    432  *	D4_M2L_F
    433  *
    434  */
    435 static void
    436 put_oxel_D4_M2L_F(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    437 {
    438 	u_int32_t *addr = (u_int32_t *)xaddr;
    439 	static u_int32_t map[] = {
    440 		0x0000, 0x0f00, 0xf000, 0xff00, 0x000f, 0x0f0f, 0xf00f, 0xff0f,
    441 		0x00f0, 0x0ff0, 0xf0f0, 0xfff0, 0x00ff, 0x0fff, 0xf0ff, 0xffff,
    442 	};
    443 	*addr = (map[data >> 4] | (map[data & 0x0f] << 16));
    444 }
    445 
    446 /*=============================================================================
    447  *
    448  *	D4_M2L_Fx2
    449  *
    450  */
    451 static void
    452 put_oxel_D4_M2L_Fx2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    453 {
    454 	u_int16_t *addr = (u_int16_t *)xaddr;
    455 	static u_int16_t map[] = {
    456 		0x00, 0x08, 0x08, 0x0f, 0x80, 0x88, 0x88, 0x8f,
    457 		0x80, 0x88, 0x88, 0x8f, 0xf0, 0xf8, 0xf8, 0xff,
    458 	};
    459 
    460 	*addr = (map[data >> 4] | (map[data & 0x0f] << 8));
    461 }
    462 
    463 /*=============================================================================
    464  *
    465  *	D4_M2L_0
    466  *
    467  */
    468 static void
    469 put_oxel_D4_M2L_0(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    470 {
    471 	u_int32_t *addr = (u_int32_t *)xaddr;
    472 	static u_int32_t map[] = {
    473 		0xffff, 0xf0ff, 0x0fff, 0x00ff, 0xfff0, 0xf0f0, 0x0ff0, 0x00f0,
    474 		0xff0f, 0xf00f, 0x0f0f, 0x000f, 0xff00, 0xf000, 0x0f00, 0x0000,
    475 	};
    476 	*addr = (map[data >> 4] | (map[data & 0x0f] << 16));
    477 }
    478 
    479 /*=============================================================================
    480  *
    481  *	D4_M2L_0x2
    482  *
    483  */
    484 static void
    485 put_oxel_D4_M2L_0x2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    486 {
    487 	u_int16_t *addr = (u_int16_t *)xaddr;
    488 	static u_int16_t map[] = {
    489 		0xff, 0xf8, 0xf8, 0xf0, 0x8f, 0x88, 0x88, 0x80,
    490 		0x8f, 0x88, 0x88, 0x80, 0x0f, 0x08, 0x08, 0x00,
    491 	};
    492 
    493 	*addr = (map[data >> 4] | (map[data & 0x0f] << 8));
    494 }
    495 
    496 /*=============================================================================
    497  *
    498  *	D8_00
    499  *
    500  */
    501 static void
    502 put_oxel_D8_00(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    503 {
    504 	int i;
    505 	u_int8_t *addr = xaddr;
    506 
    507 	for (i = 0; i < 8; i++) {
    508 		if (mask & 0x80) {
    509 			*addr = (data & 0x80) ? 0x00 : 0xFF;
    510 		}
    511 		addr++;
    512 		data <<= 1;
    513 		mask <<= 1;
    514 	}
    515 }
    516 
    517 /*=============================================================================
    518  *
    519  *	D8_FF
    520  *
    521  */
    522 static void
    523 put_oxel_D8_FF(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    524 {
    525 	int i;
    526 	u_int8_t *addr = xaddr;
    527 
    528 	for (i = 0; i < 8; i++) {
    529 		if (mask & 0x80) {
    530 			*addr = (data & 0x80) ? 0xFF : 0x00;
    531 		}
    532 		addr++;
    533 		data <<= 1;
    534 		mask <<= 1;
    535 	}
    536 }
    537 
    538 /*=============================================================================
    539  *
    540  *	D16_0000
    541  *
    542  */
    543 static void
    544 put_oxel_D16_0000(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    545 {
    546 	int i;
    547 	u_int16_t *addr = (u_int16_t *)xaddr;
    548 
    549 	for (i = 0; i < 8; i++) {
    550 		if (mask & 0x80) {
    551 			*addr = (data & 0x80) ? 0x0000 : 0xFFFF;
    552 		}
    553 		addr++;
    554 		data <<= 1;
    555 		mask <<= 1;
    556 	}
    557 }
    558 
    559 /*=============================================================================
    560  *
    561  *	D16_FFFF
    562  *
    563  */
    564 static void
    565 put_oxel_D16_FFFF(u_int8_t *xaddr, u_int8_t data, u_int8_t mask)
    566 {
    567 	int i;
    568 	u_int16_t *addr = (u_int16_t *)xaddr;
    569 
    570 	for (i = 0; i < 8; i++) {
    571 		if (mask & 0x80) {
    572 			*addr = (data & 0x80) ? 0xFFFF : 0x0000;
    573 		}
    574 		addr++;
    575 		data <<= 1;
    576 		mask <<= 1;
    577 	}
    578 }
    579