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.2 (Berkeley) 12/16/90 8 */ 9 10 /* 11 * CS80 tape driver 12 */ 13 #include "sys/types.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[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(unit) 48 register int unit; 49 { 50 register struct ct_softc *rs = &ct_softc[unit]; 51 u_char stat; 52 register int type; 53 54 if (hpibrecv(unit, C_QSTAT, &stat, 1) != 1 || stat) 55 return (0); 56 if (ctident(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(unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc)); 65 hpibswait(unit); 66 hpibrecv(unit, C_QSTAT, &stat, 1); 67 rs->sc_alive = 1; 68 return (1); 69 } 70 71 ctident(unit) 72 int 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(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[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(unit, C_CMD, cmd, sizeof(cmd)); 99 hpibrecv(unit, C_EXEC, &desc, 37); 100 hpibrecv(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 int unit = io->i_unit; 124 register struct ct_softc *rs = &ct_softc[unit]; 125 register int skip; 126 127 if (hpibalive(unit) == 0) 128 _stop("ct controller not configured"); 129 if (rs->sc_alive == 0) 130 if (ctinit(unit) == 0) 131 _stop("ct init failed"); 132 ctstrategy(io, MTREW); 133 skip = io->i_boff; 134 while (skip--) 135 ctstrategy(io, MTFSF); 136 } 137 138 ctclose(io) 139 struct iob *io; 140 { 141 ctstrategy(io, MTREW); 142 } 143 144 ctstrategy(io, func) 145 register struct iob *io; 146 register int func; 147 { 148 register int unit = io->i_unit; 149 register struct ct_softc *rs = &ct_softc[unit]; 150 char stat; 151 152 rs->sc_retry = 0; 153 ct_ioc.unit = C_SUNIT(rs->sc_punit); 154 ct_ioc.saddr = C_SADDR; 155 ct_ioc.nop2 = C_NOP; 156 ct_ioc.slen = C_SLEN; 157 ct_ioc.nop3 = C_NOP; 158 top: 159 if (func == READ) { 160 ct_ioc.cmd = C_READ; 161 ct_ioc.addr = rs->sc_blkno; 162 ct_ioc.len = io->i_cc; 163 } 164 else if (func == WRITE) { 165 ct_ioc.cmd = C_WRITE; 166 ct_ioc.addr = rs->sc_blkno; 167 ct_ioc.len = io->i_cc; 168 } 169 else if (func == MTFSF) { 170 ct_ioc.cmd = C_READ; 171 ct_ioc.addr = rs->sc_blkno; 172 ct_ioc.len = io->i_cc = MAXBSIZE; 173 io->i_ma = io->i_buf; 174 } 175 else { 176 ct_ioc.cmd = C_READ; 177 ct_ioc.addr = 0; 178 ct_ioc.len = 0; 179 rs->sc_blkno = 0; 180 io->i_cc = 0; 181 } 182 retry: 183 hpibsend(unit, C_CMD, &ct_ioc, sizeof(ct_ioc)); 184 if (func != MTREW) { 185 hpibswait(unit); 186 hpibgo(unit, C_EXEC, io->i_ma, io->i_cc, 187 func != WRITE ? READ : WRITE); 188 hpibswait(unit); 189 } 190 else { 191 while (hpibswait(unit) < 0) 192 ; 193 } 194 hpibrecv(unit, C_QSTAT, &stat, 1); 195 if (stat) { 196 stat = cterror(unit); 197 if (stat == 0) 198 return (-1); 199 if (stat == 2) 200 return (0); 201 if (++rs->sc_retry > CTRETRY) 202 return (-1); 203 else 204 goto retry; 205 } 206 rs->sc_blkno += CTBTOK(io->i_cc); 207 if (func == MTFSF) 208 goto top; 209 return (io->i_cc); 210 } 211 212 cterror(unit) 213 register int unit; 214 { 215 register struct ct_softc *ct = &ct_softc[unit]; 216 char stat; 217 218 ct_rsc.unit = C_SUNIT(ct->sc_punit); 219 ct_rsc.cmd = C_STATUS; 220 hpibsend(unit, C_CMD, &ct_rsc, sizeof(ct_rsc)); 221 hpibrecv(unit, C_EXEC, &ct_stat, sizeof(ct_stat)); 222 hpibrecv(unit, C_QSTAT, &stat, 1); 223 if (stat) { 224 printf("ct%d: request status fail %d\n", unit, stat); 225 return(0); 226 } 227 if (ct_stat.c_aef & AEF_EOF) { 228 /* 9145 drives don't increment block number at EOF */ 229 if ((ct_stat.c_blk - ct->sc_blkno) == 0) 230 ct->sc_blkno++; 231 else 232 ct->sc_blkno = ct_stat.c_blk; 233 return (2); 234 } 235 printf("ct%d err: vu 0x%x, pend 0x%x, bn%d", unit, 236 ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk); 237 printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref, 238 ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief); 239 return (1); 240 } 241