mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-12 09:58:36 +00:00
Merged from sys/dev/sio/sio.c revisions from 1.405 to 1.414.
This commit is contained in:
parent
fdd1597b47
commit
6d8fc6bf6f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=120809
@ -182,20 +182,20 @@
|
||||
#define COM_ISMULTIPORT(flags) (0)
|
||||
#endif /* COM_MULTIPORT */
|
||||
|
||||
#define COM_C_IIR_TXRDYBUG 0x80000
|
||||
#define COM_CONSOLE(flags) ((flags) & 0x10)
|
||||
#define COM_FORCECONSOLE(flags) ((flags) & 0x20)
|
||||
#define COM_LLCONSOLE(flags) ((flags) & 0x40)
|
||||
#define COM_DEBUGGER(flags) ((flags) & 0x80)
|
||||
#define COM_LOSESOUTINTS(flags) ((flags) & 0x08)
|
||||
#define COM_NOFIFO(flags) ((flags) & 0x02)
|
||||
#define COM_PPSCTS(flags) ((flags) & 0x10000)
|
||||
#define COM_ST16650A(flags) ((flags) & 0x20000)
|
||||
#define COM_C_NOPROBE (0x40000)
|
||||
#define COM_NOPROBE(flags) ((flags) & COM_C_NOPROBE)
|
||||
#define COM_C_IIR_TXRDYBUG (0x80000)
|
||||
#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
|
||||
#define COM_NOSCR(flags) ((flags) & 0x100000)
|
||||
#define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24)
|
||||
#define COM_FORCECONSOLE(flags) ((flags) & 0x20)
|
||||
#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
|
||||
#define COM_LLCONSOLE(flags) ((flags) & 0x40)
|
||||
#define COM_LOSESOUTINTS(flags) ((flags) & 0x08)
|
||||
#define COM_NOFIFO(flags) ((flags) & 0x02)
|
||||
#define COM_NOPROBE(flags) ((flags) & 0x40000)
|
||||
#define COM_NOSCR(flags) ((flags) & 0x100000)
|
||||
#define COM_PPSCTS(flags) ((flags) & 0x10000)
|
||||
#define COM_ST16650A(flags) ((flags) & 0x20000)
|
||||
#define COM_TI16754(flags) ((flags) & 0x200000)
|
||||
|
||||
#define sio_getreg(com, off) \
|
||||
(bus_space_read_1((com)->bst, (com)->bsh, (off)))
|
||||
@ -254,7 +254,6 @@ struct lbq {
|
||||
|
||||
/* com device structure */
|
||||
struct com_s {
|
||||
u_int flags; /* Copy isa device flags */
|
||||
u_char state; /* miscellaneous flag bits */
|
||||
bool_t active_out; /* nonzero if the callout device is open */
|
||||
u_char cfcr_image; /* copy of value written to CFCR */
|
||||
@ -264,7 +263,6 @@ struct com_s {
|
||||
u_char extra_state; /* more flag bits, separate for order trick */
|
||||
u_char fifo_image; /* copy of value written to FIFO */
|
||||
bool_t hasfifo; /* nonzero for 16550 UARTs */
|
||||
bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */
|
||||
bool_t loses_outints; /* nonzero if device loses output interrupts */
|
||||
u_char mcr_image; /* copy of value written to MCR */
|
||||
#ifdef COM_MULTIPORT
|
||||
@ -274,8 +272,10 @@ struct com_s {
|
||||
bool_t gone; /* hardware disappeared */
|
||||
bool_t poll; /* nonzero if polling is required */
|
||||
bool_t poll_output; /* nonzero if polling for output is required */
|
||||
bool_t st16650a; /* nonzero if Startech 16650A compatible */
|
||||
int unit; /* unit number */
|
||||
int dtr_wait; /* time to hold DTR down on close (* 1/hz) */
|
||||
u_int flags; /* copy of device flags */
|
||||
u_int tx_fifo_size;
|
||||
u_int wopeners; /* # processes waiting for DCD in open() */
|
||||
|
||||
@ -325,11 +325,11 @@ struct com_s {
|
||||
#ifdef COM_ESP
|
||||
Port_t esp_port;
|
||||
#endif
|
||||
Port_t int_ctl_port;
|
||||
Port_t int_id_port;
|
||||
Port_t modem_ctl_port;
|
||||
Port_t line_status_port;
|
||||
Port_t modem_status_port;
|
||||
Port_t intr_ctl_port; /* Ports of IIR register */
|
||||
|
||||
struct tty *tp; /* cross reference */
|
||||
|
||||
@ -784,7 +784,7 @@ siodetach(dev)
|
||||
device_printf(dev, "NULL com in siounload\n");
|
||||
return (0);
|
||||
}
|
||||
com->gone = 1;
|
||||
com->gone = TRUE;
|
||||
for (i = 0 ; i < 6; i++)
|
||||
destroy_dev(com->devs[i]);
|
||||
if (com->irqres) {
|
||||
@ -1172,7 +1172,10 @@ sioprobe(dev, xrid, rclk, noprobe)
|
||||
* it's unlikely to do more than allow the null byte out.
|
||||
*/
|
||||
sio_setreg(com, com_data, 0);
|
||||
DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
|
||||
if (iobase == siocniobase)
|
||||
DELAY((1 + 2) * 1000000 / (comdefaultrate / 10));
|
||||
else
|
||||
DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
|
||||
|
||||
/*
|
||||
* Turn off loopback mode so that the interrupt gate works again
|
||||
@ -1192,30 +1195,37 @@ sioprobe(dev, xrid, rclk, noprobe)
|
||||
sio_setreg(com, com_cfcr, CFCR_8BITS);
|
||||
|
||||
/*
|
||||
* Some pcmcia cards have the "TXRDY bug", so we check everyone
|
||||
* for IIR_TXRDY implementation ( Palido 321s, DC-1S... )
|
||||
* Some PCMCIA cards (Palido 321s, DC-1S, ...) have the "TXRDY bug",
|
||||
* so we probe for a buggy IIR_TXRDY implementation even in the
|
||||
* noprobe case. We don't probe for it in the !noprobe case because
|
||||
* noprobe is always set for PCMCIA cards and the problem is not
|
||||
* known to affect any other cards.
|
||||
*/
|
||||
if (noprobe) {
|
||||
/* Reading IIR register twice */
|
||||
/* Read IIR a few times. */
|
||||
for (fn = 0; fn < 2; fn ++) {
|
||||
DELAY(10000);
|
||||
failures[6] = sio_getreg(com, com_iir);
|
||||
}
|
||||
/* Check IIR_TXRDY clear ? */
|
||||
|
||||
/* IIR_TXRDY should be clear. Is it? */
|
||||
result = 0;
|
||||
if (failures[6] & IIR_TXRDY) {
|
||||
/* No, Double check with clearing IER */
|
||||
/*
|
||||
* No. We seem to have the bug. Does our fix for
|
||||
* it work?
|
||||
*/
|
||||
sio_setreg(com, com_ier, 0);
|
||||
if (sio_getreg(com, com_iir) & IIR_NOPEND) {
|
||||
/* Ok. We discovered TXRDY bug! */
|
||||
/* Yes. We discovered the TXRDY bug! */
|
||||
SET_FLAG(dev, COM_C_IIR_TXRDYBUG);
|
||||
} else {
|
||||
/* Unknown, Just omit this chip.. XXX */
|
||||
/* No. Just fail. XXX */
|
||||
result = ENXIO;
|
||||
sio_setreg(com, com_mcr, 0);
|
||||
}
|
||||
} else {
|
||||
/* OK. this is well-known guys */
|
||||
/* Yes. No bug. */
|
||||
CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
|
||||
}
|
||||
sio_setreg(com, com_ier, 0);
|
||||
@ -1526,21 +1536,21 @@ sioattach(dev, xrid, rclk)
|
||||
bus_addr_t *iat = if_16550a_type[if_type & 0x0f].iat;
|
||||
|
||||
com->data_port = iobase + iat[com_data];
|
||||
com->int_ctl_port = iobase + iat[com_ier];
|
||||
com->int_id_port = iobase + iat[com_iir];
|
||||
com->modem_ctl_port = iobase + iat[com_mcr];
|
||||
com->mcr_image = inb(com->modem_ctl_port);
|
||||
com->line_status_port = iobase + iat[com_lsr];
|
||||
com->modem_status_port = iobase + iat[com_msr];
|
||||
com->intr_ctl_port = iobase + iat[com_ier];
|
||||
}
|
||||
#else /* not PC98 */
|
||||
com->data_port = iobase + com_data;
|
||||
com->int_ctl_port = iobase + com_ier;
|
||||
com->int_id_port = iobase + com_iir;
|
||||
com->modem_ctl_port = iobase + com_mcr;
|
||||
com->mcr_image = inb(com->modem_ctl_port);
|
||||
com->line_status_port = iobase + com_lsr;
|
||||
com->modem_status_port = iobase + com_msr;
|
||||
com->intr_ctl_port = iobase + com_ier;
|
||||
#endif
|
||||
|
||||
#ifdef PC98
|
||||
@ -1635,7 +1645,6 @@ sioattach(dev, xrid, rclk)
|
||||
#endif /* PC98 */
|
||||
sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
|
||||
DELAY(100);
|
||||
com->st16650a = 0;
|
||||
switch (inb(com->int_id_port) & IIR_FIFO_MASK) {
|
||||
case FIFO_RX_LOW:
|
||||
printf(" 16450");
|
||||
@ -1649,22 +1658,9 @@ sioattach(dev, xrid, rclk)
|
||||
case FIFO_RX_HIGH:
|
||||
if (COM_NOFIFO(flags)) {
|
||||
printf(" 16550A fifo disabled");
|
||||
} else {
|
||||
com->hasfifo = TRUE;
|
||||
#ifdef PC98
|
||||
com->tx_fifo_size = 0; /* XXX flag conflicts. */
|
||||
printf(" 16550A");
|
||||
#else
|
||||
if (COM_ST16650A(flags)) {
|
||||
com->st16650a = 1;
|
||||
com->tx_fifo_size = 32;
|
||||
printf(" ST16650A");
|
||||
} else {
|
||||
com->tx_fifo_size = COM_FIFOSIZE(flags);
|
||||
printf(" 16550A");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
com->hasfifo = TRUE;
|
||||
#ifdef PC98
|
||||
if (com->pc98_if_type == COM_IF_RSA98III) {
|
||||
com->tx_fifo_size = 2048;
|
||||
@ -1672,8 +1668,20 @@ sioattach(dev, xrid, rclk)
|
||||
outb(com->rsabase + rsa_ier, 0x00);
|
||||
outb(com->rsabase + rsa_frr, 0x00);
|
||||
}
|
||||
#else
|
||||
if (COM_ST16650A(flags)) {
|
||||
printf(" ST16650A");
|
||||
com->st16650a = TRUE;
|
||||
com->tx_fifo_size = 32;
|
||||
break;
|
||||
}
|
||||
if (COM_TI16754(flags)) {
|
||||
printf(" TI16754");
|
||||
com->tx_fifo_size = 64;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf(" 16550A");
|
||||
#ifdef COM_ESP
|
||||
#ifdef PC98
|
||||
if (com->pc98_if_type == COM_IF_ESP98)
|
||||
@ -1683,15 +1691,19 @@ sioattach(dev, xrid, rclk)
|
||||
com->tx_fifo_size = 1024;
|
||||
break;
|
||||
}
|
||||
if (com->esp != NULL)
|
||||
break;
|
||||
#endif
|
||||
#ifdef PC98
|
||||
com->tx_fifo_size = 16;
|
||||
#else
|
||||
com->tx_fifo_size = COM_FIFOSIZE(flags);
|
||||
if (com->tx_fifo_size == 0)
|
||||
com->tx_fifo_size = 16;
|
||||
else
|
||||
printf(" lookalike with %u bytes FIFO",
|
||||
com->tx_fifo_size);
|
||||
#endif
|
||||
if (!com->st16650a) {
|
||||
if (!com->tx_fifo_size)
|
||||
com->tx_fifo_size = 16;
|
||||
else
|
||||
printf(" lookalike with %d bytes FIFO",
|
||||
com->tx_fifo_size);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1707,7 +1719,7 @@ sioattach(dev, xrid, rclk)
|
||||
#endif
|
||||
|
||||
#ifdef COM_ESP
|
||||
if (com->esp) {
|
||||
if (com->esp != NULL) {
|
||||
/*
|
||||
* Set 16550 compatibility mode.
|
||||
* We don't use the ESP_MODE_SCALE bit to increase the
|
||||
@ -1784,7 +1796,7 @@ determined_type: ;
|
||||
if (unit == comconsole)
|
||||
printf(", console");
|
||||
if (COM_IIR_TXRDYBUG(flags))
|
||||
printf(" with a bogus IIR_TXRDY register");
|
||||
printf(" with a buggy IIR_TXRDY implementation");
|
||||
printf("\n");
|
||||
|
||||
if (sio_fast_ih == NULL) {
|
||||
@ -2019,17 +2031,13 @@ sioopen(dev, flag, mode, td)
|
||||
(void) inb(com->data_port);
|
||||
com->prev_modem_status = com->last_modem_status
|
||||
= inb(com->modem_status_port);
|
||||
if (COM_IIR_TXRDYBUG(com->flags)) {
|
||||
outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
|
||||
| IER_EMSC);
|
||||
} else {
|
||||
outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
|
||||
| IER_ERLS | IER_EMSC);
|
||||
}
|
||||
outb(com->int_ctl_port,
|
||||
IER_ERXRDY | IER_ERLS | IER_EMSC
|
||||
| (COM_IIR_TXRDYBUG(com->flags) ? 0 : IER_ETXRDY));
|
||||
#ifdef PC98
|
||||
if (com->pc98_if_type == COM_IF_RSA98III) {
|
||||
outb(com->rsabase + rsa_ier, 0x1d);
|
||||
outb(com->intr_ctl_port, IER_ERLS | IER_EMSC);
|
||||
outb(com->int_ctl_port, IER_ERLS | IER_EMSC);
|
||||
}
|
||||
#endif
|
||||
#ifdef PC98
|
||||
@ -2327,8 +2335,12 @@ siodivisor(rclk, speed)
|
||||
u_int divisor;
|
||||
int error;
|
||||
|
||||
if (speed == 0 || speed > (ULONG_MAX - 1) / 8)
|
||||
if (speed == 0)
|
||||
return (0);
|
||||
#if UINT_MAX > (ULONG_MAX - 1) / 8
|
||||
if (speed > (ULONG_MAX - 1) / 8)
|
||||
return (0);
|
||||
#endif
|
||||
divisor = (rclk / (8UL * speed) + 1) / 2;
|
||||
if (divisor == 0 || divisor >= 65536)
|
||||
return (0);
|
||||
@ -2570,12 +2582,12 @@ static void
|
||||
siointr1(com)
|
||||
struct com_s *com;
|
||||
{
|
||||
u_char int_ctl;
|
||||
u_char int_ctl_new;
|
||||
u_char line_status;
|
||||
u_char modem_status;
|
||||
u_char *ioptr;
|
||||
u_char recv_data;
|
||||
u_char int_ctl;
|
||||
u_char int_ctl_new;
|
||||
|
||||
#ifdef PC98
|
||||
u_char tmp = 0;
|
||||
@ -2583,8 +2595,13 @@ siointr1(com)
|
||||
int rsa_tx_fifo_size = 0;
|
||||
#endif /* PC98 */
|
||||
|
||||
int_ctl = inb(com->intr_ctl_port);
|
||||
int_ctl_new = int_ctl;
|
||||
if (COM_IIR_TXRDYBUG(com->flags)) {
|
||||
int_ctl = inb(com->int_ctl_port);
|
||||
int_ctl_new = int_ctl;
|
||||
} else {
|
||||
int_ctl = 0;
|
||||
int_ctl_new = 0;
|
||||
}
|
||||
|
||||
while (!com->gone) {
|
||||
#ifdef PC98
|
||||
@ -2854,9 +2871,8 @@ if (com->iptr - com->ibuf == 8)
|
||||
com_int_Tx_enable(com);
|
||||
#endif
|
||||
com->obufq.l_head = ioptr;
|
||||
if (COM_IIR_TXRDYBUG(com->flags)) {
|
||||
if (COM_IIR_TXRDYBUG(com->flags))
|
||||
int_ctl_new = int_ctl | IER_ETXRDY;
|
||||
}
|
||||
if (ioptr >= com->obufq.l_tail) {
|
||||
struct lbq *qp;
|
||||
|
||||
@ -2869,9 +2885,9 @@ if (com->iptr - com->ibuf == 8)
|
||||
com->obufq.l_next = qp;
|
||||
} else {
|
||||
/* output just completed */
|
||||
if (COM_IIR_TXRDYBUG(com->flags)) {
|
||||
int_ctl_new = int_ctl & ~IER_ETXRDY;
|
||||
}
|
||||
if (COM_IIR_TXRDYBUG(com->flags))
|
||||
int_ctl_new = int_ctl
|
||||
& ~IER_ETXRDY;
|
||||
com->state &= ~CS_BUSY;
|
||||
#if defined(PC98)
|
||||
if (IS_8251(com->pc98_if_type) &&
|
||||
@ -2886,16 +2902,21 @@ if (com->iptr - com->ibuf == 8)
|
||||
swi_sched(sio_fast_ih, 0);
|
||||
}
|
||||
}
|
||||
if (COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) {
|
||||
#ifdef PC98
|
||||
if (COM_IIR_TXRDYBUG(com->flags)
|
||||
&& int_ctl != int_ctl_new) {
|
||||
if (com->pc98_if_type == COM_IF_RSA98III) {
|
||||
int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY);
|
||||
outb(com->intr_ctl_port, int_ctl_new);
|
||||
outb(com->int_ctl_port, int_ctl_new);
|
||||
outb(com->rsabase + rsa_ier, 0x1d);
|
||||
} else
|
||||
#endif
|
||||
outb(com->intr_ctl_port, int_ctl_new);
|
||||
outb(com->int_ctl_port, int_ctl_new);
|
||||
}
|
||||
#else
|
||||
if (COM_IIR_TXRDYBUG(com->flags)
|
||||
&& int_ctl != int_ctl_new)
|
||||
outb(com->int_ctl_port, int_ctl_new);
|
||||
#endif
|
||||
}
|
||||
#ifdef PC98
|
||||
else if (line_status & LSR_TXRDY) {
|
||||
@ -3235,6 +3256,7 @@ comparam(tp, t)
|
||||
u_int divisor;
|
||||
u_char dlbh;
|
||||
u_char dlbl;
|
||||
u_char efr_flowbits;
|
||||
int s;
|
||||
int unit;
|
||||
#ifdef PC98
|
||||
@ -3254,20 +3276,12 @@ comparam(tp, t)
|
||||
return (EINVAL);
|
||||
} else {
|
||||
#endif
|
||||
/* do historical conversions */
|
||||
if (t->c_ispeed == 0)
|
||||
t->c_ispeed = t->c_ospeed;
|
||||
|
||||
/* check requested parameters */
|
||||
if (t->c_ospeed == 0)
|
||||
divisor = 0;
|
||||
else {
|
||||
if (t->c_ispeed != t->c_ospeed)
|
||||
return (EINVAL);
|
||||
divisor = siodivisor(com->rclk, t->c_ispeed);
|
||||
if (divisor == 0)
|
||||
return (EINVAL);
|
||||
}
|
||||
if (t->c_ispeed != (t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed))
|
||||
return (EINVAL);
|
||||
divisor = siodivisor(com->rclk, t->c_ispeed);
|
||||
if (divisor == 0)
|
||||
return (EINVAL);
|
||||
#ifdef PC98
|
||||
}
|
||||
#endif
|
||||
@ -3276,13 +3290,13 @@ comparam(tp, t)
|
||||
s = spltty();
|
||||
#ifdef PC98
|
||||
if (IS_8251(com->pc98_if_type)) {
|
||||
if (divisor == 0)
|
||||
if (t->c_ospeed == 0)
|
||||
com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
|
||||
else
|
||||
com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
|
||||
} else
|
||||
#endif
|
||||
if (divisor == 0)
|
||||
if (t->c_ospeed == 0)
|
||||
(void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */
|
||||
else
|
||||
(void)commctl(com, TIOCM_DTR, DMBIS);
|
||||
@ -3312,7 +3326,7 @@ comparam(tp, t)
|
||||
if (cflag & CSTOPB)
|
||||
cfcr |= CFCR_STOPB;
|
||||
|
||||
if (com->hasfifo && divisor != 0) {
|
||||
if (com->hasfifo) {
|
||||
/*
|
||||
* Use a fifo trigger level low enough so that the input
|
||||
* latency from the fifo is less than about 16 msec and
|
||||
@ -3321,13 +3335,13 @@ comparam(tp, t)
|
||||
* protocols shouldn't expect anything better since modem
|
||||
* latencies are larger.
|
||||
*
|
||||
* We have to set the FIFO trigger point such that we
|
||||
* don't overflow it accidently if a serial interrupt
|
||||
* is delayed. At high speeds, FIFO_RX_HIGH does not
|
||||
* leave enough slots free.
|
||||
* The fifo trigger level cannot be set at RX_HIGH for high
|
||||
* speed connections without further work on reducing
|
||||
* interrupt disablement times in other parts of the system,
|
||||
* without producing silo overflow errors.
|
||||
*/
|
||||
com->fifo_image = com->unit == siotsunit ? 0
|
||||
: t->c_ospeed <= 4800
|
||||
: t->c_ispeed <= 4800
|
||||
? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH;
|
||||
#ifdef COM_ESP
|
||||
/*
|
||||
@ -3356,39 +3370,27 @@ comparam(tp, t)
|
||||
com_cflag_and_speed_set(com, cflag, t->c_ospeed);
|
||||
else {
|
||||
#endif
|
||||
if (divisor != 0) {
|
||||
sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
|
||||
/*
|
||||
* Only set the divisor registers if they would change,
|
||||
* since on some 16550 incompatibles (UMC8669F), setting
|
||||
* them while input is arriving them loses sync until
|
||||
* data stops arriving.
|
||||
*/
|
||||
dlbl = divisor & 0xFF;
|
||||
if (sio_getreg(com, com_dlbl) != dlbl)
|
||||
sio_setreg(com, com_dlbl, dlbl);
|
||||
dlbh = divisor >> 8;
|
||||
if (sio_getreg(com, com_dlbh) != dlbh)
|
||||
sio_setreg(com, com_dlbh, dlbh);
|
||||
}
|
||||
|
||||
sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
|
||||
sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
|
||||
/*
|
||||
* Only set the divisor registers if they would change, since on
|
||||
* some 16550 incompatibles (UMC8669F), setting them while input
|
||||
* is arriving loses sync until data stops arriving.
|
||||
*/
|
||||
dlbl = divisor & 0xFF;
|
||||
if (sio_getreg(com, com_dlbl) != dlbl)
|
||||
sio_setreg(com, com_dlbl, dlbl);
|
||||
dlbh = divisor >> 8;
|
||||
if (sio_getreg(com, com_dlbh) != dlbh)
|
||||
sio_setreg(com, com_dlbh, dlbh);
|
||||
#ifdef PC98
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(tp->t_state & TS_TTSTOP))
|
||||
com->state |= CS_TTGO;
|
||||
efr_flowbits = 0;
|
||||
|
||||
if (cflag & CRTS_IFLOW) {
|
||||
#ifndef PC98
|
||||
if (com->st16650a) {
|
||||
sio_setreg(com, com_cfcr, 0xbf);
|
||||
sio_setreg(com, com_fifo,
|
||||
sio_getreg(com, com_fifo) | 0x40);
|
||||
}
|
||||
#endif
|
||||
com->state |= CS_RTS_IFLOW;
|
||||
efr_flowbits |= EFR_AUTORTS;
|
||||
/*
|
||||
* If CS_RTS_IFLOW just changed from off to on, the change
|
||||
* needs to be propagated to MCR_RTS. This isn't urgent,
|
||||
@ -3408,15 +3410,9 @@ comparam(tp, t)
|
||||
outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
|
||||
#else
|
||||
outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
|
||||
if (com->st16650a) {
|
||||
sio_setreg(com, com_cfcr, 0xbf);
|
||||
sio_setreg(com, com_fifo,
|
||||
sio_getreg(com, com_fifo) & ~0x40);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set up state to handle output flow control.
|
||||
* XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
|
||||
@ -3432,49 +3428,35 @@ comparam(tp, t)
|
||||
#endif
|
||||
if (cflag & CCTS_OFLOW) {
|
||||
com->state |= CS_CTS_OFLOW;
|
||||
efr_flowbits |= EFR_AUTOCTS;
|
||||
#ifdef PC98
|
||||
if (IS_8251(com->pc98_if_type)) {
|
||||
if (!(pc98_get_modem_status(com) & TIOCM_CTS))
|
||||
com->state &= ~CS_ODEVREADY;
|
||||
} else {
|
||||
if (com->pc98_if_type == COM_IF_RSA98III) {
|
||||
/* Set automatic flow control mode */
|
||||
outb(com->rsabase + rsa_msr, param | 0x08);
|
||||
} else
|
||||
} else if (com->pc98_if_type == COM_IF_RSA98III) {
|
||||
/* Set automatic flow control mode */
|
||||
outb(com->rsabase + rsa_msr, param | 0x08);
|
||||
} else
|
||||
#endif
|
||||
if (!(com->last_modem_status & MSR_CTS))
|
||||
com->state &= ~CS_ODEVREADY;
|
||||
#ifdef PC98
|
||||
}
|
||||
#else
|
||||
if (com->st16650a) {
|
||||
sio_setreg(com, com_cfcr, 0xbf);
|
||||
sio_setreg(com, com_fifo,
|
||||
sio_getreg(com, com_fifo) | 0x80);
|
||||
}
|
||||
} else {
|
||||
if (com->st16650a) {
|
||||
sio_setreg(com, com_cfcr, 0xbf);
|
||||
sio_setreg(com, com_fifo,
|
||||
sio_getreg(com, com_fifo) & ~0x80);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef PC98
|
||||
if (!IS_8251(com->pc98_if_type))
|
||||
sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
|
||||
#else
|
||||
if (com->st16650a) {
|
||||
sio_setreg(com, com_lcr, LCR_EFR_ENABLE);
|
||||
sio_setreg(com, com_efr,
|
||||
(sio_getreg(com, com_efr)
|
||||
& ~(EFR_AUTOCTS | EFR_AUTORTS)) | efr_flowbits);
|
||||
}
|
||||
sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
|
||||
#endif
|
||||
sio_setreg(com, com_cfcr, com->cfcr_image);
|
||||
|
||||
/* XXX shouldn't call functions while intrs are disabled. */
|
||||
disc_optim(tp, t, com);
|
||||
/*
|
||||
* Recover from fiddling with CS_TTGO. We used to call siointr1()
|
||||
* unconditionally, but that defeated the careful discarding of
|
||||
* stale input in sioopen().
|
||||
*/
|
||||
if (com->state >= (CS_BUSY | CS_TTGO))
|
||||
siointr1(com);
|
||||
|
||||
mtx_unlock_spin(&sio_lock);
|
||||
splx(s);
|
||||
@ -4158,6 +4140,7 @@ siocnprobe(cp)
|
||||
|
||||
for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */
|
||||
int flags;
|
||||
|
||||
if (resource_disabled("sio", unit))
|
||||
continue;
|
||||
if (resource_int_value("sio", unit, "flags", &flags))
|
||||
|
@ -182,20 +182,20 @@
|
||||
#define COM_ISMULTIPORT(flags) (0)
|
||||
#endif /* COM_MULTIPORT */
|
||||
|
||||
#define COM_C_IIR_TXRDYBUG 0x80000
|
||||
#define COM_CONSOLE(flags) ((flags) & 0x10)
|
||||
#define COM_FORCECONSOLE(flags) ((flags) & 0x20)
|
||||
#define COM_LLCONSOLE(flags) ((flags) & 0x40)
|
||||
#define COM_DEBUGGER(flags) ((flags) & 0x80)
|
||||
#define COM_LOSESOUTINTS(flags) ((flags) & 0x08)
|
||||
#define COM_NOFIFO(flags) ((flags) & 0x02)
|
||||
#define COM_PPSCTS(flags) ((flags) & 0x10000)
|
||||
#define COM_ST16650A(flags) ((flags) & 0x20000)
|
||||
#define COM_C_NOPROBE (0x40000)
|
||||
#define COM_NOPROBE(flags) ((flags) & COM_C_NOPROBE)
|
||||
#define COM_C_IIR_TXRDYBUG (0x80000)
|
||||
#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
|
||||
#define COM_NOSCR(flags) ((flags) & 0x100000)
|
||||
#define COM_FIFOSIZE(flags) (((flags) & 0xff000000) >> 24)
|
||||
#define COM_FORCECONSOLE(flags) ((flags) & 0x20)
|
||||
#define COM_IIR_TXRDYBUG(flags) ((flags) & COM_C_IIR_TXRDYBUG)
|
||||
#define COM_LLCONSOLE(flags) ((flags) & 0x40)
|
||||
#define COM_LOSESOUTINTS(flags) ((flags) & 0x08)
|
||||
#define COM_NOFIFO(flags) ((flags) & 0x02)
|
||||
#define COM_NOPROBE(flags) ((flags) & 0x40000)
|
||||
#define COM_NOSCR(flags) ((flags) & 0x100000)
|
||||
#define COM_PPSCTS(flags) ((flags) & 0x10000)
|
||||
#define COM_ST16650A(flags) ((flags) & 0x20000)
|
||||
#define COM_TI16754(flags) ((flags) & 0x200000)
|
||||
|
||||
#define sio_getreg(com, off) \
|
||||
(bus_space_read_1((com)->bst, (com)->bsh, (off)))
|
||||
@ -254,7 +254,6 @@ struct lbq {
|
||||
|
||||
/* com device structure */
|
||||
struct com_s {
|
||||
u_int flags; /* Copy isa device flags */
|
||||
u_char state; /* miscellaneous flag bits */
|
||||
bool_t active_out; /* nonzero if the callout device is open */
|
||||
u_char cfcr_image; /* copy of value written to CFCR */
|
||||
@ -264,7 +263,6 @@ struct com_s {
|
||||
u_char extra_state; /* more flag bits, separate for order trick */
|
||||
u_char fifo_image; /* copy of value written to FIFO */
|
||||
bool_t hasfifo; /* nonzero for 16550 UARTs */
|
||||
bool_t st16650a; /* Is a Startech 16650A or RTS/CTS compat */
|
||||
bool_t loses_outints; /* nonzero if device loses output interrupts */
|
||||
u_char mcr_image; /* copy of value written to MCR */
|
||||
#ifdef COM_MULTIPORT
|
||||
@ -274,8 +272,10 @@ struct com_s {
|
||||
bool_t gone; /* hardware disappeared */
|
||||
bool_t poll; /* nonzero if polling is required */
|
||||
bool_t poll_output; /* nonzero if polling for output is required */
|
||||
bool_t st16650a; /* nonzero if Startech 16650A compatible */
|
||||
int unit; /* unit number */
|
||||
int dtr_wait; /* time to hold DTR down on close (* 1/hz) */
|
||||
u_int flags; /* copy of device flags */
|
||||
u_int tx_fifo_size;
|
||||
u_int wopeners; /* # processes waiting for DCD in open() */
|
||||
|
||||
@ -325,11 +325,11 @@ struct com_s {
|
||||
#ifdef COM_ESP
|
||||
Port_t esp_port;
|
||||
#endif
|
||||
Port_t int_ctl_port;
|
||||
Port_t int_id_port;
|
||||
Port_t modem_ctl_port;
|
||||
Port_t line_status_port;
|
||||
Port_t modem_status_port;
|
||||
Port_t intr_ctl_port; /* Ports of IIR register */
|
||||
|
||||
struct tty *tp; /* cross reference */
|
||||
|
||||
@ -784,7 +784,7 @@ siodetach(dev)
|
||||
device_printf(dev, "NULL com in siounload\n");
|
||||
return (0);
|
||||
}
|
||||
com->gone = 1;
|
||||
com->gone = TRUE;
|
||||
for (i = 0 ; i < 6; i++)
|
||||
destroy_dev(com->devs[i]);
|
||||
if (com->irqres) {
|
||||
@ -1172,7 +1172,10 @@ sioprobe(dev, xrid, rclk, noprobe)
|
||||
* it's unlikely to do more than allow the null byte out.
|
||||
*/
|
||||
sio_setreg(com, com_data, 0);
|
||||
DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
|
||||
if (iobase == siocniobase)
|
||||
DELAY((1 + 2) * 1000000 / (comdefaultrate / 10));
|
||||
else
|
||||
DELAY((1 + 2) * 1000000 / (SIO_TEST_SPEED / 10));
|
||||
|
||||
/*
|
||||
* Turn off loopback mode so that the interrupt gate works again
|
||||
@ -1192,30 +1195,37 @@ sioprobe(dev, xrid, rclk, noprobe)
|
||||
sio_setreg(com, com_cfcr, CFCR_8BITS);
|
||||
|
||||
/*
|
||||
* Some pcmcia cards have the "TXRDY bug", so we check everyone
|
||||
* for IIR_TXRDY implementation ( Palido 321s, DC-1S... )
|
||||
* Some PCMCIA cards (Palido 321s, DC-1S, ...) have the "TXRDY bug",
|
||||
* so we probe for a buggy IIR_TXRDY implementation even in the
|
||||
* noprobe case. We don't probe for it in the !noprobe case because
|
||||
* noprobe is always set for PCMCIA cards and the problem is not
|
||||
* known to affect any other cards.
|
||||
*/
|
||||
if (noprobe) {
|
||||
/* Reading IIR register twice */
|
||||
/* Read IIR a few times. */
|
||||
for (fn = 0; fn < 2; fn ++) {
|
||||
DELAY(10000);
|
||||
failures[6] = sio_getreg(com, com_iir);
|
||||
}
|
||||
/* Check IIR_TXRDY clear ? */
|
||||
|
||||
/* IIR_TXRDY should be clear. Is it? */
|
||||
result = 0;
|
||||
if (failures[6] & IIR_TXRDY) {
|
||||
/* No, Double check with clearing IER */
|
||||
/*
|
||||
* No. We seem to have the bug. Does our fix for
|
||||
* it work?
|
||||
*/
|
||||
sio_setreg(com, com_ier, 0);
|
||||
if (sio_getreg(com, com_iir) & IIR_NOPEND) {
|
||||
/* Ok. We discovered TXRDY bug! */
|
||||
/* Yes. We discovered the TXRDY bug! */
|
||||
SET_FLAG(dev, COM_C_IIR_TXRDYBUG);
|
||||
} else {
|
||||
/* Unknown, Just omit this chip.. XXX */
|
||||
/* No. Just fail. XXX */
|
||||
result = ENXIO;
|
||||
sio_setreg(com, com_mcr, 0);
|
||||
}
|
||||
} else {
|
||||
/* OK. this is well-known guys */
|
||||
/* Yes. No bug. */
|
||||
CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
|
||||
}
|
||||
sio_setreg(com, com_ier, 0);
|
||||
@ -1526,21 +1536,21 @@ sioattach(dev, xrid, rclk)
|
||||
bus_addr_t *iat = if_16550a_type[if_type & 0x0f].iat;
|
||||
|
||||
com->data_port = iobase + iat[com_data];
|
||||
com->int_ctl_port = iobase + iat[com_ier];
|
||||
com->int_id_port = iobase + iat[com_iir];
|
||||
com->modem_ctl_port = iobase + iat[com_mcr];
|
||||
com->mcr_image = inb(com->modem_ctl_port);
|
||||
com->line_status_port = iobase + iat[com_lsr];
|
||||
com->modem_status_port = iobase + iat[com_msr];
|
||||
com->intr_ctl_port = iobase + iat[com_ier];
|
||||
}
|
||||
#else /* not PC98 */
|
||||
com->data_port = iobase + com_data;
|
||||
com->int_ctl_port = iobase + com_ier;
|
||||
com->int_id_port = iobase + com_iir;
|
||||
com->modem_ctl_port = iobase + com_mcr;
|
||||
com->mcr_image = inb(com->modem_ctl_port);
|
||||
com->line_status_port = iobase + com_lsr;
|
||||
com->modem_status_port = iobase + com_msr;
|
||||
com->intr_ctl_port = iobase + com_ier;
|
||||
#endif
|
||||
|
||||
#ifdef PC98
|
||||
@ -1635,7 +1645,6 @@ sioattach(dev, xrid, rclk)
|
||||
#endif /* PC98 */
|
||||
sio_setreg(com, com_fifo, FIFO_ENABLE | FIFO_RX_HIGH);
|
||||
DELAY(100);
|
||||
com->st16650a = 0;
|
||||
switch (inb(com->int_id_port) & IIR_FIFO_MASK) {
|
||||
case FIFO_RX_LOW:
|
||||
printf(" 16450");
|
||||
@ -1649,22 +1658,9 @@ sioattach(dev, xrid, rclk)
|
||||
case FIFO_RX_HIGH:
|
||||
if (COM_NOFIFO(flags)) {
|
||||
printf(" 16550A fifo disabled");
|
||||
} else {
|
||||
com->hasfifo = TRUE;
|
||||
#ifdef PC98
|
||||
com->tx_fifo_size = 0; /* XXX flag conflicts. */
|
||||
printf(" 16550A");
|
||||
#else
|
||||
if (COM_ST16650A(flags)) {
|
||||
com->st16650a = 1;
|
||||
com->tx_fifo_size = 32;
|
||||
printf(" ST16650A");
|
||||
} else {
|
||||
com->tx_fifo_size = COM_FIFOSIZE(flags);
|
||||
printf(" 16550A");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
com->hasfifo = TRUE;
|
||||
#ifdef PC98
|
||||
if (com->pc98_if_type == COM_IF_RSA98III) {
|
||||
com->tx_fifo_size = 2048;
|
||||
@ -1672,8 +1668,20 @@ sioattach(dev, xrid, rclk)
|
||||
outb(com->rsabase + rsa_ier, 0x00);
|
||||
outb(com->rsabase + rsa_frr, 0x00);
|
||||
}
|
||||
#else
|
||||
if (COM_ST16650A(flags)) {
|
||||
printf(" ST16650A");
|
||||
com->st16650a = TRUE;
|
||||
com->tx_fifo_size = 32;
|
||||
break;
|
||||
}
|
||||
if (COM_TI16754(flags)) {
|
||||
printf(" TI16754");
|
||||
com->tx_fifo_size = 64;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf(" 16550A");
|
||||
#ifdef COM_ESP
|
||||
#ifdef PC98
|
||||
if (com->pc98_if_type == COM_IF_ESP98)
|
||||
@ -1683,15 +1691,19 @@ sioattach(dev, xrid, rclk)
|
||||
com->tx_fifo_size = 1024;
|
||||
break;
|
||||
}
|
||||
if (com->esp != NULL)
|
||||
break;
|
||||
#endif
|
||||
#ifdef PC98
|
||||
com->tx_fifo_size = 16;
|
||||
#else
|
||||
com->tx_fifo_size = COM_FIFOSIZE(flags);
|
||||
if (com->tx_fifo_size == 0)
|
||||
com->tx_fifo_size = 16;
|
||||
else
|
||||
printf(" lookalike with %u bytes FIFO",
|
||||
com->tx_fifo_size);
|
||||
#endif
|
||||
if (!com->st16650a) {
|
||||
if (!com->tx_fifo_size)
|
||||
com->tx_fifo_size = 16;
|
||||
else
|
||||
printf(" lookalike with %d bytes FIFO",
|
||||
com->tx_fifo_size);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1707,7 +1719,7 @@ sioattach(dev, xrid, rclk)
|
||||
#endif
|
||||
|
||||
#ifdef COM_ESP
|
||||
if (com->esp) {
|
||||
if (com->esp != NULL) {
|
||||
/*
|
||||
* Set 16550 compatibility mode.
|
||||
* We don't use the ESP_MODE_SCALE bit to increase the
|
||||
@ -1784,7 +1796,7 @@ determined_type: ;
|
||||
if (unit == comconsole)
|
||||
printf(", console");
|
||||
if (COM_IIR_TXRDYBUG(flags))
|
||||
printf(" with a bogus IIR_TXRDY register");
|
||||
printf(" with a buggy IIR_TXRDY implementation");
|
||||
printf("\n");
|
||||
|
||||
if (sio_fast_ih == NULL) {
|
||||
@ -2019,17 +2031,13 @@ sioopen(dev, flag, mode, td)
|
||||
(void) inb(com->data_port);
|
||||
com->prev_modem_status = com->last_modem_status
|
||||
= inb(com->modem_status_port);
|
||||
if (COM_IIR_TXRDYBUG(com->flags)) {
|
||||
outb(com->intr_ctl_port, IER_ERXRDY | IER_ERLS
|
||||
| IER_EMSC);
|
||||
} else {
|
||||
outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
|
||||
| IER_ERLS | IER_EMSC);
|
||||
}
|
||||
outb(com->int_ctl_port,
|
||||
IER_ERXRDY | IER_ERLS | IER_EMSC
|
||||
| (COM_IIR_TXRDYBUG(com->flags) ? 0 : IER_ETXRDY));
|
||||
#ifdef PC98
|
||||
if (com->pc98_if_type == COM_IF_RSA98III) {
|
||||
outb(com->rsabase + rsa_ier, 0x1d);
|
||||
outb(com->intr_ctl_port, IER_ERLS | IER_EMSC);
|
||||
outb(com->int_ctl_port, IER_ERLS | IER_EMSC);
|
||||
}
|
||||
#endif
|
||||
#ifdef PC98
|
||||
@ -2327,8 +2335,12 @@ siodivisor(rclk, speed)
|
||||
u_int divisor;
|
||||
int error;
|
||||
|
||||
if (speed == 0 || speed > (ULONG_MAX - 1) / 8)
|
||||
if (speed == 0)
|
||||
return (0);
|
||||
#if UINT_MAX > (ULONG_MAX - 1) / 8
|
||||
if (speed > (ULONG_MAX - 1) / 8)
|
||||
return (0);
|
||||
#endif
|
||||
divisor = (rclk / (8UL * speed) + 1) / 2;
|
||||
if (divisor == 0 || divisor >= 65536)
|
||||
return (0);
|
||||
@ -2570,12 +2582,12 @@ static void
|
||||
siointr1(com)
|
||||
struct com_s *com;
|
||||
{
|
||||
u_char int_ctl;
|
||||
u_char int_ctl_new;
|
||||
u_char line_status;
|
||||
u_char modem_status;
|
||||
u_char *ioptr;
|
||||
u_char recv_data;
|
||||
u_char int_ctl;
|
||||
u_char int_ctl_new;
|
||||
|
||||
#ifdef PC98
|
||||
u_char tmp = 0;
|
||||
@ -2583,8 +2595,13 @@ siointr1(com)
|
||||
int rsa_tx_fifo_size = 0;
|
||||
#endif /* PC98 */
|
||||
|
||||
int_ctl = inb(com->intr_ctl_port);
|
||||
int_ctl_new = int_ctl;
|
||||
if (COM_IIR_TXRDYBUG(com->flags)) {
|
||||
int_ctl = inb(com->int_ctl_port);
|
||||
int_ctl_new = int_ctl;
|
||||
} else {
|
||||
int_ctl = 0;
|
||||
int_ctl_new = 0;
|
||||
}
|
||||
|
||||
while (!com->gone) {
|
||||
#ifdef PC98
|
||||
@ -2854,9 +2871,8 @@ if (com->iptr - com->ibuf == 8)
|
||||
com_int_Tx_enable(com);
|
||||
#endif
|
||||
com->obufq.l_head = ioptr;
|
||||
if (COM_IIR_TXRDYBUG(com->flags)) {
|
||||
if (COM_IIR_TXRDYBUG(com->flags))
|
||||
int_ctl_new = int_ctl | IER_ETXRDY;
|
||||
}
|
||||
if (ioptr >= com->obufq.l_tail) {
|
||||
struct lbq *qp;
|
||||
|
||||
@ -2869,9 +2885,9 @@ if (com->iptr - com->ibuf == 8)
|
||||
com->obufq.l_next = qp;
|
||||
} else {
|
||||
/* output just completed */
|
||||
if (COM_IIR_TXRDYBUG(com->flags)) {
|
||||
int_ctl_new = int_ctl & ~IER_ETXRDY;
|
||||
}
|
||||
if (COM_IIR_TXRDYBUG(com->flags))
|
||||
int_ctl_new = int_ctl
|
||||
& ~IER_ETXRDY;
|
||||
com->state &= ~CS_BUSY;
|
||||
#if defined(PC98)
|
||||
if (IS_8251(com->pc98_if_type) &&
|
||||
@ -2886,16 +2902,21 @@ if (com->iptr - com->ibuf == 8)
|
||||
swi_sched(sio_fast_ih, 0);
|
||||
}
|
||||
}
|
||||
if (COM_IIR_TXRDYBUG(com->flags) && (int_ctl != int_ctl_new)) {
|
||||
#ifdef PC98
|
||||
if (COM_IIR_TXRDYBUG(com->flags)
|
||||
&& int_ctl != int_ctl_new) {
|
||||
if (com->pc98_if_type == COM_IF_RSA98III) {
|
||||
int_ctl_new &= ~(IER_ETXRDY | IER_ERXRDY);
|
||||
outb(com->intr_ctl_port, int_ctl_new);
|
||||
outb(com->int_ctl_port, int_ctl_new);
|
||||
outb(com->rsabase + rsa_ier, 0x1d);
|
||||
} else
|
||||
#endif
|
||||
outb(com->intr_ctl_port, int_ctl_new);
|
||||
outb(com->int_ctl_port, int_ctl_new);
|
||||
}
|
||||
#else
|
||||
if (COM_IIR_TXRDYBUG(com->flags)
|
||||
&& int_ctl != int_ctl_new)
|
||||
outb(com->int_ctl_port, int_ctl_new);
|
||||
#endif
|
||||
}
|
||||
#ifdef PC98
|
||||
else if (line_status & LSR_TXRDY) {
|
||||
@ -3235,6 +3256,7 @@ comparam(tp, t)
|
||||
u_int divisor;
|
||||
u_char dlbh;
|
||||
u_char dlbl;
|
||||
u_char efr_flowbits;
|
||||
int s;
|
||||
int unit;
|
||||
#ifdef PC98
|
||||
@ -3254,20 +3276,12 @@ comparam(tp, t)
|
||||
return (EINVAL);
|
||||
} else {
|
||||
#endif
|
||||
/* do historical conversions */
|
||||
if (t->c_ispeed == 0)
|
||||
t->c_ispeed = t->c_ospeed;
|
||||
|
||||
/* check requested parameters */
|
||||
if (t->c_ospeed == 0)
|
||||
divisor = 0;
|
||||
else {
|
||||
if (t->c_ispeed != t->c_ospeed)
|
||||
return (EINVAL);
|
||||
divisor = siodivisor(com->rclk, t->c_ispeed);
|
||||
if (divisor == 0)
|
||||
return (EINVAL);
|
||||
}
|
||||
if (t->c_ispeed != (t->c_ospeed != 0 ? t->c_ospeed : tp->t_ospeed))
|
||||
return (EINVAL);
|
||||
divisor = siodivisor(com->rclk, t->c_ispeed);
|
||||
if (divisor == 0)
|
||||
return (EINVAL);
|
||||
#ifdef PC98
|
||||
}
|
||||
#endif
|
||||
@ -3276,13 +3290,13 @@ comparam(tp, t)
|
||||
s = spltty();
|
||||
#ifdef PC98
|
||||
if (IS_8251(com->pc98_if_type)) {
|
||||
if (divisor == 0)
|
||||
if (t->c_ospeed == 0)
|
||||
com_tiocm_bic(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
|
||||
else
|
||||
com_tiocm_bis(com, TIOCM_DTR|TIOCM_RTS|TIOCM_LE);
|
||||
} else
|
||||
#endif
|
||||
if (divisor == 0)
|
||||
if (t->c_ospeed == 0)
|
||||
(void)commctl(com, TIOCM_DTR, DMBIC); /* hang up line */
|
||||
else
|
||||
(void)commctl(com, TIOCM_DTR, DMBIS);
|
||||
@ -3312,7 +3326,7 @@ comparam(tp, t)
|
||||
if (cflag & CSTOPB)
|
||||
cfcr |= CFCR_STOPB;
|
||||
|
||||
if (com->hasfifo && divisor != 0) {
|
||||
if (com->hasfifo) {
|
||||
/*
|
||||
* Use a fifo trigger level low enough so that the input
|
||||
* latency from the fifo is less than about 16 msec and
|
||||
@ -3321,13 +3335,13 @@ comparam(tp, t)
|
||||
* protocols shouldn't expect anything better since modem
|
||||
* latencies are larger.
|
||||
*
|
||||
* We have to set the FIFO trigger point such that we
|
||||
* don't overflow it accidently if a serial interrupt
|
||||
* is delayed. At high speeds, FIFO_RX_HIGH does not
|
||||
* leave enough slots free.
|
||||
* The fifo trigger level cannot be set at RX_HIGH for high
|
||||
* speed connections without further work on reducing
|
||||
* interrupt disablement times in other parts of the system,
|
||||
* without producing silo overflow errors.
|
||||
*/
|
||||
com->fifo_image = com->unit == siotsunit ? 0
|
||||
: t->c_ospeed <= 4800
|
||||
: t->c_ispeed <= 4800
|
||||
? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_MEDH;
|
||||
#ifdef COM_ESP
|
||||
/*
|
||||
@ -3356,39 +3370,27 @@ comparam(tp, t)
|
||||
com_cflag_and_speed_set(com, cflag, t->c_ospeed);
|
||||
else {
|
||||
#endif
|
||||
if (divisor != 0) {
|
||||
sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
|
||||
/*
|
||||
* Only set the divisor registers if they would change,
|
||||
* since on some 16550 incompatibles (UMC8669F), setting
|
||||
* them while input is arriving them loses sync until
|
||||
* data stops arriving.
|
||||
*/
|
||||
dlbl = divisor & 0xFF;
|
||||
if (sio_getreg(com, com_dlbl) != dlbl)
|
||||
sio_setreg(com, com_dlbl, dlbl);
|
||||
dlbh = divisor >> 8;
|
||||
if (sio_getreg(com, com_dlbh) != dlbh)
|
||||
sio_setreg(com, com_dlbh, dlbh);
|
||||
}
|
||||
|
||||
sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
|
||||
sio_setreg(com, com_cfcr, cfcr | CFCR_DLAB);
|
||||
/*
|
||||
* Only set the divisor registers if they would change, since on
|
||||
* some 16550 incompatibles (UMC8669F), setting them while input
|
||||
* is arriving loses sync until data stops arriving.
|
||||
*/
|
||||
dlbl = divisor & 0xFF;
|
||||
if (sio_getreg(com, com_dlbl) != dlbl)
|
||||
sio_setreg(com, com_dlbl, dlbl);
|
||||
dlbh = divisor >> 8;
|
||||
if (sio_getreg(com, com_dlbh) != dlbh)
|
||||
sio_setreg(com, com_dlbh, dlbh);
|
||||
#ifdef PC98
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(tp->t_state & TS_TTSTOP))
|
||||
com->state |= CS_TTGO;
|
||||
efr_flowbits = 0;
|
||||
|
||||
if (cflag & CRTS_IFLOW) {
|
||||
#ifndef PC98
|
||||
if (com->st16650a) {
|
||||
sio_setreg(com, com_cfcr, 0xbf);
|
||||
sio_setreg(com, com_fifo,
|
||||
sio_getreg(com, com_fifo) | 0x40);
|
||||
}
|
||||
#endif
|
||||
com->state |= CS_RTS_IFLOW;
|
||||
efr_flowbits |= EFR_AUTORTS;
|
||||
/*
|
||||
* If CS_RTS_IFLOW just changed from off to on, the change
|
||||
* needs to be propagated to MCR_RTS. This isn't urgent,
|
||||
@ -3408,15 +3410,9 @@ comparam(tp, t)
|
||||
outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
|
||||
#else
|
||||
outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
|
||||
if (com->st16650a) {
|
||||
sio_setreg(com, com_cfcr, 0xbf);
|
||||
sio_setreg(com, com_fifo,
|
||||
sio_getreg(com, com_fifo) & ~0x40);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set up state to handle output flow control.
|
||||
* XXX - worth handling MDMBUF (DCD) flow control at the lowest level?
|
||||
@ -3432,49 +3428,35 @@ comparam(tp, t)
|
||||
#endif
|
||||
if (cflag & CCTS_OFLOW) {
|
||||
com->state |= CS_CTS_OFLOW;
|
||||
efr_flowbits |= EFR_AUTOCTS;
|
||||
#ifdef PC98
|
||||
if (IS_8251(com->pc98_if_type)) {
|
||||
if (!(pc98_get_modem_status(com) & TIOCM_CTS))
|
||||
com->state &= ~CS_ODEVREADY;
|
||||
} else {
|
||||
if (com->pc98_if_type == COM_IF_RSA98III) {
|
||||
/* Set automatic flow control mode */
|
||||
outb(com->rsabase + rsa_msr, param | 0x08);
|
||||
} else
|
||||
} else if (com->pc98_if_type == COM_IF_RSA98III) {
|
||||
/* Set automatic flow control mode */
|
||||
outb(com->rsabase + rsa_msr, param | 0x08);
|
||||
} else
|
||||
#endif
|
||||
if (!(com->last_modem_status & MSR_CTS))
|
||||
com->state &= ~CS_ODEVREADY;
|
||||
#ifdef PC98
|
||||
}
|
||||
#else
|
||||
if (com->st16650a) {
|
||||
sio_setreg(com, com_cfcr, 0xbf);
|
||||
sio_setreg(com, com_fifo,
|
||||
sio_getreg(com, com_fifo) | 0x80);
|
||||
}
|
||||
} else {
|
||||
if (com->st16650a) {
|
||||
sio_setreg(com, com_cfcr, 0xbf);
|
||||
sio_setreg(com, com_fifo,
|
||||
sio_getreg(com, com_fifo) & ~0x80);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef PC98
|
||||
if (!IS_8251(com->pc98_if_type))
|
||||
sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
|
||||
#else
|
||||
if (com->st16650a) {
|
||||
sio_setreg(com, com_lcr, LCR_EFR_ENABLE);
|
||||
sio_setreg(com, com_efr,
|
||||
(sio_getreg(com, com_efr)
|
||||
& ~(EFR_AUTOCTS | EFR_AUTORTS)) | efr_flowbits);
|
||||
}
|
||||
sio_setreg(com, com_cfcr, com->cfcr_image = cfcr);
|
||||
#endif
|
||||
sio_setreg(com, com_cfcr, com->cfcr_image);
|
||||
|
||||
/* XXX shouldn't call functions while intrs are disabled. */
|
||||
disc_optim(tp, t, com);
|
||||
/*
|
||||
* Recover from fiddling with CS_TTGO. We used to call siointr1()
|
||||
* unconditionally, but that defeated the careful discarding of
|
||||
* stale input in sioopen().
|
||||
*/
|
||||
if (com->state >= (CS_BUSY | CS_TTGO))
|
||||
siointr1(com);
|
||||
|
||||
mtx_unlock_spin(&sio_lock);
|
||||
splx(s);
|
||||
@ -4158,6 +4140,7 @@ siocnprobe(cp)
|
||||
|
||||
for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */
|
||||
int flags;
|
||||
|
||||
if (resource_disabled("sio", unit))
|
||||
continue;
|
||||
if (resource_int_value("sio", unit, "flags", &flags))
|
||||
|
Loading…
Reference in New Issue
Block a user