1 /* $NetBSD: rd.c,v 1.1 1997/02/04 03:52:48 thorpej 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. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by the University of 23 * California, Berkeley and its contributors. 24 * 4. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: Utah Hdr: rd.c 1.20 92/12/21 41 * 42 * @(#)rd.c 8.1 (Berkeley) 7/15/93 43 */ 44 45 /* 46 * CS80/SS80 disk driver 47 */ 48 #include <sys/param.h> 49 #include <sys/disklabel.h> 50 51 #include <lib/libsa/stand.h> 52 53 #include <hp300/dev/rdreg.h> 54 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 } rd_softc[NHPIB][NRD]; 78 79 #define RDRETRY 5 80 81 struct rdidentinfo { 82 short ri_hwid; 83 short ri_maxunum; 84 int ri_nblocks; 85 } rdidentinfo[] = { 86 { RD7946AID, 0, 108416 }, 87 { RD9134DID, 1, 29088 }, 88 { RD9134LID, 1, 1232 }, 89 { RD7912PID, 0, 128128 }, 90 { RD7914PID, 0, 258048 }, 91 { RD7958AID, 0, 255276 }, 92 { RD7957AID, 0, 159544 }, 93 { RD7933HID, 0, 789958 }, 94 { RD9134LID, 1, 77840 }, 95 { RD7936HID, 0, 600978 }, 96 { RD7937HID, 0, 1116102 }, 97 { RD7914CTID, 0, 258048 }, 98 { RD7946AID, 0, 108416 }, 99 { RD9134LID, 1, 1232 }, 100 { RD7957BID, 0, 159894 }, 101 { RD7958BID, 0, 297108 }, 102 { RD7959BID, 0, 594216 }, 103 { RD2200AID, 0, 654948 }, 104 { RD2203AID, 0, 1309896 } 105 }; 106 int numrdidentinfo = sizeof(rdidentinfo) / sizeof(rdidentinfo[0]); 107 108 rdinit(ctlr, unit) 109 int ctlr, unit; 110 { 111 register struct rd_softc *rs = &rd_softc[ctlr][unit]; 112 u_char stat; 113 114 rs->sc_type = rdident(ctlr, unit); 115 if (rs->sc_type < 0) 116 return (0); 117 rs->sc_alive = 1; 118 return (1); 119 } 120 121 rdreset(ctlr, unit) 122 register int ctlr, unit; 123 { 124 u_char stat; 125 126 rd_ssmc.c_unit = C_SUNIT(0); 127 rd_ssmc.c_cmd = C_SSM; 128 rd_ssmc.c_refm = REF_MASK; 129 rd_ssmc.c_fefm = FEF_MASK; 130 rd_ssmc.c_aefm = AEF_MASK; 131 rd_ssmc.c_iefm = IEF_MASK; 132 hpibsend(ctlr, unit, C_CMD, &rd_ssmc, sizeof(rd_ssmc)); 133 hpibswait(ctlr, unit); 134 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 135 } 136 137 rdident(ctlr, unit) 138 register int ctlr, unit; 139 { 140 struct rd_describe desc; 141 u_char stat, cmd[3]; 142 char name[7]; 143 register int id, i; 144 145 id = hpibid(ctlr, unit); 146 if ((id & 0x200) == 0) 147 return(-1); 148 for (i = 0; i < numrdidentinfo; i++) 149 if (id == rdidentinfo[i].ri_hwid) 150 break; 151 if (i == numrdidentinfo) 152 return(-1); 153 id = i; 154 rdreset(ctlr, unit); 155 cmd[0] = C_SUNIT(0); 156 cmd[1] = C_SVOL(0); 157 cmd[2] = C_DESC; 158 hpibsend(ctlr, unit, C_CMD, cmd, sizeof(cmd)); 159 hpibrecv(ctlr, unit, C_EXEC, &desc, 37); 160 hpibrecv(ctlr, unit, C_QSTAT, &stat, sizeof(stat)); 161 bzero(name, sizeof(name)); 162 if (!stat) { 163 register int n = desc.d_name; 164 for (i = 5; i >= 0; i--) { 165 name[i] = (n & 0xf) + '0'; 166 n >>= 4; 167 } 168 } 169 /* 170 * Take care of a couple of anomolies: 171 * 1. 7945A and 7946A both return same HW id 172 * 2. 9122S and 9134D both return same HW id 173 * 3. 9122D and 9134L both return same HW id 174 */ 175 switch (rdidentinfo[id].ri_hwid) { 176 case RD7946AID: 177 if (bcmp(name, "079450", 6) == 0) 178 id = RD7945A; 179 else 180 id = RD7946A; 181 break; 182 183 case RD9134LID: 184 if (bcmp(name, "091340", 6) == 0) 185 id = RD9134L; 186 else 187 id = RD9122D; 188 break; 189 190 case RD9134DID: 191 if (bcmp(name, "091220", 6) == 0) 192 id = RD9122S; 193 else 194 id = RD9134D; 195 break; 196 } 197 return(id); 198 } 199 200 #ifdef COMPAT_NOLABEL 201 int rdcyloff[][8] = { 202 { 1, 143, 0, 143, 0, 0, 323, 503, }, /* 7945A */ 203 { 1, 167, 0, 0, 0, 0, 0, 0, }, /* 9134D */ 204 { 0, 0, 0, 0, 0, 0, 0, 0, }, /* 9122S */ 205 { 0, 71, 0, 221, 292, 542, 221, 0, }, /* 7912P */ 206 { 1, 72, 0, 72, 362, 802, 252, 362, }, /* 7914P */ 207 { 1, 28, 0, 140, 167, 444, 140, 721, }, /* 7933H */ 208 { 1, 200, 0, 200, 0, 0, 450, 600, }, /* 9134L */ 209 { 1, 105, 0, 105, 380, 736, 265, 380, }, /* 7957A */ 210 { 1, 65, 0, 65, 257, 657, 193, 257, }, /* 7958A */ 211 { 1, 128, 0, 128, 518, 918, 388, 518, }, /* 7957B */ 212 { 1, 44, 0, 44, 174, 496, 131, 174, }, /* 7958B */ 213 { 1, 44, 0, 44, 218, 1022,174, 218, }, /* 7959B */ 214 { 1, 37, 0, 37, 183, 857, 147, 183, }, /* 2200A */ 215 { 1, 19, 0, 94, 112, 450, 94, 788, }, /* 2203A */ 216 { 1, 20, 0, 98, 117, 256, 98, 397, }, /* 7936H */ 217 { 1, 11, 0, 53, 63, 217, 53, 371, }, /* 7937H */ 218 }; 219 220 struct rdcompatinfo { 221 int nbpc; 222 int *cyloff; 223 } rdcompatinfo[] = { 224 NRD7945ABPT*NRD7945ATRK, rdcyloff[0], 225 NRD9134DBPT*NRD9134DTRK, rdcyloff[1], 226 NRD9122SBPT*NRD9122STRK, rdcyloff[2], 227 NRD7912PBPT*NRD7912PTRK, rdcyloff[3], 228 NRD7914PBPT*NRD7914PTRK, rdcyloff[4], 229 NRD7958ABPT*NRD7958ATRK, rdcyloff[8], 230 NRD7957ABPT*NRD7957ATRK, rdcyloff[7], 231 NRD7933HBPT*NRD7933HTRK, rdcyloff[5], 232 NRD9134LBPT*NRD9134LTRK, rdcyloff[6], 233 NRD7936HBPT*NRD7936HTRK, rdcyloff[14], 234 NRD7937HBPT*NRD7937HTRK, rdcyloff[15], 235 NRD7914PBPT*NRD7914PTRK, rdcyloff[4], 236 NRD7945ABPT*NRD7945ATRK, rdcyloff[0], 237 NRD9122SBPT*NRD9122STRK, rdcyloff[2], 238 NRD7957BBPT*NRD7957BTRK, rdcyloff[9], 239 NRD7958BBPT*NRD7958BTRK, rdcyloff[10], 240 NRD7959BBPT*NRD7959BTRK, rdcyloff[11], 241 NRD2200ABPT*NRD2200ATRK, rdcyloff[12], 242 NRD2203ABPT*NRD2203ATRK, rdcyloff[13], 243 }; 244 int nrdcompatinfo = sizeof(rdcompatinfo) / sizeof(rdcompatinfo[0]); 245 #endif 246 247 char io_buf[MAXBSIZE]; 248 249 rdgetinfo(rs) 250 register struct rd_softc *rs; 251 { 252 register struct rdminilabel *pi = &rs->sc_pinfo; 253 register struct disklabel *lp = &rdlabel; 254 char *msg, *getdisklabel(); 255 int rdstrategy(), err, savepart; 256 size_t i; 257 258 bzero((caddr_t)lp, 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, ", 276 rs->sc_ctlr, rs->sc_unit, rs->sc_part, msg); 277 #ifdef COMPAT_NOLABEL 278 { 279 register struct rdcompatinfo *ci; 280 281 printf("using old default partitioning\n"); 282 ci = &rdcompatinfo[rs->sc_type]; 283 pi->npart = 8; 284 for (i = 0; i < pi->npart; i++) 285 pi->offset[i] = ci->cyloff[i] * ci->nbpc; 286 } 287 #else 288 printf("defining `c' partition as entire disk\n"); 289 pi->npart = 3; 290 pi->offset[0] = pi->offset[1] = -1; 291 pi->offset[2] = 0; 292 #endif 293 } else { 294 pi->npart = lp->d_npartitions; 295 for (i = 0; i < pi->npart; i++) 296 pi->offset[i] = lp->d_partitions[i].p_size == 0 ? 297 -1 : lp->d_partitions[i].p_offset; 298 } 299 return(1); 300 } 301 302 rdopen(f, ctlr, unit, part) 303 struct open_file *f; 304 int ctlr, unit, part; 305 { 306 register struct rd_softc *rs; 307 struct rdinfo *ri; 308 309 if (ctlr >= NHPIB || hpibalive(ctlr) == 0) 310 return (EADAPT); 311 if (unit >= NRD) 312 return (ECTLR); 313 rs = &rd_softc[ctlr][unit]; 314 rs->sc_part = part; 315 rs->sc_unit = unit; 316 rs->sc_ctlr = ctlr; 317 if (rs->sc_alive == 0) { 318 if (rdinit(ctlr, unit) == 0) 319 return (ENXIO); 320 if (rdgetinfo(rs) == 0) 321 return (ERDLAB); 322 } 323 if (part != RAW_PART && /* always allow RAW_PART to be opened */ 324 (part >= rs->sc_pinfo.npart || rs->sc_pinfo.offset[part] == -1)) 325 return (EPART); 326 f->f_devdata = (void *)rs; 327 return (0); 328 } 329 330 rdclose(f) 331 struct open_file *f; 332 { 333 struct rd_softc *rs = f->f_devdata; 334 335 /* 336 * Mark the disk `not alive' so that the disklabel 337 * will be re-loaded at next open. 338 */ 339 bzero(rs, sizeof(struct rd_softc)); 340 f->f_devdata = NULL; 341 342 return (0); 343 } 344 345 rdstrategy(devdata, func, dblk, size, v_buf, rsize) 346 void *devdata; 347 int func; 348 daddr_t dblk; 349 size_t size; 350 void *v_buf; 351 size_t *rsize; 352 { 353 char *buf = v_buf; 354 struct rd_softc *rs = devdata; 355 register int ctlr = rs->sc_ctlr; 356 register int unit = rs->sc_unit; 357 daddr_t blk; 358 char stat; 359 360 if (size == 0) 361 return(0); 362 363 /* 364 * Don't do partition translation on the `raw partition'. 365 */ 366 blk = (dblk + ((rs->sc_part == RAW_PART) ? 0 : 367 rs->sc_pinfo.offset[rs->sc_part])); 368 369 rs->sc_retry = 0; 370 rd_ioc.c_unit = C_SUNIT(0); 371 rd_ioc.c_volume = C_SVOL(0); 372 rd_ioc.c_saddr = C_SADDR; 373 rd_ioc.c_hiaddr = 0; 374 rd_ioc.c_addr = RDBTOS(blk); 375 rd_ioc.c_nop2 = C_NOP; 376 rd_ioc.c_slen = C_SLEN; 377 rd_ioc.c_len = size; 378 rd_ioc.c_cmd = func == F_READ ? C_READ : C_WRITE; 379 retry: 380 hpibsend(ctlr, unit, C_CMD, &rd_ioc.c_unit, sizeof(rd_ioc)-2); 381 hpibswait(ctlr, unit); 382 hpibgo(ctlr, unit, C_EXEC, buf, size, func); 383 hpibswait(ctlr, unit); 384 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 385 if (stat) { 386 if (rderror(ctlr, unit, rs->sc_part) == 0) 387 return(EIO); 388 if (++rs->sc_retry > RDRETRY) 389 return(EIO); 390 goto retry; 391 } 392 *rsize = size; 393 394 return(0); 395 } 396 397 rderror(ctlr, unit, part) 398 register int ctlr, unit; 399 int part; 400 { 401 register struct rd_softc *rd = &rd_softc[ctlr][unit]; 402 char stat; 403 404 rd_rsc.c_unit = C_SUNIT(0); 405 rd_rsc.c_sram = C_SRAM; 406 rd_rsc.c_ram = C_RAM; 407 rd_rsc.c_cmd = C_STATUS; 408 hpibsend(ctlr, unit, C_CMD, &rd_rsc, sizeof(rd_rsc)); 409 hpibrecv(ctlr, unit, C_EXEC, &rd_stat, sizeof(rd_stat)); 410 hpibrecv(ctlr, unit, C_QSTAT, &stat, 1); 411 if (stat) { 412 printf("rd(%d,%d,0,%d): request status fail %d\n", 413 ctlr, unit, part, stat); 414 return(0); 415 } 416 printf("rd(%d,%d,0,%d) err: vu 0x%x", 417 ctlr, unit, part, rd_stat.c_vu); 418 if ((rd_stat.c_aef & AEF_UD) || (rd_stat.c_ief & (IEF_MD|IEF_RD))) 419 printf(", block %d", rd_stat.c_blk); 420 printf(", R0x%x F0x%x A0x%x I0x%x\n", 421 rd_stat.c_ref, rd_stat.c_fef, rd_stat.c_aef, rd_stat.c_ief); 422 return(1); 423 } 424