Fork me on GitHub

root/drivers/char/console.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. is_vconsole
  2. adjust
  3. cr
  4. lf
  5. ri
  6. csi_J
  7. csi_K
  8. csi_X
  9. csi_L
  10. csi_M
  11. csi_P
  12. csi_at
  13. default_color_attr
  14. csi_m
  15. init_vt
  16. insert_seq
  17. vcbuf_scroll_up
  18. vcbuf_refresh
  19. echo_char
  20. vconsole_reset
  21. vconsole_write
  22. vconsole_select
  23. vconsole_select_final
  24. unblank_screen
  25. vconsole_start
  26. vconsole_stop
  27. vconsole_beep
  28. vconsole_deltab
  29. console_flush_log_buf
  30. console_init

   1 /*
   2  * fiwix/drivers/char/console.c
   3  *
   4  * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/asm.h>
   9 #include <fiwix/kernel.h>
  10 #include <fiwix/ctype.h>
  11 #include <fiwix/console.h>
  12 #include <fiwix/devices.h>
  13 #include <fiwix/tty.h>
  14 #include <fiwix/keyboard.h>
  15 #include <fiwix/sleep.h>
  16 #include <fiwix/pit.h>
  17 #include <fiwix/timer.h>
  18 #include <fiwix/process.h>
  19 #include <fiwix/mm.h>
  20 #include <fiwix/sched.h>
  21 #include <fiwix/kd.h>
  22 #include <fiwix/stdio.h>
  23 #include <fiwix/string.h>
  24 #include <fiwix/fbcon.h>
  25 
  26 #define CSI_J_CUR2END   0       /* clear from cursor to end of screen */
  27 #define CSI_J_STA2CUR   1       /* clear from start of screen to cursor */
  28 #define CSI_J_SCREEN    2       /* clear entire screen */
  29 
  30 #define CSI_K_CUR2END   0       /* clear from cursor to end of line */
  31 #define CSI_K_STA2CUR   1       /* clear from start of line to cursor */
  32 #define CSI_K_LINE      2       /* clear entire line */
  33 
  34 #define CSE             vc->esc = 0     /* Code Set End */
  35 
  36 /* VT100 ID string generated by <ESC>Z or <ESC>[c */
  37 #define VT100ID         "\033[?1;2c"
  38 
  39 /* VT100 report status generated by <ESC>[5n */
  40 #define DEVICE_OK       "\033[0n"
  41 #define DEVICE_NOT_OK   "\033[3n"
  42 
  43 #define SCREEN_SIZE     (video.columns * video.lines)
  44 #define VC_BUF_LINES    (video.lines * SCREENS_LOG)
  45 
  46 
  47 short int current_cons;
  48 
  49 struct video_parms video;
  50 struct vconsole vc[NR_VCONSOLES + 1];
  51 
  52 static struct fs_operations tty_driver_fsop = {
  53         0,
  54         0,
  55 
  56         tty_open,
  57         tty_close,
  58         tty_read,
  59         tty_write,
  60         tty_ioctl,
  61         tty_lseek,
  62         NULL,                   /* readdir */
  63         NULL,                   /* mmap */
  64         tty_select,
  65 
  66         NULL,                   /* readlink */
  67         NULL,                   /* followlink */
  68         NULL,                   /* bmap */
  69         NULL,                   /* lookup */
  70         NULL,                   /* rmdir */
  71         NULL,                   /* link */
  72         NULL,                   /* unlink */
  73         NULL,                   /* symlink */
  74         NULL,                   /* mkdir */
  75         NULL,                   /* mknod */
  76         NULL,                   /* truncate */
  77         NULL,                   /* create */
  78         NULL,                   /* rename */
  79 
  80         NULL,                   /* read_block */
  81         NULL,                   /* write_block */
  82 
  83         NULL,                   /* read_inode */
  84         NULL,                   /* write_inode */
  85         NULL,                   /* ialloc */
  86         NULL,                   /* ifree */
  87         NULL,                   /* statfs */
  88         NULL,                   /* read_superblock */
  89         NULL,                   /* remount_fs */
  90         NULL,                   /* write_superblock */
  91         NULL                    /* release_superblock */
  92 };
  93 
  94 static struct device tty_device = {
  95         "vconsole",
  96         VCONSOLES_MAJOR,
  97         { 0, 0, 0, 0, 0, 0, 0, 0 },
  98         0,
  99         NULL,
 100         &tty_driver_fsop,
 101         NULL
 102 };
 103 
 104 static struct device console_device = {
 105         "console",
 106         SYSCON_MAJOR,
 107         { 0, 0, 0, 0, 0, 0, 0, 0 },
 108         0,
 109         NULL,
 110         &tty_driver_fsop,
 111         NULL
 112 };
 113 
 114 unsigned short int ansi_color_table[] = {
 115         COLOR_BLACK,
 116         COLOR_RED,
 117         COLOR_GREEN,
 118         COLOR_BROWN,
 119         COLOR_BLUE,
 120         COLOR_MAGENTA,
 121         COLOR_CYAN,
 122         COLOR_WHITE
 123 };
 124 
 125 static int is_vconsole(__dev_t dev)
 126 {
 127         if(MAJOR(dev) == VCONSOLES_MAJOR && MINOR(dev) <= NR_VCONSOLES) {
 128                 return 1;
 129         }
 130 
 131         return 0;
 132 }
 133 
 134 static void adjust(struct vconsole *vc, int x, int y)
 135 {
 136         if(x < 0) {
 137                 x = 0;
 138         }
 139         if(x >= vc->columns) {
 140                 x = vc->columns - 1;
 141         }
 142         if(y < 0) {
 143                 y = 0;
 144         }
 145         if(y >= vc->lines) {
 146                 y = vc->lines - 1;
 147         }
 148         vc->x = x;
 149         vc->y = y;
 150 }
 151 
 152 static void cr(struct vconsole *vc)
 153 {
 154         vc->x = 0;
 155 }
 156 
 157 static void lf(struct vconsole *vc)
 158 {
 159         if(vc->y == vc->lines) {
 160                 video.scroll_screen(vc, 0, SCROLL_UP);
 161         } else {
 162                 vc->y++;
 163         }
 164 }
 165 
 166 static void ri(struct vconsole *vc)
 167 {
 168         video.scroll_screen(vc, 0, SCROLL_DOWN);
 169 }
 170 
 171 static void csi_J(struct vconsole *vc, int mode)
 172 {
 173         int from, count;
 174 
 175         switch(mode) {
 176                 case CSI_J_CUR2END:     /* Erase Down <ESC>[J */
 177                         from = (vc->y * vc->columns) + vc->x;
 178                         count = vc->columns - vc->x;
 179                         video.write_screen(vc, from, count, vc->color_attr);
 180                         from = ((vc->y + 1) * vc->columns);
 181                         count = SCREEN_SIZE - from;
 182                         break;
 183                 case CSI_J_STA2CUR:     /* Erase Up <ESC>[1J */
 184                         from = vc->y * vc->columns;
 185                         count = vc->x + 1;
 186                         video.write_screen(vc, from, count, vc->color_attr);
 187                         from = 0;
 188                         count = vc->y * vc->columns;
 189                         break;
 190                 case CSI_J_SCREEN:      /* Erase Screen <ESC>[2J */
 191                         from = 0;
 192                         count = SCREEN_SIZE;
 193                         break;
 194                 default:
 195                         return;
 196         }
 197         video.write_screen(vc, from, count, vc->color_attr);
 198 }
 199 
 200 static void csi_K(struct vconsole *vc, int mode)
 201 {
 202         int from, count;
 203 
 204         switch(mode) {
 205                 case CSI_K_CUR2END:     /* Erase End of Line <ESC>[K */
 206                         from = (vc->y * vc->columns) + vc->x;
 207                         count = vc->columns - vc->x;
 208                         break;
 209                 case CSI_K_STA2CUR:     /* Erase Start of Line <ESC>[1K */
 210                         from = vc->y * vc->columns;
 211                         count = vc->x + 1;
 212                         break;
 213                 case CSI_K_LINE:        /* Erase Line <ESC>[2K */
 214                         from = vc->y * vc->columns;
 215                         count = vc->columns;
 216                         break;
 217                 default:
 218                         return;
 219         }
 220         video.write_screen(vc, from, count, vc->color_attr);
 221 }
 222 
 223 static void csi_X(struct vconsole *vc, int count)
 224 {
 225         int from;
 226 
 227         from = (vc->y * vc->columns) + vc->x;
 228         count = count > (vc->columns - vc->x) ? vc->columns - vc->x : count;
 229         video.write_screen(vc, from, count, vc->color_attr);
 230 }
 231 
 232 static void csi_L(struct vconsole *vc, int count)
 233 {
 234         if(count > (vc->lines - vc->top)) {
 235                 count = vc->lines - vc->top;
 236         }
 237         while(count--) {
 238                 video.scroll_screen(vc, vc->y, SCROLL_DOWN);
 239         }
 240 }
 241 
 242 static void csi_M(struct vconsole *vc, int count)
 243 {
 244         if(count > (vc->lines - vc->top)) {
 245                 count = vc->lines - vc->top;
 246         }
 247         while(count--) {
 248                 video.scroll_screen(vc, vc->y, SCROLL_UP);
 249         }
 250 }
 251 
 252 static void csi_P(struct vconsole *vc, int count)
 253 {
 254         if(count > vc->columns) {
 255                 count = vc->columns;
 256         }
 257         while(count--) {
 258                 video.delete_char(vc);
 259         }
 260 }
 261 
 262 static void csi_at(struct vconsole *vc, int count)
 263 {
 264         if(count > vc->columns) {
 265                 count = vc->columns;
 266         }
 267         while(count--) {
 268                 video.insert_char(vc);
 269         }
 270 }
 271 
 272 static void default_color_attr(struct vconsole *vc)
 273 {
 274         vc->color_attr = DEF_MODE;
 275         vc->bold = 0;
 276         vc->underline = 0;
 277         vc->blink = 0;
 278         vc->reverse = 0;
 279 }
 280 
 281 /* Select Graphic Rendition */
 282 static void csi_m(struct vconsole *vc)
 283 {
 284         int n;
 285 
 286         if(vc->reverse) {
 287                 vc->color_attr = ((vc->color_attr & 0x7000) >> 4) | ((vc->color_attr & 0x0700) << 4) | (vc->color_attr & 0x8800); 
 288         }
 289 
 290         for(n = 0; n < vc->nparms; n++) {
 291                 switch(vc->parms[n]) {
 292                         case SGR_DEFAULT:
 293                                 default_color_attr(vc);
 294                                 break;
 295                         case SGR_BOLD:
 296                                 vc->bold = 1;
 297                                 break;
 298                         case SGR_BLINK:
 299                                 vc->blink = 1;
 300                                 break;
 301                         case SGR_REVERSE:
 302                                 vc->reverse = 1;
 303                                 break;
 304                         /* normal intensity */
 305                         case 21:
 306                         case 22:
 307                                 vc->bold = 0;
 308                                 break;
 309                         case SGR_BLINK_OFF:
 310                                 vc->blink = 0;
 311                                 break;
 312                         case SGR_REVERSE_OFF:
 313                                 vc->reverse = 0;
 314                                 break;
 315                         case SGR_BLACK_FG:
 316                         case SGR_RED_FG:
 317                         case SGR_GREEN_FG:
 318                         case SGR_BROWN_FG:
 319                         case SGR_BLUE_FG:
 320                         case SGR_MAGENTA_FG:
 321                         case SGR_CYAN_FG:
 322                         case SGR_WHITE_FG:
 323                                 vc->color_attr = (vc->color_attr & 0xF8FF) | (ansi_color_table[vc->parms[n] - 30]);
 324                                 break;
 325                         case SGR_DEFAULT_FG_U_ON:
 326                         case SGR_DEFAULT_FG_U_OFF:
 327                                 /* not supported yet */
 328                                 break;
 329                         case SGR_BLACK_BG:
 330                         case SGR_RED_BG:
 331                         case SGR_GREEN_BG:
 332                         case SGR_BROWN_BG:
 333                         case SGR_BLUE_BG:
 334                         case SGR_MAGENTA_BG:
 335                         case SGR_CYAN_BG:
 336                         case SGR_WHITE_BG:
 337                                 vc->color_attr = (vc->color_attr & 0x8FFF) | ((ansi_color_table[vc->parms[n] - 40]) << 4);
 338                                 break;
 339                         case SGR_DEFAULT_BG:
 340                                 /* not supported yet */
 341                                 break;
 342                 }
 343         }
 344         if(vc->bold) {
 345                 vc->color_attr |= 0x0800;
 346         } else {
 347                 vc->color_attr &= ~0x0800;
 348         }
 349         if(vc->blink) {
 350                 vc->color_attr |= 0x8000;
 351         } else {
 352                 vc->color_attr &= ~0x8000;
 353         }
 354         if(vc->reverse) {
 355                 vc->color_attr = ((vc->color_attr & 0x7000) >> 4) | ((vc->color_attr & 0x0700) << 4) | (vc->color_attr & 0x8800); 
 356         }
 357 }
 358 
 359 static void init_vt(struct vconsole *vc)
 360 {
 361         vc->vt_mode.mode = VT_AUTO;
 362         vc->vt_mode.waitv = 0;
 363         vc->vt_mode.relsig = 0;
 364         vc->vt_mode.acqsig = 0;
 365         vc->vt_mode.frsig = 0;
 366         vc->vc_mode = KD_TEXT;
 367         vc->tty->pid = 0;
 368         vc->switchto_tty = -1;
 369 }
 370 
 371 static void insert_seq(struct tty *tty, char *buf, int count)
 372 {
 373         while(count--) {
 374                 tty_queue_putchar(tty, &tty->read_q, *(buf++));
 375         }
 376         tty->input(tty);
 377 }
 378 
 379 static void vcbuf_scroll_up(void)
 380 {
 381         memcpy_w(vcbuf, vcbuf + video.columns, (VC_BUF_SIZE - video.columns) * 2);
 382 }
 383 
 384 static void vcbuf_refresh(struct vconsole *vc)
 385 {
 386         short int *screen;
 387 
 388         screen = (short int *)vc->screen;
 389         memset_w(vcbuf, BLANK_MEM, VC_BUF_SIZE);
 390         memcpy_w(vcbuf, screen, SCREEN_SIZE);
 391 }
 392 
 393 static void echo_char(struct vconsole *vc, unsigned char *buf, unsigned int count)
 394 {
 395         unsigned char ch;
 396         unsigned long int flags;
 397 
 398         SAVE_FLAGS(flags); CLI();
 399         if(vc->flags & CONSOLE_HAS_FOCUS) {
 400                 if(video.buf_top) {
 401                         video.restore_screen(vc);
 402                         video.show_cursor(vc, ON);
 403                         video.buf_top = 0;
 404                 }
 405         }
 406 
 407         while(count--) {
 408                 ch = *buf++;
 409                 if(ch == NULL) {
 410                         continue;
 411 
 412                 } else if(ch == '\b') {
 413                         if(vc->x) {
 414                                 vc->x--;
 415                         }
 416 
 417                 } else if(ch == '\a') {
 418                         vconsole_beep();
 419 
 420                 } else if(ch == '\r') {
 421                         cr(vc);
 422 
 423                 } else if(ch == '\n') {
 424                         cr(vc);
 425                         vc->y++;
 426                         if(vc->flags & CONSOLE_HAS_FOCUS) {
 427                                 video.buf_y++;
 428                         }
 429 
 430                 } else if(ch == '\t') {
 431                         while(vc->x < (vc->columns - 1)) {
 432                                 if(vc->tty->tab_stop[++vc->x]) {
 433                                         break;
 434                                 }
 435                         }
 436 /*                      vc->x += TAB_SIZE - (vc->x % TAB_SIZE); */
 437                         vc->check_x = 1;
 438 
 439                 } else {
 440                         if((vc->x == vc->columns - 1) && vc->check_x) {
 441                                 vc->x = 0;
 442                                 vc->y++;
 443                                 if(vc->flags & CONSOLE_HAS_FOCUS) {
 444                                         video.buf_y++;
 445                                 }
 446                         }
 447                         if(vc->y >= vc->lines) {
 448                                 video.scroll_screen(vc, 0, SCROLL_UP);
 449                                 vc->y--;
 450                         }
 451                         video.put_char(vc, ch);
 452                         if(vc->x < vc->columns - 1) {
 453                                 vc->check_x = 0;
 454                                 vc->x++;
 455                         } else {
 456                                 vc->check_x = 1;
 457                         }
 458                 }
 459                 if(vc->y >= vc->lines) {
 460                         video.scroll_screen(vc, 0, SCROLL_UP);
 461                         vc->y--;
 462                 }
 463                 if(vc->flags & CONSOLE_HAS_FOCUS) {
 464                         if(video.buf_y >= VC_BUF_LINES) {
 465                                 vcbuf_scroll_up();
 466                                 video.buf_y--;
 467                         }
 468                 }
 469         }
 470         video.update_curpos(vc);
 471         RESTORE_FLAGS(flags);
 472 }
 473 
 474 void vconsole_reset(struct tty *tty)
 475 {
 476         int n;
 477         struct vconsole *vc;
 478 
 479         vc = (struct vconsole *)tty->driver_data;
 480 
 481         vc->top = 0;
 482         vc->lines = video.lines;
 483         vc->columns = video.columns;
 484         vc->check_x = 0;
 485         vc->led_status = 0;
 486         set_leds(vc->led_status);
 487         vc->scrlock = vc->numlock = vc->capslock = 0;
 488         vc->esc = vc->sbracket = vc->semicolon = vc->question = 0;
 489         vc->parmv1 = vc->parmv2 = 0;
 490         vc->nparms = 0;
 491         memset_b(vc->parms, 0, sizeof(vc->parms));
 492         default_color_attr(vc);
 493         vc->insert_mode = 0;
 494         vc->saved_x = vc->saved_y = 0;
 495 
 496         for(n = 0; n < MAX_TAB_COLS; n++) {
 497                 if(!(n % TAB_SIZE)) {
 498                         vc->tty->tab_stop[n] = 1;
 499                 } else {
 500                         vc->tty->tab_stop[n] = 0;
 501                 }
 502         }
 503 
 504         termios_reset(tty);
 505         vc->tty->winsize.ws_row = vc->lines - vc->top;
 506         vc->tty->winsize.ws_col = vc->columns;
 507         vc->tty->winsize.ws_xpixel = 0;
 508         vc->tty->winsize.ws_ypixel = 0;
 509         vc->tty->lnext = 0;
 510 
 511         init_vt(vc);
 512         vc->flags &= ~CONSOLE_BLANKED;
 513         video.update_curpos(vc);
 514 }
 515 
 516 void vconsole_write(struct tty *tty)
 517 {
 518         int n;
 519         unsigned char ch;
 520         int numeric;
 521         struct vconsole *vc;
 522 
 523         vc = (struct vconsole *)tty->driver_data;
 524 
 525         if(vc->flags & CONSOLE_HAS_FOCUS) {
 526                 if(video.buf_top) {
 527                         video.restore_screen(vc);
 528                         video.buf_top = 0;
 529                         video.show_cursor(vc, ON);
 530                         video.update_curpos(vc);
 531                 }
 532         }
 533 
 534         ch = numeric = 0;
 535 
 536         while(!vc->scrlock && tty->write_q.count > 0) {
 537                 ch = tty_queue_getchar(&tty->write_q);
 538 
 539                 if(vc->esc) {
 540                         if(vc->sbracket) {
 541                                 if(IS_NUMERIC(ch)) {
 542                                         numeric = 1;
 543                                         if(vc->semicolon) {
 544                                                 vc->parmv2 *= 10;
 545                                                 vc->parmv2 += ch - '0';
 546                                         } else {
 547                                                 vc->parmv1 *= 10;
 548                                                 vc->parmv1 += ch - '0';
 549                                         }
 550                                         vc->parms[vc->nparms] *= 10;
 551                                         vc->parms[vc->nparms] += ch - '0';
 552                                         continue;
 553                                 }
 554                                 switch(ch) {
 555                                         case ';':
 556                                                 vc->semicolon = 1;
 557                                                 vc->parmv2 = 0;
 558                                                 vc->nparms++;
 559                                                 continue;
 560                                         case '?':
 561                                                 vc->question = 1;
 562                                                 continue;
 563                                         case '@':       /* Insert Character(s) <ESC>[ n @ */
 564                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 565                                                 csi_at(vc, vc->parmv1);
 566                                                 CSE;
 567                                                 continue;
 568                                         case 'A':       /* Cursor Up <ESC>[ n A */
 569                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 570                                                 adjust(vc, vc->x, vc->y - vc->parmv1);
 571                                                 CSE;
 572                                                 continue;
 573                                         case 'B':       /* Cursor Down <ESC>[ n B */
 574                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 575                                                 adjust(vc, vc->x, vc->y + vc->parmv1);
 576                                                 CSE;
 577                                                 continue;
 578                                         case 'C':       /* Cursor Forward <ESC>[ n C */
 579                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 580                                                 adjust(vc, vc->x + vc->parmv1, vc->y);
 581                                                 CSE;
 582                                                 continue;
 583                                         case 'D':       /* Cursor Backward <ESC>[ n D */
 584                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 585                                                 adjust(vc, vc->x - vc->parmv1, vc->y);
 586                                                 CSE;
 587                                                 continue;
 588                                         case 'E':       /* Cursor Next Line(s) <ESC>[ n E */
 589                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 590                                                 adjust(vc, 0, vc->y + vc->parmv1);
 591                                                 CSE;
 592                                                 continue;
 593                                         case 'F':       /* Cursor Previous Line(s) <ESC>[ n F */
 594                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 595                                                 adjust(vc, 0, vc->y - vc->parmv1);
 596                                                 CSE;
 597                                                 continue;
 598                                         case 'G':       /* Cursor Horizontal Position <ESC>[ n G */
 599                                         case '`':
 600                                                 vc->parmv1 = vc->parmv1 ? vc->parmv1 - 1 : vc->parmv1;
 601                                                 adjust(vc, vc->parmv1, vc->y);
 602                                                 CSE;
 603                                                 continue;
 604                                         case 'H':       /* Cursor Home <ESC>[ ROW ; COLUMN H */
 605                                         case 'f':       /* Horizontal Vertical Position <ESC>[ ROW ; COLUMN f */
 606                                                 vc->parmv1 = vc->parmv1 ? vc->parmv1 - 1 : vc->parmv1;
 607                                                 vc->parmv2 = vc->parmv2 ? vc->parmv2 - 1 : vc->parmv2;
 608                                                 adjust(vc, vc->parmv2, vc->parmv1);
 609                                                 CSE;
 610                                                 continue;
 611                                         case 'I':       /* Cursor Forward Tabulation <ESC>[ n I */
 612                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 613                                                 while(vc->parmv1--){
 614                                                         while(vc->x < (vc->columns - 1)) {
 615                                                                 if(vc->tty->tab_stop[++vc->x]) {
 616                                                                         break;
 617                                                                 }
 618                                                         }
 619                                                 }
 620                                                 adjust(vc, vc->x, vc->y);
 621                                                 CSE;
 622                                                 continue;
 623                                         case 'J':       /* Erase (Down/Up/Screen) <ESC>[J */
 624                                                 csi_J(vc, vc->parmv1);
 625                                                 CSE;
 626                                                 continue;
 627                                         case 'K':       /* Erase (End of/Start of/) Line <ESC>[K */
 628                                                 csi_K(vc, vc->parmv1);
 629                                                 CSE;
 630                                                 continue;
 631                                         case 'L':       /* Insert Line(s) <ESC>[ n L */
 632                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 633                                                 csi_L(vc, vc->parmv1);
 634                                                 CSE;
 635                                                 continue;
 636                                         case 'M':       /* Delete Line(s) <ESC>[ n M */
 637                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 638                                                 csi_M(vc, vc->parmv1);
 639                                                 CSE;
 640                                                 continue;
 641                                         case 'P':       /* Delete Character(s) <ESC>[ n P */
 642                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 643                                                 csi_P(vc, vc->parmv1);
 644                                                 CSE;
 645                                                 continue;
 646                                         case 'S':       /* Scroll Up <ESC>[ n S */
 647                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 648                                                 while(vc->parmv1--) {
 649                                                         video.scroll_screen(vc, 0, SCROLL_UP);
 650                                                 }
 651                                                 CSE;
 652                                                 continue;
 653                                         case 'T':       /* Scroll Down <ESC>[ n T */
 654                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 655                                                 while(vc->parmv1--) {
 656                                                         video.scroll_screen(vc, 0, SCROLL_DOWN);
 657                                                 }
 658                                                 CSE;
 659                                                 continue;
 660                                         case 'X':       /* Erase Character(s) <ESC>[ n X */
 661                                                 vc->parmv1 = !vc->parmv1 ? 1 : vc->parmv1;
 662                                                 csi_X(vc, vc->parmv1);
 663                                                 CSE;
 664                                                 continue;
 665                                         case 'c':       /* Query Device Code <ESC>[c */
 666                                                 if(!numeric) {
 667                                                         insert_seq(tty, VT100ID, 7);
 668                                                 }
 669                                                 CSE;
 670                                                 continue;
 671                                         case 'd':       /* Cursor Vertical Position <ESC>[ n d */
 672                                                 vc->parmv1 = vc->parmv1 ? vc->parmv1 - 1 : vc->parmv1;
 673                                                 adjust(vc, vc->x, vc->parmv1);
 674                                                 CSE;
 675                                                 continue;
 676                                         case 'g':
 677                                                 switch(vc->parmv1) {
 678                                                         case 0: /* Clear Tab <ESC>[g */
 679                                                                 vc->tty->tab_stop[vc->x] = 0;
 680                                                                 break;
 681                                                         case 3: /* Clear All Tabs <ESC>[3g */
 682                                                         case 5: /* Clear All Tabs <ESC>[5g */
 683                                                                 for(n = 0; n < MAX_TAB_COLS; n++)
 684                                                                         vc->tty->tab_stop[n] = 0;
 685                                                                 break;
 686                                                 }
 687                                                 CSE;
 688                                                 continue;
 689                                         case 'h':
 690                                                 if(vc->question) {
 691                                                         switch(vc->parmv1) {
 692                                                                 /* DEC modes */
 693                                                                 case 25: /* Switch Cursor Visible <ESC>[?25h */
 694                                                                         video.show_cursor(vc, ON);
 695                                                                         break;
 696                                                                 case 4:
 697                                                                         vc->insert_mode = ON; /* not used */
 698                                                                         break;
 699                                                         }
 700                                                 }
 701                                                 CSE;
 702                                                 continue;
 703                                         case 'l':
 704                                                 if(vc->question) {
 705                                                         switch(vc->parmv1) {
 706                                                                 /* DEC modes */
 707                                                                 case 25: /* Switch Cursor Invisible <ESC>[?25l */
 708                                                                         video.show_cursor(vc, OFF);
 709                                                                         break;
 710                                                                 case 4:
 711                                                                         vc->insert_mode = OFF; /* not used */
 712                                                                         break;
 713                                                         }
 714                                                 }
 715                                                 CSE;
 716                                                 continue;
 717                                         case 'm':       /* Select Graphic Rendition <ESC> n ... m */
 718                                                 vc->nparms++;
 719                                                 csi_m(vc);
 720                                                 CSE;
 721                                                 continue;
 722                                         case 'n':
 723                                                 if(!vc->question) {
 724                                                         switch(vc->parmv1) {
 725                                                                 case 5: /* Query Device Status <ESC>[5n */
 726                                                                         insert_seq(tty, DEVICE_OK, 4);
 727                                                                         break;
 728                                                                 case 6: /* Query Cursor Position <ESC>[6n */
 729                                                                         {
 730                                                                                 char curpos[8];
 731                                                                                 char len;
 732                                                                                 len = sprintk(curpos, "\033[%d;%dR", vc->y, vc->x);
 733                                                                                 insert_seq(tty, curpos, len);
 734                                                                         }
 735                                                                         break;
 736                                                         }
 737                                                 }
 738                                                 CSE;
 739                                                 continue;
 740                                         case 'r':       /* Top and Bottom Margins <ESC>[r  / <ESC>[{start};{end}r */
 741                                                 if(!vc->parmv1) {
 742                                                         vc->parmv1++;
 743                                                 }
 744                                                 if(!vc->parmv2) {
 745                                                         vc->parmv2 = video.lines;
 746                                                 }
 747                                                 if(vc->parmv1 < vc->parmv2 && vc->parmv2 <= video.lines) {
 748                                                         vc->top = vc->parmv1 - 1;
 749                                                         vc->lines = vc->parmv2;
 750                                                         adjust(vc, 0, 0);
 751                                                 }
 752                                                 CSE;
 753                                                 continue;
 754                                         case 's':       /* Save Cursor <ESC>[s */
 755                                                 vc->saved_x = vc->x;
 756                                                 vc->saved_y = vc->y;
 757                                                 CSE;
 758                                                 continue;
 759                                         case 'u':       /* Restore Cursor <ESC>[u */
 760                                                 vc->x = vc->saved_x;
 761                                                 vc->y = vc->saved_y;
 762                                                 CSE;
 763                                                 continue;
 764                                         default:
 765                                                 CSE;
 766                                                 break;
 767                                 }
 768                         } else {
 769                                 switch(ch) {
 770                                         case '[':
 771                                                 vc->sbracket = 1;
 772                                                 vc->semicolon = 0;
 773                                                 vc->question = 0;
 774                                                 vc->parmv1 = vc->parmv2 = 0;
 775                                                 vc->nparms = 0;
 776                                                 memset_b(vc->parms, 0, sizeof(vc->parms));
 777                                                 continue;
 778                                         case '7':       /* Save Cursor & Attrs <ESC>7 */
 779                                                 vc->saved_x = vc->x;
 780                                                 vc->saved_y = vc->y;
 781                                                 CSE;
 782                                                 continue;
 783                                         case '8':       /* Restore Cursor & Attrs <ESC>8 */
 784                                                 vc->x = vc->saved_x;
 785                                                 vc->y = vc->saved_y;
 786                                                 CSE;
 787                                                 continue;
 788                                         case 'D':       /* Scroll Up <ESC>D */
 789                                                 lf(vc);
 790                                                 CSE;
 791                                                 continue;
 792                                         case 'E':       /* Move To Next Line <ESC>E */
 793                                                 cr(vc);
 794                                                 lf(vc);
 795                                                 CSE;
 796                                                 continue;
 797                                         case 'H':       /* Set Tab <ESC>H */
 798                                                 vc->tty->tab_stop[vc->x] = 1;
 799                                                 CSE;
 800                                                 continue;
 801                                         case 'M':       /* Scroll Down <ESC>M */
 802                                                 ri(vc);
 803                                                 CSE;
 804                                                 continue;
 805                                         case 'Z':       /* Identify Terminal <ESC>Z */
 806                                                 insert_seq(tty, VT100ID, 7);
 807                                                 CSE;
 808                                                 continue;
 809                                         case 'c':       /* Reset Device <ESC>c */
 810                                                 vconsole_reset(vc->tty);
 811                                                 vc->x = vc->y = 0;
 812                                                 csi_J(vc, CSI_J_SCREEN);
 813                                                 CSE;
 814                                                 continue;
 815                                         default:
 816                                                 CSE;
 817                                                 break;
 818                                 }
 819                         }
 820                 }
 821                 switch(ch) {
 822                         case '\033':
 823                                 vc->esc = 1;
 824                                 vc->sbracket = 0;
 825                                 vc->semicolon = 0;
 826                                 vc->question = 0;
 827                                 vc->parmv1 = vc->parmv2 = 0;
 828                                 continue;
 829                         default:
 830                                 echo_char(vc, &ch, 1);
 831                                 continue;
 832                 }
 833         }
 834         if(ch) {
 835                 if(vc->vc_mode != KD_GRAPHICS) {
 836                         video.update_curpos(vc);
 837                 }
 838                 wakeup(&do_select);
 839                 wakeup(&tty_write);
 840         }
 841 }
 842 
 843 void vconsole_select(int new_cons)
 844 {
 845         new_cons++;
 846         if(current_cons != new_cons) {
 847                 if(vc[current_cons].vt_mode.mode == VT_PROCESS) {
 848                         if(!kill_pid(vc[current_cons].tty->pid, vc[current_cons].vt_mode.acqsig)) {
 849                                 vc[current_cons].switchto_tty = new_cons;
 850                                 return;
 851                         }
 852                         init_vt(&vc[current_cons]);
 853                 }
 854                 if(vc[current_cons].vc_mode == KD_GRAPHICS) {
 855                         return;
 856                 }
 857                 vconsole_select_final(new_cons);
 858         }
 859 }
 860 
 861 void vconsole_select_final(int new_cons)
 862 {
 863         if(current_cons != new_cons) {
 864                 if(vc[new_cons].vt_mode.mode == VT_PROCESS) {
 865                         if(kill_pid(vc[new_cons].tty->pid, vc[new_cons].vt_mode.acqsig)) {
 866                                 init_vt(&vc[new_cons]);
 867                         }
 868                 }
 869                 if(video.buf_top) {
 870                         video.buf_top = 0;
 871                         video.show_cursor(&vc[current_cons], ON);
 872                         video.update_curpos(&vc[current_cons]);
 873                 }
 874                 vc[current_cons].vidmem = NULL;
 875                 vc[current_cons].flags &= ~CONSOLE_HAS_FOCUS;
 876                 vc[new_cons].vidmem = (unsigned char *)video.address;
 877                 vc[new_cons].flags |= CONSOLE_HAS_FOCUS;
 878                 current_cons = new_cons;
 879                 video.update_curpos(&vc[current_cons]);
 880                 video.restore_screen(&vc[current_cons]);
 881                 set_leds(vc[current_cons].led_status);
 882 
 883                 video.buf_y = vc[current_cons].y;
 884                 video.buf_top = 0;
 885                 vcbuf_refresh(&vc[current_cons]);
 886                 video.show_cursor(&vc[current_cons], COND);
 887                 video.cursor_blink((unsigned int)&vc[current_cons]);
 888         }
 889 }
 890 
 891 void unblank_screen(struct vconsole *vc)
 892 {
 893         if(!(vc->flags & CONSOLE_BLANKED)) {
 894                 return;
 895         }
 896         video.restore_screen(vc);
 897         vc->flags &= ~CONSOLE_BLANKED;
 898         video.show_cursor(vc, ON);
 899 }
 900 
 901 void vconsole_start(struct tty *tty)
 902 {
 903         struct vconsole *vc;
 904 
 905         vc = (struct vconsole *)tty->driver_data;
 906         if(!vc->scrlock) {
 907                 return;
 908         }
 909         vc->led_status &= ~SCRLBIT;
 910         vc->scrlock = 0;
 911         set_leds(vc->led_status);
 912 }
 913 
 914 void vconsole_stop(struct tty *tty)
 915 {
 916         struct vconsole *vc;
 917 
 918         vc = (struct vconsole *)tty->driver_data;
 919         if(vc->scrlock) {
 920                 return;
 921         }
 922         vc->led_status |= SCRLBIT;
 923         vc->scrlock = 1;
 924         set_leds(vc->led_status);
 925 }
 926 
 927 void vconsole_beep(void)
 928 {
 929         struct callout_req creq;
 930 
 931         pit_beep_on();
 932         creq.fn = pit_beep_off;
 933         creq.arg = 0;
 934         add_callout(&creq, HZ / 8);
 935 }
 936 
 937 void vconsole_deltab(struct tty *tty)
 938 {
 939         int col, n;
 940         unsigned char count;
 941         struct vconsole *vc;
 942         struct cblock *cb;
 943         unsigned char ch;
 944 
 945         vc = (struct vconsole *)tty->driver_data;
 946         cb = tty->cooked_q.head;
 947         col = count = 0;
 948 
 949         while(cb) {
 950                 for(n = 0; n < cb->end_off; n++) {
 951                         if(n >= cb->start_off) {
 952                                 ch = cb->data[n];
 953                                 if(ch == '\t') {
 954                                         while(!vc->tty->tab_stop[++col]);
 955                                 } else {
 956                                         col++;
 957                                         if(ISCNTRL(ch) && !ISSPACE(ch) && tty->termios.c_lflag & ECHOCTL) {
 958                                                 col++;
 959                                         }
 960                                 }
 961                                 col %= vc->columns;
 962                         }
 963                 }
 964                 cb = cb->next;
 965         }
 966         count = vc->x - col;
 967 
 968         while(count--) {
 969                 tty_queue_putchar(tty, &tty->write_q, '\b');
 970         }
 971 }
 972 
 973 void console_flush_log_buf(char *buffer, unsigned int count)
 974 {
 975         char *b;
 976         struct tty *tty;
 977 
 978         if(!(tty = get_tty(_syscondev))) {
 979                 _syscondev = MKDEV(VCONSOLES_MAJOR, 0);
 980                 tty = get_tty(_syscondev);
 981         }
 982         b = buffer;
 983 
 984         while(count) {
 985                 if(tty_queue_putchar(tty, &tty->write_q, *b) < 0) {
 986                         tty->output(tty);
 987                         continue;
 988                 }
 989                 count--;
 990                 b++;
 991         }
 992         tty->output(tty);
 993 }
 994 
 995 void console_init(void)
 996 {
 997         int n;
 998         struct tty *tty;
 999 
1000         if(video.flags & VPF_VGA) {
1001                 printk("console   0x%04X-0x%04X    -    %s (%d virtual consoles)\n", video.port, video.port + 1, video.signature, NR_VCONSOLES);
1002         }
1003         if(video.flags & VPF_VESAFB) {
1004                 printk("console                    -    color frame buffer, screen=%dx%d, font=%dx%d\n", video.columns, video.lines, video.fb_char_width, video.fb_char_height);
1005                 printk("\t\t\t\t(%d virtual consoles)\n", NR_VCONSOLES);
1006         }
1007 
1008         for(n = 1; n <= NR_VCONSOLES; n++) {
1009                 if(!register_tty(MKDEV(VCONSOLES_MAJOR, n))) {
1010                         tty = get_tty(MKDEV(VCONSOLES_MAJOR, n));
1011                         tty->driver_data = (void *)&vc[n];
1012                         tty->stop = vconsole_stop;
1013                         tty->start = vconsole_start;
1014                         tty->deltab = vconsole_deltab;
1015                         tty->reset = vconsole_reset;
1016                         tty->input = do_cook;
1017                         tty->output = vconsole_write;
1018                         vc[n].tty = tty;
1019                         if(video.flags & VPF_VGA) {
1020                                 vc[n].screen = (short int *)kmalloc();
1021                         }
1022                         if(video.flags & VPF_VESAFB) {
1023                                 vc[n].screen = vc_screen[n];
1024                         }
1025                         vc[n].vidmem = NULL;
1026                         memset_w(vc[n].screen, BLANK_MEM, SCREEN_SIZE);
1027                         vconsole_reset(tty);
1028                 }
1029         }
1030 
1031         current_cons = 1;
1032         video.show_cursor(&vc[current_cons], ON);
1033         vc[current_cons].vidmem = (unsigned char *)video.address;
1034         vc[current_cons].flags |= CONSOLE_HAS_FOCUS;
1035 
1036         if(video.flags & VPF_VGA) {
1037                 memcpy_w(vc[current_cons].screen, video.address, SCREEN_SIZE);
1038         }
1039 
1040         video.get_curpos(&vc[current_cons]);
1041         video.update_curpos(&vc[current_cons]);
1042         video.buf_y = vc[current_cons].y;
1043         video.buf_top = 0;
1044 
1045         SET_MINOR(console_device.minors, 0);
1046         SET_MINOR(console_device.minors, 1);
1047         for(n = 0; n <= NR_VCONSOLES; n++) {
1048                 SET_MINOR(tty_device.minors, n);
1049         }
1050 
1051         register_device(CHR_DEV, &console_device);
1052         register_device(CHR_DEV, &tty_device);
1053 
1054         if(is_vconsole(_syscondev)) {
1055                 register_console(console_flush_log_buf);
1056         }
1057 }

/* [previous][next][first][last][top][bottom][index][help] */