Print this page
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    9259 libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Revert "NEX-16819 loader UEFI support"
This reverts commit ec06b9fc617b99234e538bf2e7e4d02a24993e0c.
Reverting due to failures in the zfs-tests and the sharefs-tests
NEX-16819 loader UEFI support
Includes work by Toomas Soome <tsoome@me.com>
Upstream commits:
    loader: pxe receive cleanup
    9475 libefi: Do not return only if ReceiveFilter
    installboot: should support efi system partition
    8931 boot1.efi: scan all display modes rather than
    loader: spinconsole updates
    loader: gfx experiment to try GOP Blt() function.
    sha1 build test
    loader: add sha1 hash calculation
    common/sha1: update for loader build
    loader: biosdisk rework
    uts: 32-bit kernel FB needs mapping in low memory
    uts: add diag-device
    uts: boot console mirror with diag-device
    uts: enable very early console on ttya
    kmdb: add diag-device as input/output device
    uts: test VGA memory exclusion from mapping
    uts: clear boot mapping and protect boot pages test
    uts: add dboot map debug printf
    uts: need to release FB pages in release_bootstrap()
    uts: add screenmap ioctl
    uts: update sys/queue.h
    loader: add illumos uts/common to include path
    loader: tem/gfx font cleanup
    loader: vbe checks
    uts: gfx_private set KD_TEXT when KD_RESETTEXT is
    uts: gfx 8-bit update
    loader: gfx 8-bit fix
    loader: always set media size from partition.
    uts: MB2 support for 32-bit kernel
    loader: x86 should have tem 80x25
    uts: x86 should have tem 80x25
    uts: font update
    loader: font update
    uts: tem attributes
    loader: tem.c comment added
    uts: use font module
    loader: add font module
    loader: build rules for new font setup
    uts: gfx_private update for new font structure
    uts: early boot update for new font structure
    uts: font update
    uts: font build rules update for new fonts
    uts: tem update to new font structure
    loader: module.c needs to include tem_impl.h
    uts: gfx_private 8x16 font rework
    uts: make font_lookup public
    loader: font rework
    uts: font rework
    libefi: efi_alloc_and_read should check for PMBR
    uts: tem utf-8 support
    loader: implement tem utf-8 support
    loader: tem should be able to display UTF-8
    7784 uts: console input should support utf-8
    7796 uts: ldterm default to utf-8
    uts: do not reset serial console
    uts: set up colors even if tem is not console
    uts: add type for early boot properties
    uts: gfx_private experiment with drm and vga
    uts: gfx_private should use setmode drm callback.
    uts: identify FB types and set up gfx_private based
    loader: replace gop and vesa with framebuffer
    uts: boot needs simple tem to support mdb
    uts: boot_keyboard should emit esc sequences for
    uts: gfx_private FB showuld be written by line
    kmdb: set terminal window size
    uts: gfx_private needs to keep track of early boot FB
    pnglite: move pnglite to usr/src/common
    loader: gfx_fb
    ficl-sys: add gfx primitives
    loader: add illumos.png logo
    ficl: add fb-putimage
    loader: add png support
    loader: add alpha blending for gfx_fb
    loader: use term-drawrect for menu frame
    ficl: add simple gfx words
    uts: provide fb_info via fbgattr dev_specific array.
    uts: gfx_private add alpha blending
    uts: update sys/ascii.h
    uts: tem OSC support (incomplete)
    uts: implement env module support and use data from
    uts: tem get colors from early boot data
    loader: use crc32 from libstand (libz)
    loader: optimize for size
    loader: pass tem info to the environment
    loader: import tem for loader console
    loader: UEFI loader needs to set ISADIR based on
    loader: need UEFI32 support
    8918 loader.efi: add vesa edid support
    uts: tem_safe_pix_clear_prom_output() should only
    uts: tem_safe_pix_clear_entire_screen() should use
    uts: tem_safe_check_first_time() should query cursor
    uts: tem implement cls callback & visual_io v4
    uts: gfx_vgatext use block cursor for vgatext
    uts: gfx_private implement cls callback & visual_io
    uts: gfx_private bitmap framebuffer implementation
    uts: early start frame buffer console support
    uts: font functions should check the input char
    uts: font rendering should support 16/24/32bit depths
    uts: use smallest font as fallback default.
    uts: update terminal dimensions based on selected
    7834 uts: vgatext should use gfx_private
    uts: add spacing property to 8859-1.bdf
    terminfo: add underline for sun-color
    terminfo: sun-color has 16 colors
    uts: add font load callback type
    loader: do not repeat int13 calls with error 0x20 and
    8905 loader: add skein/edonr support
    8904 common/crypto: make skein and edonr loader
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>


 104 static void     tem_free_buf(struct tem_vt_state *);
 105 static void     tem_internal_init(struct tem_vt_state *, cred_t *, boolean_t,
 106                     boolean_t);
 107 static void     tems_get_initial_color(tem_color_t *pcolor);
 108 
 109 /*
 110  * Globals
 111  */
 112 static ldi_ident_t      term_li = NULL;
 113 tem_state_t     tems;   /* common term info */
 114 _NOTE(MUTEX_PROTECTS_DATA(tems.ts_lock, tems))
 115 
 116 extern struct mod_ops mod_miscops;
 117 
 118 static struct modlmisc  modlmisc = {
 119         &mod_miscops,       /* modops */
 120         "ANSI Terminal Emulator", /* name */
 121 };
 122 
 123 static struct modlinkage modlinkage = {
 124         MODREV_1, (void *)&modlmisc, NULL
 125 };
 126 
 127 int
 128 _init(void)
 129 {
 130         int ret;
 131         ret = mod_install(&modlinkage);
 132         if (ret != 0)
 133                 return (ret);
 134         ret = ldi_ident_from_mod(&modlinkage, &term_li);
 135         if (ret != 0) {
 136                 (void) mod_remove(&modlinkage);
 137                 return (ret);
 138         }
 139 
 140         mutex_init(&tems.ts_lock, (char *)NULL, MUTEX_DRIVER, NULL);
 141         list_create(&tems.ts_list, sizeof (struct tem_vt_state),
 142             offsetof(struct tem_vt_state, tvs_list_node));
 143         tems.ts_active = NULL;
 144 


 192         mutex_enter(&tems.ts_lock);
 193         mutex_enter(&tem->tvs_lock);
 194 
 195         if (!tem->tvs_initialized) {
 196                 mutex_exit(&tem->tvs_lock);
 197                 mutex_exit(&tems.ts_lock);
 198                 return;
 199         }
 200 
 201         tem_safe_check_first_time(tem, credp, CALLED_FROM_NORMAL);
 202         tem_safe_terminal_emulate(tem, buf, len, credp, CALLED_FROM_NORMAL);
 203 
 204         mutex_exit(&tem->tvs_lock);
 205         mutex_exit(&tems.ts_lock);
 206 }
 207 
 208 static void
 209 tem_internal_init(struct tem_vt_state *ptem, cred_t *credp,
 210     boolean_t init_color, boolean_t clear_screen)
 211 {
 212         int i, j;
 213         int width, height;
 214         int total;
 215         text_color_t fg;
 216         text_color_t bg;
 217         size_t  tc_size = sizeof (text_color_t);
 218 
 219         ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&ptem->tvs_lock));
 220 
 221         if (tems.ts_display_mode == VIS_PIXEL) {
 222                 ptem->tvs_pix_data_size = tems.ts_pix_data_size;
 223                 ptem->tvs_pix_data =
 224                     kmem_alloc(ptem->tvs_pix_data_size, KM_SLEEP);
 225         }
 226 
 227         ptem->tvs_outbuf_size = tems.ts_c_dimension.width;
 228         ptem->tvs_outbuf =
 229             (unsigned char *)kmem_alloc(ptem->tvs_outbuf_size, KM_SLEEP);
 230 
 231         width = tems.ts_c_dimension.width;
 232         height = tems.ts_c_dimension.height;
 233         ptem->tvs_screen_buf_size = width * height;
 234         ptem->tvs_screen_buf =
 235             (unsigned char *)kmem_alloc(width * height, KM_SLEEP);
 236 
 237         total = width * height * tc_size;
 238         ptem->tvs_fg_buf = (text_color_t *)kmem_alloc(total, KM_SLEEP);
 239         ptem->tvs_bg_buf = (text_color_t *)kmem_alloc(total, KM_SLEEP);
 240         ptem->tvs_color_buf_size = total;

 241 
 242         tem_safe_reset_display(ptem, credp, CALLED_FROM_NORMAL,
 243             clear_screen, init_color);
 244 
 245         ptem->tvs_utf8_left = 0;
 246         ptem->tvs_utf8_partial = 0;
 247 
 248         tem_safe_get_color(ptem, &fg, &bg, TEM_ATTR_SCREEN_REVERSE);
 249         for (i = 0; i < height; i++)



 250                 for (j = 0; j < width; j++) {
 251                         ptem->tvs_screen_buf[i * width + j] = ' ';
 252                         ptem->tvs_fg_buf[(i * width +j) * tc_size] = fg;
 253                         ptem->tvs_bg_buf[(i * width +j) * tc_size] = bg;

 254 
 255                 }

 256 
 257         ptem->tvs_initialized  = 1;
 258 }
 259 
 260 int
 261 tem_initialized(tem_vt_state_t tem_arg)
 262 {
 263         struct tem_vt_state *ptem = (struct tem_vt_state *)tem_arg;
 264         int ret;
 265 
 266         mutex_enter(&ptem->tvs_lock);
 267         ret = ptem->tvs_initialized;
 268         mutex_exit(&ptem->tvs_lock);
 269 
 270         return (ret);
 271 }
 272 
 273 tem_vt_state_t
 274 tem_init(cred_t *credp)
 275 {
 276         struct tem_vt_state *ptem;
 277 
 278         ptem = kmem_zalloc(sizeof (struct tem_vt_state), KM_SLEEP);
 279         mutex_init(&ptem->tvs_lock, (char *)NULL, MUTEX_DRIVER, NULL);
 280 
 281         mutex_enter(&tems.ts_lock);
 282         mutex_enter(&ptem->tvs_lock);
 283 
 284         ptem->tvs_isactive = B_FALSE;
 285         ptem->tvs_fbmode = KD_TEXT;
 286 
 287         /*
 288          * A tem is regarded as initialized only after tem_internal_init(),
 289          * will be set at the end of tem_internal_init().
 290          */
 291         ptem->tvs_initialized = 0;
 292 
 293 
 294         if (!tems.ts_initialized) {
 295                 /*
 296                  * Only happens during early console configuration.
 297                  */
 298                 tem_add(ptem);
 299                 mutex_exit(&ptem->tvs_lock);
 300                 mutex_exit(&tems.ts_lock);
 301                 return ((tem_vt_state_t)ptem);
 302         }
 303 
 304         tem_internal_init(ptem, credp, B_TRUE, B_FALSE);
 305         tem_add(ptem);
 306         mutex_exit(&ptem->tvs_lock);
 307         mutex_exit(&tems.ts_lock);
 308 
 309         return ((tem_vt_state_t)ptem);
 310 }
 311 


 318 {
 319         ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
 320 
 321         tem_free_buf(tem); /* only free virtual buffers */
 322 
 323         /* reserve color */
 324         tem_internal_init(tem, kcred, B_FALSE, reset_display);
 325 }
 326 
 327 static void
 328 tem_free_buf(struct tem_vt_state *tem)
 329 {
 330         ASSERT(tem != NULL && MUTEX_HELD(&tem->tvs_lock));
 331 
 332         if (tem->tvs_outbuf != NULL)
 333                 kmem_free(tem->tvs_outbuf, tem->tvs_outbuf_size);
 334         if (tem->tvs_pix_data != NULL)
 335                 kmem_free(tem->tvs_pix_data, tem->tvs_pix_data_size);
 336         if (tem->tvs_screen_buf != NULL)
 337                 kmem_free(tem->tvs_screen_buf, tem->tvs_screen_buf_size);
 338         if (tem->tvs_fg_buf != NULL)
 339                 kmem_free(tem->tvs_fg_buf, tem->tvs_color_buf_size);
 340         if (tem->tvs_bg_buf != NULL)
 341                 kmem_free(tem->tvs_bg_buf, tem->tvs_color_buf_size);
 342 }
 343 
 344 void
 345 tem_destroy(tem_vt_state_t tem_arg, cred_t *credp)
 346 {
 347         struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 348 
 349         mutex_enter(&tems.ts_lock);
 350         mutex_enter(&tem->tvs_lock);
 351 
 352         if (tem->tvs_isactive && tem->tvs_fbmode == KD_TEXT)
 353                 tem_safe_blank_screen(tem, credp, CALLED_FROM_NORMAL);
 354 
 355         tem_free_buf(tem);
 356         tem_rm(tem);
 357 
 358         if (tems.ts_active == tem)
 359                 tems.ts_active = NULL;
 360 
 361         mutex_exit(&tem->tvs_lock);


 441         /* Make sure the fb driver and terminal emulator versions match */
 442         if (temargs.version != VIS_CONS_REV) {
 443                 cmn_err(CE_WARN,
 444                     "terminal emulator: VIS_CONS_REV %d (see sys/visual_io.h) "
 445                     "of console fb driver not supported", temargs.version);
 446                 ret = tems_failed(credp, B_TRUE);
 447                 mutex_exit(&tems.ts_lock);
 448                 return (ret);
 449         }
 450 
 451         if ((tems.ts_fb_polledio = temargs.polledio) == NULL) {
 452                 cmn_err(CE_WARN, "terminal emulator: fb doesn't support polled "
 453                     "I/O");
 454                 ret = tems_failed(credp, B_TRUE);
 455                 mutex_exit(&tems.ts_lock);
 456                 return (ret);
 457         }
 458 
 459         /* other sanity checks */
 460         if (!((temargs.depth == 4) || (temargs.depth == 8) ||

 461             (temargs.depth == 24) || (temargs.depth == 32))) {
 462                 cmn_err(CE_WARN, "terminal emulator: unsupported depth");
 463                 ret = tems_failed(credp, B_TRUE);
 464                 mutex_exit(&tems.ts_lock);
 465                 return (ret);
 466         }
 467 
 468         if ((temargs.mode != VIS_TEXT) && (temargs.mode != VIS_PIXEL)) {
 469                 cmn_err(CE_WARN, "terminal emulator: unsupported mode");
 470                 ret = tems_failed(credp, B_TRUE);
 471                 mutex_exit(&tems.ts_lock);
 472                 return (ret);
 473         }
 474 
 475         if ((temargs.mode == VIS_PIXEL) && plat_stdout_is_framebuffer())
 476                 plat_tem_get_prom_size(&height, &width);
 477 
 478         /*
 479          * Initialize the common terminal emulator info
 480          */


 508 
 509         if (tems.ts_pdepth != tp->depth)
 510                 result |= TEMS_DEPTH_DIFF;
 511 
 512         if (tp->mode == VIS_TEXT) {
 513                 if (tems.ts_c_dimension.width != tp->width ||
 514                     tems.ts_c_dimension.height != tp->height)
 515                         result |= TEMS_DIMENSION_DIFF;
 516         } else {
 517                 if (tems.ts_p_dimension.width != tp->width ||
 518                     tems.ts_p_dimension.height != tp->height)
 519                         result |= TEMS_DIMENSION_DIFF;
 520         }
 521 
 522         return (result);
 523 }
 524 
 525 static void
 526 tems_setup_terminal(struct vis_devinit *tp, size_t height, size_t width)
 527 {

 528         int i;
 529         int old_blank_buf_size = tems.ts_c_dimension.width;

 530 
 531         ASSERT(MUTEX_HELD(&tems.ts_lock));
 532 
 533         tems.ts_pdepth = tp->depth;
 534         tems.ts_linebytes = tp->linebytes;
 535         tems.ts_display_mode = tp->mode;

 536 
 537         switch (tp->mode) {
 538         case VIS_TEXT:
 539                 tems.ts_p_dimension.width = 0;
 540                 tems.ts_p_dimension.height = 0;
 541                 tems.ts_c_dimension.width = tp->width;
 542                 tems.ts_c_dimension.height = tp->height;
 543                 tems.ts_callbacks = &tem_safe_text_callbacks;
 544 
 545                 break;
 546 
 547         case VIS_PIXEL:
 548                 /*
 549                  * First check to see if the user has specified a screen size.
 550                  * If so, use those values.  Else use 34x80 as the default.
 551                  */
 552                 if (width == 0) {
 553                         width = TEM_DEFAULT_COLS;
 554                         height = TEM_DEFAULT_ROWS;
 555                 }
 556                 tems.ts_c_dimension.height = (screen_size_t)height;
 557                 tems.ts_c_dimension.width = (screen_size_t)width;
 558 
 559                 tems.ts_p_dimension.height = tp->height;
 560                 tems.ts_p_dimension.width = tp->width;
 561 
 562                 tems.ts_callbacks = &tem_safe_pix_callbacks;
 563 
 564                 /*
 565                  * set_font() will select a appropriate sized font for
 566                  * the number of rows and columns selected.  If we don't
 567                  * have a font that will fit, then it will use the
 568                  * default builtin font and adjust the rows and columns
 569                  * to fit on the screen.
 570                  */
 571                 set_font(&tems.ts_font,
 572                     &tems.ts_c_dimension.height,
 573                     &tems.ts_c_dimension.width,
 574                     tems.ts_p_dimension.height,
 575                     tems.ts_p_dimension.width);
 576 










 577                 tems.ts_p_offset.y = (tems.ts_p_dimension.height -
 578                     (tems.ts_c_dimension.height * tems.ts_font.height)) / 2;
 579                 tems.ts_p_offset.x = (tems.ts_p_dimension.width -
 580                     (tems.ts_c_dimension.width * tems.ts_font.width)) / 2;
 581 
 582                 tems.ts_pix_data_size =
 583                     tems.ts_font.width * tems.ts_font.height;
 584 
 585                 tems.ts_pix_data_size *= 4;
 586 
 587                 tems.ts_pdepth = tp->depth;
 588 
 589                 break;
 590         }
 591 
 592         /* Now virtual cls also uses the blank_line buffer */
 593         if (tems.ts_blank_line)
 594                 kmem_free(tems.ts_blank_line, old_blank_buf_size);
 595 
 596         tems.ts_blank_line = (unsigned char *)
 597             kmem_alloc(tems.ts_c_dimension.width, KM_SLEEP);
 598         for (i = 0; i < tems.ts_c_dimension.width; i++)
 599                 tems.ts_blank_line[i] = ' ';
 600 }
 601 
 602 /*
 603  * This is a callback function that we register with the frame
 604  * buffer driver layered underneath.  It gets invoked from
 605  * the underlying frame buffer driver to reconfigure the terminal
 606  * emulator to a new screen size and depth in conjunction with
 607  * framebuffer videomode changes.
 608  * Here we keep the foreground/background color and attributes,
 609  * which may be different with the initial settings, so that
 610  * the color won't change while the framebuffer videomode changes.
 611  * And we also reset the kernel terminal emulator and clear the
 612  * whole screen.
 613  */
 614 /* ARGSUSED */
 615 void
 616 tems_modechange_callback(struct vis_modechg_arg *arg,
 617     struct vis_devinit *devinit)
 618 {
 619         uchar_t diff;


 662                 mutex_exit(&p->tvs_lock);
 663         }
 664 
 665 
 666         if (tems.ts_modechg_cb == NULL) {
 667                 mutex_exit(&tems.ts_lock);
 668                 return;
 669         }
 670 
 671         cb = tems.ts_modechg_cb;
 672         cb_arg = tems.ts_modechg_arg;
 673 
 674         /*
 675          * Release the lock while doing callback.
 676          */
 677         mutex_exit(&tems.ts_lock);
 678         cb(cb_arg);
 679 }
 680 
 681 /*















 682  * This function is used to display a rectangular blit of data
 683  * of a given size and location via the underlying framebuffer driver.
 684  * The blit can be as small as a pixel or as large as the screen.
 685  */
 686 void
 687 tems_display_layered(
 688         struct vis_consdisplay *pda,
 689         cred_t *credp)
 690 {
 691         int rval;
 692 
 693         (void) ldi_ioctl(tems.ts_hdl, VIS_CONSDISPLAY,
 694             (intptr_t)pda, FKIOCTL, credp, &rval);
 695 }
 696 
 697 /*
 698  * This function is used to invoke a block copy operation in the
 699  * underlying framebuffer driver.  Rectangle copies are how scrolling
 700  * is implemented, as well as horizontal text shifting escape seqs.
 701  * such as from vi when deleting characters and words.
 702  */
 703 void
 704 tems_copy_layered(
 705         struct vis_conscopy *pma,
 706         cred_t *credp)
 707 {
 708         int rval;
 709 
 710         (void) ldi_ioctl(tems.ts_hdl, VIS_CONSCOPY,
 711             (intptr_t)pma, FKIOCTL, credp, &rval);
 712 }
 713 
 714 /*
 715  * This function is used to show or hide a rectangluar monochrom
 716  * pixel inverting, text block cursor via the underlying framebuffer.
 717  */
 718 void
 719 tems_cursor_layered(
 720         struct vis_conscursor *pca,
 721         cred_t *credp)
 722 {
 723         int rval;
 724 
 725         (void) ldi_ioctl(tems.ts_hdl, VIS_CONSCURSOR,
 726             (intptr_t)pca, FKIOCTL, credp, &rval);
 727 }
 728 
 729 static void
 730 tem_kdsetmode(int mode, cred_t *credp)
 731 {
 732         int rval;
 733 
 734         (void) ldi_ioctl(tems.ts_hdl, KDSETMODE,
 735             (intptr_t)mode, FKIOCTL, credp, &rval);
 736 
 737 }
 738 
 739 static void
 740 tems_reset_colormap(cred_t *credp, enum called_from called_from)
 741 {
 742         struct vis_cmap cm;
 743         int rval;
 744 
 745         if (called_from == CALLED_FROM_STANDALONE)
 746                 return;
 747 
 748         switch (tems.ts_pdepth) {
 749         case 8:
 750                 cm.index = 0;
 751                 cm.count = 16;
 752                 cm.red   = cmap4_to_24.red;   /* 8-bits (1/3 of TrueColor 24) */
 753                 cm.blue  = cmap4_to_24.blue;  /* 8-bits (1/3 of TrueColor 24) */
 754                 cm.green = cmap4_to_24.green; /* 8-bits (1/3 of TrueColor 24) */



 755                 (void) ldi_ioctl(tems.ts_hdl, VIS_PUTCMAP, (intptr_t)&cm,
 756                     FKIOCTL, credp, &rval);
 757                 break;
 758         }
 759 }
 760 
 761 void
 762 tem_get_size(ushort_t *r, ushort_t *c, ushort_t *x, ushort_t *y)
 763 {
 764         mutex_enter(&tems.ts_lock);
 765         *r = (ushort_t)tems.ts_c_dimension.height;
 766         *c = (ushort_t)tems.ts_c_dimension.width;
 767         *x = (ushort_t)tems.ts_p_dimension.width;
 768         *y = (ushort_t)tems.ts_p_dimension.height;
 769         mutex_exit(&tems.ts_lock);
 770 }
 771 
 772 void
 773 tem_register_modechg_cb(tem_modechg_cb_t func, tem_modechg_cb_arg_t arg)
 774 {
 775         mutex_enter(&tems.ts_lock);
 776 
 777         tems.ts_modechg_cb = func;
 778         tems.ts_modechg_arg = arg;
 779 
 780         mutex_exit(&tems.ts_lock);
 781 }
 782 
 783 /*
 784  * This function is to scroll up the OBP output, which has
 785  * different screen height and width with our kernel console.
 786  */
 787 static void
 788 tem_prom_scroll_up(struct tem_vt_state *tem, int nrows, cred_t *credp,
 789     enum called_from called_from)
 790 {
 791         struct vis_conscopy     ma;
 792         int     ncols, width;
 793 
 794         /* copy */
 795         ma.s_row = nrows * tems.ts_font.height;
 796         ma.e_row = tems.ts_p_dimension.height - 1;
 797         ma.t_row = 0;
 798 
 799         ma.s_col = 0;
 800         ma.e_col = tems.ts_p_dimension.width - 1;
 801         ma.t_col = 0;
 802 
 803         tems_safe_copy(&ma, credp, called_from);
 804 
 805         /* clear */
 806         width = tems.ts_font.width;
 807         ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
 808 
 809         tem_safe_pix_cls_range(tem, 0, nrows, tems.ts_p_offset.y,
 810             0, ncols, 0, B_TRUE, credp, called_from);
 811 }
 812 
 813 #define PROM_DEFAULT_FONT_HEIGHT        22
 814 #define PROM_DEFAULT_WINDOW_TOP         0x8a
 815 
 816 /*
 817  * This function is to compute the starting row of the console, according to
 818  * PROM cursor's position. Here we have to take different fonts into account.
 819  */
 820 static int
 821 tem_adjust_row(struct tem_vt_state *tem, int prom_row, cred_t *credp,
 822     enum called_from called_from)
 823 {
 824         int     tem_row;
 825         int     tem_y;
 826         int     prom_charheight = 0;
 827         int     prom_window_top = 0;
 828         int     scroll_up_lines;
 829 
 830         plat_tem_get_prom_font_size(&prom_charheight, &prom_window_top);
 831         if (prom_charheight == 0)
 832                 prom_charheight = PROM_DEFAULT_FONT_HEIGHT;
 833         if (prom_window_top == 0)
 834                 prom_window_top = PROM_DEFAULT_WINDOW_TOP;
 835 
 836         tem_y = (prom_row + 1) * prom_charheight + prom_window_top -
 837             tems.ts_p_offset.y;
 838         tem_row = (tem_y + tems.ts_font.height - 1) /
 839             tems.ts_font.height - 1;
 840 
 841         if (tem_row < 0) {
 842                 tem_row = 0;
 843         } else if (tem_row >= (tems.ts_c_dimension.height - 1)) {
 844                 /*
 845                  * Scroll up the prom outputs if the PROM cursor's position is
 846                  * below our tem's lower boundary.
 847                  */
 848                 scroll_up_lines = tem_row -
 849                     (tems.ts_c_dimension.height - 1);
 850                 tem_prom_scroll_up(tem, scroll_up_lines, credp, called_from);
 851                 tem_row = tems.ts_c_dimension.height - 1;
 852         }
 853 
 854         return (tem_row);
 855 }
 856 
 857 void
 858 tem_pix_align(struct tem_vt_state *tem, cred_t *credp,
 859     enum called_from called_from)


 897         int i_inverse_screen = 0;
 898 
 899         plat_tem_get_inverses(&i_inverse, &i_inverse_screen);
 900 
 901         *p_inverse = (i_inverse == 0) ? B_FALSE : B_TRUE;
 902         *p_inverse_screen = (i_inverse_screen == 0) ? B_FALSE : B_TRUE;
 903 }
 904 
 905 /*
 906  * Get the foreground/background color and attributes from the initial
 907  * PROM, so that our kernel console can keep the same visual behaviour.
 908  */
 909 static void
 910 tems_get_initial_color(tem_color_t *pcolor)
 911 {
 912         boolean_t inverse, inverse_screen;
 913         unsigned short  flags = 0;
 914 
 915         pcolor->fg_color = DEFAULT_ANSI_FOREGROUND;
 916         pcolor->bg_color = DEFAULT_ANSI_BACKGROUND;



 917 
 918         if (plat_stdout_is_framebuffer()) {
 919                 tems_get_inverses(&inverse, &inverse_screen);
 920                 if (inverse)
 921                         flags |= TEM_ATTR_REVERSE;
 922                 if (inverse_screen)
 923                         flags |= TEM_ATTR_SCREEN_REVERSE;
 924 
 925                 if (flags != 0) {
 926                         /*
 927                          * If either reverse flag is set, the screen is in
 928                          * white-on-black mode.  We set the bold flag to
 929                          * improve readability.
 930                          */
 931                         flags |= TEM_ATTR_BOLD;
 932                 } else {
 933                         /*
 934                          * Otherwise, the screen is in black-on-white mode.
 935                          * The SPARC PROM console, which starts in this mode,
 936                          * uses the bright white background colour so we
 937                          * match it here.
 938                          */
 939                         if (pcolor->bg_color == ANSI_COLOR_WHITE)
 940                                 flags |= TEM_ATTR_BRIGHT_BG;
 941                 }
 942         }
 943 
 944         pcolor->a_flags = flags;
 945 }
 946 
 947 uchar_t
 948 tem_get_fbmode(tem_vt_state_t tem_arg)
 949 {
 950         struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 951 
 952         uchar_t fbmode;
 953 
 954         mutex_enter(&tem->tvs_lock);
 955         fbmode = tem->tvs_fbmode;
 956         mutex_exit(&tem->tvs_lock);
 957 
 958         return (fbmode);
 959 }
 960 
 961 void
 962 tem_set_fbmode(tem_vt_state_t tem_arg, uchar_t fbmode, cred_t *credp)




 104 static void     tem_free_buf(struct tem_vt_state *);
 105 static void     tem_internal_init(struct tem_vt_state *, cred_t *, boolean_t,
 106                     boolean_t);
 107 static void     tems_get_initial_color(tem_color_t *pcolor);
 108 
 109 /*
 110  * Globals
 111  */
 112 static ldi_ident_t      term_li = NULL;
 113 tem_state_t     tems;   /* common term info */
 114 _NOTE(MUTEX_PROTECTS_DATA(tems.ts_lock, tems))
 115 
 116 extern struct mod_ops mod_miscops;
 117 
 118 static struct modlmisc  modlmisc = {
 119         &mod_miscops,       /* modops */
 120         "ANSI Terminal Emulator", /* name */
 121 };
 122 
 123 static struct modlinkage modlinkage = {
 124         MODREV_1, { (void *)&modlmisc, NULL }
 125 };
 126 
 127 int
 128 _init(void)
 129 {
 130         int ret;
 131         ret = mod_install(&modlinkage);
 132         if (ret != 0)
 133                 return (ret);
 134         ret = ldi_ident_from_mod(&modlinkage, &term_li);
 135         if (ret != 0) {
 136                 (void) mod_remove(&modlinkage);
 137                 return (ret);
 138         }
 139 
 140         mutex_init(&tems.ts_lock, (char *)NULL, MUTEX_DRIVER, NULL);
 141         list_create(&tems.ts_list, sizeof (struct tem_vt_state),
 142             offsetof(struct tem_vt_state, tvs_list_node));
 143         tems.ts_active = NULL;
 144 


 192         mutex_enter(&tems.ts_lock);
 193         mutex_enter(&tem->tvs_lock);
 194 
 195         if (!tem->tvs_initialized) {
 196                 mutex_exit(&tem->tvs_lock);
 197                 mutex_exit(&tems.ts_lock);
 198                 return;
 199         }
 200 
 201         tem_safe_check_first_time(tem, credp, CALLED_FROM_NORMAL);
 202         tem_safe_terminal_emulate(tem, buf, len, credp, CALLED_FROM_NORMAL);
 203 
 204         mutex_exit(&tem->tvs_lock);
 205         mutex_exit(&tems.ts_lock);
 206 }
 207 
 208 static void
 209 tem_internal_init(struct tem_vt_state *ptem, cred_t *credp,
 210     boolean_t init_color, boolean_t clear_screen)
 211 {
 212         unsigned i, j, width, height;
 213         text_attr_t attr;

 214         text_color_t fg;
 215         text_color_t bg;

 216 
 217         ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&ptem->tvs_lock));
 218 
 219         if (tems.ts_display_mode == VIS_PIXEL) {
 220                 ptem->tvs_pix_data_size = tems.ts_pix_data_size;
 221                 ptem->tvs_pix_data =
 222                     kmem_alloc(ptem->tvs_pix_data_size, KM_SLEEP);
 223         }
 224 
 225         ptem->tvs_outbuf_size = tems.ts_c_dimension.width *
 226             sizeof (*ptem->tvs_outbuf);
 227         ptem->tvs_outbuf = kmem_alloc(ptem->tvs_outbuf_size, KM_SLEEP);
 228 
 229         width = tems.ts_c_dimension.width;
 230         height = tems.ts_c_dimension.height;
 231         ptem->tvs_screen_history_size = height;


 232 
 233         ptem->tvs_screen_buf_size = width * ptem->tvs_screen_history_size *
 234             sizeof (*ptem->tvs_screen_buf);
 235         ptem->tvs_screen_buf = kmem_alloc(ptem->tvs_screen_buf_size, KM_SLEEP);
 236         ptem->tvs_screen_rows = kmem_alloc(ptem->tvs_screen_history_size *
 237             sizeof (term_char_t *), KM_SLEEP);
 238 
 239         tem_safe_reset_display(ptem, credp, CALLED_FROM_NORMAL,
 240             clear_screen, init_color);
 241 
 242         ptem->tvs_utf8_left = 0;
 243         ptem->tvs_utf8_partial = 0;
 244 
 245         /* Get default attributes and fill up the screen buffer. */
 246         tem_safe_get_attr(ptem, &fg, &bg, &attr, TEM_ATTR_SCREEN_REVERSE);
 247         for (i = 0; i < ptem->tvs_screen_history_size; i++) {
 248                 ptem->tvs_screen_rows[i] = &ptem->tvs_screen_buf[i * width];
 249 
 250                 for (j = 0; j < width; j++) {
 251                         ptem->tvs_screen_rows[i][j].tc_fg_color = fg;
 252                         ptem->tvs_screen_rows[i][j].tc_bg_color = bg;
 253                         ptem->tvs_screen_rows[i][j].tc_char =
 254                             TEM_ATTR(attr) | ' ';
 255 
 256                 }
 257         }
 258 
 259         ptem->tvs_initialized = B_TRUE;
 260 }
 261 
 262 int
 263 tem_initialized(tem_vt_state_t tem_arg)
 264 {
 265         struct tem_vt_state *ptem = (struct tem_vt_state *)tem_arg;
 266         int ret;
 267 
 268         mutex_enter(&ptem->tvs_lock);
 269         ret = ptem->tvs_initialized == B_TRUE? 1 : 0;
 270         mutex_exit(&ptem->tvs_lock);
 271 
 272         return (ret);
 273 }
 274 
 275 tem_vt_state_t
 276 tem_init(cred_t *credp)
 277 {
 278         struct tem_vt_state *ptem;
 279 
 280         ptem = kmem_zalloc(sizeof (struct tem_vt_state), KM_SLEEP);
 281         mutex_init(&ptem->tvs_lock, (char *)NULL, MUTEX_DRIVER, NULL);
 282 
 283         mutex_enter(&tems.ts_lock);
 284         mutex_enter(&ptem->tvs_lock);
 285 
 286         ptem->tvs_isactive = B_FALSE;
 287         ptem->tvs_fbmode = KD_TEXT;
 288 
 289         /*
 290          * A tem is regarded as initialized only after tem_internal_init(),
 291          * will be set at the end of tem_internal_init().
 292          */
 293         ptem->tvs_initialized = B_FALSE;
 294 
 295 
 296         if (!tems.ts_initialized) {
 297                 /*
 298                  * Only happens during early console configuration.
 299                  */
 300                 tem_add(ptem);
 301                 mutex_exit(&ptem->tvs_lock);
 302                 mutex_exit(&tems.ts_lock);
 303                 return ((tem_vt_state_t)ptem);
 304         }
 305 
 306         tem_internal_init(ptem, credp, B_TRUE, B_FALSE);
 307         tem_add(ptem);
 308         mutex_exit(&ptem->tvs_lock);
 309         mutex_exit(&tems.ts_lock);
 310 
 311         return ((tem_vt_state_t)ptem);
 312 }
 313 


 320 {
 321         ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
 322 
 323         tem_free_buf(tem); /* only free virtual buffers */
 324 
 325         /* reserve color */
 326         tem_internal_init(tem, kcred, B_FALSE, reset_display);
 327 }
 328 
 329 static void
 330 tem_free_buf(struct tem_vt_state *tem)
 331 {
 332         ASSERT(tem != NULL && MUTEX_HELD(&tem->tvs_lock));
 333 
 334         if (tem->tvs_outbuf != NULL)
 335                 kmem_free(tem->tvs_outbuf, tem->tvs_outbuf_size);
 336         if (tem->tvs_pix_data != NULL)
 337                 kmem_free(tem->tvs_pix_data, tem->tvs_pix_data_size);
 338         if (tem->tvs_screen_buf != NULL)
 339                 kmem_free(tem->tvs_screen_buf, tem->tvs_screen_buf_size);
 340         if (tem->tvs_screen_rows != NULL) {
 341                 kmem_free(tem->tvs_screen_rows, tem->tvs_screen_history_size *
 342                     sizeof (term_char_t *));
 343         }
 344 }
 345 
 346 void
 347 tem_destroy(tem_vt_state_t tem_arg, cred_t *credp)
 348 {
 349         struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 350 
 351         mutex_enter(&tems.ts_lock);
 352         mutex_enter(&tem->tvs_lock);
 353 
 354         if (tem->tvs_isactive && tem->tvs_fbmode == KD_TEXT)
 355                 tem_safe_blank_screen(tem, credp, CALLED_FROM_NORMAL);
 356 
 357         tem_free_buf(tem);
 358         tem_rm(tem);
 359 
 360         if (tems.ts_active == tem)
 361                 tems.ts_active = NULL;
 362 
 363         mutex_exit(&tem->tvs_lock);


 443         /* Make sure the fb driver and terminal emulator versions match */
 444         if (temargs.version != VIS_CONS_REV) {
 445                 cmn_err(CE_WARN,
 446                     "terminal emulator: VIS_CONS_REV %d (see sys/visual_io.h) "
 447                     "of console fb driver not supported", temargs.version);
 448                 ret = tems_failed(credp, B_TRUE);
 449                 mutex_exit(&tems.ts_lock);
 450                 return (ret);
 451         }
 452 
 453         if ((tems.ts_fb_polledio = temargs.polledio) == NULL) {
 454                 cmn_err(CE_WARN, "terminal emulator: fb doesn't support polled "
 455                     "I/O");
 456                 ret = tems_failed(credp, B_TRUE);
 457                 mutex_exit(&tems.ts_lock);
 458                 return (ret);
 459         }
 460 
 461         /* other sanity checks */
 462         if (!((temargs.depth == 4) || (temargs.depth == 8) ||
 463             (temargs.depth == 15) || (temargs.depth == 16) ||
 464             (temargs.depth == 24) || (temargs.depth == 32))) {
 465                 cmn_err(CE_WARN, "terminal emulator: unsupported depth");
 466                 ret = tems_failed(credp, B_TRUE);
 467                 mutex_exit(&tems.ts_lock);
 468                 return (ret);
 469         }
 470 
 471         if ((temargs.mode != VIS_TEXT) && (temargs.mode != VIS_PIXEL)) {
 472                 cmn_err(CE_WARN, "terminal emulator: unsupported mode");
 473                 ret = tems_failed(credp, B_TRUE);
 474                 mutex_exit(&tems.ts_lock);
 475                 return (ret);
 476         }
 477 
 478         if ((temargs.mode == VIS_PIXEL) && plat_stdout_is_framebuffer())
 479                 plat_tem_get_prom_size(&height, &width);
 480 
 481         /*
 482          * Initialize the common terminal emulator info
 483          */


 511 
 512         if (tems.ts_pdepth != tp->depth)
 513                 result |= TEMS_DEPTH_DIFF;
 514 
 515         if (tp->mode == VIS_TEXT) {
 516                 if (tems.ts_c_dimension.width != tp->width ||
 517                     tems.ts_c_dimension.height != tp->height)
 518                         result |= TEMS_DIMENSION_DIFF;
 519         } else {
 520                 if (tems.ts_p_dimension.width != tp->width ||
 521                     tems.ts_p_dimension.height != tp->height)
 522                         result |= TEMS_DIMENSION_DIFF;
 523         }
 524 
 525         return (result);
 526 }
 527 
 528 static void
 529 tems_setup_terminal(struct vis_devinit *tp, size_t height, size_t width)
 530 {
 531         bitmap_data_t *font_data;
 532         int i;
 533         int old_blank_buf_size = tems.ts_c_dimension.width *
 534             sizeof (*tems.ts_blank_line);
 535 
 536         ASSERT(MUTEX_HELD(&tems.ts_lock));
 537 
 538         tems.ts_pdepth = tp->depth;
 539         tems.ts_linebytes = tp->linebytes;
 540         tems.ts_display_mode = tp->mode;
 541         tems.ts_color_map = tp->color_map;
 542 
 543         switch (tp->mode) {
 544         case VIS_TEXT:
 545                 tems.ts_p_dimension.width = 0;
 546                 tems.ts_p_dimension.height = 0;
 547                 tems.ts_c_dimension.width = tp->width;
 548                 tems.ts_c_dimension.height = tp->height;
 549                 tems.ts_callbacks = &tem_safe_text_callbacks;
 550 
 551                 break;
 552 
 553         case VIS_PIXEL:
 554                 /*
 555                  * First check to see if the user has specified a screen size.
 556                  * If so, use those values.  Else use 34x80 as the default.
 557                  */
 558                 if (width == 0) {
 559                         width = TEM_DEFAULT_COLS;
 560                         height = TEM_DEFAULT_ROWS;
 561                 }
 562                 tems.ts_c_dimension.height = (screen_size_t)height;
 563                 tems.ts_c_dimension.width = (screen_size_t)width;
 564 
 565                 tems.ts_p_dimension.height = tp->height;
 566                 tems.ts_p_dimension.width = tp->width;
 567 
 568                 tems.ts_callbacks = &tem_safe_pix_callbacks;
 569 
 570                 /*
 571                  * set_font() will select a appropriate sized font for
 572                  * the number of rows and columns selected.  If we don't
 573                  * have a font that will fit, then it will use the
 574                  * default builtin font and adjust the rows and columns
 575                  * to fit on the screen.
 576                  */
 577                 font_data = set_font(&tems.ts_c_dimension.height,

 578                     &tems.ts_c_dimension.width,
 579                     tems.ts_p_dimension.height,
 580                     tems.ts_p_dimension.width);
 581 
 582                 for (i = 0; i < VFNT_MAPS; i++) {
 583                         tems.ts_font.vf_map[i] =
 584                             font_data->font->vf_map[i];
 585                         tems.ts_font.vf_map_count[i] =
 586                             font_data->font->vf_map_count[i];
 587                 }
 588                 tems.ts_font.vf_bytes = font_data->font->vf_bytes;
 589                 tems.ts_font.vf_width = font_data->font->vf_width;
 590                 tems.ts_font.vf_height = font_data->font->vf_height;
 591 
 592                 tems.ts_p_offset.y = (tems.ts_p_dimension.height -
 593                     (tems.ts_c_dimension.height * tems.ts_font.vf_height)) / 2;
 594                 tems.ts_p_offset.x = (tems.ts_p_dimension.width -
 595                     (tems.ts_c_dimension.width * tems.ts_font.vf_width)) / 2;
 596 
 597                 tems.ts_pix_data_size =
 598                     tems.ts_font.vf_width * tems.ts_font.vf_height;
 599 
 600                 tems.ts_pix_data_size *= 4;
 601 
 602                 tems.ts_pdepth = tp->depth;
 603 
 604                 break;
 605         }
 606 
 607         /* Now virtual cls also uses the blank_line buffer */
 608         if (tems.ts_blank_line)
 609                 kmem_free(tems.ts_blank_line, old_blank_buf_size);
 610 
 611         tems.ts_blank_line = kmem_alloc(tems.ts_c_dimension.width *
 612             sizeof (*tems.ts_blank_line), KM_SLEEP);


 613 }
 614 
 615 /*
 616  * This is a callback function that we register with the frame
 617  * buffer driver layered underneath.  It gets invoked from
 618  * the underlying frame buffer driver to reconfigure the terminal
 619  * emulator to a new screen size and depth in conjunction with
 620  * framebuffer videomode changes.
 621  * Here we keep the foreground/background color and attributes,
 622  * which may be different with the initial settings, so that
 623  * the color won't change while the framebuffer videomode changes.
 624  * And we also reset the kernel terminal emulator and clear the
 625  * whole screen.
 626  */
 627 /* ARGSUSED */
 628 void
 629 tems_modechange_callback(struct vis_modechg_arg *arg,
 630     struct vis_devinit *devinit)
 631 {
 632         uchar_t diff;


 675                 mutex_exit(&p->tvs_lock);
 676         }
 677 
 678 
 679         if (tems.ts_modechg_cb == NULL) {
 680                 mutex_exit(&tems.ts_lock);
 681                 return;
 682         }
 683 
 684         cb = tems.ts_modechg_cb;
 685         cb_arg = tems.ts_modechg_arg;
 686 
 687         /*
 688          * Release the lock while doing callback.
 689          */
 690         mutex_exit(&tems.ts_lock);
 691         cb(cb_arg);
 692 }
 693 
 694 /*
 695  * This function is used to clear entire screen via the underlying framebuffer
 696  * driver.
 697  */
 698 int
 699 tems_cls_layered(struct vis_consclear *pda,
 700     cred_t *credp)
 701 {
 702         int rval;
 703 
 704         (void) ldi_ioctl(tems.ts_hdl, VIS_CONSCLEAR,
 705             (intptr_t)pda, FKIOCTL, credp, &rval);
 706         return (rval);
 707 }
 708 
 709 /*
 710  * This function is used to display a rectangular blit of data
 711  * of a given size and location via the underlying framebuffer driver.
 712  * The blit can be as small as a pixel or as large as the screen.
 713  */
 714 void
 715 tems_display_layered(struct vis_consdisplay *pda,

 716     cred_t *credp)
 717 {
 718         int rval;
 719 
 720         (void) ldi_ioctl(tems.ts_hdl, VIS_CONSDISPLAY,
 721             (intptr_t)pda, FKIOCTL, credp, &rval);
 722 }
 723 
 724 /*
 725  * This function is used to invoke a block copy operation in the
 726  * underlying framebuffer driver.  Rectangle copies are how scrolling
 727  * is implemented, as well as horizontal text shifting escape seqs.
 728  * such as from vi when deleting characters and words.
 729  */
 730 void
 731 tems_copy_layered(struct vis_conscopy *pma,

 732     cred_t *credp)
 733 {
 734         int rval;
 735 
 736         (void) ldi_ioctl(tems.ts_hdl, VIS_CONSCOPY,
 737             (intptr_t)pma, FKIOCTL, credp, &rval);
 738 }
 739 
 740 /*
 741  * This function is used to show or hide a rectangluar monochrom
 742  * pixel inverting, text block cursor via the underlying framebuffer.
 743  */
 744 void
 745 tems_cursor_layered(struct vis_conscursor *pca,

 746     cred_t *credp)
 747 {
 748         int rval;
 749 
 750         (void) ldi_ioctl(tems.ts_hdl, VIS_CONSCURSOR,
 751             (intptr_t)pca, FKIOCTL, credp, &rval);
 752 }
 753 
 754 static void
 755 tem_kdsetmode(int mode, cred_t *credp)
 756 {
 757         int rval;
 758 
 759         (void) ldi_ioctl(tems.ts_hdl, KDSETMODE,
 760             (intptr_t)mode, FKIOCTL, credp, &rval);
 761 
 762 }
 763 
 764 static void
 765 tems_reset_colormap(cred_t *credp, enum called_from called_from)
 766 {
 767         struct vis_cmap cm;
 768         int rval;
 769 
 770         if (called_from == CALLED_FROM_STANDALONE)
 771                 return;
 772 
 773         switch (tems.ts_pdepth) {
 774         case 8:
 775                 cm.index = 0;
 776                 cm.count = 16;
 777                 /* 8-bits (1/3 of TrueColor 24) */
 778                 cm.red   = (uint8_t *)cmap4_to_24.red;
 779                 /* 8-bits (1/3 of TrueColor 24) */
 780                 cm.blue  = (uint8_t *)cmap4_to_24.blue;
 781                 /* 8-bits (1/3 of TrueColor 24) */
 782                 cm.green = (uint8_t *)cmap4_to_24.green;
 783                 (void) ldi_ioctl(tems.ts_hdl, VIS_PUTCMAP, (intptr_t)&cm,
 784                     FKIOCTL, credp, &rval);
 785                 break;
 786         }
 787 }
 788 
 789 void
 790 tem_get_size(ushort_t *r, ushort_t *c, ushort_t *x, ushort_t *y)
 791 {
 792         mutex_enter(&tems.ts_lock);
 793         *r = (ushort_t)tems.ts_c_dimension.height;
 794         *c = (ushort_t)tems.ts_c_dimension.width;
 795         *x = (ushort_t)tems.ts_p_dimension.width;
 796         *y = (ushort_t)tems.ts_p_dimension.height;
 797         mutex_exit(&tems.ts_lock);
 798 }
 799 
 800 void
 801 tem_register_modechg_cb(tem_modechg_cb_t func, tem_modechg_cb_arg_t arg)
 802 {
 803         mutex_enter(&tems.ts_lock);
 804 
 805         tems.ts_modechg_cb = func;
 806         tems.ts_modechg_arg = arg;
 807 
 808         mutex_exit(&tems.ts_lock);
 809 }
 810 
 811 /*
 812  * This function is to scroll up the OBP output, which has
 813  * different screen height and width with our kernel console.
 814  */
 815 static void
 816 tem_prom_scroll_up(struct tem_vt_state *tem, int nrows, cred_t *credp,
 817     enum called_from called_from)
 818 {
 819         struct vis_conscopy     ma;
 820         int     ncols, width;
 821 
 822         /* copy */
 823         ma.s_row = nrows * tems.ts_font.vf_height;
 824         ma.e_row = tems.ts_p_dimension.height - 1;
 825         ma.t_row = 0;
 826 
 827         ma.s_col = 0;
 828         ma.e_col = tems.ts_p_dimension.width - 1;
 829         ma.t_col = 0;
 830 
 831         tems_safe_copy(&ma, credp, called_from);
 832 
 833         /* clear */
 834         width = tems.ts_font.vf_width;
 835         ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
 836 
 837         tem_safe_pix_cls_range(tem, 0, nrows, tems.ts_p_offset.y,
 838             0, ncols, 0, B_TRUE, credp, called_from);
 839 }
 840 
 841 #define PROM_DEFAULT_FONT_HEIGHT        22
 842 #define PROM_DEFAULT_WINDOW_TOP         0x8a
 843 
 844 /*
 845  * This function is to compute the starting row of the console, according to
 846  * PROM cursor's position. Here we have to take different fonts into account.
 847  */
 848 static int
 849 tem_adjust_row(struct tem_vt_state *tem, int prom_row, cred_t *credp,
 850     enum called_from called_from)
 851 {
 852         int     tem_row;
 853         int     tem_y;
 854         int     prom_charheight = 0;
 855         int     prom_window_top = 0;
 856         int     scroll_up_lines;
 857 
 858         plat_tem_get_prom_font_size(&prom_charheight, &prom_window_top);
 859         if (prom_charheight == 0)
 860                 prom_charheight = PROM_DEFAULT_FONT_HEIGHT;
 861         if (prom_window_top == 0)
 862                 prom_window_top = PROM_DEFAULT_WINDOW_TOP;
 863 
 864         tem_y = (prom_row + 1) * prom_charheight + prom_window_top -
 865             tems.ts_p_offset.y;
 866         tem_row = (tem_y + tems.ts_font.vf_height - 1) /
 867             tems.ts_font.vf_height - 1;
 868 
 869         if (tem_row < 0) {
 870                 tem_row = 0;
 871         } else if (tem_row >= (tems.ts_c_dimension.height - 1)) {
 872                 /*
 873                  * Scroll up the prom outputs if the PROM cursor's position is
 874                  * below our tem's lower boundary.
 875                  */
 876                 scroll_up_lines = tem_row -
 877                     (tems.ts_c_dimension.height - 1);
 878                 tem_prom_scroll_up(tem, scroll_up_lines, credp, called_from);
 879                 tem_row = tems.ts_c_dimension.height - 1;
 880         }
 881 
 882         return (tem_row);
 883 }
 884 
 885 void
 886 tem_pix_align(struct tem_vt_state *tem, cred_t *credp,
 887     enum called_from called_from)


 925         int i_inverse_screen = 0;
 926 
 927         plat_tem_get_inverses(&i_inverse, &i_inverse_screen);
 928 
 929         *p_inverse = (i_inverse == 0) ? B_FALSE : B_TRUE;
 930         *p_inverse_screen = (i_inverse_screen == 0) ? B_FALSE : B_TRUE;
 931 }
 932 
 933 /*
 934  * Get the foreground/background color and attributes from the initial
 935  * PROM, so that our kernel console can keep the same visual behaviour.
 936  */
 937 static void
 938 tems_get_initial_color(tem_color_t *pcolor)
 939 {
 940         boolean_t inverse, inverse_screen;
 941         unsigned short  flags = 0;
 942 
 943         pcolor->fg_color = DEFAULT_ANSI_FOREGROUND;
 944         pcolor->bg_color = DEFAULT_ANSI_BACKGROUND;
 945 #ifndef _HAVE_TEM_FIRMWARE
 946         plat_tem_get_colors(&pcolor->fg_color, &pcolor->bg_color);
 947 #endif
 948 

 949         tems_get_inverses(&inverse, &inverse_screen);
 950         if (inverse)
 951                 flags |= TEM_ATTR_REVERSE;
 952         if (inverse_screen)
 953                 flags |= TEM_ATTR_SCREEN_REVERSE;
 954 
 955         if (flags != 0) {
 956                 /*
 957                  * If either reverse flag is set, the screen is in
 958                  * white-on-black mode.  We set the bold flag to
 959                  * improve readability.
 960                  */
 961                 flags |= TEM_ATTR_BOLD;
 962         } else {
 963                 /*
 964                  * Otherwise, the screen is in black-on-white mode.
 965                  * The SPARC PROM console, which starts in this mode,
 966                  * uses the bright white background colour so we
 967                  * match it here.
 968                  */
 969                 if (pcolor->bg_color == ANSI_COLOR_WHITE)
 970                         flags |= TEM_ATTR_BRIGHT_BG;
 971         }

 972 
 973         pcolor->a_flags = flags;
 974 }
 975 
 976 uchar_t
 977 tem_get_fbmode(tem_vt_state_t tem_arg)
 978 {
 979         struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
 980 
 981         uchar_t fbmode;
 982 
 983         mutex_enter(&tem->tvs_lock);
 984         fbmode = tem->tvs_fbmode;
 985         mutex_exit(&tem->tvs_lock);
 986 
 987         return (fbmode);
 988 }
 989 
 990 void
 991 tem_set_fbmode(tem_vt_state_t tem_arg, uchar_t fbmode, cred_t *credp)