1*41488Smckusick /* 2*41488Smckusick * Copyright (c) 1988 University of Utah. 3*41488Smckusick * Copyright (c) 1982, 1990 The Regents of the University of California. 4*41488Smckusick * All rights reserved. 5*41488Smckusick * 6*41488Smckusick * This code is derived from software contributed to Berkeley by 7*41488Smckusick * the Systems Programming Group of the University of Utah Computer 8*41488Smckusick * Science Department. 9*41488Smckusick * 10*41488Smckusick * %sccs.include.redist.c% 11*41488Smckusick * 12*41488Smckusick * from: Utah $Hdr: rd.c 1.14 89/02/27$ 13*41488Smckusick * 14*41488Smckusick * @(#)rd.c 7.1 (Berkeley) 05/08/90 15*41488Smckusick */ 16*41488Smckusick 17*41488Smckusick /* 18*41488Smckusick * CS80/SS80 disk driver 19*41488Smckusick */ 20*41488Smckusick #include "saio.h" 21*41488Smckusick #include "samachdep.h" 22*41488Smckusick 23*41488Smckusick #include "../hpdev/rdreg.h" 24*41488Smckusick 25*41488Smckusick struct rd_iocmd rd_ioc; 26*41488Smckusick struct rd_rscmd rd_rsc; 27*41488Smckusick struct rd_stat rd_stat; 28*41488Smckusick struct rd_ssmcmd rd_ssmc; 29*41488Smckusick 30*41488Smckusick struct rd_softc { 31*41488Smckusick char sc_retry; 32*41488Smckusick char sc_alive; 33*41488Smckusick short sc_type; 34*41488Smckusick } rd_softc[NRD]; 35*41488Smckusick 36*41488Smckusick #define RDRETRY 5 37*41488Smckusick 38*41488Smckusick int rdcyloff[][8] = { 39*41488Smckusick { 1, 143, 0, 143, 0, 0, 323, 503, }, /* 7945A */ 40*41488Smckusick { 1, 167, 0, 0, 0, 0, 0, 0, }, /* 9134D */ 41*41488Smckusick { 0, 0, 0, 0, 0, 0, 0, 0, }, /* 9122S */ 42*41488Smckusick { 0, 71, 0, 221, 292, 542, 221, 0, }, /* 7912P */ 43*41488Smckusick { 1, 72, 0, 72, 362, 802, 252, 362, }, /* 7914P */ 44*41488Smckusick { 1, 28, 0, 140, 167, 444, 140, 721, }, /* 7933H */ 45*41488Smckusick { 1, 200, 0, 200, 0, 0, 450, 600, }, /* 9134L */ 46*41488Smckusick { 1, 105, 0, 105, 380, 736, 265, 380, }, /* 7957A */ 47*41488Smckusick { 1, 65, 0, 65, 257, 657, 193, 257, }, /* 7958A */ 48*41488Smckusick { 1, 128, 0, 128, 518, 918, 388, 518, }, /* 7957B */ 49*41488Smckusick { 1, 44, 0, 44, 174, 496, 131, 174, }, /* 7958B */ 50*41488Smckusick { 1, 44, 0, 44, 218, 918, 174, 218, }, /* 7959B */ 51*41488Smckusick { 1, 20, 0, 98, 117, 256, 98, 397, }, /* 7936H */ 52*41488Smckusick { 1, 11, 0, 53, 63, 217, 53, 371, }, /* 7937H */ 53*41488Smckusick }; 54*41488Smckusick 55*41488Smckusick struct rdinfo { 56*41488Smckusick int nbpc; 57*41488Smckusick int hwid; 58*41488Smckusick int *cyloff; 59*41488Smckusick } rdinfo[] = { 60*41488Smckusick NRD7945ABPT*NRD7945ATRK, RD7946AID, rdcyloff[0], 61*41488Smckusick NRD9134DBPT*NRD9134DTRK, RD9134DID, rdcyloff[1], 62*41488Smckusick NRD9122SBPT*NRD9122STRK, RD9134LID, rdcyloff[2], 63*41488Smckusick NRD7912PBPT*NRD7912PTRK, RD7912PID, rdcyloff[3], 64*41488Smckusick NRD7914PBPT*NRD7914PTRK, RD7914PID, rdcyloff[4], 65*41488Smckusick NRD7958ABPT*NRD7958ATRK, RD7958AID, rdcyloff[8], 66*41488Smckusick NRD7957ABPT*NRD7957ATRK, RD7957AID, rdcyloff[7], 67*41488Smckusick NRD7933HBPT*NRD7933HTRK, RD7933HID, rdcyloff[5], 68*41488Smckusick NRD9134LBPT*NRD9134LTRK, RD9134LID, rdcyloff[6], 69*41488Smckusick NRD7936HBPT*NRD7936HTRK, RD7936HID, rdcyloff[12], 70*41488Smckusick NRD7937HBPT*NRD7937HTRK, RD7937HID, rdcyloff[13], 71*41488Smckusick NRD7914PBPT*NRD7914PTRK, RD7914CTID,rdcyloff[4], 72*41488Smckusick NRD7945ABPT*NRD7945ATRK, RD7946AID, rdcyloff[0], 73*41488Smckusick NRD9122SBPT*NRD9122STRK, RD9134LID, rdcyloff[2], 74*41488Smckusick NRD7957BBPT*NRD7957BTRK, RD7957BID, rdcyloff[9], 75*41488Smckusick NRD7958BBPT*NRD7958BTRK, RD7958BID, rdcyloff[10], 76*41488Smckusick NRD7959BBPT*NRD7959BTRK, RD7959BID, rdcyloff[11], 77*41488Smckusick }; 78*41488Smckusick int nrdinfo = sizeof(rdinfo) / sizeof(rdinfo[0]); 79*41488Smckusick 80*41488Smckusick rdinit(unit) 81*41488Smckusick register int unit; 82*41488Smckusick { 83*41488Smckusick register struct rd_softc *rs; 84*41488Smckusick u_char stat; 85*41488Smckusick 86*41488Smckusick if (unit > NRD) 87*41488Smckusick return (0); 88*41488Smckusick rs = &rd_softc[unit]; 89*41488Smckusick rs->sc_type = rdident(unit); 90*41488Smckusick if (rs->sc_type < 0) 91*41488Smckusick return (0); 92*41488Smckusick rs->sc_alive = 1; 93*41488Smckusick return (1); 94*41488Smckusick } 95*41488Smckusick 96*41488Smckusick rdreset(unit) 97*41488Smckusick { 98*41488Smckusick u_char stat; 99*41488Smckusick 100*41488Smckusick rd_ssmc.c_unit = C_SUNIT(0); 101*41488Smckusick rd_ssmc.c_cmd = C_SSM; 102*41488Smckusick rd_ssmc.c_refm = REF_MASK; 103*41488Smckusick rd_ssmc.c_fefm = FEF_MASK; 104*41488Smckusick rd_ssmc.c_aefm = AEF_MASK; 105*41488Smckusick rd_ssmc.c_iefm = IEF_MASK; 106*41488Smckusick hpibsend(unit, C_CMD, &rd_ssmc, sizeof(rd_ssmc)); 107*41488Smckusick hpibswait(unit); 108*41488Smckusick hpibrecv(unit, C_QSTAT, &stat, 1); 109*41488Smckusick } 110*41488Smckusick 111*41488Smckusick rdident(unit) 112*41488Smckusick { 113*41488Smckusick struct rd_describe desc; 114*41488Smckusick u_char stat, cmd[3]; 115*41488Smckusick char name[7]; 116*41488Smckusick register int id, i; 117*41488Smckusick 118*41488Smckusick id = hpibid(unit); 119*41488Smckusick if ((id & 0x200) == 0) 120*41488Smckusick return(-1); 121*41488Smckusick for (i = 0; i < nrdinfo; i++) 122*41488Smckusick if (id == rdinfo[i].hwid) 123*41488Smckusick break; 124*41488Smckusick if (i == nrdinfo) 125*41488Smckusick return(-1); 126*41488Smckusick id = i; 127*41488Smckusick rdreset(unit); 128*41488Smckusick cmd[0] = C_SUNIT(0); 129*41488Smckusick cmd[1] = C_SVOL(0); 130*41488Smckusick cmd[2] = C_DESC; 131*41488Smckusick hpibsend(unit, C_CMD, cmd, sizeof(cmd)); 132*41488Smckusick hpibrecv(unit, C_EXEC, &desc, 37); 133*41488Smckusick hpibrecv(unit, C_QSTAT, &stat, sizeof(stat)); 134*41488Smckusick bzero(name, sizeof(name)); 135*41488Smckusick if (!stat) { 136*41488Smckusick register int n = desc.d_name; 137*41488Smckusick for (i = 5; i >= 0; i--) { 138*41488Smckusick name[i] = (n & 0xf) + '0'; 139*41488Smckusick n >>= 4; 140*41488Smckusick } 141*41488Smckusick } 142*41488Smckusick /* 143*41488Smckusick * Take care of a couple of anomolies: 144*41488Smckusick * 1. 7945A and 7946A both return same HW id 145*41488Smckusick * 2. 9122S and 9134D both return same HW id 146*41488Smckusick * 3. 9122D and 9134L both return same HW id 147*41488Smckusick */ 148*41488Smckusick switch (rdinfo[id].hwid) { 149*41488Smckusick case RD7946AID: 150*41488Smckusick if (bcmp(name, "079450", 6) == 0) 151*41488Smckusick id = RD7945A; 152*41488Smckusick else 153*41488Smckusick id = RD7946A; 154*41488Smckusick break; 155*41488Smckusick 156*41488Smckusick case RD9134LID: 157*41488Smckusick if (bcmp(name, "091340", 6) == 0) 158*41488Smckusick id = RD9134L; 159*41488Smckusick else 160*41488Smckusick id = RD9122D; 161*41488Smckusick break; 162*41488Smckusick 163*41488Smckusick case RD9134DID: 164*41488Smckusick if (bcmp(name, "091220", 6) == 0) 165*41488Smckusick id = RD9122S; 166*41488Smckusick else 167*41488Smckusick id = RD9134D; 168*41488Smckusick break; 169*41488Smckusick } 170*41488Smckusick return(id); 171*41488Smckusick } 172*41488Smckusick 173*41488Smckusick rdopen(io) 174*41488Smckusick struct iob *io; 175*41488Smckusick { 176*41488Smckusick register int unit = io->i_unit; 177*41488Smckusick register struct rd_softc *rs = &rd_softc[unit]; 178*41488Smckusick struct rdinfo *ri; 179*41488Smckusick 180*41488Smckusick if (hpibalive(unit) == 0) 181*41488Smckusick _stop("rd controller not configured"); 182*41488Smckusick if (rs->sc_alive == 0) 183*41488Smckusick if (rdinit(unit) == 0) 184*41488Smckusick _stop("rd init failed"); 185*41488Smckusick if (io->i_boff < 0 || io->i_boff > 7) 186*41488Smckusick _stop("rd bad minor"); 187*41488Smckusick ri = &rdinfo[rs->sc_type]; 188*41488Smckusick io->i_boff = ri->cyloff[io->i_boff] * ri->nbpc; 189*41488Smckusick } 190*41488Smckusick 191*41488Smckusick rdstrategy(io, func) 192*41488Smckusick register struct iob *io; 193*41488Smckusick register int func; 194*41488Smckusick { 195*41488Smckusick register int unit = io->i_unit; 196*41488Smckusick register struct rd_softc *rs = &rd_softc[unit]; 197*41488Smckusick char stat; 198*41488Smckusick 199*41488Smckusick rs->sc_retry = 0; 200*41488Smckusick rd_ioc.c_unit = C_SUNIT(0); 201*41488Smckusick rd_ioc.c_volume = C_SVOL(0); 202*41488Smckusick rd_ioc.c_saddr = C_SADDR; 203*41488Smckusick rd_ioc.c_hiaddr = 0; 204*41488Smckusick rd_ioc.c_addr = RDBTOS(io->i_bn); 205*41488Smckusick rd_ioc.c_nop2 = C_NOP; 206*41488Smckusick rd_ioc.c_slen = C_SLEN; 207*41488Smckusick rd_ioc.c_len = io->i_cc; 208*41488Smckusick rd_ioc.c_cmd = func == READ ? C_READ : C_WRITE; 209*41488Smckusick retry: 210*41488Smckusick hpibsend(unit, C_CMD, &rd_ioc.c_unit, sizeof(rd_ioc)-2); 211*41488Smckusick hpibswait(unit); 212*41488Smckusick hpibgo(unit, C_EXEC, io->i_ma, io->i_cc, func); 213*41488Smckusick hpibswait(unit); 214*41488Smckusick hpibrecv(unit, C_QSTAT, &stat, 1); 215*41488Smckusick if (stat) { 216*41488Smckusick if (rderror(unit) == 0) 217*41488Smckusick return(-1); 218*41488Smckusick if (++rs->sc_retry > RDRETRY) 219*41488Smckusick return(-1); 220*41488Smckusick else 221*41488Smckusick goto retry; 222*41488Smckusick } 223*41488Smckusick return(io->i_cc); 224*41488Smckusick } 225*41488Smckusick 226*41488Smckusick rderror(unit) 227*41488Smckusick register int unit; 228*41488Smckusick { 229*41488Smckusick register struct rd_softc *rd = &rd_softc[unit]; 230*41488Smckusick char stat; 231*41488Smckusick 232*41488Smckusick rd_rsc.c_unit = C_SUNIT(0); 233*41488Smckusick rd_rsc.c_sram = C_SRAM; 234*41488Smckusick rd_rsc.c_ram = C_RAM; 235*41488Smckusick rd_rsc.c_cmd = C_STATUS; 236*41488Smckusick hpibsend(unit, C_CMD, &rd_rsc, sizeof(rd_rsc)); 237*41488Smckusick hpibrecv(unit, C_EXEC, &rd_stat, sizeof(rd_stat)); 238*41488Smckusick hpibrecv(unit, C_QSTAT, &stat, 1); 239*41488Smckusick if (stat) { 240*41488Smckusick printf("rd(%d,?): request status fail %d\n", unit, stat); 241*41488Smckusick return(0); 242*41488Smckusick } 243*41488Smckusick printf("rd(%d,?) err: vu 0x%x", unit, rd_stat.c_vu); 244*41488Smckusick if ((rd_stat.c_aef & AEF_UD) || (rd_stat.c_ief & (IEF_MD|IEF_RD))) 245*41488Smckusick printf(", block %d", rd_stat.c_blk); 246*41488Smckusick printf(", R0x%x F0x%x A0x%x I0x%x\n", 247*41488Smckusick rd_stat.c_ref, rd_stat.c_fef, rd_stat.c_aef, rd_stat.c_ief); 248*41488Smckusick return(1); 249*41488Smckusick } 250