diff options
-rw-r--r-- | sys/conf/files | 1 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu.h | 8 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_alpha.c | 16 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_amd64.c | 11 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_i386.c | 11 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_ia64.c | 54 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_pc98.c | 9 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_sparc64.c | 5 | ||||
-rw-r--r-- | sys/dev/uart/uart_subr.c | 247 |
9 files changed, 305 insertions, 57 deletions
diff --git a/sys/conf/files b/sys/conf/files index ae2a9ae..30cfa0b 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -748,6 +748,7 @@ dev/uart/uart_dev_i8251.c optional uart dev/uart/uart_dev_ns8250.c optional uart dev/uart/uart_dev_sab82532.c optional uart dev/uart/uart_dev_z8530.c optional uart +dev/uart/uart_subr.c optional uart dev/uart/uart_tty.c optional uart dev/ubsec/ubsec.c optional ubsec # diff --git a/sys/dev/uart/uart_cpu.h b/sys/dev/uart/uart_cpu.h index f124aa7..462eb59 100644 --- a/sys/dev/uart/uart_cpu.h +++ b/sys/dev/uart/uart_cpu.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Marcel Moolenaar + * Copyright (c) 2003, 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -46,6 +46,9 @@ extern struct uart_ops uart_ns8250_ops; extern struct uart_ops uart_sab82532_ops; extern struct uart_ops uart_z8530_ops; +extern bus_space_tag_t uart_bus_space_io; +extern bus_space_tag_t uart_bus_space_mem; + /* * Console and debug port device info. */ @@ -69,8 +72,9 @@ struct uart_devinfo { int uart_cpu_eqres(struct uart_bas *, struct uart_bas *); int uart_cpu_getdev(int, struct uart_devinfo *); +int uart_getenv(int, struct uart_devinfo *); -void uart_add_sysdev(struct uart_devinfo*); +void uart_add_sysdev(struct uart_devinfo *); /* * Operations for low-level access to the UART. Primarily for use diff --git a/sys/dev/uart/uart_cpu_alpha.c b/sys/dev/uart/uart_cpu_alpha.c index 1d78d6a..a3a132f 100644 --- a/sys/dev/uart/uart_cpu_alpha.c +++ b/sys/dev/uart/uart_cpu_alpha.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Marcel Moolenaar + * Copyright (c) 2003, 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> +bus_space_tag_t uart_bus_space_io; +bus_space_tag_t uart_bus_space_mem; + int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { @@ -52,6 +55,9 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) struct ctb *ctb; unsigned int i, ivar; + uart_bus_space_io = busspace_isa_io; + uart_bus_space_mem = busspace_isa_mem; + if (devtype == UART_DEV_CONSOLE) { ctb = (struct ctb *)(((caddr_t)hwrpb) + hwrpb->rpb_ctb_off); if (ctb->ctb_term_type != CTB_PRINTERPORT) @@ -59,7 +65,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) boothowto |= RB_SERIAL; di->ops = uart_ns8250_ops; di->bas.chan = 0; - di->bas.bst = busspace_isa_io; + di->bas.bst = uart_bus_space_io; if (bus_space_map(di->bas.bst, 0x3f8, 8, 0, &di->bas.bsh) != 0) return (ENXIO); di->bas.regshft = 0; @@ -71,6 +77,10 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) return (0); } + /* Check the environment. */ + if (uart_getenv(devtype, di) == 0) + return (0); + /* * Scan the hints. We only try units 0 to 3 (inclusive). This * covers the ISA legacy where 4 UARTs had their resources @@ -97,7 +107,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) */ di->ops = uart_ns8250_ops; di->bas.chan = 0; - di->bas.bst = busspace_isa_io; + di->bas.bst = uart_bus_space_io; if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0) continue; di->bas.regshft = 0; diff --git a/sys/dev/uart/uart_cpu_amd64.c b/sys/dev/uart/uart_cpu_amd64.c index be0f619..c0270ae 100644 --- a/sys/dev/uart/uart_cpu_amd64.c +++ b/sys/dev/uart/uart_cpu_amd64.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Marcel Moolenaar + * Copyright (c) 2003, 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,6 +36,9 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> +bus_space_tag_t uart_bus_space_io = AMD64_BUS_SPACE_IO; +bus_space_tag_t uart_bus_space_mem = AMD64_BUS_SPACE_MEM; + int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { @@ -48,6 +51,10 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) { unsigned int i, ivar; + /* Check the environment. */ + if (uart_getenv(devtype, di) == 0) + return (0); + /* * Scan the hints. We only try units 0 to 3 (inclusive). This * covers the ISA legacy where 4 UARTs had their resources @@ -76,7 +83,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) */ di->ops = uart_ns8250_ops; di->bas.chan = 0; - di->bas.bst = AMD64_BUS_SPACE_IO; + di->bas.bst = uart_bus_space_io; if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0) continue; di->bas.regshft = 0; diff --git a/sys/dev/uart/uart_cpu_i386.c b/sys/dev/uart/uart_cpu_i386.c index 30b6e3a..93ca770 100644 --- a/sys/dev/uart/uart_cpu_i386.c +++ b/sys/dev/uart/uart_cpu_i386.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Marcel Moolenaar + * Copyright (c) 2003, 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,6 +36,9 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> +bus_space_tag_t uart_bus_space_io = I386_BUS_SPACE_IO; +bus_space_tag_t uart_bus_space_mem = I386_BUS_SPACE_MEM; + int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { @@ -48,6 +51,10 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) { unsigned int i, ivar; + /* Check the environment. */ + if (uart_getenv(devtype, di) == 0) + return (0); + /* * Scan the hints. We only try units 0 to 3 (inclusive). This * covers the ISA legacy where 4 UARTs had their resources @@ -76,7 +83,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) */ di->ops = uart_ns8250_ops; di->bas.chan = 0; - di->bas.bst = I386_BUS_SPACE_IO; + di->bas.bst = uart_bus_space_io; if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0) continue; di->bas.regshft = 0; diff --git a/sys/dev/uart/uart_cpu_ia64.c b/sys/dev/uart/uart_cpu_ia64.c index eeaea3b..6c3f380 100644 --- a/sys/dev/uart/uart_cpu_ia64.c +++ b/sys/dev/uart/uart_cpu_ia64.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Marcel Moolenaar + * Copyright (c) 2003, 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> +bus_space_tag_t uart_bus_space_io = IA64_BUS_SPACE_IO; +bus_space_tag_t uart_bus_space_mem = IA64_BUS_SPACE_MEM; + static int dig64_to_uart_parity[] = { UART_PARITY_NONE, UART_PARITY_NONE, UART_PARITY_EVEN, UART_PARITY_ODD, UART_PARITY_MARK, UART_PARITY_SPACE @@ -57,7 +60,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) struct dig64_hcdp_table *tbl; struct dig64_hcdp_entry *ent; bus_addr_t addr; - unsigned int i, ivar; + unsigned int i; /* * Use the DIG64 HCDP table if present. @@ -80,7 +83,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) di->ops = uart_ns8250_ops; di->bas.chan = 0; di->bas.bst = (ent->address.addr_space == 0) - ? IA64_BUS_SPACE_MEM : IA64_BUS_SPACE_IO; + ? uart_bus_space_mem : uart_bus_space_io; if (bus_space_map(di->bas.bst, addr, 8, 0, &di->bas.bsh) != 0) continue; @@ -98,47 +101,6 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) /* FALLTHROUGH */ } - /* - * Scan the hints for backward compatibility. We only try units - * 0 to 3 (inclusive). This covers the ISA legacy where 4 UARTs - * had their resources predefined. - */ - for (i = 0; i < 4; i++) { - if (resource_int_value("uart", i, "flags", &ivar)) - continue; - if (devtype == UART_DEV_CONSOLE && !UART_FLAGS_CONSOLE(ivar)) - continue; - if (devtype == UART_DEV_DBGPORT && !UART_FLAGS_DBGPORT(ivar)) - continue; - /* - * We have a possible device. Make sure it's enabled and - * that we have an I/O port. - */ - if (resource_int_value("uart", i, "disabled", &ivar) == 0 && - ivar != 0) - continue; - if (resource_int_value("uart", i, "port", &ivar) != 0 || - ivar == 0) - continue; - /* - * Got it. Fill in the instance and return it. We only have - * ns8250 and successors on i386. - */ - di->ops = uart_ns8250_ops; - di->bas.chan = 0; - di->bas.bst = IA64_BUS_SPACE_IO; - if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0) - continue; - di->bas.regshft = 0; - di->bas.rclk = 0; - if (resource_int_value("uart", i, "baud", &ivar) != 0) - ivar = 0; - di->baudrate = ivar; - di->databits = 8; - di->stopbits = 1; - di->parity = UART_PARITY_NONE; - return (0); - } - - return (ENXIO); + /* Check the environment. */ + return (uart_getenv(devtype, di)); } diff --git a/sys/dev/uart/uart_cpu_pc98.c b/sys/dev/uart/uart_cpu_pc98.c index 4005a90..2446c4f 100644 --- a/sys/dev/uart/uart_cpu_pc98.c +++ b/sys/dev/uart/uart_cpu_pc98.c @@ -36,6 +36,9 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> +bus_space_tag_t uart_bus_space_io; +bus_space_tag_t uart_bus_space_mem; + int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { @@ -48,6 +51,10 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) { unsigned int i, ivar, flags; + /* Check the environment. */ + if (uart_getenv(devtype, di) == 0) + return (0); + /* * There are 2 built-in serial ports on pc98 hardware. The * first one is 8251 and the second one is I think an enhance @@ -81,7 +88,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) else di->ops = uart_i8251_ops; di->bas.chan = 0; - di->bas.bst = I386_BUS_SPACE_IO; + di->bas.bst = uart_bus_space_io; if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0) continue; di->bas.regshft = 0; diff --git a/sys/dev/uart/uart_cpu_sparc64.c b/sys/dev/uart/uart_cpu_sparc64.c index 0cada13..ea9c60d 100644 --- a/sys/dev/uart/uart_cpu_sparc64.c +++ b/sys/dev/uart/uart_cpu_sparc64.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 Marcel Moolenaar + * Copyright (c) 2003, 2004 Marcel Moolenaar * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$"); #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> +bus_space_tag_t uart_bus_space_io; +bus_space_tag_t uart_bus_space_mem; + static phandle_t uart_cpu_getdev_keyboard(phandle_t root); static struct bus_space_tag bst_store[3]; diff --git a/sys/dev/uart/uart_subr.c b/sys/dev/uart/uart_subr.c new file mode 100644 index 0000000..9a3cb85 --- /dev/null +++ b/sys/dev/uart/uart_subr.c @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2004 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <machine/bus.h> +#include <machine/vmparam.h> + +#include <dev/uart/uart.h> +#include <dev/uart/uart_cpu.h> + +#define UART_TAG_BR 0 +#define UART_TAG_CH 1 +#define UART_TAG_DB 2 +#define UART_TAG_DT 3 +#define UART_TAG_IO 4 +#define UART_TAG_MM 5 +#define UART_TAG_PA 6 +#define UART_TAG_RS 7 +#define UART_TAG_SB 8 +#define UART_TAG_XO 9 + +static bus_addr_t +uart_parse_addr(__const char **p) +{ + return (strtoul(*p, (char**)(uintptr_t)p, 0)); +} + +static long +uart_parse_long(__const char **p) +{ + return (strtol(*p, (char**)(uintptr_t)p, 0)); +} + +static int +uart_parse_parity(__const char **p) +{ + if (!strncmp(*p, "even", 4)) { + *p += 4; + return UART_PARITY_EVEN; + } + if (!strncmp(*p, "mark", 4)) { + *p += 4; + return UART_PARITY_MARK; + } + if (!strncmp(*p, "none", 4)) { + *p += 4; + return UART_PARITY_NONE; + } + if (!strncmp(*p, "odd", 3)) { + *p += 3; + return UART_PARITY_ODD; + } + if (!strncmp(*p, "space", 5)) { + *p += 5; + return UART_PARITY_SPACE; + } + return (-1); +} + +static int +uart_parse_tag(__const char **p) +{ + int tag; + + if ((*p)[0] == 'b' && (*p)[1] == 'r') { + tag = UART_TAG_BR; + goto out; + } + if ((*p)[0] == 'c' && (*p)[1] == 'h') { + tag = UART_TAG_CH; + goto out; + } + if ((*p)[0] == 'd' && (*p)[1] == 'b') { + tag = UART_TAG_DB; + goto out; + } + if ((*p)[0] == 'd' && (*p)[1] == 't') { + tag = UART_TAG_DT; + goto out; + } + if ((*p)[0] == 'i' && (*p)[1] == 'o') { + tag = UART_TAG_IO; + goto out; + } + if ((*p)[0] == 'm' && (*p)[1] == 'm') { + tag = UART_TAG_MM; + goto out; + } + if ((*p)[0] == 'p' && (*p)[1] == 'a') { + tag = UART_TAG_PA; + goto out; + } + if ((*p)[0] == 'r' && (*p)[1] == 's') { + tag = UART_TAG_RS; + goto out; + } + if ((*p)[0] == 's' && (*p)[1] == 'b') { + tag = UART_TAG_SB; + goto out; + } + if ((*p)[0] == 'x' && (*p)[1] == 'o') { + tag = UART_TAG_XO; + goto out; + } + return (-1); + +out: + *p += 2; + if ((*p)[0] != ':') + return (-1); + (*p)++; + return (tag); +} + +/* + * Parse a device specification. The specification is a list of attributes + * seperated by commas. Each attribute is a tag-value pair with the tag and + * value seperated by a colon. Supported tags are: + * + * br = Baudrate + * ch = Channel + * db = Data bits + * dt = Device type + * io = I/O port address + * mm = Memory mapped I/O address + * pa = Parity + * rs = Register shift + * sb = Stopbits + * xo = Device clock (xtal oscillator) + * + * The io and mm tags are mutually exclusive. + */ + +int +uart_getenv(int devtype, struct uart_devinfo *di) +{ + __const char *spec; + bus_addr_t addr = ~0U; + + /* + * Check the environment variables "hw.uart.console" and + * "hw.uart.dbgport". These variables, when present, specify + * which UART port is to be used as serial console or debug + * port (resp). + */ + if (devtype == UART_DEV_CONSOLE) + spec = getenv("hw.uart.console"); + else if (devtype == UART_DEV_DBGPORT) + spec = getenv("hw.uart.dbgport"); + else + return (ENXIO); + + /* Set defaults. */ + di->ops = uart_ns8250_ops; + di->bas.chan = 0; + di->bas.regshft = 0; + di->bas.rclk = 0; + di->baudrate = 0; + di->databits = 8; + di->stopbits = 1; + di->parity = UART_PARITY_NONE; + + /* Parse the attributes. */ + while (1) { + switch (uart_parse_tag(&spec)) { + case UART_TAG_BR: + di->baudrate = uart_parse_long(&spec); + break; + case UART_TAG_CH: + di->bas.chan = uart_parse_long(&spec); + break; + case UART_TAG_DB: + di->databits = uart_parse_long(&spec); + break; + case UART_TAG_DT: + return (EINVAL); /* XXX not yet implemented. */ + break; + case UART_TAG_IO: + di->bas.bst = uart_bus_space_io; + addr = uart_parse_addr(&spec); + break; + case UART_TAG_MM: + di->bas.bst = uart_bus_space_mem; + addr = uart_parse_addr(&spec); + break; + case UART_TAG_PA: + di->parity = uart_parse_parity(&spec); + break; + case UART_TAG_RS: + di->bas.regshft = uart_parse_long(&spec); + break; + case UART_TAG_SB: + di->stopbits = uart_parse_long(&spec); + break; + case UART_TAG_XO: + di->bas.rclk = uart_parse_long(&spec); + break; + default: + return (EINVAL); + } + if (*spec == '\0') + break; + if (*spec != ',') + return (EINVAL); + spec++; + } + + /* + * If we still have an invalid address, the specification must be + * missing an I/O port or memory address. We don't like that. + */ + if (addr == ~0U) + return (EINVAL); + /* XXX the size of the mapping depends on the UART class. */ + if (bus_space_map(di->bas.bst, addr, 8, 0, &di->bas.bsh) != 0) + return (EINVAL); + return (0); +} |