From 160da193e0e8d6b5baeb326880aa3cbc0d6cf654 Mon Sep 17 00:00:00 2001 From: Bruce Evans Date: Wed, 29 Jan 1997 21:50:02 +0000 Subject: [PATCH] Fixes and workarounds for Hayes ESP: - don't uselessly initialize the fifo "DMA" bit at attach time. - initialize the fifo "DMA" bit at open time. Without this, the device interrupts for every character received, reducing input performance to that of an 8250. - don't uselessly initialize the fifo trigger level to 8 (scaled to 256) at attach time. - don't scale the fifo trigger level to 512 bytes. The driver's pseudo- dma buffer has size 256, so it can't handle bursts of size 512 or 256. It should be able to handle the second lowest ftl (2 scaled to 64). - don't reset the fifos in siostop(). Reset triggers a hardware bug involving wedging of the output interrupt bit This workaround unfortunately requires ESP support to be configured. --- sys/dev/sio/sio.c | 32 +++++++++++++++++++++++++------- sys/i386/isa/sio.c | 32 +++++++++++++++++++++++++------- sys/isa/sio.c | 32 +++++++++++++++++++++++++------- 3 files changed, 75 insertions(+), 21 deletions(-) diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c index fe3c204f992..1f091682bba 100644 --- a/sys/dev/sio/sio.c +++ b/sys/dev/sio/sio.c @@ -899,14 +899,15 @@ sioattach(isdp) } #ifdef COM_ESP if (com->esp) { - outb(iobase + com_fifo, - FIFO_DMA_MODE | FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST - | FIFO_RX_MEDH); - - /* Set 16550 compatibility mode. */ + /* + * Set 16550 compatibility mode. + * We don't use the ESP_MODE_SCALE bit to increase the + * fifo trigger levels because we can't handle large + * bursts of input. + * XXX flow control should be set in comparam(), not here. + */ outb(com->esp_port + ESP_CMD1, ESP_SETMODE); - outb(com->esp_port + ESP_CMD2, - ESP_MODE_SCALE | ESP_MODE_RTS | ESP_MODE_FIFO); + outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); /* Set RTS/CTS flow control. */ outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE); @@ -1918,6 +1919,15 @@ comparam(tp, t) */ com->fifo_image = t->c_ospeed <= 4800 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; +#ifdef COM_ESP + /* + * The Hayes ESP card needs the fifo DMA mode bit set + * in compatibility mode. If not, it will interrupt + * for each character received. + */ + if (com->esp) + com->fifo_image |= FIFO_DMA_MODE; +#endif outb(iobase + com_fifo, com->fifo_image); } @@ -2128,6 +2138,10 @@ siostop(tp, rw) disable_intr(); if (rw & FWRITE) { if (com->hasfifo) +#ifdef COM_ESP + /* XXX avoid h/w bug. */ + if (!com->esp) +#endif /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_XMT_RST | com->fifo_image); @@ -2140,6 +2154,10 @@ siostop(tp, rw) } if (rw & FREAD) { if (com->hasfifo) +#ifdef COM_ESP + /* XXX avoid h/w bug. */ + if (!com->esp) +#endif /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_RCV_RST | com->fifo_image); diff --git a/sys/i386/isa/sio.c b/sys/i386/isa/sio.c index fe3c204f992..1f091682bba 100644 --- a/sys/i386/isa/sio.c +++ b/sys/i386/isa/sio.c @@ -899,14 +899,15 @@ sioattach(isdp) } #ifdef COM_ESP if (com->esp) { - outb(iobase + com_fifo, - FIFO_DMA_MODE | FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST - | FIFO_RX_MEDH); - - /* Set 16550 compatibility mode. */ + /* + * Set 16550 compatibility mode. + * We don't use the ESP_MODE_SCALE bit to increase the + * fifo trigger levels because we can't handle large + * bursts of input. + * XXX flow control should be set in comparam(), not here. + */ outb(com->esp_port + ESP_CMD1, ESP_SETMODE); - outb(com->esp_port + ESP_CMD2, - ESP_MODE_SCALE | ESP_MODE_RTS | ESP_MODE_FIFO); + outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); /* Set RTS/CTS flow control. */ outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE); @@ -1918,6 +1919,15 @@ comparam(tp, t) */ com->fifo_image = t->c_ospeed <= 4800 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; +#ifdef COM_ESP + /* + * The Hayes ESP card needs the fifo DMA mode bit set + * in compatibility mode. If not, it will interrupt + * for each character received. + */ + if (com->esp) + com->fifo_image |= FIFO_DMA_MODE; +#endif outb(iobase + com_fifo, com->fifo_image); } @@ -2128,6 +2138,10 @@ siostop(tp, rw) disable_intr(); if (rw & FWRITE) { if (com->hasfifo) +#ifdef COM_ESP + /* XXX avoid h/w bug. */ + if (!com->esp) +#endif /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_XMT_RST | com->fifo_image); @@ -2140,6 +2154,10 @@ siostop(tp, rw) } if (rw & FREAD) { if (com->hasfifo) +#ifdef COM_ESP + /* XXX avoid h/w bug. */ + if (!com->esp) +#endif /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_RCV_RST | com->fifo_image); diff --git a/sys/isa/sio.c b/sys/isa/sio.c index fe3c204f992..1f091682bba 100644 --- a/sys/isa/sio.c +++ b/sys/isa/sio.c @@ -899,14 +899,15 @@ sioattach(isdp) } #ifdef COM_ESP if (com->esp) { - outb(iobase + com_fifo, - FIFO_DMA_MODE | FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST - | FIFO_RX_MEDH); - - /* Set 16550 compatibility mode. */ + /* + * Set 16550 compatibility mode. + * We don't use the ESP_MODE_SCALE bit to increase the + * fifo trigger levels because we can't handle large + * bursts of input. + * XXX flow control should be set in comparam(), not here. + */ outb(com->esp_port + ESP_CMD1, ESP_SETMODE); - outb(com->esp_port + ESP_CMD2, - ESP_MODE_SCALE | ESP_MODE_RTS | ESP_MODE_FIFO); + outb(com->esp_port + ESP_CMD2, ESP_MODE_RTS | ESP_MODE_FIFO); /* Set RTS/CTS flow control. */ outb(com->esp_port + ESP_CMD1, ESP_SETFLOWTYPE); @@ -1918,6 +1919,15 @@ comparam(tp, t) */ com->fifo_image = t->c_ospeed <= 4800 ? FIFO_ENABLE : FIFO_ENABLE | FIFO_RX_HIGH; +#ifdef COM_ESP + /* + * The Hayes ESP card needs the fifo DMA mode bit set + * in compatibility mode. If not, it will interrupt + * for each character received. + */ + if (com->esp) + com->fifo_image |= FIFO_DMA_MODE; +#endif outb(iobase + com_fifo, com->fifo_image); } @@ -2128,6 +2138,10 @@ siostop(tp, rw) disable_intr(); if (rw & FWRITE) { if (com->hasfifo) +#ifdef COM_ESP + /* XXX avoid h/w bug. */ + if (!com->esp) +#endif /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_XMT_RST | com->fifo_image); @@ -2140,6 +2154,10 @@ siostop(tp, rw) } if (rw & FREAD) { if (com->hasfifo) +#ifdef COM_ESP + /* XXX avoid h/w bug. */ + if (!com->esp) +#endif /* XXX does this flush everything? */ outb(com->iobase + com_fifo, FIFO_RCV_RST | com->fifo_image);