Annotation of sys/arch/hp300/stand/common/ct.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ct.c,v 1.5 2006/08/17 06:31:10 miod Exp $ */
! 2: /* $NetBSD: ct.c,v 1.9 1996/10/14 07:29:57 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1982, 1990, 1993
! 6: * The Regents of the University of California. All rights reserved.
! 7: *
! 8: * Redistribution and use in source and binary forms, with or without
! 9: * modification, are permitted provided that the following conditions
! 10: * are met:
! 11: * 1. Redistributions of source code must retain the above copyright
! 12: * notice, this list of conditions and the following disclaimer.
! 13: * 2. Redistributions in binary form must reproduce the above copyright
! 14: * notice, this list of conditions and the following disclaimer in the
! 15: * documentation and/or other materials provided with the distribution.
! 16: * 3. Neither the name of the University nor the names of its contributors
! 17: * may be used to endorse or promote products derived from this software
! 18: * without specific prior written permission.
! 19: *
! 20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 30: * SUCH DAMAGE.
! 31: *
! 32: * @(#)ct.c 8.1 (Berkeley) 7/15/93
! 33: */
! 34:
! 35: /*
! 36: * CS80 tape driver
! 37: */
! 38: #include <sys/param.h>
! 39:
! 40: #include <hp300/dev/ctreg.h>
! 41:
! 42: #include <lib/libsa/stand.h>
! 43:
! 44: #include "samachdep.h"
! 45: #include "hpibvar.h"
! 46:
! 47: struct ct_iocmd ct_ioc;
! 48: struct ct_rscmd ct_rsc;
! 49: struct ct_stat ct_stat;
! 50: struct ct_ssmcmd ct_ssmc;
! 51:
! 52: struct ct_softc {
! 53: int sc_ctlr;
! 54: int sc_unit;
! 55: char sc_retry;
! 56: char sc_alive;
! 57: short sc_punit;
! 58: int sc_blkno;
! 59: } ct_softc[NHPIB][NCT];
! 60:
! 61: #define CTRETRY 5
! 62: #define MTFSF 10
! 63: #define MTREW 11
! 64:
! 65: int ctclose(struct open_file *);
! 66: int cterror(int, int);
! 67: int ctident(int, int);
! 68: int ctinit(int, int);
! 69: int ctopen(struct open_file *, int, int, int);
! 70: int ctpunit(int, int, int *);
! 71: int ctstrategy(void *, int, daddr_t, size_t, void *, size_t *);
! 72:
! 73: char ctio_buf[MAXBSIZE];
! 74:
! 75: struct ctinfo {
! 76: short hwid;
! 77: short punit;
! 78: } ctinfo[] = {
! 79: { CT7946ID, 1 },
! 80: { CT7912PID, 1 },
! 81: { CT7914PID, 1 },
! 82: { CT9144ID, 0 },
! 83: { CT9145ID, 0 }
! 84: };
! 85: int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
! 86:
! 87: int
! 88: ctinit(int ctlr, int unit)
! 89: {
! 90: struct ct_softc *rs = &ct_softc[ctlr][unit];
! 91: u_char stat;
! 92:
! 93: if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat)
! 94: return (0);
! 95: if (ctident(ctlr, unit) < 0)
! 96: return (0);
! 97: bzero(&ct_ssmc, sizeof(ct_ssmc));
! 98: ct_ssmc.unit = C_SUNIT(rs->sc_punit);
! 99: ct_ssmc.cmd = C_SSM;
! 100: ct_ssmc.fefm = FEF_MASK;
! 101: ct_ssmc.refm = REF_MASK;
! 102: ct_ssmc.aefm = AEF_MASK;
! 103: ct_ssmc.iefm = IEF_MASK;
! 104: hpibsend(ctlr, unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc));
! 105: hpibswait(ctlr, unit);
! 106: hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
! 107: rs->sc_alive = 1;
! 108: return (1);
! 109: }
! 110:
! 111: int
! 112: ctident(int ctlr, int unit)
! 113: {
! 114: struct cs80_describe desc;
! 115: u_char stat, cmd[3];
! 116: char name[7];
! 117: int id, i;
! 118:
! 119: id = hpibid(ctlr, unit);
! 120: if ((id & 0x200) == 0)
! 121: return(-1);
! 122: for (i = 0; i < nctinfo; i++)
! 123: if (id == ctinfo[i].hwid)
! 124: break;
! 125: if (i == nctinfo)
! 126: return(-1);
! 127: ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit;
! 128: id = i;
! 129:
! 130: /*
! 131: * Collect device description.
! 132: * Right now we only need this to differentiate 7945 from 7946.
! 133: * Note that we always issue the describe command to unit 0.
! 134: */
! 135: cmd[0] = C_SUNIT(0);
! 136: cmd[1] = C_SVOL(0);
! 137: cmd[2] = C_DESC;
! 138: hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd));
! 139: hpibrecv(ctlr, unit, C_EXEC, &desc, sizeof(desc));
! 140: hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat));
! 141: bzero(name, sizeof(name));
! 142: if (!stat) {
! 143: int n = desc.d_name;
! 144: for (i = 5; i >= 0; i--) {
! 145: name[i] = (n & 0xf) + '0';
! 146: n >>= 4;
! 147: }
! 148: }
! 149: switch (ctinfo[id].hwid) {
! 150: case CT7946ID:
! 151: if (bcmp(name, "079450", 6) == 0)
! 152: id = -1; /* not really a 7946 */
! 153: break;
! 154: default:
! 155: break;
! 156: }
! 157: return(id);
! 158: }
! 159:
! 160: int
! 161: ctpunit(int ctlr, int slave, int *punit)
! 162: {
! 163: struct ct_softc *rs;
! 164:
! 165: if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
! 166: return(EADAPT);
! 167: if (slave >= NCT)
! 168: return(ECTLR);
! 169: rs = &ct_softc[ctlr][slave];
! 170:
! 171: if (rs->sc_alive == 0)
! 172: return(ENXIO);
! 173:
! 174: *punit = rs->sc_punit;
! 175: return (0);
! 176: }
! 177:
! 178: int
! 179: ctopen(struct open_file *f, int ctlr, int unit, int part)
! 180: {
! 181: struct ct_softc *rs;
! 182: int skip;
! 183: size_t resid;
! 184:
! 185: if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
! 186: return(EADAPT);
! 187: if (unit >= NCT)
! 188: return(ECTLR);
! 189: rs = &ct_softc[ctlr][unit];
! 190: rs->sc_blkno = 0;
! 191: rs->sc_unit = unit;
! 192: rs->sc_ctlr = ctlr;
! 193: if (rs->sc_alive == 0)
! 194: if (ctinit(ctlr, unit) == 0)
! 195: return(ENXIO);
! 196: f->f_devdata = (void *)rs;
! 197: ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid);
! 198: skip = part;
! 199: while (skip--)
! 200: ctstrategy(f->f_devdata, MTFSF, 0, 0, ctio_buf, &resid);
! 201: return(0);
! 202: }
! 203:
! 204: int
! 205: ctclose(struct open_file *f)
! 206: {
! 207: size_t resid;
! 208:
! 209: ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid);
! 210: return (0);
! 211: }
! 212:
! 213: int
! 214: ctstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf,
! 215: size_t *rsize)
! 216: {
! 217: struct ct_softc *rs = devdata;
! 218: char *buf = v_buf;
! 219: int ctlr = rs->sc_ctlr;
! 220: int unit = rs->sc_unit;
! 221: char stat;
! 222:
! 223: if (size == 0 && (func == F_READ || func == F_WRITE))
! 224: return(0);
! 225:
! 226: rs->sc_retry = 0;
! 227: bzero(&ct_ioc, sizeof(ct_ioc));
! 228: ct_ioc.unit = C_SUNIT(rs->sc_punit);
! 229: ct_ioc.saddr = C_SADDR;
! 230: ct_ioc.nop2 = C_NOP;
! 231: ct_ioc.slen = C_SLEN;
! 232: ct_ioc.nop3 = C_NOP;
! 233: top:
! 234: if (func == F_READ) {
! 235: ct_ioc.cmd = C_READ;
! 236: ct_ioc.addr = rs->sc_blkno;
! 237: ct_ioc.len = size;
! 238: }
! 239: else if (func == F_WRITE) {
! 240: ct_ioc.cmd = C_WRITE;
! 241: ct_ioc.addr = rs->sc_blkno;
! 242: ct_ioc.len = size;
! 243: }
! 244: else if (func == MTFSF) {
! 245: ct_ioc.cmd = C_READ;
! 246: ct_ioc.addr = rs->sc_blkno;
! 247: ct_ioc.len = size = MAXBSIZE;
! 248: }
! 249: else {
! 250: ct_ioc.cmd = C_READ;
! 251: ct_ioc.addr = 0;
! 252: ct_ioc.len = 0;
! 253: rs->sc_blkno = 0;
! 254: size = 0;
! 255: }
! 256: retry:
! 257: hpibsend(ctlr, unit, C_CMD, &ct_ioc, sizeof(ct_ioc));
! 258: if (func != MTREW) {
! 259: hpibswait(ctlr, unit);
! 260: hpibgo(ctlr, unit, C_EXEC, buf, size,
! 261: func != F_WRITE ? F_READ : F_WRITE);
! 262: hpibswait(ctlr, unit);
! 263: } else {
! 264: while (hpibswait(ctlr, unit) < 0)
! 265: ;
! 266: }
! 267: hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
! 268: if (stat) {
! 269: stat = cterror(ctlr, unit);
! 270: if (stat == 0)
! 271: return (-1);
! 272: if (stat == 2)
! 273: return (0);
! 274: if (++rs->sc_retry > CTRETRY)
! 275: return (-1);
! 276: goto retry;
! 277: }
! 278: rs->sc_blkno += CTBTOK(size);
! 279: if (func == MTFSF)
! 280: goto top;
! 281: *rsize = size;
! 282:
! 283: return(0);
! 284: }
! 285:
! 286: int
! 287: cterror(int ctlr, int unit)
! 288: {
! 289: struct ct_softc *rs = &ct_softc[ctlr][unit];
! 290: char stat;
! 291:
! 292: bzero(&ct_rsc, sizeof(ct_rsc));
! 293: bzero(&ct_stat, sizeof(ct_stat));
! 294: ct_rsc.unit = C_SUNIT(rs->sc_punit);
! 295: ct_rsc.cmd = C_STATUS;
! 296: hpibsend(ctlr, unit, C_CMD, &ct_rsc, sizeof(ct_rsc));
! 297: hpibrecv(ctlr, unit, C_EXEC, &ct_stat, sizeof(ct_stat));
! 298: hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
! 299: if (stat) {
! 300: printf("ct%d: request status fail %d\n", unit, stat);
! 301: return(0);
! 302: }
! 303: if (ct_stat.c_aef & AEF_EOF) {
! 304: /* 9145 drives don't increment block number at EOF */
! 305: if ((ct_stat.c_blk - rs->sc_blkno) == 0)
! 306: rs->sc_blkno++;
! 307: else
! 308: rs->sc_blkno = ct_stat.c_blk;
! 309: return (2);
! 310: }
! 311: printf("ct%d err: vu 0x%x, pend 0x%x, bn%ld", unit,
! 312: ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk);
! 313: printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref,
! 314: ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief);
! 315: return (1);
! 316: }
CVSweb