summaryrefslogtreecommitdiff
path: root/sys/dev/gpib
diff options
context:
space:
mode:
authorgmcgarry <gmcgarry@NetBSD.org>2003-06-02 03:51:52 +0000
committergmcgarry <gmcgarry@NetBSD.org>2003-06-02 03:51:52 +0000
commitc7fc491b482e46ed61419057f2e32cd3ecc006fa (patch)
tree17bd6bfaab801f5f7c1938d92c34b13fc8169000 /sys/dev/gpib
parentff33565165c4a8bd124fe87ac69144123929b4f4 (diff)
Port hp300 driver for cartridge-style tapes to MI gpib framework.
Diffstat (limited to 'sys/dev/gpib')
-rw-r--r--sys/dev/gpib/ct.c938
-rw-r--r--sys/dev/gpib/ctreg.h76
2 files changed, 1014 insertions, 0 deletions
diff --git a/sys/dev/gpib/ct.c b/sys/dev/gpib/ct.c
new file mode 100644
index 00000000000..fd9c7324afa
--- /dev/null
+++ b/sys/dev/gpib/ct.c
@@ -0,0 +1,938 @@
+/* $NetBSD: ct.c,v 1.1 2003/06/02 03:51:52 gmcgarry Exp $ */
+
+/*-
+ * Copyright (c) 1996-2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * 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 NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1988 University of Utah.
+ * Copyright (c) 1982, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * the Systems Programming Group of the University of Utah Computer
+ * Science Department.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * 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.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Utah $Hdr: rd.c 1.44 92/12/26$
+ *
+ * @(#)rd.c 8.2 (Berkeley) 5/19/94
+ */
+
+/*
+ * CS/80 cartridge tape driver (HP9144, HP88140, HP9145)
+ *
+ * Reminder:
+ * C_CC bit (character count option) when used in the CS/80 command
+ * 'set options' will cause the tape not to stream.
+ *
+ * TODO:
+ * make filesystem compatible
+ * make block mode work according to mtio(4) spec. (if possible)
+ * merge with CS/80 disk driver
+ * finish support of HP9145
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ct.c,v 1.1 2003/06/02 03:51:52 gmcgarry Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/mtio.h>
+#include <sys/proc.h>
+#include <sys/tprintf.h>
+
+#include <dev/gpib/ctreg.h> /* XXX must be before cs80busvar.h ATM */
+
+#include <dev/gpib/gpibvar.h>
+#include <dev/gpib/cs80busvar.h>
+
+/* number of eof marks to remember */
+#define EOFS 128
+
+#ifdef DEBUG
+int ctdebug = 0xff;
+#define CDB_FILES 0x01
+#define CDB_BSF 0x02
+#define CDB_IDENT 0x04
+#define CDB_FAIL 0x08
+#define CDB_FOLLOW 0x10
+#define DPRINTF(mask, str) if (ctdebug & (mask)) printf str
+#else
+#define DPRINTF(mask, str) /* nothing */
+#endif
+
+struct ct_softc {
+ struct device sc_dev;
+
+ gpib_chipset_tag_t sc_ic;
+ gpib_handle_t sc_hdl;
+
+ int sc_slave; /* GPIB slave ID */
+ int sc_punit; /* physical unit */
+ struct ct_iocmd sc_ioc;
+ struct ct_rscmd sc_rsc;
+ struct cs80_stat sc_stat;
+ struct bufq_state sc_tab;
+ int sc_active;
+ struct buf *sc_bp;
+ struct buf sc_bufstore; /* XXX */
+ int sc_blkno;
+ int sc_cmd;
+ int sc_resid;
+ char *sc_addr;
+ int sc_flags;
+#define CTF_OPEN 0x01
+#define CTF_ALIVE 0x02
+#define CTF_WRT 0x04
+#define CTF_CMD 0x08
+#define CTF_IO 0x10
+#define CTF_BEOF 0x20
+#define CTF_AEOF 0x40
+#define CTF_EOT 0x80
+#define CTF_STATWAIT 0x100
+#define CTF_CANSTREAM 0x200
+#define CTF_WRTTN 0x400
+ short sc_type;
+ tpr_t sc_tpr;
+ int sc_eofp;
+ int sc_eofs[EOFS];
+};
+
+int ctmatch(struct device *, struct cfdata *, void *);
+void ctattach(struct device *, struct device *, void *);
+
+CFATTACH_DECL(ct, sizeof(struct ct_softc),
+ ctmatch, ctattach, NULL, NULL);
+
+int ctident(struct device *, struct ct_softc *,
+ struct cs80bus_attach_args *);
+
+int ctlookup(int, int, int);
+void ctaddeof(struct ct_softc *);
+void ctustart(struct ct_softc *);
+void cteof(struct ct_softc *, struct buf *);
+void ctdone(struct ct_softc *, struct buf *);
+
+void ctcallback(void *, int);
+void ctstart(struct ct_softc *);
+void ctintr(struct ct_softc *);
+
+void ctcommand(dev_t, int, int);
+
+dev_type_open(ctopen);
+dev_type_close(ctclose);
+dev_type_read(ctread);
+dev_type_write(ctwrite);
+dev_type_ioctl(ctioctl);
+dev_type_strategy(ctstrategy);
+
+const struct bdevsw ct_bdevsw = {
+ ctopen, ctclose, ctstrategy, ctioctl, nodump, nosize, D_TAPE
+};
+
+const struct cdevsw ct_cdevsw = {
+ ctopen, ctclose, ctread, ctwrite, ctioctl,
+ nostop, notty, nopoll, nommap, nokqfilter, D_TAPE
+};
+
+extern struct cfdriver ct_cd;
+
+struct ctinfo {
+ short hwid;
+ short punit;
+ char *desc;
+} ctinfo[] = {
+ { CT7946ID, 1, "7946A" },
+ { CT7912PID, 1, "7912P" },
+ { CT7914PID, 1, "7914P" },
+ { CT9144ID, 0, "9144" },
+ { CT9145ID, 0, "9145" },
+ { CT35401ID, 0, "35401A"},
+};
+int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
+
+#define CT_NOREW 4
+#define CT_STREAM 8
+#define CTUNIT(x) (minor(x) & 0x03)
+
+int
+ctlookup(id, slave, punit)
+ int id;
+ int slave;
+ int punit;
+{
+ int i;
+
+ for (i = 0; i < nctinfo; i++)
+ if (ctinfo[i].hwid == id)
+ break;
+ if (i == nctinfo)
+ return (-1);
+ return (i);
+}
+
+int
+ctmatch(parent, match, aux)
+ struct device *parent;
+ struct cfdata *match;
+ void *aux;
+{
+ struct cs80bus_attach_args *ca = aux;
+ int i;
+
+ if ((i = ctlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0)
+ return (0);
+ ca->ca_punit = ctinfo[i].punit;
+ return (1);
+}
+
+void
+ctattach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct ct_softc *sc = (struct ct_softc *)self;
+ struct cs80bus_attach_args *ca = aux;
+ struct cs80_description csd;
+ char name[7];
+ int type, i, n, canstream = 0;
+
+ sc->sc_ic = ca->ca_ic;
+ sc->sc_slave = ca->ca_slave;
+ sc->sc_punit = ca->ca_punit;
+
+ if ((type = ctlookup(ca->ca_id, ca->ca_slave, ca->ca_punit)) < 0)
+ return;
+
+ if (cs80reset(parent, sc->sc_slave, sc->sc_punit)) {
+ printf("\n%s: can't reset device\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ if (cs80describe(parent, sc->sc_slave, sc->sc_punit, &csd)) {
+ printf("\n%s: didn't respond to describe command\n",
+ sc->sc_dev.dv_xname);
+ return;
+ }
+ memset(name, 0, sizeof(name));
+ for (i=0, n=0; i<3; i++) {
+ name[n++] = (csd.d_name[i] >> 4) + '0';
+ name[n++] = (csd.d_name[i] & 0x0f) + '0';
+ }
+
+#ifdef DEBUG
+ if (ctdebug & CDB_IDENT) {
+ printf("\n%s: name: ('%s')\n",
+ sc->sc_dev.dv_xname,name);
+ printf(" iuw %x, maxxfr %d, ctype %d\n",
+ csd.d_iuw, csd.d_cmaxxfr, csd.d_ctype);
+ printf(" utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n",
+ csd.d_utype, csd.d_sectsize,
+ csd.d_blkbuf, csd.d_burstsize, csd.d_blocktime);
+ printf(" avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n",
+ csd.d_uavexfr, csd.d_retry, csd.d_access,
+ csd.d_maxint, csd.d_fvbyte, csd.d_rvbyte);
+ printf(" maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n",
+ csd.d_maxcylhead >> 8 , csd.d_maxcylhead & 0xff,
+ csd.d_maxsect, csd.d_maxvsectl, csd.d_interleave);
+ printf("%s", sc->sc_dev.dv_xname);
+ }
+#endif
+
+ switch (ca->ca_id) {
+ case CT7946ID:
+ if (memcmp(name, "079450", 6) == 0)
+ return; /* not really a 7946 */
+ /* fall into... */
+ case CT9144ID:
+ case CT9145ID:
+ case CT35401ID:
+ sc->sc_type = CT9144;
+ canstream = 1;
+ break;
+
+ case CT7912PID:
+ case CT7914PID:
+ sc->sc_type = CT88140;
+ break;
+ default:
+ sc->sc_type = type;
+ break;
+ }
+
+ sc->sc_type = type;
+ sc->sc_flags = canstream ? CTF_CANSTREAM : 0;
+ printf(": %s %stape\n", ctinfo[type].desc,
+ canstream ? "streaming " : "");
+
+ bufq_alloc(&sc->sc_tab, BUFQ_FCFS);
+
+ if (gpibregister(sc->sc_ic, sc->sc_slave, ctcallback, sc,
+ &sc->sc_hdl)) {
+ printf("%s: can't register callback\n", sc->sc_dev.dv_xname);
+ return;
+ }
+
+ sc->sc_flags |= CTF_ALIVE;
+}
+
+/*ARGSUSED*/
+int
+ctopen(dev, flag, type, p)
+ dev_t dev;
+ int flag, type;
+ struct proc *p;
+{
+ struct ct_softc *sc;
+ u_int8_t opt;
+
+ sc = device_lookup(&ct_cd, CTUNIT(dev));
+ if (sc == NULL || (sc->sc_flags & CTF_ALIVE) == 0)
+ return (ENXIO);
+
+ if (sc->sc_flags & CTF_OPEN)
+ return (EBUSY);
+
+ if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM))
+ opt = C_SPAR | C_IMRPT;
+ else
+ opt = C_SPAR;
+
+ if (cs80setoptions(sc->sc_dev.dv_parent, sc->sc_slave,
+ sc->sc_punit, opt))
+ return (EBUSY);
+
+ sc->sc_tpr = tprintf_open(p);
+ sc->sc_flags |= CTF_OPEN;
+
+ return (0);
+}
+
+/*ARGSUSED*/
+int
+ctclose(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+ struct proc *p;
+{
+ struct ct_softc *sc;
+
+ sc = device_lookup(&ct_cd, CTUNIT(dev));
+ if (sc == NULL)
+ return (ENXIO);
+
+ if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) &&
+ (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */
+ ctcommand(dev, MTWEOF, 2);
+ ctcommand(dev, MTBSR, 1);
+ if (sc->sc_eofp == EOFS - 1)
+ sc->sc_eofs[EOFS - 1]--;
+ else
+ sc->sc_eofp--;
+ DPRINTF(CDB_BSF, ("%s: ctclose backup eofs prt %d blk %d\n",
+ sc->sc_dev.dv_xname, sc->sc_eofp,
+ sc->sc_eofs[sc->sc_eofp]));
+ }
+
+ if ((minor(dev) & CT_NOREW) == 0)
+ ctcommand(dev, MTREW, 1);
+ sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN);
+ tprintf_close(sc->sc_tpr);
+ DPRINTF(CDB_FILES, ("ctclose: flags %x\n", sc->sc_flags));
+
+ return (0); /* XXX */
+}
+
+void
+ctcommand(dev, cmd, cnt)
+ dev_t dev;
+ int cmd;
+ int cnt;
+{
+ struct ct_softc *sc;
+ struct buf *bp;
+ struct buf *nbp = 0;
+
+ sc = device_lookup(&ct_cd, CTUNIT(dev));
+ bp = &sc->sc_bufstore;
+
+ DPRINTF(CDB_FOLLOW, ("ctcommand: called\n"));
+
+ if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) {
+ cnt = sc->sc_eofs[EOFS - 1] - cnt;
+ ctcommand(dev, MTREW, 1);
+ ctcommand(dev, MTFSF, cnt);
+ cnt = 2;
+ cmd = MTBSR;
+ }
+
+ if (cmd == MTBSF && sc->sc_eofp - cnt < 0) {
+ cnt = 1;
+ cmd = MTREW;
+ }
+
+ sc->sc_flags |= CTF_CMD;
+ sc->sc_bp = bp;
+ sc->sc_cmd = cmd;
+ bp->b_dev = dev;
+ if (cmd == MTFSF) {
+ nbp = (struct buf *)geteblk(MAXBSIZE);
+ bp->b_data = nbp->b_data;
+ bp->b_bcount = MAXBSIZE;
+ }
+
+ while (cnt-- > 0) {
+ bp->b_flags = B_BUSY;
+ if (cmd == MTBSF) {
+ sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
+ sc->sc_eofp--;
+ DPRINTF(CDB_BSF, ("%s: backup eof pos %d blk %d\n",
+ sc->sc_dev.dv_xname, sc->sc_eofp,
+ sc->sc_eofs[sc->sc_eofp]));
+ }
+ ctstrategy(bp);
+ biowait(bp);
+ }
+ bp->b_flags = 0;
+ sc->sc_flags &= ~CTF_CMD;
+ if (nbp)
+ brelse(nbp);
+}
+
+void
+ctstrategy(bp)
+ struct buf *bp;
+{
+ struct ct_softc *sc;
+ int s;
+
+ DPRINTF(CDB_FOLLOW, ("cdstrategy(%p): dev %x, bn %x, bcount %lx, %c\n",
+ bp, bp->b_dev, bp->b_blkno, bp->b_bcount,
+ (bp->b_flags & B_READ) ? 'R' : 'W'));
+
+ sc = device_lookup(&ct_cd, CTUNIT(bp->b_dev));
+
+ s = splbio();
+ BUFQ_PUT(&sc->sc_tab, bp);
+ if (sc->sc_active == 0) {
+ sc->sc_active = 1;
+ ctustart(sc);
+ }
+ splx(s);
+}
+
+void
+ctustart(sc)
+ struct ct_softc *sc;
+{
+ struct buf *bp;
+
+ bp = BUFQ_PEEK(&sc->sc_tab);
+ sc->sc_addr = bp->b_data;
+ sc->sc_resid = bp->b_bcount;
+ if (gpibrequest(sc->sc_ic, sc->sc_hdl))
+ ctstart(sc);
+}
+
+void
+ctstart(sc)
+ struct ct_softc *sc;
+{
+ struct buf *bp;
+ struct ct_ulcmd ul;
+ struct ct_wfmcmd wfm;
+ int i, slave, punit;
+
+ slave = sc->sc_slave;
+ punit = sc->sc_punit;
+
+ bp = BUFQ_PEEK(&sc->sc_tab);
+ if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {
+ switch(sc->sc_cmd) {
+ case MTFSF:
+ bp->b_flags |= B_READ;
+ goto mustio;
+
+ case MTBSF:
+ goto gotaddr;
+
+ case MTOFFL:
+ sc->sc_blkno = 0;
+ ul.unit = CS80CMD_SUNIT(punit);
+ ul.cmd = CS80CMD_UNLOAD;
+ (void) cs80send(sc->sc_dev.dv_parent, slave, punit,
+ CS80CMD_SCMD, &ul, sizeof(ul));
+ break;
+
+ case MTWEOF:
+ sc->sc_blkno++;
+ sc->sc_flags |= CTF_WRT;
+ wfm.unit = CS80CMD_SUNIT(sc->sc_punit);
+ wfm.cmd = CS80CMD_WFM;
+ (void) cs80send(sc->sc_dev.dv_parent, slave, punit,
+ CS80CMD_SCMD, &wfm, sizeof(wfm));
+ ctaddeof(sc);
+ break;
+
+ case MTBSR:
+ sc->sc_blkno--;
+ goto gotaddr;
+
+ case MTFSR:
+ sc->sc_blkno++;
+ goto gotaddr;
+
+ case MTREW:
+ sc->sc_blkno = 0;
+ DPRINTF(CDB_BSF, ("%s: clearing eofs\n",
+ sc->sc_dev.dv_xname));
+ for (i=0; i<EOFS; i++)
+ sc->sc_eofs[i] = 0;
+ sc->sc_eofp = 0;
+
+gotaddr:
+ sc->sc_ioc.unit = CS80CMD_SUNIT(sc->sc_punit);
+ sc->sc_ioc.saddr = CS80CMD_SADDR;
+ sc->sc_ioc.addr0 = 0;
+ sc->sc_ioc.addr = htobe32(sc->sc_blkno);
+ sc->sc_ioc.nop2 = CS80CMD_NOP;
+ sc->sc_ioc.slen = CS80CMD_SLEN;
+ sc->sc_ioc.len = htobe32(0);
+ sc->sc_ioc.nop3 = CS80CMD_NOP;
+ sc->sc_ioc.cmd = CS80CMD_READ;
+ (void) cs80send(sc->sc_dev.dv_parent, slave, punit,
+ CS80CMD_SCMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
+ break;
+ }
+ } else {
+mustio:
+ if ((bp->b_flags & B_READ) &&
+ sc->sc_flags & (CTF_BEOF|CTF_EOT)) {
+ DPRINTF(CDB_FILES, ("ctstart: before %x\n",
+ sc->sc_flags));
+ if (sc->sc_flags & CTF_BEOF) {
+ sc->sc_flags &= ~CTF_BEOF;
+ sc->sc_flags |= CTF_AEOF;
+ DPRINTF(CDB_FILES, ("ctstart: after %x\n",
+ sc->sc_flags));
+ }
+ bp->b_resid = bp->b_bcount;
+ ctdone(sc, bp);
+ return;
+ }
+ sc->sc_flags |= CTF_IO;
+ sc->sc_ioc.unit = CS80CMD_SUNIT(sc->sc_punit);
+ sc->sc_ioc.saddr = CS80CMD_SADDR;
+ sc->sc_ioc.addr0 = 0;
+ sc->sc_ioc.addr = htobe32(sc->sc_blkno);
+ sc->sc_ioc.nop2 = CS80CMD_NOP;
+ sc->sc_ioc.slen = CS80CMD_SLEN;
+ sc->sc_ioc.len = htobe32(sc->sc_resid);
+ sc->sc_ioc.nop3 = CS80CMD_NOP;
+ if (bp->b_flags & B_READ)
+ sc->sc_ioc.cmd = CS80CMD_READ;
+ else {
+ sc->sc_ioc.cmd = CS80CMD_WRITE;
+ sc->sc_flags |= (CTF_WRT | CTF_WRTTN);
+ }
+ (void) cs80send(sc->sc_dev.dv_parent, slave, punit,
+ CS80CMD_SCMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
+ }
+ gpibawait(sc->sc_ic);
+}
+
+/*
+ * Hideous grue to handle EOF/EOT (mostly for reads)
+ */
+void
+cteof(sc, bp)
+ struct ct_softc *sc;
+ struct buf *bp;
+{
+ long blks;
+
+ /*
+ * EOT on a write is an error.
+ */
+ if ((bp->b_flags & B_READ) == 0) {
+ bp->b_resid = bp->b_bcount;
+ bp->b_flags |= B_ERROR;
+ bp->b_error = ENOSPC;
+ sc->sc_flags |= CTF_EOT;
+ return;
+ }
+ /*
+ * Use returned block position to determine how many blocks
+ * we really read and update b_resid.
+ */
+ blks = sc->sc_stat.c_blk - sc->sc_blkno - 1;
+ DPRINTF(CDB_FILES, ("cteof: bc %ld oblk %d nblk %d read %ld, resid %ld\n",
+ bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk,
+ blks, bp->b_bcount - CTKTOB(blks)));
+ if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */
+ blks = 0;
+ sc->sc_blkno++;
+ }
+ else {
+ sc->sc_blkno = sc->sc_stat.c_blk;
+ }
+ bp->b_resid = bp->b_bcount - CTKTOB(blks);
+ /*
+ * If we are at physical EOV or were after an EOF,
+ * we are now at logical EOT.
+ */
+ if ((sc->sc_stat.c_aef & AEF_EOV) ||
+ (sc->sc_flags & CTF_AEOF)) {
+ sc->sc_flags |= CTF_EOT;
+ sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF);
+ }
+ /*
+ * If we were before an EOF or we have just completed a FSF,
+ * we are now after EOF.
+ */
+ else if ((sc->sc_flags & CTF_BEOF) ||
+ ((sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF)) {
+ sc->sc_flags |= CTF_AEOF;
+ sc->sc_flags &= ~CTF_BEOF;
+ }
+ /*
+ * Otherwise if we read something we are now before EOF
+ * (and no longer after EOF).
+ */
+ else if (blks) {
+ sc->sc_flags |= CTF_BEOF;
+ sc->sc_flags &= ~CTF_AEOF;
+ }
+ /*
+ * Finally, if we didn't read anything we just passed an EOF
+ */
+ else
+ sc->sc_flags |= CTF_AEOF;
+ DPRINTF(CDB_FILES, ("cteof: leaving flags %x\n", sc->sc_flags));
+}
+
+
+void
+ctcallback(v, action)
+ void *v;
+ int action;
+{
+ struct ct_softc *sc = v;
+
+ DPRINTF(CDB_FOLLOW, ("ctcallback: v=%p, action=%d\n", v, action));
+
+ switch (action) {
+ case GPIBCBF_START:
+ ctstart(sc);
+ break;
+ case GPIBCBF_INTR:
+ ctintr(sc);
+ break;
+#ifdef DEBUG
+ default:
+ DPRINTF(CDB_FAIL, ("ctcallback: unknown action %d\n", action));
+ break;
+#endif
+ }
+}
+
+void
+ctintr(sc)
+ struct ct_softc *sc;
+{
+ struct buf *bp;
+ u_int8_t stat;
+ int slave, punit;
+ int dir;
+
+ slave = sc->sc_slave;
+ punit = sc->sc_punit;
+
+ bp = BUFQ_PEEK(&sc->sc_tab);
+ if (bp == NULL) {
+ printf("%s: bp == NULL\n", sc->sc_dev.dv_xname);
+ return;
+ }
+ if (sc->sc_flags & CTF_IO) {
+ sc->sc_flags &= ~CTF_IO;
+ dir = (bp->b_flags & B_READ ? GPIB_READ : GPIB_WRITE);
+ gpibxfer(sc->sc_ic, slave, CS80CMD_EXEC, sc->sc_addr,
+ sc->sc_resid, dir, dir == GPIB_READ);
+ return;
+ }
+ if ((sc->sc_flags & CTF_STATWAIT) == 0) {
+ if (gpibpptest(sc->sc_ic, slave) == 0) {
+ sc->sc_flags |= CTF_STATWAIT;
+ gpibawait(sc->sc_ic);
+ return;
+ }
+ } else
+ sc->sc_flags &= ~CTF_STATWAIT;
+ (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1);
+ DPRINTF(CDB_FILES, ("ctintr: before flags %x\n", sc->sc_flags));
+ if (stat) {
+ sc->sc_rsc.unit = CS80CMD_SUNIT(punit);
+ sc->sc_rsc.cmd = CS80CMD_STATUS;
+ (void) gpibsend(sc->sc_ic, slave, CS80CMD_SCMD, &sc->sc_rsc,
+ sizeof(sc->sc_rsc));
+ (void) gpibrecv(sc->sc_ic, slave, CS80CMD_EXEC, &sc->sc_stat,
+ sizeof(sc->sc_stat));
+ (void) gpibrecv(sc->sc_ic, slave, CS80CMD_QSTAT, &stat, 1);
+ DPRINTF(CDB_FILES, ("ctintr: return stat 0x%x, A%x F%x blk %d\n",
+ stat, sc->sc_stat.c_aef,
+ sc->sc_stat.c_fef, sc->sc_stat.c_blk));
+ if (stat == 0) {
+ if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) {
+ cteof(sc, bp);
+ ctaddeof(sc);
+ goto done;
+ }
+ if (sc->sc_stat.c_fef & FEF_PF) {
+ cs80reset(sc, slave, punit);
+ ctstart(sc);
+ return;
+ }
+ if (sc->sc_stat.c_fef & FEF_REXMT) {
+ ctstart(sc);
+ return;
+ }
+ if (sc->sc_stat.c_aef & 0x5800) {
+ if (sc->sc_stat.c_aef & 0x4000)
+ tprintf(sc->sc_tpr,
+ "%s: uninitialized media\n",
+ sc->sc_dev.dv_xname);
+ if (sc->sc_stat.c_aef & 0x1000)
+ tprintf(sc->sc_tpr,
+ "%s: not ready\n",
+ sc->sc_dev.dv_xname);
+ if (sc->sc_stat.c_aef & 0x0800)
+ tprintf(sc->sc_tpr,
+ "%s: write protect\n",
+ sc->sc_dev.dv_xname);
+ } else {
+ printf("%s err: v%d u%d ru%d bn%d, ",
+ sc->sc_dev.dv_xname,
+ (sc->sc_stat.c_vu>>4)&0xF,
+ sc->sc_stat.c_vu&0xF,
+ sc->sc_stat.c_pend,
+ sc->sc_stat.c_blk);
+ printf("R0x%x F0x%x A0x%x I0x%x\n",
+ sc->sc_stat.c_ref,
+ sc->sc_stat.c_fef,
+ sc->sc_stat.c_aef,
+ sc->sc_stat.c_ief);
+ }
+ } else
+ printf("%s: request status failed\n",
+ sc->sc_dev.dv_xname);
+ bp->b_flags |= B_ERROR;
+ bp->b_error = EIO;
+ goto done;
+ } else
+ bp->b_resid = 0;
+ if (sc->sc_flags & CTF_CMD) {
+ switch (sc->sc_cmd) {
+ case MTFSF:
+ sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF);
+ sc->sc_blkno += CTBTOK(sc->sc_resid);
+ ctstart(sc);
+ return;
+ case MTBSF:
+ sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT);
+ break;
+ case MTBSR:
+ sc->sc_flags &= ~CTF_BEOF;
+ if (sc->sc_flags & CTF_EOT) {
+ sc->sc_flags |= CTF_AEOF;
+ sc->sc_flags &= ~CTF_EOT;
+ } else if (sc->sc_flags & CTF_AEOF) {
+ sc->sc_flags |= CTF_BEOF;
+ sc->sc_flags &= ~CTF_AEOF;
+ }
+ break;
+ case MTWEOF:
+ sc->sc_flags &= ~CTF_BEOF;
+ if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) {
+ sc->sc_flags |= CTF_EOT;
+ sc->sc_flags &= ~CTF_AEOF;
+ } else
+ sc->sc_flags |= CTF_AEOF;
+ break;
+ case MTREW:
+ case MTOFFL:
+ sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT);
+ break;
+ }
+ } else {
+ sc->sc_flags &= ~CTF_AEOF;
+ sc->sc_blkno += CTBTOK(sc->sc_resid);
+ }
+done:
+ DPRINTF(CDB_FILES, ("ctintr: after flags %x\n", sc->sc_flags));
+ ctdone(sc, bp);
+}
+
+void
+ctdone(sc, bp)
+ struct ct_softc *sc;
+ struct buf *bp;
+{
+
+ (void)BUFQ_GET(&sc->sc_tab);
+ biodone(bp);
+ gpibrelease(sc->sc_ic, sc->sc_hdl);
+ if (BUFQ_PEEK(&sc->sc_tab) == NULL) {
+ sc->sc_active = 0;
+ return;
+ }
+ ctustart(sc);
+}
+
+int
+ctread(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ return (physio(ctstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+ctwrite(dev, uio, flags)
+ dev_t dev;
+ struct uio *uio;
+ int flags;
+{
+ /* XXX: check for hardware write-protect? */
+ return (physio(ctstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+/*ARGSUSED*/
+int
+ctioctl(dev, cmd, data, flag, p)
+ dev_t dev;
+ u_long cmd;
+ int flag;
+ caddr_t data;
+ struct proc *p;
+{
+ struct mtop *op;
+ int cnt;
+
+ switch (cmd) {
+
+ case MTIOCTOP:
+ op = (struct mtop *)data;
+ switch(op->mt_op) {
+
+ case MTWEOF:
+ case MTFSF:
+ case MTBSR:
+ case MTBSF:
+ case MTFSR:
+ cnt = op->mt_count;
+ break;
+
+ case MTREW:
+ case MTOFFL:
+ cnt = 1;
+ break;
+
+ default:
+ return (EINVAL);
+ }
+ ctcommand(dev, op->mt_op, cnt);
+ break;
+
+ case MTIOCGET:
+ break;
+
+ default:
+ return (EINVAL);
+ }
+ return (0);
+}
+
+void
+ctaddeof(sc)
+ struct ct_softc *sc;
+{
+
+ if (sc->sc_eofp == EOFS - 1)
+ sc->sc_eofs[EOFS - 1]++;
+ else {
+ sc->sc_eofp++;
+ if (sc->sc_eofp == EOFS - 1)
+ sc->sc_eofs[EOFS - 1] = EOFS;
+ else
+ /* save blkno */
+ sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1;
+ }
+ DPRINTF(CDB_BSF, ("%s: add eof pos %d blk %d\n",
+ sc->sc_dev.dv_xname, sc->sc_eofp,
+ sc->sc_eofs[sc->sc_eofp]));
+}
diff --git a/sys/dev/gpib/ctreg.h b/sys/dev/gpib/ctreg.h
new file mode 100644
index 00000000000..b095110eda5
--- /dev/null
+++ b/sys/dev/gpib/ctreg.h
@@ -0,0 +1,76 @@
+/* $NetBSD: ctreg.h,v 1.1 2003/06/02 03:51:52 gmcgarry Exp $ */
+
+/*
+ * Copyright (c) 1982, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * 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.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)ctreg.h 8.1 (Berkeley) 6/10/93
+ */
+
+struct ct_iocmd {
+ u_int8_t unit; /* punit */
+ u_int8_t saddr; /* CS80CMD_SADDR */
+ u_int16_t addr0; /* always 0 */
+ u_int32_t addr; /* blkno */
+ u_int8_t nop2; /* CS80CMD_NOP */
+ u_int8_t slen; /* CS80CMD_SLEN */
+ u_int32_t len; /* 0 (for rewind) /resid */
+ u_int8_t nop3; /* CS80CMD_NOP */
+ u_int8_t cmd; /* CS80CMD_READ/CS80CMD_WRITE */
+} __attribute__((__packed__));
+
+struct ct_rscmd {
+ u_int8_t unit;
+ u_int8_t cmd;
+} __attribute__((__packed__));
+
+struct ct_ulcmd {
+ u_int8_t unit;
+ u_int8_t cmd;
+} __attribute__((__packed__));
+
+struct ct_wfmcmd {
+ u_int8_t unit;
+ u_int8_t cmd;
+} __attribute__((__packed__));
+
+#define CT7946ID 0x220
+#define CT9145ID 0x268
+#define CT9144ID 0x260
+#define CT9144 0
+#define CT7912PID 0x209
+#define CT7914PID 0x20B
+#define CT88140 1
+#define CT35401ID 0x270
+
+/* convert bytes to 1k tape block and back */
+#define CTBTOK(x) ((x) >> 10)
+#define CTKTOB(x) ((x) << 10)