+
+ /*
+ * Make it interrupt.
+ * TS_SETCHR|TS_IE alone refuses to interrupt for me.
+ */
+ sc = &ts_softc[ctlr];
+ tsmap(sc, numuba);
+ i = (int)&sc->sc_ubaddr->t_char;
+ sc->sc_ts.t_cmd.c_loba = i;
+ sc->sc_ts.t_cmd.c_hiba = (i >> 16) & 3;
+ sc->sc_ts.t_cmd.c_size = sizeof(struct ts_char);
+ sc->sc_ts.t_cmd.c_cmd = TS_ACK | TS_SETCHR;
+ sc->sc_ts.t_char.char_addr = (int)&sc->sc_ubaddr->t_sts;
+ sc->sc_ts.t_char.char_size = sizeof(struct ts_sts);
+ sc->sc_ts.t_char.char_mode = 0; /* mode is unimportant */
+ addr->tsdb = sc->sc_uba;
+ DELAY(20000);
+ sc->sc_ts.t_cmd.c_cmd = TS_ACK | TS_CVC | TS_IE | TS_SENSE;
+ sc->sc_ts.t_cmd.c_repcnt = 1;
+ addr->tsdb = sc->sc_uba;
+ DELAY(20000);
+ /*
+ * The controller should have interrupted by now, but some do not,
+ * even if the delays above are extended to many seconds. If the
+ * vector is still unknown, we assume the drive is present at
+ * the usual vector.
+ */
+ if (cvec == 0 || cvec == 0x200) {
+ cvec = (int)reg & 7 ? 0260 : 0224;
+ br = 0x15;
+ }
+ return (sizeof(struct tsdevice));
+}
+
+/*
+ * Map in the command, status, and characteristics packet. We
+ * make them contiguous to keep overhead down. This also sets
+ * sc_uba (which then never changes).
+ */
+tsmap(sc, uban)
+ register struct ts_softc *sc;
+ int uban;
+{
+ register int i;
+
+ i = uballoc(uban, (caddr_t)&sc->sc_ts, sizeof(sc->sc_ts), 0);
+ i = UBAI_ADDR(i);
+ sc->sc_ubaddr = (struct ts_tsdata *)i;
+ /*
+ * Note that i == the Unibus address of the command packet,
+ * and that it is a multiple of 4 (guaranteed by the compiler).
+ */
+ sc->sc_uba = i + ((i >> 16) & 3);