1 /* $NetBSD: bicons.c,v 1.12 2007/10/19 11:59:42 ad Exp $ */
4 * Copyright (c) 1999-2001
5 * Shin Takemura and PocketBSD Project. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: bicons.c,v 1.12 2007/10/19 11:59:42 ad Exp $");
42 #include <sys/param.h>
43 #include <sys/device.h>
44 #include <sys/systm.h>
48 #include <machine/bootinfo.h>
50 #include <machine/platid.h>
51 #include <machine/stdarg.h>
53 #include <dev/hpc/biconsvar.h>
54 #include <dev/hpc/bicons.h>
55 extern u_int8_t font_clR8x8_data
[];
59 static void put_oxel_D2_M2L_3(u_int8_t
*, u_int8_t
, u_int8_t
);
60 static void put_oxel_D2_M2L_3x2(u_int8_t
*, u_int8_t
, u_int8_t
);
61 static void put_oxel_D2_M2L_0(u_int8_t
*, u_int8_t
, u_int8_t
);
62 static void put_oxel_D2_M2L_0x2(u_int8_t
*, u_int8_t
, u_int8_t
);
63 static void put_oxel_D4_M2L_F(u_int8_t
*, u_int8_t
, u_int8_t
);
64 static void put_oxel_D4_M2L_Fx2(u_int8_t
*, u_int8_t
, u_int8_t
);
65 static void put_oxel_D4_M2L_0(u_int8_t
*, u_int8_t
, u_int8_t
);
66 static void put_oxel_D4_M2L_0x2(u_int8_t
*, u_int8_t
, u_int8_t
);
67 static void put_oxel_D8_00(u_int8_t
*, u_int8_t
, u_int8_t
);
68 static void put_oxel_D8_FF(u_int8_t
*, u_int8_t
, u_int8_t
);
69 static void put_oxel_D16_0000(u_int8_t
*, u_int8_t
, u_int8_t
);
70 static void put_oxel_D16_FFFF(u_int8_t
*, u_int8_t
, u_int8_t
);
75 void (*func
)(u_int8_t
*, u_int8_t
, u_int8_t
);
79 { BIFB_D2_M2L_3
, BIFBN_D2_M2L_3
,
80 put_oxel_D2_M2L_3
, 0, 2 },
81 { BIFB_D2_M2L_3x2
, BIFBN_D2_M2L_3x2
,
82 put_oxel_D2_M2L_3x2
, 0, 1 },
83 { BIFB_D2_M2L_0
, BIFBN_D2_M2L_0
,
84 put_oxel_D2_M2L_0
, 0xff, 2 },
85 { BIFB_D2_M2L_0x2
, BIFBN_D2_M2L_0x2
,
86 put_oxel_D2_M2L_0x2
, 0xff, 1 },
87 { BIFB_D4_M2L_F
, BIFBN_D4_M2L_F
,
88 put_oxel_D4_M2L_F
, 0x00, 4 },
89 { BIFB_D4_M2L_Fx2
, BIFBN_D4_M2L_Fx2
,
90 put_oxel_D4_M2L_Fx2
, 0x00, 2 },
91 { BIFB_D4_M2L_0
, BIFBN_D4_M2L_0
,
92 put_oxel_D4_M2L_0
, 0xff, 4 },
93 { BIFB_D4_M2L_0x2
, BIFBN_D4_M2L_0x2
,
94 put_oxel_D4_M2L_0x2
, 0xff, 2 },
95 { BIFB_D8_00
, BIFBN_D8_00
,
96 put_oxel_D8_00
, 0xff, 8 },
97 { BIFB_D8_FF
, BIFBN_D8_FF
,
98 put_oxel_D8_FF
, 0x00, 8 },
99 { BIFB_D16_0000
, BIFBN_D16_0000
,
100 put_oxel_D16_0000
, 0xff, 16 },
101 { BIFB_D16_FFFF
, BIFBN_D16_FFFF
,
102 put_oxel_D16_FFFF
, 0x00, 16 },
104 #define FB_TABLE_SIZE (sizeof(fb_table) / sizeof(*fb_table))
106 static u_int8_t
*fb_vram
;
107 static int16_t fb_line_bytes
;
108 static u_int8_t fb_clear_byte
;
109 int16_t bicons_ypixel
;
110 int16_t bicons_xpixel
;
112 static int16_t fb_oxel_bytes
= 1;
113 int16_t bicons_width
= 80;
114 void (*fb_put_oxel
)(u_int8_t
*, u_int8_t
, u_int8_t
) = put_oxel_D2_M2L_3x2
;
115 #else /* HALF_FONT */
116 static int16_t fb_oxel_bytes
= 2;
117 int16_t bicons_width
= 40;
118 void (*fb_put_oxel
)(u_int8_t
*, u_int8_t
, u_int8_t
) = put_oxel_D2_M2L_3
;
119 #endif /* HALF_FONT */
120 int16_t bicons_height
;
121 static int16_t curs_x
;
122 static int16_t curs_y
;
124 static int bicons_priority
;
125 int biconscninit(struct consdev
*);
126 void biconscnprobe(struct consdev
*);
127 void biconscnputc(dev_t
, int);
128 int biconscngetc(dev_t
); /* harmless place holder */
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(const char *);
134 static void bicons_printf(const char *, ...) __unused
;
137 bicons_init(struct consdev
*cndev
)
140 if (biconscninit(cndev
) != 0)
143 biconscnprobe(cndev
);
145 return (0); /* success */
149 biconscninit(struct consdev
*cndev
)
153 if (bootinfo
->fb_addr
== 0) {
154 /* Bootinfo don't have frame buffer address */
158 for (fb_index
= 0; fb_index
< FB_TABLE_SIZE
; fb_index
++)
159 if (fb_table
[fb_index
].type
== bootinfo
->fb_type
)
162 if (FB_TABLE_SIZE
<= fb_index
|| fb_index
== -1) {
163 /* Unknown frame buffer type, don't enable bicons. */
167 fb_vram
= (u_int8_t
*)bootinfo
->fb_addr
;
168 fb_line_bytes
= bootinfo
->fb_line_bytes
;
169 bicons_xpixel
= bootinfo
->fb_width
;
170 bicons_ypixel
= bootinfo
->fb_height
;
172 fb_put_oxel
= fb_table
[fb_index
].func
;
173 fb_clear_byte
= fb_table
[fb_index
].clear_byte
;
174 fb_oxel_bytes
= fb_table
[fb_index
].oxel_bytes
;
176 bicons_width
= bicons_xpixel
/ (8 * FONT_WIDTH
);
177 bicons_height
= bicons_ypixel
/ FONT_HEIGHT
;
178 clear(0, bicons_ypixel
);
183 bicons_puts("builtin console type = ");
184 bicons_puts(fb_table
[fb_index
].name
);
191 biconscnprobe(struct consdev
*cndev
)
193 extern const struct cdevsw biconsdev_cdevsw
;
196 /* locate the major number */
197 maj
= cdevsw_lookup_major(&biconsdev_cdevsw
);
199 cndev
->cn_dev
= makedev(maj
, 0);
200 cndev
->cn_pri
= bicons_priority
;
204 bicons_set_priority(int priority
)
206 bicons_priority
= priority
;
210 biconscngetc(dev_t dev
)
212 printf("no input method. reboot me.\n");
220 biconscnputc(dev_t dev
, int c
)
225 case 0x08: /* back space */
229 /* erase character ar cursor position */
230 draw_char(curs_x
, curs_y
, ' ');
240 draw_char(curs_x
, curs_y
, c
);
241 if (bicons_width
<= ++curs_x
) {
248 if (bicons_height
<= ++curs_y
) {
250 scroll(FONT_HEIGHT
, (bicons_height
- 1) * FONT_HEIGHT
,
252 clear((bicons_height
- 1) * FONT_HEIGHT
, FONT_HEIGHT
);
259 bicons_puts(const char *s
)
262 biconscnputc(0, *s
++);
267 bicons_putn(const char *s
, int n
)
270 biconscnputc(0, *s
++);
275 bicons_printf(const char *fmt
, ...)
277 bicons_printf(fmt
, va_alist
)
286 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
292 draw_char(int x
, int y
, int c
)
300 p
= &fb_vram
[(y
* FONT_HEIGHT
* fb_line_bytes
) +
301 x
* FONT_WIDTH
* fb_oxel_bytes
];
302 for (i
= 0; i
< FONT_HEIGHT
; i
++) {
303 (*fb_put_oxel
)(p
, font_clR8x8_data
304 [FONT_WIDTH
* (FONT_HEIGHT
* c
+ i
)], 0xff);
305 p
+= (fb_line_bytes
);
310 clear(int y
, int height
)
317 p
= &fb_vram
[y
* fb_line_bytes
];
319 while (0 < height
--) {
320 memset(p
, fb_clear_byte
,
321 bicons_width
* fb_oxel_bytes
* FONT_WIDTH
);
327 scroll(int y
, int height
, int d
)
335 from
= &fb_vram
[y
* fb_line_bytes
];
336 to
= from
+ d
* fb_line_bytes
;
337 while (0 < height
--) {
338 memcpy(to
, from
, bicons_width
* fb_oxel_bytes
);
339 from
+= fb_line_bytes
;
343 from
= &fb_vram
[(y
+ height
- 1) * fb_line_bytes
];
344 to
= from
+ d
* fb_line_bytes
;
345 while (0 < height
--) {
346 memcpy(to
, from
, bicons_xpixel
* fb_oxel_bytes
/ 8);
347 from
-= fb_line_bytes
;
353 /*=============================================================================
359 put_oxel_D2_M2L_3(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
362 u_int16_t
*addr
= (u_int16_t
*)xaddr
;
363 static u_int16_t map0
[] = {
364 0x0000, 0x0300, 0x0c00, 0x0f00, 0x3000, 0x3300, 0x3c00, 0x3f00,
365 0xc000, 0xc300, 0xcc00, 0xcf00, 0xf000, 0xf300, 0xfc00, 0xff00,
367 static u_int16_t map1
[] = {
368 0x0000, 0x0003, 0x000c, 0x000f, 0x0030, 0x0033, 0x003c, 0x003f,
369 0x00c0, 0x00c3, 0x00cc, 0x00cf, 0x00f0, 0x00f3, 0x00fc, 0x00ff,
371 *addr
= (map1
[data
>> 4] | map0
[data
& 0x0f]);
373 static u_int8_t map
[] = {
374 0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f,
375 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff,
377 u_int8_t
*addr
= xaddr
;
379 *addr
++ = (map
[(data
>> 4) & 0x0f] & map
[(mask
>> 4) & 0x0f]) |
380 (*addr
& ~map
[(mask
>> 4) & 0x0f]);
381 *addr
= (map
[(data
>> 0) & 0x0f] & map
[(mask
>> 0) & 0x0f]) |
382 (*addr
& ~map
[(mask
>> 0) & 0x0f]);
386 /*=============================================================================
392 put_oxel_D2_M2L_3x2(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
394 register u_int8_t odd
= (data
& 0xaa);
395 register u_int8_t even
= (data
& 0x55);
397 *xaddr
= (odd
| (even
<< 1)) | ((odd
>> 1) & even
);
400 /*=============================================================================
406 put_oxel_D2_M2L_0(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
409 u_int16_t
*addr
= (u_int16_t
*)xaddr
;
410 static u_int16_t map0
[] = {
411 0xff00, 0xfc00, 0xf300, 0xf000, 0xcf00, 0xcc00, 0xc300, 0xc000,
412 0x3f00, 0x3c00, 0x3300, 0x3000, 0x0f00, 0x0c00, 0x0300, 0x0000,
414 static u_int16_t map1
[] = {
415 0x00ff, 0x00fc, 0x00f3, 0x00f0, 0x00cf, 0x00cc, 0x00c3, 0x00c0,
416 0x003f, 0x003c, 0x0033, 0x0030, 0x000f, 0x000c, 0x0003, 0x0000,
418 *addr
= (map1
[data
>> 4] | map0
[data
& 0x0f]);
420 static u_int8_t map
[] = {
421 0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f,
422 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff,
424 u_int8_t
*addr
= xaddr
;
426 *addr
++ = (~(map
[(data
>> 4) & 0x0f] & map
[(mask
>> 4) & 0x0f])) |
427 (*addr
& ~map
[(mask
>> 4) & 0x0f]);
428 *addr
= (~(map
[(data
>> 0) & 0x0f] & map
[(mask
>> 0) & 0x0f])) |
429 (*addr
& ~map
[(mask
>> 0) & 0x0f]);
433 /*=============================================================================
439 put_oxel_D2_M2L_0x2(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
441 register u_int8_t odd
= (data
& 0xaa);
442 register u_int8_t even
= (data
& 0x55);
444 *xaddr
= ~((odd
| (even
<< 1)) | ((odd
>> 1) & even
));
447 /*=============================================================================
453 put_oxel_D4_M2L_F(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
455 u_int32_t
*addr
= (u_int32_t
*)xaddr
;
456 static u_int32_t map
[] = {
457 0x0000, 0x0f00, 0xf000, 0xff00, 0x000f, 0x0f0f, 0xf00f, 0xff0f,
458 0x00f0, 0x0ff0, 0xf0f0, 0xfff0, 0x00ff, 0x0fff, 0xf0ff, 0xffff,
460 *addr
= (map
[data
>> 4] | (map
[data
& 0x0f] << 16));
463 /*=============================================================================
469 put_oxel_D4_M2L_Fx2(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
471 u_int16_t
*addr
= (u_int16_t
*)xaddr
;
472 static u_int16_t map
[] = {
473 0x00, 0x08, 0x08, 0x0f, 0x80, 0x88, 0x88, 0x8f,
474 0x80, 0x88, 0x88, 0x8f, 0xf0, 0xf8, 0xf8, 0xff,
477 *addr
= (map
[data
>> 4] | (map
[data
& 0x0f] << 8));
480 /*=============================================================================
486 put_oxel_D4_M2L_0(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
488 u_int32_t
*addr
= (u_int32_t
*)xaddr
;
489 static u_int32_t map
[] = {
490 0xffff, 0xf0ff, 0x0fff, 0x00ff, 0xfff0, 0xf0f0, 0x0ff0, 0x00f0,
491 0xff0f, 0xf00f, 0x0f0f, 0x000f, 0xff00, 0xf000, 0x0f00, 0x0000,
493 *addr
= (map
[data
>> 4] | (map
[data
& 0x0f] << 16));
496 /*=============================================================================
502 put_oxel_D4_M2L_0x2(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
504 u_int16_t
*addr
= (u_int16_t
*)xaddr
;
505 static u_int16_t map
[] = {
506 0xff, 0xf8, 0xf8, 0xf0, 0x8f, 0x88, 0x88, 0x80,
507 0x8f, 0x88, 0x88, 0x80, 0x0f, 0x08, 0x08, 0x00,
510 *addr
= (map
[data
>> 4] | (map
[data
& 0x0f] << 8));
513 /*=============================================================================
519 put_oxel_D8_00(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
522 u_int8_t
*addr
= xaddr
;
524 for (i
= 0; i
< 8; i
++) {
526 *addr
= (data
& 0x80) ? 0x00 : 0xFF;
534 /*=============================================================================
540 put_oxel_D8_FF(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
543 u_int8_t
*addr
= xaddr
;
545 for (i
= 0; i
< 8; i
++) {
547 *addr
= (data
& 0x80) ? 0xFF : 0x00;
555 /*=============================================================================
561 put_oxel_D16_0000(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
564 u_int16_t
*addr
= (u_int16_t
*)xaddr
;
566 for (i
= 0; i
< 8; i
++) {
568 *addr
= (data
& 0x80) ? 0x0000 : 0xFFFF;
576 /*=============================================================================
582 put_oxel_D16_FFFF(u_int8_t
*xaddr
, u_int8_t data
, u_int8_t mask
)
585 u_int16_t
*addr
= (u_int16_t
*)xaddr
;
587 for (i
= 0; i
< 8; i
++) {
589 *addr
= (data
& 0x80) ? 0xFFFF : 0x0000;