1 /* 2 * Copyright (c) 1982, 1986 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 * 6 * @(#)hp.c 7.6 (Berkeley) 10/31/87 7 */ 8 9 #ifdef HPDEBUG 10 int hpdebug; 11 #endif 12 #ifdef HPBDEBUG 13 int hpbdebug; 14 #endif 15 16 #include "hp.h" 17 #if NHP > 0 18 /* 19 * HP disk driver for RP0x+RMxx+ML11 20 * 21 * TODO: 22 * see if DCLR and/or RELEASE set attention status 23 */ 24 #include "param.h" 25 #include "systm.h" 26 #include "dkstat.h" 27 #include "buf.h" 28 #include "conf.h" 29 #include "dir.h" 30 #include "file.h" 31 #include "user.h" 32 #include "map.h" 33 #include "../vax/mtpr.h" 34 #include "vm.h" 35 #include "cmap.h" 36 #include "dkbad.h" 37 #include "disklabel.h" 38 #include "ioctl.h" 39 #include "uio.h" 40 #include "syslog.h" 41 #include "stat.h" 42 43 #include "../machine/pte.h" 44 #include "../vax/dkio.h" 45 #include "mbareg.h" 46 #include "mbavar.h" 47 #include "hpreg.h" 48 49 #define COMPAT_42 50 #define B_FORMAT B_XXX 51 52 /* 53 * Table of supported Massbus drive types. 54 * When using unlabeled packs, slot numbers here 55 * are used as indices into the partition tables. 56 * Slots are left for those drives divined from other means 57 * (e.g. SI, AMPEX, etc.). 58 */ 59 short hptypes[] = { 60 #define HPDT_RM03 0 61 MBDT_RM03, 62 #define HPDT_RM05 1 63 MBDT_RM05, 64 #define HPDT_RP06 2 65 MBDT_RP06, 66 #define HPDT_RM80 3 67 MBDT_RM80, 68 #define HPDT_RP04 4 69 MBDT_RP04, 70 #define HPDT_RP05 5 71 MBDT_RP05, 72 #define HPDT_RP07 6 73 MBDT_RP07, 74 #define HPDT_ML11A 7 75 MBDT_ML11A, 76 #define HPDT_ML11B 8 77 MBDT_ML11B, 78 #define HPDT_9775 9 79 -1, 80 #define HPDT_9730 10 81 -1, 82 #define HPDT_CAPRICORN 11 83 -1, 84 #define HPDT_EAGLE 12 85 -1, 86 #define HPDT_9300 13 87 -1, 88 #define HPDT_RM02 14 89 MBDT_RM02, /* beware, actually mapped */ 90 #define HPDT_2361 15 91 -1, 92 0 93 }; 94 95 struct mba_device *hpinfo[NHP]; 96 int hpattach(),hpustart(),hpstart(),hpdtint(),hpstrategy(); 97 struct mba_driver hpdriver = 98 { hpattach, 0, hpustart, hpstart, hpdtint, 0, 99 hptypes, "hp", 0, hpinfo }; 100 101 u_char hp_offset[16] = { 102 HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 103 HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 104 HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 105 0, 0, 0, 0, 106 }; 107 108 struct buf rhpbuf[NHP]; 109 struct disklabel hplabel[NHP]; 110 struct dkbad hpbad[NHP]; 111 112 struct hpsoftc { 113 u_char sc_recal; /* recalibrate state */ 114 u_char sc_doseeks; /* perform explicit seeks */ 115 int sc_state; /* open fsm */ 116 long sc_openpart; /* bit mask of open subunits */ 117 long sc_copenpart; /* bit mask of open character subunits */ 118 long sc_bopenpart; /* bit mask of open block subunits */ 119 daddr_t sc_mlsize; /* ML11 size */ 120 int sc_blkdone; /* amount sucessfully transfered */ 121 daddr_t sc_badbn; /* replacement block number */ 122 } hpsoftc[NHP]; 123 124 /* 125 * Drive states. Used during steps of open/initialization. 126 * States < OPEN (> 0) are transient, during an open operation. 127 * OPENRAW is used for unlabeled disks, 128 * to inhibit bad-sector forwarding or allow format operations. 129 */ 130 #define CLOSED 0 /* disk is closed. */ 131 #define WANTOPEN 1 /* open requested, not started */ 132 #define WANTOPENRAW 2 /* open requested, no label */ 133 #define RDLABEL 3 /* reading pack label */ 134 #define RDBADTBL 4 /* reading bad-sector table */ 135 #define OPEN 5 /* initialized and ready */ 136 #define OPENRAW 6 /* open, no label or badsect */ 137 138 #define b_cylin b_resid 139 140 /* #define ML11 0 to remove ML11 support */ 141 #define ML11(type) ((type) == HPDT_ML11A) 142 #define RP06(type) (hptypes[type] <= MBDT_RP06) 143 #define RM80(type) ((type) == HPDT_RM80) 144 145 #define hpunit(dev) (minor(dev) >> 3) 146 #define hppart(dev) (minor(dev) & 07) 147 #define hpminor(unit, part) (((unit) << 3) | (part)) 148 149 #define MASKREG(reg) ((reg)&0xffff) 150 #ifdef lint 151 #define HPWAIT(mi, addr) (hpwait(mi)) 152 #else 153 #define HPWAIT(mi, addr) (((addr)->hpds & HPDS_DRY) || hpwait(mi)) 154 #endif 155 156 /*ARGSUSED*/ 157 hpattach(mi, slave) 158 struct mba_device *mi; 159 { 160 register int unit = mi->mi_unit; 161 162 /* 163 * Try to initialize device and read pack label. 164 */ 165 if (hpinit(hpminor(unit, 0), 0) == 0) { 166 printf(": %s", hplabel[unit].d_typename); 167 #ifdef notyet 168 addswap(makedev(HPMAJOR, hpminor(unit, 0)), &hplabel[unit]); 169 #endif 170 } else 171 printf(": offline"); 172 } 173 174 hpopen(dev, flags, fmt) 175 dev_t dev; 176 int flags, fmt; 177 { 178 register int unit = hpunit(dev); 179 register struct hpsoftc *sc; 180 register struct disklabel *lp; 181 register struct partition *pp; 182 struct mba_device *mi; 183 int s, error, part = hppart(dev), mask = 1 << part; 184 daddr_t start, end; 185 186 if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0) 187 return (ENXIO); 188 sc = &hpsoftc[unit]; 189 lp = &hplabel[unit]; 190 191 s = spl5(); 192 while (sc->sc_state != OPEN && sc->sc_state != OPENRAW && 193 sc->sc_state != CLOSED) 194 sleep ((caddr_t)sc, PZERO+1); 195 splx(s); 196 if (sc->sc_state != OPEN && sc->sc_state != OPENRAW) 197 if (error = hpinit(dev, flags)) 198 return (error); 199 if (part >= lp->d_npartitions) 200 return (ENXIO); 201 /* 202 * Warn if a partion is opened 203 * that overlaps another partition which is open 204 * unless one is the "raw" partition (whole disk). 205 */ 206 #define RAWPART 2 /* 'c' partition */ /* XXX */ 207 if ((sc->sc_openpart & (1 << part)) == 0 && 208 part != RAWPART) { 209 pp = &lp->d_partitions[part]; 210 start = pp->p_offset; 211 end = pp->p_offset + pp->p_size; 212 for (pp = lp->d_partitions; 213 pp < &lp->d_partitions[lp->d_npartitions]; pp++) { 214 if (pp->p_offset + pp->p_size <= start || 215 pp->p_offset >= end) 216 continue; 217 if (pp - lp->d_partitions == RAWPART) 218 continue; 219 if (sc->sc_openpart & (1 << (pp - lp->d_partitions))) 220 log(LOG_WARNING, 221 "hp%d%c: overlaps open partition (%c)\n", 222 unit, part + 'a', 223 pp - lp->d_partitions + 'a'); 224 } 225 } 226 switch (fmt) { 227 case S_IFCHR: 228 sc->sc_copenpart |= mask; 229 break; 230 case S_IFBLK: 231 sc->sc_bopenpart |= mask; 232 break; 233 } 234 sc->sc_openpart |= mask; 235 return (0); 236 } 237 238 hpclose(dev, flags, fmt) 239 dev_t dev; 240 int flags, fmt; 241 { 242 register int unit = hpunit(dev); 243 register struct hpsoftc *sc; 244 struct mba_device *mi; 245 int s, mask = 1 << hppart(dev); 246 247 sc = &hpsoftc[unit]; 248 mi = hpinfo[unit]; 249 switch (fmt) { 250 case S_IFCHR: 251 sc->sc_copenpart &= ~mask; 252 break; 253 case S_IFBLK: 254 sc->sc_bopenpart &= ~mask; 255 break; 256 } 257 if (((sc->sc_copenpart | sc->sc_bopenpart) & mask) == 0) 258 sc->sc_openpart &= ~mask; 259 /* 260 * Should wait for I/O to complete on this partition 261 * even if others are open, but wait for work on blkflush(). 262 */ 263 if (sc->sc_openpart == 0) { 264 s = spl5(); 265 while (mi->mi_tab.b_actf) 266 sleep((caddr_t)sc, PZERO - 1); 267 splx(s); 268 sc->sc_state = CLOSED; 269 } 270 return (0); 271 } 272 273 hpinit(dev, flags) 274 dev_t dev; 275 int flags; 276 { 277 register struct hpsoftc *sc; 278 register struct buf *bp; 279 register struct disklabel *lp; 280 struct mba_device *mi; 281 struct hpdevice *hpaddr; 282 struct dkbad *db; 283 char *msg, *readdisklabel(); 284 int unit, i, error = 0; 285 extern int cold; 286 287 unit = hpunit(dev); 288 sc = &hpsoftc[unit]; 289 lp = &hplabel[unit]; 290 mi = hpinfo[unit]; 291 hpaddr = (struct hpdevice *)mi->mi_drv; 292 293 sc->sc_state = WANTOPEN; 294 /* 295 * Use the default sizes until we've read the label, 296 * or longer if there isn't one there. 297 */ 298 lp->d_secsize = DEV_BSIZE; 299 lp->d_nsectors = 32; 300 lp->d_ntracks = 20; 301 lp->d_secpercyl = 32*20; 302 303 if (flags & O_NDELAY) 304 goto raw; 305 306 /* 307 * Map all ML11's to the same type. Also calculate 308 * transfer rates based on device characteristics. 309 * Set up dummy label with all that's needed. 310 */ 311 if (mi->mi_type == MBDT_ML11A || mi->mi_type == MBDT_ML11B) { 312 register struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 313 register int trt; 314 315 sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ; 316 if ((hpaddr->hpmr & HPMR_ARRTYP) == 0) 317 sc->sc_mlsize >>= 2; 318 if (mi->mi_dk >= 0) { 319 trt = (hpaddr->hpmr & HPMR_TRT) >> 8; 320 dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt)); 321 } 322 mi->mi_type = MBDT_ML11A; 323 lp->d_partitions[0].p_size = sc->sc_mlsize; 324 lp->d_secpercyl = sc->sc_mlsize; 325 goto raw; 326 } 327 328 /* 329 * Preset, pack acknowledge will be done in hpstart 330 * during first read operation. 331 */ 332 if (msg = readdisklabel(dev, hpstrategy, lp)) { 333 if (cold) 334 printf(": %s", msg); 335 else 336 log(LOG_ERR, "hp%d: %s\n", unit, msg); 337 #ifdef COMPAT_42 338 mi->mi_type = hpmaptype(mi, lp); 339 #else 340 goto raw; 341 #endif 342 } 343 344 /* 345 * Seconds per word = (60 / rpm) / (nsectors * secsize/2) 346 */ 347 if (mi->mi_dk >= 0 && lp->d_rpm) 348 dk_mspw[mi->mi_dk] = 120.0 / 349 (lp->d_rpm * lp->d_nsectors * lp->d_secsize); 350 /* 351 * Read bad sector table into memory. 352 */ 353 bp = geteblk(DEV_BSIZE); /* max sector size */ 354 bp->b_dev = dev; 355 sc->sc_state = RDBADTBL; 356 i = 0; 357 do { 358 u.u_error = 0; /* XXX */ 359 bp->b_flags = B_BUSY | B_READ; 360 bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i; 361 bp->b_bcount = lp->d_secsize; 362 bp->b_cylin = lp->d_ncylinders - 1; 363 hpstrategy(bp); 364 biowait(bp); 365 } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 && 366 i < lp->d_nsectors); 367 db = (struct dkbad *)(bp->b_un.b_addr); 368 if ((bp->b_flags & B_ERROR) == 0 && db->bt_mbz == 0 && 369 db->bt_flag == 0) { 370 hpbad[unit] = *db; 371 sc->sc_state = OPEN; 372 } else { 373 log(LOG_ERR, "hp%d: %s bad-sector file\n", unit, 374 (bp->b_flags & B_ERROR) ? "can't read" : "format error in"); 375 u.u_error = 0; /* XXX */ 376 sc->sc_state = OPENRAW; 377 } 378 bp->b_flags = B_INVAL | B_AGE; 379 brelse(bp); 380 done: 381 wakeup((caddr_t)sc); 382 return (error); 383 384 raw: 385 sc->sc_state = OPENRAW; 386 wakeup((caddr_t)sc); 387 return (error); 388 } 389 390 hpstrategy(bp) 391 register struct buf *bp; 392 { 393 register struct mba_device *mi; 394 register struct disklabel *lp; 395 register struct hpsoftc *sc; 396 register int unit; 397 daddr_t sz, maxsz; 398 int xunit = hppart(bp->b_dev); 399 int s; 400 401 sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 402 unit = hpunit(bp->b_dev); 403 if (unit >= NHP) { 404 bp->b_error = ENXIO; 405 goto bad; 406 } 407 mi = hpinfo[unit]; 408 sc = &hpsoftc[unit]; 409 lp = &hplabel[unit]; 410 if (mi == 0 || mi->mi_alive == 0) { 411 bp->b_error = ENXIO; 412 goto bad; 413 } 414 if (sc->sc_state < OPEN) 415 goto q; 416 if ((sc->sc_openpart & (1 << xunit)) == 0) { 417 bp->b_error = ENODEV; 418 goto bad; 419 } 420 maxsz = lp->d_partitions[xunit].p_size; 421 if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { 422 if (bp->b_blkno == maxsz) { 423 bp->b_resid = bp->b_bcount; 424 goto done; 425 } 426 sz = maxsz - bp->b_blkno; 427 if (sz <= 0) { 428 bp->b_error = EINVAL; 429 goto bad; 430 } 431 bp->b_bcount = sz << DEV_BSHIFT; 432 } 433 bp->b_cylin = (bp->b_blkno + lp->d_partitions[xunit].p_offset) / 434 lp->d_secpercyl; 435 q: 436 s = spl5(); 437 disksort(&mi->mi_tab, bp); 438 if (mi->mi_tab.b_active == 0) 439 mbustart(mi); 440 splx(s); 441 return; 442 443 bad: 444 bp->b_flags |= B_ERROR; 445 done: 446 biodone(bp); 447 return; 448 } 449 450 hpustart(mi) 451 register struct mba_device *mi; 452 { 453 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 454 register struct buf *bp = mi->mi_tab.b_actf; 455 register struct disklabel *lp; 456 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 457 daddr_t bn; 458 int sn, tn, dist; 459 460 lp = &hplabel[mi->mi_unit]; 461 hpaddr->hpcs1 = 0; 462 if ((hpaddr->hpcs1&HP_DVA) == 0) 463 return (MBU_BUSY); 464 465 switch (sc->sc_recal) { 466 467 case 1: 468 (void)HPWAIT(mi, hpaddr); 469 hpaddr->hpdc = bp->b_cylin; 470 hpaddr->hpcs1 = HP_SEEK|HP_GO; 471 sc->sc_recal++; 472 return (MBU_STARTED); 473 case 2: 474 break; 475 } 476 sc->sc_recal = 0; 477 if ((hpaddr->hpds & HPDS_VV) == 0) { 478 if (sc->sc_state == OPEN && lp->d_flags & D_REMOVABLE) { 479 if (sc->sc_openpart) 480 log(LOG_ERR, "hp%d: volume changed\n", 481 mi->mi_unit); 482 sc->sc_openpart = 0; 483 bp->b_flags |= B_ERROR; 484 return (MBU_NEXT); 485 } 486 hpaddr->hpcs1 = HP_DCLR|HP_GO; 487 if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive)) 488 printf("DCLR attn\n"); 489 hpaddr->hpcs1 = HP_PRESET|HP_GO; 490 if (!ML11(mi->mi_type)) 491 hpaddr->hpof = HPOF_FMT22; 492 mbclrattn(mi); 493 if (sc->sc_state == WANTOPENRAW) { 494 sc->sc_state = OPENRAW; 495 return (MBU_NEXT); 496 } 497 if (sc->sc_state == WANTOPEN) 498 sc->sc_state = RDLABEL; 499 } 500 if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) { 501 if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags & B_READ)) { 502 hpaddr->hpof = 503 hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22; 504 hpaddr->hpcs1 = HP_OFFSET|HP_GO; 505 (void)HPWAIT(mi, hpaddr); 506 mbclrattn(mi); 507 } 508 return (MBU_DODATA); 509 } 510 if (ML11(mi->mi_type)) 511 return (MBU_DODATA); 512 if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY) 513 return (MBU_DODATA); 514 bn = bp->b_blkno; 515 sn = bn % lp->d_secpercyl; 516 tn = sn / lp->d_nsectors; 517 sn = sn % lp->d_nsectors; 518 if (bp->b_cylin == MASKREG(hpaddr->hpdc)) { 519 if (sc->sc_doseeks) 520 return (MBU_DODATA); 521 dist = sn - (MASKREG(hpaddr->hpla) >> 6) - 1; 522 if (dist < 0) 523 dist += lp->d_nsectors; 524 if (dist <= lp->d_maxdist && dist >= lp->d_mindist) 525 return (MBU_DODATA); 526 } else 527 hpaddr->hpdc = bp->b_cylin; 528 if (sc->sc_doseeks) 529 hpaddr->hpcs1 = HP_SEEK|HP_GO; 530 else { 531 sn = (sn + lp->d_nsectors - lp->d_sdist) % lp->d_nsectors; 532 hpaddr->hpda = (tn << 8) + sn; 533 hpaddr->hpcs1 = HP_SEARCH|HP_GO; 534 } 535 return (MBU_STARTED); 536 } 537 538 hpstart(mi) 539 register struct mba_device *mi; 540 { 541 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 542 register struct buf *bp = mi->mi_tab.b_actf; 543 register struct disklabel *lp = &hplabel[mi->mi_unit]; 544 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 545 daddr_t bn; 546 int sn, tn, cn; 547 548 if (ML11(mi->mi_type)) 549 hpaddr->hpda = bp->b_blkno + sc->sc_blkdone; 550 else { 551 if (bp->b_flags & B_BAD) { 552 bn = sc->sc_badbn; 553 cn = bn / lp->d_secpercyl; 554 } else { 555 bn = bp->b_blkno; 556 cn = bp->b_cylin; 557 } 558 sn = bn % lp->d_secpercyl; 559 if ((bp->b_flags & B_BAD) == 0) 560 sn += sc->sc_blkdone; 561 tn = sn / lp->d_nsectors; 562 sn %= lp->d_nsectors; 563 cn += tn / lp->d_ntracks; 564 tn %= lp->d_ntracks; 565 hpaddr->hpda = (tn << 8) + sn; 566 hpaddr->hpdc = cn; 567 } 568 mi->mi_tab.b_bdone = dbtob(sc->sc_blkdone); 569 if (bp->b_flags & B_FORMAT) { 570 if (bp->b_flags & B_READ) 571 return (HP_RHDR|HP_GO); 572 else 573 return (HP_WHDR|HP_GO); 574 } 575 return (0); 576 } 577 578 hpdtint(mi, mbsr) 579 register struct mba_device *mi; 580 int mbsr; 581 { 582 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 583 register struct buf *bp = mi->mi_tab.b_actf; 584 register int er1, er2; 585 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 586 int retry = 0; 587 int npf; 588 daddr_t bn; 589 int bcr; 590 591 bcr = MASKREG(-mi->mi_mba->mba_bcr); 592 if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) { 593 er1 = hpaddr->hper1; 594 er2 = hpaddr->hper2; 595 if (bp->b_flags & B_BAD) { 596 npf = bp->b_error; 597 bn = sc->sc_badbn; 598 } else { 599 npf = btop(bp->b_bcount - bcr); 600 if (er1 & (HPER1_DCK | HPER1_ECH)) 601 npf--; 602 bn = bp->b_blkno + npf; 603 } 604 if (HPWAIT(mi, hpaddr) == 0) 605 goto hard; 606 #ifdef HPDEBUG 607 if (hpdebug) { 608 int dc = hpaddr->hpdc, da = hpaddr->hpda; 609 610 log(LOG_DEBUG, 611 "hperr: bp %x cyl %d blk %d blkdone %d as %o dc %x da %x\n", 612 bp, bp->b_cylin, bn, sc->sc_blkdone, 613 hpaddr->hpas&0xff, MASKREG(dc), MASKREG(da)); 614 log(LOG_DEBUG, 615 "errcnt %d mbsr=%b er1=%b er2=%b bcr -%d\n", 616 mi->mi_tab.b_errcnt, mbsr, mbsr_bits, 617 MASKREG(er1), HPER1_BITS, 618 MASKREG(er2), HPER2_BITS, bcr); 619 } 620 #endif 621 if (er1 & HPER1_HCRC) { 622 er1 &= ~(HPER1_HCE|HPER1_FER); 623 er2 &= ~HPER2_BSE; 624 } 625 if (er1 & HPER1_WLE) { 626 log(LOG_WARNING, "hp%d: write locked\n", 627 hpunit(bp->b_dev)); 628 bp->b_flags |= B_ERROR; 629 } else if (bp->b_flags & B_FORMAT) { 630 goto hard; 631 } else if (RM80(mi->mi_type) && er2&HPER2_SSE) { 632 (void) hpecc(mi, SSE); 633 return (MBD_RESTARTED); 634 } else if ((er2 & HPER2_BSE) && !ML11(mi->mi_type)) { 635 if (hpecc(mi, BSE)) 636 return (MBD_RESTARTED); 637 goto hard; 638 } else if (MASKREG(er1) == HPER1_FER && RP06(mi->mi_type)) { 639 if (hpecc(mi, BSE)) 640 return (MBD_RESTARTED); 641 goto hard; 642 } else if ((er1 & (HPER1_DCK | HPER1_ECH)) == HPER1_DCK && 643 mi->mi_tab.b_errcnt >= 3) { 644 if (hpecc(mi, ECC)) 645 return (MBD_RESTARTED); 646 /* 647 * ECC corrected. Only log retries below 648 * if we got errors other than soft ECC 649 * (as indicated by additional retries). 650 */ 651 if (mi->mi_tab.b_errcnt == 3) 652 mi->mi_tab.b_errcnt = 0; 653 } else if ((er1 & HPER1_HCRC) && !ML11(mi->mi_type) && 654 hpecc(mi, BSE)) { 655 /* 656 * HCRC means the header is screwed up and the sector 657 * might well exist in the bad sector table, 658 * better check.... 659 */ 660 return (MBD_RESTARTED); 661 } else if (++mi->mi_tab.b_errcnt > 27 || 662 (ML11(mi->mi_type) && mi->mi_tab.b_errcnt > 15) || 663 mbsr & MBSR_HARD || 664 er1 & HPER1_HARD || 665 (!ML11(mi->mi_type) && (er2 & HPER2_HARD))) { 666 hard: 667 bp->b_blkno = bn; /* XXX */ 668 harderr(bp, "hp"); 669 if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC))) 670 printf("mbsr=%b ", mbsr, mbsr_bits); 671 printf("er1=%b er2=%b", 672 MASKREG(hpaddr->hper1), HPER1_BITS, 673 MASKREG(hpaddr->hper2), HPER2_BITS); 674 if (bp->b_flags & B_FORMAT) 675 printf(" (hdr i/o)"); 676 printf("\n"); 677 bp->b_flags |= B_ERROR; 678 bp->b_flags &= ~B_BAD; 679 } else 680 retry = 1; 681 hpaddr->hpcs1 = HP_DCLR|HP_GO; 682 if (retry && (mi->mi_tab.b_errcnt & 07) == 4) { 683 hpaddr->hpcs1 = HP_RECAL|HP_GO; 684 sc->sc_recal = 1; 685 return (MBD_REPOSITION); 686 } 687 } 688 #ifdef HPDEBUG 689 else 690 if (hpdebug && sc->sc_recal) { 691 log(LOG_DEBUG, 692 "recal %d errcnt %d mbsr=%b er1=%b er2=%b\n", 693 sc->sc_recal, mi->mi_tab.b_errcnt, mbsr, mbsr_bits, 694 hpaddr->hper1, HPER1_BITS, 695 hpaddr->hper2, HPER2_BITS); 696 } 697 #endif 698 (void)HPWAIT(mi, hpaddr); 699 if (retry) 700 return (MBD_RETRY); 701 if (mi->mi_tab.b_errcnt >= 16) { 702 /* 703 * This is fast and occurs rarely; we don't 704 * bother with interrupts. 705 */ 706 hpaddr->hpcs1 = HP_RTC|HP_GO; 707 (void)HPWAIT(mi, hpaddr); 708 mbclrattn(mi); 709 } 710 if (mi->mi_tab.b_errcnt && (bp->b_flags & B_ERROR) == 0) 711 log(LOG_INFO, "hp%d%c: %d retries %sing sn%d\n", 712 hpunit(bp->b_dev), 'a'+(minor(bp->b_dev)&07), 713 mi->mi_tab.b_errcnt, 714 (bp->b_flags & B_READ) ? "read" : "writ", 715 (bp->b_flags & B_BAD) ? 716 sc->sc_badbn : bp->b_blkno + sc->sc_blkdone); 717 if ((bp->b_flags & B_BAD) && hpecc(mi, CONT)) 718 return (MBD_RESTARTED); 719 sc->sc_blkdone = 0; 720 bp->b_resid = bcr; 721 if (!ML11(mi->mi_type)) { 722 hpaddr->hpof = HPOF_FMT22; 723 hpaddr->hpcs1 = HP_RELEASE|HP_GO; 724 } 725 if (sc->sc_openpart == 0) 726 wakeup((caddr_t)sc); 727 return (MBD_DONE); 728 } 729 730 /* 731 * Wait (for a bit) for a drive to come ready; 732 * returns nonzero on success. 733 */ 734 hpwait(mi) 735 register struct mba_device *mi; 736 { 737 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 738 register i = 100000; 739 740 while ((hpaddr->hpds & HPDS_DRY) == 0 && --i) 741 DELAY(10); 742 if (i == 0) 743 printf("hp%d: intr, not ready\n", mi->mi_unit); 744 return (i); 745 } 746 747 hpread(dev, uio) 748 dev_t dev; 749 struct uio *uio; 750 { 751 register int unit = hpunit(dev); 752 753 if (unit >= NHP) 754 return (ENXIO); 755 return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio)); 756 } 757 758 hpwrite(dev, uio) 759 dev_t dev; 760 struct uio *uio; 761 { 762 register int unit = hpunit(dev); 763 764 if (unit >= NHP) 765 return (ENXIO); 766 return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio)); 767 } 768 769 hpioctl(dev, cmd, data, flag) 770 dev_t dev; 771 int cmd; 772 caddr_t data; 773 int flag; 774 { 775 int unit = hpunit(dev); 776 register struct disklabel *lp; 777 register struct format_op *fop; 778 int error = 0; 779 int hpformat(); 780 781 lp = &hplabel[unit]; 782 783 switch (cmd) { 784 785 case DIOCGDINFO: 786 *(struct disklabel *)data = *lp; 787 break; 788 789 case DIOCGPART: 790 ((struct partinfo *)data)->disklab = lp; 791 ((struct partinfo *)data)->part = 792 &lp->d_partitions[hppart(dev)]; 793 break; 794 795 case DIOCSDINFO: 796 if ((flag & FWRITE) == 0) 797 error = EBADF; 798 else 799 *lp = *(struct disklabel *)data; 800 break; 801 802 case DIOCWDINFO: 803 if ((flag & FWRITE) == 0) { 804 error = EBADF; 805 break; 806 } 807 { 808 struct buf *bp; 809 struct disklabel *dlp; 810 811 *lp = *(struct disklabel *)data; 812 bp = geteblk(lp->d_secsize); 813 bp->b_dev = makedev(major(dev), hpminor(hpunit(dev), 0)); 814 bp->b_blkno = LABELSECTOR; 815 bp->b_bcount = lp->d_secsize; 816 bp->b_flags = B_READ; 817 dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET); 818 hpstrategy(bp); 819 biowait(bp); 820 if (bp->b_flags & B_ERROR) { 821 error = u.u_error; /* XXX */ 822 u.u_error = 0; 823 goto bad; 824 } 825 *dlp = *lp; 826 bp->b_flags = B_WRITE; 827 hpstrategy(bp); 828 biowait(bp); 829 if (bp->b_flags & B_ERROR) { 830 error = u.u_error; /* XXX */ 831 u.u_error = 0; 832 } 833 bad: 834 brelse(bp); 835 } 836 break; 837 838 #ifdef notyet 839 case DIOCWFORMAT: 840 if ((flag & FWRITE) == 0) { 841 error = EBADF; 842 break; 843 } 844 { 845 struct uio auio; 846 struct iovec aiov; 847 848 fop = (struct format_op *)data; 849 aiov.iov_base = fop->df_buf; 850 aiov.iov_len = fop->df_count; 851 auio.uio_iov = &aiov; 852 auio.uio_iovcnt = 1; 853 auio.uio_resid = fop->df_count; 854 auio.uio_segflg = 0; 855 auio.uio_offset = fop->df_startblk * lp->d_secsize; 856 error = physio(hpformat, &rhpbuf[unit], dev, B_WRITE, 857 minphys, &auio); 858 fop->df_count -= auio.uio_resid; 859 fop->df_reg[0] = sc->sc_status; 860 fop->df_reg[1] = sc->sc_error; 861 } 862 break; 863 #endif 864 865 default: 866 error = ENOTTY; 867 break; 868 } 869 return (error); 870 } 871 872 hpformat(bp) 873 struct buf *bp; 874 { 875 876 bp->b_flags |= B_FORMAT; 877 return (hpstrategy(bp)); 878 } 879 880 hpecc(mi, flag) 881 register struct mba_device *mi; 882 int flag; 883 { 884 register struct mba_regs *mbp = mi->mi_mba; 885 register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; 886 register struct buf *bp = mi->mi_tab.b_actf; 887 register struct disklabel *lp = &hplabel[mi->mi_unit]; 888 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 889 int npf, o; 890 int bn, cn, tn, sn; 891 int bcr; 892 893 bcr = MASKREG(-mbp->mba_bcr); 894 if (bp->b_flags & B_BAD) 895 npf = bp->b_error; 896 else { 897 npf = bp->b_bcount - bcr; 898 /* 899 * Watch out for fractional sector at end of transfer; 900 * want to round up if finished, otherwise round down. 901 */ 902 if (bcr == 0) 903 npf += 511; 904 npf = btodb(npf); 905 } 906 o = (int)bp->b_un.b_addr & PGOFSET; 907 bn = bp->b_blkno; 908 cn = bp->b_cylin; 909 sn = bn % lp->d_secpercyl + npf; 910 tn = sn / lp->d_nsectors; 911 sn %= lp->d_nsectors; 912 cn += tn / lp->d_ntracks; 913 tn %= lp->d_ntracks; 914 bn += npf; 915 switch (flag) { 916 case ECC: { 917 register int i; 918 caddr_t addr; 919 struct pte mpte; 920 int bit, byte, mask; 921 922 npf--; /* because block in error is previous block */ 923 bn--; 924 if (bp->b_flags & B_BAD) 925 bn = sc->sc_badbn; 926 log(LOG_WARNING, "hp%d%c: soft ecc sn%d\n", hpunit(bp->b_dev), 927 'a'+(minor(bp->b_dev)&07), bn); 928 mask = MASKREG(rp->hpec2); 929 i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 930 bit = i&07; 931 i = (i&~07)>>3; 932 byte = i + o; 933 while (i < 512 && (int)dbtob(npf)+i < bp->b_bcount && bit > -11) { 934 mpte = mbp->mba_map[npf+btop(byte)]; 935 addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); 936 putmemc(addr, getmemc(addr)^(mask<<bit)); 937 byte++; 938 i++; 939 bit -= 8; 940 } 941 if (bcr == 0) 942 return (0); 943 npf++; 944 break; 945 } 946 947 case SSE: 948 rp->hpof |= HPOF_SSEI; 949 if (bp->b_flags & B_BAD) { 950 bn = sc->sc_badbn; 951 goto fixregs; 952 } 953 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 954 break; 955 956 case BSE: 957 if (sc->sc_state == OPENRAW) 958 return (0); 959 if (rp->hpof & HPOF_SSEI) 960 sn++; 961 #ifdef HPBDEBUG 962 if (hpbdebug) 963 log(LOG_DEBUG, "hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 964 #endif 965 if (bp->b_flags & B_BAD) 966 return (0); 967 if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0) 968 return (0); 969 bp->b_flags |= B_BAD; 970 bp->b_error = npf + 1; 971 rp->hpof &= ~HPOF_SSEI; 972 bn = lp->d_ncylinders * lp->d_secpercyl - 973 lp->d_nsectors - 1 - bn; 974 sc->sc_badbn = bn; 975 fixregs: 976 cn = bn / lp->d_secpercyl; 977 sn = bn % lp->d_secpercyl; 978 tn = sn / lp->d_nsectors; 979 sn %= lp->d_nsectors; 980 bcr = bp->b_bcount - (int)ptob(npf); 981 bcr = MIN(bcr, 512); 982 mbp->mba_bcr = -bcr; 983 #ifdef HPBDEBUG 984 if (hpbdebug) 985 log(LOG_DEBUG, "revector to cn %d tn %d sn %d\n", cn, tn, sn); 986 #endif 987 break; 988 989 case CONT: 990 #ifdef HPBDEBUG 991 if (hpbdebug) 992 log(LOG_DEBUG, "hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 993 #endif 994 bp->b_flags &= ~B_BAD; 995 if ((int)ptob(npf) >= bp->b_bcount) 996 return (0); 997 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 998 break; 999 } 1000 rp->hpcs1 = HP_DCLR|HP_GO; 1001 if (rp->hpof & HPOF_SSEI) 1002 sn++; 1003 rp->hpdc = cn; 1004 rp->hpda = (tn<<8) + sn; 1005 mbp->mba_sr = -1; 1006 mbp->mba_var = (int)ptob(npf) + o; 1007 rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO; 1008 mi->mi_tab.b_errcnt = 0; /* error has been corrected */ 1009 sc->sc_blkdone = npf; 1010 return (1); 1011 } 1012 1013 #define DBSIZE 20 1014 1015 hpdump(dev) 1016 dev_t dev; 1017 { 1018 register struct mba_device *mi; 1019 register struct mba_regs *mba; 1020 struct hpdevice *hpaddr; 1021 char *start; 1022 int num, unit; 1023 register struct disklabel *lp; 1024 1025 num = maxfree; 1026 start = 0; 1027 unit = hpunit(dev); 1028 if (unit >= NHP) 1029 return (ENXIO); 1030 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 1031 mi = phys(hpinfo[unit],struct mba_device *); 1032 if (mi == 0 || mi->mi_alive == 0) 1033 return (ENXIO); 1034 lp = &hplabel[unit]; 1035 mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 1036 mba->mba_cr = MBCR_INIT; 1037 hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; 1038 if ((hpaddr->hpds & HPDS_VV) == 0) { 1039 hpaddr->hpcs1 = HP_DCLR|HP_GO; 1040 hpaddr->hpcs1 = HP_PRESET|HP_GO; 1041 hpaddr->hpof = HPOF_FMT22; 1042 } 1043 if (dumplo < 0) 1044 return (EINVAL); 1045 if (dumplo + num >= lp->d_partitions[hppart(dev)].p_size) 1046 num = lp->d_partitions[hppart(dev)].p_size - dumplo; 1047 while (num > 0) { 1048 register struct pte *hpte = mba->mba_map; 1049 register int i; 1050 int blk, cn, sn, tn; 1051 daddr_t bn; 1052 1053 blk = num > DBSIZE ? DBSIZE : num; 1054 bn = dumplo + btop(start); 1055 cn = (bn + lp->d_partitions[hppart(dev)].p_offset) / 1056 lp->d_secpercyl; 1057 sn = bn % lp->d_secpercyl; 1058 tn = sn / lp->d_nsectors; 1059 sn = sn % lp->d_nsectors; 1060 hpaddr->hpdc = cn; 1061 hpaddr->hpda = (tn << 8) + sn; 1062 for (i = 0; i < blk; i++) 1063 *(int *)hpte++ = (btop(start)+i) | PG_V; 1064 mba->mba_sr = -1; 1065 mba->mba_bcr = -(blk*NBPG); 1066 mba->mba_var = 0; 1067 hpaddr->hpcs1 = HP_WCOM | HP_GO; 1068 while ((hpaddr->hpds & HPDS_DRY) == 0) 1069 DELAY(10); 1070 if (hpaddr->hpds&HPDS_ERR) 1071 return (EIO); 1072 start += blk*NBPG; 1073 num -= blk; 1074 } 1075 return (0); 1076 } 1077 1078 hpsize(dev) 1079 dev_t dev; 1080 { 1081 register int unit = hpunit(dev); 1082 struct mba_device *mi; 1083 1084 if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0 || 1085 hpsoftc[unit].sc_state != OPEN) 1086 return (-1); 1087 return ((int)hplabel[unit].d_partitions[hppart(dev)].p_size); 1088 } 1089 1090 #ifdef COMPAT_42 1091 /* 1092 * Compatibility code to fake up pack label 1093 * for unlabeled disks. 1094 */ 1095 struct size { 1096 daddr_t nblocks; 1097 int cyloff; 1098 } rp06_sizes[8] = { 1099 15884, 0, /* A=cyl 0 thru 37 */ 1100 33440, 38, /* B=cyl 38 thru 117 */ 1101 340670, 0, /* C=cyl 0 thru 814 */ 1102 15884, 118, /* D=cyl 118 thru 155 */ 1103 55936, 156, /* E=cyl 156 thru 289 */ 1104 219384, 290, /* F=cyl 290 thru 814 */ 1105 291192, 118, /* G=cyl 118 thru 814 */ 1106 0, 0, 1107 }, rp05_sizes[8] = { 1108 15884, 0, /* A=cyl 0 thru 37 */ 1109 33440, 38, /* B=cyl 38 thru 117 */ 1110 171798, 0, /* C=cyl 0 thru 410 */ 1111 15884, 118, /* D=cyl 118 thru 155 */ 1112 55936, 156, /* E=cyl 156 thru 289 */ 1113 50512, 290, /* F=cyl 290 thru 410 */ 1114 122408, 118, /* G=cyl 118 thru 410 */ 1115 0, 0, 1116 }, rm03_sizes[8] = { 1117 15884, 0, /* A=cyl 0 thru 99 */ 1118 33440, 100, /* B=cyl 100 thru 308 */ 1119 131680, 0, /* C=cyl 0 thru 822 */ 1120 15884, 309, /* D=cyl 309 thru 408 */ 1121 55936, 409, /* E=cyl 409 thru 758 */ 1122 10144, 759, /* F=cyl 759 thru 822 */ 1123 82144, 309, /* G=cyl 309 thru 822 */ 1124 0, 0, 1125 }, rm05_sizes[8] = { 1126 15884, 0, /* A=cyl 0 thru 26 */ 1127 33440, 27, /* B=cyl 27 thru 81 */ 1128 500384, 0, /* C=cyl 0 thru 822 */ 1129 15884, 562, /* D=cyl 562 thru 588 */ 1130 55936, 589, /* E=cyl 589 thru 680 */ 1131 86240, 681, /* F=cyl 681 thru 822 */ 1132 158592, 562, /* G=cyl 562 thru 822 */ 1133 291346, 82, /* H=cyl 82 thru 561 */ 1134 }, rm80_sizes[8] = { 1135 15884, 0, /* A=cyl 0 thru 36 */ 1136 33440, 37, /* B=cyl 37 thru 114 */ 1137 242606, 0, /* C=cyl 0 thru 558 */ 1138 15884, 115, /* D=cyl 115 thru 151 */ 1139 55936, 152, /* E=cyl 152 thru 280 */ 1140 120559, 281, /* F=cyl 281 thru 558 */ 1141 192603, 115, /* G=cyl 115 thru 558 */ 1142 0, 0, 1143 }, rp07_sizes[8] = { 1144 15884, 0, /* A=cyl 0 thru 9 */ 1145 66880, 10, /* B=cyl 10 thru 51 */ 1146 1008000, 0, /* C=cyl 0 thru 629 */ 1147 15884, 235, /* D=cyl 235 thru 244 */ 1148 307200, 245, /* E=cyl 245 thru 436 */ 1149 308650, 437, /* F=cyl 437 thru 629 */ 1150 631850, 235, /* G=cyl 235 thru 629 */ 1151 291346, 52, /* H=cyl 52 thru 234 */ 1152 }, cdc9775_sizes[8] = { 1153 15884, 0, /* A=cyl 0 thru 12 */ 1154 66880, 13, /* B=cyl 13 thru 65 */ 1155 1077760, 0, /* C=cyl 0 thru 841 */ 1156 15884, 294, /* D=cyl 294 thru 306 */ 1157 307200, 307, /* E=cyl 307 thru 546 */ 1158 377440, 547, /* F=cyl 547 thru 841 */ 1159 701280, 294, /* G=cyl 294 thru 841 */ 1160 291346, 66, /* H=cyl 66 thru 293 */ 1161 }, cdc9730_sizes[8] = { 1162 15884, 0, /* A=cyl 0 thru 49 */ 1163 33440, 50, /* B=cyl 50 thru 154 */ 1164 263360, 0, /* C=cyl 0 thru 822 */ 1165 15884, 155, /* D=cyl 155 thru 204 */ 1166 55936, 205, /* E=cyl 205 thru 379 */ 1167 141664, 380, /* F=cyl 380 thru 822 */ 1168 213664, 155, /* G=cyl 155 thru 822 */ 1169 0, 0, 1170 }, capricorn_sizes[8] = { 1171 15884, 0, /* A=cyl 0 thru 31 */ 1172 33440, 32, /* B=cyl 32 thru 97 */ 1173 524288, 0, /* C=cyl 0 thru 1023 */ 1174 15884, 668, /* D=cyl 668 thru 699 */ 1175 55936, 700, /* E=cyl 700 thru 809 */ 1176 109472, 810, /* F=cyl 810 thru 1023 */ 1177 182176, 668, /* G=cyl 668 thru 1023 */ 1178 291346, 98, /* H=cyl 98 thru 667 */ 1179 }, eagle_sizes[8] = { 1180 15884, 0, /* A=cyl 0 thru 16 */ 1181 66880, 17, /* B=cyl 17 thru 86 */ 1182 808320, 0, /* C=cyl 0 thru 841 */ 1183 15884, 391, /* D=cyl 391 thru 407 */ 1184 307200, 408, /* E=cyl 408 thru 727 */ 1185 109296, 728, /* F=cyl 728 thru 841 */ 1186 432816, 391, /* G=cyl 391 thru 841 */ 1187 291346, 87, /* H=cyl 87 thru 390 */ 1188 }, ampex_sizes[8] = { 1189 15884, 0, /* A=cyl 0 thru 26 */ 1190 33440, 27, /* B=cyl 27 thru 81 */ 1191 495520, 0, /* C=cyl 0 thru 814 */ 1192 15884, 562, /* D=cyl 562 thru 588 */ 1193 55936, 589, /* E=cyl 589 thru 680 */ 1194 81312, 681, /* F=cyl 681 thru 814 */ 1195 153664, 562, /* G=cyl 562 thru 814 */ 1196 291346, 82, /* H=cyl 82 thru 561 */ 1197 }, fj2361_sizes[8] = { 1198 15884, 0, /* A=cyl 0 thru 12 */ 1199 66880, 13, /* B=cyl 13 thru 65 */ 1200 1077760, 0, /* C=cyl 0 thru 841 */ 1201 15884, 294, /* D=cyl 294 thru 306 */ 1202 307200, 307, /* E=cyl 307 thru 546 */ 1203 377408, 547, /* F=cyl 547 thru 841 */ 1204 701248, 294, /* G=cyl 294 thru 841 */ 1205 291346, 66, /* H=cyl 66 thru 293 */ 1206 }; 1207 1208 /* 1209 * These variable are all measured in sectors. 1210 * Sdist is how much to "lead" in the search for a desired sector 1211 * (i.e. if want N, search for N-sdist.) 1212 * Maxdist and mindist define the region right before our desired sector within 1213 * which we don't bother searching. We don't search when we are already less 1214 * then maxdist and more than mindist sectors "before" our desired sector. 1215 * Maxdist should be >= sdist. 1216 * 1217 * Beware, sdist, mindist and maxdist are not well tuned 1218 * for many of the drives listed in this table. 1219 * Try patching things with something i/o intensive 1220 * running and watch iostat. 1221 */ 1222 struct hpst { 1223 short nsect; /* # sectors/track */ 1224 short ntrak; /* # tracks/cylinder */ 1225 short nspc; /* # sector/cylinders */ 1226 short ncyl; /* # cylinders */ 1227 struct size *sizes; /* partition tables */ 1228 short sdist; /* seek distance metric */ 1229 short maxdist; /* boundaries of non-searched area */ 1230 short mindist; /* preceding the target sector */ 1231 char *name; /* name of disk type */ 1232 } hpst[] = { 1233 { 32, 5, 32*5, 823, rm03_sizes, 7, 4, 1, "RM03" }, 1234 { 32, 19, 32*19, 823, rm05_sizes, 7, 4, 1, "RM05" }, 1235 { 22,19, 22*19, 815, rp06_sizes, 7, 4, 1, "RP06"}, 1236 { 31, 14, 31*14, 559, rm80_sizes, 7, 4, 1, "RM80"}, 1237 { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP04"}, 1238 { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP05"}, 1239 { 50, 32, 50*32, 630, rp07_sizes, 15, 8, 3, "RP07"}, 1240 { 1, 1, 1, 1, 0, 0, 0, 0, "ML11A"}, 1241 { 1, 1, 1, 1, 0, 0, 0, 0, "ML11B" }, 1242 { 32, 40, 32*40, 843, cdc9775_sizes, 7, 4, 1, "9775" }, 1243 { 32, 10, 32*10, 823, cdc9730_sizes, 7, 4, 1, "9730-160" }, 1244 { 32, 16, 32*16, 1024, capricorn_sizes,10,4, 3, "capricorn" }, 1245 { 48, 20, 48*20, 842, eagle_sizes, 15, 8, 3, "eagle" }, 1246 { 32, 19, 32*19, 815, ampex_sizes, 7, 4, 1, "9300" }, 1247 { 64, 20, 64*20, 842, fj2361_sizes, 15, 8, 3, "2361" }, 1248 }; 1249 1250 /* 1251 * Map apparent MASSBUS drive type into manufacturer 1252 * specific configuration. For SI controllers this is done 1253 * based on codes in the serial number register. For 1254 * EMULEX controllers, the track and sector attributes are 1255 * used when the drive type is an RM02 (not supported by DEC). 1256 */ 1257 hpmaptype(mi, lp) 1258 register struct mba_device *mi; 1259 register struct disklabel *lp; 1260 { 1261 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 1262 register int type = mi->mi_type; 1263 register struct hpst *st; 1264 register i; 1265 1266 /* 1267 * Model-byte processing for SI controllers. 1268 * NB: Only deals with RM03 and RM05 emulations. 1269 */ 1270 if (type == HPDT_RM03 || type == HPDT_RM05) { 1271 int hpsn = hpaddr->hpsn; 1272 1273 if ((hpsn & SIMB_LU) == mi->mi_drive) 1274 switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) { 1275 1276 case SI9775D: 1277 type = HPDT_9775; 1278 break; 1279 1280 case SI9730D: 1281 type = HPDT_9730; 1282 break; 1283 1284 case SI9766: 1285 type = HPDT_RM05; 1286 break; 1287 1288 case SI9762: 1289 type = HPDT_RM03; 1290 break; 1291 1292 case SICAPD: 1293 type = HPDT_CAPRICORN; 1294 break; 1295 1296 case SI9751D: 1297 type = HPDT_EAGLE; 1298 break; 1299 } 1300 } 1301 1302 /* 1303 * EMULEX SC750 or SC780. Poke the holding register. 1304 */ 1305 if (type == HPDT_RM02) { 1306 int nsectors, ntracks, ncyl; 1307 1308 hpaddr->hpof = HPOF_FMT22; 1309 mbclrattn(mi); 1310 hpaddr->hpcs1 = HP_NOP; 1311 hpaddr->hphr = HPHR_MAXTRAK; 1312 ntracks = MASKREG(hpaddr->hphr) + 1; 1313 DELAY(100); 1314 hpaddr->hpcs1 = HP_NOP; 1315 hpaddr->hphr = HPHR_MAXSECT; 1316 nsectors = MASKREG(hpaddr->hphr) + 1; 1317 DELAY(100); 1318 hpaddr->hpcs1 = HP_NOP; 1319 hpaddr->hphr = HPHR_MAXCYL; 1320 ncyl = MASKREG(hpaddr->hphr) + 1; 1321 for (type = 0; hptypes[type] != 0; type++) 1322 if (hpst[type].nsect == nsectors && 1323 hpst[type].ntrak == ntracks && 1324 hpst[type].ncyl == ncyl) 1325 break; 1326 1327 if (hptypes[type] == 0) { 1328 printf("hp%d: %d sectors, %d tracks, %d cylinders: unknown device\n", 1329 mi->mi_unit, nsectors, ntracks, ncyl); 1330 type = HPDT_RM02; 1331 } 1332 hpaddr->hpcs1 = HP_DCLR|HP_GO; 1333 mbclrattn(mi); /* conservative */ 1334 } 1335 1336 /* 1337 * set up minimal disk label. 1338 */ 1339 st = &hpst[type]; 1340 lp->d_secsize = 512; 1341 lp->d_nsectors = st->nsect; 1342 lp->d_ntracks = st->ntrak; 1343 lp->d_secpercyl = st->nspc; 1344 lp->d_ncylinders = st->ncyl; 1345 lp->d_secperunit = st->nspc * st->ncyl; 1346 lp->d_sdist = st->sdist; 1347 lp->d_mindist = st->mindist; 1348 lp->d_maxdist = st->maxdist; 1349 bcopy(hpst[type].name, lp->d_typename, sizeof(lp->d_typename)); 1350 lp->d_npartitions = 8; 1351 for (i = 0; i < 8; i++) { 1352 lp->d_partitions[i].p_offset = st->sizes[i].cyloff * 1353 lp->d_secpercyl; 1354 lp->d_partitions[i].p_size = st->sizes[i].nblocks; 1355 } 1356 return (type); 1357 } 1358 #endif COMPAT_42 1359 #endif 1360