summaryrefslogtreecommitdiff
path: root/sys/arch/vax/uba/ts.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch/vax/uba/ts.c')
-rw-r--r--sys/arch/vax/uba/ts.c677
1 files changed, 272 insertions, 405 deletions
diff --git a/sys/arch/vax/uba/ts.c b/sys/arch/vax/uba/ts.c
index c2bb299e6a2..cdb14f69d4a 100644
--- a/sys/arch/vax/uba/ts.c
+++ b/sys/arch/vax/uba/ts.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ts.c,v 1.6 1996/04/08 18:37:32 ragge Exp $ */
+/* $NetBSD: ts.c,v 1.11 1997/01/11 11:34:43 ragge Exp $ */
/*-
* Copyright (c) 1991 The Regents of the University of California.
@@ -14,8 +14,8 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@@ -32,35 +32,35 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)tmscp.c 7.16 (Berkeley) 5/9/91
+ * @(#)tmscp.c 7.16 (Berkeley) 5/9/91
*/
/*
- * sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86";
+ * sccsid = "@(#)tmscp.c 1.24 (ULTRIX) 1/21/86";
*/
/************************************************************************
- * *
- * Licensed from Digital Equipment Corporation *
- * Copyright (c) *
- * Digital Equipment Corporation *
- * Maynard, Massachusetts *
- * 1985, 1986 *
- * All rights reserved. *
- * *
- * The Information in this software is subject to change *
- * without notice and should not be construed as a commitment *
- * by Digital Equipment Corporation. Digital makes no *
- * representations about the suitability of this software for *
- * any purpose. It is supplied "As Is" without expressed or *
- * implied warranty. *
- * *
- * If the Regents of the University of California or its *
- * licensees modify the software in a manner creating *
- * diriviative copyright rights, appropriate copyright *
- * legends may be placed on the drivative work in addition *
- * to that set forth above. *
- * *
+ * *
+ * Licensed from Digital Equipment Corporation *
+ * Copyright (c) *
+ * Digital Equipment Corporation *
+ * Maynard, Massachusetts *
+ * 1985, 1986 *
+ * All rights reserved. *
+ * *
+ * The Information in this software is subject to change *
+ * without notice and should not be construed as a commitment *
+ * by Digital Equipment Corporation. Digital makes no *
+ * representations about the suitability of this software for *
+ * any purpose. It is supplied "As Is" without expressed or *
+ * implied warranty. *
+ * *
+ * If the Regents of the University of California or its *
+ * licensees modify the software in a manner creating *
+ * diriviative copyright rights, appropriate copyright *
+ * legends may be placed on the drivative work in addition *
+ * to that set forth above. *
+ * *
************************************************************************/
/*
@@ -69,20 +69,9 @@
* should be TS11 compatible (untested)
*/
-#define NCMD 1
-#define NMSG 1
-
-#if 0
-# define DEBUG
-# define TRACE
-#else
-# undef DEBUG
-# undef TRACE
-#endif
-
#define TS11_COMPAT /* don't use extended features provided by TS05 */
-#ifdef NEED_18BIT
+#ifdef NEED_18BIT
#define TS_UBAFLAGS UBA_NEED16
#else
#define TS_UBAFLAGS 0
@@ -92,10 +81,10 @@
#define ENABLE_END
#define ENABLE_EAI /* enable Attention-Interrupts */
-#undef ENABLE_EAI
+#undef ENABLE_EAI
#define ENABLE_ERI /* Enable Release Buffer Interrupts */
-#undef ENABLE_ERI
+#undef ENABLE_ERI
#ifdef DEBUG
int tsdebug = 1;
@@ -129,11 +118,6 @@ int tstrace = 1;
*/
-#include "ts.h"
-
-#if NTS > 0
-
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -147,7 +131,6 @@ int tstrace = 1;
#include <sys/mtio.h>
#include <sys/uio.h>
#include <sys/proc.h>
-#include <sys/tprintf.h>
#include <machine/pte.h>
#include <machine/sid.h>
@@ -159,24 +142,14 @@ int tstrace = 1;
#include <vax/uba/tsreg.h>
-int ts_match __P((struct device *, void *, void *));
-void ts_attach __P((struct device *, struct device *, void *));
-void tsstrategy __P((struct buf *));
-
-struct cfdriver ts_cd = {
- NULL, "ts", DV_DULL
-};
-
-struct cfattach ts_ca = {
- sizeof(struct device), ts_match, ts_attach
-};
+#include "ts.h"
/*
* ts command packets and communication area (per controller)
*/
-struct ts {
+struct ts {
struct tsdevice *reg; /* address of i/o-registers */
- struct tscmd cmd; /* command packet(s) */
+ struct tscmd cmd; /* command packet(s) */
struct tsmsg msg; /* message packet(s) */
} ts[NTS];
@@ -186,37 +159,38 @@ struct ts {
* (thus we have no struct ts_info)
*/
struct ts_softc {
- struct ts *sc_ts; /* Unibus address of uda struct */
- short sc_mapped; /* Unibus map allocated ? */
- int sc_ubainfo; /* Unibus mapping info */
- short sc_state; /* see below: ST_xxx */
- short sc_flags; /* see below: FL_xxx */
+ struct device sc_dev; /* Autoconf ... */
+ struct uba_unit sc_unit; /* Struct common for UBA to talk */
+ struct ts *sc_ts; /* Unibus address of uda struct */
+ short sc_mapped; /* Unibus map allocated ? */
+ int sc_ubainfo; /* Unibus mapping info */
+ short sc_state; /* see below: ST_xxx */
+ short sc_flags; /* see below: FL_xxx */
short sc_lcmd; /* last command word */
short sc_rtc; /* retry count for lcmd */
short sc_lssr; /* last status register */
short sc_lmsgh; /* last message header */
short sc_lxst0; /* last status word */
short sc_cmdf; /* command flags (ack,cvc,ie) */
- short sc_openf; /* lock against multiple opens */
+ short sc_openf; /* lock against multiple opens */
short sc_liowf; /* last operation was write */
- int sc_micro; /* microcode revision */
- int sc_ivec; /* interrupt vector address */
- short sc_ipl; /* interrupt priority, Q-bus */
- tpr_t sc_tpr; /* tprintf handle */
-} ts_softc[NTS];
-
-int tsprobe __P((caddr_t, int, struct uba_ctlr *, struct uba_softc *));
-int tsslave __P((struct uba_device *, caddr_t));
-void tsattach __P((struct uba_device *));
+ int sc_micro; /* microcode revision */
+ int sc_ivec; /* interrupt vector address */
+ short sc_ipl; /* interrupt priority, Q-bus */
+};
+
void tsintr __P((int));
-int tsinit __P((int));
+int tsinit __P((struct ts_softc *));
void tscommand __P((dev_t, int, int));
int tsstatus __P((int));
int tsexec __P((int, int));
-int tsstart __P((struct uba_ctlr *, struct buf *));
+int tsstart __P((struct ts_softc *, struct buf *));
int tswchar __P((int));
void tsreset __P((int));
void tsxstatus __P((struct tsmsg *));
+int tsmatch __P((struct device *, void *, void *));
+void tsattach __P((struct device *, struct device *, void *));
+void tsstrategy __P((struct buf *));
int tsopen __P((dev_t, int, int, struct proc *));
int tsclose __P((dev_t, int, int, struct proc *));
@@ -225,37 +199,30 @@ int tsread __P((dev_t, struct uio *));
int tswrite __P((dev_t, struct uio *));
int tsdump __P((dev_t, daddr_t, caddr_t, size_t));
+struct cfdriver ts_cd = {
+ NULL, "ts", DV_DULL
+};
+
+struct cfattach ts_ca = {
+ sizeof(struct ts_softc), tsmatch, tsattach
+};
+
#define ST_INVALID 0 /* uninitialized, before probe */
#define ST_PROBE 1 /* during tsprobe(), not used */
#define ST_SLAVE 2 /* in tsslave(), init almost complete */
#define ST_ATTACH 3 /* during tsattach(), not used */
-#define ST_INITIALIZED 4 /* init completed, set by tsintr() */
+#define ST_INITIALIZED 4 /* init completed, set by tsintr() */
#define ST_RUNNING 5
#define ST_IDLE 6
#define ST_BUSY 7
/* Bits in minor device */
#define TS_UNIT(dev) (minor(dev)&03)
-#define TS_CTLR(dev) (TS_UNIT(dev))
#define TS_HIDENSITY 010
-#define TS_PRI LOG_INFO
-
-/*
- * Definition of the driver for autoconf.
- */
-#define CTLRNAME "zs" /* ts/zs ??? */
-#define UNITNAME "ts"
-
-struct uba_ctlr *zsinfo[NTS]; /* controller-info */
-struct uba_device *tsinfo[NTS]; /* unit(tape)-info */
+#define TS_PRI LOG_INFO
-u_short tsstd[] = { 0172520, 0172524, /* standart csr for ts */
- 0172530, 0172534, 0 }; /* standart csr for ts */
-
-struct uba_driver tsdriver = { tsprobe, tsslave, tsattach, 0, tsstd,
- UNITNAME, tsinfo, CTLRNAME, zsinfo, 0 };
/*
* Since we don't have credits and thus only one operation per time,
@@ -274,30 +241,25 @@ struct buf *ts_wtab[NTS]; /* dummy I/O wait queue */
* initialize data structures, what else ???
*/
int
-tsinit (unit)
- int unit;
+tsinit (sc)
+ struct ts_softc *sc;
{
- register struct ts_softc *sc;
volatile struct tsdevice *tsregs;
- struct uba_ctlr *um;
+ int unit = sc->sc_dev.dv_unit;
+ struct uba_unit *uu;
- trace (("tsinit: unit = %d\n", unit));
-
- sc = &ts_softc[unit];
- um = zsinfo[unit];
- um->um_tab.b_active++; /* ??? */
- tsregs = (struct tsdevice *)um->um_addr;
+ uu = &sc->sc_unit;
+ tsregs = (struct tsdevice *)ts[unit].reg;
if (sc->sc_mapped == 0) {
/*
* Map the communications area and command and message
* buffer into Unibus address space.
*/
- sc->sc_ubainfo = uballoc (um->um_ubanum, (caddr_t)&ts[unit],
- sizeof (struct ts), TS_UBAFLAGS);
+ sc->sc_ubainfo = uballoc((struct uba_softc *)
+ sc->sc_dev.dv_parent,
+ (caddr_t)&ts[unit], sizeof (struct ts), TS_UBAFLAGS);
sc->sc_ts = (struct ts *)(UBAI_ADDR(sc->sc_ubainfo));
sc->sc_mapped = 1;
- debug (("sc_mapped: %d [%x, %x]\n", sc->sc_mapped,
- sc->sc_ubainfo, sc->sc_ts));
}
/*
@@ -320,7 +282,7 @@ tsexec (ctlr, cmd)
int ctlr;
int cmd;
{
- register struct ts_softc *sc = &ts_softc[ctlr];
+ register struct ts_softc *sc = ts_cd.cd_devs[ctlr];
register struct tscmd *tscmdp = &ts[ctlr].cmd;
register long tscmdma = (long)&sc->sc_ts->cmd; /* mapped address */
volatile struct tsdevice *tsreg = ts[ctlr].reg;
@@ -349,13 +311,12 @@ tsexec (ctlr, cmd)
case TS_CMD_STAT: cmdName = "Get Status (END)"; break;
default: cmdName = "unexptected Command"; break;
}
- debug (("tsexec: cmd = 0x%x (%s)\n", tscmdp->cmdr, cmdName));
#endif
sr = tsreg->tssr;
if ((sr & TS_SSR) == 0) { /* subsystem NOT ready */
printf ("%s%d: subsystem not ready [%x]\n",
- CTLRNAME, ctlr, sr);
+ sc->sc_dev.dv_xname, sr);
return (-1);
}
dbx = ((char*)tsreg) + 3; /* dbx is located at the fourth byte */
@@ -375,7 +336,7 @@ tsexec (ctlr, cmd)
* wait for SSR or RMR to show up
*/
sr = tsreg->tssr;
- if ((sr & TS_SSR) != 0) { /* something went wrong .. */
+ if ((sr & TS_SSR) != 0) { /* something went wrong .. */
if (sr & TS_RMR) {
printf ("ts: error writing TSDB (RMR)\n");
return (-1);
@@ -404,15 +365,14 @@ tscommand (dev, cmd, count)
int count;
{
register struct buf *bp;
- register int s;
+ register int s;
trace (("tscommand (%d, %x, %d)\n", TS_UNIT(dev), cmd, count));
s = splbio();
bp = &ts_cbuf[TS_UNIT(dev)];
-#if 1
+
while (bp->b_flags & B_BUSY) {
- debug (("looping 'cause B_BUSY\n"));
/*
* This special check is because B_BUSY never
* gets cleared in the non-waiting rewind case. ???
@@ -420,12 +380,11 @@ tscommand (dev, cmd, count)
if (bp->b_bcount == 0 && (bp->b_flags & B_DONE))
break;
bp->b_flags |= B_WANTED;
- debug (("sleeping ...\n"));;
sleep ((caddr_t)bp, PRIBIO);
/* check MOT-flag !!! */
}
bp->b_flags = B_BUSY | B_READ;
-#endif
+
splx(s);
/*
@@ -438,7 +397,6 @@ tscommand (dev, cmd, count)
bp->b_bcount = count;
bp->b_resid = cmd;
bp->b_blkno = 0;
- debug (("tscommand: calling tsstrategy ...\n"));
tsstrategy (bp);
/*
* In case of rewind from close, don't wait.
@@ -459,42 +417,34 @@ tscommand (dev, cmd, count)
* Start an I/O operation on TS05 controller
*/
int
-tsstart (um, bp)
- register struct uba_ctlr *um;
+tsstart (sc, bp)
+ register struct ts_softc *sc;
register struct buf *bp;
{
- register struct ts_softc *sc = &ts_softc[um->um_ctlr];
- volatile struct tsdevice *tsreg = ts[um->um_ctlr].reg;
- register struct tscmd *tscmdp = &ts[um->um_ctlr].cmd;
+ int ctlr = sc->sc_dev.dv_unit;
+ volatile struct tsdevice *tsreg = ts[ctlr].reg;
+ register struct tscmd *tscmdp = &ts[ctlr].cmd;
register struct buf *dp;
volatile int i, itmp;
- int unit;
int ioctl;
int cmd;
- unit = um->um_ctlr;
- trace (("tsstart (unit = %d)\n", unit));
- sc = &ts_softc[unit];
-
- if ((dp = ts_wtab[unit]) != NULL) {
+ if ((dp = ts_wtab[ctlr]) != NULL) {
/*
* There's already a command pending ...
* Either we are called by tsintr or we have missed
* something important (race condition).
*/
- debug (("tsstart: I/O queue not empty.\n"));
/* bertram: ubarelse ??? */
- ts_wtab[um->um_ctlr] = NULL;
+ ts_wtab[ctlr] = NULL;
dp->b_flags |= B_ERROR;
iodone (dp);
if (tsreg->tssr & TS_SC) { /* Special Condition; Error */
- tprintf (sc->sc_tpr, "%s%d: error at bn%d\n",
- UNITNAME, unit, dp->b_blkno);
- log (TS_PRI, "%s%d: tssr 0x%x, state %d\n",
- CTLRNAME, unit, tsreg->tssr, sc->sc_state);
- tsinit (unit);
+ log (TS_PRI, "%s: tssr 0x%x, state %d\n",
+ sc->sc_dev.dv_xname, tsreg->tssr, sc->sc_state);
+ tsinit (sc);
return (-1);
}
/* XXX */
@@ -505,47 +455,43 @@ tsstart (um, bp)
* If it's an ioctl then just set the flags for later use;
* For other commands attempt to setup a buffer pointer.
*/
- if (bp == &ts_cbuf[um->um_ctlr]) {
+ if (bp == &ts_cbuf[ctlr]) {
ioctl = 1;
- debug (("tsstart(ioctl): unit %d\n", um->um_ctlr));
} else {
ioctl = 0;
- debug (("tsstart(rw): unit %d\n", um->um_ctlr));
/*
* now we try to map the buffer into uba map space (???)
*/
i = TS_UBAFLAGS;
- switch (cpunumber) {
+ switch (vax_cputype) {
case VAX_8600:
case VAX_780:
i |= UBA_CANTWAIT;
break;
case VAX_750:
- i |= um->um_ubinfo | UBA_CANTWAIT;
+ i |= sc->sc_unit.uu_ubinfo | UBA_CANTWAIT;
break;
case VAX_730:
case VAX_78032:
i |= UBA_CANTWAIT;
break;
default:
- printf ("unsupported cpu %d in tsstart.\n", cpunumber);
- } /* end switch (cpunumber) */
+ printf ("unsupported cpu %d in tsstart.\n", vax_cputype);
+ } /* end switch (vax_cputype) */
- debug (("ubasetup (%x, %x, %x)\n", um->um_ubanum, bp, i));
- if ((i = ubasetup (um->um_ubanum, bp, i)) == 0) {
+ if ((i = ubasetup(sc->sc_dev.dv_parent->dv_unit, bp, i)) == 0) {
/*
* For some reasons which I don't (yet? :) understand,
* tmscp.c initiates in this situation a GET-UNIT
* command. (Because no data-buffers are neccess. ??)
*/
- debug (("tsstart: %d, ubasetup = 0\n", um->um_ctlr));
cmd = TS_CMD_STAT;
goto do_cmd;
return (-1); /* ??? */
}
#if defined(VAX750)
- if (cpunumber == VAX_750)
+ if (vax_cputype == VAX_750)
itmp = i & 0xfffffff; /* mask off bdp */
else
#endif
@@ -553,7 +499,6 @@ tsstart (um, bp)
/* XXX */
}
- debug (("ubasetup done. [%x, %x, %d]\n", i, itmp, ioctl));
/*
* If it's an ioctl command, then assemble the command.
@@ -561,7 +506,6 @@ tsstart (um, bp)
* in <sys/mtio.h>
*/
if (ioctl) {
- debug (("tsstart: doing ioctl %d\n", bp->b_resid));
switch ((int)bp->b_resid) {
case MTWEOF:
cmd = TS_CMD_WTM;
@@ -597,24 +541,20 @@ tsstart (um, bp)
cmd = TS_CMD_STAT;
break;
default:
- printf ("%s%d: bad ioctl %d\n",
- CTLRNAME, unit, (int)bp->b_resid);
+ printf ("%s: bad ioctl %d\n", sc->sc_dev.dv_xname,
+ (int)bp->b_resid);
/* Need a no-op. get status */
cmd = TS_CMD_STAT;
} /* end switch (bp->b_resid) */
} else { /* Its a read/write command (not an ioctl) */
- debug (("tsstart: non-ioctl [%x, %xi, %x]\n",
- tscmdp, UBAI_ADDR(i), bp));
tscmdp->cw1 = UBAI_ADDR(i) & 0xffff;
tscmdp->cw2 = (UBAI_ADDR(i) >> 16) & 0x3f;
tscmdp->cw3 = bp->b_bcount;
if (bp->b_flags & B_READ) {
- debug (("read-command(%d)\n", tscmdp->cw3));
cmd = TS_CMD_RNF;
}
else {
- debug (("write-command(%d)\n", tscmdp->cw3));
cmd = TS_CMD_WD;
}
bp->b_ubinfo = itmp; /* save mapping info */
@@ -623,22 +563,20 @@ tsstart (um, bp)
/*
* Move buffer to I/O wait pseudo-queue
*/
- if (ts_wtab[um->um_ctlr]) {
+ if (ts_wtab[ctlr]) {
/*
* we are already waiting for something ...
* this should not happen, so we have a problem now.
* bertram: set error-flag and call iodone() ???
*/
- debug (("tsstart: already waiting for something ...\n"));
}
- ts_wtab[um->um_ctlr] = bp;
+ ts_wtab[ctlr] = bp;
/*
* Now that the command-buffer is setup, give it to the controller
*/
do_cmd:
- debug (("tsstart: calling tsexec(%d, %d)\n", unit, cmd));
- return (tsexec (unit, cmd));
+ return (tsexec(ctlr, cmd));
}
/*
@@ -650,6 +588,7 @@ int
tswchar (ctlr)
int ctlr;
{
+ struct ts_softc *sc = ts_cd.cd_devs[ctlr];
volatile struct tsdevice *tsregs = ts[ctlr].reg;
volatile struct tscmd *tscmdp = &ts[ctlr].cmd;
volatile struct tsmsg *tsmsgp = &ts[ctlr].msg;
@@ -658,17 +597,17 @@ tswchar (ctlr)
/*
* assemble and send "WRITE CHARACTERISTICS" command
*/
- ma = (long)tsmsgp;
- if (ma & 0x7FC00001) { /* address must be even and 22-bit */
- printf ("invalid address 0x%0x for msg-buffer.\n", ma);
- return (-1);
- }
-
- tsmsgp->hdr = ma & 0xFFFF; /* low order addr. bits */
- tsmsgp->dfl = (ma >> 16) & 0x003F; /* high order addr. bits */
- tsmsgp->rbpcr = 16; /* size of message-buffer */
- tsmsgp->xst0 = 0; /* chacacteristics mode word */
- tsmsgp->xst1 = 0; /* control word (ext.feat.) */
+ ma = (long)tsmsgp;
+ if (ma & 0x7FC00001) { /* address must be even and 22-bit */
+ printf ("invalid address 0x%0x for msg-buffer.\n", ma);
+ return (-1);
+ }
+
+ tsmsgp->hdr = ma & 0xFFFF; /* low order addr. bits */
+ tsmsgp->dfl = (ma >> 16) & 0x003F; /* high order addr. bits */
+ tsmsgp->rbpcr = 16; /* size of message-buffer */
+ tsmsgp->xst0 = 0; /* chacacteristics mode word */
+ tsmsgp->xst1 = 0; /* control word (ext.feat.) */
#ifdef TS11_COMPAT
tsmsgp->rbpcr = 14; /* size of message-buffer */
@@ -695,29 +634,29 @@ tswchar (ctlr)
#endif
#endif
- tscmdp->cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_WCHAR; /* obsolete */
- tscmdp->cw1 = ma & 0xFFFF;
- tscmdp->cw2 = (ma >> 16) & 0x003F;
- tscmdp->cw3 = 10; /* size of charact.-data */
+ tscmdp->cmdr = TS_CF_ACK | TS_CF_IE | TS_CMD_WCHAR; /* obsolete */
+ tscmdp->cw1 = ma & 0xFFFF;
+ tscmdp->cw2 = (ma >> 16) & 0x003F;
+ tscmdp->cw3 = 10; /* size of charact.-data */
- if (tsexec (ctlr, TS_CMD_WCHAR) < 0) {
- printf ("%s%d: write characteristics command failed [%x]\n",
- CTLRNAME, ctlr, tsregs->tssr);
- return (-1);
+ if (tsexec (ctlr, TS_CMD_WCHAR) < 0) {
+ printf ("%s: write characteristics command failed [%x]\n",
+ sc->sc_dev.dv_xname, tsregs->tssr);
+ return (-1);
}
- timeout = 1000; /* timeout in 10 seconds */
- do {
+ timeout = 1000; /* timeout in 10 seconds */
+ do {
DELAY(10000);
- sr = tsregs->tssr;
- debug10 (("\ttssr: 0x%x\n", sr));
- if (timeout-- > 0) {
- printf ("timeout during initialize.");
- tsstatus (sr);
- return (-1);
- }
- } while ((sr & TS_SSR) == 0);
- tsstatus (sr);
+ sr = tsregs->tssr;
+ debug10 (("\ttssr: 0x%x\n", sr));
+ if (timeout-- > 0) {
+ printf ("timeout during initialize.");
+ tsstatus (sr);
+ return (-1);
+ }
+ } while ((sr & TS_SSR) == 0);
+ tsstatus (sr);
return (0);
}
@@ -729,101 +668,95 @@ void
tsreset(ctlr)
int ctlr;
{
+ struct ts_softc *sc = ts_cd.cd_devs[ctlr];
volatile struct tsdevice *tsreg = ts[ctlr].reg;
volatile unsigned int sr, timeout;
- trace (("tsreset (%d)\n", ctlr));
-
/*
* reset ctlr by writing into TSSR, then write characteristics
*/
- timeout = 1000; /* timeout in 10 seconds */
- tsreg->tssr = 0; /* start initialization */
- do {
+ timeout = 1000; /* timeout in 10 seconds */
+ tsreg->tssr = 0; /* start initialization */
+ do {
DELAY(10000);
- sr = tsreg->tssr;
- debug10 (("\ttssr: 0x%x\n", sr));
- if (timeout-- > 0) {
- if (sr != 0)
- printf ("%s%d: timeout waiting for TS_SSR\n",
- CTLRNAME, ctlr);
- tsstatus (sr);
+ sr = tsreg->tssr;
+ debug10 (("\ttssr: 0x%x\n", sr));
+ if (timeout-- > 0) {
+ if (sr != 0)
+ printf ("%s: timeout waiting for TS_SSR\n",
+ sc->sc_dev.dv_xname);
+ tsstatus (sr);
return;
- }
- } while ((sr & TS_SSR) == 0); /* wait until subsystem ready */
- tsstatus (sr);
+ }
+ } while ((sr & TS_SSR) == 0); /* wait until subsystem ready */
+ tsstatus (sr);
return;
}
-extern struct cfdriver uba_cd;
/*
* probe for device. If found, try to raise an interrupt.
+ * XXX - most of this should be done in the attach routine.
*/
-int
-tsprobe (reg, ctlr, um, uh)
- caddr_t reg; /* address of TSDB register */
- int ctlr; /* index of the controller */
- struct uba_ctlr *um; /* controller-info */
- struct uba_softc *uh;
+int
+tsmatch(parent, match, aux)
+ struct device *parent;
+ void *match, *aux;
{
- register struct ts_softc *sc;
- register struct tsdevice *tsregs = (struct tsdevice*) reg;
+ struct ts_softc *sc = match;
+ struct uba_softc *uh = (void *)parent;
+ struct uba_attach_args *ua = aux;
+ struct tsdevice *tsregs = (struct tsdevice*)ua->ua_addr;
volatile unsigned int sr, timeout, count;
- struct uba_softc *ubasc;
-
- trace (("tsprobe (%x, %d, %x)\n", reg, ctlr, um));
+ int ctlr = sc->sc_dev.dv_unit;
ts_wtab[ctlr] = NULL;
- sc = &ts_softc[ctlr];
sc->sc_ts = &ts[ctlr];
sc->sc_state = ST_PROBE;
sc->sc_flags = 0;
- zsinfo[ctlr] = um;
- ts[ctlr].reg = (struct tsdevice*) reg;
+ ts[ctlr].reg = (struct tsdevice*)ua->ua_addr;
/*
- * Set host-settable interrupt vector.
- * Assign 0 to the TSSR register to start the ts-device initialization.
- * The device is not really initialized at this point, this is just to
- * find out if the device exists.
- */
- ubasc = uba_cd.cd_devs[0]; /* XXX */
- sc->sc_ivec = (ubasc->uh_lastiv -= 4);
+ * Set host-settable interrupt vector.
+ * Assign 0 to the TSSR register to start the ts-device initialization.
+ * The device is not really initialized at this point, this is just to
+ * find out if the device exists.
+ */
+ sc->sc_ivec = (uh->uh_lastiv -= 4);
count = 0;
again:
timeout = 1000; /* timeout in 10 seconds */
- tsregs->tssr = 0; /* start initialization */
+ tsregs->tssr = 0; /* start initialization */
do {
DELAY(10000);
sr = tsregs->tssr;
debug10 (("\ttssr-1: 0x%x\n", sr));
if (timeout-- > 0) {
if (sr != 0) /* the device exists !!! */
- printf ("%s%d: timeout waiting for TS_SSR\n",
- CTLRNAME, ctlr);
+ printf ("%s: timeout waiting for TS_SSR\n",
+ sc->sc_dev.dv_xname);
tsstatus (sr);
goto bad;
}
} while ((sr & TS_SSR) == 0); /* wait until subsystem ready */
tsstatus (sr);
- tswchar (ctlr); /* write charact. to enable interrupts */
+ tswchar (ctlr); /* write charact. to enable interrupts */
/* completion of this will raise the intr. */
#ifdef notyet
- sc->sc_ipl = br = qbgetpri();
+ sc->sc_ipl = br = qbgetpri();
#else
- sc->sc_ipl = 0x15;
+ sc->sc_ipl = 0x15;
#endif
- return (sizeof (struct tsdevice));
+ return (sizeof (struct tsdevice));
bad: if (++count < 3)
goto again;
#ifdef notyet
- splx(s);
+ splx(s);
#endif
return (0);
}
@@ -834,14 +767,14 @@ bad: if (++count < 3)
* Since there's only one drive per controller there's nothing to do.
* (we could check the status of the drive (online/offline/...)
*/
-int
-tsslave (ui, reg)
- struct uba_device *ui; /* ptr to the uba device structure */
- caddr_t reg; /* addr of the device controller */
+void
+tsattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
{
- register int ctlr = ui->ui_ctlr;
- register struct ts_softc *sc = &ts_softc[ctlr];
- register struct tsmsg *tsmsgp = &ts[ctlr].msg;
+ struct ts_softc *sc = (void *)self;
+ int ctlr = sc->sc_dev.dv_unit;
+ struct tsmsg *tsmsgp = &ts[ctlr].msg;
trace (("tsslave (%x, %x)\n", ui, reg));
@@ -852,46 +785,30 @@ tsslave (ui, reg)
*/
sc->sc_state = ST_SLAVE; /* tsintr() checks this ... */
if (tswchar (ctlr) < 0) {
- printf ("%s%d: cannot initialize", CTLRNAME, ctlr);
- return (0); /* ??? XXX ??? */
+ printf ("%s: cannot initialize", sc->sc_dev.dv_xname);
}
sc->sc_micro = (tsmsgp->xst2 & TS_SF_MCRL) >> 2;
- printf ("%s%d: rev %d, extended features %s, transport %s\n",
- CTLRNAME, ctlr, sc->sc_micro,
+ printf ("%s: rev %d, extended features %s, transport %s\n",
+ sc->sc_dev.dv_xname, sc->sc_micro,
(tsmsgp->xst2 & TS_SF_EFES ? "enabled" : "disabled"),
(ts[ctlr].reg->tssr & TS_OFL ? "offline" : "online"));
- tsinit (ctlr); /* must be called once, why not here ? */
-
- return (1);
+ tsinit (sc); /* must be called once, why not here ? */
}
/*
- * Open routine will issue the online command, later.
- * Just reset the flags and do nothing ...
- */
-void
-tsattach (ui)
- struct uba_device *ui;
-{
- trace (("\ntsattach (%x)", ui));
- ui->ui_flags = 0; /* mark unit offline */
-}
-
-
-/*
* TSV05/TS05 interrupt routine
*/
void
tsintr(ctlr)
int ctlr;
{
- register struct ts_softc *sc = &ts_softc[ctlr];
+ register struct ts_softc *sc = ts_cd.cd_devs[ctlr];
register struct tsmsg *tsmsgp = &ts[ctlr].msg;
register struct tscmd *tscmdp = &ts[ctlr].cmd;
volatile struct tsdevice *tsreg = ts[ctlr].reg;
- struct uba_ctlr *um = zsinfo[ctlr];
+ struct uba_unit *um = &sc->sc_unit;
register struct buf *bp;
unsigned short sr = tsreg->tssr; /* save TSSR */
@@ -902,12 +819,16 @@ tsintr(ctlr)
short cmask = tscmdp->cmdr & TS_CF_CMASK;
#ifdef DEBUG
- printf ("TSSR: %b, MSG: %x ", sr, TS_TSSR_BITS, mh);
+ {
+ char bits[64];
+ printf ("TSSR: %s, MSG: %x ", bitmask_snprintf(sr,
+ TS_TSSR_BITS, bits, sizeof(bits)), mh);
+ }
switch (tsmsgp->hdr & 0x001F) {
case 16: printf ("(End)"); break;
case 17: printf ("(Fail)"); break;
case 18: printf ("(Error)"); break;
- case 19: printf ("(Attention)"); break;
+ case 19: printf ("(Attention)"); break;
}
#endif
@@ -917,8 +838,8 @@ tsintr(ctlr)
sc->sc_cmdf |= TS_CF_CVC;
#ifdef QBA /* copied from uda.c */
- if(cpunumber == VAX_78032)
- splx(sc->sc_ipl); /* Qbus interrupt protocol is odd */
+ if(vax_cputype == VAX_78032)
+ splx(sc->sc_ipl); /* Qbus interrupt protocol is odd */
#endif
/*
@@ -935,14 +856,12 @@ tsintr(ctlr)
switch (sc->sc_state) {
case ST_INVALID:
- /*
- * Ignore unsolicited interrupts.
- */
- debug (("%s%d: intr in state ST_INVALID [%x,%x]\n",
- CTLRNAME, ctlr, sr, mh));
- log (LOG_WARNING, "%s%d: stray intr [%x,%x]\n",
- CTLRNAME, ctlr, sr, mh);
- return;
+ /*
+ * Ignore unsolicited interrupts.
+ */
+ log (LOG_WARNING, "%s: stray intr [%x,%x]\n",
+ sc->sc_dev.dv_xname, sr, mh);
+ return;
case ST_SLAVE:
/*
@@ -950,11 +869,9 @@ tsintr(ctlr)
* issued by tsslave() and indicates the end of the
* initialization phase. Just ignore it ...
*/
- debug (("%s%d: intr in state ST_SLAVE [%x,%x]\n",
- CTLRNAME, ctlr, sr, mh));
if ((sr & TS_SC) != 0 || (sr & TS_TC) != TS_TC_NORM) {
- printf ("%s%d: problem during init [%x,%x]\n",
- CTLRNAME, ctlr, sr, mh);
+ printf("%s: problem during init [%x,%x]\n",
+ sc->sc_dev.dv_xname, sr, mh);
/* return here ??? */
/* break and check the error outside switch ??? */
break;
@@ -968,23 +885,18 @@ tsintr(ctlr)
* Here we expect interrupts indicating the end of
* commands or indicating problems.
*/
- debug (("%s%d: intr ST_RUN (%s) [%x,%x]\n",
- CTLRNAME, ctlr, ((tsmsgp->xst0 & TS_SF_ONL) ?
- "online" : "offline"), sr, mh));
/*
* Anything else is handled outside this switch ...
*/
break;
case ST_IDLE:
- debug (("%s%d: intr ST_IDLE [%x,%x]\n",
- CTLRNAME, ctlr, sr, mh));
break;
default:
- printf ("%s%d: unexpected interrupt during state %d [%x,%x]\n",
- CTLRNAME, ctlr, sc->sc_state, sr, mh);
+ printf ("%s: unexpected interrupt during state %d [%x,%x]\n",
+ sc->sc_dev.dv_xname, sc->sc_state, sr, mh);
return;
}
@@ -998,7 +910,6 @@ tsintr(ctlr)
* Normal termination -- The operation is completed
* witout incident.
*/
- debug (("%s%d: Normal Termination\n", CTLRNAME, ctlr));
sc->sc_state = ST_IDLE; /* XXX ??? */
sc->sc_state = ST_RUNNING;
sc->sc_liowf = (ccode == TS_CC_WRITE);
@@ -1006,12 +917,16 @@ tsintr(ctlr)
if ((bp = ts_wtab[ctlr]) != NULL) {
ts_wtab[ctlr] = NULL; /* pseudo-unlink */
- if (bp != &ts_cbuf[ctlr]) { /* no ioctl */
- debug (("ubarelse\n"));
- ubarelse (um->um_ubanum, (int *)&bp->b_ubinfo);
+ if (bp != &ts_cbuf[ctlr]) { /* no ioctl */
+ ubarelse((struct uba_softc *)
+ sc->sc_dev.dv_parent,
+ (int *)&bp->b_ubinfo);
#if defined(VAX750)
- if (cpunumber == VAX_750 && um->um_ubinfo != 0)
- ubarelse(um->um_ubanum, &um->um_ubinfo);
+ if (vax_cputype == VAX_750 &&
+ sc->sc_unit.uu_ubinfo != 0)
+ ubarelse((struct uba_softc *)
+ sc->sc_dev.dv_parent,
+ &sc->sc_unit.uu_ubinfo);
/* XXX */
#endif
}
@@ -1030,10 +945,9 @@ tsintr(ctlr)
* (Without EAI enabled, no Attention interrupts occur.
* drive status changes are signaled by the VCK flag.)
*/
- debug (("%s%d: Attention\n", CTLRNAME, ctlr));
return;
- case TS_TC_TSA:
+ case TS_TC_TSA:
/*
* Tape Status Alert -- A status condition is encountered
* that may have significance to the program. Bits of
@@ -1050,7 +964,7 @@ tsintr(ctlr)
}
break;
- case TS_TC_FR:
+ case TS_TC_FR:
/*
* Function Reject -- The specified function was not
* initiated. Bits of interest include OFL, VCK, BOT,
@@ -1075,7 +989,7 @@ tsintr(ctlr)
}
break;
- case TS_TC_TPD:
+ case TS_TC_TPD:
/*
* Recoverable Error -- Tape position is a record beyond
* what its position was when the function was initiated.
@@ -1096,7 +1010,7 @@ tsintr(ctlr)
return;
case TS_CMD_WD: /* Write Data (Next) */
debug (("retry write data ...\n"));
- sc->sc_rtc = 1;
+ sc->sc_rtc = 1;
tsexec (ctlr, TS_CMD_WDR);
return;
case TS_CMD_WTM:
@@ -1109,7 +1023,7 @@ tsintr(ctlr)
}
break;
- case TS_TC_TNM:
+ case TS_TC_TNM:
/*
* Recoverable Error -- Tape position has not changed.
* Suggested recovery procedure is to log the error and
@@ -1126,7 +1040,7 @@ tsintr(ctlr)
}
break;
- case TS_TC_TPL:
+ case TS_TC_TPL:
/*
* Unrecoverable Error -- Tape position has been lost.
* No valid recovery procedures exist unless the tape
@@ -1135,7 +1049,7 @@ tsintr(ctlr)
printf ("Tape position lost\n");
break;
- case TS_TC_FCE:
+ case TS_TC_FCE:
/*
* Fatal subsytem Error -- The subsytem is incapable
* of properly performing commands, or at least its
@@ -1146,8 +1060,8 @@ tsintr(ctlr)
printf ("Fatal Controller Error\n");
default:
- printf ("%s%d: error 0x%x, resetting controller\n",
- CTLRNAME, ctlr, sr & TS_TC);
+ printf ("%s: error 0x%x, resetting controller\n",
+ sc->sc_dev.dv_xname, sr & TS_TC);
tsreset (ctlr);
}
@@ -1157,14 +1071,13 @@ tsintr(ctlr)
if ((bp = ts_wtab[ctlr]) != NULL) {
ts_wtab[ctlr] = NULL; /* pseudo unlink */
- if (bp != &ts_cbuf[ctlr]) { /* no ioctl */
- debug (("ubarelse-2\n"));
- ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo);
- }
- if ((sr & TS_TC) != TS_TC_NORM) {
+ if (bp != &ts_cbuf[ctlr]) /* no ioctl */
+ ubarelse((struct uba_softc *)sc->sc_dev.dv_parent,
+ (int *)&bp->b_ubinfo);
+
+ if ((sr & TS_TC) != TS_TC_NORM)
bp->b_flags |= B_ERROR;
- debug (("tsintr: bp->b_flags |= B_ERROR\n"));
- }
+
debug (("resid:%d, count:%d, rbpcr:%d\n",
bp->b_resid, bp->b_bcount, tsmsgp->rbpcr));
bp->b_resid = tsmsgp->rbpcr; /* XXX */
@@ -1196,27 +1109,27 @@ tsopen (dev, flag, type, p)
trace (("tsopen (%x, %x)\n", dev, flag));
- if (unit >= NTS || (ui = tsinfo[unit]) == 0 || ui->ui_alive == 0) {
- debug (("ui->ui_alive == 0\n"));
- return (ENXIO);
- }
- sc = &ts_softc[ui->ui_ctlr]; /* unit ??? */
- if (sc->sc_openf) {
- debug (("sc->sc_openf\n"));
- return (EBUSY);
- }
+ if (unit >= ts_cd.cd_ndevs)
+ return ENXIO;
+
+ sc = ts_cd.cd_devs[unit];
+ if (sc == 0)
+ return ENXIO;
+
+ if (sc->sc_openf)
+ return EBUSY;
+
sc->sc_openf = 1;
- sc->sc_tpr = tprintf_open (curproc);
+
s = splbio ();
if (sc->sc_state < ST_RUNNING) { /* XXX */
- printf ("ts%d not running.\n", ui->ui_ctlr);
+ printf ("%s not running.\n", sc->sc_dev.dv_xname);
(void) splx (s);
sc->sc_openf = 0;
return (ENXIO);
}
- um = ui->ui_mi;
(void) splx (s);
-#if 1
+
/*
* check if transport is really online.
* (without attention-interrupts enabled, we really don't know
@@ -1224,14 +1137,14 @@ tsopen (dev, flag, type, p)
* (ie. MTNOP) once and check the actual status.)
*/
tscommand (dev, MTNOP, 1);
- if (ts[TS_CTLR(dev)].reg->tssr & TS_OFL) {
- printf ("ts%d: transport is offline.\n", ui->ui_ctlr);
+ if (ts[unit].reg->tssr & TS_OFL) {
+ printf ("%s: transport is offline.\n", sc->sc_dev.dv_xname);
sc->sc_openf = 0;
- return (EIO); /* transport is offline */
+ return EIO; /* transport is offline */
}
-#endif
+
sc->sc_liowf = 0;
- return (0);
+ return 0;
}
@@ -1246,16 +1159,13 @@ tsopen (dev, flag, type, p)
*/
int
tsclose (dev, flag, type, p)
- dev_t dev;
- int flag, type;
+ dev_t dev;
+ int flag, type;
struct proc *p;
{
- register struct ts_softc *sc = &ts_softc[TS_UNIT(dev)];
-
- trace (("tsclose (%x, %d)\n", dev, flag));
+ register struct ts_softc *sc = ts_cd.cd_devs[TS_UNIT(dev)];
if (flag == FWRITE || ((flag & FWRITE) && sc->sc_liowf)) {
- debug (("tsclose: writing eot\n"));
/*
* We are writing two tape marks (EOT), but place the tape
* before the second one, so that another write operation
@@ -1263,18 +1173,15 @@ tsclose (dev, flag, type, p)
*/
tscommand (dev, MTWEOF, 1); /* Write Tape Mark */
tscommand (dev, MTWEOF, 1); /* Write Tape Mark */
- tscommand (dev, MTBSF, 1); /* Skip Tape Marks Reverse */
+ tscommand (dev, MTBSF, 1); /* Skip Tape Marks Reverse */
}
- if ((minor(dev)&T_NOREWIND) == 0) {
- debug (("tsclose: rewinding\n"));
+ if ((dev & T_NOREWIND) == 0)
tscommand (dev, MTREW, 0);
- }
- tprintf_close (sc->sc_tpr);
sc->sc_openf = 0;
sc->sc_liowf = 0;
- return (0);
+ return 0;
}
@@ -1283,51 +1190,20 @@ tsclose (dev, flag, type, p)
*/
void
tsstrategy (bp)
- register struct buf *bp;
+ register struct buf *bp;
{
- register struct uba_device *ui;
- register struct uba_ctlr *um;
register int unit = TS_UNIT(bp->b_dev);
+ struct ts_softc *sc = (void *)ts_cd.cd_devs[unit];
int s;
- trace (("tsstrategy (...)\n"));
- if (unit >= NTS) {
- debug (("tsstrategy: bad unit # %d\n",unit));
- bp->b_flags |= B_ERROR;
- iodone(bp);
- return;
- }
- ui = tsinfo[unit];
- if (ui == 0 || ui->ui_alive == 0) {
- debug (("tsstrategy: ui_alive == 0\n"));
- bp->b_flags |= B_ERROR;
- iodone(bp);
- return;
- }
-
s = splbio ();
/*
* we have only one command at one time, no credits.
* thus we don't need buffer management and controller queue
* just try to execute the command ...
*/
-#if 0
- if (ts_wtab[unit] != NULL) {
- debug (("tsstrategy: already waiting for something\n"));
- ts_wtab[unit]->b_flags |= B_ERROR;
- iodone (ts_wtab[unit]);
- }
- ts_wtab[unit] = bp;
-#endif
- um = ui->ui_mi;
- if (um->um_tab.b_active == 0) {
- /*
- * If the controller is not active, start it.
- */
- }
-
- tsstart (um, bp);
+ tsstart (sc, bp);
splx(s);
return;
}
@@ -1338,10 +1214,10 @@ tsstrategy (bp)
*/
int
tsioctl (dev, cmd, data, flag, p)
- dev_t dev;
+ dev_t dev;
u_long cmd;
- caddr_t data;
- int flag;
+ caddr_t data;
+ int flag;
struct proc *p;
{
register struct buf *bp = &ts_cbuf[TS_UNIT(dev)];
@@ -1413,11 +1289,11 @@ tsioctl (dev, cmd, data, flag, p)
return (error);
case MTIOCGET: /* get tape status */
- sc = &ts_softc[TS_CTLR(dev)];
+ sc = ts_cd.cd_devs[TS_UNIT(dev)];
mtget = (struct mtget *)data;
mtget->mt_type = MT_ISTS;
- mtget->mt_dsreg = (unsigned)(ts[TS_CTLR(dev)].reg->tssr);
- mtget->mt_erreg = (unsigned)(ts[TS_CTLR(dev)].msg.hdr);
+ mtget->mt_dsreg = (unsigned)(ts[TS_UNIT(dev)].reg->tssr);
+ mtget->mt_erreg = (unsigned)(ts[TS_UNIT(dev)].msg.hdr);
mtget->mt_resid = 0; /* ??? */
mtget->mt_density = 0; /* ??? */
break;
@@ -1482,7 +1358,10 @@ tsstatus (sr)
int sr;
{
#ifdef DEBUG
- debug (("status: TSSR=%b\n", sr, TS_TSSR_BITS));
+ char bits[64];
+
+ debug (("status: TSSR=%s\n", bitmask_snprintf(sr, TS_TSSR_BITS,
+ bits, sizeof(bits))));
if (tsdebug < 5)
return (0);
@@ -1496,7 +1375,7 @@ tsstatus (sr)
if (sr & TS_A11) printf ("Address Bits 17-16\n");
if (sr & TS_SSR) printf ("Subsystem Ready\n");
if (sr & TS_OFL) printf ("Off Line\n");
- if (sr & TS_FTC) printf ("Fatal Termination Class Code\n");
+ if (sr & TS_FTC) printf ("Fatal Termination Class Code\n");
switch (sr & TS_TC) {
case TS_TC_NORM: printf ("Normal Termination\n"); break;
case TS_TC_ATTN: printf ("Attention Condition\n"); break;
@@ -1516,10 +1395,18 @@ tsxstatus (mp)
struct tsmsg *mp;
{
#ifdef DEBUG
- debug (("tsxstatus: xst0=%b, xst1=%b, xst2=%b, xst3=%b, xst4=%b\n",
- mp->xst0, TS_XST0_BITS, mp->xst1, TS_XST1_BITS,
- mp->xst2, TS_XST2_BITS, mp->xst3, TS_XST3_BITS,
- mp->xst4, "\20"));
+ char bits[64];
+
+ debug (("tsxstatus: xst0=%s, ", bitmask_snprintf(mp->xst0,
+ TS_XST0_BITS, bits, sizeof(bits))));
+ debug (("xst1=%s, ", bitmask_snprintf(mp->xst1, TS_XST1_BITS,
+ bits, sizeof(bits))));
+ debug (("xst2=%s, ", bitmask_snprintf(mp->xst2, TS_XST2_BITS,
+ bits, sizeof(bits))));
+ debug (("xst3=%s, ", bitmask_snprintf(mp->xst3, TS_XST3_BITS,
+ bits, sizeof(bits))));
+ debug (("xst4=%s\n", bitmask_snprintf(mp->xst4, "\20",
+ bits, sizeof(bits))));
if (tsdebug < 10)
return (0);
@@ -1566,23 +1453,3 @@ tsxstatus (mp)
if (mp->xst4 & TS_SF_RCX) printf ("Retry Count Exceeded\n");
#endif
}
-
-int
-ts_match(parent, match, aux)
- struct device *parent;
- void *match, *aux;
-{
- return 0;
-}
-
-void
-ts_attach(parent, self, aux)
- struct device *parent, *self;
- void *aux;
-{
-}
-
-
-
-#endif /* #if NTS > 0 */
-