diff options
-rw-r--r-- | Documentation/VGA-softcursor.txt | 12 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_fintek.c | 231 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_lpss.c | 7 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_of.c | 2 | ||||
-rw-r--r-- | drivers/tty/serial/8250/8250_pxa.c | 190 | ||||
-rw-r--r-- | drivers/tty/serial/8250/Kconfig | 10 | ||||
-rw-r--r-- | drivers/tty/serial/8250/Makefile | 1 | ||||
-rw-r--r-- | drivers/tty/serial/Kconfig | 17 | ||||
-rw-r--r-- | drivers/tty/serial/Makefile | 7 | ||||
-rw-r--r-- | drivers/tty/serial/amba-pl011.c | 55 | ||||
-rw-r--r-- | drivers/tty/serial/fsl_lpuart.c | 64 | ||||
-rw-r--r-- | drivers/tty/serial/pxa.c | 4 | ||||
-rw-r--r-- | drivers/tty/serial/sc16is7xx.c | 2 | ||||
-rw-r--r-- | drivers/tty/vt/vt.c | 85 | ||||
-rw-r--r-- | drivers/usb/misc/sisusbvga/sisusb_con.c | 55 | ||||
-rw-r--r-- | drivers/video/console/fbcon.c | 18 | ||||
-rw-r--r-- | drivers/video/console/mdacon.c | 7 | ||||
-rw-r--r-- | drivers/video/console/newport_con.c | 8 | ||||
-rw-r--r-- | drivers/video/console/sticon.c | 7 | ||||
-rw-r--r-- | drivers/video/console/vgacon.c | 133 | ||||
-rw-r--r-- | include/linux/console.h | 16 | ||||
-rw-r--r-- | include/linux/vt_kern.h | 2 |
22 files changed, 657 insertions, 276 deletions
diff --git a/Documentation/VGA-softcursor.txt b/Documentation/VGA-softcursor.txt index 70acfbf399eb..2ea8968b64a6 100644 --- a/Documentation/VGA-softcursor.txt +++ b/Documentation/VGA-softcursor.txt @@ -2,13 +2,11 @@ Software cursor for VGA by Pavel Machek <[email protected]> ======================= and Martin Mares <[email protected]> Linux now has some ability to manipulate cursor appearance. Normally, you -can set the size of hardware cursor (and also work around some ugly bugs in -those miserable Trident cards--see #define TRIDENT_GLITCH in drivers/video/ -vgacon.c). You can now play a few new tricks: you can make your cursor look -like a non-blinking red block, make it inverse background of the character it's -over or to highlight that character and still choose whether the original -hardware cursor should remain visible or not. There may be other things I have -never thought of. +can set the size of hardware cursor. You can now play a few new tricks: you +can make your cursor look like a non-blinking red block, make it inverse +background of the character it's over or to highlight that character and still +choose whether the original hardware cursor should remain visible or not. +There may be other things I have never thought of. The cursor appearance is controlled by a "<ESC>[?1;2;3c" escape sequence where 1, 2 and 3 are parameters described below. If you omit any of them, diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c index 0facc789fe7d..b67e7a544935 100644 --- a/drivers/tty/serial/8250/8250_fintek.c +++ b/drivers/tty/serial/8250/8250_fintek.c @@ -21,8 +21,11 @@ #define EXIT_KEY 0xAA #define CHIP_ID1 0x20 #define CHIP_ID2 0x21 -#define CHIP_ID_0 0x1602 -#define CHIP_ID_1 0x0501 +#define CHIP_ID_F81865 0x0407 +#define CHIP_ID_F81866 0x1010 +#define CHIP_ID_F81216AD 0x1602 +#define CHIP_ID_F81216H 0x0501 +#define CHIP_ID_F81216 0x0802 #define VENDOR_ID1 0x23 #define VENDOR_ID1_VAL 0x19 #define VENDOR_ID2 0x24 @@ -43,12 +46,60 @@ #define RXW4C_IRA BIT(3) #define TXW4C_IRA BIT(2) +#define FIFO_CTRL 0xF6 +#define FIFO_MODE_MASK (BIT(1) | BIT(0)) +#define FIFO_MODE_128 (BIT(1) | BIT(0)) +#define RXFTHR_MODE_MASK (BIT(5) | BIT(4)) +#define RXFTHR_MODE_4X BIT(5) + +#define F81216_LDN_LOW 0x0 +#define F81216_LDN_HIGH 0x4 + +/* + * F81866 registers + * + * The IRQ setting mode of F81866 is not the same with F81216 series. + * Level/Low: IRQ_MODE0:0, IRQ_MODE1:0 + * Edge/High: IRQ_MODE0:1, IRQ_MODE1:0 + */ +#define F81866_IRQ_MODE 0xf0 +#define F81866_IRQ_SHARE BIT(0) +#define F81866_IRQ_MODE0 BIT(1) + +#define F81866_FIFO_CTRL FIFO_CTRL +#define F81866_IRQ_MODE1 BIT(3) + +#define F81866_LDN_LOW 0x10 +#define F81866_LDN_HIGH 0x16 + struct fintek_8250 { + u16 pid; u16 base_port; u8 index; u8 key; }; +static u8 sio_read_reg(struct fintek_8250 *pdata, u8 reg) +{ + outb(reg, pdata->base_port + ADDR_PORT); + return inb(pdata->base_port + DATA_PORT); +} + +static void sio_write_reg(struct fintek_8250 *pdata, u8 reg, u8 data) +{ + outb(reg, pdata->base_port + ADDR_PORT); + outb(data, pdata->base_port + DATA_PORT); +} + +static void sio_write_mask_reg(struct fintek_8250 *pdata, u8 reg, u8 mask, + u8 data) +{ + u8 tmp; + + tmp = (sio_read_reg(pdata, reg) & ~mask) | (mask & data); + sio_write_reg(pdata, reg, tmp); +} + static int fintek_8250_enter_key(u16 base_port, u8 key) { if (!request_muxed_region(base_port, 2, "8250_fintek")) @@ -66,29 +117,55 @@ static void fintek_8250_exit_key(u16 base_port) release_region(base_port + ADDR_PORT, 2); } -static int fintek_8250_check_id(u16 base_port) +static int fintek_8250_check_id(struct fintek_8250 *pdata) { u16 chip; - outb(VENDOR_ID1, base_port + ADDR_PORT); - if (inb(base_port + DATA_PORT) != VENDOR_ID1_VAL) + if (sio_read_reg(pdata, VENDOR_ID1) != VENDOR_ID1_VAL) return -ENODEV; - outb(VENDOR_ID2, base_port + ADDR_PORT); - if (inb(base_port + DATA_PORT) != VENDOR_ID2_VAL) + if (sio_read_reg(pdata, VENDOR_ID2) != VENDOR_ID2_VAL) return -ENODEV; - outb(CHIP_ID1, base_port + ADDR_PORT); - chip = inb(base_port + DATA_PORT); - outb(CHIP_ID2, base_port + ADDR_PORT); - chip |= inb(base_port + DATA_PORT) << 8; - - if (chip != CHIP_ID_0 && chip != CHIP_ID_1) + chip = sio_read_reg(pdata, CHIP_ID1); + chip |= sio_read_reg(pdata, CHIP_ID2) << 8; + + switch (chip) { + case CHIP_ID_F81865: + case CHIP_ID_F81866: + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81216: + break; + default: return -ENODEV; + } + pdata->pid = chip; return 0; } +static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min, + int *max) +{ + switch (pdata->pid) { + case CHIP_ID_F81865: + case CHIP_ID_F81866: + *min = F81866_LDN_LOW; + *max = F81866_LDN_HIGH; + return 0; + + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81216: + *min = F81216_LDN_LOW; + *max = F81216_LDN_HIGH; + return 0; + } + + return -ENODEV; +} + static int fintek_8250_rs485_config(struct uart_port *port, struct serial_rs485 *rs485) { @@ -128,10 +205,8 @@ static int fintek_8250_rs485_config(struct uart_port *port, if (fintek_8250_enter_key(pdata->base_port, pdata->key)) return -EBUSY; - outb(LDN, pdata->base_port + ADDR_PORT); - outb(pdata->index, pdata->base_port + DATA_PORT); - outb(RS485, pdata->base_port + ADDR_PORT); - outb(config, pdata->base_port + DATA_PORT); + sio_write_reg(pdata, LDN, pdata->index); + sio_write_reg(pdata, RS485, config); fintek_8250_exit_key(pdata->base_port); port->rs485 = *rs485; @@ -139,40 +214,90 @@ static int fintek_8250_rs485_config(struct uart_port *port, return 0; } -static int find_base_port(struct fintek_8250 *pdata, u16 io_address) +static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level) +{ + sio_write_reg(pdata, LDN, pdata->index); + + switch (pdata->pid) { + case CHIP_ID_F81866: + sio_write_mask_reg(pdata, F81866_FIFO_CTRL, F81866_IRQ_MODE1, + 0); + /* fall through */ + case CHIP_ID_F81865: + sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_SHARE, + F81866_IRQ_SHARE); + sio_write_mask_reg(pdata, F81866_IRQ_MODE, F81866_IRQ_MODE0, + is_level ? 0 : F81866_IRQ_MODE0); + break; + + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81216: + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE, + IRQ_SHARE); + sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_MODE_MASK, + is_level ? IRQ_LEVEL_LOW : IRQ_EDGE_HIGH); + break; + } +} + +static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata) +{ + switch (pdata->pid) { + case CHIP_ID_F81216H: /* 128Bytes FIFO */ + case CHIP_ID_F81866: + sio_write_mask_reg(pdata, FIFO_CTRL, + FIFO_MODE_MASK | RXFTHR_MODE_MASK, + FIFO_MODE_128 | RXFTHR_MODE_4X); + break; + + default: /* Default 16Bytes FIFO */ + break; + } +} + +static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address, + unsigned int irq) { static const u16 addr[] = {0x4e, 0x2e}; static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67}; - int i, j, k; + struct irq_data *irq_data; + bool level_mode = false; + int i, j, k, min, max; for (i = 0; i < ARRAY_SIZE(addr); i++) { for (j = 0; j < ARRAY_SIZE(keys); j++) { + pdata->base_port = addr[i]; + pdata->key = keys[j]; if (fintek_8250_enter_key(addr[i], keys[j])) continue; - if (fintek_8250_check_id(addr[i])) { + if (fintek_8250_check_id(pdata) || + fintek_8250_get_ldn_range(pdata, &min, &max)) { fintek_8250_exit_key(addr[i]); continue; } - for (k = 0; k < 4; k++) { + for (k = min; k < max; k++) { u16 aux; - outb(LDN, addr[i] + ADDR_PORT); - outb(k, addr[i] + DATA_PORT); - - outb(IO_ADDR1, addr[i] + ADDR_PORT); - aux = inb(addr[i] + DATA_PORT); - outb(IO_ADDR2, addr[i] + ADDR_PORT); - aux |= inb(addr[i] + DATA_PORT) << 8; + sio_write_reg(pdata, LDN, k); + aux = sio_read_reg(pdata, IO_ADDR1); + aux |= sio_read_reg(pdata, IO_ADDR2) << 8; if (aux != io_address) continue; - fintek_8250_exit_key(addr[i]); - pdata->key = keys[j]; - pdata->base_port = addr[i]; pdata->index = k; + irq_data = irq_get_irq_data(irq); + if (irq_data) + level_mode = + irqd_is_level_type(irq_data); + + fintek_8250_set_irq_mode(pdata, level_mode); + fintek_8250_set_max_fifo(pdata); + fintek_8250_exit_key(addr[i]); + return 0; } @@ -183,39 +308,29 @@ static int find_base_port(struct fintek_8250 *pdata, u16 io_address) return -ENODEV; } -static int fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool level_mode) +static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart) { - int status; - u8 tmp; - - status = fintek_8250_enter_key(pdata->base_port, pdata->key); - if (status) - return status; - - outb(LDN, pdata->base_port + ADDR_PORT); - outb(pdata->index, pdata->base_port + DATA_PORT); - - outb(FINTEK_IRQ_MODE, pdata->base_port + ADDR_PORT); - tmp = inb(pdata->base_port + DATA_PORT); - - tmp &= ~IRQ_MODE_MASK; - tmp |= IRQ_SHARE; - if (!level_mode) - tmp |= IRQ_EDGE_HIGH; - - outb(tmp, pdata->base_port + DATA_PORT); - fintek_8250_exit_key(pdata->base_port); - return 0; + struct fintek_8250 *pdata = uart->port.private_data; + + switch (pdata->pid) { + case CHIP_ID_F81216AD: + case CHIP_ID_F81216H: + case CHIP_ID_F81866: + case CHIP_ID_F81865: + uart->port.rs485_config = fintek_8250_rs485_config; + break; + + default: /* No RS485 Auto direction functional */ + break; + } } int fintek_8250_probe(struct uart_8250_port *uart) { struct fintek_8250 *pdata; struct fintek_8250 probe_data; - struct irq_data *irq_data = irq_get_irq_data(uart->port.irq); - bool level_mode = irqd_is_level_type(irq_data); - if (find_base_port(&probe_data, uart->port.iobase)) + if (probe_setup_port(&probe_data, uart->port.iobase, uart->port.irq)) return -ENODEV; pdata = devm_kzalloc(uart->port.dev, sizeof(*pdata), GFP_KERNEL); @@ -223,8 +338,8 @@ int fintek_8250_probe(struct uart_8250_port *uart) return -ENOMEM; memcpy(pdata, &probe_data, sizeof(probe_data)); - uart->port.rs485_config = fintek_8250_rs485_config; uart->port.private_data = pdata; + fintek_8250_set_rs485_handler(uart); - return fintek_8250_set_irq_mode(pdata, level_mode); + return 0; } diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c index b9923464599f..f607946fd996 100644 --- a/drivers/tty/serial/8250/8250_lpss.c +++ b/drivers/tty/serial/8250/8250_lpss.c @@ -174,7 +174,7 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) int ret; chip->dev = &pdev->dev; - chip->irq = pdev->irq; + chip->irq = pci_irq_vector(pdev, 0); chip->regs = pci_ioremap_bar(pdev, 1); chip->pdata = &qrk_serial_dma_pdata; @@ -183,6 +183,9 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) if (ret) return; + pci_set_master(pdev); + pci_try_set_mwi(pdev); + /* Special DMA address for UART */ dma->rx_dma_addr = 0xfffff000; dma->tx_dma_addr = 0xfffff000; @@ -280,8 +283,6 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) return ret; - pci_set_master(pdev); - lpss = devm_kzalloc(&pdev->dev, sizeof(*lpss), GFP_KERNEL); if (!lpss) return -ENOMEM; diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c index 7a8b5fc81a19..d25ab1cd4295 100644 --- a/drivers/tty/serial/8250/8250_of.c +++ b/drivers/tty/serial/8250/8250_of.c @@ -332,8 +332,6 @@ static const struct of_device_id of_platform_serial_table[] = { .data = (void *)PORT_ALTR_16550_F128, }, { .compatible = "mrvl,mmp-uart", .data = (void *)PORT_XSCALE, }, - { .compatible = "mrvl,pxa-uart", - .data = (void *)PORT_XSCALE, }, { /* end of list */ }, }; MODULE_DEVICE_TABLE(of, of_platform_serial_table); diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c new file mode 100644 index 000000000000..3b08f342851a --- /dev/null +++ b/drivers/tty/serial/8250/8250_pxa.c @@ -0,0 +1,190 @@ +/* + * drivers/tty/serial/8250/8250_pxa.c -- driver for PXA on-board UARTS + * Copyright: (C) 2013 Sergei Ianovich <[email protected]> + * + * replaces drivers/serial/pxa.c by Nicolas Pitre + * Created: Feb 20, 2003 + * Copyright: (C) 2003 Monta Vista Software, Inc. + * + * Based on drivers/serial/8250.c by Russell King. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ + +#include <linux/device.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/serial_8250.h> +#include <linux/serial_core.h> +#include <linux/serial_reg.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/slab.h> +#include <linux/clk.h> +#include <linux/pm_runtime.h> + +#include "8250.h" + +struct pxa8250_data { + int line; + struct clk *clk; +}; + +#ifdef CONFIG_PM +static int serial_pxa_suspend(struct device *dev) +{ + struct pxa8250_data *data = dev_get_drvdata(dev); + + serial8250_suspend_port(data->line); + + return 0; +} + +static int serial_pxa_resume(struct device *dev) +{ + struct pxa8250_data *data = dev_get_drvdata(dev); + + serial8250_resume_port(data->line); + + return 0; +} +#endif + +static const struct dev_pm_ops serial_pxa_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(serial_pxa_suspend, serial_pxa_resume) +}; + +static const struct of_device_id serial_pxa_dt_ids[] = { + { .compatible = "mrvl,pxa-uart", }, + { .compatible = "mrvl,mmp-uart", }, + {} +}; +MODULE_DEVICE_TABLE(of, serial_pxa_dt_ids); + +/* Uart divisor latch write */ +static void serial_pxa_dl_write(struct uart_8250_port *up, int value) +{ + unsigned int dll; + + serial_out(up, UART_DLL, value & 0xff); + /* + * work around Erratum #74 according to Marvel(R) PXA270M Processor + * Specification Update (April 19, 2010) + */ + dll = serial_in(up, UART_DLL); + WARN_ON(dll != (value & 0xff)); + + serial_out(up, UART_DLM, value >> 8 & 0xff); +} + + +static void serial_pxa_pm(struct uart_port *port, unsigned int state, + unsigned int oldstate) +{ + struct pxa8250_data *data = port->private_data; + + if (!state) + clk_prepare_enable(data->clk); + else + clk_disable_unprepare(data->clk); +} + +static int serial_pxa_probe(struct platform_device *pdev) +{ + struct uart_8250_port uart = {}; + struct pxa8250_data *data; + struct resource *mmres, *irqres; + int ret; + + mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!mmres || !irqres) + return -ENODEV; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(data->clk)) + return PTR_ERR(data->clk); + + ret = clk_prepare(data->clk); + if (ret) + return ret; + + uart.port.type = PORT_XSCALE; + uart.port.iotype = UPIO_MEM32; + uart.port.mapbase = mmres->start; + uart.port.regshift = 2; + uart.port.irq = irqres->start; + uart.port.fifosize = 64; + uart.port.flags = UPF_IOREMAP | UPF_SKIP_TEST; + uart.port.dev = &pdev->dev; + uart.port.uartclk = clk_get_rate(data->clk); + uart.port.pm = serial_pxa_pm; + uart.port.private_data = data; + uart.dl_write = serial_pxa_dl_write; + + ret = serial8250_register_8250_port(&uart); + if (ret < 0) + goto err_clk; + + data->line = ret; + + platform_set_drvdata(pdev, data); + + return 0; + + err_clk: + clk_unprepare(data->clk); + return ret; +} + +static int serial_pxa_remove(struct platform_device *pdev) +{ + struct pxa8250_data *data = platform_get_drvdata(pdev); + + serial8250_unregister_port(data->line); + + clk_unprepare(data->clk); + + return 0; +} + +static struct platform_driver serial_pxa_driver = { + .probe = serial_pxa_probe, + .remove = serial_pxa_remove, + + .driver = { + .name = "pxa2xx-uart", + .pm = &serial_pxa_pm_ops, + .of_match_table = serial_pxa_dt_ids, + }, +}; + +module_platform_driver(serial_pxa_driver); + +static int __init early_serial_pxa_setup(struct earlycon_device *device, + const char *options) +{ + struct uart_port *port = &device->port; + + if (!(device->port.membase || device->port.iobase)) + return -ENODEV; + + port->regshift = 2; + return early_serial8250_setup(device, NULL); +} +OF_EARLYCON_DECLARE(early_pxa, "mrvl,pxa-uart", early_serial_pxa_setup); + +MODULE_AUTHOR("Sergei Ianovich"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:pxa2xx-uart"); diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 899834776b36..0b8b6740ba43 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig @@ -439,6 +439,16 @@ config SERIAL_8250_MOXA This driver can also be built as a module. The module will be called 8250_moxa. If you want to do that, say M here. +config SERIAL_8250_PXA + tristate "PXA serial port support" + depends on SERIAL_8250 + depends on ARCH_PXA || ARCH_MMP + help + If you have a machine based on an Intel XScale PXA2xx CPU you can + enable its onboard serial ports by enabling this option. The option is + applicable to both devicetree and legacy boards, and early console is + part of its support. + config SERIAL_OF_PLATFORM tristate "Devicetree based probing for 8250 ports" depends on SERIAL_8250 && OF diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index 276c6fb60337..850e721877a9 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_SERIAL_8250_INGENIC) += 8250_ingenic.o obj-$(CONFIG_SERIAL_8250_LPSS) += 8250_lpss.o obj-$(CONFIG_SERIAL_8250_MID) += 8250_mid.o obj-$(CONFIG_SERIAL_8250_MOXA) += 8250_moxa.o +obj-$(CONFIG_SERIAL_8250_PXA) += 8250_pxa.o obj-$(CONFIG_SERIAL_OF_PLATFORM) += 8250_of.o CFLAGS_8250_ingenic.o += -I$(srctree)/scripts/dtc/libfdt diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 25c1d7bc0100..5a7c9d03f8cf 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -438,17 +438,27 @@ config SERIAL_MPSC_CONSOLE Say Y here if you want to support a serial console on a Marvell MPSC. config SERIAL_PXA - bool "PXA serial port support" + bool "PXA serial port support (DEPRECATED)" depends on ARCH_PXA || ARCH_MMP select SERIAL_CORE + select SERIAL_8250_PXA if SERIAL_8250=y + select SERIAL_PXA_NON8250 if !SERIAL_8250=y help If you have a machine based on an Intel XScale PXA2xx CPU you can enable its onboard serial ports by enabling this option. + Unless you have a specific need, you should use SERIAL_8250_PXA + instead of this. + +config SERIAL_PXA_NON8250 + bool + depends on !SERIAL_8250 + config SERIAL_PXA_CONSOLE - bool "Console on PXA serial port" + bool "Console on PXA serial port (DEPRECATED)" depends on SERIAL_PXA select SERIAL_CORE_CONSOLE + select SERIAL_8250_CONSOLE if SERIAL_8250=y help If you have enabled the serial port on the Intel XScale PXA CPU you can make it the console by answering Y to this option. @@ -460,6 +470,9 @@ config SERIAL_PXA_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) + Unless you have a specific need, you should use SERIAL_8250_PXA + and SERIAL_8250_CONSOLE instead of this. + config SERIAL_SA1100 bool "SA1100 serial port support" depends on ARCH_SA1100 diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 1278d376da50..2d6288bc4554 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_SERIAL_8250) += 8250/ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o -obj-$(CONFIG_SERIAL_PXA) += pxa.o +obj-$(CONFIG_SERIAL_PXA_NON8250) += pxa.o obj-$(CONFIG_SERIAL_PNX8XXX) += pnx8xxx_uart.o obj-$(CONFIG_SERIAL_SA1100) += sa1100.o obj-$(CONFIG_SERIAL_BCM63XX) += bcm63xx_uart.o @@ -62,13 +62,11 @@ obj-$(CONFIG_SERIAL_ATMEL) += atmel_serial.o obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o obj-$(CONFIG_SERIAL_MSM) += msm_serial.o obj-$(CONFIG_SERIAL_NETX) += netx-serial.o -obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o obj-$(CONFIG_SERIAL_ALTERA_UART) += altera_uart.o obj-$(CONFIG_SERIAL_ST_ASC) += st-asc.o obj-$(CONFIG_SERIAL_TILEGX) += tilegx.o -obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o obj-$(CONFIG_SERIAL_QE) += ucc_uart.o obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o obj-$(CONFIG_SERIAL_GRLIB_GAISLER_APBUART) += apbuart.o @@ -96,3 +94,6 @@ obj-$(CONFIG_SERIAL_MPS2_UART) += mps2-uart.o # GPIOLIB helpers for modem control lines obj-$(CONFIG_SERIAL_MCTRL_GPIO) += serial_mctrl_gpio.o + +obj-$(CONFIG_SERIAL_KGDB_NMI) += kgdb_nmi.o +obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index e2c33b9528d8..c00ab22afe9e 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -2315,12 +2315,67 @@ static int __init pl011_console_setup(struct console *co, char *options) return uart_set_options(&uap->port, co, baud, parity, bits, flow); } +/** + * pl011_console_match - non-standard console matching + * @co: registering console + * @name: name from console command line + * @idx: index from console command line + * @options: ptr to option string from console command line + * + * Only attempts to match console command lines of the form: + * console=pl011,mmio|mmio32,<addr>[,<options>] + * console=pl011,0x<addr>[,<options>] + * This form is used to register an initial earlycon boot console and + * replace it with the amba_console at pl011 driver init. + * + * Performs console setup for a match (as required by interface) + * If no <options> are specified, then assume the h/w is already setup. + * + * Returns 0 if console matches; otherwise non-zero to use default matching + */ +static int __init pl011_console_match(struct console *co, char *name, int idx, + char *options) +{ + unsigned char iotype; + resource_size_t addr; + int i; + + if (strcmp(name, "pl011") != 0) + return -ENODEV; + + if (uart_parse_earlycon(options, &iotype, &addr, &options)) + return -ENODEV; + + if (iotype != UPIO_MEM && iotype != UPIO_MEM32) + return -ENODEV; + + /* try to match the port specified on the command line */ + for (i = 0; i < ARRAY_SIZE(amba_ports); i++) { + struct uart_port *port; + + if (!amba_ports[i]) + continue; + + port = &amba_ports[i]->port; + + if (port->mapbase != addr) + continue; + + co->index = i; + port->cons = co; + return pl011_console_setup(co, options); + } + + return -ENODEV; +} + static struct uart_driver amba_reg; static struct console amba_console = { .name = "ttyAMA", .write = pl011_console_write, .device = uart_console_device, .setup = pl011_console_setup, + .match = pl011_console_match, .flags = CON_PRINTBUFFER, .index = -1, .data = &amba_reg, diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 76103f2c4a80..a1c6519837a4 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -430,6 +430,65 @@ static void lpuart_flush_buffer(struct uart_port *port) } } +#if defined(CONFIG_CONSOLE_POLL) + +static int lpuart_poll_init(struct uart_port *port) +{ + struct lpuart_port *sport = container_of(port, + struct lpuart_port, port); + unsigned long flags; + unsigned char temp; + + sport->port.fifosize = 0; + + spin_lock_irqsave(&sport->port.lock, flags); + /* Disable Rx & Tx */ + writeb(0, sport->port.membase + UARTCR2); + + temp = readb(sport->port.membase + UARTPFIFO); + /* Enable Rx and Tx FIFO */ + writeb(temp | UARTPFIFO_RXFE | UARTPFIFO_TXFE, + sport->port.membase + UARTPFIFO); + + /* flush Tx and Rx FIFO */ + writeb(UARTCFIFO_TXFLUSH | UARTCFIFO_RXFLUSH, + sport->port.membase + UARTCFIFO); + + /* explicitly clear RDRF */ + if (readb(sport->port.membase + UARTSR1) & UARTSR1_RDRF) { + readb(sport->port.membase + UARTDR); + writeb(UARTSFIFO_RXUF, sport->port.membase + UARTSFIFO); + } + + writeb(0, sport->port.membase + UARTTWFIFO); + writeb(1, sport->port.membase + UARTRWFIFO); + + /* Enable Rx and Tx */ + writeb(UARTCR2_RE | UARTCR2_TE, sport->port.membase + UARTCR2); + spin_unlock_irqrestore(&sport->port.lock, flags); + + return 0; +} + +static void lpuart_poll_put_char(struct uart_port *port, unsigned char c) +{ + /* drain */ + while (!(readb(port->membase + UARTSR1) & UARTSR1_TDRE)) + barrier(); + + writeb(c, port->membase + UARTDR); +} + +static int lpuart_poll_get_char(struct uart_port *port) +{ + if (!(readb(port->membase + UARTSR1) & UARTSR1_RDRF)) + return NO_POLL_CHAR; + + return readb(port->membase + UARTDR); +} + +#endif + static inline void lpuart_transmit_buffer(struct lpuart_port *sport) { struct circ_buf *xmit = &sport->port.state->xmit; @@ -1595,6 +1654,11 @@ static const struct uart_ops lpuart_pops = { .config_port = lpuart_config_port, .verify_port = lpuart_verify_port, .flush_buffer = lpuart_flush_buffer, +#if defined(CONFIG_CONSOLE_POLL) + .poll_init = lpuart_poll_init, + .poll_get_char = lpuart_poll_get_char, + .poll_put_char = lpuart_poll_put_char, +#endif }; static const struct uart_ops lpuart32_pops = { diff --git a/drivers/tty/serial/pxa.c b/drivers/tty/serial/pxa.c index cd9d9e878475..b9dd787cb561 100644 --- a/drivers/tty/serial/pxa.c +++ b/drivers/tty/serial/pxa.c @@ -925,7 +925,9 @@ static struct platform_driver serial_pxa_driver = { }, }; -static int __init serial_pxa_init(void) + +/* 8250 driver for PXA serial ports should be used */ +static int __deprecated __init serial_pxa_init(void) { int ret; diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c index fb0672554123..793395451982 100644 --- a/drivers/tty/serial/sc16is7xx.c +++ b/drivers/tty/serial/sc16is7xx.c @@ -1264,7 +1264,7 @@ static int sc16is7xx_probe(struct device *dev, /* Setup interrupt */ ret = devm_request_irq(dev, irq, sc16is7xx_irq, - IRQF_ONESHOT | flags, dev_name(dev), s); + flags, dev_name(dev), s); if (!ret) return 0; diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 8c3bf3d613c0..623264445100 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -315,38 +315,27 @@ void schedule_console_callback(void) schedule_work(&console_work); } -static void scrup(struct vc_data *vc, unsigned int t, unsigned int b, int nr) +static void con_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int nr) { - unsigned short *d, *s; + u16 *clear, *d, *s; - if (t+nr >= b) + if (t + nr >= b) nr = b - t - 1; if (b > vc->vc_rows || t >= b || nr < 1) return; - if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_UP, nr)) + if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, dir, nr)) return; - d = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t); - s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * (t + nr)); - scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row); - scr_memsetw(d + (b - t - nr) * vc->vc_cols, vc->vc_video_erase_char, - vc->vc_size_row * nr); -} -static void scrdown(struct vc_data *vc, unsigned int t, unsigned int b, int nr) -{ - unsigned short *s; - unsigned int step; + s = clear = (u16 *)(vc->vc_origin + vc->vc_size_row * t); + d = (u16 *)(vc->vc_origin + vc->vc_size_row * (t + nr)); - if (t+nr >= b) - nr = b - t - 1; - if (b > vc->vc_rows || t >= b || nr < 1) - return; - if (con_is_visible(vc) && vc->vc_sw->con_scroll(vc, t, b, SM_DOWN, nr)) - return; - s = (unsigned short *)(vc->vc_origin + vc->vc_size_row * t); - step = vc->vc_cols * nr; - scr_memmovew(s + step, s, (b - t - nr) * vc->vc_size_row); - scr_memsetw(s, vc->vc_video_erase_char, 2 * step); + if (dir == SM_UP) { + clear = s + (b - t - nr) * vc->vc_cols; + swap(s, d); + } + scr_memmovew(d, s, (b - t - nr) * vc->vc_size_row); + scr_memsetw(clear, vc->vc_video_erase_char, vc->vc_size_row * nr); } static void do_update_region(struct vc_data *vc, unsigned long start, int count) @@ -1120,7 +1109,7 @@ static void lf(struct vc_data *vc) * if below scrolling region */ if (vc->vc_y + 1 == vc->vc_bottom) - scrup(vc, vc->vc_top, vc->vc_bottom, 1); + con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_UP, 1); else if (vc->vc_y < vc->vc_rows - 1) { vc->vc_y++; vc->vc_pos += vc->vc_size_row; @@ -1135,7 +1124,7 @@ static void ri(struct vc_data *vc) * if above scrolling region */ if (vc->vc_y == vc->vc_top) - scrdown(vc, vc->vc_top, vc->vc_bottom, 1); + con_scroll(vc, vc->vc_top, vc->vc_bottom, SM_DOWN, 1); else if (vc->vc_y > 0) { vc->vc_y--; vc->vc_pos -= vc->vc_size_row; @@ -1631,7 +1620,7 @@ static void csi_L(struct vc_data *vc, unsigned int nr) nr = vc->vc_rows - vc->vc_y; else if (!nr) nr = 1; - scrdown(vc, vc->vc_y, vc->vc_bottom, nr); + con_scroll(vc, vc->vc_y, vc->vc_bottom, SM_DOWN, nr); vc->vc_need_wrap = 0; } @@ -1652,7 +1641,7 @@ static void csi_M(struct vc_data *vc, unsigned int nr) nr = vc->vc_rows - vc->vc_y; else if (!nr) nr=1; - scrup(vc, vc->vc_y, vc->vc_bottom, nr); + con_scroll(vc, vc->vc_y, vc->vc_bottom, SM_UP, nr); vc->vc_need_wrap = 0; } @@ -4295,6 +4284,46 @@ void vcs_scr_updated(struct vc_data *vc) notify_update(vc); } +void vc_scrolldelta_helper(struct vc_data *c, int lines, + unsigned int rolled_over, void *base, unsigned int size) +{ + unsigned long ubase = (unsigned long)base; + ptrdiff_t scr_end = (void *)c->vc_scr_end - base; + ptrdiff_t vorigin = (void *)c->vc_visible_origin - base; + ptrdiff_t origin = (void *)c->vc_origin - base; + int margin = c->vc_size_row * 4; + int from, wrap, from_off, avail; + + /* Turn scrollback off */ + if (!lines) { + c->vc_visible_origin = c->vc_origin; + return; + } + + /* Do we have already enough to allow jumping from 0 to the end? */ + if (rolled_over > scr_end + margin) { + from = scr_end; + wrap = rolled_over + c->vc_size_row; + } else { + from = 0; + wrap = size; + } + + from_off = (vorigin - from + wrap) % wrap + lines * c->vc_size_row; + avail = (origin - from + wrap) % wrap; + + /* Only a little piece would be left? Show all incl. the piece! */ + if (avail < 2 * margin) + margin = 0; + if (from_off < margin) + from_off = 0; + if (from_off > avail - margin) + from_off = avail; + + c->vc_visible_origin = ubase + (from + from_off) % wrap; +} +EXPORT_SYMBOL_GPL(vc_scrolldelta_helper); + /* * Visible symbols for modules */ diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 460cebf322e3..4b5777ec1501 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -686,8 +686,6 @@ static void sisusbcon_scrolldelta(struct vc_data *c, int lines) { struct sisusb_usb_data *sisusb; - int margin = c->vc_size_row * 4; - int ul, we, p, st; sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num); if (!sisusb) @@ -700,39 +698,8 @@ sisusbcon_scrolldelta(struct vc_data *c, int lines) return; } - if (!lines) /* Turn scrollback off */ - c->vc_visible_origin = c->vc_origin; - else { - - if (sisusb->con_rolled_over > - (c->vc_scr_end - sisusb->scrbuf) + margin) { - - ul = c->vc_scr_end - sisusb->scrbuf; - we = sisusb->con_rolled_over + c->vc_size_row; - - } else { - - ul = 0; - we = sisusb->scrbuf_size; - - } - - p = (c->vc_visible_origin - sisusb->scrbuf - ul + we) % we + - lines * c->vc_size_row; - - st = (c->vc_origin - sisusb->scrbuf - ul + we) % we; - - if (st < 2 * margin) - margin = 0; - - if (p < margin) - p = 0; - - if (p > st - margin) - p = st; - - c->vc_visible_origin = sisusb->scrbuf + (p + ul) % we; - } + vc_scrolldelta_helper(c, lines, sisusb->con_rolled_over, + (void *)sisusb->scrbuf, sisusb->scrbuf_size); sisusbcon_set_start_address(sisusb, c); @@ -808,9 +775,10 @@ sisusbcon_cursor(struct vc_data *c, int mode) mutex_unlock(&sisusb->lock); } -static int +static bool sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb, - int t, int b, int dir, int lines) + unsigned int t, unsigned int b, enum con_scroll dir, + unsigned int lines) { int cols = sisusb->sisusb_num_columns; int length = ((b - t) * cols) * 2; @@ -852,8 +820,9 @@ sisusbcon_scroll_area(struct vc_data *c, struct sisusb_usb_data *sisusb, } /* Interface routine */ -static int -sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) +static bool +sisusbcon_scroll(struct vc_data *c, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int lines) { struct sisusb_usb_data *sisusb; u16 eattr = c->vc_video_erase_char; @@ -870,17 +839,17 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) */ if (!lines) - return 1; + return true; sisusb = sisusb_get_sisusb_lock_and_check(c->vc_num); if (!sisusb) - return 0; + return false; /* sisusb->lock is down */ if (sisusb_is_inactive(c, sisusb)) { mutex_unlock(&sisusb->lock); - return 0; + return false; } /* Special case */ @@ -971,7 +940,7 @@ sisusbcon_scroll(struct vc_data *c, int t, int b, int dir, int lines) mutex_unlock(&sisusb->lock); - return 1; + return true; } /* Interface routine */ diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index b87f5cfdaea5..a44f5627b82a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -164,8 +164,6 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, int count, int ypos, int xpos); static void fbcon_clear_margins(struct vc_data *vc, int bottom_only); static void fbcon_cursor(struct vc_data *vc, int mode); -static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, - int count); static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, int height, int width); static int fbcon_switch(struct vc_data *vc); @@ -1795,15 +1793,15 @@ static inline void fbcon_softback_note(struct vc_data *vc, int t, softback_curr = softback_in; } -static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, - int count) +static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct display *p = &fb_display[vc->vc_num]; int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; if (fbcon_is_inactive(vc, info)) - return -EINVAL; + return true; fbcon_cursor(vc, CM_ERASE); @@ -1831,7 +1829,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, (b - count)), vc->vc_video_erase_char, vc->vc_size_row * count); - return 1; + return true; break; case SCROLL_WRAP_MOVE: @@ -1903,7 +1901,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, (b - count)), vc->vc_video_erase_char, vc->vc_size_row * count); - return 1; + return true; } break; @@ -1922,7 +1920,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, t), vc->vc_video_erase_char, vc->vc_size_row * count); - return 1; + return true; break; case SCROLL_WRAP_MOVE: @@ -1992,10 +1990,10 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, t), vc->vc_video_erase_char, vc->vc_size_row * count); - return 1; + return true; } } - return 0; + return false; } diff --git a/drivers/video/console/mdacon.c b/drivers/video/console/mdacon.c index bacbb044d77c..ec192a1bf297 100644 --- a/drivers/video/console/mdacon.c +++ b/drivers/video/console/mdacon.c @@ -488,12 +488,13 @@ static void mdacon_cursor(struct vc_data *c, int mode) } } -static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines) +static bool mdacon_scroll(struct vc_data *c, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int lines) { u16 eattr = mda_convert_attr(c->vc_video_erase_char); if (!lines) - return 0; + return false; if (lines > c->vc_rows) /* maximum realistic size */ lines = c->vc_rows; @@ -514,7 +515,7 @@ static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines) break; } - return 0; + return false; } diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index e3b9521e4ec3..1e11614322fe 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -574,8 +574,8 @@ static int newport_font_set(struct vc_data *vc, struct console_font *font, unsig return newport_set_font(vc->vc_num, font); } -static int newport_scroll(struct vc_data *vc, int t, int b, int dir, - int lines) +static bool newport_scroll(struct vc_data *vc, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int lines) { int count, x, y; unsigned short *s, *d; @@ -595,7 +595,7 @@ static int newport_scroll(struct vc_data *vc, int t, int b, int dir, (vc->vc_color & 0xf0) >> 4); } npregs->cset.topscan = (topscan - 1) & 0x3ff; - return 0; + return false; } count = (b - t - lines) * vc->vc_cols; @@ -670,7 +670,7 @@ static int newport_scroll(struct vc_data *vc, int t, int b, int dir, } } } - return 1; + return true; } static int newport_dummy(struct vc_data *c) diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index 3a10ac19598f..79c9bd8d3025 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -153,12 +153,13 @@ static void sticon_cursor(struct vc_data *conp, int mode) } } -static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count) +static bool sticon_scroll(struct vc_data *conp, unsigned int t, + unsigned int b, enum con_scroll dir, unsigned int count) { struct sti_struct *sti = sticon_sti; if (vga_is_gfx) - return 0; + return false; sticon_cursor(conp, CM_ERASE); @@ -174,7 +175,7 @@ static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count) break; } - return 0; + return false; } static void sticon_init(struct vc_data *c, int init) diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 11576611a974..c22a56232b7c 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -60,15 +60,6 @@ static struct vgastate vgastate; #define BLANK 0x0020 -#define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */ -#define CAN_LOAD_PALETTE /* undefine if the user must not do this */ - -/* You really do _NOT_ want to define this, unless you have buggy - * Trident VGA which will resize cursor when moving it between column - * 15 & 16. If you define this and your VGA is OK, inverse bug will - * appear. - */ -#undef TRIDENT_GLITCH #define VGA_FONTWIDTH 8 /* VGA does not support fontwidths != 8 */ /* * Interface used by the world @@ -83,14 +74,12 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch); static void vgacon_scrolldelta(struct vc_data *c, int lines); static int vgacon_set_origin(struct vc_data *c); static void vgacon_save_screen(struct vc_data *c); -static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, - int lines); static void vgacon_invert_region(struct vc_data *c, u16 * p, int count); static struct uni_pagedir *vgacon_uni_pagedir; static int vgacon_refcount; /* Description of the hardware situation */ -static int vga_init_done __read_mostly; +static bool vga_init_done; static unsigned long vga_vram_base __read_mostly; /* Base of video memory */ static unsigned long vga_vram_end __read_mostly; /* End of video memory */ static unsigned int vga_vram_size __read_mostly; /* Size of video memory */ @@ -98,31 +87,31 @@ static u16 vga_video_port_reg __read_mostly; /* Video register select port */ static u16 vga_video_port_val __read_mostly; /* Video register value port */ static unsigned int vga_video_num_columns; /* Number of text columns */ static unsigned int vga_video_num_lines; /* Number of text lines */ -static int vga_can_do_color __read_mostly; /* Do we support colors? */ +static bool vga_can_do_color; /* Do we support colors? */ static unsigned int vga_default_font_height __read_mostly; /* Height of default screen font */ static unsigned char vga_video_type __read_mostly; /* Card type */ -static unsigned char vga_hardscroll_enabled __read_mostly; -static unsigned char vga_hardscroll_user_enable __read_mostly = 1; -static unsigned char vga_font_is_default = 1; +static bool vga_font_is_default = true; static int vga_vesa_blanked; -static int vga_palette_blanked; -static int vga_is_gfx; -static int vga_512_chars; +static bool vga_palette_blanked; +static bool vga_is_gfx; +static bool vga_512_chars; static int vga_video_font_height; static int vga_scan_lines __read_mostly; static unsigned int vga_rolled_over; -static int vgacon_text_mode_force; +static bool vgacon_text_mode_force; +static bool vga_hardscroll_enabled; +static bool vga_hardscroll_user_enable = true; bool vgacon_text_force(void) { - return vgacon_text_mode_force ? true : false; + return vgacon_text_mode_force; } EXPORT_SYMBOL(vgacon_text_force); static int __init text_mode(char *str) { - vgacon_text_mode_force = 1; + vgacon_text_mode_force = true; return 1; } @@ -136,7 +125,7 @@ static int __init no_scroll(char *str) * Braille reader made by F.H. Papenmeier (Germany). * Use the "no-scroll" bootflag. */ - vga_hardscroll_user_enable = vga_hardscroll_enabled = 0; + vga_hardscroll_user_enable = vga_hardscroll_enabled = false; return 1; } @@ -159,18 +148,10 @@ static inline void write_vga(unsigned char reg, unsigned int val) * handlers, thus the write has to be IRQ-atomic. */ raw_spin_lock_irqsave(&vga_lock, flags); - -#ifndef SLOW_VGA v1 = reg + (val & 0xff00); v2 = reg + 1 + ((val << 8) & 0xff00); outw(v1, vga_video_port_reg); outw(v2, vga_video_port_reg); -#else - outb_p(reg, vga_video_port_reg); - outb_p(val >> 8, vga_video_port_val); - outb_p(reg + 1, vga_video_port_reg); - outb_p(val & 0xff, vga_video_port_val); -#endif raw_spin_unlock_irqrestore(&vga_lock, flags); } @@ -334,31 +315,8 @@ static void vgacon_restore_screen(struct vc_data *c) static void vgacon_scrolldelta(struct vc_data *c, int lines) { - if (!lines) /* Turn scrollback off */ - c->vc_visible_origin = c->vc_origin; - else { - int margin = c->vc_size_row * 4; - int ul, we, p, st; - - if (vga_rolled_over > - (c->vc_scr_end - vga_vram_base) + margin) { - ul = c->vc_scr_end - vga_vram_base; - we = vga_rolled_over + c->vc_size_row; - } else { - ul = 0; - we = vga_vram_size; - } - p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + - lines * c->vc_size_row; - st = (c->vc_origin - vga_vram_base - ul + we) % we; - if (st < 2 * margin) - margin = 0; - if (p < margin) - p = 0; - if (p > st - margin) - p = st; - c->vc_visible_origin = vga_vram_base + (p + ul) % we; - } + vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base, + vga_vram_size); vga_set_mem_top(c); } #endif /* CONFIG_VGACON_SOFT_SCROLLBACK */ @@ -427,7 +385,7 @@ static const char *vgacon_startup(void) } } else { /* If not, it is color. */ - vga_can_do_color = 1; + vga_can_do_color = true; vga_vram_base = 0xb8000; vga_video_port_reg = VGA_CRT_IC; vga_video_port_val = VGA_CRT_DC; @@ -451,18 +409,6 @@ static const char *vgacon_startup(void) request_resource(&ioport_resource, &vga_console_resource); -#ifdef VGA_CAN_DO_64KB - /* - * get 64K rather than 32K of video RAM. - * This doesn't actually work on all "VGA" - * controllers (it seems like setting MM=01 - * and COE=1 isn't necessarily a good idea) - */ - vga_vram_base = 0xa0000; - vga_vram_size = 0x10000; - outb_p(6, VGA_GFX_I); - outb_p(6, VGA_GFX_D); -#endif /* * Normalise the palette registers, to point * the 16 screen colours to the first 16 @@ -542,7 +488,7 @@ static const char *vgacon_startup(void) if (!vga_init_done) { vgacon_scrollback_startup(); - vga_init_done = 1; + vga_init_done = true; } return display_desc; @@ -634,7 +580,7 @@ static u8 vgacon_build_attr(struct vc_data *c, u8 color, u8 intensity, static void vgacon_invert_region(struct vc_data *c, u16 * p, int count) { - int col = vga_can_do_color; + const bool col = vga_can_do_color; while (count--) { u16 a = scr_readw(p); @@ -652,11 +598,6 @@ static void vgacon_set_cursor_size(int xpos, int from, int to) unsigned long flags; int curs, cure; -#ifdef TRIDENT_GLITCH - if (xpos < 16) - from--, to--; -#endif - if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto)) return; cursor_size_lastfrom = from; @@ -858,12 +799,10 @@ static void vga_set_palette(struct vc_data *vc, const unsigned char *table) static void vgacon_set_palette(struct vc_data *vc, const unsigned char *table) { -#ifdef CAN_LOAD_PALETTE if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked || !con_is_visible(vc)) return; vga_set_palette(vc, table); -#endif } /* structure holding original VGA register settings */ @@ -1006,24 +945,24 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) } if (vga_palette_blanked) { vga_set_palette(c, color_table); - vga_palette_blanked = 0; + vga_palette_blanked = false; return 0; } - vga_is_gfx = 0; + vga_is_gfx = false; /* Tell console.c that it has to restore the screen itself */ return 1; case 1: /* Normal blanking */ case -1: /* Obsolete */ if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) { vga_pal_blank(&vgastate); - vga_palette_blanked = 1; + vga_palette_blanked = true; return 0; } vgacon_set_origin(c); scr_memsetw((void *) vga_vram_base, BLANK, c->vc_screenbuf_size); if (mode_switch) - vga_is_gfx = 1; + vga_is_gfx = true; return 1; default: /* VESA blanking */ if (vga_video_type == VIDEO_TYPE_VGAC) { @@ -1046,15 +985,14 @@ static int vgacon_blank(struct vc_data *c, int blank, int mode_switch) * ([email protected]). */ -#ifdef CAN_LOAD_EGA_FONTS - #define colourmap 0xa0000 /* Pauline Middelink <[email protected]> reports that we should use 0xA0000 for the bwmap as well.. */ #define blackwmap 0xa0000 #define cmapsz 8192 -static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) +static int vgacon_do_font_op(struct vgastate *state, char *arg, int set, + bool ch512) { unsigned short video_port_status = vga_video_port_reg + 6; int font_select = 0x00, beg, i; @@ -1063,10 +1001,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) if (vga_video_type != VIDEO_TYPE_EGAM) { charmap = (char *) VGA_MAP_MEM(colourmap, 0); beg = 0x0e; -#ifdef VGA_CAN_DO_64KB - if (vga_video_type == VIDEO_TYPE_VGAC) - beg = 0x06; -#endif } else { charmap = (char *) VGA_MAP_MEM(blackwmap, 0); beg = 0x0a; @@ -1080,7 +1014,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) if (!arg) return -EINVAL; /* Return to default font not supported */ - vga_font_is_default = 0; + vga_font_is_default = false; font_select = ch512 ? 0x04 : 0x00; #else /* @@ -1091,7 +1025,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) if (set) { vga_font_is_default = !arg; if (!arg) - ch512 = 0; /* Default font is always 256 */ + ch512 = false; /* Default font is always 256 */ font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00; } @@ -1295,13 +1229,6 @@ static int vgacon_font_get(struct vc_data *c, struct console_font *font) return vgacon_do_font_op(&vgastate, font->data, 0, vga_512_chars); } -#else - -#define vgacon_font_set NULL -#define vgacon_font_get NULL - -#endif - static int vgacon_resize(struct vc_data *c, unsigned int width, unsigned int height, unsigned int user) { @@ -1350,17 +1277,17 @@ static void vgacon_save_screen(struct vc_data *c) c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size); } -static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, - int lines) +static bool vgacon_scroll(struct vc_data *c, unsigned int t, unsigned int b, + enum con_scroll dir, unsigned int lines) { unsigned long oldo; unsigned int delta; if (t || b != c->vc_rows || vga_is_gfx || c->vc_mode != KD_TEXT) - return 0; + return false; if (!vga_hardscroll_enabled || lines >= c->vc_rows / 2) - return 0; + return false; vgacon_restore_screen(c); oldo = c->vc_origin; @@ -1396,7 +1323,7 @@ static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, c->vc_visible_origin = c->vc_origin; vga_set_mem_top(c); c->vc_pos = (c->vc_pos - oldo) + c->vc_origin; - return 1; + return true; } diff --git a/include/linux/console.h b/include/linux/console.h index 3672809234a7..508b012bd5bd 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -28,9 +28,17 @@ struct tty_struct; #define VT100ID "\033[?1;2c" #define VT102ID "\033[?6c" +enum con_scroll { + SM_UP, + SM_DOWN, +}; + /** * struct consw - callbacks for consoles * + * @con_scroll: move lines from @top to @bottom in direction @dir by @lines. + * Return true if no generic handling should be done. + * Invoked by csi_M and printing to the console. * @con_set_palette: sets the palette of the console to @table (optional) * @con_scrolldelta: the contents of the console should be scrolled by @lines. * Invoked by user. (optional) @@ -44,7 +52,9 @@ struct consw { void (*con_putc)(struct vc_data *, int, int, int); void (*con_putcs)(struct vc_data *, const unsigned short *, int, int, int); void (*con_cursor)(struct vc_data *, int); - int (*con_scroll)(struct vc_data *, int, int, int, int); + bool (*con_scroll)(struct vc_data *, unsigned int top, + unsigned int bottom, enum con_scroll dir, + unsigned int lines); int (*con_switch)(struct vc_data *); int (*con_blank)(struct vc_data *, int, int); int (*con_font_set)(struct vc_data *, struct console_font *, unsigned); @@ -99,10 +109,6 @@ static inline int con_debug_leave(void) } #endif -/* scroll */ -#define SM_UP (1) -#define SM_DOWN (2) - /* cursor */ #define CM_DRAW (1) #define CM_ERASE (2) diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index 6abd24f258bc..833fdd4794a0 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -191,5 +191,7 @@ extern void vt_set_led_state(int console, int leds); extern void vt_kbd_con_start(int console); extern void vt_kbd_con_stop(int console); +void vc_scrolldelta_helper(struct vc_data *c, int lines, + unsigned int rolled_over, void *_base, unsigned int size); #endif /* _VT_KERN_H */ |