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.4 (Berkeley) 04/02/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 if (flags & O_NDELAY) 294 sc->sc_state = WANTOPENRAW; 295 else 296 sc->sc_state = WANTOPEN; 297 /* 298 * Use the default sizes until we've read the label, 299 * or longer if there isn't one there. 300 */ 301 lp->d_secsize = DEV_BSIZE; 302 lp->d_nsectors = 32; 303 lp->d_ntracks = 20; 304 lp->d_secpercyl = 32*20; 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 sc->sc_state = WANTOPENRAW; 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 (sc->sc_state == OPENRAW) 334 goto done; 335 if (cold) 336 printf(": %s", msg); 337 else 338 log(LOG_ERR, "hp%d: %s\n", unit, msg); 339 #ifdef COMPAT_42 340 mi->mi_type = hpmaptype(mi, lp); 341 #else 342 sc->sc_state = OPENRAW; 343 goto done; 344 #endif 345 } 346 347 /* 348 * Seconds per word = (60 / rpm) / (nsectors * secsize/2) 349 */ 350 if (mi->mi_dk >= 0 && lp->d_rpm) 351 dk_mspw[mi->mi_dk] = 120.0 / 352 (lp->d_rpm * lp->d_nsectors * lp->d_secsize); 353 /* 354 * Read bad sector table into memory. 355 */ 356 bp = geteblk(DEV_BSIZE); /* max sector size */ 357 bp->b_dev = dev; 358 sc->sc_state = RDBADTBL; 359 i = 0; 360 do { 361 u.u_error = 0; /* XXX */ 362 bp->b_flags = B_BUSY | B_READ; 363 bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i; 364 bp->b_bcount = lp->d_secsize; 365 bp->b_cylin = lp->d_ncylinders - 1; 366 hpstrategy(bp); 367 biowait(bp); 368 } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 && 369 i < lp->d_nsectors); 370 db = (struct dkbad *)(bp->b_un.b_addr); 371 if ((bp->b_flags & B_ERROR) == 0 && db->bt_mbz == 0 && 372 db->bt_flag == 0) { 373 hpbad[unit] = *db; 374 sc->sc_state = OPEN; 375 } else { 376 log(LOG_ERR, "hp%d: %s bad-sector file\n", unit, 377 (bp->b_flags & B_ERROR) ? "can't read" : "format error in"); 378 u.u_error = 0; /* XXX */ 379 sc->sc_state = OPENRAW; 380 } 381 bp->b_flags = B_INVAL | B_AGE; 382 brelse(bp); 383 done: 384 wakeup((caddr_t)sc); 385 return (error); 386 } 387 388 hpstrategy(bp) 389 register struct buf *bp; 390 { 391 register struct mba_device *mi; 392 register struct disklabel *lp; 393 register struct hpsoftc *sc; 394 register int unit; 395 daddr_t sz, maxsz; 396 int xunit = hppart(bp->b_dev); 397 int s; 398 399 sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT; 400 unit = hpunit(bp->b_dev); 401 if (unit >= NHP) { 402 bp->b_error = ENXIO; 403 goto bad; 404 } 405 mi = hpinfo[unit]; 406 sc = &hpsoftc[unit]; 407 lp = &hplabel[unit]; 408 if (mi == 0 || mi->mi_alive == 0) { 409 bp->b_error = ENXIO; 410 goto bad; 411 } 412 if (sc->sc_state < OPEN) 413 goto q; 414 if ((sc->sc_openpart & (1 << xunit)) == 0) { 415 bp->b_error = ENODEV; 416 goto bad; 417 } 418 maxsz = lp->d_partitions[xunit].p_size; 419 if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) { 420 if (bp->b_blkno == maxsz) { 421 bp->b_resid = bp->b_bcount; 422 goto done; 423 } 424 sz = maxsz - bp->b_blkno; 425 if (sz <= 0) { 426 bp->b_error = EINVAL; 427 goto bad; 428 } 429 bp->b_bcount = sz << DEV_BSHIFT; 430 } 431 bp->b_cylin = (bp->b_blkno + lp->d_partitions[xunit].p_offset) / 432 lp->d_secpercyl; 433 q: 434 s = spl5(); 435 disksort(&mi->mi_tab, bp); 436 if (mi->mi_tab.b_active == 0) 437 mbustart(mi); 438 splx(s); 439 return; 440 441 bad: 442 bp->b_flags |= B_ERROR; 443 done: 444 biodone(bp); 445 return; 446 } 447 448 hpustart(mi) 449 register struct mba_device *mi; 450 { 451 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 452 register struct buf *bp = mi->mi_tab.b_actf; 453 register struct disklabel *lp; 454 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 455 daddr_t bn; 456 int sn, tn, dist; 457 458 lp = &hplabel[mi->mi_unit]; 459 hpaddr->hpcs1 = 0; 460 if ((hpaddr->hpcs1&HP_DVA) == 0) 461 return (MBU_BUSY); 462 463 switch (sc->sc_recal) { 464 465 case 1: 466 (void)HPWAIT(mi, hpaddr); 467 hpaddr->hpdc = bp->b_cylin; 468 hpaddr->hpcs1 = HP_SEEK|HP_GO; 469 sc->sc_recal++; 470 return (MBU_STARTED); 471 case 2: 472 break; 473 } 474 sc->sc_recal = 0; 475 if ((hpaddr->hpds & HPDS_VV) == 0) { 476 if (sc->sc_state == OPEN && lp->d_flags & D_REMOVABLE) { 477 if (sc->sc_openpart) 478 log(LOG_ERR, "hp%d: volume changed\n", 479 mi->mi_unit); 480 sc->sc_openpart = 0; 481 bp->b_flags |= B_ERROR; 482 return (MBU_NEXT); 483 } 484 hpaddr->hpcs1 = HP_DCLR|HP_GO; 485 if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive)) 486 printf("DCLR attn\n"); 487 hpaddr->hpcs1 = HP_PRESET|HP_GO; 488 if (!ML11(mi->mi_type)) 489 hpaddr->hpof = HPOF_FMT22; 490 mbclrattn(mi); 491 if (sc->sc_state == WANTOPENRAW) { 492 sc->sc_state = OPENRAW; 493 return (MBU_NEXT); 494 } 495 if (sc->sc_state == WANTOPEN) 496 sc->sc_state = RDLABEL; 497 } 498 if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) { 499 if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags & B_READ)) { 500 hpaddr->hpof = 501 hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22; 502 hpaddr->hpcs1 = HP_OFFSET|HP_GO; 503 (void)HPWAIT(mi, hpaddr); 504 mbclrattn(mi); 505 } 506 return (MBU_DODATA); 507 } 508 if (ML11(mi->mi_type)) 509 return (MBU_DODATA); 510 if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY) 511 return (MBU_DODATA); 512 bn = bp->b_blkno; 513 sn = bn % lp->d_secpercyl; 514 tn = sn / lp->d_nsectors; 515 sn = sn % lp->d_nsectors; 516 if (bp->b_cylin == MASKREG(hpaddr->hpdc)) { 517 if (sc->sc_doseeks) 518 return (MBU_DODATA); 519 dist = sn - (MASKREG(hpaddr->hpla) >> 6) - 1; 520 if (dist < 0) 521 dist += lp->d_nsectors; 522 if (dist > lp->d_maxdist || dist < lp->d_mindist) 523 return (MBU_DODATA); 524 } else 525 hpaddr->hpdc = bp->b_cylin; 526 if (sc->sc_doseeks) 527 hpaddr->hpcs1 = HP_SEEK|HP_GO; 528 else { 529 sn = (sn + lp->d_nsectors - lp->d_sdist) % lp->d_nsectors; 530 hpaddr->hpda = (tn << 8) + sn; 531 hpaddr->hpcs1 = HP_SEARCH|HP_GO; 532 } 533 return (MBU_STARTED); 534 } 535 536 hpstart(mi) 537 register struct mba_device *mi; 538 { 539 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 540 register struct buf *bp = mi->mi_tab.b_actf; 541 register struct disklabel *lp = &hplabel[mi->mi_unit]; 542 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 543 daddr_t bn; 544 int sn, tn, cn; 545 546 if (ML11(mi->mi_type)) 547 hpaddr->hpda = bp->b_blkno + sc->sc_blkdone; 548 else { 549 if (bp->b_flags & B_BAD) { 550 bn = sc->sc_badbn; 551 cn = bn / lp->d_secpercyl; 552 } else { 553 bn = bp->b_blkno; 554 cn = bp->b_cylin; 555 } 556 sn = bn % lp->d_secpercyl; 557 if ((bp->b_flags & B_BAD) == 0) 558 sn += sc->sc_blkdone; 559 tn = sn / lp->d_nsectors; 560 sn %= lp->d_nsectors; 561 cn += tn / lp->d_ntracks; 562 tn %= lp->d_ntracks; 563 hpaddr->hpda = (tn << 8) + sn; 564 hpaddr->hpdc = cn; 565 } 566 mi->mi_tab.b_bdone = dbtob(sc->sc_blkdone); 567 if (bp->b_flags & B_FORMAT) { 568 if (bp->b_flags & B_READ) 569 return (HP_RHDR|HP_GO); 570 else 571 return (HP_WHDR|HP_GO); 572 } 573 return (0); 574 } 575 576 hpdtint(mi, mbsr) 577 register struct mba_device *mi; 578 int mbsr; 579 { 580 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 581 register struct buf *bp = mi->mi_tab.b_actf; 582 register int er1, er2; 583 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 584 int retry = 0; 585 int npf; 586 daddr_t bn; 587 int bcr; 588 589 bcr = MASKREG(-mi->mi_mba->mba_bcr); 590 if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) { 591 er1 = hpaddr->hper1; 592 er2 = hpaddr->hper2; 593 if (bp->b_flags & B_BAD) { 594 npf = bp->b_error; 595 bn = sc->sc_badbn; 596 } else { 597 npf = btop(bp->b_bcount - bcr); 598 if (er1 & (HPER1_DCK | HPER1_ECH)) 599 npf--; 600 bn = bp->b_blkno + npf; 601 } 602 if (HPWAIT(mi, hpaddr) == 0) 603 goto hard; 604 #ifdef HPDEBUG 605 if (hpdebug) { 606 int dc = hpaddr->hpdc, da = hpaddr->hpda; 607 608 log(LOG_DEBUG, 609 "hperr: bp %x cyl %d blk %d blkdone %d as %o dc %x da %x\n", 610 bp, bp->b_cylin, bn, sc->sc_blkdone, 611 hpaddr->hpas&0xff, MASKREG(dc), MASKREG(da)); 612 log(LOG_DEBUG, 613 "errcnt %d mbsr=%b er1=%b er2=%b bcr -%d\n", 614 mi->mi_tab.b_errcnt, mbsr, mbsr_bits, 615 MASKREG(er1), HPER1_BITS, 616 MASKREG(er2), HPER2_BITS, bcr); 617 } 618 #endif 619 if (er1 & HPER1_HCRC) { 620 er1 &= ~(HPER1_HCE|HPER1_FER); 621 er2 &= ~HPER2_BSE; 622 } 623 if (er1 & HPER1_WLE) { 624 log(LOG_WARNING, "hp%d: write locked\n", 625 hpunit(bp->b_dev)); 626 bp->b_flags |= B_ERROR; 627 } else if (bp->b_flags & B_FORMAT) { 628 goto hard; 629 } else if (RM80(mi->mi_type) && er2&HPER2_SSE) { 630 (void) hpecc(mi, SSE); 631 return (MBD_RESTARTED); 632 } else if ((er2 & HPER2_BSE) && !ML11(mi->mi_type)) { 633 if (hpecc(mi, BSE)) 634 return (MBD_RESTARTED); 635 goto hard; 636 } else if (MASKREG(er1) == HPER1_FER && RP06(mi->mi_type)) { 637 if (hpecc(mi, BSE)) 638 return (MBD_RESTARTED); 639 goto hard; 640 } else if ((er1 & (HPER1_DCK | HPER1_ECH)) == HPER1_DCK && 641 mi->mi_tab.b_errcnt >= 3) { 642 if (hpecc(mi, ECC)) 643 return (MBD_RESTARTED); 644 /* 645 * ECC corrected. Only log retries below 646 * if we got errors other than soft ECC 647 * (as indicated by additional retries). 648 */ 649 if (mi->mi_tab.b_errcnt == 3) 650 mi->mi_tab.b_errcnt = 0; 651 } else if ((er1 & HPER1_HCRC) && !ML11(mi->mi_type) && 652 hpecc(mi, BSE)) { 653 /* 654 * HCRC means the header is screwed up and the sector 655 * might well exist in the bad sector table, 656 * better check.... 657 */ 658 return (MBD_RESTARTED); 659 } else if (++mi->mi_tab.b_errcnt > 27 || 660 (ML11(mi->mi_type) && mi->mi_tab.b_errcnt > 15) || 661 mbsr & MBSR_HARD || 662 er1 & HPER1_HARD || 663 (!ML11(mi->mi_type) && (er2 & HPER2_HARD))) { 664 hard: 665 bp->b_blkno = bn; /* XXX */ 666 harderr(bp, "hp"); 667 if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC))) 668 printf("mbsr=%b ", mbsr, mbsr_bits); 669 printf("er1=%b er2=%b", 670 MASKREG(hpaddr->hper1), HPER1_BITS, 671 MASKREG(hpaddr->hper2), HPER2_BITS); 672 if (bp->b_flags & B_FORMAT) 673 printf(" (hdr i/o)"); 674 printf("\n"); 675 bp->b_flags |= B_ERROR; 676 bp->b_flags &= ~B_BAD; 677 } else 678 retry = 1; 679 hpaddr->hpcs1 = HP_DCLR|HP_GO; 680 if (retry && (mi->mi_tab.b_errcnt & 07) == 4) { 681 hpaddr->hpcs1 = HP_RECAL|HP_GO; 682 sc->sc_recal = 1; 683 return (MBD_REPOSITION); 684 } 685 } 686 #ifdef HPDEBUG 687 else 688 if (hpdebug && sc->sc_recal) { 689 log(LOG_DEBUG, 690 "recal %d errcnt %d mbsr=%b er1=%b er2=%b\n", 691 sc->sc_recal, mi->mi_tab.b_errcnt, mbsr, mbsr_bits, 692 hpaddr->hper1, HPER1_BITS, 693 hpaddr->hper2, HPER2_BITS); 694 } 695 #endif 696 (void)HPWAIT(mi, hpaddr); 697 if (retry) 698 return (MBD_RETRY); 699 if (mi->mi_tab.b_errcnt >= 16) { 700 /* 701 * This is fast and occurs rarely; we don't 702 * bother with interrupts. 703 */ 704 hpaddr->hpcs1 = HP_RTC|HP_GO; 705 (void)HPWAIT(mi, hpaddr); 706 mbclrattn(mi); 707 } 708 if (mi->mi_tab.b_errcnt && (bp->b_flags & B_ERROR) == 0) 709 log(LOG_INFO, "hp%d%c: %d retries %sing sn%d\n", 710 hpunit(bp->b_dev), 'a'+(minor(bp->b_dev)&07), 711 mi->mi_tab.b_errcnt, 712 (bp->b_flags & B_READ) ? "read" : "writ", 713 (bp->b_flags & B_BAD) ? 714 sc->sc_badbn : bp->b_blkno + sc->sc_blkdone); 715 if ((bp->b_flags & B_BAD) && hpecc(mi, CONT)) 716 return (MBD_RESTARTED); 717 sc->sc_blkdone = 0; 718 bp->b_resid = bcr; 719 if (!ML11(mi->mi_type)) { 720 hpaddr->hpof = HPOF_FMT22; 721 hpaddr->hpcs1 = HP_RELEASE|HP_GO; 722 } 723 if (sc->sc_openpart == 0) 724 wakeup((caddr_t)sc); 725 return (MBD_DONE); 726 } 727 728 /* 729 * Wait (for a bit) for a drive to come ready; 730 * returns nonzero on success. 731 */ 732 hpwait(mi) 733 register struct mba_device *mi; 734 { 735 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 736 register i = 100000; 737 738 while ((hpaddr->hpds & HPDS_DRY) == 0 && --i) 739 DELAY(10); 740 if (i == 0) 741 printf("hp%d: intr, not ready\n", mi->mi_unit); 742 return (i); 743 } 744 745 hpread(dev, uio) 746 dev_t dev; 747 struct uio *uio; 748 { 749 register int unit = hpunit(dev); 750 751 if (unit >= NHP) 752 return (ENXIO); 753 return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio)); 754 } 755 756 hpwrite(dev, uio) 757 dev_t dev; 758 struct uio *uio; 759 { 760 register int unit = hpunit(dev); 761 762 if (unit >= NHP) 763 return (ENXIO); 764 return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio)); 765 } 766 767 hpioctl(dev, cmd, data, flag) 768 dev_t dev; 769 int cmd; 770 caddr_t data; 771 int flag; 772 { 773 int unit = hpunit(dev); 774 register struct disklabel *lp; 775 register struct format_op *fop; 776 int error = 0; 777 int hpformat(); 778 779 lp = &hplabel[unit]; 780 781 switch (cmd) { 782 783 case DIOCGDINFO: 784 *(struct disklabel *)data = *lp; 785 break; 786 787 case DIOCGPART: 788 ((struct partinfo *)data)->disklab = lp; 789 ((struct partinfo *)data)->part = 790 &lp->d_partitions[hppart(dev)]; 791 break; 792 793 case DIOCSDINFO: 794 if ((flag & FWRITE) == 0) 795 error = EBADF; 796 else 797 *lp = *(struct disklabel *)data; 798 break; 799 800 case DIOCWDINFO: 801 if ((flag & FWRITE) == 0) { 802 error = EBADF; 803 break; 804 } 805 { 806 struct buf *bp; 807 struct disklabel *dlp; 808 809 *lp = *(struct disklabel *)data; 810 bp = geteblk(lp->d_secsize); 811 bp->b_dev = makedev(major(dev), hpminor(hpunit(dev), 0)); 812 bp->b_blkno = LABELSECTOR; 813 bp->b_bcount = lp->d_secsize; 814 bp->b_flags = B_READ; 815 dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET); 816 hpstrategy(bp); 817 biowait(bp); 818 if (bp->b_flags & B_ERROR) { 819 error = u.u_error; /* XXX */ 820 u.u_error = 0; 821 goto bad; 822 } 823 *dlp = *lp; 824 bp->b_flags = B_WRITE; 825 hpstrategy(bp); 826 biowait(bp); 827 if (bp->b_flags & B_ERROR) { 828 error = u.u_error; /* XXX */ 829 u.u_error = 0; 830 } 831 bad: 832 brelse(bp); 833 } 834 break; 835 836 #ifdef notyet 837 case DIOCWFORMAT: 838 if ((flag & FWRITE) == 0) { 839 error = EBADF; 840 break; 841 } 842 { 843 struct uio auio; 844 struct iovec aiov; 845 846 fop = (struct format_op *)data; 847 aiov.iov_base = fop->df_buf; 848 aiov.iov_len = fop->df_count; 849 auio.uio_iov = &aiov; 850 auio.uio_iovcnt = 1; 851 auio.uio_resid = fop->df_count; 852 auio.uio_segflg = 0; 853 auio.uio_offset = fop->df_startblk * lp->d_secsize; 854 error = physio(hpformat, &rhpbuf[unit], dev, B_WRITE, 855 minphys, &auio); 856 fop->df_count -= auio.uio_resid; 857 fop->df_reg[0] = sc->sc_status; 858 fop->df_reg[1] = sc->sc_error; 859 } 860 break; 861 #endif 862 863 default: 864 error = ENOTTY; 865 break; 866 } 867 return (0); 868 } 869 870 hpformat(bp) 871 struct buf *bp; 872 { 873 874 bp->b_flags |= B_FORMAT; 875 return (hpstrategy(bp)); 876 } 877 878 hpecc(mi, flag) 879 register struct mba_device *mi; 880 int flag; 881 { 882 register struct mba_regs *mbp = mi->mi_mba; 883 register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; 884 register struct buf *bp = mi->mi_tab.b_actf; 885 register struct disklabel *lp = &hplabel[mi->mi_unit]; 886 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 887 int npf, o; 888 int bn, cn, tn, sn; 889 int bcr; 890 891 bcr = MASKREG(-mbp->mba_bcr); 892 if (bp->b_flags & B_BAD) 893 npf = bp->b_error; 894 else { 895 npf = bp->b_bcount - bcr; 896 /* 897 * Watch out for fractional sector at end of transfer; 898 * want to round up if finished, otherwise round down. 899 */ 900 if (bcr == 0) 901 npf += 511; 902 npf = btodb(npf); 903 } 904 o = (int)bp->b_un.b_addr & PGOFSET; 905 bn = bp->b_blkno; 906 cn = bp->b_cylin; 907 sn = bn % lp->d_secpercyl + npf; 908 tn = sn / lp->d_nsectors; 909 sn %= lp->d_nsectors; 910 cn += tn / lp->d_ntracks; 911 tn %= lp->d_ntracks; 912 bn += npf; 913 switch (flag) { 914 case ECC: { 915 register int i; 916 caddr_t addr; 917 struct pte mpte; 918 int bit, byte, mask; 919 920 npf--; /* because block in error is previous block */ 921 bn--; 922 if (bp->b_flags & B_BAD) 923 bn = sc->sc_badbn; 924 log(LOG_WARNING, "hp%d%c: soft ecc sn%d\n", hpunit(bp->b_dev), 925 'a'+(minor(bp->b_dev)&07), bn); 926 mask = MASKREG(rp->hpec2); 927 i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 928 bit = i&07; 929 i = (i&~07)>>3; 930 byte = i + o; 931 while (i < 512 && (int)dbtob(npf)+i < bp->b_bcount && bit > -11) { 932 mpte = mbp->mba_map[npf+btop(byte)]; 933 addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); 934 putmemc(addr, getmemc(addr)^(mask<<bit)); 935 byte++; 936 i++; 937 bit -= 8; 938 } 939 if (bcr == 0) 940 return (0); 941 npf++; 942 break; 943 } 944 945 case SSE: 946 rp->hpof |= HPOF_SSEI; 947 if (bp->b_flags & B_BAD) { 948 bn = sc->sc_badbn; 949 goto fixregs; 950 } 951 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 952 break; 953 954 case BSE: 955 if (sc->sc_state == OPENRAW) 956 return (0); 957 if (rp->hpof & HPOF_SSEI) 958 sn++; 959 #ifdef HPBDEBUG 960 if (hpbdebug) 961 log(LOG_DEBUG, "hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 962 #endif 963 if (bp->b_flags & B_BAD) 964 return (0); 965 if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0) 966 return (0); 967 bp->b_flags |= B_BAD; 968 bp->b_error = npf + 1; 969 rp->hpof &= ~HPOF_SSEI; 970 bn = lp->d_ncylinders * lp->d_secpercyl - 971 lp->d_nsectors - 1 - bn; 972 sc->sc_badbn = bn; 973 fixregs: 974 cn = bn / lp->d_secpercyl; 975 sn = bn % lp->d_secpercyl; 976 tn = sn / lp->d_nsectors; 977 sn %= lp->d_nsectors; 978 bcr = bp->b_bcount - (int)ptob(npf); 979 bcr = MIN(bcr, 512); 980 mbp->mba_bcr = -bcr; 981 #ifdef HPBDEBUG 982 if (hpbdebug) 983 log(LOG_DEBUG, "revector to cn %d tn %d sn %d\n", cn, tn, sn); 984 #endif 985 break; 986 987 case CONT: 988 #ifdef HPBDEBUG 989 if (hpbdebug) 990 log(LOG_DEBUG, "hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 991 #endif 992 bp->b_flags &= ~B_BAD; 993 if ((int)ptob(npf) >= bp->b_bcount) 994 return (0); 995 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 996 break; 997 } 998 rp->hpcs1 = HP_DCLR|HP_GO; 999 if (rp->hpof & HPOF_SSEI) 1000 sn++; 1001 rp->hpdc = cn; 1002 rp->hpda = (tn<<8) + sn; 1003 mbp->mba_sr = -1; 1004 mbp->mba_var = (int)ptob(npf) + o; 1005 rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO; 1006 mi->mi_tab.b_errcnt = 0; /* error has been corrected */ 1007 sc->sc_blkdone = npf; 1008 return (1); 1009 } 1010 1011 #define DBSIZE 20 1012 1013 hpdump(dev) 1014 dev_t dev; 1015 { 1016 register struct mba_device *mi; 1017 register struct mba_regs *mba; 1018 struct hpdevice *hpaddr; 1019 char *start; 1020 int num, unit; 1021 register struct disklabel *lp; 1022 1023 num = maxfree; 1024 start = 0; 1025 unit = hpunit(dev); 1026 if (unit >= NHP) 1027 return (ENXIO); 1028 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 1029 mi = phys(hpinfo[unit],struct mba_device *); 1030 if (mi == 0 || mi->mi_alive == 0) 1031 return (ENXIO); 1032 lp = &hplabel[unit]; 1033 mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 1034 mba->mba_cr = MBCR_INIT; 1035 hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; 1036 if ((hpaddr->hpds & HPDS_VV) == 0) { 1037 hpaddr->hpcs1 = HP_DCLR|HP_GO; 1038 hpaddr->hpcs1 = HP_PRESET|HP_GO; 1039 hpaddr->hpof = HPOF_FMT22; 1040 } 1041 if (dumplo < 0) 1042 return (EINVAL); 1043 if (dumplo + num >= lp->d_partitions[hppart(dev)].p_size) 1044 num = lp->d_partitions[hppart(dev)].p_size - dumplo; 1045 while (num > 0) { 1046 register struct pte *hpte = mba->mba_map; 1047 register int i; 1048 int blk, cn, sn, tn; 1049 daddr_t bn; 1050 1051 blk = num > DBSIZE ? DBSIZE : num; 1052 bn = dumplo + btop(start); 1053 cn = (bn + lp->d_partitions[hppart(dev)].p_offset) / 1054 lp->d_secpercyl; 1055 sn = bn % lp->d_secpercyl; 1056 tn = sn / lp->d_nsectors; 1057 sn = sn % lp->d_nsectors; 1058 hpaddr->hpdc = cn; 1059 hpaddr->hpda = (tn << 8) + sn; 1060 for (i = 0; i < blk; i++) 1061 *(int *)hpte++ = (btop(start)+i) | PG_V; 1062 mba->mba_sr = -1; 1063 mba->mba_bcr = -(blk*NBPG); 1064 mba->mba_var = 0; 1065 hpaddr->hpcs1 = HP_WCOM | HP_GO; 1066 while ((hpaddr->hpds & HPDS_DRY) == 0) 1067 DELAY(10); 1068 if (hpaddr->hpds&HPDS_ERR) 1069 return (EIO); 1070 start += blk*NBPG; 1071 num -= blk; 1072 } 1073 return (0); 1074 } 1075 1076 hpsize(dev) 1077 dev_t dev; 1078 { 1079 register int unit = hpunit(dev); 1080 struct mba_device *mi; 1081 1082 if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0 || 1083 hpsoftc[unit].sc_state != OPEN) 1084 return (-1); 1085 return ((int)hplabel[unit].d_partitions[hppart(dev)].p_size); 1086 } 1087 1088 #ifdef COMPAT_42 1089 /* 1090 * Compatibility code to fake up pack label 1091 * for unlabeled disks. 1092 */ 1093 struct size { 1094 daddr_t nblocks; 1095 int cyloff; 1096 } rp06_sizes[8] = { 1097 15884, 0, /* A=cyl 0 thru 37 */ 1098 33440, 38, /* B=cyl 38 thru 117 */ 1099 340670, 0, /* C=cyl 0 thru 814 */ 1100 15884, 118, /* D=cyl 118 thru 155 */ 1101 55936, 156, /* E=cyl 156 thru 289 */ 1102 219384, 290, /* F=cyl 290 thru 814 */ 1103 291280, 118, /* G=cyl 118 thru 814 */ 1104 0, 0, 1105 }, rp05_sizes[8] = { 1106 15884, 0, /* A=cyl 0 thru 37 */ 1107 33440, 38, /* B=cyl 38 thru 117 */ 1108 171798, 0, /* C=cyl 0 thru 410 */ 1109 15884, 118, /* D=cyl 118 thru 155 */ 1110 55936, 156, /* E=cyl 156 thru 289 */ 1111 50512, 290, /* F=cyl 290 thru 410 */ 1112 122408, 118, /* G=cyl 118 thru 410 */ 1113 0, 0, 1114 }, rm03_sizes[8] = { 1115 15884, 0, /* A=cyl 0 thru 99 */ 1116 33440, 100, /* B=cyl 100 thru 308 */ 1117 131680, 0, /* C=cyl 0 thru 822 */ 1118 15884, 309, /* D=cyl 309 thru 408 */ 1119 55936, 409, /* E=cyl 409 thru 758 */ 1120 10144, 759, /* F=cyl 759 thru 822 */ 1121 82144, 309, /* G=cyl 309 thru 822 */ 1122 0, 0, 1123 }, rm05_sizes[8] = { 1124 15884, 0, /* A=cyl 0 thru 26 */ 1125 33440, 27, /* B=cyl 27 thru 81 */ 1126 500384, 0, /* C=cyl 0 thru 822 */ 1127 15884, 562, /* D=cyl 562 thru 588 */ 1128 55936, 589, /* E=cyl 589 thru 680 */ 1129 86240, 681, /* F=cyl 681 thru 822 */ 1130 158592, 562, /* G=cyl 562 thru 822 */ 1131 291346, 82, /* H=cyl 82 thru 561 */ 1132 }, rm80_sizes[8] = { 1133 15884, 0, /* A=cyl 0 thru 36 */ 1134 33440, 37, /* B=cyl 37 thru 114 */ 1135 242606, 0, /* C=cyl 0 thru 558 */ 1136 15884, 115, /* D=cyl 115 thru 151 */ 1137 55936, 152, /* E=cyl 152 thru 280 */ 1138 120559, 281, /* F=cyl 281 thru 558 */ 1139 192603, 115, /* G=cyl 115 thru 558 */ 1140 0, 0, 1141 }, rp07_sizes[8] = { 1142 15884, 0, /* A=cyl 0 thru 9 */ 1143 66880, 10, /* B=cyl 10 thru 51 */ 1144 1008000, 0, /* C=cyl 0 thru 629 */ 1145 15884, 235, /* D=cyl 235 thru 244 */ 1146 307200, 245, /* E=cyl 245 thru 436 */ 1147 308650, 437, /* F=cyl 437 thru 629 */ 1148 631850, 235, /* G=cyl 235 thru 629 */ 1149 291346, 52, /* H=cyl 52 thru 234 */ 1150 }, cdc9775_sizes[8] = { 1151 15884, 0, /* A=cyl 0 thru 12 */ 1152 66880, 13, /* B=cyl 13 thru 65 */ 1153 1077760, 0, /* C=cyl 0 thru 841 */ 1154 15884, 294, /* D=cyl 294 thru 306 */ 1155 307200, 307, /* E=cyl 307 thru 546 */ 1156 377440, 547, /* F=cyl 547 thru 841 */ 1157 701280, 294, /* G=cyl 294 thru 841 */ 1158 291346, 66, /* H=cyl 66 thru 293 */ 1159 }, cdc9730_sizes[8] = { 1160 15884, 0, /* A=cyl 0 thru 49 */ 1161 33440, 50, /* B=cyl 50 thru 154 */ 1162 263360, 0, /* C=cyl 0 thru 822 */ 1163 15884, 155, /* D=cyl 155 thru 204 */ 1164 55936, 205, /* E=cyl 205 thru 379 */ 1165 141664, 380, /* F=cyl 380 thru 822 */ 1166 213664, 155, /* G=cyl 155 thru 822 */ 1167 0, 0, 1168 }, capricorn_sizes[8] = { 1169 15884, 0, /* A=cyl 0 thru 31 */ 1170 33440, 32, /* B=cyl 32 thru 97 */ 1171 524288, 0, /* C=cyl 0 thru 1023 */ 1172 15884, 668, /* D=cyl 668 thru 699 */ 1173 55936, 700, /* E=cyl 700 thru 809 */ 1174 109472, 810, /* F=cyl 810 thru 1023 */ 1175 182176, 668, /* G=cyl 668 thru 1023 */ 1176 291346, 98, /* H=cyl 98 thru 667 */ 1177 }, eagle_sizes[8] = { 1178 15884, 0, /* A=cyl 0 thru 16 */ 1179 66880, 17, /* B=cyl 17 thru 86 */ 1180 808320, 0, /* C=cyl 0 thru 841 */ 1181 15884, 391, /* D=cyl 391 thru 407 */ 1182 307200, 408, /* E=cyl 408 thru 727 */ 1183 109296, 728, /* F=cyl 728 thru 841 */ 1184 432816, 391, /* G=cyl 391 thru 841 */ 1185 291346, 87, /* H=cyl 87 thru 390 */ 1186 }, ampex_sizes[8] = { 1187 15884, 0, /* A=cyl 0 thru 26 */ 1188 33440, 27, /* B=cyl 27 thru 81 */ 1189 495520, 0, /* C=cyl 0 thru 814 */ 1190 15884, 562, /* D=cyl 562 thru 588 */ 1191 55936, 589, /* E=cyl 589 thru 680 */ 1192 81312, 681, /* F=cyl 681 thru 814 */ 1193 153664, 562, /* G=cyl 562 thru 814 */ 1194 291346, 82, /* H=cyl 82 thru 561 */ 1195 }, fj2361_sizes[8] = { 1196 15884, 0, /* A=cyl 0 thru 12 */ 1197 66880, 13, /* B=cyl 13 thru 65 */ 1198 1077760, 0, /* C=cyl 0 thru 841 */ 1199 15884, 294, /* D=cyl 294 thru 306 */ 1200 307200, 307, /* E=cyl 307 thru 546 */ 1201 377408, 547, /* F=cyl 547 thru 841 */ 1202 701248, 294, /* G=cyl 294 thru 841 */ 1203 291346, 66, /* H=cyl 66 thru 293 */ 1204 }; 1205 1206 /* 1207 * These variable are all measured in sectors. 1208 * Sdist is how much to "lead" in the search for a desired sector 1209 * (i.e. if want N, search for N-sdist.) 1210 * Maxdist and mindist define the region right before our desired sector within 1211 * which we don't bother searching. We don't search when we are already less 1212 * then maxdist and more than mindist sectors "before" our desired sector. 1213 * Maxdist should be >= sdist. 1214 * 1215 * Beware, sdist, mindist and maxdist are not well tuned 1216 * for many of the drives listed in this table. 1217 * Try patching things with something i/o intensive 1218 * running and watch iostat. 1219 */ 1220 struct hpst { 1221 short nsect; /* # sectors/track */ 1222 short ntrak; /* # tracks/cylinder */ 1223 short nspc; /* # sector/cylinders */ 1224 short ncyl; /* # cylinders */ 1225 struct size *sizes; /* partition tables */ 1226 short sdist; /* seek distance metric */ 1227 short maxdist; /* boundaries of non-searched area */ 1228 short mindist; /* preceding the target sector */ 1229 char *name; /* name of disk type */ 1230 } hpst[] = { 1231 { 32, 5, 32*5, 823, rm03_sizes, 7, 4, 1, "RM03" }, 1232 { 32, 19, 32*19, 823, rm05_sizes, 7, 4, 1, "RM05" }, 1233 { 22,19, 22*19, 815, rp06_sizes, 7, 4, 1, "RP06"}, 1234 { 31, 14, 31*14, 559, rm80_sizes, 7, 4, 1, "RM80"}, 1235 { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP04"}, 1236 { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP05"}, 1237 { 50, 32, 50*32, 630, rp07_sizes, 15, 8, 3, "RP07"}, 1238 { 1, 1, 1, 1, 0, 0, 0, 0, "ML11A"}, 1239 { 1, 1, 1, 1, 0, 0, 0, 0, "ML11B" }, 1240 { 32, 40, 32*40, 843, cdc9775_sizes, 7, 4, 1, "9775" }, 1241 { 32, 10, 32*10, 823, cdc9730_sizes, 7, 4, 1, "9730-160" }, 1242 { 32, 16, 32*16, 1024, capricorn_sizes,10,4, 3, "capricorn" }, 1243 { 48, 20, 48*20, 842, eagle_sizes, 15, 8, 3, "eagle" }, 1244 { 32, 19, 32*19, 815, ampex_sizes, 7, 4, 1, "9300" }, 1245 { 64, 20, 64*20, 842, fj2361_sizes, 15, 8, 3, "2361" }, 1246 }; 1247 1248 /* 1249 * Map apparent MASSBUS drive type into manufacturer 1250 * specific configuration. For SI controllers this is done 1251 * based on codes in the serial number register. For 1252 * EMULEX controllers, the track and sector attributes are 1253 * used when the drive type is an RM02 (not supported by DEC). 1254 */ 1255 hpmaptype(mi, lp) 1256 register struct mba_device *mi; 1257 register struct disklabel *lp; 1258 { 1259 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 1260 register int type = mi->mi_type; 1261 register struct hpst *st; 1262 register i; 1263 1264 /* 1265 * Model-byte processing for SI controllers. 1266 * NB: Only deals with RM03 and RM05 emulations. 1267 */ 1268 if (type == HPDT_RM03 || type == HPDT_RM05) { 1269 int hpsn = hpaddr->hpsn; 1270 1271 if ((hpsn & SIMB_LU) == mi->mi_drive) 1272 switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) { 1273 1274 case SI9775D: 1275 type = HPDT_9775; 1276 break; 1277 1278 case SI9730D: 1279 type = HPDT_9730; 1280 break; 1281 1282 case SI9766: 1283 type = HPDT_RM05; 1284 break; 1285 1286 case SI9762: 1287 type = HPDT_RM03; 1288 break; 1289 1290 case SICAPD: 1291 type = HPDT_CAPRICORN; 1292 break; 1293 1294 case SI9751D: 1295 type = HPDT_EAGLE; 1296 break; 1297 } 1298 } 1299 1300 /* 1301 * EMULEX SC750 or SC780. Poke the holding register. 1302 */ 1303 if (type == HPDT_RM02) { 1304 int nsectors, ntracks, ncyl; 1305 1306 hpaddr->hpof = HPOF_FMT22; 1307 mbclrattn(mi); 1308 hpaddr->hpcs1 = HP_NOP; 1309 hpaddr->hphr = HPHR_MAXTRAK; 1310 ntracks = MASKREG(hpaddr->hphr) + 1; 1311 DELAY(100); 1312 hpaddr->hpcs1 = HP_NOP; 1313 hpaddr->hphr = HPHR_MAXSECT; 1314 nsectors = MASKREG(hpaddr->hphr) + 1; 1315 DELAY(100); 1316 hpaddr->hpcs1 = HP_NOP; 1317 hpaddr->hphr = HPHR_MAXCYL; 1318 ncyl = MASKREG(hpaddr->hphr) + 1; 1319 for (type = 0; hptypes[type] != 0; type++) 1320 if (hpst[type].nsect == nsectors && 1321 hpst[type].ntrak == ntracks && 1322 hpst[type].ncyl == ncyl) 1323 break; 1324 1325 if (hptypes[type] == 0) { 1326 printf("hp%d: %d sectors, %d tracks, %d cylinders: unknown device\n", 1327 mi->mi_unit, nsectors, ntracks, ncyl); 1328 type = HPDT_RM02; 1329 } 1330 hpaddr->hpcs1 = HP_DCLR|HP_GO; 1331 mbclrattn(mi); /* conservative */ 1332 } 1333 1334 /* 1335 * set up minimal disk label. 1336 */ 1337 st = &hpst[type]; 1338 lp->d_secsize = 512; 1339 lp->d_nsectors = st->nsect; 1340 lp->d_ntracks = st->ntrak; 1341 lp->d_secpercyl = st->nspc; 1342 lp->d_ncylinders = st->ncyl; 1343 lp->d_secperunit = st->nspc * st->ncyl; 1344 lp->d_sdist = st->sdist; 1345 lp->d_mindist = st->mindist; 1346 lp->d_maxdist = st->maxdist; 1347 bcopy(hpst[type].name, lp->d_typename, sizeof(lp->d_typename)); 1348 lp->d_npartitions = 8; 1349 for (i = 0; i < 8; i++) { 1350 lp->d_partitions[i].p_offset = st->sizes[i].cyloff * 1351 lp->d_secpercyl; 1352 lp->d_partitions[i].p_size = st->sizes[i].nblocks; 1353 } 1354 return (type); 1355 } 1356 #endif COMPAT_42 1357 #endif 1358