1*10622Shelge /* hp.c 4.62 83/01/27 */ 23706Sroot 33706Sroot #ifdef HPDEBUG 43289Swnj int hpdebug; 53706Sroot #endif 63706Sroot #ifdef HPBDEBUG 73706Sroot int hpbdebug; 83706Sroot #endif 921Sbill 101939Swnj #include "hp.h" 111565Sbill #if NHP > 0 1221Sbill /* 135726Sroot * HP disk driver for RP0x+RMxx+ML11 142827Swnj * 152827Swnj * TODO: 163706Sroot * check RM80 skip sector handling when ECC's occur later 173093Swnj * check offset recovery handling 183706Sroot * see if DCLR and/or RELEASE set attention status 193706Sroot * print bits of mr && mr2 symbolically 2021Sbill */ 219786Ssam #include "../machine/pte.h" 2221Sbill 2321Sbill #include "../h/param.h" 2421Sbill #include "../h/systm.h" 25305Sbill #include "../h/dk.h" 2621Sbill #include "../h/buf.h" 2721Sbill #include "../h/conf.h" 2821Sbill #include "../h/dir.h" 2921Sbill #include "../h/user.h" 3021Sbill #include "../h/map.h" 318468Sroot #include "../vax/mtpr.h" 32420Sbill #include "../h/vm.h" 332362Swnj #include "../h/cmap.h" 343706Sroot #include "../h/dkbad.h" 357635Ssam #include "../h/ioctl.h" 367738Sroot #include "../h/uio.h" 3721Sbill 388988Sroot #include "../vax/dkio.h" 398468Sroot #include "../vaxmba/mbareg.h" 408468Sroot #include "../vaxmba/mbavar.h" 418468Sroot #include "../vaxmba/hpreg.h" 4221Sbill 432383Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 442383Swnj struct size { 4521Sbill daddr_t nblocks; 4621Sbill int cyloff; 473706Sroot } hp6_sizes[8] = { 48886Sbill 15884, 0, /* A=cyl 0 thru 37 */ 49886Sbill 33440, 38, /* B=cyl 38 thru 117 */ 50886Sbill 340670, 0, /* C=cyl 0 thru 814 */ 5121Sbill 0, 0, 5221Sbill 0, 0, 5321Sbill 0, 0, 543726Sroot #ifndef NOBADSECT 553729Sroot 291280, 118, /* G=cyl 118 thru 814 */ 563706Sroot #else 573706Sroot 291346, 118, 583706Sroot #endif 5921Sbill 0, 0, 603706Sroot }, rm3_sizes[8] = { 61886Sbill 15884, 0, /* A=cyl 0 thru 99 */ 62886Sbill 33440, 100, /* B=cyl 100 thru 309 */ 63886Sbill 131680, 0, /* C=cyl 0 thru 822 */ 6421Sbill 0, 0, 6521Sbill 0, 0, 663442Sroot 0, 0, 673726Sroot #ifndef NOBADSECT 683729Sroot 81984, 310, /* G=cyl 310 thru 822 */ 693706Sroot #else 703706Sroot 82080, 310, 713706Sroot #endif 7221Sbill 0, 0, 73886Sbill }, rm5_sizes[8] = { 74886Sbill 15884, 0, /* A=cyl 0 thru 26 */ 75886Sbill 33440, 27, /* B=cyl 27 thru 81 */ 763271Swnj 500384, 0, /* C=cyl 0 thru 822 */ 77886Sbill 15884, 562, /* D=cyl 562 thru 588 */ 78886Sbill 55936, 589, /* E=cyl 589 thru 680 */ 793726Sroot #ifndef NOBADSECT 803729Sroot 86240, 681, /* F=cyl 681 thru 822 */ 813729Sroot 158592, 562, /* G=cyl 562 thru 822 */ 823706Sroot #else 835695Sroot 86336, 681, 843706Sroot 158688, 562, 853706Sroot #endif 86886Sbill 291346, 82, /* H=cyl 82 thru 561 */ 872383Swnj }, rm80_sizes[8] = { 882383Swnj 15884, 0, /* A=cyl 0 thru 36 */ 892383Swnj 33440, 37, /* B=cyl 37 thru 114 */ 902383Swnj 242606, 0, /* C=cyl 0 thru 558 */ 912383Swnj 0, 0, 922383Swnj 0, 0, 932383Swnj 0, 0, 942383Swnj 82080, 115, /* G=cyl 115 thru 304 */ 953729Sroot 110143, 305, /* H=cyl 305 thru 558 */ 963706Sroot }, hp7_sizes[8] = { 976927Ssam 15884, 0, /* A=cyl 0 thru 9 */ 983706Sroot 64000, 10, /* B=cyl 10 thru 49 */ 993706Sroot 1008000,0, /* C=cyl 0 thru 629 */ 1003706Sroot 15884, 330, /* D=cyl 330 thru 339 */ 1013706Sroot 256000, 340, /* E=cyl 340 thru 499 */ 1023729Sroot 207850, 500, /* F=cyl 500 thru 629 */ 1033729Sroot 479850, 330, /* G=cyl 330 thru 629 */ 1043706Sroot 448000, 50, /* H=cyl 50 thru 329 */ 1056927Ssam }, si9775_sizes[8] = { 1066927Ssam 16640, 0, /* A=cyl 0 thru 12 */ 1076927Ssam 34560, 13, /* B=cyl 13 thru 39 */ 1086927Ssam 1079040, 0, /* C=cyl 0 thru 842 - whole disk */ 1096927Ssam 0, 0, /* D unused */ 1106927Ssam 0, 0, /* E unused */ 1116927Ssam 0, 0, /* F unused */ 1126927Ssam 513280, 40, /* G=cyl 40 thru 440 */ 1136927Ssam 513280, 441, /* H=cyl 441 thru 841 */ 1146927Ssam }, si9730_sizes[8] = { 1156927Ssam 15884, 0, /* A=cyl 0 thru 49 */ 1166927Ssam 33440, 50, /* B=cyl 50 thru 154 */ 1176927Ssam 263360, 0, /* C=cyl 0 thru 822 */ 1186927Ssam 0, 0, 1196927Ssam 0, 0, 1206927Ssam 0, 0, 1216927Ssam 0, 0, 1226927Ssam #ifndef NOBADSECT 1236927Ssam 213664, 155, /* H=cyl 155 thru 822 */ 1246927Ssam #else 1256927Ssam 213760, 155, 1266927Ssam #endif 1276927Ssam }, hpam_sizes[8] = { 1286927Ssam 15884, 0, /* A=cyl 0 thru 31 */ 1296927Ssam 33440, 32, /* B=cyl 32 thru 97 */ 1306927Ssam 524288, 0, /* C=cyl 0 thru 1023 */ 1316927Ssam 27786, 668, 1326927Ssam 27786, 723, 1336927Ssam 125440, 778, 1346927Ssam 181760, 668, /* G=cyl 668 thru 1022 */ 1356927Ssam 291346, 98, /* H=cyl 98 thru 667 */ 1369175Ssam }, hpfj_sizes[8] = { 1379175Ssam 15884, 0, /* A=cyl 0 thru 18 */ 1389175Ssam 33440, 19, /* B=cyl 19 thru 58 */ 13910055Ssam 724120, 0, /* C=cyl 0 thru 841 */ 1409175Ssam 0, 0, 1419175Ssam 0, 0, 1429175Ssam 0, 0, 1439175Ssam 381711, 398, /* G=cyl 398 thru 841 */ 1449175Ssam 291346, 59, /* H=cyl 59 thru 397 */ 14521Sbill }; 1462383Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 14721Sbill 1482383Swnj #define _hpSDIST 2 1492383Swnj #define _hpRDIST 3 1502383Swnj 1512383Swnj int hpSDIST = _hpSDIST; 1522383Swnj int hpRDIST = _hpRDIST; 1532383Swnj 1546927Ssam /* 1556927Ssam * Table for converting Massbus drive types into 1566927Ssam * indices into the partition tables. Slots are 1576927Ssam * left for those drives devined from other means 1586927Ssam * (e.g. SI, AMPEX, etc.). 1596927Ssam */ 1606927Ssam short hptypes[] = { 1616927Ssam #define HPDT_RM03 0 1626927Ssam MBDT_RM03, 1636927Ssam #define HPDT_RM05 1 1646927Ssam MBDT_RM05, 1656927Ssam #define HPDT_RP06 2 1666927Ssam MBDT_RP06, 1676927Ssam #define HPDT_RM80 3 1686927Ssam MBDT_RM80, 1696927Ssam #define HPDT_RP05 4 1706927Ssam MBDT_RP05, 1716927Ssam #define HPDT_RP07 5 1726927Ssam MBDT_RP07, 1736927Ssam #define HPDT_ML11A 6 1746927Ssam MBDT_ML11A, 1756927Ssam #define HPDT_ML11B 7 1766927Ssam MBDT_ML11B, 1776927Ssam #define HPDT_9775 8 1786927Ssam -1, 1796927Ssam #define HPDT_9730 9 1806927Ssam -1, 1816927Ssam #define HPDT_CAPRICORN 10 1826927Ssam -1, 1839175Ssam #define HPDT_EAGLE 11 1849175Ssam -1, 1859175Ssam #define HPDT_RM02 12 1869175Ssam MBDT_RM02, /* beware, actually capricorn or eagle */ 1876927Ssam 0 1886927Ssam }; 1892978Swnj struct mba_device *hpinfo[NHP]; 1902978Swnj int hpattach(),hpustart(),hpstart(),hpdtint(); 1912383Swnj struct mba_driver hpdriver = 1922978Swnj { hpattach, 0, hpustart, hpstart, hpdtint, 0, 1932978Swnj hptypes, "hp", 0, hpinfo }; 1942383Swnj 1952383Swnj struct hpst { 1962383Swnj short nsect; 1972383Swnj short ntrak; 1982383Swnj short nspc; 1992383Swnj short ncyl; 2002383Swnj struct size *sizes; 2012383Swnj } hpst[] = { 2023706Sroot 32, 5, 32*5, 823, rm3_sizes, /* RM03 */ 2032383Swnj 32, 19, 32*19, 823, rm5_sizes, /* RM05 */ 2043706Sroot 22, 19, 22*19, 815, hp6_sizes, /* RP06 */ 2053706Sroot 31, 14, 31*14, 559, rm80_sizes, /* RM80 */ 2063706Sroot 22, 19, 22*19, 411, hp6_sizes, /* RP05 */ 2073706Sroot 50, 32, 50*32, 630, hp7_sizes, /* RP07 */ 2085726Sroot 1, 1, 1, 1, 0, /* ML11A */ 2095726Sroot 1, 1, 1, 1, 0, /* ML11B */ 2106927Ssam 32, 40, 32*40, 843, si9775_sizes, /* 9775 */ 2116927Ssam 32, 10, 32*10, 823, si9730_sizes, /* 9730 */ 2126927Ssam 32, 16, 32*16, 1024, hpam_sizes, /* AMPEX capricorn */ 21310055Ssam 43, 20, 43*20, 842, hpfj_sizes, /* Fujitsu EAGLE */ 2142383Swnj }; 2152383Swnj 2162624Swnj u_char hp_offset[16] = { 2173093Swnj HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 2183093Swnj HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 2193093Swnj HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 2203093Swnj 0, 0, 0, 0, 22121Sbill }; 22221Sbill 2232624Swnj struct buf rhpbuf[NHP]; 2243726Sroot #ifndef NOBADSECT 2253706Sroot struct buf bhpbuf[NHP]; 2263706Sroot struct dkbad hpbad[NHP]; 2273706Sroot #endif 2285726Sroot /* SHOULD CONSOLIDATE ALL THIS STUFF INTO A STRUCTURE */ 2293706Sroot char hpinit[NHP]; 2302892Swnj char hprecal[NHP]; 2315726Sroot char hphdr[NHP]; 2325726Sroot daddr_t mlsize[NHP]; 23321Sbill 23421Sbill #define b_cylin b_resid 23521Sbill 2365726Sroot /* #define ML11 0 to remove ML11 support */ 2375726Sroot #define ML11 (hptypes[mi->mi_type] == MBDT_ML11A) 2385726Sroot #define RP06 (hptypes[mi->mi_type] <= MBDT_RP06) 2395726Sroot #define RM80 (hptypes[mi->mi_type] == MBDT_RM80) 2405726Sroot 24121Sbill #ifdef INTRLVE 24221Sbill daddr_t dkblock(); 24321Sbill #endif 24421Sbill 2452604Swnj int hpseek; 2462604Swnj 2472978Swnj /*ARGSUSED*/ 2482978Swnj hpattach(mi, slave) 2492978Swnj struct mba_device *mi; 2502604Swnj { 2516927Ssam register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 25210055Ssam int ntracks; 2536927Ssam 2546927Ssam switch (mi->mi_type) { 2556927Ssam 2566927Ssam /* 2576927Ssam * Model-byte processing for SI 9400 controllers. 2586927Ssam * NB: Only deals with RM03 and RM05 emulations. 2596927Ssam */ 2606927Ssam case HPDT_RM03: 2616927Ssam case HPDT_RM05: { 2626927Ssam register int hpsn; 2636927Ssam 2646927Ssam hpsn = hpaddr->hpsn; 2656927Ssam if ((hpsn & SIMB_LU) != mi->mi_drive) 2666927Ssam break; 2676927Ssam switch ((hpsn & SIMB_MB) & ~(SIMB_S6|SIRM03|SIRM05)) { 2686927Ssam 2696927Ssam case SI9775D: 2706927Ssam printf("hp%d: si 9775 (direct)\n", mi->mi_unit); 2716927Ssam mi->mi_type = HPDT_9775; 2726927Ssam break; 2736927Ssam 2746927Ssam case SI9730D: 2756927Ssam printf("hp%d: si 9730 (direct)\n", mi->mi_unit); 2766927Ssam mi->mi_type = HPDT_9730; 2776927Ssam break; 2786927Ssam 2797035Swnj /* 2807035Swnj * AMPEX 9300, SI Combination needs a have the drive cleared 2817035Swnj * before we start. We do not know why, but tests show 2827035Swnj * that the recalibrate fixes the problem. 2837035Swnj */ 2846927Ssam case SI9766: 2856927Ssam printf("hp%d: 9776/9300\n", mi->mi_unit); 2866927Ssam mi->mi_type = HPDT_RM05; 2877035Swnj hpaddr->hpcs1 = HP_RECAL|HP_GO; 2887035Swnj DELAY(100000); 2896927Ssam break; 2906927Ssam 2916927Ssam case SI9762: 2926927Ssam printf("hp%d: 9762\n", mi->mi_unit); 2936927Ssam mi->mi_type = HPDT_RM03; 2946927Ssam break; 2956927Ssam } 2966927Ssam break; 2976927Ssam } 2986927Ssam 2996927Ssam /* 3006927Ssam * CAPRICORN KLUDGE...poke the holding register 3019175Ssam * we believe it's a Capricorn. Otherwise assume 3029175Ssam * its an Eagle. 3036927Ssam */ 3046927Ssam case HPDT_RM02: 3056927Ssam hpaddr->hpcs1 = HP_NOP; 3066927Ssam hpaddr->hphr = HPHR_MAXTRAK; 30710055Ssam ntracks = (hpaddr->hphr & 0xffff) + 1; 30810055Ssam if (ntracks == 16) { 3096927Ssam printf("hp%d: capricorn\n", mi->mi_unit); 3106927Ssam mi->mi_type = HPDT_CAPRICORN; 31110055Ssam } else if (ntracks == 20) { 3129175Ssam printf("hp%d: eagle\n", mi->mi_unit); 3139175Ssam mi->mi_type = HPDT_EAGLE; 31410055Ssam } else 31510055Ssam printf("hp%d: ntracks %d: unknown device\n", ntracks); 3166927Ssam hpaddr->hpcs1 = HP_DCLR|HP_GO; 3176927Ssam break; 3186927Ssam 3196927Ssam case HPDT_ML11A: 3206927Ssam case HPDT_ML11B: { 3215726Sroot register int trt, sz; 3222604Swnj 3235726Sroot sz = hpaddr->hpmr & HPMR_SZ; 3245726Sroot if ((hpaddr->hpmr & HPMR_ARRTYP) == 0) 3255726Sroot sz >>= 2; 3265726Sroot mlsize[mi->mi_unit] = sz; 3275726Sroot if (mi->mi_dk >= 0) { 3285726Sroot trt = (hpaddr->hpmr & HPMR_TRT) >> 8; 3295726Sroot dk_mspw[mi->mi_dk] = 1.0 / (1<<(20-trt)); 3305726Sroot } 3316927Ssam /* A CHEAT - ML11B D.T. SHOULD == ML11A */ 3326927Ssam mi->mi_type = HPDT_ML11A; 3336927Ssam break; 3346927Ssam } 3356927Ssam } 3366927Ssam if (!ML11 && mi->mi_dk >= 0) { 3375726Sroot register struct hpst *st = &hpst[mi->mi_type]; 3385726Sroot 3392757Swnj dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256); 3405726Sroot } 3412604Swnj } 3422604Swnj 3438579Sroot hpopen(dev) 3448579Sroot dev_t dev; 3458579Sroot { 3468579Sroot register int unit = minor(dev) >> 3; 3478579Sroot register struct mba_device *mi; 3488579Sroot 3498579Sroot if (unit >= NHP || (mi = hpinfo[unit]) == 0 || mi->mi_alive == 0) 3508579Sroot return (ENXIO); 3518579Sroot return (0); 3528579Sroot } 3538579Sroot 35421Sbill hpstrategy(bp) 3552383Swnj register struct buf *bp; 35621Sbill { 3572978Swnj register struct mba_device *mi; 3582383Swnj register struct hpst *st; 3592383Swnj register int unit; 36021Sbill long sz, bn; 3612383Swnj int xunit = minor(bp->b_dev) & 07; 3625432Sroot int s; 36321Sbill 36421Sbill sz = bp->b_bcount; 36521Sbill sz = (sz+511) >> 9; 36621Sbill unit = dkunit(bp); 3672383Swnj if (unit >= NHP) 3682383Swnj goto bad; 3692383Swnj mi = hpinfo[unit]; 3702395Swnj if (mi == 0 || mi->mi_alive == 0) 3712383Swnj goto bad; 3722383Swnj st = &hpst[mi->mi_type]; 3735726Sroot if (ML11) { 3745726Sroot if (bp->b_blkno < 0 || 3755726Sroot dkblock(bp)+sz > mlsize[mi->mi_unit]) 3765726Sroot goto bad; 3775726Sroot bp->b_cylin = 0; 3785726Sroot } else { 3795726Sroot if (bp->b_blkno < 0 || 3805726Sroot (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 3815726Sroot goto bad; 3825726Sroot bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 3835726Sroot } 3845432Sroot s = spl5(); 3852383Swnj disksort(&mi->mi_tab, bp); 3862383Swnj if (mi->mi_tab.b_active == 0) 3872383Swnj mbustart(mi); 3885432Sroot splx(s); 3892383Swnj return; 3902383Swnj 3912383Swnj bad: 3922383Swnj bp->b_flags |= B_ERROR; 3932383Swnj iodone(bp); 3942383Swnj return; 39521Sbill } 39621Sbill 3972383Swnj hpustart(mi) 3982978Swnj register struct mba_device *mi; 39921Sbill { 4002624Swnj register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 4012383Swnj register struct buf *bp = mi->mi_tab.b_actf; 4023706Sroot register struct hpst *st = &hpst[mi->mi_type]; 40321Sbill daddr_t bn; 4043102Swnj int sn, dist; 40521Sbill 4063706Sroot hpaddr->hpcs1 = 0; 4072624Swnj if ((hpaddr->hpcs1&HP_DVA) == 0) 4082383Swnj return (MBU_BUSY); 4093706Sroot if ((hpaddr->hpds & HPDS_VV) == 0 || hpinit[mi->mi_unit] == 0) { 4103726Sroot #ifndef NOBADSECT 4113706Sroot struct buf *bbp = &bhpbuf[mi->mi_unit]; 4123706Sroot #endif 4133706Sroot 4143706Sroot hpinit[mi->mi_unit] = 1; 4152624Swnj hpaddr->hpcs1 = HP_DCLR|HP_GO; 4163140Swnj if (mi->mi_mba->mba_drv[0].mbd_as & (1<<mi->mi_drive)) 4173140Swnj printf("DCLR attn\n"); 4182624Swnj hpaddr->hpcs1 = HP_PRESET|HP_GO; 4195726Sroot if (!ML11) 4205726Sroot hpaddr->hpof = HPOF_FMT22; 4213140Swnj mbclrattn(mi); 4223726Sroot #ifndef NOBADSECT 4235726Sroot if (!ML11) { 4245726Sroot bbp->b_flags = B_READ|B_BUSY; 4255726Sroot bbp->b_dev = bp->b_dev; 4265726Sroot bbp->b_bcount = 512; 4275726Sroot bbp->b_un.b_addr = (caddr_t)&hpbad[mi->mi_unit]; 4285726Sroot bbp->b_blkno = st->ncyl*st->nspc - st->nsect; 4295726Sroot bbp->b_cylin = st->ncyl - 1; 4305726Sroot mi->mi_tab.b_actf = bbp; 4315726Sroot bbp->av_forw = bp; 4325726Sroot bp = bbp; 4335726Sroot } 4343706Sroot #endif 43521Sbill } 4362604Swnj if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) 4372383Swnj return (MBU_DODATA); 4385726Sroot if (ML11) 4395726Sroot return (MBU_DODATA); 4403093Swnj if ((hpaddr->hpds & HPDS_DREADY) != HPDS_DREADY) 4412383Swnj return (MBU_DODATA); 4422395Swnj bn = dkblock(bp); 4432395Swnj sn = bn%st->nspc; 4442395Swnj sn = (sn+st->nsect-hpSDIST)%st->nsect; 4452383Swnj if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) { 4462604Swnj if (hpseek) 4472383Swnj return (MBU_DODATA); 4482383Swnj dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1; 4492383Swnj if (dist < 0) 4502383Swnj dist += st->nsect; 4512383Swnj if (dist > st->nsect - hpRDIST) 4522383Swnj return (MBU_DODATA); 4532614Swnj } else 4542614Swnj hpaddr->hpdc = bp->b_cylin; 4552604Swnj if (hpseek) 4562624Swnj hpaddr->hpcs1 = HP_SEEK|HP_GO; 457305Sbill else { 458305Sbill hpaddr->hpda = sn; 4592624Swnj hpaddr->hpcs1 = HP_SEARCH|HP_GO; 460305Sbill } 4612383Swnj return (MBU_STARTED); 46221Sbill } 46321Sbill 4642383Swnj hpstart(mi) 4652978Swnj register struct mba_device *mi; 46621Sbill { 4672624Swnj register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 4682383Swnj register struct buf *bp = mi->mi_tab.b_actf; 4692383Swnj register struct hpst *st = &hpst[mi->mi_type]; 47021Sbill daddr_t bn; 4712383Swnj int sn, tn; 47221Sbill 47321Sbill bn = dkblock(bp); 4745726Sroot if (ML11) 4755726Sroot hpaddr->hpda = bn; 4765726Sroot else { 4775726Sroot sn = bn%st->nspc; 4785726Sroot tn = sn/st->nsect; 4795726Sroot sn %= st->nsect; 4805726Sroot hpaddr->hpdc = bp->b_cylin; 4815726Sroot hpaddr->hpda = (tn << 8) + sn; 4825726Sroot } 4835726Sroot if (hphdr[mi->mi_unit]) { 4845726Sroot if (bp->b_flags & B_READ) 4855726Sroot return (HP_RHDR|HP_GO); 4865726Sroot else 4875726Sroot return (HP_WHDR|HP_GO); 4885726Sroot } 4895726Sroot return (0); 49021Sbill } 49121Sbill 4923102Swnj hpdtint(mi, mbsr) 4932978Swnj register struct mba_device *mi; 4943102Swnj int mbsr; 49521Sbill { 4962624Swnj register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 4972383Swnj register struct buf *bp = mi->mi_tab.b_actf; 498*10622Shelge register struct hpst *st = &hpst[mi->mi_type]; 4995893Swnj register int er1, er2; 5002826Swnj int retry = 0; 50121Sbill 5023726Sroot #ifndef NOBADSECT 5033706Sroot if (bp->b_flags&B_BAD) { 5043706Sroot if (hpecc(mi, CONT)) 5053706Sroot return(MBD_RESTARTED); 5063706Sroot } 5073706Sroot #endif 5083102Swnj if (hpaddr->hpds&HPDS_ERR || mbsr&MBSR_EBITS) { 5093706Sroot #ifdef HPDEBUG 5103289Swnj if (hpdebug) { 5113706Sroot int dc = hpaddr->hpdc, da = hpaddr->hpda; 5123706Sroot 5133706Sroot printf("hperr: bp %x cyl %d blk %d as %o ", 5143706Sroot bp, bp->b_cylin, bp->b_blkno, 5153706Sroot hpaddr->hpas&0xff); 5163706Sroot printf("dc %x da %x\n",dc&0xffff, da&0xffff); 5173289Swnj printf("errcnt %d ", mi->mi_tab.b_errcnt); 5183289Swnj printf("mbsr=%b ", mbsr, mbsr_bits); 5193289Swnj printf("er1=%b er2=%b\n", 5203289Swnj hpaddr->hper1, HPER1_BITS, 5213289Swnj hpaddr->hper2, HPER2_BITS); 5223289Swnj DELAY(1000000); 5233289Swnj } 5243706Sroot #endif 5255858Swnj er1 = hpaddr->hper1; 5265893Swnj er2 = hpaddr->hper2; 5275893Swnj if (er1 & HPER1_HCRC) { 5285858Swnj er1 &= ~(HPER1_HCE|HPER1_FER); 5295893Swnj er2 &= ~HPER2_BSE; 5305893Swnj } 5315858Swnj if (er1&HPER1_WLE) { 5322925Swnj printf("hp%d: write locked\n", dkunit(bp)); 5332826Swnj bp->b_flags |= B_ERROR; 5345858Swnj } else if ((er1&0xffff) == HPER1_FER && RP06 && 5355726Sroot hphdr[mi->mi_unit] == 0) { 5365726Sroot #ifndef NOBADSECT 5375726Sroot if (hpecc(mi, BSE)) 5385726Sroot return(MBD_RESTARTED); 5395726Sroot else 5405726Sroot #endif 5415726Sroot goto hard; 5422826Swnj } else if (++mi->mi_tab.b_errcnt > 27 || 5433102Swnj mbsr & MBSR_HARD || 5445858Swnj er1 & HPER1_HARD || 5455726Sroot hphdr[mi->mi_unit] || 5465893Swnj (!ML11 && (er2 & HPER2_HARD))) { 5473706Sroot hard: 548*10622Shelge if (ML11) 549*10622Shelge bp->b_blkno = hpaddr->hpda&0xffff; 550*10622Shelge else 551*10622Shelge bp->b_blkno = (hpaddr->hpdc*st->nspc)&0xffff + 552*10622Shelge ((hpaddr->hpda>>8)&0xffff)*st->nsect + 553*10622Shelge (hpaddr->hpda&0x1f); 5542925Swnj harderr(bp, "hp"); 5553271Swnj if (mbsr & (MBSR_EBITS &~ (MBSR_DTABT|MBSR_MBEXC))) 5563271Swnj printf("mbsr=%b ", mbsr, mbsr_bits); 5573706Sroot printf("er1=%b er2=%b", 5582826Swnj hpaddr->hper1, HPER1_BITS, 5592826Swnj hpaddr->hper2, HPER2_BITS); 5603706Sroot if (hpaddr->hpmr) 5613706Sroot printf(" mr=%o", hpaddr->hpmr&0xffff); 5623706Sroot if (hpaddr->hpmr2) 5633706Sroot printf(" mr2=%o", hpaddr->hpmr2&0xffff); 5643706Sroot printf("\n"); 5652826Swnj bp->b_flags |= B_ERROR; 566*10622Shelge retry = 0; 5673143Swnj hprecal[mi->mi_unit] = 0; 5685893Swnj } else if ((er2 & HPER2_BSE) && !ML11) { 5693726Sroot #ifndef NOBADSECT 5703706Sroot if (hpecc(mi, BSE)) 5713706Sroot return(MBD_RESTARTED); 5723706Sroot else 5733706Sroot #endif 5743706Sroot goto hard; 5755893Swnj } else if (RM80 && er2&HPER2_SSE) { 5763988Sroot (void) hpecc(mi, SSE); 5772883Swnj return (MBD_RESTARTED); 5785858Swnj } else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) { 5793706Sroot if (hpecc(mi, ECC)) 5802383Swnj return (MBD_RESTARTED); 5812826Swnj /* else done */ 5822826Swnj } else 5832826Swnj retry = 1; 5842826Swnj hpaddr->hpcs1 = HP_DCLR|HP_GO; 5855726Sroot if (ML11) { 5865726Sroot if (mi->mi_tab.b_errcnt >= 16) 5875726Sroot goto hard; 5885726Sroot } else if ((mi->mi_tab.b_errcnt&07) == 4) { 5892826Swnj hpaddr->hpcs1 = HP_RECAL|HP_GO; 5903706Sroot hprecal[mi->mi_unit] = 1; 5913706Sroot return(MBD_RESTARTED); 59221Sbill } 5932826Swnj if (retry) 5942826Swnj return (MBD_RETRY); 5952826Swnj } 5963706Sroot #ifdef HPDEBUG 5973289Swnj else 5983289Swnj if (hpdebug && hprecal[mi->mi_unit]) { 5993289Swnj printf("recal %d ", hprecal[mi->mi_unit]); 6003289Swnj printf("errcnt %d\n", mi->mi_tab.b_errcnt); 6013289Swnj printf("mbsr=%b ", mbsr, mbsr_bits); 6023289Swnj printf("er1=%b er2=%b\n", 6033289Swnj hpaddr->hper1, HPER1_BITS, 6043289Swnj hpaddr->hper2, HPER2_BITS); 6053289Swnj } 6063706Sroot #endif 6073093Swnj switch (hprecal[mi->mi_unit]) { 6083093Swnj 6093093Swnj case 1: 6103093Swnj hpaddr->hpdc = bp->b_cylin; 6113093Swnj hpaddr->hpcs1 = HP_SEEK|HP_GO; 6123706Sroot hprecal[mi->mi_unit]++; 6133706Sroot return (MBD_RESTARTED); 6143093Swnj case 2: 6153093Swnj if (mi->mi_tab.b_errcnt < 16 || 6163289Swnj (bp->b_flags & B_READ) == 0) 6173093Swnj goto donerecal; 6183093Swnj hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017]|HPOF_FMT22; 6193093Swnj hpaddr->hpcs1 = HP_OFFSET|HP_GO; 6203093Swnj hprecal[mi->mi_unit]++; 6213093Swnj return (MBD_RESTARTED); 6223093Swnj donerecal: 6233158Swnj case 3: 6242892Swnj hprecal[mi->mi_unit] = 0; 6252892Swnj return (MBD_RETRY); 6262892Swnj } 6275726Sroot hphdr[mi->mi_unit] = 0; 6282383Swnj bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff; 6293640Swnj if (mi->mi_tab.b_errcnt >= 16) { 6303093Swnj /* 6313093Swnj * This is fast and occurs rarely; we don't 6323093Swnj * bother with interrupts. 6333093Swnj */ 6342624Swnj hpaddr->hpcs1 = HP_RTC|HP_GO; 6353093Swnj while (hpaddr->hpds & HPDS_PIP) 6362383Swnj ; 6372383Swnj mbclrattn(mi); 63821Sbill } 6395726Sroot if (!ML11) { 6405726Sroot hpaddr->hpof = HPOF_FMT22; 6415726Sroot hpaddr->hpcs1 = HP_RELEASE|HP_GO; 6425726Sroot } 6432383Swnj return (MBD_DONE); 64421Sbill } 64521Sbill 6467738Sroot hpread(dev, uio) 6472624Swnj dev_t dev; 6487738Sroot struct uio *uio; 64921Sbill { 6502624Swnj register int unit = minor(dev) >> 3; 65121Sbill 6522624Swnj if (unit >= NHP) 6538156Sroot return (ENXIO); 6548156Sroot return (physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys, uio)); 65521Sbill } 65621Sbill 6577831Sroot hpwrite(dev, uio) 6582624Swnj dev_t dev; 6597831Sroot struct uio *uio; 66021Sbill { 6612624Swnj register int unit = minor(dev) >> 3; 66221Sbill 6632624Swnj if (unit >= NHP) 6648156Sroot return (ENXIO); 6658156Sroot return (physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys, uio)); 66621Sbill } 66721Sbill 6685726Sroot /*ARGSUSED*/ 6697635Ssam hpioctl(dev, cmd, data, flag) 6705726Sroot dev_t dev; 6715726Sroot int cmd; 6727635Ssam caddr_t data; 6735726Sroot int flag; 6745726Sroot { 6755726Sroot 6765726Sroot switch (cmd) { 6777635Ssam 6785726Sroot case DKIOCHDR: /* do header read/write */ 6795726Sroot hphdr[minor(dev)>>3] = 1; 6808579Sroot return (0); 6815726Sroot 6825726Sroot default: 6838579Sroot return (ENXIO); 6845726Sroot } 6855726Sroot } 6865726Sroot 6873706Sroot hpecc(mi, flag) 6882978Swnj register struct mba_device *mi; 6893706Sroot int flag; 69021Sbill { 6912383Swnj register struct mba_regs *mbp = mi->mi_mba; 6922624Swnj register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; 6932383Swnj register struct buf *bp = mi->mi_tab.b_actf; 6943706Sroot register struct hpst *st = &hpst[mi->mi_type]; 6953706Sroot int npf, o; 6962383Swnj int bn, cn, tn, sn; 697914Sbill int bcr; 69821Sbill 699914Sbill bcr = mbp->mba_bcr & 0xffff; 700914Sbill if (bcr) 701914Sbill bcr |= 0xffff0000; /* sxt */ 7023726Sroot #ifndef NOBADSECT 7033706Sroot if (flag == CONT) 7043706Sroot npf = bp->b_error; 7053706Sroot else 7063706Sroot #endif 7073706Sroot npf = btop(bcr + bp->b_bcount); 708420Sbill o = (int)bp->b_un.b_addr & PGOFSET; 709420Sbill bn = dkblock(bp); 710420Sbill cn = bp->b_cylin; 7113706Sroot sn = bn%(st->nspc) + npf; 7122383Swnj tn = sn/st->nsect; 7132383Swnj sn %= st->nsect; 7142383Swnj cn += tn/st->ntrak; 7152383Swnj tn %= st->ntrak; 7163706Sroot switch (flag) { 7173706Sroot case ECC: 7183706Sroot { 7193706Sroot register int i; 7203706Sroot caddr_t addr; 7213706Sroot struct pte mpte; 7223706Sroot int bit, byte, mask; 7233706Sroot 7243706Sroot npf--; /* because block in error is previous block */ 7253706Sroot printf("hp%d%c: soft ecc sn%d\n", dkunit(bp), 7263706Sroot 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 7273706Sroot mask = rp->hpec2&0xffff; 7283706Sroot i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */ 7293706Sroot bit = i&07; 7303706Sroot i = (i&~07)>>3; 7313706Sroot byte = i + o; 7323706Sroot while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 7333706Sroot mpte = mbp->mba_map[npf+btop(byte)]; 7343706Sroot addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); 7353706Sroot putmemc(addr, getmemc(addr)^(mask<<bit)); 7363706Sroot byte++; 7373706Sroot i++; 7383706Sroot bit -= 8; 7393706Sroot } 7403706Sroot if (bcr == 0) 7413706Sroot return (0); 7423847Sroot npf++; 7433706Sroot break; 7443706Sroot } 7453706Sroot 7463706Sroot case SSE: 7473706Sroot rp->hpof |= HPOF_SSEI; 7483706Sroot mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 7493706Sroot break; 7503706Sroot 7513726Sroot #ifndef NOBADSECT 7523706Sroot case BSE: 7533706Sroot #ifdef HPBDEBUG 7543706Sroot if (hpbdebug) 7553706Sroot printf("hpecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); 7563706Sroot #endif 7573706Sroot if ((bn = isbad(&hpbad[mi->mi_unit], cn, tn, sn)) < 0) 7583706Sroot return(0); 7593706Sroot bp->b_flags |= B_BAD; 7603706Sroot bp->b_error = npf + 1; 7613706Sroot bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 7623706Sroot cn = bn/st->nspc; 7633706Sroot sn = bn%st->nspc; 7643706Sroot tn = sn/st->nsect; 7653706Sroot sn %= st->nsect; 7663706Sroot mbp->mba_bcr = -512; 7673706Sroot #ifdef HPBDEBUG 7683706Sroot if (hpbdebug) 7693706Sroot printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 7703706Sroot #endif 7713706Sroot break; 7723706Sroot 7733706Sroot case CONT: 7743706Sroot #ifdef HPBDEBUG 7753706Sroot if (hpbdebug) 7763706Sroot printf("hpecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); 7773706Sroot #endif 7783706Sroot npf = bp->b_error; 7793706Sroot bp->b_flags &= ~B_BAD; 7803706Sroot mbp->mba_bcr = -(bp->b_bcount - (int)ptob(npf)); 7813706Sroot if ((mbp->mba_bcr & 0xffff) == 0) 7823706Sroot return(0); 7833706Sroot break; 7843706Sroot #endif 7853706Sroot } 7863706Sroot rp->hpcs1 = HP_DCLR|HP_GO; 7873350Swnj if (rp->hpof&HPOF_SSEI) 7882883Swnj sn++; 789420Sbill rp->hpdc = cn; 790420Sbill rp->hpda = (tn<<8) + sn; 791420Sbill mbp->mba_sr = -1; 7923706Sroot mbp->mba_var = (int)ptob(npf) + o; 7933706Sroot rp->hpcs1 = bp->b_flags&B_READ ? HP_RCOM|HP_GO : HP_WCOM|HP_GO; 7943706Sroot mi->mi_tab.b_errcnt = 0; /* error has been corrected */ 795420Sbill return (1); 79621Sbill } 7972362Swnj 7982362Swnj #define DBSIZE 20 7992362Swnj 8002362Swnj hpdump(dev) 8012362Swnj dev_t dev; 8022362Swnj { 8032978Swnj register struct mba_device *mi; 8042383Swnj register struct mba_regs *mba; 8052624Swnj struct hpdevice *hpaddr; 8062362Swnj char *start; 8072383Swnj int num, unit; 8082383Swnj register struct hpst *st; 8092362Swnj 8102362Swnj num = maxfree; 8112362Swnj start = 0; 8122362Swnj unit = minor(dev) >> 3; 8132827Swnj if (unit >= NHP) 8142827Swnj return (ENXIO); 8152383Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 8162978Swnj mi = phys(hpinfo[unit],struct mba_device *); 8172827Swnj if (mi == 0 || mi->mi_alive == 0) 8182827Swnj return (ENXIO); 8192383Swnj mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 8203102Swnj mba->mba_cr = MBCR_INIT; 8212624Swnj hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; 8223093Swnj if ((hpaddr->hpds & HPDS_VV) == 0) { 8232624Swnj hpaddr->hpcs1 = HP_DCLR|HP_GO; 8242624Swnj hpaddr->hpcs1 = HP_PRESET|HP_GO; 8253093Swnj hpaddr->hpof = HPOF_FMT22; 8262362Swnj } 8272383Swnj st = &hpst[mi->mi_type]; 8282827Swnj if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks) 8292827Swnj return (EINVAL); 8302362Swnj while (num > 0) { 8312383Swnj register struct pte *hpte = mba->mba_map; 8322362Swnj register int i; 8332383Swnj int blk, cn, sn, tn; 8342362Swnj daddr_t bn; 8352362Swnj 8362362Swnj blk = num > DBSIZE ? DBSIZE : num; 8372362Swnj bn = dumplo + btop(start); 8382383Swnj cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; 8392383Swnj sn = bn%st->nspc; 8402383Swnj tn = sn/st->nsect; 8412383Swnj sn = sn%st->nsect; 8422362Swnj hpaddr->hpdc = cn; 8432362Swnj hpaddr->hpda = (tn << 8) + sn; 8442362Swnj for (i = 0; i < blk; i++) 8452362Swnj *(int *)hpte++ = (btop(start)+i) | PG_V; 8462383Swnj mba->mba_sr = -1; 8472383Swnj mba->mba_bcr = -(blk*NBPG); 8482383Swnj mba->mba_var = 0; 8492624Swnj hpaddr->hpcs1 = HP_WCOM | HP_GO; 8503093Swnj while ((hpaddr->hpds & HPDS_DRY) == 0) 8512362Swnj ; 8523093Swnj if (hpaddr->hpds&HPDS_ERR) 8532827Swnj return (EIO); 8542362Swnj start += blk*NBPG; 8552362Swnj num -= blk; 8562362Swnj } 8572362Swnj return (0); 8582362Swnj } 8591565Sbill #endif 860