/*-
* Copyright (c) 1996, 1997 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.
*
* 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) 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. 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.
*
* @(#)ct.c 8.2 (Berkeley) 1/12/94
*/
/*
* CS80 cartridge tape driver (9144, 88140, 9145)
*
* 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 cs80 disk driver
* finish support of 9145
*/
static int
ctident(device_t parent, struct ct_softc *sc, struct hpibbus_attach_args *ha)
{
struct cs80_describe desc;
u_char stat, cmd[3];
char name[7];
int i, id, n, type, canstream;
type = canstream = 0;
/* Verify that we have a CS80 device. */
if ((ha->ha_id & 0x200) == 0)
return 0;
/* Is it one of the tapes we support? */
for (id = 0; id < nctinfo; id++)
if (ha->ha_id == ctinfo[id].hwid &&
ha->ha_punit == ctinfo[id].punit)
break;
if (id == nctinfo)
return 0;
/*
* So far, so good. Get drive parameters. Note command
* is always issued to unit 0.
*/
cmd[0] = C_SUNIT(0);
cmd[1] = C_SVOL(0);
cmd[2] = C_DESC;
hpibsend(device_unit(parent), ha->ha_slave, C_CMD, cmd, sizeof(cmd));
hpibrecv(device_unit(parent), ha->ha_slave, C_EXEC, &desc,
sizeof(desc));
hpibrecv(device_unit(parent), ha->ha_slave, C_QSTAT, &stat,
sizeof(stat));
memset(name, 0, sizeof(name));
if (stat == 0) {
n = desc.d_name;
for (i = 5; i >= 0; i--) {
name[i] = (n & 0xf) + '0';
n >>= 4;
}
}
switch (ha->ha_id) {
case CT7946ID:
if (memcmp(name, "079450", 6) == 0)
return 0; /* not really a 7946 */
/* fall into... */
case CT9144ID:
case CT9145ID:
case CT35401ID:
type = CT9144;
canstream = 1;
break;
case CT7912PID:
case CT7914PID:
type = CT88140;
break;
}
/*
* Check the return of hpibsend() and hpibswait().
* Drive could be loading/unloading a tape. If not checked,
* driver hangs.
*/
cc = hpibsend(ctlr, slave, C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc));
if (cc != sizeof(sc->sc_soptc))
return EBUSY;
hpibswait(ctlr, slave);
cc = hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
if (cc != sizeof(stat))
return EBUSY;
/*
* Hideous grue to handle EOF/EOT (mostly for reads)
*/
static void
cteof(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_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;
#ifdef DEBUG
if (ctdebug & CDB_FILES)
printf("cteof: bc %d oblk %d nblk %ld read %ld, resid %ld\n",
bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk,
blks, bp->b_bcount - CTKTOB(blks));
#endif
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;
#ifdef DEBUG
if (ctdebug & CDB_FILES)
printf("cteof: leaving flags %x\n", sc->sc_flags);
#endif
}