1 /* $NetBSD: rd.c,v 1.9 2011/02/08 20:20:14 rmind Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1982, 1990, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: Utah Hdr: rd.c 1.20 92/12/21 37 * 38 * @(#)rd.c 8.1 (Berkeley) 7/15/93 39 */ 40 41 /* 42 * CS80/SS80 disk driver 43 */ 44 #include <sys/param.h> 45 #include <sys/disklabel.h> 46 47 #include <machine/stdarg.h> 48 49 #include <lib/libsa/stand.h> 50 51 #include <hp300/dev/rdreg.h> 52 53 #include <hp300/stand/common/conf.h> 54 #include <hp300/stand/common/hpibvar.h> 55 #include <hp300/stand/common/samachdep.h> 56 57 struct rd_iocmd rd_ioc; 58 struct rd_rscmd rd_rsc; 59 struct rd_stat rd_stat; 60 struct rd_ssmcmd rd_ssmc; 61 62 struct disklabel rdlabel; 63 64 struct rdminilabel { 65 u_short npart; 66 u_long offset[MAXPARTITIONS]; 67 }; 68 69 struct rd_softc { 70 int sc_ctlr; 71 int sc_unit; 72 int sc_part; 73 char sc_retry; 74 char sc_alive; 75 short sc_type; 76 struct rdminilabel sc_pinfo; 77 }; 78 79 #define RDRETRY 5 80 81 struct rdidentinfo { 82 short ri_hwid; 83 short ri_maxunum; 84 int ri_nblocks; 85 }; 86 87 static int rdinit(int, int); 88 static int rdident(int, int); 89 static void rdreset(int, int); 90 static int rdgetinfo(struct rd_softc *); 91 static int rderror(int, int, int); 92 93 struct rd_softc rd_softc[NHPIB][NRD]; 94 95 struct rdidentinfo rdidentinfo[] = { 96 { RD7946AID, 0, 108416 }, 97 { RD9134DID, 1, 29088 }, 98 { RD9134LID, 1, 1232 }, 99 { RD7912PID, 0, 128128 }, 100 { RD7914PID, 0, 258048 }, 101 { RD7958AID, 0, 255276 }, 102 { RD7957AID, 0, 159544 }, 103 { RD7933HID, 0, 789958 }, 104 { RD9134LID, 1, 77840 }, 105 { RD7936HID, 0, 600978 }, 106 { RD7937HID, 0, 1116102 }, 107 { RD7914CTID, 0, 258048 }, 108 { RD7946AID, 0, 108416 }, 109 { RD9134LID, 1, 1232 }, 110 { RD7957BID, 0, 159894 }, 111 { RD7958BID, 0, 297108 }, 112 { RD7959BID, 0, 594216 }, 113 { RD2200AID, 0, 654948 }, 114 { RD2203AID, 0, 1309896 } 115 }; 116 int numrdidentinfo = sizeof(rdidentinfo) / sizeof(rdidentinfo[0]); 117 118 int 119 rdinit(int ctlr, int unit) 120 { 121 struct rd_softc *rs = &rd_softc[ctlr][unit]; 122 123 rs->sc_type = rdident(ctlr, unit); 124 if (rs->sc_type < 0) 125 return 0; 126 rs->sc_alive = 1; 127 return 1; 128 } 129 130 static void 131 rdreset(int ctlr, int unit) 132 { 133 uint8_t stat; 134 135 rd_ssmc.c_unit = C_SUNIT(0); 136 rd_ssmc.c_cmd = C_SSM; 137 rd_ssmc.c_refm = REF_MASK; 138 rd_ssmc.c_fefm = FEF_MASK; 139 rd_ssmc.c_aefm = AEF_MASK; 140 rd_ssmc.c_iefm = IEF_MASK; 141 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&rd_ssmc, sizeof(rd_ssmc)); 142 hpibswait(ctlr, unit); 143 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 144 } 145 146 static int 147 rdident(int ctlr, int unit) 148 { 149 struct rd_describe desc; 150 uint8_t stat, cmd[3]; 151 char name[7]; 152 int id, i; 153 154 id = hpibid(ctlr, unit); 155 if ((id & 0x200) == 0) 156 return -1; 157 for (i = 0; i < numrdidentinfo; i++) 158 if (id == rdidentinfo[i].ri_hwid) 159 break; 160 if (i == numrdidentinfo) 161 return -1; 162 id = i; 163 rdreset(ctlr, unit); 164 cmd[0] = C_SUNIT(0); 165 cmd[1] = C_SVOL(0); 166 cmd[2] = C_DESC; 167 hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd)); 168 hpibrecv(ctlr, unit, C_EXEC, (uint8_t *)&desc, 37); 169 hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat)); 170 memset(name, 0, sizeof(name)); 171 if (!stat) { 172 int n = desc.d_name; 173 for (i = 5; i >= 0; i--) { 174 name[i] = (n & 0xf) + '0'; 175 n >>= 4; 176 } 177 } 178 /* 179 * Take care of a couple of anomolies: 180 * 1. 7945A and 7946A both return same HW id 181 * 2. 9122S and 9134D both return same HW id 182 * 3. 9122D and 9134L both return same HW id 183 */ 184 switch (rdidentinfo[id].ri_hwid) { 185 case RD7946AID: 186 if (memcmp(name, "079450", 6) == 0) 187 id = RD7945A; 188 else 189 id = RD7946A; 190 break; 191 192 case RD9134LID: 193 if (memcmp(name, "091340", 6) == 0) 194 id = RD9134L; 195 else 196 id = RD9122D; 197 break; 198 199 case RD9134DID: 200 if (memcmp(name, "091220", 6) == 0) 201 id = RD9122S; 202 else 203 id = RD9134D; 204 break; 205 } 206 return id; 207 } 208 209 char io_buf[MAXBSIZE]; 210 211 static int 212 rdgetinfo(struct rd_softc *rs) 213 { 214 struct rdminilabel *pi = &rs->sc_pinfo; 215 struct disklabel *lp = &rdlabel; 216 char *msg; 217 int err, savepart; 218 size_t i; 219 220 memset((void *)lp, 0, sizeof *lp); 221 lp->d_secsize = DEV_BSIZE; 222 223 /* Disklabel is always from RAW_PART. */ 224 savepart = rs->sc_part; 225 rs->sc_part = RAW_PART; 226 err = rdstrategy(rs, F_READ, LABELSECTOR, 227 lp->d_secsize ? lp->d_secsize : DEV_BSIZE, io_buf, &i); 228 rs->sc_part = savepart; 229 230 if (err) { 231 printf("rdgetinfo: rdstrategy error %d\n", err); 232 return 0; 233 } 234 235 msg = getdisklabel(io_buf, lp); 236 if (msg) { 237 printf("rd(%d,%d,%d): WARNING: %s\n", 238 rs->sc_ctlr, rs->sc_unit, rs->sc_part, msg); 239 pi->npart = 3; 240 pi->offset[0] = pi->offset[1] = -1; 241 pi->offset[2] = 0; 242 } else { 243 pi->npart = lp->d_npartitions; 244 for (i = 0; i < pi->npart; i++) 245 pi->offset[i] = lp->d_partitions[i].p_size == 0 ? 246 -1 : lp->d_partitions[i].p_offset; 247 } 248 return 1; 249 } 250 251 int 252 rdopen(struct open_file *f, ...) 253 { 254 va_list ap; 255 int ctlr, unit, part; 256 struct rd_softc *rs; 257 258 va_start(ap, f); 259 ctlr = va_arg(ap, int); 260 unit = va_arg(ap, int); 261 part = va_arg(ap, int); 262 va_end(ap); 263 264 if (ctlr >= NHPIB || hpibalive(ctlr) == 0) 265 return EADAPT; 266 if (unit >= NRD) 267 return ECTLR; 268 rs = &rd_softc[ctlr][unit]; 269 rs->sc_part = part; 270 rs->sc_unit = unit; 271 rs->sc_ctlr = ctlr; 272 if (rs->sc_alive == 0) { 273 if (rdinit(ctlr, unit) == 0) 274 return ENXIO; 275 if (rdgetinfo(rs) == 0) 276 return ERDLAB; 277 } 278 if (part != RAW_PART && /* always allow RAW_PART to be opened */ 279 (part >= rs->sc_pinfo.npart || rs->sc_pinfo.offset[part] == -1)) 280 return EPART; 281 f->f_devdata = (void *)rs; 282 return 0; 283 } 284 285 int 286 rdclose(struct open_file *f) 287 { 288 struct rd_softc *rs = f->f_devdata; 289 290 /* 291 * Mark the disk `not alive' so that the disklabel 292 * will be re-loaded at next open. 293 */ 294 memset(rs, 0, sizeof(struct rd_softc)); 295 f->f_devdata = NULL; 296 297 return 0; 298 } 299 300 int 301 rdstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf, 302 size_t *rsize) 303 { 304 uint8_t *buf = v_buf; 305 struct rd_softc *rs = devdata; 306 int ctlr = rs->sc_ctlr; 307 int unit = rs->sc_unit; 308 daddr_t blk; 309 uint8_t stat; 310 311 if (size == 0) 312 return 0; 313 314 /* 315 * Don't do partition translation on the `raw partition'. 316 */ 317 blk = (dblk + ((rs->sc_part == RAW_PART) ? 0 : 318 rs->sc_pinfo.offset[rs->sc_part])); 319 320 rs->sc_retry = 0; 321 rd_ioc.c_unit = C_SUNIT(0); 322 rd_ioc.c_volume = C_SVOL(0); 323 rd_ioc.c_saddr = C_SADDR; 324 rd_ioc.c_hiaddr = 0; 325 rd_ioc.c_addr = RDBTOS(blk); 326 rd_ioc.c_nop2 = C_NOP; 327 rd_ioc.c_slen = C_SLEN; 328 rd_ioc.c_len = size; 329 rd_ioc.c_cmd = func == F_READ ? C_READ : C_WRITE; 330 retry: 331 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&rd_ioc.c_unit, 332 sizeof(rd_ioc) - 2); 333 hpibswait(ctlr, unit); 334 hpibgo(ctlr, unit, C_EXEC, buf, size, func); 335 hpibswait(ctlr, unit); 336 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 337 if (stat) { 338 if (rderror(ctlr, unit, rs->sc_part) == 0) 339 return EIO; 340 if (++rs->sc_retry > RDRETRY) 341 return EIO; 342 goto retry; 343 } 344 *rsize = size; 345 346 return 0; 347 } 348 349 static int 350 rderror(int ctlr, int unit, int part) 351 { 352 uint8_t stat; 353 354 rd_rsc.c_unit = C_SUNIT(0); 355 rd_rsc.c_sram = C_SRAM; 356 rd_rsc.c_ram = C_RAM; 357 rd_rsc.c_cmd = C_STATUS; 358 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&rd_rsc, sizeof(rd_rsc)); 359 hpibrecv(ctlr, unit, C_EXEC, (uint8_t *)&rd_stat, sizeof(rd_stat)); 360 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 361 if (stat) { 362 printf("rd(%d,%d,0,%d): request status fail %d\n", 363 ctlr, unit, part, stat); 364 return 0; 365 } 366 printf("rd(%d,%d,0,%d) err: vu 0x%x", 367 ctlr, unit, part, rd_stat.c_vu); 368 if ((rd_stat.c_aef & AEF_UD) || (rd_stat.c_ief & (IEF_MD|IEF_RD))) 369 printf(", block %ld", rd_stat.c_blk); 370 printf(", R0x%x F0x%x A0x%x I0x%x\n", 371 rd_stat.c_ref, rd_stat.c_fef, rd_stat.c_aef, rd_stat.c_ief); 372 return 1; 373 } 374