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*56510Sbostic * @(#)ct.c 7.6 (Berkeley) 10/11/92 841488Smckusick */ 941488Smckusick 1041488Smckusick /* 1141488Smckusick * CS80 tape driver 1241488Smckusick */ 13*56510Sbostic #include <sys/param.h> 1441488Smckusick 15*56510Sbostic #include <hp300/dev/ctreg.h> 1641488Smckusick 17*56510Sbostic #include <stand/saio.h> 18*56510Sbostic #include <hp300/stand/samachdep.h> 19*56510Sbostic 2041488Smckusick struct ct_iocmd ct_ioc; 2141488Smckusick struct ct_rscmd ct_rsc; 2241488Smckusick struct ct_stat ct_stat; 2341488Smckusick struct ct_ssmcmd ct_ssmc; 2441488Smckusick 2541488Smckusick struct ct_softc { 2641488Smckusick char sc_retry; 2741488Smckusick char sc_alive; 2841488Smckusick short sc_punit; 2941488Smckusick int sc_blkno; 3054073Shibler } ct_softc[NHPIB][NCT]; 3141488Smckusick 3241488Smckusick #define CTRETRY 5 3341488Smckusick #define MTFSF 10 3441488Smckusick #define MTREW 11 3541488Smckusick 3641488Smckusick struct ctinfo { 3741488Smckusick short hwid; 3841488Smckusick short punit; 3941488Smckusick } ctinfo[] = { 4041488Smckusick CT7946ID, 1, 4141488Smckusick CT7912PID, 1, 4241488Smckusick CT7914PID, 1, 4341488Smckusick CT9144ID, 0, 4441488Smckusick CT9145ID, 0, 4541488Smckusick }; 4641488Smckusick int nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]); 4741488Smckusick 4854073Shibler ctinit(ctlr, unit) 4954073Shibler register int ctlr, unit; 5041488Smckusick { 5154073Shibler register struct ct_softc *rs = &ct_softc[ctlr][unit]; 5241488Smckusick u_char stat; 5341488Smckusick register int type; 5441488Smckusick 5554073Shibler if (hpibrecv(ctlr, unit, C_QSTAT, &stat, 1) != 1 || stat) 5641488Smckusick return (0); 5754073Shibler if (ctident(ctlr, unit) < 0) 5841488Smckusick return (0); 5941488Smckusick ct_ssmc.unit = C_SUNIT(rs->sc_punit); 6041488Smckusick ct_ssmc.cmd = C_SSM; 6141488Smckusick ct_ssmc.fefm = FEF_MASK; 6241488Smckusick ct_ssmc.refm = REF_MASK; 6341488Smckusick ct_ssmc.aefm = AEF_MASK; 6441488Smckusick ct_ssmc.iefm = IEF_MASK; 6554073Shibler hpibsend(ctlr, unit, C_CMD, &ct_ssmc, sizeof(ct_ssmc)); 6654073Shibler hpibswait(ctlr, unit); 6754073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 6841488Smckusick rs->sc_alive = 1; 6941488Smckusick return (1); 7041488Smckusick } 7141488Smckusick 7254073Shibler ctident(ctlr, unit) 7354073Shibler int ctlr, unit; 7441488Smckusick { 7541488Smckusick struct ct_describe desc; 7641488Smckusick u_char stat, cmd[3]; 7741488Smckusick char name[7]; 7841488Smckusick int id, i; 7941488Smckusick 8054073Shibler id = hpibid(ctlr, unit); 8141488Smckusick if ((id & 0x200) == 0) 8241488Smckusick return(-1); 8341488Smckusick for (i = 0; i < nctinfo; i++) 8441488Smckusick if (id == ctinfo[i].hwid) 8541488Smckusick break; 8641488Smckusick if (i == nctinfo) 8741488Smckusick return(-1); 8854073Shibler ct_softc[ctlr][unit].sc_punit = ctinfo[i].punit; 8941488Smckusick id = i; 9041488Smckusick 9141488Smckusick /* 9241488Smckusick * Collect device description. 9341488Smckusick * Right now we only need this to differentiate 7945 from 7946. 9441488Smckusick * Note that we always issue the describe command to unit 0. 9541488Smckusick */ 9641488Smckusick cmd[0] = C_SUNIT(0); 9741488Smckusick cmd[1] = C_SVOL(0); 9841488Smckusick cmd[2] = C_DESC; 9954073Shibler hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd)); 10054073Shibler hpibrecv(ctlr, unit, C_EXEC, &desc, 37); 10154073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat)); 10241488Smckusick bzero(name, sizeof(name)); 10341488Smckusick if (!stat) { 10441488Smckusick register int n = desc.d_name; 10541488Smckusick for (i = 5; i >= 0; i--) { 10641488Smckusick name[i] = (n & 0xf) + '0'; 10741488Smckusick n >>= 4; 10841488Smckusick } 10941488Smckusick } 11041488Smckusick switch (ctinfo[id].hwid) { 11141488Smckusick case CT7946ID: 11241488Smckusick if (bcmp(name, "079450", 6) == 0) 11341488Smckusick id = -1; /* not really a 7946 */ 11441488Smckusick break; 11541488Smckusick default: 11641488Smckusick break; 11741488Smckusick } 11841488Smckusick return(id); 11941488Smckusick } 12041488Smckusick 12141488Smckusick ctopen(io) 12241488Smckusick struct iob *io; 12341488Smckusick { 12454073Shibler register struct ct_softc *rs; 12554073Shibler register int unit, ctlr; 12641488Smckusick register int skip; 12741488Smckusick 12854073Shibler devconvert(io); 12954073Shibler 13054073Shibler ctlr = io->i_adapt; 13154073Shibler if (ctlr >= NHPIB || hpibalive(ctlr) == 0) 13254073Shibler return(EADAPT); 13354073Shibler unit = io->i_ctlr; 13454073Shibler if (unit >= NCT) 13554073Shibler return(ECTLR); 13641488Smckusick if (rs->sc_alive == 0) 13754073Shibler if (ctinit(ctlr, unit) == 0) 13854073Shibler return(ENXIO); 13941488Smckusick ctstrategy(io, MTREW); 14054073Shibler skip = io->i_part; 14141488Smckusick while (skip--) 14241488Smckusick ctstrategy(io, MTFSF); 14355897Shibler return(0); 14441488Smckusick } 14541488Smckusick 14641488Smckusick ctclose(io) 14741488Smckusick struct iob *io; 14841488Smckusick { 14941488Smckusick ctstrategy(io, MTREW); 15041488Smckusick } 15141488Smckusick 15241488Smckusick ctstrategy(io, func) 15341488Smckusick register struct iob *io; 15441488Smckusick register int func; 15541488Smckusick { 15654073Shibler register int ctlr = io->i_adapt; 15754073Shibler register int unit = io->i_ctlr; 15854073Shibler register struct ct_softc *rs = &ct_softc[ctlr][unit]; 15941488Smckusick char stat; 16041488Smckusick 16155897Shibler if (io->i_cc == 0 && (func == F_READ || func == F_WRITE)) 16255897Shibler return(0); 16355897Shibler 16441488Smckusick rs->sc_retry = 0; 16541488Smckusick ct_ioc.unit = C_SUNIT(rs->sc_punit); 16641488Smckusick ct_ioc.saddr = C_SADDR; 16741488Smckusick ct_ioc.nop2 = C_NOP; 16841488Smckusick ct_ioc.slen = C_SLEN; 16941488Smckusick ct_ioc.nop3 = C_NOP; 17041488Smckusick top: 17149154Sbostic if (func == F_READ) { 17241488Smckusick ct_ioc.cmd = C_READ; 17341488Smckusick ct_ioc.addr = rs->sc_blkno; 17441488Smckusick ct_ioc.len = io->i_cc; 17541488Smckusick } 17649154Sbostic else if (func == F_WRITE) { 17741488Smckusick ct_ioc.cmd = C_WRITE; 17841488Smckusick ct_ioc.addr = rs->sc_blkno; 17941488Smckusick ct_ioc.len = io->i_cc; 18041488Smckusick } 18141488Smckusick else if (func == MTFSF) { 18241488Smckusick ct_ioc.cmd = C_READ; 18341488Smckusick ct_ioc.addr = rs->sc_blkno; 18441488Smckusick ct_ioc.len = io->i_cc = MAXBSIZE; 18541488Smckusick io->i_ma = io->i_buf; 18641488Smckusick } 18741488Smckusick else { 18841488Smckusick ct_ioc.cmd = C_READ; 18941488Smckusick ct_ioc.addr = 0; 19041488Smckusick ct_ioc.len = 0; 19141488Smckusick rs->sc_blkno = 0; 19241488Smckusick io->i_cc = 0; 19341488Smckusick } 19441488Smckusick retry: 19554073Shibler hpibsend(ctlr, unit, C_CMD, &ct_ioc, sizeof(ct_ioc)); 19641488Smckusick if (func != MTREW) { 19754073Shibler hpibswait(ctlr, unit); 19854073Shibler hpibgo(ctlr, unit, C_EXEC, io->i_ma, io->i_cc, 19949154Sbostic func != F_WRITE ? F_READ : F_WRITE); 20054073Shibler hpibswait(ctlr, unit); 20154073Shibler } else { 20254073Shibler while (hpibswait(ctlr, unit) < 0) 20341488Smckusick ; 20441488Smckusick } 20554073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 20641488Smckusick if (stat) { 20754073Shibler stat = cterror(ctlr, unit); 20841488Smckusick if (stat == 0) 20941488Smckusick return (-1); 21041488Smckusick if (stat == 2) 21141488Smckusick return (0); 21241488Smckusick if (++rs->sc_retry > CTRETRY) 21341488Smckusick return (-1); 21454073Shibler goto retry; 21541488Smckusick } 21641488Smckusick rs->sc_blkno += CTBTOK(io->i_cc); 21741488Smckusick if (func == MTFSF) 21841488Smckusick goto top; 21941488Smckusick return (io->i_cc); 22041488Smckusick } 22141488Smckusick 22254073Shibler cterror(ctlr, unit) 22354073Shibler register int ctlr, unit; 22441488Smckusick { 22554073Shibler register struct ct_softc *rs = &ct_softc[ctlr][unit]; 22641488Smckusick char stat; 22741488Smckusick 22854073Shibler ct_rsc.unit = C_SUNIT(rs->sc_punit); 22941488Smckusick ct_rsc.cmd = C_STATUS; 23054073Shibler hpibsend(ctlr, unit, C_CMD, &ct_rsc, sizeof(ct_rsc)); 23154073Shibler hpibrecv(ctlr, unit, C_EXEC, &ct_stat, sizeof(ct_stat)); 23254073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 23341488Smckusick if (stat) { 23441488Smckusick printf("ct%d: request status fail %d\n", unit, stat); 23541488Smckusick return(0); 23641488Smckusick } 23741488Smckusick if (ct_stat.c_aef & AEF_EOF) { 23841488Smckusick /* 9145 drives don't increment block number at EOF */ 23954073Shibler if ((ct_stat.c_blk - rs->sc_blkno) == 0) 24054073Shibler rs->sc_blkno++; 24141488Smckusick else 24254073Shibler rs->sc_blkno = ct_stat.c_blk; 24341488Smckusick return (2); 24441488Smckusick } 24541488Smckusick printf("ct%d err: vu 0x%x, pend 0x%x, bn%d", unit, 24641488Smckusick ct_stat.c_vu, ct_stat.c_pend, ct_stat.c_blk); 24741488Smckusick printf(", R 0x%x F 0x%x A 0x%x I 0x%x\n", ct_stat.c_ref, 24841488Smckusick ct_stat.c_fef, ct_stat.c_aef, ct_stat.c_ief); 24941488Smckusick return (1); 25041488Smckusick } 251