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