wsemul_sun.c revision 1.4
1/* $NetBSD: wsemul_sun.c,v 1.4 1998/05/19 18:47:13 drochner Exp $ */ 2 3/* 4 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Christopher G. Demetriou 17 * for the NetBSD Project. 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33static const char _copyright[] __attribute__ ((unused)) = 34 "Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved."; 35static const char _rcsid[] __attribute__ ((unused)) = 36 "$NetBSD: wsemul_sun.c,v 1.4 1998/05/19 18:47:13 drochner Exp $"; 37 38/* XXX DESCRIPTION/SOURCE OF INFORMATION */ 39 40#include <sys/param.h> 41#include <sys/systm.h> 42#include <sys/time.h> 43#include <sys/malloc.h> 44#include <sys/fcntl.h> 45 46#include <dev/wscons/wsconsio.h> 47#include <dev/wscons/wsdisplayvar.h> 48#include <dev/wscons/wsemulvar.h> 49#include <dev/wscons/ascii.h> 50 51#include "opt_wskernattr.h" 52 53void *wsemul_sun_cnattach __P((const struct wsscreen_descr *, void *, 54 int, int, long)); 55void *wsemul_sun_attach __P((int console, const struct wsscreen_descr *, 56 void *, int, int, void *, long)); 57void wsemul_sun_output __P((void *cookie, const u_char *data, u_int count, 58 int)); 59void wsemul_sun_detach __P((void *cookie, u_int *crowp, u_int *ccolp)); 60 61const struct wsemul_ops wsemul_sun_ops = { 62 "sun", 63 wsemul_sun_cnattach, 64 wsemul_sun_attach, 65 wsemul_sun_output, 66 wsemul_sun_detach, 67}; 68 69#define SUN_EMUL_STATE_NORMAL 0 /* normal processing */ 70#define SUN_EMUL_STATE_HAVEESC 1 /* seen start of ctl seq */ 71#define SUN_EMUL_STATE_CONTROL 2 /* processing ctl seq */ 72 73#define SUN_EMUL_NARGS 2 /* max # of args to a command */ 74 75struct wsemul_sun_emuldata { 76 const struct wsdisplay_emulops *emulops; 77 void *emulcookie; 78 void *cbcookie; 79 int scrcapabilities; 80 u_int nrows, ncols, crow, ccol; 81 82 u_int state; /* processing state */ 83 u_int args[SUN_EMUL_NARGS]; /* command args, if CONTROL */ 84 u_int scrolldist; /* distance to scroll */ 85 long defattr; /* default attribute (rendition) */ 86 long bowattr; /* attribute for reversed mode */ 87 int rendflags; 88#define REND_BOW 1 89#define REND_SO 2 90 long curattr; /* currently used attribute */ 91 long kernattr; /* attribute for kernel output */ 92#ifdef DIAGNOSTIC 93 int console; 94#endif 95}; 96 97static u_int wsemul_sun_output_normal __P((struct wsemul_sun_emuldata *, 98 u_char, int)); 99static u_int wsemul_sun_output_haveesc __P((struct wsemul_sun_emuldata *, 100 u_char)); 101static u_int wsemul_sun_output_control __P((struct wsemul_sun_emuldata *, 102 u_char)); 103static void wsemul_sun_control __P((struct wsemul_sun_emuldata *, u_char)); 104 105struct wsemul_sun_emuldata wsemul_sun_console_emuldata; 106 107/* some useful utility macros */ 108#define ARG(n) (edp->args[(n)]) 109#define NORMALIZE_ARG(n) (ARG(n) ? ARG(n) : 1) 110#define COLS_LEFT (edp->ncols - edp->ccol - 1) 111#define ROWS_LEFT (edp->nrows - edp->crow - 1) 112 113void * 114wsemul_sun_cnattach(type, cookie, ccol, crow, defattr) 115 const struct wsscreen_descr *type; 116 void *cookie; 117 int ccol, crow; 118 long defattr; 119{ 120 struct wsemul_sun_emuldata *edp; 121 int res; 122 123 edp = &wsemul_sun_console_emuldata; 124 125 edp->emulops = type->textops; 126 edp->emulcookie = cookie; 127 edp->scrcapabilities = type->capabilities; 128 edp->nrows = type->nrows; 129 edp->ncols = type->ncols; 130 edp->crow = crow; 131 edp->ccol = ccol; 132 edp->curattr = edp->defattr = defattr; 133#if defined(WS_KERNEL_FG) || defined(WS_KERNEL_BG) || \ 134 defined(WS_KERNEL_COLATTR) || defined(WS_KERNEL_MONOATTR) 135#ifndef WS_KERNEL_FG 136#define WS_KERNEL_FG WSCOL_WHITE 137#endif 138#ifndef WS_KERNEL_BG 139#define WS_KERNEL_BG WSCOL_BLACK 140#endif 141#ifndef WS_KERNEL_COLATTR 142#define WS_KERNEL_COLATTR 0 143#endif 144#ifndef WS_KERNEL_MONOATTR 145#define WS_KERNEL_MONOATTR 0 146#endif 147 if (type->capabilities & WSSCREEN_WSCOLORS) 148 res = (*edp->emulops->alloc_attr)(cookie, 149 WS_KERNEL_FG, WS_KERNEL_BG, 150 WS_KERNEL_COLATTR | WSATTR_WSCOLORS, 151 &edp->kernattr); 152 else 153 res = (*edp->emulops->alloc_attr)(cookie, 0, 0, 154 WS_KERNEL_MONOATTR, 155 &edp->kernattr); 156 if (res) 157#else 158 res = 0; /* XXX gcc */ 159#endif 160 edp->kernattr = defattr; 161 162 edp->cbcookie = NULL; 163 164 edp->state = SUN_EMUL_STATE_NORMAL; 165 edp->scrolldist = 1; 166#ifdef DIAGNOSTIC 167 edp->console = 1; 168#endif 169 return (edp); 170} 171 172void * 173wsemul_sun_attach(console, type, cookie, ccol, crow, cbcookie, defattr) 174 int console; 175 const struct wsscreen_descr *type; 176 void *cookie; 177 int ccol, crow; 178 void *cbcookie; 179 long defattr; 180{ 181 struct wsemul_sun_emuldata *edp; 182 183 if (console) { 184 edp = &wsemul_sun_console_emuldata; 185#ifdef DIAGNOSTIC 186 KASSERT(edp->console == 1); 187#endif 188 } else { 189 edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK); 190 191 edp->emulops = type->textops; 192 edp->emulcookie = cookie; 193 edp->scrcapabilities = type->capabilities; 194 edp->nrows = type->nrows; 195 edp->ncols = type->ncols; 196 edp->crow = crow; 197 edp->ccol = ccol; 198 edp->defattr = defattr; 199 200 edp->state = SUN_EMUL_STATE_NORMAL; 201 edp->scrolldist = 1; 202#ifdef DIAGNOSTIC 203 edp->console = 0; 204#endif 205 } 206 207 edp->cbcookie = cbcookie; 208 209 /* XXX This assumes that the default attribute is wob. */ 210 if ((!(edp->scrcapabilities & WSSCREEN_WSCOLORS) || 211 (*edp->emulops->alloc_attr)(edp->emulcookie, 212 WSCOL_BLACK, WSCOL_WHITE, 213 WSATTR_WSCOLORS, 214 &edp->bowattr)) && 215 (!(edp->scrcapabilities & WSSCREEN_REVERSE) || 216 (*edp->emulops->alloc_attr)(edp->emulcookie, 0, 0, 217 WSATTR_REVERSE, 218 &edp->bowattr))) 219 edp->bowattr = edp->defattr; 220 221 edp->curattr = edp->defattr; 222 edp->rendflags = 0; 223 224 return (edp); 225} 226 227static inline u_int 228wsemul_sun_output_normal(edp, c, kernel) 229 struct wsemul_sun_emuldata *edp; 230 u_char c; 231 int kernel; 232{ 233 u_int newstate = SUN_EMUL_STATE_NORMAL; 234 u_int n; 235 236 switch (c) { 237 case ASCII_BEL: /* "Bell (BEL)" */ 238 wsdisplay_emulbell(edp->cbcookie); 239 break; 240 241 case ASCII_BS: /* "Backspace (BS)" */ 242 if (edp->ccol > 0) 243 edp->ccol--; 244 break; 245 246 case ASCII_CR: /* "Return (CR)" */ 247 edp->ccol = 0; 248 break; 249 250 case ASCII_HT: /* "Tab (TAB)" */ 251 n = min(8 - (edp->ccol & 7), COLS_LEFT); 252 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 253 edp->ccol, n, 254 kernel ? edp->kernattr : edp->curattr); 255 edp->ccol += n; 256 break; 257 258 case ASCII_NP: /* "Form Feed (FF)" */ 259 (*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows, 260 kernel ? edp->kernattr : edp->curattr); 261 /* XXX possible in kernel output? */ 262 edp->ccol = 0; 263 edp->crow = 0; 264 break; 265 266 case ASCII_VT: /* "Reverse Line Feed" */ 267 if (edp->crow > 0) 268 edp->crow--; 269 break; 270 271 case ASCII_ESC: /* "Escape (ESC)" */ 272#ifdef DIAGNOSTIC 273 if (kernel) 274 panic("ESC in kernel output"); 275#endif 276 if (edp->state == SUN_EMUL_STATE_NORMAL) { 277 newstate = SUN_EMUL_STATE_HAVEESC; 278 break; 279 } 280 /* special case: fall through, we're printing one out */ 281 /* FALLTHRU */ 282 283 default: /* normal character */ 284 (*edp->emulops->putstr)(edp->emulcookie, edp->crow, edp->ccol, 285 &c, 1, kernel ? edp->kernattr : edp->curattr); 286 edp->ccol++; 287 288 /* if cur col is still on cur line, done. */ 289 if (edp->ccol < edp->ncols) 290 break; 291 292 /* wrap the column around. */ 293 edp->ccol = 0; 294 295 /* FALLTHRU */ 296 297 case ASCII_LF: /* "Line Feed (LF)" */ 298 /* if the cur line isn't the last, incr and leave. */ 299 if (edp->crow < edp->nrows - 1) { 300 edp->crow++; 301 break; 302 } 303 304 /* 305 * if we're in wrap-around mode, go to the first 306 * line and clear it. 307 */ 308 if (edp->scrolldist == 0) { 309 edp->crow = 0; 310 (*edp->emulops->eraserows)(edp->emulcookie, 0, 1, 311 edp->curattr); 312 break; 313 } 314 315 /* scroll by the scrolling distance. */ 316 (*edp->emulops->copyrows)(edp->emulcookie, edp->scrolldist, 0, 317 edp->nrows - edp->scrolldist); 318 (*edp->emulops->eraserows)(edp->emulcookie, 319 edp->nrows - edp->scrolldist, edp->scrolldist, 320 edp->curattr); 321 edp->crow -= edp->scrolldist - 1; 322 break; 323 } 324 325 return (newstate); 326} 327 328static inline u_int 329wsemul_sun_output_haveesc(edp, c) 330 struct wsemul_sun_emuldata *edp; 331 u_char c; 332{ 333 u_int newstate; 334 335 switch (c) { 336 case '[': /* continuation of multi-char sequence */ 337 bzero(edp->args, sizeof (edp->args)); 338 newstate = SUN_EMUL_STATE_CONTROL; 339 break; 340 341 default: 342 /* spit out the escape char (???), then the new character */ 343 wsemul_sun_output_normal(edp, ASCII_ESC, 0); /* ??? */ 344 newstate = wsemul_sun_output_normal(edp, c, 0); 345 break; 346 } 347 348 return (newstate); 349} 350 351static inline void 352wsemul_sun_control(edp, c) 353 struct wsemul_sun_emuldata *edp; 354 u_char c; 355{ 356 u_int n, src, dst; 357 358 switch (c) { 359 case '@': /* "Insert Character (ICH)" */ 360 n = min(NORMALIZE_ARG(0), COLS_LEFT + 1); 361 src = edp->ccol; 362 dst = edp->ccol + n; 363 if (dst < edp->ncols) { 364 (*edp->emulops->copycols)(edp->emulcookie, edp->crow, 365 src, dst, edp->ncols - dst); 366 } 367 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 368 src, dst - src, edp->curattr); 369 break; 370 371 case 'E': /* "Cursor Next Line (CNL)" */ 372 edp->ccol = 0; 373 /* FALLTHRU */ 374 case 'A': /* "Cursor Up (CUU)" */ 375 edp->crow -= min(NORMALIZE_ARG(0), edp->crow); 376 break; 377 378 case 'B': /* "Cursor Down (CUD)" */ 379 edp->crow += min(NORMALIZE_ARG(0), ROWS_LEFT); 380 break; 381 382 case 'C': /* "Cursor Forward (CUF)" */ 383 edp->ccol += min(NORMALIZE_ARG(0), COLS_LEFT); 384 break; 385 386 case 'D': /* "Cursor Backward (CUB)" */ 387 edp->ccol -= min(NORMALIZE_ARG(0), edp->ccol); 388 break; 389 390 case 'f': /* "Horizontal And Vertical Position (HVP)" */ 391 case 'H': /* "Cursor Position (CUP)" */ 392 edp->crow = min(NORMALIZE_ARG(1), edp->nrows) - 1; 393 edp->ccol = min(NORMALIZE_ARG(0), edp->ncols) - 1; 394 break; 395 396 case 'J': /* "Erase in Display (ED)" */ 397 if (ROWS_LEFT > 0) { 398 (*edp->emulops->eraserows)(edp->emulcookie, 399 edp->crow + 1, ROWS_LEFT, edp->curattr); 400 } 401 /* FALLTHRU */ 402 case 'K': /* "Erase in Line (EL)" */ 403 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 404 edp->ccol, COLS_LEFT + 1, edp->curattr); 405 break; 406 407 case 'L': /* "Insert Line (IL)" */ 408 n = min(NORMALIZE_ARG(0), ROWS_LEFT + 1); 409 src = edp->crow; 410 dst = edp->crow + n; 411 if (dst < edp->nrows) { 412 (*edp->emulops->copyrows)(edp->emulcookie, 413 src, dst, edp->nrows - dst); 414 } 415 (*edp->emulops->eraserows)(edp->emulcookie, 416 src, dst - src, edp->curattr); 417 break; 418 419 case 'M': /* "Delete Line (DL)" */ 420 n = min(NORMALIZE_ARG(0), ROWS_LEFT + 1); 421 src = edp->crow + n; 422 dst = edp->crow; 423 if (src < edp->nrows) { 424 (*edp->emulops->copyrows)(edp->emulcookie, 425 src, dst, edp->nrows - src); 426 } 427 (*edp->emulops->eraserows)(edp->emulcookie, 428 dst + edp->nrows - src, src - dst, edp->curattr); 429 break; 430 431 case 'P': /* "Delete Character (DCH)" */ 432 n = min(NORMALIZE_ARG(0), COLS_LEFT + 1); 433 src = edp->ccol + n; 434 dst = edp->ccol; 435 if (src < edp->ncols) { 436 (*edp->emulops->copycols)(edp->emulcookie, edp->crow, 437 src, dst, edp->ncols - src); 438 } 439 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 440 dst + edp->ncols - src, src - dst, edp->curattr); 441 break; 442 443 case 'm': /* "Select Graphic Rendition (SGR)" */ 444 if (ARG(0)) 445 edp->rendflags |= REND_SO; 446 else 447 edp->rendflags &= ~REND_SO; 448 goto setattr; 449 450 case 'p': /* "Black On White (SUNBOW)" */ 451 edp->rendflags |= REND_BOW; 452 goto setattr; 453 454 case 'q': /* "White On Black (SUNWOB)" */ 455 edp->rendflags &= ~REND_BOW; 456 goto setattr; 457 458 case 'r': /* "Set Scrolling (SUNSCRL)" */ 459 edp->scrolldist = min(ARG(0), edp->nrows); 460 break; 461 462 case 's': /* "Reset Terminal Emulator (SUNRESET)" */ 463 edp->scrolldist = 1; 464 edp->rendflags = 0; 465setattr: 466 if (((edp->rendflags & REND_BOW) != 0) ^ 467 ((edp->rendflags & REND_SO) != 0)) 468 edp->curattr = edp->bowattr; 469 else 470 edp->curattr = edp->defattr; 471 break; 472 } 473} 474 475static inline u_int 476wsemul_sun_output_control(edp, c) 477 struct wsemul_sun_emuldata *edp; 478 u_char c; 479{ 480 u_int newstate = SUN_EMUL_STATE_CONTROL; 481 u_int i; 482 483 switch (c) { 484 case '0': case '1': case '2': case '3': case '4': /* argument digit */ 485 case '5': case '6': case '7': case '8': case '9': 486 edp->args[0] = (edp->args[0] * 10) + (c - '0'); 487 break; 488 489 case ';': /* argument terminator */ 490 for (i = 1; i < SUN_EMUL_NARGS; i++) 491 edp->args[i] = edp->args[i - 1]; 492 edp->args[0] = 0; 493 break; 494 495 default: /* end of escape sequence */ 496 wsemul_sun_control(edp, c); 497 newstate = SUN_EMUL_STATE_NORMAL; 498 break; 499 } 500 return (newstate); 501} 502 503void 504wsemul_sun_output(cookie, data, count, kernel) 505 void *cookie; 506 const u_char *data; 507 u_int count; 508 int kernel; 509{ 510 struct wsemul_sun_emuldata *edp = cookie; 511 u_int newstate; 512 513#ifdef DIAGNOSTIC 514 if (kernel && !edp->console) 515 panic("wsemul_sun_output: kernel output, not console"); 516#endif 517 518 /* XXX */ 519 (*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow, edp->ccol); 520 for (; count > 0; data++, count--) { 521 if (kernel) { 522 wsemul_sun_output_normal(edp, *data, 1); 523 continue; 524 } 525 switch (edp->state) { 526 case SUN_EMUL_STATE_NORMAL: 527 /* XXX SCAN INPUT FOR NEWLINES, DO PRESCROLLING */ 528 newstate = wsemul_sun_output_normal(edp, *data, 0); 529 break; 530 case SUN_EMUL_STATE_HAVEESC: 531 newstate = wsemul_sun_output_haveesc(edp, *data); 532 break; 533 case SUN_EMUL_STATE_CONTROL: 534 newstate = wsemul_sun_output_control(edp, *data); 535 break; 536 default: 537#ifdef DIAGNOSTIC 538 panic("wsemul_sun: invalid state %d\n", edp->state); 539#endif 540 /* try to recover, if things get screwed up... */ 541 newstate = wsemul_sun_output_normal(edp, *data, 0); 542 break; 543 } 544 edp->state = newstate; 545 } 546 /* XXX */ 547 (*edp->emulops->cursor)(edp->emulcookie, 1, edp->crow, edp->ccol); 548} 549 550void 551wsemul_sun_detach(cookie, crowp, ccolp) 552 void *cookie; 553 u_int *crowp, *ccolp; 554{ 555 struct wsemul_sun_emuldata *edp = cookie; 556 557 *crowp = edp->crow; 558 *ccolp = edp->ccol; 559 if (edp != &wsemul_sun_console_emuldata) 560 free(edp, M_DEVBUF); 561} 562