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