PERFORCE change 38554 for review
Marcel Moolenaar
marcel at FreeBSD.org
Wed Sep 24 20:49:53 PDT 2003
http://perforce.freebsd.org/chv.cgi?CH=38554
Change 38554 by marcel at 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);
}
More information about the p4-projects
mailing list