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 * 1254073Shibler * from: Utah $Hdr: rd.c 1.17 92/06/18$ 1341488Smckusick * 14*55898Shibler * @(#)rd.c 7.5 (Berkeley) 08/14/92 1541488Smckusick */ 1641488Smckusick 1741488Smckusick /* 1841488Smckusick * CS80/SS80 disk driver 1941488Smckusick */ 2054073Shibler #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; 3554073Shibler } rd_softc[NHPIB][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 */ 5154073Shibler { 1, 44, 0, 44, 218, 1022,174, 218, }, /* 7959B */ 5254073Shibler { 1, 37, 0, 37, 183, 857, 147, 183, }, /* 2200A */ 5354073Shibler { 1, 19, 0, 94, 112, 450, 94, 788, }, /* 2203A */ 5441488Smckusick { 1, 20, 0, 98, 117, 256, 98, 397, }, /* 7936H */ 5541488Smckusick { 1, 11, 0, 53, 63, 217, 53, 371, }, /* 7937H */ 5641488Smckusick }; 5741488Smckusick 5841488Smckusick struct rdinfo { 5941488Smckusick int nbpc; 6041488Smckusick int hwid; 6141488Smckusick int *cyloff; 6241488Smckusick } rdinfo[] = { 6341488Smckusick NRD7945ABPT*NRD7945ATRK, RD7946AID, rdcyloff[0], 6441488Smckusick NRD9134DBPT*NRD9134DTRK, RD9134DID, rdcyloff[1], 6541488Smckusick NRD9122SBPT*NRD9122STRK, RD9134LID, rdcyloff[2], 6641488Smckusick NRD7912PBPT*NRD7912PTRK, RD7912PID, rdcyloff[3], 6741488Smckusick NRD7914PBPT*NRD7914PTRK, RD7914PID, rdcyloff[4], 6841488Smckusick NRD7958ABPT*NRD7958ATRK, RD7958AID, rdcyloff[8], 6941488Smckusick NRD7957ABPT*NRD7957ATRK, RD7957AID, rdcyloff[7], 7041488Smckusick NRD7933HBPT*NRD7933HTRK, RD7933HID, rdcyloff[5], 7141488Smckusick NRD9134LBPT*NRD9134LTRK, RD9134LID, rdcyloff[6], 7254073Shibler NRD7936HBPT*NRD7936HTRK, RD7936HID, rdcyloff[14], 7354073Shibler NRD7937HBPT*NRD7937HTRK, RD7937HID, rdcyloff[15], 7441488Smckusick NRD7914PBPT*NRD7914PTRK, RD7914CTID,rdcyloff[4], 7541488Smckusick NRD7945ABPT*NRD7945ATRK, RD7946AID, rdcyloff[0], 7641488Smckusick NRD9122SBPT*NRD9122STRK, RD9134LID, rdcyloff[2], 7741488Smckusick NRD7957BBPT*NRD7957BTRK, RD7957BID, rdcyloff[9], 7841488Smckusick NRD7958BBPT*NRD7958BTRK, RD7958BID, rdcyloff[10], 7941488Smckusick NRD7959BBPT*NRD7959BTRK, RD7959BID, rdcyloff[11], 8054073Shibler NRD2200ABPT*NRD2200ATRK, RD2200AID, rdcyloff[12], 8154073Shibler NRD2203ABPT*NRD2203ATRK, RD2203AID, rdcyloff[13], 8241488Smckusick }; 8341488Smckusick int nrdinfo = sizeof(rdinfo) / sizeof(rdinfo[0]); 8441488Smckusick 8554073Shibler rdinit(ctlr, unit) 8654073Shibler int ctlr, unit; 8741488Smckusick { 8854073Shibler register struct rd_softc *rs = &rd_softc[ctlr][unit]; 8941488Smckusick u_char stat; 9041488Smckusick 9154073Shibler rs->sc_type = rdident(ctlr, unit); 9241488Smckusick if (rs->sc_type < 0) 9341488Smckusick return (0); 9441488Smckusick rs->sc_alive = 1; 9541488Smckusick return (1); 9641488Smckusick } 9741488Smckusick 9854073Shibler rdreset(ctlr, unit) 9954073Shibler register int ctlr, unit; 10041488Smckusick { 10141488Smckusick u_char stat; 10241488Smckusick 10341488Smckusick rd_ssmc.c_unit = C_SUNIT(0); 10441488Smckusick rd_ssmc.c_cmd = C_SSM; 10541488Smckusick rd_ssmc.c_refm = REF_MASK; 10641488Smckusick rd_ssmc.c_fefm = FEF_MASK; 10741488Smckusick rd_ssmc.c_aefm = AEF_MASK; 10841488Smckusick rd_ssmc.c_iefm = IEF_MASK; 10954073Shibler hpibsend(ctlr, unit, C_CMD, &rd_ssmc, sizeof(rd_ssmc)); 11054073Shibler hpibswait(ctlr, unit); 11154073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 11241488Smckusick } 11341488Smckusick 11454073Shibler rdident(ctlr, unit) 11554073Shibler register int ctlr, unit; 11641488Smckusick { 11741488Smckusick struct rd_describe desc; 11841488Smckusick u_char stat, cmd[3]; 11941488Smckusick char name[7]; 12041488Smckusick register int id, i; 12141488Smckusick 12254073Shibler id = hpibid(ctlr, unit); 12341488Smckusick if ((id & 0x200) == 0) 12441488Smckusick return(-1); 12541488Smckusick for (i = 0; i < nrdinfo; i++) 12641488Smckusick if (id == rdinfo[i].hwid) 12741488Smckusick break; 12841488Smckusick if (i == nrdinfo) 12941488Smckusick return(-1); 13041488Smckusick id = i; 13154073Shibler rdreset(ctlr, unit); 13241488Smckusick cmd[0] = C_SUNIT(0); 13341488Smckusick cmd[1] = C_SVOL(0); 13441488Smckusick cmd[2] = C_DESC; 13554073Shibler hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd)); 13654073Shibler hpibrecv(ctlr, unit, C_EXEC, &desc, 37); 13754073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat)); 13841488Smckusick bzero(name, sizeof(name)); 13941488Smckusick if (!stat) { 14041488Smckusick register int n = desc.d_name; 14141488Smckusick for (i = 5; i >= 0; i--) { 14241488Smckusick name[i] = (n & 0xf) + '0'; 14341488Smckusick n >>= 4; 14441488Smckusick } 14541488Smckusick } 14641488Smckusick /* 14741488Smckusick * Take care of a couple of anomolies: 14841488Smckusick * 1. 7945A and 7946A both return same HW id 14941488Smckusick * 2. 9122S and 9134D both return same HW id 15041488Smckusick * 3. 9122D and 9134L both return same HW id 15141488Smckusick */ 15241488Smckusick switch (rdinfo[id].hwid) { 15341488Smckusick case RD7946AID: 15441488Smckusick if (bcmp(name, "079450", 6) == 0) 15541488Smckusick id = RD7945A; 15641488Smckusick else 15741488Smckusick id = RD7946A; 15841488Smckusick break; 15941488Smckusick 16041488Smckusick case RD9134LID: 16141488Smckusick if (bcmp(name, "091340", 6) == 0) 16241488Smckusick id = RD9134L; 16341488Smckusick else 16441488Smckusick id = RD9122D; 16541488Smckusick break; 16641488Smckusick 16741488Smckusick case RD9134DID: 16841488Smckusick if (bcmp(name, "091220", 6) == 0) 16941488Smckusick id = RD9122S; 17041488Smckusick else 17141488Smckusick id = RD9134D; 17241488Smckusick break; 17341488Smckusick } 17441488Smckusick return(id); 17541488Smckusick } 17641488Smckusick 17741488Smckusick rdopen(io) 17841488Smckusick struct iob *io; 17941488Smckusick { 18054073Shibler register struct rd_softc *rs; 18141488Smckusick struct rdinfo *ri; 18254073Shibler int unit, ctlr, part; 18341488Smckusick 18454073Shibler devconvert(io); 18554073Shibler 18654073Shibler ctlr = io->i_adapt; 18754073Shibler if (ctlr >= NHPIB || hpibalive(ctlr) == 0) 18854073Shibler return (EADAPT); 18954073Shibler unit = io->i_ctlr; 19054073Shibler if (unit >= NRD) 19154073Shibler return (ECTLR); 19254073Shibler rs = &rd_softc[ctlr][unit]; 19341488Smckusick if (rs->sc_alive == 0) 19454073Shibler if (rdinit(ctlr, unit) == 0) 19554073Shibler return (ENXIO); 19654073Shibler part = io->i_part; 19754073Shibler if (part >= 8) 19854073Shibler return (EPART); 19941488Smckusick ri = &rdinfo[rs->sc_type]; 20054073Shibler io->i_boff = ri->cyloff[part] * ri->nbpc; 201*55898Shibler return (0); 20241488Smckusick } 20341488Smckusick 20441488Smckusick rdstrategy(io, func) 20541488Smckusick register struct iob *io; 20654073Shibler int func; 20741488Smckusick { 20854073Shibler register int ctlr = io->i_adapt; 20954073Shibler register int unit = io->i_ctlr; 21054073Shibler register struct rd_softc *rs = &rd_softc[ctlr][unit]; 21141488Smckusick char stat; 21241488Smckusick 213*55898Shibler if (io->i_cc == 0) 214*55898Shibler return(0); 215*55898Shibler 21641488Smckusick rs->sc_retry = 0; 21741488Smckusick rd_ioc.c_unit = C_SUNIT(0); 21841488Smckusick rd_ioc.c_volume = C_SVOL(0); 21941488Smckusick rd_ioc.c_saddr = C_SADDR; 22041488Smckusick rd_ioc.c_hiaddr = 0; 22141488Smckusick rd_ioc.c_addr = RDBTOS(io->i_bn); 22241488Smckusick rd_ioc.c_nop2 = C_NOP; 22341488Smckusick rd_ioc.c_slen = C_SLEN; 22441488Smckusick rd_ioc.c_len = io->i_cc; 22549156Sbostic rd_ioc.c_cmd = func == F_READ ? C_READ : C_WRITE; 22641488Smckusick retry: 22754073Shibler hpibsend(ctlr, unit, C_CMD, &rd_ioc.c_unit, sizeof(rd_ioc)-2); 22854073Shibler hpibswait(ctlr, unit); 22954073Shibler hpibgo(ctlr, unit, C_EXEC, io->i_ma, io->i_cc, func); 23054073Shibler hpibswait(ctlr, unit); 23154073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 23241488Smckusick if (stat) { 23354073Shibler if (rderror(ctlr, unit, io->i_part) == 0) 23441488Smckusick return(-1); 23541488Smckusick if (++rs->sc_retry > RDRETRY) 23641488Smckusick return(-1); 23754073Shibler goto retry; 23841488Smckusick } 23941488Smckusick return(io->i_cc); 24041488Smckusick } 24141488Smckusick 24254073Shibler rderror(ctlr, unit, part) 24354073Shibler register int ctlr, unit; 24454073Shibler int part; 24541488Smckusick { 24654073Shibler register struct rd_softc *rd = &rd_softc[ctlr][unit]; 24741488Smckusick char stat; 24841488Smckusick 24941488Smckusick rd_rsc.c_unit = C_SUNIT(0); 25041488Smckusick rd_rsc.c_sram = C_SRAM; 25141488Smckusick rd_rsc.c_ram = C_RAM; 25241488Smckusick rd_rsc.c_cmd = C_STATUS; 25354073Shibler hpibsend(ctlr, unit, C_CMD, &rd_rsc, sizeof(rd_rsc)); 25454073Shibler hpibrecv(ctlr, unit, C_EXEC, &rd_stat, sizeof(rd_stat)); 25554073Shibler hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 25641488Smckusick if (stat) { 25754073Shibler printf("rd(%d,%d,0,%d): request status fail %d\n", 25854073Shibler ctlr, unit, part, stat); 25941488Smckusick return(0); 26041488Smckusick } 26154073Shibler printf("rd(%d,%d,0,%d) err: vu 0x%x", 26254073Shibler ctlr, unit, part, rd_stat.c_vu); 26341488Smckusick if ((rd_stat.c_aef & AEF_UD) || (rd_stat.c_ief & (IEF_MD|IEF_RD))) 26441488Smckusick printf(", block %d", rd_stat.c_blk); 26541488Smckusick printf(", R0x%x F0x%x A0x%x I0x%x\n", 26641488Smckusick rd_stat.c_ref, rd_stat.c_fef, rd_stat.c_aef, rd_stat.c_ief); 26741488Smckusick return(1); 26841488Smckusick } 269