1 /* $NetBSD: bicons.c,v 1.2 2001/02/09 20:42:27 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 bicons_init(struct consdev *cndev) 138 { 139 biconscninit(cndev); 140 biconscnprobe(cndev); 141 } 142 143 void 144 biconscninit(struct consdev *cndev) 145 { 146 int fb_index = -1; 147 148 for (fb_index = 0; fb_index < FB_TABLE_SIZE; fb_index++) 149 if (fb_table[fb_index].type == bootinfo->fb_type) 150 break; 151 152 if (FB_TABLE_SIZE <= fb_index || fb_index == -1) { 153 /* 154 * Unknown frame buffer type, but what can I do ? 155 */ 156 fb_index = 0; 157 } 158 159 fb_vram = (u_int8_t *)bootinfo->fb_addr; 160 fb_line_bytes = bootinfo->fb_line_bytes; 161 bicons_xpixel = bootinfo->fb_width; 162 bicons_ypixel = bootinfo->fb_height; 163 164 fb_put_oxel = fb_table[fb_index].func; 165 fb_clear_byte = fb_table[fb_index].clear_byte; 166 fb_oxel_bytes = fb_table[fb_index].oxel_bytes; 167 168 bicons_width = bicons_xpixel / (8 * FONT_WIDTH); 169 bicons_height = bicons_ypixel / FONT_HEIGHT; 170 clear(0, bicons_ypixel); 171 172 curs_x = 0; 173 curs_y = 0; 174 175 bicons_puts("builtin console type = "); 176 bicons_puts(fb_table[fb_index].name); 177 bicons_puts("\n"); 178 } 179 180 void 181 biconscnprobe(struct consdev *cndev) 182 { 183 int maj; 184 185 /* locate the major number */ 186 for (maj = 0; maj < nchrdev; maj++) 187 if (cdevsw[maj].d_open == biconsdevopen) 188 break; 189 190 cndev->cn_dev = makedev(maj, 0); 191 cndev->cn_pri = bicons_priority; 192 } 193 194 void 195 bicons_set_priority(int priority) 196 { 197 bicons_priority = priority; 198 } 199 200 int 201 biconscngetc(dev_t dev) 202 { 203 printf("no input method. reboot me.\n"); 204 while (1) 205 ; 206 /* NOTREACHED */ 207 } 208 209 void 210 biconscnputc(dev_t dev, int c) 211 { 212 int line_feed = 0; 213 214 switch (c) { 215 case 0x08: /* back space */ 216 if (--curs_x < 0) { 217 curs_x = 0; 218 } 219 /* erase character ar cursor position */ 220 draw_char(curs_x, curs_y, ' '); 221 break; 222 case '\r': 223 curs_x = 0; 224 break; 225 case '\n': 226 curs_x = 0; 227 line_feed = 1; 228 break; 229 default: 230 draw_char(curs_x, curs_y, c); 231 if (bicons_width <= ++curs_x) { 232 curs_x = 0; 233 line_feed = 1; 234 } 235 } 236 237 if (line_feed) { 238 if (bicons_height <= ++curs_y) { 239 /* scroll up */ 240 scroll(FONT_HEIGHT, (bicons_height - 1) * FONT_HEIGHT, 241 - FONT_HEIGHT); 242 clear((bicons_height - 1) * FONT_HEIGHT, FONT_HEIGHT); 243 curs_y--; 244 } 245 } 246 } 247 248 void 249 bicons_puts(char *s) 250 { 251 while (*s) 252 biconscnputc(NULL, *s++); 253 } 254 255 256 void 257 bicons_putn(const char *s, int n) 258 { 259 while (0 < n--) 260 biconscnputc(NULL, *s++); 261 } 262 263 void 264 #ifdef __STDC__ 265 bicons_printf(const char *fmt, ...) 266 #else 267 bicons_printf(fmt, va_alist) 268 char *fmt; 269 va_dcl 270 #endif 271 { 272 va_list ap; 273 char buf[0x100]; 274 275 va_start(ap, fmt); 276 vsnprintf(buf, sizeof(buf), fmt, ap); 277 va_end(ap); 278 bicons_puts(buf); 279 } 280 281 static void 282 draw_char(int x, int y, int c) 283 { 284 int i; 285 u_int8_t *p; 286 287 if (!fb_vram) 288 return; 289 290 p = &fb_vram[(y * FONT_HEIGHT * fb_line_bytes) + 291 x * FONT_WIDTH * fb_oxel_bytes]; 292 for (i = 0; i < FONT_HEIGHT; i++) { 293 (*fb_put_oxel)(p, font_clR8x8_data 294 [FONT_WIDTH * (FONT_HEIGHT * c + i)], 0xff); 295 p += (fb_line_bytes); 296 } 297 } 298 299 static void 300 clear(int y, int height) 301 { 302 u_int8_t *p; 303 304 if (!fb_vram) 305 return; 306 307 p = &fb_vram[y * fb_line_bytes]; 308 309 while (0 < height--) { 310 memset(p, fb_clear_byte, 311 bicons_width * fb_oxel_bytes * FONT_WIDTH); 312 p += fb_line_bytes; 313 } 314 } 315 316 static void 317 scroll(int y, int height, int d) 318 { 319 u_int8_t *from, *to; 320 321 if (!fb_vram) 322 return; 323 324 if (d < 0) { 325 from = &fb_vram[y * fb_line_bytes]; 326 to = from + d * fb_line_bytes; 327 while (0 < height--) { 328 memcpy(to, from, bicons_width * fb_oxel_bytes); 329 from += fb_line_bytes; 330 to += fb_line_bytes; 331 } 332 } else { 333 from = &fb_vram[(y + height - 1) * fb_line_bytes]; 334 to = from + d * fb_line_bytes; 335 while (0 < height--) { 336 memcpy(to, from, bicons_xpixel * fb_oxel_bytes / 8); 337 from -= fb_line_bytes; 338 to -= fb_line_bytes; 339 } 340 } 341 } 342 343 /*============================================================================= 344 * 345 * D2_M2L_3 346 * 347 */ 348 static void 349 put_oxel_D2_M2L_3(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 350 { 351 #if 1 352 u_int16_t *addr = (u_int16_t *)xaddr; 353 static u_int16_t map0[] = { 354 0x0000, 0x0300, 0x0c00, 0x0f00, 0x3000, 0x3300, 0x3c00, 0x3f00, 355 0xc000, 0xc300, 0xcc00, 0xcf00, 0xf000, 0xf300, 0xfc00, 0xff00, 356 }; 357 static u_int16_t map1[] = { 358 0x0000, 0x0003, 0x000c, 0x000f, 0x0030, 0x0033, 0x003c, 0x003f, 359 0x00c0, 0x00c3, 0x00cc, 0x00cf, 0x00f0, 0x00f3, 0x00fc, 0x00ff, 360 }; 361 *addr = (map1[data >> 4] | map0[data & 0x0f]); 362 #else 363 static u_int8_t map[] = { 364 0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f, 365 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff, 366 }; 367 u_int8_t *addr = xaddr; 368 369 *addr++ = (map[(data >> 4) & 0x0f] & map[(mask >> 4) & 0x0f]) | 370 (*addr & ~map[(mask >> 4) & 0x0f]); 371 *addr = (map[(data >> 0) & 0x0f] & map[(mask >> 0) & 0x0f]) | 372 (*addr & ~map[(mask >> 0) & 0x0f]); 373 #endif 374 } 375 376 /*============================================================================= 377 * 378 * D2_M2L_3x2 379 * 380 */ 381 static void 382 put_oxel_D2_M2L_3x2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 383 { 384 register u_int8_t odd = (data & 0xaa); 385 register u_int8_t even = (data & 0x55); 386 387 *xaddr = (odd | (even << 1)) | ((odd >> 1) & even); 388 } 389 390 /*============================================================================= 391 * 392 * D2_M2L_0 393 * 394 */ 395 static void 396 put_oxel_D2_M2L_0(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 397 { 398 #if 1 399 u_int16_t *addr = (u_int16_t *)xaddr; 400 static u_int16_t map0[] = { 401 0xff00, 0xfc00, 0xf300, 0xf000, 0xcf00, 0xcc00, 0xc300, 0xc000, 402 0x3f00, 0x3c00, 0x3300, 0x3000, 0x0f00, 0x0c00, 0x0300, 0x0000, 403 }; 404 static u_int16_t map1[] = { 405 0x00ff, 0x00fc, 0x00f3, 0x00f0, 0x00cf, 0x00cc, 0x00c3, 0x00c0, 406 0x003f, 0x003c, 0x0033, 0x0030, 0x000f, 0x000c, 0x0003, 0x0000, 407 }; 408 *addr = (map1[data >> 4] | map0[data & 0x0f]); 409 #else 410 static u_int8_t map[] = { 411 0x00, 0x03, 0x0c, 0x0f, 0x30, 0x33, 0x3c, 0x3f, 412 0xc0, 0xc3, 0xcc, 0xcf, 0xf0, 0xf3, 0xfc, 0xff, 413 }; 414 u_int8_t *addr = xaddr; 415 416 *addr++ = (~(map[(data >> 4) & 0x0f] & map[(mask >> 4) & 0x0f])) | 417 (*addr & ~map[(mask >> 4) & 0x0f]); 418 *addr = (~(map[(data >> 0) & 0x0f] & map[(mask >> 0) & 0x0f])) | 419 (*addr & ~map[(mask >> 0) & 0x0f]); 420 #endif 421 } 422 423 /*============================================================================= 424 * 425 * D2_M2L_0x2 426 * 427 */ 428 static void 429 put_oxel_D2_M2L_0x2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 430 { 431 register u_int8_t odd = (data & 0xaa); 432 register u_int8_t even = (data & 0x55); 433 434 *xaddr = ~((odd | (even << 1)) | ((odd >> 1) & even)); 435 } 436 437 /*============================================================================= 438 * 439 * D4_M2L_F 440 * 441 */ 442 static void 443 put_oxel_D4_M2L_F(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 444 { 445 u_int32_t *addr = (u_int32_t *)xaddr; 446 static u_int32_t map[] = { 447 0x0000, 0x0f00, 0xf000, 0xff00, 0x000f, 0x0f0f, 0xf00f, 0xff0f, 448 0x00f0, 0x0ff0, 0xf0f0, 0xfff0, 0x00ff, 0x0fff, 0xf0ff, 0xffff, 449 }; 450 *addr = (map[data >> 4] | (map[data & 0x0f] << 16)); 451 } 452 453 /*============================================================================= 454 * 455 * D4_M2L_Fx2 456 * 457 */ 458 static void 459 put_oxel_D4_M2L_Fx2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 460 { 461 u_int16_t *addr = (u_int16_t *)xaddr; 462 static u_int16_t map[] = { 463 0x00, 0x08, 0x08, 0x0f, 0x80, 0x88, 0x88, 0x8f, 464 0x80, 0x88, 0x88, 0x8f, 0xf0, 0xf8, 0xf8, 0xff, 465 }; 466 467 *addr = (map[data >> 4] | (map[data & 0x0f] << 8)); 468 } 469 470 /*============================================================================= 471 * 472 * D4_M2L_0 473 * 474 */ 475 static void 476 put_oxel_D4_M2L_0(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 477 { 478 u_int32_t *addr = (u_int32_t *)xaddr; 479 static u_int32_t map[] = { 480 0xffff, 0xf0ff, 0x0fff, 0x00ff, 0xfff0, 0xf0f0, 0x0ff0, 0x00f0, 481 0xff0f, 0xf00f, 0x0f0f, 0x000f, 0xff00, 0xf000, 0x0f00, 0x0000, 482 }; 483 *addr = (map[data >> 4] | (map[data & 0x0f] << 16)); 484 } 485 486 /*============================================================================= 487 * 488 * D4_M2L_0x2 489 * 490 */ 491 static void 492 put_oxel_D4_M2L_0x2(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 493 { 494 u_int16_t *addr = (u_int16_t *)xaddr; 495 static u_int16_t map[] = { 496 0xff, 0xf8, 0xf8, 0xf0, 0x8f, 0x88, 0x88, 0x80, 497 0x8f, 0x88, 0x88, 0x80, 0x0f, 0x08, 0x08, 0x00, 498 }; 499 500 *addr = (map[data >> 4] | (map[data & 0x0f] << 8)); 501 } 502 503 /*============================================================================= 504 * 505 * D8_00 506 * 507 */ 508 static void 509 put_oxel_D8_00(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 510 { 511 int i; 512 u_int8_t *addr = xaddr; 513 514 for (i = 0; i < 8; i++) { 515 if (mask & 0x80) { 516 *addr = (data & 0x80) ? 0x00 : 0xFF; 517 } 518 addr++; 519 data <<= 1; 520 mask <<= 1; 521 } 522 } 523 524 /*============================================================================= 525 * 526 * D8_FF 527 * 528 */ 529 static void 530 put_oxel_D8_FF(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 531 { 532 int i; 533 u_int8_t *addr = xaddr; 534 535 for (i = 0; i < 8; i++) { 536 if (mask & 0x80) { 537 *addr = (data & 0x80) ? 0xFF : 0x00; 538 } 539 addr++; 540 data <<= 1; 541 mask <<= 1; 542 } 543 } 544 545 /*============================================================================= 546 * 547 * D16_0000 548 * 549 */ 550 static void 551 put_oxel_D16_0000(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 552 { 553 int i; 554 u_int16_t *addr = (u_int16_t *)xaddr; 555 556 for (i = 0; i < 8; i++) { 557 if (mask & 0x80) { 558 *addr = (data & 0x80) ? 0x0000 : 0xFFFF; 559 } 560 addr++; 561 data <<= 1; 562 mask <<= 1; 563 } 564 } 565 566 /*============================================================================= 567 * 568 * D16_FFFF 569 * 570 */ 571 static void 572 put_oxel_D16_FFFF(u_int8_t *xaddr, u_int8_t data, u_int8_t mask) 573 { 574 int i; 575 u_int16_t *addr = (u_int16_t *)xaddr; 576 577 for (i = 0; i < 8; i++) { 578 if (mask & 0x80) { 579 *addr = (data & 0x80) ? 0xFFFF : 0x0000; 580 } 581 addr++; 582 data <<= 1; 583 mask <<= 1; 584 } 585 } 586