aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMarcel Moolenaar <marcel@FreeBSD.org>2007-04-02 22:00:22 +0000
committerMarcel Moolenaar <marcel@FreeBSD.org>2007-04-02 22:00:22 +0000
commitf8100ce2a70db5c60672578fee913d986ac1cf01 (patch)
treeb3ad51f3cb65c3badfb015aea4f71d800157abb8 /sys/dev
parent1bdb3fb97eb936148ebd3be52850c09ae7f72260 (diff)
downloadsrc-f8100ce2a70db5c60672578fee913d986ac1cf01.tar.gz
src-f8100ce2a70db5c60672578fee913d986ac1cf01.zip
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.
Notes
Notes: svn path=/head/; revision=168281
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/uart/uart.h9
-rw-r--r--sys/dev/uart/uart_bus.h5
-rw-r--r--sys/dev/uart/uart_core.c37
-rw-r--r--sys/dev/uart/uart_cpu.h29
-rw-r--r--sys/dev/uart/uart_cpu_amd64.c13
-rw-r--r--sys/dev/uart/uart_cpu_i386.c13
-rw-r--r--sys/dev/uart/uart_cpu_ia64.c14
-rw-r--r--sys/dev/uart/uart_cpu_pc98.c13
-rw-r--r--sys/dev/uart/uart_cpu_powerpc.c7
-rw-r--r--sys/dev/uart/uart_cpu_sparc64.c19
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c5
-rw-r--r--sys/dev/uart/uart_dev_sab82532.c5
-rw-r--r--sys/dev/uart/uart_dev_z8530.c5
-rw-r--r--sys/dev/uart/uart_kbd_sun.c4
-rw-r--r--sys/dev/uart/uart_subr.c50
15 files changed, 165 insertions, 63 deletions
diff --git a/sys/dev/uart/uart.h b/sys/dev/uart/uart.h
index da9bd1baf4d4..f4320d4c53ab 100644
--- a/sys/dev/uart/uart.h
+++ b/sys/dev/uart/uart.h
@@ -60,6 +60,15 @@ struct uart_bas {
BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)
/*
+ * UART device classes.
+ */
+struct uart_class;
+
+extern struct uart_class uart_ns8250_class __attribute__((weak));
+extern struct uart_class uart_sab82532_class __attribute__((weak));
+extern struct uart_class uart_z8530_class __attribute__((weak));
+
+/*
* Device flags.
*/
#define UART_FLAGS_CONSOLE(f) ((f) & 0x10)
diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h
index 5396515a8c91..7154d859026a 100644
--- a/sys/dev/uart/uart_bus.h
+++ b/sys/dev/uart/uart_bus.h
@@ -67,14 +67,11 @@
*/
struct uart_class {
KOBJ_CLASS_FIELDS;
+ struct uart_ops *uc_ops; /* Low-level console operations. */
u_int uc_range; /* Bus space address range. */
u_int uc_rclk; /* Default rclk for this device. */
};
-extern struct uart_class uart_ns8250_class;
-extern struct uart_class uart_sab82532_class;
-extern struct uart_class uart_z8530_class;
-
struct uart_softc {
KOBJ_FIELDS;
struct uart_class *sc_class;
diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c
index 6daf938c0482..f99127881e82 100644
--- a/sys/dev/uart/uart_core.c
+++ b/sys/dev/uart/uart_core.c
@@ -70,6 +70,24 @@ uart_add_sysdev(struct uart_devinfo *di)
SLIST_INSERT_HEAD(&uart_sysdevs, di, next);
}
+const char *
+uart_getname(struct uart_class *uc)
+{
+ return ((uc != NULL) ? uc->name : NULL);
+}
+
+struct uart_ops *
+uart_getops(struct uart_class *uc)
+{
+ return ((uc != NULL) ? uc->uc_ops : NULL);
+}
+
+int
+uart_getrange(struct uart_class *uc)
+{
+ return ((uc != NULL) ? uc->uc_range : 0);
+}
+
/*
* Schedule a soft interrupt. We do this on the 0 to !0 transition
* of the TTY pending interrupt status.
@@ -293,6 +311,15 @@ uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan)
struct uart_devinfo *sysdev;
int error;
+ sc = device_get_softc(dev);
+
+ /*
+ * All uart_class references are weak. Check that the needed
+ * class has been compiled-in. Fail if not.
+ */
+ if (sc->sc_class == NULL)
+ return (ENXIO);
+
/*
* Initialize the instance. Note that the instance (=softc) does
* not necessarily match the hardware specific softc. We can't do
@@ -300,11 +327,10 @@ uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan)
* Hardware drivers cannot use any of the class specific fields
* while probing.
*/
- sc = device_get_softc(dev);
kobj_init((kobj_t)sc, (kobj_class_t)sc->sc_class);
sc->sc_dev = dev;
if (device_get_desc(dev) == NULL)
- device_set_desc(dev, sc->sc_class->name);
+ device_set_desc(dev, uart_getname(sc->sc_class));
/*
* Allocate the register resource. We assume that all UARTs have
@@ -316,12 +342,13 @@ uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan)
sc->sc_rrid = rid;
sc->sc_rtype = SYS_RES_IOPORT;
sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
- 0, ~0, sc->sc_class->uc_range, RF_ACTIVE);
+ 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE);
if (sc->sc_rres == NULL) {
sc->sc_rrid = rid;
sc->sc_rtype = SYS_RES_MEMORY;
sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype,
- &sc->sc_rrid, 0, ~0, sc->sc_class->uc_range, RF_ACTIVE);
+ &sc->sc_rrid, 0, ~0, uart_getrange(sc->sc_class),
+ RF_ACTIVE);
if (sc->sc_rres == NULL)
return (ENXIO);
}
@@ -390,7 +417,7 @@ uart_bus_attach(device_t dev)
* collected by uart_bus_probe() intact.
*/
sc->sc_rres = bus_alloc_resource(dev, sc->sc_rtype, &sc->sc_rrid,
- 0, ~0, sc->sc_class->uc_range, RF_ACTIVE);
+ 0, ~0, uart_getrange(sc->sc_class), RF_ACTIVE);
if (sc->sc_rres == NULL) {
mtx_destroy(&sc->sc_hwmtx_s);
return (ENXIO);
diff --git a/sys/dev/uart/uart_cpu.h b/sys/dev/uart/uart_cpu.h
index b41ed508f09e..db64d497e594 100644
--- a/sys/dev/uart/uart_cpu.h
+++ b/sys/dev/uart/uart_cpu.h
@@ -45,11 +45,6 @@ struct uart_ops {
int (*getc)(struct uart_bas *, struct mtx *);
};
-extern struct uart_ops uart_i8251_ops;
-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;
@@ -59,7 +54,7 @@ extern bus_space_tag_t uart_bus_space_mem;
struct uart_softc;
struct uart_devinfo {
SLIST_ENTRY(uart_devinfo) next;
- struct uart_ops ops;
+ struct uart_ops *ops;
struct uart_bas bas;
int baudrate;
int databits;
@@ -77,7 +72,11 @@ 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 *);
+
+int uart_getenv(int, struct uart_devinfo *, struct uart_class *);
+const char *uart_getname(struct uart_class *);
+struct uart_ops *uart_getops(struct uart_class *);
+int uart_getrange(struct uart_class *);
void uart_add_sysdev(struct uart_devinfo *);
@@ -106,7 +105,7 @@ uart_probe(struct uart_devinfo *di)
int res;
uart_lock(di->hwmtx);
- res = di->ops.probe(&di->bas);
+ res = di->ops->probe(&di->bas);
uart_unlock(di->hwmtx);
return (res);
}
@@ -115,7 +114,7 @@ static __inline void
uart_init(struct uart_devinfo *di)
{
uart_lock(di->hwmtx);
- di->ops.init(&di->bas, di->baudrate, di->databits, di->stopbits,
+ di->ops->init(&di->bas, di->baudrate, di->databits, di->stopbits,
di->parity);
uart_unlock(di->hwmtx);
}
@@ -124,7 +123,7 @@ static __inline void
uart_term(struct uart_devinfo *di)
{
uart_lock(di->hwmtx);
- di->ops.term(&di->bas);
+ di->ops->term(&di->bas);
uart_unlock(di->hwmtx);
}
@@ -132,7 +131,7 @@ static __inline void
uart_putc(struct uart_devinfo *di, int c)
{
uart_lock(di->hwmtx);
- di->ops.putc(&di->bas, c);
+ di->ops->putc(&di->bas, c);
uart_unlock(di->hwmtx);
}
@@ -142,7 +141,7 @@ uart_rxready(struct uart_devinfo *di)
int res;
uart_lock(di->hwmtx);
- res = di->ops.rxready(&di->bas);
+ res = di->ops->rxready(&di->bas);
uart_unlock(di->hwmtx);
return (res);
}
@@ -153,8 +152,8 @@ uart_poll(struct uart_devinfo *di)
int res;
uart_lock(di->hwmtx);
- if (di->ops.rxready(&di->bas))
- res = di->ops.getc(&di->bas, NULL);
+ if (di->ops->rxready(&di->bas))
+ res = di->ops->getc(&di->bas, NULL);
else
res = -1;
uart_unlock(di->hwmtx);
@@ -165,7 +164,7 @@ static __inline int
uart_getc(struct uart_devinfo *di)
{
- return (di->ops.getc(&di->bas, di->hwmtx));
+ return (di->ops->getc(&di->bas, di->hwmtx));
}
#endif /* _DEV_UART_CPU_H_ */
diff --git a/sys/dev/uart/uart_cpu_amd64.c b/sys/dev/uart/uart_cpu_amd64.c
index fb8b99476eb6..3624f7973d5c 100644
--- a/sys/dev/uart/uart_cpu_amd64.c
+++ b/sys/dev/uart/uart_cpu_amd64.c
@@ -49,11 +49,15 @@ uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
+ struct uart_class *class;
unsigned int i, ivar;
+ class = &uart_ns8250_class;
+ if (class == NULL)
+ return (ENXIO);
+
/* Check the environment. */
- di->ops = uart_ns8250_ops;
- if (uart_getenv(devtype, di) == 0)
+ if (uart_getenv(devtype, di, class) == 0)
return (0);
/*
@@ -82,10 +86,11 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
* Got it. Fill in the instance and return it. We only have
* ns8250 and successors on i386.
*/
- di->ops = uart_ns8250_ops;
+ di->ops = uart_getops(class);
di->bas.chan = 0;
di->bas.bst = uart_bus_space_io;
- if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0)
+ if (bus_space_map(di->bas.bst, ivar, uart_getrange(class), 0,
+ &di->bas.bsh) != 0)
continue;
di->bas.regshft = 0;
di->bas.rclk = 0;
diff --git a/sys/dev/uart/uart_cpu_i386.c b/sys/dev/uart/uart_cpu_i386.c
index c8e2e2ec721f..0d0f0f71134f 100644
--- a/sys/dev/uart/uart_cpu_i386.c
+++ b/sys/dev/uart/uart_cpu_i386.c
@@ -49,11 +49,15 @@ uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
+ struct uart_class *class;
unsigned int i, ivar;
+ class = &uart_ns8250_class;
+ if (class == NULL)
+ return (ENXIO);
+
/* Check the environment. */
- di->ops = uart_ns8250_ops;
- if (uart_getenv(devtype, di) == 0)
+ if (uart_getenv(devtype, di, class) == 0)
return (0);
/*
@@ -82,10 +86,11 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
* Got it. Fill in the instance and return it. We only have
* ns8250 and successors on i386.
*/
- di->ops = uart_ns8250_ops;
+ di->ops = uart_getops(class);
di->bas.chan = 0;
di->bas.bst = uart_bus_space_io;
- if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0)
+ if (bus_space_map(di->bas.bst, ivar, uart_getrange(class), 0,
+ &di->bas.bsh) != 0)
continue;
di->bas.regshft = 0;
di->bas.rclk = 0;
diff --git a/sys/dev/uart/uart_cpu_ia64.c b/sys/dev/uart/uart_cpu_ia64.c
index 496049200c2d..9a71e20e506e 100644
--- a/sys/dev/uart/uart_cpu_ia64.c
+++ b/sys/dev/uart/uart_cpu_ia64.c
@@ -59,10 +59,15 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
struct dig64_hcdp_table *tbl;
struct dig64_hcdp_entry *ent;
+ struct uart_class *class;
bus_addr_t addr;
uint64_t hcdp;
unsigned int i;
+ class = &uart_ns8250_class;
+ if (class == NULL)
+ return (ENXIO);
+
/*
* Use the DIG64 HCDP table if present.
*/
@@ -82,12 +87,12 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
addr = ent->address.addr_high;
addr = (addr << 32) + ent->address.addr_low;
- di->ops = uart_ns8250_ops;
+ di->ops = uart_getops(class);
di->bas.chan = 0;
di->bas.bst = (ent->address.addr_space == 0)
? uart_bus_space_mem : uart_bus_space_io;
- if (bus_space_map(di->bas.bst, addr, 8, 0,
- &di->bas.bsh) != 0)
+ if (bus_space_map(di->bas.bst, addr,
+ uart_getrange(class), 0, &di->bas.bsh) != 0)
continue;
di->bas.regshft = 0;
di->bas.rclk = ent->pclock << 4;
@@ -104,6 +109,5 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
}
/* Check the environment. */
- di->ops = uart_ns8250_ops;
- return (uart_getenv(devtype, di));
+ return (uart_getenv(devtype, di, class));
}
diff --git a/sys/dev/uart/uart_cpu_pc98.c b/sys/dev/uart/uart_cpu_pc98.c
index 0887a6766624..c0c1f4e1d5c2 100644
--- a/sys/dev/uart/uart_cpu_pc98.c
+++ b/sys/dev/uart/uart_cpu_pc98.c
@@ -49,11 +49,15 @@ uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
+ struct uart_class *class;
unsigned int i, ivar, flags;
+ class = &uart_ns8250_class;
+ if (class == NULL)
+ return (ENXIO);
+
/* Check the environment. */
- di->ops = uart_ns8250_ops;
- if (uart_getenv(devtype, di) == 0)
+ if (uart_getenv(devtype, di, class) == 0)
return (0);
/*
@@ -81,10 +85,11 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
ivar == 0)
continue;
- di->ops = uart_ns8250_ops;
+ di->ops = uart_getops(class);
di->bas.chan = 0;
di->bas.bst = uart_bus_space_io;
- if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0)
+ if (bus_space_map(di->bas.bst, ivar, uart_getrange(class), 0,
+ &di->bas.bsh) != 0)
continue;
di->bas.regshft = 0;
di->bas.rclk = 0;
diff --git a/sys/dev/uart/uart_cpu_powerpc.c b/sys/dev/uart/uart_cpu_powerpc.c
index 53f57dc7e49a..6647c7dbb347 100644
--- a/sys/dev/uart/uart_cpu_powerpc.c
+++ b/sys/dev/uart/uart_cpu_powerpc.c
@@ -52,9 +52,14 @@ int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
char buf[64];
+ struct uart_class *class;
phandle_t input, opts;
int error;
+ class = &uart_z8530_class;
+ if (class == NULL)
+ return (ENXIO);
+
if ((opts = OF_finddevice("/options")) == -1)
return (ENXIO);
switch (devtype) {
@@ -93,7 +98,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
if (error)
return (error);
- di->ops = uart_z8530_ops;
+ di->ops = uart_getops(class);
di->bas.rclk = 230400;
di->bas.chan = 1;
diff --git a/sys/dev/uart/uart_cpu_sparc64.c b/sys/dev/uart/uart_cpu_sparc64.c
index efe0283df204..9d92a3908732 100644
--- a/sys/dev/uart/uart_cpu_sparc64.c
+++ b/sys/dev/uart/uart_cpu_sparc64.c
@@ -194,9 +194,10 @@ int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
char buf[32], compat[32], dev[64];
+ struct uart_class *class;
phandle_t input, options;
bus_addr_t addr;
- int baud, bits, error, space, stop;
+ int baud, bits, error, range, space, stop;
char flag, par;
if ((options = OF_finddevice("/options")) == -1)
@@ -228,14 +229,15 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
compat[0] = '\0';
di->bas.regshft = 0;
di->bas.rclk = 0;
+ class = NULL;
if (!strcmp(buf, "se") || !strcmp(compat, "sab82532")) {
- di->ops = uart_sab82532_ops;
+ class = &uart_sab82532_class;
/* SAB82532 are only known to be used for TTYs. */
if ((di->bas.chan = uart_cpu_channel(dev)) == 0)
return (ENXIO);
- addr += 64 * (di->bas.chan - 1);
+ addr += uart_getrange(class) * (di->bas.chan - 1);
} else if (!strcmp(buf, "zs")) {
- di->ops = uart_z8530_ops;
+ class = &uart_z8530_class;
if ((di->bas.chan = uart_cpu_channel(dev)) == 0) {
/*
* There's no way to determine from OF which
@@ -248,16 +250,19 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
return (ENXIO);
}
di->bas.regshft = 1;
- addr += 4 - 4 * (di->bas.chan - 1);
+ range = uart_getrange(class) << di->bas.regshft;
+ addr += range - range * (di->bas.chan - 1);
} else if (!strcmp(buf, "lom-console") || !strcmp(buf, "su") ||
!strcmp(buf, "su_pnp") || !strcmp(compat, "rsc-console") ||
!strcmp(compat, "su") || !strcmp(compat, "su16550")) {
- di->ops = uart_ns8250_ops;
+ class = &uart_ns8250_class;
di->bas.chan = 0;
- } else
+ }
+ if (class == NULL)
return (ENXIO);
/* Fill in the device info. */
+ di->ops = uart_getops(class);
di->bas.bst = &bst_store[devtype];
di->bas.bsh = sparc64_fake_bustag(space, addr, di->bas.bst);
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 8e6177be329d..4e5141796d20 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -222,7 +222,7 @@ static void ns8250_putc(struct uart_bas *bas, int);
static int ns8250_rxready(struct uart_bas *bas);
static int ns8250_getc(struct uart_bas *bas, struct mtx *);
-struct uart_ops uart_ns8250_ops = {
+static struct uart_ops uart_ns8250_ops = {
.probe = ns8250_probe,
.init = ns8250_init,
.term = ns8250_term,
@@ -368,9 +368,10 @@ static kobj_method_t ns8250_methods[] = {
};
struct uart_class uart_ns8250_class = {
- "ns8250 class",
+ "ns8250",
ns8250_methods,
sizeof(struct ns8250_softc),
+ .uc_ops = &uart_ns8250_ops,
.uc_range = 8,
.uc_rclk = DEFAULT_RCLK
};
diff --git a/sys/dev/uart/uart_dev_sab82532.c b/sys/dev/uart/uart_dev_sab82532.c
index e10ae177a277..11cdb4b47387 100644
--- a/sys/dev/uart/uart_dev_sab82532.c
+++ b/sys/dev/uart/uart_dev_sab82532.c
@@ -176,7 +176,7 @@ static void sab82532_putc(struct uart_bas *bas, int);
static int sab82532_rxready(struct uart_bas *bas);
static int sab82532_getc(struct uart_bas *bas, struct mtx *);
-struct uart_ops uart_sab82532_ops = {
+static struct uart_ops uart_sab82532_ops = {
.probe = sab82532_probe,
.init = sab82532_init,
.term = sab82532_term,
@@ -382,9 +382,10 @@ static kobj_method_t sab82532_methods[] = {
};
struct uart_class uart_sab82532_class = {
- "sab82532 class",
+ "sab82532",
sab82532_methods,
sizeof(struct sab82532_softc),
+ .uc_ops = &uart_sab82532_ops,
.uc_range = 64,
.uc_rclk = DEFAULT_RCLK
};
diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c
index 850971817050..33bacdc98f72 100644
--- a/sys/dev/uart/uart_dev_z8530.c
+++ b/sys/dev/uart/uart_dev_z8530.c
@@ -195,7 +195,7 @@ static void z8530_putc(struct uart_bas *bas, int);
static int z8530_rxready(struct uart_bas *bas);
static int z8530_getc(struct uart_bas *bas, struct mtx *);
-struct uart_ops uart_z8530_ops = {
+static struct uart_ops uart_z8530_ops = {
.probe = z8530_probe,
.init = z8530_init,
.term = z8530_term,
@@ -298,9 +298,10 @@ static kobj_method_t z8530_methods[] = {
};
struct uart_class uart_z8530_class = {
- "z8530 class",
+ "z8530",
z8530_methods,
sizeof(struct z8530_softc),
+ .uc_ops = &uart_z8530_ops,
.uc_range = 2,
.uc_rclk = DEFAULT_RCLK
};
diff --git a/sys/dev/uart/uart_kbd_sun.c b/sys/dev/uart/uart_kbd_sun.c
index 7395f9dcc12a..78238a73d95c 100644
--- a/sys/dev/uart/uart_kbd_sun.c
+++ b/sys/dev/uart/uart_kbd_sun.c
@@ -712,8 +712,8 @@ sunkbd_ioctl(keyboard_t *kbd, u_long cmd, caddr_t data)
if (*(int *)data & SLKED)
c |= SKBD_LED_SCROLLLOCK;
uart_lock(sc->sc_sysdev->hwmtx);
- sc->sc_sysdev->ops.putc(&sc->sc_sysdev->bas, SKBD_CMD_SETLED);
- sc->sc_sysdev->ops.putc(&sc->sc_sysdev->bas, c);
+ sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, SKBD_CMD_SETLED);
+ sc->sc_sysdev->ops->putc(&sc->sc_sysdev->bas, c);
uart_unlock(sc->sc_sysdev->hwmtx);
KBD_LED_VAL(kbd) = *(int *)data;
break;
diff --git a/sys/dev/uart/uart_subr.c b/sys/dev/uart/uart_subr.c
index c9b6fe7ab504..2cab82535d0a 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);
}