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