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.
This commit is contained in:
parent
1bdb3fb97e
commit
f8100ce2a7
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -59,6 +59,15 @@ struct uart_bas {
|
||||
bus_space_barrier((bas)->bst, (bas)->bsh, 0, 0, \
|
||||
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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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_ */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user