1 /* $NetBSD: rd.c,v 1.8 2007/03/04 05:59:50 christos 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(int ctlr, int unit) 158 { 159 struct rd_softc *rs = &rd_softc[ctlr][unit]; 160 161 rs->sc_type = rdident(ctlr, unit); 162 if (rs->sc_type < 0) 163 return 0; 164 rs->sc_alive = 1; 165 return 1; 166 } 167 168 static void 169 rdreset(int ctlr, int unit) 170 { 171 uint8_t stat; 172 173 rd_ssmc.c_unit = C_SUNIT(0); 174 rd_ssmc.c_cmd = C_SSM; 175 rd_ssmc.c_refm = REF_MASK; 176 rd_ssmc.c_fefm = FEF_MASK; 177 rd_ssmc.c_aefm = AEF_MASK; 178 rd_ssmc.c_iefm = IEF_MASK; 179 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&rd_ssmc, sizeof(rd_ssmc)); 180 hpibswait(ctlr, unit); 181 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 182 } 183 184 static int 185 rdident(int ctlr, int unit) 186 { 187 struct rd_describe desc; 188 uint8_t stat, cmd[3]; 189 char name[7]; 190 int id, i; 191 192 id = hpibid(ctlr, unit); 193 if ((id & 0x200) == 0) 194 return -1; 195 for (i = 0; i < numrdidentinfo; i++) 196 if (id == rdidentinfo[i].ri_hwid) 197 break; 198 if (i == numrdidentinfo) 199 return -1; 200 id = i; 201 rdreset(ctlr, unit); 202 cmd[0] = C_SUNIT(0); 203 cmd[1] = C_SVOL(0); 204 cmd[2] = C_DESC; 205 hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd)); 206 hpibrecv(ctlr, unit, C_EXEC, (uint8_t *)&desc, 37); 207 hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat)); 208 memset(name, 0, sizeof(name)); 209 if (!stat) { 210 int n = desc.d_name; 211 for (i = 5; i >= 0; i--) { 212 name[i] = (n & 0xf) + '0'; 213 n >>= 4; 214 } 215 } 216 /* 217 * Take care of a couple of anomolies: 218 * 1. 7945A and 7946A both return same HW id 219 * 2. 9122S and 9134D both return same HW id 220 * 3. 9122D and 9134L both return same HW id 221 */ 222 switch (rdidentinfo[id].ri_hwid) { 223 case RD7946AID: 224 if (memcmp(name, "079450", 6) == 0) 225 id = RD7945A; 226 else 227 id = RD7946A; 228 break; 229 230 case RD9134LID: 231 if (memcmp(name, "091340", 6) == 0) 232 id = RD9134L; 233 else 234 id = RD9122D; 235 break; 236 237 case RD9134DID: 238 if (memcmp(name, "091220", 6) == 0) 239 id = RD9122S; 240 else 241 id = RD9134D; 242 break; 243 } 244 return id; 245 } 246 247 char io_buf[MAXBSIZE]; 248 249 static int 250 rdgetinfo(struct rd_softc *rs) 251 { 252 struct rdminilabel *pi = &rs->sc_pinfo; 253 struct disklabel *lp = &rdlabel; 254 char *msg; 255 int err, savepart; 256 size_t i; 257 258 memset((void *)lp, 0, sizeof *lp); 259 lp->d_secsize = DEV_BSIZE; 260 261 /* Disklabel is always from RAW_PART. */ 262 savepart = rs->sc_part; 263 rs->sc_part = RAW_PART; 264 err = rdstrategy(rs, F_READ, LABELSECTOR, 265 lp->d_secsize ? lp->d_secsize : DEV_BSIZE, io_buf, &i); 266 rs->sc_part = savepart; 267 268 if (err) { 269 printf("rdgetinfo: rdstrategy error %d\n", err); 270 return 0; 271 } 272 273 msg = getdisklabel(io_buf, lp); 274 if (msg) { 275 printf("rd(%d,%d,%d): WARNING: %s\n", 276 rs->sc_ctlr, rs->sc_unit, rs->sc_part, msg); 277 pi->npart = 3; 278 pi->offset[0] = pi->offset[1] = -1; 279 pi->offset[2] = 0; 280 } else { 281 pi->npart = lp->d_npartitions; 282 for (i = 0; i < pi->npart; i++) 283 pi->offset[i] = lp->d_partitions[i].p_size == 0 ? 284 -1 : lp->d_partitions[i].p_offset; 285 } 286 return 1; 287 } 288 289 int 290 rdopen(struct open_file *f, ...) 291 { 292 va_list ap; 293 int ctlr, unit, part; 294 struct rd_softc *rs; 295 296 va_start(ap, f); 297 ctlr = va_arg(ap, int); 298 unit = va_arg(ap, int); 299 part = va_arg(ap, int); 300 va_end(ap); 301 302 if (ctlr >= NHPIB || hpibalive(ctlr) == 0) 303 return EADAPT; 304 if (unit >= NRD) 305 return ECTLR; 306 rs = &rd_softc[ctlr][unit]; 307 rs->sc_part = part; 308 rs->sc_unit = unit; 309 rs->sc_ctlr = ctlr; 310 if (rs->sc_alive == 0) { 311 if (rdinit(ctlr, unit) == 0) 312 return ENXIO; 313 if (rdgetinfo(rs) == 0) 314 return ERDLAB; 315 } 316 if (part != RAW_PART && /* always allow RAW_PART to be opened */ 317 (part >= rs->sc_pinfo.npart || rs->sc_pinfo.offset[part] == -1)) 318 return EPART; 319 f->f_devdata = (void *)rs; 320 return 0; 321 } 322 323 int 324 rdclose(struct open_file *f) 325 { 326 struct rd_softc *rs = f->f_devdata; 327 328 /* 329 * Mark the disk `not alive' so that the disklabel 330 * will be re-loaded at next open. 331 */ 332 memset(rs, 0, sizeof(struct rd_softc)); 333 f->f_devdata = NULL; 334 335 return 0; 336 } 337 338 int 339 rdstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf, 340 size_t *rsize) 341 { 342 uint8_t *buf = v_buf; 343 struct rd_softc *rs = devdata; 344 int ctlr = rs->sc_ctlr; 345 int unit = rs->sc_unit; 346 daddr_t blk; 347 uint8_t stat; 348 349 if (size == 0) 350 return 0; 351 352 /* 353 * Don't do partition translation on the `raw partition'. 354 */ 355 blk = (dblk + ((rs->sc_part == RAW_PART) ? 0 : 356 rs->sc_pinfo.offset[rs->sc_part])); 357 358 rs->sc_retry = 0; 359 rd_ioc.c_unit = C_SUNIT(0); 360 rd_ioc.c_volume = C_SVOL(0); 361 rd_ioc.c_saddr = C_SADDR; 362 rd_ioc.c_hiaddr = 0; 363 rd_ioc.c_addr = RDBTOS(blk); 364 rd_ioc.c_nop2 = C_NOP; 365 rd_ioc.c_slen = C_SLEN; 366 rd_ioc.c_len = size; 367 rd_ioc.c_cmd = func == F_READ ? C_READ : C_WRITE; 368 retry: 369 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&rd_ioc.c_unit, 370 sizeof(rd_ioc) - 2); 371 hpibswait(ctlr, unit); 372 hpibgo(ctlr, unit, C_EXEC, buf, size, func); 373 hpibswait(ctlr, unit); 374 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 375 if (stat) { 376 if (rderror(ctlr, unit, rs->sc_part) == 0) 377 return EIO; 378 if (++rs->sc_retry > RDRETRY) 379 return EIO; 380 goto retry; 381 } 382 *rsize = size; 383 384 return 0; 385 } 386 387 static int 388 rderror(int ctlr, int unit, int part) 389 { 390 uint8_t stat; 391 392 rd_rsc.c_unit = C_SUNIT(0); 393 rd_rsc.c_sram = C_SRAM; 394 rd_rsc.c_ram = C_RAM; 395 rd_rsc.c_cmd = C_STATUS; 396 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&rd_rsc, sizeof(rd_rsc)); 397 hpibrecv(ctlr, unit, C_EXEC, (uint8_t *)&rd_stat, sizeof(rd_stat)); 398 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 399 if (stat) { 400 printf("rd(%d,%d,0,%d): request status fail %d\n", 401 ctlr, unit, part, stat); 402 return 0; 403 } 404 printf("rd(%d,%d,0,%d) err: vu 0x%x", 405 ctlr, unit, part, rd_stat.c_vu); 406 if ((rd_stat.c_aef & AEF_UD) || (rd_stat.c_ief & (IEF_MD|IEF_RD))) 407 printf(", block %ld", rd_stat.c_blk); 408 printf(", R0x%x F0x%x A0x%x I0x%x\n", 409 rd_stat.c_ref, rd_stat.c_fef, rd_stat.c_aef, rd_stat.c_ief); 410 return 1; 411 } 412