aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/vt
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-07-24 20:14:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-07-24 20:14:37 -0400
commit721413aff218118548b84b18cb5b49660e6e2940 (patch)
tree967b1c535645a25c19e948d0b9fdf096f93b253e /drivers/tty/vt
parent25a0dc4be86fc0d8c7e81bb5f8be8427022bf15f (diff)
parent67417f9c262e2cd4b706eba3e1fd879d0bebc6d8 (diff)
Merge tag 'tty-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
Pull tty/serial driver updates from Greg KH: "Here is the big tty and serial driver update for 4.8-rc1. Lots of good cleanups from Jiri on a number of vt and other tty related things, and the normal driver updates. Full details are in the shortlog. All of these have been in linux-next for a while with no reported issues" * tag 'tty-4.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (90 commits) tty/serial: atmel: enforce tasklet init and termination sequences serial: sh-sci: Stop transfers in sci_shutdown() serial: 8250_ingenic: drop #if conditional surrounding earlycon code serial: 8250_mtk: drop !defined(MODULE) conditional serial: 8250_uniphier: drop !defined(MODULE) conditional earlycon: mark earlycon code as __used iif the caller is built-in tty/serial/8250: use mctrl_gpio helpers serial: mctrl_gpio: enable API usage only for initialized mctrl_gpios struct serial: mctrl_gpio: add modem control read routine tty/serial/8250: make UART_MCR register access consistent serial: 8250_mid: Read RX buffer on RX DMA timeout for DNV serial: 8250_dma: Export serial8250_rx_dma_flush() dmaengine: hsu: Export hsu_dma_get_status() tty: serial: 8250: add CON_CONSDEV to flags tty: serial: samsung: add byte-order aware bit functions tty: serial: samsung: fixup accessors for endian serial: sirf: make fifo functions static serial: mps2-uart: make driver explicitly non-modular serial: mvebu-uart: free the IRQ in ->shutdown() serial/bcm63xx_uart: use correct alias naming ...
Diffstat (limited to 'drivers/tty/vt')
-rw-r--r--drivers/tty/vt/consolemap.c13
-rw-r--r--drivers/tty/vt/keyboard.c16
-rw-r--r--drivers/tty/vt/vt.c431
-rw-r--r--drivers/tty/vt/vt_ioctl.c8
4 files changed, 221 insertions, 247 deletions
diff --git a/drivers/tty/vt/consolemap.c b/drivers/tty/vt/consolemap.c
index c8c91f0476a2..9d7ab7b66a8a 100644
--- a/drivers/tty/vt/consolemap.c
+++ b/drivers/tty/vt/consolemap.c
@@ -499,9 +499,8 @@ con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
499 return 0; 499 return 0;
500} 500}
501 501
502/* ui is a leftover from using a hashtable, but might be used again 502/* Caller must hold the lock */
503 Caller must hold the lock */ 503static int con_do_clear_unimap(struct vc_data *vc)
504static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
505{ 504{
506 struct uni_pagedir *p, *q; 505 struct uni_pagedir *p, *q;
507 506
@@ -524,11 +523,11 @@ static int con_do_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
524 return 0; 523 return 0;
525} 524}
526 525
527int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui) 526int con_clear_unimap(struct vc_data *vc)
528{ 527{
529 int ret; 528 int ret;
530 console_lock(); 529 console_lock();
531 ret = con_do_clear_unimap(vc, ui); 530 ret = con_do_clear_unimap(vc);
532 console_unlock(); 531 console_unlock();
533 return ret; 532 return ret;
534} 533}
@@ -556,7 +555,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
556 int j, k; 555 int j, k;
557 u16 **p1, *p2, l; 556 u16 **p1, *p2, l;
558 557
559 err1 = con_do_clear_unimap(vc, NULL); 558 err1 = con_do_clear_unimap(vc);
560 if (err1) { 559 if (err1) {
561 console_unlock(); 560 console_unlock();
562 return err1; 561 return err1;
@@ -677,7 +676,7 @@ int con_set_default_unimap(struct vc_data *vc)
677 676
678 /* The default font is always 256 characters */ 677 /* The default font is always 256 characters */
679 678
680 err = con_do_clear_unimap(vc, NULL); 679 err = con_do_clear_unimap(vc);
681 if (err) 680 if (err)
682 return err; 681 return err;
683 682
diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c
index 1e93a37e27f0..0f8caae4267d 100644
--- a/drivers/tty/vt/keyboard.c
+++ b/drivers/tty/vt/keyboard.c
@@ -567,7 +567,7 @@ static void fn_scroll_forw(struct vc_data *vc)
567 567
568static void fn_scroll_back(struct vc_data *vc) 568static void fn_scroll_back(struct vc_data *vc)
569{ 569{
570 scrollback(vc, 0); 570 scrollback(vc);
571} 571}
572 572
573static void fn_show_mem(struct vc_data *vc) 573static void fn_show_mem(struct vc_data *vc)
@@ -1733,16 +1733,10 @@ int vt_do_diacrit(unsigned int cmd, void __user *udp, int perm)
1733 return -EINVAL; 1733 return -EINVAL;
1734 1734
1735 if (ct) { 1735 if (ct) {
1736 buf = kmalloc(ct * sizeof(struct kbdiacruc), 1736 buf = memdup_user(a->kbdiacruc,
1737 GFP_KERNEL); 1737 ct * sizeof(struct kbdiacruc));
1738 if (buf == NULL) 1738 if (IS_ERR(buf))
1739 return -ENOMEM; 1739 return PTR_ERR(buf);
1740
1741 if (copy_from_user(buf, a->kbdiacruc,
1742 ct * sizeof(struct kbdiacruc))) {
1743 kfree(buf);
1744 return -EFAULT;
1745 }
1746 } 1740 }
1747 spin_lock_irqsave(&kbd_event_lock, flags); 1741 spin_lock_irqsave(&kbd_event_lock, flags);
1748 if (ct) 1742 if (ct)
diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c
index 5b0fe97c46ca..2705ca960e92 100644
--- a/drivers/tty/vt/vt.c
+++ b/drivers/tty/vt/vt.c
@@ -277,13 +277,15 @@ static void notify_update(struct vc_data *vc)
277 * Low-Level Functions 277 * Low-Level Functions
278 */ 278 */
279 279
280#define IS_FG(vc) ((vc)->vc_num == fg_console) 280static inline bool con_is_fg(const struct vc_data *vc)
281{
282 return vc->vc_num == fg_console;
283}
281 284
282#ifdef VT_BUF_VRAM_ONLY 285static inline bool con_should_update(const struct vc_data *vc)
283#define DO_UPDATE(vc) 0 286{
284#else 287 return con_is_visible(vc) && !console_blanked;
285#define DO_UPDATE(vc) (CON_IS_VISIBLE(vc) && !console_blanked) 288}
286#endif
287 289
288static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed) 290static inline unsigned short *screenpos(struct vc_data *vc, int offset, int viewed)
289{ 291{
@@ -321,7 +323,7 @@ static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
321 nr = b - t - 1; 323 nr = b - t - 1;
322 if (b > vc->vc_rows || t >= b || nr < 1) 324 if (b > vc->vc_rows || t >= b || nr < 1)
323 return; 325 return;
324 if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr)) 326 if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr))
325 return; 327 return;
326 d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t); 328 d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
327 s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr)); 329 s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr));
@@ -339,7 +341,7 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
339 nr = b - t - 1; 341 nr = b - t - 1;
340 if (b > vc->vc_rows || t >= b || nr < 1) 342 if (b > vc->vc_rows || t >= b || nr < 1)
341 return; 343 return;
342 if (CON_IS_VISIBLE(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr)) 344 if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr))
343 return; 345 return;
344 s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t); 346 s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t);
345 step = vc->vc_cols * nr; 347 step = vc->vc_cols * nr;
@@ -349,7 +351,6 @@ static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr)
349 351
350static void do_update_region(struct vc_data *vc, unsigned long start, int count) 352static void do_update_region(struct vc_data *vc, unsigned long start, int count)
351{ 353{
352#ifndef VT_BUF_VRAM_ONLY
353 unsigned int xx, yy, offset; 354 unsigned int xx, yy, offset;
354 u16 *p; 355 u16 *p;
355 356
@@ -390,14 +391,13 @@ static void do_update_region(struct vc_data *vc, unsigned long start, int count)
390 start = vc->vc_sw->con_getxy(vc, start, NULL, NULL); 391 start = vc->vc_sw->con_getxy(vc, start, NULL, NULL);
391 } 392 }
392 } 393 }
393#endif
394} 394}
395 395
396void update_region(struct vc_data *vc, unsigned long start, int count) 396void update_region(struct vc_data *vc, unsigned long start, int count)
397{ 397{
398 WARN_CONSOLE_UNLOCKED(); 398 WARN_CONSOLE_UNLOCKED();
399 399
400 if (DO_UPDATE(vc)) { 400 if (con_should_update(vc)) {
401 hide_cursor(vc); 401 hide_cursor(vc);
402 do_update_region(vc, start, count); 402 do_update_region(vc, start, count);
403 set_cursor(vc); 403 set_cursor(vc);
@@ -413,7 +413,6 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
413 return vc->vc_sw->con_build_attr(vc, _color, _intensity, 413 return vc->vc_sw->con_build_attr(vc, _color, _intensity,
414 _blink, _underline, _reverse, _italic); 414 _blink, _underline, _reverse, _italic);
415 415
416#ifndef VT_BUF_VRAM_ONLY
417/* 416/*
418 * ++roman: I completely changed the attribute format for monochrome 417 * ++roman: I completely changed the attribute format for monochrome
419 * mode (!can_do_color). The formerly used MDA (monochrome display 418 * mode (!can_do_color). The formerly used MDA (monochrome display
@@ -448,9 +447,6 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,
448 a <<= 1; 447 a <<= 1;
449 return a; 448 return a;
450 } 449 }
451#else
452 return 0;
453#endif
454} 450}
455 451
456static void update_attr(struct vc_data *vc) 452static void update_attr(struct vc_data *vc)
@@ -470,10 +466,9 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
470 466
471 count /= 2; 467 count /= 2;
472 p = screenpos(vc, offset, viewed); 468 p = screenpos(vc, offset, viewed);
473 if (vc->vc_sw->con_invert_region) 469 if (vc->vc_sw->con_invert_region) {
474 vc->vc_sw->con_invert_region(vc, p, count); 470 vc->vc_sw->con_invert_region(vc, p, count);
475#ifndef VT_BUF_VRAM_ONLY 471 } else {
476 else {
477 u16 *q = p; 472 u16 *q = p;
478 int cnt = count; 473 int cnt = count;
479 u16 a; 474 u16 a;
@@ -501,8 +496,8 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed)
501 } 496 }
502 } 497 }
503 } 498 }
504#endif 499
505 if (DO_UPDATE(vc)) 500 if (con_should_update(vc))
506 do_update_region(vc, (unsigned long) p, count); 501 do_update_region(vc, (unsigned long) p, count);
507 notify_update(vc); 502 notify_update(vc);
508} 503}
@@ -519,7 +514,7 @@ void complement_pos(struct vc_data *vc, int offset)
519 if (old_offset != -1 && old_offset >= 0 && 514 if (old_offset != -1 && old_offset >= 0 &&
520 old_offset < vc->vc_screenbuf_size) { 515 old_offset < vc->vc_screenbuf_size) {
521 scr_writew(old, screenpos(vc, old_offset, 1)); 516 scr_writew(old, screenpos(vc, old_offset, 1));
522 if (DO_UPDATE(vc)) 517 if (con_should_update(vc))
523 vc->vc_sw->con_putc(vc, old, oldy, oldx); 518 vc->vc_sw->con_putc(vc, old, oldy, oldx);
524 notify_update(vc); 519 notify_update(vc);
525 } 520 }
@@ -534,7 +529,7 @@ void complement_pos(struct vc_data *vc, int offset)
534 old = scr_readw(p); 529 old = scr_readw(p);
535 new = old ^ vc->vc_complement_mask; 530 new = old ^ vc->vc_complement_mask;
536 scr_writew(new, p); 531 scr_writew(new, p);
537 if (DO_UPDATE(vc)) { 532 if (con_should_update(vc)) {
538 oldx = (offset >> 1) % vc->vc_cols; 533 oldx = (offset >> 1) % vc->vc_cols;
539 oldy = (offset >> 1) / vc->vc_cols; 534 oldy = (offset >> 1) / vc->vc_cols;
540 vc->vc_sw->con_putc(vc, new, oldy, oldx); 535 vc->vc_sw->con_putc(vc, new, oldy, oldx);
@@ -550,7 +545,7 @@ static void insert_char(struct vc_data *vc, unsigned int nr)
550 scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2); 545 scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2);
551 scr_memsetw(p, vc->vc_video_erase_char, nr * 2); 546 scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
552 vc->vc_need_wrap = 0; 547 vc->vc_need_wrap = 0;
553 if (DO_UPDATE(vc)) 548 if (con_should_update(vc))
554 do_update_region(vc, (unsigned long) p, 549 do_update_region(vc, (unsigned long) p,
555 vc->vc_cols - vc->vc_x); 550 vc->vc_cols - vc->vc_x);
556} 551}
@@ -563,7 +558,7 @@ static void delete_char(struct vc_data *vc, unsigned int nr)
563 scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char, 558 scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,
564 nr * 2); 559 nr * 2);
565 vc->vc_need_wrap = 0; 560 vc->vc_need_wrap = 0;
566 if (DO_UPDATE(vc)) 561 if (con_should_update(vc))
567 do_update_region(vc, (unsigned long) p, 562 do_update_region(vc, (unsigned long) p,
568 vc->vc_cols - vc->vc_x); 563 vc->vc_cols - vc->vc_x);
569} 564}
@@ -583,7 +578,7 @@ static void add_softcursor(struct vc_data *vc)
583 if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000; 578 if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
584 if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700; 579 if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
585 scr_writew(i, (u16 *) vc->vc_pos); 580 scr_writew(i, (u16 *) vc->vc_pos);
586 if (DO_UPDATE(vc)) 581 if (con_should_update(vc))
587 vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x); 582 vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x);
588} 583}
589 584
@@ -591,7 +586,7 @@ static void hide_softcursor(struct vc_data *vc)
591{ 586{
592 if (softcursor_original != -1) { 587 if (softcursor_original != -1) {
593 scr_writew(softcursor_original, (u16 *)vc->vc_pos); 588 scr_writew(softcursor_original, (u16 *)vc->vc_pos);
594 if (DO_UPDATE(vc)) 589 if (con_should_update(vc))
595 vc->vc_sw->con_putc(vc, softcursor_original, 590 vc->vc_sw->con_putc(vc, softcursor_original,
596 vc->vc_y, vc->vc_x); 591 vc->vc_y, vc->vc_x);
597 softcursor_original = -1; 592 softcursor_original = -1;
@@ -608,8 +603,7 @@ static void hide_cursor(struct vc_data *vc)
608 603
609static void set_cursor(struct vc_data *vc) 604static void set_cursor(struct vc_data *vc)
610{ 605{
611 if (!IS_FG(vc) || console_blanked || 606 if (!con_is_fg(vc) || console_blanked || vc->vc_mode == KD_GRAPHICS)
612 vc->vc_mode == KD_GRAPHICS)
613 return; 607 return;
614 if (vc->vc_deccm) { 608 if (vc->vc_deccm) {
615 if (vc == sel_cons) 609 if (vc == sel_cons)
@@ -625,7 +619,7 @@ static void set_origin(struct vc_data *vc)
625{ 619{
626 WARN_CONSOLE_UNLOCKED(); 620 WARN_CONSOLE_UNLOCKED();
627 621
628 if (!CON_IS_VISIBLE(vc) || 622 if (!con_is_visible(vc) ||
629 !vc->vc_sw->con_set_origin || 623 !vc->vc_sw->con_set_origin ||
630 !vc->vc_sw->con_set_origin(vc)) 624 !vc->vc_sw->con_set_origin(vc))
631 vc->vc_origin = (unsigned long)vc->vc_screenbuf; 625 vc->vc_origin = (unsigned long)vc->vc_screenbuf;
@@ -673,12 +667,12 @@ void redraw_screen(struct vc_data *vc, int is_switch)
673 struct vc_data *old_vc = vc_cons[fg_console].d; 667 struct vc_data *old_vc = vc_cons[fg_console].d;
674 if (old_vc == vc) 668 if (old_vc == vc)
675 return; 669 return;
676 if (!CON_IS_VISIBLE(vc)) 670 if (!con_is_visible(vc))
677 redraw = 1; 671 redraw = 1;
678 *vc->vc_display_fg = vc; 672 *vc->vc_display_fg = vc;
679 fg_console = vc->vc_num; 673 fg_console = vc->vc_num;
680 hide_cursor(old_vc); 674 hide_cursor(old_vc);
681 if (!CON_IS_VISIBLE(old_vc)) { 675 if (!con_is_visible(old_vc)) {
682 save_screen(old_vc); 676 save_screen(old_vc);
683 set_origin(old_vc); 677 set_origin(old_vc);
684 } 678 }
@@ -954,7 +948,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
954 tty_do_resize(tty, &ws); 948 tty_do_resize(tty, &ws);
955 } 949 }
956 950
957 if (CON_IS_VISIBLE(vc)) 951 if (con_is_visible(vc))
958 update_screen(vc); 952 update_screen(vc);
959 vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num); 953 vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
960 return err; 954 return err;
@@ -1103,11 +1097,9 @@ static void gotoxay(struct vc_data *vc, int new_x, int new_y)
1103 gotoxy(vc, new_x, vc->vc_decom ? (vc->vc_top + new_y) : new_y); 1097 gotoxy(vc, new_x, vc->vc_decom ? (vc->vc_top + new_y) : new_y);
1104} 1098}
1105 1099
1106void scrollback(struct vc_data *vc, int lines) 1100void scrollback(struct vc_data *vc)
1107{ 1101{
1108 if (!lines) 1102 scrolldelta(-(vc->vc_rows / 2));
1109 lines = vc->vc_rows / 2;
1110 scrolldelta(-lines);
1111} 1103}
1112 1104
1113void scrollfront(struct vc_data *vc, int lines) 1105void scrollfront(struct vc_data *vc, int lines)
@@ -1186,7 +1178,7 @@ static void csi_J(struct vc_data *vc, int vpar)
1186 scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char, 1178 scr_memsetw(vc->vc_screenbuf, vc->vc_video_erase_char,
1187 vc->vc_screenbuf_size >> 1); 1179 vc->vc_screenbuf_size >> 1);
1188 set_origin(vc); 1180 set_origin(vc);
1189 if (CON_IS_VISIBLE(vc)) 1181 if (con_is_visible(vc))
1190 update_screen(vc); 1182 update_screen(vc);
1191 /* fall through */ 1183 /* fall through */
1192 case 2: /* erase whole display */ 1184 case 2: /* erase whole display */
@@ -1197,7 +1189,7 @@ static void csi_J(struct vc_data *vc, int vpar)
1197 return; 1189 return;
1198 } 1190 }
1199 scr_memsetw(start, vc->vc_video_erase_char, 2 * count); 1191 scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
1200 if (DO_UPDATE(vc)) 1192 if (con_should_update(vc))
1201 do_update_region(vc, (unsigned long) start, count); 1193 do_update_region(vc, (unsigned long) start, count);
1202 vc->vc_need_wrap = 0; 1194 vc->vc_need_wrap = 0;
1203} 1195}
@@ -1225,7 +1217,7 @@ static void csi_K(struct vc_data *vc, int vpar)
1225 } 1217 }
1226 scr_memsetw(start, vc->vc_video_erase_char, 2 * count); 1218 scr_memsetw(start, vc->vc_video_erase_char, 2 * count);
1227 vc->vc_need_wrap = 0; 1219 vc->vc_need_wrap = 0;
1228 if (DO_UPDATE(vc)) 1220 if (con_should_update(vc))
1229 do_update_region(vc, (unsigned long) start, count); 1221 do_update_region(vc, (unsigned long) start, count);
1230} 1222}
1231 1223
@@ -1238,7 +1230,7 @@ static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar posi
1238 count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar; 1230 count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar;
1239 1231
1240 scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count); 1232 scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
1241 if (DO_UPDATE(vc)) 1233 if (con_should_update(vc))
1242 vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count); 1234 vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count);
1243 vc->vc_need_wrap = 0; 1235 vc->vc_need_wrap = 0;
1244} 1236}
@@ -1255,48 +1247,87 @@ static void default_attr(struct vc_data *vc)
1255 1247
1256struct rgb { u8 r; u8 g; u8 b; }; 1248struct rgb { u8 r; u8 g; u8 b; };
1257 1249
1258static struct rgb rgb_from_256(int i) 1250static void rgb_from_256(int i, struct rgb *c)
1259{ 1251{
1260 struct rgb c;
1261 if (i < 8) { /* Standard colours. */ 1252 if (i < 8) { /* Standard colours. */
1262 c.r = i&1 ? 0xaa : 0x00; 1253 c->r = i&1 ? 0xaa : 0x00;
1263 c.g = i&2 ? 0xaa : 0x00; 1254 c->g = i&2 ? 0xaa : 0x00;
1264 c.b = i&4 ? 0xaa : 0x00; 1255 c->b = i&4 ? 0xaa : 0x00;
1265 } else if (i < 16) { 1256 } else if (i < 16) {
1266 c.r = i&1 ? 0xff : 0x55; 1257 c->r = i&1 ? 0xff : 0x55;
1267 c.g = i&2 ? 0xff : 0x55; 1258 c->g = i&2 ? 0xff : 0x55;
1268 c.b = i&4 ? 0xff : 0x55; 1259 c->b = i&4 ? 0xff : 0x55;
1269 } else if (i < 232) { /* 6x6x6 colour cube. */ 1260 } else if (i < 232) { /* 6x6x6 colour cube. */
1270 c.r = (i - 16) / 36 * 85 / 2; 1261 c->r = (i - 16) / 36 * 85 / 2;
1271 c.g = (i - 16) / 6 % 6 * 85 / 2; 1262 c->g = (i - 16) / 6 % 6 * 85 / 2;
1272 c.b = (i - 16) % 6 * 85 / 2; 1263 c->b = (i - 16) % 6 * 85 / 2;
1273 } else /* Grayscale ramp. */ 1264 } else /* Grayscale ramp. */
1274 c.r = c.g = c.b = i * 10 - 2312; 1265 c->r = c->g = c->b = i * 10 - 2312;
1275 return c;
1276} 1266}
1277 1267
1278static void rgb_foreground(struct vc_data *vc, struct rgb c) 1268static void rgb_foreground(struct vc_data *vc, const struct rgb *c)
1279{ 1269{
1280 u8 hue, max = c.r; 1270 u8 hue = 0, max = max3(c->r, c->g, c->b);
1281 if (c.g > max) 1271
1282 max = c.g; 1272 if (c->r > max / 2)
1283 if (c.b > max) 1273 hue |= 4;
1284 max = c.b; 1274 if (c->g > max / 2)
1285 hue = (c.r > max/2 ? 4 : 0) 1275 hue |= 2;
1286 | (c.g > max/2 ? 2 : 0) 1276 if (c->b > max / 2)
1287 | (c.b > max/2 ? 1 : 0); 1277 hue |= 1;
1288 if (hue == 7 && max <= 0x55) 1278
1289 hue = 0, vc->vc_intensity = 2; 1279 if (hue == 7 && max <= 0x55) {
1280 hue = 0;
1281 vc->vc_intensity = 2;
1282 } else if (max > 0xaa)
1283 vc->vc_intensity = 2;
1290 else 1284 else
1291 vc->vc_intensity = (max > 0xaa) + 1; 1285 vc->vc_intensity = 1;
1286
1292 vc->vc_color = (vc->vc_color & 0xf0) | hue; 1287 vc->vc_color = (vc->vc_color & 0xf0) | hue;
1293} 1288}
1294 1289
1295static void rgb_background(struct vc_data *vc, struct rgb c) 1290static void rgb_background(struct vc_data *vc, const struct rgb *c)
1296{ 1291{
1297 /* For backgrounds, err on the dark side. */ 1292 /* For backgrounds, err on the dark side. */
1298 vc->vc_color = (vc->vc_color & 0x0f) 1293 vc->vc_color = (vc->vc_color & 0x0f)
1299 | (c.r&0x80) >> 1 | (c.g&0x80) >> 2 | (c.b&0x80) >> 3; 1294 | (c->r&0x80) >> 1 | (c->g&0x80) >> 2 | (c->b&0x80) >> 3;
1295}
1296
1297/*
1298 * ITU T.416 Higher colour modes. They break the usual properties of SGR codes
1299 * and thus need to be detected and ignored by hand. Strictly speaking, that
1300 * standard also wants : rather than ; as separators, contrary to ECMA-48, but
1301 * no one produces such codes and almost no one accepts them.
1302 *
1303 * Subcommands 3 (CMY) and 4 (CMYK) are so insane there's no point in
1304 * supporting them.
1305 */
1306static int vc_t416_color(struct vc_data *vc, int i,
1307 void(*set_color)(struct vc_data *vc, const struct rgb *c))
1308{
1309 struct rgb c;
1310
1311 i++;
1312 if (i > vc->vc_npar)
1313 return i;
1314
1315 if (vc->vc_par[i] == 5 && i < vc->vc_npar) {
1316 /* 256 colours -- ubiquitous */
1317 i++;
1318 rgb_from_256(vc->vc_par[i], &c);
1319 } else if (vc->vc_par[i] == 2 && i <= vc->vc_npar + 3) {
1320 /* 24 bit -- extremely rare */
1321 c.r = vc->vc_par[i + 1];
1322 c.g = vc->vc_par[i + 2];
1323 c.b = vc->vc_par[i + 3];
1324 i += 3;
1325 } else
1326 return i;
1327
1328 set_color(vc, &c);
1329
1330 return i;
1300} 1331}
1301 1332
1302/* console_lock is held */ 1333/* console_lock is held */
@@ -1306,135 +1337,91 @@ static void csi_m(struct vc_data *vc)
1306 1337
1307 for (i = 0; i <= vc->vc_npar; i++) 1338 for (i = 0; i <= vc->vc_npar; i++)
1308 switch (vc->vc_par[i]) { 1339 switch (vc->vc_par[i]) {
1309 case 0: /* all attributes off */ 1340 case 0: /* all attributes off */
1310 default_attr(vc); 1341 default_attr(vc);
1311 break; 1342 break;
1312 case 1: 1343 case 1:
1313 vc->vc_intensity = 2; 1344 vc->vc_intensity = 2;
1314 break; 1345 break;
1315 case 2: 1346 case 2:
1316 vc->vc_intensity = 0; 1347 vc->vc_intensity = 0;
1317 break; 1348 break;
1318 case 3: 1349 case 3:
1319 vc->vc_italic = 1; 1350 vc->vc_italic = 1;
1320 break; 1351 break;
1321 case 4: 1352 case 4:
1322 vc->vc_underline = 1; 1353 vc->vc_underline = 1;
1323 break; 1354 break;
1324 case 5: 1355 case 5:
1325 vc->vc_blink = 1; 1356 vc->vc_blink = 1;
1326 break; 1357 break;
1327 case 7: 1358 case 7:
1328 vc->vc_reverse = 1; 1359 vc->vc_reverse = 1;
1329 break; 1360 break;
1330 case 10: /* ANSI X3.64-1979 (SCO-ish?) 1361 case 10: /* ANSI X3.64-1979 (SCO-ish?)
1331 * Select primary font, don't display 1362 * Select primary font, don't display control chars if
1332 * control chars if defined, don't set 1363 * defined, don't set bit 8 on output.
1333 * bit 8 on output. 1364 */
1334 */ 1365 vc->vc_translate = set_translate(vc->vc_charset == 0
1335 vc->vc_translate = set_translate(vc->vc_charset == 0 1366 ? vc->vc_G0_charset
1336 ? vc->vc_G0_charset 1367 : vc->vc_G1_charset, vc);
1337 : vc->vc_G1_charset, vc); 1368 vc->vc_disp_ctrl = 0;
1338 vc->vc_disp_ctrl = 0; 1369 vc->vc_toggle_meta = 0;
1339 vc->vc_toggle_meta = 0; 1370 break;
1340 break; 1371 case 11: /* ANSI X3.64-1979 (SCO-ish?)
1341 case 11: /* ANSI X3.64-1979 (SCO-ish?) 1372 * Select first alternate font, lets chars < 32 be
1342 * Select first alternate font, lets 1373 * displayed as ROM chars.
1343 * chars < 32 be displayed as ROM chars. 1374 */
1344 */ 1375 vc->vc_translate = set_translate(IBMPC_MAP, vc);
1345 vc->vc_translate = set_translate(IBMPC_MAP, vc); 1376 vc->vc_disp_ctrl = 1;
1346 vc->vc_disp_ctrl = 1; 1377 vc->vc_toggle_meta = 0;
1347 vc->vc_toggle_meta = 0; 1378 break;
1348 break; 1379 case 12: /* ANSI X3.64-1979 (SCO-ish?)
1349 case 12: /* ANSI X3.64-1979 (SCO-ish?) 1380 * Select second alternate font, toggle high bit
1350 * Select second alternate font, toggle 1381 * before displaying as ROM char.
1351 * high bit before displaying as ROM char. 1382 */
1352 */ 1383 vc->vc_translate = set_translate(IBMPC_MAP, vc);
1353 vc->vc_translate = set_translate(IBMPC_MAP, vc); 1384 vc->vc_disp_ctrl = 1;
1354 vc->vc_disp_ctrl = 1; 1385 vc->vc_toggle_meta = 1;
1355 vc->vc_toggle_meta = 1; 1386 break;
1356 break; 1387 case 21:
1357 case 21: 1388 case 22:
1358 case 22: 1389 vc->vc_intensity = 1;
1359 vc->vc_intensity = 1; 1390 break;
1360 break; 1391 case 23:
1361 case 23: 1392 vc->vc_italic = 0;
1362 vc->vc_italic = 0; 1393 break;
1363 break; 1394 case 24:
1364 case 24: 1395 vc->vc_underline = 0;
1365 vc->vc_underline = 0; 1396 break;
1366 break; 1397 case 25:
1367 case 25: 1398 vc->vc_blink = 0;
1368 vc->vc_blink = 0; 1399 break;
1369 break; 1400 case 27:
1370 case 27: 1401 vc->vc_reverse = 0;
1371 vc->vc_reverse = 0; 1402 break;
1372 break; 1403 case 38:
1373 case 38: /* ITU T.416 1404 i = vc_t416_color(vc, i, rgb_foreground);
1374 * Higher colour modes. 1405 break;
1375 * They break the usual properties of SGR codes 1406 case 48:
1376 * and thus need to be detected and ignored by 1407 i = vc_t416_color(vc, i, rgb_background);
1377 * hand. Strictly speaking, that standard also 1408 break;
1378 * wants : rather than ; as separators, contrary 1409 case 39:
1379 * to ECMA-48, but no one produces such codes 1410 vc->vc_color = (vc->vc_def_color & 0x0f) |
1380 * and almost no one accepts them. 1411 (vc->vc_color & 0xf0);
1381 */ 1412 break;
1382 i++; 1413 case 49:
1383 if (i > vc->vc_npar) 1414 vc->vc_color = (vc->vc_def_color & 0xf0) |
1384 break; 1415 (vc->vc_color & 0x0f);
1385 if (vc->vc_par[i] == 5 && /* 256 colours */ 1416 break;
1386 i < vc->vc_npar) { /* ubiquitous */ 1417 default:
1387 i++; 1418 if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
1388 rgb_foreground(vc, 1419 vc->vc_color = color_table[vc->vc_par[i] - 30]
1389 rgb_from_256(vc->vc_par[i])); 1420 | (vc->vc_color & 0xf0);
1390 } else if (vc->vc_par[i] == 2 && /* 24 bit */ 1421 else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
1391 i <= vc->vc_npar + 3) {/* extremely rare */ 1422 vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)
1392 struct rgb c = { 1423 | (vc->vc_color & 0x0f);
1393 .r = vc->vc_par[i + 1], 1424 break;
1394 .g = vc->vc_par[i + 2],
1395 .b = vc->vc_par[i + 3],
1396 };
1397 rgb_foreground(vc, c);
1398 i += 3;
1399 }
1400 /* Subcommands 3 (CMY) and 4 (CMYK) are so insane
1401 * there's no point in supporting them.
1402 */
1403 break;
1404 case 48:
1405 i++;
1406 if (i > vc->vc_npar)
1407 break;
1408 if (vc->vc_par[i] == 5 && /* 256 colours */
1409 i < vc->vc_npar) {
1410 i++;
1411 rgb_background(vc,
1412 rgb_from_256(vc->vc_par[i]));
1413 } else if (vc->vc_par[i] == 2 && /* 24 bit */
1414 i <= vc->vc_npar + 3) {
1415 struct rgb c = {
1416 .r = vc->vc_par[i + 1],
1417 .g = vc->vc_par[i + 2],
1418 .b = vc->vc_par[i + 3],
1419 };
1420 rgb_background(vc, c);
1421 i += 3;
1422 }
1423 break;
1424 case 39:
1425 vc->vc_color = (vc->vc_def_color & 0x0f) | (vc->vc_color & 0xf0);
1426 break;
1427 case 49:
1428 vc->vc_color = (vc->vc_def_color & 0xf0) | (vc->vc_color & 0x0f);
1429 break;
1430 default:
1431 if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
1432 vc->vc_color = color_table[vc->vc_par[i] - 30]
1433 | (vc->vc_color & 0xf0);
1434 else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
1435 vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)
1436 | (vc->vc_color & 0x0f);
1437 break;
1438 } 1425 }
1439 update_attr(vc); 1426 update_attr(vc);
1440} 1427}
@@ -1496,7 +1483,6 @@ static void set_mode(struct vc_data *vc, int on_off)
1496 clr_kbd(vc, decckm); 1483 clr_kbd(vc, decckm);
1497 break; 1484 break;
1498 case 3: /* 80/132 mode switch unimplemented */ 1485 case 3: /* 80/132 mode switch unimplemented */
1499 vc->vc_deccolm = on_off;
1500#if 0 1486#if 0
1501 vc_resize(deccolm ? 132 : 80, vc->vc_rows); 1487 vc_resize(deccolm ? 132 : 80, vc->vc_rows);
1502 /* this alone does not suffice; some user mode 1488 /* this alone does not suffice; some user mode
@@ -2178,18 +2164,20 @@ static int is_double_width(uint32_t ucs)
2178 return bisearch(ucs, double_width, ARRAY_SIZE(double_width) - 1); 2164 return bisearch(ucs, double_width, ARRAY_SIZE(double_width) - 1);
2179} 2165}
2180 2166
2167static void con_flush(struct vc_data *vc, unsigned long draw_from,
2168 unsigned long draw_to, int *draw_x)
2169{
2170 if (*draw_x < 0)
2171 return;
2172
2173 vc->vc_sw->con_putcs(vc, (u16 *)draw_from,
2174 (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, *draw_x);
2175 *draw_x = -1;
2176}
2177
2181/* acquires console_lock */ 2178/* acquires console_lock */
2182static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count) 2179static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count)
2183{ 2180{
2184#ifdef VT_BUF_VRAM_ONLY
2185#define FLUSH do { } while(0);
2186#else
2187#define FLUSH if (draw_x >= 0) { \
2188 vc->vc_sw->con_putcs(vc, (u16 *)draw_from, (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, draw_x); \
2189 draw_x = -1; \
2190 }
2191#endif
2192
2193 int c, tc, ok, n = 0, draw_x = -1; 2181 int c, tc, ok, n = 0, draw_x = -1;
2194 unsigned int currcons; 2182 unsigned int currcons;
2195 unsigned long draw_from = 0, draw_to = 0; 2183 unsigned long draw_from = 0, draw_to = 0;
@@ -2226,7 +2214,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
2226 charmask = himask ? 0x1ff : 0xff; 2214 charmask = himask ? 0x1ff : 0xff;
2227 2215
2228 /* undraw cursor first */ 2216 /* undraw cursor first */
2229 if (IS_FG(vc)) 2217 if (con_is_fg(vc))
2230 hide_cursor(vc); 2218 hide_cursor(vc);
2231 2219
2232 param.vc = vc; 2220 param.vc = vc;
@@ -2381,12 +2369,13 @@ rescan_last_byte:
2381 } else { 2369 } else {
2382 vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4); 2370 vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4);
2383 } 2371 }
2384 FLUSH 2372 con_flush(vc, draw_from, draw_to, &draw_x);
2385 } 2373 }
2386 2374
2387 while (1) { 2375 while (1) {
2388 if (vc->vc_need_wrap || vc->vc_decim) 2376 if (vc->vc_need_wrap || vc->vc_decim)
2389 FLUSH 2377 con_flush(vc, draw_from, draw_to,
2378 &draw_x);
2390 if (vc->vc_need_wrap) { 2379 if (vc->vc_need_wrap) {
2391 cr(vc); 2380 cr(vc);
2392 lf(vc); 2381 lf(vc);
@@ -2397,7 +2386,7 @@ rescan_last_byte:
2397 ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) : 2386 ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
2398 (vc_attr << 8) + tc, 2387 (vc_attr << 8) + tc,
2399 (u16 *) vc->vc_pos); 2388 (u16 *) vc->vc_pos);
2400 if (DO_UPDATE(vc) && draw_x < 0) { 2389 if (con_should_update(vc) && draw_x < 0) {
2401 draw_x = vc->vc_x; 2390 draw_x = vc->vc_x;
2402 draw_from = vc->vc_pos; 2391 draw_from = vc->vc_pos;
2403 } 2392 }
@@ -2416,9 +2405,8 @@ rescan_last_byte:
2416 } 2405 }
2417 notify_write(vc, c); 2406 notify_write(vc, c);
2418 2407
2419 if (inverse) { 2408 if (inverse)
2420 FLUSH 2409 con_flush(vc, draw_from, draw_to, &draw_x);
2421 }
2422 2410
2423 if (rescan) { 2411 if (rescan) {
2424 rescan = 0; 2412 rescan = 0;
@@ -2429,15 +2417,14 @@ rescan_last_byte:
2429 } 2417 }
2430 continue; 2418 continue;
2431 } 2419 }
2432 FLUSH 2420 con_flush(vc, draw_from, draw_to, &draw_x);
2433 do_con_trol(tty, vc, orig); 2421 do_con_trol(tty, vc, orig);
2434 } 2422 }
2435 FLUSH 2423 con_flush(vc, draw_from, draw_to, &draw_x);
2436 console_conditional_schedule(); 2424 console_conditional_schedule();
2437 console_unlock(); 2425 console_unlock();
2438 notify_update(vc); 2426 notify_update(vc);
2439 return n; 2427 return n;
2440#undef FLUSH
2441} 2428}
2442 2429
2443/* 2430/*
@@ -2471,7 +2458,7 @@ static void console_callback(struct work_struct *ignored)
2471 if (scrollback_delta) { 2458 if (scrollback_delta) {
2472 struct vc_data *vc = vc_cons[fg_console].d; 2459 struct vc_data *vc = vc_cons[fg_console].d;
2473 clear_selection(); 2460 clear_selection();
2474 if (vc->vc_mode == KD_TEXT) 2461 if (vc->vc_mode == KD_TEXT && vc->vc_sw->con_scrolldelta)
2475 vc->vc_sw->con_scrolldelta(vc, scrollback_delta); 2462 vc->vc_sw->con_scrolldelta(vc, scrollback_delta);
2476 scrollback_delta = 0; 2463 scrollback_delta = 0;
2477 } 2464 }
@@ -2583,7 +2570,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
2583 goto quit; 2570 goto quit;
2584 2571
2585 /* undraw cursor first */ 2572 /* undraw cursor first */
2586 if (IS_FG(vc)) 2573 if (con_is_fg(vc))
2587 hide_cursor(vc); 2574 hide_cursor(vc);
2588 2575
2589 start = (ushort *)vc->vc_pos; 2576 start = (ushort *)vc->vc_pos;
@@ -2594,7 +2581,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
2594 c = *b++; 2581 c = *b++;
2595 if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) { 2582 if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
2596 if (cnt > 0) { 2583 if (cnt > 0) {
2597 if (CON_IS_VISIBLE(vc)) 2584 if (con_is_visible(vc))
2598 vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x); 2585 vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
2599 vc->vc_x += cnt; 2586 vc->vc_x += cnt;
2600 if (vc->vc_need_wrap) 2587 if (vc->vc_need_wrap)
@@ -2626,7 +2613,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
2626 myx++; 2613 myx++;
2627 } 2614 }
2628 if (cnt > 0) { 2615 if (cnt > 0) {
2629 if (CON_IS_VISIBLE(vc)) 2616 if (con_is_visible(vc))
2630 vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x); 2617 vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
2631 vc->vc_x += cnt; 2618 vc->vc_x += cnt;
2632 if (vc->vc_x == vc->vc_cols) { 2619 if (vc->vc_x == vc->vc_cols) {
@@ -3173,7 +3160,7 @@ static int do_bind_con_driver(const struct consw *csw, int first, int last,
3173 3160
3174 j = i; 3161 j = i;
3175 3162
3176 if (CON_IS_VISIBLE(vc)) { 3163 if (con_is_visible(vc)) {
3177 k = i; 3164 k = i;
3178 save_screen(vc); 3165 save_screen(vc);
3179 } 3166 }
@@ -3981,7 +3968,7 @@ static void set_palette(struct vc_data *vc)
3981{ 3968{
3982 WARN_CONSOLE_UNLOCKED(); 3969 WARN_CONSOLE_UNLOCKED();
3983 3970
3984 if (vc->vc_mode != KD_GRAPHICS) 3971 if (vc->vc_mode != KD_GRAPHICS && vc->vc_sw->con_set_palette)
3985 vc->vc_sw->con_set_palette(vc, color_table); 3972 vc->vc_sw->con_set_palette(vc, color_table);
3986} 3973}
3987 3974
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c
index 97d5a74558a3..f62c598810ff 100644
--- a/drivers/tty/vt/vt_ioctl.c
+++ b/drivers/tty/vt/vt_ioctl.c
@@ -1006,16 +1006,10 @@ int vt_ioctl(struct tty_struct *tty,
1006 break; 1006 break;
1007 1007
1008 case PIO_UNIMAPCLR: 1008 case PIO_UNIMAPCLR:
1009 { struct unimapinit ui;
1010 if (!perm) 1009 if (!perm)
1011 return -EPERM; 1010 return -EPERM;
1012 ret = copy_from_user(&ui, up, sizeof(struct unimapinit)); 1011 con_clear_unimap(vc);
1013 if (ret)
1014 ret = -EFAULT;
1015 else
1016 con_clear_unimap(vc, &ui);
1017 break; 1012 break;
1018 }
1019 1013
1020 case PIO_UNIMAP: 1014 case PIO_UNIMAP:
1021 case GIO_UNIMAP: 1015 case GIO_UNIMAP: