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