|
From: James S. <jsi...@us...> - 2001-12-25 06:50:54
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/serial
In directory usw-pr-cvs1:/tmp/cvs-serv30082/drivers/serial
Modified Files:
ChangeLog serial_21285.c serial_8250.c serial_8250.h
serial_8250_pci.c serial_8250_pnp.c serial_amba.c
serial_anakin.c serial_clps711x.c serial_core.c
serial_sa1100.c serial_uart00.c
Log Message:
Synced to RMK work. See ChangeLg for comments.
Index: ChangeLog
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/ChangeLog,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- ChangeLog 2001/12/25 04:29:59 1.3
+++ ChangeLog 2001/12/25 06:50:51 1.4
@@ -9,3 +9,10 @@
2001-12-24 James Simmons <jsi...@us...>
* Removed ops field in uart_info. Instead use in in uart_port instead.
+2001-12-24 James Simmons <jsi...@us...>
+ * Synced to RMK latest changes. He removed the awful table, termios
+ stuff from struct uart_driver. This makes life easier for us :-)
+ He also implemented a struct uart_xxx_port that wraps around the
+ default struct uart_port. From my experience with the fbdev layer
+ this is a bad idea and will lead to really bad code. This must
+ change.
Index: serial_21285.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_21285.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- serial_21285.c 2001/12/25 04:29:59 1.8
+++ serial_21285.c 2001/12/25 06:50:51 1.9
@@ -54,9 +54,6 @@
#define H_UBRLCR_FIFO (1 << 4)
static struct tty_driver normal, callout;
-static struct tty_struct *serial21285_table[1];
-static struct termios *serial21285_termios[1];
-static struct termios *serial21285_termios_locked[1];
static const char serial21285_name[] = "Footbridge UART";
/*
@@ -471,9 +468,6 @@
normal_driver: &normal,
callout_major: SERIAL_21285_AUXMAJOR,
callout_driver: &callout,
- table: serial21285_table,
- termios: serial21285_termios,
- termios_locked: serial21285_termios_locked,
minor: SERIAL_21285_MINOR,
nr: 1,
port: &serial21285_port,
Index: serial_8250.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- serial_8250.c 2001/12/25 04:29:59 1.13
+++ serial_8250.c 2001/12/25 06:50:51 1.14
@@ -75,10 +75,7 @@
#define UART_NR ARRAY_SIZE(old_serial_port)
static struct tty_driver normal, callout;
-static struct tty_struct *serial8250_table[UART_NR];
-static struct termios *serial8250_termios[UART_NR], *serial8250_termios_locked[UART_NR];
#ifdef CONFIG_SERIAL_8250_CONSOLE
-static struct console serial8250_console;
static unsigned int lsr_break_flag;
#endif
static struct uart_info *IRQ_ports[NR_IRQS];
@@ -95,10 +92,13 @@
MODULE_PARM_DESC(force_rsa, "Force I/O ports for RSA");
#endif /* CONFIG_SERIAL_RSA */
-#define port_acr unused[0] /* 8bit */
-#define port_ier unused[1] /* 8bit */
-#define port_rev unused[2] /* 8bit */
-#define port_lcr unused[3] /* 8bit */
+struct uart_8250_port {
+ struct uart_port port;
+ u_char acr;
+ u_char ier;
+ u_char rev;
+ u_char lcr;
+};
/*
* Here we define the default xmit fifo size used for each type of UART.
@@ -182,12 +182,13 @@
static unsigned int serial_icr_read(struct uart_port *port, int offset)
{
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
unsigned int value;
- serial_icr_write(port, UART_ACR, port->port_acr | UART_ACR_ICRRD);
+ serial_icr_write(port, UART_ACR, up->acr | UART_ACR_ICRRD);
serial_out(port, UART_SCR, offset);
value = serial_in(port, UART_ICR);
- serial_icr_write(port, UART_ACR, port->port_acr);
+ serial_icr_write(port, UART_ACR, up->acr);
return value;
}
@@ -284,6 +285,7 @@
static void
autoconfig_startech_uarts(struct uart_port *port)
{
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
unsigned char scratch, scratch2, scratch3, scratch4;
/*
@@ -301,7 +303,7 @@
* (Ex...@is...) claims that it's needed for 952
* dual UART's (which are not recommended for new designs).
*/
- port->port_acr = 0;
+ up->acr = 0;
serial_out(port, UART_LCR, 0xBF);
serial_out(port, UART_EFR, 0x10);
serial_out(port, UART_LCR, 0x00);
@@ -314,8 +316,8 @@
(scratch3 == 0x50 || scratch3 == 0x52 ||
scratch3 == 0x54)) {
port->type = PORT_16C950;
- port->port_rev = serial_icr_read(port, UART_REV) |
- (scratch3 << 8);
+ up->rev = serial_icr_read(port, UART_REV) |
+ (scratch3 << 8);
return;
}
}
@@ -343,7 +345,7 @@
if (scratch == 0x10 || scratch == 0x12 || scratch == 0x14) {
if (scratch == 0x10)
- port->port_rev = scratch2;
+ up->rev = scratch2;
port->type = PORT_16850;
return;
}
@@ -624,42 +626,50 @@
static void serial8250_stop_tx(struct uart_port *port, u_int from_tty)
{
- if (port->port_ier & UART_IER_THRI) {
- port->port_ier &= ~UART_IER_THRI;
- serial_out(port, UART_IER, port->port_ier);
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
+
+ if (up->ier & UART_IER_THRI) {
+ up->ier &= ~UART_IER_THRI;
+ serial_out(port, UART_IER, up->ier);
}
if (port->type == PORT_16C950) {
- port->port_acr |= UART_ACR_TXDIS;
- serial_icr_write(port, UART_ACR, port->port_acr);
+ up->acr |= UART_ACR_TXDIS;
+ serial_icr_write(port, UART_ACR, up->acr);
}
}
static void serial8250_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
{
- if (nonempty && !(port->port_ier & UART_IER_THRI)) {
- port->port_ier |= UART_IER_THRI;
- serial_out(port, UART_IER, port->port_ier);
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
+
+ if (nonempty && !(up->ier & UART_IER_THRI)) {
+ up->ier |= UART_IER_THRI;
+ serial_out(port, UART_IER, up->ier);
}
/*
* We only do this from uart_start
*/
if (from_tty && port->type == PORT_16C950) {
- port->port_acr &= ~UART_ACR_TXDIS;
- serial_icr_write(port, UART_ACR, port->port_acr);
+ up->acr &= ~UART_ACR_TXDIS;
+ serial_icr_write(port, UART_ACR, up->acr);
}
}
static void serial8250_stop_rx(struct uart_port *port)
{
- port->port_ier &= ~UART_IER_RLSI;
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
+
+ up->ier &= ~UART_IER_RLSI;
port->read_status_mask &= ~UART_LSR_DR;
- serial_out(port, UART_IER, port->port_ier);
+ serial_out(port, UART_IER, up->ier);
}
static void serial8250_enable_ms(struct uart_port *port)
{
- port->port_ier |= UART_IER_MSI;
- serial_out(port, UART_IER, port->port_ier);
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
+
+ up->ier |= UART_IER_MSI;
+ serial_out(port, UART_IER, up->ier);
}
static _INLINE_ void
@@ -695,7 +705,7 @@
* may get masked by ignore_status_mask
* or read_status_mask.
*/
- uart_handle_break(info, &serial8250_console);
+ uart_handle_break(info, port->cons);
} else if (*status & UART_LSR_PE)
port->icount.parity++;
else if (*status & UART_LSR_FE)
@@ -709,7 +719,7 @@
*status &= port->read_status_mask;
#ifdef CONFIG_SERIAL_8250_CONSOLE
- if (port->line == serial8250_console.index) {
+ if (port->line == port->cons->index) {
/* Recover the break flag from console xmit */
*status |= lsr_break_flag;
lsr_break_flag = 0;
@@ -1085,21 +1095,24 @@
static void serial8250_break_ctl(struct uart_port *port, int break_state)
{
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
+
if (break_state == -1)
- port->port_lcr |= UART_LCR_SBC;
+ up->lcr |= UART_LCR_SBC;
else
- port->port_lcr &= ~UART_LCR_SBC;
- serial_out(port, UART_LCR, port->port_lcr);
+ up->lcr &= ~UART_LCR_SBC;
+ serial_out(port, UART_LCR, up->lcr);
}
static int serial8250_startup(struct uart_port *port, struct uart_info *info)
{
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
void (*handler)(int, void *, struct pt_regs *);
int retval;
if (port->type == PORT_16C950) {
/* Wake up and initialize UART */
- port->port_acr = 0;
+ up->acr = 0;
serial_outp(port, UART_LCR, 0xBF);
serial_outp(port, UART_EFR, UART_EFR_ECB);
serial_outp(port, UART_IER, 0);
@@ -1197,8 +1210,8 @@
* are set via change_speed(), which will be occuring imminently
* anyway, so we don't enable them here.
*/
- port->port_ier = UART_IER_RLSI | UART_IER_RDI;
- serial_outp(port, UART_IER, port->port_ier);
+ up->ier = UART_IER_RLSI | UART_IER_RDI;
+ serial_outp(port, UART_IER, up->ier);
#ifdef CONFIG_SERIAL_MANY_PORTS
if (port->flags & ASYNC_FOURPORT) {
@@ -1225,6 +1238,7 @@
static void serial8250_shutdown(struct uart_port *port, struct uart_info *info)
{
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
struct uart_info **infop;
int retval;
@@ -1256,7 +1270,7 @@
/*
* Disable all intrs
*/
- port->port_ier = 0;
+ up->ier = 0;
serial_outp(port, UART_IER, 0);
/*
@@ -1286,6 +1300,7 @@
static void serial8250_change_speed(struct uart_port *port, u_int cflag, u_int iflag, u_int quot)
{
+ struct uart_8250_port *up = (struct uart_8250_port *)port;
unsigned char cval, fcr = 0;
unsigned long flags;
@@ -1314,7 +1329,7 @@
* when DLL is 0.
*/
if ((quot & 0xff) == 0 && port->type == PORT_16C950 &&
- port->port_rev == 0x5201)
+ up->rev == 0x5201)
quot ++;
if (uart_config[port->type].flags & UART_USE_FIFO) {
@@ -1361,17 +1376,17 @@
/*
* CTS flow control flag and modem status interrupts
*/
- port->port_ier &= ~UART_IER_MSI;
+ up->ier &= ~UART_IER_MSI;
if (port->flags & ASYNC_HARDPPS_CD || cflag & CRTSCTS ||
!(cflag & CLOCAL))
- port->port_ier |= UART_IER_MSI;
+ up->ier |= UART_IER_MSI;
/*
* Ok, we're now changing the port state. Do it with
* interrupts disabled.
*/
save_flags(flags); cli();
- serial_out(port, UART_IER, port->port_ier);
+ serial_out(port, UART_IER, up->ier);
if (uart_config[port->type].flags & UART_STARTECH) {
serial_outp(port, UART_LCR, 0xBF);
@@ -1383,7 +1398,7 @@
if (port->type == PORT_16750)
serial_outp(port, UART_FCR, fcr); /* set fcr */
serial_outp(port, UART_LCR, cval); /* reset DLAB */
- port->port_lcr = cval; /* Save LCR */
+ up->lcr = cval; /* Save LCR */
if (port->type != PORT_16750) {
if (fcr & UART_FCR_ENABLE_FIFO) {
/* emulated UARTs (Lucent Venus 167x) need two steps */
@@ -1655,7 +1670,7 @@
verify_port: serial8250_verify_port,
};
-static struct uart_port serial8250_ports[UART_NR];
+static struct uart_8250_port serial8250_ports[UART_NR];
static void __init serial8250_isa_init_ports(void)
{
@@ -1667,14 +1682,26 @@
first = 0;
for (i = 0; i < ARRAY_SIZE(old_serial_port); i++) {
- serial8250_ports[i].iobase = old_serial_port[i].port;
- serial8250_ports[i].irq = irq_cannonicalize(old_serial_port[i].irq);
- serial8250_ports[i].uartclk = old_serial_port[i].base_baud * 16;
- serial8250_ports[i].flags = old_serial_port[i].flags;
- serial8250_ports[i].ops = &serial8250_pops;
+ serial8250_ports[i].port.iobase = old_serial_port[i].port;
+ serial8250_ports[i].port.irq = irq_cannonicalize(old_serial_port[i].irq);
+ serial8250_ports[i].port.uartclk = old_serial_port[i].base_baud * 16;
+ serial8250_ports[i].port.flags = old_serial_port[i].flags;
+ serial8250_ports[i].port.ops = &serial8250_pops;
}
}
+static void __init serial8250_register_ports(struct uart_driver *drv)
+{
+ int i;
+
+ serial8250_isa_init_ports();
+
+ for (i = 0; i < UART_NR; i++) {
+ serial8250_ports[i].port.line = i;
+ uart_add_one_port(drv, &serial8250_ports[i].port);
+ }
+}
+
#ifdef CONFIG_SERIAL_8250_CONSOLE
#ifdef used_and_not_const_char_pointer
static int serial8250_console_read(struct uart_port *port, char *s, u_int count)
@@ -1717,7 +1744,7 @@
*/
static void serial8250_console_write(struct console *co, const char *s, u_int count)
{
- struct uart_port *port = serial8250_ports + co->index;
+ struct uart_port *port = &serial8250_ports[co->index].port;
unsigned int ier;
int i;
@@ -1759,7 +1786,7 @@
static int serial8250_console_wait_key(struct console *co)
{
- struct uart_port *port = serial8250_ports + co->index;
+ struct uart_port *port = &serial8250_ports[co->index].port;
int ier, c;
/*
@@ -1794,11 +1821,15 @@
* if so, search for the first available port that does have
* console support.
*/
+#if 0
port = uart_get_console(serial8250_ports, UART_NR, co);
-
+#else
+ if (co->index >= UART_NR)
+ co->index = 0;
+ port = &serial8250_ports[co->index].port;
+#endif
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
-
return uart_set_options(port, co, baud, parity, bits, flow);
}
@@ -1839,12 +1870,8 @@
callout_major: TTYAUX_MAJOR,
normal_driver: &normal,
callout_driver: &callout,
- table: serial8250_table,
- termios: serial8250_termios,
- termios_locked: serial8250_termios_locked,
minor: 64,
- nr: ARRAY_SIZE(old_serial_port),
- port: serial8250_ports,
+ nr: UART_NR,
cons: SERIAL8250_CONSOLE,
};
@@ -1883,6 +1910,7 @@
port->regshift = req->iomem_reg_shift;
port->iotype = req->io_type;
port->flags = req->flags | ASYNC_BOOT_AUTOCONF;
+ port->line = -1;
if (HIGH_BITS_OFFSET)
port->iobase |= req->port_high << HIGH_BITS_OFFSET;
@@ -1910,14 +1938,37 @@
uart_unregister_port(&serial8250_reg, line);
}
+/*
+ * This is for ISAPNP only.
+ */
+void serial8250_get_irq_map(int *map)
+{
+ int i;
+
+ for (i = 0; i < UART_NR; i++) {
+ if (serial8250_ports[i].port.type != PORT_UNKNOWN)
+ clear_bit(serial8250_ports[i].port.irq, map);
+ }
+}
+
static int __init serial8250_init(void)
{
- serial8250_isa_init_ports();
- return uart_register_driver(&serial8250_reg);
+ int ret;
+
+ ret = uart_register_driver(&serial8250_reg);
+ if (ret)
+ return ret;
+
+ serial8250_register_ports(&serial8250_reg);
+ return 0;
}
static void __exit serial8250_exit(void)
{
+ int i;
+
+ for (i = 0; i < UART_NR; i++)
+ uart_remove_one_port(&serial8250_reg,&serial8250_ports[i].port);
uart_unregister_driver(&serial8250_reg);
}
@@ -1926,7 +1977,7 @@
EXPORT_SYMBOL(register_serial);
EXPORT_SYMBOL(unregister_serial);
+EXPORT_SYMBOL(serial8250_get_irq_map);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
-
Index: serial_8250.h
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- serial_8250.h 2001/12/13 04:46:52 1.5
+++ serial_8250.h 2001/12/25 06:50:51 1.6
@@ -24,6 +24,7 @@
int serial8250_register_probe(struct serial8250_probe *probe);
void serial8250_unregister_probe(struct serial8250_probe *probe);
+void serial8250_get_irq_map(int *map);
struct old_serial_port {
unsigned int uart;
@@ -46,7 +47,7 @@
#endif
#endif
-#if defined(CONFIG_ISAPNP)|| (defined(CONFIG_ISAPNP_MODULE) && defined(MODULE))
+#ifdef __ISAPNP__
#ifndef ENABLE_SERIAL_PNP
#define ENABLE_SERIAL_PNP
#endif
Index: serial_8250_pci.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250_pci.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- serial_8250_pci.c 2001/12/25 04:29:59 1.13
+++ serial_8250_pci.c 2001/12/25 06:50:51 1.14
@@ -1078,4 +1078,4 @@
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
-//MODULE_GENERIC_TABLE(pci, serial_pci_tbl);
+MODULE_DEVICE_TABLE(pci, serial_pci_tbl);
Index: serial_8250_pnp.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_8250_pnp.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- serial_8250_pnp.c 2001/12/25 04:29:59 1.8
+++ serial_8250_pnp.c 2001/12/25 06:50:51 1.9
@@ -29,9 +29,6 @@
#include "serial_8250.h"
-static struct serial_state rs_table[] = { };
-#define NR_PORTS 0
-
struct pnpbios_device_id
{
char id[8];
@@ -312,16 +309,11 @@
static void inline avoid_irq_share(struct pci_dev *dev)
{
- int i, map = 0x1FF8;
- struct serial_state *state = rs_table;
struct isapnp_irq *irq;
struct isapnp_resources *res = dev->sysdata;
+ int map = 0x1FF8;
- for (i = 0; i < NR_PORTS; i++) {
- if (state->type != PORT_UNKNOWN)
- clear_bit(state->irq, &map);
- state++;
- }
+ serial8250_get_irq_map(&map);
for ( ; res; res = res->alt)
for(irq = res->irq; irq; irq = irq->next)
@@ -549,5 +541,4 @@
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic 8250/16x50 PNPBIOS serial probe module");
-//MODULE_GENERIC_TABLE(pnp, pnp_dev_table);
-
+MODULE_DEVICE_TABLE(pnpbios, pnp_dev_table);
Index: serial_amba.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_amba.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- serial_amba.c 2001/12/25 04:29:59 1.11
+++ serial_amba.c 2001/12/25 06:50:51 1.12
@@ -78,11 +78,6 @@
#define CALLOUT_AMBA_NR UART_NR
static struct tty_driver normal, callout;
-static struct tty_struct *amba_table[UART_NR];
-static struct termios *amba_termios[UART_NR], *amba_termios_locked[UART_NR];
-#ifdef SUPPORT_SYSRQ
-static struct console amba_console;
-#endif
#define AMBA_ISR_PASS_LIMIT 256
@@ -120,17 +115,18 @@
* We encode this bit information into port->driver_priv using the
* following macros.
*/
-//#define PORT_CTRLS(dtrbit,rtsbit) ((1 << dtrbit) | (1 << (16 + rtsbit)))
-#define PORT_CTRLS_DTR(port) (1 << (port)->unused[1])
-#define PORT_CTRLS_RTS(port) (1 << (port)->unused[0])
-
#define SC_CTRLC (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLC_OFFSET)
#define SC_CTRLS (IO_ADDRESS(INTEGRATOR_SC_BASE) + INTEGRATOR_SC_CTRLS_OFFSET)
/*
- * Our private driver data mappings.
+ * We wrap our port structure around the generic uart_port.
*/
-#define drv_old_status driver_priv
+struct uart_amba_port {
+ struct uart_port port;
+ u_int dtr_mask;
+ u_int rts_mask;
+ u_int old_status;
+};
static void ambauart_stop_tx(struct uart_port *port, u_int from_tty)
{
@@ -206,7 +202,7 @@
if (rsr & AMBA_UARTRSR_BE) {
rsr &= ~(AMBA_UARTRSR_FE | AMBA_UARTRSR_PE);
port->icount.brk++;
- if (uart_handle_break(info, &amba_console))
+ if (uart_handle_break(info, port->cons))
goto ignore_char;
} else if (rsr & AMBA_UARTRSR_PE)
port->icount.parity++;
@@ -288,15 +284,16 @@
static void ambauart_modem_status(struct uart_info *info)
{
+ struct uart_amba_port *uap = (struct uart_amba_port *)info->port;
struct uart_port *port = info->port;
unsigned int status, delta;
- UART_PUT_ICR(port, 0);
+ UART_PUT_ICR(&uap->port, 0);
- status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY;
+ status = UART_GET_FR(&uap->port) & AMBA_UARTFR_MODEM_ANY;
- delta = status ^ info->drv_old_status;
- info->drv_old_status = status;
+ delta = status ^ uap->old_status;
+ uap->old_status = status;
if (!delta)
return;
@@ -362,17 +359,18 @@
static void ambauart_set_mctrl(struct uart_port *port, u_int mctrl)
{
+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
u_int ctrls = 0, ctrlc = 0;
if (mctrl & TIOCM_RTS)
- ctrlc |= PORT_CTRLS_RTS(port);
+ ctrlc |= uap->rts_mask;
else
- ctrls |= PORT_CTRLS_RTS(port);
+ ctrls |= uap->rts_mask;
if (mctrl & TIOCM_DTR)
- ctrlc |= PORT_CTRLS_DTR(port);
+ ctrlc |= uap->dtr_mask;
else
- ctrls |= PORT_CTRLS_DTR(port);
+ ctrls |= uap->dtr_mask;
__raw_writel(ctrls, SC_CTRLS);
__raw_writel(ctrlc, SC_CTRLC);
@@ -392,6 +390,7 @@
static int ambauart_startup(struct uart_port *port, struct uart_info *info)
{
+ struct uart_amba_port *uap = (struct uart_amba_port *)port;
int retval;
/*
@@ -404,7 +403,7 @@
/*
* initialise the old status of the modem signals
*/
- info->drv_old_status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY;
+ uap->old_status = UART_GET_FR(port) & AMBA_UARTFR_MODEM_ANY;
/*
* Finally, enable interrupts
@@ -578,28 +577,36 @@
verify_port: ambauart_verify_port,
};
-static struct uart_port amba_ports[UART_NR] = {
+static struct uart_amba_port amba_ports[UART_NR] = {
{
- membase: (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
- mapbase: INTEGRATOR_UART0_BASE,
- iotype: SERIAL_IO_MEM,
- irq: IRQ_UARTINT0,
- uartclk: 14745600,
- fifosize: 16,
- unused: { 4, 5 }, /*driver_priv: PORT_CTRLS(5, 4), */
- ops: &amba_pops,
- flags: ASYNC_BOOT_AUTOCONF,
+ port: {
+ membase: (void *)IO_ADDRESS(INTEGRATOR_UART0_BASE),
+ mapbase: INTEGRATOR_UART0_BASE,
+ iotype: SERIAL_IO_MEM,
+ irq: IRQ_UARTINT0,
+ uartclk: 14745600,
+ fifosize: 16,
+ unused: { 4, 5 }, /*driver_priv: PORT_CTRLS(5, 4), */
+ ops: &amba_pops,
+ flags: ASYNC_BOOT_AUTOCONF,
+ },
+ dtr_mask: 1 << 5,
+ rts_mask: 1 << 4,
},
{
- membase: (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
- mapbase: INTEGRATOR_UART1_BASE,
- iotype: SERIAL_IO_MEM,
- irq: IRQ_UARTINT1,
- uartclk: 14745600,
- fifosize: 16,
- unused: { 6, 7 }, /*driver_priv: PORT_CTRLS(7, 6), */
- ops: &amba_pops,
- flags: ASYNC_BOOT_AUTOCONF,
+ port: {
+ membase: (void *)IO_ADDRESS(INTEGRATOR_UART1_BASE),
+ mapbase: INTEGRATOR_UART1_BASE,
+ iotype: SERIAL_IO_MEM,
+ irq: IRQ_UARTINT1,
+ uartclk: 14745600,
+ fifosize: 16,
+ unused: { 6, 7 }, /*driver_priv: PORT_CTRLS(7, 6), */
+ ops: &amba_pops,
+ flags: ASYNC_BOOT_AUTOCONF,
+ },
+ dtr_mask: 1 << 7,
+ rts_mask: 1 << 6,
}
};
@@ -631,7 +638,7 @@
static void ambauart_console_write(struct console *co, const char *s, u_int count)
{
- struct uart_port *port = amba_ports + co->index;
+ struct uart_port *port = &amba_ports[co->index].port;
unsigned int status, old_cr;
int i;
@@ -674,7 +681,7 @@
static int ambauart_console_wait_key(struct console *co)
{
- struct uart_port *port = amba_ports + co->index;
+ struct uart_port *port = &amba_ports[co->index].port;
unsigned int status;
do {
@@ -721,8 +728,14 @@
* if so, search for the first available port that does have
* console support.
*/
+#if 0
port = uart_get_console(amba_ports, UART_NR, co);
-
+#else
+ if (co->index >= UART_NR)
+ co->index = 0;
+ port = &amba_ports[co->index].port;
+#endif
+
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
@@ -767,22 +780,32 @@
normal_driver: &normal,
callout_major: CALLOUT_AMBA_MAJOR,
callout_driver: &callout,
- table: amba_table,
- termios: amba_termios,
- termios_locked: amba_termios_locked,
minor: SERIAL_AMBA_MINOR,
nr: UART_NR,
- port: amba_ports,
cons: AMBA_CONSOLE,
};
static int __init ambauart_init(void)
{
- return uart_register_driver(&amba_reg);
+ int ret;
+
+ ret = uart_register_driver(&amba_reg);
+ if (ret == 0) {
+ int i;
+
+ for (i = 0; i < UART_NR; i++)
+ uart_add_one_port(&amba_reg, &amba_ports[i].port);
+ }
+ return ret;
}
static void __exit ambauart_exit(void)
{
+ int i;
+
+ for (i = 0; i < UART_NR; i++)
+ uart_remove_one_port(&amba_reg, &amba_ports[i].port);
+
uart_unregister_driver(&amba_reg);
}
Index: serial_anakin.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_anakin.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- serial_anakin.c 2001/12/25 04:29:59 1.4
+++ serial_anakin.c 2001/12/25 06:50:51 1.5
@@ -64,11 +64,13 @@
#define CALLOUT_ANAKIN_MINOR 32
static struct tty_driver normal, callout;
-static struct tty_struct *anakin_table[UART_NR];
-static struct termios *anakin_termios[UART_NR], *anakin_termios_locked[UART_NR];
-static struct uart_state anakin_state[UART_NR];
static u_int txenable[NR_IRQS]; /* Software interrupt register */
+struct uart_anakin_port {
+ struct uart_port port;
+ struct uart_info *info;
+};
+
static inline unsigned int
anakin_in(struct uart_port *port, u_int offset)
{
@@ -112,6 +114,7 @@
static void
anakin_start_tx(struct uart_port *port, u_int nonempty, u_int from_tty)
{
+ struct uart_anakin_port *up = (struct uart_anakin_port *)port;
unsigned int flags;
save_flags_cli(flags);
@@ -121,7 +124,7 @@
txenable[port->irq] = TXENABLE;
if ((anakin_in(port, 0x10) & TXEMPTY) && nonempty) {
- anakin_transmit_buffer(port);
+ anakin_transmit_buffer(up->port);
}
}
restore_flags(flags);
@@ -273,8 +276,9 @@
static int
anakin_startup(struct uart_port *port, struct uart_info *info)
{
- int retval;
+ struct uart_anakin_port *up = (struct uart_anakin_port *)port;
unsigned int read,write;
+ int retval;
/*
* Allocate the IRQ
@@ -300,8 +304,7 @@
/* Store the uart_info pointer so we can reference it in
* anakin_start_tx() */
- port->unused = (u_int)info;
-
+ up->info = info;
return 0;
}
@@ -354,41 +357,51 @@
type: anakin_type,
};
-static struct uart_port anakin_ports[UART_NR] = {
+static struct uart_anakin_port anakin_ports[UART_NR] = {
{
- base: IO_BASE + UART0,
- irq: IRQ_UART0,
- uartclk: 3686400,
- fifosize: 0,
- ops: &anakin_pops,
+ port: {
+ base: IO_BASE + UART0,
+ irq: IRQ_UART0,
+ uartclk: 3686400,
+ fifosize: 0,
+ ops: &anakin_pops,
+ },
},
{
- base: IO_BASE + UART1,
- irq: IRQ_UART1,
- uartclk: 3686400,
- fifosize: 0,
- ops: &anakin_pops,
+ port: {
+ base: IO_BASE + UART1,
+ irq: IRQ_UART1,
+ uartclk: 3686400,
+ fifosize: 0,
+ ops: &anakin_pops,
+ },
},
{
- base: IO_BASE + UART2,
- irq: IRQ_UART2,
- uartclk: 3686400,
- fifosize: 0,
- ops: &anakin_pops,
+ port: {
+ base: IO_BASE + UART2,
+ irq: IRQ_UART2,
+ uartclk: 3686400,
+ fifosize: 0,
+ ops: &anakin_pops,
+ },
},
{
- base: IO_BASE + UART3,
- irq: IRQ_UART3,
- uartclk: 3686400,
- fifosize: 0,
- ops: &anakin_pops,
+ port: {
+ base: IO_BASE + UART3,
+ irq: IRQ_UART3,
+ uartclk: 3686400,
+ fifosize: 0,
+ ops: &anakin_pops,
+ },
},
{
- base: IO_BASE + UART4,
- irq: IRQ_UART4,
- uartclk: 3686400,
- fifosize: 0,
- ops: &anakin_pops,
+ port: {
+ base: IO_BASE + UART4,
+ irq: IRQ_UART4,
+ uartclk: 3686400,
+ fifosize: 0,
+ ops: &anakin_pops,
+ },
},
};
@@ -398,7 +411,7 @@
static void
anakin_console_write(struct console *co, const char *s, u_int count)
{
- struct uart_port *port = anakin_ports + co->index;
+ struct uart_port *port = &anakin_ports[co->index].port;
unsigned int flags, status, i;
/*
@@ -436,10 +449,11 @@
*/
while (!(anakin_in(port, 0x10) & TXEMPTY));
- if (status & IRQENABLE)
+ if (status & IRQENABLE) {
save_flags_cli(flags);
anakin_out(port, 0x18, anakin_in(port, 0x18) | IRQENABLE);
restore_flags(flags);
+ }
}
static kdev_t
@@ -451,7 +465,7 @@
static int
anakin_console_wait_key(struct console *co)
{
- struct uart_port *port = anakin_ports + co->index;
+ struct uart_port *port = &anakin_ports[co->index].port;
unsigned int flags, status, ch;
save_flags_cli(flags);
@@ -501,7 +515,13 @@
* if so, search for the first available port that does have
* console support.
*/
+#if 0
port = uart_get_console(anakin_ports, UART_NR, co);
+#else
+ if (co->index >= UART_NR)
+ co->index = 0;
+ port = &anakin_ports[co->index].port;
+#endif
if (options)
uart_parse_options(options, &baud, &parity, &bits);
@@ -539,20 +559,24 @@
callout_major: CALLOUT_ANAKIN_MAJOR,
callout_name: CALLOUT_ANAKIN_NAME,
callout_driver: &callout,
- table: anakin_table,
- termios: anakin_termios,
- termios_locked: anakin_termios_locked,
minor: SERIAL_ANAKIN_MINOR,
nr: UART_NR,
- state: anakin_state,
- port: anakin_ports,
cons: ANAKIN_CONSOLE,
};
static int __init
anakin_init(void)
{
- return uart_register_port(&anakin_reg);
+ int ret;
+
+ ret = uart_register_driver(&anakin_reg);
+ if (ret == 0) {
+ int i;
+
+ for (i = 0; i < UART_NR; i++)
+ uart_add_one_port(&anakin_reg, &anakin_ports[i].port);
+ }
+ return ret;
}
__initcall(anakin_init);
Index: serial_clps711x.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_clps711x.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- serial_clps711x.c 2001/12/25 04:29:59 1.11
+++ serial_clps711x.c 2001/12/25 06:50:51 1.12
@@ -59,19 +59,17 @@
#define UART_NR 2
-#define SERIAL_CLPS711X_NAME "ttyAM"
+#define SERIAL_CLPS711X_NAME "ttyCL"
#define SERIAL_CLPS711X_MAJOR 204
-#define SERIAL_CLPS711X_MINOR 16
+#define SERIAL_CLPS711X_MINOR 40
#define SERIAL_CLPS711X_NR UART_NR
-#define CALLOUT_CLPS711X_NAME "cuaam"
+#define CALLOUT_CLPS711X_NAME "cuacl"
#define CALLOUT_CLPS711X_MAJOR 205
-#define CALLOUT_CLPS711X_MINOR 16
+#define CALLOUT_CLPS711X_MINOR 40
#define CALLOUT_CLPS711X_NR UART_NR
static struct tty_driver normal, callout;
-static struct tty_struct *clps711x_table[UART_NR];
-static struct termios *clps711x_termios[UART_NR], *clps711x_termios_locked[UART_NR];
/*
* We use the relevant SYSCON register as a base address for these ports.
@@ -661,10 +659,6 @@
normal_driver: &normal,
callout_major: CALLOUT_CLPS711X_MAJOR,
callout_driver: &callout,
-
- table: clps711x_table,
- termios: clps711x_termios,
- termios_locked: clps711x_termios_locked,
minor: SERIAL_CLPS711X_MINOR,
nr: UART_NR,
Index: serial_core.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_core.c,v
retrieving revision 1.18
retrieving revision 1.19
diff -u -d -r1.18 -r1.19
--- serial_core.c 2001/12/25 04:29:59 1.18
+++ serial_core.c 2001/12/25 06:50:51 1.19
@@ -831,7 +831,8 @@
* from incrementing, and hence any extra opens
* of the port while we're auto-configging.
*/
- down(&info->state->count_sem);
+ if (down_interruptible(&info->state->count_sem))
+ return -ERESTARTSYS;
ret = -EBUSY;
if (info->state->count == 1) {
@@ -1348,38 +1349,38 @@
static struct uart_info *uart_get(struct uart_driver *drv, int line)
{
struct uart_state *state = drv->state + line;
- struct uart_info *info;
+ struct uart_info *info = NULL;
down(&state->count_sem);
- state->count++;
- if (state->info)
+ if (!state->port)
goto out;
- info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
- if (info) {
- memset(info, 0, sizeof(struct uart_info));
- init_waitqueue_head(&info->open_wait);
- init_waitqueue_head(&info->close_wait);
- init_waitqueue_head(&info->delta_msr_wait);
- info->port = state->port;
- info->flags = info->port->flags;
- info->state = state;
- tasklet_init(&info->tlet, uart_tasklet_action,
- (unsigned long)info);
+ state->count++;
+ info = state->info;
+
+ if (!info) {
+ info = kmalloc(sizeof(struct uart_info), GFP_KERNEL);
+ if (info) {
+ memset(info, 0, sizeof(struct uart_info));
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
+ init_waitqueue_head(&info->delta_msr_wait);
+ info->port = state->port;
+ info->flags = info->port->flags;
+ info->state = state;
+ tasklet_init(&info->tlet, uart_tasklet_action,
+ (unsigned long)info);
+ state->info = info;
+ } else
+ state->count--;
}
- if (state->info)
- kfree(info);
- else
- state->info = info;
out:
up(&state->count_sem);
- return state->info;
+ return info;
}
/*
- * Make sure we have the temporary buffer allocated. Note
- * that we set retval appropriately above, and we rely on
- * this.
+ * Make sure we have the temporary buffer allocated.
*/
static inline int uart_alloc_tmpbuf(void)
{
@@ -1411,23 +1412,44 @@
printk("uart_open(%d) called\n", line);
#endif
+ /*
+ * tty->driver.num won't change, so we won't fail here with
+ * tty->driver_data set to something non-NULL (and therefore
+ * we won't get caught by uart_close()).
+ */
retval = -ENODEV;
if (line >= tty->driver.num)
goto fail;
- if (!try_inc_mod_count(drv->owner))
+ /*
+ * If we fail to increment the module use count, we can't have
+ * any other users of this tty (since this implies that the module
+ * is about to be unloaded). Therefore, it is safe to set
+ * tty->driver_data to be NULL, so uart_close() doesn't bite us.
+ */
+ if (!try_inc_mod_count(drv->owner)) {
+ tty->driver_data = NULL;
goto fail;
+ }
+ /*
+ * FIXME: This one isn't fun. We can't guarantee that the tty isn't
+ * already in open, nor can we guarantee the state of tty->driver_data
+ */
info = uart_get(drv, line);
retval = -ENOMEM;
- if (!info)
- goto out;
+ if (!info) {
+ if (tty->driver_data)
+ goto out;
+ else
+ goto fail;
+ }
/*
- * Set the tty driver_data. If we fail from this point on,
- * the generic tty layer will cause uart_close(), which will
- * decrement the module use count.
- */
+ * Once we set tty->driver_data here, we are guaranteed that
+ * uart_close() will decrement the driver module use count.
+ * Any failures from here onwards should not touch the count.
+ */
tty->driver_data = info;
info->tty = tty;
info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
@@ -1485,7 +1507,7 @@
* Copy across the serial console cflag setting
*/
{
- struct console *c = drv->cons;
+ struct console *c = info->port->cons;
if (c && c->cflag && c->index == line) {
tty->termios->c_cflag = c->cflag;
c->cflag = 0;
@@ -1767,7 +1789,7 @@
int running = state->info &&
state->info->flags & ASYNC_INITIALIZED;
- if (port->type == PORT_UNKNOWN)
+ if (!port || port->type == PORT_UNKNOWN)
return 0;
//printk("pm: %08x: %d -> %d, %srunning\n", port->iobase, dev->state, pm_state, running ? "" : "not ");
@@ -1785,8 +1807,8 @@
/*
* Re-enable the console device after suspending.
*/
- if (state->cons && state->cons->index == port->line)
- state->cons->flags |= CON_ENABLED;
+ if (port->cons && port->cons->index == port->line)
+ port->cons->flags |= CON_ENABLED;
} else if (pm_state == 1) {
if (ops->pm)
ops->pm(port, pm_state, oldstate);
@@ -1794,8 +1816,8 @@
/*
* Disable the console device before suspending.
*/
- if (state->cons && state->cons->index == port->line)
- state->cons->flags &= ~CON_ENABLED;
+ if (port->cons && port->cons->index == port->line)
+ port->cons->flags &= ~CON_ENABLED;
if (running) {
ops->stop_tx(port, 0);
@@ -1860,24 +1882,15 @@
}
static void
-uart_setup_port(struct uart_driver *drv, struct uart_state *state)
+__uart_register_port(struct uart_driver *drv, struct uart_state *state,
+ struct uart_port *port)
{
- struct uart_port *port = state->port;
- int flags = UART_CONFIG_TYPE;
-
- init_MUTEX(&state->count_sem);
-
- state->close_delay = 5 * HZ / 10;
- state->closing_wait = 30 * HZ;
+ u_int flags;
+ state->port = port;
+
port->type = PORT_UNKNOWN;
-
-#ifdef CONFIG_PM
- state->cons = drv->cons;
- state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);
- if (state->pm)
- state->pm->data = state;
-#endif
+ port->cons = drv->cons;
/*
* If there isn't a port here, don't do anything further.
@@ -1889,39 +1902,80 @@
* Now do the auto configuration stuff. Note that config_port
* is expected to claim the resources and map the port for us.
*/
+ flags = UART_CONFIG_TYPE;
if (port->flags & ASYNC_AUTO_IRQ)
flags |= UART_CONFIG_IRQ;
if (port->flags & ASYNC_BOOT_AUTOCONF)
port->ops->config_port(port, flags);
/*
- * Only register this port if it is detected.
+ * Register the port whether it's detected or not. This allows
+ * setserial to be used to alter this ports parameters.
*/
+ tty_register_devfs(drv->normal_driver, 0, drv->minor + port->line);
+ tty_register_devfs(drv->callout_driver, 0, drv->minor + port->line);
+
if (port->type != PORT_UNKNOWN) {
- tty_register_devfs(drv->normal_driver, 0, drv->minor +
- state->port->line);
- tty_register_devfs(drv->callout_driver, 0, drv->minor +
- state->port->line);
uart_report_port(drv, port);
- }
#ifdef CONFIG_PM
+ /*
+ * Power down all ports by default, except
+ * the console if we have one.
+ */
+ if (state->pm && (!drv->cons || port->line != drv->cons->index))
+ pm_send(state->pm, PM_SUSPEND, (void *)3);
+#endif
+ }
+}
+
+/*
+ * This reverses the affects of __uart_register_port.
+ */
+static void
+__uart_unregister_port(struct uart_driver *drv, struct uart_state *state)
+{
+ struct uart_port *port = state->port;
+
/*
- * Power down all ports by default, except the console if we have one.
+ * Hang up the line to kill all usage of this port.
+ */
+ if (state->info && state->info->tty)
+ tty_hangup(state->info->tty);
+
+ /*
+ * Remove the devices from devfs
*/
- if (state->pm && (!drv->cons || port->line != drv->cons->index))
- pm_send(state->pm, PM_SUSPEND, (void *)3);
-#endif
+ tty_unregister_devfs(drv->normal_driver, drv->minor + port->line);
+ tty_unregister_devfs(drv->callout_driver, drv->minor + port->line);
+
+ /*
+ * Free the ports resources, if any.
+ */
+ if (port->type != PORT_UNKNOWN)
+ port->ops->release_port(port);
+
+ /*
+ * Indicate that there isn't a port here anymore.
+ */
+ port->type = PORT_UNKNOWN;
+
+ /*
+ * Kill the tasklet, and free resources.
+ */
+ if (state->info) {
+ tasklet_kill(&state->info->tlet);
+ kfree(state->info);
+ }
}
/*
- * Register a set of ports with the core driver. Note that we don't
- * printk any information about the ports; that is up to the low level
- * driver to do if they so wish.
+ * Register a set of ports with the core driver.
*/
int uart_register_driver(struct uart_driver *drv)
{
struct tty_driver *normal, *callout;
+ struct termios **termios;
int i, retval;
if (drv->state)
@@ -1941,6 +1995,11 @@
memset(drv->state, 0, sizeof(struct uart_state) * drv->nr +
sizeof(int));
+ termios = kmalloc(sizeof(struct termios *) * drv->nr * 2 +
+ sizeof(struct tty_struct *) * drv->nr, GFP_KERNEL);
+ if (!termios)
+ goto out;
+
normal = drv->normal_driver;
callout = drv->callout_driver;
@@ -1956,9 +2015,9 @@
normal->init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;
normal->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
normal->refcount = (int *)(drv->state + drv->nr);
- normal->table = drv->table;
- normal->termios = drv->termios;
- normal->termios_locked = drv->termios_locked;
+ normal->termios = termios;
+ normal->termios_locked = termios + drv->nr;
+ normal->table = (struct tty_struct **)(termios + drv->nr * 2);
normal->driver_state = drv;
normal->open = uart_open;
@@ -1992,27 +2051,53 @@
callout->major = drv->callout_major;
callout->subtype = SERIAL_TYPE_CALLOUT;
callout->read_proc = NULL;
- callout->proc_entry = NULL;
+ /*
+ * Initialise the UART state(s).
+ */
for (i = 0; i < drv->nr; i++) {
struct uart_state *state = drv->state + i;
+ init_MUTEX(&state->count_sem);
state->callout_termios = callout->init_termios;
state->normal_termios = normal->init_termios;
- state->port = drv->port + i;
- state->port->line = i;
-
- uart_setup_port(drv, state);
- }
+ state->close_delay = 5 * HZ / 10;
+ state->closing_wait = 30 * HZ;
+#ifdef CONFIG_PM
+ state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);
+ if (state->pm)
+ state->pm->data = state;
+#endif
+ }
retval = tty_register_driver(normal);
- if (retval)
+ if (retval)
goto out;
retval = tty_register_driver(callout);
- if (retval)
+ if (retval) {
tty_unregister_driver(normal);
+ goto out;
+ }
+ /*
+ * And finally the port(s). This part will eventually
+ * become the responsibility of the low level drivers -
+ * and will allow the low level drivers to extend the
+ * uart_port structure in any way they see fit.
+ *
+ * Any drivers using this method should not set drv->port.
+ */
+ if (drv->port) {
+ printk("serial_core: driver %s uses obsolete registration\n",
+ drv->normal_name);
+ for (i = 0; i < drv->nr; i++) {
+ struct uart_port *port = drv->port + i;
+
+ port->line = i;
+ __uart_register_port(drv, drv->state + i, port);
+ }
+ }
out:
if (retval && drv->state)
kfree(drv->state);
@@ -2022,33 +2107,60 @@
void uart_unregister_driver(struct uart_driver *drv)
{
int i;
-
- for (i = 0; i < drv->nr; i++) {
- struct uart_state *state = drv->state + i;
- if (state->info && state->info->tty)
- tty_hangup(state->info->tty);
-
- pm_unregister(state->pm);
+ /*
+ * First, remove all ports. We only do this if the driver
+ * isn't using the new API (and therefore registering its own
+ * port structures).
+ */
+ if (drv->port) {
+ for (i = 0; i < drv->nr; i++) {
+ struct uart_state *state = drv->state + i;
+
+ __uart_unregister_port(drv, state);
+ }
+ }
- if (state->port->type != PORT_UNKNOWN)
- state->port->ops->release_port(state->port);
- if (state->info) {
- tasklet_kill(&state->info->tlet);
- kfree(state->info);
- }
- }
+ for (i = 0; i < drv->nr; i++)
+ pm_unregister(drv->state[i].pm);
tty_unregister_driver(drv->normal_driver);
tty_unregister_driver(drv->callout_driver);
kfree(drv->state);
+ kfree(drv->normal_driver->termios);
}
+int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)
+{
+ struct uart_state *state = drv->state + port->line;
+
+ down(&state->count_sem);
+ __uart_register_port(drv, state, port);
+ up(&state->count_sem);
+
+ return 0;
+}
+
+int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)
+{
+ struct uart_state *state = drv->state + port->line;
+
+ if (state->port != port)
+ printk(KERN_ALERT "Removing wrong port: %p != %p\n",
+ state->port, port);
+
+ down(&state->count_sem);
+ __uart_unregister_port(drv, state);
+ up(&state->count_sem);
+ return 0;
+}
+
static int uart_match_port(struct uart_port *port1, struct uart_port *port2)
{
if (port1->iotype != port2->iotype)
return 0;
+
switch (port1->iotype) {
case SERIAL_IO_PORT: return (port1->iobase == port2->iobase);
case SERIAL_IO_MEM: return (port1->membase == port2->membase);
@@ -2065,19 +2177,23 @@
* type of the port if ASYNC_BOOT_AUTOCONF is set, and detect the IRQ
* if ASYNC_AUTO_IRQ is set.
*
+ * We try to pick the same port for the same IO base address, so that
+ * when a modem is plugged in, unplugged and plugged back in, it gets
+ * allocated the same port.
+ *
* Returns negative error, or positive line number.
*/
int uart_register_port(struct uart_driver *drv, struct uart_port *port)
{
struct uart_state *state = NULL;
- int i, flags = UART_CONFIG_TYPE;
+ int i;
+ down(&port_sem);
/*
* First, find a port entry which matches. Note: if we do
* find a matching entry, and it has a non-zero use count,
* then we can't register the port.
*/
- down(&port_sem);
for (i = 0; i < drv->nr; i++) {
if (uart_match_port(drv->state[i].port, port)) {
down(&drv->state[i].count_sem);
@@ -2120,6 +2236,11 @@
}
}
+ /*
+ * Ok, we've found a line that we can use. We have taken the
+ * per-port semaphore, so we can release the global port
+ * semaphore now.
+ */
up(&port_sem);
if (!state)
@@ -2149,34 +2270,9 @@
state->port->regshift = port->regshift;
state->port->iotype = port->iotype;
state->port->flags = port->flags;
-
-#if 0 //def CONFIG_PM
- /* we have already registered the power management handlers */
- state->pm = pm_register(PM_SYS_DEV, PM_SYS_COM, uart_pm);
- if (state->pm) {
- state->pm->data = state;
-
- /*
- * Power down all ports by default, except
- * the console if we have one.
- */
- if (!drv->cons || state->port->line != drv->cons->index)
- pm_send(state->pm, PM_SUSPEND, (void *)3);
- }
-#endif
-
- if (state->port->flags & ASYNC_AUTO_IRQ)
- flags |= UART_CONFIG_IRQ;
- if (state->port->flags & ASYNC_BOOT_AUTOCONF)
- state->port->ops->config_port(state->port, flags);
-
- tty_register_devfs(drv->normal_driver, 0, drv->minor +
- state->port->line);
- tty_register_devfs(drv->callout_driver, 0, drv->minor +
- state->port->line);
-
- uart_report_port(drv, state->port);
+ state->port->line = drv->state - state;
+ __uart_register_port(drv, state, state->port);
up(&state->count_sem);
return i;
}
@@ -2197,36 +2293,7 @@
state = drv->state + line;
down(&state->count_sem);
- /*
- * The port has already gone. We have to hang up the line
- * to kill all usage of this port.
- */
- if (state->info && state->info->tty)
- tty_hangup(state->info->tty);
-
- /*
- * Free the ports resources, if any.
- */
- state->port->ops->release_port(state->port);
-
- /*
- * Indicate that there isn't a port here anymore.
- */
- state->port->type = PORT_UNKNOWN;
-
-#if 0 // not yet
- /*
- * No point in doing power management for hardware that
- * isn't present.
- */
- pm_unregister(state->pm);
-#endif
-
- /*
- * Remove the devices from devfs
- */
- tty_unregister_devfs(drv->normal_driver, drv->minor + line);
- tty_unregister_devfs(drv->callout_driver, drv->minor + line);
+ __uart_unregister_port(drv, state);
up(&state->count_sem);
}
Index: serial_sa1100.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_sa1100.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- serial_sa1100.c 2001/12/25 04:29:59 1.16
+++ serial_sa1100.c 2001/12/25 06:50:51 1.17
@@ -98,13 +98,8 @@
#define UART_PORT_SIZE 0x24
static struct tty_driver normal, callout;
-static struct tty_struct *sa1100_table[NR_PORTS];
-static struct termios *sa1100_termios[NR_PORTS], *sa1100_termios_locked[NR_PORTS];
static int (*sa1100_open)(struct uart_port *, struct uart_info *);
static void (*sa1100_close)(struct uart_port *, struct uart_info *);
-#ifdef SUPPORT_SYSRQ
-static struct console sa1100_console;
-#endif
/*
* interrupts disabled on entry
@@ -289,7 +284,7 @@
if (status & UTSR0_REB) {
#ifdef SUPPORT_SYSRQ
- if (port->line == sa1100_console.index &&
+ if (port->line == port->cons->index &&
!info->sysrq) {
info->sysrq = jiffies + HZ*5;
}
@@ -787,9 +782,6 @@
normal_driver: &normal,
callout_major: CALLOUT_SA1100_MAJOR,
callout_driver: &callout,
- table: sa1100_table,
- termios: sa1100_termios,
- termios_locked: sa1100_termios_locked,
minor: MINOR_START,
nr: NR_PORTS,
port: sa1100_ports,
Index: serial_uart00.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/serial/serial_uart00.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- serial_uart00.c 2001/12/25 04:29:59 1.4
+++ serial_uart00.c 2001/12/25 06:50:51 1.5
@@ -81,13 +81,8 @@
#define CALLOUT_UART00_MINOR 16 /* Temporary - will change in future */
#define CALLOUT_UART00_NR UART_NR
-
-
static struct tty_driver normal, callout;
-static struct tty_struct *uart00_table[UART_NR];
-static struct termios *uart00_termios[UART_NR], *uart00_termios_locked[UART_NR];
//static struct uart_state uart00_state[UART_NR];
-static struct console uart00_console;
#define UART00_ISR_PASS_LIMIT 256
@@ -187,7 +182,7 @@
port->icount.brk++;
#ifdef SUPPORT_SYSRQ
- if (uart_handle_break(info, &uart00_console))
+ if (uart_handle_break(info, port->cons))
goto ignore_char;
#endif
} else if (rds & UART_RDS_PE_MSK)
@@ -782,9 +777,6 @@
callout_major: CALLOUT_UART00_MAJOR,
callout_name: CALLOUT_UART00_NAME,
callout_driver: &callout,
- table: uart00_table,
- termios: uart00_termios,
- termios_locked: uart00_termios_locked,
minor: SERIAL_UART00_MINOR,
nr: UART_NR,
state: NULL,
|