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