Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/tem.c
+++ new/usr/src/uts/common/io/tem.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /*
28 28 * ANSI terminal emulator module; parse ANSI X3.64 escape sequences and
29 29 * the like.
30 30 *
31 31 * How Virtual Terminal Emulator Works:
32 32 *
33 33 * Every virtual terminal is associated with a tem_vt_state structure
34 34 * and maintains a virtual screen buffer in tvs_screen_buf, which contains
35 35 * all the characters which should be shown on the physical screen when
36 36 * the terminal is activated. There are also two other buffers, tvs_fg_buf
37 37 * and tvs_bg_buf, which track the foreground and background colors of the
38 38 * on screen characters
39 39 *
40 40 * Data written to a virtual terminal is composed of characters which
41 41 * should be displayed on the screen when this virtual terminal is
42 42 * activated, fg/bg colors of these characters, and other control
43 43 * information (escape sequence, etc).
44 44 *
45 45 * When data is passed to a virtual terminal it first is parsed for
46 46 * control information by tem_safe_parse(). Subsequently the character
47 47 * and color data are written to tvs_screen_buf, tvs_fg_buf, and
48 48 * tvs_bg_buf. They are saved in these buffers in order to refresh
49 49 * the screen when this terminal is activated. If the terminal is
50 50 * currently active, the data (characters and colors) are also written
51 51 * to the physical screen by invoking a callback function,
52 52 * tem_safe_text_callbacks() or tem_safe_pix_callbacks().
53 53 *
54 54 * When rendering data to the framebuffer, if the framebuffer is in
55 55 * VIS_PIXEL mode, the character data will first be converted to pixel
56 56 * data using tem_safe_pix_bit2pix(), and then the pixels get displayed
57 57 * on the physical screen. We only store the character and color data in
58 58 * tem_vt_state since the bit2pix conversion only happens when actually
59 59 * rendering to the physical framebuffer.
60 60 */
61 61
62 62
63 63 #include <sys/types.h>
64 64 #include <sys/file.h>
65 65 #include <sys/conf.h>
66 66 #include <sys/errno.h>
67 67 #include <sys/open.h>
68 68 #include <sys/cred.h>
69 69 #include <sys/kmem.h>
70 70 #include <sys/ascii.h>
71 71 #include <sys/consdev.h>
72 72 #include <sys/font.h>
73 73 #include <sys/fbio.h>
74 74 #include <sys/conf.h>
75 75 #include <sys/modctl.h>
76 76 #include <sys/strsubr.h>
77 77 #include <sys/stat.h>
78 78 #include <sys/visual_io.h>
79 79 #include <sys/mutex.h>
80 80 #include <sys/param.h>
81 81 #include <sys/debug.h>
82 82 #include <sys/cmn_err.h>
83 83 #include <sys/console.h>
84 84 #include <sys/ddi.h>
85 85 #include <sys/sunddi.h>
86 86 #include <sys/sunldi.h>
87 87 #include <sys/tem_impl.h>
88 88 #ifdef _HAVE_TEM_FIRMWARE
89 89 #include <sys/promif.h>
90 90 #endif /* _HAVE_TEM_FIRMWARE */
91 91 #include <sys/consplat.h>
92 92 #include <sys/kd.h>
93 93 #include <sys/sysmacros.h>
94 94 #include <sys/note.h>
95 95 #include <sys/t_lock.h>
96 96
97 97 /* Terminal emulator internal helper functions */
98 98 static void tems_setup_terminal(struct vis_devinit *, size_t, size_t);
99 99 static void tems_modechange_callback(struct vis_modechg_arg *,
100 100 struct vis_devinit *);
101 101
102 102 static void tems_reset_colormap(cred_t *, enum called_from);
103 103
104 104 static void tem_free_buf(struct tem_vt_state *);
105 105 static void tem_internal_init(struct tem_vt_state *, cred_t *, boolean_t,
106 106 boolean_t);
107 107 static void tems_get_initial_color(tem_color_t *pcolor);
108 108
109 109 /*
110 110 * Globals
111 111 */
112 112 static ldi_ident_t term_li = NULL;
113 113 tem_state_t tems; /* common term info */
↓ open down ↓ |
113 lines elided |
↑ open up ↑ |
114 114 _NOTE(MUTEX_PROTECTS_DATA(tems.ts_lock, tems))
115 115
116 116 extern struct mod_ops mod_miscops;
117 117
118 118 static struct modlmisc modlmisc = {
119 119 &mod_miscops, /* modops */
120 120 "ANSI Terminal Emulator", /* name */
121 121 };
122 122
123 123 static struct modlinkage modlinkage = {
124 - MODREV_1, (void *)&modlmisc, NULL
124 + MODREV_1, { (void *)&modlmisc, NULL }
125 125 };
126 126
127 127 int
128 128 _init(void)
129 129 {
130 130 int ret;
131 131 ret = mod_install(&modlinkage);
132 132 if (ret != 0)
133 133 return (ret);
134 134 ret = ldi_ident_from_mod(&modlinkage, &term_li);
135 135 if (ret != 0) {
136 136 (void) mod_remove(&modlinkage);
137 137 return (ret);
138 138 }
139 139
140 140 mutex_init(&tems.ts_lock, (char *)NULL, MUTEX_DRIVER, NULL);
141 141 list_create(&tems.ts_list, sizeof (struct tem_vt_state),
142 142 offsetof(struct tem_vt_state, tvs_list_node));
143 143 tems.ts_active = NULL;
144 144
145 145 return (0);
146 146 }
147 147
148 148 int
149 149 _fini()
150 150 {
151 151 int ret;
152 152
153 153 ret = mod_remove(&modlinkage);
154 154 if (ret == 0) {
155 155 ldi_ident_release(term_li);
156 156 term_li = NULL;
157 157 }
158 158 return (ret);
159 159 }
160 160
161 161 int
162 162 _info(struct modinfo *modinfop)
163 163 {
164 164 return (mod_info(&modlinkage, modinfop));
165 165 }
166 166
167 167 static void
168 168 tem_add(struct tem_vt_state *tem)
169 169 {
170 170 ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
171 171
172 172 list_insert_head(&tems.ts_list, tem);
173 173 }
174 174
175 175 static void
176 176 tem_rm(struct tem_vt_state *tem)
177 177 {
178 178 ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
179 179
180 180 list_remove(&tems.ts_list, tem);
181 181 }
182 182
183 183 /*
184 184 * This is the main entry point to the module. It handles output requests
185 185 * during normal system operation, when (e.g.) mutexes are available.
186 186 */
187 187 void
188 188 tem_write(tem_vt_state_t tem_arg, uchar_t *buf, ssize_t len, cred_t *credp)
189 189 {
190 190 struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
191 191
192 192 mutex_enter(&tems.ts_lock);
193 193 mutex_enter(&tem->tvs_lock);
194 194
195 195 if (!tem->tvs_initialized) {
196 196 mutex_exit(&tem->tvs_lock);
197 197 mutex_exit(&tems.ts_lock);
198 198 return;
199 199 }
200 200
201 201 tem_safe_check_first_time(tem, credp, CALLED_FROM_NORMAL);
202 202 tem_safe_terminal_emulate(tem, buf, len, credp, CALLED_FROM_NORMAL);
203 203
204 204 mutex_exit(&tem->tvs_lock);
205 205 mutex_exit(&tems.ts_lock);
206 206 }
207 207
208 208 static void
209 209 tem_internal_init(struct tem_vt_state *ptem, cred_t *credp,
210 210 boolean_t init_color, boolean_t clear_screen)
211 211 {
212 212 int i, j;
213 213 int width, height;
214 214 int total;
215 215 text_color_t fg;
216 216 text_color_t bg;
217 217 size_t tc_size = sizeof (text_color_t);
218 218
219 219 ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&ptem->tvs_lock));
220 220
221 221 if (tems.ts_display_mode == VIS_PIXEL) {
222 222 ptem->tvs_pix_data_size = tems.ts_pix_data_size;
223 223 ptem->tvs_pix_data =
224 224 kmem_alloc(ptem->tvs_pix_data_size, KM_SLEEP);
225 225 }
226 226
227 227 ptem->tvs_outbuf_size = tems.ts_c_dimension.width;
228 228 ptem->tvs_outbuf =
229 229 (unsigned char *)kmem_alloc(ptem->tvs_outbuf_size, KM_SLEEP);
230 230
231 231 width = tems.ts_c_dimension.width;
232 232 height = tems.ts_c_dimension.height;
233 233 ptem->tvs_screen_buf_size = width * height;
234 234 ptem->tvs_screen_buf =
235 235 (unsigned char *)kmem_alloc(width * height, KM_SLEEP);
236 236
237 237 total = width * height * tc_size;
238 238 ptem->tvs_fg_buf = (text_color_t *)kmem_alloc(total, KM_SLEEP);
239 239 ptem->tvs_bg_buf = (text_color_t *)kmem_alloc(total, KM_SLEEP);
240 240 ptem->tvs_color_buf_size = total;
241 241
242 242 tem_safe_reset_display(ptem, credp, CALLED_FROM_NORMAL,
243 243 clear_screen, init_color);
244 244
245 245 tem_safe_get_color(ptem, &fg, &bg, TEM_ATTR_SCREEN_REVERSE);
246 246 for (i = 0; i < height; i++)
247 247 for (j = 0; j < width; j++) {
248 248 ptem->tvs_screen_buf[i * width + j] = ' ';
249 249 ptem->tvs_fg_buf[(i * width +j) * tc_size] = fg;
250 250 ptem->tvs_bg_buf[(i * width +j) * tc_size] = bg;
251 251
252 252 }
253 253
254 254 ptem->tvs_initialized = 1;
255 255 }
256 256
257 257 int
258 258 tem_initialized(tem_vt_state_t tem_arg)
259 259 {
260 260 struct tem_vt_state *ptem = (struct tem_vt_state *)tem_arg;
261 261 int ret;
262 262
263 263 mutex_enter(&ptem->tvs_lock);
264 264 ret = ptem->tvs_initialized;
265 265 mutex_exit(&ptem->tvs_lock);
266 266
267 267 return (ret);
268 268 }
269 269
270 270 tem_vt_state_t
271 271 tem_init(cred_t *credp)
272 272 {
273 273 struct tem_vt_state *ptem;
274 274
275 275 ptem = kmem_zalloc(sizeof (struct tem_vt_state), KM_SLEEP);
276 276 mutex_init(&ptem->tvs_lock, (char *)NULL, MUTEX_DRIVER, NULL);
277 277
278 278 mutex_enter(&tems.ts_lock);
279 279 mutex_enter(&ptem->tvs_lock);
280 280
281 281 ptem->tvs_isactive = B_FALSE;
282 282 ptem->tvs_fbmode = KD_TEXT;
283 283
284 284 /*
285 285 * A tem is regarded as initialized only after tem_internal_init(),
286 286 * will be set at the end of tem_internal_init().
287 287 */
288 288 ptem->tvs_initialized = 0;
289 289
290 290
291 291 if (!tems.ts_initialized) {
292 292 /*
293 293 * Only happens during early console configuration.
294 294 */
295 295 tem_add(ptem);
296 296 mutex_exit(&ptem->tvs_lock);
297 297 mutex_exit(&tems.ts_lock);
298 298 return ((tem_vt_state_t)ptem);
299 299 }
300 300
301 301 tem_internal_init(ptem, credp, B_TRUE, B_FALSE);
302 302 tem_add(ptem);
303 303 mutex_exit(&ptem->tvs_lock);
304 304 mutex_exit(&tems.ts_lock);
305 305
306 306 return ((tem_vt_state_t)ptem);
307 307 }
308 308
309 309 /*
310 310 * re-init the tem after video mode has changed and tems_info has
311 311 * been re-inited. The lock is already held.
312 312 */
313 313 static void
314 314 tem_reinit(struct tem_vt_state *tem, boolean_t reset_display)
315 315 {
316 316 ASSERT(MUTEX_HELD(&tems.ts_lock) && MUTEX_HELD(&tem->tvs_lock));
317 317
318 318 tem_free_buf(tem); /* only free virtual buffers */
319 319
320 320 /* reserve color */
321 321 tem_internal_init(tem, kcred, B_FALSE, reset_display);
322 322 }
323 323
324 324 static void
325 325 tem_free_buf(struct tem_vt_state *tem)
326 326 {
327 327 ASSERT(tem != NULL && MUTEX_HELD(&tem->tvs_lock));
328 328
329 329 if (tem->tvs_outbuf != NULL)
330 330 kmem_free(tem->tvs_outbuf, tem->tvs_outbuf_size);
331 331 if (tem->tvs_pix_data != NULL)
332 332 kmem_free(tem->tvs_pix_data, tem->tvs_pix_data_size);
333 333 if (tem->tvs_screen_buf != NULL)
334 334 kmem_free(tem->tvs_screen_buf, tem->tvs_screen_buf_size);
335 335 if (tem->tvs_fg_buf != NULL)
336 336 kmem_free(tem->tvs_fg_buf, tem->tvs_color_buf_size);
337 337 if (tem->tvs_bg_buf != NULL)
338 338 kmem_free(tem->tvs_bg_buf, tem->tvs_color_buf_size);
339 339 }
340 340
341 341 void
342 342 tem_destroy(tem_vt_state_t tem_arg, cred_t *credp)
343 343 {
344 344 struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
345 345
346 346 mutex_enter(&tems.ts_lock);
347 347 mutex_enter(&tem->tvs_lock);
348 348
349 349 if (tem->tvs_isactive && tem->tvs_fbmode == KD_TEXT)
350 350 tem_safe_blank_screen(tem, credp, CALLED_FROM_NORMAL);
351 351
352 352 tem_free_buf(tem);
353 353 tem_rm(tem);
354 354
355 355 if (tems.ts_active == tem)
356 356 tems.ts_active = NULL;
357 357
358 358 mutex_exit(&tem->tvs_lock);
359 359 mutex_exit(&tems.ts_lock);
360 360
361 361 kmem_free(tem, sizeof (struct tem_vt_state));
362 362 }
363 363
364 364 static int
365 365 tems_failed(cred_t *credp, boolean_t finish_ioctl)
366 366 {
367 367 int lyr_rval;
368 368
369 369 ASSERT(MUTEX_HELD(&tems.ts_lock));
370 370
371 371 if (finish_ioctl)
372 372 (void) ldi_ioctl(tems.ts_hdl, VIS_DEVFINI, 0,
373 373 FWRITE|FKIOCTL, credp, &lyr_rval);
374 374
375 375 (void) ldi_close(tems.ts_hdl, NULL, credp);
376 376 tems.ts_hdl = NULL;
377 377 return (ENXIO);
378 378 }
379 379
380 380 /*
381 381 * only called once during boot
382 382 */
383 383 int
384 384 tem_info_init(char *pathname, cred_t *credp)
385 385 {
386 386 int lyr_rval, ret;
387 387 struct vis_devinit temargs;
388 388 char *pathbuf;
389 389 size_t height = 0;
390 390 size_t width = 0;
391 391 struct tem_vt_state *p;
392 392
393 393 mutex_enter(&tems.ts_lock);
394 394
395 395 if (tems.ts_initialized) {
396 396 mutex_exit(&tems.ts_lock);
397 397 return (0);
398 398 }
399 399
400 400 /*
401 401 * Open the layered device using the devfs physical device name
402 402 * after adding the /devices prefix.
403 403 */
404 404 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
405 405 (void) strcpy(pathbuf, "/devices");
406 406 if (i_ddi_prompath_to_devfspath(pathname,
407 407 pathbuf + strlen("/devices")) != DDI_SUCCESS) {
408 408 cmn_err(CE_WARN, "terminal-emulator: path conversion error");
409 409 kmem_free(pathbuf, MAXPATHLEN);
410 410
411 411 mutex_exit(&tems.ts_lock);
412 412 return (ENXIO);
413 413 }
414 414 if (ldi_open_by_name(pathbuf, FWRITE, credp,
415 415 &tems.ts_hdl, term_li) != 0) {
416 416 cmn_err(CE_WARN, "terminal-emulator: device path open error");
417 417 kmem_free(pathbuf, MAXPATHLEN);
418 418
419 419 mutex_exit(&tems.ts_lock);
420 420 return (ENXIO);
421 421 }
422 422 kmem_free(pathbuf, MAXPATHLEN);
423 423
424 424 temargs.modechg_cb = (vis_modechg_cb_t)tems_modechange_callback;
425 425 temargs.modechg_arg = NULL;
426 426
427 427 /*
428 428 * Initialize the console and get the device parameters
429 429 */
430 430 if (ldi_ioctl(tems.ts_hdl, VIS_DEVINIT,
431 431 (intptr_t)&temargs, FWRITE|FKIOCTL, credp, &lyr_rval) != 0) {
432 432 cmn_err(CE_WARN, "terminal emulator: Compatible fb not found");
433 433 ret = tems_failed(credp, B_FALSE);
434 434 mutex_exit(&tems.ts_lock);
435 435 return (ret);
436 436 }
437 437
438 438 /* Make sure the fb driver and terminal emulator versions match */
439 439 if (temargs.version != VIS_CONS_REV) {
440 440 cmn_err(CE_WARN,
441 441 "terminal emulator: VIS_CONS_REV %d (see sys/visual_io.h) "
442 442 "of console fb driver not supported", temargs.version);
443 443 ret = tems_failed(credp, B_TRUE);
444 444 mutex_exit(&tems.ts_lock);
445 445 return (ret);
446 446 }
447 447
448 448 if ((tems.ts_fb_polledio = temargs.polledio) == NULL) {
449 449 cmn_err(CE_WARN, "terminal emulator: fb doesn't support polled "
450 450 "I/O");
451 451 ret = tems_failed(credp, B_TRUE);
452 452 mutex_exit(&tems.ts_lock);
453 453 return (ret);
454 454 }
455 455
456 456 /* other sanity checks */
457 457 if (!((temargs.depth == 4) || (temargs.depth == 8) ||
458 458 (temargs.depth == 24) || (temargs.depth == 32))) {
459 459 cmn_err(CE_WARN, "terminal emulator: unsupported depth");
460 460 ret = tems_failed(credp, B_TRUE);
461 461 mutex_exit(&tems.ts_lock);
462 462 return (ret);
463 463 }
464 464
465 465 if ((temargs.mode != VIS_TEXT) && (temargs.mode != VIS_PIXEL)) {
466 466 cmn_err(CE_WARN, "terminal emulator: unsupported mode");
467 467 ret = tems_failed(credp, B_TRUE);
468 468 mutex_exit(&tems.ts_lock);
469 469 return (ret);
470 470 }
471 471
472 472 if ((temargs.mode == VIS_PIXEL) && plat_stdout_is_framebuffer())
473 473 plat_tem_get_prom_size(&height, &width);
474 474
475 475 /*
476 476 * Initialize the common terminal emulator info
477 477 */
478 478 tems_setup_terminal(&temargs, height, width);
479 479
480 480 tems_reset_colormap(credp, CALLED_FROM_NORMAL);
481 481 tems_get_initial_color(&tems.ts_init_color);
482 482
483 483 tems.ts_initialized = 1; /* initialization flag */
484 484
485 485 for (p = list_head(&tems.ts_list); p != NULL;
486 486 p = list_next(&tems.ts_list, p)) {
487 487 mutex_enter(&p->tvs_lock);
488 488 tem_internal_init(p, credp, B_TRUE, B_FALSE);
489 489 if (temargs.mode == VIS_PIXEL)
490 490 tem_pix_align(p, credp, CALLED_FROM_NORMAL);
491 491 mutex_exit(&p->tvs_lock);
492 492 }
493 493
494 494 mutex_exit(&tems.ts_lock);
495 495 return (0);
496 496 }
497 497
498 498 #define TEMS_DEPTH_DIFF 0x01
499 499 #define TEMS_DIMENSION_DIFF 0x02
500 500
501 501 static uchar_t
502 502 tems_check_videomode(struct vis_devinit *tp)
503 503 {
504 504 uchar_t result = 0;
505 505
506 506 if (tems.ts_pdepth != tp->depth)
507 507 result |= TEMS_DEPTH_DIFF;
508 508
509 509 if (tp->mode == VIS_TEXT) {
510 510 if (tems.ts_c_dimension.width != tp->width ||
511 511 tems.ts_c_dimension.height != tp->height)
512 512 result |= TEMS_DIMENSION_DIFF;
513 513 } else {
514 514 if (tems.ts_p_dimension.width != tp->width ||
515 515 tems.ts_p_dimension.height != tp->height)
516 516 result |= TEMS_DIMENSION_DIFF;
517 517 }
518 518
519 519 return (result);
520 520 }
521 521
522 522 static void
523 523 tems_setup_terminal(struct vis_devinit *tp, size_t height, size_t width)
524 524 {
525 525 int i;
526 526 int old_blank_buf_size = tems.ts_c_dimension.width;
527 527
528 528 ASSERT(MUTEX_HELD(&tems.ts_lock));
529 529
530 530 tems.ts_pdepth = tp->depth;
531 531 tems.ts_linebytes = tp->linebytes;
532 532 tems.ts_display_mode = tp->mode;
533 533
534 534 switch (tp->mode) {
535 535 case VIS_TEXT:
536 536 tems.ts_p_dimension.width = 0;
537 537 tems.ts_p_dimension.height = 0;
538 538 tems.ts_c_dimension.width = tp->width;
539 539 tems.ts_c_dimension.height = tp->height;
540 540 tems.ts_callbacks = &tem_safe_text_callbacks;
541 541
542 542 break;
543 543
544 544 case VIS_PIXEL:
545 545 /*
546 546 * First check to see if the user has specified a screen size.
547 547 * If so, use those values. Else use 34x80 as the default.
548 548 */
549 549 if (width == 0) {
550 550 width = TEM_DEFAULT_COLS;
551 551 height = TEM_DEFAULT_ROWS;
552 552 }
553 553 tems.ts_c_dimension.height = (screen_size_t)height;
554 554 tems.ts_c_dimension.width = (screen_size_t)width;
555 555
556 556 tems.ts_p_dimension.height = tp->height;
557 557 tems.ts_p_dimension.width = tp->width;
558 558
559 559 tems.ts_callbacks = &tem_safe_pix_callbacks;
560 560
561 561 /*
562 562 * set_font() will select a appropriate sized font for
563 563 * the number of rows and columns selected. If we don't
564 564 * have a font that will fit, then it will use the
565 565 * default builtin font and adjust the rows and columns
566 566 * to fit on the screen.
567 567 */
568 568 set_font(&tems.ts_font,
569 569 &tems.ts_c_dimension.height,
570 570 &tems.ts_c_dimension.width,
571 571 tems.ts_p_dimension.height,
572 572 tems.ts_p_dimension.width);
573 573
574 574 tems.ts_p_offset.y = (tems.ts_p_dimension.height -
575 575 (tems.ts_c_dimension.height * tems.ts_font.height)) / 2;
576 576 tems.ts_p_offset.x = (tems.ts_p_dimension.width -
577 577 (tems.ts_c_dimension.width * tems.ts_font.width)) / 2;
578 578
579 579 tems.ts_pix_data_size =
580 580 tems.ts_font.width * tems.ts_font.height;
581 581
582 582 tems.ts_pix_data_size *= 4;
583 583
584 584 tems.ts_pdepth = tp->depth;
585 585
586 586 break;
587 587 }
588 588
589 589 /* Now virtual cls also uses the blank_line buffer */
590 590 if (tems.ts_blank_line)
591 591 kmem_free(tems.ts_blank_line, old_blank_buf_size);
592 592
593 593 tems.ts_blank_line = (unsigned char *)
594 594 kmem_alloc(tems.ts_c_dimension.width, KM_SLEEP);
595 595 for (i = 0; i < tems.ts_c_dimension.width; i++)
596 596 tems.ts_blank_line[i] = ' ';
597 597 }
598 598
599 599 /*
600 600 * This is a callback function that we register with the frame
601 601 * buffer driver layered underneath. It gets invoked from
602 602 * the underlying frame buffer driver to reconfigure the terminal
603 603 * emulator to a new screen size and depth in conjunction with
604 604 * framebuffer videomode changes.
605 605 * Here we keep the foreground/background color and attributes,
606 606 * which may be different with the initial settings, so that
607 607 * the color won't change while the framebuffer videomode changes.
608 608 * And we also reset the kernel terminal emulator and clear the
609 609 * whole screen.
610 610 */
611 611 /* ARGSUSED */
612 612 void
613 613 tems_modechange_callback(struct vis_modechg_arg *arg,
614 614 struct vis_devinit *devinit)
615 615 {
616 616 uchar_t diff;
617 617 struct tem_vt_state *p;
618 618 tem_modechg_cb_t cb;
619 619 tem_modechg_cb_arg_t cb_arg;
620 620
621 621 ASSERT(!(list_is_empty(&tems.ts_list)));
622 622
623 623 mutex_enter(&tems.ts_lock);
624 624
625 625 /*
626 626 * currently only for pixel mode
627 627 */
628 628 diff = tems_check_videomode(devinit);
629 629 if (diff == 0) {
630 630 mutex_exit(&tems.ts_lock);
631 631 return;
632 632 }
633 633
634 634 diff = diff & TEMS_DIMENSION_DIFF;
635 635
636 636 if (diff == 0) {
637 637 /*
638 638 * Only need to reinit the active tem.
639 639 */
640 640 struct tem_vt_state *active = tems.ts_active;
641 641 tems.ts_pdepth = devinit->depth;
642 642
643 643 mutex_enter(&active->tvs_lock);
644 644 ASSERT(active->tvs_isactive);
645 645 tem_reinit(active, B_TRUE);
646 646 mutex_exit(&active->tvs_lock);
647 647
648 648 mutex_exit(&tems.ts_lock);
649 649 return;
650 650 }
651 651
652 652 tems_setup_terminal(devinit, tems.ts_c_dimension.height,
653 653 tems.ts_c_dimension.width);
654 654
655 655 for (p = list_head(&tems.ts_list); p != NULL;
656 656 p = list_next(&tems.ts_list, p)) {
657 657 mutex_enter(&p->tvs_lock);
658 658 tem_reinit(p, p->tvs_isactive);
659 659 mutex_exit(&p->tvs_lock);
660 660 }
661 661
662 662
663 663 if (tems.ts_modechg_cb == NULL) {
664 664 mutex_exit(&tems.ts_lock);
665 665 return;
666 666 }
667 667
668 668 cb = tems.ts_modechg_cb;
669 669 cb_arg = tems.ts_modechg_arg;
670 670
671 671 /*
672 672 * Release the lock while doing callback.
673 673 */
674 674 mutex_exit(&tems.ts_lock);
675 675 cb(cb_arg);
676 676 }
677 677
678 678 /*
679 679 * This function is used to display a rectangular blit of data
680 680 * of a given size and location via the underlying framebuffer driver.
681 681 * The blit can be as small as a pixel or as large as the screen.
682 682 */
683 683 void
684 684 tems_display_layered(
685 685 struct vis_consdisplay *pda,
686 686 cred_t *credp)
687 687 {
688 688 int rval;
689 689
690 690 (void) ldi_ioctl(tems.ts_hdl, VIS_CONSDISPLAY,
691 691 (intptr_t)pda, FKIOCTL, credp, &rval);
692 692 }
693 693
694 694 /*
695 695 * This function is used to invoke a block copy operation in the
696 696 * underlying framebuffer driver. Rectangle copies are how scrolling
697 697 * is implemented, as well as horizontal text shifting escape seqs.
698 698 * such as from vi when deleting characters and words.
699 699 */
700 700 void
701 701 tems_copy_layered(
702 702 struct vis_conscopy *pma,
703 703 cred_t *credp)
704 704 {
705 705 int rval;
706 706
707 707 (void) ldi_ioctl(tems.ts_hdl, VIS_CONSCOPY,
708 708 (intptr_t)pma, FKIOCTL, credp, &rval);
709 709 }
710 710
711 711 /*
712 712 * This function is used to show or hide a rectangluar monochrom
713 713 * pixel inverting, text block cursor via the underlying framebuffer.
714 714 */
715 715 void
716 716 tems_cursor_layered(
717 717 struct vis_conscursor *pca,
718 718 cred_t *credp)
719 719 {
720 720 int rval;
721 721
722 722 (void) ldi_ioctl(tems.ts_hdl, VIS_CONSCURSOR,
723 723 (intptr_t)pca, FKIOCTL, credp, &rval);
724 724 }
725 725
726 726 static void
727 727 tem_kdsetmode(int mode, cred_t *credp)
728 728 {
729 729 int rval;
730 730
731 731 (void) ldi_ioctl(tems.ts_hdl, KDSETMODE,
732 732 (intptr_t)mode, FKIOCTL, credp, &rval);
733 733
734 734 }
735 735
736 736 static void
737 737 tems_reset_colormap(cred_t *credp, enum called_from called_from)
738 738 {
739 739 struct vis_cmap cm;
740 740 int rval;
741 741
742 742 if (called_from == CALLED_FROM_STANDALONE)
743 743 return;
744 744
745 745 switch (tems.ts_pdepth) {
746 746 case 8:
747 747 cm.index = 0;
748 748 cm.count = 16;
749 749 cm.red = cmap4_to_24.red; /* 8-bits (1/3 of TrueColor 24) */
750 750 cm.blue = cmap4_to_24.blue; /* 8-bits (1/3 of TrueColor 24) */
751 751 cm.green = cmap4_to_24.green; /* 8-bits (1/3 of TrueColor 24) */
752 752 (void) ldi_ioctl(tems.ts_hdl, VIS_PUTCMAP, (intptr_t)&cm,
753 753 FKIOCTL, credp, &rval);
754 754 break;
755 755 }
756 756 }
757 757
758 758 void
759 759 tem_get_size(ushort_t *r, ushort_t *c,
760 760 ushort_t *x, ushort_t *y)
761 761 {
762 762 mutex_enter(&tems.ts_lock);
763 763 *r = (ushort_t)tems.ts_c_dimension.height;
764 764 *c = (ushort_t)tems.ts_c_dimension.width;
765 765 *x = (ushort_t)tems.ts_p_dimension.width;
766 766 *y = (ushort_t)tems.ts_p_dimension.height;
767 767 mutex_exit(&tems.ts_lock);
768 768 }
769 769
770 770 void
771 771 tem_register_modechg_cb(tem_modechg_cb_t func,
772 772 tem_modechg_cb_arg_t arg)
773 773 {
774 774 mutex_enter(&tems.ts_lock);
775 775
776 776 tems.ts_modechg_cb = func;
777 777 tems.ts_modechg_arg = arg;
778 778
779 779 mutex_exit(&tems.ts_lock);
780 780 }
781 781
782 782 /*
783 783 * This function is to scroll up the OBP output, which has
784 784 * different screen height and width with our kernel console.
785 785 */
786 786 static void
787 787 tem_prom_scroll_up(struct tem_vt_state *tem, int nrows, cred_t *credp,
788 788 enum called_from called_from)
789 789 {
790 790 struct vis_conscopy ma;
791 791 int ncols, width;
792 792
793 793 /* copy */
794 794 ma.s_row = nrows * tems.ts_font.height;
795 795 ma.e_row = tems.ts_p_dimension.height - 1;
796 796 ma.t_row = 0;
797 797
798 798 ma.s_col = 0;
799 799 ma.e_col = tems.ts_p_dimension.width - 1;
800 800 ma.t_col = 0;
801 801
802 802 tems_safe_copy(&ma, credp, called_from);
803 803
804 804 /* clear */
805 805 width = tems.ts_font.width;
806 806 ncols = (tems.ts_p_dimension.width + (width - 1))/ width;
807 807
808 808 tem_safe_pix_cls_range(tem, 0, nrows, tems.ts_p_offset.y,
809 809 0, ncols, 0, B_TRUE, credp, called_from);
810 810 }
811 811
812 812 #define PROM_DEFAULT_FONT_HEIGHT 22
813 813 #define PROM_DEFAULT_WINDOW_TOP 0x8a
814 814
815 815 /*
816 816 * This function is to compute the starting row of the console, according to
817 817 * PROM cursor's position. Here we have to take different fonts into account.
818 818 */
819 819 static int
820 820 tem_adjust_row(struct tem_vt_state *tem, int prom_row, cred_t *credp,
821 821 enum called_from called_from)
822 822 {
823 823 int tem_row;
824 824 int tem_y;
825 825 int prom_charheight = 0;
826 826 int prom_window_top = 0;
827 827 int scroll_up_lines;
828 828
829 829 plat_tem_get_prom_font_size(&prom_charheight, &prom_window_top);
830 830 if (prom_charheight == 0)
831 831 prom_charheight = PROM_DEFAULT_FONT_HEIGHT;
832 832 if (prom_window_top == 0)
833 833 prom_window_top = PROM_DEFAULT_WINDOW_TOP;
834 834
835 835 tem_y = (prom_row + 1) * prom_charheight + prom_window_top -
836 836 tems.ts_p_offset.y;
837 837 tem_row = (tem_y + tems.ts_font.height - 1) /
838 838 tems.ts_font.height - 1;
839 839
840 840 if (tem_row < 0) {
841 841 tem_row = 0;
842 842 } else if (tem_row >= (tems.ts_c_dimension.height - 1)) {
843 843 /*
844 844 * Scroll up the prom outputs if the PROM cursor's position is
845 845 * below our tem's lower boundary.
846 846 */
847 847 scroll_up_lines = tem_row -
848 848 (tems.ts_c_dimension.height - 1);
849 849 tem_prom_scroll_up(tem, scroll_up_lines, credp, called_from);
850 850 tem_row = tems.ts_c_dimension.height - 1;
851 851 }
852 852
853 853 return (tem_row);
854 854 }
855 855
856 856 void
857 857 tem_pix_align(struct tem_vt_state *tem, cred_t *credp,
858 858 enum called_from called_from)
859 859 {
860 860 uint32_t row = 0;
861 861 uint32_t col = 0;
862 862
863 863 if (plat_stdout_is_framebuffer()) {
864 864 plat_tem_hide_prom_cursor();
865 865
866 866 /*
867 867 * We are getting the current cursor position in pixel
868 868 * mode so that we don't over-write the console output
869 869 * during boot.
870 870 */
871 871 plat_tem_get_prom_pos(&row, &col);
872 872
873 873 /*
874 874 * Adjust the row if necessary when the font of our
875 875 * kernel console tem is different with that of prom
876 876 * tem.
877 877 */
878 878 row = tem_adjust_row(tem, row, credp, called_from);
879 879
880 880 /* first line of our kernel console output */
881 881 tem->tvs_first_line = row + 1;
882 882
883 883 /* re-set and align cusror position */
884 884 tem->tvs_s_cursor.row = tem->tvs_c_cursor.row =
885 885 (screen_pos_t)row;
886 886 tem->tvs_s_cursor.col = tem->tvs_c_cursor.col = 0;
887 887 } else {
888 888 tem_safe_reset_display(tem, credp, called_from, B_TRUE, B_TRUE);
889 889 }
890 890 }
891 891
892 892 static void
893 893 tems_get_inverses(boolean_t *p_inverse, boolean_t *p_inverse_screen)
894 894 {
895 895 int i_inverse = 0;
896 896 int i_inverse_screen = 0;
897 897
898 898 plat_tem_get_inverses(&i_inverse, &i_inverse_screen);
899 899
900 900 *p_inverse = (i_inverse == 0) ? B_FALSE : B_TRUE;
901 901 *p_inverse_screen = (i_inverse_screen == 0) ? B_FALSE : B_TRUE;
902 902 }
903 903
904 904 /*
905 905 * Get the foreground/background color and attributes from the initial
906 906 * PROM, so that our kernel console can keep the same visual behaviour.
907 907 */
908 908 static void
909 909 tems_get_initial_color(tem_color_t *pcolor)
910 910 {
911 911 boolean_t inverse, inverse_screen;
912 912 unsigned short flags = 0;
913 913
914 914 pcolor->fg_color = DEFAULT_ANSI_FOREGROUND;
915 915 pcolor->bg_color = DEFAULT_ANSI_BACKGROUND;
916 916
917 917 if (plat_stdout_is_framebuffer()) {
918 918 tems_get_inverses(&inverse, &inverse_screen);
919 919 if (inverse)
920 920 flags |= TEM_ATTR_REVERSE;
921 921 if (inverse_screen)
922 922 flags |= TEM_ATTR_SCREEN_REVERSE;
923 923 if (flags != 0)
924 924 flags |= TEM_ATTR_BOLD;
925 925 }
926 926
927 927 pcolor->a_flags = flags;
928 928 }
929 929
930 930 uchar_t
931 931 tem_get_fbmode(tem_vt_state_t tem_arg)
932 932 {
933 933 struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
934 934
935 935 uchar_t fbmode;
936 936
937 937 mutex_enter(&tem->tvs_lock);
938 938 fbmode = tem->tvs_fbmode;
939 939 mutex_exit(&tem->tvs_lock);
940 940
941 941 return (fbmode);
942 942 }
943 943
944 944 void
945 945 tem_set_fbmode(tem_vt_state_t tem_arg, uchar_t fbmode, cred_t *credp)
946 946 {
947 947 struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
948 948
949 949 mutex_enter(&tems.ts_lock);
950 950 mutex_enter(&tem->tvs_lock);
951 951
952 952 if (fbmode == tem->tvs_fbmode) {
953 953 mutex_exit(&tem->tvs_lock);
954 954 mutex_exit(&tems.ts_lock);
955 955 return;
956 956 }
957 957
958 958 tem->tvs_fbmode = fbmode;
959 959
960 960 if (tem->tvs_isactive) {
961 961 tem_kdsetmode(tem->tvs_fbmode, credp);
962 962 if (fbmode == KD_TEXT)
963 963 tem_safe_unblank_screen(tem, credp, CALLED_FROM_NORMAL);
964 964 }
965 965
966 966 mutex_exit(&tem->tvs_lock);
967 967 mutex_exit(&tems.ts_lock);
968 968 }
969 969
970 970 void
971 971 tem_activate(tem_vt_state_t tem_arg, boolean_t unblank, cred_t *credp)
972 972 {
973 973 struct tem_vt_state *tem = (struct tem_vt_state *)tem_arg;
974 974
975 975 mutex_enter(&tems.ts_lock);
976 976 tems.ts_active = tem;
977 977
978 978 mutex_enter(&tem->tvs_lock);
979 979 tem->tvs_isactive = B_TRUE;
980 980
981 981 tem_kdsetmode(tem->tvs_fbmode, credp);
982 982
983 983 if (unblank)
984 984 tem_safe_unblank_screen(tem, credp, CALLED_FROM_NORMAL);
985 985
986 986 mutex_exit(&tem->tvs_lock);
987 987 mutex_exit(&tems.ts_lock);
988 988 }
989 989
990 990 void
991 991 tem_switch(tem_vt_state_t tem_arg1, tem_vt_state_t tem_arg2, cred_t *credp)
992 992 {
993 993 struct tem_vt_state *cur = (struct tem_vt_state *)tem_arg1;
994 994 struct tem_vt_state *tobe = (struct tem_vt_state *)tem_arg2;
995 995
996 996 mutex_enter(&tems.ts_lock);
997 997 mutex_enter(&tobe->tvs_lock);
998 998 mutex_enter(&cur->tvs_lock);
999 999
1000 1000 tems.ts_active = tobe;
1001 1001 cur->tvs_isactive = B_FALSE;
1002 1002 tobe->tvs_isactive = B_TRUE;
1003 1003
1004 1004 mutex_exit(&cur->tvs_lock);
1005 1005
1006 1006 if (cur->tvs_fbmode != tobe->tvs_fbmode)
1007 1007 tem_kdsetmode(tobe->tvs_fbmode, credp);
1008 1008
1009 1009 if (tobe->tvs_fbmode == KD_TEXT)
1010 1010 tem_safe_unblank_screen(tobe, credp, CALLED_FROM_NORMAL);
1011 1011
1012 1012 mutex_exit(&tobe->tvs_lock);
1013 1013 mutex_exit(&tems.ts_lock);
1014 1014 }
↓ open down ↓ |
880 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX