diff options
author | Marcel Moolenaar <marcel@FreeBSD.org> | 2007-04-02 22:00:22 +0000 |
---|---|---|
committer | Marcel Moolenaar <marcel@FreeBSD.org> | 2007-04-02 22:00:22 +0000 |
commit | f8100ce2a70db5c60672578fee913d986ac1cf01 (patch) | |
tree | b3ad51f3cb65c3badfb015aea4f71d800157abb8 | |
parent | 1bdb3fb97eb936148ebd3be52850c09ae7f72260 (diff) |
Notes
-rw-r--r-- | sys/arm/at91/uart_cpu_at91rm9200usart.c | 11 | ||||
-rw-r--r-- | sys/arm/at91/uart_dev_at91usart.c | 6 | ||||
-rw-r--r-- | sys/arm/sa11x0/uart_cpu_sa1110.c | 5 | ||||
-rw-r--r-- | sys/arm/sa11x0/uart_dev_sa1110.c | 6 | ||||
-rw-r--r-- | sys/arm/xscale/i80321/uart_cpu_i80321.c | 2 | ||||
-rw-r--r-- | sys/arm/xscale/ixp425/uart_cpu_ixp425.c | 2 | ||||
-rw-r--r-- | sys/dev/uart/uart.h | 9 | ||||
-rw-r--r-- | sys/dev/uart/uart_bus.h | 5 | ||||
-rw-r--r-- | sys/dev/uart/uart_core.c | 37 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu.h | 29 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_amd64.c | 13 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_i386.c | 13 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_ia64.c | 14 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_pc98.c | 13 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_powerpc.c | 7 | ||||
-rw-r--r-- | sys/dev/uart/uart_cpu_sparc64.c | 19 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_ns8250.c | 5 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_sab82532.c | 5 | ||||
-rw-r--r-- | sys/dev/uart/uart_dev_z8530.c | 5 | ||||
-rw-r--r-- | sys/dev/uart/uart_kbd_sun.c | 4 | ||||
-rw-r--r-- | sys/dev/uart/uart_subr.c | 50 |
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); } |