1 1.8 tsutsui /* $NetBSD: ct.c,v 1.8 2021/07/05 14:51:23 tsutsui 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.8 tsutsui 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.8 tsutsui 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