1 /*- 2 * Copyright (c) 1998 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The DragonFly Project 6 * by Sascha Wildner <saw@online.de> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer as 13 * the first lines of this file unmodified. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * $FreeBSD: src/sys/dev/syscons/scvidctl.c,v 1.19.2.2 2000/05/05 09:16:08 nyan Exp $ 30 * $DragonFly: src/sys/dev/misc/syscons/scvidctl.c,v 1.15 2006/12/29 00:10:35 swildner Exp $ 31 */ 32 33 #include "opt_syscons.h" 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/conf.h> 38 #include <sys/signalvar.h> 39 #include <sys/tty.h> 40 #include <sys/kernel.h> 41 #include <sys/thread2.h> 42 43 #include <machine/console.h> 44 45 #include <dev/video/fb/fbreg.h> 46 #include "syscons.h" 47 48 SET_DECLARE(scrndr_set, const sc_renderer_t); 49 50 int 51 sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize, 52 int fontsize) 53 { 54 video_info_t info; 55 u_char *font; 56 int prev_ysize; 57 int new_ysize; 58 int error; 59 60 if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info)) 61 return ENODEV; 62 63 /* adjust argument values */ 64 if (fontsize <= 0) 65 fontsize = info.vi_cheight; 66 if (fontsize < 14) { 67 fontsize = 8; 68 #ifndef SC_NO_FONT_LOADING 69 if (!(scp->sc->fonts_loaded & FONT_8)) 70 return EINVAL; 71 font = scp->sc->font_8; 72 #else 73 font = NULL; 74 #endif 75 } else if (fontsize >= 16) { 76 fontsize = 16; 77 #ifndef SC_NO_FONT_LOADING 78 if (!(scp->sc->fonts_loaded & FONT_16)) 79 return EINVAL; 80 font = scp->sc->font_16; 81 #else 82 font = NULL; 83 #endif 84 } else { 85 fontsize = 14; 86 #ifndef SC_NO_FONT_LOADING 87 if (!(scp->sc->fonts_loaded & FONT_14)) 88 return EINVAL; 89 font = scp->sc->font_14; 90 #else 91 font = NULL; 92 #endif 93 } 94 if ((xsize <= 0) || (xsize > info.vi_width)) 95 xsize = info.vi_width; 96 if ((ysize <= 0) || (ysize > info.vi_height)) 97 ysize = info.vi_height; 98 99 /* stop screen saver, etc */ 100 crit_enter(); 101 if ((error = sc_clean_up(scp))) { 102 crit_exit(); 103 return error; 104 } 105 106 if (sc_render_match(scp, scp->sc->adp->va_name, 0) == NULL) { 107 crit_exit(); 108 return ENODEV; 109 } 110 111 /* set up scp */ 112 new_ysize = 0; 113 #ifndef SC_NO_HISTORY 114 if (scp->history != NULL) { 115 sc_hist_save(scp); 116 new_ysize = sc_vtb_rows(scp->history); 117 } 118 #endif 119 prev_ysize = scp->ysize; 120 /* 121 * This is a kludge to fend off scrn_update() while we 122 * muck around with scp. XXX 123 */ 124 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 125 scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE | MOUSE_VISIBLE); 126 scp->mode = mode; 127 scp->xsize = xsize; 128 scp->ysize = ysize; 129 scp->xoff = 0; 130 scp->yoff = 0; 131 scp->xpixel = scp->xsize*8; 132 scp->ypixel = scp->ysize*fontsize; 133 scp->font = font; 134 scp->font_size = fontsize; 135 136 /* allocate buffers */ 137 sc_alloc_scr_buffer(scp, TRUE, TRUE); 138 sc_init_emulator(scp, NULL); 139 #ifndef SC_NO_CUTPASTE 140 sc_alloc_cut_buffer(scp, FALSE); 141 #endif 142 #ifndef SC_NO_HISTORY 143 sc_alloc_history_buffer(scp, new_ysize, prev_ysize, FALSE); 144 #endif 145 crit_exit(); 146 147 if (scp == scp->sc->cur_scp) 148 set_mode(scp); 149 scp->status &= ~UNKNOWN_MODE; 150 151 if (tp == NULL) 152 return 0; 153 DPRINTF(5, ("ws_*size (%d,%d), size (%d,%d)\n", 154 tp->t_winsize.ws_col, tp->t_winsize.ws_row, scp->xsize, scp->ysize)); 155 if (tp->t_winsize.ws_col != scp->xsize 156 || tp->t_winsize.ws_row != scp->ysize) { 157 tp->t_winsize.ws_col = scp->xsize; 158 tp->t_winsize.ws_row = scp->ysize; 159 pgsignal(tp->t_pgrp, SIGWINCH, 1); 160 } 161 162 return 0; 163 } 164 165 int 166 sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode) 167 { 168 #ifdef SC_NO_MODE_CHANGE 169 return ENODEV; 170 #else 171 video_info_t info; 172 int error; 173 174 if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info)) 175 return ENODEV; 176 177 /* stop screen saver, etc */ 178 crit_enter(); 179 if ((error = sc_clean_up(scp))) { 180 crit_exit(); 181 return error; 182 } 183 184 if (sc_render_match(scp, scp->sc->adp->va_name, GRAPHICS_MODE) == NULL) { 185 crit_exit(); 186 return ENODEV; 187 } 188 189 /* set up scp */ 190 scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE | MOUSE_HIDDEN); 191 scp->status &= ~(PIXEL_MODE | MOUSE_VISIBLE); 192 scp->mode = mode; 193 /* 194 * Don't change xsize and ysize; preserve the previous vty 195 * and history buffers. 196 */ 197 scp->xoff = 0; 198 scp->yoff = 0; 199 scp->xpixel = info.vi_width; 200 scp->ypixel = info.vi_height; 201 scp->font = NULL; 202 scp->font_size = 0; 203 #ifndef SC_NO_SYSMOUSE 204 /* move the mouse cursor at the center of the screen */ 205 sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2); 206 #endif 207 sc_init_emulator(scp, NULL); 208 crit_exit(); 209 210 if (scp == scp->sc->cur_scp) 211 set_mode(scp); 212 /* clear_graphics();*/ 213 refresh_ega_palette(scp); 214 scp->status &= ~UNKNOWN_MODE; 215 216 if (tp == NULL) 217 return 0; 218 if (tp->t_winsize.ws_xpixel != scp->xpixel 219 || tp->t_winsize.ws_ypixel != scp->ypixel) { 220 tp->t_winsize.ws_xpixel = scp->xpixel; 221 tp->t_winsize.ws_ypixel = scp->ypixel; 222 pgsignal(tp->t_pgrp, SIGWINCH, 1); 223 } 224 225 return 0; 226 #endif /* SC_NO_MODE_CHANGE */ 227 } 228 229 int 230 sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, 231 int fontsize) 232 { 233 #ifndef SC_PIXEL_MODE 234 return ENODEV; 235 #else 236 video_info_t info; 237 u_char *font; 238 int prev_ysize; 239 int new_ysize; 240 int error; 241 242 if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) 243 return ENODEV; /* this shouldn't happen */ 244 245 /* adjust argument values */ 246 if (fontsize <= 0) 247 fontsize = info.vi_cheight; 248 if (fontsize < 14) { 249 fontsize = 8; 250 #ifndef SC_NO_FONT_LOADING 251 if (!(scp->sc->fonts_loaded & FONT_8)) 252 return EINVAL; 253 font = scp->sc->font_8; 254 #else 255 font = NULL; 256 #endif 257 } else if (fontsize >= 16) { 258 fontsize = 16; 259 #ifndef SC_NO_FONT_LOADING 260 if (!(scp->sc->fonts_loaded & FONT_16)) 261 return EINVAL; 262 font = scp->sc->font_16; 263 #else 264 font = NULL; 265 #endif 266 } else { 267 fontsize = 14; 268 #ifndef SC_NO_FONT_LOADING 269 if (!(scp->sc->fonts_loaded & FONT_14)) 270 return EINVAL; 271 font = scp->sc->font_14; 272 #else 273 font = NULL; 274 #endif 275 } 276 if (xsize <= 0) 277 xsize = info.vi_width/8; 278 if (ysize <= 0) 279 ysize = info.vi_height/fontsize; 280 281 if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize)) 282 return EINVAL; 283 284 /* 285 * We currently support the following graphic modes: 286 * 287 * - 4 bpp planar modes whose memory size does not exceed 64K 288 * - 15, 16, 24 and 32 bpp direct modes with linear frame buffer 289 */ 290 291 if (info.vi_mem_model == V_INFO_MM_PLANAR) { 292 if (info.vi_planes != 4) 293 return ENODEV; 294 295 /* 296 * A memory size >64K requires bank switching to access the entire 297 * screen. XXX 298 */ 299 300 if (info.vi_width * info.vi_height / 8 > info.vi_window_size) 301 return ENODEV; 302 } else if (info.vi_mem_model == V_INFO_MM_DIRECT) { 303 if (!(info.vi_flags & V_INFO_LINEAR) && 304 (info.vi_depth != 15) && (info.vi_depth != 16) && 305 (info.vi_depth != 24) && (info.vi_depth != 32)) 306 return ENODEV; 307 } else 308 return ENODEV; 309 310 /* stop screen saver, etc */ 311 crit_enter(); 312 if ((error = sc_clean_up(scp))) { 313 crit_exit(); 314 return error; 315 } 316 317 if (sc_render_match(scp, scp->sc->adp->va_name, PIXEL_MODE) == NULL) { 318 crit_exit(); 319 return ENODEV; 320 } 321 322 #if 0 323 if (scp->tsw) 324 (*scp->tsw->te_term)(scp, scp->ts); 325 scp->tsw = NULL; 326 scp->ts = NULL; 327 #endif 328 329 /* set up scp */ 330 new_ysize = 0; 331 #ifndef SC_NO_HISTORY 332 if (scp->history != NULL) { 333 sc_hist_save(scp); 334 new_ysize = sc_vtb_rows(scp->history); 335 } 336 #endif 337 prev_ysize = scp->ysize; 338 scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); 339 scp->status &= ~(GRAPHICS_MODE | MOUSE_VISIBLE); 340 scp->xsize = xsize; 341 scp->ysize = ysize; 342 scp->xoff = (scp->xpixel/8 - xsize)/2; 343 scp->yoff = (scp->ypixel/fontsize - ysize)/2; 344 scp->font = font; 345 scp->font_size = fontsize; 346 347 /* allocate buffers */ 348 sc_alloc_scr_buffer(scp, TRUE, TRUE); 349 sc_init_emulator(scp, NULL); 350 #ifndef SC_NO_CUTPASTE 351 sc_alloc_cut_buffer(scp, FALSE); 352 #endif 353 #ifndef SC_NO_HISTORY 354 sc_alloc_history_buffer(scp, new_ysize, prev_ysize, FALSE); 355 #endif 356 crit_exit(); 357 358 if (scp == scp->sc->cur_scp) { 359 sc_set_border(scp, scp->border); 360 sc_set_cursor_image(scp); 361 } 362 363 scp->status &= ~UNKNOWN_MODE; 364 365 if (tp == NULL) 366 return 0; 367 if (tp->t_winsize.ws_col != scp->xsize 368 || tp->t_winsize.ws_row != scp->ysize) { 369 tp->t_winsize.ws_col = scp->xsize; 370 tp->t_winsize.ws_row = scp->ysize; 371 pgsignal(tp->t_pgrp, SIGWINCH, 1); 372 } 373 374 return 0; 375 #endif /* SC_PIXEL_MODE */ 376 } 377 378 #define fb_ioctl(a, c, d) \ 379 (((a) == NULL) ? ENODEV : \ 380 (*vidsw[(a)->va_index]->ioctl)((a), (c), (caddr_t)(d))) 381 382 int 383 sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag) 384 { 385 scr_stat *scp; 386 video_adapter_t *adp; 387 video_info_t info; 388 int error; 389 390 scp = SC_STAT(tp->t_dev); 391 if (scp == NULL) /* tp == SC_MOUSE */ 392 return ENOIOCTL; 393 adp = scp->sc->adp; 394 if (adp == NULL) /* shouldn't happen??? */ 395 return ENODEV; 396 397 switch (cmd) { 398 399 case CONS_CURRENTADP: /* get current adapter index */ 400 case FBIO_ADAPTER: 401 return fb_ioctl(adp, FBIO_ADAPTER, data); 402 403 case CONS_CURRENT: /* get current adapter type */ 404 case FBIO_ADPTYPE: 405 return fb_ioctl(adp, FBIO_ADPTYPE, data); 406 407 case CONS_ADPINFO: /* adapter information */ 408 case FBIO_ADPINFO: 409 if (((video_adapter_info_t *)data)->va_index >= 0) { 410 adp = vid_get_adapter(((video_adapter_info_t *)data)->va_index); 411 if (adp == NULL) 412 return ENODEV; 413 } 414 return fb_ioctl(adp, FBIO_ADPINFO, data); 415 416 case CONS_GET: /* get current video mode */ 417 case FBIO_GETMODE: 418 *(int *)data = scp->mode; 419 return 0; 420 421 #ifndef SC_NO_MODE_CHANGE 422 case FBIO_SETMODE: /* set video mode */ 423 if (!(adp->va_flags & V_ADP_MODECHANGE)) 424 return ENODEV; 425 info.vi_mode = *(int *)data; 426 error = fb_ioctl(adp, FBIO_MODEINFO, &info); 427 if (error) 428 return error; 429 if (info.vi_flags & V_INFO_GRAPHICS) 430 return sc_set_graphics_mode(scp, tp, *(int *)data); 431 else 432 return sc_set_text_mode(scp, tp, *(int *)data, 0, 0, 0); 433 #endif /* SC_NO_MODE_CHANGE */ 434 435 case CONS_MODEINFO: /* get mode information */ 436 case FBIO_MODEINFO: 437 return fb_ioctl(adp, FBIO_MODEINFO, data); 438 439 case CONS_FINDMODE: /* find a matching video mode */ 440 case FBIO_FINDMODE: 441 return fb_ioctl(adp, FBIO_FINDMODE, data); 442 443 case CONS_SETWINORG: /* set frame buffer window origin */ 444 case FBIO_SETWINORG: 445 if (scp != scp->sc->cur_scp) 446 return ENODEV; /* XXX */ 447 return fb_ioctl(adp, FBIO_SETWINORG, data); 448 449 case FBIO_GETWINORG: /* get frame buffer window origin */ 450 if (scp != scp->sc->cur_scp) 451 return ENODEV; /* XXX */ 452 return fb_ioctl(adp, FBIO_GETWINORG, data); 453 454 case FBIO_GETDISPSTART: 455 case FBIO_SETDISPSTART: 456 case FBIO_GETLINEWIDTH: 457 case FBIO_SETLINEWIDTH: 458 if (scp != scp->sc->cur_scp) 459 return ENODEV; /* XXX */ 460 return fb_ioctl(adp, cmd, data); 461 462 case FBIO_GETPALETTE: 463 case FBIO_SETPALETTE: 464 case FBIOPUTCMAP: 465 case FBIOGETCMAP: 466 case FBIOGTYPE: 467 case FBIOGATTR: 468 case FBIOSVIDEO: 469 case FBIOGVIDEO: 470 case FBIOSCURSOR: 471 case FBIOGCURSOR: 472 case FBIOSCURPOS: 473 case FBIOGCURPOS: 474 case FBIOGCURMAX: 475 if (scp != scp->sc->cur_scp) 476 return ENODEV; /* XXX */ 477 return fb_ioctl(adp, cmd, data); 478 479 #ifndef SC_NO_MODE_CHANGE 480 /* VGA TEXT MODES */ 481 case SW_VGA_C40x25: 482 case SW_VGA_C80x25: case SW_VGA_M80x25: 483 case SW_VGA_C80x30: case SW_VGA_M80x30: 484 case SW_VGA_C80x50: case SW_VGA_M80x50: 485 case SW_VGA_C80x60: case SW_VGA_M80x60: 486 case SW_VGA_C90x25: case SW_VGA_M90x25: 487 case SW_VGA_C90x30: case SW_VGA_M90x30: 488 case SW_VGA_C90x43: case SW_VGA_M90x43: 489 case SW_VGA_C90x50: case SW_VGA_M90x50: 490 case SW_VGA_C90x60: case SW_VGA_M90x60: 491 case SW_B40x25: case SW_C40x25: 492 case SW_B80x25: case SW_C80x25: 493 case SW_ENH_B40x25: case SW_ENH_C40x25: 494 case SW_ENH_B80x25: case SW_ENH_C80x25: 495 case SW_ENH_B80x43: case SW_ENH_C80x43: 496 case SW_EGAMONO80x25: 497 if (!(adp->va_flags & V_ADP_MODECHANGE)) 498 return ENODEV; 499 return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0); 500 501 /* GRAPHICS MODES */ 502 case SW_BG320: case SW_BG640: 503 case SW_CG320: case SW_CG320_D: case SW_CG640_E: 504 case SW_CG640x350: case SW_ENH_CG640: 505 case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: 506 case SW_VGA_MODEX: 507 if (!(adp->va_flags & V_ADP_MODECHANGE)) 508 return ENODEV; 509 return sc_set_graphics_mode(scp, tp, cmd & 0xff); 510 #endif /* SC_NO_MODE_CHANGE */ 511 512 case KDSETMODE: /* set current mode of this (virtual) console */ 513 switch (*(int *)data) { 514 case KD_TEXT: /* switch to TEXT (known) mode */ 515 /* 516 * If scp->mode is of graphics modes, we don't know which 517 * text mode to switch back to... 518 */ 519 if (scp->status & GRAPHICS_MODE) 520 return EINVAL; 521 /* restore fonts & palette ! */ 522 #if 0 523 #ifndef SC_NO_FONT_LOADING 524 if (ISFONTAVAIL(adp->va_flags) 525 && !(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 526 /* 527 * FONT KLUDGE 528 * Don't load fonts for now... XXX 529 */ 530 if (scp->sc->fonts_loaded & FONT_8) 531 sc_load_font(scp, 0, 8, scp->sc->font_8, 0, 256); 532 if (scp->sc->fonts_loaded & FONT_14) 533 sc_load_font(scp, 0, 14, scp->sc->font_14, 0, 256); 534 if (scp->sc->fonts_loaded & FONT_16) 535 sc_load_font(scp, 0, 16, scp->sc->font_16, 0, 256); 536 } 537 #endif /* SC_NO_FONT_LOADING */ 538 #endif 539 540 #ifndef SC_NO_PALETTE_LOADING 541 load_palette(adp, scp->sc->palette); 542 #endif 543 544 /* move hardware cursor out of the way */ 545 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1); 546 /* FALL THROUGH */ 547 548 case KD_TEXT1: /* switch to TEXT (known) mode */ 549 /* 550 * If scp->mode is of graphics modes, we don't know which 551 * text/pixel mode to switch back to... 552 */ 553 if (scp->status & GRAPHICS_MODE) 554 return EINVAL; 555 crit_enter(); 556 if ((error = sc_clean_up(scp))) { 557 crit_exit(); 558 return error; 559 } 560 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 561 crit_exit(); 562 /* no restore fonts & palette */ 563 if (scp == scp->sc->cur_scp) 564 set_mode(scp); 565 sc_clear_screen(scp); 566 scp->status &= ~UNKNOWN_MODE; 567 return 0; 568 569 #ifdef SC_PIXEL_MODE 570 case KD_PIXEL: /* pixel (raster) display */ 571 if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 572 return EINVAL; 573 if (scp->status & GRAPHICS_MODE) 574 return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, 575 scp->font_size); 576 crit_enter(); 577 if ((error = sc_clean_up(scp))) { 578 crit_exit(); 579 return error; 580 } 581 scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); 582 crit_exit(); 583 if (scp == scp->sc->cur_scp) { 584 set_mode(scp); 585 #ifndef SC_NO_PALETTE_LOADING 586 load_palette(adp, scp->sc->palette); 587 #endif 588 } 589 sc_clear_screen(scp); 590 scp->status &= ~UNKNOWN_MODE; 591 return 0; 592 #endif /* SC_PIXEL_MODE */ 593 594 case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ 595 crit_enter(); 596 if ((error = sc_clean_up(scp))) { 597 crit_exit(); 598 return error; 599 } 600 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 601 crit_exit(); 602 return 0; 603 604 default: 605 return EINVAL; 606 } 607 /* NOT REACHED */ 608 609 #ifdef SC_PIXEL_MODE 610 case KDRASTER: /* set pixel (raster) display mode */ 611 if (ISUNKNOWNSC(scp) || ISTEXTSC(scp)) 612 return ENODEV; 613 return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1], 614 ((int *)data)[2]); 615 #endif /* SC_PIXEL_MODE */ 616 617 case KDGETMODE: /* get current mode of this (virtual) console */ 618 /* 619 * From the user program's point of view, KD_PIXEL is the same 620 * as KD_TEXT... 621 */ 622 *data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT; 623 return 0; 624 625 case KDSBORDER: /* set border color of this (virtual) console */ 626 scp->border = *data; 627 if (scp == scp->sc->cur_scp) 628 sc_set_border(scp, scp->border); 629 return 0; 630 } 631 632 return ENOIOCTL; 633 } 634 635 static LIST_HEAD(, sc_renderer) sc_rndr_list = 636 LIST_HEAD_INITIALIZER(sc_rndr_list); 637 638 int 639 sc_render_add(sc_renderer_t *rndr) 640 { 641 LIST_INSERT_HEAD(&sc_rndr_list, rndr, link); 642 return 0; 643 } 644 645 int 646 sc_render_remove(sc_renderer_t *rndr) 647 { 648 /* 649 LIST_REMOVE(rndr, link); 650 */ 651 return EBUSY; /* XXX */ 652 } 653 654 sc_rndr_sw_t * 655 sc_render_match(scr_stat *scp, char *name, int mode) 656 { 657 const sc_renderer_t **list; 658 const sc_renderer_t *p; 659 660 if (!LIST_EMPTY(&sc_rndr_list)) { 661 LIST_FOREACH(p, &sc_rndr_list, link) { 662 if ((strcmp(p->name, name) == 0) 663 && (mode == p->mode)) { 664 scp->status &= 665 ~(VR_CURSOR_ON | VR_CURSOR_BLINK); 666 return p->rndrsw; 667 } 668 } 669 } else { 670 SET_FOREACH(list, scrndr_set) { 671 p = *list; 672 if ((strcmp(p->name, name) == 0) 673 && (mode == p->mode)) { 674 scp->status &= 675 ~(VR_CURSOR_ON | VR_CURSOR_BLINK); 676 return p->rndrsw; 677 } 678 } 679 } 680 681 return NULL; 682 } 683