summaryrefslogtreecommitdiffstats
path: root/sys/dev/uart/uart_subr.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2007-04-02 22:00:22 +0000
committermarcel <marcel@FreeBSD.org>2007-04-02 22:00:22 +0000
commitf30daf4b49b0b9e3c8eeb46082244bf7a7f354ae (patch)
treeb3ad51f3cb65c3badfb015aea4f71d800157abb8 /sys/dev/uart/uart_subr.c
parent5f0f57215ba83757397d27e8dcc686612e48e921 (diff)
downloadFreeBSD-src-f30daf4b49b0b9e3c8eeb46082244bf7a7f354ae.zip
FreeBSD-src-f30daf4b49b0b9e3c8eeb46082244bf7a7f354ae.tar.gz
Don't expose the uart_ops structure directly, but instead have
it obtained through the uart_class structure. This allows us to declare the uart_class structure as weak and as such allows us to reference it even when it's not compiled-in. It also allows is to get the uart_ops structure by name, which makes it possible to implement the dt tag handling in uart_getenv(). The side-effect of all this is that we're using the uart_class structure more consistently which means that we now also have access to the size of the bus space block needed by the hardware when we map the bus space, eliminating any hardcoding.
Diffstat (limited to 'sys/dev/uart/uart_subr.c')
-rw-r--r--sys/dev/uart/uart_subr.c50
1 files changed, 44 insertions, 6 deletions
diff --git a/sys/dev/uart/uart_subr.c b/sys/dev/uart/uart_subr.c
index c9b6fe7..2cab825 100644
--- a/sys/dev/uart/uart_subr.c
+++ b/sys/dev/uart/uart_subr.c
@@ -48,12 +48,41 @@ __FBSDID("$FreeBSD$");
#define UART_TAG_SB 8
#define UART_TAG_XO 9
+static struct uart_class *uart_classes[] = {
+ &uart_ns8250_class,
+ &uart_sab82532_class,
+ &uart_z8530_class,
+};
+static size_t uart_nclasses = sizeof(uart_classes) / sizeof(uart_classes[0]);
+
static bus_addr_t
uart_parse_addr(__const char **p)
{
return (strtoul(*p, (char**)(uintptr_t)p, 0));
}
+static struct uart_class *
+uart_parse_class(struct uart_class *class, __const char **p)
+{
+ struct uart_class *uc;
+ const char *nm;
+ size_t len;
+ u_int i;
+
+ for (i = 0; i < uart_nclasses; i++) {
+ uc = uart_classes[i];
+ nm = uart_getname(uc);
+ if (nm == NULL || *nm == '\0')
+ continue;
+ len = strlen(nm);
+ if (strncmp(nm, *p, len) == 0) {
+ *p += len;
+ return (uc);
+ }
+ }
+ return (class);
+}
+
static long
uart_parse_long(__const char **p)
{
@@ -161,10 +190,18 @@ out:
*/
int
-uart_getenv(int devtype, struct uart_devinfo *di)
+uart_getenv(int devtype, struct uart_devinfo *di, struct uart_class *class)
{
__const char *spec;
bus_addr_t addr = ~0U;
+ int error;
+
+ /*
+ * All uart_class references are weak. Make sure the default
+ * device class has been compiled-in.
+ */
+ if (class == NULL)
+ return (ENXIO);
/*
* Check the environment variables "hw.uart.console" and
@@ -203,7 +240,7 @@ uart_getenv(int devtype, struct uart_devinfo *di)
di->databits = uart_parse_long(&spec);
break;
case UART_TAG_DT:
- return (EINVAL); /* XXX not yet implemented. */
+ class = uart_parse_class(class, &spec);
break;
case UART_TAG_IO:
di->bas.bst = uart_bus_space_io;
@@ -261,8 +298,9 @@ uart_getenv(int devtype, struct uart_devinfo *di)
} else
di->baudrate = 0;
- /* 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);
+ /* Set the ops and create a bus space handle. */
+ di->ops = uart_getops(class);
+ error = bus_space_map(di->bas.bst, addr, uart_getrange(class), 0,
+ &di->bas.bsh);
+ return (error);
}
OpenPOWER on IntegriCloud