-/* up.c 4.21 81/02/23 */
+/* up.c 4.40 81/11/18 */
#include "up.h"
#if NSC > 0
/*
* UNIBUS disk driver with overlapped seeks and ECC recovery.
+ *
+ * TODO:
+ * Add bad sector forwarding code
+ * Check that offset recovery code works
*/
-#define DELAY(N) { register int d; d = N; while (--d > 0); }
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/user.h"
#include "../h/map.h"
#include "../h/pte.h"
-#include "../h/mba.h"
#include "../h/mtpr.h"
#include "../h/vm.h"
-#include "../h/uba.h"
+#include "../h/ubavar.h"
+#include "../h/ubareg.h"
#include "../h/cmap.h"
#include "../h/upreg.h"
int sc_softas;
int sc_ndrive;
int sc_wticks;
+ int sc_recal;
} up_softc[NSC];
/* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
495520, 0, /* C=cyl 0 thru 814 */
15884, 562, /* D=cyl 562 thru 588 */
55936, 589, /* E=cyl 589 thru 680 */
- 81472, 681, /* F=cyl 681 thru 814 */
- 153824, 562, /* G=cyl 562 thru 814 */
+#ifndef NOBADSECT
+ 81376, 681, /* F=cyl 681 thru 814 */
+ 153728, 562, /* G=cyl 562 thru 814 */
+#else
+ 81472, 681,
+ 153824, 562,
+#endif
291346, 82, /* H=cyl 82 thru 561 */
}, fj_sizes[8] = {
15884, 0, /* A=cyl 0 thru 49 */
0, 0,
0, 0,
0, 0,
- 213760, 155, /* H=cyl 155 thru 822 */
+#ifndef NOBADSECT
+ 213664, 155, /* H=cyl 155 thru 822 */
+#else
+ 213760, 155,
+#endif
};
/* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
int upRDIST = _upRDIST;
int upprobe(), upslave(), upattach(), updgo(), upintr();
-struct uba_minfo *upminfo[NSC];
-struct uba_dinfo *updinfo[NUP];
-struct uba_dinfo *upip[NSC][4];
+struct uba_ctlr *upminfo[NSC];
+struct uba_device *updinfo[NUP];
+struct uba_device *upip[NSC][4];
u_short upstd[] = { 0776700, 0774400, 0776300, 0 };
struct uba_driver scdriver =
};
u_char up_offset[16] = {
- UP_P400, UP_M400, UP_P400, UP_M400, UP_P800, UP_M800, UP_P800, UP_M800,
- UP_P1200, UP_M1200, UP_P1200, UP_M1200, 0, 0, 0, 0
+ UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400,
+ UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800,
+ UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200,
+ 0, 0, 0, 0
};
struct buf rupbuf[NUP];
int upwstart, upwatch(); /* Have started guardian */
int upseek;
+int upwaitdry;
/*ARGSUSED*/
upprobe(reg)
#ifdef lint
br = 0; cvec = br; br = cvec;
+ upintr(0);
#endif
((struct updevice *)reg)->upcs1 = UP_IE|UP_RDY;
DELAY(10);
}
upslave(ui, reg)
- struct uba_dinfo *ui;
+ struct uba_device *ui;
caddr_t reg;
{
register struct updevice *upaddr = (struct updevice *)reg;
upaddr->upcs1 = 0; /* conservative */
upaddr->upcs2 = ui->ui_slave;
- if (upaddr->upcs2&UP_NED) {
+ if (upaddr->upcs2&UPCS2_NED) {
upaddr->upcs1 = UP_DCLR|UP_GO;
return (0);
}
}
upattach(ui)
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
{
-#ifdef notdef
register struct updevice *upaddr;
-#endif
if (upwstart == 0) {
- timeout(upwatch, (caddr_t)0, HZ);
+ timeout(upwatch, (caddr_t)0, hz);
upwstart++;
}
if (ui->ui_dk >= 0)
dk_mspw[ui->ui_dk] = .0000020345;
upip[ui->ui_ctlr][ui->ui_slave] = ui;
up_softc[ui->ui_ctlr].sc_ndrive++;
-#ifdef notdef
upaddr = (struct updevice *)ui->ui_addr;
upaddr->upcs1 = 0;
upaddr->upcs2 = ui->ui_slave;
- upaddr->uphr = -1;
- /* ... */
- if (upaddr-> ... == 10)
- ui->ui_type = 1;
-#endif
+ upaddr->uphr = UPHR_MAXTRAK;
+ if (upaddr->uphr == 9)
+ ui->ui_type = 1; /* fujitsu hack */
+ upaddr->upcs2 = UPCS2_CLR;
+/*
+ upaddr->uphr = UPHR_MAXCYL;
+ printf("maxcyl %d\n", upaddr->uphr);
+ upaddr->uphr = UPHR_MAXTRAK;
+ printf("maxtrak %d\n", upaddr->uphr);
+ upaddr->uphr = UPHR_MAXSECT;
+ printf("maxsect %d\n", upaddr->uphr);
+*/
}
upstrategy(bp)
register struct buf *bp;
{
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
register struct upst *st;
register int unit;
register struct buf *dp;
return;
}
+/*
+ * Unit start routine.
+ * Seek the drive to be where the data is
+ * and then generate another interrupt
+ * to actually start the transfer.
+ * If there is only one drive on the controller,
+ * or we are very close to the data, don't
+ * bother with the search. If called after
+ * searching once, don't bother to look where
+ * we are, just queue for transfer (to avoid
+ * positioning forever without transferrring.)
+ */
upustart(ui)
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
{
register struct buf *bp, *dp;
- register struct uba_minfo *um;
+ register struct uba_ctlr *um;
register struct updevice *upaddr;
register struct upst *st;
daddr_t bn;
- int sn, cn, csn;
- int didie = 0;
-
- if (ui == 0)
- return (0);
+ int sn, csn;
/*
* The SC21 cancels commands if you just say
* cs1 = UP_IE
* so we are cautious about handling of cs1.
* Also don't bother to clear as bits other than in upintr().
*/
+ int didie = 0;
+
+ if (ui == 0)
+ return (0);
+ um = ui->ui_mi;
dk_busy &= ~(1<<ui->ui_dk);
dp = &uputab[ui->ui_unit];
if ((bp = dp->b_actf) == NULL)
goto out;
- /* dont confuse controller by giving SEARCH while dt in progress */
- um = ui->ui_mi;
+ /*
+ * If the controller is active, just remember
+ * that this device would like to be positioned...
+ * if we tried to position now we would confuse the SC21.
+ */
if (um->um_tab.b_active) {
up_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave;
return (0);
}
+ /*
+ * If we have already positioned this drive,
+ * then just put it on the ready queue.
+ */
if (dp->b_active)
goto done;
dp->b_active = 1;
upaddr = (struct updevice *)um->um_addr;
upaddr->upcs2 = ui->ui_slave;
- if ((upaddr->upds & UP_VV) == 0) {
+ /*
+ * If drive has just come up,
+ * setup the pack.
+ */
+ if ((upaddr->upds & UPDS_VV) == 0) {
/* SHOULD WARN SYSTEM THAT THIS HAPPENED */
upaddr->upcs1 = UP_IE|UP_DCLR|UP_GO;
upaddr->upcs1 = UP_IE|UP_PRESET|UP_GO;
- upaddr->upof = UP_FMT22;
+ upaddr->upof = UPOF_FMT22;
didie = 1;
}
- if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL))
+ /*
+ * If drive is offline, forget about positioning.
+ */
+ if ((upaddr->upds & (UPDS_DPR|UPDS_MOL)) != (UPDS_DPR|UPDS_MOL))
goto done;
+ /*
+ * If there is only one drive,
+ * dont bother searching.
+ */
if (up_softc[um->um_ctlr].sc_ndrive == 1)
goto done;
+ /*
+ * Figure out where this transfer is going to
+ * and see if we are close enough to justify not searching.
+ */
st = &upst[ui->ui_type];
bn = dkblock(bp);
- cn = bp->b_cylin;
sn = bn%st->nspc;
sn = (sn + st->nsect - upSDIST) % st->nsect;
- if (cn - upaddr->updc)
+ if (bp->b_cylin - upaddr->updc)
goto search; /* Not on-cylinder */
else if (upseek)
goto done; /* Ok just to be on-cylinder */
if (csn > st->nsect - upRDIST)
goto done;
search:
- upaddr->updc = cn;
+ upaddr->updc = bp->b_cylin;
+ /*
+ * Not on cylinder at correct position,
+ * seek/search.
+ */
if (upseek)
upaddr->upcs1 = UP_IE|UP_SEEK|UP_GO;
else {
upaddr->upcs1 = UP_IE|UP_SEARCH|UP_GO;
}
didie = 1;
+ /*
+ * Mark unit busy for iostat.
+ */
if (ui->ui_dk >= 0) {
dk_busy |= 1<<ui->ui_dk;
dk_seek[ui->ui_dk]++;
}
goto out;
done:
+ /*
+ * Device is ready to go.
+ * Put it on the ready queue for the controller
+ * (unless its already there.)
+ */
if (dp->b_active != 2) {
dp->b_forw = NULL;
if (um->um_tab.b_actf == NULL)
return (didie);
}
+/*
+ * Start up a transfer on a drive.
+ */
upstart(um)
- register struct uba_minfo *um;
+ register struct uba_ctlr *um;
{
register struct buf *bp, *dp;
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
register struct updevice *upaddr;
struct upst *st;
daddr_t bn;
- int dn, sn, tn, cmd;
+ int dn, sn, tn, cmd, waitdry;
loop:
+ /*
+ * Pull a request off the controller queue
+ */
if ((dp = um->um_tab.b_actf) == NULL)
return (0);
if ((bp = dp->b_actf) == NULL) {
um->um_tab.b_actf = dp->b_forw;
goto loop;
}
+ /*
+ * Mark controller busy, and
+ * determine destination of this request.
+ */
um->um_tab.b_active++;
ui = updinfo[dkunit(bp)];
bn = dkblock(bp);
tn = sn/st->nsect;
sn %= st->nsect;
upaddr = (struct updevice *)ui->ui_addr;
- upaddr->upcs2 = dn;
- if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL)) {
- printf("up%d not ready", dkunit(bp));
- if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL)) {
+ /*
+ * Select drive if not selected already.
+ */
+ if ((upaddr->upcs2&07) != dn)
+ upaddr->upcs2 = dn;
+ /*
+ * Check that it is ready and online
+ */
+ waitdry = 0;
+ while ((upaddr->upds&UPDS_DRY) == 0) {
+ if (++waitdry > 512)
+ break;
+ upwaitdry++;
+ }
+ if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
+ printf("up%d: not ready", dkunit(bp));
+ if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY) {
printf("\n");
um->um_tab.b_active = 0;
um->um_tab.b_errcnt = 0;
iodone(bp);
goto loop;
}
+ /*
+ * Oh, well, sometimes this
+ * happens, for reasons unknown.
+ */
printf(" (flakey)\n");
}
- if (um->um_tab.b_errcnt >= 16 && (bp->b_flags&B_READ) != 0) {
- upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | UP_FMT22;
- upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO;
- while (upaddr->upds & UP_PIP)
- DELAY(25);
- }
+ /*
+ * Setup for the transfer, and get in the
+ * UNIBUS adaptor queue.
+ */
upaddr->updc = bp->b_cylin;
upaddr->upda = (tn << 8) + sn;
upaddr->upwc = -bp->b_bcount / sizeof (short);
else
cmd = UP_IE|UP_WCOM|UP_GO;
um->um_cmd = cmd;
- ubago(ui);
+ (void) ubago(ui);
return (1);
}
+/*
+ * Now all ready to go, stuff the registers.
+ */
updgo(um)
- struct uba_minfo *um;
+ struct uba_ctlr *um;
{
register struct updevice *upaddr = (struct updevice *)um->um_addr;
upaddr->upcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300);
}
-scintr(sc21)
+/*
+ * Handle a disk interrupt.
+ */
+upintr(sc21)
register sc21;
{
register struct buf *bp, *dp;
- register struct uba_minfo *um = upminfo[sc21];
- register struct uba_dinfo *ui;
+ register struct uba_ctlr *um = upminfo[sc21];
+ register struct uba_device *ui;
register struct updevice *upaddr = (struct updevice *)um->um_addr;
register unit;
struct up_softc *sc = &up_softc[um->um_ctlr];
int as = (upaddr->upas & 0377) | sc->sc_softas;
- int needie = 1;
+ int needie = 1, waitdry;
sc->sc_wticks = 0;
sc->sc_softas = 0;
- if (um->um_tab.b_active) {
- if ((upaddr->upcs1 & UP_RDY) == 0)
- printf("upintr !RDY\n");
- dp = um->um_tab.b_actf;
- bp = dp->b_actf;
- ui = updinfo[dkunit(bp)];
- dk_busy &= ~(1 << ui->ui_dk);
+ /*
+ * If controller wasn't transferring, then this is an
+ * interrupt for attention status on seeking drives.
+ * Just service them.
+ */
+ if (um->um_tab.b_active == 0) {
+ if (upaddr->upcs1 & UP_TRE)
+ upaddr->upcs1 = UP_TRE;
+ goto doattn;
+ }
+ /*
+ * Get device and block structures, and a pointer
+ * to the uba_device for the drive. Select the drive.
+ */
+ dp = um->um_tab.b_actf;
+ bp = dp->b_actf;
+ ui = updinfo[dkunit(bp)];
+ dk_busy &= ~(1 << ui->ui_dk);
+ if ((upaddr->upcs2&07) != ui->ui_slave)
upaddr->upcs2 = ui->ui_slave;
- if ((upaddr->upds&UP_ERR) || (upaddr->upcs1&UP_TRE)) {
- int cs2;
- while ((upaddr->upds & UP_DRY) == 0)
- DELAY(25);
- if (upaddr->uper1&UP_WLE)
- printf("up%d is write locked\n", dkunit(bp));
- if (++um->um_tab.b_errcnt > 28 || upaddr->uper1&UP_WLE)
- bp->b_flags |= B_ERROR;
- else
- um->um_tab.b_active = 0; /* force retry */
- if (um->um_tab.b_errcnt > 27) {
- cs2 = (int)upaddr->upcs2;
- deverror(bp, cs2, (int)upaddr->uper1);
- }
- if ((upaddr->uper1&(UP_DCK|UP_ECH))==UP_DCK)
+ /*
+ * Check for and process errors on
+ * either the drive or the controller.
+ */
+ if ((upaddr->upds&UPDS_ERR) || (upaddr->upcs1&UP_TRE)) {
+ waitdry = 0;
+ while ((upaddr->upds & UPDS_DRY) == 0) {
+ if (++waitdry > 512)
+ break;
+ upwaitdry++;
+ }
+ if (upaddr->uper1&UPER1_WLE) {
+ /*
+ * Give up on write locked devices
+ * immediately.
+ */
+ printf("up%d: write locked\n", dkunit(bp));
+ bp->b_flags |= B_ERROR;
+ } else if (++um->um_tab.b_errcnt > 27) {
+ /*
+ * After 28 retries (16 without offset, and
+ * 12 with offset positioning) give up.
+ */
+ harderr(bp, "up");
+ printf("cs2=%b er1=%b er2=%b\n",
+ upaddr->upcs2, UPCS2_BITS,
+ upaddr->uper1, UPER1_BITS,
+ upaddr->uper2, UPER2_BITS);
+ bp->b_flags |= B_ERROR;
+ } else {
+ /*
+ * Retriable error.
+ * If a soft ecc, correct it (continuing
+ * by returning if necessary.
+ * Otherwise fall through and retry the transfer
+ */
+ um->um_tab.b_active = 0; /* force retry */
+ if ((upaddr->uper1&(UPER1_DCK|UPER1_ECH))==UPER1_DCK)
if (upecc(ui))
return;
- upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
- needie = 0;
- if ((um->um_tab.b_errcnt&07) == 4) {
- upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO;
- while(upaddr->upds & UP_PIP)
- DELAY(25);
- }
- if (um->um_tab.b_errcnt == 28 && cs2&(UP_NEM|UP_MXF)) {
- printf("FLAKEY UP ");
- ubareset(um->um_ubanum);
- return;
- }
}
- ubadone(um);
- if (um->um_tab.b_active) {
- if (um->um_tab.b_errcnt >= 16) {
- upaddr->upcs1 = UP_RTC|UP_GO|UP_IE;
- while (upaddr->upds & UP_PIP)
- DELAY(25);
- needie = 0;
- }
- um->um_tab.b_active = 0;
- um->um_tab.b_errcnt = 0;
- um->um_tab.b_actf = dp->b_forw;
- dp->b_active = 0;
- dp->b_errcnt = 0;
- dp->b_actf = bp->av_forw;
- bp->b_resid = (-upaddr->upwc * sizeof(short));
- iodone(bp);
- if (dp->b_actf)
- if (upustart(ui))
- needie = 0;
+ /*
+ * Clear drive error and, every eight attempts,
+ * (starting with the fourth)
+ * recalibrate to clear the slate.
+ */
+ upaddr->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
+ needie = 0;
+ if ((um->um_tab.b_errcnt&07) == 4 && um->um_tab.b_active == 0) {
+ upaddr->upcs1 = UP_RECAL|UP_IE|UP_GO;
+ sc->sc_recal = 0;
+ goto nextrecal;
}
- as &= ~(1<<ui->ui_slave);
- } else {
- if (upaddr->upcs1 & UP_TRE)
- upaddr->upcs1 = UP_TRE;
}
- for (unit = 0; as; as >>= 1, unit++)
- if (as & 1) {
- upaddr->upas = 1<<unit;
- if (upustart(upip[sc21][unit]))
- needie = 0;
+ /*
+ * Advance recalibration finite state machine
+ * if recalibrate in progress, through
+ * RECAL
+ * SEEK
+ * OFFSET (optional)
+ * RETRY
+ */
+ switch (sc->sc_recal) {
+
+ case 1:
+ upaddr->updc = bp->b_cylin;
+ upaddr->upcs1 = UP_SEEK|UP_IE|UP_GO;
+ goto nextrecal;
+ case 2:
+ if (um->um_tab.b_errcnt < 16 || (bp->b_flags&B_READ) == 0)
+ goto donerecal;
+ upaddr->upof = up_offset[um->um_tab.b_errcnt & 017] | UPOF_FMT22;
+ upaddr->upcs1 = UP_IE|UP_OFFSET|UP_GO;
+ goto nextrecal;
+ nextrecal:
+ sc->sc_recal++;
+ um->um_tab.b_active = 1;
+ return;
+ donerecal:
+ case 3:
+ sc->sc_recal = 0;
+ um->um_tab.b_active = 0;
+ break;
+ }
+ /*
+ * If still ``active'', then don't need any more retries.
+ */
+ if (um->um_tab.b_active) {
+ /*
+ * If we were offset positioning,
+ * return to centerline.
+ */
+ if (um->um_tab.b_errcnt >= 16) {
+ upaddr->upof = UPOF_FMT22;
+ upaddr->upcs1 = UP_RTC|UP_GO|UP_IE;
+ while (upaddr->upds & UPDS_PIP)
+ DELAY(25);
+ needie = 0;
}
+ um->um_tab.b_active = 0;
+ um->um_tab.b_errcnt = 0;
+ um->um_tab.b_actf = dp->b_forw;
+ dp->b_active = 0;
+ dp->b_errcnt = 0;
+ dp->b_actf = bp->av_forw;
+ bp->b_resid = (-upaddr->upwc * sizeof(short));
+ iodone(bp);
+ /*
+ * If this unit has more work to do,
+ * then start it up right away.
+ */
+ if (dp->b_actf)
+ if (upustart(ui))
+ needie = 0;
+ }
+ as &= ~(1<<ui->ui_slave);
+ /*
+ * Release unibus resources and flush data paths.
+ */
+ ubadone(um);
+doattn:
+ /*
+ * Process other units which need attention.
+ * For each unit which needs attention, call
+ * the unit start routine to place the slave
+ * on the controller device queue.
+ */
+ while (unit = ffs(as)) {
+ unit--; /* was 1 origin */
+ as &= ~(1<<unit);
+ upaddr->upas = 1<<unit;
+ if (upustart(upip[sc21][unit]))
+ needie = 0;
+ }
+ /*
+ * If the controller is not transferring, but
+ * there are devices ready to transfer, start
+ * the controller.
+ */
if (um->um_tab.b_actf && um->um_tab.b_active == 0)
if (upstart(um))
needie = 0;
* across a page boundary.
*/
upecc(ui)
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
{
register struct updevice *up = (struct updevice *)ui->ui_addr;
register struct buf *bp = uputab[ui->ui_unit].b_actf;
- register struct uba_minfo *um = ui->ui_mi;
+ register struct uba_ctlr *um = ui->ui_mi;
register struct upst *st;
struct uba_regs *ubp = ui->ui_hd->uh_uba;
register int i;
npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1;
reg = btop(um->um_ubinfo&0x3ffff) + npf;
o = (int)bp->b_un.b_addr & PGOFSET;
- printf("%D ", bp->b_blkno+npf);
- prdev("ECC", bp->b_dev);
+ printf("up%d%c: soft ecc sn%d\n", dkunit(bp),
+ 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf);
mask = up->upec2;
- if (mask == 0) {
- up->upof = UP_FMT22; /* == RTC ???? */
- return (0);
- }
+#ifdef UPECCDEBUG
+ printf("npf %d reg %x o %d mask %o pos %d\n", npf, reg, o, mask,
+ up->upec1);
+#endif
/*
* Flush the buffered data path, and compute the
* byte and bit position of the error. The variable i
* is the byte offset in the transfer, the variable byte
* is the offset from a page boundary in main memory.
*/
- ubp->uba_dpr[(um->um_ubinfo>>28)&0x0f] |= UBA_BNE;
+ ubapurge(um);
i = up->upec1 - 1; /* -1 makes 0 origin */
bit = i&07;
i = (i&~07)>>3;
while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
(byte & PGOFSET);
+#ifdef UPECCDEBUG
+ printf("addr %x map reg %x\n",
+ addr, *(int *)(&ubp->uba_map[reg+btop(byte)]));
+ printf("old: %x, ", getmemc(addr));
+#endif
putmemc(addr, getmemc(addr)^(mask<<bit));
+#ifdef UPECCDEBUG
+ printf("new: %x\n", getmemc(addr));
+#endif
byte++;
i++;
bit -= 8;
* and restart all units and the controller.
*/
upreset(uban)
+ int uban;
{
- register struct uba_minfo *um;
- register struct uba_dinfo *ui;
+ register struct uba_ctlr *um;
+ register struct uba_device *ui;
register sc21, unit;
- int any = 0;
for (sc21 = 0; sc21 < NSC; sc21++) {
if ((um = upminfo[sc21]) == 0 || um->um_ubanum != uban ||
um->um_alive == 0)
continue;
- if (any == 0) {
- printf(" up");
- DELAY(10000000); /* give it time to self-test */
- any++;
- }
+ printf(" sc%d", sc21);
um->um_tab.b_active = 0;
um->um_tab.b_actf = um->um_tab.b_actl = 0;
+ up_softc[sc21].sc_recal = 0;
if (um->um_ubinfo) {
printf("<%d>", (um->um_ubinfo>>28)&0xf);
ubadone(um);
}
- ((struct updevice *)(um->um_addr))->upcs2 = UP_CLR;
+ ((struct updevice *)(um->um_addr))->upcs2 = UPCS2_CLR;
for (unit = 0; unit < NUP; unit++) {
if ((ui = updinfo[unit]) == 0)
continue;
- if (ui->ui_alive == 0)
+ if (ui->ui_alive == 0 || ui->ui_mi != um)
continue;
uputab[unit].b_active = 0;
(void) upustart(ui);
/*
* Wake up every second and if an interrupt is pending
* but nothing has happened increment a counter.
- * If nothing happens for 20 seconds, reset the controller
+ * If nothing happens for 20 seconds, reset the UNIBUS
* and begin anew.
*/
upwatch()
{
- register struct uba_minfo *um;
+ register struct uba_ctlr *um;
register sc21, unit;
register struct up_softc *sc;
- timeout(upwatch, (caddr_t)0, HZ);
+ timeout(upwatch, (caddr_t)0, hz);
for (sc21 = 0; sc21 < NSC; sc21++) {
um = upminfo[sc21];
if (um == 0 || um->um_alive == 0)
sc->sc_wticks = 0;
continue;
}
- active:
+active:
sc->sc_wticks++;
if (sc->sc_wticks >= 20) {
sc->sc_wticks = 0;
- printf("LOST upintr ");
+ printf("sc%d: lost interrupt\n", sc21);
ubareset(um->um_ubanum);
}
}
int num, blk, unit;
struct size *sizes;
register struct uba_regs *uba;
- register struct uba_dinfo *ui;
+ register struct uba_device *ui;
register short *rp;
struct upst *st;
unit = minor(dev) >> 3;
- if (unit >= NUP) {
- printf("bad unit\n");
- return (-1);
- }
+ if (unit >= NUP)
+ return (ENXIO);
#define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
- ui = phys(struct uba_dinfo *, updinfo[unit]);
- if (ui->ui_alive == 0) {
- printf("dna\n");
- return(-1);
- }
+ ui = phys(struct uba_device *, updinfo[unit]);
+ if (ui->ui_alive == 0)
+ return (ENXIO);
uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
-#if VAX780
- if (cpu == VAX_780)
- ubainit(uba);
-#endif
- DELAY(1000000);
+ ubainit(uba);
upaddr = (struct updevice *)ui->ui_physaddr;
- while ((upaddr->upcs1&UP_DVA) == 0)
- ;
+ DELAY(2000000);
num = maxfree;
start = 0;
upaddr->upcs2 = unit;
- if ((upaddr->upds & UP_VV) == 0) {
+ DELAY(100);
+ if ((upaddr->upcs1&UP_DVA) == 0)
+ return (EFAULT);
+ if ((upaddr->upds & UPDS_VV) == 0) {
upaddr->upcs1 = UP_DCLR|UP_GO;
upaddr->upcs1 = UP_PRESET|UP_GO;
- upaddr->upof = UP_FMT22;
- }
- if ((upaddr->upds & (UP_DPR|UP_MOL)) != (UP_DPR|UP_MOL)) {
- printf("dna\n");
- return (-1);
+ upaddr->upof = UPOF_FMT22;
}
+ if ((upaddr->upds & UPDS_DREADY) != UPDS_DREADY)
+ return (EFAULT);
st = &upst[ui->ui_type];
sizes = phys(struct size *, st->sizes);
- if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) {
- printf("oor\n");
- return (-1);
- }
+ if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
+ return (EINVAL);
while (num > 0) {
register struct pte *io;
register int i;
blk = num > DBSIZE ? DBSIZE : num;
io = uba->uba_map;
for (i = 0; i < blk; i++)
- *(int *)io++ = (btop(start)+i) | (1<<21) | UBA_MRV;
+ *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
*(int *)io = 0;
bn = dumplo + btop(start);
cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
do {
DELAY(25);
} while ((upaddr->upcs1 & UP_RDY) == 0);
- if (upaddr->upcs1&UP_ERR) {
- printf("up dump dsk err: (%d,%d,%d) cs1=%x, er1=%x\n",
- cn, tn, sn, upaddr->upcs1, upaddr->uper1);
- return (-1);
- }
+ if (upaddr->upds&UPDS_ERR)
+ return (EIO);
start += blk*NBPG;
num -= blk;
}