1 /* $NetBSD: ct.c,v 1.1 1997/02/04 03:52:19 thorpej 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. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)ct.c 8.1 (Berkeley) 7/15/93 36 */ 37 38 /* 39 * CS80 tape driver 40 */ 41 #include <sys/param.h> 42 43 #include <hp300/dev/ctreg.h> 44 45 #include <lib/libsa/stand.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 ctinit(ctlr, unit) 81 register int ctlr, unit; 82 { 83 register struct ct_softc *rs = &ct_softc[ctlr][unit]; 84 u_char stat; 85 register int type; 86 87 if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat) 88 return (0); 89 if (ctident(ctlr, unit) < 0) 90 return (0); 91 bzero(&ct_ssmc, sizeof(ct_ssmc)); 92 ct_ssmc.unit = C_SUNIT(rs->sc_punit); 93 ct_ssmc.cmd = C_SSM; 94 ct_ssmc.fefm = FEF_MASK; 95 ct_ssmc.refm = REF_MASK; 96 ct_ssmc.aefm = AEF_MASK; 97 ct_ssmc.iefm = IEF_MASK; 98 hpibsend(ctlr, unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc)); 99 hpibswait(ctlr, unit); 100 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 101 rs->sc_alive = 1; 102 return (1); 103 } 104 105 ctident(ctlr, unit) 106 int ctlr, unit; 107 { 108 struct ct_describe desc; 109 u_char stat, cmd[3]; 110 char name[7]; 111 int id, i; 112 113 id = hpibid(ctlr, unit); 114 if ((id & 0x200) == 0) 115 return(-1); 116 for (i = 0; i < nctinfo; i++) 117 if (id == ctinfo[i].hwid) 118 break; 119 if (i == nctinfo) 120 return(-1); 121 ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit; 122 id = i; 123 124 /* 125 * Collect device description. 126 * Right now we only need this to differentiate 7945 from 7946. 127 * Note that we always issue the describe command to unit 0. 128 */ 129 cmd[0] = C_SUNIT(0); 130 cmd[1] = C_SVOL(0); 131 cmd[2] = C_DESC; 132 hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd)); 133 hpibrecv(ctlr, unit, C_EXEC, &desc, 37); 134 hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat)); 135 bzero(name, sizeof(name)); 136 if (!stat) { 137 register int n = desc.d_name; 138 for (i = 5; i >= 0; i--) { 139 name[i] = (n & 0xf) + '0'; 140 n >>= 4; 141 } 142 } 143 switch (ctinfo[id].hwid) { 144 case CT7946ID: 145 if (bcmp(name, "079450", 6) == 0) 146 id = -1; /* not really a 7946 */ 147 break; 148 default: 149 break; 150 } 151 return(id); 152 } 153 154 int 155 ctpunit(ctlr, slave, punit) 156 int ctlr, slave, *punit; 157 { 158 register 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 ctopen(f, ctlr, unit, part) 174 struct open_file *f; 175 int ctlr, unit, part; 176 { 177 register struct ct_softc *rs; 178 register int skip; 179 size_t resid; 180 181 if (ctlr >= NHPIB || hpibalive(ctlr) == 0) 182 return(EADAPT); 183 if (unit >= NCT) 184 return(ECTLR); 185 rs = &ct_softc[ctlr][unit]; 186 rs->sc_blkno = 0; 187 rs->sc_unit = unit; 188 rs->sc_ctlr = ctlr; 189 if (rs->sc_alive == 0) 190 if (ctinit(ctlr, unit) == 0) 191 return(ENXIO); 192 f->f_devdata = (void *)rs; 193 ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid); 194 skip = part; 195 while (skip--) 196 ctstrategy(f->f_devdata, MTFSF, 0, 0, ctio_buf, &resid); 197 return(0); 198 } 199 200 ctclose(f) 201 struct open_file *f; 202 { 203 size_t resid; 204 205 ctstrategy(f->f_devdata, MTREW, 0, 0, ctio_buf, &resid); 206 } 207 208 ctstrategy(devdata, func, dblk, size, v_buf, rsize) 209 void *devdata; 210 int func; 211 daddr_t dblk; 212 size_t size; 213 void *v_buf; 214 size_t *rsize; 215 { 216 struct ct_softc *rs = devdata; 217 char *buf = v_buf; 218 int ctlr = rs->sc_ctlr; 219 int unit = rs->sc_unit; 220 char stat; 221 222 if (size == 0 && (func == F_READ || func == F_WRITE)) 223 return(0); 224 225 rs->sc_retry = 0; 226 bzero(&ct_ioc, sizeof(ct_ioc)); 227 ct_ioc.unit = C_SUNIT(rs->sc_punit); 228 ct_ioc.saddr = C_SADDR; 229 ct_ioc.nop2 = C_NOP; 230 ct_ioc.slen = C_SLEN; 231 ct_ioc.nop3 = C_NOP; 232 top: 233 if (func == F_READ) { 234 ct_ioc.cmd = C_READ; 235 ct_ioc.addr = rs->sc_blkno; 236 ct_ioc.len = size; 237 } 238 else if (func == F_WRITE) { 239 ct_ioc.cmd = C_WRITE; 240 ct_ioc.addr = rs->sc_blkno; 241 ct_ioc.len = size; 242 } 243 else if (func == MTFSF) { 244 ct_ioc.cmd = C_READ; 245 ct_ioc.addr = rs->sc_blkno; 246 ct_ioc.len = size = MAXBSIZE; 247 } 248 else { 249 ct_ioc.cmd = C_READ; 250 ct_ioc.addr = 0; 251 ct_ioc.len = 0; 252 rs->sc_blkno = 0; 253 size = 0; 254 } 255 retry: 256 hpibsend(ctlr, unit, C_CMD, &ct_ioc, sizeof(ct_ioc)); 257 if (func != MTREW) { 258 hpibswait(ctlr, unit); 259 hpibgo(ctlr, unit, C_EXEC, buf, size, 260 func != F_WRITE ? F_READ : F_WRITE); 261 hpibswait(ctlr, unit); 262 } else { 263 while (hpibswait(ctlr, unit) < 0) 264 ; 265 } 266 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 267 if (stat) { 268 stat = cterror(ctlr, unit); 269 if (stat == 0) 270 return (-1); 271 if (stat == 2) 272 return (0); 273 if (++rs->sc_retry > CTRETRY) 274 return (-1); 275 goto retry; 276 } 277 rs->sc_blkno += CTBTOK(size); 278 if (func == MTFSF) 279 goto top; 280 *rsize = size; 281 282 return(0); 283 } 284 285 cterror(ctlr, unit) 286 register int ctlr, unit; 287 { 288 register struct ct_softc *rs = &ct_softc[ctlr][unit]; 289 char stat; 290 291 bzero(&ct_rsc, sizeof(ct_rsc)); 292 bzero(&ct_stat, sizeof(ct_stat)); 293 ct_rsc.unit = C_SUNIT(rs->sc_punit); 294 ct_rsc.cmd = C_STATUS; 295 hpibsend(ctlr, unit, C_CMD, &ct_rsc, sizeof(ct_rsc)); 296 hpibrecv(ctlr, unit, C_EXEC, &ct_stat, sizeof(ct_stat)); 297 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 298 if (stat) { 299 printf("ct%d: request status fail %d\n", unit, stat); 300 return(0); 301 } 302 if (ct_stat.c_aef & AEF_EOF) { 303 /* 9145 drives don't increment block number at EOF */ 304 if ((ct_stat.c_blk - rs->sc_blkno) == 0) 305 rs->sc_blkno++; 306 else 307 rs->sc_blkno = ct_stat.c_blk; 308 return (2); 309 } 310 printf("ct%d err: vu 0x%x, pend 0x%x, bn%d", unit, 311 ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk); 312 printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref, 313 ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief); 314 return (1); 315 } 316