1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-14 10:09:48 +00:00

Revert the introduction of iobase in struct uart_bas. Both the SAB82532

and the Z8530 drivers used the I/O address as a quick and dirty way to
determine which channel they operated on, but formalizing this by
introducing iobase is not a solution. How for example would a driver
know which channel it controls for a multi-channel UART that only has a
single I/O range?

Instead, add an explicit field, called chan, to struct uart_bas that
holds the channel within a device, or 0 otherwise. The chan field is
initialized both by the system device probing (i.e. a system console)
or it is passed down to uart_bus_probe() by any of the bus front-ends.
As such, it impacts all platforms and bus drivers and makes it a rather
large commit.

Remove the use of iobase in uart_cpu_eqres() for pc98. It is expected
that platforms have the capability to compare tag and handle pairs for
equality; as to determine whether two pairs access the same device or
not. The use of iobase for pc98 makes it impossible to formalize this
and turn it into a real newbus function later. This commit reverts
uart_cpu_eqres() for pc98 to an unimplemented function. It has to be
reimplemented using only the tag and handle fields in struct uart_bas.

Rewrite the SAB82532 and Z8530 drivers to use the chan field in struct
uart_bas. Remove the IS_CHANNEL_A and IS_CHANNEL_B macros. We don't
need to abstract anything anymore.

Discussed with: nyan
Tested on: i386, ia64, sparc64
This commit is contained in:
Marcel Moolenaar 2003-09-26 05:14:56 +00:00
parent 153bbe3e6a
commit 875f70dba4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=120452
17 changed files with 99 additions and 61 deletions

View File

@ -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)

View File

@ -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 *);

View File

@ -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. */

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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, &regshft))
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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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. */

View File

@ -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);
}