141488Smckusick /* 241488Smckusick * Copyright (c) 1988 University of Utah. 341488Smckusick * Copyright (c) 1982, 1990 The Regents of the University of California. 441488Smckusick * All rights reserved. 541488Smckusick * 641488Smckusick * This code is derived from software contributed to Berkeley by 741488Smckusick * the Systems Programming Group of the University of Utah Computer 841488Smckusick * Science Department. 941488Smckusick * 1041488Smckusick * %sccs.include.redist.c% 1141488Smckusick * 1241488Smckusick * from: Utah $Hdr: rd.c 1.14 89/02/27$ 1341488Smckusick * 14*49156Sbostic * @(#)rd.c 7.3 (Berkeley) 05/05/91 1541488Smckusick */ 1641488Smckusick 1741488Smckusick /* 1841488Smckusick * CS80/SS80 disk driver 1941488Smckusick */ 20*49156Sbostic #include <sys/param.h> 2141488Smckusick #include "saio.h" 2241488Smckusick #include "samachdep.h" 2341488Smckusick 2445790Sbostic #include "../dev/rdreg.h" 2541488Smckusick 2641488Smckusick struct rd_iocmd rd_ioc; 2741488Smckusick struct rd_rscmd rd_rsc; 2841488Smckusick struct rd_stat rd_stat; 2941488Smckusick struct rd_ssmcmd rd_ssmc; 3041488Smckusick 3141488Smckusick struct rd_softc { 3241488Smckusick char sc_retry; 3341488Smckusick char sc_alive; 3441488Smckusick short sc_type; 3541488Smckusick } rd_softc[NRD]; 3641488Smckusick 3741488Smckusick #define RDRETRY 5 3841488Smckusick 3941488Smckusick int rdcyloff[][8] = { 4041488Smckusick { 1, 143, 0, 143, 0, 0, 323, 503, }, /* 7945A */ 4141488Smckusick { 1, 167, 0, 0, 0, 0, 0, 0, }, /* 9134D */ 4241488Smckusick { 0, 0, 0, 0, 0, 0, 0, 0, }, /* 9122S */ 4341488Smckusick { 0, 71, 0, 221, 292, 542, 221, 0, }, /* 7912P */ 4441488Smckusick { 1, 72, 0, 72, 362, 802, 252, 362, }, /* 7914P */ 4541488Smckusick { 1, 28, 0, 140, 167, 444, 140, 721, }, /* 7933H */ 4641488Smckusick { 1, 200, 0, 200, 0, 0, 450, 600, }, /* 9134L */ 4741488Smckusick { 1, 105, 0, 105, 380, 736, 265, 380, }, /* 7957A */ 4841488Smckusick { 1, 65, 0, 65, 257, 657, 193, 257, }, /* 7958A */ 4941488Smckusick { 1, 128, 0, 128, 518, 918, 388, 518, }, /* 7957B */ 5041488Smckusick { 1, 44, 0, 44, 174, 496, 131, 174, }, /* 7958B */ 5141488Smckusick { 1, 44, 0, 44, 218, 918, 174, 218, }, /* 7959B */ 5241488Smckusick { 1, 20, 0, 98, 117, 256, 98, 397, }, /* 7936H */ 5341488Smckusick { 1, 11, 0, 53, 63, 217, 53, 371, }, /* 7937H */ 5441488Smckusick }; 5541488Smckusick 5641488Smckusick struct rdinfo { 5741488Smckusick int nbpc; 5841488Smckusick int hwid; 5941488Smckusick int *cyloff; 6041488Smckusick } rdinfo[] = { 6141488Smckusick NRD7945ABPT*NRD7945ATRK, RD7946AID, rdcyloff[0], 6241488Smckusick NRD9134DBPT*NRD9134DTRK, RD9134DID, rdcyloff[1], 6341488Smckusick NRD9122SBPT*NRD9122STRK, RD9134LID, rdcyloff[2], 6441488Smckusick NRD7912PBPT*NRD7912PTRK, RD7912PID, rdcyloff[3], 6541488Smckusick NRD7914PBPT*NRD7914PTRK, RD7914PID, rdcyloff[4], 6641488Smckusick NRD7958ABPT*NRD7958ATRK, RD7958AID, rdcyloff[8], 6741488Smckusick NRD7957ABPT*NRD7957ATRK, RD7957AID, rdcyloff[7], 6841488Smckusick NRD7933HBPT*NRD7933HTRK, RD7933HID, rdcyloff[5], 6941488Smckusick NRD9134LBPT*NRD9134LTRK, RD9134LID, rdcyloff[6], 7041488Smckusick NRD7936HBPT*NRD7936HTRK, RD7936HID, rdcyloff[12], 7141488Smckusick NRD7937HBPT*NRD7937HTRK, RD7937HID, rdcyloff[13], 7241488Smckusick NRD7914PBPT*NRD7914PTRK, RD7914CTID,rdcyloff[4], 7341488Smckusick NRD7945ABPT*NRD7945ATRK, RD7946AID, rdcyloff[0], 7441488Smckusick NRD9122SBPT*NRD9122STRK, RD9134LID, rdcyloff[2], 7541488Smckusick NRD7957BBPT*NRD7957BTRK, RD7957BID, rdcyloff[9], 7641488Smckusick NRD7958BBPT*NRD7958BTRK, RD7958BID, rdcyloff[10], 7741488Smckusick NRD7959BBPT*NRD7959BTRK, RD7959BID, rdcyloff[11], 7841488Smckusick }; 7941488Smckusick int nrdinfo = sizeof(rdinfo) / sizeof(rdinfo[0]); 8041488Smckusick 8141488Smckusick rdinit(unit) 8241488Smckusick register int unit; 8341488Smckusick { 8441488Smckusick register struct rd_softc *rs; 8541488Smckusick u_char stat; 8641488Smckusick 8741488Smckusick if (unit > NRD) 8841488Smckusick return (0); 8941488Smckusick rs = &rd_softc[unit]; 9041488Smckusick rs->sc_type = rdident(unit); 9141488Smckusick if (rs->sc_type < 0) 9241488Smckusick return (0); 9341488Smckusick rs->sc_alive = 1; 9441488Smckusick return (1); 9541488Smckusick } 9641488Smckusick 9741488Smckusick rdreset(unit) 9841488Smckusick { 9941488Smckusick u_char stat; 10041488Smckusick 10141488Smckusick rd_ssmc.c_unit = C_SUNIT(0); 10241488Smckusick rd_ssmc.c_cmd = C_SSM; 10341488Smckusick rd_ssmc.c_refm = REF_MASK; 10441488Smckusick rd_ssmc.c_fefm = FEF_MASK; 10541488Smckusick rd_ssmc.c_aefm = AEF_MASK; 10641488Smckusick rd_ssmc.c_iefm = IEF_MASK; 10741488Smckusick hpibsend(unit, C_CMD, &rd_ssmc, sizeof(rd_ssmc)); 10841488Smckusick hpibswait(unit); 10941488Smckusick hpibrecv(unit, C_QSTAT, &stat, 1); 11041488Smckusick } 11141488Smckusick 11241488Smckusick rdident(unit) 11341488Smckusick { 11441488Smckusick struct rd_describe desc; 11541488Smckusick u_char stat, cmd[3]; 11641488Smckusick char name[7]; 11741488Smckusick register int id, i; 11841488Smckusick 11941488Smckusick id = hpibid(unit); 12041488Smckusick if ((id & 0x200) == 0) 12141488Smckusick return(-1); 12241488Smckusick for (i = 0; i < nrdinfo; i++) 12341488Smckusick if (id == rdinfo[i].hwid) 12441488Smckusick break; 12541488Smckusick if (i == nrdinfo) 12641488Smckusick return(-1); 12741488Smckusick id = i; 12841488Smckusick rdreset(unit); 12941488Smckusick cmd[0] = C_SUNIT(0); 13041488Smckusick cmd[1] = C_SVOL(0); 13141488Smckusick cmd[2] = C_DESC; 13241488Smckusick hpibsend(unit, C_CMD, cmd, sizeof(cmd)); 13341488Smckusick hpibrecv(unit, C_EXEC, &desc, 37); 13441488Smckusick hpibrecv(unit, C_QSTAT, &stat, sizeof(stat)); 13541488Smckusick bzero(name, sizeof(name)); 13641488Smckusick if (!stat) { 13741488Smckusick register int n = desc.d_name; 13841488Smckusick for (i = 5; i >= 0; i--) { 13941488Smckusick name[i] = (n & 0xf) + '0'; 14041488Smckusick n >>= 4; 14141488Smckusick } 14241488Smckusick } 14341488Smckusick /* 14441488Smckusick * Take care of a couple of anomolies: 14541488Smckusick * 1. 7945A and 7946A both return same HW id 14641488Smckusick * 2. 9122S and 9134D both return same HW id 14741488Smckusick * 3. 9122D and 9134L both return same HW id 14841488Smckusick */ 14941488Smckusick switch (rdinfo[id].hwid) { 15041488Smckusick case RD7946AID: 15141488Smckusick if (bcmp(name, "079450", 6) == 0) 15241488Smckusick id = RD7945A; 15341488Smckusick else 15441488Smckusick id = RD7946A; 15541488Smckusick break; 15641488Smckusick 15741488Smckusick case RD9134LID: 15841488Smckusick if (bcmp(name, "091340", 6) == 0) 15941488Smckusick id = RD9134L; 16041488Smckusick else 16141488Smckusick id = RD9122D; 16241488Smckusick break; 16341488Smckusick 16441488Smckusick case RD9134DID: 16541488Smckusick if (bcmp(name, "091220", 6) == 0) 16641488Smckusick id = RD9122S; 16741488Smckusick else 16841488Smckusick id = RD9134D; 16941488Smckusick break; 17041488Smckusick } 17141488Smckusick return(id); 17241488Smckusick } 17341488Smckusick 17441488Smckusick rdopen(io) 17541488Smckusick struct iob *io; 17641488Smckusick { 17741488Smckusick register int unit = io->i_unit; 17841488Smckusick register struct rd_softc *rs = &rd_softc[unit]; 17941488Smckusick struct rdinfo *ri; 18041488Smckusick 18141488Smckusick if (hpibalive(unit) == 0) 18241488Smckusick _stop("rd controller not configured"); 18341488Smckusick if (rs->sc_alive == 0) 18441488Smckusick if (rdinit(unit) == 0) 18541488Smckusick _stop("rd init failed"); 18641488Smckusick if (io->i_boff < 0 || io->i_boff > 7) 18741488Smckusick _stop("rd bad minor"); 18841488Smckusick ri = &rdinfo[rs->sc_type]; 18941488Smckusick io->i_boff = ri->cyloff[io->i_boff] * ri->nbpc; 19041488Smckusick } 19141488Smckusick 19241488Smckusick rdstrategy(io, func) 19341488Smckusick register struct iob *io; 19441488Smckusick register int func; 19541488Smckusick { 19641488Smckusick register int unit = io->i_unit; 19741488Smckusick register struct rd_softc *rs = &rd_softc[unit]; 19841488Smckusick char stat; 19941488Smckusick 20041488Smckusick rs->sc_retry = 0; 20141488Smckusick rd_ioc.c_unit = C_SUNIT(0); 20241488Smckusick rd_ioc.c_volume = C_SVOL(0); 20341488Smckusick rd_ioc.c_saddr = C_SADDR; 20441488Smckusick rd_ioc.c_hiaddr = 0; 20541488Smckusick rd_ioc.c_addr = RDBTOS(io->i_bn); 20641488Smckusick rd_ioc.c_nop2 = C_NOP; 20741488Smckusick rd_ioc.c_slen = C_SLEN; 20841488Smckusick rd_ioc.c_len = io->i_cc; 209*49156Sbostic rd_ioc.c_cmd = func == F_READ ? C_READ : C_WRITE; 21041488Smckusick retry: 21141488Smckusick hpibsend(unit, C_CMD, &rd_ioc.c_unit, sizeof(rd_ioc)-2); 21241488Smckusick hpibswait(unit); 21341488Smckusick hpibgo(unit, C_EXEC, io->i_ma, io->i_cc, func); 21441488Smckusick hpibswait(unit); 21541488Smckusick hpibrecv(unit, C_QSTAT, &stat, 1); 21641488Smckusick if (stat) { 21741488Smckusick if (rderror(unit) == 0) 21841488Smckusick return(-1); 21941488Smckusick if (++rs->sc_retry > RDRETRY) 22041488Smckusick return(-1); 22141488Smckusick else 22241488Smckusick goto retry; 22341488Smckusick } 22441488Smckusick return(io->i_cc); 22541488Smckusick } 22641488Smckusick 22741488Smckusick rderror(unit) 22841488Smckusick register int unit; 22941488Smckusick { 23041488Smckusick register struct rd_softc *rd = &rd_softc[unit]; 23141488Smckusick char stat; 23241488Smckusick 23341488Smckusick rd_rsc.c_unit = C_SUNIT(0); 23441488Smckusick rd_rsc.c_sram = C_SRAM; 23541488Smckusick rd_rsc.c_ram = C_RAM; 23641488Smckusick rd_rsc.c_cmd = C_STATUS; 23741488Smckusick hpibsend(unit, C_CMD, &rd_rsc, sizeof(rd_rsc)); 23841488Smckusick hpibrecv(unit, C_EXEC, &rd_stat, sizeof(rd_stat)); 23941488Smckusick hpibrecv(unit, C_QSTAT, &stat, 1); 24041488Smckusick if (stat) { 24141488Smckusick printf("rd(%d,?): request status fail %d\n", unit, stat); 24241488Smckusick return(0); 24341488Smckusick } 24441488Smckusick printf("rd(%d,?) err: vu 0x%x", unit, rd_stat.c_vu); 24541488Smckusick if ((rd_stat.c_aef & AEF_UD) || (rd_stat.c_ief & (IEF_MD|IEF_RD))) 24641488Smckusick printf(", block %d", rd_stat.c_blk); 24741488Smckusick printf(", R0x%x F0x%x A0x%x I0x%x\n", 24841488Smckusick rd_stat.c_ref, rd_stat.c_fef, rd_stat.c_aef, rd_stat.c_ief); 24941488Smckusick return(1); 25041488Smckusick } 251