convert these to use new <machine/bus.h> interfaces. This involved

substantial reworking of the multi-port drivers, as they need to frob
bits in the io-port spaces of their children.  As a result, the
commulti->com attachment interface is substantially more complex.
(This may be fixable in the future by making some of the code common,
but as long as io-port allocation checking is planned, it's necessary.)
This commit is contained in:
cgd 1996-03-10 09:01:20 +00:00
parent ab5476b242
commit 85286bff2f
7 changed files with 797 additions and 414 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: com.c,v 1.74 1996/03/09 01:02:08 cgd Exp $ */
/* $NetBSD: com.c,v 1.75 1996/03/10 09:01:24 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995, 1996
@ -57,7 +57,7 @@
#include <sys/device.h>
#include <machine/cpu.h>
#include <machine/pio.h>
#include <machine/bus.h>
#include <dev/isa/isavar.h>
#include <dev/isa/comreg.h>
@ -86,6 +86,11 @@ struct com_softc {
#ifdef COM_HAYESP
int sc_hayespbase;
#endif
bus_chipset_tag_t sc_bc;
bus_io_handle_t sc_ioh;
bus_io_handle_t sc_hayespioh;
u_char sc_hwflags;
#define COM_HW_NOIEN 0x01
#define COM_HW_FIFO 0x02
@ -104,6 +109,9 @@ struct com_softc {
};
int comprobe __P((struct device *, void *, void *));
#ifdef COM_HAYESP
int comprobeHAYESP __P((bus_io_handle_t hayespioh, struct com_softc *sc));
#endif
void comattach __P((struct device *, struct device *, void *));
int comopen __P((dev_t, int, int, struct proc *));
int comclose __P((dev_t, int, int, struct proc *));
@ -113,18 +121,23 @@ void compoll __P((void *));
int comparam __P((struct tty *, struct termios *));
void comstart __P((struct tty *));
int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
struct cfdriver comcd = {
NULL, "com", comprobe, comattach, DV_TTY, sizeof(struct com_softc)
};
#ifdef COMCONSOLE
int comdefaultrate = CONSPEED;
int comconsole = COMCONSOLE;
int comdefaultrate = CONSPEED; /* XXX why set default? */
#else
int comdefaultrate = TTYDEF_SPEED;
int comconsole = -1;
#endif
int comconsaddr;
int comconsinit;
int comconsattached;
bus_chipset_tag_t comconsbc;
bus_io_handle_t comconsioh;
int commajor;
int comsopen = 0;
int comevents = 0;
@ -169,14 +182,16 @@ comspeed(speed)
}
int
comprobe1(iobase)
comprobe1(bc, ioh, iobase)
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
int iobase;
{
/* force access to id reg */
outb(iobase + com_lcr, 0);
outb(iobase + com_iir, 0);
if (inb(iobase + com_iir) & 0x38)
bus_io_write_1(bc, ioh, com_lcr, 0);
bus_io_write_1(bc, ioh, com_iir, 0);
if (bus_io_read_1(bc, ioh, com_iir) & 0x38)
return 0;
return 1;
@ -184,12 +199,13 @@ comprobe1(iobase)
#ifdef COM_HAYESP
int
comprobeHAYESP(iobase, sc)
int iobase;
comprobeHAYESP(hayespioh, sc)
bus_io_handle_t hayespioh;
struct com_softc *sc;
{
char val, dips;
int combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
bus_chipset_tag_t bc = sc->sc_bc;
/*
* Hayes ESP cards have two iobases. One is for compatibility with
@ -199,7 +215,7 @@ comprobeHAYESP(iobase, sc)
*/
/* Test for ESP signature */
if ((inb(iobase) & 0xf3) == 0)
if ((bus_io_read_1(bc, hayespioh, 0) & 0xf3) == 0)
return 0;
/*
@ -207,8 +223,8 @@ comprobeHAYESP(iobase, sc)
*/
/* Get the dip-switch configurations */
outb(iobase + HAYESP_CMD1, HAYESP_GETDIPS);
dips = inb(iobase + HAYESP_STATUS1);
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS);
dips = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1);
/* Determine which com port this ESP card services: bits 0,1 of */
/* dips is the port # (0-3); combaselist[val] is the com_iobase */
@ -219,9 +235,9 @@ comprobeHAYESP(iobase, sc)
/* Check ESP Self Test bits. */
/* Check for ESP version 2.0: bits 4,5,6 == 010 */
outb(iobase + HAYESP_CMD1, HAYESP_GETTEST);
val = inb(iobase + HAYESP_STATUS1); /* Clear reg 1 */
val = inb(iobase + HAYESP_STATUS2);
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETTEST);
val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1); /* Clear reg 1 */
val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS2);
if ((val & 0x70) < 0x20) {
printf("-old (%o)", val & 0x70);
/* we do not support the necessary features */
@ -251,15 +267,50 @@ comprobe(parent, match, aux)
struct device *parent;
void *match, *aux;
{
struct isa_attach_args *ia = aux;
int iobase = ia->ia_iobase;
struct cfdata *cf = match;
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
int iobase, needioh;
int rv = 1;
if (!comprobe1(iobase))
return 0;
if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
ia->ia_iosize = COM_NPORTS;
ia->ia_msize = 0;
return 1;
bc = ia->ia_bc;
iobase = ia->ia_iobase;
needioh = 1;
} else {
struct commulti_attach_args *ca = aux;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
return (0);
bc = ca->ca_bc;
iobase = ca->ca_iobase;
ioh = ca->ca_ioh;
needioh = 0;
}
/* if it's in use as console, it's there. */
if (iobase == comconsaddr && !comconsattached)
goto out;
if (needioh && bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
rv = 0;
goto out;
}
rv = comprobe1(bc, ioh, iobase);
if (needioh)
bus_io_unmap(bc, ioh, COM_NPORTS);
out:
if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
ia->ia_iosize = COM_NPORTS;
ia->ia_msize = 0;
}
return (rv);
}
void
@ -268,64 +319,114 @@ comattach(parent, self, aux)
void *aux;
{
struct com_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
struct cfdata *cf = sc->sc_dev.dv_cfdata;
int iobase = ia->ia_iobase;
int iobase, irq;
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
struct tty *tp;
#ifdef COM_HAYESP
int hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
int *hayespp;
#endif
sc->sc_iobase = iobase;
sc->sc_hwflags = ISSET(cf->cf_flags, COM_HW_NOIEN);
sc->sc_hwflags = 0;
sc->sc_swflags = 0;
if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
if (sc->sc_dev.dv_unit == comconsole)
delay(1000);
/*
* We're living on an isa.
*/
iobase = ia->ia_iobase;
bc = ia->ia_bc;
if (iobase != comconsaddr) {
if (bus_io_map(bc, iobase, COM_NPORTS, &ioh))
panic("comattach: io mapping failed");
} else
ioh = comconsioh;
irq = ia->ia_irq;
} else {
struct commulti_attach_args *ca = aux;
/*
* We're living on a commulti.
*/
iobase = ca->ca_iobase;
bc = ca->ca_bc;
ioh = ca->ca_ioh;
irq = IRQUNK;
if (ca->ca_noien)
sc->sc_hwflags |= COM_HW_NOIEN;
}
sc->sc_bc = bc;
sc->sc_ioh = ioh;
sc->sc_iobase = iobase;
if (iobase == comconsaddr) {
comconsattached = 1;
/*
* Need to reset baud rate, etc. of next print so reset
* comconsinit. Also make sure console is always "hardwired".
*/
delay(1000); /* wait for output to finish */
comconsinit = 0;
SET(sc->sc_hwflags, COM_HW_CONSOLE);
SET(sc->sc_swflags, COM_SW_SOFTCAR);
}
#ifdef COM_HAYESP
/* Look for a Hayes ESP board. */
for (hayespp = hayesp_ports; *hayespp != 0; hayespp++)
if (comprobeHAYESP(*hayespp, sc)) {
for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
bus_io_handle_t hayespioh;
#define HAYESP_NPORTS 8 /* XXX XXX XXX ??? ??? ??? */
if (bus_io_map(bc, *hayespp, HAYESP_NPORTS, &hayespioh))
continue;
if (comprobeHAYESP(hayespioh, sc)) {
sc->sc_hayespbase = *hayespp;
sc->sc_hayespioh = hayespioh;
break;
}
bus_io_unmap(bc, hayespioh, HAYESP_NPORTS);
}
/* No ESP; look for other things. */
if (*hayespp == 0) {
#endif
/* look for a NS 16550AF UART with FIFOs */
outb(iobase + com_fifo,
bus_io_write_1(bc, ioh, com_fifo,
FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
delay(100);
if (ISSET(inb(iobase + com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK)
if (ISSET(inb(iobase + com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK)
if (ISSET(bus_io_read_1(bc, ioh, com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
SET(sc->sc_hwflags, COM_HW_FIFO);
printf(": ns16550a, working fifo\n");
} else
printf(": ns16550, broken fifo\n");
else
printf(": ns8250 or ns16450, no fifo\n");
outb(iobase + com_fifo, 0);
bus_io_write_1(bc, ioh, com_fifo, 0);
#ifdef COM_HAYESP
}
#endif
/* disable interrupts */
outb(iobase + com_ier, 0);
outb(iobase + com_mcr, 0);
bus_io_write_1(bc, ioh, com_ier, 0);
bus_io_write_1(bc, ioh, com_mcr, 0);
if (ia->ia_irq != IRQUNK)
sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_TTY,
if (irq != IRQUNK)
sc->sc_ih = isa_intr_establish(irq, IST_EDGE, IPL_TTY,
comintr, sc);
#ifdef KGDB
if (kgdb_dev == makedev(commajor, unit)) {
if (comconsole == unit)
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
kgdb_dev = -1; /* can't debug over console port */
else {
(void) cominit(unit, kgdb_rate);
(void) cominit(bc, ioh, kgdb_rate);
if (kgdb_debug_init) {
/*
* Print prefix of device name,
@ -340,15 +441,9 @@ comattach(parent, self, aux)
}
#endif
if (sc->sc_dev.dv_unit == comconsole) {
/*
* Need to reset baud rate, etc. of next print so reset
* comconsinit. Also make sure console is always "hardwired".
*/
comconsinit = 0;
SET(sc->sc_hwflags, COM_HW_CONSOLE);
SET(sc->sc_swflags, COM_SW_SOFTCAR);
}
/* XXX maybe move up some? */
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
printf("%s: console\n", sc->sc_dev.dv_xname);
}
int
@ -359,7 +454,8 @@ comopen(dev, flag, mode, p)
{
int unit = COMUNIT(dev);
struct com_softc *sc;
int iobase;
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
struct tty *tp;
int s;
int error = 0;
@ -405,56 +501,57 @@ comopen(dev, flag, mode, p)
sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
iobase = sc->sc_iobase;
bc = sc->sc_bc;
ioh = sc->sc_ioh;
#ifdef COM_HAYESP
/* Setup the ESP board */
if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
int hayespbase = sc->sc_hayespbase;
bus_io_handle_t hayespioh = sc->sc_hayespioh;
outb(iobase + com_fifo,
bus_io_write_1(bc, ioh, com_fifo,
FIFO_DMA_MODE|FIFO_ENABLE|
FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8);
/* Set 16550 compatibility mode */
outb(hayespbase + HAYESP_CMD1, HAYESP_SETMODE);
outb(hayespbase + HAYESP_CMD2,
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
HAYESP_MODE_SCALE);
/* Set RTS/CTS flow control */
outb(hayespbase + HAYESP_CMD1, HAYESP_SETFLOWTYPE);
outb(hayespbase + HAYESP_CMD2, HAYESP_FLOW_RTS);
outb(hayespbase + HAYESP_CMD2, HAYESP_FLOW_CTS);
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE);
bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS);
bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS);
/* Set flow control levels */
outb(hayespbase + HAYESP_CMD1, HAYESP_SETRXFLOW);
outb(hayespbase + HAYESP_CMD2,
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW);
bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
HAYESP_HIBYTE(HAYESP_RXHIWMARK));
outb(hayespbase + HAYESP_CMD2,
bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
HAYESP_LOBYTE(HAYESP_RXHIWMARK));
outb(hayespbase + HAYESP_CMD2,
bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
HAYESP_HIBYTE(HAYESP_RXLOWMARK));
outb(hayespbase + HAYESP_CMD2,
bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
HAYESP_LOBYTE(HAYESP_RXLOWMARK));
} else
#endif
if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
/* Set the FIFO threshold based on the receive speed. */
outb(iobase + com_fifo,
bus_io_write_1(bc, ioh, com_fifo,
FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
(tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
/* flush any pending I/O */
while (ISSET(inb(iobase + com_lsr), LSR_RXRDY))
(void) inb(iobase + com_data);
while (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
(void) bus_io_read_1(bc, ioh, com_data);
/* you turn me on, baby */
sc->sc_mcr = MCR_DTR | MCR_RTS;
if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
SET(sc->sc_mcr, MCR_IENABLE);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
outb(iobase + com_ier, sc->sc_ier);
bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
sc->sc_msr = inb(iobase + com_msr);
sc->sc_msr = bus_io_read_1(bc, ioh, com_msr);
if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) ||
ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
SET(tp->t_state, TS_CARR_ON);
@ -493,7 +590,8 @@ comclose(dev, flag, mode, p)
int unit = COMUNIT(dev);
struct com_softc *sc = comcd.cd_devs[unit];
struct tty *tp = sc->sc_tty;
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int s;
/* XXX This is for cons.c. */
@ -503,12 +601,12 @@ comclose(dev, flag, mode, p)
(*linesw[tp->t_line].l_close)(tp, flag);
s = spltty();
CLR(sc->sc_lcr, LCR_SBREAK);
outb(iobase + com_lcr, sc->sc_lcr);
outb(iobase + com_ier, 0);
bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
bus_io_write_1(bc, ioh, com_ier, 0);
if (ISSET(tp->t_cflag, HUPCL) &&
!ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
/* XXX perhaps only clear DTR */
outb(iobase + com_mcr, 0);
bus_io_write_1(bc, ioh, com_mcr, 0);
}
CLR(tp->t_state, TS_BUSY | TS_FLUSH);
if (--comsopen == 0)
@ -516,7 +614,7 @@ comclose(dev, flag, mode, p)
splx(s);
ttyclose(tp);
#ifdef notyet /* XXXX */
if (unit != comconsole) {
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
ttyfree(tp);
sc->sc_tty = 0;
}
@ -582,7 +680,8 @@ comioctl(dev, cmd, data, flag, p)
int unit = COMUNIT(dev);
struct com_softc *sc = comcd.cd_devs[unit];
struct tty *tp = sc->sc_tty;
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int error;
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
@ -595,29 +694,29 @@ comioctl(dev, cmd, data, flag, p)
switch (cmd) {
case TIOCSBRK:
SET(sc->sc_lcr, LCR_SBREAK);
outb(iobase + com_lcr, sc->sc_lcr);
bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
break;
case TIOCCBRK:
CLR(sc->sc_lcr, LCR_SBREAK);
outb(iobase + com_lcr, sc->sc_lcr);
bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
break;
case TIOCSDTR:
SET(sc->sc_mcr, sc->sc_dtr);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
break;
case TIOCCDTR:
CLR(sc->sc_mcr, sc->sc_dtr);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
break;
case TIOCMSET:
CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
case TIOCMBIS:
SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
break;
case TIOCMBIC:
CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
break;
case TIOCMGET: {
u_char m;
@ -637,7 +736,7 @@ comioctl(dev, cmd, data, flag, p)
SET(bits, TIOCM_DSR);
if (ISSET(m, MSR_RI | MSR_TERI))
SET(bits, TIOCM_RI);
if (inb(iobase + com_ier))
if (bus_io_read_1(bc, ioh, com_ier))
SET(bits, TIOCM_LE);
*(int *)data = bits;
break;
@ -692,7 +791,8 @@ comparam(tp, t)
struct termios *t;
{
struct com_softc *sc = comcd.cd_devs[COMUNIT(tp->t_dev)];
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int ospeed = comspeed(t->c_ospeed);
u_char lcr;
tcflag_t oldcflag;
@ -732,7 +832,7 @@ comparam(tp, t)
if (ospeed == 0) {
CLR(sc->sc_mcr, MCR_DTR);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
}
/*
@ -767,34 +867,34 @@ comparam(tp, t)
}
}
outb(iobase + com_lcr, lcr | LCR_DLAB);
outb(iobase + com_dlbl, ospeed);
outb(iobase + com_dlbh, ospeed >> 8);
outb(iobase + com_lcr, lcr);
bus_io_write_1(bc, ioh, com_lcr, lcr | LCR_DLAB);
bus_io_write_1(bc, ioh, com_dlbl, ospeed);
bus_io_write_1(bc, ioh, com_dlbh, ospeed >> 8);
bus_io_write_1(bc, ioh, com_lcr, lcr);
SET(sc->sc_mcr, MCR_DTR);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
} else
outb(iobase + com_lcr, lcr);
bus_io_write_1(bc, ioh, com_lcr, lcr);
if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) &&
ISSET(sc->sc_hwflags, COM_HW_FIFO))
outb(iobase + com_fifo,
bus_io_write_1(bc, ioh, com_fifo,
FIFO_ENABLE |
(t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
} else
outb(iobase + com_lcr, lcr);
bus_io_write_1(bc, ioh, com_lcr, lcr);
/* When not using CRTSCTS, RTS follows DTR. */
if (!ISSET(t->c_cflag, CRTSCTS)) {
if (ISSET(sc->sc_mcr, MCR_DTR)) {
if (!ISSET(sc->sc_mcr, MCR_RTS)) {
SET(sc->sc_mcr, MCR_RTS);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
}
} else {
if (ISSET(sc->sc_mcr, MCR_RTS)) {
CLR(sc->sc_mcr, MCR_RTS);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
}
}
sc->sc_dtr = MCR_DTR | MCR_RTS;
@ -816,7 +916,7 @@ comparam(tp, t)
ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
(*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
CLR(sc->sc_mcr, sc->sc_dtr);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
}
/* Just to be sure... */
@ -830,7 +930,8 @@ comstart(tp)
struct tty *tp;
{
struct com_softc *sc = comcd.cd_devs[COMUNIT(tp->t_dev)];
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int s;
s = spltty();
@ -854,14 +955,14 @@ comstart(tp)
if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
SET(sc->sc_ier, IER_ETXRDY);
outb(iobase + com_ier, sc->sc_ier);
bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
}
#ifdef COM_HAYESP
if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
u_char buffer[1024], *cp = buffer;
int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
do
outb(iobase + com_data, *cp++);
bus_io_write_1(bc, ioh, com_data, *cp++);
while (--n);
}
else
@ -870,17 +971,17 @@ comstart(tp)
u_char buffer[16], *cp = buffer;
int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
do {
outb(iobase + com_data, *cp++);
bus_io_write_1(bc, ioh, com_data, *cp++);
} while (--n);
} else
outb(iobase + com_data, getc(&tp->t_outq));
bus_io_write_1(bc, ioh, com_data, getc(&tp->t_outq));
out:
splx(s);
return;
stopped:
if (ISSET(sc->sc_ier, IER_ETXRDY)) {
CLR(sc->sc_ier, IER_ETXRDY);
outb(iobase + com_ier, sc->sc_ier);
bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
}
splx(s);
}
@ -980,7 +1081,8 @@ compoll(arg)
!ISSET(sc->sc_mcr, MCR_RTS)) {
/* XXX */
SET(sc->sc_mcr, MCR_RTS);
outb(sc->sc_iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(sc->sc_bc, sc->sc_ioh, com_mcr,
sc->sc_mcr);
}
splx(s);
@ -1007,7 +1109,8 @@ comintr(arg)
void *arg;
{
struct com_softc *sc = arg;
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
struct tty *tp;
u_char lsr, data, msr, delta;
#ifdef COM_DEBUG
@ -1019,10 +1122,10 @@ comintr(arg)
#ifdef COM_DEBUG
n = 0;
if (ISSET(iter[n].iir = inb(iobase + com_iir), IIR_NOPEND))
if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
return (0);
#else
if (ISSET(inb(iobase + com_iir), IIR_NOPEND))
if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
return (0);
#endif
@ -1032,14 +1135,14 @@ comintr(arg)
#ifdef COM_DEBUG
iter[n].lsr =
#endif
lsr = inb(iobase + com_lsr);
lsr = bus_io_read_1(bc, ioh, com_lsr);
if (ISSET(lsr, LSR_RXRDY)) {
register u_char *p = sc->sc_ibufp;
comevents = 1;
do {
data = inb(iobase + com_data);
data = bus_io_read_1(bc, ioh, com_data);
if (ISSET(lsr, LSR_BI)) {
#ifdef notdef
printf("break %02x %02x %02x %02x\n",
@ -1047,7 +1150,8 @@ comintr(arg)
sc->sc_dtr);
#endif
#ifdef DDB
if (sc->sc_dev.dv_unit == comconsole) {
if (ISSET(sc->sc_hwflags,
COM_HW_CONSOLE)) {
Debugger();
goto next;
}
@ -1064,8 +1168,8 @@ comintr(arg)
ISSET(tp->t_cflag, CRTSCTS)) {
/* XXX */
CLR(sc->sc_mcr, MCR_RTS);
outb(iobase + com_mcr,
sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr,
sc->sc_mcr);
}
}
next:
@ -1074,7 +1178,7 @@ comintr(arg)
goto ohfudge;
iter[n].lsr =
#endif
lsr = inb(iobase + com_lsr);
lsr = bus_io_read_1(bc, ioh, com_lsr);
} while (ISSET(lsr, LSR_RXRDY));
sc->sc_ibufp = p;
@ -1087,7 +1191,7 @@ comintr(arg)
#ifdef COM_DEBUG
iter[n].msr =
#endif
msr = inb(iobase + com_msr);
msr = bus_io_read_1(bc, ioh, com_msr);
if (msr != sc->sc_msr) {
delta = msr ^ sc->sc_msr;
@ -1096,7 +1200,7 @@ comintr(arg)
!ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
(*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
CLR(sc->sc_mcr, sc->sc_dtr);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
}
if (ISSET(delta & msr, MSR_CTS) &&
ISSET(tp->t_cflag, CRTSCTS)) {
@ -1115,10 +1219,10 @@ comintr(arg)
#ifdef COM_DEBUG
if (++n >= 32)
goto ohfudge;
if (ISSET(iter[n].iir = inb(iobase + com_iir), IIR_NOPEND))
if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
return (1);
#else
if (ISSET(inb(iobase + com_iir), IIR_NOPEND))
if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
return (1);
#endif
}
@ -1147,8 +1251,21 @@ void
comcnprobe(cp)
struct consdev *cp;
{
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
int found;
if (!comprobe1(CONADDR)) {
#if 0
XXX NEEDS TO BE FIXED XXX
bc = ???;
#endif
if (bus_io_map(bc, CONADDR, COM_NPORTS, &ioh)) {
cp->cn_pri = CN_DEAD;
return;
}
found = comprobe1(bc, ioh, CONADDR);
bus_io_unmap(bc, ioh, COM_NPORTS);
if (!found) {
cp->cn_pri = CN_DEAD;
return;
}
@ -1172,26 +1289,34 @@ comcninit(cp)
struct consdev *cp;
{
cominit(CONUNIT, comdefaultrate);
comconsole = CONUNIT;
#if 0
XXX NEEDS TO BE FIXED XXX
comconsbc = ???;
#endif
if (bus_io_map(comconsbc, CONADDR, COM_NPORTS, &comconsioh))
panic("comcninit: mapping failed");
cominit(comconsbc, comconsioh, comdefaultrate);
comconsaddr = CONADDR;
comconsinit = 0;
}
cominit(unit, rate)
int unit, rate;
cominit(bc, ioh, rate)
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
int rate;
{
int s = splhigh();
int iobase = CONADDR;
u_char stat;
outb(iobase + com_lcr, LCR_DLAB);
bus_io_write_1(bc, ioh, com_lcr, LCR_DLAB);
rate = comspeed(comdefaultrate);
outb(iobase + com_dlbl, rate);
outb(iobase + com_dlbh, rate >> 8);
outb(iobase + com_lcr, LCR_8BITS);
outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY);
outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
stat = inb(iobase + com_iir);
bus_io_write_1(bc, ioh, com_dlbl, rate);
bus_io_write_1(bc, ioh, com_dlbh, rate >> 8);
bus_io_write_1(bc, ioh, com_lcr, LCR_8BITS);
bus_io_write_1(bc, ioh, com_ier, IER_ERXRDY | IER_ETXRDY);
bus_io_write_1(bc, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
stat = bus_io_read_1(bc, ioh, com_iir);
splx(s);
}
@ -1199,13 +1324,14 @@ comcngetc(dev)
dev_t dev;
{
int s = splhigh();
int iobase = CONADDR;
bus_chipset_tag_t bc = comconsbc;
bus_io_handle_t ioh = comconsioh;
u_char stat, c;
while (!ISSET(stat = inb(iobase + com_lsr), LSR_RXRDY))
while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
;
c = inb(iobase + com_data);
stat = inb(iobase + com_iir);
c = bus_io_read_1(bc, ioh, com_data);
stat = bus_io_read_1(bc, ioh, com_iir);
splx(s);
return c;
}
@ -1219,7 +1345,8 @@ comcnputc(dev, c)
int c;
{
int s = splhigh();
int iobase = CONADDR;
bus_chipset_tag_t bc = comconsbc;
bus_io_handle_t ioh = comconsioh;
u_char stat;
register int timo;
@ -1227,20 +1354,20 @@ comcnputc(dev, c)
if (dev != kgdb_dev)
#endif
if (comconsinit == 0) {
(void) cominit(COMUNIT(dev), comdefaultrate);
(void) cominit(bc, ioh, comdefaultrate);
comconsinit = 1;
}
/* wait for any pending transmission to finish */
timo = 50000;
while (!ISSET(stat = inb(iobase + com_lsr), LSR_TXRDY) && --timo)
while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
;
outb(iobase + com_data, c);
bus_io_write_1(bc, ioh, com_data, c);
/* wait for this transmission to complete */
timo = 1500000;
while (!ISSET(stat = inb(iobase + com_lsr), LSR_TXRDY) && --timo)
while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
;
/* clear any interrupts generated by this transmission */
stat = inb(iobase + com_iir);
stat = bus_io_read_1(bc, ioh, com_iir);
splx(s);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: comvar.h,v 1.2 1996/03/09 23:37:14 cgd Exp $ */
/* $NetBSD: comvar.h,v 1.3 1996/03/10 09:01:26 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@ -32,6 +32,16 @@
struct commulti_attach_args {
int ca_slave; /* slave number */
bus_chipset_tag_t ca_bc;
bus_io_handle_t ca_ioh;
int ca_iobase;
int ca_noien;
};
int comprobe1 __P((int));
int comprobe1 __P((bus_chipset_tag_t, bus_io_handle_t, int));
extern int comconsaddr;
extern int comconsattached;
extern bus_chipset_tag_t comconsbc;
extern bus_io_handle_t comconsioh;

View File

@ -1,6 +1,7 @@
/* $NetBSD: ast.c,v 1.21 1996/03/09 01:03:59 cgd Exp $ */
/* $NetBSD: ast.c,v 1.22 1996/03/10 09:01:20 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
* Copyright (c) 1995 Charles Hannum. All rights reserved.
*
* This code is derived from public-domain software written by
@ -35,7 +36,7 @@
#include <sys/param.h>
#include <sys/device.h>
#include <machine/pio.h>
#include <machine/bus.h>
#include <dev/isa/isavar.h>
#include <dev/isa/comreg.h>
@ -47,9 +48,12 @@ struct ast_softc {
struct device sc_dev;
void *sc_ih;
bus_chipset_tag_t sc_bc;
int sc_iobase;
int sc_alive; /* mask of slave units attached */
void *sc_slaves[NSLAVES]; /* com device unit numbers */
bus_io_handle_t sc_slaveioh[NSLAVES];
};
int astprobe();
@ -66,40 +70,62 @@ astprobe(parent, self, aux)
void *aux;
{
struct isa_attach_args *ia = aux;
int iobase = ia->ia_iobase;
bus_chipset_tag_t bc = ia->ia_bc;
bus_io_handle_t ioh;
int i, rv = 1;
/*
* Do the normal com probe for the first UART and assume
* its presence means there is a multiport board there.
* its presence, and the ability to map the other UARTS,
* means there is a multiport board there.
* XXX Needs more robustness.
*/
ia->ia_iosize = NSLAVES * COM_NPORTS;
return (comprobe1(ia->ia_iobase));
/* if the first port is in use as console, then it. */
if (iobase == comconsaddr && !comconsattached)
goto checkmappings;
if (bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
rv = 0;
goto out;
}
rv = comprobe1(bc, ioh, iobase);
bus_io_unmap(bc, ioh, COM_NPORTS);
if (rv == 0)
goto out;
checkmappings:
for (i = 1; i < NSLAVES; i++) {
iobase += COM_NPORTS;
if (iobase == comconsaddr && !comconsattached)
continue;
if (bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
rv = 0;
goto out;
}
bus_io_unmap(bc, ioh, COM_NPORTS);
}
out:
if (rv)
ia->ia_iosize = NSLAVES * COM_NPORTS;
return (rv);
}
int
astsubmatch(parent, match, aux)
struct device *parent;
void *match, *aux;
{
struct ast_softc *sc = (void *)parent;
struct cfdata *cf = match;
struct isa_attach_args *ia = aux;
struct commulti_attach_args *ca = ia->ia_aux;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
return (0);
return ((*cf->cf_driver->cd_match)(parent, match, ia));
}
int
astprint(aux, ast)
astprint(aux, pnp)
void *aux;
char *ast;
char *pnp;
{
struct isa_attach_args *ia = aux;
struct commulti_attach_args *ca = ia->ia_aux;
struct commulti_attach_args *ca = aux;
if (pnp)
printf("com at %s", pnp);
printf(" slave %d", ca->ca_slave);
return (UNCONF);
}
void
@ -110,32 +136,41 @@ astattach(parent, self, aux)
struct ast_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
struct commulti_attach_args ca;
struct isa_attach_args isa;
int subunit;
int i, subunit;
sc->sc_bc = ia->ia_bc;
sc->sc_iobase = ia->ia_iobase;
for (i = 0; i < NSLAVES; i++)
if (bus_io_map(bc, sc->sc_iobase + i * COM_NPORTS, COM_NPORTS,
&sc->sc_slaveioh[i]))
panic("astattach: couldn't map slave %d", i);
/*
* Enable the master interrupt.
*/
outb(sc->sc_iobase | 0x1f, 0x80);
bus_io_write_1(bc, sc->sc_slaveioh[3], 7, 0x80);
printf("\n");
isa.ia_aux = &ca;
for (ca.ca_slave = 0; ca.ca_slave < NSLAVES; ca.ca_slave++) {
struct cfdata *cf;
isa.ia_iobase = sc->sc_iobase + COM_NPORTS * ca.ca_slave;
isa.ia_iosize = 0x666;
isa.ia_irq = IRQUNK;
isa.ia_drq = DRQUNK;
isa.ia_msize = 0;
if ((cf = config_search(astsubmatch, self, &isa)) != 0) {
subunit = cf->cf_unit; /* can change if unit == * */
config_attach(self, cf, &isa, astprint);
sc->sc_slaves[ca.ca_slave] =
cf->cf_driver->cd_devs[subunit];
sc->sc_alive |= 1 << ca.ca_slave;
for (i = 0; i < NSLAVES; i++) {
struct cfdata *match;
ca.ca_slave = i;
ca.ca_bc = sc->sc_bc;
ca.ca_ioh = sc->sc_slaveioh[i];
ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS;
ca.ca_noien = 1;
/* mimic config_found(), but with special functionality */
if ((match = config_search(NULL, self, &ca)) != NULL) {
subunit = match->cf_unit; /* can change if unit == * */
config_attach(self, match, &ca, astprint);
sc->sc_slaves[i] = match->cf_driver->cd_devs[subunit];
sc->sc_alive |= 1 << i;
} else {
astprint(&ca, self->dv_xname);
printf(" not configured\n");
}
}
@ -148,11 +183,11 @@ astintr(arg)
void *arg;
{
struct ast_softc *sc = arg;
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
int alive = sc->sc_alive;
int bits;
bits = ~inb(iobase | 0x1f) & alive;
bits = ~bus_io_read_1(bc, sc->sc_slaveioh[3], 7) & alive;
if (bits == 0)
return (0);
@ -165,7 +200,7 @@ astintr(arg)
TRY(2);
TRY(3);
#undef TRY
bits = ~inb(iobase | 0x1f) & alive;
bits = ~bus_io_read_1(bc, sc->sc_slaveioh[3], 7) & alive;
if (bits == 0)
return (1);
}

View File

@ -1,6 +1,7 @@
/* $NetBSD: boca.c,v 1.8 1996/03/09 01:04:00 cgd Exp $ */
/* $NetBSD: boca.c,v 1.9 1996/03/10 09:01:22 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
* Copyright (c) 1995 Charles Hannum. All rights reserved.
*
* This code is derived from public-domain software written by
@ -35,7 +36,7 @@
#include <sys/param.h>
#include <sys/device.h>
#include <machine/pio.h>
#include <machine/bus.h>
#include <dev/isa/isavar.h>
#include <dev/isa/comreg.h>
@ -47,9 +48,12 @@ struct boca_softc {
struct device sc_dev;
void *sc_ih;
bus_chipset_tag_t sc_bc;
int sc_iobase;
int sc_alive; /* mask of slave units attached */
void *sc_slaves[NSLAVES]; /* com device unit numbers */
bus_io_handle_t sc_slaveioh[NSLAVES];
};
int bocaprobe();
@ -66,40 +70,62 @@ bocaprobe(parent, self, aux)
void *aux;
{
struct isa_attach_args *ia = aux;
int iobase = ia->ia_iobase;
bus_chipset_tag_t bc = ia->ia_bc;
bus_io_handle_t ioh;
int i, rv = 1;
/*
* Do the normal com probe for the first UART and assume
* its presence means there is a multiport board there.
* its presence, and the ability to map the other UARTS,
* means there is a multiport board there.
* XXX Needs more robustness.
*/
ia->ia_iosize = NSLAVES * COM_NPORTS;
return (comprobe1(ia->ia_iobase));
/* if the first port is in use as console, then it. */
if (iobase == comconsaddr && !comconsattached)
goto checkmappings;
if (bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
rv = 0;
goto out;
}
rv = comprobe1(bc, ioh, iobase);
bus_io_unmap(bc, ioh, COM_NPORTS);
if (rv == 0)
goto out;
checkmappings:
for (i = 1; i < NSLAVES; i++) {
iobase += COM_NPORTS;
if (iobase == comconsaddr && !comconsattached)
continue;
if (bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
rv = 0;
goto out;
}
bus_io_unmap(bc, ioh, COM_NPORTS);
}
out:
if (rv)
ia->ia_iosize = NSLAVES * COM_NPORTS;
return (rv);
}
int
bocasubmatch(parent, match, aux)
struct device *parent;
void *match, *aux;
{
struct boca_softc *sc = (void *)parent;
struct cfdata *cf = match;
struct isa_attach_args *ia = aux;
struct commulti_attach_args *ca = ia->ia_aux;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
return (0);
return ((*cf->cf_driver->cd_match)(parent, match, ia));
}
int
bocaprint(aux, boca)
bocaprint(aux, pnp)
void *aux;
char *boca;
char *pnp;
{
struct isa_attach_args *ia = aux;
struct commulti_attach_args *ca = ia->ia_aux;
struct commulti_attach_args *ca = aux;
if (pnp)
printf("com at %s", pnp);
printf(" slave %d", ca->ca_slave);
return (UNCONF);
}
void
@ -110,27 +136,36 @@ bocaattach(parent, self, aux)
struct boca_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
struct commulti_attach_args ca;
struct isa_attach_args isa;
int subunit;
int i, subunit;
sc->sc_bc = ia->ia_bc;
sc->sc_iobase = ia->ia_iobase;
for (i = 0; i < NSLAVES; i++)
if (bus_io_map(bc, sc->sc_iobase + i * COM_NPORTS, COM_NPORTS,
&sc->sc_slaveioh[i]))
panic("bocaattach: couldn't map slave %d", i);
printf("\n");
isa.ia_aux = &ca;
for (ca.ca_slave = 0; ca.ca_slave < NSLAVES; ca.ca_slave++) {
struct cfdata *cf;
isa.ia_iobase = sc->sc_iobase + COM_NPORTS * ca.ca_slave;
isa.ia_iosize = 0x666;
isa.ia_irq = IRQUNK;
isa.ia_drq = DRQUNK;
isa.ia_msize = 0;
if ((cf = config_search(bocasubmatch, self, &isa)) != 0) {
subunit = cf->cf_unit; /* can change if unit == * */
config_attach(self, cf, &isa, bocaprint);
sc->sc_slaves[ca.ca_slave] =
cf->cf_driver->cd_devs[subunit];
sc->sc_alive |= 1 << ca.ca_slave;
for (i = 0; i < NSLAVES; i++) {
struct cfdata *match;
ca.ca_slave = i;
ca.ca_bc = sc->sc_bc;
ca.ca_ioh = sc->sc_slaveioh[i];
ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS;
ca.ca_noien = 0;
/* mimic config_found(), but with special functionality */
if ((match = config_search(NULL, self, &ca)) != NULL) {
subunit = match->cf_unit; /* can change if unit == * */
config_attach(self, match, &ca, bocaprint);
sc->sc_slaves[i] = match->cf_driver->cd_devs[subunit];
sc->sc_alive |= 1 << i;
} else {
bocaprint(&ca, self->dv_xname);
printf(" not configured\n");
}
}
@ -143,11 +178,11 @@ bocaintr(arg)
void *arg;
{
struct boca_softc *sc = arg;
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
int alive = sc->sc_alive;
int bits;
bits = inb(iobase | 0x07) & alive;
bits = bus_io_read_1(bc, sc->sc_slaveioh[0], 7) & alive;
if (bits == 0)
return (0);
@ -164,7 +199,7 @@ bocaintr(arg)
TRY(6);
TRY(7);
#undef TRY
bits = inb(iobase | 0x07) & alive;
bits = bus_io_read_1(bc, sc->sc_slaveioh[0], 7) & alive;
if (bits == 0)
return (1);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: com.c,v 1.74 1996/03/09 01:02:08 cgd Exp $ */
/* $NetBSD: com.c,v 1.75 1996/03/10 09:01:24 cgd Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995, 1996
@ -57,7 +57,7 @@
#include <sys/device.h>
#include <machine/cpu.h>
#include <machine/pio.h>
#include <machine/bus.h>
#include <dev/isa/isavar.h>
#include <dev/isa/comreg.h>
@ -86,6 +86,11 @@ struct com_softc {
#ifdef COM_HAYESP
int sc_hayespbase;
#endif
bus_chipset_tag_t sc_bc;
bus_io_handle_t sc_ioh;
bus_io_handle_t sc_hayespioh;
u_char sc_hwflags;
#define COM_HW_NOIEN 0x01
#define COM_HW_FIFO 0x02
@ -104,6 +109,9 @@ struct com_softc {
};
int comprobe __P((struct device *, void *, void *));
#ifdef COM_HAYESP
int comprobeHAYESP __P((bus_io_handle_t hayespioh, struct com_softc *sc));
#endif
void comattach __P((struct device *, struct device *, void *));
int comopen __P((dev_t, int, int, struct proc *));
int comclose __P((dev_t, int, int, struct proc *));
@ -113,18 +121,23 @@ void compoll __P((void *));
int comparam __P((struct tty *, struct termios *));
void comstart __P((struct tty *));
int cominit __P((bus_chipset_tag_t, bus_io_handle_t, int));
struct cfdriver comcd = {
NULL, "com", comprobe, comattach, DV_TTY, sizeof(struct com_softc)
};
#ifdef COMCONSOLE
int comdefaultrate = CONSPEED;
int comconsole = COMCONSOLE;
int comdefaultrate = CONSPEED; /* XXX why set default? */
#else
int comdefaultrate = TTYDEF_SPEED;
int comconsole = -1;
#endif
int comconsaddr;
int comconsinit;
int comconsattached;
bus_chipset_tag_t comconsbc;
bus_io_handle_t comconsioh;
int commajor;
int comsopen = 0;
int comevents = 0;
@ -169,14 +182,16 @@ comspeed(speed)
}
int
comprobe1(iobase)
comprobe1(bc, ioh, iobase)
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
int iobase;
{
/* force access to id reg */
outb(iobase + com_lcr, 0);
outb(iobase + com_iir, 0);
if (inb(iobase + com_iir) & 0x38)
bus_io_write_1(bc, ioh, com_lcr, 0);
bus_io_write_1(bc, ioh, com_iir, 0);
if (bus_io_read_1(bc, ioh, com_iir) & 0x38)
return 0;
return 1;
@ -184,12 +199,13 @@ comprobe1(iobase)
#ifdef COM_HAYESP
int
comprobeHAYESP(iobase, sc)
int iobase;
comprobeHAYESP(hayespioh, sc)
bus_io_handle_t hayespioh;
struct com_softc *sc;
{
char val, dips;
int combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
bus_chipset_tag_t bc = sc->sc_bc;
/*
* Hayes ESP cards have two iobases. One is for compatibility with
@ -199,7 +215,7 @@ comprobeHAYESP(iobase, sc)
*/
/* Test for ESP signature */
if ((inb(iobase) & 0xf3) == 0)
if ((bus_io_read_1(bc, hayespioh, 0) & 0xf3) == 0)
return 0;
/*
@ -207,8 +223,8 @@ comprobeHAYESP(iobase, sc)
*/
/* Get the dip-switch configurations */
outb(iobase + HAYESP_CMD1, HAYESP_GETDIPS);
dips = inb(iobase + HAYESP_STATUS1);
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS);
dips = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1);
/* Determine which com port this ESP card services: bits 0,1 of */
/* dips is the port # (0-3); combaselist[val] is the com_iobase */
@ -219,9 +235,9 @@ comprobeHAYESP(iobase, sc)
/* Check ESP Self Test bits. */
/* Check for ESP version 2.0: bits 4,5,6 == 010 */
outb(iobase + HAYESP_CMD1, HAYESP_GETTEST);
val = inb(iobase + HAYESP_STATUS1); /* Clear reg 1 */
val = inb(iobase + HAYESP_STATUS2);
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_GETTEST);
val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS1); /* Clear reg 1 */
val = bus_io_read_1(bc, hayespioh, HAYESP_STATUS2);
if ((val & 0x70) < 0x20) {
printf("-old (%o)", val & 0x70);
/* we do not support the necessary features */
@ -251,15 +267,50 @@ comprobe(parent, match, aux)
struct device *parent;
void *match, *aux;
{
struct isa_attach_args *ia = aux;
int iobase = ia->ia_iobase;
struct cfdata *cf = match;
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
int iobase, needioh;
int rv = 1;
if (!comprobe1(iobase))
return 0;
if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
ia->ia_iosize = COM_NPORTS;
ia->ia_msize = 0;
return 1;
bc = ia->ia_bc;
iobase = ia->ia_iobase;
needioh = 1;
} else {
struct commulti_attach_args *ca = aux;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
return (0);
bc = ca->ca_bc;
iobase = ca->ca_iobase;
ioh = ca->ca_ioh;
needioh = 0;
}
/* if it's in use as console, it's there. */
if (iobase == comconsaddr && !comconsattached)
goto out;
if (needioh && bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
rv = 0;
goto out;
}
rv = comprobe1(bc, ioh, iobase);
if (needioh)
bus_io_unmap(bc, ioh, COM_NPORTS);
out:
if (rv && !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
ia->ia_iosize = COM_NPORTS;
ia->ia_msize = 0;
}
return (rv);
}
void
@ -268,64 +319,114 @@ comattach(parent, self, aux)
void *aux;
{
struct com_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
struct cfdata *cf = sc->sc_dev.dv_cfdata;
int iobase = ia->ia_iobase;
int iobase, irq;
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
struct tty *tp;
#ifdef COM_HAYESP
int hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
int *hayespp;
#endif
sc->sc_iobase = iobase;
sc->sc_hwflags = ISSET(cf->cf_flags, COM_HW_NOIEN);
sc->sc_hwflags = 0;
sc->sc_swflags = 0;
if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isa")) {
struct isa_attach_args *ia = aux;
if (sc->sc_dev.dv_unit == comconsole)
delay(1000);
/*
* We're living on an isa.
*/
iobase = ia->ia_iobase;
bc = ia->ia_bc;
if (iobase != comconsaddr) {
if (bus_io_map(bc, iobase, COM_NPORTS, &ioh))
panic("comattach: io mapping failed");
} else
ioh = comconsioh;
irq = ia->ia_irq;
} else {
struct commulti_attach_args *ca = aux;
/*
* We're living on a commulti.
*/
iobase = ca->ca_iobase;
bc = ca->ca_bc;
ioh = ca->ca_ioh;
irq = IRQUNK;
if (ca->ca_noien)
sc->sc_hwflags |= COM_HW_NOIEN;
}
sc->sc_bc = bc;
sc->sc_ioh = ioh;
sc->sc_iobase = iobase;
if (iobase == comconsaddr) {
comconsattached = 1;
/*
* Need to reset baud rate, etc. of next print so reset
* comconsinit. Also make sure console is always "hardwired".
*/
delay(1000); /* wait for output to finish */
comconsinit = 0;
SET(sc->sc_hwflags, COM_HW_CONSOLE);
SET(sc->sc_swflags, COM_SW_SOFTCAR);
}
#ifdef COM_HAYESP
/* Look for a Hayes ESP board. */
for (hayespp = hayesp_ports; *hayespp != 0; hayespp++)
if (comprobeHAYESP(*hayespp, sc)) {
for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
bus_io_handle_t hayespioh;
#define HAYESP_NPORTS 8 /* XXX XXX XXX ??? ??? ??? */
if (bus_io_map(bc, *hayespp, HAYESP_NPORTS, &hayespioh))
continue;
if (comprobeHAYESP(hayespioh, sc)) {
sc->sc_hayespbase = *hayespp;
sc->sc_hayespioh = hayespioh;
break;
}
bus_io_unmap(bc, hayespioh, HAYESP_NPORTS);
}
/* No ESP; look for other things. */
if (*hayespp == 0) {
#endif
/* look for a NS 16550AF UART with FIFOs */
outb(iobase + com_fifo,
bus_io_write_1(bc, ioh, com_fifo,
FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
delay(100);
if (ISSET(inb(iobase + com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK)
if (ISSET(inb(iobase + com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_FIFO_MASK) == IIR_FIFO_MASK)
if (ISSET(bus_io_read_1(bc, ioh, com_fifo), FIFO_TRIGGER_14) == FIFO_TRIGGER_14) {
SET(sc->sc_hwflags, COM_HW_FIFO);
printf(": ns16550a, working fifo\n");
} else
printf(": ns16550, broken fifo\n");
else
printf(": ns8250 or ns16450, no fifo\n");
outb(iobase + com_fifo, 0);
bus_io_write_1(bc, ioh, com_fifo, 0);
#ifdef COM_HAYESP
}
#endif
/* disable interrupts */
outb(iobase + com_ier, 0);
outb(iobase + com_mcr, 0);
bus_io_write_1(bc, ioh, com_ier, 0);
bus_io_write_1(bc, ioh, com_mcr, 0);
if (ia->ia_irq != IRQUNK)
sc->sc_ih = isa_intr_establish(ia->ia_irq, IST_EDGE, IPL_TTY,
if (irq != IRQUNK)
sc->sc_ih = isa_intr_establish(irq, IST_EDGE, IPL_TTY,
comintr, sc);
#ifdef KGDB
if (kgdb_dev == makedev(commajor, unit)) {
if (comconsole == unit)
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
kgdb_dev = -1; /* can't debug over console port */
else {
(void) cominit(unit, kgdb_rate);
(void) cominit(bc, ioh, kgdb_rate);
if (kgdb_debug_init) {
/*
* Print prefix of device name,
@ -340,15 +441,9 @@ comattach(parent, self, aux)
}
#endif
if (sc->sc_dev.dv_unit == comconsole) {
/*
* Need to reset baud rate, etc. of next print so reset
* comconsinit. Also make sure console is always "hardwired".
*/
comconsinit = 0;
SET(sc->sc_hwflags, COM_HW_CONSOLE);
SET(sc->sc_swflags, COM_SW_SOFTCAR);
}
/* XXX maybe move up some? */
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
printf("%s: console\n", sc->sc_dev.dv_xname);
}
int
@ -359,7 +454,8 @@ comopen(dev, flag, mode, p)
{
int unit = COMUNIT(dev);
struct com_softc *sc;
int iobase;
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
struct tty *tp;
int s;
int error = 0;
@ -405,56 +501,57 @@ comopen(dev, flag, mode, p)
sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
iobase = sc->sc_iobase;
bc = sc->sc_bc;
ioh = sc->sc_ioh;
#ifdef COM_HAYESP
/* Setup the ESP board */
if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
int hayespbase = sc->sc_hayespbase;
bus_io_handle_t hayespioh = sc->sc_hayespioh;
outb(iobase + com_fifo,
bus_io_write_1(bc, ioh, com_fifo,
FIFO_DMA_MODE|FIFO_ENABLE|
FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_8);
/* Set 16550 compatibility mode */
outb(hayespbase + HAYESP_CMD1, HAYESP_SETMODE);
outb(hayespbase + HAYESP_CMD2,
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
HAYESP_MODE_SCALE);
/* Set RTS/CTS flow control */
outb(hayespbase + HAYESP_CMD1, HAYESP_SETFLOWTYPE);
outb(hayespbase + HAYESP_CMD2, HAYESP_FLOW_RTS);
outb(hayespbase + HAYESP_CMD2, HAYESP_FLOW_CTS);
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE);
bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS);
bus_io_write_1(bc, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS);
/* Set flow control levels */
outb(hayespbase + HAYESP_CMD1, HAYESP_SETRXFLOW);
outb(hayespbase + HAYESP_CMD2,
bus_io_write_1(bc, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW);
bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
HAYESP_HIBYTE(HAYESP_RXHIWMARK));
outb(hayespbase + HAYESP_CMD2,
bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
HAYESP_LOBYTE(HAYESP_RXHIWMARK));
outb(hayespbase + HAYESP_CMD2,
bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
HAYESP_HIBYTE(HAYESP_RXLOWMARK));
outb(hayespbase + HAYESP_CMD2,
bus_io_write_1(bc, hayespioh, HAYESP_CMD2,
HAYESP_LOBYTE(HAYESP_RXLOWMARK));
} else
#endif
if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
/* Set the FIFO threshold based on the receive speed. */
outb(iobase + com_fifo,
bus_io_write_1(bc, ioh, com_fifo,
FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST |
(tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
/* flush any pending I/O */
while (ISSET(inb(iobase + com_lsr), LSR_RXRDY))
(void) inb(iobase + com_data);
while (ISSET(bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
(void) bus_io_read_1(bc, ioh, com_data);
/* you turn me on, baby */
sc->sc_mcr = MCR_DTR | MCR_RTS;
if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
SET(sc->sc_mcr, MCR_IENABLE);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
outb(iobase + com_ier, sc->sc_ier);
bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
sc->sc_msr = inb(iobase + com_msr);
sc->sc_msr = bus_io_read_1(bc, ioh, com_msr);
if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) ||
ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
SET(tp->t_state, TS_CARR_ON);
@ -493,7 +590,8 @@ comclose(dev, flag, mode, p)
int unit = COMUNIT(dev);
struct com_softc *sc = comcd.cd_devs[unit];
struct tty *tp = sc->sc_tty;
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int s;
/* XXX This is for cons.c. */
@ -503,12 +601,12 @@ comclose(dev, flag, mode, p)
(*linesw[tp->t_line].l_close)(tp, flag);
s = spltty();
CLR(sc->sc_lcr, LCR_SBREAK);
outb(iobase + com_lcr, sc->sc_lcr);
outb(iobase + com_ier, 0);
bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
bus_io_write_1(bc, ioh, com_ier, 0);
if (ISSET(tp->t_cflag, HUPCL) &&
!ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
/* XXX perhaps only clear DTR */
outb(iobase + com_mcr, 0);
bus_io_write_1(bc, ioh, com_mcr, 0);
}
CLR(tp->t_state, TS_BUSY | TS_FLUSH);
if (--comsopen == 0)
@ -516,7 +614,7 @@ comclose(dev, flag, mode, p)
splx(s);
ttyclose(tp);
#ifdef notyet /* XXXX */
if (unit != comconsole) {
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
ttyfree(tp);
sc->sc_tty = 0;
}
@ -582,7 +680,8 @@ comioctl(dev, cmd, data, flag, p)
int unit = COMUNIT(dev);
struct com_softc *sc = comcd.cd_devs[unit];
struct tty *tp = sc->sc_tty;
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int error;
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
@ -595,29 +694,29 @@ comioctl(dev, cmd, data, flag, p)
switch (cmd) {
case TIOCSBRK:
SET(sc->sc_lcr, LCR_SBREAK);
outb(iobase + com_lcr, sc->sc_lcr);
bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
break;
case TIOCCBRK:
CLR(sc->sc_lcr, LCR_SBREAK);
outb(iobase + com_lcr, sc->sc_lcr);
bus_io_write_1(bc, ioh, com_lcr, sc->sc_lcr);
break;
case TIOCSDTR:
SET(sc->sc_mcr, sc->sc_dtr);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
break;
case TIOCCDTR:
CLR(sc->sc_mcr, sc->sc_dtr);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
break;
case TIOCMSET:
CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
case TIOCMBIS:
SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
break;
case TIOCMBIC:
CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
break;
case TIOCMGET: {
u_char m;
@ -637,7 +736,7 @@ comioctl(dev, cmd, data, flag, p)
SET(bits, TIOCM_DSR);
if (ISSET(m, MSR_RI | MSR_TERI))
SET(bits, TIOCM_RI);
if (inb(iobase + com_ier))
if (bus_io_read_1(bc, ioh, com_ier))
SET(bits, TIOCM_LE);
*(int *)data = bits;
break;
@ -692,7 +791,8 @@ comparam(tp, t)
struct termios *t;
{
struct com_softc *sc = comcd.cd_devs[COMUNIT(tp->t_dev)];
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int ospeed = comspeed(t->c_ospeed);
u_char lcr;
tcflag_t oldcflag;
@ -732,7 +832,7 @@ comparam(tp, t)
if (ospeed == 0) {
CLR(sc->sc_mcr, MCR_DTR);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
}
/*
@ -767,34 +867,34 @@ comparam(tp, t)
}
}
outb(iobase + com_lcr, lcr | LCR_DLAB);
outb(iobase + com_dlbl, ospeed);
outb(iobase + com_dlbh, ospeed >> 8);
outb(iobase + com_lcr, lcr);
bus_io_write_1(bc, ioh, com_lcr, lcr | LCR_DLAB);
bus_io_write_1(bc, ioh, com_dlbl, ospeed);
bus_io_write_1(bc, ioh, com_dlbh, ospeed >> 8);
bus_io_write_1(bc, ioh, com_lcr, lcr);
SET(sc->sc_mcr, MCR_DTR);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
} else
outb(iobase + com_lcr, lcr);
bus_io_write_1(bc, ioh, com_lcr, lcr);
if (!ISSET(sc->sc_hwflags, COM_HW_HAYESP) &&
ISSET(sc->sc_hwflags, COM_HW_FIFO))
outb(iobase + com_fifo,
bus_io_write_1(bc, ioh, com_fifo,
FIFO_ENABLE |
(t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
} else
outb(iobase + com_lcr, lcr);
bus_io_write_1(bc, ioh, com_lcr, lcr);
/* When not using CRTSCTS, RTS follows DTR. */
if (!ISSET(t->c_cflag, CRTSCTS)) {
if (ISSET(sc->sc_mcr, MCR_DTR)) {
if (!ISSET(sc->sc_mcr, MCR_RTS)) {
SET(sc->sc_mcr, MCR_RTS);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
}
} else {
if (ISSET(sc->sc_mcr, MCR_RTS)) {
CLR(sc->sc_mcr, MCR_RTS);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
}
}
sc->sc_dtr = MCR_DTR | MCR_RTS;
@ -816,7 +916,7 @@ comparam(tp, t)
ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
(*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
CLR(sc->sc_mcr, sc->sc_dtr);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
}
/* Just to be sure... */
@ -830,7 +930,8 @@ comstart(tp)
struct tty *tp;
{
struct com_softc *sc = comcd.cd_devs[COMUNIT(tp->t_dev)];
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
int s;
s = spltty();
@ -854,14 +955,14 @@ comstart(tp)
if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
SET(sc->sc_ier, IER_ETXRDY);
outb(iobase + com_ier, sc->sc_ier);
bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
}
#ifdef COM_HAYESP
if (ISSET(sc->sc_hwflags, COM_HW_HAYESP)) {
u_char buffer[1024], *cp = buffer;
int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
do
outb(iobase + com_data, *cp++);
bus_io_write_1(bc, ioh, com_data, *cp++);
while (--n);
}
else
@ -870,17 +971,17 @@ comstart(tp)
u_char buffer[16], *cp = buffer;
int n = q_to_b(&tp->t_outq, cp, sizeof buffer);
do {
outb(iobase + com_data, *cp++);
bus_io_write_1(bc, ioh, com_data, *cp++);
} while (--n);
} else
outb(iobase + com_data, getc(&tp->t_outq));
bus_io_write_1(bc, ioh, com_data, getc(&tp->t_outq));
out:
splx(s);
return;
stopped:
if (ISSET(sc->sc_ier, IER_ETXRDY)) {
CLR(sc->sc_ier, IER_ETXRDY);
outb(iobase + com_ier, sc->sc_ier);
bus_io_write_1(bc, ioh, com_ier, sc->sc_ier);
}
splx(s);
}
@ -980,7 +1081,8 @@ compoll(arg)
!ISSET(sc->sc_mcr, MCR_RTS)) {
/* XXX */
SET(sc->sc_mcr, MCR_RTS);
outb(sc->sc_iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(sc->sc_bc, sc->sc_ioh, com_mcr,
sc->sc_mcr);
}
splx(s);
@ -1007,7 +1109,8 @@ comintr(arg)
void *arg;
{
struct com_softc *sc = arg;
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
bus_io_handle_t ioh = sc->sc_ioh;
struct tty *tp;
u_char lsr, data, msr, delta;
#ifdef COM_DEBUG
@ -1019,10 +1122,10 @@ comintr(arg)
#ifdef COM_DEBUG
n = 0;
if (ISSET(iter[n].iir = inb(iobase + com_iir), IIR_NOPEND))
if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
return (0);
#else
if (ISSET(inb(iobase + com_iir), IIR_NOPEND))
if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
return (0);
#endif
@ -1032,14 +1135,14 @@ comintr(arg)
#ifdef COM_DEBUG
iter[n].lsr =
#endif
lsr = inb(iobase + com_lsr);
lsr = bus_io_read_1(bc, ioh, com_lsr);
if (ISSET(lsr, LSR_RXRDY)) {
register u_char *p = sc->sc_ibufp;
comevents = 1;
do {
data = inb(iobase + com_data);
data = bus_io_read_1(bc, ioh, com_data);
if (ISSET(lsr, LSR_BI)) {
#ifdef notdef
printf("break %02x %02x %02x %02x\n",
@ -1047,7 +1150,8 @@ comintr(arg)
sc->sc_dtr);
#endif
#ifdef DDB
if (sc->sc_dev.dv_unit == comconsole) {
if (ISSET(sc->sc_hwflags,
COM_HW_CONSOLE)) {
Debugger();
goto next;
}
@ -1064,8 +1168,8 @@ comintr(arg)
ISSET(tp->t_cflag, CRTSCTS)) {
/* XXX */
CLR(sc->sc_mcr, MCR_RTS);
outb(iobase + com_mcr,
sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr,
sc->sc_mcr);
}
}
next:
@ -1074,7 +1178,7 @@ comintr(arg)
goto ohfudge;
iter[n].lsr =
#endif
lsr = inb(iobase + com_lsr);
lsr = bus_io_read_1(bc, ioh, com_lsr);
} while (ISSET(lsr, LSR_RXRDY));
sc->sc_ibufp = p;
@ -1087,7 +1191,7 @@ comintr(arg)
#ifdef COM_DEBUG
iter[n].msr =
#endif
msr = inb(iobase + com_msr);
msr = bus_io_read_1(bc, ioh, com_msr);
if (msr != sc->sc_msr) {
delta = msr ^ sc->sc_msr;
@ -1096,7 +1200,7 @@ comintr(arg)
!ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
(*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
CLR(sc->sc_mcr, sc->sc_dtr);
outb(iobase + com_mcr, sc->sc_mcr);
bus_io_write_1(bc, ioh, com_mcr, sc->sc_mcr);
}
if (ISSET(delta & msr, MSR_CTS) &&
ISSET(tp->t_cflag, CRTSCTS)) {
@ -1115,10 +1219,10 @@ comintr(arg)
#ifdef COM_DEBUG
if (++n >= 32)
goto ohfudge;
if (ISSET(iter[n].iir = inb(iobase + com_iir), IIR_NOPEND))
if (ISSET(iter[n].iir = bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
return (1);
#else
if (ISSET(inb(iobase + com_iir), IIR_NOPEND))
if (ISSET(bus_io_read_1(bc, ioh, com_iir), IIR_NOPEND))
return (1);
#endif
}
@ -1147,8 +1251,21 @@ void
comcnprobe(cp)
struct consdev *cp;
{
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
int found;
if (!comprobe1(CONADDR)) {
#if 0
XXX NEEDS TO BE FIXED XXX
bc = ???;
#endif
if (bus_io_map(bc, CONADDR, COM_NPORTS, &ioh)) {
cp->cn_pri = CN_DEAD;
return;
}
found = comprobe1(bc, ioh, CONADDR);
bus_io_unmap(bc, ioh, COM_NPORTS);
if (!found) {
cp->cn_pri = CN_DEAD;
return;
}
@ -1172,26 +1289,34 @@ comcninit(cp)
struct consdev *cp;
{
cominit(CONUNIT, comdefaultrate);
comconsole = CONUNIT;
#if 0
XXX NEEDS TO BE FIXED XXX
comconsbc = ???;
#endif
if (bus_io_map(comconsbc, CONADDR, COM_NPORTS, &comconsioh))
panic("comcninit: mapping failed");
cominit(comconsbc, comconsioh, comdefaultrate);
comconsaddr = CONADDR;
comconsinit = 0;
}
cominit(unit, rate)
int unit, rate;
cominit(bc, ioh, rate)
bus_chipset_tag_t bc;
bus_io_handle_t ioh;
int rate;
{
int s = splhigh();
int iobase = CONADDR;
u_char stat;
outb(iobase + com_lcr, LCR_DLAB);
bus_io_write_1(bc, ioh, com_lcr, LCR_DLAB);
rate = comspeed(comdefaultrate);
outb(iobase + com_dlbl, rate);
outb(iobase + com_dlbh, rate >> 8);
outb(iobase + com_lcr, LCR_8BITS);
outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY);
outb(iobase + com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
stat = inb(iobase + com_iir);
bus_io_write_1(bc, ioh, com_dlbl, rate);
bus_io_write_1(bc, ioh, com_dlbh, rate >> 8);
bus_io_write_1(bc, ioh, com_lcr, LCR_8BITS);
bus_io_write_1(bc, ioh, com_ier, IER_ERXRDY | IER_ETXRDY);
bus_io_write_1(bc, ioh, com_fifo, FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
stat = bus_io_read_1(bc, ioh, com_iir);
splx(s);
}
@ -1199,13 +1324,14 @@ comcngetc(dev)
dev_t dev;
{
int s = splhigh();
int iobase = CONADDR;
bus_chipset_tag_t bc = comconsbc;
bus_io_handle_t ioh = comconsioh;
u_char stat, c;
while (!ISSET(stat = inb(iobase + com_lsr), LSR_RXRDY))
while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_RXRDY))
;
c = inb(iobase + com_data);
stat = inb(iobase + com_iir);
c = bus_io_read_1(bc, ioh, com_data);
stat = bus_io_read_1(bc, ioh, com_iir);
splx(s);
return c;
}
@ -1219,7 +1345,8 @@ comcnputc(dev, c)
int c;
{
int s = splhigh();
int iobase = CONADDR;
bus_chipset_tag_t bc = comconsbc;
bus_io_handle_t ioh = comconsioh;
u_char stat;
register int timo;
@ -1227,20 +1354,20 @@ comcnputc(dev, c)
if (dev != kgdb_dev)
#endif
if (comconsinit == 0) {
(void) cominit(COMUNIT(dev), comdefaultrate);
(void) cominit(bc, ioh, comdefaultrate);
comconsinit = 1;
}
/* wait for any pending transmission to finish */
timo = 50000;
while (!ISSET(stat = inb(iobase + com_lsr), LSR_TXRDY) && --timo)
while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
;
outb(iobase + com_data, c);
bus_io_write_1(bc, ioh, com_data, c);
/* wait for this transmission to complete */
timo = 1500000;
while (!ISSET(stat = inb(iobase + com_lsr), LSR_TXRDY) && --timo)
while (!ISSET(stat = bus_io_read_1(bc, ioh, com_lsr), LSR_TXRDY) && --timo)
;
/* clear any interrupts generated by this transmission */
stat = inb(iobase + com_iir);
stat = bus_io_read_1(bc, ioh, com_iir);
splx(s);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: comvar.h,v 1.2 1996/03/09 23:37:14 cgd Exp $ */
/* $NetBSD: comvar.h,v 1.3 1996/03/10 09:01:26 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@ -32,6 +32,16 @@
struct commulti_attach_args {
int ca_slave; /* slave number */
bus_chipset_tag_t ca_bc;
bus_io_handle_t ca_ioh;
int ca_iobase;
int ca_noien;
};
int comprobe1 __P((int));
int comprobe1 __P((bus_chipset_tag_t, bus_io_handle_t, int));
extern int comconsaddr;
extern int comconsattached;
extern bus_chipset_tag_t comconsbc;
extern bus_io_handle_t comconsioh;

View File

@ -1,6 +1,7 @@
/* $NetBSD: rtfps.c,v 1.16 1996/03/09 01:04:01 cgd Exp $ */
/* $NetBSD: rtfps.c,v 1.17 1996/03/10 09:01:28 cgd Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
* Copyright (c) 1995 Charles Hannum. All rights reserved.
*
* This code is derived from public-domain software written by
@ -35,7 +36,7 @@
#include <sys/param.h>
#include <sys/device.h>
#include <machine/pio.h>
#include <machine/bus.h>
#include <dev/isa/isavar.h>
#include <dev/isa/comreg.h>
@ -47,10 +48,14 @@ struct rtfps_softc {
struct device sc_dev;
void *sc_ih;
bus_chipset_tag_t sc_bc;
int sc_iobase;
int sc_irqport;
bus_io_handle_t sc_irqioh;
int sc_alive; /* mask of slave units attached */
void *sc_slaves[NSLAVES]; /* com device unit numbers */
bus_io_handle_t sc_slaveioh[NSLAVES];
};
int rtfpsprobe();
@ -67,40 +72,62 @@ rtfpsprobe(parent, self, aux)
void *aux;
{
struct isa_attach_args *ia = aux;
int iobase = ia->ia_iobase;
bus_chipset_tag_t bc = ia->ia_bc;
bus_io_handle_t ioh;
int i, rv = 1;
/*
* Do the normal com probe for the first UART and assume
* its presence means there is a multiport board there.
* its presence, and the ability to map the other UARTS,
* means there is a multiport board there.
* XXX Needs more robustness.
*/
ia->ia_iosize = NSLAVES * COM_NPORTS;
return (comprobe1(ia->ia_iobase));
/* if the first port is in use as console, then it. */
if (iobase == comconsaddr && !comconsattached)
goto checkmappings;
if (bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
rv = 0;
goto out;
}
rv = comprobe1(bc, ioh, iobase);
bus_io_unmap(bc, ioh, COM_NPORTS);
if (rv == 0)
goto out;
checkmappings:
for (i = 1; i < NSLAVES; i++) {
iobase += COM_NPORTS;
if (iobase == comconsaddr && !comconsattached)
continue;
if (bus_io_map(bc, iobase, COM_NPORTS, &ioh)) {
rv = 0;
goto out;
}
bus_io_unmap(bc, ioh, COM_NPORTS);
}
out:
if (rv)
ia->ia_iosize = NSLAVES * COM_NPORTS;
return (rv);
}
int
rtfpssubmatch(parent, match, aux)
struct device *parent;
void *match, *aux;
{
struct rtfps_softc *sc = (void *)parent;
struct cfdata *cf = match;
struct isa_attach_args *ia = aux;
struct commulti_attach_args *ca = ia->ia_aux;
if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
return (0);
return ((*cf->cf_driver->cd_match)(parent, match, ia));
}
int
rtfpsprint(aux, rtfps)
rtfpsprint(aux, pnp)
void *aux;
char *rtfps;
char *pnp;
{
struct isa_attach_args *ia = aux;
struct commulti_attach_args *ca = ia->ia_aux;
struct commulti_attach_args *ca = aux;
if (pnp)
printf("com at %s", pnp);
printf(" slave %d", ca->ca_slave);
return (UNCONF);
}
void
@ -111,39 +138,51 @@ rtfpsattach(parent, self, aux)
struct rtfps_softc *sc = (void *)self;
struct isa_attach_args *ia = aux;
struct commulti_attach_args ca;
struct isa_attach_args isa;
static int irqport[] = {
IOBASEUNK, IOBASEUNK, IOBASEUNK, IOBASEUNK,
IOBASEUNK, IOBASEUNK, IOBASEUNK, IOBASEUNK,
IOBASEUNK, 0x2f2, 0x6f2, 0x6f3,
IOBASEUNK, IOBASEUNK, IOBASEUNK, IOBASEUNK
};
int subunit;
int i, subunit;
sc->sc_bc = ia->ia_bc;
sc->sc_iobase = ia->ia_iobase;
if (ia->ia_irq >= 16 || irqport[ia->ia_irq] == IOBASEUNK)
panic("rtfpsattach: invalid irq");
sc->sc_irqport = irqport[ia->ia_irq];
outb(sc->sc_irqport, 0);
for (i = 0; i < NSLAVES; i++)
if (bus_io_map(bc, sc->sc_iobase + i * COM_NPORTS, COM_NPORTS,
&sc->sc_slaveioh[i]))
panic("rtfpsattach: couldn't map slave %d", i);
if (bus_io_map(bc, sc->sc_irqport, 1, &sc->sc_irqioh))
panic("rtfpsattach: couldn't map irq port at 0x%x\n",
sc->sc_irqport);
bus_io_write_1(bc, sc->sc_irqioh, 0, 0);
printf("\n");
isa.ia_aux = &ca;
for (ca.ca_slave = 0; ca.ca_slave < NSLAVES; ca.ca_slave++) {
struct cfdata *cf;
isa.ia_iobase = sc->sc_iobase + COM_NPORTS * ca.ca_slave;
isa.ia_iosize = 0x666;
isa.ia_irq = IRQUNK;
isa.ia_drq = DRQUNK;
isa.ia_msize = 0;
if ((cf = config_search(rtfpssubmatch, self, &isa)) != 0) {
subunit = cf->cf_unit; /* can change if unit == * */
config_attach(self, cf, &isa, rtfpsprint);
sc->sc_slaves[ca.ca_slave] =
cf->cf_driver->cd_devs[subunit];
sc->sc_alive |= 1 << ca.ca_slave;
for (i = 0; i < NSLAVES; i++) {
struct cfdata *match;
ca.ca_slave = i;
ca.ca_bc = sc->sc_bc;
ca.ca_ioh = sc->sc_slaveioh[i];
ca.ca_iobase = sc->sc_iobase + i * COM_NPORTS;
ca.ca_noien = 0;
/* mimic config_found(), but with special functionality */
if ((match = config_search(NULL, self, &ca)) != NULL) {
subunit = match->cf_unit; /* can change if unit == * */
config_attach(self, match, &ca, rtfpsprint);
sc->sc_slaves[i] = match->cf_driver->cd_devs[subunit];
sc->sc_alive |= 1 << i;
} else {
rtfpsprint(&ca, self->dv_xname);
printf(" not configured\n");
}
}
@ -156,10 +195,10 @@ rtfpsintr(arg)
void *arg;
{
struct rtfps_softc *sc = arg;
int iobase = sc->sc_iobase;
bus_chipset_tag_t bc = sc->sc_bc;
int alive = sc->sc_alive;
outb(sc->sc_irqport, 0);
bus_io_write_1(bc, sc->sc_irqioh, 0, 0);
#define TRY(n) \
if (alive & (1 << (n))) \