summaryrefslogtreecommitdiff
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
parent1bdb3fb97eb936148ebd3be52850c09ae7f72260 (diff)
Notes
-rw-r--r--sys/arm/at91/uart_cpu_at91rm9200usart.c11
-rw-r--r--sys/arm/at91/uart_dev_at91usart.c6
-rw-r--r--sys/arm/sa11x0/uart_cpu_sa1110.c5
-rw-r--r--sys/arm/sa11x0/uart_dev_sa1110.c6
-rw-r--r--sys/arm/xscale/i80321/uart_cpu_i80321.c2
-rw-r--r--sys/arm/xscale/ixp425/uart_cpu_ixp425.c2
-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
21 files changed, 184 insertions, 76 deletions
diff --git a/sys/arm/at91/uart_cpu_at91rm9200usart.c b/sys/arm/at91/uart_cpu_at91rm9200usart.c
index 75a053d0f091d..459badbd14082 100644
--- a/sys/arm/at91/uart_cpu_at91rm9200usart.c
+++ b/sys/arm/at91/uart_cpu_at91rm9200usart.c
@@ -43,7 +43,7 @@ __FBSDID("$FreeBSD$");
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
-extern struct uart_ops at91_usart_ops;
+extern struct uart_class at91_usart_class;
extern struct bus_space at91_bs_tag;
int
@@ -55,7 +55,10 @@ uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
- di->ops = at91_usart_ops;
+ struct uart_class *class;
+
+ class = &at91_usart_class;
+ di->ops = uart_getops(class);
di->bas.chan = 0;
di->bas.bst = &at91_bs_tag;
/*
@@ -77,7 +80,5 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di)
uart_bus_space_io = &at91_bs_tag;
uart_bus_space_mem = NULL;
/* Check the environment for overrides */
- if (uart_getenv(devtype, di) == 0)
- return (0);
- return (0);
+ return (uart_getenv(devtype, di, class));
}
diff --git a/sys/arm/at91/uart_dev_at91usart.c b/sys/arm/at91/uart_dev_at91usart.c
index a405aa3120101..88625899f1970 100644
--- a/sys/arm/at91/uart_dev_at91usart.c
+++ b/sys/arm/at91/uart_dev_at91usart.c
@@ -196,7 +196,7 @@ at91_usart_param(struct uart_bas *bas, int baudrate, int databits,
return (0);
}
-struct uart_ops at91_usart_ops = {
+static struct uart_ops at91_usart_ops = {
.probe = at91_usart_probe,
.init = at91_usart_init,
.term = at91_usart_term,
@@ -662,10 +662,12 @@ at91_usart_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
}
return (EINVAL);
}
+
struct uart_class at91_usart_class = {
- "at91_usart class",
+ "at91_usart",
at91_usart_methods,
sizeof(struct at91_usart_softc),
+ .uc_ops = &at91_usart_ops,
.uc_range = 8,
.uc_rclk = DEFAULT_RCLK
};
diff --git a/sys/arm/sa11x0/uart_cpu_sa1110.c b/sys/arm/sa11x0/uart_cpu_sa1110.c
index d96dee309e4de..5d6a3c3bfe721 100644
--- a/sys/arm/sa11x0/uart_cpu_sa1110.c
+++ b/sys/arm/sa11x0/uart_cpu_sa1110.c
@@ -42,7 +42,7 @@ __FBSDID("$FreeBSD$");
bus_space_tag_t uart_bus_space_io;
bus_space_tag_t uart_bus_space_mem;
-extern struct uart_ops uart_sa1110_ops;
+extern struct uart_class uart_sa1110_class;
vm_offset_t sa1110_uart_vaddr;
@@ -55,7 +55,8 @@ uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
- di->ops = uart_sa1110_ops;
+
+ di->ops = uart_getops(&uart_sa1110_class);
di->bas.chan = 0;
di->bas.bst = &sa11x0_bs_tag;
di->bas.bsh = sa1110_uart_vaddr;
diff --git a/sys/arm/sa11x0/uart_dev_sa1110.c b/sys/arm/sa11x0/uart_dev_sa1110.c
index 0a36bca116255..35ff22bc00d31 100644
--- a/sys/arm/sa11x0/uart_dev_sa1110.c
+++ b/sys/arm/sa11x0/uart_dev_sa1110.c
@@ -57,7 +57,7 @@ static int sa1110_getc(struct uart_bas *bas, struct mtx *mtx);
extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs;
-struct uart_ops uart_sa1110_ops = {
+static struct uart_ops uart_sa1110_ops = {
.probe = sa1110_probe,
.init = sa1110_init,
.term = sa1110_term,
@@ -272,10 +272,12 @@ sa1110_bus_ioctl(struct uart_softc *sc, int request, intptr_t data)
{
return (EINVAL);
}
+
struct uart_class uart_sa1110_class = {
- "sa1110 class",
+ "sa1110",
sa1110_methods,
1,
+ .uc_ops = &uart_sa1110_ops,
.uc_range = 8,
.uc_rclk = 3686400
};
diff --git a/sys/arm/xscale/i80321/uart_cpu_i80321.c b/sys/arm/xscale/i80321/uart_cpu_i80321.c
index 987422ee24d01..32dd463cfb47d 100644
--- a/sys/arm/xscale/i80321/uart_cpu_i80321.c
+++ b/sys/arm/xscale/i80321/uart_cpu_i80321.c
@@ -51,7 +51,7 @@ uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
- di->ops = uart_ns8250_ops;
+ di->ops = uart_getops(&uart_ns8250_class);
di->bas.chan = 0;
di->bas.bst = &obio_bs_tag;
di->bas.regshft = 0;
diff --git a/sys/arm/xscale/ixp425/uart_cpu_ixp425.c b/sys/arm/xscale/ixp425/uart_cpu_ixp425.c
index e691968538c67..837e2711378cf 100644
--- a/sys/arm/xscale/ixp425/uart_cpu_ixp425.c
+++ b/sys/arm/xscale/ixp425/uart_cpu_ixp425.c
@@ -51,7 +51,7 @@ uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2)
int
uart_cpu_getdev(int devtype, struct uart_devinfo *di)
{
- di->ops = uart_ns8250_ops;
+ di->ops = uart_getops(&uart_ns8250_class);
di->bas.chan = 0;
di->bas.bst = &ixp425_a4x_bs_tag;
di->bas.regshft = 0;
diff --git a/sys/dev/uart/uart.h b/sys/dev/uart/uart.h
index da9bd1baf4d46..f4320d4c53ab0 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 5396515a8c910..7154d859026a0 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 6daf938c04823..f99127881e82b 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 b41ed508f09ef..db64d497e5946 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 fb8b99476eb60..3624f7973d5c4 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 c8e2e2ec721fc..0d0f0f71134fa 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 496049200c2d4..9a71e20e506e0 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 0887a67666241..c0c1f4e1d5c23 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 53f57dc7e49a5..6647c7dbb3479 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 efe0283df2048..9d92a3908732f 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 8e6177be329d9..4e5141796d203 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 e10ae177a2774..11cdb4b47387a 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 850971817050b..33bacdc98f72c 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 7395f9dcc12a1..78238a73d95c6 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 c9b6fe7ab5042..2cab82535d0a7 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);
}