backout to recent changes w/o lwp changes

This commit is contained in:
ichiro 2003-07-02 10:40:46 +00:00
parent 2f35689ef7
commit 25096a1afe
3 changed files with 220 additions and 61 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: ixp425_com.c,v 1.10 2003/06/29 22:28:11 fvdl Exp $ */
/* $NetBSD: ixp425_com.c,v 1.11 2003/07/02 10:40:46 ichiro Exp $ */
/*
* Copyright (c) 2003
* Ichiro FUKUHARA <ichiro@ichiro.org>.
@ -68,7 +68,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: ixp425_com.c,v 1.10 2003/06/29 22:28:11 fvdl Exp $");
__KERNEL_RCSID(0, "$NetBSD: ixp425_com.c,v 1.11 2003/07/02 10:40:46 ichiro Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@ -111,13 +111,15 @@ static void tiocm_to_ixp4xx_com(struct ixp4xx_com_softc *, u_long, int);
static int ixp4xx_com_to_tiocm(struct ixp4xx_com_softc *);
static void ixp4xx_com_set_cr(struct ixp4xx_com_softc *);
static void ixpcom_hwiflow(struct ixp4xx_com_softc *);
static void ixp4xxcomsoft(void *);
static void ixpcomdiag(void *);
inline static void ixp4xx_com_txsoft(struct ixp4xx_com_softc *, struct tty *);
inline static void ixp4xx_com_rxsoft(struct ixp4xx_com_softc *, struct tty *);
inline static void ixpcom_schedrx(struct ixp4xx_com_softc *);
int ixp4xx_cominit(bus_space_tag_t, bus_space_handle_t, int, int, tcflag_t);
int ixp4xx_comcngetc(dev_t);
void ixp4xx_comcnputc(dev_t, int);
void ixp4xx_comcnpollc(dev_t, int);
@ -155,6 +157,10 @@ const struct cdevsw ixpcom_cdevsw = {
nommap, ttykqfilter, D_TTY
};
/* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
u_int ixpcom_rbuf_hiwat = (IXPCOM_RING_SIZE * 1) / 4;
u_int ixpcom_rbuf_lowat = (IXPCOM_RING_SIZE * 3) / 4;
#define COMUNIT_MASK 0x7ffff
#define COMDIALOUT_MASK 0x80000
@ -164,8 +170,6 @@ const struct cdevsw ixpcom_cdevsw = {
#define COM_ISALIVE(sc) ((sc)->enabled != 0 && \
ISSET((sc)->sc_dev.dv_flags, DVF_ACTIVE))
#define COM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, COM_NPORTS, (f))
#define COM_LOCK(sc);
#define COM_UNLOCK(sc);
@ -230,9 +234,8 @@ ixp4xx_com_attach_subr(struct ixp4xx_com_softc *sc)
ixp4xx_com_sc = sc;
#if 0
callout_init(&sc->sc_diag_callout);
#endif
/* configuring the device. */
sc->sc_frequency = FREQ;
sc->sc_dlbl = ixp4xx_comspeed(CONSPEED, sc->sc_frequency);
@ -242,7 +245,7 @@ ixp4xx_com_attach_subr(struct ixp4xx_com_softc *sc)
sc->sc_ier = IER_UUE;
bus_space_write_4(iot, ioh, IXP425_UART_IER, sc->sc_ier);
sc->sc_fcr = FCR_TRIGGER_8 | FCR_RESETTF | FCR_RESETRF | FCR_ENABLE;
sc->sc_fcr = FCR_TRIGGER_32 | FCR_RESETTF | FCR_RESETRF | FCR_ENABLE;
bus_space_write_4(iot, ioh, IXP425_UART_FCR, sc->sc_fcr);
if (iot == ixp4xx_comcn_sc.sc_iot
@ -282,6 +285,10 @@ ixp4xx_com_attach_subr(struct ixp4xx_com_softc *sc)
tty_attach(tp);
sc->sc_mcr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IXP425_UART_MCR);
SET(sc->sc_mcr, MCR_IENABLE);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_UART_MCR, sc->sc_mcr);
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
int maj;
@ -425,6 +432,23 @@ ixp4xx_comparam(struct tty *tp, struct termios *t)
ixp4xx_com_set_cr(sc);
}
if (!ISSET(t->c_cflag, CHWFLOW)) {
/* Disable the high water mark. */
sc->sc_r_hiwat = 0;
sc->sc_r_lowat = 0;
if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
ixpcom_schedrx(sc);
}
if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) {
CLR(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED);
ixpcom_hwiflow(sc);
}
} else {
sc->sc_r_hiwat = ixpcom_rbuf_hiwat;
sc->sc_r_lowat = ixpcom_rbuf_lowat;
}
COM_UNLOCK(sc);
splx(s);
@ -432,7 +456,7 @@ ixp4xx_comparam(struct tty *tp, struct termios *t)
* Update the tty layer's idea of the carrier bit.
* We tell tty the carrier is always on.
*/
(void) (*tp->t_linesw->l_modem)(tp, 1);
(void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, MSR_DCD));
#ifdef COM_DEBUG
if (com_debug)
@ -457,6 +481,8 @@ ixp4xx_com_set_cr(struct ixp4xx_com_softc *sc)
ixp4xx_com_iflush(sc);
bus_space_write_4(iot, ioh, IXP425_UART_IER, IER_UUE);
bus_space_write_4(iot, ioh, IXP425_UART_LCR, sc->sc_lcr | LCR_DLAB);
bus_space_write_4(iot, ioh, IXP425_UART_DLL, sc->sc_dlbl);
bus_space_write_4(iot, ioh, IXP425_UART_DLH, sc->sc_dlbh);
@ -469,7 +495,60 @@ ixp4xx_com_set_cr(struct ixp4xx_com_softc *sc)
static int
ixp4xx_comhwiflow(struct tty *tp, int block)
{
return (0);
struct ixp4xx_com_softc *sc
= device_lookup(&ixpcom_cd, COMUNIT(tp->t_dev));
int s;
if (COM_ISALIVE(sc) == 0)
return (0);
if (sc->sc_mcr_rts == 0)
return (0);
s = splserial();
COM_LOCK(sc);
if (block) {
if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
SET(sc->sc_rx_flags, RX_TTY_BLOCKED);
ixpcom_hwiflow(sc);
}
} else {
if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
ixpcom_schedrx(sc);
}
if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
CLR(sc->sc_rx_flags, RX_TTY_BLOCKED);
ixpcom_hwiflow(sc);
}
}
COM_UNLOCK(sc);
splx(s);
return (1);
}
/*
* (un)block input via hw flowcontrol
*/
void
ixpcom_hwiflow(struct ixp4xx_com_softc *sc)
{
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
if (sc->sc_mcr_rts == 0)
return;
if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) {
CLR(sc->sc_mcr, sc->sc_mcr_rts);
CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
} else {
SET(sc->sc_mcr, sc->sc_mcr_rts);
SET(sc->sc_mcr_active, sc->sc_mcr_rts);
}
bus_space_write_4(iot, ioh, IXP425_UART_MCR, sc->sc_mcr_active);
}
static void
@ -488,7 +567,9 @@ ixp4xx_com_filltx(struct ixp4xx_com_softc *sc)
n++;
}
sc->sc_tbc -= n;
sc->sc_tba += n;
}
static void
ixp4xx_comstart(struct tty *tp)
@ -538,7 +619,7 @@ ixp4xx_comstart(struct tty *tp)
if (!ISSET(sc->sc_ier, IER_TIE)) {
SET(sc->sc_ier, IER_TIE);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_UART_IER,
sc->sc_ier | IER_UUE);
sc->sc_ier);
}
/* Output the first chunk of the contiguous buffer. */
@ -550,6 +631,15 @@ out:
return;
}
inline static void
ixpcom_schedrx(struct ixp4xx_com_softc *sc)
{
sc->sc_rx_ready = 1;
/* Wake up the poller. */
softintr_schedule(sc->sc_si);
}
static void
ixp4xx_com_break(struct ixp4xx_com_softc *sc, int onoff)
{
@ -597,9 +687,18 @@ ixp4xx_com_shutdown(struct ixp4xx_com_softc *sc)
}
/* Turn off interrupts. */
#if 1
if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
sc->sc_ier = IER_RAVIE | IER_RTOIE;
} else
sc->sc_ier = IER_UUE;
bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_UART_IER,
sc->sc_ier);
#else
sc->sc_ier &= ~(IER_RAVIE | IER_TIE);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_UART_IER,
sc->sc_ier | IER_UUE);
#endif
if (sc->disable) {
#ifdef DIAGNOSTIC
@ -669,15 +768,14 @@ ixp4xx_comopen(dev_t dev, int flag, int mode, struct proc *p)
sc->enabled = 1;
}
/* Turn on interrupts. */
sc->sc_mcr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, IXP425_UART_MCR);
SET(sc->sc_mcr, MCR_IENABLE);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_UART_MCR, sc->sc_mcr);
SET(sc->sc_ier, IER_RAVIE | IER_TIE);
bus_space_write_4(sc->sc_iot, sc->sc_ioh, IXP425_UART_IER, sc->sc_ier);
#if 0
SET(sc->sc_ier, IER_RAVIE | IER_RTOIE | IER_RLSE | IER_RIE);
bus_space_write_4(sc->sc_iot, sc->sc_ioh,
IXP425_UART_IER, sc->sc_ier);
/* Fetch the current modem control status, needed later. */
sc->sc_msr = bus_space_read_4(iot, ioh, IXP425_UART_MSR);
#endif
sc->sc_msr = bus_space_read_4(sc->sc_iot, sc->sc_ioh,
IXP425_UART_MSR);
COM_UNLOCK(sc);
splx(s2);
@ -724,6 +822,7 @@ ixp4xx_comopen(dev_t dev, int flag, int mode, struct proc *p)
sc->sc_rbavail = IXPCOM_RING_SIZE;
ixp4xx_com_iflush(sc);
CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
ixpcom_hwiflow(sc);
#ifdef COM_DEBUG
if (com_debug)
@ -1017,7 +1116,7 @@ ixp4xx_com_to_tiocm(struct ixp4xx_com_softc *sc)
if (ISSET(combits, MSR_RI | MSR_TERI))
SET(ttybits, TIOCM_RI);
if ((sc->sc_ier & IER_UUE) != 0)
if ((sc->sc_ier & 0x0f) != 0)
SET(ttybits, TIOCM_LE);
return (ttybits);
@ -1112,6 +1211,29 @@ ixp4xx_com_txsoft(struct ixp4xx_com_softc *sc, struct tty *tp)
(*tp->t_linesw->l_start)(tp);
}
void
ixpcomdiag(void *arg)
{
struct ixp4xx_com_softc *sc = arg;
int overflows, floods;
int s;
s = splserial();
COM_LOCK(sc);
overflows = sc->sc_overflows;
sc->sc_overflows = 0;
floods = sc->sc_floods;
sc->sc_floods = 0;
sc->sc_errors = 0;
COM_UNLOCK(sc);
splx(s);
printf("%s: %d silo overflow%s, %d ibuf flood%s\n",
sc->sc_dev.dv_xname,
overflows, overflows == 1 ? "" : "s",
floods, floods == 1 ? "" : "s");
}
inline static void
ixp4xx_com_rxsoft(struct ixp4xx_com_softc *sc, struct tty *tp)
{
@ -1128,8 +1250,14 @@ ixp4xx_com_rxsoft(struct ixp4xx_com_softc *sc, struct tty *tp)
while (cc) {
code = get[0];
lsr = get[1];
if (ISSET(lsr, LSR_OE | LSR_FE | LSR_PE)) {
if (ISSET(lsr, LSR_FE))
if (ISSET(lsr, LSR_OE | LSR_FE | LSR_PE | LSR_BI)) {
if (ISSET(lsr, LSR_OE)) {
sc->sc_overflows++;
if (sc->sc_errors++ == 0)
callout_reset(&sc->sc_diag_callout,
60 * hz, ixpcomdiag, sc);
}
if (ISSET(lsr, LSR_BI | LSR_FE))
SET(code, TTY_FE);
if (ISSET(lsr, LSR_PE))
SET(code, TTY_PE);
@ -1178,11 +1306,12 @@ ixp4xx_com_rxsoft(struct ixp4xx_com_softc *sc, struct tty *tp)
if (cc >= 1) {
if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
SET(sc->sc_ier,IER_RAVIE);
SET(sc->sc_ier, IER_RAVIE | IER_RTOIE);
ixp4xx_com_set_cr(sc);
}
if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) {
CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED);
ixpcom_hwiflow(sc);
}
}
COM_UNLOCK(sc);
@ -1197,48 +1326,59 @@ ixp4xxcomintr(void* arg)
bus_space_tag_t iot = sc->sc_iot;
bus_space_handle_t ioh = sc->sc_ioh;
u_char *put, *end;
u_int cc, res;
u_int32_t c;
u_int cc;
u_char iir, lsr;
if (COM_ISALIVE(sc) == 0)
return (0);
COM_LOCK(sc);
res = bus_space_read_4(iot, ioh, IXP425_UART_IER) & IER_UUE;
if (!res) {
iir = bus_space_read_4(iot, ioh, IXP425_UART_IIR);
if (ISSET(iir, IIR_NOPEND)) {
COM_UNLOCK(sc);
return (0);
}
res = bus_space_read_4(iot, ioh, IXP425_UART_LSR);
if (!ISSET(res, LSR_DR | LSR_TDRQ))
return (0);
end = sc->sc_ebuf;
put = sc->sc_rbput;
cc = sc->sc_rbavail;
if (ISSET(res, LSR_DR)) {
if (!ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
again: do {
u_char msr;
lsr = bus_space_read_4(iot, ioh, IXP425_UART_LSR);
if (ISSET(lsr, LSR_BI)) {
int cn_trapped = 0;
cn_check_magic(sc->sc_tty->t_dev,
CNC_BREAK, ixp4xx_com_cnm_state);
if (cn_trapped)
continue;
}
if (ISSET(lsr, LSR_RCV_MASK) &&
!ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
while (cc > 0) {
if (!ISSET(res, LSR_DR))
break;
c = bus_space_read_4(iot, ioh, IXP425_UART_DATA);
if (ISSET(res, LSR_FE)) {
cn_check_magic(sc->sc_tty->t_dev,
CNC_BREAK,
ixp4xx_com_cnm_state);
}
put[0] = c & 0xff;
put[1] = (c >> 8) & 0xff;
int cn_trapped = 0;
put[0] = bus_space_read_4(iot, ioh, IXP425_UART_DATA);
put[1] = lsr;
cn_check_magic(sc->sc_tty->t_dev,
put[0], ixp4xx_com_cnm_state);
put[0], ixp4xx_com_cnm_state);
if (cn_trapped) {
lsr = bus_space_read_4(iot, ioh,
IXP425_UART_LSR);
if (!ISSET(lsr, LSR_RCV_MASK))
break;
continue;
}
put += 2;
if (put >= end)
put = sc->sc_rbuf;
cc--;
res = bus_space_read_4(iot, ioh, IXP425_UART_LSR);
lsr = bus_space_read_4(iot, ioh, IXP425_UART_LSR);
if (!ISSET(lsr, LSR_RCV_MASK))
break;
}
/*
@ -1256,7 +1396,12 @@ ixp4xxcomintr(void* arg)
* See if we are in danger of overflowing a buffer. If
* so, use hardware flow control to ease the pressure.
*/
/* later XXXX */
if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) &&
cc < sc->sc_r_hiwat) {
SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
ixpcom_hwiflow(sc);
}
/*
* If we're out of space, disable receive interrupts
@ -1264,26 +1409,29 @@ ixp4xxcomintr(void* arg)
*/
if (!cc) {
SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
CLR(sc->sc_ier, IER_RAVIE);
CLR(sc->sc_ier, IER_RAVIE | IER_RTOIE);
ixp4xx_com_set_cr(sc);
}
} else {
#ifdef DIAGNOSTIC
panic("ixpcomintr: we shouldn't reach here");
#endif
CLR(sc->sc_ier, IER_RAVIE);
ixp4xx_com_set_cr(sc);
if ((iir & IIR_IMASK) == IIR_RXRDY) {
sc->sc_ier = IER_UUE;
delay(10);
ixp4xx_com_set_cr(sc);
}
}
}
msr = bus_space_read_4(iot, ioh, IXP425_UART_MSR);
sc->sc_msr = msr;
} while (ISSET((iir = bus_space_read_4(iot, ioh, IXP425_UART_IIR)),
IIR_RXRDY) || ((iir & IIR_IMASK) == 0));
/*
* Done handling any receive interrupts. See if data can be
* transmitted as well. Schedule tx done event if no data left
* and tty was marked busy.
*/
res = bus_space_read_4(iot, ioh, IXP425_UART_LSR);
if (ISSET(res, LSR_TDRQ)) {
if (ISSET(lsr, LSR_TDRQ)) {
/*
* If we've delayed a parameter change, do it now, and restart
* output.
@ -1310,6 +1458,10 @@ ixp4xxcomintr(void* arg)
}
}
}
if (!ISSET((iir = bus_space_read_4(iot, ioh, IXP425_UART_IIR)), IIR_NOPEND))
goto again;
COM_UNLOCK(sc);
/* Wake up the poller. */

View File

@ -1,4 +1,4 @@
/* $NetBSD: ixp425_comvar.h,v 1.5 2003/06/29 22:28:12 fvdl Exp $ */
/* $NetBSD: ixp425_comvar.h,v 1.6 2003/07/02 10:40:47 ichiro Exp $ */
/*-
* Copyright (c) 2001, The NetBSD Foundation, Inc. All rights reserved.
*
@ -77,14 +77,19 @@ struct ixp4xx_com_softc {
volatile u_int sc_rbavail;
/* status flags */
int sc_hwflags, sc_swflags;
int sc_hwflags,
sc_swflags;
volatile u_int sc_rx_flags,
sc_tx_busy,
sc_tx_done,
sc_tx_stopped,
sc_st_check,
sc_rx_ready;
u_int sc_overflows,
sc_floods,
sc_errors;
u_int sc_r_hiwat,
sc_r_lowat;
volatile int sc_heldchange;
volatile int sc_msr, sc_msr_delta, sc_msr_mask, sc_mcr,
sc_mcr_active, sc_lcr, sc_ier, sc_fcr,

View File

@ -1,4 +1,4 @@
/* $NetBSD: ixp425reg.h,v 1.7 2003/06/29 22:28:12 fvdl Exp $ */
/* $NetBSD: ixp425reg.h,v 1.8 2003/07/02 10:40:47 ichiro Exp $ */
/*
* Copyright (c) 2003
* Ichiro FUKUHARA <ichiro@ichiro.org>.
@ -140,6 +140,7 @@
/* Interrupt Identification Register */
#define IXP425_UART_IIR 0x0008
#define IIR_IMASK 0xf
#define IIR_NOPEND (1U << 0) /* No pending interrupts */
#define IIR_MLSC (0U << 1) /* Modem status */
#define IIR_TXRDY (1U << 1) /* Transmitter ready */
@ -191,6 +192,7 @@
#define LSR_PE (1U << 2) /* Parity error */
#define LSR_OE (1U << 1) /* Overrun, lost incoming byte */
#define LSR_DR (1U << 0) /* Byte ready in Receive Buffer */
#define LSR_RCV_MASK 0x1f /* Incoming data and error */
/* Modem Status Register */
#define IXP425_UART_MSR 0x0018