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