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