|
|||
Prex Home / Browse Source - Prex Version: 0.9.0 |
|||
root/bsp/drv/dev/base/wscons.c/* [<][>][^][v][top][bottom][index][help] */DEFINITIONSThis source file includes following definitions.
1 /*- 2 * Copyright (c) 2005-2009, Kohsuke Ohtani 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the author nor the names of any co-contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * wscons.c - "Workstation console" multiplexor driver. 32 */ 33 34 #include <driver.h> 35 #include <cons.h> 36 #include <tty.h> 37 #include <wscons.h> 38 39 /* #define DEBUG_WSCONS 1 */ 40 41 #ifdef DEBUG_WSCONS 42 #define DPRINTF(a) printf a 43 #else 44 #define DPRINTF(a) 45 #endif 46 47 struct esc_state { 48 int index; 49 int arg1; 50 int arg2; 51 int argc; 52 int saved_col; 53 int saved_row; 54 }; 55 56 struct wscons_softc { 57 device_t dev; /* our device */ 58 struct tty tty; /* associated tty */ 59 int row; /* current row */ 60 int col; /* current col */ 61 int nrows; /* number of rows */ 62 int ncols; /* number of cols */ 63 int attr; /* current attribute */ 64 struct esc_state esc; /* escape state */ 65 struct wscons_video_ops *vid_ops; /* video operations */ 66 struct wscons_kbd_ops *kbd_ops; /* keyboard operations */ 67 void *vid_aux; /* video private data */ 68 void *kbd_aux; /* keyboard private data */ 69 }; 70 71 static int wscons_init(struct driver *); 72 static int wscons_read(device_t, char *, size_t *, int); 73 static int wscons_write(device_t, char *, size_t *, int); 74 static int wscons_ioctl(device_t, u_long, void *); 75 76 static int wscons_cngetc(device_t); 77 static void wscons_cnputc(device_t, int); 78 static void wscons_cnpollc(device_t, int); 79 80 81 static struct devops wscons_devops = { 82 /* open */ no_open, 83 /* close */ no_close, 84 /* read */ wscons_read, 85 /* write */ wscons_write, 86 /* ioctl */ wscons_ioctl, 87 /* devctl */ no_devctl, 88 }; 89 90 struct driver wscons_driver = { 91 /* name */ "wscons", 92 /* devops */ &wscons_devops, 93 /* devsz */ sizeof(struct wscons_softc), 94 /* flags */ 0, 95 /* probe */ NULL, 96 /* init */ wscons_init, 97 /* unload */ NULL, 98 }; 99 100 static struct consdev wsconsdev = { 101 /* dev */ NODEV, 102 /* devops */ &wscons_devops, 103 /* cngetc */ wscons_cngetc, 104 /* cnputc */ wscons_cnputc, 105 /* cnpollc */ wscons_cnpollc, 106 }; 107 108 static const u_short ansi_colors[] = {0, 4, 2, 6, 1, 5, 3, 7}; 109 110 /* 111 * Pointer to the wscons state. There can be only one instance. 112 */ 113 static struct wscons_softc *wscons_softc; 114 115 116 static int 117 wscons_read(device_t dev, char *buf, size_t *nbyte, int blkno) 118 { 119 struct tty *tty = &wscons_softc->tty; 120 121 return tty_read(tty, buf, nbyte); 122 } 123 124 static int 125 wscons_write(device_t dev, char *buf, size_t *nbyte, int blkno) 126 { 127 struct tty *tty = &wscons_softc->tty; 128 129 return tty_write(tty, buf, nbyte); 130 } 131 132 static int 133 wscons_ioctl(device_t dev, u_long cmd, void *arg) 134 { 135 struct tty *tty = &wscons_softc->tty; 136 137 return tty_ioctl(tty, cmd, arg); 138 } 139 140 static void 141 wscons_move_cursor(struct wscons_softc *sc) 142 { 143 struct wscons_video_ops *vops = sc->vid_ops; 144 145 vops->cursor(sc->vid_aux, sc->row, sc->col); 146 } 147 148 static void 149 wscons_set_attr(struct wscons_softc *sc) 150 { 151 struct wscons_video_ops *vops = sc->vid_ops; 152 153 vops->set_attr(sc->vid_aux, sc->attr); 154 } 155 156 static void 157 wscons_clear(struct wscons_softc *sc) 158 { 159 struct wscons_video_ops *vops = sc->vid_ops; 160 161 vops->eraserows(sc->vid_aux, 0, sc->nrows); 162 sc->col = 0; 163 sc->row = 0; 164 wscons_move_cursor(sc); 165 } 166 167 static void 168 wscons_scrollup(struct wscons_softc *sc) 169 { 170 struct wscons_video_ops *vops = sc->vid_ops; 171 172 vops->copyrows(sc->vid_aux, 1, 0, sc->nrows - 1); 173 vops->eraserows(sc->vid_aux, sc->nrows - 1, 1); 174 } 175 176 static void 177 wscons_newline(struct wscons_softc *sc) 178 { 179 180 sc->col = 0; 181 sc->row++; 182 if (sc->row >= sc->nrows) { 183 sc->row = sc->nrows - 1; 184 wscons_scrollup(sc); 185 } 186 } 187 188 /* 189 * Check for escape code sequence. 190 * Rreturn true if escape 191 * 192 * <Support list> 193 * ESC[#;#H or : moves cursor to line #, column # 194 * ESC[#;#f 195 * ESC[#A : moves cursor up # lines 196 * ESC[#B : moves cursor down # lines 197 * ESC[#C : moves cursor right # spaces 198 * ESC[#D : moves cursor left # spaces 199 * ESC[#;#R : reports current cursor line & column 200 * ESC[s : save cursor position for recall later 201 * ESC[u : return to saved cursor position 202 * ESC[2J : clear screen and home cursor 203 * ESC[K : clear to end of line 204 * ESC[#m : attribute (0=attribure off, 4=underline, 5=blink) 205 */ 206 static int 207 wscons_check_escape(struct wscons_softc *sc, char c) 208 { 209 struct esc_state *esc = &sc->esc; 210 int move = 0; 211 int val; 212 u_short color; 213 214 if (c == 033) { 215 esc->index = 1; 216 esc->argc = 0; 217 return 1; 218 } 219 if (esc->index == 0) 220 return 0; 221 222 if (c >= '0' && c <= '9') { 223 val = c - '0'; 224 switch (esc->argc) { 225 case 0: 226 esc->arg1 = val; 227 esc->index++; 228 break; 229 case 1: 230 esc->arg1 = esc->arg1 * 10 + val; 231 break; 232 case 2: 233 esc->arg2 = val; 234 esc->index++; 235 break; 236 case 3: 237 esc->arg2 = esc->arg2 * 10 + val; 238 break; 239 default: 240 goto reset; 241 } 242 esc->argc++; 243 return 1; 244 } 245 246 esc->index++; 247 248 switch (esc->index) { 249 case 2: 250 if (c != '[') 251 goto reset; 252 return 1; 253 case 3: 254 switch (c) { 255 case 's': /* Save cursor position */ 256 esc->saved_col = sc->col; 257 esc->saved_row = sc->row; 258 printf("TTY: save %d %d\n", sc->col, sc->row); 259 break; 260 case 'u': /* Return to saved cursor position */ 261 sc->col = esc->saved_col; 262 sc->row = esc->saved_row; 263 printf("TTY: restore %d %d\n", sc->col, sc->row); 264 wscons_move_cursor(sc); 265 break; 266 case 'K': /* Clear to end of line */ 267 break; 268 } 269 goto reset; 270 case 4: 271 switch (c) { 272 case 'A': /* Move cursor up # lines */ 273 sc->row -= esc->arg1; 274 if (sc->row < 0) 275 sc->row = 0; 276 move = 1; 277 break; 278 case 'B': /* Move cursor down # lines */ 279 sc->row += esc->arg1; 280 if (sc->row >= sc->nrows) 281 sc->row = sc->nrows - 1; 282 move = 1; 283 break; 284 case 'C': /* Move cursor forward # spaces */ 285 sc->col += esc->arg1; 286 if (sc->col >= sc->ncols) 287 sc->col = sc->ncols - 1; 288 move = 1; 289 break; 290 case 'D': /* Move cursor back # spaces */ 291 sc->col -= esc->arg1; 292 if (sc->col < 0) 293 sc->col = 0; 294 move = 1; 295 break; 296 case ';': 297 if (esc->argc == 1) 298 esc->argc = 2; 299 return 1; 300 case 'J': 301 if (esc->arg1 == 2) /* Clear screen */ 302 wscons_clear(sc); 303 break; 304 case 'm': /* Change attribute */ 305 switch (esc->arg1) { 306 case 0: /* reset */ 307 sc->attr = 0x0F; 308 break; 309 case 1: /* bold */ 310 sc->attr = 0x0F; 311 break; 312 case 4: /* under line */ 313 break; 314 case 5: /* blink */ 315 sc->attr |= 0x80; 316 break; 317 case 30: case 31: case 32: case 33: 318 case 34: case 35: case 36: case 37: 319 color = ansi_colors[esc->arg1 - 30]; 320 sc->attr = (sc->attr & 0xf0) | color; 321 break; 322 case 40: case 41: case 42: case 43: 323 case 44: case 45: case 46: case 47: 324 color = ansi_colors[esc->arg1 - 40]; 325 sc->attr = (sc->attr & 0x0f) | (color << 4); 326 break; 327 } 328 wscons_set_attr(sc); 329 break; 330 331 } 332 if (move) 333 wscons_move_cursor(sc); 334 goto reset; 335 case 6: 336 switch (c) { 337 case 'H': /* Cursor position */ 338 case 'f': 339 sc->row = esc->arg1; 340 sc->col = esc->arg2; 341 if (sc->row >= sc->nrows) 342 sc->row = sc->nrows - 1; 343 if (sc->col >= sc->ncols) 344 sc->col = sc->ncols - 1; 345 wscons_move_cursor(sc); 346 break; 347 case 'R': 348 /* XXX */ 349 break; 350 } 351 goto reset; 352 default: 353 goto reset; 354 } 355 /* NOTREACHED */ 356 reset: 357 esc->index = 0; 358 esc->argc = 0; 359 return 1; 360 } 361 362 static void 363 wscons_putc(int c) 364 { 365 struct wscons_softc *sc = wscons_softc; 366 struct wscons_video_ops *vops = sc->vid_ops; 367 368 if (wscons_check_escape(sc, c)) 369 return; 370 371 switch (c) { 372 case '\n': 373 wscons_newline(sc); 374 return; 375 case '\r': 376 sc->col = 0; 377 return; 378 case '\b': 379 if (sc->col == 0) 380 return; 381 sc->col--; 382 return; 383 } 384 385 vops->putc(sc->vid_aux, sc->row, sc->col, c); 386 387 sc->col++; 388 if (sc->col >= sc->ncols) { 389 sc->col = 0; 390 sc->row++; 391 if (sc->row >= sc->nrows) { 392 sc->row = sc->nrows - 1; 393 wscons_scrollup(sc); 394 } 395 } 396 } 397 398 /* 399 * Start output operation. 400 */ 401 static void 402 wscons_start(struct tty *tp) 403 { 404 struct wscons_softc *sc = wscons_softc; 405 int c; 406 407 while ((c = tty_getc(&tp->t_outq)) >= 0) 408 wscons_putc(c); 409 410 wscons_move_cursor(sc); 411 tty_done(tp); 412 } 413 414 static int 415 wscons_cngetc(device_t dev) 416 { 417 struct wscons_softc *sc = wscons_softc; 418 struct wscons_kbd_ops *kops = sc->kbd_ops; 419 420 return kops->getc(sc->kbd_aux); 421 } 422 423 static void 424 wscons_cnputc(device_t dev, int c) 425 { 426 struct wscons_softc *sc = wscons_softc; 427 428 wscons_putc(c); 429 wscons_move_cursor(sc); 430 } 431 432 static void 433 wscons_cnpollc(device_t dev, int on) 434 { 435 struct wscons_softc *sc = wscons_softc; 436 struct wscons_kbd_ops *kops = sc->kbd_ops; 437 438 kops->set_poll(sc->kbd_aux, on); 439 } 440 441 void 442 wscons_kbd_input(int c) 443 { 444 struct wscons_softc *sc = wscons_softc; 445 446 tty_input(c, &sc->tty); 447 } 448 449 void 450 wscons_attach_video(struct wscons_video_ops *ops, void *aux) 451 { 452 struct wscons_softc *sc = wscons_softc; 453 int diag = 0; 454 455 sc->vid_ops = ops; 456 sc->vid_aux = aux; 457 ops->get_cursor(aux, &sc->col, &sc->row); 458 459 #ifdef CONFIG_DIAG_SCREEN 460 diag = 1; 461 #endif 462 wsconsdev.dev = sc->dev; 463 cons_attach(&wsconsdev, diag); 464 } 465 466 void 467 wscons_attach_kbd(struct wscons_kbd_ops *ops, void *aux) 468 { 469 struct wscons_softc *sc = wscons_softc; 470 471 sc->kbd_ops = ops; 472 sc->kbd_aux = aux; 473 } 474 475 static int 476 wscons_init(struct driver *self) 477 { 478 struct bootinfo *bi; 479 struct wscons_softc *sc; 480 device_t dev; 481 482 dev = device_create(self, "tty", D_CHR|D_TTY); 483 484 sc = device_private(dev); 485 sc->dev = dev; 486 sc->esc.index = 0; 487 sc->attr = 0x0f; 488 wscons_softc = sc; 489 490 tty_attach(&sc->tty); 491 sc->tty.t_dev = dev; 492 sc->tty.t_oproc = wscons_start; 493 494 machine_bootinfo(&bi); 495 sc->nrows = bi->video.text_y; 496 sc->ncols = bi->video.text_x; 497 return 0; 498 } /* [<][>][^][v][top][bottom][index][help] */ | |||
Copyright© 2005-2009 Kohsuke Ohtani |