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.9 2005/02/18 16:38:23 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 42 #include <machine/console.h> 43 44 #include <dev/video/fb/fbreg.h> 45 #include "syscons.h" 46 47 SET_DECLARE(scrndr_set, const sc_renderer_t); 48 49 int 50 sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize, 51 int fontsize) 52 { 53 video_info_t info; 54 u_char *font; 55 int prev_ysize; 56 int error; 57 int s; 58 59 if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info)) 60 return ENODEV; 61 62 /* adjust argument values */ 63 if (fontsize <= 0) 64 fontsize = info.vi_cheight; 65 if (fontsize < 14) { 66 fontsize = 8; 67 #ifndef SC_NO_FONT_LOADING 68 if (!(scp->sc->fonts_loaded & FONT_8)) 69 return EINVAL; 70 font = scp->sc->font_8; 71 #else 72 font = NULL; 73 #endif 74 } else if (fontsize >= 16) { 75 fontsize = 16; 76 #ifndef SC_NO_FONT_LOADING 77 if (!(scp->sc->fonts_loaded & FONT_16)) 78 return EINVAL; 79 font = scp->sc->font_16; 80 #else 81 font = NULL; 82 #endif 83 } else { 84 fontsize = 14; 85 #ifndef SC_NO_FONT_LOADING 86 if (!(scp->sc->fonts_loaded & FONT_14)) 87 return EINVAL; 88 font = scp->sc->font_14; 89 #else 90 font = NULL; 91 #endif 92 } 93 if ((xsize <= 0) || (xsize > info.vi_width)) 94 xsize = info.vi_width; 95 if ((ysize <= 0) || (ysize > info.vi_height)) 96 ysize = info.vi_height; 97 98 /* stop screen saver, etc */ 99 s = spltty(); 100 if ((error = sc_clean_up(scp))) { 101 splx(s); 102 return error; 103 } 104 105 if (sc_render_match(scp, scp->sc->adp->va_name, 0) == NULL) { 106 splx(s); 107 return ENODEV; 108 } 109 110 /* set up scp */ 111 #ifndef SC_NO_HISTORY 112 if (scp->history != NULL) 113 sc_hist_save(scp); 114 #endif 115 prev_ysize = scp->ysize; 116 /* 117 * This is a kludge to fend off scrn_update() while we 118 * muck around with scp. XXX 119 */ 120 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 121 scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE | MOUSE_VISIBLE); 122 scp->mode = mode; 123 scp->xsize = xsize; 124 scp->ysize = ysize; 125 scp->xoff = 0; 126 scp->yoff = 0; 127 scp->xpixel = scp->xsize*8; 128 scp->ypixel = scp->ysize*fontsize; 129 scp->font = font; 130 scp->font_size = fontsize; 131 132 /* allocate buffers */ 133 sc_alloc_scr_buffer(scp, TRUE, TRUE); 134 sc_init_emulator(scp, NULL); 135 #ifndef SC_NO_CUTPASTE 136 sc_alloc_cut_buffer(scp, FALSE); 137 #endif 138 #ifndef SC_NO_HISTORY 139 sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE); 140 #endif 141 splx(s); 142 143 if (scp == scp->sc->cur_scp) 144 set_mode(scp); 145 scp->status &= ~UNKNOWN_MODE; 146 147 if (tp == NULL) 148 return 0; 149 DPRINTF(5, ("ws_*size (%d,%d), size (%d,%d)\n", 150 tp->t_winsize.ws_col, tp->t_winsize.ws_row, scp->xsize, scp->ysize)); 151 if (tp->t_winsize.ws_col != scp->xsize 152 || tp->t_winsize.ws_row != scp->ysize) { 153 tp->t_winsize.ws_col = scp->xsize; 154 tp->t_winsize.ws_row = scp->ysize; 155 pgsignal(tp->t_pgrp, SIGWINCH, 1); 156 } 157 158 return 0; 159 } 160 161 int 162 sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode) 163 { 164 #ifdef SC_NO_MODE_CHANGE 165 return ENODEV; 166 #else 167 video_info_t info; 168 int error; 169 int s; 170 171 if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info)) 172 return ENODEV; 173 174 /* stop screen saver, etc */ 175 s = spltty(); 176 if ((error = sc_clean_up(scp))) { 177 splx(s); 178 return error; 179 } 180 181 if (sc_render_match(scp, scp->sc->adp->va_name, GRAPHICS_MODE) == NULL) { 182 splx(s); 183 return ENODEV; 184 } 185 186 /* set up scp */ 187 scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE | MOUSE_HIDDEN); 188 scp->status &= ~(PIXEL_MODE | MOUSE_VISIBLE); 189 scp->mode = mode; 190 /* 191 * Don't change xsize and ysize; preserve the previous vty 192 * and history buffers. 193 */ 194 scp->xoff = 0; 195 scp->yoff = 0; 196 scp->xpixel = info.vi_width; 197 scp->ypixel = info.vi_height; 198 scp->font = NULL; 199 scp->font_size = 0; 200 #ifndef SC_NO_SYSMOUSE 201 /* move the mouse cursor at the center of the screen */ 202 sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2); 203 #endif 204 sc_init_emulator(scp, NULL); 205 splx(s); 206 207 if (scp == scp->sc->cur_scp) 208 set_mode(scp); 209 /* clear_graphics();*/ 210 refresh_ega_palette(scp); 211 scp->status &= ~UNKNOWN_MODE; 212 213 if (tp == NULL) 214 return 0; 215 if (tp->t_winsize.ws_xpixel != scp->xpixel 216 || tp->t_winsize.ws_ypixel != scp->ypixel) { 217 tp->t_winsize.ws_xpixel = scp->xpixel; 218 tp->t_winsize.ws_ypixel = scp->ypixel; 219 pgsignal(tp->t_pgrp, SIGWINCH, 1); 220 } 221 222 return 0; 223 #endif /* SC_NO_MODE_CHANGE */ 224 } 225 226 int 227 sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, 228 int fontsize) 229 { 230 #ifndef SC_PIXEL_MODE 231 return ENODEV; 232 #else 233 video_info_t info; 234 u_char *font; 235 int prev_ysize; 236 int error; 237 int s; 238 239 if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) 240 return ENODEV; /* this shouldn't happen */ 241 242 /* adjust argument values */ 243 if (fontsize <= 0) 244 fontsize = info.vi_cheight; 245 if (fontsize < 14) { 246 fontsize = 8; 247 #ifndef SC_NO_FONT_LOADING 248 if (!(scp->sc->fonts_loaded & FONT_8)) 249 return EINVAL; 250 font = scp->sc->font_8; 251 #else 252 font = NULL; 253 #endif 254 } else if (fontsize >= 16) { 255 fontsize = 16; 256 #ifndef SC_NO_FONT_LOADING 257 if (!(scp->sc->fonts_loaded & FONT_16)) 258 return EINVAL; 259 font = scp->sc->font_16; 260 #else 261 font = NULL; 262 #endif 263 } else { 264 fontsize = 14; 265 #ifndef SC_NO_FONT_LOADING 266 if (!(scp->sc->fonts_loaded & FONT_14)) 267 return EINVAL; 268 font = scp->sc->font_14; 269 #else 270 font = NULL; 271 #endif 272 } 273 if (xsize <= 0) 274 xsize = info.vi_width/8; 275 if (ysize <= 0) 276 ysize = info.vi_height/fontsize; 277 278 if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize)) 279 return EINVAL; 280 281 /* 282 * We currently support the following graphic modes: 283 * 284 * - 4 bpp planar modes whose memory size does not exceed 64K 285 * - 15, 16, 24 and 32 bpp linear modes 286 */ 287 288 if (info.vi_mem_model == V_INFO_MM_PLANAR) { 289 if (info.vi_planes != 4) 290 return ENODEV; 291 292 /* 293 * A memory size >64K requires bank switching to access the entire 294 * screen. XXX 295 */ 296 297 if (info.vi_width * info.vi_height / 8 > info.vi_window_size) 298 return ENODEV; 299 } else if (info.vi_mem_model == V_INFO_MM_DIRECT) { 300 if ((info.vi_depth != 15) && (info.vi_depth != 16) && 301 (info.vi_depth != 24) && (info.vi_depth != 32)) 302 return ENODEV; 303 } else 304 return ENODEV; 305 306 /* stop screen saver, etc */ 307 s = spltty(); 308 if ((error = sc_clean_up(scp))) { 309 splx(s); 310 return error; 311 } 312 313 if (sc_render_match(scp, scp->sc->adp->va_name, PIXEL_MODE) == NULL) { 314 splx(s); 315 return ENODEV; 316 } 317 318 #if 0 319 if (scp->tsw) 320 (*scp->tsw->te_term)(scp, scp->ts); 321 scp->tsw = NULL; 322 scp->ts = NULL; 323 #endif 324 325 /* set up scp */ 326 #ifndef SC_NO_HISTORY 327 if (scp->history != NULL) 328 sc_hist_save(scp); 329 #endif 330 prev_ysize = scp->ysize; 331 scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); 332 scp->status &= ~(GRAPHICS_MODE | MOUSE_VISIBLE); 333 scp->xsize = xsize; 334 scp->ysize = ysize; 335 scp->xoff = (scp->xpixel/8 - xsize)/2; 336 scp->yoff = (scp->ypixel/fontsize - ysize)/2; 337 scp->font = font; 338 scp->font_size = fontsize; 339 340 /* allocate buffers */ 341 sc_alloc_scr_buffer(scp, TRUE, TRUE); 342 sc_init_emulator(scp, NULL); 343 #ifndef SC_NO_CUTPASTE 344 sc_alloc_cut_buffer(scp, FALSE); 345 #endif 346 #ifndef SC_NO_HISTORY 347 sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE); 348 #endif 349 splx(s); 350 351 if (scp == scp->sc->cur_scp) { 352 sc_set_border(scp, scp->border); 353 sc_set_cursor_image(scp); 354 } 355 356 scp->status &= ~UNKNOWN_MODE; 357 358 if (tp == NULL) 359 return 0; 360 if (tp->t_winsize.ws_col != scp->xsize 361 || tp->t_winsize.ws_row != scp->ysize) { 362 tp->t_winsize.ws_col = scp->xsize; 363 tp->t_winsize.ws_row = scp->ysize; 364 pgsignal(tp->t_pgrp, SIGWINCH, 1); 365 } 366 367 return 0; 368 #endif /* SC_PIXEL_MODE */ 369 } 370 371 #define fb_ioctl(a, c, d) \ 372 (((a) == NULL) ? ENODEV : \ 373 (*vidsw[(a)->va_index]->ioctl)((a), (c), (caddr_t)(d))) 374 375 int 376 sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct thread *td) 377 { 378 scr_stat *scp; 379 video_adapter_t *adp; 380 video_info_t info; 381 int error; 382 int s; 383 384 scp = SC_STAT(tp->t_dev); 385 if (scp == NULL) /* tp == SC_MOUSE */ 386 return ENOIOCTL; 387 adp = scp->sc->adp; 388 if (adp == NULL) /* shouldn't happen??? */ 389 return ENODEV; 390 391 switch (cmd) { 392 393 case CONS_CURRENTADP: /* get current adapter index */ 394 case FBIO_ADAPTER: 395 return fb_ioctl(adp, FBIO_ADAPTER, data); 396 397 case CONS_CURRENT: /* get current adapter type */ 398 case FBIO_ADPTYPE: 399 return fb_ioctl(adp, FBIO_ADPTYPE, data); 400 401 case CONS_ADPINFO: /* adapter information */ 402 case FBIO_ADPINFO: 403 if (((video_adapter_info_t *)data)->va_index >= 0) { 404 adp = vid_get_adapter(((video_adapter_info_t *)data)->va_index); 405 if (adp == NULL) 406 return ENODEV; 407 } 408 return fb_ioctl(adp, FBIO_ADPINFO, data); 409 410 case CONS_GET: /* get current video mode */ 411 case FBIO_GETMODE: 412 *(int *)data = scp->mode; 413 return 0; 414 415 #ifndef SC_NO_MODE_CHANGE 416 case FBIO_SETMODE: /* set video mode */ 417 if (!(adp->va_flags & V_ADP_MODECHANGE)) 418 return ENODEV; 419 info.vi_mode = *(int *)data; 420 error = fb_ioctl(adp, FBIO_MODEINFO, &info); 421 if (error) 422 return error; 423 if (info.vi_flags & V_INFO_GRAPHICS) 424 return sc_set_graphics_mode(scp, tp, *(int *)data); 425 else 426 return sc_set_text_mode(scp, tp, *(int *)data, 0, 0, 0); 427 #endif /* SC_NO_MODE_CHANGE */ 428 429 case CONS_MODEINFO: /* get mode information */ 430 case FBIO_MODEINFO: 431 return fb_ioctl(adp, FBIO_MODEINFO, data); 432 433 case CONS_FINDMODE: /* find a matching video mode */ 434 case FBIO_FINDMODE: 435 return fb_ioctl(adp, FBIO_FINDMODE, data); 436 437 case CONS_SETWINORG: /* set frame buffer window origin */ 438 case FBIO_SETWINORG: 439 if (scp != scp->sc->cur_scp) 440 return ENODEV; /* XXX */ 441 return fb_ioctl(adp, FBIO_SETWINORG, data); 442 443 case FBIO_GETWINORG: /* get frame buffer window origin */ 444 if (scp != scp->sc->cur_scp) 445 return ENODEV; /* XXX */ 446 return fb_ioctl(adp, FBIO_GETWINORG, data); 447 448 case FBIO_GETDISPSTART: 449 case FBIO_SETDISPSTART: 450 case FBIO_GETLINEWIDTH: 451 case FBIO_SETLINEWIDTH: 452 if (scp != scp->sc->cur_scp) 453 return ENODEV; /* XXX */ 454 return fb_ioctl(adp, cmd, data); 455 456 case FBIO_GETPALETTE: 457 case FBIO_SETPALETTE: 458 case FBIOPUTCMAP: 459 case FBIOGETCMAP: 460 case FBIOGTYPE: 461 case FBIOGATTR: 462 case FBIOSVIDEO: 463 case FBIOGVIDEO: 464 case FBIOSCURSOR: 465 case FBIOGCURSOR: 466 case FBIOSCURPOS: 467 case FBIOGCURPOS: 468 case FBIOGCURMAX: 469 if (scp != scp->sc->cur_scp) 470 return ENODEV; /* XXX */ 471 return fb_ioctl(adp, cmd, data); 472 473 #ifndef SC_NO_MODE_CHANGE 474 /* generic text modes */ 475 case SW_TEXT_80x25: case SW_TEXT_80x30: 476 case SW_TEXT_80x43: case SW_TEXT_80x50: 477 case SW_TEXT_80x60: 478 /* FALL THROUGH */ 479 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 s = spltty(); 556 if ((error = sc_clean_up(scp))) { 557 splx(s); 558 return error; 559 } 560 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 561 splx(s); 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 s = spltty(); 577 if ((error = sc_clean_up(scp))) { 578 splx(s); 579 return error; 580 } 581 scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); 582 splx(s); 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 s = spltty(); 596 if ((error = sc_clean_up(scp))) { 597 splx(s); 598 return error; 599 } 600 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 601 splx(s); 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