diff options
author | Jason Wessel <jason.wessel@windriver.com> | 2008-04-17 14:05:37 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-04-17 14:05:37 -0400 |
commit | f2d937f3bf00665ccf048b3b6616ef95859b0945 (patch) | |
tree | 6136ded0706be0d39a09a0a912e8f79a4ab63322 /drivers/serial/8250.c | |
parent | dc7d552705215ac50a0617fcf51bb9c736255b8e (diff) |
consoles: polling support, kgdboc
polled console handling support, to access a console in an irq-less
way while in debug or irq context.
absolutely zero impact as long as CONFIG_CONSOLE_POLL is disabled.
(which is the default)
[ jan.kiszka@siemens.com: lots of cleanups ]
[ mingo@elte.hu: redesign, splitups, cleanups. ]
Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Jan Kiszka <jan.kiszka@web.de>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/serial/8250.c')
-rw-r--r-- | drivers/serial/8250.c | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 77f7a7f0646e..96a585e1cee8 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -1740,6 +1740,60 @@ static inline void wait_for_xmitr(struct uart_8250_port *up, int bits) | |||
1740 | } | 1740 | } |
1741 | } | 1741 | } |
1742 | 1742 | ||
1743 | #ifdef CONFIG_CONSOLE_POLL | ||
1744 | /* | ||
1745 | * Console polling routines for writing and reading from the uart while | ||
1746 | * in an interrupt or debug context. | ||
1747 | */ | ||
1748 | |||
1749 | static int serial8250_get_poll_char(struct uart_port *port) | ||
1750 | { | ||
1751 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
1752 | unsigned char lsr = serial_inp(up, UART_LSR); | ||
1753 | |||
1754 | while (!(lsr & UART_LSR_DR)) | ||
1755 | lsr = serial_inp(up, UART_LSR); | ||
1756 | |||
1757 | return serial_inp(up, UART_RX); | ||
1758 | } | ||
1759 | |||
1760 | |||
1761 | static void serial8250_put_poll_char(struct uart_port *port, | ||
1762 | unsigned char c) | ||
1763 | { | ||
1764 | unsigned int ier; | ||
1765 | struct uart_8250_port *up = (struct uart_8250_port *)port; | ||
1766 | |||
1767 | /* | ||
1768 | * First save the IER then disable the interrupts | ||
1769 | */ | ||
1770 | ier = serial_in(up, UART_IER); | ||
1771 | if (up->capabilities & UART_CAP_UUE) | ||
1772 | serial_out(up, UART_IER, UART_IER_UUE); | ||
1773 | else | ||
1774 | serial_out(up, UART_IER, 0); | ||
1775 | |||
1776 | wait_for_xmitr(up, BOTH_EMPTY); | ||
1777 | /* | ||
1778 | * Send the character out. | ||
1779 | * If a LF, also do CR... | ||
1780 | */ | ||
1781 | serial_out(up, UART_TX, c); | ||
1782 | if (c == 10) { | ||
1783 | wait_for_xmitr(up, BOTH_EMPTY); | ||
1784 | serial_out(up, UART_TX, 13); | ||
1785 | } | ||
1786 | |||
1787 | /* | ||
1788 | * Finally, wait for transmitter to become empty | ||
1789 | * and restore the IER | ||
1790 | */ | ||
1791 | wait_for_xmitr(up, BOTH_EMPTY); | ||
1792 | serial_out(up, UART_IER, ier); | ||
1793 | } | ||
1794 | |||
1795 | #endif /* CONFIG_CONSOLE_POLL */ | ||
1796 | |||
1743 | static int serial8250_startup(struct uart_port *port) | 1797 | static int serial8250_startup(struct uart_port *port) |
1744 | { | 1798 | { |
1745 | struct uart_8250_port *up = (struct uart_8250_port *)port; | 1799 | struct uart_8250_port *up = (struct uart_8250_port *)port; |
@@ -2386,6 +2440,10 @@ static struct uart_ops serial8250_pops = { | |||
2386 | .request_port = serial8250_request_port, | 2440 | .request_port = serial8250_request_port, |
2387 | .config_port = serial8250_config_port, | 2441 | .config_port = serial8250_config_port, |
2388 | .verify_port = serial8250_verify_port, | 2442 | .verify_port = serial8250_verify_port, |
2443 | #ifdef CONFIG_CONSOLE_POLL | ||
2444 | .poll_get_char = serial8250_get_poll_char, | ||
2445 | .poll_put_char = serial8250_put_poll_char, | ||
2446 | #endif | ||
2389 | }; | 2447 | }; |
2390 | 2448 | ||
2391 | static struct uart_8250_port serial8250_ports[UART_NR]; | 2449 | static struct uart_8250_port serial8250_ports[UART_NR]; |