diff --git a/sys/dev/uart/uart.h b/sys/dev/uart/uart.h index ba17e89bf8c7..5de4d420ac5c 100644 --- a/sys/dev/uart/uart.h +++ b/sys/dev/uart/uart.h @@ -36,11 +36,11 @@ * other timing related computations. */ struct uart_bas { - bus_addr_t iobase; bus_space_tag_t bst; bus_space_handle_t bsh; - u_int regshft; + u_int chan; u_int rclk; + u_int regshft; }; #define uart_regofs(bas, reg) ((reg) << (bas)->regshft) diff --git a/sys/dev/uart/uart_bus.h b/sys/dev/uart/uart_bus.h index dde9ff803a29..3c45199d980d 100644 --- a/sys/dev/uart/uart_bus.h +++ b/sys/dev/uart/uart_bus.h @@ -172,7 +172,7 @@ extern char uart_driver_name[]; int uart_bus_attach(device_t dev); int uart_bus_detach(device_t dev); -int uart_bus_probe(device_t dev, int regshft, int rclk, int rid); +int uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan); int uart_tty_attach(struct uart_softc *); int uart_tty_detach(struct uart_softc *); diff --git a/sys/dev/uart/uart_bus_acpi.c b/sys/dev/uart/uart_bus_acpi.c index ac75f0cc6b41..a26357132d04 100644 --- a/sys/dev/uart/uart_bus_acpi.c +++ b/sys/dev/uart/uart_bus_acpi.c @@ -73,7 +73,7 @@ uart_acpi_probe(device_t dev) if (!ISA_PNP_PROBE(parent, dev, acpi_ns8250_ids)) { sc->sc_class = &uart_ns8250_class; - return (uart_bus_probe(dev, 0, 0, 0)); + return (uart_bus_probe(dev, 0, 0, 0, 0)); } /* Add checks for non-ns8250 IDs here. */ diff --git a/sys/dev/uart/uart_bus_ebus.c b/sys/dev/uart/uart_bus_ebus.c index 0eab11fb41f5..9445c186b5e6 100644 --- a/sys/dev/uart/uart_bus_ebus.c +++ b/sys/dev/uart/uart_bus_ebus.c @@ -71,11 +71,11 @@ uart_ebus_probe(device_t dev) nm = ebus_get_name(dev); if (!strcmp(nm, "su")) { sc->sc_class = &uart_ns8250_class; - return (uart_bus_probe(dev, 0, 0, 0)); + return (uart_bus_probe(dev, 0, 0, 0, 0)); } if (!strcmp(nm, "se")) { sc->sc_class = &uart_sab82532_class; - error = uart_bus_probe(dev, 0, 0, 0); + error = uart_bus_probe(dev, 0, 0, 0, 1); return ((error) ? error : -1); } diff --git a/sys/dev/uart/uart_bus_isa.c b/sys/dev/uart/uart_bus_isa.c index 784d7f9a6d75..d6b5cda734bb 100644 --- a/sys/dev/uart/uart_bus_isa.c +++ b/sys/dev/uart/uart_bus_isa.c @@ -155,13 +155,13 @@ uart_isa_probe(device_t dev) if (!ISA_PNP_PROBE(parent, dev, isa_ns8250_ids)) { sc->sc_class = &uart_ns8250_class; - return (uart_bus_probe(dev, 0, 0, 0)); + return (uart_bus_probe(dev, 0, 0, 0, 0)); } /* Add checks for non-ns8250 IDs here. */ sc->sc_class = &uart_ns8250_class; - return (uart_bus_probe(dev, 0, 0, 0)); + return (uart_bus_probe(dev, 0, 0, 0, 0)); } DRIVER_MODULE(uart, isa, uart_isa_driver, uart_devclass, 0, 0); diff --git a/sys/dev/uart/uart_bus_pccard.c b/sys/dev/uart/uart_bus_pccard.c index c321060f332f..096392121788 100644 --- a/sys/dev/uart/uart_bus_pccard.c +++ b/sys/dev/uart/uart_bus_pccard.c @@ -95,7 +95,7 @@ uart_pccard_probe(dev) /* Do not probe IRQ - pccard doesn't turn on the interrupt line */ /* until bus_setup_intr but how can I do so?*/ - return (uart_bus_probe(dev, 0, 0, 0)); + return (uart_bus_probe(dev, 0, 0, 0, 0)); } DRIVER_MODULE(uart, pccard, uart_pccard_driver, uart_devclass, 0, 0); diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c index 3555e5f4a8f5..2e4573d4e26b 100644 --- a/sys/dev/uart/uart_bus_pci.c +++ b/sys/dev/uart/uart_bus_pci.c @@ -111,7 +111,7 @@ uart_pci_probe(device_t dev) match: if (id->desc) device_set_desc(dev, id->desc); - return (uart_bus_probe(dev, 0, 0, id->rid)); + return (uart_bus_probe(dev, 0, 0, id->rid, 0)); } DRIVER_MODULE(uart, pci, uart_pci_driver, uart_devclass, 0, 0); diff --git a/sys/dev/uart/uart_bus_puc.c b/sys/dev/uart/uart_bus_puc.c index 94b042ef4d39..7277df99fc41 100644 --- a/sys/dev/uart/uart_bus_puc.c +++ b/sys/dev/uart/uart_bus_puc.c @@ -63,7 +63,7 @@ uart_puc_probe(device_t dev) { device_t parent; struct uart_softc *sc; - uintptr_t rclk, regshft, type; + uintptr_t port, rclk, regshft, type; parent = device_get_parent(dev); sc = device_get_softc(dev); @@ -73,12 +73,17 @@ uart_puc_probe(device_t dev) switch (type) { case PUC_PORT_UART_NS8250: sc->sc_class = &uart_ns8250_class; + port = 0; break; case PUC_PORT_UART_SAB82532: sc->sc_class = &uart_sab82532_class; + if (BUS_READ_IVAR(parent, dev, PUC_IVAR_PORT, &port)) + port = 0; break; case PUC_PORT_UART_Z8530: sc->sc_class = &uart_z8530_class; + if (BUS_READ_IVAR(parent, dev, PUC_IVAR_PORT, &port)) + port = 0; break; default: return (ENXIO); @@ -88,7 +93,7 @@ uart_puc_probe(device_t dev) rclk = 0; if (BUS_READ_IVAR(parent, dev, PUC_IVAR_REGSHFT, ®shft)) regshft = 0; - return (uart_bus_probe(dev, regshft, rclk, 0)); + return (uart_bus_probe(dev, regshft, rclk, 0, port)); } DRIVER_MODULE(uart, puc, uart_puc_driver, uart_devclass, 0, 0); diff --git a/sys/dev/uart/uart_core.c b/sys/dev/uart/uart_core.c index 501156fea0ad..18141c25769f 100644 --- a/sys/dev/uart/uart_core.c +++ b/sys/dev/uart/uart_core.c @@ -221,7 +221,7 @@ uart_intr(void *arg) } int -uart_bus_probe(device_t dev, int regshft, int rclk, int rid) +uart_bus_probe(device_t dev, int regshft, int rclk, int rid, int chan) { struct uart_softc *sc; struct uart_devinfo *sysdev; @@ -267,14 +267,15 @@ uart_bus_probe(device_t dev, int regshft, int rclk, int rid) * accordingly. In general, you don't want to permanently disrupt * console I/O. */ - sc->sc_bas.iobase = rman_get_start(sc->sc_rres); sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); + sc->sc_bas.chan = chan; sc->sc_bas.regshft = regshft; sc->sc_bas.rclk = (rclk == 0) ? sc->sc_class->uc_rclk : rclk; SLIST_FOREACH(sysdev, &uart_sysdevs, next) { - if (uart_cpu_eqres(&sc->sc_bas, &sysdev->bas)) { + if (chan == sysdev->bas.chan && + uart_cpu_eqres(&sc->sc_bas, &sysdev->bas)) { /* XXX check if ops matches class. */ sc->sc_sysdev = sysdev; break; @@ -324,8 +325,6 @@ uart_bus_attach(device_t dev) 0, ~0, sc->sc_class->uc_range, RF_ACTIVE); if (sc->sc_rres == NULL) return (ENXIO); - - sc->sc_bas.iobase = rman_get_start(sc->sc_rres); sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres); sc->sc_bas.bst = rman_get_bustag(sc->sc_rres); diff --git a/sys/dev/uart/uart_cpu_alpha.c b/sys/dev/uart/uart_cpu_alpha.c index fffed6f83a9a..1d78d6a1853c 100644 --- a/sys/dev/uart/uart_cpu_alpha.c +++ b/sys/dev/uart/uart_cpu_alpha.c @@ -58,7 +58,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) return (ENXIO); boothowto |= RB_SERIAL; di->ops = uart_ns8250_ops; - di->bas.iobase = 0x3f8; + di->bas.chan = 0; di->bas.bst = busspace_isa_io; if (bus_space_map(di->bas.bst, 0x3f8, 8, 0, &di->bas.bsh) != 0) return (ENXIO); @@ -96,7 +96,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) * only have ns8250 and successors on alpha. */ di->ops = uart_ns8250_ops; - di->bas.iobase = ivar; + di->bas.chan = 0; di->bas.bst = busspace_isa_io; if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0) continue; diff --git a/sys/dev/uart/uart_cpu_amd64.c b/sys/dev/uart/uart_cpu_amd64.c index 53f7d975833e..be0f619d2042 100644 --- a/sys/dev/uart/uart_cpu_amd64.c +++ b/sys/dev/uart/uart_cpu_amd64.c @@ -75,7 +75,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) * ns8250 and successors on i386. */ di->ops = uart_ns8250_ops; - di->bas.iobase = ivar; + di->bas.chan = 0; di->bas.bst = AMD64_BUS_SPACE_IO; if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0) continue; diff --git a/sys/dev/uart/uart_cpu_i386.c b/sys/dev/uart/uart_cpu_i386.c index 8f252bb649b1..30b6e3ae517d 100644 --- a/sys/dev/uart/uart_cpu_i386.c +++ b/sys/dev/uart/uart_cpu_i386.c @@ -75,7 +75,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) * ns8250 and successors on i386. */ di->ops = uart_ns8250_ops; - di->bas.iobase = ivar; + di->bas.chan = 0; di->bas.bst = I386_BUS_SPACE_IO; if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0) continue; diff --git a/sys/dev/uart/uart_cpu_ia64.c b/sys/dev/uart/uart_cpu_ia64.c index 8fa5b058e325..eeaea3b479cf 100644 --- a/sys/dev/uart/uart_cpu_ia64.c +++ b/sys/dev/uart/uart_cpu_ia64.c @@ -56,6 +56,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) { struct dig64_hcdp_table *tbl; struct dig64_hcdp_entry *ent; + bus_addr_t addr; unsigned int i, ivar; /* @@ -74,14 +75,14 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) ent->type != DIG64_HCDP_DBGPORT) continue; + addr = ent->address.addr_high; + addr = (addr << 32) + ent->address.addr_low; di->ops = uart_ns8250_ops; - di->bas.iobase = (ent->address.addr_high << 32) + - ent->address.addr_low; - di->bas.bst = IA64_BUS_SPACE_IO; + di->bas.chan = 0; di->bas.bst = (ent->address.addr_space == 0) ? IA64_BUS_SPACE_MEM : IA64_BUS_SPACE_IO; - if (bus_space_map(di->bas.bst, di->bas.iobase, 8, 0, - &di->bas.bsh) != 0) + if (bus_space_map(di->bas.bst, addr, 8, 0, + &di->bas.bsh) != 0) continue; di->bas.regshft = 0; di->bas.rclk = ent->pclock << 4; @@ -124,7 +125,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) * ns8250 and successors on i386. */ di->ops = uart_ns8250_ops; - di->bas.iobase = ivar; + di->bas.chan = 0; di->bas.bst = IA64_BUS_SPACE_IO; if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0) continue; diff --git a/sys/dev/uart/uart_cpu_pc98.c b/sys/dev/uart/uart_cpu_pc98.c index 11c6e91c941c..4005a90dfd2d 100644 --- a/sys/dev/uart/uart_cpu_pc98.c +++ b/sys/dev/uart/uart_cpu_pc98.c @@ -40,7 +40,7 @@ int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { - return ((b1->iobase == b2->iobase && b1->bst == b2->bst) ? 1 : 0); + return (0); /* XXX */ } int @@ -80,7 +80,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) di->ops = uart_ns8250_ops; else di->ops = uart_i8251_ops; - di->bas.iobase = ivar; + di->bas.chan = 0; di->bas.bst = I386_BUS_SPACE_IO; if (bus_space_map(di->bas.bst, ivar, 8, 0, &di->bas.bsh) != 0) continue; diff --git a/sys/dev/uart/uart_cpu_sparc64.c b/sys/dev/uart/uart_cpu_sparc64.c index 5b8b1c62abc5..b99bc7101c28 100644 --- a/sys/dev/uart/uart_cpu_sparc64.c +++ b/sys/dev/uart/uart_cpu_sparc64.c @@ -55,7 +55,7 @@ uart_cpu_channel(char *dev) if (len < 2 || alias[len - 2] != ':' || alias[len - 1] < 'a' || alias[len - 1] > 'b') return (0); - return (alias[len - 1] - 'a'); + return (alias[len - 1] - 'a' + 1); } int @@ -71,7 +71,7 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) char buf[32], dev[32], compat[32]; phandle_t input, options, output; bus_addr_t addr; - int baud, bits, ch, error, space, stop; + int baud, bits, error, space, stop; char flag, par; /* @@ -123,20 +123,21 @@ uart_cpu_getdev(int devtype, struct uart_devinfo *di) di->bas.rclk = 0; if (!strcmp(buf, "se")) { di->ops = uart_sab82532_ops; - addr += 64 * uart_cpu_channel(dev); + di->bas.chan = uart_cpu_channel(dev); + addr += 64 * (di->bas.chan - 1); } else if (!strcmp(buf, "zs")) { di->ops = uart_z8530_ops; + di->bas.chan = uart_cpu_channel(dev); di->bas.regshft = 1; - ch = uart_cpu_channel(dev); - addr += 4 - 4 * ch; + addr += 4 - 4 * (di->bas.chan - 1); } else if (!strcmp(buf, "su") || !strcmp(buf, "su_pnp") || - !strcmp(compat, "su") || !strcmp(compat, "su16550")) + !strcmp(compat, "su") || !strcmp(compat, "su16550")) { di->ops = uart_ns8250_ops; - else + di->bas.chan = 0; + } else return (ENXIO); /* Fill in the device info. */ - di->bas.iobase = addr; 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_sab82532.c b/sys/dev/uart/uart_dev_sab82532.c index b9e781f5f1e7..72c297bb4da8 100644 --- a/sys/dev/uart/uart_dev_sab82532.c +++ b/sys/dev/uart/uart_dev_sab82532.c @@ -42,9 +42,6 @@ __FBSDID("$FreeBSD$"); #define DEFAULT_RCLK 29491200 -#define IS_CHANNEL_A(bas) (((bas)->iobase & 0x40) == 0x00) -#define IS_CHANNEL_B(bas) (((bas)->iobase & 0x40) == 0x40) - /* * NOTE: To allow us to read the baudrate divisor from the chip, we * copy the value written to the write-only BGR register to an unused @@ -219,7 +216,14 @@ sab82532_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, uart_barrier(bas); /* Set DTR. */ pvr = uart_getreg(bas, SAB_PVR); - pvr &= IS_CHANNEL_A(bas) ? ~SAB_PVR_DTR_A : ~SAB_PVR_DTR_B; + switch (bas->chan) { + case 1: + pvr &= ~SAB_PVR_DTR_A; + break; + case 2: + pvr &= ~SAB_PVR_DTR_B; + break; + } uart_setreg(bas, SAB_PVR, pvr | SAB_PVR_MAGIC); uart_barrier(bas); @@ -268,7 +272,14 @@ sab82532_term(struct uart_bas *bas) uint8_t pvr; pvr = uart_getreg(bas, SAB_PVR); - pvr |= IS_CHANNEL_A(bas) ? SAB_PVR_DTR_A : SAB_PVR_DTR_B; + switch (bas->chan) { + case 1: + pvr |= SAB_PVR_DTR_A; + break; + case 2: + pvr |= SAB_PVR_DTR_B; + break; + } uart_setreg(bas, SAB_PVR, pvr); uart_barrier(bas); } @@ -448,7 +459,14 @@ sab82532_bus_getsig(struct uart_softc *sc) vstr = uart_getreg(bas, SAB_VSTR); SIGCHG(vstr & SAB_VSTR_CD, sig, UART_SIG_DCD, UART_SIG_DDCD); pvr = uart_getreg(bas, SAB_PVR); - pvr &= (IS_CHANNEL_A(bas)) ? SAB_PVR_DSR_A : SAB_PVR_DSR_B; + switch (bas->chan) { + case 1: + pvr &= SAB_PVR_DSR_A; + break; + case 2: + pvr &= SAB_PVR_DSR_B; + break; + } SIGCHG(~pvr, sig, UART_SIG_DSR, UART_SIG_DDSR); mtx_unlock_spin(&sc->sc_hwmtx); new = sig & ~UART_SIGMASK_DELTA; @@ -558,15 +576,15 @@ static int sab82532_bus_probe(struct uart_softc *sc) { char buf[80]; - const char *ch, *vstr; + const char *vstr; int error; + char ch; error = sab82532_probe(&sc->sc_bas); if (error) return (error); - /* Assume the address range is naturally aligned. */ - ch = IS_CHANNEL_A(&sc->sc_bas) ? "A" : "B"; + ch = sc->sc_bas.chan - 1 + 'A'; switch (uart_getreg(&sc->sc_bas, SAB_VSTR) & SAB_VSTR_VMASK) { case SAB_VSTR_V_1: @@ -585,7 +603,7 @@ sab82532_bus_probe(struct uart_softc *sc) break; } - snprintf(buf, sizeof(buf), "SAB 82532 %s, channel %s", vstr, ch); + snprintf(buf, sizeof(buf), "SAB 82532 %s, channel %c", vstr, ch); device_set_desc_copy(sc->sc_dev, buf); return (0); } @@ -650,10 +668,20 @@ sab82532_bus_setsig(struct uart_softc *sc, int sig) mtx_lock_spin(&sc->sc_hwmtx); /* Set DTR pin. */ pvr = uart_getreg(bas, SAB_PVR); - if (new & UART_SIG_DTR) - pvr &= (IS_CHANNEL_A(bas)) ? ~SAB_PVR_DTR_A : ~SAB_PVR_DTR_B; - else - pvr |= (IS_CHANNEL_A(bas)) ? SAB_PVR_DTR_A : SAB_PVR_DTR_B; + switch (bas->chan) { + case 1: + if (new & UART_SIG_DTR) + pvr &= ~SAB_PVR_DTR_A; + else + pvr |= SAB_PVR_DTR_A; + break; + case 2: + if (new & UART_SIG_DTR) + pvr &= ~SAB_PVR_DTR_B; + else + pvr |= SAB_PVR_DTR_B; + break; + } uart_setreg(bas, SAB_PVR, pvr); /* Set RTS pin. */ diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c index 30d8ed8ede7e..25bdca7df30e 100644 --- a/sys/dev/uart/uart_dev_z8530.c +++ b/sys/dev/uart/uart_dev_z8530.c @@ -42,9 +42,6 @@ __FBSDID("$FreeBSD$"); #define DEFAULT_RCLK 307200 -#define IS_CHANNEL_A(bas) (((bas)->iobase & 7) != 0) -#define IS_CHANNEL_B(bas) (((bas)->iobase & 7) == 0) - /* Multiplexed I/O. */ static __inline void uart_setmreg(struct uart_bas *bas, int reg, int val) @@ -144,14 +141,22 @@ static int z8530_setup(struct uart_bas *bas, int baudrate, int databits, int stopbits, int parity) { - uint8_t tpc; + uint8_t mic, tpc; if (bas->rclk == 0) bas->rclk = DEFAULT_RCLK; /* Assume we don't need to perform a full hardware reset. */ - uart_setmreg(bas, WR_MIC, ((IS_CHANNEL_A(bas)) ? MIC_CRA : MIC_CRB) | - MIC_MIE | MIC_NV); + mic = MIC_MIE | MIC_NV; + switch (bas->chan) { + case 1: + mic |= MIC_CRA; + break; + case 2: + mic |= MIC_CRB; + break; + } + uart_setmreg(bas, WR_MIC, mic); uart_barrier(bas); /* Set clock sources and enable BRG. */ uart_setmreg(bas, WR_CMC, CMC_RC_BRG | CMC_TC_BRG); @@ -433,17 +438,16 @@ static int z8530_bus_probe(struct uart_softc *sc) { char buf[80]; - const char *ch; int error; + char ch; error = z8530_probe(&sc->sc_bas); if (error) return (error); - /* Assume the address range is naturally aligned. */ - ch = IS_CHANNEL_A(&sc->sc_bas) ? "A" : "B"; + ch = sc->sc_bas.chan - 1 + 'A'; - snprintf(buf, sizeof(buf), "z8530, channel %s", ch); + snprintf(buf, sizeof(buf), "z8530, channel %c", ch); device_set_desc_copy(sc->sc_dev, buf); return (0); }