SCCS-vsn: sys/vax/uba/rx.c 4.7
#include "rx.h"
#if NFX > 0
/*
* RX02 floppy disk device driver
*
#include "rx.h"
#if NFX > 0
/*
* RX02 floppy disk device driver
*
- * -- WARNING, UNTESTED --
+ * -- WARNING, NOT THOROUGHLY TESTED --
*/
#include "../machine/pte.h"
*/
#include "../machine/pte.h"
} rx_ctlr[NFX];
/* per-drive buffers */
} rx_ctlr[NFX];
/* per-drive buffers */
-struct buf rrxbuf[NRX]; /* buffers for I/O */
+struct buf rrxbuf[NRX]; /* buffers for raw I/O */
struct buf erxbuf[NRX]; /* buffers for reading error status */
struct buf erxbuf[NRX]; /* buffers for reading error status */
+struct buf rxutab[NRX]; /* per drive buffer queue heads */
/* per-drive data */
struct rx_softc {
/* per-drive data */
struct rx_softc {
#define RXF_USEWDDS 0x40 /* write deleted-data sector */
int sc_csbits; /* constant bits for CS register */
int sc_tocnt; /* for watchdog routine */
#define RXF_USEWDDS 0x40 /* write deleted-data sector */
int sc_csbits; /* constant bits for CS register */
int sc_tocnt; /* for watchdog routine */
+ caddr_t sc_uaddr; /* save orig. unibus address while */
+ /* doing multisector transfers */
+ long sc_bcnt; /* save total transfer count for */
+ /* multisector transfers */
} rx_softc[NRX];
struct rxerr {
} rx_softc[NRX];
struct rxerr {
register int unit = RXUNIT(dev);
register struct rx_softc *sc;
register struct uba_device *ui;
register int unit = RXUNIT(dev);
register struct rx_softc *sc;
register struct uba_device *ui;
+ register struct rxdevice *rxaddr;
if (unit >= NRX || (ui = rxdinfo[unit]) == 0 || ui->ui_alive == 0)
return (ENXIO);
if (unit >= NRX || (ui = rxdinfo[unit]) == 0 || ui->ui_alive == 0)
return (ENXIO);
sc->sc_csbits = RX_INTR;
sc->sc_csbits |= ui->ui_slave == 0 ? RX_DRV0 : RX_DRV1;
sc->sc_csbits |= minor(dev) & RXF_DBLDEN ? RX_DDEN : RX_SDEN;
sc->sc_csbits = RX_INTR;
sc->sc_csbits |= ui->ui_slave == 0 ? RX_DRV0 : RX_DRV1;
sc->sc_csbits |= minor(dev) & RXF_DBLDEN ? RX_DDEN : RX_SDEN;
+ rxaddr = (struct rxdevice *)rxminfo[unit]->um_addr;
+ if (rxaddr->rxcs == 0x800) {
+ /*
+ * If the drive subsystem has been powered down,
+ * the rx211 controller must be initialized.
+ */
+ rxreset(rxminfo[unit]->um_ubanum);
+ }
{
struct uba_device *ui;
register struct uba_ctlr *um;
{
struct uba_device *ui;
register struct uba_ctlr *um;
+ register struct buf *dp;
+ struct rx_softc *sc;
+ int s, unit = RXUNIT(bp->b_dev);
- ui = rxdinfo[RXUNIT(bp->b_dev)];
- if (ui == 0 || ui->ui_alive == 0) {
- bp->b_flags |= B_ERROR;
- iodone(bp);
- return;
- }
+ ui = rxdinfo[unit];
+ sc = &rx_softc[unit];
+ if (ui == 0 || ui->ui_alive == 0)
+ goto bad;
+ if (bp->b_blkno < 0 || (bp->b_blkno * DEV_BSIZE) > RXSIZE )
+ goto bad;
- if (um->um_tab.b_actf == NULL)
- um->um_tab.b_actf = bp;
- else
- um->um_tab.b_actl->b_forw = bp;
- um->um_tab.b_actl = bp;
+ dp = &rxutab[ui->ui_unit];
+ disksort(dp, bp);
+ rxustart(ui);
+ bp->b_resid = bp->b_bcount;
+ sc->sc_uaddr = bp->b_un.b_addr;
+ sc->sc_bcnt = bp->b_bcount;
+ return;
+
+bad: bp->b_flags |= B_ERROR;
+ iodone(bp);
+ return;
+/*
+ * Unit start routine.
+ * Put this unit on the ready queue for the controller,
+ * unless it is already there.
+ */
+rxustart(ui)
+ register struct uba_device *ui;
+{
+ struct buf *dp;
+ struct uba_ctlr *um;
+
+ dp = &rxutab[ui->ui_unit];
+ um = ui->ui_mi;
+
+ if (!dp->b_active) {
+ dp->b_forw = NULL;
+ if (um->um_tab.b_actf == NULL)
+ um->um_tab.b_actf = dp;
+ else
+ um->um_tab.b_actl->b_forw = dp;
+ um->um_tab.b_actl = dp;
+ dp->b_active++;
+ }
+}
/*
* Sector mapping routine.
* Two independent sets of choices are available:
/*
* Sector mapping routine.
* Two independent sets of choices are available:
register int lt, ls, ptoff;
struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
register int lt, ls, ptoff;
struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
- ls = ( bp->b_blkno * DEV_BSIZE ) / NBPS;
+ ls = ( bp->b_blkno * DEV_BSIZE + ( sc->sc_bcnt - bp->b_resid )) / NBPS;
lt = ls / 26;
ls %= 26;
/*
lt = ls / 26;
ls %= 26;
/*
ptoff = 0;
if (sc->sc_flags&RXF_DIRECT)
ptoff = 77;
ptoff = 0;
if (sc->sc_flags&RXF_DIRECT)
ptoff = 77;
- if (sc->sc_flags&RXF_TRKZERO)
+ if (!sc->sc_flags&RXF_TRKZERO)
ptoff++;
if (lt + ptoff < 77)
ls = ((ls << 1) + (ls >= 13) + (6*lt)) % 26;
ptoff++;
if (lt + ptoff < 77)
ls = ((ls << 1) + (ls >= 13) + (6*lt)) % 26;
+/*
+ * Controller start routine
+ */
rxstart(um)
register struct uba_ctlr *um;
{
register struct rxdevice *rxaddr;
register struct rx_ctlr *rxc;
register struct rx_softc *sc;
rxstart(um)
register struct uba_ctlr *um;
{
register struct rxdevice *rxaddr;
register struct rx_ctlr *rxc;
register struct rx_softc *sc;
- if (um->um_tab.b_active || (bp = um->um_tab.b_actf) == NULL)
+ if (um->um_tab.b_active)
+ return;
+loop:
+ if ((dp = um->um_tab.b_actf) == NULL)
+ if ((bp = dp->b_actf) == NULL) {
+ um->um_tab.b_actf = dp->b_forw;
+ goto loop;
+ }
um->um_tab.b_active++;
unit = RXUNIT(bp->b_dev);
sc = &rx_softc[unit];
rxaddr = (struct rxdevice *)um->um_addr;
rxc = &rx_ctlr[um->um_ctlr];
um->um_tab.b_active++;
unit = RXUNIT(bp->b_dev);
sc = &rx_softc[unit];
rxaddr = (struct rxdevice *)um->um_addr;
rxc = &rx_ctlr[um->um_ctlr];
+ sc->sc_tocnt = 0;
+ bp->b_bcount = bp->b_resid;
+ if (bp->b_bcount > NBPS)
+ bp->b_bcount = NBPS;
rxtimo(bp->b_dev); /* start watchdog */
if (bp->b_flags&B_CTRL) { /* format */
rxc->rxc_state = RXS_FORMAT;
rxtimo(bp->b_dev); /* start watchdog */
if (bp->b_flags&B_CTRL) { /* format */
rxc->rxc_state = RXS_FORMAT;
rxmap(bp, §or, &track);
rxc->rxc_state = RXS_READ;
rxaddr->rxcs = RX_READ | sc->sc_csbits;
rxmap(bp, §or, &track);
rxc->rxc_state = RXS_READ;
rxaddr->rxcs = RX_READ | sc->sc_csbits;
- printf("rxstart: (read) track=%d, sector=%d\n", track, sector);
+ printf("rxstart/r: tr=%d, sc=%d, bl=%d, cnt=%d\n",
+ track, sector, bp->b_blkno, bp->b_bcount);
while ((rxaddr->rxcs&RX_TREQ) == 0)
;
rxaddr->rxdb = (u_short)sector;
while ((rxaddr->rxcs&RX_TREQ) == 0)
;
rxaddr->rxdb = (u_short)sector;
{
register struct rxdevice *rxaddr = (struct rxdevice *)um->um_addr;
int ubinfo = um->um_ubinfo;
{
register struct rxdevice *rxaddr = (struct rxdevice *)um->um_addr;
int ubinfo = um->um_ubinfo;
- struct buf *bp = um->um_tab.b_actf;
+ struct buf *bp = um->um_tab.b_actf->b_actf;
struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
struct rx_ctlr *rxc = &rx_ctlr[um->um_ctlr];
struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)];
struct rx_ctlr *rxc = &rx_ctlr[um->um_ctlr];
+ rxaddr->rxcs = um->um_cmd | ((ubinfo & 0x30000) >> 4) | sc->sc_csbits;
if (rxc->rxc_state != RXS_RDERR) {
while ((rxaddr->rxcs&RX_TREQ) == 0)
;
if (rxc->rxc_state != RXS_RDERR) {
while ((rxaddr->rxcs&RX_TREQ) == 0)
;
while ((rxaddr->rxcs&RX_TREQ) == 0)
;
rxaddr->rxdb = ubinfo;
while ((rxaddr->rxcs&RX_TREQ) == 0)
;
rxaddr->rxdb = ubinfo;
- rxaddr->rxcs = um->um_cmd | ((ubinfo & 0x30000) >> 4) | sc->sc_csbits;
int unit = RXUNIT(dev), sector, track;
struct uba_ctlr *um = rxminfo[unit];
register struct rxdevice *rxaddr;
int unit = RXUNIT(dev), sector, track;
struct uba_ctlr *um = rxminfo[unit];
register struct rxdevice *rxaddr;
- register struct buf *bp;
+ register struct buf *bp, *dp;
register struct rx_softc *sc = &rx_softc[unit];
struct uba_device *ui = rxdinfo[unit];
struct rxerr *er;
register struct rx_softc *sc = &rx_softc[unit];
struct uba_device *ui = rxdinfo[unit];
struct rxerr *er;
sc->sc_tocnt = 0;
if (!um->um_tab.b_active)
return;
sc->sc_tocnt = 0;
if (!um->um_tab.b_active)
return;
+ dp = um->um_tab.b_actf;
+ if (!dp->b_active)
+ return;
rxaddr = (struct rxdevice *)um->um_addr;
rxc = &rx_ctlr[um->um_ctlr];
er = &rxerr[unit];
rxaddr = (struct rxdevice *)um->um_addr;
rxc = &rx_ctlr[um->um_ctlr];
er = &rxerr[unit];
- bp = um->um_tab.b_actf;
- printf("rxintr: unit=%d, state=0x%x, ctrlr status=0x%x\n",
+ bp = dp->b_actf;
+ printf("rxintr: dev=%d, state=0x%x, status=0x%x\n",
unit, rxc->rxc_state, rxaddr->rxcs);
if ((rxaddr->rxcs & RX_ERR) &&
rxc->rxc_state != RXS_RDSTAT && rxc->rxc_state != RXS_RDERR)
unit, rxc->rxc_state, rxaddr->rxcs);
if ((rxaddr->rxcs & RX_ERR) &&
rxc->rxc_state != RXS_RDSTAT && rxc->rxc_state != RXS_RDERR)
- printf("rx%d: state %d (reset)", unit, rxc->rxc_state);
+ printf("rx%d: state %d (reset)\n", unit, rxc->rxc_state);
bp->b_un.b_addr = (caddr_t)er->rxxt;
bp->b_bcount = sizeof (er->rxxt);
bp->b_flags &= ~(B_DIRTY|B_UAREA|B_PHYS|B_PAGET);
bp->b_un.b_addr = (caddr_t)er->rxxt;
bp->b_bcount = sizeof (er->rxxt);
bp->b_flags &= ~(B_DIRTY|B_UAREA|B_PHYS|B_PAGET);
- if (um->um_tab.b_actf == NULL)
- um->um_tab.b_actl = bp;
- bp->b_forw = um->um_tab.b_actf;
- um->um_tab.b_actf = bp;
+ if (um->um_tab.b_actf->b_actf == NULL)
+ um->um_tab.b_actf->b_actl = bp;
+ bp->b_forw = um->um_tab.b_actf->b_actf;
+ um->um_tab.b_actf->b_actf = bp;
rxc->rxc_state = RXS_RDERR;
um->um_cmd = RX_RDERR;
(void) ubago(ui);
return;
done:
um->um_tab.b_active = 0;
rxc->rxc_state = RXS_RDERR;
um->um_cmd = RX_RDERR;
(void) ubago(ui);
return;
done:
um->um_tab.b_active = 0;
- um->um_tab.b_actf = bp->b_forw;
+ um->um_tab.b_errcnt = 0;
+ ubadone(um);
+ if ((bp->b_resid -= NBPS) > 0) {
+ bp->b_un.b_addr += NBPS;
+ rxstart(um);
+ return;
+ }
+ bp->b_un.b_addr = sc->sc_uaddr;
+ bp->b_bcount = sc->sc_bcnt;
iodone(bp);
rxc->rxc_state = RXS_IDLE;
iodone(bp);
rxc->rxc_state = RXS_IDLE;
+ um->um_tab.b_actf = dp->b_forw;
+ dp->b_active = 0;
+ dp->b_errcnt = 0;
+ dp->b_actf = bp->av_forw;
- * If this unit (controller) has more work to do,
+ * If this controller has more work to do,
* start it up right away
*/
if (um->um_tab.b_actf)
* start it up right away
*/
if (um->um_tab.b_actf)
minrxphys(bp)
struct buf *bp;
{
minrxphys(bp)
struct buf *bp;
{
if (bp->b_bcount > NBPS)
bp->b_bcount = NBPS;
}
if (bp->b_bcount > NBPS)
bp->b_bcount = NBPS;
}
timeout(rxtimo, (caddr_t)dev, hz);
if (++sc->sc_tocnt < RX_MAXTIMEOUT)
return;
timeout(rxtimo, (caddr_t)dev, hz);
if (++sc->sc_tocnt < RX_MAXTIMEOUT)
return;
- printf("rx: timeout on dev %d\n", dev);
+ printf("rx: timeout dev 0x%x\n", dev);
+ sc->sc_tocnt = 0;
if ((um = rxminfo[ctlr]) == 0 || um->um_ubanum != uban ||
um->um_alive == 0)
continue;
if ((um = rxminfo[ctlr]) == 0 || um->um_ubanum != uban ||
um->um_alive == 0)
continue;
- printf(" fx%d: ", ctlr);
- if (um->um_ubinfo) {
- printf("<%d>", (um->um_ubinfo>>28)&0xf);
rx_ctlr[ctlr].rxc_state = RXS_IDLE;
rxaddr = (struct rxdevice *)um->um_addr;
rxaddr->rxcs = RX_INIT;
rx_ctlr[ctlr].rxc_state = RXS_IDLE;
rxaddr = (struct rxdevice *)um->um_addr;
rxaddr->rxcs = RX_INIT;
+/*
+ * make the world believe this is a
+ * 512b/s device
+ */
+
rxread(dev, uio)
dev_t dev;
struct uio *uio;
{
rxread(dev, uio)
dev_t dev;
struct uio *uio;
{
- int unit = RXUNIT(dev), ctlr = rxdinfo[unit]->ui_ctlr;
- struct rx_softc *sc = &rx_softc[RXUNIT(dev)];
+ int unit = RXUNIT(dev) ;
+ struct rx_softc *sc = &rx_softc[unit];
if (uio->uio_offset + uio->uio_resid > RXSIZE)
return (ENXIO);
if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
return (EIO);
if (uio->uio_offset + uio->uio_resid > RXSIZE)
return (ENXIO);
if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
return (EIO);
- return (physio(rxstrategy, &rrxbuf[ctlr], dev, B_READ, minrxphys, uio));
+ return (physio(rxstrategy, &rrxbuf[unit], dev, B_READ, minphys, uio));
}
rxwrite(dev, uio)
dev_t dev;
struct uio *uio;
{
}
rxwrite(dev, uio)
dev_t dev;
struct uio *uio;
{
- int unit = RXUNIT(dev), ctlr = rxdinfo[unit]->ui_ctlr;
- struct rx_softc *sc = &rx_softc[RXUNIT(dev)];
+ int unit = RXUNIT(dev);
+ struct rx_softc *sc = &rx_softc[unit];
if (uio->uio_offset + uio->uio_resid > RXSIZE)
return (ENXIO);
if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
return (EIO);
if (uio->uio_offset + uio->uio_resid > RXSIZE)
return (ENXIO);
if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0)
return (EIO);
- return(physio(rxstrategy, &rrxbuf[ctlr], dev, B_WRITE, minrxphys, uio));
+ return(physio(rxstrategy, &rrxbuf[unit], dev, B_WRITE, minphys, uio));
* (by returning with an EIO error code if it did).
*
* Requests relating to deleted-data marks can be handled right here.
* (by returning with an EIO error code if it did).
*
* Requests relating to deleted-data marks can be handled right here.
- * A "set density" request, however, must additionally be processed
- * through "rxstart", just like a read or write request.
+ * A "set density" (format) request, however, must additionally be
+ * processed through "rxstart", just like a read or write request.
*/
/*ARGSUSED3*/
rxioctl(dev, cmd, data, flag)
*/
/*ARGSUSED3*/
rxioctl(dev, cmd, data, flag)
rxformat(dev)
dev_t dev;
{
rxformat(dev)
dev_t dev;
{
- int ctlr = rxdinfo[RXUNIT(dev)]->ui_mi->um_ctlr;
+ int unit = RXUNIT(dev);
- struct rx_softc *sc = &rx_softc[RXUNIT(dev)];
+ struct rx_softc *sc = &rx_softc[unit];
- bp = &rrxbuf[RXUNIT(dev)];
s = spl5();
while (bp->b_flags & B_BUSY)
sleep(bp, PRIBIO);
s = spl5();
while (bp->b_flags & B_BUSY)
sleep(bp, PRIBIO);