1 /* 2 * Copyright (c) 1982, 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)ct.c 7.5 (Berkeley) 08/14/92 8 */ 9 10 /* 11 * CS80 tape driver 12 */ 13 #include "sys/param.h" 14 #include "../dev/ctreg.h" 15 16 #include "saio.h" 17 #include "samachdep.h" 18 19 struct ct_iocmd ct_ioc; 20 struct ct_rscmd ct_rsc; 21 struct ct_stat ct_stat; 22 struct ct_ssmcmd ct_ssmc; 23 24 struct ct_softc { 25 char sc_retry; 26 char sc_alive; 27 short sc_punit; 28 int sc_blkno; 29 } ct_softc[NHPIB][NCT]; 30 31 #define CTRETRY 5 32 #define MTFSF 10 33 #define MTREW 11 34 35 struct ctinfo { 36 short hwid; 37 short punit; 38 } ctinfo[] = { 39 CT7946ID, 1, 40 CT7912PID, 1, 41 CT7914PID, 1, 42 CT9144ID, 0, 43 CT9145ID, 0, 44 }; 45 int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]); 46 47 ctinit(ctlr, unit) 48 register int ctlr, unit; 49 { 50 register struct ct_softc *rs = &ct_softc[ctlr][unit]; 51 u_char stat; 52 register int type; 53 54 if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat) 55 return (0); 56 if (ctident(ctlr, unit) < 0) 57 return (0); 58 ct_ssmc.unit = C_SUNIT(rs->sc_punit); 59 ct_ssmc.cmd = C_SSM; 60 ct_ssmc.fefm = FEF_MASK; 61 ct_ssmc.refm = REF_MASK; 62 ct_ssmc.aefm = AEF_MASK; 63 ct_ssmc.iefm = IEF_MASK; 64 hpibsend(ctlr, unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc)); 65 hpibswait(ctlr, unit); 66 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 67 rs->sc_alive = 1; 68 return (1); 69 } 70 71 ctident(ctlr, unit) 72 int ctlr, unit; 73 { 74 struct ct_describe desc; 75 u_char stat, cmd[3]; 76 char name[7]; 77 int id, i; 78 79 id = hpibid(ctlr, unit); 80 if ((id & 0x200) == 0) 81 return(-1); 82 for (i = 0; i < nctinfo; i++) 83 if (id == ctinfo[i].hwid) 84 break; 85 if (i == nctinfo) 86 return(-1); 87 ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit; 88 id = i; 89 90 /* 91 * Collect device description. 92 * Right now we only need this to differentiate 7945 from 7946. 93 * Note that we always issue the describe command to unit 0. 94 */ 95 cmd[0] = C_SUNIT(0); 96 cmd[1] = C_SVOL(0); 97 cmd[2] = C_DESC; 98 hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd)); 99 hpibrecv(ctlr, unit, C_EXEC, &desc, 37); 100 hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat)); 101 bzero(name, sizeof(name)); 102 if (!stat) { 103 register int n = desc.d_name; 104 for (i = 5; i >= 0; i--) { 105 name[i] = (n & 0xf) + '0'; 106 n >>= 4; 107 } 108 } 109 switch (ctinfo[id].hwid) { 110 case CT7946ID: 111 if (bcmp(name, "079450", 6) == 0) 112 id = -1; /* not really a 7946 */ 113 break; 114 default: 115 break; 116 } 117 return(id); 118 } 119 120 ctopen(io) 121 struct iob *io; 122 { 123 register struct ct_softc *rs; 124 register int unit, ctlr; 125 register int skip; 126 127 devconvert(io); 128 129 ctlr = io->i_adapt; 130 if (ctlr >= NHPIB || hpibalive(ctlr) == 0) 131 return(EADAPT); 132 unit = io->i_ctlr; 133 if (unit >= NCT) 134 return(ECTLR); 135 if (rs->sc_alive == 0) 136 if (ctinit(ctlr, unit) == 0) 137 return(ENXIO); 138 ctstrategy(io, MTREW); 139 skip = io->i_part; 140 while (skip--) 141 ctstrategy(io, MTFSF); 142 return(0); 143 } 144 145 ctclose(io) 146 struct iob *io; 147 { 148 ctstrategy(io, MTREW); 149 } 150 151 ctstrategy(io, func) 152 register struct iob *io; 153 register int func; 154 { 155 register int ctlr = io->i_adapt; 156 register int unit = io->i_ctlr; 157 register struct ct_softc *rs = &ct_softc[ctlr][unit]; 158 char stat; 159 160 if (io->i_cc == 0 && (func == F_READ || func == F_WRITE)) 161 return(0); 162 163 rs->sc_retry = 0; 164 ct_ioc.unit = C_SUNIT(rs->sc_punit); 165 ct_ioc.saddr = C_SADDR; 166 ct_ioc.nop2 = C_NOP; 167 ct_ioc.slen = C_SLEN; 168 ct_ioc.nop3 = C_NOP; 169 top: 170 if (func == F_READ) { 171 ct_ioc.cmd = C_READ; 172 ct_ioc.addr = rs->sc_blkno; 173 ct_ioc.len = io->i_cc; 174 } 175 else if (func == F_WRITE) { 176 ct_ioc.cmd = C_WRITE; 177 ct_ioc.addr = rs->sc_blkno; 178 ct_ioc.len = io->i_cc; 179 } 180 else if (func == MTFSF) { 181 ct_ioc.cmd = C_READ; 182 ct_ioc.addr = rs->sc_blkno; 183 ct_ioc.len = io->i_cc = MAXBSIZE; 184 io->i_ma = io->i_buf; 185 } 186 else { 187 ct_ioc.cmd = C_READ; 188 ct_ioc.addr = 0; 189 ct_ioc.len = 0; 190 rs->sc_blkno = 0; 191 io->i_cc = 0; 192 } 193 retry: 194 hpibsend(ctlr, unit, C_CMD, &ct_ioc, sizeof(ct_ioc)); 195 if (func != MTREW) { 196 hpibswait(ctlr, unit); 197 hpibgo(ctlr, unit, C_EXEC, io->i_ma, io->i_cc, 198 func != F_WRITE ? F_READ : F_WRITE); 199 hpibswait(ctlr, unit); 200 } else { 201 while (hpibswait(ctlr, unit) < 0) 202 ; 203 } 204 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 205 if (stat) { 206 stat = cterror(ctlr, unit); 207 if (stat == 0) 208 return (-1); 209 if (stat == 2) 210 return (0); 211 if (++rs->sc_retry > CTRETRY) 212 return (-1); 213 goto retry; 214 } 215 rs->sc_blkno += CTBTOK(io->i_cc); 216 if (func == MTFSF) 217 goto top; 218 return (io->i_cc); 219 } 220 221 cterror(ctlr, unit) 222 register int ctlr, unit; 223 { 224 register struct ct_softc *rs = &ct_softc[ctlr][unit]; 225 char stat; 226 227 ct_rsc.unit = C_SUNIT(rs->sc_punit); 228 ct_rsc.cmd = C_STATUS; 229 hpibsend(ctlr, unit, C_CMD, &ct_rsc, sizeof(ct_rsc)); 230 hpibrecv(ctlr, unit, C_EXEC, &ct_stat, sizeof(ct_stat)); 231 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 232 if (stat) { 233 printf("ct%d: request status fail %d\n", unit, stat); 234 return(0); 235 } 236 if (ct_stat.c_aef & AEF_EOF) { 237 /* 9145 drives don't increment block number at EOF */ 238 if ((ct_stat.c_blk - rs->sc_blkno) == 0) 239 rs->sc_blkno++; 240 else 241 rs->sc_blkno = ct_stat.c_blk; 242 return (2); 243 } 244 printf("ct%d err: vu 0x%x, pend 0x%x, bn%d", unit, 245 ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk); 246 printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref, 247 ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief); 248 return (1); 249 } 250