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