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