Date: Wed, 24 Sep 2003 20:49:45 -0700 (PDT) From: Marcel Moolenaar <marcel@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 38554 for review Message-ID: <200309250349.h8P3njii049737@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=38554 Change 38554 by marcel@marcel_nfs on 2003/09/24 20:49:34 The problem: some hardware drivers communicate with multi-channel hardware and need to know which channel they control so that they can figure out how to program the hardware. The old solution: use the bus handle at first and the I/O address after that to determine the channel. The problem is that it creates a hardware dependency we can do without and also doesn't handle devices that access multiple channels through a single bus space. The new solution: add a channel number to struct uart_bas. It is filled in when the bas is constructed. The bus front-ends also pass a channel number to uart_bus_probe() for when it creates the bas in the softc. This way hardware drivers have direct (non-kludged) access to something that tells them which channel they control. Note that the current change to puc(4) is wrong. It sets the channel number for each UART, even those that aren't multi-channeled. We may not match system devices for which the channel is not set. This change is in preparation of syncing with HEAD after talking to nyan@ about the best way to go forward. A backout of his change is probably more work than committing on top of it. In any case it's better to work out the details off- branch and merge the end result to CVS when everybody is happy. Affected files ... .. //depot/projects/uart/dev/puc/puc.c#10 edit .. //depot/projects/uart/dev/puc/pucvar.h#8 edit .. //depot/projects/uart/dev/uart/uart.h#5 edit .. //depot/projects/uart/dev/uart/uart_bus.h#30 edit .. //depot/projects/uart/dev/uart/uart_bus_acpi.c#4 edit .. //depot/projects/uart/dev/uart/uart_bus_ebus.c#6 edit .. //depot/projects/uart/dev/uart/uart_bus_isa.c#4 edit .. //depot/projects/uart/dev/uart/uart_bus_pccard.c#2 edit .. //depot/projects/uart/dev/uart/uart_bus_pci.c#6 edit .. //depot/projects/uart/dev/uart/uart_bus_puc.c#8 edit .. //depot/projects/uart/dev/uart/uart_core.c#30 edit .. //depot/projects/uart/dev/uart/uart_cpu.h#11 edit .. //depot/projects/uart/dev/uart/uart_cpu_alpha.c#6 edit .. //depot/projects/uart/dev/uart/uart_cpu_amd64.c#4 edit .. //depot/projects/uart/dev/uart/uart_cpu_i386.c#5 edit .. //depot/projects/uart/dev/uart/uart_cpu_ia64.c#5 edit .. //depot/projects/uart/dev/uart/uart_cpu_pc98.c#4 edit .. //depot/projects/uart/dev/uart/uart_cpu_sparc64.c#14 edit .. //depot/projects/uart/dev/uart/uart_dev_sab82532.c#29 edit .. //depot/projects/uart/dev/uart/uart_dev_z8530.c#15 edit Differences ... ==== //depot/projects/uart/dev/puc/puc.c#10 (text+ko) ==== @@ -105,9 +105,10 @@ struct puc_device { struct resource_list resources; + int port; + int regshft; u_int serialfreq; u_int subtype; - int regshft; }; static void puc_intr(void *arg); @@ -331,6 +332,7 @@ &rle->res->r_bushandle); } + pdev->port = i + 1; pdev->serialfreq = sc->sc_desc.ports[i].serialfreq; pdev->subtype = sc->sc_desc.ports[i].type & PUC_PORT_SUBTYPE_MASK; @@ -598,12 +600,15 @@ case PUC_IVAR_FREQ: *result = pdev->serialfreq; break; - case PUC_IVAR_SUBTYPE: - *result = pdev->subtype; + case PUC_IVAR_PORT: + *result = pdev->port; break; case PUC_IVAR_REGSHFT: *result = pdev->regshft; break; + case PUC_IVAR_SUBTYPE: + *result = pdev->subtype; + break; default: return (ENOENT); } ==== //depot/projects/uart/dev/puc/pucvar.h#8 (text+ko) ==== @@ -115,8 +115,9 @@ enum puc_device_ivars { PUC_IVAR_FREQ, - PUC_IVAR_SUBTYPE, - PUC_IVAR_REGSHFT + PUC_IVAR_PORT, + PUC_IVAR_REGSHFT, + PUC_IVAR_SUBTYPE }; #ifdef PUC_ENTRAILS ==== //depot/projects/uart/dev/uart/uart.h#5 (text+ko) ==== @@ -38,8 +38,9 @@ struct uart_bas { bus_space_tag_t bst; bus_space_handle_t bsh; + u_int chan; + u_int rclk; u_int regshft; - u_int rclk; }; #define uart_regofs(bas, reg) ((reg) << (bas)->regshft) ==== //depot/projects/uart/dev/uart/uart_bus.h#30 (text+ko) ==== @@ -172,7 +172,7 @@ 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 *); ==== //depot/projects/uart/dev/uart/uart_bus_acpi.c#4 (text+ko) ==== @@ -73,7 +73,7 @@ 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. */ ==== //depot/projects/uart/dev/uart/uart_bus_ebus.c#6 (text+ko) ==== @@ -71,11 +71,11 @@ 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); } ==== //depot/projects/uart/dev/uart/uart_bus_isa.c#4 (text+ko) ==== @@ -155,13 +155,13 @@ 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); ==== //depot/projects/uart/dev/uart/uart_bus_pccard.c#2 (text+ko) ==== @@ -100,7 +100,7 @@ /* 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); ==== //depot/projects/uart/dev/uart/uart_bus_pci.c#6 (text+ko) ==== @@ -111,7 +111,7 @@ 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); ==== //depot/projects/uart/dev/uart/uart_bus_puc.c#8 (text+ko) ==== @@ -63,7 +63,7 @@ { 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); @@ -84,11 +84,13 @@ return (ENXIO); } + if (BUS_READ_IVAR(parent, dev, PUC_IVAR_PORT, &port)) + port = 0; if (BUS_READ_IVAR(parent, dev, PUC_IVAR_FREQ, &rclk)) 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); ==== //depot/projects/uart/dev/uart/uart_core.c#30 (text+ko) ==== @@ -221,7 +221,7 @@ } 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; @@ -269,11 +269,13 @@ */ 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; ==== //depot/projects/uart/dev/uart/uart_cpu.h#11 (text+ko) ==== @@ -67,7 +67,6 @@ void *cookie; /* Type dependent use. */ }; -bus_addr_t uart_cpu_busaddr(struct uart_bas *); int uart_cpu_eqres(struct uart_bas *, struct uart_bas *); int uart_cpu_getdev(int, struct uart_devinfo *); ==== //depot/projects/uart/dev/uart/uart_cpu_alpha.c#6 (text+ko) ==== @@ -39,13 +39,6 @@ #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> -bus_addr_t -uart_cpu_busaddr(struct uart_bas *bas) -{ - - return (bas->bsh); -} - int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { @@ -65,6 +58,7 @@ return (ENXIO); boothowto |= RB_SERIAL; di->ops = uart_ns8250_ops; + di->bas.chan = 0; di->bas.bst = busspace_isa_io; di->bas.bsh = 0x3f8; di->bas.regshft = 0; @@ -101,6 +95,7 @@ * only have ns8250 and successors on alpha. */ di->ops = uart_ns8250_ops; + di->bas.chan = 0; di->bas.bst = busspace_isa_io; di->bas.bsh = ivar; di->bas.regshft = 0; ==== //depot/projects/uart/dev/uart/uart_cpu_amd64.c#4 (text+ko) ==== @@ -36,13 +36,6 @@ #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> -bus_addr_t -uart_cpu_busaddr(struct uart_bas *bas) -{ - - return (bas->bsh); -} - int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { @@ -82,6 +75,7 @@ * ns8250 and successors on i386. */ di->ops = uart_ns8250_ops; + di->bas.chan = 0; di->bas.bst = AMD64_BUS_SPACE_IO; di->bas.bsh = ivar; di->bas.regshft = 0; ==== //depot/projects/uart/dev/uart/uart_cpu_i386.c#5 (text+ko) ==== @@ -36,13 +36,6 @@ #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> -bus_addr_t -uart_cpu_busaddr(struct uart_bas *bas) -{ - - return (bas->bsh); -} - int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { @@ -82,6 +75,7 @@ * ns8250 and successors on i386. */ di->ops = uart_ns8250_ops; + di->bas.chan = 0; di->bas.bst = I386_BUS_SPACE_IO; di->bas.bsh = ivar; di->bas.regshft = 0; ==== //depot/projects/uart/dev/uart/uart_cpu_ia64.c#5 (text+ko) ==== @@ -44,13 +44,6 @@ UART_PARITY_ODD, UART_PARITY_MARK, UART_PARITY_SPACE }; -bus_addr_t -uart_cpu_busaddr(struct uart_bas *bas) -{ - - return (bas->bsh); -} - int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { @@ -82,7 +75,7 @@ continue; di->ops = uart_ns8250_ops; - 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; di->bas.bsh = ent->address.addr_high; @@ -129,6 +122,7 @@ * ns8250 and successors on i386. */ di->ops = uart_ns8250_ops; + di->bas.chan = 0; di->bas.bst = IA64_BUS_SPACE_IO; di->bas.bsh = ivar; di->bas.regshft = 0; ==== //depot/projects/uart/dev/uart/uart_cpu_pc98.c#4 (text+ko) ==== @@ -36,13 +36,6 @@ #include <dev/uart/uart.h> #include <dev/uart/uart_cpu.h> -bus_addr_t -uart_cpu_busaddr(struct uart_bas *bas) -{ - - return (bas->bsh->bsh_base); -} - int uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) { @@ -87,6 +80,7 @@ di->ops = uart_ns8250_ops; else di->ops = uart_i8251_ops; + di->bas.chan = 0; di->bas.bst = I386_BUS_SPACE_IO; i386_bus_space_handle_alloc(di->bas.bst, ivar, 8, &di->bas.bsh); di->bas.regshft = 0; ==== //depot/projects/uart/dev/uart/uart_cpu_sparc64.c#14 (text+ko) ==== @@ -55,14 +55,7 @@ if (len < 2 || alias[len - 2] != ':' || alias[len - 1] < 'a' || alias[len - 1] > 'b') return (0); - return (alias[len - 1] - 'a'); -} - -bus_addr_t -uart_cpu_busaddr(struct uart_bas *bas) -{ - - return (bas->bsh); + return (alias[len - 1] - 'a' + 1); } int @@ -78,7 +71,7 @@ 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; /* @@ -130,16 +123,18 @@ 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. */ ==== //depot/projects/uart/dev/uart/uart_dev_sab82532.c#29 (text+ko) ==== @@ -42,9 +42,6 @@ #define DEFAULT_RCLK 29491200 -#define IS_CHANNEL_A(bas) ((uart_cpu_busaddr(bas) & 0x40) == 0x00) -#define IS_CHANNEL_B(bas) ((uart_cpu_busaddr(bas) & 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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. */ ==== //depot/projects/uart/dev/uart/uart_dev_z8530.c#15 (text+ko) ==== @@ -42,9 +42,6 @@ #define DEFAULT_RCLK 307200 -#define IS_CHANNEL_A(bas) ((uart_cpu_busaddr(bas) & 7) != 0) -#define IS_CHANNEL_B(bas) ((uart_cpu_busaddr(bas) & 7) == 0) - /* Multiplexed I/O. */ static __inline void uart_setmreg(struct uart_bas *bas, int reg, int val) @@ -144,14 +141,22 @@ 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 @@ 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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200309250349.h8P3njii049737>