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.1 (Berkeley) 06/05/86 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 "dk.h" 29 #include "buf.h" 30 #include "conf.h" 31 #include "dir.h" 32 #include "user.h" 33 #include "map.h" 34 #include "../vax/mtpr.h" 35 #include "vm.h" 36 #include "cmap.h" 37 #include "dkbad.h" 38 #include "ioctl.h" 39 #include "uio.h" 40 #include "syslog.h" 41 42 #include "../vax/dkio.h" 43 #include "mbareg.h" 44 #include "mbavar.h" 45 #include "hpreg.h" 46 47 /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 48 struct size { 49 daddr_t nblocks; 50 int cyloff; 51 } rp06_sizes[8] = { 52 15884, 0, /* A=cyl 0 thru 37 */ 53 33440, 38, /* B=cyl 38 thru 117 */ 54 340670, 0, /* C=cyl 0 thru 814 */ 55 15884, 118, /* D=cyl 118 thru 155 */ 56 55936, 156, /* E=cyl 156 thru 289 */ 57 219384, 290, /* F=cyl 290 thru 814 */ 58 291280, 118, /* G=cyl 118 thru 814 */ 59 0, 0, 60 }, rp05_sizes[8] = { 61 15884, 0, /* A=cyl 0 thru 37 */ 62 33440, 38, /* B=cyl 38 thru 117 */ 63 171798, 0, /* C=cyl 0 thru 410 */ 64 15884, 118, /* D=cyl 118 thru 155 */ 65 55936, 156, /* E=cyl 156 thru 289 */ 66 50512, 290, /* F=cyl 290 thru 410 */ 67 122408, 118, /* G=cyl 118 thru 410 */ 68 0, 0, 69 }, rm03_sizes[8] = { 70 15884, 0, /* A=cyl 0 thru 99 */ 71 33440, 100, /* B=cyl 100 thru 308 */ 72 131680, 0, /* C=cyl 0 thru 822 */ 73 15884, 309, /* D=cyl 309 thru 408 */ 74 55936, 409, /* E=cyl 409 thru 758 */ 75 10144, 759, /* F=cyl 759 thru 822 */ 76 82144, 309, /* G=cyl 309 thru 822 */ 77 0, 0, 78 }, rm05_sizes[8] = { 79 15884, 0, /* A=cyl 0 thru 26 */ 80 33440, 27, /* B=cyl 27 thru 81 */ 81 500384, 0, /* C=cyl 0 thru 822 */ 82 15884, 562, /* D=cyl 562 thru 588 */ 83 55936, 589, /* E=cyl 589 thru 680 */ 84 86240, 681, /* F=cyl 681 thru 822 */ 85 158592, 562, /* G=cyl 562 thru 822 */ 86 291346, 82, /* H=cyl 82 thru 561 */ 87 }, rm80_sizes[8] = { 88 15884, 0, /* A=cyl 0 thru 36 */ 89 33440, 37, /* B=cyl 37 thru 114 */ 90 242606, 0, /* C=cyl 0 thru 558 */ 91 15884, 115, /* D=cyl 115 thru 151 */ 92 55936, 152, /* E=cyl 152 thru 280 */ 93 120559, 281, /* F=cyl 281 thru 558 */ 94 192603, 115, /* G=cyl 115 thru 558 */ 95 0, 0, 96 }, rp07_sizes[8] = { 97 15884, 0, /* A=cyl 0 thru 9 */ 98 66880, 10, /* B=cyl 10 thru 51 */ 99 1008000, 0, /* C=cyl 0 thru 629 */ 100 15884, 235, /* D=cyl 235 thru 244 */ 101 307200, 245, /* E=cyl 245 thru 436 */ 102 308650, 437, /* F=cyl 437 thru 629 */ 103 631850, 235, /* G=cyl 235 thru 629 */ 104 291346, 52, /* H=cyl 52 thru 234 */ 105 }, cdc9775_sizes[8] = { 106 15884, 0, /* A=cyl 0 thru 12 */ 107 66880, 13, /* B=cyl 13 thru 65 */ 108 1077760, 0, /* C=cyl 0 thru 841 */ 109 15884, 294, /* D=cyl 294 thru 306 */ 110 307200, 307, /* E=cyl 307 thru 546 */ 111 377440, 547, /* F=cyl 547 thru 841 */ 112 701280, 294, /* G=cyl 294 thru 841 */ 113 291346, 66, /* H=cyl 66 thru 293 */ 114 }, cdc9730_sizes[8] = { 115 15884, 0, /* A=cyl 0 thru 49 */ 116 33440, 50, /* B=cyl 50 thru 154 */ 117 263360, 0, /* C=cyl 0 thru 822 */ 118 15884, 155, /* D=cyl 155 thru 204 */ 119 55936, 205, /* E=cyl 205 thru 379 */ 120 141664, 380, /* F=cyl 380 thru 822 */ 121 213664, 155, /* G=cyl 155 thru 822 */ 122 0, 0, 123 }, capricorn_sizes[8] = { 124 15884, 0, /* A=cyl 0 thru 31 */ 125 33440, 32, /* B=cyl 32 thru 97 */ 126 524288, 0, /* C=cyl 0 thru 1023 */ 127 15884, 668, /* D=cyl 668 thru 699 */ 128 55936, 700, /* E=cyl 700 thru 809 */ 129 109472, 810, /* F=cyl 810 thru 1023 */ 130 182176, 668, /* G=cyl 668 thru 1023 */ 131 291346, 98, /* H=cyl 98 thru 667 */ 132 }, eagle_sizes[8] = { 133 15884, 0, /* A=cyl 0 thru 16 */ 134 66880, 17, /* B=cyl 17 thru 86 */ 135 808320, 0, /* C=cyl 0 thru 841 */ 136 15884, 391, /* D=cyl 391 thru 407 */ 137 307200, 408, /* E=cyl 408 thru 727 */ 138 109296, 728, /* F=cyl 728 thru 841 */ 139 432816, 391, /* G=cyl 391 thru 841 */ 140 291346, 87, /* H=cyl 87 thru 390 */ 141 }, ampex_sizes[8] = { 142 15884, 0, /* A=cyl 0 thru 26 */ 143 33440, 27, /* B=cyl 27 thru 81 */ 144 495520, 0, /* C=cyl 0 thru 814 */ 145 15884, 562, /* D=cyl 562 thru 588 */ 146 55936, 589, /* E=cyl 589 thru 680 */ 147 81312, 681, /* F=cyl 681 thru 814 */ 148 153664, 562, /* G=cyl 562 thru 814 */ 149 291346, 82, /* H=cyl 82 thru 561 */ 150 }, fj2361_sizes[8] = { 151 15884, 0, /* A=cyl 0 thru 12 */ 152 66880, 13, /* B=cyl 13 thru 65 */ 153 1077760, 0, /* C=cyl 0 thru 841 */ 154 15884, 294, /* D=cyl 294 thru 306 */ 155 307200, 307, /* E=cyl 307 thru 546 */ 156 377408, 547, /* F=cyl 547 thru 841 */ 157 701248, 294, /* G=cyl 294 thru 841 */ 158 291346, 66, /* H=cyl 66 thru 293 */ 159 }; 160 /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 161 162 /* 163 * Table for converting Massbus drive types into 164 * indices into the partition tables. Slots are 165 * left for those drives divined from other means 166 * (e.g. SI, AMPEX, etc.). 167 */ 168 short hptypes[] = { 169 #define HPDT_RM03 0 170 MBDT_RM03, 171 #define HPDT_RM05 1 172 MBDT_RM05, 173 #define HPDT_RP06 2 174 MBDT_RP06, 175 #define HPDT_RM80 3 176 MBDT_RM80, 177 #define HPDT_RP04 4 178 MBDT_RP04, 179 #define HPDT_RP05 5 180 MBDT_RP05, 181 #define HPDT_RP07 6 182 MBDT_RP07, 183 #define HPDT_ML11A 7 184 MBDT_ML11A, 185 #define HPDT_ML11B 8 186 MBDT_ML11B, 187 #define HPDT_9775 9 188 -1, 189 #define HPDT_9730 10 190 -1, 191 #define HPDT_CAPRICORN 11 192 -1, 193 #define HPDT_EAGLE 12 194 -1, 195 #define HPDT_9300 13 196 -1, 197 #define HPDT_RM02 14 198 MBDT_RM02, /* beware, actually mapped */ 199 #define HPDT_2361 15 200 -1, 201 0 202 }; 203 struct mba_device *hpinfo[NHP]; 204 int hpattach(),hpustart(),hpstart(),hpdtint(); 205 struct mba_driver hpdriver = 206 { hpattach, 0, hpustart, hpstart, hpdtint, 0, 207 hptypes, "hp", 0, hpinfo }; 208 209 /* 210 * These variable are all measured in sectors. 211 * Sdist is how much to "lead" in the search for a desired sector 212 * (i.e. if want N, search for N-sdist.) 213 * Maxdist and mindist define the region right before our desired sector within 214 * which we don't bother searching. We don't search when we are already less 215 * then maxdist and more than mindist sectors "before" our desired sector. 216 * Maxdist should be >= sdist. 217 * 218 * Beware, sdist, mindist and maxdist are not well tuned 219 * for many of the drives listed in this table. 220 * Try patching things with something i/o intensive 221 * running and watch iostat. 222 */ 223 struct hpst { 224 short nsect; /* # sectors/track */ 225 short ntrak; /* # tracks/cylinder */ 226 short nspc; /* # sector/cylinders */ 227 short ncyl; /* # cylinders */ 228 struct size *sizes; /* partition tables */ 229 short sdist; /* seek distance metric */ 230 short maxdist; /* boundaries of non-searched area */ 231 short mindist; /* preceding the target sector */ 232 char *name; /* name of disk type */ 233 } hpst[] = { 234 { 32, 5, 32*5, 823, rm03_sizes, 7, 4, 1, "RM03" }, 235 { 32, 19, 32*19, 823, rm05_sizes, 7, 4, 1, "RM05" }, 236 { 22,19, 22*19, 815, rp06_sizes, 7, 4, 1, "RP06"}, 237 { 31, 14, 31*14, 559, rm80_sizes, 7, 4, 1, "RM80"}, 238 { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP04"}, 239 { 22, 19, 22*19, 411, rp05_sizes, 7, 4, 1, "RP05"}, 240 { 50, 32, 50*32, 630, rp07_sizes, 15, 8, 3, "RP07"}, 241 { 1, 1, 1, 1, 0, 0, 0, 0, "ML11A"}, 242 { 1, 1, 1, 1, 0, 0, 0, 0, "ML11B" }, 243 { 32, 40, 32*40, 843, cdc9775_sizes, 7, 4, 1, "9775" }, 244 { 32, 10, 32*10, 823, cdc9730_sizes, 7, 4, 1, "9730-160" }, 245 { 32, 16, 32*16, 1024, capricorn_sizes,10,4, 3, "capricorn" }, 246 { 48, 20, 48*20, 842, eagle_sizes, 15, 8, 3, "eagle" }, 247 { 32, 19, 32*19, 815, ampex_sizes, 7, 4, 1, "9300" }, 248 { 64, 20, 64*20, 842, fj2361_sizes, 15, 8, 3, "2361" }, 249 }; 250 251 u_char hp_offset[16] = { 252 HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 253 HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 254 HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 255 0, 0, 0, 0, 256 }; 257 258 struct buf rhpbuf[NHP]; 259 struct buf bhpbuf[NHP]; 260 struct dkbad hpbad[NHP]; 261 262 struct hpsoftc { 263 u_char sc_hpinit; /* drive initialized */ 264 u_char sc_recal; /* recalibrate state */ 265 u_char sc_hdr; /* next i/o includes header */ 266 u_char sc_doseeks; /* perform explicit seeks */ 267 daddr_t sc_mlsize; /* ML11 size */ 268 int sc_blkdone; /* amount sucessfully transfered */ 269 daddr_t sc_badbn; /* replacement block number */ 270 } hpsoftc[NHP]; 271 272 #define b_cylin b_resid 273 274 /* #define ML11 0 to remove ML11 support */ 275 #define ML11 (hptypes[mi->mi_type] == MBDT_ML11A) 276 #define RP06 (hptypes[mi->mi_type] <= MBDT_RP06) 277 #define RM80 (hptypes[mi->mi_type] == MBDT_RM80) 278 279 #define hpunit(dev) (minor(dev) >> 3) 280 #define MASKREG(reg) ((reg)&0xffff) 281 #ifdef lint 282 #define HPWAIT(mi, addr) (hpwait(mi)) 283 #else 284 #define HPWAIT(mi, addr) (((addr)->hpds & HPDS_DRY) || hpwait(mi)) 285 #endif 286 287 /*ARGSUSED*/ 288 hpattach(mi, slave) 289 register struct mba_device *mi; 290 { 291 292 mi->mi_type = hpmaptype(mi); 293 if (!ML11 && mi->mi_dk >= 0) { 294 struct hpst *st = &hpst[mi->mi_type]; 295 296 dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256); 297 } 298 } 299 300 /* 301 * Map apparent MASSBUS drive type into manufacturer 302 * specific configuration. For SI controllers this is done 303 * based on codes in the serial number register. For 304 * EMULEX controllers, the track and sector attributes are 305 * used when the drive type is an RM02 (not supported by DEC). 306 */ 307 hpmaptype(mi) 308 register struct mba_device *mi; 309 { 310 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 311 register int type = mi->mi_type; 312 313 /* 314 * Model-byte processing for SI controllers. 315 * NB: Only deals with RM03 and RM05 emulations. 316 */ 317 if (type == HPDT_RM03 || type == HPDT_RM05) { 318 int hpsn = hpaddr->hpsn; 319 320 if ((hpsn & SIMB_LU) != mi->mi_drive) 321 return (type); 322 switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) { 323 324 case SI9775D: 325 printf("hp%d: 9775 (direct)\n", mi->mi_unit); 326 type = HPDT_9775; 327 break; 328 329 case SI9730D: 330 printf("hp%d: 9730 (direct)\n", mi->mi_unit); 331 type = HPDT_9730; 332 break; 333 334 case SI9766: 335 printf("hp%d: 9766\n", mi->mi_unit); 336 type = HPDT_RM05; 337 break; 338 339 case SI9762: 340 printf("hp%d: 9762\n", mi->mi_unit); 341 type = HPDT_RM03; 342 break; 343 344 case SICAPD: 345 printf("hp%d: capricorn\n", mi->mi_unit); 346 type = HPDT_CAPRICORN; 347 break; 348 349 case SI9751D: 350 printf("hp%d: eagle\n", mi->mi_unit); 351 type = HPDT_EAGLE; 352 break; 353 } 354 return (type); 355 } 356 357 /* 358 * EMULEX SC750 or SC780. Poke the holding register. 359 */ 360 if (type == HPDT_RM02) { 361 int nsectors, ntracks, ncyl; 362 363 hpaddr->hpof = HPOF_FMT22; 364 mbclrattn(mi); 365 hpaddr->hpcs1 = HP_NOP; 366 hpaddr->hphr = HPHR_MAXTRAK; 367 ntracks = MASKREG(hpaddr->hphr) + 1; 368 DELAY(100); 369 hpaddr->hpcs1 = HP_NOP; 370 hpaddr->hphr = HPHR_MAXSECT; 371 nsectors = MASKREG(hpaddr->hphr) + 1; 372 DELAY(100); 373 hpaddr->hpcs1 = HP_NOP; 374 hpaddr->hphr = HPHR_MAXCYL; 375 ncyl = MASKREG(hpaddr->hphr) + 1; 376 for (type = 0; hptypes[type] != 0; type++) 377 if (hpst[type].nsect == nsectors && 378 hpst[type].ntrak == ntracks && 379 hpst[type].ncyl == ncyl) 380 break; 381 382 if (hptypes[type] == 0) { 383 printf("hp%d: %d sectors, %d tracks, %d cylinders: unknown device\n", 384 mi->mi_unit, nsectors, ntracks, ncyl); 385 type = HPDT_RM02; 386 } 387 printf("hp%d: %s\n", mi->mi_unit, hpst[type].name); 388 hpaddr->hpcs1 = HP_DCLR|HP_GO; 389 mbclrattn(mi); /* conservative */ 390 return (type); 391 } 392 393 /* 394 * Map all ML11's to the same type. Also calculate 395 * transfer rates based on device characteristics. 396 */ 397 if (type == HPDT_ML11A || type == HPDT_ML11B) { 398 register struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 399 register int trt; 400 401 sc->sc_mlsize = hpaddr->hpmr & HPMR_SZ; 402 if ((hpaddr->hpmr & HPMR_ARRTYP) == 0) 403 sc->sc_mlsize >>= 2; 404 if (mi->mi_dk >= 0) { 405 trt = (hpaddr->hpmr & HPMR_TRT) >> 8; 406 dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt)); 407 } 408 type = HPDT_ML11A; 409 } 410 return (type); 411 } 412 413 hpopen(dev) 414 dev_t dev; 415 { 416 register int unit = hpunit(dev); 417 register struct mba_device *mi; 418 419 if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0) 420 return (ENXIO); 421 return (0); 422 } 423 424 hpstrategy(bp) 425 register struct buf *bp; 426 { 427 register struct mba_device *mi; 428 register struct hpst *st; 429 register int unit; 430 long sz; 431 int xunit = minor(bp->b_dev) & 07; 432 int s; 433 434 sz = bp->b_bcount; 435 sz = (sz+511) >> 9; 436 unit = hpunit(bp->b_dev); 437 if (unit >= NHP) { 438 bp->b_error = ENXIO; 439 goto bad; 440 } 441 mi = hpinfo[unit]; 442 if (mi == 0 || mi->mi_alive == 0) { 443 bp->b_error = ENXIO; 444 goto bad; 445 } 446 st = &hpst[mi->mi_type]; 447 if (ML11) { 448 struct hpsoftc *sc = &hpsoftc[unit]; 449 450 if (bp->b_blkno < 0 || 451 bp->b_blkno+sz > sc->sc_mlsize) { 452 if (bp->b_blkno == sc->sc_mlsize) { 453 bp->b_resid = bp->b_bcount; 454 goto done; 455 } 456 bp->b_error = EINVAL; 457 goto bad; 458 } 459 bp->b_cylin = 0; 460 } else { 461 if (bp->b_blkno < 0 || 462 bp->b_blkno+sz > st->sizes[xunit].nblocks) { 463 if (bp->b_blkno == st->sizes[xunit].nblocks) { 464 bp->b_resid = bp->b_bcount; 465 goto done; 466 } 467 bp->b_error = EINVAL; 468 goto bad; 469 } 470 bp->b_cylin = bp->b_blkno/st->nspc + st->sizes[xunit].cyloff; 471 } 472 s = spl5(); 473 disksort(&mi->mi_tab, bp); 474 if (mi->mi_tab.b_active == 0) 475 mbustart(mi); 476 splx(s); 477 return; 478 479 bad: 480 bp->b_flags |= B_ERROR; 481 done: 482 iodone(bp); 483 return; 484 } 485 486 hpustart(mi) 487 register struct mba_device *mi; 488 { 489 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 490 register struct buf *bp = mi->mi_tab.b_actf; 491 register struct hpst *st; 492 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 493 daddr_t bn; 494 int sn, tn, dist; 495 496 st = &hpst[mi->mi_type]; 497 hpaddr->hpcs1 = 0; 498 if ((hpaddr->hpcs1&HP_DVA) == 0) 499 return (MBU_BUSY); 500 501 switch (sc->sc_recal) { 502 503 case 1: 504 (void)HPWAIT(mi, hpaddr); 505 hpaddr->hpdc = bp->b_cylin; 506 hpaddr->hpcs1 = HP_SEEK|HP_GO; 507 sc->sc_recal++; 508 return (MBU_STARTED); 509 case 2: 510 break; 511 } 512 sc->sc_recal = 0; 513 if ((hpaddr->hpds & HPDS_VV) == 0 || !sc->sc_hpinit) { 514 struct buf *bbp = &bhpbuf[mi->mi_unit]; 515 516 sc->sc_hpinit = 1; 517 hpaddr->hpcs1 = HP_DCLR|HP_GO; 518 if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive)) 519 printf("DCLR attn\n"); 520 hpaddr->hpcs1 = HP_PRESET|HP_GO; 521 if (!ML11) 522 hpaddr->hpof = HPOF_FMT22; 523 mbclrattn(mi); 524 if (!ML11) { 525 bbp->b_flags = B_READ|B_BUSY; 526 bbp->b_dev = bp->b_dev; 527 bbp->b_bcount = 512; 528 bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit]; 529 bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 530 bbp->b_cylin = st->ncyl - 1; 531 mi->mi_tab.b_actf = bbp; 532 bbp->av_forw = bp; 533 bp = bbp; 534 } 535 } 536 if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) { 537 if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags & B_READ)) { 538 hpaddr->hpof = 539 hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22; 540 hpaddr->hpcs1 = HP_OFFSET|HP_GO; 541 (void)HPWAIT(mi, hpaddr); 542 mbclrattn(mi); 543 } 544 return (MBU_DODATA); 545 } 546 if (ML11) 547 return (MBU_DODATA); 548 if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY) 549 return (MBU_DODATA); 550 bn = bp->b_blkno; 551 sn = bn % st->nspc; 552 tn = sn / st->nsect; 553 sn = sn % st->nsect; 554 if (bp->b_cylin == MASKREG(hpaddr->hpdc)) { 555 if (sc->sc_doseeks) 556 return (MBU_DODATA); 557 dist = sn - (MASKREG(hpaddr->hpla) >> 6) - 1; 558 if (dist < 0) 559 dist += st->nsect; 560 if (dist > st->maxdist || dist < st->mindist) 561 return (MBU_DODATA); 562 } else 563 hpaddr->hpdc = bp->b_cylin; 564 if (sc->sc_doseeks) 565 hpaddr->hpcs1 = HP_SEEK|HP_GO; 566 else { 567 sn = (sn + st->nsect - st->sdist) % st->nsect; 568 hpaddr->hpda = (tn << 8) + sn; 569 hpaddr->hpcs1 = HP_SEARCH|HP_GO; 570 } 571 return (MBU_STARTED); 572 } 573 574 hpstart(mi) 575 register struct mba_device *mi; 576 { 577 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 578 register struct buf *bp = mi->mi_tab.b_actf; 579 register struct hpst *st = &hpst[mi->mi_type]; 580 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 581 daddr_t bn; 582 int sn, tn, cn; 583 584 if (ML11) 585 hpaddr->hpda = bp->b_blkno + sc->sc_blkdone; 586 else { 587 if (bp->b_flags & B_BAD) { 588 bn = sc->sc_badbn; 589 cn = bn / st->nspc; 590 } else { 591 bn = bp->b_blkno; 592 cn = bp->b_cylin; 593 } 594 sn = bn % st->nspc; 595 if ((bp->b_flags & B_BAD) == 0) 596 sn += sc->sc_blkdone; 597 tn = sn / st->nsect; 598 sn %= st->nsect; 599 cn += tn / st->ntrak; 600 tn %= st->ntrak; 601 hpaddr->hpda = (tn << 8) + sn; 602 hpaddr->hpdc = cn; 603 } 604 mi->mi_tab.b_bdone = dbtob(sc->sc_blkdone); 605 if (sc->sc_hdr) { 606 if (bp->b_flags & B_READ) 607 return (HP_RHDR|HP_GO); 608 else 609 return (HP_WHDR|HP_GO); 610 } 611 return (0); 612 } 613 614 hpdtint(mi, mbsr) 615 register struct mba_device *mi; 616 int mbsr; 617 { 618 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 619 register struct buf *bp = mi->mi_tab.b_actf; 620 register int er1, er2; 621 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 622 int retry = 0; 623 int npf; 624 daddr_t bn; 625 int bcr; 626 627 bcr = MASKREG(-mi->mi_mba->mba_bcr); 628 if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) { 629 er1 = hpaddr->hper1; 630 er2 = hpaddr->hper2; 631 if (bp->b_flags & B_BAD) { 632 npf = bp->b_error; 633 bn = sc->sc_badbn; 634 } else { 635 npf = btop(bp->b_bcount - bcr); 636 if (er1 & (HPER1_DCK | HPER1_ECH)) 637 npf--; 638 bn = bp->b_blkno + npf; 639 } 640 if (HPWAIT(mi, hpaddr) == 0) 641 goto hard; 642 #ifdef HPDEBUG 643 if (hpdebug) { 644 int dc = hpaddr->hpdc, da = hpaddr->hpda; 645 646 log(LOG_DEBUG, 647 "hperr: bp %x cyl %d blk %d blkdone %d as %o dc %x da %x\n", 648 bp, bp->b_cylin, bn, sc->sc_blkdone, 649 hpaddr->hpas&0xff, MASKREG(dc), MASKREG(da)); 650 log(LOG_DEBUG, 651 "errcnt %d mbsr=%b er1=%b er2=%b bcr -%d\n", 652 mi->mi_tab.b_errcnt, mbsr, mbsr_bits, 653 MASKREG(er1), HPER1_BITS, 654 MASKREG(er2), HPER2_BITS, bcr); 655 } 656 #endif 657 if (er1 & HPER1_HCRC) { 658 er1 &= ~(HPER1_HCE|HPER1_FER); 659 er2 &= ~HPER2_BSE; 660 } 661 if (er1 & HPER1_WLE) { 662 log(LOG_WARNING, "hp%d: write locked\n", 663 hpunit(bp->b_dev)); 664 bp->b_flags |= B_ERROR; 665 } else if (sc->sc_hdr) { 666 goto hard; 667 } else if (RM80 && er2&HPER2_SSE) { 668 (void) hpecc(mi, SSE); 669 return (MBD_RESTARTED); 670 } else if ((er2 & HPER2_BSE) && !ML11) { 671 if (hpecc(mi, BSE)) 672 return (MBD_RESTARTED); 673 goto hard; 674 } else if (MASKREG(er1) == HPER1_FER && RP06) { 675 if (hpecc(mi, BSE)) 676 return (MBD_RESTARTED); 677 goto hard; 678 } else if ((er1 & (HPER1_DCK | HPER1_ECH)) == HPER1_DCK && 679 mi->mi_tab.b_errcnt >= 3) { 680 if (hpecc(mi, ECC)) 681 return (MBD_RESTARTED); 682 /* 683 * ECC corrected. Only log retries below 684 * if we got errors other than soft ECC 685 * (as indicated by additional retries). 686 */ 687 if (mi->mi_tab.b_errcnt == 3) 688 mi->mi_tab.b_errcnt = 0; 689 } else if ((er1 & HPER1_HCRC) && !ML11 && hpecc(mi, BSE)) { 690 /* 691 * HCRC means the header is screwed up and the sector 692 * might well exist in the bad sector table, 693 * better check.... 694 */ 695 return (MBD_RESTARTED); 696 } else if (++mi->mi_tab.b_errcnt > 27 || 697 (ML11 && mi->mi_tab.b_errcnt > 15) || 698 mbsr & MBSR_HARD || 699 er1 & HPER1_HARD || 700 (!ML11 && (er2 & HPER2_HARD))) { 701 hard: 702 bp->b_blkno = bn; /* XXX */ 703 harderr(bp, "hp"); 704 if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC))) 705 printf("mbsr=%b ", mbsr, mbsr_bits); 706 printf("er1=%b er2=%b", 707 MASKREG(hpaddr->hper1), HPER1_BITS, 708 MASKREG(hpaddr->hper2), HPER2_BITS); 709 if (sc->sc_hdr) 710 printf(" (hdr i/o)"); 711 printf("\n"); 712 bp->b_flags |= B_ERROR; 713 bp->b_flags &= ~B_BAD; 714 } else 715 retry = 1; 716 hpaddr->hpcs1 = HP_DCLR|HP_GO; 717 if (retry && (mi->mi_tab.b_errcnt & 07) == 4) { 718 hpaddr->hpcs1 = HP_RECAL|HP_GO; 719 sc->sc_recal = 1; 720 return (MBD_REPOSITION); 721 } 722 } 723 #ifdef HPDEBUG 724 else 725 if (hpdebug && sc->sc_recal) { 726 log(LOG_DEBUG, 727 "recal %d errcnt %d mbsr=%b er1=%b er2=%b\n", 728 sc->sc_recal, mi->mi_tab.b_errcnt, mbsr, mbsr_bits, 729 hpaddr->hper1, HPER1_BITS, 730 hpaddr->hper2, HPER2_BITS); 731 } 732 #endif 733 (void)HPWAIT(mi, hpaddr); 734 if (retry) 735 return (MBD_RETRY); 736 if (mi->mi_tab.b_errcnt >= 16) { 737 /* 738 * This is fast and occurs rarely; we don't 739 * bother with interrupts. 740 */ 741 hpaddr->hpcs1 = HP_RTC|HP_GO; 742 (void)HPWAIT(mi, hpaddr); 743 mbclrattn(mi); 744 } 745 if (mi->mi_tab.b_errcnt && (bp->b_flags & B_ERROR) == 0) 746 log(LOG_INFO, "hp%d%c: %d retries %sing sn%d\n", 747 hpunit(bp->b_dev), 'a'+(minor(bp->b_dev)&07), 748 mi->mi_tab.b_errcnt, 749 (bp->b_flags & B_READ) ? "read" : "writ", 750 (bp->b_flags & B_BAD) ? 751 sc->sc_badbn : bp->b_blkno + sc->sc_blkdone); 752 if ((bp->b_flags & B_BAD) && hpecc(mi, CONT)) 753 return (MBD_RESTARTED); 754 sc->sc_hdr = 0; 755 sc->sc_blkdone = 0; 756 bp->b_resid = bcr; 757 if (!ML11) { 758 hpaddr->hpof = HPOF_FMT22; 759 hpaddr->hpcs1 = HP_RELEASE|HP_GO; 760 } 761 return (MBD_DONE); 762 } 763 764 /* 765 * Wait (for a bit) for a drive to come ready; 766 * returns nonzero on success. 767 */ 768 hpwait(mi) 769 register struct mba_device *mi; 770 { 771 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 772 register i = 100000; 773 774 while ((hpaddr->hpds & HPDS_DRY) == 0 && --i) 775 DELAY(10); 776 if (i == 0) 777 printf("hp%d: intr, not ready\n", mi->mi_unit); 778 return (i); 779 } 780 781 hpread(dev, uio) 782 dev_t dev; 783 struct uio *uio; 784 { 785 register int unit = hpunit(dev); 786 787 if (unit >= NHP) 788 return (ENXIO); 789 return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio)); 790 } 791 792 hpwrite(dev, uio) 793 dev_t dev; 794 struct uio *uio; 795 { 796 register int unit = hpunit(dev); 797 798 if (unit >= NHP) 799 return (ENXIO); 800 return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio)); 801 } 802 803 /*ARGSUSED*/ 804 hpioctl(dev, cmd, data, flag) 805 dev_t dev; 806 int cmd; 807 caddr_t data; 808 int flag; 809 { 810 811 switch (cmd) { 812 813 case DKIOCHDR: /* do header read/write */ 814 hpsoftc[hpunit(dev)].sc_hdr = 1; 815 return (0); 816 817 default: 818 return (ENXIO); 819 } 820 } 821 822 hpecc(mi, flag) 823 register struct mba_device *mi; 824 int flag; 825 { 826 register struct mba_regs *mbp = mi->mi_mba; 827 register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; 828 register struct buf *bp = mi->mi_tab.b_actf; 829 register struct hpst *st = &hpst[mi->mi_type]; 830 struct hpsoftc *sc = &hpsoftc[mi->mi_unit]; 831 int npf, o; 832 int bn, cn, tn, sn; 833 int bcr; 834 835 bcr = MASKREG(-mbp->mba_bcr); 836 if (bp->b_flags & B_BAD) 837 npf = bp->b_error; 838 else { 839 npf = bp->b_bcount - bcr; 840 /* 841 * Watch out for fractional sector at end of transfer; 842 * want to round up if finished, otherwise round down. 843 */ 844 if (bcr == 0) 845 npf += 511; 846 npf = btodb(npf); 847 } 848 o = (int)bp->b_un.b_addr & PGOFSET; 849 bn = bp->b_blkno; 850 cn = bp->b_cylin; 851 sn = bn%(st->nspc) + npf; 852 tn = sn/st->nsect; 853 sn %= st->nsect; 854 cn += tn/st->ntrak; 855 tn %= st->ntrak; 856 bn += npf; 857 switch (flag) { 858 case ECC: { 859 register int i; 860 caddr_t addr; 861 struct pte mpte; 862 int bit, byte, mask; 863 864 npf--; /* because block in error is previous block */ 865 bn--; 866 if (bp->b_flags & B_BAD) 867 bn = sc->sc_badbn; 868 log(LOG_WARNING, "hp%d%c: soft ecc sn%d\n", hpunit(bp->b_dev), 869 'a'+(minor(bp->b_dev)&07), bn); 870 mask = MASKREG(rp->hpec2); 871 i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 872 bit = i&07; 873 i = (i&~07)>>3; 874 byte = i + o; 875 while (i < 512 && (int)dbtob(npf)+i < bp->b_bcount && bit > -11) { 876 mpte = mbp->mba_map[npf+btop(byte)]; 877 addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); 878 putmemc(addr, getmemc(addr)^(mask<<bit)); 879 byte++; 880 i++; 881 bit -= 8; 882 } 883 if (bcr == 0) 884 return (0); 885 npf++; 886 break; 887 } 888 889 case SSE: 890 rp->hpof |= HPOF_SSEI; 891 if (bp->b_flags & B_BAD) { 892 bn = sc->sc_badbn; 893 goto fixregs; 894 } 895 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 896 break; 897 898 case BSE: 899 if (rp->hpof & HPOF_SSEI) 900 sn++; 901 #ifdef HPBDEBUG 902 if (hpbdebug) 903 log(LOG_DEBUG, "hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 904 #endif 905 if (bp->b_flags & B_BAD) 906 return (0); 907 if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0) 908 return (0); 909 bp->b_flags |= B_BAD; 910 bp->b_error = npf + 1; 911 rp->hpof &= ~HPOF_SSEI; 912 bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 913 sc->sc_badbn = bn; 914 fixregs: 915 cn = bn/st->nspc; 916 sn = bn%st->nspc; 917 tn = sn/st->nsect; 918 sn %= st->nsect; 919 bcr = bp->b_bcount - (int)ptob(npf); 920 bcr = MIN(bcr, 512); 921 mbp->mba_bcr = -bcr; 922 #ifdef HPBDEBUG 923 if (hpbdebug) 924 log(LOG_DEBUG, "revector to cn %d tn %d sn %d\n", cn, tn, sn); 925 #endif 926 break; 927 928 case CONT: 929 #ifdef HPBDEBUG 930 if (hpbdebug) 931 log(LOG_DEBUG, "hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 932 #endif 933 bp->b_flags &= ~B_BAD; 934 if ((int)ptob(npf) >= bp->b_bcount) 935 return (0); 936 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 937 break; 938 } 939 rp->hpcs1 = HP_DCLR|HP_GO; 940 if (rp->hpof & HPOF_SSEI) 941 sn++; 942 rp->hpdc = cn; 943 rp->hpda = (tn<<8) + sn; 944 mbp->mba_sr = -1; 945 mbp->mba_var = (int)ptob(npf) + o; 946 rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO; 947 mi->mi_tab.b_errcnt = 0; /* error has been corrected */ 948 sc->sc_blkdone = npf; 949 return (1); 950 } 951 952 #define DBSIZE 20 953 954 hpdump(dev) 955 dev_t dev; 956 { 957 register struct mba_device *mi; 958 register struct mba_regs *mba; 959 struct hpdevice *hpaddr; 960 char *start; 961 int num, unit; 962 register struct hpst *st; 963 964 num = maxfree; 965 start = 0; 966 unit = hpunit(dev); 967 if (unit >= NHP) 968 return (ENXIO); 969 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 970 mi = phys(hpinfo[unit],struct mba_device *); 971 if (mi == 0 || mi->mi_alive == 0) 972 return (ENXIO); 973 mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 974 mba->mba_cr = MBCR_INIT; 975 hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; 976 if ((hpaddr->hpds & HPDS_VV) == 0) { 977 hpaddr->hpcs1 = HP_DCLR|HP_GO; 978 hpaddr->hpcs1 = HP_PRESET|HP_GO; 979 hpaddr->hpof = HPOF_FMT22; 980 } 981 st = &hpst[mi->mi_type]; 982 if (dumplo < 0) 983 return (EINVAL); 984 if (dumplo + num >= st->sizes[minor(dev)&07].nblocks) 985 num = st->sizes[minor(dev)&07].nblocks - dumplo; 986 while (num > 0) { 987 register struct pte *hpte = mba->mba_map; 988 register int i; 989 int blk, cn, sn, tn; 990 daddr_t bn; 991 992 blk = num > DBSIZE ? DBSIZE : num; 993 bn = dumplo + btop(start); 994 cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; 995 sn = bn%st->nspc; 996 tn = sn/st->nsect; 997 sn = sn%st->nsect; 998 hpaddr->hpdc = cn; 999 hpaddr->hpda = (tn << 8) + sn; 1000 for (i = 0; i < blk; i++) 1001 *(int *)hpte++ = (btop(start)+i) | PG_V; 1002 mba->mba_sr = -1; 1003 mba->mba_bcr = -(blk*NBPG); 1004 mba->mba_var = 0; 1005 hpaddr->hpcs1 = HP_WCOM | HP_GO; 1006 while ((hpaddr->hpds & HPDS_DRY) == 0) 1007 DELAY(10); 1008 if (hpaddr->hpds&HPDS_ERR) 1009 return (EIO); 1010 start += blk*NBPG; 1011 num -= blk; 1012 } 1013 return (0); 1014 } 1015 1016 hpsize(dev) 1017 dev_t dev; 1018 { 1019 int unit = hpunit(dev); 1020 struct mba_device *mi; 1021 struct hpst *st; 1022 1023 if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0) 1024 return (-1); 1025 st = &hpst[mi->mi_type]; 1026 return ((int)st->sizes[minor(dev) & 07].nblocks); 1027 } 1028 #endif 1029