brunner@bullhead.uucp (07/22/89)
Subject: Fix for multiport asychronous driver Index: /sys/caio/asy.c IBM/4.3 Description: Several problems exist with the December release of the multiport asychronous driver (rcsid 12.0): interrupts are lost, interrupts are not lost but characters are, buffers overflow, and spurious interrupts are generated. These problems are have been reported in several APARs, and degrade the performance of uucp, slip, tip, etc. Fix: Apply these patchs to the files: /sys/ca/{autoconf.c, clock.c, machparam.h, trap.c} /sys/caio/{asy.c, asyreg.h} /sys/conf/param.c /sys/sys/kern_clock.c Note that this may be accomplished easiest from /sys, using the -p1 flag to patch, e.g., patch -p1 < this_file A known timing bug is introduced with this fix for the 6150, due to a 2.4% error in the clock rate. This bug will be corrected in a following patch. diff -r -c2 sys.ship/ca/autoconf.c sys.new/ca/autoconf.c *** sys.ship/ca/autoconf.c Wed Dec 14 18:23:39 1988 --- sys.new/ca/autoconf.c Tue Jul 11 12:49:10 1989 *************** *** 12,15 **** --- 12,17 ---- #endif + + #include <syslog.h> #include "reg.h" #include "pte.h" *************** *** 219,223 **** DEBUGF(autodebug & 0x01, printf("autoconf interrupt: level %x irq %d\n", int_level, int_irq)); } else { ! printf("Stray Interrupt! level=%d info=%x", s & 07, info); if (iodebug & 0x01) printf(" icscs=%x iar=%x", icscs, iar); --- 221,225 ---- DEBUGF(autodebug & 0x01, printf("autoconf interrupt: level %x irq %d\n", int_level, int_irq)); } else { ! log(LOG_WARNING, "Stray Interrupt! level=%d info=%x", s & 07, info); if (iodebug & 0x01) printf(" icscs=%x iar=%x", icscs, iar); *************** *** 577,581 **** } } ! printf("8259 (%x) IRQ %d: %s ", i, irq, s ? "no SLIH" : "unclaimed"); } i = devunk((int)table, iar, icscs); --- 579,583 ---- } } ! log(LOG_WARNING, "8259 (%x) IRQ %d: %s ", i, irq, s ? "no SLIH" : "unclaimed"); } i = devunk((int)table, iar, icscs); *************** *** 783,787 **** if (*t == addr && addr != (caddr_t) PROBE_NULL) return (PROBE_BAD); /* oops, already in use */ - *t = addr; /* device found - remember it's address */ if (id->idr_probe == 0) { DEBUGF(autodebug, printf("no probe routine - ignored\n")); --- 785,788 ---- *************** *** 798,801 **** --- 799,803 ---- /* fall thru */ case PROBE_NOINT: + *t = addr; /* device found - remember it's address */ break; default: diff -r -c2 sys.ship/ca/clock.c sys.new/ca/clock.c *** sys.ship/ca/clock.c Fri Dec 9 14:46:06 1988 --- sys.new/ca/clock.c Tue Jul 11 12:48:01 1989 *************** *** 14,17 **** --- 14,18 ---- /* clock.c 6.1 83/07/29 */ + #include "param.h" #include "time.h" *************** *** 117,122 **** { ! if (tick * hz != MICROSECSEC) panic("MICROSECSEC % hz not 0"); if (phz) --- 118,125 ---- { ! if (tick * hz != MICROSECSEC) { ! printf("startrtclock: hz = %d\ntick= %d\n", hz, tick); panic("MICROSECSEC % hz not 0"); + } if (phz) *************** *** 156,160 **** } ! #if defined(ATR) && !defined(GPROF) /* * adjust the tick count to account for the incorrect tick frequency --- 159,163 ---- } ! #if !defined(GPROF) /* * adjust the tick count to account for the incorrect tick frequency *************** *** 161,165 **** * on the 6152 */ ! #define HZ 64 /* number of clock tics/second */ adjtick() { --- 164,168 ---- * on the 6152 */ ! #define HZ 100 /* number of clock tics/second */ adjtick() { diff -r -c2 sys.ship/ca/machparam.h sys.new/ca/machparam.h *** sys.ship/ca/machparam.h Fri Dec 9 14:47:21 1988 --- sys.new/ca/machparam.h Tue Jul 11 12:50:27 1989 *************** *** 11,15 **** static char *rcsidca_param = "$Header: V1.3,v 1.1 89/07/14 15:15:50 brunner Locked $"; #endif - /* * IMPORTANT NOTE: --- 11,14 ---- *************** *** 101,110 **** char ccr_default; /* default value for CCR */ ! #ifndef ATR ! #define spltty() spl1() ! #define splttl() spl5() ! #else ! #define spltty() spl5() ! #endif ATR #define splclock() spl6() #define splbio() _spl1() --- 100,105 ---- char ccr_default; /* default value for CCR */ ! #define splttl() spl4() ! #define spltty() spl4() #define splclock() spl6() #define splbio() _spl1() diff -r -c2 sys.ship/ca/trap.c sys.new/ca/trap.c *** sys.ship/ca/trap.c Fri Dec 9 14:45:57 1988 --- sys.new/ca/trap.c Tue Jul 11 12:48:41 1989 *************** *** 11,15 **** static char *rcsid = "$Header: V1.3,v 1.1 89/07/14 15:15:50 brunner Locked $"; #endif - #if defined(DEBUG) && !defined(SYSCALLTRACE) #define SYSCALLTRACE --- 11,14 ---- *************** *** 707,716 **** softkls(); } - #if NASY > 0 - if (softlevel & SOFT_ASY) { - softlevel &= ~SOFT_ASY; - softasy(); - } - #endif NASY #if NPSP > 0 if (softlevel & SOFT_PSP) { --- 706,709 ---- diff -r -c2 sys.ship/caio/asy.c sys.new/caio/asy.c *** sys.ship/caio/asy.c Fri Dec 9 14:50:57 1988 --- sys.new/caio/asy.c Tue Jul 11 12:52:24 1989 *************** *** 11,15 **** static char *rcsid = "$Header: V1.3,v 1.1 89/07/14 15:15:50 brunner Locked $"; #endif - /* * Multiport asynchronous driver --- 11,14 ---- *************** *** 17,20 **** --- 16,20 ---- #include "asy.h" #if NASY > 0 + #include "../h/param.h" #include "../h/conf.h" *************** *** 28,31 **** --- 28,32 ---- #include "../h/file.h" #include "../machine/debug.h" + #include <syslog.h> #ifdef ATR *************** *** 102,108 **** */ #define NPORTS 4 /* number of serial port per multiport card */ ! #define MAXUNIT (NASY * NPORTS) /* total number of ports configured */ struct cbuf asycbuf[MAXUNIT]; - struct clist asyxclist; /* * Terminology: --- 103,109 ---- */ #define NPORTS 4 /* number of serial port per multiport card */ ! #define MAXCTLR 6 /* total ctrl cards */ ! #define MAXUNIT 18 /* total number of ports configured */ struct cbuf asycbuf[MAXUNIT]; /* * Terminology: *************** *** 134,144 **** #define PORT(unit) ((unit) & 0x03) #define PORTMASK(port) ((1 << (port)) & 0x0f) struct tty asy[MAXUNIT]; ! int nasy = MAXUNIT; #if NAP > 0 int asyoutc(); #endif ! int asystart(), ttrstrt(), asyattach(), asyprobe(), asyint(); /* following is a hokey test for a quad card */ --- 135,161 ---- #define PORT(unit) ((unit) & 0x03) #define PORTMASK(port) ((1 << (port)) & 0x0f) + + struct tty asy[MAXUNIT]; ! /* Average new into old with aging factor time */ ! #define ave(smooth, cnt, time) \ ! smooth = ((time - 1) * (smooth) + (cnt)) / (time) ! #define FASTTIMER (hz/100) /* scan rate with silos on */ ! #define SLOWTIMER (hz) /* scan rate without silos on */ ! int asysilos = 0; /* mask of ports with silo in use */ ! int asytimeout = 0; /* mask ports with enq timeout set */ ! int asychars[MAXUNIT]; /* recent input count */ ! int asyinchars[MAXUNIT]; /* previous input count */ ! int asyrate[MAXUNIT]; /* smoothed input count */ ! int asyhighrate = 100; /* silo on if dhchars >= dhhighrate */ ! int asylowrate = 15; ! int asyfasttimers = 0; /*DEBUG*/ ! static short timerstarted; + #if NAP > 0 int asyoutc(); #endif ! int asystart(), ttrstrt(), asyattach(), asyprobe(), asyint(), asytimer(); /* following is a hokey test for a quad card */ *************** *** 201,212 **** BADD_ADDR, BADD_ADDR, BADD_ADDR, BADD_ADDR, /* 12 - 15 */ }; - #define ASYFIFO 1 /* RT can have FIFO cards */ #endif IBMRTPC ! char asysoftCAR[NASY]; /* software carrier detect */ ! #ifdef ASYFIFO ! unsigned char asysoftFIFO[NASY]; /* software - FIFO mode */ ! #define fifomode 0xff ! #endif struct iocc_device *asydinfo[NASY]; --- 218,225 ---- BADD_ADDR, BADD_ADDR, BADD_ADDR, BADD_ADDR, /* 12 - 15 */ }; #endif IBMRTPC ! char asysoftCAR[NASY]; /* software carrier detect */ ! unsigned char asysoftFIFO[MAXUNIT]; /* software - FIFO mode */ struct iocc_device *asydinfo[NASY]; *************** *** 230,233 **** --- 243,247 ---- DEBUGF(ttydebug, printf("asyprobe(%x):\n", addr)); + if (isquad(asyp)) { *************** *** 290,293 **** --- 304,308 ---- register int ctlr = iod->iod_unit; register int port; /* line number on this ctlr */ + register int saveiir; register struct asydevice *addr = ASY_ADDR(iod->iod_addr); *************** *** 300,310 **** tp->t_cbufp = &asycbuf[UNIT(ctlr,port)]; tp->t_state = 0; if (!isquad(addr)) break; /* only one port per PC card */ } - asysoftCAR[iod->iod_unit] = iod->iod_flags; /* carrier detect */ } - /*ARGSUSED*/ asyopen(dev, flag) --- 315,337 ---- tp->t_cbufp = &asycbuf[UNIT(ctlr,port)]; tp->t_state = 0; + /* these instructions have no effect on non-FIFO card */ + /* clear fifos */ + IOOUT(&addr->fcr, FCR_FCR1|FCR_FCR2); + /* enable FIFO mode, interrupt at 14 chars */ + IOOUT(&addr->fcr, + FCR_FCR0|FCR_FCR6|FCR_FCR7); + saveiir=IOIN(&addr->iir) ; + if (saveiir & (IIR_FIFO1 | IIR_FIFO2)) { + ++asysoftFIFO[UNIT(ctlr,port)]; + } + else + asysoftFIFO[UNIT(ctlr,port)] = 0; + + asysoftCAR[iod->iod_unit] = iod->iod_flags; /* carrier detect */ if (!isquad(addr)) break; /* only one port per PC card */ } } /*ARGSUSED*/ asyopen(dev, flag) *************** *** 313,321 **** register struct tty *tp; register int unit = minor(dev); ! register int s, error; register struct asydevice *asyaddr; register struct iocc_device *iod; int ctlr = CTLR(unit); - register unsigned char saveiir; DEBUGF(ttydebug & SHOW_OPEN, printf("asyopen%x: \n", unit)); --- 340,347 ---- register struct tty *tp; register int unit = minor(dev); ! register int s, msrbits, error; register struct asydevice *asyaddr; register struct iocc_device *iod; int ctlr = CTLR(unit); DEBUGF(ttydebug & SHOW_OPEN, printf("asyopen%x: \n", unit)); *************** *** 346,383 **** asyparam(unit); - /* turn DTR RTS on */ - IOOUT(&asyaddr->mcr, MCR_IEN | MCR_DTR | MCR_RTS); /* enable receive, line, modem and transmit interrupts */ IOOUT(&asyaddr->ier, IER_DR | IER_LSR | IER_MSR | IER_THRE); ! ! #ifdef ASYFIFO ! /* enable FIFO mode */ ! /* This has no effect for a non-buffered card. */ ! IOOUT(&asyaddr->fcr, FCR_FCR0); ! #endif ASYFIFO ! (void) splx(s); } - s = spl_asy(); /* wait for carrier to come up */ - /* check if modem control is on or the carrier is up */ - if ( ( (IOIN(&asyaddr->msr)) & MSR_DCD) || - ( asysoftCAR[ctlr] & PORTMASK(PORT(unit)) ) ) { - tp->t_state |= TS_CARR_ON; - saveiir=IOIN(&asyaddr->iir) ; - #ifdef ASYFIFO - if (saveiir & (IIR_FIFO1 | IIR_FIFO2)) { - asysoftFIFO[ctlr] = fifomode; - DEBUGF(ttydebug & SHOW_OPEN, - printf("asyopen - fifomode\n")); - } - #endif ASYFIFO - } - while ( (tp->t_state & TS_CARR_ON) == 0 ) { tp->t_state |= TS_WOPEN; ! sleep((caddr_t) & tp->t_rawq, TTIPRI); } (void) splx(s); --- 372,401 ---- asyparam(unit); + if (asysoftFIFO[unit]) { + /* flush FIFO */ + IOOUT(&asyaddr->fcr, FCR_FCR1|FCR_FCR2); + /* enable FIFO mode, interrupt at 1 chars */ + IOOUT(&asyaddr->fcr, FCR_FCR0); + } /* enable receive, line, modem and transmit interrupts */ IOOUT(&asyaddr->ier, IER_DR | IER_LSR | IER_MSR | IER_THRE); ! /* turn DTR RTS on */ ! if (isquad(asyaddr)) ! IOOUT(&asyaddr->mcr, MCR_DTR | MCR_RTS); ! else ! IOOUT(&asyaddr->mcr, MCR_IEN | MCR_DTR | MCR_RTS); (void) splx(s); } s = spl_asy(); + /* check if carrier is or up modem is on */ + msrbits = IOIN(&asyaddr->msr); + if ((msrbits & MSR_DCD) || + ( asysoftCAR[ctlr] & PORTMASK(PORT(unit)) ) ) + tp->t_state |= TS_CARR_ON; /* wait for carrier to come up */ while ( (tp->t_state & TS_CARR_ON) == 0 ) { tp->t_state |= TS_WOPEN; ! sleep((caddr_t) &tp->t_rawq, TTIPRI); } (void) splx(s); *************** *** 389,392 **** --- 407,414 ---- DEBUGF(ttydebug & SHOW_OPEN, printf(" ldisc=%x, flags=%x, state=%x\n", tp->t_line, tp->t_flags, tp->t_state )); + if (timerstarted == 0) { + timeout(asytimer, (caddr_t) 0, SLOWTIMER); + ++timerstarted; + } return ( error ); } *************** *** 406,411 **** --- 428,436 ---- tp->t_state |= TS_CLOSE; /* close in progress */ + asychars[unit] = 0; + asysilos &= ~(1 << unit); timeout(asycls, tp, asyouttime(tp)); /* set timeout for close */ + (*linesw[tp->t_line].l_close)(tp); IOOUT(&asyaddr->lcr, IOIN(&asyaddr->lcr) & ~LCR_SETB); /* clr break */ *************** *** 412,416 **** if ((tp->t_state&(TS_WOPEN|TS_HUPCLS))||(tp->t_state&TS_ISOPEN)==0) { IOOUT(&asyaddr->ier, ~(IER_DR | IER_LSR | IER_MSR) ); ! IOOUT(&asyaddr->mcr, MCR_IEN); IOOUT(&asyaddr->fcr, ~(FCR_FCR0)); DEBUGF(ttydebug & SHOW_OPEN, --- 437,444 ---- if ((tp->t_state&(TS_WOPEN|TS_HUPCLS))||(tp->t_state&TS_ISOPEN)==0) { IOOUT(&asyaddr->ier, ~(IER_DR | IER_LSR | IER_MSR) ); ! if (isquad(asyaddr)) ! IOOUT(&asyaddr->mcr, 0); ! else ! IOOUT(&asyaddr->mcr, MCR_IEN); IOOUT(&asyaddr->fcr, ~(FCR_FCR0)); DEBUGF(ttydebug & SHOW_OPEN, *************** *** 425,429 **** --- 453,515 ---- } + int asyfasttimers, asytransitions, asyslowtimers, asybogons; /*DEBUG*/ /* + * At software clock interrupt time, check status. + * Empty all the asy silos that are in use, and decide whether + * to turn any silos off or on. + */ + asytimer() + { + register int unit = 0, s; + static int timercalls; + register struct tty *tp; + register struct asydevice *asyaddr; + + if (asysilos) { + s = spl_asy(); + asyfasttimers++; /*DEBUG*/ + timercalls++; + for (unit = 0; unit < MAXUNIT; unit++) + if (asysilos & (1 << unit)) { + tp = &asy[unit]; + asychars[unit] += asyrint(unit, tp, + (struct asydevice *)tp->t_addr); + } + splx(s); + } + if ((asysilos == 0) || ((timercalls+=FASTTIMER) >= SLOWTIMER)) { + asyslowtimers++; /*DEBUG*/ + timercalls = 0; + for (unit = 0; unit < MAXUNIT; unit++) { + ave(asyrate[unit], asychars[unit], 8); + if ((asychars[unit] >= asyhighrate) && + ((asysilos & (1 << unit)) == 0)) { + asysilos |= (1 << unit); + asytransitions++; /*DEBUG*/ + if (asysoftFIFO[unit]) { + tp = &asy[unit]; + asyaddr = (struct asydevice *)tp->t_addr; + /* FIFO mode, trigger at 14 chars */ + IOOUT(&asyaddr->fcr, + FCR_FCR0|FCR_FCR6|FCR_FCR7); + } + } else if ((asysilos & (1 << unit)) && + (asyrate[unit] < asylowrate)) { + asysilos &= ~(1 << unit); + if (asysoftFIFO[unit]) { + tp = &asy[unit]; + asyaddr = (struct asydevice *)tp->t_addr; + /* FIFO mode, trigger at 1 char */ + IOOUT(&asyaddr->fcr, FCR_FCR0); + } + } + asychars[unit] = 0; + } + } + timeout(asytimer, (caddr_t) 0, asysilos? FASTTIMER: SLOWTIMER); + } + + + /* * return an overestimate of the number of clock ticks it will take * to output the remaining output after close has started *************** *** 450,454 **** if (tp->t_state & TS_CLOSE) { /* if close in progress */ ttyflush(tp, FREAD|FWRITE); ! tp->t_state &= ~TS_CLOSE; /* close in progress */ } (void) splx(s); --- 536,540 ---- if (tp->t_state & TS_CLOSE) { /* if close in progress */ ttyflush(tp, FREAD|FWRITE); ! tp->t_state = 0; } (void) splx(s); *************** *** 455,458 **** --- 541,545 ---- } + /*ARGSUSED*/ asyread(dev, uio) *************** *** 524,531 **** break; case TIOCSDTR: /* Set DTR and RTS */ ! IOOUT(&asyaddr->mcr, MCR_IEN | MCR_DTR | MCR_RTS); break; case TIOCCDTR: /* Clear DTR and RTS */ ! IOOUT(&asyaddr->mcr, MCR_IEN); break; case TIOCSETT: /* Set trigger level */ --- 611,624 ---- break; case TIOCSDTR: /* Set DTR and RTS */ ! if (isquad(asyaddr)) ! IOOUT(&asyaddr->mcr, MCR_DTR | MCR_RTS); ! else ! IOOUT(&asyaddr->mcr, MCR_IEN | MCR_DTR | MCR_RTS); break; case TIOCCDTR: /* Clear DTR and RTS */ ! if (isquad(asyaddr)) ! IOOUT(&asyaddr->mcr, 0); ! else ! IOOUT(&asyaddr->mcr, MCR_IEN); break; case TIOCSETT: /* Set trigger level */ *************** *** 541,546 **** else trigger_bits = (FCR_FCR7 | FCR_FCR6); ! ! IOOUT(&asyaddr->fcr, (FCR_FCR0 | FCR_FCR3 | trigger_bits)); break; default: --- 634,638 ---- else trigger_bits = (FCR_FCR7 | FCR_FCR6); ! IOOUT(&asyaddr->fcr, (FCR_FCR0 | trigger_bits)); break; default: *************** *** 599,603 **** register int ctlr; { - register unsigned char port; register int unit = UNIT(ctlr,0); register struct asydevice *asyaddr = ASY_ADDR(asydinfo[ctlr]->iod_addr); --- 691,694 ---- *************** *** 604,608 **** register struct tty *tp; register unsigned char saveiir; ! register int i, didit = 0; #ifdef ATR --- 695,701 ---- register struct tty *tp; register unsigned char saveiir; ! register unsigned char port = 0; ! register char c; ! register int counter; #ifdef ATR *************** *** 617,687 **** DEBUGF(ttydebug & SHOW_INTR,printf("asyint%d: addr=%x ",unit,asyaddr)); #ifdef IBMRTPC ! if (isquad(asyaddr)) { ! port = IOIN(&asyaddr->ppir); DEBUGF(ttydebug & SHOW_INTR, printf("port=%x ",port)); ! for ( i = 0 ; i < NPORTS ; i++, unit++ ) { ! if (port & PORTMASK(i) ) { ! tp = &asy[unit]; ! asyaddr = (struct asydevice *)tp->t_addr; ! while (((saveiir=IOIN(&asyaddr->iir))&IIR_PEND)==0) { ! DEBUGF(ttydebug & SHOW_REGS, ! printf("saveiir=%x\n", saveiir)); ! switch (saveiir & IIR_MASK) { ! case IIR_LSR: ! case IIR_CTI: ! case IIR_RXB: ! asyrint(unit, tp, asyaddr); ! didit++; ! break; ! case IIR_TXB: ! asyxint(unit, tp, asyaddr); ! didit++; ! break; ! case IIR_MSR: ! asymint(unit, tp, asyaddr); ! didit++; ! break; ! default: ! printf("asy%d:iir=%x\n",unit,saveiir); ! break; ! } ! } } } ! if (!isquad(asyaddr)) { ! if ( didit ) ! IOOUT(asyreset[asydinfo[ctlr]->iod_irq & 0xf], 0); ! } ! } else #endif IBMRTPC ! { ! tp = &asy[unit]; ! asyaddr = (struct asydevice *)tp->t_addr; ! while (( (saveiir=IOIN(&asyaddr->iir) ) & IIR_PEND) == 0) { ! switch (saveiir & IIR_MASK) { ! case IIR_LSR: ! case IIR_RXB: ! asyrint(unit, tp, asyaddr); ! didit++; ! break; ! case IIR_TXB: ! asyxint(unit, tp, asyaddr); ! didit++; ! break; ! case IIR_MSR: ! asymint(unit, tp, asyaddr); ! didit++; ! break; ! default: ! printf("asy%d:iir=%x\n",unit,saveiir); ! break; } } ! } ! DEBUGF(ttydebug & SHOW_INTR, printf("didit=%x\n",didit )); ! return( didit == 0 ); } /*ARGSUSED*/ asyrint(unit, tp, asyaddr) register int unit; --- 710,793 ---- DEBUGF(ttydebug & SHOW_INTR,printf("asyint%d: addr=%x ",unit,asyaddr)); #ifdef IBMRTPC ! if (isquad(asyaddr)) { ! port = IOIN(&asyaddr->ppir); ! port &= 0x0F; DEBUGF(ttydebug & SHOW_INTR, printf("port=%x ",port)); ! if (0 == port) { ! saveiir = IOIN(&asyaddr->iir); ! if ((0xC0 & saveiir)||(0x01 == saveiir)) ! ; ! else { ! log(LOG_WARNING, ! "asyint: no ppir, saveiir = %x\n", ! saveiir); } + return(0); } ! portselect: ! if (port & PORT_A) { ! unit = UNIT(ctlr,0); ! port &= ~PORT_A; ! } ! else if (port & PORT_B) { ! unit = UNIT(ctlr,1); ! port &= ~PORT_B; ! } ! else if (port & PORT_C) { ! unit = UNIT(ctlr,2); ! port &= ~PORT_C; ! } ! else if (port & PORT_D) { ! unit = UNIT(ctlr,3); ! port &= ~PORT_D; ! } ! else { ! unit = UNIT(ctlr,0); ! printf("asyint: Bogus port = %x\n", port); ! } ! } #endif IBMRTPC ! tp = &asy[unit]; ! asyaddr = (struct asydevice *)tp->t_addr; ! saveiir = IOIN(&asyaddr->iir); ! if (IIR_PEND & saveiir) { ! ++asybogons; ! return(0); ! } ! counter = asychars[unit]; ! do { ! switch (saveiir & IIR_MASK) { ! case IIR_RXB: ! while (IOIN(&asyaddr->lsr) & LSR_DR) { ! c = IOIN(&asyaddr->rxb); ! (*linesw[tp->t_line].l_rint)(c,tp); ! ++counter; } + break; + case IIR_LSR: + case IIR_CTI: + counter += asyrint(unit, tp, asyaddr); + break; + case IIR_TXB: + asyxint(unit, tp, asyaddr); + break; + case IIR_MSR: + asymint(unit, tp, asyaddr); + break; + default: + printf("asy%d:iir=%x\n",unit,saveiir); + break; } ! } while (((saveiir=IOIN(&asyaddr->iir))&IIR_PEND)==0); ! asychars[unit] = counter; ! #ifdef IBMRTPC ! if ((port) && isquad(asyaddr)) ! goto portselect; /*more than one port pending*/ ! #endif ! return(0); } /*ARGSUSED*/ + int asyrint(unit, tp, asyaddr) register int unit; *************** *** 689,693 **** register struct asydevice *asyaddr; { ! register int c, err; register char savelsr; int charcount = 0; --- 795,799 ---- register struct asydevice *asyaddr; { ! register int c; register char savelsr; int charcount = 0; *************** *** 728,750 **** if (savelsr & LSR_OR) ! printf("asy%d: overrun error\n", unit ); DEBUGF(ttydebug & SHOW_CHARS, printf("GOT -> (%c) (%x)\n", c, c)); } /* end if errors */ ! DEBUGF(ttydebug & SHOW_REGS, printf("TTYBUF\n")); ! charcount++; ! CPUT( tp->t_cbufp, c, err ); ! if ( err ) { ! printf("asy%d: cbuf full\n", unit ); ! break; ! } } /* end else */ } /* end while */ - if ( charcount ) { - TTY_ENQUEUE( &ttyintrq, tp ); - setsoftTTY(); - } DEBUGF(ttydebug & SHOW_INTR, printf("asy%d: charcount=%d\n",unit,charcount)); } --- 834,849 ---- if (savelsr & LSR_OR) ! log(LOG_WARNING, "asy%d: overrun\n", unit); DEBUGF(ttydebug & SHOW_CHARS, printf("GOT -> (%c) (%x)\n", c, c)); } /* end if errors */ ! (*linesw[tp->t_line].l_rint)(c,tp); } /* end else */ + if (charcount > 32) + break; /* DEBUG */ } /* end while */ DEBUGF(ttydebug & SHOW_INTR, printf("asy%d: charcount=%d\n",unit,charcount)); + return(charcount); } *************** *** 755,767 **** register struct asydevice *asyaddr; { - DEBUGF(ttydebug & SHOW_INTR, printf("asyxint%d: ", unit)); - #ifdef IBMRTPC - char c = (char) unit; - putc(c, &asyxclist); - setsoftASY(); - return; - #else - #if NAP > 0 if (tp->t_line == APLDISC) { --- 854,858 ---- *************** *** 778,818 **** } DEBUGF(ttydebug & SHOW_INTR, printf("asyxint end\n")); - #endif IBMRTPC } - - #ifdef IBMRTPC - softasy() - { - register struct tty *tp; - char unit; - register int s = spl5(); - register struct asydevice *asyaddr; - - unit = getc(&asyxclist); - (void) splx(s); - s = spl_asy(); - tp = &asy[unit]; - asyaddr = (struct asydevice *)tp->t_addr; - - #if NAP > 0 - if (tp->t_line == APLDISC) { - DEBUGF(ttydebug & SHOW_INTR, printf("calling AP xint \n")); - (*linesw[tp->t_line].l_start)(tp); - } else - #endif NAP - { - tp->t_state &= ~TS_BUSY; - if (tp->t_line) - (*linesw[tp->t_line].l_start)(tp); - else - asystart(tp); - } - DEBUGF(ttydebug & SHOW_INTR, printf("asyxint end\n")); - - (void) splx(s); - } - #endif IBMRTPC - asystart(tp) register struct tty *tp; --- 869,874 ---- *************** *** 819,823 **** { register struct asydevice *asyaddr = (struct asydevice *)tp->t_addr; ! register int c, s; DEBUGF(ttydebug & SHOW_IO, printf("asystart addr=%x\n", asyaddr)); --- 875,880 ---- { register struct asydevice *asyaddr = (struct asydevice *)tp->t_addr; ! register int i, s; ! register int c = 0; DEBUGF(ttydebug & SHOW_IO, printf("asystart addr=%x\n", asyaddr)); *************** *** 830,852 **** * if it's currently active, or delaying, no need to do anything. */ ! if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) { } - DEBUGF(ttydebug & SHOW_CHARS, - printf("asystart - non-fifomode/n")); - while (IOIN(&asyaddr->lsr) & LSR_THRE) { - if ((tp->t_outq.c_cc <= 0) || (c = getc(&tp->t_outq)) == -1) { - goto out1; - } - DEBUGF(ttydebug & SHOW_CHARS, - printf("put (%c) (%x)\n", (char)(c), (char)(c) )); - if ( tp->t_flags & (RAW | LITOUT) || (c <= 0177) ) { - IOOUT(&asyaddr->txb, c); - } else { - timeout(ttrstrt, (caddr_t)tp, (c & 0177)); - tp->t_state |= TS_TIMEOUT; - DEBUGF(ttydebug & SHOW_CHARS,printf("asystart timeout\n")); - goto out1; - } - } /* end of while */ tp->t_state |= TS_BUSY; DEBUGF(ttydebug & SHOW_REGS, printf("asystart: enable TX int\n")); --- 887,921 ---- * if it's currently active, or delaying, no need to do anything. */ ! if (tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP)) ! goto out2; ! if (IOIN(&asyaddr->lsr) & LSR_THRE) { ! /* unit = tp - asy */ ! if ((asysoftFIFO[tp - asy]) && ! (tp->t_flags & (RAW | LITOUT))) { ! for (i=0; i<9; i++) { ! if (tp->t_outq.c_cc <= 0) ! goto out1; ! if ((c = getc(&tp->t_outq)) == -1) ! goto out1; ! IOOUT(&asyaddr->txb, c); ! } ! } ! ! do { ! if ((tp->t_outq.c_cc <= 0) || (c = getc(&tp->t_outq)) == -1) ! goto out1; ! DEBUGF(ttydebug & SHOW_CHARS, ! printf("put (%c) (%x)\n", (char)(c), (char)(c) )); ! if ( tp->t_flags & (RAW | LITOUT) || (c <= 0177) ) ! IOOUT(&asyaddr->txb, c); ! else { ! timeout(ttrstrt, (caddr_t)tp, (c & 0177)); ! tp->t_state |= TS_TIMEOUT; ! DEBUGF(ttydebug & SHOW_CHARS, ! printf("asystart timeout\n")); ! goto out1; ! } ! } while (IOIN(&asyaddr->lsr) & LSR_THRE); } tp->t_state |= TS_BUSY; DEBUGF(ttydebug & SHOW_REGS, printf("asystart: enable TX int\n")); *************** *** 896,900 **** DEBUGF( ttydebug & SHOW_INTR,printf("Carrier detect ")); if ((tp->t_state & TS_CARR_ON) == 0) { ! wakeup((caddr_t) & tp->t_rawq); tp->t_state |= TS_CARR_ON; } --- 971,976 ---- DEBUGF( ttydebug & SHOW_INTR,printf("Carrier detect ")); if ((tp->t_state & TS_CARR_ON) == 0) { ! wakeup((caddr_t) &tp->t_rawq); ! (*linesw[tp->t_line].l_modem)(tp, 1); tp->t_state |= TS_CARR_ON; } *************** *** 906,909 **** --- 982,986 ---- ttyflush(tp, FREAD | FWRITE); } + (*linesw[tp->t_line].l_modem)(tp, 0); tp->t_state &= ~TS_CARR_ON; } *************** *** 911,915 **** DEBUGF(ttydebug & SHOW_INTR, printf("asymint end\n")); } - asyselect(dev, rw) --- 988,991 ---- diff -r -c2 sys.ship/caio/asyreg.h sys.new/caio/asyreg.h *** sys.ship/caio/asyreg.h Fri Dec 9 14:50:59 1988 --- sys.new/caio/asyreg.h Tue Jul 11 12:54:01 1989 *************** *** 39,43 **** #define IIR_PEND 0x01 /* This Bit is 0 when an interrupt is pending */ #define IIR_CTI 0x0c /* Character timeout - FIFO mode only */ ! #define IIR_MASK 0x07 /* Mask off just the meaningful bits in iir */ /* Interrupt types in oder of priority (high to low) */ #define IIR_LSR 0x06 /* Line Status (Some error condition) */ --- 39,43 ---- #define IIR_PEND 0x01 /* This Bit is 0 when an interrupt is pending */ #define IIR_CTI 0x0c /* Character timeout - FIFO mode only */ ! #define IIR_MASK 0x0F /* Mask off just the meaningful bits in iir */ /* Interrupt types in oder of priority (high to low) */ #define IIR_LSR 0x06 /* Line Status (Some error condition) */ *************** *** 92,96 **** #define MSR_DDCD 0x08 /* Delta Data Carrier Detect (DRLSD) */ #define MSR_CTS 0x10 /* Clear To Send */ ! #define MSR_DSD 0x20 /* Data Set Ready */ #define MSR_RI 0x40 /* Ring Indicator */ #define MSR_DCD 0x80 /* Data Carrier Detect (RLSD) */ --- 92,96 ---- #define MSR_DDCD 0x08 /* Delta Data Carrier Detect (DRLSD) */ #define MSR_CTS 0x10 /* Clear To Send */ ! #define MSR_DSR 0x20 /* Data Set Ready */ #define MSR_RI 0x40 /* Ring Indicator */ #define MSR_DCD 0x80 /* Data Carrier Detect (RLSD) */ *************** *** 103,105 **** #define spl_asy() _spl3() - --- 103,104 ---- diff -r -c2 sys.ship/conf/param.c sys.new/conf/param.c *** sys.ship/conf/param.c Fri Dec 9 14:53:03 1988 --- sys.new/conf/param.c Tue Jul 11 12:51:27 1989 *************** *** 67,71 **** #endif #ifdef ibm032 ! #define HZ 64 #endif #ifdef ibm370 --- 67,71 ---- #endif #ifdef ibm032 ! #define HZ 100 #endif #ifdef ibm370 diff -r -c2 sys.ship/sys/kern_clock.c sys.new/sys/kern_clock.c *** sys.ship/sys/kern_clock.c Fri Dec 9 15:05:04 1988 --- sys.new/sys/kern_clock.c Tue Jul 11 12:54:43 1989 *************** *** 135,139 **** } ! #if defined(ATR) && !defined(GPROF) adjtick(); #endif --- 135,139 ---- } ! #if !defined(GPROF) adjtick(); #endif Eric Brunner uunet!ibmsupt!brunner
brunner@bullhead.uucp (11/17/89)
Subject: Patch for multiport asychronous driver Index: /sys/caio/asy.c, IBM/4.3 Description: A bug was introduced in V1.3 limiting minor device numbers. I/O on /dev/ttyc1 results in a trap. Fix: Apply the following patch: *** asy.c Wed Nov 15 14:33:41 1989 --- asy.c.fix Wed Nov 15 14:33:10 1989 *************** *** 102,109 **** * ----------- */ #define NPORTS 4 /* number of serial port per multiport card */ ! #define MAXCTLR 6 /* total ctrl cards */ ! #define MAXUNIT 18 /* total number of ports configured */ struct cbuf asycbuf[MAXUNIT]; /* * Terminology: --- 102,108 ---- * ----------- */ #define NPORTS 4 /* number of serial port per multiport card */ ! #define MAXUNIT (NASY * NPORTS) /* total number of ports configured */ struct cbuf asycbuf[MAXUNIT]; /* * Terminology: Eric Brunner, Consultant, IBM AWD Palo Alto (415) 855-4486 inet: brunner@monet.berkeley.edu uucp: uunet!ibmsupt!brunner
brunner@bullhead.uucp (11/17/89)
Subject: Patch for multiport asychronous driver Index: /sys/caio/asy.c, IBM/4.3 Description: The watchdog close timer expires too early. In the case of the IBM Proprinter at 9600 bps this causes the last few lines of output to be lost. Fix: Apply the following patch: *** asy.c Tue Nov 14 15:11:57 1989 --- asy.c.fix Tue Nov 14 15:20:27 1989 *************** *** 520,526 **** asyouttime(tp) register struct tty *tp; { ! return (hz + 3 * hz * tp->t_outq.c_cc / (2 * asyoutputrate[tp->t_ospeed])); } /* --- 520,527 ---- asyouttime(tp) register struct tty *tp; { ! return (18 * hz * (1 + tp->t_outq.c_cc / asyoutputrate[tp->t_ospeed])); ! } /* Eric Brunner, Consultant, IBM AWD Palo Alto (415) 855-4486 inet: brunner@monet.berkeley.edu uucp: uunet!ibmsupt!brunner