1 /* hp.c 4.53 82/08/22 */ 2 3 #ifdef HPDEBUG 4 int hpdebug; 5 #endif 6 #ifdef HPBDEBUG 7 int hpbdebug; 8 #endif 9 10 #include "hp.h" 11 #if NHP > 0 12 /* 13 * HP disk driver for RP0x+RMxx+ML11 14 * 15 * TODO: 16 * check RM80 skip sector handling when ECC's occur later 17 * check offset recovery handling 18 * see if DCLR and/or RELEASE set attention status 19 * print bits of mr && mr2 symbolically 20 */ 21 22 #include "../h/param.h" 23 #include "../h/systm.h" 24 #include "../h/dk.h" 25 #include "../h/buf.h" 26 #include "../h/conf.h" 27 #include "../h/dir.h" 28 #include "../h/user.h" 29 #include "../h/map.h" 30 #include "../h/pte.h" 31 #include "../h/mbareg.h" 32 #include "../h/mbavar.h" 33 #include "../h/mtpr.h" 34 #include "../h/vm.h" 35 #include "../h/cmap.h" 36 #include "../h/dkbad.h" 37 #include "../h/ioctl.h" 38 #include "../h/dkio.h" 39 #include "../h/uio.h" 40 41 #include "../h/hpreg.h" 42 43 /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 44 struct size { 45 daddr_t nblocks; 46 int cyloff; 47 } hp6_sizes[8] = { 48 15884, 0, /* A=cyl 0 thru 37 */ 49 33440, 38, /* B=cyl 38 thru 117 */ 50 340670, 0, /* C=cyl 0 thru 814 */ 51 0, 0, 52 0, 0, 53 0, 0, 54 #ifndef NOBADSECT 55 291280, 118, /* G=cyl 118 thru 814 */ 56 #else 57 291346, 118, 58 #endif 59 0, 0, 60 }, rm3_sizes[8] = { 61 15884, 0, /* A=cyl 0 thru 99 */ 62 33440, 100, /* B=cyl 100 thru 309 */ 63 131680, 0, /* C=cyl 0 thru 822 */ 64 0, 0, 65 0, 0, 66 0, 0, 67 #ifndef NOBADSECT 68 81984, 310, /* G=cyl 310 thru 822 */ 69 #else 70 82080, 310, 71 #endif 72 0, 0, 73 }, rm5_sizes[8] = { 74 #ifndef CAD 75 15884, 0, /* A=cyl 0 thru 26 */ 76 33440, 27, /* B=cyl 27 thru 81 */ 77 500384, 0, /* C=cyl 0 thru 822 */ 78 15884, 562, /* D=cyl 562 thru 588 */ 79 55936, 589, /* E=cyl 589 thru 680 */ 80 #ifndef NOBADSECT 81 86240, 681, /* F=cyl 681 thru 822 */ 82 158592, 562, /* G=cyl 562 thru 822 */ 83 #else 84 86336, 681, 85 158688, 562, 86 #endif 87 291346, 82, /* H=cyl 82 thru 561 */ 88 #else 89 15884, 0, /* A=cyl 0 thru 26 */ 90 33440, 27, /* B=cyl 27 thru 81 */ 91 495520, 0, /* C=cyl 0 thru 814 */ 92 15884, 562, /* D=cyl 562 thru 588 */ 93 55936, 589, /* E=cyl 589 thru 680 */ 94 #ifndef NOBADSECT 95 81376, 681, /* F=cyl 681 thru 814 */ 96 153728, 562, /* G=cyl 562 thru 814 */ 97 #else 98 81472, 681, 99 153824, 562, 100 #endif 101 291346, 82, /* H=cyl 82 thru 561 */ 102 #endif 103 }, rm80_sizes[8] = { 104 15884, 0, /* A=cyl 0 thru 36 */ 105 33440, 37, /* B=cyl 37 thru 114 */ 106 242606, 0, /* C=cyl 0 thru 558 */ 107 0, 0, 108 0, 0, 109 0, 0, 110 82080, 115, /* G=cyl 115 thru 304 */ 111 110143, 305, /* H=cyl 305 thru 558 */ 112 }, hp7_sizes[8] = { 113 15884, 0, /* A=cyl 0 thru 9 */ 114 64000, 10, /* B=cyl 10 thru 49 */ 115 1008000,0, /* C=cyl 0 thru 629 */ 116 15884, 330, /* D=cyl 330 thru 339 */ 117 256000, 340, /* E=cyl 340 thru 499 */ 118 207850, 500, /* F=cyl 500 thru 629 */ 119 479850, 330, /* G=cyl 330 thru 629 */ 120 448000, 50, /* H=cyl 50 thru 329 */ 121 }, si9775_sizes[8] = { 122 16640, 0, /* A=cyl 0 thru 12 */ 123 34560, 13, /* B=cyl 13 thru 39 */ 124 1079040, 0, /* C=cyl 0 thru 842 - whole disk */ 125 0, 0, /* D unused */ 126 0, 0, /* E unused */ 127 0, 0, /* F unused */ 128 513280, 40, /* G=cyl 40 thru 440 */ 129 513280, 441, /* H=cyl 441 thru 841 */ 130 }, si9730_sizes[8] = { 131 15884, 0, /* A=cyl 0 thru 49 */ 132 33440, 50, /* B=cyl 50 thru 154 */ 133 263360, 0, /* C=cyl 0 thru 822 */ 134 0, 0, 135 0, 0, 136 0, 0, 137 0, 0, 138 #ifndef NOBADSECT 139 213664, 155, /* H=cyl 155 thru 822 */ 140 #else 141 213760, 155, 142 #endif 143 }, hpam_sizes[8] = { 144 15884, 0, /* A=cyl 0 thru 31 */ 145 33440, 32, /* B=cyl 32 thru 97 */ 146 524288, 0, /* C=cyl 0 thru 1023 */ 147 27786, 668, 148 27786, 723, 149 125440, 778, 150 181760, 668, /* G=cyl 668 thru 1022 */ 151 291346, 98, /* H=cyl 98 thru 667 */ 152 }; 153 /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 154 155 #define _hpSDIST 2 156 #define _hpRDIST 3 157 158 int hpSDIST = _hpSDIST; 159 int hpRDIST = _hpRDIST; 160 161 /* 162 * Table for converting Massbus drive types into 163 * indices into the partition tables. Slots are 164 * left for those drives devined from other means 165 * (e.g. SI, AMPEX, etc.). 166 */ 167 short hptypes[] = { 168 #define HPDT_RM03 0 169 MBDT_RM03, 170 #define HPDT_RM05 1 171 MBDT_RM05, 172 #define HPDT_RP06 2 173 MBDT_RP06, 174 #define HPDT_RM80 3 175 MBDT_RM80, 176 #define HPDT_RP05 4 177 MBDT_RP05, 178 #define HPDT_RP07 5 179 MBDT_RP07, 180 #define HPDT_ML11A 6 181 MBDT_ML11A, 182 #define HPDT_ML11B 7 183 MBDT_ML11B, 184 #define HPDT_9775 8 185 -1, 186 #define HPDT_9730 9 187 -1, 188 #define HPDT_CAPRICORN 10 189 -1, 190 #define HPDT_RM02 11 191 MBDT_RM02, /* beware, actually capricorn */ 192 0 193 }; 194 struct mba_device *hpinfo[NHP]; 195 int hpattach(),hpustart(),hpstart(),hpdtint(); 196 struct mba_driver hpdriver = 197 { hpattach, 0, hpustart, hpstart, hpdtint, 0, 198 hptypes, "hp", 0, hpinfo }; 199 200 struct hpst { 201 short nsect; 202 short ntrak; 203 short nspc; 204 short ncyl; 205 struct size *sizes; 206 } hpst[] = { 207 32, 5, 32*5, 823, rm3_sizes, /* RM03 */ 208 32, 19, 32*19, 823, rm5_sizes, /* RM05 */ 209 22, 19, 22*19, 815, hp6_sizes, /* RP06 */ 210 31, 14, 31*14, 559, rm80_sizes, /* RM80 */ 211 22, 19, 22*19, 411, hp6_sizes, /* RP05 */ 212 50, 32, 50*32, 630, hp7_sizes, /* RP07 */ 213 1, 1, 1, 1, 0, /* ML11A */ 214 1, 1, 1, 1, 0, /* ML11B */ 215 32, 40, 32*40, 843, si9775_sizes, /* 9775 */ 216 32, 10, 32*10, 823, si9730_sizes, /* 9730 */ 217 32, 16, 32*16, 1024, hpam_sizes, /* AMPEX capricorn */ 218 }; 219 220 u_char hp_offset[16] = { 221 HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 222 HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 223 HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 224 0, 0, 0, 0, 225 }; 226 227 struct buf rhpbuf[NHP]; 228 #ifndef NOBADSECT 229 struct buf bhpbuf[NHP]; 230 struct dkbad hpbad[NHP]; 231 #endif 232 /* SHOULD CONSOLIDATE ALL THIS STUFF INTO A STRUCTURE */ 233 char hpinit[NHP]; 234 char hprecal[NHP]; 235 char hphdr[NHP]; 236 daddr_t mlsize[NHP]; 237 238 #define b_cylin b_resid 239 240 /* #define ML11 0 to remove ML11 support */ 241 #define ML11 (hptypes[mi->mi_type] == MBDT_ML11A) 242 #define RP06 (hptypes[mi->mi_type] <= MBDT_RP06) 243 #define RM80 (hptypes[mi->mi_type] == MBDT_RM80) 244 245 #ifdef INTRLVE 246 daddr_t dkblock(); 247 #endif 248 249 int hpseek; 250 251 /*ARGSUSED*/ 252 hpattach(mi, slave) 253 struct mba_device *mi; 254 { 255 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 256 257 switch (mi->mi_type) { 258 259 /* 260 * Model-byte processing for SI 9400 controllers. 261 * NB: Only deals with RM03 and RM05 emulations. 262 */ 263 case HPDT_RM03: 264 case HPDT_RM05: { 265 register int hpsn; 266 267 hpsn = hpaddr->hpsn; 268 if ((hpsn & SIMB_LU) != mi->mi_drive) 269 break; 270 switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) { 271 272 case SI9775D: 273 printf("hp%d: si 9775 (direct)\n", mi->mi_unit); 274 mi->mi_type = HPDT_9775; 275 break; 276 277 case SI9730D: 278 printf("hp%d: si 9730 (direct)\n", mi->mi_unit); 279 mi->mi_type = HPDT_9730; 280 break; 281 282 #ifdef CAD 283 /* 284 * AMPEX 9300, SI Combination needs a have the drive cleared 285 * before we start. We do not know why, but tests show 286 * that the recalibrate fixes the problem. 287 */ 288 case SI9766: 289 printf("hp%d: 9776/9300\n", mi->mi_unit); 290 mi->mi_type = HPDT_RM05; 291 hpaddr->hpcs1 = HP_RECAL|HP_GO; 292 DELAY(100000); 293 break; 294 295 case SI9762: 296 printf("hp%d: 9762\n", mi->mi_unit); 297 mi->mi_type = HPDT_RM03; 298 break; 299 #endif 300 } 301 break; 302 } 303 304 /* 305 * CAPRICORN KLUDGE...poke the holding register 306 * to find out the number of tracks. If it's 15 307 * we believe it's a Capricorn. 308 */ 309 case HPDT_RM02: 310 hpaddr->hpcs1 = HP_NOP; 311 hpaddr->hphr = HPHR_MAXTRAK; 312 if ((hpaddr->hphr&0xffff) == 15) { 313 printf("hp%d: capricorn\n", mi->mi_unit); 314 mi->mi_type = HPDT_CAPRICORN; 315 } 316 hpaddr->hpcs1 = HP_DCLR|HP_GO; 317 break; 318 319 case HPDT_ML11A: 320 case HPDT_ML11B: { 321 register int trt, sz; 322 323 sz = hpaddr->hpmr & HPMR_SZ; 324 if ((hpaddr->hpmr & HPMR_ARRTYP) == 0) 325 sz >>= 2; 326 mlsize[mi->mi_unit] = sz; 327 if (mi->mi_dk >= 0) { 328 trt = (hpaddr->hpmr & HPMR_TRT) >> 8; 329 dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt)); 330 } 331 /* A CHEAT - ML11B D.T. SHOULD == ML11A */ 332 mi->mi_type = HPDT_ML11A; 333 break; 334 } 335 } 336 if (!ML11 && mi->mi_dk >= 0) { 337 register struct hpst *st = &hpst[mi->mi_type]; 338 339 dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256); 340 } 341 } 342 343 hpstrategy(bp) 344 register struct buf *bp; 345 { 346 register struct mba_device *mi; 347 register struct hpst *st; 348 register int unit; 349 long sz, bn; 350 int xunit = minor(bp->b_dev) & 07; 351 int s; 352 353 sz = bp->b_bcount; 354 sz = (sz+511) >> 9; 355 unit = dkunit(bp); 356 if (unit >= NHP) 357 goto bad; 358 mi = hpinfo[unit]; 359 if (mi == 0 || mi->mi_alive == 0) 360 goto bad; 361 st = &hpst[mi->mi_type]; 362 if (ML11) { 363 if (bp->b_blkno < 0 || 364 dkblock(bp)+sz > mlsize[mi->mi_unit]) 365 goto bad; 366 bp->b_cylin = 0; 367 } else { 368 if (bp->b_blkno < 0 || 369 (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 370 goto bad; 371 bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 372 } 373 s = spl5(); 374 disksort(&mi->mi_tab, bp); 375 if (mi->mi_tab.b_active == 0) 376 mbustart(mi); 377 splx(s); 378 return; 379 380 bad: 381 bp->b_flags |= B_ERROR; 382 iodone(bp); 383 return; 384 } 385 386 hpustart(mi) 387 register struct mba_device *mi; 388 { 389 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 390 register struct buf *bp = mi->mi_tab.b_actf; 391 register struct hpst *st = &hpst[mi->mi_type]; 392 daddr_t bn; 393 int sn, dist; 394 395 hpaddr->hpcs1 = 0; 396 if ((hpaddr->hpcs1&HP_DVA) == 0) 397 return (MBU_BUSY); 398 if ((hpaddr->hpds & HPDS_VV) == 0 || hpinit[mi->mi_unit] == 0) { 399 #ifndef NOBADSECT 400 struct buf *bbp = &bhpbuf[mi->mi_unit]; 401 #endif 402 403 hpinit[mi->mi_unit] = 1; 404 hpaddr->hpcs1 = HP_DCLR|HP_GO; 405 if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive)) 406 printf("DCLR attn\n"); 407 hpaddr->hpcs1 = HP_PRESET|HP_GO; 408 if (!ML11) 409 hpaddr->hpof = HPOF_FMT22; 410 mbclrattn(mi); 411 #ifndef NOBADSECT 412 if (!ML11) { 413 bbp->b_flags = B_READ|B_BUSY; 414 bbp->b_dev = bp->b_dev; 415 bbp->b_bcount = 512; 416 bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit]; 417 bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 418 bbp->b_cylin = st->ncyl - 1; 419 mi->mi_tab.b_actf = bbp; 420 bbp->av_forw = bp; 421 bp = bbp; 422 } 423 #endif 424 } 425 if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) 426 return (MBU_DODATA); 427 if (ML11) 428 return (MBU_DODATA); 429 if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY) 430 return (MBU_DODATA); 431 bn = dkblock(bp); 432 sn = bn%st->nspc; 433 sn = (sn+st->nsect-hpSDIST)%st->nsect; 434 if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) { 435 if (hpseek) 436 return (MBU_DODATA); 437 dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1; 438 if (dist < 0) 439 dist += st->nsect; 440 if (dist > st->nsect - hpRDIST) 441 return (MBU_DODATA); 442 } else 443 hpaddr->hpdc = bp->b_cylin; 444 if (hpseek) 445 hpaddr->hpcs1 = HP_SEEK|HP_GO; 446 else { 447 hpaddr->hpda = sn; 448 hpaddr->hpcs1 = HP_SEARCH|HP_GO; 449 } 450 return (MBU_STARTED); 451 } 452 453 hpstart(mi) 454 register struct mba_device *mi; 455 { 456 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 457 register struct buf *bp = mi->mi_tab.b_actf; 458 register struct hpst *st = &hpst[mi->mi_type]; 459 daddr_t bn; 460 int sn, tn; 461 462 bn = dkblock(bp); 463 if (ML11) 464 hpaddr->hpda = bn; 465 else { 466 sn = bn%st->nspc; 467 tn = sn/st->nsect; 468 sn %= st->nsect; 469 hpaddr->hpdc = bp->b_cylin; 470 hpaddr->hpda = (tn << 8) + sn; 471 } 472 if (hphdr[mi->mi_unit]) { 473 if (bp->b_flags & B_READ) 474 return (HP_RHDR|HP_GO); 475 else 476 return (HP_WHDR|HP_GO); 477 } 478 return (0); 479 } 480 481 hpdtint(mi, mbsr) 482 register struct mba_device *mi; 483 int mbsr; 484 { 485 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 486 register struct buf *bp = mi->mi_tab.b_actf; 487 register int er1, er2; 488 int retry = 0; 489 490 #ifndef NOBADSECT 491 if (bp->b_flags&B_BAD) { 492 if (hpecc(mi, CONT)) 493 return(MBD_RESTARTED); 494 } 495 #endif 496 if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) { 497 #ifdef HPDEBUG 498 if (hpdebug) { 499 int dc = hpaddr->hpdc, da = hpaddr->hpda; 500 501 printf("hperr: bp %x cyl %d blk %d as %o ", 502 bp, bp->b_cylin, bp->b_blkno, 503 hpaddr->hpas&0xff); 504 printf("dc %x da %x\n",dc&0xffff, da&0xffff); 505 printf("errcnt %d ", mi->mi_tab.b_errcnt); 506 printf("mbsr=%b ", mbsr, mbsr_bits); 507 printf("er1=%b er2=%b\n", 508 hpaddr->hper1, HPER1_BITS, 509 hpaddr->hper2, HPER2_BITS); 510 DELAY(1000000); 511 } 512 #endif 513 er1 = hpaddr->hper1; 514 er2 = hpaddr->hper2; 515 if (er1 & HPER1_HCRC) { 516 er1 &= ~(HPER1_HCE|HPER1_FER); 517 er2 &= ~HPER2_BSE; 518 } 519 if (er1&HPER1_WLE) { 520 printf("hp%d: write locked\n", dkunit(bp)); 521 bp->b_flags |= B_ERROR; 522 } else if ((er1&0xffff) == HPER1_FER && RP06 && 523 hphdr[mi->mi_unit] == 0) { 524 #ifndef NOBADSECT 525 if (hpecc(mi, BSE)) 526 return(MBD_RESTARTED); 527 else 528 #endif 529 goto hard; 530 } else if (++mi->mi_tab.b_errcnt > 27 || 531 mbsr & MBSR_HARD || 532 er1 & HPER1_HARD || 533 hphdr[mi->mi_unit] || 534 (!ML11 && (er2 & HPER2_HARD))) { 535 hard: 536 harderr(bp, "hp"); 537 if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC))) 538 printf("mbsr=%b ", mbsr, mbsr_bits); 539 printf("er1=%b er2=%b", 540 hpaddr->hper1, HPER1_BITS, 541 hpaddr->hper2, HPER2_BITS); 542 if (hpaddr->hpmr) 543 printf(" mr=%o", hpaddr->hpmr&0xffff); 544 if (hpaddr->hpmr2) 545 printf(" mr2=%o", hpaddr->hpmr2&0xffff); 546 printf("\n"); 547 bp->b_flags |= B_ERROR; 548 hprecal[mi->mi_unit] = 0; 549 } else if ((er2 & HPER2_BSE) && !ML11) { 550 #ifndef NOBADSECT 551 if (hpecc(mi, BSE)) 552 return(MBD_RESTARTED); 553 else 554 #endif 555 goto hard; 556 } else if (RM80 && er2&HPER2_SSE) { 557 (void) hpecc(mi, SSE); 558 return (MBD_RESTARTED); 559 } else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) { 560 if (hpecc(mi, ECC)) 561 return (MBD_RESTARTED); 562 /* else done */ 563 } else 564 retry = 1; 565 hpaddr->hpcs1 = HP_DCLR|HP_GO; 566 if (ML11) { 567 if (mi->mi_tab.b_errcnt >= 16) 568 goto hard; 569 } else if ((mi->mi_tab.b_errcnt&07) == 4) { 570 hpaddr->hpcs1 = HP_RECAL|HP_GO; 571 hprecal[mi->mi_unit] = 1; 572 return(MBD_RESTARTED); 573 } 574 if (retry) 575 return (MBD_RETRY); 576 } 577 #ifdef HPDEBUG 578 else 579 if (hpdebug && hprecal[mi->mi_unit]) { 580 printf("recal %d ", hprecal[mi->mi_unit]); 581 printf("errcnt %d\n", mi->mi_tab.b_errcnt); 582 printf("mbsr=%b ", mbsr, mbsr_bits); 583 printf("er1=%b er2=%b\n", 584 hpaddr->hper1, HPER1_BITS, 585 hpaddr->hper2, HPER2_BITS); 586 } 587 #endif 588 switch (hprecal[mi->mi_unit]) { 589 590 case 1: 591 hpaddr->hpdc = bp->b_cylin; 592 hpaddr->hpcs1 = HP_SEEK|HP_GO; 593 hprecal[mi->mi_unit]++; 594 return (MBD_RESTARTED); 595 case 2: 596 if (mi->mi_tab.b_errcnt < 16 || 597 (bp->b_flags & B_READ) == 0) 598 goto donerecal; 599 hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22; 600 hpaddr->hpcs1 = HP_OFFSET|HP_GO; 601 hprecal[mi->mi_unit]++; 602 return (MBD_RESTARTED); 603 donerecal: 604 case 3: 605 hprecal[mi->mi_unit] = 0; 606 return (MBD_RETRY); 607 } 608 hphdr[mi->mi_unit] = 0; 609 bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff; 610 if (mi->mi_tab.b_errcnt >= 16) { 611 /* 612 * This is fast and occurs rarely; we don't 613 * bother with interrupts. 614 */ 615 hpaddr->hpcs1 = HP_RTC|HP_GO; 616 while (hpaddr->hpds & HPDS_PIP) 617 ; 618 mbclrattn(mi); 619 } 620 if (!ML11) { 621 hpaddr->hpof = HPOF_FMT22; 622 hpaddr->hpcs1 = HP_RELEASE|HP_GO; 623 } 624 return (MBD_DONE); 625 } 626 627 hpread(dev, uio) 628 dev_t dev; 629 struct uio *uio; 630 { 631 register int unit = minor(dev) >> 3; 632 633 if (unit >= NHP) 634 u.u_error = ENXIO; 635 else 636 physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio); 637 } 638 639 hpwrite(dev, uio) 640 dev_t dev; 641 struct uio *uio; 642 { 643 register int unit = minor(dev) >> 3; 644 645 if (unit >= NHP) 646 u.u_error = ENXIO; 647 else 648 physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio); 649 } 650 651 /*ARGSUSED*/ 652 hpioctl(dev, cmd, data, flag) 653 dev_t dev; 654 int cmd; 655 caddr_t data; 656 int flag; 657 { 658 659 switch (cmd) { 660 661 case DKIOCHDR: /* do header read/write */ 662 hphdr[minor(dev)>>3] = 1; 663 return; 664 665 default: 666 u.u_error = ENXIO; 667 } 668 } 669 670 hpecc(mi, flag) 671 register struct mba_device *mi; 672 int flag; 673 { 674 register struct mba_regs *mbp = mi->mi_mba; 675 register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; 676 register struct buf *bp = mi->mi_tab.b_actf; 677 register struct hpst *st = &hpst[mi->mi_type]; 678 int npf, o; 679 int bn, cn, tn, sn; 680 int bcr; 681 682 bcr = mbp->mba_bcr & 0xffff; 683 if (bcr) 684 bcr |= 0xffff0000; /* sxt */ 685 #ifndef NOBADSECT 686 if (flag == CONT) 687 npf = bp->b_error; 688 else 689 #endif 690 npf = btop(bcr + bp->b_bcount); 691 o = (int)bp->b_un.b_addr & PGOFSET; 692 bn = dkblock(bp); 693 cn = bp->b_cylin; 694 sn = bn%(st->nspc) + npf; 695 tn = sn/st->nsect; 696 sn %= st->nsect; 697 cn += tn/st->ntrak; 698 tn %= st->ntrak; 699 switch (flag) { 700 case ECC: 701 { 702 register int i; 703 caddr_t addr; 704 struct pte mpte; 705 int bit, byte, mask; 706 707 npf--; /* because block in error is previous block */ 708 printf("hp%d%c: soft ecc sn%d\n", dkunit(bp), 709 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 710 mask = rp->hpec2&0xffff; 711 i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */ 712 bit = i&07; 713 i = (i&~07)>>3; 714 byte = i + o; 715 while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 716 mpte = mbp->mba_map[npf+btop(byte)]; 717 addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); 718 putmemc(addr, getmemc(addr)^(mask<<bit)); 719 byte++; 720 i++; 721 bit -= 8; 722 } 723 if (bcr == 0) 724 return (0); 725 npf++; 726 break; 727 } 728 729 case SSE: 730 rp->hpof |= HPOF_SSEI; 731 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 732 break; 733 734 #ifndef NOBADSECT 735 case BSE: 736 #ifdef HPBDEBUG 737 if (hpbdebug) 738 printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 739 #endif 740 if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0) 741 return(0); 742 bp->b_flags |= B_BAD; 743 bp->b_error = npf + 1; 744 bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 745 cn = bn/st->nspc; 746 sn = bn%st->nspc; 747 tn = sn/st->nsect; 748 sn %= st->nsect; 749 mbp->mba_bcr = -512; 750 #ifdef HPBDEBUG 751 if (hpbdebug) 752 printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 753 #endif 754 break; 755 756 case CONT: 757 #ifdef HPBDEBUG 758 if (hpbdebug) 759 printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 760 #endif 761 npf = bp->b_error; 762 bp->b_flags &= ~B_BAD; 763 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 764 if ((mbp->mba_bcr & 0xffff) == 0) 765 return(0); 766 break; 767 #endif 768 } 769 rp->hpcs1 = HP_DCLR|HP_GO; 770 if (rp->hpof&HPOF_SSEI) 771 sn++; 772 rp->hpdc = cn; 773 rp->hpda = (tn<<8) + sn; 774 mbp->mba_sr = -1; 775 mbp->mba_var = (int)ptob(npf) + o; 776 rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO; 777 mi->mi_tab.b_errcnt = 0; /* error has been corrected */ 778 return (1); 779 } 780 781 #define DBSIZE 20 782 783 hpdump(dev) 784 dev_t dev; 785 { 786 register struct mba_device *mi; 787 register struct mba_regs *mba; 788 struct hpdevice *hpaddr; 789 char *start; 790 int num, unit; 791 register struct hpst *st; 792 793 num = maxfree; 794 start = 0; 795 unit = minor(dev) >> 3; 796 if (unit >= NHP) 797 return (ENXIO); 798 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 799 mi = phys(hpinfo[unit],struct mba_device *); 800 if (mi == 0 || mi->mi_alive == 0) 801 return (ENXIO); 802 mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 803 mba->mba_cr = MBCR_INIT; 804 hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; 805 if ((hpaddr->hpds & HPDS_VV) == 0) { 806 hpaddr->hpcs1 = HP_DCLR|HP_GO; 807 hpaddr->hpcs1 = HP_PRESET|HP_GO; 808 hpaddr->hpof = HPOF_FMT22; 809 } 810 st = &hpst[mi->mi_type]; 811 if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks) 812 return (EINVAL); 813 while (num > 0) { 814 register struct pte *hpte = mba->mba_map; 815 register int i; 816 int blk, cn, sn, tn; 817 daddr_t bn; 818 819 blk = num > DBSIZE ? DBSIZE : num; 820 bn = dumplo + btop(start); 821 cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; 822 sn = bn%st->nspc; 823 tn = sn/st->nsect; 824 sn = sn%st->nsect; 825 hpaddr->hpdc = cn; 826 hpaddr->hpda = (tn << 8) + sn; 827 for (i = 0; i < blk; i++) 828 *(int *)hpte++ = (btop(start)+i) | PG_V; 829 mba->mba_sr = -1; 830 mba->mba_bcr = -(blk*NBPG); 831 mba->mba_var = 0; 832 hpaddr->hpcs1 = HP_WCOM | HP_GO; 833 while ((hpaddr->hpds & HPDS_DRY) == 0) 834 ; 835 if (hpaddr->hpds&HPDS_ERR) 836 return (EIO); 837 start += blk*NBPG; 838 num -= blk; 839 } 840 return (0); 841 } 842 #endif 843