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