141488Smckusick /* 241488Smckusick * Copyright (c) 1982, 1990 The Regents of the University of California. 341488Smckusick * All rights reserved. 441488Smckusick * 541488Smckusick * %sccs.include.redist.c% 641488Smckusick * 7*49154Sbostic * @(#)ct.c 7.3 (Berkeley) 05/05/91 841488Smckusick */ 941488Smckusick 1041488Smckusick /* 1141488Smckusick * CS80 tape driver 1241488Smckusick */ 13*49154Sbostic #include <sys/param.h> 1445790Sbostic #include "../dev/ctreg.h" 1541488Smckusick 1641488Smckusick #include "saio.h" 1741488Smckusick #include "samachdep.h" 1841488Smckusick 1941488Smckusick struct ct_iocmd ct_ioc; 2041488Smckusick struct ct_rscmd ct_rsc; 2141488Smckusick struct ct_stat ct_stat; 2241488Smckusick struct ct_ssmcmd ct_ssmc; 2341488Smckusick 2441488Smckusick struct ct_softc { 2541488Smckusick char sc_retry; 2641488Smckusick char sc_alive; 2741488Smckusick short sc_punit; 2841488Smckusick int sc_blkno; 2941488Smckusick } ct_softc[NCT]; 3041488Smckusick 3141488Smckusick #define CTRETRY 5 3241488Smckusick #define MTFSF 10 3341488Smckusick #define MTREW 11 3441488Smckusick 3541488Smckusick struct ctinfo { 3641488Smckusick short hwid; 3741488Smckusick short punit; 3841488Smckusick } ctinfo[] = { 3941488Smckusick CT7946ID, 1, 4041488Smckusick CT7912PID, 1, 4141488Smckusick CT7914PID, 1, 4241488Smckusick CT9144ID, 0, 4341488Smckusick CT9145ID, 0, 4441488Smckusick }; 4541488Smckusick int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]); 4641488Smckusick 4741488Smckusick ctinit(unit) 4841488Smckusick register int unit; 4941488Smckusick { 5041488Smckusick register struct ct_softc *rs = &ct_softc[unit]; 5141488Smckusick u_char stat; 5241488Smckusick register int type; 5341488Smckusick 5441488Smckusick if (hpibrecv(unit, C_QSTAT, &stat, 1) != 1 || stat) 5541488Smckusick return (0); 5641488Smckusick if (ctident(unit) < 0) 5741488Smckusick return (0); 5841488Smckusick ct_ssmc.unit = C_SUNIT(rs->sc_punit); 5941488Smckusick ct_ssmc.cmd = C_SSM; 6041488Smckusick ct_ssmc.fefm = FEF_MASK; 6141488Smckusick ct_ssmc.refm = REF_MASK; 6241488Smckusick ct_ssmc.aefm = AEF_MASK; 6341488Smckusick ct_ssmc.iefm = IEF_MASK; 6441488Smckusick hpibsend(unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc)); 6541488Smckusick hpibswait(unit); 6641488Smckusick hpibrecv(unit, C_QSTAT, &stat, 1); 6741488Smckusick rs->sc_alive = 1; 6841488Smckusick return (1); 6941488Smckusick } 7041488Smckusick 7141488Smckusick ctident(unit) 7241488Smckusick int unit; 7341488Smckusick { 7441488Smckusick struct ct_describe desc; 7541488Smckusick u_char stat, cmd[3]; 7641488Smckusick char name[7]; 7741488Smckusick int id, i; 7841488Smckusick 7941488Smckusick id = hpibid(unit); 8041488Smckusick if ((id & 0x200) == 0) 8141488Smckusick return(-1); 8241488Smckusick for (i = 0; i < nctinfo; i++) 8341488Smckusick if (id == ctinfo[i].hwid) 8441488Smckusick break; 8541488Smckusick if (i == nctinfo) 8641488Smckusick return(-1); 8741488Smckusick ct_softc[unit].sc_punit = ctinfo[i].punit; 8841488Smckusick id = i; 8941488Smckusick 9041488Smckusick /* 9141488Smckusick * Collect device description. 9241488Smckusick * Right now we only need this to differentiate 7945 from 7946. 9341488Smckusick * Note that we always issue the describe command to unit 0. 9441488Smckusick */ 9541488Smckusick cmd[0] = C_SUNIT(0); 9641488Smckusick cmd[1] = C_SVOL(0); 9741488Smckusick cmd[2] = C_DESC; 9841488Smckusick hpibsend(unit, C_CMD, cmd, sizeof(cmd)); 9941488Smckusick hpibrecv(unit, C_EXEC, &desc, 37); 10041488Smckusick hpibrecv(unit, C_QSTAT, &stat, sizeof(stat)); 10141488Smckusick bzero(name, sizeof(name)); 10241488Smckusick if (!stat) { 10341488Smckusick register int n = desc.d_name; 10441488Smckusick for (i = 5; i >= 0; i--) { 10541488Smckusick name[i] = (n & 0xf) + '0'; 10641488Smckusick n >>= 4; 10741488Smckusick } 10841488Smckusick } 10941488Smckusick switch (ctinfo[id].hwid) { 11041488Smckusick case CT7946ID: 11141488Smckusick if (bcmp(name, "079450", 6) == 0) 11241488Smckusick id = -1; /* not really a 7946 */ 11341488Smckusick break; 11441488Smckusick default: 11541488Smckusick break; 11641488Smckusick } 11741488Smckusick return(id); 11841488Smckusick } 11941488Smckusick 12041488Smckusick ctopen(io) 12141488Smckusick struct iob *io; 12241488Smckusick { 12341488Smckusick register int unit = io->i_unit; 12441488Smckusick register struct ct_softc *rs = &ct_softc[unit]; 12541488Smckusick register int skip; 12641488Smckusick 12741488Smckusick if (hpibalive(unit) == 0) 12841488Smckusick _stop("ct controller not configured"); 12941488Smckusick if (rs->sc_alive == 0) 13041488Smckusick if (ctinit(unit) == 0) 13141488Smckusick _stop("ct init failed"); 13241488Smckusick ctstrategy(io, MTREW); 13341488Smckusick skip = io->i_boff; 13441488Smckusick while (skip--) 13541488Smckusick ctstrategy(io, MTFSF); 13641488Smckusick } 13741488Smckusick 13841488Smckusick ctclose(io) 13941488Smckusick struct iob *io; 14041488Smckusick { 14141488Smckusick ctstrategy(io, MTREW); 14241488Smckusick } 14341488Smckusick 14441488Smckusick ctstrategy(io, func) 14541488Smckusick register struct iob *io; 14641488Smckusick register int func; 14741488Smckusick { 14841488Smckusick register int unit = io->i_unit; 14941488Smckusick register struct ct_softc *rs = &ct_softc[unit]; 15041488Smckusick char stat; 15141488Smckusick 15241488Smckusick rs->sc_retry = 0; 15341488Smckusick ct_ioc.unit = C_SUNIT(rs->sc_punit); 15441488Smckusick ct_ioc.saddr = C_SADDR; 15541488Smckusick ct_ioc.nop2 = C_NOP; 15641488Smckusick ct_ioc.slen = C_SLEN; 15741488Smckusick ct_ioc.nop3 = C_NOP; 15841488Smckusick top: 159*49154Sbostic if (func == F_READ) { 16041488Smckusick ct_ioc.cmd = C_READ; 16141488Smckusick ct_ioc.addr = rs->sc_blkno; 16241488Smckusick ct_ioc.len = io->i_cc; 16341488Smckusick } 164*49154Sbostic else if (func == F_WRITE) { 16541488Smckusick ct_ioc.cmd = C_WRITE; 16641488Smckusick ct_ioc.addr = rs->sc_blkno; 16741488Smckusick ct_ioc.len = io->i_cc; 16841488Smckusick } 16941488Smckusick else if (func == MTFSF) { 17041488Smckusick ct_ioc.cmd = C_READ; 17141488Smckusick ct_ioc.addr = rs->sc_blkno; 17241488Smckusick ct_ioc.len = io->i_cc = MAXBSIZE; 17341488Smckusick io->i_ma = io->i_buf; 17441488Smckusick } 17541488Smckusick else { 17641488Smckusick ct_ioc.cmd = C_READ; 17741488Smckusick ct_ioc.addr = 0; 17841488Smckusick ct_ioc.len = 0; 17941488Smckusick rs->sc_blkno = 0; 18041488Smckusick io->i_cc = 0; 18141488Smckusick } 18241488Smckusick retry: 18341488Smckusick hpibsend(unit, C_CMD, &ct_ioc, sizeof(ct_ioc)); 18441488Smckusick if (func != MTREW) { 18541488Smckusick hpibswait(unit); 18641488Smckusick hpibgo(unit, C_EXEC, io->i_ma, io->i_cc, 187*49154Sbostic func != F_WRITE ? F_READ : F_WRITE); 18841488Smckusick hpibswait(unit); 18941488Smckusick } 19041488Smckusick else { 19141488Smckusick while (hpibswait(unit) < 0) 19241488Smckusick ; 19341488Smckusick } 19441488Smckusick hpibrecv(unit, C_QSTAT, &stat, 1); 19541488Smckusick if (stat) { 19641488Smckusick stat = cterror(unit); 19741488Smckusick if (stat == 0) 19841488Smckusick return (-1); 19941488Smckusick if (stat == 2) 20041488Smckusick return (0); 20141488Smckusick if (++rs->sc_retry > CTRETRY) 20241488Smckusick return (-1); 20341488Smckusick else 20441488Smckusick goto retry; 20541488Smckusick } 20641488Smckusick rs->sc_blkno += CTBTOK(io->i_cc); 20741488Smckusick if (func == MTFSF) 20841488Smckusick goto top; 20941488Smckusick return (io->i_cc); 21041488Smckusick } 21141488Smckusick 21241488Smckusick cterror(unit) 21341488Smckusick register int unit; 21441488Smckusick { 21541488Smckusick register struct ct_softc *ct = &ct_softc[unit]; 21641488Smckusick char stat; 21741488Smckusick 21841488Smckusick ct_rsc.unit = C_SUNIT(ct->sc_punit); 21941488Smckusick ct_rsc.cmd = C_STATUS; 22041488Smckusick hpibsend(unit, C_CMD, &ct_rsc, sizeof(ct_rsc)); 22141488Smckusick hpibrecv(unit, C_EXEC, &ct_stat, sizeof(ct_stat)); 22241488Smckusick hpibrecv(unit, C_QSTAT, &stat, 1); 22341488Smckusick if (stat) { 22441488Smckusick printf("ct%d: request status fail %d\n", unit, stat); 22541488Smckusick return(0); 22641488Smckusick } 22741488Smckusick if (ct_stat.c_aef & AEF_EOF) { 22841488Smckusick /* 9145 drives don't increment block number at EOF */ 22941488Smckusick if ((ct_stat.c_blk - ct->sc_blkno) == 0) 23041488Smckusick ct->sc_blkno++; 23141488Smckusick else 23241488Smckusick ct->sc_blkno = ct_stat.c_blk; 23341488Smckusick return (2); 23441488Smckusick } 23541488Smckusick printf("ct%d err: vu 0x%x, pend 0x%x, bn%d", unit, 23641488Smckusick ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk); 23741488Smckusick printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref, 23841488Smckusick ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief); 23941488Smckusick return (1); 24041488Smckusick } 241