+
+/*
+ * Reset driver after UBA init.
+ * Cancel software state of all pending transfers
+ * and restart all units and the controller.
+ */
+upreset(uban)
+ int uban;
+{
+ register struct uba_ctlr *um;
+ register struct uba_device *ui;
+ register sc21, unit;
+
+ for (sc21 = 0; sc21 < NSC; sc21++) {
+ if ((um = upminfo[sc21]) == 0 || um->um_ubanum != uban ||
+ um->um_alive == 0)
+ continue;
+ 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;
+ up_softc[sc21].sc_wticks = 0;
+ if (um->um_ubinfo) {
+ printf("<%d>", (um->um_ubinfo>>28)&0xf);
+ ubadone(um);
+ }
+ ((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 || ui->ui_mi != um)
+ continue;
+ uputab[unit].b_active = 0;
+ (void) upustart(ui);
+ }
+ (void) upstart(um);
+ }
+}
+
+/*
+ * 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 UNIBUS
+ * and begin anew.
+ */
+upwatch()
+{
+ register struct uba_ctlr *um;
+ register sc21, unit;
+ register struct up_softc *sc;
+
+ timeout(upwatch, (caddr_t)0, hz);
+ for (sc21 = 0; sc21 < NSC; sc21++) {
+ um = upminfo[sc21];
+ if (um == 0 || um->um_alive == 0)
+ continue;
+ sc = &up_softc[sc21];
+ if (um->um_tab.b_active == 0) {
+ for (unit = 0; unit < NUP; unit++)
+ if (uputab[unit].b_active &&
+ updinfo[unit]->ui_mi == um)
+ goto active;
+ sc->sc_wticks = 0;
+ continue;
+ }
+active:
+ sc->sc_wticks++;
+ if (sc->sc_wticks >= 20) {
+ sc->sc_wticks = 0;
+ printf("sc%d: lost interrupt\n", sc21);
+ ubareset(um->um_ubanum);
+ }
+ }
+}
+
+#define DBSIZE 20
+
+updump(dev)
+ dev_t dev;
+{
+ struct updevice *upaddr;
+ char *start;
+ int num, blk, unit;
+ struct size *sizes;
+ register struct uba_regs *uba;
+ register struct uba_device *ui;
+ register short *rp;
+ struct upst *st;
+
+ unit = minor(dev) >> 3;
+ if (unit >= NUP)
+ return (ENXIO);
+#define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
+ ui = phys(struct uba_device *, updinfo[unit]);
+ if (ui->ui_alive == 0)
+ return (ENXIO);
+ uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
+ ubainit(uba);
+ upaddr = (struct updevice *)ui->ui_physaddr;
+ DELAY(2000000);
+ num = maxfree;
+ start = 0;
+ upaddr->upcs2 = unit;
+ 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 = 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)
+ return (EINVAL);
+ while (num > 0) {
+ register struct pte *io;
+ register int i;
+ int cn, sn, tn;
+ daddr_t bn;
+
+ blk = num > DBSIZE ? DBSIZE : num;
+ io = uba->uba_map;
+ for (i = 0; i < blk; i++)
+ *(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;
+ sn = bn%st->nspc;
+ tn = sn/st->nsect;
+ sn = sn%st->nsect;
+ upaddr->updc = cn;
+ rp = (short *) &upaddr->upda;
+ *rp = (tn << 8) + sn;
+ *--rp = 0;
+ *--rp = -blk*NBPG / sizeof (short);
+ *--rp = UP_GO|UP_WCOM;
+ do {
+ DELAY(25);
+ } while ((upaddr->upcs1 & UP_RDY) == 0);
+ if (upaddr->upds&UPDS_ERR)
+ return (EIO);
+ start += blk*NBPG;
+ num -= blk;
+ }
+ return (0);
+}
+#endif