1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-18 10:35:55 +00:00

Merge up to rev 1.226 of i386/isa/sio.c

This commit is contained in:
Peter Wemm 1999-04-17 00:37:01 +00:00
parent 8da287cee8
commit c976cd3849
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=45729
2 changed files with 28 additions and 420 deletions

View File

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: sio.c,v 1.221 1999/01/30 12:17:35 phk Exp $
* $Id: sio.c,v 1.222 1999/04/16 21:22:34 peter Exp $
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
* from: i386/isa sio.c,v 1.215
*/
@ -80,6 +80,9 @@
#include <machine/clock.h>
#include <machine/ipl.h>
#ifndef SMP
#include <machine/lock.h>
#endif
#include <machine/resource.h>
#include <isa/sioreg.h>
@ -341,9 +344,6 @@ static timeout_t comwakeup;
static void disc_optim __P((struct tty *tp, struct termios *t,
struct com_s *com));
#ifdef DSI_SOFT_MODEM
static int LoadSoftModem __P((int unit,int base_io, u_long size, u_char *ptr));
#endif /* DSI_SOFT_MODEM */
static char driver_name[] = "sio";
@ -989,12 +989,6 @@ sioattach(dev)
/* attempt to determine UART type */
printf("sio%d: type", unit);
#ifdef DSI_SOFT_MODEM
if((inb(iobase+7) ^ inb(iobase+7)) & 0x80) {
printf(" Digicom Systems, Inc. SoftModem");
goto determined_type;
}
#endif /* DSI_SOFT_MODEM */
#ifdef COM_MULTIPORT
if (!COM_ISMULTIPORT(flags) && !COM_IIR_TXRDYBUG(flags))
@ -1558,7 +1552,6 @@ siointr1(com)
u_char modem_status;
u_char *ioptr;
u_char recv_data;
u_char int_ident;
u_char int_ctl;
u_char int_ctl_new;
@ -1782,34 +1775,6 @@ sioioctl(dev, cmd, data, flag, p)
case TIOCGWINSZ:
bzero(data, sizeof(struct winsize));
return (0);
#ifdef DSI_SOFT_MODEM
/*
* Download micro-code to Digicom modem.
*/
case TIOCDSIMICROCODE:
{
u_long l;
u_char *p,*pi;
pi = (u_char*)(*(caddr_t*)data);
error = copyin(pi,&l,sizeof l);
if(error)
{return error;};
pi += sizeof l;
p = malloc(l,M_TEMP,M_NOWAIT);
if(!p)
{return ENOBUFS;}
error = copyin(pi,p,l);
if(error)
{free(p,M_TEMP); return error;};
if(error = LoadSoftModem(
MINOR_TO_UNIT(mynor),iobase,l,p))
{free(p,M_TEMP); return error;}
free(p,M_TEMP);
return(0);
}
#endif /* DSI_SOFT_MODEM */
default:
return (ENOTTY);
}
@ -2074,11 +2039,9 @@ comparam(tp, t)
int divisor;
u_char dlbh;
u_char dlbl;
int error;
Port_t iobase;
int s;
int unit;
int txtimeout;
/* do historical conversions */
if (t->c_ispeed == 0)
@ -2144,54 +2107,8 @@ comparam(tp, t)
outb(iobase + com_fifo, com->fifo_image);
}
/*
* Some UARTs lock up if the divisor latch registers are selected
* while the UART is doing output (they refuse to transmit anything
* more until given a hard reset). Fix this by stopping filling
* the device buffers and waiting for them to drain. Reading the
* line status port outside of siointr1() might lose some receiver
* error bits, but that is acceptable here.
*/
disable_intr();
retry:
com->state &= ~CS_TTGO;
txtimeout = tp->t_timeout;
enable_intr();
while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
!= (LSR_TSRE | LSR_TXRDY)) {
tp->t_state |= TS_SO_OCOMPLETE;
error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH,
"siotx", hz / 100);
if ( txtimeout != 0
&& (!error || error == EAGAIN)
&& (txtimeout -= hz / 100) <= 0
)
error = EIO;
if (com->gone)
error = ENODEV;
if (error != 0 && error != EAGAIN) {
if (!(tp->t_state & TS_TTSTOP)) {
disable_intr();
com->state |= CS_TTGO;
enable_intr();
}
splx(s);
return (error);
}
}
disable_intr(); /* very important while com_data is hidden */
/*
* XXX - clearing CS_TTGO is not sufficient to stop further output,
* because siopoll() calls comstart() which usually sets it again
* because TS_TTSTOP is clear. Setting TS_TTSTOP would not be
* sufficient, for similar reasons.
*/
if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
!= (LSR_TSRE | LSR_TXRDY))
goto retry;
if (divisor != 0) {
outb(iobase + com_cfcr, cfcr | CFCR_DLAB);
/*
@ -2383,7 +2300,6 @@ siostop(tp, rw)
/* 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);
com->obufs[0].l_queued = FALSE;
@ -2399,7 +2315,6 @@ siostop(tp, rw)
/* 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);
com_events -= (com->iptr - com->ibuf);
@ -2745,6 +2660,9 @@ siocnclose(sp, iobase)
outb(iobase + com_ier, sp->ier);
}
#ifdef __i386__
static
#endif
void
siocnprobe(cp)
struct consdev *cp;
@ -2903,6 +2821,9 @@ siogdbattach(port, speed)
#endif
#ifdef __i386__
static
#endif
void
siocninit(cp)
struct consdev *cp;
@ -2910,6 +2831,9 @@ siocninit(cp)
comconsole = DEV_TO_UNIT(cp->cn_dev);
}
#ifdef __i386__
static
#endif
int
siocncheckc(dev)
dev_t dev;
@ -3002,126 +2926,6 @@ siogdbputc(c)
splx(s);
}
#ifdef DSI_SOFT_MODEM
/*
* The magic code to download microcode to a "Connection 14.4+Fax"
* modem from Digicom Systems Inc. Very magic.
*/
#define DSI_ERROR(str) { ptr = str; goto error; }
static int
LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr)
{
int int_c,int_k;
int data_0188, data_0187;
/*
* First see if it is a DSI SoftModem
*/
if(!((inb(base_io+7) ^ inb(base_io+7)) & 0x80))
return ENODEV;
data_0188 = inb(base_io+4);
data_0187 = inb(base_io+3);
outb(base_io+3,0x80);
outb(base_io+4,0x0C);
outb(base_io+0,0x31);
outb(base_io+1,0x8C);
outb(base_io+7,0x10);
outb(base_io+7,0x19);
if(0x18 != (inb(base_io+7) & 0x1A))
DSI_ERROR("dsp bus not granted");
if(0x01 != (inb(base_io+7) & 0x01)) {
outb(base_io+7,0x18);
outb(base_io+7,0x19);
if(0x01 != (inb(base_io+7) & 0x01))
DSI_ERROR("program mem not granted");
}
int_c = 0;
while(1) {
if(int_c >= 7 || size <= 0x1800)
break;
for(int_k = 0 ; int_k < 0x800; int_k++) {
outb(base_io+0,*ptr++);
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
size -= 0x1800;
int_c++;
}
if(size > 0x1800) {
outb(base_io+7,0x18);
outb(base_io+7,0x19);
if(0x00 != (inb(base_io+7) & 0x01))
DSI_ERROR("program data not granted");
for(int_k = 0 ; int_k < 0x800; int_k++) {
outb(base_io+1,*ptr++);
outb(base_io+2,0);
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
size -= 0x1800;
while(size > 0x1800) {
for(int_k = 0 ; int_k < 0xC00; int_k++) {
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
size -= 0x1800;
}
if(size < 0x1800) {
for(int_k=0;int_k<size/2;int_k++) {
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
}
} else if (size > 0) {
if(int_c == 7) {
outb(base_io+7,0x18);
outb(base_io+7,0x19);
if(0x00 != (inb(base_io+7) & 0x01))
DSI_ERROR("program data not granted");
for(int_k = 0 ; int_k < size/3; int_k++) {
outb(base_io+1,*ptr++);
outb(base_io+2,0);
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
} else {
for(int_k = 0 ; int_k < size/3; int_k++) {
outb(base_io+0,*ptr++);
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
}
}
outb(base_io+7,0x11);
outb(base_io+7,3);
outb(base_io+4,data_0188 & 0xfb);
outb(base_io+3,data_0187);
return 0;
error:
printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr);
outb(base_io+7,0x00); \
outb(base_io+3,data_0187); \
outb(base_io+4,data_0188); \
return EIO;
}
#endif /* DSI_SOFT_MODEM */
/*
* support PnP cards if we are using 'em
@ -3199,7 +3003,7 @@ siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
dev->id_iobase = d.port[0];
dev->id_irq = (1 << d.irq[0]);
dev->id_intr = siointr;
dev->id_ointr = siointr;
dev->id_ri_flags = RI_FAST;
dev->id_drq = -1;

View File

@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: sio.c,v 1.221 1999/01/30 12:17:35 phk Exp $
* $Id: sio.c,v 1.222 1999/04/16 21:22:34 peter Exp $
* from: @(#)com.c 7.5 (Berkeley) 5/16/91
* from: i386/isa sio.c,v 1.215
*/
@ -80,6 +80,9 @@
#include <machine/clock.h>
#include <machine/ipl.h>
#ifndef SMP
#include <machine/lock.h>
#endif
#include <machine/resource.h>
#include <isa/sioreg.h>
@ -341,9 +344,6 @@ static timeout_t comwakeup;
static void disc_optim __P((struct tty *tp, struct termios *t,
struct com_s *com));
#ifdef DSI_SOFT_MODEM
static int LoadSoftModem __P((int unit,int base_io, u_long size, u_char *ptr));
#endif /* DSI_SOFT_MODEM */
static char driver_name[] = "sio";
@ -989,12 +989,6 @@ sioattach(dev)
/* attempt to determine UART type */
printf("sio%d: type", unit);
#ifdef DSI_SOFT_MODEM
if((inb(iobase+7) ^ inb(iobase+7)) & 0x80) {
printf(" Digicom Systems, Inc. SoftModem");
goto determined_type;
}
#endif /* DSI_SOFT_MODEM */
#ifdef COM_MULTIPORT
if (!COM_ISMULTIPORT(flags) && !COM_IIR_TXRDYBUG(flags))
@ -1558,7 +1552,6 @@ siointr1(com)
u_char modem_status;
u_char *ioptr;
u_char recv_data;
u_char int_ident;
u_char int_ctl;
u_char int_ctl_new;
@ -1782,34 +1775,6 @@ sioioctl(dev, cmd, data, flag, p)
case TIOCGWINSZ:
bzero(data, sizeof(struct winsize));
return (0);
#ifdef DSI_SOFT_MODEM
/*
* Download micro-code to Digicom modem.
*/
case TIOCDSIMICROCODE:
{
u_long l;
u_char *p,*pi;
pi = (u_char*)(*(caddr_t*)data);
error = copyin(pi,&l,sizeof l);
if(error)
{return error;};
pi += sizeof l;
p = malloc(l,M_TEMP,M_NOWAIT);
if(!p)
{return ENOBUFS;}
error = copyin(pi,p,l);
if(error)
{free(p,M_TEMP); return error;};
if(error = LoadSoftModem(
MINOR_TO_UNIT(mynor),iobase,l,p))
{free(p,M_TEMP); return error;}
free(p,M_TEMP);
return(0);
}
#endif /* DSI_SOFT_MODEM */
default:
return (ENOTTY);
}
@ -2074,11 +2039,9 @@ comparam(tp, t)
int divisor;
u_char dlbh;
u_char dlbl;
int error;
Port_t iobase;
int s;
int unit;
int txtimeout;
/* do historical conversions */
if (t->c_ispeed == 0)
@ -2144,54 +2107,8 @@ comparam(tp, t)
outb(iobase + com_fifo, com->fifo_image);
}
/*
* Some UARTs lock up if the divisor latch registers are selected
* while the UART is doing output (they refuse to transmit anything
* more until given a hard reset). Fix this by stopping filling
* the device buffers and waiting for them to drain. Reading the
* line status port outside of siointr1() might lose some receiver
* error bits, but that is acceptable here.
*/
disable_intr();
retry:
com->state &= ~CS_TTGO;
txtimeout = tp->t_timeout;
enable_intr();
while ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
!= (LSR_TSRE | LSR_TXRDY)) {
tp->t_state |= TS_SO_OCOMPLETE;
error = ttysleep(tp, TSA_OCOMPLETE(tp), TTIPRI | PCATCH,
"siotx", hz / 100);
if ( txtimeout != 0
&& (!error || error == EAGAIN)
&& (txtimeout -= hz / 100) <= 0
)
error = EIO;
if (com->gone)
error = ENODEV;
if (error != 0 && error != EAGAIN) {
if (!(tp->t_state & TS_TTSTOP)) {
disable_intr();
com->state |= CS_TTGO;
enable_intr();
}
splx(s);
return (error);
}
}
disable_intr(); /* very important while com_data is hidden */
/*
* XXX - clearing CS_TTGO is not sufficient to stop further output,
* because siopoll() calls comstart() which usually sets it again
* because TS_TTSTOP is clear. Setting TS_TTSTOP would not be
* sufficient, for similar reasons.
*/
if ((inb(com->line_status_port) & (LSR_TSRE | LSR_TXRDY))
!= (LSR_TSRE | LSR_TXRDY))
goto retry;
if (divisor != 0) {
outb(iobase + com_cfcr, cfcr | CFCR_DLAB);
/*
@ -2383,7 +2300,6 @@ siostop(tp, rw)
/* 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);
com->obufs[0].l_queued = FALSE;
@ -2399,7 +2315,6 @@ siostop(tp, rw)
/* 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);
com_events -= (com->iptr - com->ibuf);
@ -2745,6 +2660,9 @@ siocnclose(sp, iobase)
outb(iobase + com_ier, sp->ier);
}
#ifdef __i386__
static
#endif
void
siocnprobe(cp)
struct consdev *cp;
@ -2903,6 +2821,9 @@ siogdbattach(port, speed)
#endif
#ifdef __i386__
static
#endif
void
siocninit(cp)
struct consdev *cp;
@ -2910,6 +2831,9 @@ siocninit(cp)
comconsole = DEV_TO_UNIT(cp->cn_dev);
}
#ifdef __i386__
static
#endif
int
siocncheckc(dev)
dev_t dev;
@ -3002,126 +2926,6 @@ siogdbputc(c)
splx(s);
}
#ifdef DSI_SOFT_MODEM
/*
* The magic code to download microcode to a "Connection 14.4+Fax"
* modem from Digicom Systems Inc. Very magic.
*/
#define DSI_ERROR(str) { ptr = str; goto error; }
static int
LoadSoftModem(int unit, int base_io, u_long size, u_char *ptr)
{
int int_c,int_k;
int data_0188, data_0187;
/*
* First see if it is a DSI SoftModem
*/
if(!((inb(base_io+7) ^ inb(base_io+7)) & 0x80))
return ENODEV;
data_0188 = inb(base_io+4);
data_0187 = inb(base_io+3);
outb(base_io+3,0x80);
outb(base_io+4,0x0C);
outb(base_io+0,0x31);
outb(base_io+1,0x8C);
outb(base_io+7,0x10);
outb(base_io+7,0x19);
if(0x18 != (inb(base_io+7) & 0x1A))
DSI_ERROR("dsp bus not granted");
if(0x01 != (inb(base_io+7) & 0x01)) {
outb(base_io+7,0x18);
outb(base_io+7,0x19);
if(0x01 != (inb(base_io+7) & 0x01))
DSI_ERROR("program mem not granted");
}
int_c = 0;
while(1) {
if(int_c >= 7 || size <= 0x1800)
break;
for(int_k = 0 ; int_k < 0x800; int_k++) {
outb(base_io+0,*ptr++);
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
size -= 0x1800;
int_c++;
}
if(size > 0x1800) {
outb(base_io+7,0x18);
outb(base_io+7,0x19);
if(0x00 != (inb(base_io+7) & 0x01))
DSI_ERROR("program data not granted");
for(int_k = 0 ; int_k < 0x800; int_k++) {
outb(base_io+1,*ptr++);
outb(base_io+2,0);
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
size -= 0x1800;
while(size > 0x1800) {
for(int_k = 0 ; int_k < 0xC00; int_k++) {
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
size -= 0x1800;
}
if(size < 0x1800) {
for(int_k=0;int_k<size/2;int_k++) {
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
}
} else if (size > 0) {
if(int_c == 7) {
outb(base_io+7,0x18);
outb(base_io+7,0x19);
if(0x00 != (inb(base_io+7) & 0x01))
DSI_ERROR("program data not granted");
for(int_k = 0 ; int_k < size/3; int_k++) {
outb(base_io+1,*ptr++);
outb(base_io+2,0);
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
} else {
for(int_k = 0 ; int_k < size/3; int_k++) {
outb(base_io+0,*ptr++);
outb(base_io+1,*ptr++);
outb(base_io+2,*ptr++);
}
}
}
outb(base_io+7,0x11);
outb(base_io+7,3);
outb(base_io+4,data_0188 & 0xfb);
outb(base_io+3,data_0187);
return 0;
error:
printf("sio%d: DSI SoftModem microcode load failed: <%s>\n",unit,ptr);
outb(base_io+7,0x00); \
outb(base_io+3,data_0187); \
outb(base_io+4,data_0188); \
return EIO;
}
#endif /* DSI_SOFT_MODEM */
/*
* support PnP cards if we are using 'em
@ -3199,7 +3003,7 @@ siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev)
dev->id_iobase = d.port[0];
dev->id_irq = (1 << d.irq[0]);
dev->id_intr = siointr;
dev->id_ointr = siointr;
dev->id_ri_flags = RI_FAST;
dev->id_drq = -1;