Home | History | Annotate | Line # | Download | only in common
ct.c revision 1.5
      1 /*	$NetBSD: ct.c,v 1.5 2005/12/11 12:17:19 christos 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(int ctlr, int unit)
     86 {
     87 	struct ct_softc *rs = &ct_softc[ctlr][unit];
     88 	u_char stat;
     89 
     90 	if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat)
     91 		return 0;
     92 	if (ctident(ctlr, unit) < 0)
     93 		return 0;
     94 	memset(&ct_ssmc, 0, sizeof(ct_ssmc));
     95 	ct_ssmc.unit = C_SUNIT(rs->sc_punit);
     96 	ct_ssmc.cmd = C_SSM;
     97 	ct_ssmc.fefm = FEF_MASK;
     98 	ct_ssmc.refm = REF_MASK;
     99 	ct_ssmc.aefm = AEF_MASK;
    100 	ct_ssmc.iefm = IEF_MASK;
    101 	hpibsend(ctlr, unit, C_CMD, (char *)&ct_ssmc, sizeof(ct_ssmc));
    102 	hpibswait(ctlr, unit);
    103 	hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
    104 	rs->sc_alive = 1;
    105 	return 1;
    106 }
    107 
    108 int
    109 ctident(int ctlr, int unit)
    110 {
    111 	struct ct_describe desc;
    112 	u_char stat, cmd[3];
    113 	char name[7];
    114 	int id, i;
    115 
    116 	id = hpibid(ctlr, unit);
    117 	if ((id & 0x200) == 0)
    118 		return -1;
    119 	for (i = 0; i < nctinfo; i++)
    120 		if (id == ctinfo[i].hwid)
    121 			break;
    122 	if (i == nctinfo)
    123 		return -1;
    124 	ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit;
    125 	id = i;
    126 
    127 	/*
    128 	 * Collect device description.
    129 	 * Right now we only need this to differentiate 7945 from 7946.
    130 	 * Note that we always issue the describe command to unit 0.
    131 	 */
    132 	cmd[0] = C_SUNIT(0);
    133 	cmd[1] = C_SVOL(0);
    134 	cmd[2] = C_DESC;
    135 	hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd));
    136 	hpibrecv(ctlr, unit, C_EXEC, (char *)&desc, 37);
    137 	hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat));
    138 	memset(name, 0, sizeof(name));
    139 	if (!stat) {
    140 		int n = desc.d_name;
    141 		for (i = 5; i >= 0; i--) {
    142 			name[i] = (n & 0xf) + '0';
    143 			n >>= 4;
    144 		}
    145 	}
    146 	switch (ctinfo[id].hwid) {
    147 	case CT7946ID:
    148 		if (memcmp(name, "079450", 6) == 0)
    149 			id = -1;		/* not really a 7946 */
    150 		break;
    151 	default:
    152 		break;
    153 	}
    154 	return id;
    155 }
    156 
    157 int
    158 ctpunit(int ctlr, int slave, int *punit)
    159 {
    160 	struct ct_softc *rs;
    161 
    162 	if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
    163 		return EADAPT;
    164 	if (slave >= NCT)
    165 		return ECTLR;
    166 	rs = &ct_softc[ctlr][slave];
    167 
    168 	if (rs->sc_alive == 0)
    169 		return ENXIO;
    170 
    171 	*punit = rs->sc_punit;
    172 	return 0;
    173 }
    174 
    175 int
    176 ctopen(struct open_file *f, ...)
    177 {
    178 	va_list ap;
    179 	int ctlr, unit, part;
    180 	struct ct_softc *rs;
    181 	int skip;
    182 	size_t resid;
    183 
    184 	va_start(ap, f);
    185 	ctlr = va_arg(ap, int);
    186 	unit = va_arg(ap, int);
    187 	part = va_arg(ap, int);
    188 	va_end(ap);
    189 
    190 	if (ctlr >= NHPIB || hpibalive(ctlr) == 0)
    191 		return EADAPT;
    192 	if (unit >= NCT)
    193 		return ECTLR;
    194 	rs = &ct_softc[ctlr][unit];
    195 	rs->sc_blkno = 0;
    196 	rs->sc_unit = unit;
    197 	rs->sc_ctlr = ctlr;
    198 	if (rs->sc_alive == 0)
    199 		if (ctinit(ctlr, unit) == 0)
    200 			return ENXIO;
    201 	f->f_devdata = (void *)rs;
    202 	ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid);
    203 	skip = part;
    204 	while (skip--)
    205 		ctstrategy(f->f_devdata, MTFSF, 0, 0, ctio_buf, &resid);
    206 	return 0;
    207 }
    208 
    209 int
    210 ctclose(struct open_file *f)
    211 {
    212 	size_t resid;
    213 
    214 	ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid);
    215 	return 0;
    216 }
    217 
    218 int
    219 ctstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf,
    220     size_t *rsize)
    221 {
    222 	struct ct_softc *rs = devdata;
    223 	char *buf = v_buf;
    224 	int ctlr = rs->sc_ctlr;
    225 	int unit = rs->sc_unit;
    226 	char stat;
    227 
    228 	if (size == 0 && (func == F_READ || func == F_WRITE))
    229 		return 0;
    230 
    231 	rs->sc_retry = 0;
    232 	memset(&ct_ioc, 0, sizeof(ct_ioc));
    233 	ct_ioc.unit = C_SUNIT(rs->sc_punit);
    234 	ct_ioc.saddr = C_SADDR;
    235 	ct_ioc.nop2 = C_NOP;
    236 	ct_ioc.slen = C_SLEN;
    237 	ct_ioc.nop3 = C_NOP;
    238 top:
    239 	if (func == F_READ) {
    240 		ct_ioc.cmd = C_READ;
    241 		ct_ioc.addr = rs->sc_blkno;
    242 		ct_ioc.len = size;
    243 	}
    244 	else if (func == F_WRITE) {
    245 		ct_ioc.cmd = C_WRITE;
    246 		ct_ioc.addr = rs->sc_blkno;
    247 		ct_ioc.len = size;
    248 	}
    249 	else if (func == MTFSF) {
    250 		ct_ioc.cmd = C_READ;
    251 		ct_ioc.addr = rs->sc_blkno;
    252 		ct_ioc.len = size = MAXBSIZE;
    253 	}
    254 	else {
    255 		ct_ioc.cmd = C_READ;
    256 		ct_ioc.addr = 0;
    257 		ct_ioc.len = 0;
    258 		rs->sc_blkno = 0;
    259 		size = 0;
    260 	}
    261 retry:
    262 	hpibsend(ctlr, unit, C_CMD, (char *)&ct_ioc, sizeof(ct_ioc));
    263 	if (func != MTREW) {
    264 		hpibswait(ctlr, unit);
    265 		hpibgo(ctlr, unit, C_EXEC, buf, size,
    266 			func != F_WRITE ? F_READ : F_WRITE);
    267 		hpibswait(ctlr, unit);
    268 	} else {
    269 		while (hpibswait(ctlr, unit) < 0)
    270 			;
    271 	}
    272 	hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
    273 	if (stat) {
    274 		stat = cterror(ctlr, unit);
    275 		if (stat == 0)
    276 			return -1;
    277 		if (stat == 2)
    278 			return 0;
    279 		if (++rs->sc_retry > CTRETRY)
    280 			return -1;
    281 		goto retry;
    282 	}
    283 	rs->sc_blkno += CTBTOK(size);
    284 	if (func == MTFSF)
    285 		goto top;
    286 	*rsize = size;
    287 
    288 	return 0;
    289 }
    290 
    291 int
    292 cterror(int ctlr, int unit)
    293 {
    294 	struct ct_softc *rs = &ct_softc[ctlr][unit];
    295 	char stat;
    296 
    297 	memset(&ct_rsc, 0, sizeof(ct_rsc));
    298 	memset(&ct_stat, 0, sizeof(ct_stat));
    299 	ct_rsc.unit = C_SUNIT(rs->sc_punit);
    300 	ct_rsc.cmd = C_STATUS;
    301 	hpibsend(ctlr, unit, C_CMD, (char *)&ct_rsc, sizeof(ct_rsc));
    302 	hpibrecv(ctlr, unit, C_EXEC, (char *)&ct_stat, sizeof(ct_stat));
    303 	hpibrecv(ctlr, unit, C_QSTAT, &stat, 1);
    304 	if (stat) {
    305 		printf("ct%d: request status fail %d\n", unit, stat);
    306 		return 0;
    307 	}
    308 	if (ct_stat.c_aef & AEF_EOF) {
    309 		/* 9145 drives don't increment block number at EOF */
    310 		if ((ct_stat.c_blk - rs->sc_blkno) == 0)
    311 			rs->sc_blkno++;
    312 		else
    313 			rs->sc_blkno = ct_stat.c_blk;
    314 		return 2;
    315 	}
    316 	printf("ct%d err: vu 0x%x, pend 0x%x, bn%ld", unit,
    317 	    ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk);
    318 	printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref,
    319 	    ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief);
    320 	return 1;
    321 }
    322