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