1 /* hp.c 4.48 82/05/24 */ 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 case SI9766: 282 printf("hp%d: 9776/9300\n", mi->mi_unit); 283 mi->mi_type = HPDT_RM05; 284 break; 285 286 case SI9762: 287 printf("hp%d: 9762\n", mi->mi_unit); 288 mi->mi_type = HPDT_RM03; 289 break; 290 #endif 291 } 292 break; 293 } 294 295 /* 296 * CAPRICORN KLUDGE...poke the holding register 297 * to find out the number of tracks. If it's 15 298 * we believe it's a Capricorn. 299 */ 300 case HPDT_RM02: 301 hpaddr->hpcs1 = HP_NOP; 302 hpaddr->hphr = HPHR_MAXTRAK; 303 if (hpaddr->hphr == 15) { 304 printf("hp%d: capricorn\n", mi->mi_unit); 305 mi->mi_type = HPDT_CAPRICORN; 306 } 307 hpaddr->hpcs1 = HP_DCLR|HP_GO; 308 break; 309 310 case HPDT_ML11A: 311 case HPDT_ML11B: { 312 register int trt, sz; 313 314 sz = hpaddr->hpmr & HPMR_SZ; 315 if ((hpaddr->hpmr & HPMR_ARRTYP) == 0) 316 sz >>= 2; 317 mlsize[mi->mi_unit] = sz; 318 if (mi->mi_dk >= 0) { 319 trt = (hpaddr->hpmr & HPMR_TRT) >> 8; 320 dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt)); 321 } 322 /* A CHEAT - ML11B D.T. SHOULD == ML11A */ 323 mi->mi_type = HPDT_ML11A; 324 break; 325 } 326 } 327 if (!ML11 && mi->mi_dk >= 0) { 328 register struct hpst *st = &hpst[mi->mi_type]; 329 330 dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256); 331 } 332 } 333 334 hpstrategy(bp) 335 register struct buf *bp; 336 { 337 register struct mba_device *mi; 338 register struct hpst *st; 339 register int unit; 340 long sz, bn; 341 int xunit = minor(bp->b_dev) & 07; 342 int s; 343 344 sz = bp->b_bcount; 345 sz = (sz+511) >> 9; 346 unit = dkunit(bp); 347 if (unit >= NHP) 348 goto bad; 349 mi = hpinfo[unit]; 350 if (mi == 0 || mi->mi_alive == 0) 351 goto bad; 352 st = &hpst[mi->mi_type]; 353 if (ML11) { 354 if (bp->b_blkno < 0 || 355 dkblock(bp)+sz > mlsize[mi->mi_unit]) 356 goto bad; 357 bp->b_cylin = 0; 358 } else { 359 if (bp->b_blkno < 0 || 360 (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 361 goto bad; 362 bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 363 } 364 s = spl5(); 365 disksort(&mi->mi_tab, bp); 366 if (mi->mi_tab.b_active == 0) 367 mbustart(mi); 368 splx(s); 369 return; 370 371 bad: 372 bp->b_flags |= B_ERROR; 373 iodone(bp); 374 return; 375 } 376 377 hpustart(mi) 378 register struct mba_device *mi; 379 { 380 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 381 register struct buf *bp = mi->mi_tab.b_actf; 382 register struct hpst *st = &hpst[mi->mi_type]; 383 daddr_t bn; 384 int sn, dist; 385 386 hpaddr->hpcs1 = 0; 387 if ((hpaddr->hpcs1&HP_DVA) == 0) 388 return (MBU_BUSY); 389 if ((hpaddr->hpds & HPDS_VV) == 0 || hpinit[mi->mi_unit] == 0) { 390 #ifndef NOBADSECT 391 struct buf *bbp = &bhpbuf[mi->mi_unit]; 392 #endif 393 394 hpinit[mi->mi_unit] = 1; 395 hpaddr->hpcs1 = HP_DCLR|HP_GO; 396 if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive)) 397 printf("DCLR attn\n"); 398 hpaddr->hpcs1 = HP_PRESET|HP_GO; 399 if (!ML11) 400 hpaddr->hpof = HPOF_FMT22; 401 mbclrattn(mi); 402 #ifndef NOBADSECT 403 if (!ML11) { 404 bbp->b_flags = B_READ|B_BUSY; 405 bbp->b_dev = bp->b_dev; 406 bbp->b_bcount = 512; 407 bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit]; 408 bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 409 bbp->b_cylin = st->ncyl - 1; 410 mi->mi_tab.b_actf = bbp; 411 bbp->av_forw = bp; 412 bp = bbp; 413 } 414 #endif 415 } 416 if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) 417 return (MBU_DODATA); 418 if (ML11) 419 return (MBU_DODATA); 420 if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY) 421 return (MBU_DODATA); 422 bn = dkblock(bp); 423 sn = bn%st->nspc; 424 sn = (sn+st->nsect-hpSDIST)%st->nsect; 425 if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) { 426 if (hpseek) 427 return (MBU_DODATA); 428 dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1; 429 if (dist < 0) 430 dist += st->nsect; 431 if (dist > st->nsect - hpRDIST) 432 return (MBU_DODATA); 433 } else 434 hpaddr->hpdc = bp->b_cylin; 435 if (hpseek) 436 hpaddr->hpcs1 = HP_SEEK|HP_GO; 437 else { 438 hpaddr->hpda = sn; 439 hpaddr->hpcs1 = HP_SEARCH|HP_GO; 440 } 441 return (MBU_STARTED); 442 } 443 444 hpstart(mi) 445 register struct mba_device *mi; 446 { 447 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 448 register struct buf *bp = mi->mi_tab.b_actf; 449 register struct hpst *st = &hpst[mi->mi_type]; 450 daddr_t bn; 451 int sn, tn; 452 453 bn = dkblock(bp); 454 if (ML11) 455 hpaddr->hpda = bn; 456 else { 457 sn = bn%st->nspc; 458 tn = sn/st->nsect; 459 sn %= st->nsect; 460 hpaddr->hpdc = bp->b_cylin; 461 hpaddr->hpda = (tn << 8) + sn; 462 } 463 if (hphdr[mi->mi_unit]) { 464 if (bp->b_flags & B_READ) 465 return (HP_RHDR|HP_GO); 466 else 467 return (HP_WHDR|HP_GO); 468 } 469 return (0); 470 } 471 472 hpdtint(mi, mbsr) 473 register struct mba_device *mi; 474 int mbsr; 475 { 476 register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 477 register struct buf *bp = mi->mi_tab.b_actf; 478 register int er1, er2; 479 int retry = 0; 480 481 #ifndef NOBADSECT 482 if (bp->b_flags&B_BAD) { 483 if (hpecc(mi, CONT)) 484 return(MBD_RESTARTED); 485 } 486 #endif 487 if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) { 488 #ifdef HPDEBUG 489 if (hpdebug) { 490 int dc = hpaddr->hpdc, da = hpaddr->hpda; 491 492 printf("hperr: bp %x cyl %d blk %d as %o ", 493 bp, bp->b_cylin, bp->b_blkno, 494 hpaddr->hpas&0xff); 495 printf("dc %x da %x\n",dc&0xffff, da&0xffff); 496 printf("errcnt %d ", mi->mi_tab.b_errcnt); 497 printf("mbsr=%b ", mbsr, mbsr_bits); 498 printf("er1=%b er2=%b\n", 499 hpaddr->hper1, HPER1_BITS, 500 hpaddr->hper2, HPER2_BITS); 501 DELAY(1000000); 502 } 503 #endif 504 er1 = hpaddr->hper1; 505 er2 = hpaddr->hper2; 506 if (er1 & HPER1_HCRC) { 507 er1 &= ~(HPER1_HCE|HPER1_FER); 508 er2 &= ~HPER2_BSE; 509 } 510 if (er1&HPER1_WLE) { 511 printf("hp%d: write locked\n", dkunit(bp)); 512 bp->b_flags |= B_ERROR; 513 } else if ((er1&0xffff) == HPER1_FER && RP06 && 514 hphdr[mi->mi_unit] == 0) { 515 #ifndef NOBADSECT 516 if (hpecc(mi, BSE)) 517 return(MBD_RESTARTED); 518 else 519 #endif 520 goto hard; 521 } else if (++mi->mi_tab.b_errcnt > 27 || 522 mbsr & MBSR_HARD || 523 er1 & HPER1_HARD || 524 hphdr[mi->mi_unit] || 525 (!ML11 && (er2 & HPER2_HARD))) { 526 hard: 527 harderr(bp, "hp"); 528 if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC))) 529 printf("mbsr=%b ", mbsr, mbsr_bits); 530 printf("er1=%b er2=%b", 531 hpaddr->hper1, HPER1_BITS, 532 hpaddr->hper2, HPER2_BITS); 533 if (hpaddr->hpmr) 534 printf(" mr=%o", hpaddr->hpmr&0xffff); 535 if (hpaddr->hpmr2) 536 printf(" mr2=%o", hpaddr->hpmr2&0xffff); 537 printf("\n"); 538 bp->b_flags |= B_ERROR; 539 hprecal[mi->mi_unit] = 0; 540 } else if ((er2 & HPER2_BSE) && !ML11) { 541 #ifndef NOBADSECT 542 if (hpecc(mi, BSE)) 543 return(MBD_RESTARTED); 544 else 545 #endif 546 goto hard; 547 } else if (RM80 && er2&HPER2_SSE) { 548 (void) hpecc(mi, SSE); 549 return (MBD_RESTARTED); 550 } else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) { 551 if (hpecc(mi, ECC)) 552 return (MBD_RESTARTED); 553 /* else done */ 554 } else 555 retry = 1; 556 hpaddr->hpcs1 = HP_DCLR|HP_GO; 557 if (ML11) { 558 if (mi->mi_tab.b_errcnt >= 16) 559 goto hard; 560 } else if ((mi->mi_tab.b_errcnt&07) == 4) { 561 hpaddr->hpcs1 = HP_RECAL|HP_GO; 562 hprecal[mi->mi_unit] = 1; 563 return(MBD_RESTARTED); 564 } 565 if (retry) 566 return (MBD_RETRY); 567 } 568 #ifdef HPDEBUG 569 else 570 if (hpdebug && hprecal[mi->mi_unit]) { 571 printf("recal %d ", hprecal[mi->mi_unit]); 572 printf("errcnt %d\n", mi->mi_tab.b_errcnt); 573 printf("mbsr=%b ", mbsr, mbsr_bits); 574 printf("er1=%b er2=%b\n", 575 hpaddr->hper1, HPER1_BITS, 576 hpaddr->hper2, HPER2_BITS); 577 } 578 #endif 579 switch (hprecal[mi->mi_unit]) { 580 581 case 1: 582 hpaddr->hpdc = bp->b_cylin; 583 hpaddr->hpcs1 = HP_SEEK|HP_GO; 584 hprecal[mi->mi_unit]++; 585 return (MBD_RESTARTED); 586 case 2: 587 if (mi->mi_tab.b_errcnt < 16 || 588 (bp->b_flags & B_READ) == 0) 589 goto donerecal; 590 hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22; 591 hpaddr->hpcs1 = HP_OFFSET|HP_GO; 592 hprecal[mi->mi_unit]++; 593 return (MBD_RESTARTED); 594 donerecal: 595 case 3: 596 hprecal[mi->mi_unit] = 0; 597 return (MBD_RETRY); 598 } 599 hphdr[mi->mi_unit] = 0; 600 bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff; 601 if (mi->mi_tab.b_errcnt >= 16) { 602 /* 603 * This is fast and occurs rarely; we don't 604 * bother with interrupts. 605 */ 606 hpaddr->hpcs1 = HP_RTC|HP_GO; 607 while (hpaddr->hpds & HPDS_PIP) 608 ; 609 mbclrattn(mi); 610 } 611 if (!ML11) { 612 hpaddr->hpof = HPOF_FMT22; 613 hpaddr->hpcs1 = HP_RELEASE|HP_GO; 614 } 615 return (MBD_DONE); 616 } 617 618 hpread(dev) 619 dev_t dev; 620 { 621 register int unit = minor(dev) >> 3; 622 623 if (unit >= NHP) 624 u.u_error = ENXIO; 625 else 626 physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys); 627 } 628 629 hpwrite(dev) 630 dev_t dev; 631 { 632 register int unit = minor(dev) >> 3; 633 634 if (unit >= NHP) 635 u.u_error = ENXIO; 636 else 637 physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys); 638 } 639 640 /*ARGSUSED*/ 641 hpioctl(dev, cmd, addr, flag) 642 dev_t dev; 643 int cmd; 644 caddr_t addr; 645 int flag; 646 { 647 648 switch (cmd) { 649 case DKIOCHDR: /* do header read/write */ 650 hphdr[minor(dev)>>3] = 1; 651 return; 652 653 default: 654 u.u_error = ENXIO; 655 } 656 } 657 658 hpecc(mi, flag) 659 register struct mba_device *mi; 660 int flag; 661 { 662 register struct mba_regs *mbp = mi->mi_mba; 663 register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; 664 register struct buf *bp = mi->mi_tab.b_actf; 665 register struct hpst *st = &hpst[mi->mi_type]; 666 int npf, o; 667 int bn, cn, tn, sn; 668 int bcr; 669 670 bcr = mbp->mba_bcr & 0xffff; 671 if (bcr) 672 bcr |= 0xffff0000; /* sxt */ 673 #ifndef NOBADSECT 674 if (flag == CONT) 675 npf = bp->b_error; 676 else 677 #endif 678 npf = btop(bcr + bp->b_bcount); 679 o = (int)bp->b_un.b_addr & PGOFSET; 680 bn = dkblock(bp); 681 cn = bp->b_cylin; 682 sn = bn%(st->nspc) + npf; 683 tn = sn/st->nsect; 684 sn %= st->nsect; 685 cn += tn/st->ntrak; 686 tn %= st->ntrak; 687 switch (flag) { 688 case ECC: 689 { 690 register int i; 691 caddr_t addr; 692 struct pte mpte; 693 int bit, byte, mask; 694 695 npf--; /* because block in error is previous block */ 696 printf("hp%d%c: soft ecc sn%d\n", dkunit(bp), 697 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 698 mask = rp->hpec2&0xffff; 699 i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */ 700 bit = i&07; 701 i = (i&~07)>>3; 702 byte = i + o; 703 while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 704 mpte = mbp->mba_map[npf+btop(byte)]; 705 addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); 706 putmemc(addr, getmemc(addr)^(mask<<bit)); 707 byte++; 708 i++; 709 bit -= 8; 710 } 711 if (bcr == 0) 712 return (0); 713 npf++; 714 break; 715 } 716 717 case SSE: 718 rp->hpof |= HPOF_SSEI; 719 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 720 break; 721 722 #ifndef NOBADSECT 723 case BSE: 724 #ifdef HPBDEBUG 725 if (hpbdebug) 726 printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 727 #endif 728 if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0) 729 return(0); 730 bp->b_flags |= B_BAD; 731 bp->b_error = npf + 1; 732 bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 733 cn = bn/st->nspc; 734 sn = bn%st->nspc; 735 tn = sn/st->nsect; 736 sn %= st->nsect; 737 mbp->mba_bcr = -512; 738 #ifdef HPBDEBUG 739 if (hpbdebug) 740 printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 741 #endif 742 break; 743 744 case CONT: 745 #ifdef HPBDEBUG 746 if (hpbdebug) 747 printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 748 #endif 749 npf = bp->b_error; 750 bp->b_flags &= ~B_BAD; 751 mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 752 if ((mbp->mba_bcr & 0xffff) == 0) 753 return(0); 754 break; 755 #endif 756 } 757 rp->hpcs1 = HP_DCLR|HP_GO; 758 if (rp->hpof&HPOF_SSEI) 759 sn++; 760 rp->hpdc = cn; 761 rp->hpda = (tn<<8) + sn; 762 mbp->mba_sr = -1; 763 mbp->mba_var = (int)ptob(npf) + o; 764 rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO; 765 mi->mi_tab.b_errcnt = 0; /* error has been corrected */ 766 return (1); 767 } 768 769 #define DBSIZE 20 770 771 hpdump(dev) 772 dev_t dev; 773 { 774 register struct mba_device *mi; 775 register struct mba_regs *mba; 776 struct hpdevice *hpaddr; 777 char *start; 778 int num, unit; 779 register struct hpst *st; 780 781 num = maxfree; 782 start = 0; 783 unit = minor(dev) >> 3; 784 if (unit >= NHP) 785 return (ENXIO); 786 #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 787 mi = phys(hpinfo[unit],struct mba_device *); 788 if (mi == 0 || mi->mi_alive == 0) 789 return (ENXIO); 790 mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 791 mba->mba_cr = MBCR_INIT; 792 hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; 793 if ((hpaddr->hpds & HPDS_VV) == 0) { 794 hpaddr->hpcs1 = HP_DCLR|HP_GO; 795 hpaddr->hpcs1 = HP_PRESET|HP_GO; 796 hpaddr->hpof = HPOF_FMT22; 797 } 798 st = &hpst[mi->mi_type]; 799 if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks) 800 return (EINVAL); 801 while (num > 0) { 802 register struct pte *hpte = mba->mba_map; 803 register int i; 804 int blk, cn, sn, tn; 805 daddr_t bn; 806 807 blk = num > DBSIZE ? DBSIZE : num; 808 bn = dumplo + btop(start); 809 cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; 810 sn = bn%st->nspc; 811 tn = sn/st->nsect; 812 sn = sn%st->nsect; 813 hpaddr->hpdc = cn; 814 hpaddr->hpda = (tn << 8) + sn; 815 for (i = 0; i < blk; i++) 816 *(int *)hpte++ = (btop(start)+i) | PG_V; 817 mba->mba_sr = -1; 818 mba->mba_bcr = -(blk*NBPG); 819 mba->mba_var = 0; 820 hpaddr->hpcs1 = HP_WCOM | HP_GO; 821 while ((hpaddr->hpds & HPDS_DRY) == 0) 822 ; 823 if (hpaddr->hpds&HPDS_ERR) 824 return (EIO); 825 start += blk*NBPG; 826 num -= blk; 827 } 828 return (0); 829 } 830 #endif 831