History

Merge tag 'tty-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty

Pull tty/serial updates from Greg KH: "Here is the large set of TTY and Serial driver patches for 5.9-rc1. Lots of bugfixes in here, thanks to syzbot fuzzing for serial and vt and console code. Other highlights include: - much needed vt/vc code cleanup from Jiri Slaby - 8250 driver fixes and additions - various serial driver updates and feature enhancements - locking cleanup for serial/console initializations - other minor cleanups All of these have been in linux-next with no reported issues" * tag 'tty-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (90 commits) MAINTAINERS: enlist Greg formally for console stuff vgacon: Fix for missing check in scrollback handling Revert "serial: 8250: Let serial core initialise spin lock" serial: 8250: Let serial core initialise spin lock tty: keyboard, do not speculate on func_table index serial: stm32: Add RS485 RTS GPIO control serial: 8250_dw: Fix common clocks usage race condition serial: 8250_dw: Pass the same rate to the clk round and set rate methods serial: 8250_dw: Simplify the ref clock rate setting procedure serial: 8250: Add 8250 port clock update method tty: serial: imx: add imx earlycon driver tty: serial: imx: enable imx serial console port as module tty/synclink: remove leftover bits of non-PCI card support tty: Use the preferred form for passing the size of a structure type tty: Fix identation issues in struct serial_struct32 tty: Avoid the use of one-element arrays serial: msm_serial: add sparse context annotation serial: pmac_zilog: add sparse context annotation newport_con: vc_color is now in state serial: imx: use hrtimers for rs485 delays ...

Linus Torvalds committed 6 years ago

Commit d6efb3a2 parents c0c419c f6c6eb263 files · +1847 −1613Browse files

Unified · Split

63 files
  1. Documentation/devicetree/bindings/serial/st,stm32-uart.yaml +3 −1
  2. Documentation/driver-api/serial/n_gsm.rst +1 −1
  3. MAINTAINERS +6 −0
  4. arch/um/drivers/line.c +0 −5
  5. arch/um/drivers/line.h +0 −1
  6. arch/um/drivers/ssl.c +0 −1
  7. arch/um/drivers/stdio_console.c +0 −1
  8. drivers/accessibility/braille/braille_console.c +5 −5
  9. drivers/accessibility/speakup/main.c +14 −14
  10. drivers/tty/moxa.h +1 −1
  11. drivers/tty/serial/8250/8250_dw.c +106 −14
  12. drivers/tty/serial/8250/8250_em.c +10 −6
  13. drivers/tty/serial/8250/8250_ingenic.c +10 −6
  14. drivers/tty/serial/8250/8250_men_mcb.c +2 −2
  15. drivers/tty/serial/8250/8250_mtk.c +10 −6
  16. drivers/tty/serial/8250/8250_omap.c +10 −6
  17. drivers/tty/serial/8250/8250_port.c +41 −0
  18. drivers/tty/serial/8250/8250_pxa.c +8 −6
  19. drivers/tty/serial/8250/Kconfig +2 −2
  20. drivers/tty/serial/Kconfig +12 −5
  21. drivers/tty/serial/altera_jtaguart.c +1 −1
  22. drivers/tty/serial/amba-pl011.c +0 −1
  23. drivers/tty/serial/fsl_lpuart.c +3 −0
  24. drivers/tty/serial/imx.c +133 −74
  25. drivers/tty/serial/imx_earlycon.c +50 −0
  26. drivers/tty/serial/jsm/jsm_driver.c +1 −1
  27. drivers/tty/serial/kgdboc.c +2 −1
  28. drivers/tty/serial/msm_serial.c +2 −0
  29. drivers/tty/serial/pch_uart.c +10 −24
  30. drivers/tty/serial/pmac_zilog.c +1 −0
  31. drivers/tty/serial/qcom_geni_serial.c +1 −1
  32. drivers/tty/serial/samsung_tty.c +10 −14
  33. drivers/tty/serial/serial-tegra.c +3 −3
  34. drivers/tty/serial/serial_core.c +4 −1
  35. drivers/tty/serial/sh-sci.c +0 −3
  36. drivers/tty/serial/sifive.c +0 −1
  37. drivers/tty/serial/stm32-usart.c +11 −2
  38. drivers/tty/serial/sunhv.c +0 −3
  39. drivers/tty/serial/uartlite.c +1 −1
  40. drivers/tty/synclink.c +109 −241
  41. drivers/tty/tty_io.c +26 −26
  42. drivers/tty/vt/consolemap.c +1 −1
  43. drivers/tty/vt/keyboard.c +2 −1
  44. drivers/tty/vt/selection.c +1 −1
  45. drivers/tty/vt/vt.c +533 −449
  46. drivers/tty/vt/vt_ioctl.c +557 −552
  47. drivers/usb/misc/sisusbvga/sisusb_con.c +6 −5
  48. drivers/video/console/mdacon.c +11 −9
  49. drivers/video/console/newport_con.c +5 −5
  50. drivers/video/console/sticon.c +8 −6
  51. drivers/video/console/vgacon.c +23 −17
  52. drivers/video/fbdev/core/bitblit.c +5 −5
  53. drivers/video/fbdev/core/fbcon.c +5 −5
  54. drivers/video/fbdev/core/fbcon_ccw.c +4 −4
  55. drivers/video/fbdev/core/fbcon_cw.c +4 −4
  56. drivers/video/fbdev/core/fbcon_ud.c +4 −4
  57. drivers/video/fbdev/core/tileblit.c +3 −3
  58. include/linux/console.h +5 −8
  59. include/linux/console_struct.h +58 −35
  60. include/linux/serial_8250.h +2 −0
  61. include/linux/serial_core.h +1 −1
  62. include/linux/vt_kern.h +0 −3
  63. include/uapi/linux/serial_core.h +0 −14
Documentation/devicetree/bindings/serial/st,stm32-uart.yaml+3−1
@@ -35,9 +35,11 @@ properties: · 34 unmodified lines
35 description: label associated with this uart35 description: label associated with this uart
36 36
37 st,hw-flow-ctrl:37 st,hw-flow-ctrl:
38 description: enable hardware flow control38 description: enable hardware flow control (deprecated)
39 $ref: /schemas/types.yaml#/definitions/flag39 $ref: /schemas/types.yaml#/definitions/flag
40 40
41 uart-has-rtscts: true
42
41 dmas:43 dmas:
42 minItems: 144 minItems: 1
43 maxItems: 245 maxItems: 2
Documentation/driver-api/serial/n_gsm.rst+1−1
@@ -5,7 +5,7 @@ GSM 0710 tty multiplexor HOWTO · 4 unmodified lines
5This line discipline implements the GSM 07.10 multiplexing protocol5This line discipline implements the GSM 07.10 multiplexing protocol
6detailed in the following 3GPP document:6detailed in the following 3GPP document:
7 7
8 http://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip8 https://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
9 9
10This document give some hints on how to use this driver with GPRS and 3G10This document give some hints on how to use this driver with GPRS and 3G
11modems connected to a physical serial port.11modems connected to a physical serial port.
MAINTAINERS+6−0
@@ -4386,6 +4386,12 @@ L: netdev@vger.kernel.org · 4385 unmodified lines
4386S: Maintained4386S: Maintained
4387F: drivers/connector/4387F: drivers/connector/
4388 4388
4389CONSOLE SUBSYSTEM
4390M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
4391S: Supported
4392F: drivers/video/console/
4393F: include/linux/console*
4394
4389CONTROL GROUP (CGROUP)4395CONTROL GROUP (CGROUP)
4390M: Tejun Heo <tj@kernel.org>4396M: Tejun Heo <tj@kernel.org>
4391M: Li Zefan <lizefan@huawei.com>4397M: Li Zefan <lizefan@huawei.com>
arch/um/drivers/line.c+0−5
@@ -184,11 +184,6 @@ void line_flush_chars(struct tty_struct *tty) · 183 unmodified lines
184 line_flush_buffer(tty);184 line_flush_buffer(tty);
185}185}
186 186
187int line_put_char(struct tty_struct *tty, unsigned char ch)
188{
189 return line_write(tty, &ch, sizeof(ch));
190}
191
192int line_write(struct tty_struct *tty, const unsigned char *buf, int len)187int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
193{188{
194 struct line *line = tty->driver_data;189 struct line *line = tty->driver_data;
arch/um/drivers/line.h+0−1
@@ -66,7 +66,6 @@ extern int line_setup(char **conf, unsigned nlines, char **def, · 65 unmodified lines
66 char *init, char *name);66 char *init, char *name);
67extern int line_write(struct tty_struct *tty, const unsigned char *buf,67extern int line_write(struct tty_struct *tty, const unsigned char *buf,
68 int len);68 int len);
69extern int line_put_char(struct tty_struct *tty, unsigned char ch);
70extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);69extern void line_set_termios(struct tty_struct *tty, struct ktermios * old);
71extern int line_chars_in_buffer(struct tty_struct *tty);70extern int line_chars_in_buffer(struct tty_struct *tty);
72extern void line_flush_buffer(struct tty_struct *tty);71extern void line_flush_buffer(struct tty_struct *tty);
arch/um/drivers/ssl.c+0−1
@@ -95,7 +95,6 @@ static const struct tty_operations ssl_ops = { · 94 unmodified lines
95 .open = line_open,95 .open = line_open,
96 .close = line_close,96 .close = line_close,
97 .write = line_write,97 .write = line_write,
98 .put_char = line_put_char,
99 .write_room = line_write_room,98 .write_room = line_write_room,
100 .chars_in_buffer = line_chars_in_buffer,99 .chars_in_buffer = line_chars_in_buffer,
101 .flush_buffer = line_flush_buffer,100 .flush_buffer = line_flush_buffer,
arch/um/drivers/stdio_console.c+0−1
@@ -102,7 +102,6 @@ static const struct tty_operations console_ops = { · 101 unmodified lines
102 .install = con_install,102 .install = con_install,
103 .close = line_close,103 .close = line_close,
104 .write = line_write,104 .write = line_write,
105 .put_char = line_put_char,
106 .write_room = line_write_room,105 .write_room = line_write_room,
107 .chars_in_buffer = line_chars_in_buffer,106 .chars_in_buffer = line_chars_in_buffer,
108 .flush_buffer = line_flush_buffer,107 .flush_buffer = line_flush_buffer,
drivers/accessibility/braille/braille_console.c+5−5
@@ -109,16 +109,16 @@ static void braille_write(u16 *buf) · 108 unmodified lines
109/* Follow the VC cursor*/109/* Follow the VC cursor*/
110static void vc_follow_cursor(struct vc_data *vc)110static void vc_follow_cursor(struct vc_data *vc)
111{111{
112 vc_x = vc->vc_x - (vc->vc_x % WIDTH);112 vc_x = vc->state.x - (vc->state.x % WIDTH);
113 vc_y = vc->vc_y;113 vc_y = vc->state.y;
114 lastvc_x = vc->vc_x;114 lastvc_x = vc->state.x;
115 lastvc_y = vc->vc_y;115 lastvc_y = vc->state.y;
116}116}
117 117
118/* Maybe the VC cursor moved, if so follow it */118/* Maybe the VC cursor moved, if so follow it */
119static void vc_maybe_cursor_moved(struct vc_data *vc)119static void vc_maybe_cursor_moved(struct vc_data *vc)
120{120{
121 if (vc->vc_x != lastvc_x || vc->vc_y != lastvc_y)121 if (vc->state.x != lastvc_x || vc->state.y != lastvc_y)
122 vc_follow_cursor(vc);122 vc_follow_cursor(vc);
123}123}
124 124
drivers/accessibility/speakup/main.c+14−14
@@ -263,8 +263,8 @@ static unsigned char get_attributes(struct vc_data *vc, u16 *pos) · 262 unmodified lines
263 263
264static void speakup_date(struct vc_data *vc)264static void speakup_date(struct vc_data *vc)
265{265{
266 spk_x = spk_cx = vc->vc_x;266 spk_x = spk_cx = vc->state.x;
267 spk_y = spk_cy = vc->vc_y;267 spk_y = spk_cy = vc->state.y;
268 spk_pos = spk_cp = vc->vc_pos;268 spk_pos = spk_cp = vc->vc_pos;
269 spk_old_attr = spk_attr;269 spk_old_attr = spk_attr;
270 spk_attr = get_attributes(vc, (u_short *)spk_pos);270 spk_attr = get_attributes(vc, (u_short *)spk_pos);
@@ -1551,9 +1551,9 @@ static void do_handle_cursor(struct vc_data *vc, u_char value, char up_flag) · 1280 unmodified lines
1551 */1551 */
1552 is_cursor = value + 1;1552 is_cursor = value + 1;
1553 old_cursor_pos = vc->vc_pos;1553 old_cursor_pos = vc->vc_pos;
1554 old_cursor_x = vc->vc_x;1554 old_cursor_x = vc->state.x;
1555 old_cursor_y = vc->vc_y;1555 old_cursor_y = vc->state.y;
1556 speakup_console[vc->vc_num]->ht.cy = vc->vc_y;1556 speakup_console[vc->vc_num]->ht.cy = vc->state.y;
1557 cursor_con = vc->vc_num;1557 cursor_con = vc->vc_num;
1558 if (cursor_track == CT_Highlight)1558 if (cursor_track == CT_Highlight)
1559 reset_highlight_buffers(vc);1559 reset_highlight_buffers(vc);
@@ -1574,8 +1574,8 @@ static void update_color_buffer(struct vc_data *vc, const u16 *ic, int len) · 14 unmodified lines
1574 i = 0;1574 i = 0;
1575 if (speakup_console[vc_num]->ht.highsize[bi] == 0) {1575 if (speakup_console[vc_num]->ht.highsize[bi] == 0) {
1576 speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;1576 speakup_console[vc_num]->ht.rpos[bi] = vc->vc_pos;
1577 speakup_console[vc_num]->ht.rx[bi] = vc->vc_x;1577 speakup_console[vc_num]->ht.rx[bi] = vc->state.x;
1578 speakup_console[vc_num]->ht.ry[bi] = vc->vc_y;1578 speakup_console[vc_num]->ht.ry[bi] = vc->state.y;
1579 }1579 }
1580 while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {1580 while ((hi < COLOR_BUFFER_SIZE) && (i < len)) {
1581 if (ic[i] > 32) {1581 if (ic[i] > 32) {
@@ -1664,9 +1664,9 @@ static int speak_highlight(struct vc_data *vc) · 82 unmodified lines
1664 return 0;1664 return 0;
1665 hc = get_highlight_color(vc);1665 hc = get_highlight_color(vc);
1666 if (hc != -1) {1666 if (hc != -1) {
1667 d = vc->vc_y - speakup_console[vc_num]->ht.cy;1667 d = vc->state.y - speakup_console[vc_num]->ht.cy;
1668 if ((d == 1) || (d == -1))1668 if ((d == 1) || (d == -1))
1669 if (speakup_console[vc_num]->ht.ry[hc] != vc->vc_y)1669 if (speakup_console[vc_num]->ht.ry[hc] != vc->state.y)
1670 return 0;1670 return 0;
1671 spk_parked |= 0x01;1671 spk_parked |= 0x01;
1672 spk_do_flush();1672 spk_do_flush();
@@ -1693,8 +1693,8 @@ static void cursor_done(struct timer_list *unused) · 20 unmodified lines
1693 }1693 }
1694 speakup_date(vc);1694 speakup_date(vc);
1695 if (win_enabled) {1695 if (win_enabled) {
1696 if (vc->vc_x >= win_left && vc->vc_x <= win_right &&1696 if (vc->state.x >= win_left && vc->state.x <= win_right &&
1697 vc->vc_y >= win_top && vc->vc_y <= win_bottom) {1697 vc->state.y >= win_top && vc->state.y <= win_bottom) {
1698 spk_keydown = 0;1698 spk_keydown = 0;
1699 is_cursor = 0;1699 is_cursor = 0;
1700 goto out;1700 goto out;
@@ -1757,7 +1757,7 @@ static void speakup_con_write(struct vc_data *vc, u16 *str, int len) · 56 unmodified lines
1757 if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))1757 if (!spin_trylock_irqsave(&speakup_info.spinlock, flags))
1758 /* Speakup output, discard */1758 /* Speakup output, discard */
1759 return;1759 return;
1760 if (spk_bell_pos && spk_keydown && (vc->vc_x == spk_bell_pos - 1))1760 if (spk_bell_pos && spk_keydown && (vc->state.x == spk_bell_pos - 1))
1761 bleep(3);1761 bleep(3);
1762 if ((is_cursor) || (cursor_track == read_all_mode)) {1762 if ((is_cursor) || (cursor_track == read_all_mode)) {
1763 if (cursor_track == CT_Highlight)1763 if (cursor_track == CT_Highlight)
@@ -1766,8 +1766,8 @@ static void speakup_con_write(struct vc_data *vc, u16 *str, int len) · 2 unmodified lines
1766 return;1766 return;
1767 }1767 }
1768 if (win_enabled) {1768 if (win_enabled) {
1769 if (vc->vc_x >= win_left && vc->vc_x <= win_right &&1769 if (vc->state.x >= win_left && vc->state.x <= win_right &&
1770 vc->vc_y >= win_top && vc->vc_y <= win_bottom) {1770 vc->state.y >= win_top && vc->state.y <= win_bottom) {
1771 spin_unlock_irqrestore(&speakup_info.spinlock, flags);1771 spin_unlock_irqrestore(&speakup_info.spinlock, flags);
1772 return;1772 return;
1773 }1773 }
drivers/tty/moxa.h+1−1
@@ -138,7 +138,7 @@ · 137 unmodified lines
138#define IntrQuit 0x40 /* received QUIT code */138#define IntrQuit 0x40 /* received QUIT code */
139#define IntrEOF 0x80 /* received EOF code */139#define IntrEOF 0x80 /* received EOF code */
140 140
141#define IntrRxTrigger 0x100 /* rx data count reach tigger value */141#define IntrRxTrigger 0x100 /* rx data count reach trigger value */
142#define IntrTxTrigger 0x200 /* tx data count below trigger value */142#define IntrTxTrigger 0x200 /* tx data count below trigger value */
143 143
144#define Magic_no (Config_base + 0)144#define Magic_no (Config_base + 0)
drivers/tty/serial/8250/8250_dw.c+106−14
@@ -19,6 +19,8 @@ · 18 unmodified lines
19#include <linux/of_irq.h>19#include <linux/of_irq.h>
20#include <linux/of_platform.h>20#include <linux/of_platform.h>
21#include <linux/platform_device.h>21#include <linux/platform_device.h>
22#include <linux/workqueue.h>
23#include <linux/notifier.h>
22#include <linux/slab.h>24#include <linux/slab.h>
23#include <linux/acpi.h>25#include <linux/acpi.h>
24#include <linux/clk.h>26#include <linux/clk.h>
@@ -43,6 +45,8 @@ struct dw8250_data { · 18 unmodified lines
43 int msr_mask_off;45 int msr_mask_off;
44 struct clk *clk;46 struct clk *clk;
45 struct clk *pclk;47 struct clk *pclk;
48 struct notifier_block clk_notifier;
49 struct work_struct clk_work;
46 struct reset_control *rst;50 struct reset_control *rst;
47 51
48 unsigned int skip_autocfg:1;52 unsigned int skip_autocfg:1;
@@ -54,6 +58,16 @@ static inline struct dw8250_data *to_dw8250_data(struct dw8250_port_data *data) · 5 unmodified lines
54 return container_of(data, struct dw8250_data, data);58 return container_of(data, struct dw8250_data, data);
55}59}
56 60
61static inline struct dw8250_data *clk_to_dw8250_data(struct notifier_block *nb)
62{
63 return container_of(nb, struct dw8250_data, clk_notifier);
64}
65
66static inline struct dw8250_data *work_to_dw8250_data(struct work_struct *work)
67{
68 return container_of(work, struct dw8250_data, clk_work);
69}
70
57static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)71static inline int dw8250_modify_msr(struct uart_port *p, int offset, int value)
58{72{
59 struct dw8250_data *d = to_dw8250_data(p->private_data);73 struct dw8250_data *d = to_dw8250_data(p->private_data);
@@ -260,6 +274,46 @@ static int dw8250_handle_irq(struct uart_port *p) · 200 unmodified lines
260 return 0;274 return 0;
261}275}
262 276
277static void dw8250_clk_work_cb(struct work_struct *work)
278{
279 struct dw8250_data *d = work_to_dw8250_data(work);
280 struct uart_8250_port *up;
281 unsigned long rate;
282
283 rate = clk_get_rate(d->clk);
284 if (rate <= 0)
285 return;
286
287 up = serial8250_get_port(d->data.line);
288
289 serial8250_update_uartclk(&up->port, rate);
290}
291
292static int dw8250_clk_notifier_cb(struct notifier_block *nb,
293 unsigned long event, void *data)
294{
295 struct dw8250_data *d = clk_to_dw8250_data(nb);
296
297 /*
298 * We have no choice but to defer the uartclk update due to two
299 * deadlocks. First one is caused by a recursive mutex lock which
300 * happens when clk_set_rate() is called from dw8250_set_termios().
301 * Second deadlock is more tricky and is caused by an inverted order of
302 * the clk and tty-port mutexes lock. It happens if clock rate change
303 * is requested asynchronously while set_termios() is executed between
304 * tty-port mutex lock and clk_set_rate() function invocation and
305 * vise-versa. Anyway if we didn't have the reference clock alteration
306 * in the dw8250_set_termios() method we wouldn't have needed this
307 * deferred event handling complication.
308 */
309 if (event == POST_RATE_CHANGE) {
310 queue_work(system_unbound_wq, &d->clk_work);
311 return NOTIFY_OK;
312 }
313
314 return NOTIFY_DONE;
315}
316
263static void317static void
264dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)318dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old)
265{319{
@@ -275,27 +329,27 @@ dw8250_do_pm(struct uart_port *port, unsigned int state, unsigned int old) · 9 unmodified lines
275static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,329static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios,
276 struct ktermios *old)330 struct ktermios *old)
277{331{
278 unsigned int baud = tty_termios_baud_rate(termios);332 unsigned long newrate = tty_termios_baud_rate(termios) * 16;
279 struct dw8250_data *d = to_dw8250_data(p->private_data);333 struct dw8250_data *d = to_dw8250_data(p->private_data);
280 long rate;334 long rate;
281 int ret;335 int ret;
282 336
283 clk_disable_unprepare(d->clk);337 clk_disable_unprepare(d->clk);
284 rate = clk_round_rate(d->clk, baud * 16);338 rate = clk_round_rate(d->clk, newrate);
285 if (rate < 0)339 if (rate > 0) {
286 ret = rate;340 /*
287 else if (rate == 0)341 * Premilinary set the uartclk to the new clock rate so the
288 ret = -ENOENT;342 * clock update event handler caused by the clk_set_rate()
289 else343 * calling wouldn't actually update the UART divisor since
290 ret = clk_set_rate(d->clk, rate);344 * we about to do this anyway.
345 */
346 swap(p->uartclk, rate);
347 ret = clk_set_rate(d->clk, newrate);
348 if (ret)
349 swap(p->uartclk, rate);
350 }
291 clk_prepare_enable(d->clk);351 clk_prepare_enable(d->clk);
292 352
293 if (ret)
294 goto out;
295
296 p->uartclk = rate;
297
298out:
299 p->status &= ~UPSTAT_AUTOCTS;353 p->status &= ~UPSTAT_AUTOCTS;
300 if (termios->c_cflag & CRTSCTS)354 if (termios->c_cflag & CRTSCTS)
301 p->status |= UPSTAT_AUTOCTS;355 p->status |= UPSTAT_AUTOCTS;
@@ -319,6 +373,39 @@ static void dw8250_set_ldisc(struct uart_port *p, struct ktermios *termios) · 17 unmodified lines
319 serial8250_do_set_ldisc(p, termios);373 serial8250_do_set_ldisc(p, termios);
320}374}
321 375
376static int dw8250_startup(struct uart_port *p)
377{
378 struct dw8250_data *d = to_dw8250_data(p->private_data);
379 int ret;
380
381 /*
382 * Some platforms may provide a reference clock shared between several
383 * devices. In this case before using the serial port first we have to
384 * make sure that any clock state change is known to the UART port at
385 * least post factum.
386 */
387 if (d->clk) {
388 ret = clk_notifier_register(d->clk, &d->clk_notifier);
389 if (ret)
390 dev_warn(p->dev, "Failed to set the clock notifier\n");
391 }
392
393 return serial8250_do_startup(p);
394}
395
396static void dw8250_shutdown(struct uart_port *p)
397{
398 struct dw8250_data *d = to_dw8250_data(p->private_data);
399
400 serial8250_do_shutdown(p);
401
402 if (d->clk) {
403 clk_notifier_unregister(d->clk, &d->clk_notifier);
404
405 flush_work(&d->clk_work);
406 }
407}
408
322/*409/*
323 * dw8250_fallback_dma_filter will prevent the UART from getting just any free410 * dw8250_fallback_dma_filter will prevent the UART from getting just any free
324 * channel on platforms that have DMA engines, but don't have any channels411 * channel on platforms that have DMA engines, but don't have any channels
@@ -414,6 +501,8 @@ static int dw8250_probe(struct platform_device *pdev) · 89 unmodified lines
414 p->serial_out = dw8250_serial_out;501 p->serial_out = dw8250_serial_out;
415 p->set_ldisc = dw8250_set_ldisc;502 p->set_ldisc = dw8250_set_ldisc;
416 p->set_termios = dw8250_set_termios;503 p->set_termios = dw8250_set_termios;
504 p->startup = dw8250_startup;
505 p->shutdown = dw8250_shutdown;
417 506
418 p->membase = devm_ioremap(dev, regs->start, resource_size(regs));507 p->membase = devm_ioremap(dev, regs->start, resource_size(regs));
419 if (!p->membase)508 if (!p->membase)
@@ -475,6 +564,9 @@ static int dw8250_probe(struct platform_device *pdev) · 55 unmodified lines
475 if (IS_ERR(data->clk))564 if (IS_ERR(data->clk))
476 return PTR_ERR(data->clk);565 return PTR_ERR(data->clk);
477 566
567 INIT_WORK(&data->clk_work, dw8250_clk_work_cb);
568 data->clk_notifier.notifier_call = dw8250_clk_notifier_cb;
569
478 err = clk_prepare_enable(data->clk);570 err = clk_prepare_enable(data->clk);
479 if (err)571 if (err)
480 dev_warn(dev, "could not enable optional baudclk: %d\n", err);572 dev_warn(dev, "could not enable optional baudclk: %d\n", err);
drivers/tty/serial/8250/8250_em.c+10−6
@@ -78,14 +78,18 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, int value) · 77 unmodified lines
78 78
79static int serial8250_em_probe(struct platform_device *pdev)79static int serial8250_em_probe(struct platform_device *pdev)
80{80{
81 struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
82 struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
83 struct serial8250_em_priv *priv;81 struct serial8250_em_priv *priv;
84 struct uart_8250_port up;82 struct uart_8250_port up;
85 int ret;83 struct resource *regs;
84 int irq, ret;
86 85
87 if (!regs || !irq) {86 irq = platform_get_irq(pdev, 0);
88 dev_err(&pdev->dev, "missing registers or irq\n");87 if (irq < 0)
88 return irq;
89
90 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
91 if (!regs) {
92 dev_err(&pdev->dev, "missing registers\n");
89 return -EINVAL;93 return -EINVAL;
90 }94 }
91 95
@@ -101,7 +105,7 @@ static int serial8250_em_probe(struct platform_device *pdev) · 9 unmodified lines
101 105
102 memset(&up, 0, sizeof(up));106 memset(&up, 0, sizeof(up));
103 up.port.mapbase = regs->start;107 up.port.mapbase = regs->start;
104 up.port.irq = irq->start;108 up.port.irq = irq;
105 up.port.type = PORT_UNKNOWN;109 up.port.type = PORT_UNKNOWN;
106 up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;110 up.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT | UPF_IOREMAP;
107 up.port.dev = &pdev->dev;111 up.port.dev = &pdev->dev;
drivers/tty/serial/8250/8250_ingenic.c+10−6
@@ -207,12 +207,11 @@ static unsigned int ingenic_uart_serial_in(struct uart_port *p, int offset) · 206 unmodified lines
207static int ingenic_uart_probe(struct platform_device *pdev)207static int ingenic_uart_probe(struct platform_device *pdev)
208{208{
209 struct uart_8250_port uart = {};209 struct uart_8250_port uart = {};
210 struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
211 struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
212 struct ingenic_uart_data *data;210 struct ingenic_uart_data *data;
213 const struct ingenic_uart_config *cdata;211 const struct ingenic_uart_config *cdata;
214 const struct of_device_id *match;212 const struct of_device_id *match;
215 int err, line;213 struct resource *regs;
214 int irq, err, line;
216 215
217 match = of_match_device(of_match, &pdev->dev);216 match = of_match_device(of_match, &pdev->dev);
218 if (!match) {217 if (!match) {
@@ -221,8 +220,13 @@ static int ingenic_uart_probe(struct platform_device *pdev) · 2 unmodified lines
221 }220 }
222 cdata = match->data;221 cdata = match->data;
223 222
224 if (!regs || !irq) {223 irq = platform_get_irq(pdev, 0);
225 dev_err(&pdev->dev, "no registers/irq defined\n");224 if (irq < 0)
225 return irq;
226
227 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
228 if (!regs) {
229 dev_err(&pdev->dev, "no registers defined\n");
226 return -EINVAL;230 return -EINVAL;
227 }231 }
228 232
@@ -238,7 +242,7 @@ static int ingenic_uart_probe(struct platform_device *pdev) · 9 unmodified lines
238 uart.port.regshift = 2;242 uart.port.regshift = 2;
239 uart.port.serial_out = ingenic_uart_serial_out;243 uart.port.serial_out = ingenic_uart_serial_out;
240 uart.port.serial_in = ingenic_uart_serial_in;244 uart.port.serial_in = ingenic_uart_serial_in;
241 uart.port.irq = irq->start;245 uart.port.irq = irq;
242 uart.port.dev = &pdev->dev;246 uart.port.dev = &pdev->dev;
243 uart.port.fifosize = cdata->fifosize;247 uart.port.fifosize = cdata->fifosize;
244 uart.tx_loadsz = cdata->tx_loadsz;248 uart.tx_loadsz = cdata->tx_loadsz;
drivers/tty/serial/8250/8250_men_mcb.c+2−2
@@ -51,7 +51,7 @@ static u32 men_lookup_uartclk(struct mcb_device *mdev) · 50 unmodified lines
51 return clkval;51 return clkval;
52}52}
53 53
54static unsigned int get_num_ports(struct mcb_device *mdev,54static int get_num_ports(struct mcb_device *mdev,
55 void __iomem *membase)55 void __iomem *membase)
56{56{
57 switch (mdev->id) {57 switch (mdev->id) {
@@ -140,7 +140,7 @@ static void serial_8250_men_mcb_remove(struct mcb_device *mdev) · 82 unmodified lines
140 return;140 return;
141 141
142 num_ports = get_num_ports(mdev, data[0].uart.port.membase);142 num_ports = get_num_ports(mdev, data[0].uart.port.membase);
143 if (num_ports < 0 || num_ports > 4) {143 if (num_ports <= 0 || num_ports > 4) {
144 dev_err(&mdev->dev, "error retrieving number of ports!\n");144 dev_err(&mdev->dev, "error retrieving number of ports!\n");
145 return;145 return;
146 }146 }
drivers/tty/serial/8250/8250_mtk.c+10−6
@@ -512,13 +512,17 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p, · 511 unmodified lines
512static int mtk8250_probe(struct platform_device *pdev)512static int mtk8250_probe(struct platform_device *pdev)
513{513{
514 struct uart_8250_port uart = {};514 struct uart_8250_port uart = {};
515 struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
516 struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
517 struct mtk8250_data *data;515 struct mtk8250_data *data;
518 int err;516 struct resource *regs;
517 int irq, err;
518
519 irq = platform_get_irq(pdev, 0);
520 if (irq < 0)
521 return irq;
519 522
520 if (!regs || !irq) {523 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
521 dev_err(&pdev->dev, "no registers/irq defined\n");524 if (!regs) {
525 dev_err(&pdev->dev, "no registers defined\n");
522 return -EINVAL;526 return -EINVAL;
523 }527 }
524 528
@@ -542,7 +546,7 @@ static int mtk8250_probe(struct platform_device *pdev) · 17 unmodified lines
542 546
543 spin_lock_init(&uart.port.lock);547 spin_lock_init(&uart.port.lock);
544 uart.port.mapbase = regs->start;548 uart.port.mapbase = regs->start;
545 uart.port.irq = irq->start;549 uart.port.irq = irq;
546 uart.port.pm = mtk8250_do_pm;550 uart.port.pm = mtk8250_do_pm;
547 uart.port.type = PORT_16550;551 uart.port.type = PORT_16550;
548 uart.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;552 uart.port.flags = UPF_BOOT_AUTOCONF | UPF_FIXED_PORT;
drivers/tty/serial/8250/8250_omap.c+10−6
@@ -1209,17 +1209,21 @@ MODULE_DEVICE_TABLE(of, omap8250_dt_ids); · 1208 unmodified lines
1209 1209
1210static int omap8250_probe(struct platform_device *pdev)1210static int omap8250_probe(struct platform_device *pdev)
1211{1211{
1212 struct resource *regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1213 struct resource *irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1214 struct device_node *np = pdev->dev.of_node;1212 struct device_node *np = pdev->dev.of_node;
1215 struct omap8250_priv *priv;1213 struct omap8250_priv *priv;
1216 const struct omap8250_platdata *pdata;1214 const struct omap8250_platdata *pdata;
1217 struct uart_8250_port up;1215 struct uart_8250_port up;
1218 int ret;1216 struct resource *regs;
1219 void __iomem *membase;1217 void __iomem *membase;
1218 int irq, ret;
1219
1220 irq = platform_get_irq(pdev, 0);
1221 if (irq < 0)
1222 return irq;
1220 1223
1221 if (!regs || !irq) {1224 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1222 dev_err(&pdev->dev, "missing registers or irq\n");1225 if (!regs) {
1226 dev_err(&pdev->dev, "missing registers\n");
1223 return -EINVAL;1227 return -EINVAL;
1224 }1228 }
1225 1229
@@ -1236,7 +1240,7 @@ static int omap8250_probe(struct platform_device *pdev) · 10 unmodified lines
1236 up.port.dev = &pdev->dev;1240 up.port.dev = &pdev->dev;
1237 up.port.mapbase = regs->start;1241 up.port.mapbase = regs->start;
1238 up.port.membase = membase;1242 up.port.membase = membase;
1239 up.port.irq = irq->start;1243 up.port.irq = irq;
1240 /*1244 /*
1241 * It claims to be 16C750 compatible however it is a little different.1245 * It claims to be 16C750 compatible however it is a little different.
1242 * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to1246 * It has EFR and has no FCR7_64byte bit. The AFE (which it claims to
drivers/tty/serial/8250/8250_port.c+41−0
@@ -16,6 +16,7 @@ · 15 unmodified lines
16#include <linux/ioport.h>16#include <linux/ioport.h>
17#include <linux/init.h>17#include <linux/init.h>
18#include <linux/console.h>18#include <linux/console.h>
19#include <linux/gpio/consumer.h>
19#include <linux/sysrq.h>20#include <linux/sysrq.h>
20#include <linux/delay.h>21#include <linux/delay.h>
21#include <linux/platform_device.h>22#include <linux/platform_device.h>
@@ -2631,6 +2632,46 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, · 2609 unmodified lines
2631 (port->uartclk + tolerance) / 16);2632 (port->uartclk + tolerance) / 16);
2632}2633}
2633 2634
2635/*
2636 * Note in order to avoid the tty port mutex deadlock don't use the next method
2637 * within the uart port callbacks. Primarily it's supposed to be utilized to
2638 * handle a sudden reference clock rate change.
2639 */
2640void serial8250_update_uartclk(struct uart_port *port, unsigned int uartclk)
2641{
2642 struct uart_8250_port *up = up_to_u8250p(port);
2643 unsigned int baud, quot, frac = 0;
2644 struct ktermios *termios;
2645 unsigned long flags;
2646
2647 mutex_lock(&port->state->port.mutex);
2648
2649 if (port->uartclk == uartclk)
2650 goto out_lock;
2651
2652 port->uartclk = uartclk;
2653 termios = &port->state->port.tty->termios;
2654
2655 baud = serial8250_get_baud_rate(port, termios, NULL);
2656 quot = serial8250_get_divisor(port, baud, &frac);
2657
2658 serial8250_rpm_get(up);
2659 spin_lock_irqsave(&port->lock, flags);
2660
2661 uart_update_timeout(port, termios->c_cflag, baud);
2662
2663 serial8250_set_divisor(port, baud, quot, frac);
2664 serial_port_out(port, UART_LCR, up->lcr);
2665 serial8250_out_MCR(up, UART_MCR_DTR | UART_MCR_RTS);
2666
2667 spin_unlock_irqrestore(&port->lock, flags);
2668 serial8250_rpm_put(up);
2669
2670out_lock:
2671 mutex_unlock(&port->state->port.mutex);
2672}
2673EXPORT_SYMBOL_GPL(serial8250_update_uartclk);
2674
2634void2675void
2635serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,2676serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios,
2636 struct ktermios *old)2677 struct ktermios *old)
drivers/tty/serial/8250/8250_pxa.c+8−6
@@ -18,7 +18,6 @@ · 17 unmodified lines
18#include <linux/serial_core.h>18#include <linux/serial_core.h>
19#include <linux/serial_reg.h>19#include <linux/serial_reg.h>
20#include <linux/of.h>20#include <linux/of.h>
21#include <linux/of_irq.h>
22#include <linux/of_platform.h>21#include <linux/of_platform.h>
23#include <linux/platform_device.h>22#include <linux/platform_device.h>
24#include <linux/slab.h>23#include <linux/slab.h>
@@ -93,12 +92,15 @@ static int serial_pxa_probe(struct platform_device *pdev) · 68 unmodified lines
93{92{
94 struct uart_8250_port uart = {};93 struct uart_8250_port uart = {};
95 struct pxa8250_data *data;94 struct pxa8250_data *data;
96 struct resource *mmres, *irqres;95 struct resource *mmres;
97 int ret;96 int irq, ret;
97
98 irq = platform_get_irq(pdev, 0);
99 if (irq < 0)
100 return irq;
98 101
99 mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);102 mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
100 irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);103 if (!mmres)
101 if (!mmres || !irqres)
102 return -ENODEV;104 return -ENODEV;
103 105
104 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);106 data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
@@ -121,7 +123,7 @@ static int serial_pxa_probe(struct platform_device *pdev) · 16 unmodified lines
121 uart.port.iotype = UPIO_MEM32;123 uart.port.iotype = UPIO_MEM32;
122 uart.port.mapbase = mmres->start;124 uart.port.mapbase = mmres->start;
123 uart.port.regshift = 2;125 uart.port.regshift = 2;
124 uart.port.irq = irqres->start;126 uart.port.irq = irq;
125 uart.port.fifosize = 64;127 uart.port.fifosize = 64;
126 uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE;128 uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST | UPF_FIXED_TYPE;
127 uart.port.dev = &pdev->dev;129 uart.port.dev = &pdev->dev;
drivers/tty/serial/8250/Kconfig+2−2
@@ -222,7 +222,7 @@ config SERIAL_8250_MANY_PORTS · 221 unmodified lines
222 Say Y here if you have dumb serial boards other than the four222 Say Y here if you have dumb serial boards other than the four
223 standard COM 1/2/3/4 ports. This may happen if you have an AST223 standard COM 1/2/3/4 ports. This may happen if you have an AST
224 FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available224 FourPort, Accent Async, Boca (read the Boca mini-HOWTO, available
225 from <http://www.tldp.org/docs.html#howto>), or other custom225 from <https://www.tldp.org/docs.html#howto>), or other custom
226 serial port hardware which acts similar to standard serial port226 serial port hardware which acts similar to standard serial port
227 hardware. If you only use the standard COM 1/2/3/4 ports, you can227 hardware. If you only use the standard COM 1/2/3/4 ports, you can
228 say N here to save some memory. You can also say Y if you have an228 say N here to save some memory. You can also say Y if you have an
@@ -266,7 +266,7 @@ config SERIAL_8250_BOCA · 37 unmodified lines
266 depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS266 depends on SERIAL_8250 != n && ISA && SERIAL_8250_MANY_PORTS
267 help267 help
268 Say Y here if you have a Boca serial board. Please read the Boca268 Say Y here if you have a Boca serial board. Please read the Boca
269 mini-HOWTO, available from <http://www.tldp.org/docs.html#howto>269 mini-HOWTO, available from <https://www.tldp.org/docs.html#howto>
270 270
271 To compile this driver as a module, choose M here: the module271 To compile this driver as a module, choose M here: the module
272 will be called 8250_boca.272 will be called 8250_boca.
drivers/tty/serial/Kconfig+12−5
@@ -502,20 +502,27 @@ config SERIAL_IMX · 501 unmodified lines
502 can enable its onboard serial port by enabling this option.502 can enable its onboard serial port by enabling this option.
503 503
504config SERIAL_IMX_CONSOLE504config SERIAL_IMX_CONSOLE
505 bool "Console on IMX serial port"505 tristate "Console on IMX serial port"
506 depends on SERIAL_IMX=y506 depends on SERIAL_IMX
507 select SERIAL_CORE_CONSOLE507 select SERIAL_CORE_CONSOLE
508 select SERIAL_EARLYCON if OF
509 help508 help
510 If you have enabled the serial port on the Freescale IMX509 If you have enabled the serial port on the Freescale IMX
511 CPU you can make it the console by answering Y to this option.510 CPU you can make it the console by answering Y/M to this option.
512 511
513 Even if you say Y here, the currently visible virtual console512 Even if you say Y/M here, the currently visible virtual console
514 (/dev/tty0) will still be used as the system console by default, but513 (/dev/tty0) will still be used as the system console by default, but
515 you can alter that using a kernel command line option such as514 you can alter that using a kernel command line option such as
516 "console=ttymxc0". (Try "man bootparam" or see the documentation of515 "console=ttymxc0". (Try "man bootparam" or see the documentation of
517 your bootloader about how to pass options to the kernel at boot time.)516 your bootloader about how to pass options to the kernel at boot time.)
518 517
518config SERIAL_IMX_EARLYCON
519 bool "Earlycon on IMX serial port"
520 depends on OF
521 select SERIAL_EARLYCON
522 help
523 If you have enabled the earlycon on the Freescale IMX
524 CPU you can make it the earlycon by answering Y to this option.
525
519config SERIAL_UARTLITE526config SERIAL_UARTLITE
520 tristate "Xilinx uartlite serial port support"527 tristate "Xilinx uartlite serial port support"
521 depends on HAS_IOMEM528 depends on HAS_IOMEM
drivers/tty/serial/altera_jtaguart.c+1−1
@@ -27,7 +27,7 @@ · 26 unmodified lines
27 27
28/*28/*
29 * Altera JTAG UART register definitions according to the Altera JTAG UART29 * Altera JTAG UART register definitions according to the Altera JTAG UART
30 * datasheet: http://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf30 * datasheet: https://www.altera.com/literature/hb/nios2/n2cpu_nii51009.pdf
31 */31 */
32 32
33#define ALTERA_JTAGUART_SIZE 833#define ALTERA_JTAGUART_SIZE 8
drivers/tty/serial/amba-pl011.c+0−1
@@ -2607,7 +2607,6 @@ static int pl011_setup_port(struct device *dev, struct uart_amba_port *uap, · 2606 unmodified lines
2607 uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE);2607 uap->port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_AMBA_PL011_CONSOLE);
2608 uap->port.flags = UPF_BOOT_AUTOCONF;2608 uap->port.flags = UPF_BOOT_AUTOCONF;
2609 uap->port.line = index;2609 uap->port.line = index;
2610 spin_lock_init(&uap->port.lock);
2611 2610
2612 amba_ports[index] = uap;2611 amba_ports[index] = uap;
2613 2612
drivers/tty/serial/fsl_lpuart.c+3−0
@@ -1925,6 +1925,9 @@ static void __lpuart32_serial_setbrg(struct uart_port *port, · 1924 unmodified lines
1925 tmp_sbr++;1925 tmp_sbr++;
1926 }1926 }
1927 1927
1928 if (tmp_sbr > UARTBAUD_SBR_MASK)
1929 continue;
1930
1928 if (tmp_diff <= baud_diff) {1931 if (tmp_diff <= baud_diff) {
1929 baud_diff = tmp_diff;1932 baud_diff = tmp_diff;
1930 osr = tmp_osr;1933 osr = tmp_osr;
drivers/tty/serial/imx.c+133−74
@@ -20,6 +20,7 @@ · 19 unmodified lines
20#include <linux/serial.h>20#include <linux/serial.h>
21#include <linux/clk.h>21#include <linux/clk.h>
22#include <linux/delay.h>22#include <linux/delay.h>
23#include <linux/ktime.h>
23#include <linux/pinctrl/consumer.h>24#include <linux/pinctrl/consumer.h>
24#include <linux/rational.h>25#include <linux/rational.h>
25#include <linux/slab.h>26#include <linux/slab.h>
@@ -188,6 +189,13 @@ struct imx_uart_data { · 162 unmodified lines
188 enum imx_uart_type devtype;189 enum imx_uart_type devtype;
189};190};
190 191
192enum imx_tx_state {
193 OFF,
194 WAIT_AFTER_RTS,
195 SEND,
196 WAIT_AFTER_SEND,
197};
198
191struct imx_port {199struct imx_port {
192 struct uart_port port;200 struct uart_port port;
193 struct timer_list timer;201 struct timer_list timer;
@@ -224,6 +232,10 @@ struct imx_port { · 30 unmodified lines
224 unsigned int dma_tx_nents;232 unsigned int dma_tx_nents;
225 unsigned int saved_reg[10];233 unsigned int saved_reg[10];
226 bool context_saved;234 bool context_saved;
235
236 enum imx_tx_state tx_state;
237 struct hrtimer trigger_start_tx;
238 struct hrtimer trigger_stop_tx;
227};239};
228 240
229struct imx_port_ucrs {241struct imx_port_ucrs {
@@ -361,7 +373,7 @@ static inline int imx_uart_is_imx6q(struct imx_port *sport) · 131 unmodified lines
361/*373/*
362 * Save and restore functions for UCR1, UCR2 and UCR3 registers374 * Save and restore functions for UCR1, UCR2 and UCR3 registers
363 */375 */
364#if defined(CONFIG_SERIAL_IMX_CONSOLE)376#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
365static void imx_uart_ucrs_save(struct imx_port *sport,377static void imx_uart_ucrs_save(struct imx_port *sport,
366 struct imx_port_ucrs *ucr)378 struct imx_port_ucrs *ucr)
367{379{
@@ -400,6 +412,15 @@ static void imx_uart_rts_inactive(struct imx_port *sport, u32 *ucr2) · 32 unmodified lines
400 mctrl_gpio_set(sport->gpios, sport->port.mctrl);412 mctrl_gpio_set(sport->gpios, sport->port.mctrl);
401}413}
402 414
415static void start_hrtimer_ms(struct hrtimer *hrt, unsigned long msec)
416{
417 long sec = msec / MSEC_PER_SEC;
418 long nsec = (msec % MSEC_PER_SEC) * 1000000;
419 ktime_t t = ktime_set(sec, nsec);
420
421 hrtimer_start(hrt, t, HRTIMER_MODE_REL);
422}
423
403/* called with port.lock taken and irqs off */424/* called with port.lock taken and irqs off */
404static void imx_uart_start_rx(struct uart_port *port)425static void imx_uart_start_rx(struct uart_port *port)
405{426{
@@ -427,7 +448,10 @@ static void imx_uart_start_rx(struct uart_port *port) · 21 unmodified lines
427static void imx_uart_stop_tx(struct uart_port *port)448static void imx_uart_stop_tx(struct uart_port *port)
428{449{
429 struct imx_port *sport = (struct imx_port *)port;450 struct imx_port *sport = (struct imx_port *)port;
430 u32 ucr1;451 u32 ucr1, ucr4, usr2;
452
453 if (sport->tx_state == OFF)
454 return;
431 455
432 /*456 /*
433 * We are maybe in the SMP context, so if the DMA TX thread is running457 * We are maybe in the SMP context, so if the DMA TX thread is running
@@ -439,21 +463,44 @@ static void imx_uart_stop_tx(struct uart_port *port) · 5 unmodified lines
439 ucr1 = imx_uart_readl(sport, UCR1);463 ucr1 = imx_uart_readl(sport, UCR1);
440 imx_uart_writel(sport, ucr1 & ~UCR1_TRDYEN, UCR1);464 imx_uart_writel(sport, ucr1 & ~UCR1_TRDYEN, UCR1);
441 465
442 /* in rs485 mode disable transmitter if shifter is empty */466 usr2 = imx_uart_readl(sport, USR2);
443 if (port->rs485.flags & SER_RS485_ENABLED &&467 if (!(usr2 & USR2_TXDC)) {
444 imx_uart_readl(sport, USR2) & USR2_TXDC) {468 /* The shifter is still busy, so retry once TC triggers */
445 u32 ucr2 = imx_uart_readl(sport, UCR2), ucr4;469 return;
446 if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)470 }
447 imx_uart_rts_active(sport, &ucr2);
448 else
449 imx_uart_rts_inactive(sport, &ucr2);
450 imx_uart_writel(sport, ucr2, UCR2);
451 471
452 imx_uart_start_rx(port);472 ucr4 = imx_uart_readl(sport, UCR4);
473 ucr4 &= ~UCR4_TCEN;
474 imx_uart_writel(sport, ucr4, UCR4);
453 475
454 ucr4 = imx_uart_readl(sport, UCR4);476 /* in rs485 mode disable transmitter */
455 ucr4 &= ~UCR4_TCEN;477 if (port->rs485.flags & SER_RS485_ENABLED) {
456 imx_uart_writel(sport, ucr4, UCR4);478 if (sport->tx_state == SEND) {
479 sport->tx_state = WAIT_AFTER_SEND;
480 start_hrtimer_ms(&sport->trigger_stop_tx,
481 port->rs485.delay_rts_after_send);
482 return;
483 }
484
485 if (sport->tx_state == WAIT_AFTER_RTS ||
486 sport->tx_state == WAIT_AFTER_SEND) {
487 u32 ucr2;
488
489 hrtimer_try_to_cancel(&sport->trigger_start_tx);
490
491 ucr2 = imx_uart_readl(sport, UCR2);
492 if (port->rs485.flags & SER_RS485_RTS_AFTER_SEND)
493 imx_uart_rts_active(sport, &ucr2);
494 else
495 imx_uart_rts_inactive(sport, &ucr2);
496 imx_uart_writel(sport, ucr2, UCR2);
497
498 imx_uart_start_rx(port);
499
500 sport->tx_state = OFF;
501 }
502 } else {
503 sport->tx_state = OFF;
457 }504 }
458}505}
459 506
@@ -651,28 +698,50 @@ static void imx_uart_start_tx(struct uart_port *port) · 191 unmodified lines
651 if (!sport->port.x_char && uart_circ_empty(&port->state->xmit))698 if (!sport->port.x_char && uart_circ_empty(&port->state->xmit))
652 return;699 return;
653 700
701 /*
702 * We cannot simply do nothing here if sport->tx_state == SEND already
703 * because UCR1_TXMPTYEN might already have been cleared in
704 * imx_uart_stop_tx(), but tx_state is still SEND.
705 */
706
654 if (port->rs485.flags & SER_RS485_ENABLED) {707 if (port->rs485.flags & SER_RS485_ENABLED) {
655 u32 ucr2;708 if (sport->tx_state == OFF) {
709 u32 ucr2 = imx_uart_readl(sport, UCR2);
710 if (port->rs485.flags & SER_RS485_RTS_ON_SEND)
711 imx_uart_rts_active(sport, &ucr2);
712 else
713 imx_uart_rts_inactive(sport, &ucr2);
714 imx_uart_writel(sport, ucr2, UCR2);
656 715
657 ucr2 = imx_uart_readl(sport, UCR2);716 if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))
658 if (port->rs485.flags & SER_RS485_RTS_ON_SEND)717 imx_uart_stop_rx(port);
659 imx_uart_rts_active(sport, &ucr2);718
660 else719 sport->tx_state = WAIT_AFTER_RTS;
661 imx_uart_rts_inactive(sport, &ucr2);720 start_hrtimer_ms(&sport->trigger_start_tx,
662 imx_uart_writel(sport, ucr2, UCR2);721 port->rs485.delay_rts_before_send);
722 return;
723 }
663 724
664 if (!(port->rs485.flags & SER_RS485_RX_DURING_TX))725 if (sport->tx_state == WAIT_AFTER_SEND
665 imx_uart_stop_rx(port);726 || sport->tx_state == WAIT_AFTER_RTS) {
666 727
667 /*728 hrtimer_try_to_cancel(&sport->trigger_stop_tx);
668 * Enable transmitter and shifter empty irq only if DMA is off.729
669 * In the DMA case this is done in the tx-callback.730 /*
670 */731 * Enable transmitter and shifter empty irq only if DMA
671 if (!sport->dma_is_enabled) {732 * is off. In the DMA case this is done in the
672 u32 ucr4 = imx_uart_readl(sport, UCR4);733 * tx-callback.
673 ucr4 |= UCR4_TCEN;734 */
674 imx_uart_writel(sport, ucr4, UCR4);735 if (!sport->dma_is_enabled) {
736 u32 ucr4 = imx_uart_readl(sport, UCR4);
737 ucr4 |= UCR4_TCEN;
738 imx_uart_writel(sport, ucr4, UCR4);
739 }
740
741 sport->tx_state = SEND;
675 }742 }
743 } else {
744 sport->tx_state = SEND;
676 }745 }
677 746
678 if (!sport->dma_is_enabled) {747 if (!sport->dma_is_enabled) {
@@ -1630,7 +1699,6 @@ imx_uart_set_termios(struct uart_port *port, struct ktermios *termios, · 951 unmodified lines
1630 1699
1631 if (termios->c_cflag & CRTSCTS)1700 if (termios->c_cflag & CRTSCTS)
1632 ucr2 &= ~UCR2_IRTS;1701 ucr2 &= ~UCR2_IRTS;
1633
1634 if (termios->c_cflag & CSTOPB)1702 if (termios->c_cflag & CSTOPB)
1635 ucr2 |= UCR2_STPB;1703 ucr2 |= UCR2_STPB;
1636 if (termios->c_cflag & PARENB) {1704 if (termios->c_cflag & PARENB) {
@@ -1857,10 +1925,6 @@ static int imx_uart_rs485_config(struct uart_port *port, · 220 unmodified lines
1857 struct imx_port *sport = (struct imx_port *)port;1925 struct imx_port *sport = (struct imx_port *)port;
1858 u32 ucr2;1926 u32 ucr2;
1859 1927
1860 /* unimplemented */
1861 rs485conf->delay_rts_before_send = 0;
1862 rs485conf->delay_rts_after_send = 0;
1863
1864 /* RTS is required to control the transmitter */1928 /* RTS is required to control the transmitter */
1865 if (!sport->have_rtscts && !sport->have_rtsgpio)1929 if (!sport->have_rtscts && !sport->have_rtsgpio)
1866 rs485conf->flags &= ~SER_RS485_ENABLED;1930 rs485conf->flags &= ~SER_RS485_ENABLED;
@@ -1915,7 +1979,7 @@ static const struct uart_ops imx_uart_pops = { · 48 unmodified lines
1915 1979
1916static struct imx_port *imx_uart_ports[UART_NR];1980static struct imx_port *imx_uart_ports[UART_NR];
1917 1981
1918#ifdef CONFIG_SERIAL_IMX_CONSOLE1982#if IS_ENABLED(CONFIG_SERIAL_IMX_CONSOLE)
1919static void imx_uart_console_putchar(struct uart_port *port, int ch)1983static void imx_uart_console_putchar(struct uart_port *port, int ch)
1920{1984{
1921 struct imx_port *sport = (struct imx_port *)port;1985 struct imx_port *sport = (struct imx_port *)port;
@@ -2112,39 +2176,6 @@ static struct console imx_uart_console = { · 190 unmodified lines
2112 2176
2113#define IMX_CONSOLE &imx_uart_console2177#define IMX_CONSOLE &imx_uart_console
2114 2178
2115#ifdef CONFIG_OF
2116static void imx_uart_console_early_putchar(struct uart_port *port, int ch)
2117{
2118 struct imx_port *sport = (struct imx_port *)port;
2119
2120 while (imx_uart_readl(sport, IMX21_UTS) & UTS_TXFULL)
2121 cpu_relax();
2122
2123 imx_uart_writel(sport, ch, URTX0);
2124}
2125
2126static void imx_uart_console_early_write(struct console *con, const char *s,
2127 unsigned count)
2128{
2129 struct earlycon_device *dev = con->data;
2130
2131 uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar);
2132}
2133
2134static int __init
2135imx_console_early_setup(struct earlycon_device *dev, const char *opt)
2136{
2137 if (!dev->port.membase)
2138 return -ENODEV;
2139
2140 dev->con->write = imx_uart_console_early_write;
2141
2142 return 0;
2143}
2144OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
2145OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
2146#endif
2147
2148#else2179#else
2149#define IMX_CONSOLE NULL2180#define IMX_CONSOLE NULL
2150#endif2181#endif
@@ -2223,6 +2254,32 @@ static void imx_uart_probe_pdata(struct imx_port *sport, · 72 unmodified lines
2223 sport->have_rtscts = 1;2254 sport->have_rtscts = 1;
2224}2255}
2225 2256
2257static enum hrtimer_restart imx_trigger_start_tx(struct hrtimer *t)
2258{
2259 struct imx_port *sport = container_of(t, struct imx_port, trigger_start_tx);
2260 unsigned long flags;
2261
2262 spin_lock_irqsave(&sport->port.lock, flags);
2263 if (sport->tx_state == WAIT_AFTER_RTS)
2264 imx_uart_start_tx(&sport->port);
2265 spin_unlock_irqrestore(&sport->port.lock, flags);
2266
2267 return HRTIMER_NORESTART;
2268}
2269
2270static enum hrtimer_restart imx_trigger_stop_tx(struct hrtimer *t)
2271{
2272 struct imx_port *sport = container_of(t, struct imx_port, trigger_stop_tx);
2273 unsigned long flags;
2274
2275 spin_lock_irqsave(&sport->port.lock, flags);
2276 if (sport->tx_state == WAIT_AFTER_SEND)
2277 imx_uart_stop_tx(&sport->port);
2278 spin_unlock_irqrestore(&sport->port.lock, flags);
2279
2280 return HRTIMER_NORESTART;
2281}
2282
2226static int imx_uart_probe(struct platform_device *pdev)2283static int imx_uart_probe(struct platform_device *pdev)
2227{2284{
2228 struct imx_port *sport;2285 struct imx_port *sport;
@@ -2369,6 +2426,11 @@ static int imx_uart_probe(struct platform_device *pdev) · 140 unmodified lines
2369 2426
2370 clk_disable_unprepare(sport->clk_ipg);2427 clk_disable_unprepare(sport->clk_ipg);
2371 2428
2429 hrtimer_init(&sport->trigger_start_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2430 hrtimer_init(&sport->trigger_stop_tx, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
2431 sport->trigger_start_tx.function = imx_trigger_start_tx;
2432 sport->trigger_stop_tx.function = imx_trigger_stop_tx;
2433
2372 /*2434 /*
2373 * Allocate the IRQ(s) i.MX1 has three interrupts whereas later2435 * Allocate the IRQ(s) i.MX1 has three interrupts whereas later
2374 * chips only have one interrupt.2436 * chips only have one interrupt.
@@ -2406,9 +2468,6 @@ static int imx_uart_probe(struct platform_device *pdev) · 31 unmodified lines
2406 }2468 }
2407 }2469 }
2408 2470
2409 /* We need to initialize lock even for non-registered console */
2410 spin_lock_init(&sport->port.lock);
2411
2412 imx_uart_ports[sport->port.line] = sport;2471 imx_uart_ports[sport->port.line] = sport;
2413 2472
2414 platform_set_drvdata(pdev, sport);2473 platform_set_drvdata(pdev, sport);
drivers/tty/serial/imx_earlycon.c+50−0
@@ -0,0 +1,50 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2020 NXP
4 */
5
6#include <linux/module.h>
7#include <linux/ioport.h>
8#include <linux/init.h>
9#include <linux/serial_core.h>
10#include <linux/serial.h>
11#include <linux/delay.h>
12#include <linux/of.h>
13#include <linux/io.h>
14
15#define URTX0 0x40 /* Transmitter Register */
16#define UTS_TXFULL (1<<4) /* TxFIFO full */
17#define IMX21_UTS 0xb4 /* UART Test Register on all other i.mx*/
18
19static void imx_uart_console_early_putchar(struct uart_port *port, int ch)
20{
21 while (readl_relaxed(port->membase + IMX21_UTS) & UTS_TXFULL)
22 cpu_relax();
23
24 writel_relaxed(ch, port->membase + URTX0);
25}
26
27static void imx_uart_console_early_write(struct console *con, const char *s,
28 unsigned count)
29{
30 struct earlycon_device *dev = con->data;
31
32 uart_console_write(&dev->port, s, count, imx_uart_console_early_putchar);
33}
34
35static int __init
36imx_console_early_setup(struct earlycon_device *dev, const char *opt)
37{
38 if (!dev->port.membase)
39 return -ENODEV;
40
41 dev->con->write = imx_uart_console_early_write;
42
43 return 0;
44}
45OF_EARLYCON_DECLARE(ec_imx6q, "fsl,imx6q-uart", imx_console_early_setup);
46OF_EARLYCON_DECLARE(ec_imx21, "fsl,imx21-uart", imx_console_early_setup);
47
48MODULE_AUTHOR("NXP");
49MODULE_DESCRIPTION("IMX earlycon driver");
50MODULE_LICENSE("GPL");
drivers/tty/serial/jsm/jsm_driver.c+1−1
@@ -16,7 +16,7 @@ · 15 unmodified lines
16 16
17#include "jsm.h"17#include "jsm.h"
18 18
19MODULE_AUTHOR("Digi International, http://www.digi.com");19MODULE_AUTHOR("Digi International, https://www.digi.com");
20MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line");20MODULE_DESCRIPTION("Driver for the Digi International Neo and Classic PCI based product line");
21MODULE_LICENSE("GPL");21MODULE_LICENSE("GPL");
22MODULE_SUPPORTED_DEVICE("jsm");22MODULE_SUPPORTED_DEVICE("jsm");
drivers/tty/serial/kgdboc.c+2−1
@@ -538,7 +538,8 @@ static int __init kgdboc_earlycon_init(char *opt) · 537 unmodified lines
538 538
539 if (!con) {539 if (!con) {
540 /*540 /*
541 * Both earlycon and kgdboc_earlycon are initialized during * early parameter parsing. We cannot guarantee earlycon gets541 * Both earlycon and kgdboc_earlycon are initialized during
542 * early parameter parsing. We cannot guarantee earlycon gets
542 * in first and, in any case, on ACPI systems earlycon may543 * in first and, in any case, on ACPI systems earlycon may
543 * defer its own initialization (usually to somewhere within544 * defer its own initialization (usually to somewhere within
544 * setup_arch() ). To cope with either of these situations545 * setup_arch() ). To cope with either of these situations
drivers/tty/serial/msm_serial.c+2−0
@@ -696,6 +696,7 @@ static void msm_enable_ms(struct uart_port *port) · 695 unmodified lines
696}696}
697 697
698static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)698static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr)
699 __must_hold(&port->lock)
699{700{
700 struct tty_port *tport = &port->state->port;701 struct tty_port *tport = &port->state->port;
701 unsigned int sr;702 unsigned int sr;
@@ -771,6 +772,7 @@ static void msm_handle_rx_dm(struct uart_port *port, unsigned int misr) · 69 unmodified lines
771}772}
772 773
773static void msm_handle_rx(struct uart_port *port)774static void msm_handle_rx(struct uart_port *port)
775 __must_hold(&port->lock)
774{776{
775 struct tty_port *tport = &port->state->port;777 struct tty_port *tport = &port->state->port;
776 unsigned int sr;778 unsigned int sr;
drivers/tty/serial/pch_uart.c+10−24
@@ -1857,41 +1857,24 @@ static void pch_uart_pci_remove(struct pci_dev *pdev) · 1856 unmodified lines
1857 kfree(priv);1857 kfree(priv);
1858 return;1858 return;
1859}1859}
1860#ifdef CONFIG_PM1860
1861static int pch_uart_pci_suspend(struct pci_dev *pdev, pm_message_t state)1861static int __maybe_unused pch_uart_pci_suspend(struct device *dev)
1862{1862{
1863 struct eg20t_port *priv = pci_get_drvdata(pdev);1863 struct eg20t_port *priv = dev_get_drvdata(dev);
1864 1864
1865 uart_suspend_port(&pch_uart_driver, &priv->port);1865 uart_suspend_port(&pch_uart_driver, &priv->port);
1866 1866
1867 pci_save_state(pdev);
1868 pci_set_power_state(pdev, pci_choose_state(pdev, state));
1869 return 0;1867 return 0;
1870}1868}
1871 1869
1872static int pch_uart_pci_resume(struct pci_dev *pdev)1870static int __maybe_unused pch_uart_pci_resume(struct device *dev)
1873{1871{
1874 struct eg20t_port *priv = pci_get_drvdata(pdev);1872 struct eg20t_port *priv = dev_get_drvdata(dev);
1875 int ret;
1876
1877 pci_set_power_state(pdev, PCI_D0);
1878 pci_restore_state(pdev);
1879
1880 ret = pci_enable_device(pdev);
1881 if (ret) {
1882 dev_err(&pdev->dev,
1883 "%s-pci_enable_device failed(ret=%d) ", __func__, ret);
1884 return ret;
1885 }
1886 1873
1887 uart_resume_port(&pch_uart_driver, &priv->port);1874 uart_resume_port(&pch_uart_driver, &priv->port);
1888 1875
1889 return 0;1876 return 0;
1890}1877}
1891#else
1892#define pch_uart_pci_suspend NULL
1893#define pch_uart_pci_resume NULL
1894#endif
1895 1878
1896static const struct pci_device_id pch_uart_pci_id[] = {1879static const struct pci_device_id pch_uart_pci_id[] = {
1897 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811),1880 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x8811),
@@ -1945,13 +1928,16 @@ probe_error: · 47 unmodified lines
1945 return ret;1928 return ret;
1946}1929}
1947 1930
1931static SIMPLE_DEV_PM_OPS(pch_uart_pci_pm_ops,
1932 pch_uart_pci_suspend,
1933 pch_uart_pci_resume);
1934
1948static struct pci_driver pch_uart_pci_driver = {1935static struct pci_driver pch_uart_pci_driver = {
1949 .name = "pch_uart",1936 .name = "pch_uart",
1950 .id_table = pch_uart_pci_id,1937 .id_table = pch_uart_pci_id,
1951 .probe = pch_uart_pci_probe,1938 .probe = pch_uart_pci_probe,
1952 .remove = pch_uart_pci_remove,1939 .remove = pch_uart_pci_remove,
1953 .suspend = pch_uart_pci_suspend,1940 .driver.pm = &pch_uart_pci_pm_ops,
1954 .resume = pch_uart_pci_resume,
1955};1941};
1956 1942
1957static int __init pch_uart_module_init(void)1943static int __init pch_uart_module_init(void)
drivers/tty/serial/pmac_zilog.c+1−0
@@ -213,6 +213,7 @@ static void pmz_interrupt_control(struct uart_pmac_port *uap, int enable) · 212 unmodified lines
213}213}
214 214
215static bool pmz_receive_chars(struct uart_pmac_port *uap)215static bool pmz_receive_chars(struct uart_pmac_port *uap)
216 __must_hold(&uap->port.lock)
216{217{
217 struct tty_port *port;218 struct tty_port *port;
218 unsigned char ch, r1, drop, flag;219 unsigned char ch, r1, drop, flag;
drivers/tty/serial/qcom_geni_serial.c+1−1
@@ -768,7 +768,7 @@ static void qcom_geni_serial_handle_tx(struct uart_port *uport, bool done, · 767 unmodified lines
768 u8 buf[sizeof(u32)];768 u8 buf[sizeof(u32)];
769 int c;769 int c;
770 770
771 memset(buf, 0, ARRAY_SIZE(buf));771 memset(buf, 0, sizeof(buf));
772 tx_bytes = min_t(size_t, remaining, BYTES_PER_FIFO_WORD);772 tx_bytes = min_t(size_t, remaining, BYTES_PER_FIFO_WORD);
773 773
774 for (c = 0; c < tx_bytes ; c++) {774 for (c = 0; c < tx_bytes ; c++) {
drivers/tty/serial/samsung_tty.c+10−14
@@ -6,7 +6,7 @@ · 5 unmodified lines
6 * http://armlinux.simtec.co.uk/6 * http://armlinux.simtec.co.uk/
7 */7 */
8 8
9/* Hote on 2410 error handling9/* Note on 2410 error handling
10 *10 *
11 * The s3c2410 manual has a love/hate affair with the contents of the11 * The s3c2410 manual has a love/hate affair with the contents of the
12 * UERSTAT register in the UART blocks, and keeps marking some of the12 * UERSTAT register in the UART blocks, and keeps marking some of the
@@ -327,7 +327,6 @@ static void s3c24xx_serial_tx_dma_complete(void *args) · 314 unmodified lines
327 unsigned long flags;327 unsigned long flags;
328 int count;328 int count;
329 329
330
331 dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state);330 dmaengine_tx_status(dma->tx_chan, dma->tx_cookie, &state);
332 count = dma->tx_bytes_requested - state.residue;331 count = dma->tx_bytes_requested - state.residue;
333 async_tx_ack(dma->tx_desc);332 async_tx_ack(dma->tx_desc);
@@ -409,7 +408,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport, · 75 unmodified lines
409 struct circ_buf *xmit = &port->state->xmit;408 struct circ_buf *xmit = &port->state->xmit;
410 struct s3c24xx_uart_dma *dma = ourport->dma;409 struct s3c24xx_uart_dma *dma = ourport->dma;
411 410
412
413 if (ourport->tx_mode != S3C24XX_TX_DMA)411 if (ourport->tx_mode != S3C24XX_TX_DMA)
414 enable_tx_dma(ourport);412 enable_tx_dma(ourport);
415 413
@@ -816,7 +814,6 @@ static irqreturn_t s3c24xx_serial_rx_chars_pio(void *dev_id) · 400 unmodified lines
816 return IRQ_HANDLED;814 return IRQ_HANDLED;
817}815}
818 816
819
820static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)817static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
821{818{
822 struct s3c24xx_uart_port *ourport = dev_id;819 struct s3c24xx_uart_port *ourport = dev_id;
@@ -842,8 +839,8 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id) · 19 unmodified lines
842 count >= ourport->min_dma_size) {839 count >= ourport->min_dma_size) {
843 int align = dma_get_cache_alignment() -840 int align = dma_get_cache_alignment() -
844 (xmit->tail & (dma_get_cache_alignment() - 1));841 (xmit->tail & (dma_get_cache_alignment() - 1));
845 if (count-align >= ourport->min_dma_size) {842 if (count - align >= ourport->min_dma_size) {
846 dma_count = count-align;843 dma_count = count - align;
847 count = align;844 count = align;
848 }845 }
849 }846 }
@@ -1589,7 +1586,6 @@ s3c24xx_serial_verify_port(struct uart_port *port, struct serial_struct *ser) · 739 unmodified lines
1589 return 0;1586 return 0;
1590}1587}
1591 1588
1592
1593#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE1589#ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
1594 1590
1595static struct console s3c24xx_serial_console;1591static struct console s3c24xx_serial_console;
@@ -1672,7 +1668,6 @@ s3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS] = { · 76 unmodified lines
1672 }1668 }
1673 },1669 },
1674#if CONFIG_SERIAL_SAMSUNG_UARTS > 21670#if CONFIG_SERIAL_SAMSUNG_UARTS > 2
1675
1676 [2] = {1671 [2] = {
1677 .port = {1672 .port = {
1678 .lock = __PORT_LOCK_UNLOCKED(2),1673 .lock = __PORT_LOCK_UNLOCKED(2),
@@ -1728,7 +1723,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port, · 49 unmodified lines
1728 udelay(1);1723 udelay(1);
1729}1724}
1730 1725
1731
1732#ifdef CONFIG_ARM_S3C24XX_CPUFREQ1726#ifdef CONFIG_ARM_S3C24XX_CPUFREQ
1733 1727
1734static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,1728static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb,
@@ -1903,9 +1897,9 @@ static int s3c24xx_serial_init_port(struct s3c24xx_uart_port *ourport, · 168 unmodified lines
1903 1897
1904 port->mapbase = res->start;1898 port->mapbase = res->start;
1905 ret = platform_get_irq(platdev, 0);1899 ret = platform_get_irq(platdev, 0);
1906 if (ret < 0)1900 if (ret < 0) {
1907 port->irq = 0;1901 port->irq = 0;
1908 else {1902 } else {
1909 port->irq = ret;1903 port->irq = ret;
1910 ourport->rx_irq = ret;1904 ourport->rx_irq = ret;
1911 ourport->tx_irq = ret + 1;1905 ourport->tx_irq = ret + 1;
@@ -1977,8 +1971,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[]; · 65 unmodified lines
1977 1971
1978static int probe_index;1972static int probe_index;
1979 1973
1980static inline struct s3c24xx_serial_drv_data *s3c24xx_get_driver_data(1974static inline struct s3c24xx_serial_drv_data *
1981 struct platform_device *pdev)1975s3c24xx_get_driver_data(struct platform_device *pdev)
1982{1976{
1983#ifdef CONFIG_OF1977#ifdef CONFIG_OF
1984 if (pdev->dev.of_node) {1978 if (pdev->dev.of_node) {
@@ -2329,7 +2323,6 @@ s3c24xx_serial_get_options(struct uart_port *port, int *baud, · 344 unmodified lines
2329 *baud = rate / (16 * (ubrdiv + 1));2323 *baud = rate / (16 * (ubrdiv + 1));
2330 dev_dbg(port->dev, "calculated baud %d\n", *baud);2324 dev_dbg(port->dev, "calculated baud %d\n", *baud);
2331 }2325 }
2332
2333}2326}
2334 2327
2335static int __init2328static int __init
@@ -2696,6 +2689,7 @@ static int __init s3c2410_early_console_setup(struct earlycon_device *device, · 360 unmodified lines
2696 device->port.private_data = &s3c2410_early_console_data;2689 device->port.private_data = &s3c2410_early_console_data;
2697 return samsung_early_console_setup(device, opt);2690 return samsung_early_console_setup(device, opt);
2698}2691}
2692
2699OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart",2693OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart",
2700 s3c2410_early_console_setup);2694 s3c2410_early_console_setup);
2701 2695
@@ -2710,6 +2704,7 @@ static int __init s3c2440_early_console_setup(struct earlycon_device *device, · 8 unmodified lines
2710 device->port.private_data = &s3c2440_early_console_data;2704 device->port.private_data = &s3c2440_early_console_data;
2711 return samsung_early_console_setup(device, opt);2705 return samsung_early_console_setup(device, opt);
2712}2706}
2707
2713OF_EARLYCON_DECLARE(s3c2412, "samsung,s3c2412-uart",2708OF_EARLYCON_DECLARE(s3c2412, "samsung,s3c2412-uart",
2714 s3c2440_early_console_setup);2709 s3c2440_early_console_setup);
2715OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart",2710OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart",
@@ -2728,6 +2723,7 @@ static int __init s5pv210_early_console_setup(struct earlycon_device *device, · 12 unmodified lines
2728 device->port.private_data = &s5pv210_early_console_data;2723 device->port.private_data = &s5pv210_early_console_data;
2729 return samsung_early_console_setup(device, opt);2724 return samsung_early_console_setup(device, opt);
2730}2725}
2726
2731OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",2727OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
2732 s5pv210_early_console_setup);2728 s5pv210_early_console_setup);
2733OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",2729OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
drivers/tty/serial/serial-tegra.c+3−3
@@ -439,16 +439,16 @@ static char tegra_uart_decode_rx_error(struct tegra_uart_port *tup, · 438 unmodified lines
439 /* Overrrun error */439 /* Overrrun error */
440 flag = TTY_OVERRUN;440 flag = TTY_OVERRUN;
441 tup->uport.icount.overrun++;441 tup->uport.icount.overrun++;
442 dev_err(tup->uport.dev, "Got overrun errors\n");442 dev_dbg(tup->uport.dev, "Got overrun errors\n");
443 } else if (lsr & UART_LSR_PE) {443 } else if (lsr & UART_LSR_PE) {
444 /* Parity error */444 /* Parity error */
445 flag = TTY_PARITY;445 flag = TTY_PARITY;
446 tup->uport.icount.parity++;446 tup->uport.icount.parity++;
447 dev_err(tup->uport.dev, "Got Parity errors\n");447 dev_dbg(tup->uport.dev, "Got Parity errors\n");
448 } else if (lsr & UART_LSR_FE) {448 } else if (lsr & UART_LSR_FE) {
449 flag = TTY_FRAME;449 flag = TTY_FRAME;
450 tup->uport.icount.frame++;450 tup->uport.icount.frame++;
451 dev_err(tup->uport.dev, "Got frame errors\n");451 dev_dbg(tup->uport.dev, "Got frame errors\n");
452 } else if (lsr & UART_LSR_BI) {452 } else if (lsr & UART_LSR_BI) {
453 /*453 /*
454 * Break error454 * Break error
drivers/tty/serial/serial_core.c+4−1
@@ -14,6 +14,7 @@ · 13 unmodified lines
14#include <linux/sched/signal.h>14#include <linux/sched/signal.h>
15#include <linux/init.h>15#include <linux/init.h>
16#include <linux/console.h>16#include <linux/console.h>
17#include <linux/gpio/consumer.h>
17#include <linux/of.h>18#include <linux/of.h>
18#include <linux/proc_fs.h>19#include <linux/proc_fs.h>
19#include <linux/seq_file.h>20#include <linux/seq_file.h>
@@ -1120,7 +1121,7 @@ out: · 1100 unmodified lines
1120 return ret;1121 return ret;
1121}1122}
1122 1123
1123static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)1124static int uart_do_autoconfig(struct tty_struct *tty, struct uart_state *state)
1124{1125{
1125 struct tty_port *port = &state->port;1126 struct tty_port *port = &state->port;
1126 struct uart_port *uport;1127 struct uart_port *uport;
@@ -1523,6 +1524,7 @@ static void uart_set_termios(struct tty_struct *tty, · 396 unmodified lines
1523 /* Handle transition away from B0 status */1524 /* Handle transition away from B0 status */
1524 else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {1525 else if (!(old_termios->c_cflag & CBAUD) && (cflag & CBAUD)) {
1525 unsigned int mask = TIOCM_DTR;1526 unsigned int mask = TIOCM_DTR;
1527
1526 if (!(cflag & CRTSCTS) || !tty_throttled(tty))1528 if (!(cflag & CRTSCTS) || !tty_throttled(tty))
1527 mask |= TIOCM_RTS;1529 mask |= TIOCM_RTS;
1528 uart_set_mctrl(uport, mask);1530 uart_set_mctrl(uport, mask);
@@ -2279,6 +2281,7 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) · 750 unmodified lines
2279 if (console_suspend_enabled || !uart_console(uport)) {2281 if (console_suspend_enabled || !uart_console(uport)) {
2280 /* Protected by port mutex for now */2282 /* Protected by port mutex for now */
2281 struct tty_struct *tty = port->tty;2283 struct tty_struct *tty = port->tty;
2284
2282 ret = ops->startup(uport);2285 ret = ops->startup(uport);
2283 if (ret == 0) {2286 if (ret == 0) {
2284 if (tty)2287 if (tty)
drivers/tty/serial/sh-sci.c+0−3
@@ -3301,9 +3301,6 @@ static int sci_probe_single(struct platform_device *dev, · 3300 unmodified lines
3301 sciport->port.flags |= UPF_HARD_FLOW;3301 sciport->port.flags |= UPF_HARD_FLOW;
3302 }3302 }
3303 3303
3304 if (sci_uart_driver.cons->index == sciport->port.line)
3305 spin_lock_init(&sciport->port.lock);
3306
3307 ret = uart_add_one_port(&sci_uart_driver, &sciport->port);3304 ret = uart_add_one_port(&sci_uart_driver, &sciport->port);
3308 if (ret) {3305 if (ret) {
3309 sci_cleanup_single(sciport);3306 sci_cleanup_single(sciport);
drivers/tty/serial/sifive.c+0−1
@@ -883,7 +883,6 @@ console_initcall(sifive_console_init); · 882 unmodified lines
883 883
884static void __ssp_add_console_port(struct sifive_serial_port *ssp)884static void __ssp_add_console_port(struct sifive_serial_port *ssp)
885{885{
886 spin_lock_init(&ssp->port.lock);
887 sifive_serial_console_ports[ssp->port.line] = ssp;886 sifive_serial_console_ports[ssp->port.line] = ssp;
888}887}
889 888
drivers/tty/serial/stm32-usart.c+11−2
@@ -129,9 +129,13 @@ static int stm32_config_rs485(struct uart_port *port, · 128 unmodified lines
129 if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {129 if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
130 cr3 &= ~USART_CR3_DEP;130 cr3 &= ~USART_CR3_DEP;
131 rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;131 rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
132 mctrl_gpio_set(stm32_port->gpios,
133 stm32_port->port.mctrl & ~TIOCM_RTS);
132 } else {134 } else {
133 cr3 |= USART_CR3_DEP;135 cr3 |= USART_CR3_DEP;
134 rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;136 rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
137 mctrl_gpio_set(stm32_port->gpios,
138 stm32_port->port.mctrl | TIOCM_RTS);
135 }139 }
136 140
137 writel_relaxed(cr3, port->membase + ofs->cr3);141 writel_relaxed(cr3, port->membase + ofs->cr3);
@@ -847,9 +851,13 @@ static void stm32_set_termios(struct uart_port *port, struct ktermios *termios, · 709 unmodified lines
847 if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {851 if (rs485conf->flags & SER_RS485_RTS_ON_SEND) {
848 cr3 &= ~USART_CR3_DEP;852 cr3 &= ~USART_CR3_DEP;
849 rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;853 rs485conf->flags &= ~SER_RS485_RTS_AFTER_SEND;
854 mctrl_gpio_set(stm32_port->gpios,
855 stm32_port->port.mctrl & ~TIOCM_RTS);
850 } else {856 } else {
851 cr3 |= USART_CR3_DEP;857 cr3 |= USART_CR3_DEP;
852 rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;858 rs485conf->flags |= SER_RS485_RTS_AFTER_SEND;
859 mctrl_gpio_set(stm32_port->gpios,
860 stm32_port->port.mctrl | TIOCM_RTS);
853 }861 }
854 862
855 } else {863 } else {
@@ -1033,8 +1041,9 @@ static struct stm32_port *stm32_of_get_stm32_port(struct platform_device *pdev) · 177 unmodified lines
1033 if (WARN_ON(id >= STM32_MAX_PORTS))1041 if (WARN_ON(id >= STM32_MAX_PORTS))
1034 return NULL;1042 return NULL;
1035 1043
1036 stm32_ports[id].hw_flow_control = of_property_read_bool(np,1044 stm32_ports[id].hw_flow_control =
1037 "st,hw-flow-ctrl");1045 of_property_read_bool (np, "st,hw-flow-ctrl") /*deprecated*/ ||
1046 of_property_read_bool (np, "uart-has-rtscts");
1038 stm32_ports[id].port.line = id;1047 stm32_ports[id].port.line = id;
1039 stm32_ports[id].cr1_irq = USART_CR1_RXNEIE;1048 stm32_ports[id].cr1_irq = USART_CR1_RXNEIE;
1040 stm32_ports[id].cr3_irq = 0;1049 stm32_ports[id].cr3_irq = 0;
drivers/tty/serial/sunhv.c+0−3
@@ -567,9 +567,6 @@ static int hv_probe(struct platform_device *op) · 566 unmodified lines
567 sunserial_console_match(&sunhv_console, op->dev.of_node,567 sunserial_console_match(&sunhv_console, op->dev.of_node,
568 &sunhv_reg, port->line, false);568 &sunhv_reg, port->line, false);
569 569
570 /* We need to initialize lock even for non-registered console */
571 spin_lock_init(&port->lock);
572
573 err = uart_add_one_port(&sunhv_reg, port);570 err = uart_add_one_port(&sunhv_reg, port);
574 if (err)571 if (err)
575 goto out_unregister_driver;572 goto out_unregister_driver;
drivers/tty/serial/uartlite.c+1−1
@@ -32,7 +32,7 @@ · 31 unmodified lines
32 * Register definitions32 * Register definitions
33 *33 *
34 * For register details see datasheet:34 * For register details see datasheet:
35 * http://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf35 * https://www.xilinx.com/support/documentation/ip_documentation/opb_uartlite.pdf
36 */36 */
37 37
38#define ULITE_RX 0x0038#define ULITE_RX 0x00
drivers/tty/synclink.c+109−241
@@ -252,7 +252,6 @@ struct mgsl_struct { · 251 unmodified lines
252 252
253 char device_name[25]; /* device instance name */253 char device_name[25]; /* device instance name */
254 254
255 unsigned int bus_type; /* expansion bus type (ISA,EISA,PCI) */
256 unsigned char bus; /* expansion bus number (zero based) */255 unsigned char bus; /* expansion bus number (zero based) */
257 unsigned char function; /* PCI device number */256 unsigned char function; /* PCI device number */
258 257
@@ -3432,15 +3431,9 @@ static inline void line_info(struct seq_file *m, struct mgsl_struct *info) · 3173 unmodified lines
3432 char stat_buf[30];3431 char stat_buf[30];
3433 unsigned long flags;3432 unsigned long flags;
3434 3433
3435 if (info->bus_type == MGSL_BUS_TYPE_PCI) {3434 seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X",
3436 seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X",3435 info->device_name, info->io_base, info->irq_level,
3437 info->device_name, info->io_base, info->irq_level,3436 info->phys_memory_base, info->phys_lcr_base);
3438 info->phys_memory_base, info->phys_lcr_base);
3439 } else {
3440 seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d",
3441 info->device_name, info->io_base,
3442 info->irq_level, info->dma_level);
3443 }
3444 3437
3445 /* output current serial signal states */3438 /* output current serial signal states */
3446 spin_lock_irqsave(&info->irq_spinlock,flags);3439 spin_lock_irqsave(&info->irq_spinlock,flags);
@@ -3556,54 +3549,27 @@ static int mgsl_allocate_dma_buffers(struct mgsl_struct *info) · 109 unmodified lines
3556 if ( info->max_frame_size % DMABUFFERSIZE )3549 if ( info->max_frame_size % DMABUFFERSIZE )
3557 BuffersPerFrame++;3550 BuffersPerFrame++;
3558 3551
3559 if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {3552 /*
3560 /*3553 * The PCI adapter has 256KBytes of shared memory to use. This is 64
3561 * The PCI adapter has 256KBytes of shared memory to use.3554 * PAGE_SIZE buffers.
3562 * This is 64 PAGE_SIZE buffers.3555 *
3563 *3556 * The first page is used for padding at this time so the buffer list
3564 * The first page is used for padding at this time so the3557 * does not begin at offset 0 of the PCI adapter's shared memory.
3565 * buffer list does not begin at offset 0 of the PCI3558 *
3566 * adapter's shared memory.3559 * The 2nd page is used for the buffer list. A 4K buffer list can hold
3567 *3560 * 128 DMA_BUFFER structures at 32 bytes each.
3568 * The 2nd page is used for the buffer list. A 4K buffer3561 *
3569 * list can hold 128 DMA_BUFFER structures at 32 bytes3562 * This leaves 62 4K pages.
3570 * each.3563 *
3571 *3564 * The next N pages are used for transmit frame(s). We reserve enough
3572 * This leaves 62 4K pages.3565 * 4K page blocks to hold the required number of transmit dma buffers
3573 *3566 * (num_tx_dma_buffers), each of MaxFrameSize size.
3574 * The next N pages are used for transmit frame(s). We3567 *
3575 * reserve enough 4K page blocks to hold the required3568 * Of the remaining pages (62-N), determine how many can be used to
3576 * number of transmit dma buffers (num_tx_dma_buffers),3569 * receive full MaxFrameSize inbound frames
3577 * each of MaxFrameSize size.3570 */
3578 *3571 info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
3579 * Of the remaining pages (62-N), determine how many can3572 info->rx_buffer_count = 62 - info->tx_buffer_count;
3580 * be used to receive full MaxFrameSize inbound frames
3581 */
3582 info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
3583 info->rx_buffer_count = 62 - info->tx_buffer_count;
3584 } else {
3585 /* Calculate the number of PAGE_SIZE buffers needed for */
3586 /* receive and transmit DMA buffers. */
3587
3588
3589 /* Calculate the number of DMA buffers necessary to */
3590 /* hold 7 max size receive frames and one max size transmit frame. */
3591 /* The receive buffer count is bumped by one so we avoid an */
3592 /* End of List condition if all receive buffers are used when */
3593 /* using linked list DMA buffers. */
3594
3595 info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
3596 info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6;
3597
3598 /*
3599 * limit total TxBuffers & RxBuffers to 62 4K total
3600 * (ala PCI Allocation)
3601 */
3602
3603 if ( (info->tx_buffer_count + info->rx_buffer_count) > 62 )
3604 info->rx_buffer_count = 62 - info->tx_buffer_count;
3605
3606 }
3607 3573
3608 if ( debug_level >= DEBUG_LEVEL_INFO )3574 if ( debug_level >= DEBUG_LEVEL_INFO )
3609 printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n",3575 printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n",
@@ -3652,23 +3618,10 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) · 42 unmodified lines
3652{3618{
3653 unsigned int i;3619 unsigned int i;
3654 3620
3655 if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {3621 /* PCI adapter uses shared memory. */
3656 /* PCI adapter uses shared memory. */3622 info->buffer_list = info->memory_base + info->last_mem_alloc;
3657 info->buffer_list = info->memory_base + info->last_mem_alloc;3623 info->buffer_list_phys = info->last_mem_alloc;
3658 info->buffer_list_phys = info->last_mem_alloc;3624 info->last_mem_alloc += BUFFERLISTSIZE;
3659 info->last_mem_alloc += BUFFERLISTSIZE;
3660 } else {
3661 /* ISA adapter uses system memory. */
3662 /* The buffer lists are allocated as a common buffer that both */
3663 /* the processor and adapter can access. This allows the driver to */
3664 /* inspect portions of the buffer while other portions are being */
3665 /* updated by the adapter using Bus Master DMA. */
3666
3667 info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL);
3668 if (info->buffer_list == NULL)
3669 return -ENOMEM;
3670 info->buffer_list_phys = (u32)(info->buffer_list_dma_addr);
3671 }
3672 3625
3673 /* We got the memory for the buffer entry lists. */3626 /* We got the memory for the buffer entry lists. */
3674 /* Initialize the memory block to all zeros. */3627 /* Initialize the memory block to all zeros. */
@@ -3734,9 +3687,6 @@ static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info ) · 59 unmodified lines
3734 */3687 */
3735static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )3688static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
3736{3689{
3737 if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI)
3738 dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr);
3739
3740 info->buffer_list = NULL;3690 info->buffer_list = NULL;
3741 info->rx_buffer_list = NULL;3691 info->rx_buffer_list = NULL;
3742 info->tx_buffer_list = NULL;3692 info->tx_buffer_list = NULL;
@@ -3762,24 +3712,13 @@ static void mgsl_free_buffer_list_memory( struct mgsl_struct *info ) · 19 unmodified lines
3762static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)3712static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)
3763{3713{
3764 int i;3714 int i;
3765 u32 phys_addr;
3766 3715
3767 /* Allocate page sized buffers for the receive buffer list */3716 /* Allocate page sized buffers for the receive buffer list */
3768 3717
3769 for ( i = 0; i < Buffercount; i++ ) {3718 for ( i = 0; i < Buffercount; i++ ) {
3770 if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {3719 BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc;
3771 /* PCI adapter uses shared memory buffers. */3720 BufferList[i].phys_addr = info->last_mem_alloc;
3772 BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc;3721 info->last_mem_alloc += DMABUFFERSIZE;
3773 phys_addr = info->last_mem_alloc;
3774 info->last_mem_alloc += DMABUFFERSIZE;
3775 } else {
3776 /* ISA adapter uses system memory. */
3777 BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL);
3778 if (BufferList[i].virt_addr == NULL)
3779 return -ENOMEM;
3780 phys_addr = (u32)(BufferList[i].dma_addr);
3781 }
3782 BufferList[i].phys_addr = phys_addr;
3783 }3722 }
3784 3723
3785 return 0;3724 return 0;
@@ -3807,8 +3746,6 @@ static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *Buf · 21 unmodified lines
3807 if ( BufferList ) {3746 if ( BufferList ) {
3808 for ( i = 0 ; i < Buffercount ; i++ ) {3747 for ( i = 0 ; i < Buffercount ; i++ ) {
3809 if ( BufferList[i].virt_addr ) {3748 if ( BufferList[i].virt_addr ) {
3810 if ( info->bus_type != MGSL_BUS_TYPE_PCI )
3811 dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr);
3812 BufferList[i].virt_addr = NULL;3749 BufferList[i].virt_addr = NULL;
3813 }3750 }
3814 }3751 }
@@ -4040,58 +3977,40 @@ static int mgsl_claim_resources(struct mgsl_struct *info) · 225 unmodified lines
4040 }3977 }
4041 info->irq_requested = true;3978 info->irq_requested = true;
4042 3979
4043 if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {3980 if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) {
4044 if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) {3981 printk( "%s(%d):mem addr conflict device %s Addr=%08X\n",
4045 printk( "%s(%d):mem addr conflict device %s Addr=%08X\n",3982 __FILE__,__LINE__,info->device_name, info->phys_memory_base);
4046 __FILE__,__LINE__,info->device_name, info->phys_memory_base);3983 goto errout;
4047 goto errout;3984 }
4048 }3985 info->shared_mem_requested = true;
4049 info->shared_mem_requested = true;3986 if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) {
4050 if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) {3987 printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n",
4051 printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n",3988 __FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset);
4052 __FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset);3989 goto errout;
4053 goto errout;3990 }
4054 }3991 info->lcr_mem_requested = true;
4055 info->lcr_mem_requested = true;3992
4056 3993 info->memory_base = ioremap(info->phys_memory_base, 0x40000);
4057 info->memory_base = ioremap(info->phys_memory_base,3994 if (!info->memory_base) {
4058 0x40000);3995 printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n",
4059 if (!info->memory_base) {3996 __FILE__,__LINE__,info->device_name, info->phys_memory_base );
4060 printk( "%s(%d):Can't map shared memory on device %s MemAddr=%08X\n",3997 goto errout;
4061 __FILE__,__LINE__,info->device_name, info->phys_memory_base );3998 }
4062 goto errout;
4063 }
4064
4065 if ( !mgsl_memory_test(info) ) {
4066 printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n",
4067 __FILE__,__LINE__,info->device_name, info->phys_memory_base );
4068 goto errout;
4069 }
4070
4071 info->lcr_base = ioremap(info->phys_lcr_base,
4072 PAGE_SIZE);
4073 if (!info->lcr_base) {
4074 printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n",
4075 __FILE__,__LINE__,info->device_name, info->phys_lcr_base );
4076 goto errout;
4077 }
4078 info->lcr_base += info->lcr_offset;
4079 3999
4080 } else {4000 if ( !mgsl_memory_test(info) ) {
4081 /* claim DMA channel */4001 printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n",
4002 __FILE__,__LINE__,info->device_name, info->phys_memory_base );
4003 goto errout;
4004 }
4082 4005
4083 if (request_dma(info->dma_level,info->device_name) < 0){4006 info->lcr_base = ioremap(info->phys_lcr_base, PAGE_SIZE);
4084 printk( "%s(%d):Can't request DMA channel on device %s DMA=%d\n",4007 if (!info->lcr_base) {
4085 __FILE__,__LINE__,info->device_name, info->dma_level );4008 printk( "%s(%d):Can't map LCR memory on device %s MemAddr=%08X\n",
4086 goto errout;4009 __FILE__,__LINE__,info->device_name, info->phys_lcr_base );
4087 }4010 goto errout;
4088 info->dma_requested = true;
4089
4090 /* ISA adapter uses bus master DMA */
4091 set_dma_mode(info->dma_level,DMA_MODE_CASCADE);
4092 enable_dma(info->dma_level);
4093 }4011 }
4094 4012 info->lcr_base += info->lcr_offset;
4013
4095 if ( mgsl_allocate_dma_buffers(info) < 0 ) {4014 if ( mgsl_allocate_dma_buffers(info) < 0 ) {
4096 printk( "%s(%d):Can't allocate DMA buffers on device %s DMA=%d\n",4015 printk( "%s(%d):Can't allocate DMA buffers on device %s DMA=%d\n",
4097 __FILE__,__LINE__,info->device_name, info->dma_level );4016 __FILE__,__LINE__,info->device_name, info->dma_level );
@@ -4200,16 +4119,10 @@ static void mgsl_add_device( struct mgsl_struct *info ) · 102 unmodified lines
4200 else if ( info->max_frame_size > 65535 )4119 else if ( info->max_frame_size > 65535 )
4201 info->max_frame_size = 65535;4120 info->max_frame_size = 65535;
4202 4121
4203 if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {4122 printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n",
4204 printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n",4123 info->hw_version + 1, info->device_name, info->io_base, info->irq_level,
4205 info->hw_version + 1, info->device_name, info->io_base, info->irq_level,4124 info->phys_memory_base, info->phys_lcr_base,
4206 info->phys_memory_base, info->phys_lcr_base,4125 info->max_frame_size );
4207 info->max_frame_size );
4208 } else {
4209 printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n",
4210 info->device_name, info->io_base, info->irq_level, info->dma_level,
4211 info->max_frame_size );
4212 }
4213 4126
4214#if SYNCLINK_GENERIC_HDLC4127#if SYNCLINK_GENERIC_HDLC
4215 hdlcdev_init(info);4128 hdlcdev_init(info);
@@ -4420,8 +4333,7 @@ static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd ) · 204 unmodified lines
4420 outw( Cmd + info->loopback_bits, info->io_base + CCAR );4333 outw( Cmd + info->loopback_bits, info->io_base + CCAR );
4421 4334
4422 /* Read to flush write to CCAR */4335 /* Read to flush write to CCAR */
4423 if ( info->bus_type == MGSL_BUS_TYPE_PCI )4336 inw( info->io_base + CCAR );
4424 inw( info->io_base + CCAR );
4425 4337
4426} /* end of usc_RTCmd() */4338} /* end of usc_RTCmd() */
4427 4339
@@ -4445,8 +4357,7 @@ static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd ) · 17 unmodified lines
4445 outw( Cmd + info->mbre_bit, info->io_base );4357 outw( Cmd + info->mbre_bit, info->io_base );
4446 4358
4447 /* Read to flush write to DCAR */4359 /* Read to flush write to DCAR */
4448 if ( info->bus_type == MGSL_BUS_TYPE_PCI )4360 inw( info->io_base );
4449 inw( info->io_base );
4450 4361
4451} /* end of usc_DmaCmd() */4362} /* end of usc_DmaCmd() */
4452 4363
@@ -4475,8 +4386,7 @@ static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) · 22 unmodified lines
4475 outw( RegValue, info->io_base );4386 outw( RegValue, info->io_base );
4476 4387
4477 /* Read to flush write to DCAR */4388 /* Read to flush write to DCAR */
4478 if ( info->bus_type == MGSL_BUS_TYPE_PCI )4389 inw( info->io_base );
4479 inw( info->io_base );
4480 4390
4481} /* end of usc_OutDmaReg() */4391} /* end of usc_OutDmaReg() */
4482 4392
@@ -4528,8 +4438,7 @@ static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue ) · 45 unmodified lines
4528 outw( RegValue, info->io_base + CCAR );4438 outw( RegValue, info->io_base + CCAR );
4529 4439
4530 /* Read to flush write to CCAR */4440 /* Read to flush write to CCAR */
4531 if ( info->bus_type == MGSL_BUS_TYPE_PCI )4441 inw( info->io_base + CCAR );
4532 inw( info->io_base + CCAR );
4533 4442
4534} /* end of usc_OutReg() */4443} /* end of usc_OutReg() */
4535 4444
@@ -4728,10 +4637,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) · 192 unmodified lines
4728 4637
4729 RegValue = usc_InReg( info, RICR ) & 0xc0;4638 RegValue = usc_InReg( info, RICR ) & 0xc0;
4730 4639
4731 if ( info->bus_type == MGSL_BUS_TYPE_PCI )4640 usc_OutReg( info, RICR, (u16)(0x030a | RegValue) );
4732 usc_OutReg( info, RICR, (u16)(0x030a | RegValue) );
4733 else
4734 usc_OutReg( info, RICR, (u16)(0x140a | RegValue) );
4735 4641
4736 /* Unlatch all Rx status bits and clear Rx status IRQ Pending */4642 /* Unlatch all Rx status bits and clear Rx status IRQ Pending */
4737 4643
@@ -4792,10 +4698,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) · 54 unmodified lines
4792 * 0000 0000 0011 0110 = 0x00364698 * 0000 0000 0011 0110 = 0x0036
4793 */4699 */
4794 4700
4795 if ( info->bus_type == MGSL_BUS_TYPE_PCI )4701 usc_OutReg( info, TICR, 0x0736 );
4796 usc_OutReg( info, TICR, 0x0736 );
4797 else
4798 usc_OutReg( info, TICR, 0x1436 );
4799 4702
4800 usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );4703 usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
4801 usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );4704 usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
@@ -4885,10 +4788,7 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) · 83 unmodified lines
4885 /* DPLL is enabled. Use BRG1 to provide continuous reference clock */4788 /* DPLL is enabled. Use BRG1 to provide continuous reference clock */
4886 /* for DPLL. DPLL mode in HCR is dependent on the encoding used. */4789 /* for DPLL. DPLL mode in HCR is dependent on the encoding used. */
4887 4790
4888 if ( info->bus_type == MGSL_BUS_TYPE_PCI )4791 XtalSpeed = 11059200;
4889 XtalSpeed = 11059200;
4890 else
4891 XtalSpeed = 14745600;
4892 4792
4893 if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) {4793 if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) {
4894 DpllDivisor = 16;4794 DpllDivisor = 16;
@@ -5011,13 +4911,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) · 116 unmodified lines
5011 * 0110 0000 0000 1011 = 0x600b4911 * 0110 0000 0000 1011 = 0x600b
5012 */4912 */
5013 4913
5014 if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {4914 /* PCI adapter does not need DMA wait state */
5015 /* PCI adapter does not need DMA wait state */4915 usc_OutDmaReg( info, DCR, 0xa00b );
5016 usc_OutDmaReg( info, DCR, 0xa00b );
5017 }
5018 else
5019 usc_OutDmaReg( info, DCR, 0x800b );
5020
5021 4916
5022 /* Receive DMA mode Register (RDMR)4917 /* Receive DMA mode Register (RDMR)
5023 *4918 *
@@ -5109,12 +5004,8 @@ static void usc_set_sdlc_mode( struct mgsl_struct *info ) · 85 unmodified lines
5109 * <7..0> 0x00 Maximum number of clock cycles per bus grant5004 * <7..0> 0x00 Maximum number of clock cycles per bus grant
5110 */5005 */
5111 5006
5112 if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {5007 /* don't limit bus occupancy on PCI adapter */
5113 /* don't limit bus occupancy on PCI adapter */5008 usc_OutDmaReg( info, BDCR, 0x0000 );
5114 usc_OutDmaReg( info, BDCR, 0x0000 );
5115 }
5116 else
5117 usc_OutDmaReg( info, BDCR, 0x2000 );
5118 5009
5119 usc_stop_transmitter(info);5010 usc_stop_transmitter(info);
5120 usc_stop_receiver(info);5011 usc_stop_receiver(info);
@@ -5155,10 +5046,7 @@ static void usc_enable_loopback(struct mgsl_struct *info, int enable) · 34 unmodified lines
5155 /* Write 16-bit Time Constant for BRG0 */5046 /* Write 16-bit Time Constant for BRG0 */
5156 /* use clock speed if available, otherwise use 8 for diagnostics */5047 /* use clock speed if available, otherwise use 8 for diagnostics */
5157 if (info->params.clock_speed) {5048 if (info->params.clock_speed) {
5158 if (info->bus_type == MGSL_BUS_TYPE_PCI)5049 usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1));
5159 usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1));
5160 else
5161 usc_OutReg(info, TC0R, (u16)((14745600/info->params.clock_speed)-1));
5162 } else5050 } else
5163 usc_OutReg(info, TC0R, (u16)8);5051 usc_OutReg(info, TC0R, (u16)8);
5164 5052
@@ -5201,10 +5089,7 @@ static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate ) · 36 unmodified lines
5201 u16 Tc;5089 u16 Tc;
5202 5090
5203 if ( data_rate ) {5091 if ( data_rate ) {
5204 if ( info->bus_type == MGSL_BUS_TYPE_PCI )5092 XtalSpeed = 11059200;
5205 XtalSpeed = 11059200;
5206 else
5207 XtalSpeed = 14745600;
5208 5093
5209 5094
5210 /* Tc = (Xtal/Speed) - 1 */5095 /* Tc = (Xtal/Speed) - 1 */
@@ -5682,44 +5567,38 @@ static void usc_load_txfifo( struct mgsl_struct *info ) · 471 unmodified lines
5682 */5567 */
5683static void usc_reset( struct mgsl_struct *info )5568static void usc_reset( struct mgsl_struct *info )
5684{5569{
5685 if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {5570 int i;
5686 int i;5571 u32 readval;
5687 u32 readval;
5688 5572
5689 /* Set BIT30 of Misc Control Register */5573 /* Set BIT30 of Misc Control Register */
5690 /* (Local Control Register 0x50) to force reset of USC. */5574 /* (Local Control Register 0x50) to force reset of USC. */
5691 5575
5692 volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50);5576 volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50);
5693 u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28);5577 u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28);
5694 5578
5695 info->misc_ctrl_value |= BIT30;5579 info->misc_ctrl_value |= BIT30;
5696 *MiscCtrl = info->misc_ctrl_value;5580 *MiscCtrl = info->misc_ctrl_value;
5697 5581
5698 /*5582 /*
5699 * Force at least 170ns delay before clearing 5583 * Force at least 170ns delay before clearing reset bit. Each read from
5700 * reset bit. Each read from LCR takes at least 5584 * LCR takes at least 30ns so 10 times for 300ns to be safe.
5701 * 30ns so 10 times for 300ns to be safe.5585 */
5702 */5586 for(i=0;i<10;i++)
5703 for(i=0;i<10;i++)5587 readval = *MiscCtrl;
5704 readval = *MiscCtrl;5588
5705 5589 info->misc_ctrl_value &= ~BIT30;
5706 info->misc_ctrl_value &= ~BIT30;5590 *MiscCtrl = info->misc_ctrl_value;
5707 *MiscCtrl = info->misc_ctrl_value;5591
5708 5592 *LCR0BRDR = BUS_DESCRIPTOR(
5709 *LCR0BRDR = BUS_DESCRIPTOR(5593 1, // Write Strobe Hold (0-3)
5710 1, // Write Strobe Hold (0-3)5594 2, // Write Strobe Delay (0-3)
5711 2, // Write Strobe Delay (0-3)5595 2, // Read Strobe Delay (0-3)
5712 2, // Read Strobe Delay (0-3)5596 0, // NWDD (Write data-data) (0-3)
5713 0, // NWDD (Write data-data) (0-3)5597 4, // NWAD (Write Addr-data) (0-31)
5714 4, // NWAD (Write Addr-data) (0-31)5598 0, // NXDA (Read/Write Data-Addr) (0-3)
5715 0, // NXDA (Read/Write Data-Addr) (0-3)5599 0, // NRDD (Read Data-Data) (0-3)
5716 0, // NRDD (Read Data-Data) (0-3)5600 5 // NRAD (Read Addr-Data) (0-31)
5717 5 // NRAD (Read Addr-Data) (0-31)5601 );
5718 );
5719 } else {
5720 /* do HW reset */
5721 outb( 0,info->io_base + 8 );
5722 }
5723 5602
5724 info->mbre_bit = 0;5603 info->mbre_bit = 0;
5725 info->loopback_bits = 0;5604 info->loopback_bits = 0;
@@ -6228,11 +6107,7 @@ static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate ) · 502 unmodified lines
6228 * ClkSpeed = 921600 (ISA), 691200 (PCI)6107 * ClkSpeed = 921600 (ISA), 691200 (PCI)
6229 */6108 */
6230 6109
6231 if ( info->bus_type == MGSL_BUS_TYPE_PCI )6110 usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) );
6232 usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) );
6233 else
6234 usc_OutReg( info, TC0R, (u16)((921600/data_rate) - 1) );
6235
6236 6111
6237 /*6112 /*
6238 * Hardware Configuration Register (HCR)6113 * Hardware Configuration Register (HCR)
@@ -6837,10 +6712,7 @@ static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, · 598 unmodified lines
6837 6712
6838 /* Actually copy data from source buffer to DMA buffer. */6713 /* Actually copy data from source buffer to DMA buffer. */
6839 /* Also set the data count for this individual DMA buffer. */6714 /* Also set the data count for this individual DMA buffer. */
6840 if ( info->bus_type == MGSL_BUS_TYPE_PCI )6715 mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount);
6841 mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount);
6842 else
6843 memcpy(pBufEntry->virt_addr, Buffer, Copycount);
6844 6716
6845 pBufEntry->count = Copycount;6717 pBufEntry->count = Copycount;
6846 6718
@@ -7315,9 +7187,6 @@ static bool mgsl_memory_test( struct mgsl_struct *info ) · 468 unmodified lines
7315 unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long);7187 unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long);
7316 unsigned long * TestAddr;7188 unsigned long * TestAddr;
7317 7189
7318 if ( info->bus_type != MGSL_BUS_TYPE_PCI )
7319 return true;
7320
7321 TestAddr = (unsigned long *)info->memory_base;7190 TestAddr = (unsigned long *)info->memory_base;
7322 7191
7323 /* Test data lines with test pattern at one location. */7192 /* Test data lines with test pattern at one location. */
@@ -8003,7 +7872,6 @@ static int synclink_init_one (struct pci_dev *dev, · 679 unmodified lines
8003 info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1);7872 info->lcr_offset = info->phys_lcr_base & (PAGE_SIZE-1);
8004 info->phys_lcr_base &= ~(PAGE_SIZE-1);7873 info->phys_lcr_base &= ~(PAGE_SIZE-1);
8005 7874
8006 info->bus_type = MGSL_BUS_TYPE_PCI;
8007 info->io_addr_size = 8;7875 info->io_addr_size = 8;
8008 info->irq_flags = IRQF_SHARED;7876 info->irq_flags = IRQF_SHARED;
8009 7877
drivers/tty/tty_io.c+26−26
@@ -1405,7 +1405,7 @@ void tty_save_termios(struct tty_struct *tty) · 1404 unmodified lines
1405 /* Stash the termios data */1405 /* Stash the termios data */
1406 tp = tty->driver->termios[idx];1406 tp = tty->driver->termios[idx];
1407 if (tp == NULL) {1407 if (tp == NULL) {
1408 tp = kmalloc(sizeof(struct ktermios), GFP_KERNEL);1408 tp = kmalloc(sizeof(*tp), GFP_KERNEL);
1409 if (tp == NULL)1409 if (tp == NULL)
1410 return;1410 return;
1411 tty->driver->termios[idx] = tp;1411 tty->driver->termios[idx] = tp;
@@ -2489,7 +2489,7 @@ static int tty_tiocsserial(struct tty_struct *tty, struct serial_struct __user * · 1077 unmodified lines
2489 struct serial_struct v;2489 struct serial_struct v;
2490 int flags;2490 int flags;
2491 2491
2492 if (copy_from_user(&v, ss, sizeof(struct serial_struct)))2492 if (copy_from_user(&v, ss, sizeof(*ss)))
2493 return -EFAULT;2493 return -EFAULT;
2494 2494
2495 flags = v.flags & ASYNC_DEPRECATED;2495 flags = v.flags & ASYNC_DEPRECATED;
@@ -2507,11 +2507,11 @@ static int tty_tiocgserial(struct tty_struct *tty, struct serial_struct __user * · 11 unmodified lines
2507 struct serial_struct v;2507 struct serial_struct v;
2508 int err;2508 int err;
2509 2509
2510 memset(&v, 0, sizeof(struct serial_struct));2510 memset(&v, 0, sizeof(v));
2511 if (!tty->ops->get_serial)2511 if (!tty->ops->get_serial)
2512 return -ENOTTY;2512 return -ENOTTY;
2513 err = tty->ops->get_serial(tty, &v);2513 err = tty->ops->get_serial(tty, &v);
2514 if (!err && copy_to_user(ss, &v, sizeof(struct serial_struct)))2514 if (!err && copy_to_user(ss, &v, sizeof(v)))
2515 err = -EFAULT;2515 err = -EFAULT;
2516 return err;2516 return err;
2517}2517}
@@ -2673,25 +2673,25 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) · 155 unmodified lines
2673#ifdef CONFIG_COMPAT2673#ifdef CONFIG_COMPAT
2674 2674
2675struct serial_struct32 {2675struct serial_struct32 {
2676 compat_int_t type;2676 compat_int_t type;
2677 compat_int_t line;2677 compat_int_t line;
2678 compat_uint_t port;2678 compat_uint_t port;
2679 compat_int_t irq;2679 compat_int_t irq;
2680 compat_int_t flags;2680 compat_int_t flags;
2681 compat_int_t xmit_fifo_size;2681 compat_int_t xmit_fifo_size;
2682 compat_int_t custom_divisor;2682 compat_int_t custom_divisor;
2683 compat_int_t baud_base;2683 compat_int_t baud_base;
2684 unsigned short close_delay;2684 unsigned short close_delay;
2685 char io_type;2685 char io_type;
2686 char reserved_char[1];2686 char reserved_char;
2687 compat_int_t hub6;2687 compat_int_t hub6;
2688 unsigned short closing_wait; /* time to wait before closing */2688 unsigned short closing_wait; /* time to wait before closing */
2689 unsigned short closing_wait2; /* no longer used... */2689 unsigned short closing_wait2; /* no longer used... */
2690 compat_uint_t iomem_base;2690 compat_uint_t iomem_base;
2691 unsigned short iomem_reg_shift;2691 unsigned short iomem_reg_shift;
2692 unsigned int port_high;2692 unsigned int port_high;
2693 /* compat_ulong_t iomap_base FIXME */2693 /* compat_ulong_t iomap_base FIXME */
2694 compat_int_t reserved[1];2694 compat_int_t reserved;
2695};2695};
2696 2696
2697static int compat_tty_tiocsserial(struct tty_struct *tty,2697static int compat_tty_tiocsserial(struct tty_struct *tty,
@@ -2705,7 +2705,7 @@ static int compat_tty_tiocsserial(struct tty_struct *tty, · 7 unmodified lines
2705 struct serial_struct v;2705 struct serial_struct v;
2706 int flags;2706 int flags;
2707 2707
2708 if (copy_from_user(&v32, ss, sizeof(struct serial_struct32)))2708 if (copy_from_user(&v32, ss, sizeof(*ss)))
2709 return -EFAULT;2709 return -EFAULT;
2710 2710
2711 memcpy(&v, &v32, offsetof(struct serial_struct32, iomem_base));2711 memcpy(&v, &v32, offsetof(struct serial_struct32, iomem_base));
@@ -2743,7 +2743,7 @@ static int compat_tty_tiocgserial(struct tty_struct *tty, · 31 unmodified lines
2743 0xfffffff : ptr_to_compat(v.iomem_base);2743 0xfffffff : ptr_to_compat(v.iomem_base);
2744 v32.iomem_reg_shift = v.iomem_reg_shift;2744 v32.iomem_reg_shift = v.iomem_reg_shift;
2745 v32.port_high = v.port_high;2745 v32.port_high = v.port_high;
2746 if (copy_to_user(ss, &v32, sizeof(struct serial_struct32)))2746 if (copy_to_user(ss, &v32, sizeof(v32)))
2747 err = -EFAULT;2747 err = -EFAULT;
2748 }2748 }
2749 return err;2749 return err;
@@ -3215,7 +3215,7 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner, · 465 unmodified lines
3215 if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1))3215 if (!lines || (flags & TTY_DRIVER_UNNUMBERED_NODE && lines > 1))
3216 return ERR_PTR(-EINVAL);3216 return ERR_PTR(-EINVAL);
3217 3217
3218 driver = kzalloc(sizeof(struct tty_driver), GFP_KERNEL);3218 driver = kzalloc(sizeof(*driver), GFP_KERNEL);
3219 if (!driver)3219 if (!driver)
3220 return ERR_PTR(-ENOMEM);3220 return ERR_PTR(-ENOMEM);
3221 3221
drivers/tty/vt/consolemap.c+1−1
@@ -542,7 +542,7 @@ int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list) · 541 unmodified lines
542 if (!ct)542 if (!ct)
543 return 0;543 return 0;
544 544
545 unilist = vmemdup_user(list, ct * sizeof(struct unipair));545 unilist = vmemdup_user(list, array_size(sizeof(struct unipair), ct));
546 if (IS_ERR(unilist))546 if (IS_ERR(unilist))
547 return PTR_ERR(unilist);547 return PTR_ERR(unilist);
548 548
drivers/tty/vt/keyboard.c+2−1
@@ -32,6 +32,7 @@ · 31 unmodified lines
32#include <linux/tty.h>32#include <linux/tty.h>
33#include <linux/tty_flip.h>33#include <linux/tty_flip.h>
34#include <linux/mm.h>34#include <linux/mm.h>
35#include <linux/nospec.h>
35#include <linux/string.h>36#include <linux/string.h>
36#include <linux/init.h>37#include <linux/init.h>
37#include <linux/slab.h>38#include <linux/slab.h>
@@ -2019,7 +2020,7 @@ int vt_do_kdgkb_ioctl(int cmd, struct kbsentry __user *user_kdgkb, int perm) · 1981 unmodified lines
2019 goto reterr;2020 goto reterr;
2020 }2021 }
2021 kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';2022 kbs->kb_string[sizeof(kbs->kb_string)-1] = '\0';
2022 i = kbs->kb_func;2023 i = array_index_nospec(kbs->kb_func, MAX_NR_FUNC);
2023 2024
2024 switch (cmd) {2025 switch (cmd) {
2025 case KDGKBSENT:2026 case KDGKBSENT:
drivers/tty/vt/selection.c+1−1
@@ -193,7 +193,7 @@ static int vc_selection_store_chars(struct vc_data *vc, bool unicode) · 192 unmodified lines
193 /* Allocate a new buffer before freeing the old one ... */193 /* Allocate a new buffer before freeing the old one ... */
194 /* chars can take up to 4 bytes with unicode */194 /* chars can take up to 4 bytes with unicode */
195 bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1,195 bp = kmalloc_array((vc_sel.end - vc_sel.start) / 2 + 1, unicode ? 4 : 1,
196 GFP_KERNEL);196 GFP_KERNEL | __GFP_NOWARN);
197 if (!bp) {197 if (!bp) {
198 printk(KERN_WARNING "selection: kmalloc() failed\n");198 printk(KERN_WARNING "selection: kmalloc() failed\n");
199 clear_selection();199 clear_selection();
drivers/tty/vt/vt.c+533−449
@@ -127,14 +127,6 @@ struct con_driver { · 126 unmodified lines
127static struct con_driver registered_con_driver[MAX_NR_CON_DRIVER];127static struct con_driver registered_con_driver[MAX_NR_CON_DRIVER];
128const struct consw *conswitchp;128const struct consw *conswitchp;
129 129
130/* A bitmap for codes <32. A bit of 1 indicates that the code
131 * corresponding to that bit number invokes some special action
132 * (such as cursor movement) and should not be displayed as a
133 * glyph unless the disp_ctrl mode is explicitly enabled.
134 */
135#define CTRL_ACTION 0x0d00ff81
136#define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */
137
138/*130/*
139 * Here is the default bell parameters: 750HZ, 1/8th of a second131 * Here is the default bell parameters: 750HZ, 1/8th of a second
140 */132 */
@@ -171,7 +163,7 @@ module_param(default_utf8, int, S_IRUGO | S_IWUSR); · 30 unmodified lines
171int global_cursor_default = -1;163int global_cursor_default = -1;
172module_param(global_cursor_default, int, S_IRUGO | S_IWUSR);164module_param(global_cursor_default, int, S_IRUGO | S_IWUSR);
173 165
174static int cur_default = CUR_DEFAULT;166static int cur_default = CUR_UNDERLINE;
175module_param(cur_default, int, S_IRUGO | S_IWUSR);167module_param(cur_default, int, S_IRUGO | S_IWUSR);
176 168
177/*169/*
@@ -381,7 +373,7 @@ static void vc_uniscr_putc(struct vc_data *vc, char32_t uc) · 203 unmodified lines
381 struct uni_screen *uniscr = get_vc_uniscr(vc);373 struct uni_screen *uniscr = get_vc_uniscr(vc);
382 374
383 if (uniscr)375 if (uniscr)
384 uniscr->lines[vc->vc_y][vc->vc_x] = uc;376 uniscr->lines[vc->state.y][vc->state.x] = uc;
385}377}
386 378
387static void vc_uniscr_insert(struct vc_data *vc, unsigned int nr)379static void vc_uniscr_insert(struct vc_data *vc, unsigned int nr)
@@ -389,8 +381,8 @@ static void vc_uniscr_insert(struct vc_data *vc, unsigned int nr) · 1 unmodified line
389 struct uni_screen *uniscr = get_vc_uniscr(vc);381 struct uni_screen *uniscr = get_vc_uniscr(vc);
390 382
391 if (uniscr) {383 if (uniscr) {
392 char32_t *ln = uniscr->lines[vc->vc_y];384 char32_t *ln = uniscr->lines[vc->state.y];
393 unsigned int x = vc->vc_x, cols = vc->vc_cols;385 unsigned int x = vc->state.x, cols = vc->vc_cols;
394 386
395 memmove(&ln[x + nr], &ln[x], (cols - x - nr) * sizeof(*ln));387 memmove(&ln[x + nr], &ln[x], (cols - x - nr) * sizeof(*ln));
396 memset32(&ln[x], ' ', nr);388 memset32(&ln[x], ' ', nr);
@@ -402,8 +394,8 @@ static void vc_uniscr_delete(struct vc_data *vc, unsigned int nr) · 5 unmodified lines
402 struct uni_screen *uniscr = get_vc_uniscr(vc);394 struct uni_screen *uniscr = get_vc_uniscr(vc);
403 395
404 if (uniscr) {396 if (uniscr) {
405 char32_t *ln = uniscr->lines[vc->vc_y];397 char32_t *ln = uniscr->lines[vc->state.y];
406 unsigned int x = vc->vc_x, cols = vc->vc_cols;398 unsigned int x = vc->state.x, cols = vc->vc_cols;
407 399
408 memcpy(&ln[x], &ln[x + nr], (cols - x - nr) * sizeof(*ln));400 memcpy(&ln[x], &ln[x + nr], (cols - x - nr) * sizeof(*ln));
409 memset32(&ln[cols - nr], ' ', nr);401 memset32(&ln[cols - nr], ' ', nr);
@@ -416,7 +408,7 @@ static void vc_uniscr_clear_line(struct vc_data *vc, unsigned int x, · 6 unmodified lines
416 struct uni_screen *uniscr = get_vc_uniscr(vc);408 struct uni_screen *uniscr = get_vc_uniscr(vc);
417 409
418 if (uniscr) {410 if (uniscr) {
419 char32_t *ln = uniscr->lines[vc->vc_y];411 char32_t *ln = uniscr->lines[vc->state.y];
420 412
421 memset32(&ln[x], ' ', nr);413 memset32(&ln[x], ' ', nr);
422 }414 }
@@ -705,8 +697,9 @@ void update_region(struct vc_data *vc, unsigned long start, int count) · 282 unmodified lines
705 697
706/* Structure of attributes is hardware-dependent */698/* Structure of attributes is hardware-dependent */
707 699
708static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink,700static u8 build_attr(struct vc_data *vc, u8 _color,
709 u8 _underline, u8 _reverse, u8 _italic)701 enum vc_intensity _intensity, bool _blink, bool _underline,
702 bool _reverse, bool _italic)
710{703{
711 if (vc->vc_sw->con_build_attr)704 if (vc->vc_sw->con_build_attr)
712 return vc->vc_sw->con_build_attr(vc, _color, _intensity,705 return vc->vc_sw->con_build_attr(vc, _color, _intensity,
@@ -726,21 +719,21 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, · 13 unmodified lines
726 u8 a = _color;719 u8 a = _color;
727 if (!vc->vc_can_do_color)720 if (!vc->vc_can_do_color)
728 return _intensity |721 return _intensity |
729 (_italic ? 2 : 0) |722 (_italic << 1) |
730 (_underline ? 4 : 0) |723 (_underline << 2) |
731 (_reverse ? 8 : 0) |724 (_reverse << 3) |
732 (_blink ? 0x80 : 0);725 (_blink << 7);
733 if (_italic)726 if (_italic)
734 a = (a & 0xF0) | vc->vc_itcolor;727 a = (a & 0xF0) | vc->vc_itcolor;
735 else if (_underline)728 else if (_underline)
736 a = (a & 0xf0) | vc->vc_ulcolor;729 a = (a & 0xf0) | vc->vc_ulcolor;
737 else if (_intensity == 0)730 else if (_intensity == VCI_HALF_BRIGHT)
738 a = (a & 0xf0) | vc->vc_halfcolor;731 a = (a & 0xf0) | vc->vc_halfcolor;
739 if (_reverse)732 if (_reverse)
740 a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77);733 a = (a & 0x88) | (((a >> 4) | (a << 4)) & 0x77);
741 if (_blink)734 if (_blink)
742 a ^= 0x80;735 a ^= 0x80;
743 if (_intensity == 2)736 if (_intensity == VCI_BOLD)
744 a ^= 0x08;737 a ^= 0x08;
745 if (vc->vc_hi_font_mask == 0x100)738 if (vc->vc_hi_font_mask == 0x100)
746 a <<= 1;739 a <<= 1;
@@ -750,10 +743,12 @@ static u8 build_attr(struct vc_data *vc, u8 _color, u8 _intensity, u8 _blink, · 3 unmodified lines
750 743
751static void update_attr(struct vc_data *vc)744static void update_attr(struct vc_data *vc)
752{745{
753 vc->vc_attr = build_attr(vc, vc->vc_color, vc->vc_intensity,746 vc->vc_attr = build_attr(vc, vc->state.color, vc->state.intensity,
754 vc->vc_blink, vc->vc_underline,747 vc->state.blink, vc->state.underline,
755 vc->vc_reverse ^ vc->vc_decscnm, vc->vc_italic);748 vc->state.reverse ^ vc->vc_decscnm, vc->state.italic);
756 vc->vc_video_erase_char = (build_attr(vc, vc->vc_color, 1, vc->vc_blink, 0, vc->vc_decscnm, 0) << 8) | ' ';749 vc->vc_video_erase_char = ' ' | (build_attr(vc, vc->state.color,
750 VCI_NORMAL, vc->state.blink, false,
751 vc->vc_decscnm, false) << 8);
757}752}
758 753
759/* Note: inverting the screen twice should revert to the original state */754/* Note: inverting the screen twice should revert to the original state */
@@ -782,14 +777,18 @@ void invert_screen(struct vc_data *vc, int offset, int count, int viewed) · 22 unmodified lines
782 } else if (vc->vc_hi_font_mask == 0x100) {777 } else if (vc->vc_hi_font_mask == 0x100) {
783 while (cnt--) {778 while (cnt--) {
784 a = scr_readw(q);779 a = scr_readw(q);
785 a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);780 a = (a & 0x11ff) |
781 ((a & 0xe000) >> 4) |
782 ((a & 0x0e00) << 4);
786 scr_writew(a, q);783 scr_writew(a, q);
787 q++;784 q++;
788 }785 }
789 } else {786 } else {
790 while (cnt--) {787 while (cnt--) {
791 a = scr_readw(q);788 a = scr_readw(q);
792 a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);789 a = (a & 0x88ff) |
790 ((a & 0x7000) >> 4) |
791 ((a & 0x0700) << 4);
793 scr_writew(a, q);792 scr_writew(a, q);
794 q++;793 q++;
795 }794 }
@@ -842,12 +841,12 @@ static void insert_char(struct vc_data *vc, unsigned int nr) · 46 unmodified lines
842 unsigned short *p = (unsigned short *) vc->vc_pos;841 unsigned short *p = (unsigned short *) vc->vc_pos;
843 842
844 vc_uniscr_insert(vc, nr);843 vc_uniscr_insert(vc, nr);
845 scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2);844 scr_memmovew(p + nr, p, (vc->vc_cols - vc->state.x - nr) * 2);
846 scr_memsetw(p, vc->vc_video_erase_char, nr * 2);845 scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
847 vc->vc_need_wrap = 0;846 vc->vc_need_wrap = 0;
848 if (con_should_update(vc))847 if (con_should_update(vc))
849 do_update_region(vc, (unsigned long) p,848 do_update_region(vc, (unsigned long) p,
850 vc->vc_cols - vc->vc_x);849 vc->vc_cols - vc->state.x);
851}850}
852 851
853static void delete_char(struct vc_data *vc, unsigned int nr)852static void delete_char(struct vc_data *vc, unsigned int nr)
@@ -855,13 +854,13 @@ static void delete_char(struct vc_data *vc, unsigned int nr) · 1 unmodified line
855 unsigned short *p = (unsigned short *) vc->vc_pos;854 unsigned short *p = (unsigned short *) vc->vc_pos;
856 855
857 vc_uniscr_delete(vc, nr);856 vc_uniscr_delete(vc, nr);
858 scr_memcpyw(p, p + nr, (vc->vc_cols - vc->vc_x - nr) * 2);857 scr_memcpyw(p, p + nr, (vc->vc_cols - vc->state.x - nr) * 2);
859 scr_memsetw(p + vc->vc_cols - vc->vc_x - nr, vc->vc_video_erase_char,858 scr_memsetw(p + vc->vc_cols - vc->state.x - nr, vc->vc_video_erase_char,
860 nr * 2);859 nr * 2);
861 vc->vc_need_wrap = 0;860 vc->vc_need_wrap = 0;
862 if (con_should_update(vc))861 if (con_should_update(vc))
863 do_update_region(vc, (unsigned long) p,862 do_update_region(vc, (unsigned long) p,
864 vc->vc_cols - vc->vc_x);863 vc->vc_cols - vc->state.x);
865}864}
866 865
867static int softcursor_original = -1;866static int softcursor_original = -1;
@@ -871,16 +870,21 @@ static void add_softcursor(struct vc_data *vc) · 3 unmodified lines
871 int i = scr_readw((u16 *) vc->vc_pos);870 int i = scr_readw((u16 *) vc->vc_pos);
872 u32 type = vc->vc_cursor_type;871 u32 type = vc->vc_cursor_type;
873 872
874 if (! (type & 0x10)) return;873 if (!(type & CUR_SW))
875 if (softcursor_original != -1) return;874 return;
875 if (softcursor_original != -1)
876 return;
876 softcursor_original = i;877 softcursor_original = i;
877 i |= ((type >> 8) & 0xff00 );878 i |= CUR_SET(type);
878 i ^= ((type) & 0xff00 );879 i ^= CUR_CHANGE(type);
879 if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;880 if ((type & CUR_ALWAYS_BG) &&
880 if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;881 (softcursor_original & CUR_BG) == (i & CUR_BG))
881 scr_writew(i, (u16 *) vc->vc_pos);882 i ^= CUR_BG;
883 if ((type & CUR_INVERT_FG_BG) && (i & CUR_FG) == ((i & CUR_BG) >> 4))
884 i ^= CUR_FG;
885 scr_writew(i, (u16 *)vc->vc_pos);
882 if (con_should_update(vc))886 if (con_should_update(vc))
883 vc->vc_sw->con_putc(vc, i, vc->vc_y, vc->vc_x);887 vc->vc_sw->con_putc(vc, i, vc->state.y, vc->state.x);
884}888}
885 889
886static void hide_softcursor(struct vc_data *vc)890static void hide_softcursor(struct vc_data *vc)
@@ -889,7 +893,7 @@ static void hide_softcursor(struct vc_data *vc) · 2 unmodified lines
889 scr_writew(softcursor_original, (u16 *)vc->vc_pos);893 scr_writew(softcursor_original, (u16 *)vc->vc_pos);
890 if (con_should_update(vc))894 if (con_should_update(vc))
891 vc->vc_sw->con_putc(vc, softcursor_original,895 vc->vc_sw->con_putc(vc, softcursor_original,
892 vc->vc_y, vc->vc_x);896 vc->state.y, vc->state.x);
893 softcursor_original = -1;897 softcursor_original = -1;
894 }898 }
895}899}
@@ -911,7 +915,7 @@ static void set_cursor(struct vc_data *vc) · 15 unmodified lines
911 if (vc_is_sel(vc))915 if (vc_is_sel(vc))
912 clear_selection();916 clear_selection();
913 add_softcursor(vc);917 add_softcursor(vc);
914 if ((vc->vc_cursor_type & 0x0f) != 1)918 if (CUR_SIZE(vc->vc_cursor_type) != CUR_NONE)
915 vc->vc_sw->con_cursor(vc, CM_DRAW);919 vc->vc_sw->con_cursor(vc, CM_DRAW);
916 } else920 } else
917 hide_cursor(vc);921 hide_cursor(vc);
@@ -927,7 +931,8 @@ static void set_origin(struct vc_data *vc) · 9 unmodified lines
927 vc->vc_origin = (unsigned long)vc->vc_screenbuf;931 vc->vc_origin = (unsigned long)vc->vc_screenbuf;
928 vc->vc_visible_origin = vc->vc_origin;932 vc->vc_visible_origin = vc->vc_origin;
929 vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;933 vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
930 vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;934 vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->state.y +
935 2 * vc->state.x;
931}936}
932 937
933static void save_screen(struct vc_data *vc)938static void save_screen(struct vc_data *vc)
@@ -1256,8 +1261,8 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, · 322 unmodified lines
1256 new_origin = (long) newscreen;1261 new_origin = (long) newscreen;
1257 new_scr_end = new_origin + new_screen_size;1262 new_scr_end = new_origin + new_screen_size;
1258 1263
1259 if (vc->vc_y > new_rows) {1264 if (vc->state.y > new_rows) {
1260 if (old_rows - vc->vc_y < new_rows) {1265 if (old_rows - vc->state.y < new_rows) {
1261 /*1266 /*
1262 * Cursor near the bottom, copy contents from the1267 * Cursor near the bottom, copy contents from the
1263 * bottom of buffer1268 * bottom of buffer
@@ -1268,7 +1273,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, · 4 unmodified lines
1268 * Cursor is in no man's land, copy 1/2 screenful1273 * Cursor is in no man's land, copy 1/2 screenful
1269 * from the top and bottom of cursor position1274 * from the top and bottom of cursor position
1270 */1275 */
1271 first_copied_row = (vc->vc_y - new_rows/2);1276 first_copied_row = (vc->state.y - new_rows/2);
1272 }1277 }
1273 old_origin += first_copied_row * old_row_size;1278 old_origin += first_copied_row * old_row_size;
1274 } else1279 } else
@@ -1302,7 +1307,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc, · 27 unmodified lines
1302 /* do part of a reset_terminal() */1307 /* do part of a reset_terminal() */
1303 vc->vc_top = 0;1308 vc->vc_top = 0;
1304 vc->vc_bottom = vc->vc_rows;1309 vc->vc_bottom = vc->vc_rows;
1305 gotoxy(vc, vc->vc_x, vc->vc_y);1310 gotoxy(vc, vc->state.x, vc->state.y);
1306 save_cur(vc);1311 save_cur(vc);
1307 1312
1308 if (tty) {1313 if (tty) {
@@ -1399,12 +1404,6 @@ enum { EPecma = 0, EPdec, EPeq, EPgt, EPlt}; · 90 unmodified lines
1399#define kbdapplic VC_APPLIC1404#define kbdapplic VC_APPLIC
1400#define lnm VC_CRLF1405#define lnm VC_CRLF
1401 1406
1402/*
1403 * this is what the terminal answers to a ESC-Z or csi0c query.
1404 */
1405#define VT100ID "\033[?1;2c"
1406#define VT102ID "\033[?6c"
1407
1408const unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,1407const unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
1409 8,12,10,14, 9,13,11,15 };1408 8,12,10,14, 9,13,11,15 };
1410 1409
@@ -1437,12 +1436,12 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y) · 26 unmodified lines
1437 int min_y, max_y;1436 int min_y, max_y;
1438 1437
1439 if (new_x < 0)1438 if (new_x < 0)
1440 vc->vc_x = 0;1439 vc->state.x = 0;
1441 else {1440 else {
1442 if (new_x >= vc->vc_cols)1441 if (new_x >= vc->vc_cols)
1443 vc->vc_x = vc->vc_cols - 1;1442 vc->state.x = vc->vc_cols - 1;
1444 else1443 else
1445 vc->vc_x = new_x;1444 vc->state.x = new_x;
1446 }1445 }
1447 1446
1448 if (vc->vc_decom) {1447 if (vc->vc_decom) {
@@ -1453,12 +1452,13 @@ static void gotoxy(struct vc_data *vc, int new_x, int new_y) · 4 unmodified lines
1453 max_y = vc->vc_rows;1452 max_y = vc->vc_rows;
1454 }1453 }
1455 if (new_y < min_y)1454 if (new_y < min_y)
1456 vc->vc_y = min_y;1455 vc->state.y = min_y;
1457 else if (new_y >= max_y)1456 else if (new_y >= max_y)
1458 vc->vc_y = max_y - 1;1457 vc->state.y = max_y - 1;
1459 else1458 else
1460 vc->vc_y = new_y;1459 vc->state.y = new_y;
1461 vc->vc_pos = vc->vc_origin + vc->vc_y * vc->vc_size_row + (vc->vc_x<<1);1460 vc->vc_pos = vc->vc_origin + vc->state.y * vc->vc_size_row +
1461 (vc->state.x << 1);
1462 vc->vc_need_wrap = 0;1462 vc->vc_need_wrap = 0;
1463}1463}
1464 1464
@@ -1485,10 +1485,10 @@ static void lf(struct vc_data *vc) · 20 unmodified lines
1485 /* don't scroll if above bottom of scrolling region, or1485 /* don't scroll if above bottom of scrolling region, or
1486 * if below scrolling region1486 * if below scrolling region
1487 */1487 */
1488 if (vc->vc_y + 1 == vc->vc_bottom)1488 if (vc->state.y + 1 == vc->vc_bottom)
1489 con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_UP, 1);1489 con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_UP, 1);
1490 else if (vc->vc_y < vc->vc_rows - 1) {1490 else if (vc->state.y < vc->vc_rows - 1) {
1491 vc->vc_y++;1491 vc->state.y++;
1492 vc->vc_pos += vc->vc_size_row;1492 vc->vc_pos += vc->vc_size_row;
1493 }1493 }
1494 vc->vc_need_wrap = 0;1494 vc->vc_need_wrap = 0;
@@ -1500,10 +1500,10 @@ static void ri(struct vc_data *vc) · 5 unmodified lines
1500 /* don't scroll if below top of scrolling region, or1500 /* don't scroll if below top of scrolling region, or
1501 * if above scrolling region1501 * if above scrolling region
1502 */1502 */
1503 if (vc->vc_y == vc->vc_top)1503 if (vc->state.y == vc->vc_top)
1504 con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_DOWN, 1);1504 con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_DOWN, 1);
1505 else if (vc->vc_y > 0) {1505 else if (vc->state.y > 0) {
1506 vc->vc_y--;1506 vc->state.y--;
1507 vc->vc_pos -= vc->vc_size_row;1507 vc->vc_pos -= vc->vc_size_row;
1508 }1508 }
1509 vc->vc_need_wrap = 0;1509 vc->vc_need_wrap = 0;
@@ -1511,16 +1511,16 @@ static void ri(struct vc_data *vc) · 1 unmodified line
1511 1511
1512static inline void cr(struct vc_data *vc)1512static inline void cr(struct vc_data *vc)
1513{1513{
1514 vc->vc_pos -= vc->vc_x << 1;1514 vc->vc_pos -= vc->state.x << 1;
1515 vc->vc_need_wrap = vc->vc_x = 0;1515 vc->vc_need_wrap = vc->state.x = 0;
1516 notify_write(vc, '\r');1516 notify_write(vc, '\r');
1517}1517}
1518 1518
1519static inline void bs(struct vc_data *vc)1519static inline void bs(struct vc_data *vc)
1520{1520{
1521 if (vc->vc_x) {1521 if (vc->state.x) {
1522 vc->vc_pos -= 2;1522 vc->vc_pos -= 2;
1523 vc->vc_x--;1523 vc->state.x--;
1524 vc->vc_need_wrap = 0;1524 vc->vc_need_wrap = 0;
1525 notify_write(vc, '\b');1525 notify_write(vc, '\b');
1526 }1526 }
@@ -1538,16 +1538,16 @@ static void csi_J(struct vc_data *vc, int vpar) · 11 unmodified lines
1538 1538
1539 switch (vpar) {1539 switch (vpar) {
1540 case 0: /* erase from cursor to end of display */1540 case 0: /* erase from cursor to end of display */
1541 vc_uniscr_clear_line(vc, vc->vc_x,1541 vc_uniscr_clear_line(vc, vc->state.x,
1542 vc->vc_cols - vc->vc_x);1542 vc->vc_cols - vc->state.x);
1543 vc_uniscr_clear_lines(vc, vc->vc_y + 1,1543 vc_uniscr_clear_lines(vc, vc->state.y + 1,
1544 vc->vc_rows - vc->vc_y - 1);1544 vc->vc_rows - vc->state.y - 1);
1545 count = (vc->vc_scr_end - vc->vc_pos) >> 1;1545 count = (vc->vc_scr_end - vc->vc_pos) >> 1;
1546 start = (unsigned short *)vc->vc_pos;1546 start = (unsigned short *)vc->vc_pos;
1547 break;1547 break;
1548 case 1: /* erase from start to cursor */1548 case 1: /* erase from start to cursor */
1549 vc_uniscr_clear_line(vc, 0, vc->vc_x + 1);1549 vc_uniscr_clear_line(vc, 0, vc->state.x + 1);
1550 vc_uniscr_clear_lines(vc, 0, vc->vc_y);1550 vc_uniscr_clear_lines(vc, 0, vc->state.y);
1551 count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;1551 count = ((vc->vc_pos - vc->vc_origin) >> 1) + 1;
1552 start = (unsigned short *)vc->vc_origin;1552 start = (unsigned short *)vc->vc_origin;
1553 break;1553 break;
@@ -1577,49 +1577,51 @@ static void csi_K(struct vc_data *vc, int vpar) · 23 unmodified lines
1577 switch (vpar) {1577 switch (vpar) {
1578 case 0: /* erase from cursor to end of line */1578 case 0: /* erase from cursor to end of line */
1579 offset = 0;1579 offset = 0;
1580 count = vc->vc_cols - vc->vc_x;1580 count = vc->vc_cols - vc->state.x;
1581 break;1581 break;
1582 case 1: /* erase from start of line to cursor */1582 case 1: /* erase from start of line to cursor */
1583 offset = -vc->vc_x;1583 offset = -vc->state.x;
1584 count = vc->vc_x + 1;1584 count = vc->state.x + 1;
1585 break;1585 break;
1586 case 2: /* erase whole line */1586 case 2: /* erase whole line */
1587 offset = -vc->vc_x;1587 offset = -vc->state.x;
1588 count = vc->vc_cols;1588 count = vc->vc_cols;
1589 break;1589 break;
1590 default:1590 default:
1591 return;1591 return;
1592 }1592 }
1593 vc_uniscr_clear_line(vc, vc->vc_x + offset, count);1593 vc_uniscr_clear_line(vc, vc->state.x + offset, count);
1594 scr_memsetw(start + offset, vc->vc_video_erase_char, 2 * count);1594 scr_memsetw(start + offset, vc->vc_video_erase_char, 2 * count);
1595 vc->vc_need_wrap = 0;1595 vc->vc_need_wrap = 0;
1596 if (con_should_update(vc))1596 if (con_should_update(vc))
1597 do_update_region(vc, (unsigned long)(start + offset), count);1597 do_update_region(vc, (unsigned long)(start + offset), count);
1598}1598}
1599 1599
1600static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */1600/* erase the following vpar positions */
1601static void csi_X(struct vc_data *vc, unsigned int vpar)
1601{ /* not vt100? */1602{ /* not vt100? */
1602 int count;1603 unsigned int count;
1603 1604
1604 if (!vpar)1605 if (!vpar)
1605 vpar++;1606 vpar++;
1606 count = (vpar > vc->vc_cols - vc->vc_x) ? (vc->vc_cols - vc->vc_x) : vpar;
1607 1607
1608 vc_uniscr_clear_line(vc, vc->vc_x, count);1608 count = min(vpar, vc->vc_cols - vc->state.x);
1609
1610 vc_uniscr_clear_line(vc, vc->state.x, count);
1609 scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);1611 scr_memsetw((unsigned short *)vc->vc_pos, vc->vc_video_erase_char, 2 * count);
1610 if (con_should_update(vc))1612 if (con_should_update(vc))
1611 vc->vc_sw->con_clear(vc, vc->vc_y, vc->vc_x, 1, count);1613 vc->vc_sw->con_clear(vc, vc->state.y, vc->state.x, 1, count);
1612 vc->vc_need_wrap = 0;1614 vc->vc_need_wrap = 0;
1613}1615}
1614 1616
1615static void default_attr(struct vc_data *vc)1617static void default_attr(struct vc_data *vc)
1616{1618{
1617 vc->vc_intensity = 1;1619 vc->state.intensity = VCI_NORMAL;
1618 vc->vc_italic = 0;1620 vc->state.italic = false;
1619 vc->vc_underline = 0;1621 vc->state.underline = false;
1620 vc->vc_reverse = 0;1622 vc->state.reverse = false;
1621 vc->vc_blink = 0;1623 vc->state.blink = false;
1622 vc->vc_color = vc->vc_def_color;1624 vc->state.color = vc->vc_def_color;
1623}1625}
1624 1626
1625struct rgb { u8 r; u8 g; u8 b; };1627struct rgb { u8 r; u8 g; u8 b; };
@@ -1655,19 +1657,19 @@ static void rgb_foreground(struct vc_data *vc, const struct rgb *c) · 29 unmodified lines
1655 1657
1656 if (hue == 7 && max <= 0x55) {1658 if (hue == 7 && max <= 0x55) {
1657 hue = 0;1659 hue = 0;
1658 vc->vc_intensity = 2;1660 vc->state.intensity = VCI_BOLD;
1659 } else if (max > 0xaa)1661 } else if (max > 0xaa)
1660 vc->vc_intensity = 2;1662 vc->state.intensity = VCI_BOLD;
1661 else1663 else
1662 vc->vc_intensity = 1;1664 vc->state.intensity = VCI_NORMAL;
1663 1665
1664 vc->vc_color = (vc->vc_color & 0xf0) | hue;1666 vc->state.color = (vc->state.color & 0xf0) | hue;
1665}1667}
1666 1668
1667static void rgb_background(struct vc_data *vc, const struct rgb *c)1669static void rgb_background(struct vc_data *vc, const struct rgb *c)
1668{1670{
1669 /* For backgrounds, err on the dark side. */1671 /* For backgrounds, err on the dark side. */
1670 vc->vc_color = (vc->vc_color & 0x0f)1672 vc->state.color = (vc->state.color & 0x0f)
1671 | (c->r&0x80) >> 1 | (c->g&0x80) >> 2 | (c->b&0x80) >> 3;1673 | (c->r&0x80) >> 1 | (c->g&0x80) >> 2 | (c->b&0x80) >> 3;
1672}1674}
1673 1675
@@ -1718,13 +1720,13 @@ static void csi_m(struct vc_data *vc) · 44 unmodified lines
1718 default_attr(vc);1720 default_attr(vc);
1719 break;1721 break;
1720 case 1:1722 case 1:
1721 vc->vc_intensity = 2;1723 vc->state.intensity = VCI_BOLD;
1722 break;1724 break;
1723 case 2:1725 case 2:
1724 vc->vc_intensity = 0;1726 vc->state.intensity = VCI_HALF_BRIGHT;
1725 break;1727 break;
1726 case 3:1728 case 3:
1727 vc->vc_italic = 1;1729 vc->state.italic = true;
1728 break;1730 break;
1729 case 21:1731 case 21:
1730 /*1732 /*
@@ -1732,21 +1734,19 @@ static void csi_m(struct vc_data *vc) · 1 unmodified line
1732 * convert it to a single underline.1734 * convert it to a single underline.
1733 */1735 */
1734 case 4:1736 case 4:
1735 vc->vc_underline = 1;1737 vc->state.underline = true;
1736 break;1738 break;
1737 case 5:1739 case 5:
1738 vc->vc_blink = 1;1740 vc->state.blink = true;
1739 break;1741 break;
1740 case 7:1742 case 7:
1741 vc->vc_reverse = 1;1743 vc->state.reverse = true;
1742 break;1744 break;
1743 case 10: /* ANSI X3.64-1979 (SCO-ish?)1745 case 10: /* ANSI X3.64-1979 (SCO-ish?)
1744 * Select primary font, don't display control chars if1746 * Select primary font, don't display control chars if
1745 * defined, don't set bit 8 on output.1747 * defined, don't set bit 8 on output.
1746 */1748 */
1747 vc->vc_translate = set_translate(vc->vc_charset == 01749 vc->vc_translate = set_translate(vc->state.Gx_charset[vc->state.charset], vc);
1748 ? vc->vc_G0_charset
1749 : vc->vc_G1_charset, vc);
1750 vc->vc_disp_ctrl = 0;1750 vc->vc_disp_ctrl = 0;
1751 vc->vc_toggle_meta = 0;1751 vc->vc_toggle_meta = 0;
1752 break;1752 break;
@@ -1767,19 +1767,19 @@ static void csi_m(struct vc_data *vc) · 14 unmodified lines
1767 vc->vc_toggle_meta = 1;1767 vc->vc_toggle_meta = 1;
1768 break;1768 break;
1769 case 22:1769 case 22:
1770 vc->vc_intensity = 1;1770 vc->state.intensity = VCI_NORMAL;
1771 break;1771 break;
1772 case 23:1772 case 23:
1773 vc->vc_italic = 0;1773 vc->state.italic = false;
1774 break;1774 break;
1775 case 24:1775 case 24:
1776 vc->vc_underline = 0;1776 vc->state.underline = false;
1777 break;1777 break;
1778 case 25:1778 case 25:
1779 vc->vc_blink = 0;1779 vc->state.blink = false;
1780 break;1780 break;
1781 case 27:1781 case 27:
1782 vc->vc_reverse = 0;1782 vc->state.reverse = false;
1783 break;1783 break;
1784 case 38:1784 case 38:
1785 i = vc_t416_color(vc, i, rgb_foreground);1785 i = vc_t416_color(vc, i, rgb_foreground);
@@ -1788,64 +1788,70 @@ static void csi_m(struct vc_data *vc) · 2 unmodified lines
1788 i = vc_t416_color(vc, i, rgb_background);1788 i = vc_t416_color(vc, i, rgb_background);
1789 break;1789 break;
1790 case 39:1790 case 39:
1791 vc->vc_color = (vc->vc_def_color & 0x0f) |1791 vc->state.color = (vc->vc_def_color & 0x0f) |
1792 (vc->vc_color & 0xf0);1792 (vc->state.color & 0xf0);
1793 break;1793 break;
1794 case 49:1794 case 49:
1795 vc->vc_color = (vc->vc_def_color & 0xf0) |1795 vc->state.color = (vc->vc_def_color & 0xf0) |
1796 (vc->vc_color & 0x0f);1796 (vc->state.color & 0x0f);
1797 break;1797 break;
1798 default:1798 default:
1799 if (vc->vc_par[i] >= 90 && vc->vc_par[i] <= 107) {1799 if (vc->vc_par[i] >= 90 && vc->vc_par[i] <= 107) {
1800 if (vc->vc_par[i] < 100)1800 if (vc->vc_par[i] < 100)
1801 vc->vc_intensity = 2;1801 vc->state.intensity = VCI_BOLD;
1802 vc->vc_par[i] -= 60;1802 vc->vc_par[i] -= 60;
1803 }1803 }
1804 if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)1804 if (vc->vc_par[i] >= 30 && vc->vc_par[i] <= 37)
1805 vc->vc_color = color_table[vc->vc_par[i] - 30]1805 vc->state.color = color_table[vc->vc_par[i] - 30]
1806 | (vc->vc_color & 0xf0);1806 | (vc->state.color & 0xf0);
1807 else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)1807 else if (vc->vc_par[i] >= 40 && vc->vc_par[i] <= 47)
1808 vc->vc_color = (color_table[vc->vc_par[i] - 40] << 4)1808 vc->state.color = (color_table[vc->vc_par[i] - 40] << 4)
1809 | (vc->vc_color & 0x0f);1809 | (vc->state.color & 0x0f);
1810 break;1810 break;
1811 }1811 }
1812 update_attr(vc);1812 update_attr(vc);
1813}1813}
1814 1814
1815static void respond_string(const char *p, struct tty_port *port)1815static void respond_string(const char *p, size_t len, struct tty_port *port)
1816{1816{
1817 while (*p) {1817 tty_insert_flip_string(port, p, len);
1818 tty_insert_flip_char(port, *p, 0);
1819 p++;
1820 }
1821 tty_schedule_flip(port);1818 tty_schedule_flip(port);
1822}1819}
1823 1820
1824static void cursor_report(struct vc_data *vc, struct tty_struct *tty)1821static void cursor_report(struct vc_data *vc, struct tty_struct *tty)
1825{1822{
1826 char buf[40];1823 char buf[40];
1824 int len;
1827 1825
1828 sprintf(buf, "\033[%d;%dR", vc->vc_y + (vc->vc_decom ? vc->vc_top + 1 : 1), vc->vc_x + 1);1826 len = sprintf(buf, "\033[%d;%dR", vc->state.y +
1829 respond_string(buf, tty->port);1827 (vc->vc_decom ? vc->vc_top + 1 : 1),
1828 vc->state.x + 1);
1829 respond_string(buf, len, tty->port);
1830}1830}
1831 1831
1832static inline void status_report(struct tty_struct *tty)1832static inline void status_report(struct tty_struct *tty)
1833{1833{
1834 respond_string("\033[0n", tty->port); /* Terminal ok */1834 static const char teminal_ok[] = "\033[0n";
1835
1836 respond_string(teminal_ok, strlen(teminal_ok), tty->port);
1835}1837}
1836 1838
1837static inline void respond_ID(struct tty_struct *tty)1839static inline void respond_ID(struct tty_struct *tty)
1838{1840{
1839 respond_string(VT102ID, tty->port);1841 /* terminal answer to an ESC-Z or csi0c query. */
1842 static const char vt102_id[] = "\033[?6c";
1843
1844 respond_string(vt102_id, strlen(vt102_id), tty->port);
1840}1845}
1841 1846
1842void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry)1847void mouse_report(struct tty_struct *tty, int butt, int mrx, int mry)
1843{1848{
1844 char buf[8];1849 char buf[8];
1850 int len;
1845 1851
1846 sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),1852 len = sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt),
1847 (char)('!' + mry));1853 (char)('!' + mrx), (char)('!' + mry));
1848 respond_string(buf, tty->port);1854 respond_string(buf, len, tty->port);
1849}1855}
1850 1856
1851/* invoked via ioctl(TIOCLINUX) and through set_selection_user */1857/* invoked via ioctl(TIOCLINUX) and through set_selection_user */
@@ -1930,14 +1936,14 @@ static void setterm_command(struct vc_data *vc) · 78 unmodified lines
1930 case 1: /* set color for underline mode */1936 case 1: /* set color for underline mode */
1931 if (vc->vc_can_do_color && vc->vc_par[1] < 16) {1937 if (vc->vc_can_do_color && vc->vc_par[1] < 16) {
1932 vc->vc_ulcolor = color_table[vc->vc_par[1]];1938 vc->vc_ulcolor = color_table[vc->vc_par[1]];
1933 if (vc->vc_underline)1939 if (vc->state.underline)
1934 update_attr(vc);1940 update_attr(vc);
1935 }1941 }
1936 break;1942 break;
1937 case 2: /* set color for half intensity mode */1943 case 2: /* set color for half intensity mode */
1938 if (vc->vc_can_do_color && vc->vc_par[1] < 16) {1944 if (vc->vc_can_do_color && vc->vc_par[1] < 16) {
1939 vc->vc_halfcolor = color_table[vc->vc_par[1]];1945 vc->vc_halfcolor = color_table[vc->vc_par[1]];
1940 if (vc->vc_intensity == 0)1946 if (vc->state.intensity == VCI_HALF_BRIGHT)
1941 update_attr(vc);1947 update_attr(vc);
1942 }1948 }
1943 break;1949 break;
@@ -1991,8 +1997,8 @@ static void setterm_command(struct vc_data *vc) · 47 unmodified lines
1991/* console_lock is held */1997/* console_lock is held */
1992static void csi_at(struct vc_data *vc, unsigned int nr)1998static void csi_at(struct vc_data *vc, unsigned int nr)
1993{1999{
1994 if (nr > vc->vc_cols - vc->vc_x)2000 if (nr > vc->vc_cols - vc->state.x)
1995 nr = vc->vc_cols - vc->vc_x;2001 nr = vc->vc_cols - vc->state.x;
1996 else if (!nr)2002 else if (!nr)
1997 nr = 1;2003 nr = 1;
1998 insert_char(vc, nr);2004 insert_char(vc, nr);
@@ -2001,19 +2007,19 @@ static void csi_at(struct vc_data *vc, unsigned int nr) · 2 unmodified lines
2001/* console_lock is held */2007/* console_lock is held */
2002static void csi_L(struct vc_data *vc, unsigned int nr)2008static void csi_L(struct vc_data *vc, unsigned int nr)
2003{2009{
2004 if (nr > vc->vc_rows - vc->vc_y)2010 if (nr > vc->vc_rows - vc->state.y)
2005 nr = vc->vc_rows - vc->vc_y;2011 nr = vc->vc_rows - vc->state.y;
2006 else if (!nr)2012 else if (!nr)
2007 nr = 1;2013 nr = 1;
2008 con_scroll(vc, vc->vc_y, vc->vc_bottom, SM_DOWN, nr);2014 con_scroll(vc, vc->state.y, vc->vc_bottom, SM_DOWN, nr);
2009 vc->vc_need_wrap = 0;2015 vc->vc_need_wrap = 0;
2010}2016}
2011 2017
2012/* console_lock is held */2018/* console_lock is held */
2013static void csi_P(struct vc_data *vc, unsigned int nr)2019static void csi_P(struct vc_data *vc, unsigned int nr)
2014{2020{
2015 if (nr > vc->vc_cols - vc->vc_x)2021 if (nr > vc->vc_cols - vc->state.x)
2016 nr = vc->vc_cols - vc->vc_x;2022 nr = vc->vc_cols - vc->state.x;
2017 else if (!nr)2023 else if (!nr)
2018 nr = 1;2024 nr = 1;
2019 delete_char(vc, nr);2025 delete_char(vc, nr);
@@ -2022,44 +2028,28 @@ static void csi_P(struct vc_data *vc, unsigned int nr) · 2 unmodified lines
2022/* console_lock is held */2028/* console_lock is held */
2023static void csi_M(struct vc_data *vc, unsigned int nr)2029static void csi_M(struct vc_data *vc, unsigned int nr)
2024{2030{
2025 if (nr > vc->vc_rows - vc->vc_y)2031 if (nr > vc->vc_rows - vc->state.y)
2026 nr = vc->vc_rows - vc->vc_y;2032 nr = vc->vc_rows - vc->state.y;
2027 else if (!nr)2033 else if (!nr)
2028 nr=1;2034 nr=1;
2029 con_scroll(vc, vc->vc_y, vc->vc_bottom, SM_UP, nr);2035 con_scroll(vc, vc->state.y, vc->vc_bottom, SM_UP, nr);
2030 vc->vc_need_wrap = 0;2036 vc->vc_need_wrap = 0;
2031}2037}
2032 2038
2033/* console_lock is held (except via vc_init->reset_terminal */2039/* console_lock is held (except via vc_init->reset_terminal */
2034static void save_cur(struct vc_data *vc)2040static void save_cur(struct vc_data *vc)
2035{2041{
2036 vc->vc_saved_x = vc->vc_x;2042 memcpy(&vc->saved_state, &vc->state, sizeof(vc->state));
2037 vc->vc_saved_y = vc->vc_y;
2038 vc->vc_s_intensity = vc->vc_intensity;
2039 vc->vc_s_italic = vc->vc_italic;
2040 vc->vc_s_underline = vc->vc_underline;
2041 vc->vc_s_blink = vc->vc_blink;
2042 vc->vc_s_reverse = vc->vc_reverse;
2043 vc->vc_s_charset = vc->vc_charset;
2044 vc->vc_s_color = vc->vc_color;
2045 vc->vc_saved_G0 = vc->vc_G0_charset;
2046 vc->vc_saved_G1 = vc->vc_G1_charset;
2047}2043}
2048 2044
2049/* console_lock is held */2045/* console_lock is held */
2050static void restore_cur(struct vc_data *vc)2046static void restore_cur(struct vc_data *vc)
2051{2047{
2052 gotoxy(vc, vc->vc_saved_x, vc->vc_saved_y);2048 memcpy(&vc->state, &vc->saved_state, sizeof(vc->state));
2053 vc->vc_intensity = vc->vc_s_intensity;2049
2054 vc->vc_italic = vc->vc_s_italic;2050 gotoxy(vc, vc->state.x, vc->state.y);
2055 vc->vc_underline = vc->vc_s_underline;2051 vc->vc_translate = set_translate(vc->state.Gx_charset[vc->state.charset],
2056 vc->vc_blink = vc->vc_s_blink;2052 vc);
2057 vc->vc_reverse = vc->vc_s_reverse;
2058 vc->vc_charset = vc->vc_s_charset;
2059 vc->vc_color = vc->vc_s_color;
2060 vc->vc_G0_charset = vc->vc_saved_G0;
2061 vc->vc_G1_charset = vc->vc_saved_G1;
2062 vc->vc_translate = set_translate(vc->vc_charset ? vc->vc_G1_charset : vc->vc_G0_charset, vc);
2063 update_attr(vc);2053 update_attr(vc);
2064 vc->vc_need_wrap = 0;2054 vc->vc_need_wrap = 0;
2065}2055}
@@ -2071,14 +2061,16 @@ enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey, · 5 unmodified lines
2071/* console_lock is held (except via vc_init()) */2061/* console_lock is held (except via vc_init()) */
2072static void reset_terminal(struct vc_data *vc, int do_clear)2062static void reset_terminal(struct vc_data *vc, int do_clear)
2073{2063{
2064 unsigned int i;
2065
2074 vc->vc_top = 0;2066 vc->vc_top = 0;
2075 vc->vc_bottom = vc->vc_rows;2067 vc->vc_bottom = vc->vc_rows;
2076 vc->vc_state = ESnormal;2068 vc->vc_state = ESnormal;
2077 vc->vc_priv = EPecma;2069 vc->vc_priv = EPecma;
2078 vc->vc_translate = set_translate(LAT1_MAP, vc);2070 vc->vc_translate = set_translate(LAT1_MAP, vc);
2079 vc->vc_G0_charset = LAT1_MAP;2071 vc->state.Gx_charset[0] = LAT1_MAP;
2080 vc->vc_G1_charset = GRAF_MAP;2072 vc->state.Gx_charset[1] = GRAF_MAP;
2081 vc->vc_charset = 0;2073 vc->state.charset = 0;
2082 vc->vc_need_wrap = 0;2074 vc->vc_need_wrap = 0;
2083 vc->vc_report_mouse = 0;2075 vc->vc_report_mouse = 0;
2084 vc->vc_utf = default_utf8;2076 vc->vc_utf = default_utf8;
@@ -2101,14 +2093,9 @@ static void reset_terminal(struct vc_data *vc, int do_clear) · 16 unmodified lines
2101 default_attr(vc);2093 default_attr(vc);
2102 update_attr(vc);2094 update_attr(vc);
2103 2095
2104 vc->vc_tab_stop[0] =2096 bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT);
2105 vc->vc_tab_stop[1] =2097 for (i = 0; i < VC_TABSTOPS_COUNT; i += 8)
2106 vc->vc_tab_stop[2] =2098 set_bit(i, vc->vc_tab_stop);
2107 vc->vc_tab_stop[3] =
2108 vc->vc_tab_stop[4] =
2109 vc->vc_tab_stop[5] =
2110 vc->vc_tab_stop[6] =
2111 vc->vc_tab_stop[7] = 0x01010101;
2112 2099
2113 vc->vc_bell_pitch = DEFAULT_BELL_PITCH;2100 vc->vc_bell_pitch = DEFAULT_BELL_PITCH;
2114 vc->vc_bell_duration = DEFAULT_BELL_DURATION;2101 vc->vc_bell_duration = DEFAULT_BELL_DURATION;
@@ -2120,6 +2107,29 @@ static void reset_terminal(struct vc_data *vc, int do_clear) · 5 unmodified lines
2120 csi_J(vc, 2);2107 csi_J(vc, 2);
2121}2108}
2122 2109
2110static void vc_setGx(struct vc_data *vc, unsigned int which, int c)
2111{
2112 unsigned char *charset = &vc->state.Gx_charset[which];
2113
2114 switch (c) {
2115 case '0':
2116 *charset = GRAF_MAP;
2117 break;
2118 case 'B':
2119 *charset = LAT1_MAP;
2120 break;
2121 case 'U':
2122 *charset = IBMPC_MAP;
2123 break;
2124 case 'K':
2125 *charset = USER_MAP;
2126 break;
2127 }
2128
2129 if (vc->state.charset == which)
2130 vc->vc_translate = set_translate(*charset, vc);
2131}
2132
2123/* console_lock is held */2133/* console_lock is held */
2124static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)2134static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
2125{2135{
@@ -2142,13 +2152,15 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 16 unmodified lines
2142 bs(vc);2152 bs(vc);
2143 return;2153 return;
2144 case 9:2154 case 9:
2145 vc->vc_pos -= (vc->vc_x << 1);2155 vc->vc_pos -= (vc->state.x << 1);
2146 while (vc->vc_x < vc->vc_cols - 1) {2156
2147 vc->vc_x++;2157 vc->state.x = find_next_bit(vc->vc_tab_stop,
2148 if (vc->vc_tab_stop[7 & (vc->vc_x >> 5)] & (1 << (vc->vc_x & 31)))2158 min(vc->vc_cols - 1, VC_TABSTOPS_COUNT),
2149 break;2159 vc->state.x + 1);
2150 }2160 if (vc->state.x >= VC_TABSTOPS_COUNT)
2151 vc->vc_pos += (vc->vc_x << 1);2161 vc->state.x = vc->vc_cols - 1;
2162
2163 vc->vc_pos += (vc->state.x << 1);
2152 notify_write(vc, '\t');2164 notify_write(vc, '\t');
2153 return;2165 return;
2154 case 10: case 11: case 12:2166 case 10: case 11: case 12:
@@ -2160,13 +2172,13 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 5 unmodified lines
2160 cr(vc);2172 cr(vc);
2161 return;2173 return;
2162 case 14:2174 case 14:
2163 vc->vc_charset = 1;2175 vc->state.charset = 1;
2164 vc->vc_translate = set_translate(vc->vc_G1_charset, vc);2176 vc->vc_translate = set_translate(vc->state.Gx_charset[1], vc);
2165 vc->vc_disp_ctrl = 1;2177 vc->vc_disp_ctrl = 1;
2166 return;2178 return;
2167 case 15:2179 case 15:
2168 vc->vc_charset = 0;2180 vc->state.charset = 0;
2169 vc->vc_translate = set_translate(vc->vc_G0_charset, vc);2181 vc->vc_translate = set_translate(vc->state.Gx_charset[0], vc);
2170 vc->vc_disp_ctrl = 0;2182 vc->vc_disp_ctrl = 0;
2171 return;2183 return;
2172 case 24: case 26:2184 case 24: case 26:
@@ -2206,7 +2218,8 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 33 unmodified lines
2206 lf(vc);2218 lf(vc);
2207 return;2219 return;
2208 case 'H':2220 case 'H':
2209 vc->vc_tab_stop[7 & (vc->vc_x >> 5)] |= (1 << (vc->vc_x & 31));2221 if (vc->state.x < VC_TABSTOPS_COUNT)
2222 set_bit(vc->state.x, vc->vc_tab_stop);
2210 return;2223 return;
2211 case 'Z':2224 case 'Z':
2212 respond_ID(tty);2225 respond_ID(tty);
@@ -2320,7 +2333,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 107 unmodified lines
2320 case 'c':2333 case 'c':
2321 if (vc->vc_priv == EPdec) {2334 if (vc->vc_priv == EPdec) {
2322 if (vc->vc_par[0])2335 if (vc->vc_par[0])
2323 vc->vc_cursor_type = vc->vc_par[0] | (vc->vc_par[1] << 8) | (vc->vc_par[2] << 16);2336 vc->vc_cursor_type =
2337 CUR_MAKE(vc->vc_par[0],
2338 vc->vc_par[1],
2339 vc->vc_par[2]);
2324 else2340 else
2325 vc->vc_cursor_type = cur_default;2341 vc->vc_cursor_type = cur_default;
2326 return;2342 return;
@@ -2353,42 +2369,42 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 26 unmodified lines
2353 case 'G': case '`':2369 case 'G': case '`':
2354 if (vc->vc_par[0])2370 if (vc->vc_par[0])
2355 vc->vc_par[0]--;2371 vc->vc_par[0]--;
2356 gotoxy(vc, vc->vc_par[0], vc->vc_y);2372 gotoxy(vc, vc->vc_par[0], vc->state.y);
2357 return;2373 return;
2358 case 'A':2374 case 'A':
2359 if (!vc->vc_par[0])2375 if (!vc->vc_par[0])
2360 vc->vc_par[0]++;2376 vc->vc_par[0]++;
2361 gotoxy(vc, vc->vc_x, vc->vc_y - vc->vc_par[0]);2377 gotoxy(vc, vc->state.x, vc->state.y - vc->vc_par[0]);
2362 return;2378 return;
2363 case 'B': case 'e':2379 case 'B': case 'e':
2364 if (!vc->vc_par[0])2380 if (!vc->vc_par[0])
2365 vc->vc_par[0]++;2381 vc->vc_par[0]++;
2366 gotoxy(vc, vc->vc_x, vc->vc_y + vc->vc_par[0]);2382 gotoxy(vc, vc->state.x, vc->state.y + vc->vc_par[0]);
2367 return;2383 return;
2368 case 'C': case 'a':2384 case 'C': case 'a':
2369 if (!vc->vc_par[0])2385 if (!vc->vc_par[0])
2370 vc->vc_par[0]++;2386 vc->vc_par[0]++;
2371 gotoxy(vc, vc->vc_x + vc->vc_par[0], vc->vc_y);2387 gotoxy(vc, vc->state.x + vc->vc_par[0], vc->state.y);
2372 return;2388 return;
2373 case 'D':2389 case 'D':
2374 if (!vc->vc_par[0])2390 if (!vc->vc_par[0])
2375 vc->vc_par[0]++;2391 vc->vc_par[0]++;
2376 gotoxy(vc, vc->vc_x - vc->vc_par[0], vc->vc_y);2392 gotoxy(vc, vc->state.x - vc->vc_par[0], vc->state.y);
2377 return;2393 return;
2378 case 'E':2394 case 'E':
2379 if (!vc->vc_par[0])2395 if (!vc->vc_par[0])
2380 vc->vc_par[0]++;2396 vc->vc_par[0]++;
2381 gotoxy(vc, 0, vc->vc_y + vc->vc_par[0]);2397 gotoxy(vc, 0, vc->state.y + vc->vc_par[0]);
2382 return;2398 return;
2383 case 'F':2399 case 'F':
2384 if (!vc->vc_par[0])2400 if (!vc->vc_par[0])
2385 vc->vc_par[0]++;2401 vc->vc_par[0]++;
2386 gotoxy(vc, 0, vc->vc_y - vc->vc_par[0]);2402 gotoxy(vc, 0, vc->state.y - vc->vc_par[0]);
2387 return;2403 return;
2388 case 'd':2404 case 'd':
2389 if (vc->vc_par[0])2405 if (vc->vc_par[0])
2390 vc->vc_par[0]--;2406 vc->vc_par[0]--;
2391 gotoxay(vc, vc->vc_x ,vc->vc_par[0]);2407 gotoxay(vc, vc->state.x ,vc->vc_par[0]);
2392 return;2408 return;
2393 case 'H': case 'f':2409 case 'H': case 'f':
2394 if (vc->vc_par[0])2410 if (vc->vc_par[0])
@@ -2417,18 +2433,10 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 22 unmodified lines
2417 respond_ID(tty);2433 respond_ID(tty);
2418 return;2434 return;
2419 case 'g':2435 case 'g':
2420 if (!vc->vc_par[0])2436 if (!vc->vc_par[0] && vc->state.x < VC_TABSTOPS_COUNT)
2421 vc->vc_tab_stop[7 & (vc->vc_x >> 5)] &= ~(1 << (vc->vc_x & 31));2437 set_bit(vc->state.x, vc->vc_tab_stop);
2422 else if (vc->vc_par[0] == 3) {2438 else if (vc->vc_par[0] == 3)
2423 vc->vc_tab_stop[0] =2439 bitmap_zero(vc->vc_tab_stop, VC_TABSTOPS_COUNT);
2424 vc->vc_tab_stop[1] =
2425 vc->vc_tab_stop[2] =
2426 vc->vc_tab_stop[3] =
2427 vc->vc_tab_stop[4] =
2428 vc->vc_tab_stop[5] =
2429 vc->vc_tab_stop[6] =
2430 vc->vc_tab_stop[7] = 0;
2431 }
2432 return;2440 return;
2433 case 'm':2441 case 'm':
2434 csi_m(vc);2442 csi_m(vc);
@@ -2502,29 +2510,11 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 67 unmodified lines
2502 }2510 }
2503 return;2511 return;
2504 case ESsetG0:2512 case ESsetG0:
2505 if (c == '0')2513 vc_setGx(vc, 0, c);
2506 vc->vc_G0_charset = GRAF_MAP;
2507 else if (c == 'B')
2508 vc->vc_G0_charset = LAT1_MAP;
2509 else if (c == 'U')
2510 vc->vc_G0_charset = IBMPC_MAP;
2511 else if (c == 'K')
2512 vc->vc_G0_charset = USER_MAP;
2513 if (vc->vc_charset == 0)
2514 vc->vc_translate = set_translate(vc->vc_G0_charset, vc);
2515 vc->vc_state = ESnormal;2514 vc->vc_state = ESnormal;
2516 return;2515 return;
2517 case ESsetG1:2516 case ESsetG1:
2518 if (c == '0')2517 vc_setGx(vc, 1, c);
2519 vc->vc_G1_charset = GRAF_MAP;
2520 else if (c == 'B')
2521 vc->vc_G1_charset = LAT1_MAP;
2522 else if (c == 'U')
2523 vc->vc_G1_charset = IBMPC_MAP;
2524 else if (c == 'K')
2525 vc->vc_G1_charset = USER_MAP;
2526 if (vc->vc_charset == 1)
2527 vc->vc_translate = set_translate(vc->vc_G1_charset, vc);
2528 vc->vc_state = ESnormal;2518 vc->vc_state = ESnormal;
2529 return;2519 return;
2530 case ESosc:2520 case ESosc:
@@ -2536,7 +2526,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) · 5 unmodified lines
2536 2526
2537/* is_double_width() is based on the wcwidth() implementation by2527/* is_double_width() is based on the wcwidth() implementation by
2538 * Markus Kuhn -- 2007-05-26 (Unicode 5.0)2528 * Markus Kuhn -- 2007-05-26 (Unicode 5.0)
2539 * Latest version: http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c2529 * Latest version: https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c
2540 */2530 */
2541struct interval {2531struct interval {
2542 uint32_t first;2532 uint32_t first;
@@ -2571,30 +2561,300 @@ static int is_double_width(uint32_t ucs) · 28 unmodified lines
2571 sizeof(struct interval), ucs_cmp) != NULL;2561 sizeof(struct interval), ucs_cmp) != NULL;
2572}2562}
2573 2563
2574static void con_flush(struct vc_data *vc, unsigned long draw_from,2564struct vc_draw_region {
2575 unsigned long draw_to, int *draw_x)2565 unsigned long from, to;
2566 int x;
2567};
2568
2569static void con_flush(struct vc_data *vc, struct vc_draw_region *draw)
2576{2570{
2577 if (*draw_x < 0)2571 if (draw->x < 0)
2578 return;2572 return;
2579 2573
2580 vc->vc_sw->con_putcs(vc, (u16 *)draw_from,2574 vc->vc_sw->con_putcs(vc, (u16 *)draw->from,
2581 (u16 *)draw_to - (u16 *)draw_from, vc->vc_y, *draw_x);2575 (u16 *)draw->to - (u16 *)draw->from, vc->state.y,
2582 *draw_x = -1;2576 draw->x);
2577 draw->x = -1;
2578}
2579
2580static inline int vc_translate_ascii(const struct vc_data *vc, int c)
2581{
2582 if (IS_ENABLED(CONFIG_CONSOLE_TRANSLATIONS)) {
2583 if (vc->vc_toggle_meta)
2584 c |= 0x80;
2585
2586 return vc->vc_translate[c];
2587 }
2588
2589 return c;
2590}
2591
2592
2593/**
2594 * vc_sanitize_unicode -- Replace invalid Unicode code points with U+FFFD
2595 * @c: the received character, or U+FFFD for invalid sequences.
2596 */
2597static inline int vc_sanitize_unicode(const int c)
2598{
2599 if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff)
2600 return 0xfffd;
2601
2602 return c;
2603}
2604
2605/**
2606 * vc_translate_unicode -- Combine UTF-8 into Unicode in @vc_utf_char
2607 *
2608 * @vc_utf_char is the being-constructed unicode character.
2609 * @vc_utf_count is the number of continuation bytes still expected to arrive.
2610 * @vc_npar is the number of continuation bytes arrived so far.
2611 */
2612static int vc_translate_unicode(struct vc_data *vc, int c, bool *rescan)
2613{
2614 static const u32 utf8_length_changes[] = {
2615 0x0000007f, 0x000007ff, 0x0000ffff,
2616 0x001fffff, 0x03ffffff, 0x7fffffff
2617 };
2618
2619 /* Continuation byte received */
2620 if ((c & 0xc0) == 0x80) {
2621 /* Unexpected continuation byte? */
2622 if (!vc->vc_utf_count)
2623 return 0xfffd;
2624
2625 vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);
2626 vc->vc_npar++;
2627 if (--vc->vc_utf_count)
2628 goto need_more_bytes;
2629
2630 /* Got a whole character */
2631 c = vc->vc_utf_char;
2632 /* Reject overlong sequences */
2633 if (c <= utf8_length_changes[vc->vc_npar - 1] ||
2634 c > utf8_length_changes[vc->vc_npar])
2635 return 0xfffd;
2636
2637 return vc_sanitize_unicode(c);
2638 }
2639
2640 /* Single ASCII byte or first byte of a sequence received */
2641 if (vc->vc_utf_count) {
2642 /* Continuation byte expected */
2643 *rescan = true;
2644 vc->vc_utf_count = 0;
2645 return 0xfffd;
2646 }
2647
2648 /* Nothing to do if an ASCII byte was received */
2649 if (c <= 0x7f)
2650 return c;
2651
2652 /* First byte of a multibyte sequence received */
2653 vc->vc_npar = 0;
2654 if ((c & 0xe0) == 0xc0) {
2655 vc->vc_utf_count = 1;
2656 vc->vc_utf_char = (c & 0x1f);
2657 } else if ((c & 0xf0) == 0xe0) {
2658 vc->vc_utf_count = 2;
2659 vc->vc_utf_char = (c & 0x0f);
2660 } else if ((c & 0xf8) == 0xf0) {
2661 vc->vc_utf_count = 3;
2662 vc->vc_utf_char = (c & 0x07);
2663 } else if ((c & 0xfc) == 0xf8) {
2664 vc->vc_utf_count = 4;
2665 vc->vc_utf_char = (c & 0x03);
2666 } else if ((c & 0xfe) == 0xfc) {
2667 vc->vc_utf_count = 5;
2668 vc->vc_utf_char = (c & 0x01);
2669 } else {
2670 /* 254 and 255 are invalid */
2671 return 0xfffd;
2672 }
2673
2674need_more_bytes:
2675 return -1;
2676}
2677
2678static int vc_translate(struct vc_data *vc, int *c, bool *rescan)
2679{
2680 /* Do no translation at all in control states */
2681 if (vc->vc_state != ESnormal)
2682 return *c;
2683
2684 if (vc->vc_utf && !vc->vc_disp_ctrl)
2685 return *c = vc_translate_unicode(vc, *c, rescan);
2686
2687 /* no utf or alternate charset mode */
2688 return vc_translate_ascii(vc, *c);
2689}
2690
2691static inline unsigned char vc_invert_attr(const struct vc_data *vc)
2692{
2693 if (!vc->vc_can_do_color)
2694 return vc->vc_attr ^ 0x08;
2695
2696 if (vc->vc_hi_font_mask == 0x100)
2697 return (vc->vc_attr & 0x11) |
2698 ((vc->vc_attr & 0xe0) >> 4) |
2699 ((vc->vc_attr & 0x0e) << 4);
2700
2701 return (vc->vc_attr & 0x88) |
2702 ((vc->vc_attr & 0x70) >> 4) |
2703 ((vc->vc_attr & 0x07) << 4);
2704}
2705
2706static bool vc_is_control(struct vc_data *vc, int tc, int c)
2707{
2708 /*
2709 * A bitmap for codes <32. A bit of 1 indicates that the code
2710 * corresponding to that bit number invokes some special action (such
2711 * as cursor movement) and should not be displayed as a glyph unless
2712 * the disp_ctrl mode is explicitly enabled.
2713 */
2714 static const u32 CTRL_ACTION = 0x0d00ff81;
2715 /* Cannot be overridden by disp_ctrl */
2716 static const u32 CTRL_ALWAYS = 0x0800f501;
2717
2718 if (vc->vc_state != ESnormal)
2719 return true;
2720
2721 if (!tc)
2722 return true;
2723
2724 /*
2725 * If the original code was a control character we only allow a glyph
2726 * to be displayed if the code is not normally used (such as for cursor
2727 * movement) or if the disp_ctrl mode has been explicitly enabled.
2728 * Certain characters (as given by the CTRL_ALWAYS bitmap) are always
2729 * displayed as control characters, as the console would be pretty
2730 * useless without them; to display an arbitrary font position use the
2731 * direct-to-font zone in UTF-8 mode.
2732 */
2733 if (c < 32) {
2734 if (vc->vc_disp_ctrl)
2735 return CTRL_ALWAYS & BIT(c);
2736 else
2737 return vc->vc_utf || (CTRL_ACTION & BIT(c));
2738 }
2739
2740 if (c == 127 && !vc->vc_disp_ctrl)
2741 return true;
2742
2743 if (c == 128 + 27)
2744 return true;
2745
2746 return false;
2747}
2748
2749static int vc_con_write_normal(struct vc_data *vc, int tc, int c,
2750 struct vc_draw_region *draw)
2751{
2752 int next_c;
2753 unsigned char vc_attr = vc->vc_attr;
2754 u16 himask = vc->vc_hi_font_mask, charmask = himask ? 0x1ff : 0xff;
2755 u8 width = 1;
2756 bool inverse = false;
2757
2758 if (vc->vc_utf && !vc->vc_disp_ctrl) {
2759 if (is_double_width(c))
2760 width = 2;
2761 }
2762
2763 /* Now try to find out how to display it */
2764 tc = conv_uni_to_pc(vc, tc);
2765 if (tc & ~charmask) {
2766 if (tc == -1 || tc == -2)
2767 return -1; /* nothing to display */
2768
2769 /* Glyph not found */
2770 if ((!vc->vc_utf || vc->vc_disp_ctrl || c < 128) &&
2771 !(c & ~charmask)) {
2772 /*
2773 * In legacy mode use the glyph we get by a 1:1
2774 * mapping.
2775 * This would make absolutely no sense with Unicode in
2776 * mind, but do this for ASCII characters since a font
2777 * may lack Unicode mapping info and we don't want to
2778 * end up with having question marks only.
2779 */
2780 tc = c;
2781 } else {
2782 /*
2783 * Display U+FFFD. If it's not found, display an inverse
2784 * question mark.
2785 */
2786 tc = conv_uni_to_pc(vc, 0xfffd);
2787 if (tc < 0) {
2788 inverse = true;
2789 tc = conv_uni_to_pc(vc, '?');
2790 if (tc < 0)
2791 tc = '?';
2792
2793 vc_attr = vc_invert_attr(vc);
2794 con_flush(vc, draw);
2795 }
2796 }
2797 }
2798
2799 next_c = c;
2800 while (1) {
2801 if (vc->vc_need_wrap || vc->vc_decim)
2802 con_flush(vc, draw);
2803 if (vc->vc_need_wrap) {
2804 cr(vc);
2805 lf(vc);
2806 }
2807 if (vc->vc_decim)
2808 insert_char(vc, 1);
2809 vc_uniscr_putc(vc, next_c);
2810
2811 if (himask)
2812 tc = ((tc & 0x100) ? himask : 0) |
2813 (tc & 0xff);
2814 tc |= (vc_attr << 8) & ~himask;
2815
2816 scr_writew(tc, (u16 *)vc->vc_pos);
2817
2818 if (con_should_update(vc) && draw->x < 0) {
2819 draw->x = vc->state.x;
2820 draw->from = vc->vc_pos;
2821 }
2822 if (vc->state.x == vc->vc_cols - 1) {
2823 vc->vc_need_wrap = vc->vc_decawm;
2824 draw->to = vc->vc_pos + 2;
2825 } else {
2826 vc->state.x++;
2827 draw->to = (vc->vc_pos += 2);
2828 }
2829
2830 if (!--width)
2831 break;
2832
2833 /* A space is printed in the second column */
2834 tc = conv_uni_to_pc(vc, ' ');
2835 if (tc < 0)
2836 tc = ' ';
2837 next_c = ' ';
2838 }
2839 notify_write(vc, c);
2840
2841 if (inverse)
2842 con_flush(vc, draw);
2843
2844 return 0;
2583}2845}
2584 2846
2585/* acquires console_lock */2847/* acquires console_lock */
2586static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count)2848static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int count)
2587{2849{
2588 int c, next_c, tc, ok, n = 0, draw_x = -1;2850 struct vc_draw_region draw = {
2851 .x = -1,
2852 };
2853 int c, tc, n = 0;
2589 unsigned int currcons;2854 unsigned int currcons;
2590 unsigned long draw_from = 0, draw_to = 0;
2591 struct vc_data *vc;2855 struct vc_data *vc;
2592 unsigned char vc_attr;
2593 struct vt_notifier_param param;2856 struct vt_notifier_param param;
2594 uint8_t rescan;2857 bool rescan;
2595 uint8_t inverse;
2596 uint8_t width;
2597 u16 himask, charmask;
2598 2858
2599 if (in_interrupt())2859 if (in_interrupt())
2600 return count;2860 return count;
@@ -2615,8 +2875,6 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co · 14 unmodified lines
2615 return 0;2875 return 0;
2616 }2876 }
2617 2877
2618 himask = vc->vc_hi_font_mask;
2619 charmask = himask ? 0x1ff : 0xff;
2620 2878
2621 /* undraw cursor first */2879 /* undraw cursor first */
2622 if (con_is_fg(vc))2880 if (con_is_fg(vc))
@@ -2626,209 +2884,35 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co · 3 unmodified lines
2626 2884
2627 while (!tty->stopped && count) {2885 while (!tty->stopped && count) {
2628 int orig = *buf;2886 int orig = *buf;
2629 c = orig;
2630 buf++;2887 buf++;
2631 n++;2888 n++;
2632 count--;2889 count--;
2633 rescan = 0;
2634 inverse = 0;
2635 width = 1;
2636
2637 /* Do no translation at all in control states */
2638 if (vc->vc_state != ESnormal) {
2639 tc = c;
2640 } else if (vc->vc_utf && !vc->vc_disp_ctrl) {
2641 /* Combine UTF-8 into Unicode in vc_utf_char.
2642 * vc_utf_count is the number of continuation bytes still
2643 * expected to arrive.
2644 * vc_npar is the number of continuation bytes arrived so
2645 * far
2646 */
2647rescan_last_byte:2890rescan_last_byte:
2648 if ((c & 0xc0) == 0x80) {2891 c = orig;
2649 /* Continuation byte received */2892 rescan = false;
2650 static const uint32_t utf8_length_changes[] = { 0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff };2893
2651 if (vc->vc_utf_count) {2894 tc = vc_translate(vc, &c, &rescan);
2652 vc->vc_utf_char = (vc->vc_utf_char << 6) | (c & 0x3f);2895 if (tc == -1)
2653 vc->vc_npar++;2896 continue;
2654 if (--vc->vc_utf_count) {
2655 /* Still need some bytes */
2656 continue;
2657 }
2658 /* Got a whole character */
2659 c = vc->vc_utf_char;
2660 /* Reject overlong sequences */
2661 if (c <= utf8_length_changes[vc->vc_npar - 1] ||
2662 c > utf8_length_changes[vc->vc_npar])
2663 c = 0xfffd;
2664 } else {
2665 /* Unexpected continuation byte */
2666 vc->vc_utf_count = 0;
2667 c = 0xfffd;
2668 }
2669 } else {
2670 /* Single ASCII byte or first byte of a sequence received */
2671 if (vc->vc_utf_count) {
2672 /* Continuation byte expected */
2673 rescan = 1;
2674 vc->vc_utf_count = 0;
2675 c = 0xfffd;
2676 } else if (c > 0x7f) {
2677 /* First byte of a multibyte sequence received */
2678 vc->vc_npar = 0;
2679 if ((c & 0xe0) == 0xc0) {
2680 vc->vc_utf_count = 1;
2681 vc->vc_utf_char = (c & 0x1f);
2682 } else if ((c & 0xf0) == 0xe0) {
2683 vc->vc_utf_count = 2;
2684 vc->vc_utf_char = (c & 0x0f);
2685 } else if ((c & 0xf8) == 0xf0) {
2686 vc->vc_utf_count = 3;
2687 vc->vc_utf_char = (c & 0x07);
2688 } else if ((c & 0xfc) == 0xf8) {
2689 vc->vc_utf_count = 4;
2690 vc->vc_utf_char = (c & 0x03);
2691 } else if ((c & 0xfe) == 0xfc) {
2692 vc->vc_utf_count = 5;
2693 vc->vc_utf_char = (c & 0x01);
2694 } else {
2695 /* 254 and 255 are invalid */
2696 c = 0xfffd;
2697 }
2698 if (vc->vc_utf_count) {
2699 /* Still need some bytes */
2700 continue;
2701 }
2702 }
2703 /* Nothing to do if an ASCII byte was received */
2704 }
2705 /* End of UTF-8 decoding. */
2706 /* c is the received character, or U+FFFD for invalid sequences. */
2707 /* Replace invalid Unicode code points with U+FFFD too */
2708 if ((c >= 0xd800 && c <= 0xdfff) || c == 0xfffe || c == 0xffff)
2709 c = 0xfffd;
2710 tc = c;
2711 } else { /* no utf or alternate charset mode */
2712 tc = vc_translate(vc, c);
2713 }
2714 2897
2715 param.c = tc;2898 param.c = tc;
2716 if (atomic_notifier_call_chain(&vt_notifier_list, VT_PREWRITE,2899 if (atomic_notifier_call_chain(&vt_notifier_list, VT_PREWRITE,
2717 &param) == NOTIFY_STOP)2900 &param) == NOTIFY_STOP)
2718 continue;2901 continue;
2719 2902
2720 /* If the original code was a control character we2903 if (vc_is_control(vc, tc, c)) {
2721 * only allow a glyph to be displayed if the code is2904 con_flush(vc, &draw);
2722 * not normally used (such as for cursor movement) or2905 do_con_trol(tty, vc, orig);
2723 * if the disp_ctrl mode has been explicitly enabled.
2724 * Certain characters (as given by the CTRL_ALWAYS
2725 * bitmap) are always displayed as control characters,
2726 * as the console would be pretty useless without
2727 * them; to display an arbitrary font position use the
2728 * direct-to-font zone in UTF-8 mode.
2729 */
2730 ok = tc && (c >= 32 ||
2731 !(vc->vc_disp_ctrl ? (CTRL_ALWAYS >> c) & 1 :
2732 vc->vc_utf || ((CTRL_ACTION >> c) & 1)))
2733 && (c != 127 || vc->vc_disp_ctrl)
2734 && (c != 128+27);
2735
2736 if (vc->vc_state == ESnormal && ok) {
2737 if (vc->vc_utf && !vc->vc_disp_ctrl) {
2738 if (is_double_width(c))
2739 width = 2;
2740 }
2741 /* Now try to find out how to display it */
2742 tc = conv_uni_to_pc(vc, tc);
2743 if (tc & ~charmask) {
2744 if (tc == -1 || tc == -2) {
2745 continue; /* nothing to display */
2746 }
2747 /* Glyph not found */
2748 if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) {
2749 /* In legacy mode use the glyph we get by a 1:1 mapping.
2750 This would make absolutely no sense with Unicode in mind,
2751 but do this for ASCII characters since a font may lack
2752 Unicode mapping info and we don't want to end up with
2753 having question marks only. */
2754 tc = c;
2755 } else {
2756 /* Display U+FFFD. If it's not found, display an inverse question mark. */
2757 tc = conv_uni_to_pc(vc, 0xfffd);
2758 if (tc < 0) {
2759 inverse = 1;
2760 tc = conv_uni_to_pc(vc, '?');
2761 if (tc < 0) tc = '?';
2762 }
2763 }
2764 }
2765
2766 if (!inverse) {
2767 vc_attr = vc->vc_attr;
2768 } else {
2769 /* invert vc_attr */
2770 if (!vc->vc_can_do_color) {
2771 vc_attr = (vc->vc_attr) ^ 0x08;
2772 } else if (vc->vc_hi_font_mask == 0x100) {
2773 vc_attr = ((vc->vc_attr) & 0x11) | (((vc->vc_attr) & 0xe0) >> 4) | (((vc->vc_attr) & 0x0e) << 4);
2774 } else {
2775 vc_attr = ((vc->vc_attr) & 0x88) | (((vc->vc_attr) & 0x70) >> 4) | (((vc->vc_attr) & 0x07) << 4);
2776 }
2777 con_flush(vc, draw_from, draw_to, &draw_x);
2778 }
2779
2780 next_c = c;
2781 while (1) {
2782 if (vc->vc_need_wrap || vc->vc_decim)
2783 con_flush(vc, draw_from, draw_to,
2784 &draw_x);
2785 if (vc->vc_need_wrap) {
2786 cr(vc);
2787 lf(vc);
2788 }
2789 if (vc->vc_decim)
2790 insert_char(vc, 1);
2791 vc_uniscr_putc(vc, next_c);
2792 scr_writew(himask ?
2793 ((vc_attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
2794 (vc_attr << 8) + tc,
2795 (u16 *) vc->vc_pos);
2796 if (con_should_update(vc) && draw_x < 0) {
2797 draw_x = vc->vc_x;
2798 draw_from = vc->vc_pos;
2799 }
2800 if (vc->vc_x == vc->vc_cols - 1) {
2801 vc->vc_need_wrap = vc->vc_decawm;
2802 draw_to = vc->vc_pos + 2;
2803 } else {
2804 vc->vc_x++;
2805 draw_to = (vc->vc_pos += 2);
2806 }
2807
2808 if (!--width) break;
2809
2810 tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */
2811 if (tc < 0) tc = ' ';
2812 next_c = ' ';
2813 }
2814 notify_write(vc, c);
2815
2816 if (inverse)
2817 con_flush(vc, draw_from, draw_to, &draw_x);
2818
2819 if (rescan) {
2820 rescan = 0;
2821 inverse = 0;
2822 width = 1;
2823 c = orig;
2824 goto rescan_last_byte;
2825 }
2826 continue;2906 continue;
2827 }2907 }
2828 con_flush(vc, draw_from, draw_to, &draw_x);2908
2829 do_con_trol(tty, vc, orig);2909 if (vc_con_write_normal(vc, tc, c, &draw) < 0)
2910 continue;
2911
2912 if (rescan)
2913 goto rescan_last_byte;
2830 }2914 }
2831 con_flush(vc, draw_from, draw_to, &draw_x);2915 con_flush(vc, &draw);
2832 vc_uniscr_debug_check(vc);2916 vc_uniscr_debug_check(vc);
2833 console_conditional_schedule();2917 console_conditional_schedule();
2834 notify_update(vc);2918 notify_update(vc);
@@ -2978,25 +3062,25 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) · 143 unmodified lines
2978 hide_cursor(vc);3062 hide_cursor(vc);
2979 3063
2980 start = (ushort *)vc->vc_pos;3064 start = (ushort *)vc->vc_pos;
2981 start_x = vc->vc_x;3065 start_x = vc->state.x;
2982 cnt = 0;3066 cnt = 0;
2983 while (count--) {3067 while (count--) {
2984 c = *b++;3068 c = *b++;
2985 if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {3069 if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
2986 if (cnt && con_is_visible(vc))3070 if (cnt && con_is_visible(vc))
2987 vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);3071 vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x);
2988 cnt = 0;3072 cnt = 0;
2989 if (c == 8) { /* backspace */3073 if (c == 8) { /* backspace */
2990 bs(vc);3074 bs(vc);
2991 start = (ushort *)vc->vc_pos;3075 start = (ushort *)vc->vc_pos;
2992 start_x = vc->vc_x;3076 start_x = vc->state.x;
2993 continue;3077 continue;
2994 }3078 }
2995 if (c != 13)3079 if (c != 13)
2996 lf(vc);3080 lf(vc);
2997 cr(vc);3081 cr(vc);
2998 start = (ushort *)vc->vc_pos;3082 start = (ushort *)vc->vc_pos;
2999 start_x = vc->vc_x;3083 start_x = vc->state.x;
3000 if (c == 10 || c == 13)3084 if (c == 10 || c == 13)
3001 continue;3085 continue;
3002 }3086 }
@@ -3004,15 +3088,15 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) · 1 unmodified line
3004 scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);3088 scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
3005 notify_write(vc, c);3089 notify_write(vc, c);
3006 cnt++;3090 cnt++;
3007 if (vc->vc_x == vc->vc_cols - 1) {3091 if (vc->state.x == vc->vc_cols - 1) {
3008 vc->vc_need_wrap = 1;3092 vc->vc_need_wrap = 1;
3009 } else {3093 } else {
3010 vc->vc_pos += 2;3094 vc->vc_pos += 2;
3011 vc->vc_x++;3095 vc->state.x++;
3012 }3096 }
3013 }3097 }
3014 if (cnt && con_is_visible(vc))3098 if (cnt && con_is_visible(vc))
3015 vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);3099 vc->vc_sw->con_putcs(vc, start, cnt, vc->state.y, start_x);
3016 set_cursor(vc);3100 set_cursor(vc);
3017 notify_update(vc);3101 notify_update(vc);
3018 3102
@@ -3408,7 +3492,7 @@ static int __init con_init(void) · 389 unmodified lines
3408 master_display_fg = vc = vc_cons[currcons].d;3492 master_display_fg = vc = vc_cons[currcons].d;
3409 set_origin(vc);3493 set_origin(vc);
3410 save_screen(vc);3494 save_screen(vc);
3411 gotoxy(vc, vc->vc_x, vc->vc_y);3495 gotoxy(vc, vc->state.x, vc->state.y);
3412 csi_J(vc, 0);3496 csi_J(vc, 0);
3413 update_screen(vc);3497 update_screen(vc);
3414 pr_info("Console: %s %s %dx%d\n",3498 pr_info("Console: %s %s %dx%d\n",
@@ -4687,8 +4771,8 @@ EXPORT_SYMBOL_GPL(screen_pos); · 1272 unmodified lines
4687void getconsxy(struct vc_data *vc, unsigned char *p)4771void getconsxy(struct vc_data *vc, unsigned char *p)
4688{4772{
4689 /* clamp values if they don't fit */4773 /* clamp values if they don't fit */
4690 p[0] = min(vc->vc_x, 0xFFu);4774 p[0] = min(vc->state.x, 0xFFu);
4691 p[1] = min(vc->vc_y, 0xFFu);4775 p[1] = min(vc->state.y, 0xFFu);
4692}4776}
4693 4777
4694void putconsxy(struct vc_data *vc, unsigned char *p)4778void putconsxy(struct vc_data *vc, unsigned char *p)
drivers/tty/vt/vt_ioctl.c+557−552
@@ -241,136 +241,56 @@ int vt_waitactive(int n) · 240 unmodified lines
241#define GPLAST 0x3df241#define GPLAST 0x3df
242#define GPNUM (GPLAST - GPFIRST + 1)242#define GPNUM (GPLAST - GPFIRST + 1)
243 243
244 244/*
245 245 * currently, setting the mode from KD_TEXT to KD_GRAPHICS doesn't do a whole
246static inline int 246 * lot. i'm not sure if it should do any restoration of modes or what...
247do_fontx_ioctl(int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op)247 *
248{248 * XXX It should at least call into the driver, fbdev's definitely need to
249 struct consolefontdesc cfdarg;249 * restore their engine state. --BenH
250 int i;250 */
251 251static int vt_kdsetmode(struct vc_data *vc, unsigned long mode)
252 if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
253 return -EFAULT;
254
255 switch (cmd) {
256 case PIO_FONTX:
257 if (!perm)
258 return -EPERM;
259 op->op = KD_FONT_OP_SET;
260 op->flags = KD_FONT_FLAG_OLD;
261 op->width = 8;
262 op->height = cfdarg.charheight;
263 op->charcount = cfdarg.charcount;
264 op->data = cfdarg.chardata;
265 return con_font_op(vc_cons[fg_console].d, op);
266 case GIO_FONTX: {
267 op->op = KD_FONT_OP_GET;
268 op->flags = KD_FONT_FLAG_OLD;
269 op->width = 8;
270 op->height = cfdarg.charheight;
271 op->charcount = cfdarg.charcount;
272 op->data = cfdarg.chardata;
273 i = con_font_op(vc_cons[fg_console].d, op);
274 if (i)
275 return i;
276 cfdarg.charheight = op->height;
277 cfdarg.charcount = op->charcount;
278 if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
279 return -EFAULT;
280 return 0;
281 }
282 }
283 return -EINVAL;
284}
285
286static inline int
287do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc)
288{252{
289 struct unimapdesc tmp;253 switch (mode) {
290 254 case KD_GRAPHICS:
291 if (copy_from_user(&tmp, user_ud, sizeof tmp))255 break;
292 return -EFAULT;256 case KD_TEXT0:
293 switch (cmd) {257 case KD_TEXT1:
294 case PIO_UNIMAP:258 mode = KD_TEXT;
295 if (!perm)259 fallthrough;
296 return -EPERM;260 case KD_TEXT:
297 return con_set_unimap(vc, tmp.entry_ct, tmp.entries);261 break;
298 case GIO_UNIMAP:262 default:
299 if (!perm && fg_console != vc->vc_num)263 return -EINVAL;
300 return -EPERM;
301 return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
302 }264 }
303 return 0;
304}
305
306/* deallocate a single console, if possible (leave 0) */
307static int vt_disallocate(unsigned int vc_num)
308{
309 struct vc_data *vc = NULL;
310 int ret = 0;
311
312 console_lock();
313 if (vt_busy(vc_num))
314 ret = -EBUSY;
315 else if (vc_num)
316 vc = vc_deallocate(vc_num);
317 console_unlock();
318 265
319 if (vc && vc_num >= MIN_NR_CONSOLES)266 /* FIXME: this needs the console lock extending */
320 tty_port_put(&vc->port);267 if (vc->vc_mode == mode)
321 268 return 0;
322 return ret;
323}
324 269
325/* deallocate all unused consoles, but leave 0 */270 vc->vc_mode = mode;
326static void vt_disallocate_all(void)271 if (vc->vc_num != fg_console)
327{272 return 0;
328 struct vc_data *vc[MAX_NR_CONSOLES];
329 int i;
330 273
274 /* explicitly blank/unblank the screen if switching modes */
331 console_lock();275 console_lock();
332 for (i = 1; i < MAX_NR_CONSOLES; i++)276 if (mode == KD_TEXT)
333 if (!vt_busy(i))277 do_unblank_screen(1);
334 vc[i] = vc_deallocate(i);278 else
335 else279 do_blank_screen(1);
336 vc[i] = NULL;
337 console_unlock();280 console_unlock();
338 281
339 for (i = 1; i < MAX_NR_CONSOLES; i++) {282 return 0;
340 if (vc[i] && i >= MIN_NR_CONSOLES)
341 tty_port_put(&vc[i]->port);
342 }
343}283}
344 284
345 285static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd,
346/*286 unsigned long arg, bool perm)
347 * We handle the console-specific ioctl's here. We allow the
348 * capability to modify any console, not just the fg_console.
349 */
350int vt_ioctl(struct tty_struct *tty,
351 unsigned int cmd, unsigned long arg)
352{287{
353 struct vc_data *vc = tty->driver_data;288 struct vc_data *vc = tty->driver_data;
354 struct console_font_op op; /* used in multiple places here */
355 unsigned int console = vc->vc_num;
356 unsigned char ucval;
357 unsigned int uival;
358 void __user *up = (void __user *)arg;289 void __user *up = (void __user *)arg;
359 int i, perm;290 unsigned int console = vc->vc_num;
360 int ret = 0;291 int ret;
361 292
362 /*
363 * To have permissions to do most of the vt ioctls, we either have
364 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
365 */
366 perm = 0;
367 if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
368 perm = 1;
369
370 switch (cmd) {293 switch (cmd) {
371 case TIOCLINUX:
372 ret = tioclinux(tty, arg);
373 break;
374 case KIOCSOUND:294 case KIOCSOUND:
375 if (!perm)295 if (!perm)
376 return -EPERM;296 return -EPERM;
@@ -390,7 +310,7 @@ int vt_ioctl(struct tty_struct *tty, · 13 unmodified lines
390 return -EPERM;310 return -EPERM;
391 {311 {
392 unsigned int ticks, count;312 unsigned int ticks, count;
393 313
394 /*314 /*
395 * Generate the tone for the appropriate number of ticks.315 * Generate the tone for the appropriate number of ticks.
396 * If the time is zero, turn off sound ourselves.316 * If the time is zero, turn off sound ourselves.
@@ -407,9 +327,7 @@ int vt_ioctl(struct tty_struct *tty, · 10 unmodified lines
407 /*327 /*
408 * this is naïve.328 * this is naïve.
409 */329 */
410 ucval = KB_101;330 return put_user(KB_101, (char __user *)arg);
411 ret = put_user(ucval, (char __user *)arg);
412 break;
413 331
414 /*332 /*
415 * These cannot be implemented on any machine that implements333 * These cannot be implemented on any machine that implements
@@ -426,84 +344,45 @@ int vt_ioctl(struct tty_struct *tty, · 10 unmodified lines
426 *344 *
427 * These are locked internally via sys_ioperm345 * These are locked internally via sys_ioperm
428 */346 */
429 if (arg < GPFIRST || arg > GPLAST) {347 if (arg < GPFIRST || arg > GPLAST)
430 ret = -EINVAL;348 return -EINVAL;
431 break;349
432 }350 return ksys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
433 ret = ksys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
434 break;
435 351
436 case KDENABIO:352 case KDENABIO:
437 case KDDISABIO:353 case KDDISABIO:
438 ret = ksys_ioperm(GPFIRST, GPNUM,354 return ksys_ioperm(GPFIRST, GPNUM,
439 (cmd == KDENABIO)) ? -ENXIO : 0;355 (cmd == KDENABIO)) ? -ENXIO : 0;
440 break;
441#endif356#endif
442 357
443 /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */358 /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
444 359
445 case KDKBDREP:360 case KDKBDREP:
446 {361 {
447 struct kbd_repeat kbrep;362 struct kbd_repeat kbrep;
448 363
449 if (!capable(CAP_SYS_TTY_CONFIG))364 if (!capable(CAP_SYS_TTY_CONFIG))
450 return -EPERM;365 return -EPERM;
451 366
452 if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) {367 if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat)))
453 ret = -EFAULT;368 return -EFAULT;
454 break;369
455 }
456 ret = kbd_rate(&kbrep);370 ret = kbd_rate(&kbrep);
457 if (ret)371 if (ret)
458 break;372 return ret;
459 if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))373 if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))
460 ret = -EFAULT;374 return -EFAULT;
461 break;375 break;
462 }376 }
463 377
464 case KDSETMODE:378 case KDSETMODE:
465 /*
466 * currently, setting the mode from KD_TEXT to KD_GRAPHICS
467 * doesn't do a whole lot. i'm not sure if it should do any
468 * restoration of modes or what...
469 *
470 * XXX It should at least call into the driver, fbdev's definitely
471 * need to restore their engine state. --BenH
472 */
473 if (!perm)379 if (!perm)
474 return -EPERM;380 return -EPERM;
475 switch (arg) {381
476 case KD_GRAPHICS:382 return vt_kdsetmode(vc, arg);
477 break;
478 case KD_TEXT0:
479 case KD_TEXT1:
480 arg = KD_TEXT;
481 case KD_TEXT:
482 break;
483 default:
484 ret = -EINVAL;
485 goto out;
486 }
487 /* FIXME: this needs the console lock extending */
488 if (vc->vc_mode == (unsigned char) arg)
489 break;
490 vc->vc_mode = (unsigned char) arg;
491 if (console != fg_console)
492 break;
493 /*
494 * explicitly blank/unblank the screen if switching modes
495 */
496 console_lock();
497 if (arg == KD_TEXT)
498 do_unblank_screen(1);
499 else
500 do_blank_screen(1);
501 console_unlock();
502 break;
503 383
504 case KDGETMODE:384 case KDGETMODE:
505 uival = vc->vc_mode;385 return put_user(vc->vc_mode, (int __user *)arg);
506 goto setint;
507 386
508 case KDMAPDISP:387 case KDMAPDISP:
509 case KDUNMAPDISP:388 case KDUNMAPDISP:
@@ -511,51 +390,42 @@ int vt_ioctl(struct tty_struct *tty, · 1 unmodified line
511 * these work like a combination of mmap and KDENABIO.390 * these work like a combination of mmap and KDENABIO.
512 * this could be easily finished.391 * this could be easily finished.
513 */392 */
514 ret = -EINVAL;393 return -EINVAL;
515 break;
516 394
517 case KDSKBMODE:395 case KDSKBMODE:
518 if (!perm)396 if (!perm)
519 return -EPERM;397 return -EPERM;
520 ret = vt_do_kdskbmode(console, arg);398 ret = vt_do_kdskbmode(console, arg);
521 if (ret == 0)399 if (ret)
522 tty_ldisc_flush(tty);400 return ret;
401 tty_ldisc_flush(tty);
523 break;402 break;
524 403
525 case KDGKBMODE:404 case KDGKBMODE:
526 uival = vt_do_kdgkbmode(console);405 return put_user(vt_do_kdgkbmode(console), (int __user *)arg);
527 ret = put_user(uival, (int __user *)arg);
528 break;
529 406
530 /* this could be folded into KDSKBMODE, but for compatibility407 /* this could be folded into KDSKBMODE, but for compatibility
531 reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */408 reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
532 case KDSKBMETA:409 case KDSKBMETA:
533 ret = vt_do_kdskbmeta(console, arg);410 return vt_do_kdskbmeta(console, arg);
534 break;
535 411
536 case KDGKBMETA:412 case KDGKBMETA:
537 /* FIXME: should review whether this is worth locking */413 /* FIXME: should review whether this is worth locking */
538 uival = vt_do_kdgkbmeta(console);414 return put_user(vt_do_kdgkbmeta(console), (int __user *)arg);
539 setint:
540 ret = put_user(uival, (int __user *)arg);
541 break;
542 415
543 case KDGETKEYCODE:416 case KDGETKEYCODE:
544 case KDSETKEYCODE:417 case KDSETKEYCODE:
545 if(!capable(CAP_SYS_TTY_CONFIG))418 if(!capable(CAP_SYS_TTY_CONFIG))
546 perm = 0;419 perm = 0;
547 ret = vt_do_kbkeycode_ioctl(cmd, up, perm);420 return vt_do_kbkeycode_ioctl(cmd, up, perm);
548 break;
549 421
550 case KDGKBENT:422 case KDGKBENT:
551 case KDSKBENT:423 case KDSKBENT:
552 ret = vt_do_kdsk_ioctl(cmd, up, perm, console);424 return vt_do_kdsk_ioctl(cmd, up, perm, console);
553 break;
554 425
555 case KDGKBSENT:426 case KDGKBSENT:
556 case KDSKBSENT:427 case KDSKBSENT:
557 ret = vt_do_kdgkb_ioctl(cmd, up, perm);428 return vt_do_kdgkb_ioctl(cmd, up, perm);
558 break;
559 429
560 /* Diacritical processing. Handled in keyboard.c as it has430 /* Diacritical processing. Handled in keyboard.c as it has
561 to operate on the keyboard locks and structures */431 to operate on the keyboard locks and structures */
@@ -563,8 +433,7 @@ int vt_ioctl(struct tty_struct *tty, · 1 unmodified line
563 case KDGKBDIACRUC:433 case KDGKBDIACRUC:
564 case KDSKBDIACR:434 case KDSKBDIACR:
565 case KDSKBDIACRUC:435 case KDSKBDIACRUC:
566 ret = vt_do_diacrit(cmd, up, perm);436 return vt_do_diacrit(cmd, up, perm);
567 break;
568 437
569 /* the ioctls below read/set the flags usually shown in the leds */438 /* the ioctls below read/set the flags usually shown in the leds */
570 /* don't use them - they will go away without warning */439 /* don't use them - they will go away without warning */
@@ -572,8 +441,7 @@ int vt_ioctl(struct tty_struct *tty, · 1 unmodified line
572 case KDSKBLED:441 case KDSKBLED:
573 case KDGETLED:442 case KDGETLED:
574 case KDSETLED:443 case KDSETLED:
575 ret = vt_do_kdskled(console, cmd, arg, perm);444 return vt_do_kdskled(console, cmd, arg, perm);
576 break;
577 445
578 /*446 /*
579 * A process can indicate its willingness to accept signals447 * A process can indicate its willingness to accept signals
@@ -583,161 +451,504 @@ int vt_ioctl(struct tty_struct *tty, · 3 unmodified lines
583 * See also the kbrequest field of inittab(5).451 * See also the kbrequest field of inittab(5).
584 */452 */
585 case KDSIGACCEPT:453 case KDSIGACCEPT:
586 {
587 if (!perm || !capable(CAP_KILL))454 if (!perm || !capable(CAP_KILL))
588 return -EPERM;455 return -EPERM;
589 if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)456 if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
590 ret = -EINVAL;457 return -EINVAL;
591 else {458
592 spin_lock_irq(&vt_spawn_con.lock);459 spin_lock_irq(&vt_spawn_con.lock);
593 put_pid(vt_spawn_con.pid);460 put_pid(vt_spawn_con.pid);
594 vt_spawn_con.pid = get_pid(task_pid(current));461 vt_spawn_con.pid = get_pid(task_pid(current));
595 vt_spawn_con.sig = arg;462 vt_spawn_con.sig = arg;
596 spin_unlock_irq(&vt_spawn_con.lock);463 spin_unlock_irq(&vt_spawn_con.lock);
597 }
598 break;464 break;
599 }
600 465
601 case VT_SETMODE:466 case KDFONTOP: {
602 {467 struct console_font_op op;
603 struct vt_mode tmp;
604 468
605 if (!perm)469 if (copy_from_user(&op, up, sizeof(op)))
470 return -EFAULT;
471 if (!perm && op.op != KD_FONT_OP_GET)
606 return -EPERM;472 return -EPERM;
607 if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) {473 ret = con_font_op(vc, &op);
608 ret = -EFAULT;474 if (ret)
609 goto out;475 return ret;
610 }476 if (copy_to_user(up, &op, sizeof(op)))
611 if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) {477 return -EFAULT;
612 ret = -EINVAL;
613 goto out;
614 }
615 console_lock();
616 vc->vt_mode = tmp;
617 /* the frsig is ignored, so we set it to 0 */
618 vc->vt_mode.frsig = 0;
619 put_pid(vc->vt_pid);
620 vc->vt_pid = get_pid(task_pid(current));
621 /* no switch is required -- saw@shade.msu.ru */
622 vc->vt_newvt = -1;
623 console_unlock();
624 break;478 break;
625 }479 }
626 480
627 case VT_GETMODE:481 default:
628 {482 return -ENOIOCTLCMD;
629 struct vt_mode tmp;483 }
630 int rc;
631 484
632 console_lock();485 return 0;
633 memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode));486}
634 console_unlock();
635 487
636 rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));488static inline int do_fontx_ioctl(int cmd,
637 if (rc)489 struct consolefontdesc __user *user_cfd,
638 ret = -EFAULT;490 struct console_font_op *op)
639 break;491{
640 }492 struct consolefontdesc cfdarg;
493 int i;
641 494
642 /*495 if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
643 * Returns global vt state. Note that VT 0 is always open, since496 return -EFAULT;
644 * it's an alias for the current VT, and people can't use it here.
645 * We cannot return state for more than 16 VTs, since v_state is short.
646 */
647 case VT_GETSTATE:
648 {
649 struct vt_stat __user *vtstat = up;
650 unsigned short state, mask;
651 497
652 if (put_user(fg_console + 1, &vtstat->v_active))498 switch (cmd) {
653 ret = -EFAULT;499 case PIO_FONTX:
654 else {500 op->op = KD_FONT_OP_SET;
655 state = 1; /* /dev/tty0 is always open */501 op->flags = KD_FONT_FLAG_OLD;
656 console_lock(); /* required by vt_in_use() */502 op->width = 8;
657 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;503 op->height = cfdarg.charheight;
658 ++i, mask <<= 1)504 op->charcount = cfdarg.charcount;
659 if (vt_in_use(i))505 op->data = cfdarg.chardata;
660 state |= mask;506 return con_font_op(vc_cons[fg_console].d, op);
661 console_unlock();507 case GIO_FONTX: {
662 ret = put_user(state, &vtstat->v_state);508 op->op = KD_FONT_OP_GET;
509 op->flags = KD_FONT_FLAG_OLD;
510 op->width = 8;
511 op->height = cfdarg.charheight;
512 op->charcount = cfdarg.charcount;
513 op->data = cfdarg.chardata;
514 i = con_font_op(vc_cons[fg_console].d, op);
515 if (i)
516 return i;
517 cfdarg.charheight = op->height;
518 cfdarg.charcount = op->charcount;
519 if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
520 return -EFAULT;
521 return 0;
663 }522 }
664 break;
665 }523 }
524 return -EINVAL;
525}
666 526
667 /*527static int vt_io_fontreset(struct console_font_op *op)
668 * Returns the first available (non-opened) console.528{
669 */529 int ret;
670 case VT_OPENQRY:
671 console_lock(); /* required by vt_in_use() */
672 for (i = 0; i < MAX_NR_CONSOLES; ++i)
673 if (!vt_in_use(i))
674 break;
675 console_unlock();
676 uival = i < MAX_NR_CONSOLES ? (i+1) : -1;
677 goto setint;
678 530
679 /*531 if (__is_defined(BROKEN_GRAPHICS_PROGRAMS)) {
680 * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,532 /*
681 * with num >= 1 (switches to vt 0, our console, are not allowed, just533 * With BROKEN_GRAPHICS_PROGRAMS defined, the default font is
682 * to preserve sanity).534 * not saved.
683 */535 */
684 case VT_ACTIVATE:536 return -ENOSYS;
537 }
538
539 op->op = KD_FONT_OP_SET_DEFAULT;
540 op->data = NULL;
541 ret = con_font_op(vc_cons[fg_console].d, op);
542 if (ret)
543 return ret;
544
545 console_lock();
546 con_set_default_unimap(vc_cons[fg_console].d);
547 console_unlock();
548
549 return 0;
550}
551
552static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
553 struct vc_data *vc)
554{
555 struct unimapdesc tmp;
556
557 if (copy_from_user(&tmp, user_ud, sizeof tmp))
558 return -EFAULT;
559 switch (cmd) {
560 case PIO_UNIMAP:
561 return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
562 case GIO_UNIMAP:
563 if (fg_console != vc->vc_num)
564 return -EPERM;
565 return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
566 tmp.entries);
567 }
568 return 0;
569}
570
571static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up,
572 bool perm)
573{
574 struct console_font_op op; /* used in multiple places here */
575
576 switch (cmd) {
577 case PIO_FONT:
685 if (!perm)578 if (!perm)
686 return -EPERM;579 return -EPERM;
687 if (arg == 0 || arg > MAX_NR_CONSOLES)580 op.op = KD_FONT_OP_SET;
688 ret = -ENXIO;581 op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */
689 else {582 op.width = 8;
690 arg--;583 op.height = 0;
691 console_lock();584 op.charcount = 256;
692 ret = vc_allocate(arg);585 op.data = up;
693 console_unlock();586 return con_font_op(vc_cons[fg_console].d, &op);
694 if (ret)
695 break;
696 set_console(arg);
697 }
698 break;
699 587
700 case VT_SETACTIVATE:588 case GIO_FONT:
701 {589 op.op = KD_FONT_OP_GET;
702 struct vt_setactivate vsa;590 op.flags = KD_FONT_FLAG_OLD;
591 op.width = 8;
592 op.height = 32;
593 op.charcount = 256;
594 op.data = up;
595 return con_font_op(vc_cons[fg_console].d, &op);
596
597 case PIO_CMAP:
598 if (!perm)
599 return -EPERM;
600 return con_set_cmap(up);
703 601
602 case GIO_CMAP:
603 return con_get_cmap(up);
604
605 case PIO_FONTX:
606 if (!perm)
607 return -EPERM;
608
609 fallthrough;
610 case GIO_FONTX:
611 return do_fontx_ioctl(cmd, up, &op);
612
613 case PIO_FONTRESET:
614 if (!perm)
615 return -EPERM;
616
617 return vt_io_fontreset(&op);
618
619 case PIO_SCRNMAP:
620 if (!perm)
621 return -EPERM;
622 return con_set_trans_old(up);
623
624 case GIO_SCRNMAP:
625 return con_get_trans_old(up);
626
627 case PIO_UNISCRNMAP:
628 if (!perm)
629 return -EPERM;
630 return con_set_trans_new(up);
631
632 case GIO_UNISCRNMAP:
633 return con_get_trans_new(up);
634
635 case PIO_UNIMAPCLR:
704 if (!perm)636 if (!perm)
705 return -EPERM;637 return -EPERM;
638 con_clear_unimap(vc);
639 break;
640
641 case PIO_UNIMAP:
642 case GIO_UNIMAP:
643 if (!perm)
644 return -EPERM;
645
646 return do_unimap_ioctl(cmd, up, vc);
647
648 default:
649 return -ENOIOCTLCMD;
650 }
651
652 return 0;
653}
654
655static int vt_reldisp(struct vc_data *vc, unsigned int swtch)
656{
657 int newvt, ret;
658
659 if (vc->vt_mode.mode != VT_PROCESS)
660 return -EINVAL;
661
662 /* Switched-to response */
663 if (vc->vt_newvt < 0) {
664 /* If it's just an ACK, ignore it */
665 return swtch == VT_ACKACQ ? 0 : -EINVAL;
666 }
667
668 /* Switching-from response */
669 if (swtch == 0) {
670 /* Switch disallowed, so forget we were trying to do it. */
671 vc->vt_newvt = -1;
672 return 0;
673 }
674
675 /* The current vt has been released, so complete the switch. */
676 newvt = vc->vt_newvt;
677 vc->vt_newvt = -1;
678 ret = vc_allocate(newvt);
679 if (ret)
680 return ret;
706 681
707 if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg,682 /*
708 sizeof(struct vt_setactivate))) {683 * When we actually do the console switch, make sure we are atomic with
709 ret = -EFAULT;684 * respect to other console switches..
710 goto out;685 */
686 complete_change_console(vc_cons[newvt].d);
687
688 return 0;
689}
690
691static int vt_setactivate(struct vt_setactivate __user *sa)
692{
693 struct vt_setactivate vsa;
694 struct vc_data *nvc;
695 int ret;
696
697 if (copy_from_user(&vsa, sa, sizeof(vsa)))
698 return -EFAULT;
699 if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
700 return -ENXIO;
701
702 vsa.console = array_index_nospec(vsa.console, MAX_NR_CONSOLES + 1);
703 vsa.console--;
704 console_lock();
705 ret = vc_allocate(vsa.console);
706 if (ret) {
707 console_unlock();
708 return ret;
709 }
710
711 /*
712 * This is safe providing we don't drop the console sem between
713 * vc_allocate and finishing referencing nvc.
714 */
715 nvc = vc_cons[vsa.console].d;
716 nvc->vt_mode = vsa.mode;
717 nvc->vt_mode.frsig = 0;
718 put_pid(nvc->vt_pid);
719 nvc->vt_pid = get_pid(task_pid(current));
720 console_unlock();
721
722 /* Commence switch and lock */
723 /* Review set_console locks */
724 set_console(vsa.console);
725
726 return 0;
727}
728
729/* deallocate a single console, if possible (leave 0) */
730static int vt_disallocate(unsigned int vc_num)
731{
732 struct vc_data *vc = NULL;
733 int ret = 0;
734
735 console_lock();
736 if (vt_busy(vc_num))
737 ret = -EBUSY;
738 else if (vc_num)
739 vc = vc_deallocate(vc_num);
740 console_unlock();
741
742 if (vc && vc_num >= MIN_NR_CONSOLES)
743 tty_port_put(&vc->port);
744
745 return ret;
746}
747
748/* deallocate all unused consoles, but leave 0 */
749static void vt_disallocate_all(void)
750{
751 struct vc_data *vc[MAX_NR_CONSOLES];
752 int i;
753
754 console_lock();
755 for (i = 1; i < MAX_NR_CONSOLES; i++)
756 if (!vt_busy(i))
757 vc[i] = vc_deallocate(i);
758 else
759 vc[i] = NULL;
760 console_unlock();
761
762 for (i = 1; i < MAX_NR_CONSOLES; i++) {
763 if (vc[i] && i >= MIN_NR_CONSOLES)
764 tty_port_put(&vc[i]->port);
765 }
766}
767
768static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs)
769{
770 struct vt_consize v;
771 int i;
772
773 if (copy_from_user(&v, cs, sizeof(struct vt_consize)))
774 return -EFAULT;
775
776 /* FIXME: Should check the copies properly */
777 if (!v.v_vlin)
778 v.v_vlin = vc->vc_scan_lines;
779
780 if (v.v_clin) {
781 int rows = v.v_vlin / v.v_clin;
782 if (v.v_rows != rows) {
783 if (v.v_rows) /* Parameters don't add up */
784 return -EINVAL;
785 v.v_rows = rows;
711 }786 }
712 if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)787 }
713 ret = -ENXIO;788
714 else {789 if (v.v_vcol && v.v_ccol) {
715 vsa.console = array_index_nospec(vsa.console,790 int cols = v.v_vcol / v.v_ccol;
716 MAX_NR_CONSOLES + 1);791 if (v.v_cols != cols) {
717 vsa.console--;792 if (v.v_cols)
718 console_lock();793 return -EINVAL;
719 ret = vc_allocate(vsa.console);794 v.v_cols = cols;
720 if (ret == 0) {
721 struct vc_data *nvc;
722 /* This is safe providing we don't drop the
723 console sem between vc_allocate and
724 finishing referencing nvc */
725 nvc = vc_cons[vsa.console].d;
726 nvc->vt_mode = vsa.mode;
727 nvc->vt_mode.frsig = 0;
728 put_pid(nvc->vt_pid);
729 nvc->vt_pid = get_pid(task_pid(current));
730 }
731 console_unlock();
732 if (ret)
733 break;
734 /* Commence switch and lock */
735 /* Review set_console locks */
736 set_console(vsa.console);
737 }795 }
796 }
797
798 if (v.v_clin > 32)
799 return -EINVAL;
800
801 for (i = 0; i < MAX_NR_CONSOLES; i++) {
802 struct vc_data *vcp;
803
804 if (!vc_cons[i].d)
805 continue;
806 console_lock();
807 vcp = vc_cons[i].d;
808 if (vcp) {
809 if (v.v_vlin)
810 vcp->vc_scan_lines = v.v_vlin;
811 if (v.v_clin)
812 vcp->vc_font.height = v.v_clin;
813 vcp->vc_resize_user = 1;
814 vc_resize(vcp, v.v_cols, v.v_rows);
815 }
816 console_unlock();
817 }
818
819 return 0;
820}
821
822/*
823 * We handle the console-specific ioctl's here. We allow the
824 * capability to modify any console, not just the fg_console.
825 */
826int vt_ioctl(struct tty_struct *tty,
827 unsigned int cmd, unsigned long arg)
828{
829 struct vc_data *vc = tty->driver_data;
830 void __user *up = (void __user *)arg;
831 int i, perm;
832 int ret;
833
834 /*
835 * To have permissions to do most of the vt ioctls, we either have
836 * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
837 */
838 perm = 0;
839 if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
840 perm = 1;
841
842 ret = vt_k_ioctl(tty, cmd, arg, perm);
843 if (ret != -ENOIOCTLCMD)
844 return ret;
845
846 ret = vt_io_ioctl(vc, cmd, up, perm);
847 if (ret != -ENOIOCTLCMD)
848 return ret;
849
850 switch (cmd) {
851 case TIOCLINUX:
852 return tioclinux(tty, arg);
853 case VT_SETMODE:
854 {
855 struct vt_mode tmp;
856
857 if (!perm)
858 return -EPERM;
859 if (copy_from_user(&tmp, up, sizeof(struct vt_mode)))
860 return -EFAULT;
861 if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
862 return -EINVAL;
863
864 console_lock();
865 vc->vt_mode = tmp;
866 /* the frsig is ignored, so we set it to 0 */
867 vc->vt_mode.frsig = 0;
868 put_pid(vc->vt_pid);
869 vc->vt_pid = get_pid(task_pid(current));
870 /* no switch is required -- saw@shade.msu.ru */
871 vc->vt_newvt = -1;
872 console_unlock();
873 break;
874 }
875
876 case VT_GETMODE:
877 {
878 struct vt_mode tmp;
879 int rc;
880
881 console_lock();
882 memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode));
883 console_unlock();
884
885 rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
886 if (rc)
887 return -EFAULT;
738 break;888 break;
739 }889 }
740 890
891 /*
892 * Returns global vt state. Note that VT 0 is always open, since
893 * it's an alias for the current VT, and people can't use it here.
894 * We cannot return state for more than 16 VTs, since v_state is short.
895 */
896 case VT_GETSTATE:
897 {
898 struct vt_stat __user *vtstat = up;
899 unsigned short state, mask;
900
901 if (put_user(fg_console + 1, &vtstat->v_active))
902 return -EFAULT;
903
904 state = 1; /* /dev/tty0 is always open */
905 console_lock(); /* required by vt_in_use() */
906 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
907 ++i, mask <<= 1)
908 if (vt_in_use(i))
909 state |= mask;
910 console_unlock();
911 return put_user(state, &vtstat->v_state);
912 }
913
914 /*
915 * Returns the first available (non-opened) console.
916 */
917 case VT_OPENQRY:
918 console_lock(); /* required by vt_in_use() */
919 for (i = 0; i < MAX_NR_CONSOLES; ++i)
920 if (!vt_in_use(i))
921 break;
922 console_unlock();
923 i = i < MAX_NR_CONSOLES ? (i+1) : -1;
924 return put_user(i, (int __user *)arg);
925
926 /*
927 * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
928 * with num >= 1 (switches to vt 0, our console, are not allowed, just
929 * to preserve sanity).
930 */
931 case VT_ACTIVATE:
932 if (!perm)
933 return -EPERM;
934 if (arg == 0 || arg > MAX_NR_CONSOLES)
935 return -ENXIO;
936
937 arg--;
938 console_lock();
939 ret = vc_allocate(arg);
940 console_unlock();
941 if (ret)
942 return ret;
943 set_console(arg);
944 break;
945
946 case VT_SETACTIVATE:
947 if (!perm)
948 return -EPERM;
949
950 return vt_setactivate(up);
951
741 /*952 /*
742 * wait until the specified VT has been activated953 * wait until the specified VT has been activated
743 */954 */
@@ -745,10 +956,8 @@ int vt_ioctl(struct tty_struct *tty, · 1 unmodified line
745 if (!perm)956 if (!perm)
746 return -EPERM;957 return -EPERM;
747 if (arg == 0 || arg > MAX_NR_CONSOLES)958 if (arg == 0 || arg > MAX_NR_CONSOLES)
748 ret = -ENXIO;959 return -ENXIO;
749 else960 return vt_waitactive(arg);
750 ret = vt_waitactive(arg);
751 break;
752 961
753 /*962 /*
754 * If a vt is under process control, the kernel will not switch to it963 * If a vt is under process control, the kernel will not switch to it
@@ -765,258 +974,56 @@ int vt_ioctl(struct tty_struct *tty, · 10 unmodified lines
765 return -EPERM;974 return -EPERM;
766 975
767 console_lock();976 console_lock();
768 if (vc->vt_mode.mode != VT_PROCESS) {977 ret = vt_reldisp(vc, arg);
769 console_unlock();
770 ret = -EINVAL;
771 break;
772 }
773 /*
774 * Switching-from response
775 */
776 if (vc->vt_newvt >= 0) {
777 if (arg == 0)
778 /*
779 * Switch disallowed, so forget we were trying
780 * to do it.
781 */
782 vc->vt_newvt = -1;
783
784 else {
785 /*
786 * The current vt has been released, so
787 * complete the switch.
788 */
789 int newvt;
790 newvt = vc->vt_newvt;
791 vc->vt_newvt = -1;
792 ret = vc_allocate(newvt);
793 if (ret) {
794 console_unlock();
795 break;
796 }
797 /*
798 * When we actually do the console switch,
799 * make sure we are atomic with respect to
800 * other console switches..
801 */
802 complete_change_console(vc_cons[newvt].d);
803 }
804 } else {
805 /*
806 * Switched-to response
807 */
808 /*
809 * If it's just an ACK, ignore it
810 */
811 if (arg != VT_ACKACQ)
812 ret = -EINVAL;
813 }
814 console_unlock();978 console_unlock();
815 break;979
980 return ret;
981
816 982
817 /*983 /*
818 * Disallocate memory associated to VT (but leave VT1)984 * Disallocate memory associated to VT (but leave VT1)
819 */985 */
820 case VT_DISALLOCATE:986 case VT_DISALLOCATE:
821 if (arg > MAX_NR_CONSOLES) {987 if (arg > MAX_NR_CONSOLES)
822 ret = -ENXIO;988 return -ENXIO;
823 break;989
824 }
825 if (arg == 0)990 if (arg == 0)
826 vt_disallocate_all();991 vt_disallocate_all();
827 else992 else
828 ret = vt_disallocate(--arg);993 return vt_disallocate(--arg);
829 break;994 break;
830 995
831 case VT_RESIZE:996 case VT_RESIZE:
832 {997 {
833 struct vt_sizes __user *vtsizes = up;998 struct vt_sizes __user *vtsizes = up;
834 struct vc_data *vc;999 struct vc_data *vc;
835
836 ushort ll,cc;1000 ushort ll,cc;
1001
837 if (!perm)1002 if (!perm)
838 return -EPERM;1003 return -EPERM;
839 if (get_user(ll, &vtsizes->v_rows) ||1004 if (get_user(ll, &vtsizes->v_rows) ||
840 get_user(cc, &vtsizes->v_cols))1005 get_user(cc, &vtsizes->v_cols))
841 ret = -EFAULT;
842 else {
843 console_lock();
844 for (i = 0; i < MAX_NR_CONSOLES; i++) {
845 vc = vc_cons[i].d;
846
847 if (vc) {
848 vc->vc_resize_user = 1;
849 /* FIXME: review v tty lock */
850 vc_resize(vc_cons[i].d, cc, ll);
851 }
852 }
853 console_unlock();
854 }
855 break;
856 }
857
858 case VT_RESIZEX:
859 {
860 struct vt_consize v;
861 if (!perm)
862 return -EPERM;
863 if (copy_from_user(&v, up, sizeof(struct vt_consize)))
864 return -EFAULT;1006 return -EFAULT;
865 /* FIXME: Should check the copies properly */
866 if (!v.v_vlin)
867 v.v_vlin = vc->vc_scan_lines;
868 if (v.v_clin) {
869 int rows = v.v_vlin/v.v_clin;
870 if (v.v_rows != rows) {
871 if (v.v_rows) /* Parameters don't add up */
872 return -EINVAL;
873 v.v_rows = rows;
874 }
875 }
876 if (v.v_vcol && v.v_ccol) {
877 int cols = v.v_vcol/v.v_ccol;
878 if (v.v_cols != cols) {
879 if (v.v_cols)
880 return -EINVAL;
881 v.v_cols = cols;
882 }
883 }
884
885 if (v.v_clin > 32)
886 return -EINVAL;
887 1007
1008 console_lock();
888 for (i = 0; i < MAX_NR_CONSOLES; i++) {1009 for (i = 0; i < MAX_NR_CONSOLES; i++) {
889 struct vc_data *vcp;1010 vc = vc_cons[i].d;
890 1011
891 if (!vc_cons[i].d)1012 if (vc) {
892 continue;1013 vc->vc_resize_user = 1;
893 console_lock();1014 /* FIXME: review v tty lock */
894 vcp = vc_cons[i].d;1015 vc_resize(vc_cons[i].d, cc, ll);
895 if (vcp) {
896 if (v.v_vlin)
897 vcp->vc_scan_lines = v.v_vlin;
898 if (v.v_clin)
899 vcp->vc_font.height = v.v_clin;
900 vcp->vc_resize_user = 1;
901 vc_resize(vcp, v.v_cols, v.v_rows);
902 }1016 }
903 console_unlock();
904 }1017 }
905 break;
906 }
907
908 case PIO_FONT: {
909 if (!perm)
910 return -EPERM;
911 op.op = KD_FONT_OP_SET;
912 op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */
913 op.width = 8;
914 op.height = 0;
915 op.charcount = 256;
916 op.data = up;
917 ret = con_font_op(vc_cons[fg_console].d, &op);
918 break;
919 }
920
921 case GIO_FONT: {
922 op.op = KD_FONT_OP_GET;
923 op.flags = KD_FONT_FLAG_OLD;
924 op.width = 8;
925 op.height = 32;
926 op.charcount = 256;
927 op.data = up;
928 ret = con_font_op(vc_cons[fg_console].d, &op);
929 break;
930 }
931
932 case PIO_CMAP:
933 if (!perm)
934 ret = -EPERM;
935 else
936 ret = con_set_cmap(up);
937 break;
938
939 case GIO_CMAP:
940 ret = con_get_cmap(up);
941 break;
942
943 case PIO_FONTX:
944 case GIO_FONTX:
945 ret = do_fontx_ioctl(cmd, up, perm, &op);
946 break;
947
948 case PIO_FONTRESET:
949 {
950 if (!perm)
951 return -EPERM;
952
953#ifdef BROKEN_GRAPHICS_PROGRAMS
954 /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
955 font is not saved. */
956 ret = -ENOSYS;
957 break;
958#else
959 {
960 op.op = KD_FONT_OP_SET_DEFAULT;
961 op.data = NULL;
962 ret = con_font_op(vc_cons[fg_console].d, &op);
963 if (ret)
964 break;
965 console_lock();
966 con_set_default_unimap(vc_cons[fg_console].d);
967 console_unlock();1018 console_unlock();
968 break;1019 break;
969 }
970#endif
971 }
972
973 case KDFONTOP: {
974 if (copy_from_user(&op, up, sizeof(op))) {
975 ret = -EFAULT;
976 break;
977 }
978 if (!perm && op.op != KD_FONT_OP_GET)
979 return -EPERM;
980 ret = con_font_op(vc, &op);
981 if (ret)
982 break;
983 if (copy_to_user(up, &op, sizeof(op)))
984 ret = -EFAULT;
985 break;
986 }1020 }
987 1021
988 case PIO_SCRNMAP:1022 case VT_RESIZEX:
989 if (!perm)
990 ret = -EPERM;
991 else
992 ret = con_set_trans_old(up);
993 break;
994
995 case GIO_SCRNMAP:
996 ret = con_get_trans_old(up);
997 break;
998
999 case PIO_UNISCRNMAP:
1000 if (!perm)
1001 ret = -EPERM;
1002 else
1003 ret = con_set_trans_new(up);
1004 break;
1005
1006 case GIO_UNISCRNMAP:
1007 ret = con_get_trans_new(up);
1008 break;
1009
1010 case PIO_UNIMAPCLR:
1011 if (!perm)1023 if (!perm)
1012 return -EPERM;1024 return -EPERM;
1013 con_clear_unimap(vc);
1014 break;
1015 1025
1016 case PIO_UNIMAP:1026 return vt_resizex(vc, up);
1017 case GIO_UNIMAP:
1018 ret = do_unimap_ioctl(cmd, up, perm, vc);
1019 break;
1020 1027
1021 case VT_LOCKSWITCH:1028 case VT_LOCKSWITCH:
1022 if (!capable(CAP_SYS_TTY_CONFIG))1029 if (!capable(CAP_SYS_TTY_CONFIG))
@@ -1029,17 +1036,15 @@ int vt_ioctl(struct tty_struct *tty, · 6 unmodified lines
1029 vt_dont_switch = false;1036 vt_dont_switch = false;
1030 break;1037 break;
1031 case VT_GETHIFONTMASK:1038 case VT_GETHIFONTMASK:
1032 ret = put_user(vc->vc_hi_font_mask,1039 return put_user(vc->vc_hi_font_mask,
1033 (unsigned short __user *)arg);1040 (unsigned short __user *)arg);
1034 break;
1035 case VT_WAITEVENT:1041 case VT_WAITEVENT:
1036 ret = vt_event_wait_ioctl((struct vt_event __user *)arg);1042 return vt_event_wait_ioctl((struct vt_event __user *)arg);
1037 break;
1038 default:1043 default:
1039 ret = -ENOIOCTLCMD;1044 return -ENOIOCTLCMD;
1040 }1045 }
1041out:1046
1042 return ret;1047 return 0;
1043}1048}
1044 1049
1045void reset_vc(struct vc_data *vc)1050void reset_vc(struct vc_data *vc)
drivers/usb/misc/sisusbvga/sisusb_con.c+6−5
@@ -302,14 +302,15 @@ sisusbcon_deinit(struct vc_data *c) · 301 unmodified lines
302 302
303/* interface routine */303/* interface routine */
304static u8304static u8
305sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity,305sisusbcon_build_attr(struct vc_data *c, u8 color, enum vc_intensity intensity,
306 u8 blink, u8 underline, u8 reverse, u8 unused)306 bool blink, bool underline, bool reverse,
307 bool unused)
307{308{
308 u8 attr = color;309 u8 attr = color;
309 310
310 if (underline)311 if (underline)
311 attr = (attr & 0xf0) | c->vc_ulcolor;312 attr = (attr & 0xf0) | c->vc_ulcolor;
312 else if (intensity == 0)313 else if (intensity == VCI_HALF_BRIGHT)
313 attr = (attr & 0xf0) | c->vc_halfcolor;314 attr = (attr & 0xf0) | c->vc_halfcolor;
314 315
315 if (reverse)316 if (reverse)
@@ -320,7 +321,7 @@ sisusbcon_build_attr(struct vc_data *c, u8 color, u8 intensity, · 4 unmodified lines
320 if (blink)321 if (blink)
321 attr ^= 0x80;322 attr ^= 0x80;
322 323
323 if (intensity == 2)324 if (intensity == VCI_BOLD)
324 attr ^= 0x08;325 attr ^= 0x08;
325 326
326 return attr;327 return attr;
@@ -726,7 +727,7 @@ sisusbcon_cursor(struct vc_data *c, int mode) · 399 unmodified lines
726 727
727 baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);728 baseline = c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2);
728 729
729 switch (c->vc_cursor_type & 0x0f) {730 switch (CUR_SIZE(c->vc_cursor_type)) {
730 case CUR_BLOCK: from = 1;731 case CUR_BLOCK: from = 1;
731 to = c->vc_font.height;732 to = c->vc_font.height;
732 break;733 break;
drivers/video/console/mdacon.c+11−9
@@ -394,8 +394,10 @@ static inline u16 mda_convert_attr(u16 ch) · 393 unmodified lines
394 (ch & 0x00ff) | attr;394 (ch & 0x00ff) | attr;
395}395}
396 396
397static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, 397static u8 mdacon_build_attr(struct vc_data *c, u8 color,
398 u8 blink, u8 underline, u8 reverse, u8 italic)398 enum vc_intensity intensity,
399 bool blink, bool underline, bool reverse,
400 bool italic)
399{401{
400 /* The attribute is just a bit vector:402 /* The attribute is just a bit vector:
401 *403 *
@@ -405,11 +407,11 @@ static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, · 3 unmodified lines
405 * Bit 7 : blink407 * Bit 7 : blink
406 */408 */
407 409
408 return (intensity & 3) |410 return (intensity & VCI_MASK) |
409 ((underline & 1) << 2) |411 (underline << 2) |
410 ((reverse & 1) << 3) |412 (reverse << 3) |
411 (!!italic << 4) |413 (italic << 4) |
412 ((blink & 1) << 7);414 (blink << 7);
413}415}
414 416
415static void mdacon_invert_region(struct vc_data *c, u16 *p, int count)417static void mdacon_invert_region(struct vc_data *c, u16 *p, int count)
@@ -488,9 +490,9 @@ static void mdacon_cursor(struct vc_data *c, int mode) · 72 unmodified lines
488 return;490 return;
489 }491 }
490 492
491 mda_set_cursor(c->vc_y*mda_num_columns*2 + c->vc_x*2);493 mda_set_cursor(c->state.y * mda_num_columns * 2 + c->state.x * 2);
492 494
493 switch (c->vc_cursor_type & 0x0f) {495 switch (CUR_SIZE(c->vc_cursor_type)) {
494 496
495 case CUR_LOWER_THIRD: mda_set_cursor_size(10, 13); break;497 case CUR_LOWER_THIRD: mda_set_cursor_size(10, 13); break;
496 case CUR_LOWER_HALF: mda_set_cursor_size(7, 13); break;498 case CUR_LOWER_HALF: mda_set_cursor_size(7, 13); break;
drivers/video/console/newport_con.c+5−5
@@ -362,12 +362,12 @@ static void newport_clear(struct vc_data *vc, int sy, int sx, int height, · 361 unmodified lines
362 362
363 if (ystart < yend) {363 if (ystart < yend) {
364 newport_clear_screen(sx << 3, ystart, xend, yend,364 newport_clear_screen(sx << 3, ystart, xend, yend,
365 (vc->vc_color & 0xf0) >> 4);365 (vc->state.color & 0xf0) >> 4);
366 } else {366 } else {
367 newport_clear_screen(sx << 3, ystart, xend, 1023,367 newport_clear_screen(sx << 3, ystart, xend, 1023,
368 (vc->vc_color & 0xf0) >> 4);368 (vc->state.color & 0xf0) >> 4);
369 newport_clear_screen(sx << 3, 0, xend, yend,369 newport_clear_screen(sx << 3, 0, xend, yend,
370 (vc->vc_color & 0xf0) >> 4);370 (vc->state.color & 0xf0) >> 4);
371 }371 }
372}372}
373 373
@@ -591,11 +591,11 @@ static bool newport_scroll(struct vc_data *vc, unsigned int t, unsigned int b, · 217 unmodified lines
591 topscan = (topscan + (lines << 4)) & 0x3ff;591 topscan = (topscan + (lines << 4)) & 0x3ff;
592 newport_clear_lines(vc->vc_rows - lines,592 newport_clear_lines(vc->vc_rows - lines,
593 vc->vc_rows - 1,593 vc->vc_rows - 1,
594 (vc->vc_color & 0xf0) >> 4);594 (vc->state.color & 0xf0) >> 4);
595 } else {595 } else {
596 topscan = (topscan + (-lines << 4)) & 0x3ff;596 topscan = (topscan + (-lines << 4)) & 0x3ff;
597 newport_clear_lines(0, lines - 1,597 newport_clear_lines(0, lines - 1,
598 (vc->vc_color & 0xf0) >> 4);598 (vc->state.color & 0xf0) >> 4);
599 }599 }
600 npregs->cset.topscan = (topscan - 1) & 0x3ff;600 npregs->cset.topscan = (topscan - 1) & 0x3ff;
601 return false;601 return false;
drivers/video/console/sticon.c+8−6
@@ -132,21 +132,21 @@ static void sticon_cursor(struct vc_data *conp, int mode) · 131 unmodified lines
132{132{
133 unsigned short car1;133 unsigned short car1;
134 134
135 car1 = conp->vc_screenbuf[conp->vc_x + conp->vc_y * conp->vc_cols];135 car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols];
136 switch (mode) {136 switch (mode) {
137 case CM_ERASE:137 case CM_ERASE:
138 sti_putc(sticon_sti, car1, conp->vc_y, conp->vc_x);138 sti_putc(sticon_sti, car1, conp->state.y, conp->state.x);
139 break;139 break;
140 case CM_MOVE:140 case CM_MOVE:
141 case CM_DRAW:141 case CM_DRAW:
142 switch (conp->vc_cursor_type & 0x0f) {142 switch (CUR_SIZE(conp->vc_cursor_type)) {
143 case CUR_UNDERLINE:143 case CUR_UNDERLINE:
144 case CUR_LOWER_THIRD:144 case CUR_LOWER_THIRD:
145 case CUR_LOWER_HALF:145 case CUR_LOWER_HALF:
146 case CUR_TWO_THIRDS:146 case CUR_TWO_THIRDS:
147 case CUR_BLOCK:147 case CUR_BLOCK:
148 sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),148 sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
149 conp->vc_y, conp->vc_x);149 conp->state.y, conp->state.x);
150 break;150 break;
151 }151 }
152 break;152 break;
@@ -288,8 +288,10 @@ static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, · 135 unmodified lines
288 return ret;288 return ret;
289}289}
290 290
291static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens,291static u8 sticon_build_attr(struct vc_data *conp, u8 color,
292 u8 blink, u8 underline, u8 reverse, u8 italic)292 enum vc_intensity intens,
293 bool blink, bool underline, bool reverse,
294 bool italic)
293{295{
294 u8 attr = ((color & 0x70) >> 1) | ((color & 7));296 u8 attr = ((color & 0x70) >> 1) | ((color & 7));
295 297
drivers/video/console/vgacon.c+23−17
@@ -251,6 +251,10 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count) · 250 unmodified lines
251 p = (void *) (c->vc_origin + t * c->vc_size_row);251 p = (void *) (c->vc_origin + t * c->vc_size_row);
252 252
253 while (count--) {253 while (count--) {
254 if ((vgacon_scrollback_cur->tail + c->vc_size_row) >
255 vgacon_scrollback_cur->size)
256 vgacon_scrollback_cur->tail = 0;
257
254 scr_memcpyw(vgacon_scrollback_cur->data +258 scr_memcpyw(vgacon_scrollback_cur->data +
255 vgacon_scrollback_cur->tail,259 vgacon_scrollback_cur->tail,
256 p, c->vc_size_row);260 p, c->vc_size_row);
@@ -629,8 +633,10 @@ static void vgacon_deinit(struct vc_data *c) · 372 unmodified lines
629 con_set_default_unimap(c);633 con_set_default_unimap(c);
630}634}
631 635
632static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity,636static u8 vgacon_build_attr(struct vc_data *c, u8 color,
633 u8 blink, u8 underline, u8 reverse, u8 italic)637 enum vc_intensity intensity,
638 bool blink, bool underline, bool reverse,
639 bool italic)
634{640{
635 u8 attr = color;641 u8 attr = color;
636 642
@@ -639,7 +645,7 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, · 2 unmodified lines
639 attr = (attr & 0xF0) | c->vc_itcolor;645 attr = (attr & 0xF0) | c->vc_itcolor;
640 else if (underline)646 else if (underline)
641 attr = (attr & 0xf0) | c->vc_ulcolor;647 attr = (attr & 0xf0) | c->vc_ulcolor;
642 else if (intensity == 0)648 else if (intensity == VCI_HALF_BRIGHT)
643 attr = (attr & 0xf0) | c->vc_halfcolor;649 attr = (attr & 0xf0) | c->vc_halfcolor;
644 }650 }
645 if (reverse)651 if (reverse)
@@ -648,14 +654,14 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, · 2 unmodified lines
648 0x77);654 0x77);
649 if (blink)655 if (blink)
650 attr ^= 0x80;656 attr ^= 0x80;
651 if (intensity == 2)657 if (intensity == VCI_BOLD)
652 attr ^= 0x08;658 attr ^= 0x08;
653 if (!vga_can_do_color) {659 if (!vga_can_do_color) {
654 if (italic)660 if (italic)
655 attr = (attr & 0xF8) | 0x02;661 attr = (attr & 0xF8) | 0x02;
656 else if (underline)662 else if (underline)
657 attr = (attr & 0xf8) | 0x01;663 attr = (attr & 0xf8) | 0x01;
658 else if (intensity == 0)664 else if (intensity == VCI_HALF_BRIGHT)
659 attr = (attr & 0xf0) | 0x08;665 attr = (attr & 0xf0) | 0x08;
660 }666 }
661 return attr;667 return attr;
@@ -718,17 +724,17 @@ static void vgacon_cursor(struct vc_data *c, int mode) · 56 unmodified lines
718 case CM_ERASE:724 case CM_ERASE:
719 write_vga(14, (c->vc_pos - vga_vram_base) / 2);725 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
720 if (vga_video_type >= VIDEO_TYPE_VGAC)726 if (vga_video_type >= VIDEO_TYPE_VGAC)
721 vgacon_set_cursor_size(c->vc_x, 31, 30);727 vgacon_set_cursor_size(c->state.x, 31, 30);
722 else728 else
723 vgacon_set_cursor_size(c->vc_x, 31, 31);729 vgacon_set_cursor_size(c->state.x, 31, 31);
724 break;730 break;
725 731
726 case CM_MOVE:732 case CM_MOVE:
727 case CM_DRAW:733 case CM_DRAW:
728 write_vga(14, (c->vc_pos - vga_vram_base) / 2);734 write_vga(14, (c->vc_pos - vga_vram_base) / 2);
729 switch (c->vc_cursor_type & 0x0f) {735 switch (CUR_SIZE(c->vc_cursor_type)) {
730 case CUR_UNDERLINE:736 case CUR_UNDERLINE:
731 vgacon_set_cursor_size(c->vc_x,737 vgacon_set_cursor_size(c->state.x,
732 c->vc_font.height -738 c->vc_font.height -
733 (c->vc_font.height <739 (c->vc_font.height <
734 10 ? 2 : 3),740 10 ? 2 : 3),
@@ -737,21 +743,21 @@ static void vgacon_cursor(struct vc_data *c, int mode) · 2 unmodified lines
737 10 ? 1 : 2));743 10 ? 1 : 2));
738 break;744 break;
739 case CUR_TWO_THIRDS:745 case CUR_TWO_THIRDS:
740 vgacon_set_cursor_size(c->vc_x,746 vgacon_set_cursor_size(c->state.x,
741 c->vc_font.height / 3,747 c->vc_font.height / 3,
742 c->vc_font.height -748 c->vc_font.height -
743 (c->vc_font.height <749 (c->vc_font.height <
744 10 ? 1 : 2));750 10 ? 1 : 2));
745 break;751 break;
746 case CUR_LOWER_THIRD:752 case CUR_LOWER_THIRD:
747 vgacon_set_cursor_size(c->vc_x,753 vgacon_set_cursor_size(c->state.x,
748 (c->vc_font.height * 2) / 3,754 (c->vc_font.height * 2) / 3,
749 c->vc_font.height -755 c->vc_font.height -
750 (c->vc_font.height <756 (c->vc_font.height <
751 10 ? 1 : 2));757 10 ? 1 : 2));
752 break;758 break;
753 case CUR_LOWER_HALF:759 case CUR_LOWER_HALF:
754 vgacon_set_cursor_size(c->vc_x,760 vgacon_set_cursor_size(c->state.x,
755 c->vc_font.height / 2,761 c->vc_font.height / 2,
756 c->vc_font.height -762 c->vc_font.height -
757 (c->vc_font.height <763 (c->vc_font.height <
@@ -759,12 +765,12 @@ static void vgacon_cursor(struct vc_data *c, int mode) · 1 unmodified line
759 break;765 break;
760 case CUR_NONE:766 case CUR_NONE:
761 if (vga_video_type >= VIDEO_TYPE_VGAC)767 if (vga_video_type >= VIDEO_TYPE_VGAC)
762 vgacon_set_cursor_size(c->vc_x, 31, 30);768 vgacon_set_cursor_size(c->state.x, 31, 30);
763 else769 else
764 vgacon_set_cursor_size(c->vc_x, 31, 31);770 vgacon_set_cursor_size(c->state.x, 31, 31);
765 break;771 break;
766 default:772 default:
767 vgacon_set_cursor_size(c->vc_x, 1,773 vgacon_set_cursor_size(c->state.x, 1,
768 c->vc_font.height);774 c->vc_font.height);
769 break;775 break;
770 }776 }
@@ -1352,8 +1358,8 @@ static void vgacon_save_screen(struct vc_data *c) · 581 unmodified lines
1352 * console initialization routines.1358 * console initialization routines.
1353 */1359 */
1354 vga_bootup_console = 1;1360 vga_bootup_console = 1;
1355 c->vc_x = screen_info.orig_x;1361 c->state.x = screen_info.orig_x;
1356 c->vc_y = screen_info.orig_y;1362 c->state.y = screen_info.orig_y;
1357 }1363 }
1358 1364
1359 /* We can't copy in more than the size of the video buffer,1365 /* We can't copy in more than the size of the video buffer,
drivers/video/fbdev/core/bitblit.c+5−5
@@ -240,8 +240,8 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 239 unmodified lines
240 struct fbcon_ops *ops = info->fbcon_par;240 struct fbcon_ops *ops = info->fbcon_par;
241 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;241 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
242 int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;242 int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;
243 int y = real_y(ops->p, vc->vc_y);243 int y = real_y(ops->p, vc->state.y);
244 int attribute, use_sw = (vc->vc_cursor_type & 0x10);244 int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
245 int err = 1;245 int err = 1;
246 char *src;246 char *src;
247 247
@@ -286,10 +286,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 38 unmodified lines
286 cursor.set |= FB_CUR_SETCMAP;286 cursor.set |= FB_CUR_SETCMAP;
287 }287 }
288 288
289 if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->vc_x)) ||289 if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) ||
290 (ops->cursor_state.image.dy != (vc->vc_font.height * y)) ||290 (ops->cursor_state.image.dy != (vc->vc_font.height * y)) ||
291 ops->cursor_reset) {291 ops->cursor_reset) {
292 ops->cursor_state.image.dx = vc->vc_font.width * vc->vc_x;292 ops->cursor_state.image.dx = vc->vc_font.width * vc->state.x;
293 ops->cursor_state.image.dy = vc->vc_font.height * y;293 ops->cursor_state.image.dy = vc->vc_font.height * y;
294 cursor.set |= FB_CUR_SETPOS;294 cursor.set |= FB_CUR_SETPOS;
295 }295 }
@@ -325,7 +325,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 29 unmodified lines
325 ops->p->cursor_shape = vc->vc_cursor_type;325 ops->p->cursor_shape = vc->vc_cursor_type;
326 cursor.set |= FB_CUR_SETSHAPE;326 cursor.set |= FB_CUR_SETSHAPE;
327 327
328 switch (ops->p->cursor_shape & CUR_HWMASK) {328 switch (CUR_SIZE(ops->p->cursor_shape)) {
329 case CUR_NONE:329 case CUR_NONE:
330 cur_height = 0;330 cur_height = 0;
331 break;331 break;
drivers/video/fbdev/core/fbcon.c+5−5
@@ -655,11 +655,11 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, · 654 unmodified lines
655 }655 }
656 if (!save) {656 if (!save) {
657 int lines;657 int lines;
658 if (vc->vc_y + logo_lines >= rows)658 if (vc->state.y + logo_lines >= rows)
659 lines = rows - vc->vc_y - 1;659 lines = rows - vc->state.y - 1;
660 else660 else
661 lines = logo_lines;661 lines = logo_lines;
662 vc->vc_y += lines;662 vc->state.y += lines;
663 vc->vc_pos += lines * vc->vc_size_row;663 vc->vc_pos += lines * vc->vc_size_row;
664 }664 }
665 }665 }
@@ -677,7 +677,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, · 11 unmodified lines
677 vc->vc_size_row *677 vc->vc_size_row *
678 rows);678 rows);
679 scr_memcpyw(q, save, array3_size(logo_lines, new_cols, 2));679 scr_memcpyw(q, save, array3_size(logo_lines, new_cols, 2));
680 vc->vc_y += logo_lines;680 vc->state.y += logo_lines;
681 vc->vc_pos += logo_lines * vc->vc_size_row;681 vc->vc_pos += logo_lines * vc->vc_size_row;
682 kfree(save);682 kfree(save);
683 }683 }
@@ -1393,7 +1393,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode) · 709 unmodified lines
1393 if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)1393 if (fbcon_is_inactive(vc, info) || vc->vc_deccm != 1)
1394 return;1394 return;
1395 1395
1396 if (vc->vc_cursor_type & 0x10)1396 if (vc->vc_cursor_type & CUR_SW)
1397 fbcon_del_cursor_timer(info);1397 fbcon_del_cursor_timer(info);
1398 else1398 else
1399 fbcon_add_cursor_timer(info);1399 fbcon_add_cursor_timer(info);
drivers/video/fbdev/core/fbcon_ccw.c+4−4
@@ -225,8 +225,8 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 224 unmodified lines
225 struct fbcon_ops *ops = info->fbcon_par;225 struct fbcon_ops *ops = info->fbcon_par;
226 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;226 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
227 int w = (vc->vc_font.height + 7) >> 3, c;227 int w = (vc->vc_font.height + 7) >> 3, c;
228 int y = real_y(ops->p, vc->vc_y);228 int y = real_y(ops->p, vc->state.y);
229 int attribute, use_sw = (vc->vc_cursor_type & 0x10);229 int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
230 int err = 1, dx, dy;230 int err = 1, dx, dy;
231 char *src;231 char *src;
232 u32 vyres = GETVYRES(ops->p->scrollmode, info);232 u32 vyres = GETVYRES(ops->p->scrollmode, info);
@@ -284,7 +284,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 51 unmodified lines
284 }284 }
285 285
286 dx = y * vc->vc_font.height;286 dx = y * vc->vc_font.height;
287 dy = vyres - ((vc->vc_x + 1) * vc->vc_font.width);287 dy = vyres - ((vc->state.x + 1) * vc->vc_font.width);
288 288
289 if (ops->cursor_state.image.dx != dx ||289 if (ops->cursor_state.image.dx != dx ||
290 ops->cursor_state.image.dy != dy ||290 ops->cursor_state.image.dy != dy ||
@@ -325,7 +325,7 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 34 unmodified lines
325 ops->p->cursor_shape = vc->vc_cursor_type;325 ops->p->cursor_shape = vc->vc_cursor_type;
326 cursor.set |= FB_CUR_SETSHAPE;326 cursor.set |= FB_CUR_SETSHAPE;
327 327
328 switch (ops->p->cursor_shape & CUR_HWMASK) {328 switch (CUR_SIZE(ops->p->cursor_shape)) {
329 case CUR_NONE:329 case CUR_NONE:
330 cur_height = 0;330 cur_height = 0;
331 break;331 break;
drivers/video/fbdev/core/fbcon_cw.c+4−4
@@ -208,8 +208,8 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 207 unmodified lines
208 struct fbcon_ops *ops = info->fbcon_par;208 struct fbcon_ops *ops = info->fbcon_par;
209 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;209 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
210 int w = (vc->vc_font.height + 7) >> 3, c;210 int w = (vc->vc_font.height + 7) >> 3, c;
211 int y = real_y(ops->p, vc->vc_y);211 int y = real_y(ops->p, vc->state.y);
212 int attribute, use_sw = (vc->vc_cursor_type & 0x10);212 int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
213 int err = 1, dx, dy;213 int err = 1, dx, dy;
214 char *src;214 char *src;
215 u32 vxres = GETVXRES(ops->p->scrollmode, info);215 u32 vxres = GETVXRES(ops->p->scrollmode, info);
@@ -267,7 +267,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 51 unmodified lines
267 }267 }
268 268
269 dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height);269 dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height);
270 dy = vc->vc_x * vc->vc_font.width;270 dy = vc->state.x * vc->vc_font.width;
271 271
272 if (ops->cursor_state.image.dx != dx ||272 if (ops->cursor_state.image.dx != dx ||
273 ops->cursor_state.image.dy != dy ||273 ops->cursor_state.image.dy != dy ||
@@ -308,7 +308,7 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 34 unmodified lines
308 ops->p->cursor_shape = vc->vc_cursor_type;308 ops->p->cursor_shape = vc->vc_cursor_type;
309 cursor.set |= FB_CUR_SETSHAPE;309 cursor.set |= FB_CUR_SETSHAPE;
310 310
311 switch (ops->p->cursor_shape & CUR_HWMASK) {311 switch (CUR_SIZE(ops->p->cursor_shape)) {
312 case CUR_NONE:312 case CUR_NONE:
313 cur_height = 0;313 cur_height = 0;
314 break;314 break;
drivers/video/fbdev/core/fbcon_ud.c+4−4
@@ -255,8 +255,8 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 254 unmodified lines
255 struct fbcon_ops *ops = info->fbcon_par;255 struct fbcon_ops *ops = info->fbcon_par;
256 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;256 unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
257 int w = (vc->vc_font.width + 7) >> 3, c;257 int w = (vc->vc_font.width + 7) >> 3, c;
258 int y = real_y(ops->p, vc->vc_y);258 int y = real_y(ops->p, vc->state.y);
259 int attribute, use_sw = (vc->vc_cursor_type & 0x10);259 int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
260 int err = 1, dx, dy;260 int err = 1, dx, dy;
261 char *src;261 char *src;
262 u32 vyres = GETVYRES(ops->p->scrollmode, info);262 u32 vyres = GETVYRES(ops->p->scrollmode, info);
@@ -315,7 +315,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 52 unmodified lines
315 }315 }
316 316
317 dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height);317 dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height);
318 dx = vxres - ((vc->vc_x * vc->vc_font.width) + vc->vc_font.width);318 dx = vxres - ((vc->state.x * vc->vc_font.width) + vc->vc_font.width);
319 319
320 if (ops->cursor_state.image.dx != dx ||320 if (ops->cursor_state.image.dx != dx ||
321 ops->cursor_state.image.dy != dy ||321 ops->cursor_state.image.dy != dy ||
@@ -348,7 +348,7 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 26 unmodified lines
348 ops->p->cursor_shape = vc->vc_cursor_type;348 ops->p->cursor_shape = vc->vc_cursor_type;
349 cursor.set |= FB_CUR_SETSHAPE;349 cursor.set |= FB_CUR_SETSHAPE;
350 350
351 switch (ops->p->cursor_shape & CUR_HWMASK) {351 switch (CUR_SIZE(ops->p->cursor_shape)) {
352 case CUR_NONE:352 case CUR_NONE:
353 cur_height = 0;353 cur_height = 0;
354 break;354 break;
drivers/video/fbdev/core/tileblit.c+3−3
@@ -83,10 +83,10 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, int mode, · 82 unmodified lines
83 int softback_lines, int fg, int bg)83 int softback_lines, int fg, int bg)
84{84{
85 struct fb_tilecursor cursor;85 struct fb_tilecursor cursor;
86 int use_sw = (vc->vc_cursor_type & 0x10);86 int use_sw = vc->vc_cursor_type & CUR_SW;
87 87
88 cursor.sx = vc->vc_x;88 cursor.sx = vc->state.x;
89 cursor.sy = vc->vc_y;89 cursor.sy = vc->state.y;
90 cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1;90 cursor.mode = (mode == CM_ERASE || use_sw) ? 0 : 1;
91 cursor.fg = fg;91 cursor.fg = fg;
92 cursor.bg = bg;92 cursor.bg = bg;
include/linux/console.h+5−8
@@ -24,17 +24,13 @@ struct module; · 23 unmodified lines
24struct tty_struct;24struct tty_struct;
25struct notifier_block;25struct notifier_block;
26 26
27/*
28 * this is what the terminal answers to a ESC-Z or csi0c query.
29 */
30#define VT100ID "\033[?1;2c"
31#define VT102ID "\033[?6c"
32
33enum con_scroll {27enum con_scroll {
34 SM_UP,28 SM_UP,
35 SM_DOWN,29 SM_DOWN,
36};30};
37 31
32enum vc_intensity;
33
38/**34/**
39 * struct consw - callbacks for consoles35 * struct consw - callbacks for consoles
40 *36 *
@@ -74,8 +70,9 @@ struct consw { · 33 unmodified lines
74 void (*con_scrolldelta)(struct vc_data *vc, int lines);70 void (*con_scrolldelta)(struct vc_data *vc, int lines);
75 int (*con_set_origin)(struct vc_data *vc);71 int (*con_set_origin)(struct vc_data *vc);
76 void (*con_save_screen)(struct vc_data *vc);72 void (*con_save_screen)(struct vc_data *vc);
77 u8 (*con_build_attr)(struct vc_data *vc, u8 color, u8 intensity,73 u8 (*con_build_attr)(struct vc_data *vc, u8 color,
78 u8 blink, u8 underline, u8 reverse, u8 italic);74 enum vc_intensity intensity,
75 bool blink, bool underline, bool reverse, bool italic);
79 void (*con_invert_region)(struct vc_data *vc, u16 *p, int count);76 void (*con_invert_region)(struct vc_data *vc, u16 *p, int count);
80 u16 *(*con_screen_pos)(struct vc_data *vc, int offset);77 u16 *(*con_screen_pos)(struct vc_data *vc, int offset);
81 unsigned long (*con_getxy)(struct vc_data *vc, unsigned long position,78 unsigned long (*con_getxy)(struct vc_data *vc, unsigned long position,
include/linux/console_struct.h+58−35
@@ -21,6 +21,43 @@ struct uni_pagedir; · 20 unmodified lines
21struct uni_screen;21struct uni_screen;
22 22
23#define NPAR 1623#define NPAR 16
24#define VC_TABSTOPS_COUNT 256U
25
26enum vc_intensity {
27 VCI_HALF_BRIGHT,
28 VCI_NORMAL,
29 VCI_BOLD,
30 VCI_MASK = 0x3,
31};
32
33/**
34 * struct vc_state -- state of a VC
35 * @x: cursor's x-position
36 * @y: cursor's y-position
37 * @color: foreground & background colors
38 * @Gx_charset: what's G0/G1 slot set to (like GRAF_MAP, LAT1_MAP)
39 * @charset: what character set to use (0=G0 or 1=G1)
40 * @intensity: see enum vc_intensity for values
41 * @reverse: reversed foreground/background colors
42 *
43 * These members are defined separately from struct vc_data as we save &
44 * restore them at times.
45 */
46struct vc_state {
47 unsigned int x, y;
48
49 unsigned char color;
50
51 unsigned char Gx_charset[2];
52 unsigned int charset : 1;
53
54 /* attribute flags */
55 enum vc_intensity intensity;
56 bool italic;
57 bool underline;
58 bool blink;
59 bool reverse;
60};
24 61
25/*62/*
26 * Example: vc_data of a console that was scrolled 3 lines down.63 * Example: vc_data of a console that was scrolled 3 lines down.
@@ -57,6 +94,8 @@ struct uni_screen; · 30 unmodified lines
57struct vc_data {94struct vc_data {
58 struct tty_port port; /* Upper level data */95 struct tty_port port; /* Upper level data */
59 96
97 struct vc_state state, saved_state;
98
60 unsigned short vc_num; /* Console number */99 unsigned short vc_num; /* Console number */
61 unsigned int vc_cols; /* [#] Console size */100 unsigned int vc_cols; /* [#] Console size */
62 unsigned int vc_rows;101 unsigned int vc_rows;
@@ -73,8 +112,6 @@ struct vc_data { · 10 unmodified lines
73 /* attributes for all characters on screen */112 /* attributes for all characters on screen */
74 unsigned char vc_attr; /* Current attributes */113 unsigned char vc_attr; /* Current attributes */
75 unsigned char vc_def_color; /* Default colors */114 unsigned char vc_def_color; /* Default colors */
76 unsigned char vc_color; /* Foreground & background */
77 unsigned char vc_s_color; /* Saved foreground & background */
78 unsigned char vc_ulcolor; /* Color for underline mode */115 unsigned char vc_ulcolor; /* Color for underline mode */
79 unsigned char vc_itcolor;116 unsigned char vc_itcolor;
80 unsigned char vc_halfcolor; /* Color for half intensity mode */117 unsigned char vc_halfcolor; /* Color for half intensity mode */
@@ -82,8 +119,6 @@ struct vc_data { · 1 unmodified line
82 unsigned int vc_cursor_type;119 unsigned int vc_cursor_type;
83 unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */120 unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */
84 unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */121 unsigned short vc_s_complement_mask; /* Saved mouse pointer mask */
85 unsigned int vc_x, vc_y; /* Cursor position */
86 unsigned int vc_saved_x, vc_saved_y;
87 unsigned long vc_pos; /* Cursor address */122 unsigned long vc_pos; /* Cursor address */
88 /* fonts */ 123 /* fonts */
89 unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */124 unsigned short vc_hi_font_mask; /* [#] Attribute set for upper 256 chars of font or 0 if not supported */
@@ -98,8 +133,6 @@ struct vc_data { · 8 unmodified lines
98 int vt_newvt;133 int vt_newvt;
99 wait_queue_head_t paste_wait;134 wait_queue_head_t paste_wait;
100 /* mode flags */135 /* mode flags */
101 unsigned int vc_charset : 1; /* Character set G0 / G1 */
102 unsigned int vc_s_charset : 1; /* Saved character set */
103 unsigned int vc_disp_ctrl : 1; /* Display chars < 32? */136 unsigned int vc_disp_ctrl : 1; /* Display chars < 32? */
104 unsigned int vc_toggle_meta : 1; /* Toggle high bit? */137 unsigned int vc_toggle_meta : 1; /* Toggle high bit? */
105 unsigned int vc_decscnm : 1; /* Screen Mode */138 unsigned int vc_decscnm : 1; /* Screen Mode */
@@ -107,17 +140,6 @@ struct vc_data { · 1 unmodified line
107 unsigned int vc_decawm : 1; /* Autowrap Mode */140 unsigned int vc_decawm : 1; /* Autowrap Mode */
108 unsigned int vc_deccm : 1; /* Cursor Visible */141 unsigned int vc_deccm : 1; /* Cursor Visible */
109 unsigned int vc_decim : 1; /* Insert Mode */142 unsigned int vc_decim : 1; /* Insert Mode */
110 /* attribute flags */
111 unsigned int vc_intensity : 2; /* 0=half-bright, 1=normal, 2=bold */
112 unsigned int vc_italic:1;
113 unsigned int vc_underline : 1;
114 unsigned int vc_blink : 1;
115 unsigned int vc_reverse : 1;
116 unsigned int vc_s_intensity : 2; /* saved rendition */
117 unsigned int vc_s_italic:1;
118 unsigned int vc_s_underline : 1;
119 unsigned int vc_s_blink : 1;
120 unsigned int vc_s_reverse : 1;
121 /* misc */143 /* misc */
122 unsigned int vc_priv : 3;144 unsigned int vc_priv : 3;
123 unsigned int vc_need_wrap : 1;145 unsigned int vc_need_wrap : 1;
@@ -126,13 +148,9 @@ struct vc_data { · 2 unmodified lines
126 unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */148 unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */
127 unsigned char vc_utf_count;149 unsigned char vc_utf_count;
128 int vc_utf_char;150 int vc_utf_char;
129 unsigned int vc_tab_stop[8]; /* Tab stops. 256 columns. */151 DECLARE_BITMAP(vc_tab_stop, VC_TABSTOPS_COUNT); /* Tab stops. 256 columns. */
130 unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */152 unsigned char vc_palette[16*3]; /* Colour palette for VGA+ */
131 unsigned short * vc_translate;153 unsigned short * vc_translate;
132 unsigned char vc_G0_charset;
133 unsigned char vc_G1_charset;
134 unsigned char vc_saved_G0;
135 unsigned char vc_saved_G1;
136 unsigned int vc_resize_user; /* resize request from user */154 unsigned int vc_resize_user; /* resize request from user */
137 unsigned int vc_bell_pitch; /* Console bell pitch */155 unsigned int vc_bell_pitch; /* Console bell pitch */
138 unsigned int vc_bell_duration; /* Console bell duration */156 unsigned int vc_bell_duration; /* Console bell duration */
@@ -149,24 +167,29 @@ struct vc { · 10 unmodified lines
149 struct work_struct SAK_work;167 struct work_struct SAK_work;
150 168
151 /* might add scrmem, kbd at some time,169 /* might add scrmem, kbd at some time,
152 to have everything in one place - the disadvantage170 to have everything in one place */
153 would be that vc_cons etc can no longer be static */
154};171};
155 172
156extern struct vc vc_cons [MAX_NR_CONSOLES];173extern struct vc vc_cons [MAX_NR_CONSOLES];
157extern void vc_SAK(struct work_struct *work);174extern void vc_SAK(struct work_struct *work);
158 175
159#define CUR_DEF 0176#define CUR_MAKE(size, change, set) ((size) | ((change) << 8) | \
160#define CUR_NONE 1177 ((set) << 16))
161#define CUR_UNDERLINE 2178#define CUR_SIZE(c) ((c) & 0x00000f)
162#define CUR_LOWER_THIRD 3179# define CUR_DEF 0
163#define CUR_LOWER_HALF 4180# define CUR_NONE 1
164#define CUR_TWO_THIRDS 5181# define CUR_UNDERLINE 2
165#define CUR_BLOCK 6182# define CUR_LOWER_THIRD 3
166#define CUR_HWMASK 0x0f183# define CUR_LOWER_HALF 4
167#define CUR_SWMASK 0xfff0184# define CUR_TWO_THIRDS 5
168 185# define CUR_BLOCK 6
169#define CUR_DEFAULT CUR_UNDERLINE186#define CUR_SW 0x000010
187#define CUR_ALWAYS_BG 0x000020
188#define CUR_INVERT_FG_BG 0x000040
189#define CUR_FG 0x000700
190#define CUR_BG 0x007000
191#define CUR_CHANGE(c) ((c) & 0x00ff00)
192#define CUR_SET(c) (((c) & 0xff0000) >> 8)
170 193
171bool con_is_visible(const struct vc_data *vc);194bool con_is_visible(const struct vc_data *vc);
172 195
include/linux/serial_8250.h+2−0
@@ -155,6 +155,8 @@ extern int early_serial_setup(struct uart_port *port); · 154 unmodified lines
155 155
156extern int early_serial8250_setup(struct earlycon_device *device,156extern int early_serial8250_setup(struct earlycon_device *device,
157 const char *options);157 const char *options);
158extern void serial8250_update_uartclk(struct uart_port *port,
159 unsigned int uartclk);
158extern void serial8250_do_set_termios(struct uart_port *port,160extern void serial8250_do_set_termios(struct uart_port *port,
159 struct ktermios *termios, struct ktermios *old);161 struct ktermios *termios, struct ktermios *old);
160extern void serial8250_do_set_ldisc(struct uart_port *port,162extern void serial8250_do_set_ldisc(struct uart_port *port,
include/linux/serial_core.h+1−1
@@ -10,7 +10,6 @@ · 9 unmodified lines
10#include <linux/bitops.h>10#include <linux/bitops.h>
11#include <linux/compiler.h>11#include <linux/compiler.h>
12#include <linux/console.h>12#include <linux/console.h>
13#include <linux/gpio/consumer.h>
14#include <linux/interrupt.h>13#include <linux/interrupt.h>
15#include <linux/circ_buf.h>14#include <linux/circ_buf.h>
16#include <linux/spinlock.h>15#include <linux/spinlock.h>
@@ -30,6 +29,7 @@ · 13 unmodified lines
30struct uart_port;29struct uart_port;
31struct serial_struct;30struct serial_struct;
32struct device;31struct device;
32struct gpio_desc;
33 33
34/*34/*
35 * This structure describes all the operations that can be done on the35 * This structure describes all the operations that can be done on the
include/linux/vt_kern.h+0−3
@@ -74,8 +74,6 @@ int con_set_default_unimap(struct vc_data *vc); · 73 unmodified lines
74void con_free_unimap(struct vc_data *vc);74void con_free_unimap(struct vc_data *vc);
75int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);75int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc);
76 76
77#define vc_translate(vc, c) ((vc)->vc_translate[(c) | \
78 ((vc)->vc_toggle_meta ? 0x80 : 0)])
79#else77#else
80static inline int con_set_trans_old(unsigned char __user *table)78static inline int con_set_trans_old(unsigned char __user *table)
81{79{
@@ -124,7 +122,6 @@ int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc) · 42 unmodified lines
124 return 0;122 return 0;
125}123}
126 124
127#define vc_translate(vc, c) (c)
128#endif125#endif
129 126
130/* vt.c */127/* vt.c */
include/uapi/linux/serial_core.h+0−14
@@ -26,20 +26,6 @@ · 25 unmodified lines
26/*26/*
27 * The type definitions. These are from Ted Ts'o's serial.h27 * The type definitions. These are from Ted Ts'o's serial.h
28 */28 */
29#define PORT_UNKNOWN 0
30#define PORT_8250 1
31#define PORT_16450 2
32#define PORT_16550 3
33#define PORT_16550A 4
34#define PORT_CIRRUS 5
35#define PORT_16650 6
36#define PORT_16650V2 7
37#define PORT_16750 8
38#define PORT_STARTECH 9
39#define PORT_16C950 10
40#define PORT_16654 11
41#define PORT_16850 12
42#define PORT_RSA 13
43#define PORT_NS16550A 1429#define PORT_NS16550A 14
44#define PORT_XSCALE 1530#define PORT_XSCALE 15
45#define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */31#define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */