summaryrefslogtreecommitdiffstats
path: root/sys/i386/isa
diff options
context:
space:
mode:
authorache <ache@FreeBSD.org>1995-06-14 19:37:02 +0000
committerache <ache@FreeBSD.org>1995-06-14 19:37:02 +0000
commit38b4136817368a83634c8339861616489175c107 (patch)
tree9d49653e062061d6e7c358b364d705ed7ad1cbbf /sys/i386/isa
parent27d378a02a571f4c4d2d0056aa5bbe02639f045d (diff)
downloadFreeBSD-src-38b4136817368a83634c8339861616489175c107.zip
FreeBSD-src-38b4136817368a83634c8339861616489175c107.tar.gz
Next version, many bugs fixed
Diffstat (limited to 'sys/i386/isa')
-rw-r--r--sys/i386/isa/ic/cd180.h85
-rw-r--r--sys/i386/isa/rc.c837
-rw-r--r--sys/i386/isa/rcreg.h12
3 files changed, 527 insertions, 407 deletions
diff --git a/sys/i386/isa/ic/cd180.h b/sys/i386/isa/ic/cd180.h
index 6e011c0..5783ebd 100644
--- a/sys/i386/isa/ic/cd180.h
+++ b/sys/i386/isa/ic/cd180.h
@@ -86,48 +86,47 @@
#define RCSR_OE 0x01 /* Overrun Error */
#define RCSR_FE 0x02 /* Frame Error */
#define RCSR_PE 0x04 /* Parity Error */
-#define RCSR_BREAK 0x08 /* Break detected */
-#define RCSR_TOUT 0x80 /* Rx Timeout */
-#define RCSR_SCDET 0x70 /* Special Character Detected Mask */
+#define RCSR_Break 0x08 /* Break detected */
+#define RCSR_Timeout 0x80 /* Rx Timeout */
+#define RCSR_SCMASK 0x70 /* Special Character Detected Mask */
#define RCSR_SC1 0x10 /* Special Char 1 (or 1 & 3 seq matched) */
#define RCSR_SC2 0x20 /* Special Char 2 (or 2 & 4 seq matched) */
#define RCSR_SC3 0x30 /* Special Char 3 */
#define RCSR_SC4 0x40 /* Special Char 4 */
/* Channel Command Register */
-#define CCR_RESETCHAN 0x80 /* Reset Channel */
+#define CCR_ResetChan 0x80 /* Reset Channel */
#define CCR_HWRESET 0x81 /* Hardware Reset (all channels) */
#define CCR_CORCHG1 0x42 /* Channel Option Register 1 Changed */
#define CCR_CORCHG2 0x44 /* Channel Option Register 2 Changed */
#define CCR_CORCHG3 0x48 /* Channel Option Register 3 Changed */
-#define CCR_SSPC1 0x21 /* Send Special Character 1 */
-#define CCR_SSPC2 0x22 /* Send Special Character 2 */
-#define CCR_SSPC3 0x23 /* Send Special Character 3 */
-#define CCR_SSPC4 0x24 /* Send Special Character 4 */
-#define CCR_CHANCTL 0x10 /* Channel Control Command */
-#define CCR_RXDIS 0x11 /* Receiver Disable */
-#define CCR_RXEN 0x12 /* Receiver Enable */
-#define CCR_TXDIS 0x14 /* Transmitter Disable */
-#define CCR_TXEN 0x18 /* Transmitter Enable */
+#define CCR_SENDSPCH1 0x21 /* Send Special Character 1 */
+#define CCR_SENDSPCH2 0x22 /* Send Special Character 2 */
+#define CCR_SENDSPCH3 0x23 /* Send Special Character 3 */
+#define CCR_SENDSPCH4 0x24 /* Send Special Character 4 */
+#define CCR_RCVRDIS 0x11 /* Receiver Disable */
+#define CCR_RCVREN 0x12 /* Receiver Enable */
+#define CCR_XMTRDIS 0x14 /* Transmitter Disable */
+#define CCR_XMTREN 0x18 /* Transmitter Enable */
/* Interrupt Enable Register */
#define IER_DSR 0x80 /* Enable interrupt on DSR change */
#define IER_CD 0x40 /* Enable interrupt on CD change */
#define IER_CTS 0x20 /* Enable interrupt on CTS change */
-#define IER_RXD 0x10 /* Enable interrupt on Receive Data */
-#define IER_RXSC 0x08 /* Enable interrupt on Receive Spec. Char */
-#define IER_TXRDY 0x04 /* Enable interrupt on TX FIFO empty */
-#define IER_TXMPTY 0x02 /* Enable interrupt on TX completely empty*/
+#define IER_RxData 0x10 /* Enable interrupt on Receive Data */
+#define IER_RxSC 0x08 /* Enable interrupt on Receive Spec. Char */
+#define IER_TxRdy 0x04 /* Enable interrupt on TX FIFO empty */
+#define IER_TxMpty 0x02 /* Enable interrupt on TX completely empty*/
#define IER_RET 0x01 /* Enable interrupt on RX Except. Timeout */
/* Channel Option Register 1 */
#define COR1_ODDP 0x80 /* Odd Parity */
-#define COR1_PARMASK 0x60 /* Parity Mode mask */
+#define COR1_ParMMASK 0x60 /* Parity Mode mask */
#define COR1_NOPAR 0x02 /* No Parity */
#define COR1_FORCEPAR 0x20 /* Force Parity */
#define COR1_NORMPAR 0x40 /* Normal Parity */
-#define COR1_IGNORE 0x10 /* Ignore Parity on RX */
-#define COR1_STOPMASK 0x0C /* Stop Bits mode mask */
+#define COR1_Ignore 0x10 /* Ignore Parity on RX */
+#define COR1_StopMASK 0x0C /* Stop Bits mode mask */
#define COR1_1SB 0x00 /* 1 Stop Bit */
#define COR1_15SB 0x04 /* 1.5 Stop Bits */
#define COR1_2SB 0x08 /* 2 Stop Bits */
@@ -139,44 +138,44 @@
/* Channel Option Register 2 */
#define COR2_IXM 0x80 /* Implied XON mode */
-#define COR2_TXIBE 0x40 /* Enable In-Band XON/XOFF Flow Control */
+#define COR2_TxIBE 0x40 /* Enable In-Band XON/XOFF Flow Control */
#define COR2_ETC 0x20 /* Embedded Tx Commands Enable */
#define COR2_LLM 0x10 /* Local Loopback Mode */
#define COR2_RLM 0x08 /* Remote Loopback Mode */
-#define COR2_RTSAO 0x04 /* RTS Automatic Output Enable */
-#define COR2_CTSAE 0x02 /* CTS Automatic Enable */
-#define COR2_DSRAE 0x01 /* DSR Automatic Enable */
+#define COR2_RtsAO 0x04 /* RTS Automatic Output Enable */
+#define COR2_CtsAE 0x02 /* CTS Automatic Enable */
+#define COR2_DsrAE 0x01 /* DSR Automatic Enable */
/* Channel Option Register 3 */
-#define COR3_XONCH 0x80 /* XON is a double seq (1 & 3) */
-#define COR3_XOFFCH 0x40 /* XOFF is a double seq (1 & 3) */
+#define COR3_XonCH 0x80 /* XON is a double seq (1 & 3) */
+#define COR3_XoffCH 0x40 /* XOFF is a double seq (1 & 3) */
#define COR3_FCT 0x20 /* Flow-Control Transparency Mode */
#define COR3_SCDE 0x10 /* Special Character Detection Enable */
-#define COR3_RXTHMASK 0x0F /* RX FIFO Threshold value (1-8) */
+#define COR3_RxTHMASK 0x0F /* RX FIFO Threshold value (1-8) */
/* Channel Control Status Register */
-#define CCSR_RXEN 0x80 /* Revceiver Enabled */
-#define CCSR_RXFLOFF 0x40 /* Receive Flow Off (XOFF sent) */
-#define CCSR_RXFLON 0x20 /* Receive Flow On (XON sent) */
-#define CCSR_TXEN 0x08 /* Transmitter Enabled */
-#define CCSR_TXFLOFF 0x04 /* Transmit Flow Off (got XOFF) */
-#define CCSR_TXFLON 0x02 /* Transmit Flow On (got XON) */
+#define CCSR_RxEn 0x80 /* Revceiver Enabled */
+#define CCSR_RxFloff 0x40 /* Receive Flow Off (XOFF sent) */
+#define CCSR_RxFlon 0x20 /* Receive Flow On (XON sent) */
+#define CCSR_TxEn 0x08 /* Transmitter Enabled */
+#define CCSR_TxFloff 0x04 /* Transmit Flow Off (got XOFF) */
+#define CCSR_TxFlon 0x02 /* Transmit Flow On (got XON) */
/* Modem Change Option Register 1 */
-#define MCOR1_DSRZD 0x80 /* Detect 0->1 transition of DSR */
-#define MCOR1_CDZD 0x40 /* Detect 0->1 transition of CD */
-#define MCOR1_CTSZD 0x20 /* Detect 0->1 transition of CTS */
-#define MCOR1_DTRTH 0x0F /* Automatic DTR FC Threshold (1-8) */
+#define MCOR1_DSRzd 0x80 /* Detect 0->1 transition of DSR */
+#define MCOR1_CDzd 0x40 /* Detect 0->1 transition of CD */
+#define MCOR1_CTSzd 0x20 /* Detect 0->1 transition of CTS */
+#define MCOR1_DTRthMASK 0x0F /* Automatic DTR FC Threshold (1-8) chars */
/* Modem Change Option Register 2 */
-#define MCOR2_DSROD 0x80 /* Detect 1->0 transition of DSR */
-#define MCOR2_CDOD 0x40 /* Detect 1->0 transition of CD */
-#define MCOR2_CTSOD 0x20 /* Detect 1->0 transition of CTS */
+#define MCOR2_DSRod 0x80 /* Detect 1->0 transition of DSR */
+#define MCOR2_CDod 0x40 /* Detect 1->0 transition of CD */
+#define MCOR2_CTSod 0x20 /* Detect 1->0 transition of CTS */
/* Modem Change Register */
-#define MCR_DSRCHG 0x80 /* DSR Changed */
-#define MCR_CDCHG 0x40 /* CD Changed */
-#define MCR_CTSCHG 0x20 /* CTS Changed */
+#define MCR_DSRchg 0x80 /* DSR Changed */
+#define MCR_CDchg 0x40 /* CD Changed */
+#define MCR_CTSchg 0x20 /* CTS Changed */
/* Modem Signal Value Register */
#define MSVR_DSR 0x80 /* Current state of DSR input */
diff --git a/sys/i386/isa/rc.c b/sys/i386/isa/rc.c
index 2892515..8eb0f93 100644
--- a/sys/i386/isa/rc.c
+++ b/sys/i386/isa/rc.c
@@ -33,7 +33,7 @@
#include "rc.h"
#if NRC > 0
-/*#define RCDEBUG */
+/*#define RCDEBUG*/
#include <sys/param.h>
#include <sys/systm.h>
@@ -74,21 +74,21 @@ int rcioctl __P((dev_t, int, caddr_t, int, struct proc *));
#define rcin(port) RC_IN (nec, port)
#define rcout(port,v) RC_OUT (nec, port, v)
-/* Counter short for timeouts */
-static volatile int rcnt;
+#define WAITFORCCR(u,c) rc_wait0(nec, (u), (c), __LINE__)
+#define CCRCMD(u,c,cmd) WAITFORCCR((u), (c)); rcout(CD180_CCR, (cmd))
-#define WAITFORCCR { for (rcnt = 100000; rcin(CD180_CCR) && rcnt; rcnt--) ; }
-#define CCRCMD(cmd) WAITFORCCR; rcout(CD180_CCR, cmd)
-
-#define RC_IBUFSIZE 512
-#define RC_OBUFSIZE 1024
+#define RC_IBUFSIZE 256
+#define RB_I_HIGH_WATER (TTYHOG - 2 * RC_IBUFSIZE)
+#define RC_OBUFSIZE 512
#define RC_IHIGHWATER (3 * RC_IBUFSIZE / 4)
#define INPUT_FLAGS_SHIFT (2 * RC_IBUFSIZE)
#define LOTS_OF_EVENTS 64
-#define RC_TXTIMEO 30 /* 30 seconds wait if intr loss */
#define RC_FAKEID 0x10
+#define RC_PROBED 1
+#define RC_ATTACHED 2
+
#define GET_UNIT(dev) (minor(dev) & 0x3F)
#define CALLOUT(dev) (minor(dev) & 0x80)
@@ -99,7 +99,7 @@ struct isa_driver rcdriver = {
/* Per-board structure */
static struct rc_softc {
- u_int rcb_probed; /* 1 if device probed */
+ u_int rcb_probed; /* 1 - probed, 2 - attached */
u_int rcb_addr; /* Base I/O addr */
u_int rcb_unit; /* unit # */
u_char rcb_dtr; /* DTR status */
@@ -116,7 +116,6 @@ static struct rc_chans {
u_char rc_cor2; /* options reg */
u_char rc_pendcmd; /* special cmd pending */
u_int rc_dtrwait; /* dtr timeout */
- long rc_txitime; /* time of last TX intr */
u_int rc_dcdwaits; /* how many waits DCD in open */
u_char rc_hotchar; /* end packed optimize */
struct tty *rc_tp; /* tty struct */
@@ -124,7 +123,6 @@ static struct rc_chans {
u_char *rc_hiwat; /* hi-water mark */
u_char *rc_bufend; /* end of buffer */
u_char *rc_optr; /* ptr in output buf */
- u_char rc_ocnt;
u_char *rc_obufend; /* end of output buf */
u_char rc_ibuf[4 * RC_IBUFSIZE]; /* input buffer */
u_char rc_obuf[RC_OBUFSIZE]; /* output buffer */
@@ -137,18 +135,18 @@ struct tty rc_tty[NRC * CD180_NCHAN];
int nrc_tty = NRC * CD180_NCHAN;
/* Flags */
-#define RC_DTR_OFF 000001 /* DTR wait, for close/open */
-#define RC_ACTOUT 000002 /* Dial-out port active */
-#define RC_RTSFLOW 000004 /* RTS flow ctl enabled */
-#define RC_CTSFLOW 000010 /* CTS flow ctl enabled */
-#define RC_DORXFER 000020 /* RXFER event planned */
-#define RC_DOXXFER 000040 /* RXFER event planned */
-#define RC_MODCHG 000100 /* Modem status changed */
-#define RC_OSUSP 000200 /* Output suspended */
-#define RC_OSBUSY 000400 /* start() routine in progress */
-#define RC_WAS_BUFOVFL 001000 /* low-level buffer ovferflow */
-#define RC_WAS_SILOVFL 002000 /* silo buffer overflow */
-#define RC_SEND_RDY 004000 /* ready to send */
+#define RC_DTR_OFF 0x0001 /* DTR wait, for close/open */
+#define RC_ACTOUT 0x0002 /* Dial-out port active */
+#define RC_RTSFLOW 0x0004 /* RTS flow ctl enabled */
+#define RC_CTSFLOW 0x0008 /* CTS flow ctl enabled */
+#define RC_DORXFER 0x0010 /* RXFER event planned */
+#define RC_DOXXFER 0x0020 /* XXFER event planned */
+#define RC_MODCHG 0x0040 /* Modem status changed */
+#define RC_OSUSP 0x0080 /* Output suspended */
+#define RC_OSBUSY 0x0100 /* start() routine in progress */
+#define RC_WAS_BUFOVFL 0x0200 /* low-level buffer ovferflow */
+#define RC_WAS_SILOVFL 0x0400 /* silo buffer overflow */
+#define RC_SEND_RDY 0x0800 /* ready to send */
static struct speedtab rc_speedtab[] = {
0, 0,
@@ -183,7 +181,7 @@ static int rc_rcsrt[16] = {
};
/* Static prototypes */
-static void rc_hwreset __P((int, unsigned int));
+static void rc_hwreset __P((int, int, unsigned int));
static int rc_test __P((int, int));
static void rc_discard_output __P((struct rc_chans *));
static void rc_hardclose __P((struct rc_chans *));
@@ -191,9 +189,14 @@ static int rc_modctl __P((struct rc_chans *, int, int));
static void rc_start __P((struct tty *));
static int rc_param __P((struct tty *, struct termios *));
static void rc_registerdev __P((struct isa_device *id));
+static void rc_reinit __P((struct rc_softc *));
+#ifdef RCDEBUG
+static void printrcflags();
+#endif
static timeout_t rc_dtrwakeup;
static timeout_t rc_wakeup;
static void disc_optim __P((struct tty *tp, struct termios *t, struct rc_chans *));
+static void rc_wait0 __P((int nec, int unit, int chan, int line));
/**********************************************/
@@ -206,7 +209,6 @@ int rcprobe(dvp)
if (dvp->id_unit > NRC)
return 0;
- rc_softc[dvp->id_unit].rcb_probed = 0;
if (!RC_VALIDADDR(nec)) {
printf("rc%d: illegal base address %x\n", nec);
return 0;
@@ -222,8 +224,9 @@ int rcprobe(dvp)
/* Now, test the board more thoroughly, with diagnostic */
if (rc_test(nec, dvp->id_unit))
return 0;
- rc_softc[dvp->id_unit].rcb_probed = 1;
- return 1;
+ rc_softc[dvp->id_unit].rcb_probed = RC_PROBED;
+
+ return 0xF;
}
static struct kern_devconf kdc_rc[NRC] = { {
@@ -252,7 +255,6 @@ rc_registerdev(id)
dev_attach(&kdc_rc[unit]);
}
-/* Test device, then attach */
int rcattach(dvp)
struct isa_device *dvp;
{
@@ -260,9 +262,10 @@ int rcattach(dvp)
struct rc_softc *rcb = &rc_softc[dvp->id_unit];
struct rc_chans *rc = &rc_chans[dvp->id_unit * CD180_NCHAN];
static int rc_wakeup_started = 0;
+ struct tty *tp;
/* Thorooughly test the device */
- if (!rcb->rcb_probed)
+ if (rcb->rcb_probed != RC_PROBED)
return 0;
rcb->rcb_addr = nec;
rcb->rcb_dtr = 0;
@@ -282,12 +285,16 @@ int rcattach(dvp)
rc->rc_flags = rc->rc_ier = rc->rc_msvr = 0;
rc->rc_cor2 = rc->rc_pendcmd = 0;
rc->rc_optr = rc->rc_obufend = rc->rc_obuf;
- rc->rc_txitime = (~0UL >> 1);
rc->rc_dtrwait = 3 * hz;
- rc->rc_ocnt = 0;
rc->rc_dcdwaits= 0;
rc->rc_hotchar = 0;
+ tp = rc->rc_tp = &rc_tty[chan];
+ ttychars(tp);
+ tp->t_lflag = tp->t_iflag = tp->t_oflag = 0;
+ tp->t_cflag = TTYDEF_CFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
}
+ rcb->rcb_probed = RC_ATTACHED;
if (!rc_wakeup_started) {
rc_wakeup((void *)NULL);
rc_wakeup_started = 0;
@@ -301,192 +308,214 @@ void rcintr(unit)
{
register struct rc_softc *rcb = &rc_softc[unit];
register struct rc_chans *rc;
- register u_char val;
- register u_int nec, bsr, iack, ucnt;
- int good_data, resid;
+ register int nec, resid;
+ register u_char val, iack, bsr, ucnt, *optr;
+ int good_data, t_state;
+ if (rcb->rcb_probed != RC_ATTACHED) {
+ printf("rc%d: bogus interrupt\n", unit);
+ return;
+ }
nec = rcb->rcb_addr;
-possibly_more_intrs:
bsr = ~(rcin(RC_BSR));
-#ifdef RCDEBUG
- printf("rcintr: %d (%02x) %s %s %s %s\n", unit, bsr,
- (bsr & RC_BSR_TOUT)?"TOUT":"",
- (bsr & RC_BSR_RXINT)?"RXINT":"",
- (bsr & RC_BSR_TXINT)?"TXINT":"",
- (bsr & RC_BSR_MOINT)?"MOINT":"");
-#endif
- if (bsr & RC_BSR_RXINT) {
- iack = rcin(RC_PILR_RX);
-#ifdef RCDEBUG
- printf("rxint iack = %02x\n", iack);
-#endif
- rc = rcb->rcb_baserc + (rcin(CD180_GICR) >> GICR_LSH);
- ucnt = rcin(CD180_RDCR);
- resid = 0;
- good_data = (iack == (GIVR_IT_RGDI | RC_FAKEID));
-#ifdef RCDEBUG
- printrcflags(rc, "rxint");
+ if (!(bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT))) {
+ printf("rc%d: extra interrupt\n", unit);
+ rcout(CD180_EOIR, 0);
+ return;
+ }
+
+ while (bsr & (RC_BSR_TOUT|RC_BSR_RXINT|RC_BSR_TXINT|RC_BSR_MOINT)) {
+#ifdef RCDEBUG_DETAILED
+ printf("rc%d: intr (%02x) %s%s%s%s\n", unit, bsr,
+ (bsr & RC_BSR_TOUT)?"TOUT ":"",
+ (bsr & RC_BSR_RXINT)?"RXINT ":"",
+ (bsr & RC_BSR_TXINT)?"TXINT ":"",
+ (bsr & RC_BSR_MOINT)?"MOINT":"");
#endif
- /* Do RTS flow control stuff */
- if ( (rc->rc_flags & RC_RTSFLOW)
- || !rc->rc_tp
- || !(rc->rc_tp->t_state & TS_ISOPEN)) {
- if ( (!rc->rc_tp
- || !(rc->rc_tp->t_state & TS_ISOPEN)
- || (rc->rc_tp->t_state & TS_TBLOCK))
- && (rc->rc_msvr & MSVR_RTS))
- rcout(CD180_MSVR,
- rc->rc_msvr &= ~MSVR_RTS);
- else if (!(rc->rc_msvr & MSVR_RTS))
- rcout(CD180_MSVR,
- rc->rc_msvr |= MSVR_RTS);
+ if (bsr & RC_BSR_TOUT) {
+ printf("rc%d: hardware failure, reset board\n", unit);
+ rcout(RC_CTOUT, 0);
+ rc_reinit(rcb);
+ return;
}
-
- if (rc->rc_tp && (rc->rc_tp->t_state & TS_ISOPEN)) {
- /* check for input buffer overflow */
- if ((rc->rc_iptr + ucnt) >= rc->rc_bufend) {
- resid = ucnt;
- ucnt = rc->rc_bufend - rc->rc_iptr;
- resid -= ucnt;
- if (!(rc->rc_flags & RC_WAS_BUFOVFL)) {
- rc->rc_flags |= RC_WAS_BUFOVFL;
- rc_scheduled_event++;
- }
+ if (bsr & RC_BSR_RXINT) {
+ iack = rcin(RC_PILR_RX);
+ good_data = (iack == (GIVR_IT_RGDI | RC_FAKEID));
+ if (!good_data && iack != (GIVR_IT_REI | RC_FAKEID)) {
+ printf("rc%d: fake rxint: %02x\n", unit, iack);
+ goto more_intrs;
}
- /* check foor good data */
- if (good_data) {
- while (ucnt-- > 0) {
- val = rcin(CD180_RDR);
- rc->rc_iptr[0] = val;
- rc->rc_iptr[INPUT_FLAGS_SHIFT] = 0;
- rc->rc_iptr++;
- rc_scheduled_event++;
- if (rc->rc_hotchar != 0 && val == rc->rc_hotchar)
- setsofttty();
- }
- } else {
- /* Store also status data */
- while (ucnt-- > 0) {
- iack = rcin(CD180_RCSR);
- if (iack & RCSR_TOUT) {
- (void) rcin(CD180_RDR);
- break;
- }
- if ( (iack & RCSR_OE)
- && !(rc->rc_flags & RC_WAS_SILOVFL)) {
- rc->rc_flags |= RC_WAS_SILOVFL;
+ rc = rcb->rcb_baserc + ((rcin(CD180_GICR) & GICR_CHAN) >> GICR_LSH);
+ t_state = rc->rc_tp->t_state;
+ /* Do RTS flow control stuff */
+ if ( (rc->rc_flags & RC_RTSFLOW)
+ || !(t_state & TS_ISOPEN)
+ ) {
+ if ( ( !(t_state & TS_ISOPEN)
+ || (t_state & TS_TBLOCK)
+ )
+ && (rc->rc_msvr & MSVR_RTS)
+ )
+ rcout(CD180_MSVR,
+ rc->rc_msvr &= ~MSVR_RTS);
+ else if (!(rc->rc_msvr & MSVR_RTS))
+ rcout(CD180_MSVR,
+ rc->rc_msvr |= MSVR_RTS);
+ }
+ ucnt = rcin(CD180_RDCR) & 0xF;
+ resid = 0;
+
+ if (t_state & TS_ISOPEN) {
+ /* check for input buffer overflow */
+ if ((rc->rc_iptr + ucnt) >= rc->rc_bufend) {
+ resid = ucnt;
+ ucnt = rc->rc_bufend - rc->rc_iptr;
+ resid -= ucnt;
+ if (!(rc->rc_flags & RC_WAS_BUFOVFL)) {
+ rc->rc_flags |= RC_WAS_BUFOVFL;
rc_scheduled_event++;
}
- val = rcin(CD180_RDR);
- /*
- Don't store PE if IGNPAR and BREAK if IGNBRK,
- this hack allows "raw" tty optimization
- works even if IGN* is set.
- */
- if ( !(iack & (RCSR_PE|RCSR_FE|RCSR_BREAK))
- || (!(iack & (RCSR_PE|RCSR_FE))
- || !(rc->rc_tp->t_iflag & IGNPAR))
- && (!(iack & RCSR_BREAK)
- || !(rc->rc_tp->t_iflag & IGNBRK))) {
- if ( (iack & (RCSR_PE|RCSR_FE))
- && (rc->rc_tp->t_state & TS_CAN_BYPASS_L_RINT)
- && ((iack & RCSR_FE)
- || (iack & RCSR_PE)
- && (rc->rc_tp->t_iflag & INPCK)))
- val = 0;
- else if (rc->rc_hotchar != 0 && val == rc->rc_hotchar)
- setsofttty();
- rc->rc_iptr[0] = val;
- rc->rc_iptr[INPUT_FLAGS_SHIFT] = iack;
- rc->rc_iptr++;
+ }
+ optr = rc->rc_iptr;
+ /* check foor good data */
+ if (good_data) {
+ while (ucnt-- > 0) {
+ val = rcin(CD180_RDR);
+ optr[0] = val;
+ optr[INPUT_FLAGS_SHIFT] = 0;
+ optr++;
rc_scheduled_event++;
+ if (val != 0 && val == rc->rc_hotchar)
+ setsofttty();
+ }
+ } else {
+ /* Store also status data */
+ while (ucnt-- > 0) {
+ iack = rcin(CD180_RCSR);
+ if (iack & RCSR_Timeout)
+ break;
+ if ( (iack & RCSR_OE)
+ && !(rc->rc_flags & RC_WAS_SILOVFL)) {
+ rc->rc_flags |= RC_WAS_SILOVFL;
+ rc_scheduled_event++;
+ }
+ val = rcin(CD180_RDR);
+ /*
+ Don't store PE if IGNPAR and BREAK if IGNBRK,
+ this hack allows "raw" tty optimization
+ works even if IGN* is set.
+ */
+ if ( !(iack & (RCSR_PE|RCSR_FE|RCSR_Break))
+ || (!(iack & (RCSR_PE|RCSR_FE))
+ || !(rc->rc_tp->t_iflag & IGNPAR))
+ && (!(iack & RCSR_Break)
+ || !(rc->rc_tp->t_iflag & IGNBRK))) {
+ if ( (iack & (RCSR_PE|RCSR_FE))
+ && (t_state & TS_CAN_BYPASS_L_RINT)
+ && ((iack & RCSR_FE)
+ || (iack & RCSR_PE)
+ && (rc->rc_tp->t_iflag & INPCK)))
+ val = 0;
+ else if (val != 0 && val == rc->rc_hotchar)
+ setsofttty();
+ optr[0] = val;
+ optr[INPUT_FLAGS_SHIFT] = iack;
+ optr++;
+ rc_scheduled_event++;
+ }
}
}
+ rc->rc_iptr = optr;
+ rc->rc_flags |= RC_DORXFER;
+ } else
+ resid = ucnt;
+ /* Clear FIFO if necessary */
+ while (resid-- > 0) {
+ if (!good_data)
+ iack = rcin(CD180_RCSR);
+ else
+ iack = 0;
+ if (iack & RCSR_Timeout)
+ break;
+ (void) rcin(CD180_RDR);
}
- rc->rc_flags |= RC_DORXFER;
- } else
- resid = ucnt;
- /* Clear FIFO if necessary */
- while (resid-- > 0) {
- if (!good_data)
- iack = rcin(CD180_RCSR);
- else
- iack = 0;
- (void) rcin(CD180_RDR);
- if (iack & RCSR_TOUT)
- break;
+ goto more_intrs;
}
- rcout(CD180_EOIR, 0);
- goto possibly_more_intrs;
- }
- if (bsr & RC_BSR_MOINT) {
- iack = rcin(CD180_MCR);
- rc = rcb->rcb_baserc + (rcin(CD180_GICR) >> GICR_LSH);
+ if (bsr & RC_BSR_MOINT) {
+ iack = rcin(RC_PILR_MODEM);
+ if (iack != (GIVR_IT_MSCI | RC_FAKEID)) {
+ printf("rc%d: fake moint: %02x\n", unit, iack);
+ goto more_intrs;
+ }
+ rc = rcb->rcb_baserc + ((rcin(CD180_GICR) & GICR_CHAN) >> GICR_LSH);
+ iack = rcin(CD180_MCR);
+ rc->rc_msvr = rcin(CD180_MSVR);
+ rcout(CD180_MCR, 0);
#ifdef RCDEBUG
- printrcflags(rc, "moint");
+ printrcflags(rc, "moint");
#endif
- rc->rc_msvr = rcin(CD180_MSVR);
- if (rc->rc_flags & RC_CTSFLOW) {
- if (rc->rc_msvr & MSVR_CTS)
+ if (rc->rc_flags & RC_CTSFLOW) {
+ if (rc->rc_msvr & MSVR_CTS)
+ rc->rc_flags |= RC_SEND_RDY;
+ else
+ rc->rc_flags &= ~RC_SEND_RDY;
+ } else
rc->rc_flags |= RC_SEND_RDY;
- else
- rc->rc_flags &= ~RC_SEND_RDY;
- }
- if (iack & MCR_CDCHG) {
- rc->rc_flags |= RC_MODCHG;
- rc_scheduled_event += LOTS_OF_EVENTS;
- setsofttty();
- }
- rcout(CD180_EOIR, 0);
- goto possibly_more_intrs;
- }
- if (bsr & RC_BSR_TXINT) {
- rc = rcb->rcb_baserc + (rcin(CD180_GICR) >> GICR_LSH);
- rc->rc_txitime = time.tv_sec;
-#ifdef RCDEBUG
- printrcflags(rc, "txint");
-#endif
- if ( (rc->rc_flags & RC_OSUSP)
- || !(rc->rc_flags & RC_SEND_RDY))
- goto skip;
- ucnt = rc->rc_obufend - rc->rc_optr;
- if (ucnt > CD180_NFIFO)
- ucnt = CD180_NFIFO;
- /* Handle breaks and other stuff */
- if (rc->rc_pendcmd) {
- rcout(CD180_COR2, rc->rc_cor2 |= COR2_ETC);
- rcout(CD180_TDR, CD180_C_ESC);
- rcout(CD180_TDR, rc->rc_pendcmd);
- rcout(CD180_COR2, rc->rc_cor2 &= ~COR2_ETC);
- rc->rc_pendcmd = 0;
- rcout(CD180_EOIR, 0);
- goto possibly_more_intrs;
+ if ((iack & MCR_CDchg) && !(rc->rc_flags & RC_MODCHG)) {
+ rc_scheduled_event += LOTS_OF_EVENTS;
+ rc->rc_flags |= RC_MODCHG;
+ setsofttty();
+ }
+ goto more_intrs;
}
- while (ucnt-- > 0)
- rcout(CD180_TDR, *rc->rc_optr++);
-
- /* output completed? */
- if (rc->rc_optr >= rc->rc_obufend) {
- rcout(CD180_IER, rc->rc_ier &=
- ~(IER_TXRDY|IER_TXMPTY));
+ if (bsr & RC_BSR_TXINT) {
+ iack = rcin(RC_PILR_TX);
+ if (iack != (GIVR_IT_TDI | RC_FAKEID)) {
+ printf("rc%d: fake txint: %02x\n", unit, iack);
+ goto more_intrs;
+ }
+ rc = rcb->rcb_baserc + ((rcin(CD180_GICR) & GICR_CHAN) >> GICR_LSH);
+ if ( (rc->rc_flags & RC_OSUSP)
+ || !(rc->rc_flags & RC_SEND_RDY)
+ )
+ goto more_intrs;
+ /* Handle breaks and other stuff */
+ if (rc->rc_pendcmd) {
+ rcout(CD180_COR2, rc->rc_cor2 |= COR2_ETC);
+ rcout(CD180_TDR, CD180_C_ESC);
+ rcout(CD180_TDR, rc->rc_pendcmd);
+ rcout(CD180_COR2, rc->rc_cor2 &= ~COR2_ETC);
+ rc->rc_pendcmd = 0;
+ goto more_intrs;
+ }
+ optr = rc->rc_optr;
+ resid = rc->rc_obufend - optr;
+ if (resid > CD180_NFIFO)
+ resid = CD180_NFIFO;
+ while (resid-- > 0)
+ rcout(CD180_TDR, *optr++);
+ rc->rc_optr = optr;
+
+ /* output completed? */
+ if (optr >= rc->rc_obufend) {
+ rcout(CD180_IER, rc->rc_ier &= ~IER_TxRdy);
#ifdef RCDEBUG
- printf("tx intr disabled\n");
+ printf("rc%d/%d: output completed\n", unit, rc->rc_chan);
#endif
- rc->rc_flags |= RC_DOXXFER;
- rc_scheduled_event += LOTS_OF_EVENTS;
- setsofttty();
+ if (!(rc->rc_flags & RC_DOXXFER)) {
+ rc_scheduled_event += LOTS_OF_EVENTS;
+ rc->rc_flags |= RC_DOXXFER;
+ setsofttty();
+ }
+ }
}
- skip:
- rcout(CD180_EOIR, 0);
- goto possibly_more_intrs;
+ more_intrs:
+ rcout(CD180_EOIR, 0); /* end of interrupt */
+ rcout(RC_CTOUT, 0);
+ bsr = ~(rcin(RC_BSR));
}
- rcout(RC_BSR, 0); /* -/- */
-#ifdef RCDEBUG
- if (rc_scheduled_event)
- printf("event scheduled unit %d\n", unit);
-#endif
}
/* Feed characters to output buffer */
@@ -506,17 +535,15 @@ register struct tty *tp;
else
rc->rc_flags &= ~RC_OSUSP;
/* Do RTS flow control stuff */
- if (rc->rc_flags & RC_RTSFLOW) {
- if ((tp->t_state & TS_TBLOCK) &&
- (rc->rc_msvr & MSVR_RTS)) {
- rcout(CD180_CAR, rc->rc_chan);
- rcout(CD180_MSVR,
- rc->rc_msvr &= ~MSVR_RTS);
- } else if (!(rc->rc_msvr & MSVR_RTS)) {
- rcout(CD180_CAR, rc->rc_chan);
- rcout(CD180_MSVR,
- rc->rc_msvr |= MSVR_RTS);
- }
+ if ( (rc->rc_flags & RC_RTSFLOW)
+ && (tp->t_state & TS_TBLOCK)
+ && (rc->rc_msvr & MSVR_RTS)
+ ) {
+ rcout(CD180_CAR, rc->rc_chan);
+ rcout(CD180_MSVR, rc->rc_msvr &= ~MSVR_RTS);
+ } else if (!(rc->rc_msvr & MSVR_RTS)) {
+ rcout(CD180_CAR, rc->rc_chan);
+ rcout(CD180_MSVR, rc->rc_msvr |= MSVR_RTS);
}
enable_intr();
if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
@@ -524,17 +551,6 @@ register struct tty *tp;
#ifdef RCDEBUG
printrcflags(rc, "rcstart");
#endif
- /* Checking for stale tx intrs */
- if ((rc->rc_ier & IER_TXRDY) &&
- (rc->rc_txitime - time.tv_sec) > RC_TXTIMEO) {
- rc->rc_txitime = time.tv_sec;
- printf("rc%d: chan %d: lost TX intr, reinit\n",
- rc->rc_rcb->rcb_unit, rc->rc_chan);
- /* try to re-initialize channel */
- rcout(CD180_CAR, rc->rc_chan);
- CCRCMD(CCR_RESETCHAN);
- (void) rc_param(rc->rc_tp, &rc->rc_tp->t_termios);
- }
if (tp->t_outq.c_cc <= tp->t_lowat) {
if (tp->t_state & TS_ASLEEP) {
tp->t_state &= ~TS_ASLEEP;
@@ -543,11 +559,10 @@ register struct tty *tp;
selwakeup(&tp->t_wsel);
}
#ifdef RCDEBUG
- printf("rcstart: q = %d olen = %d\n",
+ printf("rcstart: outq = %d obuf = %d\n",
tp->t_outq.c_cc, rc->rc_obufend - rc->rc_optr);
#endif
- /* maybe we need to check for lost intrs here */
- if (rc->rc_optr < rc->rc_obufend)
+ if (tp->t_state & TS_BUSY)
goto out; /* output still in progress ... */
if (tp->t_outq.c_cc > 0) {
@@ -556,20 +571,16 @@ register struct tty *tp;
tp->t_state |= TS_BUSY;
ocnt = q_to_b(&tp->t_outq, rc->rc_obuf, sizeof rc->rc_obuf);
disable_intr();
- rc->rc_ocnt = ocnt;
rc->rc_optr = rc->rc_obuf;
- rc->rc_obufend = rc->rc_optr + rc->rc_ocnt;
+ rc->rc_obufend = rc->rc_optr + ocnt;
enable_intr();
- if ((rc->rc_ier & IER_TXRDY) == 0) {
+ if (!(rc->rc_ier & IER_TxRdy)) {
#ifdef RCDEBUG
- printf("rcstart: enable txint\n");
+ printf("rc%d/%d: rcstart enable txint\n", rc->rc_rcb->rcb_unit, rc->rc_chan);
#endif
rcout(CD180_CAR, rc->rc_chan);
- rcout(CD180_IER, rc->rc_ier |= IER_TXRDY);
+ rcout(CD180_IER, rc->rc_ier |= IER_TxRdy);
}
- } else {
- rc->rc_ocnt = 0;
- tp->t_flags &= ~TS_BUSY;
}
out:
rc->rc_flags &= ~RC_OSBUSY;
@@ -601,27 +612,31 @@ repeat:
printrcflags(rc, "rcevent");
#endif
if (rc->rc_flags & RC_WAS_BUFOVFL) {
+ disable_intr();
rc->rc_flags &= ~RC_WAS_BUFOVFL;
rc_scheduled_event--;
+ enable_intr();
printf("rc%d/%d: interrupt-level buffer overflow\n",
unit, chan);
}
if (rc->rc_flags & RC_WAS_SILOVFL) {
+ disable_intr();
rc->rc_flags &= ~RC_WAS_SILOVFL;
rc_scheduled_event--;
+ enable_intr();
printf("rc%d/%d: silo overflow\n",
unit, chan);
}
if (rc->rc_flags & RC_MODCHG) {
+ disable_intr();
rc->rc_flags &= ~RC_MODCHG;
rc_scheduled_event -= LOTS_OF_EVENTS;
- if (tp)
- (*linesw[tp->t_line].l_modem)(tp, !!(rc->rc_msvr & MSVR_CD));
+ enable_intr();
+ (*linesw[tp->t_line].l_modem)(tp, !!(rc->rc_msvr & MSVR_CD));
}
if (rc->rc_flags & RC_DORXFER) {
- rc->rc_flags &= ~RC_DORXFER;
-
disable_intr();
+ rc->rc_flags &= ~RC_DORXFER;
eptr = rc->rc_iptr;
if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE])
tptr = &rc->rc_ibuf[RC_IBUFSIZE];
@@ -639,11 +654,11 @@ repeat:
rc->rc_hiwat =
&rc->rc_ibuf[RC_IBUFSIZE + RC_IHIGHWATER];
}
- if ((rc->rc_flags & RC_RTSFLOW)
- && !(rc->rc_msvr & MSVR_RTS)
- && tp != NULL
+ if ( (rc->rc_flags & RC_RTSFLOW)
&& (tp->t_state & TS_ISOPEN)
- && !(tp->t_state & TS_TBLOCK)) {
+ && !(tp->t_state & TS_TBLOCK)
+ && !(rc->rc_msvr & MSVR_RTS)
+ ) {
rcout(CD180_CAR, chan);
rcout(CD180_MSVR,
rc->rc_msvr |= MSVR_RTS);
@@ -652,13 +667,13 @@ repeat:
}
enable_intr();
- if (icnt <= 0 || !tp || !(tp->t_state & TS_ISOPEN))
+ if (icnt <= 0 || !(tp->t_state & TS_ISOPEN))
goto done1;
if ( linesw[tp->t_line].l_rint == ttyinput
&& ((rc->rc_flags & RC_RTSFLOW) || (tp->t_iflag & IXOFF))
&& !(tp->t_state & TS_TBLOCK)
- && (tp->t_rawq.c_cc + icnt) > RC_IHIGHWATER) {
+ && (tp->t_rawq.c_cc + icnt) > RB_I_HIGH_WATER) {
int queue_full = 0;
if ((tp->t_iflag & IXOFF) &&
@@ -695,7 +710,11 @@ repeat:
done1:
}
if (rc->rc_flags & RC_DOXXFER) {
- rc_discard_output(rc);
+ disable_intr();
+ rc_scheduled_event -= LOTS_OF_EVENTS;
+ rc->rc_flags &= ~RC_DOXXFER;
+ rc->rc_tp->t_state &= ~TS_BUSY;
+ enable_intr();
(*linesw[tp->t_line].l_start)(tp);
}
}
@@ -714,13 +733,14 @@ void rcstop(tp, rw)
u_char *tptr, *eptr;
#ifdef RCDEBUG
- printf("rcstop %d/%d: %s%s\n", rc->rc_rcb->rcb_unit, rc->rc_chan,
+ printf("rc%d/%d: rcstop %s%s\n", rc->rc_rcb->rcb_unit, rc->rc_chan,
(rw & FWRITE)?"FWRITE ":"", (rw & FREAD)?"FREAD":"");
#endif
if (rw & FWRITE)
rc_discard_output(rc);
disable_intr();
if (rw & FREAD) {
+ rc->rc_flags &= ~RC_DORXFER;
eptr = rc->rc_iptr;
if (rc->rc_bufend == &rc->rc_ibuf[2 * RC_IBUFSIZE]) {
tptr = &rc->rc_ibuf[RC_IBUFSIZE];
@@ -750,17 +770,19 @@ int rcopen(dev, flag, mode, p)
unit = GET_UNIT(dev);
if (unit >= NRC * CD180_NCHAN)
return ENXIO;
+ if (rc_softc[unit / CD180_NCHAN].rcb_probed != RC_ATTACHED)
+ return ENXIO;
rc = &rc_chans[unit];
- tp = rc->rc_tp = &rc_tty[unit];
+ tp = rc->rc_tp;
nec = rc->rc_rcb->rcb_addr;
#ifdef RCDEBUG
- printf("rcopen: dev %02x\n", dev);
+ printf("rc%d/%d: rcopen: dev %x\n", rc->rc_rcb->rcb_unit, unit, dev);
#endif
s = spltty();
again:
while (rc->rc_flags & RC_DTR_OFF) {
- error = tsleep(&rc->rc_dtrwait, TTIPRI | PCATCH, "rcdtr", 0);
+ error = tsleep(&(rc->rc_dtrwait), TTIPRI | PCATCH, "rcdtr", 0);
if (error != 0)
goto out;
}
@@ -791,31 +813,18 @@ again:
tp->t_param = rc_param;
tp->t_dev = dev;
- if (tp->t_ispeed == 0) {
- ttychars(tp);
- tp->t_lflag = tp->t_iflag = tp->t_oflag = 0;
- tp->t_cflag = TTYDEF_CFLAG;
- tp->t_ispeed = tp->t_ospeed = 9600;
- }
if (CALLOUT(dev))
tp->t_cflag |= CLOCAL;
else
tp->t_cflag &= ~CLOCAL;
- (void) rc_modctl(rc, TIOCM_DTR|TIOCM_RTS, DMSET);
-
error = rc_param(tp, &tp->t_termios);
if (error)
goto out;
+ (void) rc_modctl(rc, TIOCM_RTS|TIOCM_DTR, DMSET);
ttsetwater(tp);
- disable_intr();
- rcout(CD180_CAR, rc->rc_chan);
- rc->rc_msvr = rcin(CD180_MSVR);
- rcout(CD180_IER, rc->rc_ier |= IER_CD | IER_TXRDY | IER_RXD);
- enable_intr();
-
if ((rc->rc_msvr & MSVR_CD) || CALLOUT(dev))
(*linesw[tp->t_line].l_modem)(tp, 1);
}
@@ -853,6 +862,9 @@ int rcclose(dev, flag, mode, p)
return ENXIO;
rc = &rc_chans[unit];
tp = rc->rc_tp;
+#ifdef RCDEBUG
+ printf("rc%d/%d: rcclose dev %x\n", rc->rc_rcb->rcb_unit, unit, dev);
+#endif
s = spltty();
(*linesw[tp->t_line].l_close)(tp, flag);
rcstop(tp, FREAD | FWRITE);
@@ -871,13 +883,16 @@ register struct rc_chans *rc;
s = spltty();
rcout(CD180_CAR, rc->rc_chan);
- /* Disable all intrs */
+ /* Disable rx/tx intrs */
rcout(CD180_IER, rc->rc_ier = 0);
- if ( tp->t_cflag & HUPCL
+ if ( (tp->t_cflag & HUPCL)
|| !(rc->rc_flags & RC_ACTOUT)
&& !(rc->rc_msvr & MSVR_CD)
&& !(tp->t_cflag & CLOCAL)
- || !(tp->t_state & TS_ISOPEN)) {
+ || !(tp->t_state & TS_ISOPEN)
+ ) {
+ CCRCMD(rc->rc_rcb->rcb_unit, rc->rc_chan, CCR_ResetChan);
+ WAITFORCCR(rc->rc_rcb->rcb_unit, rc->rc_chan);
(void) rc_modctl(rc, TIOCM_RTS, DMSET);
if (rc->rc_dtrwait) {
timeout(rc_dtrwakeup, rc, rc->rc_dtrwait);
@@ -897,6 +912,7 @@ int rcread(dev, uio, flag)
int flag;
{
struct tty *tp = rc_chans[GET_UNIT(dev)].rc_tp;
+
return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
}
@@ -907,23 +923,26 @@ int rcwrite(dev, uio, flag)
int flag;
{
struct tty *tp = rc_chans[GET_UNIT(dev)].rc_tp;
+
return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
}
/* Reset the bastard */
-static void rc_hwreset(nec, chipid)
- register int nec;
+static void rc_hwreset(unit, nec, chipid)
+ register int unit, nec;
unsigned int chipid;
{
- CCRCMD(CCR_HWRESET); /* Hardware reset */
+ CCRCMD(unit, -1, CCR_HWRESET); /* Hardware reset */
DELAY(20000);
- rcout(RC_BSR_TOUT, 0); /* Clear timeout */
+ WAITFORCCR(unit, -1);
+
+ rcout(RC_CTOUT, 0); /* Clear timeout */
rcout(CD180_GIVR, chipid);
rcout(CD180_GICR, 0);
/* Set Prescaler Registers (1 msec) */
- rcout(CD180_PPRL, (RC_OSCFREQ / 1000) & 0xFF);
- rcout(CD180_PPRH, (RC_OSCFREQ / 1000) >> 8);
+ rcout(CD180_PPRL, ((RC_OSCFREQ + 999) / 1000) & 0xFF);
+ rcout(CD180_PPRH, ((RC_OSCFREQ + 999) / 1000) >> 8);
/* Initialize Priority Interrupt Level Registers */
rcout(CD180_PILR1, RC_PILR_MODEM);
@@ -931,7 +950,7 @@ static void rc_hwreset(nec, chipid)
rcout(CD180_PILR3, RC_PILR_RX);
/* Reset DTR */
- rcout(RC_DTR, ~0);
+ rcout(RC_DTREG, ~0);
}
/* Set channel parameters */
@@ -939,9 +958,9 @@ static int rc_param(tp, ts)
register struct tty *tp;
struct termios *ts;
{
- register struct rc_chans *rc = &rc_chans[GET_UNIT(tp->t_dev)];
+ register struct rc_chans *rc = &rc_chans[GET_UNIT(tp->t_dev)];
register int nec = rc->rc_rcb->rcb_addr;
- int idivs, odivs, s, val, cflag, iflag, lflag;
+ int idivs, odivs, s, val, cflag, iflag, lflag, inpflow;
odivs = ttspeedtab(ts->c_ospeed, rc_speedtab);
if (ts->c_ispeed == 0)
@@ -952,20 +971,21 @@ static int rc_param(tp, ts)
s = spltty();
+ /* Select channel */
+ rcout(CD180_CAR, rc->rc_chan);
+
/* If speed == 0, hangup line */
- if (ts->c_ospeed == 0)
- rc_modctl(rc, TIOCM_DTR, DMBIC);
- else
- rc_modctl(rc, TIOCM_RTS|TIOCM_DTR, DMBIS);
+ if (ts->c_ospeed == 0) {
+ CCRCMD(rc->rc_rcb->rcb_unit, rc->rc_chan, CCR_ResetChan);
+ WAITFORCCR(rc->rc_rcb->rcb_unit, rc->rc_chan);
+ (void) rc_modctl(rc, TIOCM_DTR, DMBIC);
+ }
tp->t_state &= ~TS_CAN_BYPASS_L_RINT;
cflag = ts->c_cflag;
iflag = ts->c_iflag;
lflag = ts->c_lflag;
- /* Select channel */
- rcout(CD180_CAR, rc->rc_chan);
-
if (idivs > 0) {
rcout(CD180_RBPRL, idivs & 0xFF);
rcout(CD180_RBPRH, idivs >> 8);
@@ -976,7 +996,16 @@ static int rc_param(tp, ts)
}
/* set timeout value */
- rcout(CD180_RTPR, 0);
+ if (ts->c_ispeed > 0) {
+ int itm = ts->c_ispeed > 2400 ? 5 : 10000 / ts->c_ispeed + 1;
+
+ if ( !(lflag & ICANON)
+ && ts->c_cc[VMIN] != 0 && ts->c_cc[VTIME] != 0
+ && ts->c_cc[VTIME] * 10 > itm)
+ itm = ts->c_cc[VTIME] * 10;
+
+ rcout(CD180_RTPR, itm <= 255 ? itm : 255);
+ }
switch (cflag & CSIZE) {
case CS5: val = COR1_5BITS; break;
@@ -989,62 +1018,109 @@ static int rc_param(tp, ts)
val |= COR1_NORMPAR;
if (cflag & PARODD)
val |= COR1_ODDP;
+ if (!(cflag & INPCK))
+ val |= COR1_Ignore;
} else
- val |= COR1_IGNORE;
+ val |= COR1_Ignore;
if (cflag & CSTOPB)
val |= COR1_2SB;
rcout(CD180_COR1, val);
/* Set FIFO threshold */
- rcout(CD180_COR3, ts->c_ospeed <= 4800 ? 1 : CD180_NFIFO / 2);
- CCRCMD(CCR_CORCHG1 | CCR_CORCHG3);
+ val = ts->c_ospeed <= 4800 ? 1 : CD180_NFIFO / 2;
+ inpflow = 0;
+ if ( (iflag & IXOFF)
+ && ( ts->c_cc[VSTOP] != _POSIX_VDISABLE
+ && ( ts->c_cc[VSTART] != _POSIX_VDISABLE
+ || (iflag & IXANY)
+ )
+ )
+ ) {
+ inpflow = 1;
+ val |= COR3_SCDE|COR3_FCT;
+ }
+ rcout(CD180_COR3, val);
/* Initialize on-chip automatic flow control */
val = 0;
-
+ rc->rc_flags &= ~(RC_CTSFLOW|RC_SEND_RDY);
if (cflag & CCTS_OFLOW) {
rc->rc_flags |= RC_CTSFLOW;
- val |= COR2_CTSAE;
- rc->rc_msvr = rcin(CD180_MSVR);
- if (rc->rc_msvr & MSVR_CTS)
- rc->rc_flags |= RC_SEND_RDY;
- else
- rc->rc_flags &= ~RC_SEND_RDY;
- }
- else
+ val |= COR2_CtsAE;
+ } else
rc->rc_flags |= RC_SEND_RDY;
-
+ if (tp->t_state & TS_TTSTOP)
+ rc->rc_flags |= RC_OSUSP;
+ else
+ rc->rc_flags &= ~RC_OSUSP;
if (cflag & CRTS_IFLOW)
rc->rc_flags |= RC_RTSFLOW;
-
- if (iflag & (IXON|IXOFF)) {
- /* Initailize xon/xoff characters */
- rcout(CD180_SCHR1, ts->c_cc[CSTART]);
- rcout(CD180_SCHR2, ts->c_cc[CSTOP]);
- if (iflag & IXON) {
- val |= COR2_TXIBE;
- if (iflag & IXANY)
- val |= COR2_IXM;
- }
+ else
+ rc->rc_flags &= ~RC_RTSFLOW;
+
+ if (inpflow) {
+ if (ts->c_cc[VSTART] != _POSIX_VDISABLE)
+ rcout(CD180_SCHR1, ts->c_cc[VSTART]);
+ rcout(CD180_SCHR2, ts->c_cc[VSTOP]);
+ val |= COR2_TxIBE;
+ if (iflag & IXANY)
+ val |= COR2_IXM;
}
- rcout(CD180_COR2, val);
- CCRCMD(CCR_CORCHG2);
+ rcout(CD180_COR2, rc->rc_cor2 = val);
+
+ CCRCMD(rc->rc_rcb->rcb_unit, rc->rc_chan,
+ CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
disc_optim(tp, ts, rc);
/* modem ctl */
- rcout(CD180_MCOR1, MCOR1_CDZD);
- rcout(CD180_MCOR2, MCOR2_CDOD);
+ val = cflag & CLOCAL ? 0 : MCOR1_CDzd;
+ if (cflag & CCTS_OFLOW)
+ val |= MCOR1_CTSzd;
+ rcout(CD180_MCOR1, val);
- /* enable i/o and interrupts */
- CCRCMD(CCR_TXEN|CCR_RXEN);
- rcout(CD180_IER, rc->rc_ier |= IER_CD | IER_RXD);
+ val = cflag & CLOCAL ? 0 : MCOR2_CDod;
+ if (cflag & CCTS_OFLOW)
+ val |= MCOR2_CTSod;
+ rcout(CD180_MCOR2, val);
+ /* enable i/o and interrupts */
+ CCRCMD(rc->rc_rcb->rcb_unit, rc->rc_chan,
+ CCR_XMTREN | ((cflag & CREAD) ? CCR_RCVREN : CCR_RCVRDIS));
+ WAITFORCCR(rc->rc_rcb->rcb_unit, rc->rc_chan);
+
+ rc->rc_ier = cflag & CLOCAL ? 0 : IER_CD;
+ if (cflag & CCTS_OFLOW)
+ rc->rc_ier |= IER_CTS;
+ if (cflag & CREAD)
+ rc->rc_ier |= IER_RxData;
+ if (tp->t_state & TS_BUSY)
+ rc->rc_ier |= IER_TxRdy;
+ if (ts->c_ospeed != 0)
+ rc_modctl(rc, TIOCM_DTR, DMBIS);
+ if ((cflag & CCTS_OFLOW) && (rc->rc_msvr & MSVR_CTS))
+ rc->rc_flags |= RC_SEND_RDY;
+ rcout(CD180_IER, rc->rc_ier);
(void) splx(s);
return 0;
}
+/* Re-initialize board after bogus interrupts */
+static void rc_reinit(rcb)
+struct rc_softc *rcb;
+{
+ register struct rc_chans *rc, *rce;
+ register int i, nec;
+
+ nec = rcb->rcb_addr;
+ rc_hwreset(rcb->rcb_unit, nec, RC_FAKEID);
+ rc = &rc_chans[rcb->rcb_unit * CD180_NCHAN];
+ rce = rc + CD180_NCHAN;
+ for (; rc < rce; rc++)
+ (void) rc_param(rc->rc_tp, &rc->rc_tp->t_termios);
+}
+
int rcioctl(dev, cmd, data, flag, p)
dev_t dev;
int cmd, flag;
@@ -1073,7 +1149,7 @@ struct proc *p;
break;
case TIOCSDTR:
- (void) rc_modctl(rc, TIOCM_RTS|TIOCM_DTR, DMBIS);
+ (void) rc_modctl(rc, TIOCM_DTR, DMBIS);
break;
case TIOCCDTR:
@@ -1125,27 +1201,41 @@ register struct rc_chans *rc;
int bits, cmd;
{
register int nec = rc->rc_rcb->rcb_addr;
- u_char *dtr = &rc->rc_rcb->rcb_dtr;
- unsigned int msvr;
+ u_char *dtr = &rc->rc_rcb->rcb_dtr, msvr;
rcout(CD180_CAR, rc->rc_chan);
switch (cmd) {
case DMSET:
- rcout(CD180_MSVR, 0);
- *dtr &= ~(1 << rc->rc_chan);
- /* falltrough */
+ rcout(RC_DTREG, (bits & TIOCM_DTR) ?
+ ~(*dtr |= 1 << rc->rc_chan) :
+ ~(*dtr &= ~(1 << rc->rc_chan)));
+ msvr = rcin(CD180_MSVR);
+ if (bits & TIOCM_RTS)
+ msvr |= MSVR_RTS;
+ else
+ msvr &= ~MSVR_RTS;
+ if (bits & TIOCM_DTR)
+ msvr |= MSVR_DTR;
+ else
+ msvr &= ~MSVR_DTR;
+ rcout(CD180_MSVR, msvr);
+ break;
case DMBIS:
+ if (bits & TIOCM_DTR)
+ rcout(RC_DTREG, ~(*dtr |= 1 << rc->rc_chan));
+ msvr = rcin(CD180_MSVR);
if (bits & TIOCM_RTS)
- rcout(CD180_MSVR, MSVR_RTS);
+ msvr |= MSVR_RTS;
if (bits & TIOCM_DTR)
- rcout(RC_DTR, ~(*dtr |= (1 << rc->rc_chan)));
+ msvr |= MSVR_DTR;
+ rcout(CD180_MSVR, msvr);
break;
case DMGET:
- msvr = rcin(CD180_MSVR);
bits = TIOCM_LE;
+ msvr = rc->rc_msvr = rcin(CD180_MSVR);
if (msvr & MSVR_RTS)
bits |= TIOCM_RTS;
@@ -1155,15 +1245,24 @@ int bits, cmd;
bits |= TIOCM_DSR;
if (msvr & MSVR_DTR)
bits |= TIOCM_DTR;
+ if (msvr & MSVR_CD)
+ bits |= TIOCM_CD;
+ if (~rcin(RC_RIREG) & (1 << rc->rc_chan))
+ bits |= TIOCM_RI;
return bits;
case DMBIC:
if (bits & TIOCM_DTR)
- rcout(RC_DTR, ~(*dtr &= ~(1 << rc->rc_chan)));
+ rcout(RC_DTREG, ~(*dtr &= ~(1 << rc->rc_chan)));
+ msvr = rcin(CD180_MSVR);
if (bits & TIOCM_RTS)
- rcout(CD180_MSVR, 0);
+ msvr &= ~MSVR_RTS;
+ if (bits & TIOCM_DTR)
+ msvr &= ~MSVR_DTR;
+ rcout(CD180_MSVR, msvr);
break;
}
+ rc->rc_msvr = rcin(CD180_MSVR);
return 0;
}
@@ -1181,9 +1280,6 @@ int rc_test(nec, unit)
#define ERR(s) { \
printf("rc%d: ", unit); printf s ; printf("\n"); \
(void) splx(old_level); return 1; }
-#define TWAITFORCCR \
- for (rcnt = 100000; rcin(CD180_CCR) && rcnt; rcnt--) ; \
- if (!rcnt) ERR(("Timeout waiting for zero CCR"))
struct rtest {
u_char txbuf[CD180_NFIFO]; /* TX buffer */
@@ -1192,24 +1288,22 @@ int rc_test(nec, unit)
int txptr; /* TX pointer */
} tchans[CD180_NCHAN];
- old_level = splhigh();
+ old_level = spltty();
chipid = RC_FAKEID;
/* First, reset board to inital state */
- rc_hwreset(nec, chipid);
+ rc_hwreset(unit, nec, chipid);
+
+ divs = RC_BRD(19200);
/* Initialize channels */
for (chan = 0; chan < CD180_NCHAN; chan++) {
- divs = RC_BRD(19200);
-
- TWAITFORCCR;
-
/* Select and reset channel */
rcout(CD180_CAR, chan);
- rcout(CD180_CCR, CCR_RESETCHAN);
- TWAITFORCCR;
+ CCRCMD(unit, chan, CCR_ResetChan);
+ WAITFORCCR(unit, chan);
/* Set speed */
rcout(CD180_RBPRL, divs & 0xFF);
@@ -1224,10 +1318,9 @@ int rc_test(nec, unit)
rcout(CD180_COR1, COR1_NOPAR | COR1_8BITS | COR1_1SB);
rcout(CD180_COR2, COR2_LLM);
rcout(CD180_COR3, CD180_NFIFO);
- TWAITFORCCR;
- rcout(CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
- TWAITFORCCR;
- rcout(CD180_CCR, CCR_RXEN | CCR_TXEN);
+ CCRCMD(unit, chan, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
+ CCRCMD(unit, chan, CCR_RCVREN | CCR_XMTREN);
+ WAITFORCCR(unit, chan);
rcout(CD180_MSVR, MSVR_RTS);
/* Fill TXBUF with test data */
@@ -1238,46 +1331,44 @@ int rc_test(nec, unit)
tchans[chan].txptr = tchans[chan].rxptr = 0;
/* Now, start transmit */
- rcout(CD180_IER, IER_TXMPTY | IER_RXD);
+ rcout(CD180_IER, IER_TxMpty|IER_RxData);
}
/* Pseudo-interrupt poll stuff */
for (rcnt = 10000; rcnt-- > 0; rcnt--) {
- i = ~(rcin(RC_BSR)) & 0xF;
+ i = ~(rcin(RC_BSR));
if (i & RC_BSR_TOUT)
ERR(("BSR timeout bit set\n"))
- if (i & RC_BSR_TXINT) {
+ else if (i & RC_BSR_TXINT) {
iack = rcin(RC_PILR_TX);
if (iack != (GIVR_IT_TDI | chipid))
ERR(("Bad TX intr ack (%02x != %02x)\n",
iack, GIVR_IT_TDI | chipid));
- chan = (rcin(CD180_GICR) >> 2) & 07;
+ chan = (rcin(CD180_GICR) & GICR_CHAN) >> GICR_LSH;
/* If no more data to transmit, disable TX intr */
if (tchans[chan].txptr >= CD180_NFIFO) {
iack = rcin(CD180_IER);
- rcout(CD180_IER, iack & ~IER_TXMPTY);
+ rcout(CD180_IER, iack & ~IER_TxMpty);
} else {
for (iack = tchans[chan].txptr;
iack < CD180_NFIFO; iack++)
rcout(CD180_TDR,
tchans[chan].txbuf[iack]);
tchans[chan].txptr = iack;
- rcout(CD180_EOIR, 0);
}
-
- }
- if (i & RC_BSR_RXINT) {
- unsigned int ucnt;
+ rcout(CD180_EOIR, 0);
+ } else if (i & RC_BSR_RXINT) {
+ u_char ucnt;
iack = rcin(RC_PILR_RX);
if (iack != (GIVR_IT_RGDI | chipid) &&
iack != (GIVR_IT_REI | chipid))
ERR(("Bad RX intr ack (%02x != %02x)\n",
iack, GIVR_IT_RGDI | chipid))
- chan = (rcin(CD180_GICR) >> 2) & 07;
+ chan = (rcin(CD180_GICR) & GICR_CHAN) >> GICR_LSH;
ucnt = rcin(CD180_RDCR) & 0xF;
while (ucnt-- > 0) {
iack = rcin(CD180_RCSR);
- if (iack & RCSR_TOUT)
+ if (iack & RCSR_Timeout)
break;
if (iack & 0xF)
ERR(("Bad char chan %d (RCSR = %02X)\n",
@@ -1290,13 +1381,19 @@ int rc_test(nec, unit)
}
rcout(CD180_EOIR, 0);
}
- rcout(RC_BSR, 0);
+ rcout(RC_CTOUT, 0);
for (iack = chan = 0; chan < CD180_NCHAN; chan++)
if (tchans[chan].rxptr >= CD180_NFIFO)
iack++;
if (iack == CD180_NCHAN)
break;
}
+ for (chan = 0; chan < CD180_NCHAN; chan++) {
+ /* Select and reset channel */
+ rcout(CD180_CAR, chan);
+ CCRCMD(unit, chan, CCR_ResetChan);
+ }
+
if (!rcnt)
ERR(("looses characters during local loopback\n"))
/* Now, check data */
@@ -1310,24 +1407,35 @@ int rc_test(nec, unit)
}
#ifdef RCDEBUG
-
-int printrcflags(rc, comment)
+static void printrcflags(rc, comment)
struct rc_chans *rc;
char *comment;
{
u_short f = rc->rc_flags;
+ register int nec = rc->rc_rcb->rcb_addr;
- printf("rc %d/%d %s flags: %s%s%s%s%s%s%s%s%s\n",
+ printf("rc%d/%d: %s flags: %s%s%s%s%s%s%s%s%s%s%s%s\n",
rc->rc_rcb->rcb_unit, rc->rc_chan, comment,
(f & RC_DTR_OFF)?"DTR_OFF " :"",
- (f & RC_ACTOUT) ?"ACTOUT ":"",
- (f & RC_RTSFLOW)?"RTSFL " :"",
- (f & RC_CTSFLOW)?"CTSFL " :"",
- (f & RC_DORXFER)?"DORXF " :"",
- (f & RC_DOXXFER)?"DOXXF " :"",
- (f & RC_MODCHG) ?"MODC " :"",
- (f & RC_OSUSP) ?"OSUSP " :"");
- return 0;
+ (f & RC_ACTOUT) ?"ACTOUT " :"",
+ (f & RC_RTSFLOW)?"RTSFLOW " :"",
+ (f & RC_CTSFLOW)?"CTSFLOW " :"",
+ (f & RC_DORXFER)?"DORXFER " :"",
+ (f & RC_DOXXFER)?"DOXXFER " :"",
+ (f & RC_MODCHG) ?"MODCHG " :"",
+ (f & RC_OSUSP) ?"OSUSP " :"",
+ (f & RC_OSBUSY) ?"OSBUSY " :"",
+ (f & RC_WAS_BUFOVFL) ?"BUFOVFL " :"",
+ (f & RC_WAS_SILOVFL) ?"SILOVFL " :"",
+ (f & RC_SEND_RDY) ?"SEND_RDY":"");
+
+ rcout(CD180_CAR, rc->rc_chan);
+
+ printf("rc%d/%d: msvr %02x ier %02x ccsr %02x\n",
+ rc->rc_rcb->rcb_unit, rc->rc_chan,
+ rcin(CD180_MSVR),
+ rcin(CD180_IER),
+ rcin(CD180_CCSR));
}
#endif /* RCDEBUG */
@@ -1364,8 +1472,8 @@ rc_discard_output(rc)
rc->rc_flags &= ~RC_DOXXFER;
}
rc->rc_optr = rc->rc_obufend;
- enable_intr();
rc->rc_tp->t_state &= ~TS_BUSY;
+ enable_intr();
}
static void
@@ -1410,4 +1518,17 @@ disc_optim(tp, t, rc)
else
rc->rc_hotchar = 0;
}
+
+static void
+rc_wait0(nec, unit, chan, line)
+ int nec, unit, chan, line;
+{
+ int rcnt;
+
+ for (rcnt = 100; rcnt && rcin(CD180_CCR); rcnt--)
+ DELAY(15);
+ if (rcnt == 0)
+ printf("rc%d/%d: channel command timeout, rc.c line: %d\n",
+ unit, chan, line);
+}
#endif /* NRC */
diff --git a/sys/i386/isa/rcreg.h b/sys/i386/isa/rcreg.h
index 1cc3354..bd92540 100644
--- a/sys/i386/isa/rcreg.h
+++ b/sys/i386/isa/rcreg.h
@@ -42,7 +42,7 @@
#define RC_VALIDIRQ(i) ((i) < 16 && \
"\0\0\0\1\1\1\0\1\0\0\1\1\1\0\0\1"[(i) & 0xF])
-/* Riscom/8 board I/O mapping */
+/* Riscom/8 board ISA I/O mapping */
#define RC_IOMAP(r) ((((r) & 07) << 1) | (((r) & ~07) << 7))
/* I/O commands */
@@ -50,8 +50,8 @@
#define RC_IN(p,i) inb (RC_IOMAP(i) + (p))
/* Riscom on-board registers (mapping assumed) */
-#define RC_RI 0x100 /* Ring Indicator Register (read-only) */
-#define RC_DTR 0x100 /* DTR Register (write-only) */
+#define RC_RIREG 0x100 /* Ring Indicator Register (read-only) */
+#define RC_DTREG 0x100 /* DTR Register (write-only) */
#define RC_BSR 0x101 /* Board Status Register (read-only) */
#define RC_CTOUT 0x101 /* Clear Timeout (write-only) */
@@ -63,10 +63,10 @@
/* Interrupt groups */
#define RC_MODEMGRP 0x01 /* Modem interrupt group */
-#define RC_TXGRP 0x02 /* Transmitter interrupt group */
-#define RC_RXGRP 0x04 /* Receiver interrupt group */
+#define RC_RXGRP 0x02 /* Receiver interrupt group */
+#define RC_TXGRP 0x04 /* Transmitter interrupt group */
/* Priority Interrupt Level definitions */
#define RC_PILR_MODEM (0x80 | RC_MODEMGRP)
-#define RC_PILR_TX (0x80 | RC_TXGRP )
#define RC_PILR_RX (0x80 | RC_RXGRP )
+#define RC_PILR_TX (0x80 | RC_TXGRP )
OpenPOWER on IntegriCloud