4.3 dmf driver that works with emulex boards
Keith Muller
muller at sdcc7.ucsd.EDU
Sat Aug 2 18:55:37 AEST 1986
Since a lot of people seem to have problems with emulex dmf's,
enclosed is diffs from the june 86 release of 4.3 for a dmf driver
that works with emulex cs11 and cs21's. NOTE: make sure you get prom
upgrades from emulex if you have an OLD board. The old microcode will
wedge your system while doing dma output (or all 8 ports on a dmf will
stop working).
If you have questions comments etc pleas contact me.
Keith muller
University of California, San Diego
muller at sdcsvax.ucsd.edu
muller at nprdc.arpa
*** vaxuba/dmf.c Thu Jun 5 01:07:44 1986
--- local/dmf.c Thu Jun 19 10:54:55 1986
***************
*** 68,75 ****
struct uba_driver dmfdriver =
{ dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
! int dmf_timeout = 10; /* silo timeout, in ms */
! int dmf_mindma = 4; /* don't dma below this point */
/*
* Local variables for the driver
--- 68,75 ----
struct uba_driver dmfdriver =
{ dmfprobe, 0, dmfattach, 0, dmfstd, "dmf", dmfinfo };
! int dmf_timeout = 4; /* silo timeout, in ms */
! int dmf_mindma = 3; /* don't dma below this point */
/*
* Local variables for the driver
***************
*** 122,129 ****
int dmf_ubinfo[NUBA]; /* info about allocated unibus map */
int cbase[NUBA]; /* base address in unibus map */
#define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
- char dmf_dma[NDMF*8];
/*
* Routine for configuration to set dmf interrupt.
*/
--- 122,137 ----
int dmf_ubinfo[NUBA]; /* info about allocated unibus map */
int cbase[NUBA]; /* base address in unibus map */
#define UBACVT(x, uban) (cbase[uban] + ((x)-(char *)cfree))
+ struct dmfa_softc {
+ int dmfa_state;
+ int dmfa_count;
+ } dmfa_softc[NDMF * 8];
+
+ #define ST_TXOFF (0x01) /* tx turned off */
+ #define ST_DMA (0x02) /* tx doing dma output */
+ #define ST_INBUSY (0x04) /* tx off while in TS_BUSY */
+
/*
* Routine for configuration to set dmf interrupt.
*/
***************
*** 275,280 ****
--- 283,289 ----
#ifndef PORTSELECTOR
}
#endif PORTSELECTOR
+ dmfa_softc[unit].dmfa_state = 0;
dmfparam(unit);
}
/*
***************
*** 566,572 ****
register struct dmfdevice *addr;
register struct uba_device *ui;
register int t;
! short cntr;
ui = dmfinfo[dmf];
addr = (struct dmfdevice *)ui->ui_addr;
--- 575,582 ----
register struct dmfdevice *addr;
register struct uba_device *ui;
register int t;
! struct dmfa_softc *sc0 = &dmfa_softc[unit0];
! register struct dmfa_softc *sc;
ui = dmfinfo[dmf];
addr = (struct dmfdevice *)ui->ui_addr;
***************
*** 573,594 ****
while ((t = addr->dmfcsr) & DMF_TI) {
if (t & DMF_NXM)
/* SHOULD RESTART OR SOMETHING... */
! printf("dmf%d: NXM line %d\n", dmf, t >> 8 & 7);
t = t >> 8 & 7;
tp = tp0 + t;
! tp->t_state &= ~TS_BUSY;
! if (tp->t_state&TS_FLUSH)
tp->t_state &= ~TS_FLUSH;
! else if (dmf_dma[unit0 + t]) {
! /*
! * Do arithmetic in a short to make up
! * for lost 16&17 bits.
! */
! addr->dmfcsr = DMFIR_TBA | DMF_IE | t;
! cntr = addr->dmftba -
! UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
! ndflush(&tp->t_outq, (int)cntr);
! }
if (tp->t_line)
(*linesw[tp->t_line].l_start)(tp);
else
--- 583,600 ----
while ((t = addr->dmfcsr) & DMF_TI) {
if (t & DMF_NXM)
/* SHOULD RESTART OR SOMETHING... */
! log(LOG_WARNING, "dmf%d: NXM line %d\n", dmf, t >> 8 & 7);
t = t >> 8 & 7;
tp = tp0 + t;
! sc = sc0 + t;
! if (tp->t_state&TS_FLUSH) {
tp->t_state &= ~TS_FLUSH;
! addr->dmfcsr = DMF_IE | DMFIR_LCR | t;
! addr->dmflctms = addr->dmflctms | DMF_TE;
! } else if (sc->dmfa_state & ST_DMA)
! ndflush(&tp->t_outq, sc->dmfa_count);
! sc->dmfa_state = 0;
! tp->t_state &= ~TS_BUSY;
if (tp->t_line)
(*linesw[tp->t_line].l_start)(tp);
else
***************
*** 604,614 ****
--- 610,622 ----
{
register struct dmfdevice *addr;
register int unit, nch;
+ register struct dmfa_softc *sc;
int s;
register int dmf;
unit = minor(tp->t_dev);
dmf = unit >> 3;
+ sc = &dmfa_softc[unit];
unit &= 07;
addr = (struct dmfdevice *)tp->t_addr;
***************
*** 623,637 ****
if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
goto out;
/*
! * If there are still characters in the silo,
! * just reenable the transmitter.
*/
! addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
! if (addr->dmftsc) {
addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
addr->dmflctms = addr->dmflctms | DMF_TE;
- tp->t_state |= TS_BUSY;
- goto out;
}
/*
* If there are sleepers, and output has drained below low
--- 631,651 ----
if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
goto out;
/*
! * If tx off, turn on. If tx was turned off while TS_BUSY (before
! * the interrupt), reset TS_BUSY and wait for interrupt. Otherwise
! * turn on tx and start a new transmission.
*/
! if (sc->dmfa_state & ST_TXOFF) {
! sc->dmfa_state &= ~ST_TXOFF;
! if (sc->dmfa_state & ST_INBUSY) {
! sc->dmfa_state &= ~ST_INBUSY;
! tp->t_state |= TS_BUSY;
! addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
! addr->dmflctms = addr->dmflctms | DMF_TE;
! goto out;
! }
addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
addr->dmflctms = addr->dmflctms | DMF_TE;
}
/*
* If there are sleepers, and output has drained below low
***************
*** 673,699 ****
if (nch >= dmf_mindma) {
register car;
! dmf_dma[minor(tp->t_dev)] = 1;
addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
addr->dmflctms = addr->dmflctms | DMF_TE;
car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
addr->dmftba = car;
addr->dmftcc = ((car >> 2) & 0xc000) | nch;
- tp->t_state |= TS_BUSY;
} else if (nch) {
register char *cp = tp->t_outq.c_cf;
register int i;
! dmf_dma[minor(tp->t_dev)] = 0;
nch = MIN(nch, DMF_SILOCNT);
addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
addr->dmflctms = addr->dmflctms | DMF_TE;
addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
for (i = 0; i < nch; i++)
addr->dmftbuf = *cp++;
ndflush(&tp->t_outq, nch);
- tp->t_state |= TS_BUSY;
}
out:
splx(s);
--- 687,714 ----
if (nch >= dmf_mindma) {
register car;
! tp->t_state |= TS_BUSY;
addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
addr->dmflctms = addr->dmflctms | DMF_TE;
car = UBACVT(tp->t_outq.c_cf, dmfinfo[dmf]->ui_ubanum);
+ sc->dmfa_count = nch;
+ sc->dmfa_state |= ST_DMA;
addr->dmfcsr = DMF_IE | DMFIR_TBA | unit;
addr->dmftba = car;
addr->dmftcc = ((car >> 2) & 0xc000) | nch;
} else if (nch) {
register char *cp = tp->t_outq.c_cf;
register int i;
! tp->t_state |= TS_BUSY;
nch = MIN(nch, DMF_SILOCNT);
addr->dmfcsr = DMF_IE | DMFIR_LCR | unit;
addr->dmflctms = addr->dmflctms | DMF_TE;
+ sc->dmfa_state &= ~ST_DMA;
addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
for (i = 0; i < nch; i++)
addr->dmftbuf = *cp++;
ndflush(&tp->t_outq, nch);
}
out:
splx(s);
***************
*** 707,713 ****
register struct tty *tp;
{
register struct dmfdevice *addr;
! register unit = minor(tp->t_dev) & 7;
int s;
addr = (struct dmfdevice *)tp->t_addr;
--- 722,729 ----
register struct tty *tp;
{
register struct dmfdevice *addr;
! register unit = minor(tp->t_dev);
! register struct dmfa_softc *sc = &dmfa_softc[unit];
int s;
addr = (struct dmfdevice *)tp->t_addr;
***************
*** 715,745 ****
* Block input/output interrupts while messing with state.
*/
s = spltty();
if (flag) {
! addr->dmfcsr = DMF_IE | DMFIR_TBUF | unit;
! if (addr->dmftsc) {
! /*
! * Flush regardless of whether we're transmitting
! * (TS_BUSY), if the silo contains untransmitted
! * characters.
! */
! addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
! addr->dmflctms = addr->dmflctms | DMF_TE | DMF_FLUSH;
! /* this will interrupt so let dmfxint handle the rest */
! tp->t_state |= TS_FLUSH|TS_BUSY;
! }
! } else {
! if (tp->t_state & TS_BUSY) {
! /*
! * Stop transmission by disabling
! * the transmitter. We'll pick up where we
! * left off by reenabling in dmfstart.
! */
! addr->dmfcsr = DMFIR_LCR | unit | DMF_IE;
! addr->dmflctms = addr->dmflctms &~ DMF_TE;
! /* no interrupt here */
! tp->t_state &= ~TS_BUSY;
! }
}
splx(s);
}
--- 731,747 ----
* Block input/output interrupts while messing with state.
*/
s = spltty();
+ addr->dmfcsr = DMFIR_LCR | (unit & 07) | DMF_IE;
+ addr->dmflctms = addr->dmflctms &~ DMF_TE;
+ sc->dmfa_state |= ST_TXOFF;
if (flag) {
! tp->t_state |= TS_FLUSH|TS_BUSY;
! addr->dmflctms = addr->dmflctms | DMF_FLUSH;
! /* this will interrupt so let dmfxint handle the rest */
! } else if (tp->t_state & TS_BUSY) {
! sc->dmfa_state |= ST_INBUSY;
! tp->t_state &= ~TS_BUSY;
! /* no interrupt here reenable in dmfstart */
}
splx(s);
}
***************
*** 819,824 ****
--- 821,827 ----
addr->dmfrsp = dmf_timeout;
unit = dmf * 8;
for (i = 0; i < 8; i++) {
+ dmfa_softc[unit].dmfa_state = 0;
tp = &dmf_tty[unit];
if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
dmfparam(unit);
More information about the Comp.unix.wizards
mailing list