1 /* $NetBSD: rd.c,v 1.10 2011/07/17 20:54:40 joerg 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 <lib/libsa/stand.h> 48 49 #include <hp300/dev/rdreg.h> 50 51 #include <hp300/stand/common/conf.h> 52 #include <hp300/stand/common/hpibvar.h> 53 #include <hp300/stand/common/samachdep.h> 54 55 struct rd_iocmd rd_ioc; 56 struct rd_rscmd rd_rsc; 57 struct rd_stat rd_stat; 58 struct rd_ssmcmd rd_ssmc; 59 60 struct disklabel rdlabel; 61 62 struct rdminilabel { 63 u_short npart; 64 u_long offset[MAXPARTITIONS]; 65 }; 66 67 struct rd_softc { 68 int sc_ctlr; 69 int sc_unit; 70 int sc_part; 71 char sc_retry; 72 char sc_alive; 73 short sc_type; 74 struct rdminilabel sc_pinfo; 75 }; 76 77 #define RDRETRY 5 78 79 struct rdidentinfo { 80 short ri_hwid; 81 short ri_maxunum; 82 int ri_nblocks; 83 }; 84 85 static int rdinit(int, int); 86 static int rdident(int, int); 87 static void rdreset(int, int); 88 static int rdgetinfo(struct rd_softc *); 89 static int rderror(int, int, int); 90 91 struct rd_softc rd_softc[NHPIB][NRD]; 92 93 struct rdidentinfo rdidentinfo[] = { 94 { RD7946AID, 0, 108416 }, 95 { RD9134DID, 1, 29088 }, 96 { RD9134LID, 1, 1232 }, 97 { RD7912PID, 0, 128128 }, 98 { RD7914PID, 0, 258048 }, 99 { RD7958AID, 0, 255276 }, 100 { RD7957AID, 0, 159544 }, 101 { RD7933HID, 0, 789958 }, 102 { RD9134LID, 1, 77840 }, 103 { RD7936HID, 0, 600978 }, 104 { RD7937HID, 0, 1116102 }, 105 { RD7914CTID, 0, 258048 }, 106 { RD7946AID, 0, 108416 }, 107 { RD9134LID, 1, 1232 }, 108 { RD7957BID, 0, 159894 }, 109 { RD7958BID, 0, 297108 }, 110 { RD7959BID, 0, 594216 }, 111 { RD2200AID, 0, 654948 }, 112 { RD2203AID, 0, 1309896 } 113 }; 114 int numrdidentinfo = sizeof(rdidentinfo) / sizeof(rdidentinfo[0]); 115 116 int 117 rdinit(int ctlr, int unit) 118 { 119 struct rd_softc *rs = &rd_softc[ctlr][unit]; 120 121 rs->sc_type = rdident(ctlr, unit); 122 if (rs->sc_type < 0) 123 return 0; 124 rs->sc_alive = 1; 125 return 1; 126 } 127 128 static void 129 rdreset(int ctlr, int unit) 130 { 131 uint8_t stat; 132 133 rd_ssmc.c_unit = C_SUNIT(0); 134 rd_ssmc.c_cmd = C_SSM; 135 rd_ssmc.c_refm = REF_MASK; 136 rd_ssmc.c_fefm = FEF_MASK; 137 rd_ssmc.c_aefm = AEF_MASK; 138 rd_ssmc.c_iefm = IEF_MASK; 139 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&rd_ssmc, sizeof(rd_ssmc)); 140 hpibswait(ctlr, unit); 141 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 142 } 143 144 static int 145 rdident(int ctlr, int unit) 146 { 147 struct rd_describe desc; 148 uint8_t stat, cmd[3]; 149 char name[7]; 150 int id, i; 151 152 id = hpibid(ctlr, unit); 153 if ((id & 0x200) == 0) 154 return -1; 155 for (i = 0; i < numrdidentinfo; i++) 156 if (id == rdidentinfo[i].ri_hwid) 157 break; 158 if (i == numrdidentinfo) 159 return -1; 160 id = i; 161 rdreset(ctlr, unit); 162 cmd[0] = C_SUNIT(0); 163 cmd[1] = C_SVOL(0); 164 cmd[2] = C_DESC; 165 hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd)); 166 hpibrecv(ctlr, unit, C_EXEC, (uint8_t *)&desc, 37); 167 hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat)); 168 memset(name, 0, sizeof(name)); 169 if (!stat) { 170 int n = desc.d_name; 171 for (i = 5; i >= 0; i--) { 172 name[i] = (n & 0xf) + '0'; 173 n >>= 4; 174 } 175 } 176 /* 177 * Take care of a couple of anomolies: 178 * 1. 7945A and 7946A both return same HW id 179 * 2. 9122S and 9134D both return same HW id 180 * 3. 9122D and 9134L both return same HW id 181 */ 182 switch (rdidentinfo[id].ri_hwid) { 183 case RD7946AID: 184 if (memcmp(name, "079450", 6) == 0) 185 id = RD7945A; 186 else 187 id = RD7946A; 188 break; 189 190 case RD9134LID: 191 if (memcmp(name, "091340", 6) == 0) 192 id = RD9134L; 193 else 194 id = RD9122D; 195 break; 196 197 case RD9134DID: 198 if (memcmp(name, "091220", 6) == 0) 199 id = RD9122S; 200 else 201 id = RD9134D; 202 break; 203 } 204 return id; 205 } 206 207 char io_buf[MAXBSIZE]; 208 209 static int 210 rdgetinfo(struct rd_softc *rs) 211 { 212 struct rdminilabel *pi = &rs->sc_pinfo; 213 struct disklabel *lp = &rdlabel; 214 char *msg; 215 int err, savepart; 216 size_t i; 217 218 memset((void *)lp, 0, sizeof *lp); 219 lp->d_secsize = DEV_BSIZE; 220 221 /* Disklabel is always from RAW_PART. */ 222 savepart = rs->sc_part; 223 rs->sc_part = RAW_PART; 224 err = rdstrategy(rs, F_READ, LABELSECTOR, 225 lp->d_secsize ? lp->d_secsize : DEV_BSIZE, io_buf, &i); 226 rs->sc_part = savepart; 227 228 if (err) { 229 printf("rdgetinfo: rdstrategy error %d\n", err); 230 return 0; 231 } 232 233 msg = getdisklabel(io_buf, lp); 234 if (msg) { 235 printf("rd(%d,%d,%d): WARNING: %s\n", 236 rs->sc_ctlr, rs->sc_unit, rs->sc_part, msg); 237 pi->npart = 3; 238 pi->offset[0] = pi->offset[1] = -1; 239 pi->offset[2] = 0; 240 } else { 241 pi->npart = lp->d_npartitions; 242 for (i = 0; i < pi->npart; i++) 243 pi->offset[i] = lp->d_partitions[i].p_size == 0 ? 244 -1 : lp->d_partitions[i].p_offset; 245 } 246 return 1; 247 } 248 249 int 250 rdopen(struct open_file *f, ...) 251 { 252 va_list ap; 253 int ctlr, unit, part; 254 struct rd_softc *rs; 255 256 va_start(ap, f); 257 ctlr = va_arg(ap, int); 258 unit = va_arg(ap, int); 259 part = va_arg(ap, int); 260 va_end(ap); 261 262 if (ctlr >= NHPIB || hpibalive(ctlr) == 0) 263 return EADAPT; 264 if (unit >= NRD) 265 return ECTLR; 266 rs = &rd_softc[ctlr][unit]; 267 rs->sc_part = part; 268 rs->sc_unit = unit; 269 rs->sc_ctlr = ctlr; 270 if (rs->sc_alive == 0) { 271 if (rdinit(ctlr, unit) == 0) 272 return ENXIO; 273 if (rdgetinfo(rs) == 0) 274 return ERDLAB; 275 } 276 if (part != RAW_PART && /* always allow RAW_PART to be opened */ 277 (part >= rs->sc_pinfo.npart || rs->sc_pinfo.offset[part] == -1)) 278 return EPART; 279 f->f_devdata = (void *)rs; 280 return 0; 281 } 282 283 int 284 rdclose(struct open_file *f) 285 { 286 struct rd_softc *rs = f->f_devdata; 287 288 /* 289 * Mark the disk `not alive' so that the disklabel 290 * will be re-loaded at next open. 291 */ 292 memset(rs, 0, sizeof(struct rd_softc)); 293 f->f_devdata = NULL; 294 295 return 0; 296 } 297 298 int 299 rdstrategy(void *devdata, int func, daddr_t dblk, size_t size, void *v_buf, 300 size_t *rsize) 301 { 302 uint8_t *buf = v_buf; 303 struct rd_softc *rs = devdata; 304 int ctlr = rs->sc_ctlr; 305 int unit = rs->sc_unit; 306 daddr_t blk; 307 uint8_t stat; 308 309 if (size == 0) 310 return 0; 311 312 /* 313 * Don't do partition translation on the `raw partition'. 314 */ 315 blk = (dblk + ((rs->sc_part == RAW_PART) ? 0 : 316 rs->sc_pinfo.offset[rs->sc_part])); 317 318 rs->sc_retry = 0; 319 rd_ioc.c_unit = C_SUNIT(0); 320 rd_ioc.c_volume = C_SVOL(0); 321 rd_ioc.c_saddr = C_SADDR; 322 rd_ioc.c_hiaddr = 0; 323 rd_ioc.c_addr = RDBTOS(blk); 324 rd_ioc.c_nop2 = C_NOP; 325 rd_ioc.c_slen = C_SLEN; 326 rd_ioc.c_len = size; 327 rd_ioc.c_cmd = func == F_READ ? C_READ : C_WRITE; 328 retry: 329 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&rd_ioc.c_unit, 330 sizeof(rd_ioc) - 2); 331 hpibswait(ctlr, unit); 332 hpibgo(ctlr, unit, C_EXEC, buf, size, func); 333 hpibswait(ctlr, unit); 334 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 335 if (stat) { 336 if (rderror(ctlr, unit, rs->sc_part) == 0) 337 return EIO; 338 if (++rs->sc_retry > RDRETRY) 339 return EIO; 340 goto retry; 341 } 342 *rsize = size; 343 344 return 0; 345 } 346 347 static int 348 rderror(int ctlr, int unit, int part) 349 { 350 uint8_t stat; 351 352 rd_rsc.c_unit = C_SUNIT(0); 353 rd_rsc.c_sram = C_SRAM; 354 rd_rsc.c_ram = C_RAM; 355 rd_rsc.c_cmd = C_STATUS; 356 hpibsend(ctlr, unit, C_CMD, (uint8_t *)&rd_rsc, sizeof(rd_rsc)); 357 hpibrecv(ctlr, unit, C_EXEC, (uint8_t *)&rd_stat, sizeof(rd_stat)); 358 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 359 if (stat) { 360 printf("rd(%d,%d,0,%d): request status fail %d\n", 361 ctlr, unit, part, stat); 362 return 0; 363 } 364 printf("rd(%d,%d,0,%d) err: vu 0x%x", 365 ctlr, unit, part, rd_stat.c_vu); 366 if ((rd_stat.c_aef & AEF_UD) || (rd_stat.c_ief & (IEF_MD|IEF_RD))) 367 printf(", block %ld", rd_stat.c_blk); 368 printf(", R0x%x F0x%x A0x%x I0x%x\n", 369 rd_stat.c_ref, rd_stat.c_fef, rd_stat.c_aef, rd_stat.c_ief); 370 return 1; 371 } 372