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