+#include "../h/pte.h"
+#include "../h/vm.h"
+#include "../h/ubareg.h"
+#include "../h/ubavar.h"
+#include "../h/mtio.h"
+#include "../h/ioctl.h"
+#include "../h/cmap.h"
+#include "../h/cpu.h"
+
+#include "../h/tsreg.h"
+
+/*
+ * There is a ctsbuf per tape controller.
+ * It is used as the token to pass to the internal routines
+ * to execute tape ioctls.
+ * In particular, when the tape is rewinding on close we release
+ * the user process but any further attempts to use the tape drive
+ * before the rewind completes will hang waiting for ctsbuf.
+ */
+struct buf ctsbuf[NTS];
+
+/*
+ * Raw tape operations use rtsbuf. The driver
+ * notices when rtsbuf is being used and allows the user
+ * program to continue after errors and read records
+ * not of the standard length (BSIZE).
+ */
+struct buf rtsbuf[NTS];
+
+/*
+ * Driver unibus interface routines and variables.
+ */
+int tsprobe(), tsslave(), tsattach(), tsdgo(), tsintr();
+struct uba_ctlr *tsminfo[NTS];
+struct uba_device *tsdinfo[NTS];
+struct buf tsutab[NTS];
+u_short tsstd[] = { 0772520, 0 };
+/*** PROBABLY DON'T NEED ALL THESE SINCE CONTROLLER == DRIVE ***/
+struct uba_driver zsdriver =
+ { tsprobe, tsslave, tsattach, tsdgo, tsstd, "ts", tsdinfo, "zs", tsminfo, 0 };
+
+/* bits in minor device */
+#define TSUNIT(dev) (minor(dev)&03)
+#define T_NOREWIND 04
+
+#define INF (daddr_t)1000000L
+
+/*
+ * Software state per tape transport.
+ * Also contains hardware state in message packets.
+ *
+ * 1. A tape drive is a unique-open device; we refuse opens when it is already.
+ * 2. We keep track of the current position on a block tape and seek
+ * before operations by forward/back spacing if necessary.
+ * 3. We remember if the last operation was a write on a tape, so if a tape
+ * is open read write and the last thing done is a write we can
+ * write a standard end of tape mark (two eofs).
+ * 4. We remember the status registers after the last command, using
+ * then internally and returning them to the SENSE ioctl.
+ */
+struct ts_softc {
+ char sc_openf; /* lock against multiple opens */
+ char sc_lastiow; /* last op was a write */
+ short sc_resid; /* copy of last bc */
+ daddr_t sc_blkno; /* block number, for block device tape */
+ daddr_t sc_nxrec; /* position of end of tape, if known */
+ struct ts_cmd sc_cmd; /* the command packet */
+ struct ts_sts sc_sts; /* status packet, for returned status */
+ struct ts_char sc_char; /* characteristics packet */
+ struct ts_softc *sc_ubaddr; /* Unibus address of ts_softc structure */
+ u_short sc_uba; /* Unibus addr of cmd pkt for tsdb */
+ short sc_mapped; /* is ts_sfotc mapped in Unibus space? */
+} ts_softc[NTS];
+
+/*
+ * States for um->um_tab.b_active, the per controller state flag.
+ * This is used to sequence control in the driver.
+ */
+#define SSEEK 1 /* seeking */
+#define SIO 2 /* doing seq i/o */
+#define SCOM 3 /* sending control command */
+#define SREW 4 /* sending a drive rewind */
+
+/*
+ * Determine if there is a controller for
+ * a ts at address reg. Our goal is to make the
+ * device interrupt.
+ */
+/*ARGSUSED*/
+tsprobe(reg)
+ caddr_t reg;
+{
+ register int br, cvec; /* must be r11,r10; value-result */
+
+#ifdef lint
+ br = 0; cvec = br; br = cvec;
+ tsintr(0);
+#endif
+ ((struct tsdevice *)reg)->tssr = 0;
+ DELAY(100);
+ if ((((struct tsdevice *)reg)->tssr & TS_NBA) == 0)
+ return(0);
+ /* IT'S TOO HARD TO MAKE THIS THING INTERRUPT JUST TO FIND ITS VECTOR */
+ cvec = ((unsigned)reg) & 07 ? 0260 : 0224;
+ br = 0x15;
+ return (1);
+}
+
+/*
+ * TS11 only supports one drive per controller;
+ * check for ui_slave == 0.
+ *
+ * DO WE REALLY NEED THIS ROUTINE???
+ */
+/*ARGSUSED*/
+tsslave(ui, reg)
+ struct uba_device *ui;
+ caddr_t reg;
+{
+
+ if (ui->ui_slave) /* non-zero slave not allowed */
+ return(0);
+ return (1);
+}
+
+/*
+ * Record attachment of the unit to the controller.
+ *
+ * SHOULD THIS ROUTINE DO ANYTHING???
+ */
+/*ARGSUSED*/
+tsattach(ui)
+ struct uba_device *ui;
+{
+
+}