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