New version of the z8530 driver that should permit the mac68k port

to use this instead of its own.  Also fix warnings, etc.
This commit is contained in:
gwr 1996-12-17 20:42:40 +00:00
parent 6a4e12cde0
commit 494730c376
4 changed files with 371 additions and 362 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: z8530sc.c,v 1.4 1996/05/17 19:30:34 gwr Exp $ */
/* $NetBSD: z8530sc.c,v 1.5 1996/12/17 20:42:40 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@ -67,7 +67,7 @@
#include <dev/ic/z8530reg.h>
#include <machine/z8530var.h>
int
void
zs_break(cs, set)
struct zs_chanstate *cs;
int set;
@ -87,20 +87,6 @@ zs_break(cs, set)
}
/*
* Compute the current baud rate given a ZSCC channel.
*/
int
zs_getspeed(cs)
struct zs_chanstate *cs;
{
int tconst;
tconst = zs_read_reg(cs, 12);
tconst |= zs_read_reg(cs, 13) << 8;
return (TCONST_TO_BPS(cs->cs_brg_clk, tconst));
}
/*
* drain on-chip fifo
*/
@ -142,7 +128,6 @@ zs_loadchannelregs(cs)
struct zs_chanstate *cs;
{
u_char *reg;
int i;
/* Copy "pending" regs to "current" */
bcopy((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16);
@ -158,6 +143,9 @@ zs_loadchannelregs(cs)
zs_iflush(cs); /* XXX */
#endif
/* disable interrupts */
zs_write_reg(cs, 1, reg[1] & ~ZSWR1_IMASK);
/* baud clock divisor, stop bits, parity */
zs_write_reg(cs, 4, reg[4]);
@ -168,8 +156,9 @@ zs_loadchannelregs(cs)
zs_write_reg(cs, 3, reg[3] & ~ZSWR3_RX_ENABLE);
zs_write_reg(cs, 5, reg[5] & ~ZSWR5_TX_ENABLE);
/* interrupt enables: TX, TX, STATUS */
zs_write_reg(cs, 1, reg[1]);
/* synchronous mode stuff */
zs_write_reg(cs, 6, reg[6]);
zs_write_reg(cs, 7, reg[7]);
#if 0
/*
@ -185,6 +174,14 @@ zs_loadchannelregs(cs)
zs_write_reg(cs, 9, reg[9]);
#endif
/* Shut down the BRG */
zs_write_reg(cs, 14, reg[14] & ~ZSWR14_BAUD_ENA);
#ifdef ZS_MD_SETCLK
/* Let the MD code setup any external clock. */
ZS_MD_SETCLK(cs);
#endif /* ZS_MD_SETCLK */
/* clock mode control */
zs_write_reg(cs, 11, reg[11]);
@ -198,9 +195,21 @@ zs_loadchannelregs(cs)
/* which lines cause status interrupts */
zs_write_reg(cs, 15, reg[15]);
/*
* Zilog docs recommend resetting external status twice at this
* point. Mainly as the status bits are latched, and the first
* interrupt clear might unlatch them to new values, generating
* a second interrupt request.
*/
zs_write_csr(cs, ZSM_RESET_STINT);
zs_write_csr(cs, ZSM_RESET_STINT);
/* char size, enable (RX/TX)*/
zs_write_reg(cs, 3, reg[3]);
zs_write_reg(cs, 5, reg[5]);
/* interrupt enables: RX, TX, STATUS */
zs_write_reg(cs, 1, reg[1]);
}
@ -223,48 +232,49 @@ zsc_intr_hard(arg)
register struct zs_chanstate *cs_a;
register struct zs_chanstate *cs_b;
register int rval;
register u_char rr3;
register u_char rr3, rr3a;
cs_a = &zsc->zsc_cs[0];
cs_b = &zsc->zsc_cs[1];
cs_a = zsc->zsc_cs[0];
cs_b = zsc->zsc_cs[1];
rval = 0;
rr3a = 0;
/* Note: only channel A has an RR3 */
rr3 = zs_read_reg(cs_a, 3);
while ((rr3 = zs_read_reg(cs_a, 3)) != 0) {
/* Handle receive interrupts first. */
if (rr3 & ZSRR3_IP_A_RX)
(*cs_a->cs_ops->zsop_rxint)(cs_a);
if (rr3 & ZSRR3_IP_B_RX)
(*cs_b->cs_ops->zsop_rxint)(cs_b);
/* Handle receive interrupts first. */
if (rr3 & ZSRR3_IP_A_RX)
(*cs_a->cs_ops->zsop_rxint)(cs_a);
if (rr3 & ZSRR3_IP_B_RX)
(*cs_b->cs_ops->zsop_rxint)(cs_b);
/* Handle status interrupts (i.e. flow control). */
if (rr3 & ZSRR3_IP_A_STAT)
(*cs_a->cs_ops->zsop_stint)(cs_a);
if (rr3 & ZSRR3_IP_B_STAT)
(*cs_b->cs_ops->zsop_stint)(cs_b);
/* Handle status interrupts (i.e. flow control). */
if (rr3 & ZSRR3_IP_A_STAT)
(*cs_a->cs_ops->zsop_stint)(cs_a);
if (rr3 & ZSRR3_IP_B_STAT)
(*cs_b->cs_ops->zsop_stint)(cs_b);
/* Handle transmit done interrupts. */
if (rr3 & ZSRR3_IP_A_TX)
(*cs_a->cs_ops->zsop_txint)(cs_a);
if (rr3 & ZSRR3_IP_B_TX)
(*cs_b->cs_ops->zsop_txint)(cs_b);
/* Handle transmit done interrupts. */
if (rr3 & ZSRR3_IP_A_TX)
(*cs_a->cs_ops->zsop_txint)(cs_a);
if (rr3 & ZSRR3_IP_B_TX)
(*cs_b->cs_ops->zsop_txint)(cs_b);
/* Accumulate so we know what needs to be cleared. */
rr3a |= rr3;
}
/* Clear interrupt. */
if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
if (rr3a & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
zs_write_csr(cs_a, ZSWR0_CLR_INTR);
rval |= 1;
}
if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
if (rr3a & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
zs_write_csr(cs_b, ZSWR0_CLR_INTR);
rval |= 2;
}
if ((cs_a->cs_softreq) || (cs_b->cs_softreq)) {
/* This is a machine-dependent function (or macro). */
zsc_req_softint(zsc);
}
/* Note: caller will check cs_x->cs_softreq and DTRT. */
return (rval);
}
@ -278,11 +288,11 @@ zsc_intr_soft(arg)
{
register struct zsc_softc *zsc = arg;
register struct zs_chanstate *cs;
register int rval, unit;
register int rval, chan;
rval = 0;
for (unit = 0; unit < 2; unit++) {
cs = &zsc->zsc_cs[unit];
for (chan = 0; chan < 2; chan++) {
cs = zsc->zsc_cs[chan];
/*
* The softint flag can be safely cleared once
@ -292,25 +302,33 @@ zsc_intr_soft(arg)
if (cs->cs_softreq) {
cs->cs_softreq = 0;
(*cs->cs_ops->zsop_softint)(cs);
rval = 1;
rval++;
}
}
return (rval);
}
/*
* Provide a null zs "ops" vector.
*/
static void zsnull_intr __P((struct zs_chanstate *));
static void zsnull_softint __P((struct zs_chanstate *));
static void
zsnull_intr(cs)
struct zs_chanstate *cs;
{
zs_write_reg(cs, 1, 0);
zs_write_reg(cs, 15, 0);
/* Ask for softint() call. */
cs->cs_softreq = 1;
}
static void
zsnull_softint(cs)
struct zs_chanstate *cs;
{
zs_write_reg(cs, 1, 0);
zs_write_reg(cs, 15, 0);
}
struct zsops zsops_null = {

View File

@ -1,4 +1,4 @@
/* $NetBSD: z8530sc.h,v 1.4 1996/10/16 20:34:54 gwr Exp $ */
/* $NetBSD: z8530sc.h,v 1.5 1996/12/17 20:42:42 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@ -49,11 +49,13 @@
/*
* Function vector - per channel
*/
struct zs_chanstate;
typedef void (*zsop_t) __P((struct zs_chanstate *));
struct zsops {
void (*zsop_rxint)(); /* receive char available */
void (*zsop_stint)(); /* external/status */
void (*zsop_txint)(); /* xmit buffer empty */
void (*zsop_softint)(); /* process software interrupt */
zsop_t zsop_rxint; /* receive char available */
zsop_t zsop_stint; /* external/status */
zsop_t zsop_txint; /* xmit buffer empty */
zsop_t zsop_softint; /* process software interrupt */
};
extern struct zsops zsops_null;
@ -74,7 +76,8 @@ struct zs_chanstate {
int cs_brg_clk; /* BAUD Rate Generator clock
* (usually PCLK / 16) */
int cs_defspeed; /* default baud rate (from PROM) */
int cs_defspeed; /* default baud rate */
int cs_defcflag; /* default cflag */
/*
* We must keep a copy of the write registers as they are
@ -91,22 +94,41 @@ struct zs_chanstate {
*/
u_char cs_creg[16]; /* current values */
u_char cs_preg[16]; /* pending values */
int cs_heldchange; /* change pending (creg != preg) */
u_char cs_heldchange; /* change pending (creg != preg) */
u_char cs_rr0; /* last rr0 processed */
u_char cs_rr0_delta; /* rr0 changes at status intr. */
u_char cs_rr0_dcd; /* which bit to read as DCD */
u_char cs_rr0_cts; /* which bit to read as CTS */
/* the above is set only while CRTSCTS is enabled. */
u_char cs_wr5_dtr; /* which bit to write as DTR */
u_char cs_wr5_rts; /* which bit to write as RTS */
/* the above is set only while CRTSCTS is enabled. */
char cs_softreq; /* need soft interrupt call */
};
struct zsc_softc {
struct device zsc_dev; /* required first: base device */
struct zs_chanstate zsc_cs[2]; /* channel A and B soft state */
char cs_pad[1];
/* MD code might define a larger variant of this. */
};
struct zsc_attach_args {
int channel; /* two serial channels per zsc */
int hwflags;
};
#define ZS_HWFLAG_CONSOLE 1
#define ZS_HWFLAG_CONSOLE 1
#define ZS_HWFLAG_NO_DCD 2 /* Ignore the DCD bit */
#define ZS_HWFLAG_NO_CTS 4 /* Ignore the CTS bit */
#define ZS_HWFLAG_RAW 8 /* advise raw mode */
int zsc_intr_soft __P((void *));
int zsc_intr_hard __P((void *));
void zs_abort __P((struct zs_chanstate *));
void zs_break __P((struct zs_chanstate *, int));
void zs_iflush __P((struct zs_chanstate *));
void zs_loadchannelregs __P((struct zs_chanstate *));
int zs_set_speed __P((struct zs_chanstate *, int));
int zs_set_modes __P((struct zs_chanstate *, int));
extern int zs_major;

View File

@ -1,4 +1,4 @@
/* $NetBSD: z8530tty.c,v 1.13 1996/10/16 20:42:14 gwr Exp $ */
/* $NetBSD: z8530tty.c,v 1.14 1996/12/17 20:42:43 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@ -85,14 +85,6 @@
extern int zs_check_kgdb();
#endif
/*
* Allow the MD var.h to override the default CFLAG so that
* console messages during boot come out with correct parity.
*/
#ifndef ZSTTY_DEF_CFLAG
#define ZSTTY_DEF_CFLAG TTYDEF_CFLAG
#endif
/*
* How many input characters we can buffer.
* The port-specific var.h may override this.
@ -158,7 +150,11 @@ struct zstty_softc {
/* Definition of the driver for autoconfig. */
#ifdef __BROKEN_INDIRECT_CONFIG
static int zstty_match(struct device *, void *, void *);
#else
static int zstty_match(struct device *, struct cfdata *, void *);
#endif
static void zstty_attach(struct device *, struct device *, void *);
struct cfattach zstty_ca = {
@ -174,21 +170,22 @@ struct zsops zsops_tty;
/* Routines called from other code. */
cdev_decl(zs); /* open, close, read, write, ioctl, stop, ... */
static void zsstart(struct tty *);
static int zsparam(struct tty *, struct termios *);
static void zs_modem(struct zstty_softc *zst, int onoff);
static int zshwiflow(struct tty *, int);
static void zs_hwiflow(struct zstty_softc *, int);
static void zsstart __P((struct tty *));
static int zsparam __P((struct tty *, struct termios *));
static void zs_modem __P((struct zstty_softc *zst, int onoff));
static int zshwiflow __P((struct tty *, int));
static void zs_hwiflow __P((struct zstty_softc *, int));
/*
* zstty_match: how is this zs channel configured?
*/
#ifdef __BROKEN_INDIRECT_CONFIG
int
zstty_match(parent, match, aux)
zstty_match(parent, vcf, aux)
struct device *parent;
void *match, *aux;
void *vcf, *aux;
{
struct cfdata *cf = match;
struct cfdata *cf = vcf;
struct zsc_attach_args *args = aux;
/* Exact match is better than wildcard. */
@ -201,6 +198,26 @@ zstty_match(parent, match, aux)
return 0;
}
#else /* __BROKEN_INDIRECT_CONFIG */
int
zstty_match(parent, cf, aux)
struct device *parent;
struct cfdata *cf;
void *aux;
{
struct zsc_attach_args *args = aux;
/* Exact match is better than wildcard. */
if (cf->cf_loc[0] == args->channel)
return 2;
/* This driver accepts wildcard. */
if (cf->cf_loc[0] == -1)
return 1;
return 0;
}
#endif /* __BROKEN_INDIRECT_CONFIG */
void
zstty_attach(parent, self, aux)
@ -210,24 +227,23 @@ zstty_attach(parent, self, aux)
{
struct zsc_softc *zsc = (void *) parent;
struct zstty_softc *zst = (void *) self;
struct cfdata *cf = self->dv_cfdata;
struct zsc_attach_args *args = aux;
struct zs_chanstate *cs;
struct cfdata *cf;
struct tty *tp;
int channel, tty_unit;
dev_t dev;
cf = zst->zst_dev.dv_cfdata;
tty_unit = zst->zst_dev.dv_unit;
channel = args->channel;
cs = &zsc->zsc_cs[channel];
cs = zsc->zsc_cs[channel];
cs->cs_private = zst;
cs->cs_ops = &zsops_tty;
zst->zst_cs = cs;
zst->zst_swflags = cf->cf_flags; /* softcar, etc. */
zst->zst_hwflags = args->hwflags;
dev = makedev(ZSTTY_MAJOR, tty_unit);
dev = makedev(zs_major, tty_unit);
if (zst->zst_swflags)
printf(" flags 0x%x", zst->zst_swflags);
@ -266,18 +282,26 @@ zstty_attach(parent, self, aux)
zst->zst_rbuf = malloc(zstty_rbuf_size * sizeof(zst->zst_rbuf[0]),
M_DEVBUF, M_WAITOK);
/* XXX - Do we need an MD hook here? */
/*
* Hardware init
*/
if (zst->zst_hwflags & ZS_HWFLAG_CONSOLE) {
/* This unit is the console. */
/* Call zsparam similar to open. */
struct termios t;
/* Make console output work while closed. */
zst->zst_swflags |= TIOCFLAG_SOFTCAR;
/* Call _param so interrupts get enabled. */
cs->cs_defspeed = zs_getspeed(cs);
tp->t_ispeed = cs->cs_defspeed;
tp->t_ospeed = cs->cs_defspeed;
tp->t_cflag = ZSTTY_DEF_CFLAG;
(void) zsparam(tp, &tp->t_termios);
/* Setup the "new" parameters in t. */
bzero((void*)&t, sizeof(t));
t.c_cflag = cs->cs_defcflag;
t.c_ospeed = cs->cs_defspeed;
/* Enable interrupts. */
cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_SIE;
/* Make sure zsparam will see changes. */
tp->t_ospeed = 0;
(void) zsparam(tp, &t);
} else {
/* Not the console; may need reset. */
int reset, s;
@ -357,48 +381,77 @@ zsopen(dev, flags, mode, p)
if ((tp->t_state & TS_ISOPEN) == 0) {
/* First open. */
ttychars(tp);
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
tp->t_cflag = ZSTTY_DEF_CFLAG;
struct termios t;
/*
* Setup the "new" parameters in t.
* Can not use tp->t because zsparam
* deals only with what has changed.
*/
bzero((void*)&t, sizeof(t));
t.c_cflag = cs->cs_defcflag;
if (zst->zst_swflags & TIOCFLAG_CLOCAL)
tp->t_cflag |= CLOCAL;
t.c_cflag |= CLOCAL;
if (zst->zst_swflags & TIOCFLAG_CRTSCTS)
tp->t_cflag |= CRTSCTS;
t.c_cflag |= CRTSCTS;
if (zst->zst_swflags & TIOCFLAG_MDMBUF)
tp->t_cflag |= MDMBUF;
tp->t_lflag = TTYDEF_LFLAG;
tp->t_ispeed = tp->t_ospeed = cs->cs_defspeed;
(void) zsparam(tp, &tp->t_termios);
t.c_cflag |= MDMBUF;
t.c_ospeed = cs->cs_defspeed;
/* Enable interrupts. */
cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_SIE;
/* Make sure zsparam will see changes. */
tp->t_ospeed = 0;
(void) zsparam(tp, &t);
/*
* Note: zsparam has done: cflag, ispeed, ospeed
* so we just need to do: iflag, oflag, lflag, cc
* For "raw" mode, just leave all zeros.
*/
if ((zst->zst_hwflags & ZS_HWFLAG_RAW) == 0) {
tp->t_iflag = TTYDEF_IFLAG;
tp->t_oflag = TTYDEF_OFLAG;
tp->t_lflag = TTYDEF_LFLAG;
ttychars(tp);
}
ttsetwater(tp);
/* Flush any pending input. */
zst->zst_rbget = zst->zst_rbput;
zs_iflush(cs); /* XXX */
/* Turn on DTR */
zs_modem(zst, 1);
/* DTR was turned on by zsparam. */
if (zst->zst_swflags & TIOCFLAG_SOFTCAR) {
tp->t_state |= TS_CARR_ON;
}
/* XXX - The MD code could just force CLOCAL instead. */
if (zst->zst_hwflags & ZS_HWFLAG_NO_DCD) {
tp->t_state |= TS_CARR_ON;
}
}
error = 0;
/* Wait for carrier. */
for (;;) {
/* In this section, we may touch the chip. */
(void)splzs();
/* Might never get status intr if carrier already on. */
cs->cs_rr0 = zs_read_csr(cs);
if (cs->cs_rr0 & ZSRR0_DCD) {
/*
* Get initial value of RR0. This is done after we
* raise DTR in case the cable loops DTR back to CTS.
*/
cs->cs_rr0 = zs_read_csr(cs);
/*
* Wait for DCD (if necessary). Note that we might
* never get status interrupt if DCD is already on.
*/
for (;;) {
/* Check the DCD bit (if we have one). */
if (cs->cs_rr0 & cs->cs_rr0_dcd)
tp->t_state |= TS_CARR_ON;
break;
}
if ((tp->t_state & TS_CARR_ON) ||
(tp->t_cflag & CLOCAL) ||
(flags & O_NONBLOCK) )
{
break;
}
/* Sleep waiting for a status interrupt. */
tp->t_state |= TS_WOPEN;
error = ttysleep(tp, (caddr_t)&tp->t_rawq,
TTIPRI | PCATCH, ttopen, 0);
@ -411,13 +464,12 @@ zsopen(dev, flags, mode, p)
}
break;
}
/* The status interrupt changed cs->cs_rr0 */
}
splx(s);
if (error == 0)
error = linesw[tp->t_line].l_open(dev, tp);
return (error);
}
@ -434,7 +486,6 @@ zsclose(dev, flags, mode, p)
struct zstty_softc *zst;
register struct zs_chanstate *cs;
register struct tty *tp;
struct zsinfo *zi;
int hup, s;
zst = zstty_cd.cd_devs[minor(dev)];
@ -446,6 +497,14 @@ zsclose(dev, flags, mode, p)
return 0;
(*linesw[tp->t_line].l_close)(tp, flags);
/* Disable interrupts. */
s = splzs();
cs->cs_creg[1] = cs->cs_preg[1] = 0;
zs_write_reg(cs, 1, cs->cs_creg[1]);
splx(s);
/* Maybe do "hangup" (drop DTR). */
hup = tp->t_cflag & HUPCL;
if (zst->zst_swflags & TIOCFLAG_SOFTCAR)
hup = 0;
@ -457,7 +516,6 @@ zsclose(dev, flags, mode, p)
if (cs->cs_creg[5] & ZSWR5_BREAK) {
zs_break(cs, 0);
}
/* XXX - turn off interrupts? */
ttyclose(tp);
return (0);
@ -517,10 +575,17 @@ zsioctl(dev, cmd, data, flag, p)
error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
if (error >= 0)
return (error);
error = ttioctl(tp, cmd, data, flag, p);
if (error >= 0)
return (error);
#ifdef ZS_MD_IOCTL
error = ZS_MD_IOCTL;
if (error >= 0)
return (error);
#endif /* ZS_MD_IOCTL */
switch (cmd) {
case TIOCSBRK:
@ -592,10 +657,10 @@ zsstart(tp)
/*
* If under CRTSCTS hfc and halted, do nothing
* This flag can only be set with CRTSCTS.
*/
if (tp->t_cflag & CRTSCTS)
if (zst->zst_tx_stopped)
goto out;
if (zst->zst_tx_stopped)
goto out;
/*
* If there are sleepers, and output has drained below low
@ -671,101 +736,116 @@ zsstop(tp, flag)
* Set ZS tty parameters from termios.
* XXX - Should just copy the whole termios after
* making sure all the changes could be done.
* XXX - Only whack the UART when params change...
*/
static int
zsparam(tp, t)
register struct tty *tp;
register struct termios *t;
{
register struct zstty_softc *zst;
register struct zs_chanstate *cs;
register int s, bps, cflag, tconst;
u_char tmp3, tmp4, tmp5, reset;
struct zstty_softc *zst;
struct zs_chanstate *cs;
int s, bps, cflag, error;
u_char tmp3, tmp4, tmp5;
zst = zstty_cd.cd_devs[minor(tp->t_dev)];
cs = zst->zst_cs;
/* XXX: Need to use an MD function for this. */
bps = t->c_ospeed;
cflag = t->c_cflag;
if (bps < 0 || (t->c_ispeed && t->c_ispeed != bps))
return (EINVAL);
if (bps == 0) {
/* stty 0 => drop DTR and RTS */
zs_modem(zst, 0);
/*
* Only whack the UART when params change.
* Some callers need to clear tp->t_ospeed
* to make sure initialization gets done.
*/
if ((tp->t_ospeed == bps) &&
(tp->t_cflag == cflag) )
return (0);
}
tconst = BPS_TO_TCONST(cs->cs_brg_clk, bps);
if (tconst < 0)
return (EINVAL);
/* Convert back to make sure we can do it. */
bps = TCONST_TO_BPS(cs->cs_brg_clk, tconst);
if (bps != t->c_ospeed)
return (EINVAL);
tp->t_ispeed = tp->t_ospeed = bps;
/*
* Call MD functions to deal with changed
* clock modes or H/W flow control modes.
* The BRG divisor is set now. (reg 12,13)
*/
error = zs_set_speed(cs, bps);
if (error)
return (error);
error = zs_set_modes(cs, cflag);
if (error)
return (error);
cflag = t->c_cflag;
/* OK, we are now committed to do it. */
tp->t_cflag = cflag;
tp->t_ospeed = bps;
tp->t_ispeed = bps;
/*
* Block interrupts so that state will not
* be altered until we are done setting it up.
*/
s = splzs();
/*
*
* Initial values in cs_preg are set before
* our attach routine is called. The master
* interrupt enable is handled by zsc.c
*
*/
s = splzs();
cs->cs_preg[12] = tconst;
cs->cs_preg[13] = tconst >> 8;
/* Recompute character size bits. */
tmp3 = cs->cs_preg[3] & ~ZSWR3_RXSIZE;
tmp5 = cs->cs_preg[5] & ~ZSWR5_TXSIZE;
switch (cflag & CSIZE) {
case CS5:
tmp3 = ZSWR3_RX_5;
tmp5 = ZSWR5_TX_5;
/* These are |= 0 but let the optimizer deal with it. */
tmp3 |= ZSWR3_RX_5;
tmp5 |= ZSWR5_TX_5;
break;
case CS6:
tmp3 = ZSWR3_RX_6;
tmp5 = ZSWR5_TX_6;
tmp3 |= ZSWR3_RX_6;
tmp5 |= ZSWR5_TX_6;
break;
case CS7:
tmp3 = ZSWR3_RX_7;
tmp5 = ZSWR5_TX_7;
tmp3 |= ZSWR3_RX_7;
tmp5 |= ZSWR5_TX_7;
break;
case CS8:
default:
tmp3 = ZSWR3_RX_8;
tmp5 = ZSWR5_TX_8;
tmp3 |= ZSWR3_RX_8;
tmp5 |= ZSWR5_TX_8;
break;
}
/* Raise or lower DTR and RTS as appropriate. */
if (bps) {
/* Raise DTR and RTS */
tmp5 |= cs->cs_wr5_dtr;
} else {
/* Drop DTR and RTS */
/* XXX: Should SOFTCAR prevent this? */
tmp5 &= ~(cs->cs_wr5_dtr);
}
cs->cs_preg[3] = tmp3;
cs->cs_preg[5] = tmp5;
cs->cs_preg[3] = tmp3 | ZSWR3_RX_ENABLE;
cs->cs_preg[5] = tmp5 | ZSWR5_TX_ENABLE | ZSWR5_DTR | ZSWR5_RTS;
tmp4 = ZSWR4_CLK_X16 | (cflag & CSTOPB ? ZSWR4_TWOSB : ZSWR4_ONESB);
/*
* Recompute the stop bits and parity bits. Note that
* zs_set_speed() may have set clock selection bits etc.
* in wr4, so those must preserved.
*/
tmp4 = cs->cs_preg[4];
/* Recompute stop bits. */
tmp4 &= ~ZSWR4_SBMASK;
tmp4 |= (cflag & CSTOPB) ?
ZSWR4_TWOSB : ZSWR4_ONESB;
/* Recompute parity bits. */
tmp4 &= ~ZSWR4_PARMASK;
if ((cflag & PARODD) == 0)
tmp4 |= ZSWR4_EVENP;
if (cflag & PARENB)
tmp4 |= ZSWR4_PARENB;
cs->cs_preg[4] = tmp4;
/*
* Output hardware flow control on the chip is horrendous:
* if carrier detect drops, the receiver is disabled.
* Therefore, NEVER set the HFC bit, and instead use
* the status interrupts to detect CTS changes.
*/
if (cflag & CRTSCTS) {
zst->zst_rbhiwat = zstty_rbuf_hiwat;
cs->cs_preg[15] |= ZSWR15_CTS_IE;
} else {
zst->zst_rbhiwat = zstty_rbuf_size; /* impossible value */
cs->cs_preg[15] &= ~ZSWR15_CTS_IE;
}
/* The MD function zs_set_modes handled CRTSCTS, etc. */
/*
* If nothing is being transmitted, set up new current values,
@ -775,12 +855,27 @@ zsparam(tp, t)
if (zst->zst_tx_busy) {
zst->zst_heldtbc = zst->zst_tbc;
zst->zst_tbc = 0;
cs->cs_heldchange = 0xFF; /* XXX */
cs->cs_heldchange = 0xFFFF;
} else {
zs_loadchannelregs(cs);
}
}
splx(s);
/* If we can throttle input, enable "high water" detection. */
if (cflag & CHWFLOW) {
zst->zst_rbhiwat = zstty_rbuf_hiwat;
} else {
/* This impossible value prevents a "high water" trigger. */
zst->zst_rbhiwat = zstty_rbuf_size;
/* XXX: Lost hwi ability, so unblock and restart. */
zst->zst_rx_blocked = 0;
if (zst->zst_tx_stopped) {
zst->zst_tx_stopped = 0;
zsstart(tp);
}
}
return (0);
}
@ -794,21 +889,23 @@ zs_modem(zst, onoff)
int onoff;
{
struct zs_chanstate *cs;
struct tty *tp;
int s, bis, and;
int s, clr, set;
cs = zst->zst_cs;
tp = zst->zst_tty;
if (cs->cs_wr5_dtr == 0)
return;
if (onoff) {
bis = ZSWR5_DTR | ZSWR5_RTS;
and = ~0;
clr = 0;
set = cs->cs_wr5_dtr;
} else {
bis = 0;
and = ~(ZSWR5_DTR | ZSWR5_RTS);
clr = cs->cs_wr5_dtr;
set = 0;
}
s = splzs();
cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
cs->cs_preg[5] &= ~clr;
cs->cs_preg[5] |= set;
if (cs->cs_heldchange == 0) {
if (zst->zst_tx_busy) {
zst->zst_heldtbc = zst->zst_tbc;
@ -834,9 +931,15 @@ zshwiflow(tp, stop)
int stop;
{
register struct zstty_softc *zst;
register struct zs_chanstate *cs;
int s;
zst = zstty_cd.cd_devs[minor(tp->t_dev)];
cs = zst->zst_cs;
/* Can not do this without some bit assigned as RTS. */
if (cs->cs_wr5_rts == 0)
return (0);
s = splzs();
if (stop) {
@ -870,23 +973,25 @@ zs_hwiflow(zst, stop)
int stop;
{
register struct zs_chanstate *cs;
register struct tty *tp;
register int bis, and;
register int clr, set;
cs = zst->zst_cs;
tp = zst->zst_tty;
if (cs->cs_wr5_rts == 0)
return;
if (stop) {
/* Block input (Lower RTS) */
bis = 0;
and = ~ZSWR5_RTS;
clr = cs->cs_wr5_rts;
set = 0;
} else {
/* Unblock input (Raise RTS) */
bis = ZSWR5_RTS;
and = ~0;
clr = 0;
set = cs->cs_wr5_rts;
}
cs->cs_preg[5] = (cs->cs_preg[5] | bis) & and;
cs->cs_preg[5] &= ~clr;
cs->cs_preg[5] |= set;
if (cs->cs_heldchange == 0) {
if (zst->zst_tx_busy) {
zst->zst_heldtbc = zst->zst_tbc;
@ -904,6 +1009,12 @@ zs_hwiflow(zst, stop)
* Interface to the lower layer (zscc)
****************************************************************/
static void zstty_rxint __P((struct zs_chanstate *));
static void zstty_txint __P((struct zs_chanstate *));
static void zstty_stint __P((struct zs_chanstate *));
static void zstty_softint __P((struct zs_chanstate *));
static void zsoverrun __P((struct zstty_softc *, long *, char *));
/*
* receiver ready interrupt.
@ -1033,11 +1144,9 @@ zstty_stint(cs)
register struct zs_chanstate *cs;
{
register struct zstty_softc *zst;
register struct tty *tp;
register u_char rr0;
register u_char rr0, delta;
zst = cs->cs_private;
tp = zst->zst_tty;
rr0 = zs_read_csr(cs);
zs_write_csr(cs, ZSWR0_RESET_STATUS);
@ -1049,23 +1158,10 @@ zstty_stint(cs)
if ((rr0 & ZSRR0_BREAK) &&
(zst->zst_hwflags & ZS_HWFLAG_CONSOLE))
{
zs_abort();
zs_abort(cs);
return;
}
/*
* Need to handle CTS output flow control here.
* Output remains stopped as long as either the
* zst_tx_stopped or TS_TTSTOP flag is set.
* Never restart here; the softint routine will
* do that after things are ready to move.
*/
if (((rr0 & ZSRR0_CTS) == 0) && (tp->t_cflag & CRTSCTS)) {
zst->zst_tbc = 0;
zst->zst_heldtbc = 0;
zst->zst_tx_stopped = 1;
}
/*
* We have to accumulate status line changes here.
* Otherwise, if we get multiple status interrupts
@ -1073,8 +1169,24 @@ zstty_stint(cs)
* some status line changes in the softint routine.
* Fix from Bill Studenmund, October 1996.
*/
cs->cs_rr0_delta |= (cs->cs_rr0 ^ rr0);
delta = (cs->cs_rr0 ^ rr0);
cs->cs_rr0_delta |= delta;
cs->cs_rr0 = rr0;
/*
* Need to handle CTS output flow control here.
* Output remains stopped as long as either the
* zst_tx_stopped or TS_TTSTOP flag is set.
* Never restart here; the softint routine will
* do that after things are ready to move.
*/
if ((delta & cs->cs_rr0_cts) &&
((rr0 & cs->cs_rr0_cts) == 0))
{
zst->zst_tbc = 0;
zst->zst_heldtbc = 0;
zst->zst_tx_stopped = 1;
}
zst->zst_st_check = 1;
/* Ask for softint() call. */
@ -1120,7 +1232,7 @@ zstty_softint(cs)
register int get, c, s;
int ringmask, overrun;
register u_short ring_data;
register u_char rr0, rr1, delta;
register u_char rr0, delta;
zst = cs->cs_private;
tp = zst->zst_tty;
@ -1189,22 +1301,28 @@ zstty_softint(cs)
if (zst->zst_st_check) {
zst->zst_st_check = 0;
(void) splzs();
rr0 = cs->cs_rr0;
delta = cs->cs_rr0_delta;
cs->cs_rr0_delta = 0;
if (delta & ZSRR0_DCD) {
c = ((rr0 & ZSRR0_DCD) != 0);
(void) spltty();
/* Note, the MD code may use DCD for something else. */
if (delta & cs->cs_rr0_dcd) {
c = ((rr0 & cs->cs_rr0_dcd) != 0);
if (line->l_modem(tp, c) == 0)
zs_modem(zst, c);
}
if ((delta & ZSRR0_CTS) && (tp->t_cflag & CRTSCTS)) {
/* Note, cs_rr0_cts is set only with H/W flow control. */
if (delta & cs->cs_rr0_cts) {
/*
* Only do restart here. Stop is handled
* at the h/w interrupt level.
*/
if (rr0 & ZSRR0_CTS) {
if (rr0 & cs->cs_rr0_cts) {
zst->zst_tx_stopped = 0;
tp->t_state &= ~TS_TTSTOP;
/* tp->t_state &= ~TS_TTSTOP; */
(*line->l_start)(tp);
}
}

View File

@ -1,149 +0,0 @@
/* $NetBSD: z8530var.h,v 1.5 1996/10/23 00:38:05 gwr Exp $ */
/*
* Copyright (c) 1994 Gordon W. Ross
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This software was developed by the Computer Systems Engineering group
* at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
* contributed to Berkeley.
*
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Lawrence Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)zsvar.h 8.1 (Berkeley) 6/11/93
*/
/*
* Function vector - per channel
*/
struct zs_chanstate;
typedef void (*zsop_t) __P((struct zs_chanstate *));
struct zsops {
zsop_t zsop_rxint; /* receive char available */
zsop_t zsop_stint; /* external/status */
zsop_t zsop_txint; /* xmit buffer empty */
zsop_t zsop_softint; /* process software interrupt */
};
extern struct zsops zsops_null;
/*
* Software state, per zs channel.
*/
struct zs_chanstate {
/* Pointers to the device registers. */
volatile u_char *cs_reg_csr; /* ctrl, status, and reg. number. */
volatile u_char *cs_reg_data; /* data or numbered register */
int cs_channel; /* sub-unit number */
void *cs_private; /* sub-driver data pointer */
struct zsops *cs_ops;
int cs_brg_clk; /* BAUD Rate Generator clock
* (usually PCLK / 16) */
int cs_defspeed; /* default baud rate */
int cs_defcflag; /* default cflag */
/*
* We must keep a copy of the write registers as they are
* mostly write-only and we sometimes need to set and clear
* individual bits (e.g., in WR3). Not all of these are
* needed but 16 bytes is cheap and this makes the addressing
* simpler. Unfortunately, we can only write to some registers
* when the chip is not actually transmitting, so whenever
* we are expecting a `transmit done' interrupt the preg array
* is allowed to `get ahead' of the current values. In a
* few places we must change the current value of a register,
* rather than (or in addition to) the pending value; for these
* cs_creg[] contains the current value.
*/
u_char cs_creg[16]; /* current values */
u_char cs_preg[16]; /* pending values */
int cs_heldchange; /* change pending (creg != preg) */
u_char cs_rr0; /* last rr0 processed */
u_char cs_rr0_delta; /* rr0 changes at status intr. */
u_char cs_rr0_dcd; /* which bit to read as DCD */
u_char cs_rr0_cts; /* which bit to read as CTS */
/* the above is set only while CRTSCTS is enabled. */
u_char cs_wr5_dtr; /* which bit to write as DTR */
u_char cs_wr5_rts; /* which bit to write as RTS */
/* the above is set only while CRTSCTS is enabled. */
char cs_softreq; /* need soft interrupt call */
char cs_pad[1];
/* MD code might define a larger variant of this. */
};
struct zsc_softc {
struct device zsc_dev; /* required first: base device */
struct zs_chanstate *zsc_cs[2]; /* channel A and B soft state */
/* MD code might define a larger variant of this. */
};
struct zsc_attach_args {
int channel; /* two serial channels per zsc */
int hwflags;
};
#define ZS_HWFLAG_CONSOLE 1
#define ZS_HWFLAG_NO_DCD 2 /* Ignore the DCD bit */
#define ZS_HWFLAG_NO_CTS 4 /* Ignore the CTS bit */
#define ZS_HWFLAG_RAW 8 /* advise raw mode */
int zsc_intr_soft __P((void *));
int zsc_intr_hard __P((void *));
void zs_abort __P((struct zs_chanstate *));
void zs_break __P((struct zs_chanstate *, int));
void zs_iflush __P((struct zs_chanstate *));
void zs_loadchannelregs __P((struct zs_chanstate *));
int zs_set_speed __P((struct zs_chanstate *, int));
int zs_set_modes __P((struct zs_chanstate *, int));
u_char zs_read_reg __P((struct zs_chanstate *, u_char));
void zs_write_reg __P((struct zs_chanstate *, u_char, u_char));
u_char zs_read_csr __P((struct zs_chanstate *));
void zs_write_csr __P((struct zs_chanstate *, u_char));
u_char zs_read_data __P((struct zs_chanstate *));
void zs_write_data __P((struct zs_chanstate *, u_char));
extern int zs_major;