From b73334678d405e42f6f5adb04913f57b1398f837 Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Fri, 20 Feb 1981 05:58:37 -0800 Subject: [PATCH] almost working ubago version (tm.c problems) SCCS-vsn: sys/vax/uba/uba.c 4.11 SCCS-vsn: sys/vax/uba/up.c 4.17 --- usr/src/sys/vax/uba/uba.c | 138 +++++++++++++++++++++++++++++++++----- usr/src/sys/vax/uba/up.c | 54 ++++++--------- 2 files changed, 142 insertions(+), 50 deletions(-) diff --git a/usr/src/sys/vax/uba/uba.c b/usr/src/sys/vax/uba/uba.c index 2497e85c38..bd2b65b0b3 100644 --- a/usr/src/sys/vax/uba/uba.c +++ b/usr/src/sys/vax/uba/uba.c @@ -1,4 +1,6 @@ -/* uba.c 4.10 %G% */ +/* uba.c 4.11 %G% */ + +#define DELAY(N) { register int d; d = N; while (--d > 0); } #include "../h/param.h" #include "../h/systm.h" @@ -6,21 +8,73 @@ #include "../h/map.h" #include "../h/pte.h" #include "../h/buf.h" +#include "../h/vm.h" #include "../h/uba.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/proc.h" -#include "../h/vm.h" #include "../h/conf.h" #include "../h/mtpr.h" #include "../h/nexus.h" +#include "../h/dk.h" + +/* + * Do transfer on device argument. The controller + * and uba involved are implied by the device. + * We queue for resource wait in the uba code if necessary. + * We return 1 if the transfer was started, 0 if it was not. + * If you call this routine with the head of the queue for a + * UBA, it will automatically remove the device from the UBA + * queue before it returns. If some other device is given + * as argument, it will be added to the request queue if the + * request cannot be started immediately. This means that + * passing a device which is on the queue but not at the head + * of the request queue is likely to be a disaster. + */ +ubago(ui) + register struct uba_dinfo *ui; +{ + register struct uba_minfo *um = ui->ui_mi; + register struct uba_hd *uh; + register int s, unit; + + uh = &uba_hd[um->um_ubanum]; + s = spl6(); + um->um_ubinfo = ubasetup(um->um_ubanum, um->um_tab.b_actf->b_actf, + UBA_NEEDBDP|UBA_CANTWAIT); + if (um->um_ubinfo == 0) { + if (uh->uh_actf != ui) { + ui->ui_forw = NULL; + if (uh->uh_actf == NULL) + uh->uh_actf = ui; + else + uh->uh_actl->ui_forw = ui; + uh->uh_actl = ui; + } + splx(s); + return (0); + } + splx(s); + if (ui->ui_dk >= 0) { + unit = ui->ui_dk; + dk_busy |= 1<uh_actf == ui) + uh->uh_actf = ui->ui_forw; + (*um->um_driver->ud_dgo)(um); + if (ui->ui_dk >= 0) { + dk_xfer[unit]++; + dk_wds[unit] += um->um_tab.b_actf->b_bcount>>6; + } + return (1); +} /* * Allocate and setup UBA map registers, and bdp's * Flags says whether bdp is needed, whether the caller can't * wait (e.g. if the caller is at interrupt level). * - * Return value (cruft): + * Return value: * Bits 0-8 Byte offset * Bits 9-17 Start map reg. no. * Bits 18-27 No. mapping reg's @@ -93,7 +147,7 @@ ubasetup(uban, bp, flags) } /* - * Non buffer unibus interface... set up a buffer and call ubasetup. + * Non buffer setup interface... set up a buffer and call ubasetup. */ uballoc(uban, addr, bcnt, flags) caddr_t addr; @@ -109,22 +163,33 @@ uballoc(uban, addr, bcnt, flags) } /* - * Old ubafree(info) is now ubarelse(&info) to avoid races. + * Release resources on uba uban, and then unblock resource waiters. + * The map register parameter is by value since we need to block + * against uba resets on 11/780's. */ ubarelse(uban, amr) int *amr; { register struct uba_hd *uh = &uba_hd[uban]; - register int bdp, reg, npf, a; + register int bdp, reg, npf, s; int mr; - a = spl6(); + /* + * Carefully see if we should release the space, since + * it may be released asynchronously at uba reset time. + */ + s = spl6(); mr = *amr; if (mr == 0) { - splx(a); + /* + * A ubareset() occurred before we got around + * to releasing the space... no need to bother. + */ + splx(s); return; } *amr = 0; + splx(s); /* let interrupts in, we're safe for a while */ bdp = (mr >> 28) & 0x0f; if (bdp) { switch (cpu) @@ -140,25 +205,43 @@ ubarelse(uban, amr) break; #endif } - uh->uh_bdpfree |= 1 << (bdp-1); + uh->uh_bdpfree |= 1 << (bdp-1); /* atomic */ if (uh->uh_bdpwant) { uh->uh_bdpwant = 0; wakeup((caddr_t)uh->uh_map); } } + /* + * Put back the registers in the resource map. + * The map code must not be reentered, so we do this + * at high ipl. + */ npf = (mr >> 18) & 0x3ff; reg = ((mr >> 9) & 0x1ff) + 1; + s = spl6(); mfree(uh->uh_map, npf, reg); + splx(s); + + /* + * Wakeup sleepers for map registers, + * and also, if there are processes blocked in dgo(), + * give them a chance at the UNIBUS. + */ if (uh->uh_mrwant) { uh->uh_mrwant = 0; wakeup((caddr_t)uh->uh_map); } - splx(a); + while (uh->uh_actf && ubago(uh->uh_actf)) + ; } -#define DELAY(N) { register int d; d = N; while (--d > 0); } - +/* + * Generate a reset on uba number uban. Then + * call each device in the character device table, + * giving it a chance to clean up so as to be able to continue. + */ ubareset(uban) + int uban; { register struct cdevsw *cdp; int s; @@ -185,7 +268,14 @@ ubareset(uban) splx(s); } -/* pointer rather than number so we can be called with virt and phys addrs */ +/* + * Init a uba. This is called with a pointer + * rather than a virtual address since it is called + * by code which runs with memory mapping disabled. + * In these cases we really don't need the interrupts + * enabled, but since we run with ipl high, we don't care + * if they are, they will never happen anyways. + */ ubainit(uba) register struct uba_regs *uba; { @@ -197,6 +287,11 @@ ubainit(uba) } #if VAX780 +/* + * Check to make sure the UNIBUS adaptor is not hung, + * with an interrupt in the register to be presented, + * but not presenting it for an extended period (5 seconds). + */ unhang() { register int uban; @@ -216,8 +311,12 @@ unhang() } } -/* timeout routine to decrement ``i forgot to interrupt counts */ -/* this prevents the counts from growing slowly, which isn't interesting */ +/* + * This is a timeout routine which decrements the ``i forgot to + * interrupt'' counts, on an 11/780. This prevents slowly growing + * counts from causing a UBA reset since we are interested only + * in hang situations. + */ ubawatch() { register struct uba_hd *uh; @@ -230,7 +329,14 @@ ubawatch() } } -/* called from locore.s; parameters here (i.e. uvec) are value-result! */ +/* + * This routine is called by the locore code to + * process a UBA error on an 11/780. The arguments are passed + * on the stack, and value-result (through some trickery). + * In particular, the uvec argument is used for further + * uba processing so the result aspect of it is very important. + * It must not be declared register. + */ /*ARGSUSED*/ ubaerror(uban, uh, xx, uvec, uba) register int uban; diff --git a/usr/src/sys/vax/uba/up.c b/usr/src/sys/vax/uba/up.c index 57382ad4d1..95bc4ad9a4 100644 --- a/usr/src/sys/vax/uba/up.c +++ b/usr/src/sys/vax/uba/up.c @@ -1,4 +1,4 @@ -/* up.c 4.16 81/02/17 */ +/* up.c 4.17 81/02/19 */ #include "up.h" #if NSC21 > 0 @@ -20,8 +20,8 @@ #include "../h/pte.h" #include "../h/mba.h" #include "../h/mtpr.h" -#include "../h/uba.h" #include "../h/vm.h" +#include "../h/uba.h" #include "../h/cmap.h" #include "../h/upreg.h" @@ -29,7 +29,6 @@ struct up_softc { int sc_softas; int sc_seek; - int sc_info; int sc_wticks; /* struct uba_minfo sc_minfo; */ } up_softc[NSC21]; @@ -72,7 +71,7 @@ struct uba_dinfo *updinfo[NUP]; u_short upstd[] = { 0776700, 0774400, 0776300 }; struct uba_driver updriver = - { upcntrlr, upslave, updgo, 0, upstd, "up", updinfo, upminfo }; + { upcntrlr, upslave, updgo, 0, upstd, "up", updinfo, "sc", upminfo }; struct buf uputab[NUP]; struct upst { @@ -133,13 +132,11 @@ upslave(ui, reg, slaveno) timeout(upwatch, (caddr_t)0, HZ); upwstart++; } + if (ui->ui_dk >= 0) + dk_mspw[ui->ui_dk] = .0000020345; return (1); } -/* - dk_mspw[UPDK_N+unit] = .0000020345; -*/ - upstrategy(bp) register struct buf *bp; { @@ -289,8 +286,6 @@ loop: upaddr = (struct device *)ui->ui_addr; if ((upaddr->upcs2 & 07) != dn) upaddr->upcs2 = dn; - sc->sc_info = - ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP|UBA_CANTWAIT); /* * If drive is not present and on-line, then * get rid of this with an error and loop to get @@ -307,8 +302,6 @@ loop: dp->b_active = 0; bp->b_flags |= B_ERROR; iodone(bp); - /* A funny place to do this ... */ - ubarelse(ui->ui_ubanum, &sc->sc_info); goto loop; } printf("-- came back\n"); @@ -330,29 +323,23 @@ loop: */ upaddr->updc = bp->b_cylin; upaddr->upda = (tn << 8) + sn; - upaddr->upba = sc->sc_info; upaddr->upwc = -bp->b_bcount / sizeof (short); - cmd = (sc->sc_info >> 8) & 0x300; if (bp->b_flags & B_READ) - cmd |= IE|RCOM|GO; + cmd = IE|RCOM|GO; else - cmd |= IE|WCOM|GO; - upaddr->upcs1 = cmd; - /* - * Mark i/o in progress - */ - if (ui->ui_dk >= 0) { - unit = ui->ui_dk; - dk_busy |= 1<b_bcount>>6; - } + cmd = IE|WCOM|GO; + um->um_cmd = cmd; + ubago(ui); return (1); } -updgo() +updgo(um) + struct uba_minfo *um; { + register struct device *upaddr = (struct device *)um->um_addr; + upaddr->upba = um->um_ubinfo; + upaddr->upcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); } /* @@ -376,7 +363,6 @@ upintr(sc21) int as = upaddr->upas & 0377; int needie = 1; - (void) spl6(); sc->sc_wticks = 0; if (um->um_tab.b_active) { if ((upaddr->upcs1 & RDY) == 0) @@ -413,6 +399,7 @@ upintr(sc21) return; } } + ubarelse(ui->ui_ubanum, &um->um_ubinfo); if (um->um_tab.b_active) { if (um->um_tab.b_errcnt >= 16) { upaddr->upcs1 = RTC|GO|IE; @@ -438,7 +425,6 @@ upintr(sc21) needie = 0; } sc->sc_softas &= ~(1<ui_slave); - ubarelse(ui->ui_ubanum, &sc->sc_info); } else { if (upaddr->upcs1 & TRE) upaddr->upcs1 = TRE; @@ -500,7 +486,7 @@ upecc(ui) * O is offset within a memory page of the first byte transferred. */ npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1; - reg = btop(sc->sc_info&0x3ffff) + npf; + 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); @@ -515,7 +501,7 @@ upecc(ui) * is the byte offset in the transfer, the variable byte * is the offset from a page boundary in main memory. */ - ubp->uba_dpr[(sc->sc_info>>28)&0x0f] |= UBA_BNE; + ubp->uba_dpr[(um->um_ubinfo>>28)&0x0f] |= UBA_BNE; i = up->upec1 - 1; /* -1 makes 0 origin */ bit = i&07; i = (i&~07)>>3; @@ -587,9 +573,9 @@ upreset(uban) } um->um_tab.b_active = 0; um->um_tab.b_actf = um->um_tab.b_actl = 0; - if (sc->sc_info) { - printf("<%d>", (sc->sc_info>>28)&0xf); - ubarelse(um->um_ubanum, &sc->sc_info); + if (um->um_ubinfo) { + printf("<%d>", (um->um_ubinfo>>28)&0xf); + ubarelse(um->um_ubanum, &um->um_ubinfo); } ((struct device *)(um->um_addr))->upcs2 = CLR; for (unit = 0; unit < NUP; unit++) { -- 2.20.1