diff options
author | amurai <amurai@FreeBSD.org> | 1998-01-08 04:53:43 +0000 |
---|---|---|
committer | amurai <amurai@FreeBSD.org> | 1998-01-08 04:53:43 +0000 |
commit | 6c81cb515e7e148d0c45813affa89a8a464a3a50 (patch) | |
tree | 4f85577e038ae7694ba7e94359fd5669c86826ef /sys/dev/sio | |
parent | 35f59936c3cbf51c3f961b2cf754a13f5d40359e (diff) | |
download | FreeBSD-src-6c81cb515e7e148d0c45813affa89a8a464a3a50.zip FreeBSD-src-6c81cb515e7e148d0c45813affa89a8a464a3a50.tar.gz |
1. Supporting a bogus 16550A compatible PCMCIA CARD stuffs
- IIR_TXRDY is never off even if reading a IIR register.
- Know as PIAFS "Palido 321S", "DC-*S" oemed by Sharp corp.
2. Omiting a restrict probing if it's already probed by pccardd.
Note: Define a new id_flags as follows
0x40000 - NO PROBE (Already probed as serial)
0x80000 - Has a bogus IIR_TXRDY register
Sato Junichi <junichi@astec.co.jp>
Nrihiro Kumagai <kuma@slab.tnr.sharp.co.jp>
Hirao Tetsuya <ai.cs.fujitsu.co.jp>
Toshiharu Asai <asai@mbc.infoshere.or.jp>
Shin'ya Kumabuchi <kumabu@t3.rim.or.jp>
Freebsd-users-jp@jp.freebsd.org
bsd-nomads@ai.cs.fujitsu.co.jp
Diffstat (limited to 'sys/dev/sio')
-rw-r--r-- | sys/dev/sio/sio.c | 75 |
1 files changed, 71 insertions, 4 deletions
diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c index 5bf2968..8c9b71d 100644 --- a/sys/dev/sio/sio.c +++ b/sys/dev/sio/sio.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)com.c 7.5 (Berkeley) 5/16/91 - * $Id: sio.c,v 1.192 1997/12/28 06:20:47 bde Exp $ + * $Id: sio.c,v 1.193 1997/12/28 06:36:35 bde Exp $ */ #include "opt_comconsole.h" @@ -143,6 +143,10 @@ #define COM_VERBOSE(dev) ((dev)->id_flags & 0x80) #define COM_NOTST3(dev) ((dev)->id_flags & 0x10000) #define COM_ST16650A(dev) ((dev)->id_flags & 0x20000) +#define COM_C_NOPROBE (0x40000) +#define COM_NOPROBE(dev) ((dev)->id_flags & COM_C_NOPROBE) +#define COM_C_IIR_TXRDYBUG (0x80000) +#define COM_IIR_TXRDYBUG(dev) ((dev)->id_flags & COM_C_IIR_TXRDYBUG) #define COM_FIFOSIZE(dev) (((dev)->id_flags & 0xff000000) >> 24) #define com_scr 7 /* scratch register for 16450-16550 (R/W) */ @@ -211,6 +215,7 @@ struct lbq { /* com device structure */ struct com_s { + u_int id_flags; /* Copy isa device falgas */ 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 */ @@ -262,6 +267,7 @@ struct com_s { 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 */ @@ -504,6 +510,10 @@ sioinit(struct pccard_devinfo *devi) /* Make sure it isn't already probed. */ if (com_addr(devi->isahd.id_unit)) return(EBUSY); + + /* It's already probed as serial by Upper */ + devi->isahd.id_flags |= COM_C_NOPROBE; + /* * Probe the device. If a value is returned, the * device was found at the location. @@ -705,6 +715,37 @@ sioprobe(dev) /* EXTRA DELAY? */ outb(iobase + com_mcr, mcr_image); + /* + * It's a definitly Serial PCMCIA(16550A), but still be required + * for IIR_TXRDY implementation ( Palido 321s, DC-1S... ) + */ + if ( COM_NOPROBE(dev) ) { + /* Reading IIR register twice */ + for ( fn = 0; fn < 2; fn ++ ) { + DELAY(10000); + failures[6] = inb(iobase + com_iir); + } + /* Check IIR_TXRDY clear ? */ + result = IO_COMSIZE; + if ( failures[6] & IIR_TXRDY ) { + /* Nop, Double check with clearing IER */ + outb(iobase + com_ier, 0); + if ( inb(iobase + com_iir) & IIR_NOPEND ) { + /* Ok. we're familia this gang */ + dev->id_flags |= COM_C_IIR_TXRDYBUG; /* Set IIR_TXRDYBUG */ + } else { + /* Unknow, Just omit this chip.. XXX*/ + result = 0; + } + } else { + /* OK. this is well-known guys */ + dev->id_flags &= ~COM_C_IIR_TXRDYBUG; /*Clear IIR_TXRDYBUG*/ + } + outb(iobase + com_cfcr, CFCR_8BITS); + enable_intr(); + return( result ); + } + /* * Check that * o the CFCR, IER and MCR in UART hold the values written to them @@ -875,6 +916,7 @@ sioattach(isdp) 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; /* * We don't use all the flags from <sys/ttydefaults.h> since they @@ -911,7 +953,9 @@ sioattach(isdp) #endif /* DSI_SOFT_MODEM */ #ifdef COM_MULTIPORT - if (!COM_ISMULTIPORT(isdp)) + if (!COM_ISMULTIPORT(isdp) && !COM_IIR_TXRDYBUG(isdp)) +#else + if (!COM_IIR_TXRDYBUG(isdp)) #endif { u_char scr; @@ -1015,6 +1059,8 @@ determined_type: ; #endif /* COM_MULTIPORT */ if (unit == comconsole) printf(", console"); + if ( COM_IIR_TXRDYBUG(isdp) ) + printf(" with a bogus IIR_TXRDY register"); printf("\n"); s = spltty(); @@ -1043,6 +1089,7 @@ determined_type: ; unit | CALLOUT_MASK | CONTROL_LOCK_STATE, DV_CHR, UID_UUCP, GID_DIALER, 0660, "cuala%n", unit); #endif + com->id_flags = isdp->id_flags; /* Heritate id_flags for later */ return (1); } @@ -1182,8 +1229,13 @@ open_top: (void) inb(com->data_port); com->prev_modem_status = com->last_modem_status = inb(com->modem_status_port); - outb(iobase + com_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS - | IER_EMSC); + if (COM_IIR_TXRDYBUG(com)) { + 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); + } enable_intr(); /* * Handle initial DCD. Callout devices get a fake initial @@ -1457,6 +1509,12 @@ 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; + + int_ctl = inb(com->intr_ctl_port); + int_ctl_new = int_ctl; while (TRUE) { line_status = inb(com->line_status_port); @@ -1583,6 +1641,9 @@ cont: ++com->bytes_out; } com->obufq.l_head = ioptr; + if (COM_IIR_TXRDYBUG(com)) { + int_ctl_new = int_ctl | IER_ETXRDY; + } if (ioptr >= com->obufq.l_tail) { struct lbq *qp; @@ -1595,6 +1656,9 @@ cont: com->obufq.l_next = qp; } else { /* output just completed */ + if ( COM_IIR_TXRDYBUG(com) ) { + int_ctl_new = int_ctl & ~IER_ETXRDY; + } com->state &= ~CS_BUSY; } if (!(com->state & CS_ODONE)) { @@ -1603,6 +1667,9 @@ cont: setsofttty(); /* handle at high level ASAP */ } } + if ( COM_IIR_TXRDYBUG(com) && (int_ctl != int_ctl_new)) { + outb(com->intr_ctl_port, int_ctl_new); + } } /* finished? */ |