1*2826Swnj /* hp.c 4.18 81/03/01 */ 221Sbill 31939Swnj #include "hp.h" 41565Sbill #if NHP > 0 521Sbill /* 62624Swnj * HP disk driver for RP0x+RM0x 721Sbill */ 821Sbill 921Sbill #include "../h/param.h" 1021Sbill #include "../h/systm.h" 11305Sbill #include "../h/dk.h" 1221Sbill #include "../h/buf.h" 1321Sbill #include "../h/conf.h" 1421Sbill #include "../h/dir.h" 1521Sbill #include "../h/user.h" 1621Sbill #include "../h/map.h" 17420Sbill #include "../h/pte.h" 1821Sbill #include "../h/mba.h" 1921Sbill #include "../h/mtpr.h" 20420Sbill #include "../h/vm.h" 212362Swnj #include "../h/cmap.h" 2221Sbill 232383Swnj #include "../h/hpreg.h" 2421Sbill 252383Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 262383Swnj struct size { 2721Sbill daddr_t nblocks; 2821Sbill int cyloff; 292383Swnj } hp_sizes[8] = { 30886Sbill 15884, 0, /* A=cyl 0 thru 37 */ 31886Sbill 33440, 38, /* B=cyl 38 thru 117 */ 32886Sbill 340670, 0, /* C=cyl 0 thru 814 */ 3321Sbill 0, 0, 3421Sbill 0, 0, 3521Sbill 0, 0, 36886Sbill 291346, 118, /* G=cyl 118 thru 814 */ 3721Sbill 0, 0, 3821Sbill }, rm_sizes[8] = { 39886Sbill 15884, 0, /* A=cyl 0 thru 99 */ 40886Sbill 33440, 100, /* B=cyl 100 thru 309 */ 41886Sbill 131680, 0, /* C=cyl 0 thru 822 */ 422362Swnj 2720, 291, 4321Sbill 0, 0, 4421Sbill 0, 0, 45886Sbill 82080, 310, /* G=cyl 310 thru 822 */ 4621Sbill 0, 0, 47886Sbill }, rm5_sizes[8] = { 48886Sbill 15884, 0, /* A=cyl 0 thru 26 */ 49886Sbill 33440, 27, /* B=cyl 27 thru 81 */ 50886Sbill 500992, 0, /* C=cyl 0 thru 823 */ 51886Sbill 15884, 562, /* D=cyl 562 thru 588 */ 52886Sbill 55936, 589, /* E=cyl 589 thru 680 */ 53886Sbill 86944, 681, /* F=cyl 681 thru 823 */ 54886Sbill 159296, 562, /* G=cyl 562 thru 823 */ 55886Sbill 291346, 82, /* H=cyl 82 thru 561 */ 562383Swnj }, rm80_sizes[8] = { 572383Swnj 15884, 0, /* A=cyl 0 thru 36 */ 582383Swnj 33440, 37, /* B=cyl 37 thru 114 */ 592383Swnj 242606, 0, /* C=cyl 0 thru 558 */ 602383Swnj 0, 0, 612383Swnj 0, 0, 622383Swnj 0, 0, 632383Swnj 82080, 115, /* G=cyl 115 thru 304 */ 642383Swnj 110236, 305, /* H=cyl 305 thru 558 */ 6521Sbill }; 662383Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 6721Sbill 682383Swnj #define _hpSDIST 2 692383Swnj #define _hpRDIST 3 702383Swnj 712383Swnj int hpSDIST = _hpSDIST; 722383Swnj int hpRDIST = _hpRDIST; 732383Swnj 742383Swnj short hptypes[] = 752383Swnj { MBDT_RM03, MBDT_RM05, MBDT_RP06, MBDT_RM80, 0 }; 762383Swnj struct mba_info *hpinfo[NHP]; 772383Swnj int hpdkinit(),hpustart(),hpstart(),hpdtint(); 782383Swnj struct mba_driver hpdriver = 792383Swnj { hpdkinit, hpustart, hpstart, hpdtint, 0, hptypes, hpinfo }; 802383Swnj 812383Swnj struct hpst { 822383Swnj short nsect; 832383Swnj short ntrak; 842383Swnj short nspc; 852383Swnj short ncyl; 862383Swnj struct size *sizes; 872383Swnj } hpst[] = { 882383Swnj 32, 5, 32*5, 823, rm_sizes, /* RM03 */ 892383Swnj 32, 19, 32*19, 823, rm5_sizes, /* RM05 */ 902383Swnj 22, 19, 22*19, 815, hp_sizes, /* RP06 */ 912383Swnj 31, 14, 31*14, 559, rm80_sizes /* RM80 */ 922383Swnj }; 932383Swnj 942624Swnj u_char hp_offset[16] = { 952624Swnj HP_P400, HP_M400, HP_P400, HP_M400, HP_P800, HP_M800, HP_P800, HP_M800, 962624Swnj HP_P1200, HP_M1200, HP_P1200, HP_M1200, 0, 0, 0, 0, 9721Sbill }; 9821Sbill 992624Swnj struct buf rhpbuf[NHP]; 10021Sbill 10121Sbill #define b_cylin b_resid 10221Sbill 10321Sbill #ifdef INTRLVE 10421Sbill daddr_t dkblock(); 10521Sbill #endif 10621Sbill 1072604Swnj int hpseek; 1082604Swnj 1092604Swnj hpdkinit(mi) 1102604Swnj struct mba_info *mi; 1112604Swnj { 1122604Swnj register struct hpst *st = &hpst[mi->mi_type]; 1132604Swnj 1142604Swnj if (mi->mi_dk >= 0) 1152757Swnj dk_mspw[mi->mi_dk] = 1.0 / 60 / (st->nsect * 256); 1162604Swnj } 1172604Swnj 11821Sbill hpstrategy(bp) 1192383Swnj register struct buf *bp; 12021Sbill { 1212383Swnj register struct mba_info *mi; 1222383Swnj register struct hpst *st; 1232383Swnj register int unit; 12421Sbill long sz, bn; 1252383Swnj int xunit = minor(bp->b_dev) & 07; 12621Sbill 12721Sbill sz = bp->b_bcount; 12821Sbill sz = (sz+511) >> 9; 12921Sbill unit = dkunit(bp); 1302383Swnj if (unit >= NHP) 1312383Swnj goto bad; 1322383Swnj mi = hpinfo[unit]; 1332395Swnj if (mi == 0 || mi->mi_alive == 0) 1342383Swnj goto bad; 1352383Swnj st = &hpst[mi->mi_type]; 1362383Swnj if (bp->b_blkno < 0 || 1372383Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 1382383Swnj goto bad; 1392383Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 140127Sbill (void) spl5(); 1412383Swnj disksort(&mi->mi_tab, bp); 1422383Swnj if (mi->mi_tab.b_active == 0) 1432383Swnj mbustart(mi); 144127Sbill (void) spl0(); 1452383Swnj return; 1462383Swnj 1472383Swnj bad: 1482383Swnj bp->b_flags |= B_ERROR; 1492383Swnj iodone(bp); 1502383Swnj return; 15121Sbill } 15221Sbill 1532383Swnj hpustart(mi) 1542383Swnj register struct mba_info *mi; 15521Sbill { 1562624Swnj register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 1572383Swnj register struct buf *bp = mi->mi_tab.b_actf; 1582383Swnj register struct hpst *st; 15921Sbill daddr_t bn; 1602383Swnj int sn, dist, flags; 16121Sbill 1622624Swnj if ((hpaddr->hpcs1&HP_DVA) == 0) 1632383Swnj return (MBU_BUSY); 1642624Swnj if ((hpaddr->hpds & HP_VV) == 0) { 1652624Swnj hpaddr->hpcs1 = HP_DCLR|HP_GO; 1662624Swnj hpaddr->hpcs1 = HP_PRESET|HP_GO; 1672624Swnj hpaddr->hpof = HP_FMT22; 16821Sbill } 1692604Swnj if (mi->mi_tab.b_active || mi->mi_hd->mh_ndrive == 1) 1702383Swnj return (MBU_DODATA); 1712624Swnj if ((hpaddr->hpds & (HP_DPR|HP_MOL)) != (HP_DPR|HP_MOL)) 1722383Swnj return (MBU_DODATA); 1732395Swnj st = &hpst[mi->mi_type]; 1742395Swnj bn = dkblock(bp); 1752395Swnj sn = bn%st->nspc; 1762395Swnj sn = (sn+st->nsect-hpSDIST)%st->nsect; 1772383Swnj if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) { 1782604Swnj if (hpseek) 1792383Swnj return (MBU_DODATA); 1802383Swnj dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1; 1812383Swnj if (dist < 0) 1822383Swnj dist += st->nsect; 1832383Swnj if (dist > st->nsect - hpRDIST) 1842383Swnj return (MBU_DODATA); 1852614Swnj } else 1862614Swnj hpaddr->hpdc = bp->b_cylin; 1872604Swnj if (hpseek) 1882624Swnj hpaddr->hpcs1 = HP_SEEK|HP_GO; 189305Sbill else { 190305Sbill hpaddr->hpda = sn; 1912624Swnj hpaddr->hpcs1 = HP_SEARCH|HP_GO; 192305Sbill } 1932383Swnj return (MBU_STARTED); 19421Sbill } 19521Sbill 1962383Swnj hpstart(mi) 1972383Swnj register struct mba_info *mi; 19821Sbill { 1992624Swnj register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 2002383Swnj register struct buf *bp = mi->mi_tab.b_actf; 2012383Swnj register struct hpst *st = &hpst[mi->mi_type]; 20221Sbill daddr_t bn; 2032383Swnj int sn, tn; 20421Sbill 20521Sbill bn = dkblock(bp); 2062383Swnj sn = bn%st->nspc; 2072383Swnj tn = sn/st->nsect; 2082395Swnj sn %= st->nsect; 2092383Swnj if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags&B_READ) != 0) { 2102624Swnj hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017] | HP_FMT22; 2112624Swnj hpaddr->hpcs1 = HP_OFFSET|HP_GO; 2122624Swnj while (hpaddr->hpds & HP_PIP) 21321Sbill ; 2142383Swnj mbclrattn(mi); 21521Sbill } 2162383Swnj hpaddr->hpdc = bp->b_cylin; 21721Sbill hpaddr->hpda = (tn << 8) + sn; 21821Sbill } 21921Sbill 2202672Swnj hpdtint(mi, mbasr) 2212383Swnj register struct mba_info *mi; 2222672Swnj int mbasr; 22321Sbill { 2242624Swnj register struct hpdevice *hpaddr = (struct hpdevice *)mi->mi_drv; 2252383Swnj register struct buf *bp = mi->mi_tab.b_actf; 226*2826Swnj int retry = 0; 22721Sbill 228*2826Swnj if (hpaddr->hpds&HP_ERR || mbasr&MBAEBITS) { 229*2826Swnj int dready = 0; 230*2826Swnj 231*2826Swnj while ((hpaddr->hpds & HP_DRY) == 0) { 232*2826Swnj if (++dready > 32) 233*2826Swnj break; 234*2826Swnj } 235*2826Swnj if ((hpaddr->hpds&HP_DREADY) != HP_DREADY) { 236*2826Swnj printf("hp%d not ready\n", dkunit(bp)); 237*2826Swnj bp->b_flags |= B_ERROR; 238*2826Swnj } else if (hpaddr->hper1&HP_WLE) { 239*2826Swnj printf("hp%d is write locked\n", dkunit(bp)); 240*2826Swnj bp->b_flags |= B_ERROR; 241*2826Swnj } else if (++mi->mi_tab.b_errcnt > 27 || 242*2826Swnj mbasr & MBASR_HARD || 243*2826Swnj hpaddr->hper1 & HPER1_HARD || 244*2826Swnj hpaddr->hper2 & HPER2_HARD) { 245*2826Swnj harderr(bp); 246*2826Swnj printf("hp%d mbasr=%b er1=%b er2=%b\n", 247*2826Swnj dkunit(bp), mbasr, mbasr_bits, 248*2826Swnj hpaddr->hper1, HPER1_BITS, 249*2826Swnj hpaddr->hper2, HPER2_BITS); 250*2826Swnj bp->b_flags |= B_ERROR; 251*2826Swnj } else if ((hpaddr->hper1&(HP_DCK|HP_ECH)) == HP_DCK) { 252*2826Swnj if (hpecc(mi)) 2532383Swnj return (MBD_RESTARTED); 254*2826Swnj /* else done */ 255*2826Swnj } else 256*2826Swnj retry = 1; 257*2826Swnj hpaddr->hpcs1 = HP_DCLR|HP_GO; 258*2826Swnj if ((mi->mi_tab.b_errcnt&07) == 4) { 259*2826Swnj hpaddr->hpcs1 = HP_RECAL|HP_GO; 260*2826Swnj /* SHOULD SET AN INTERRUPT AND RETURN */ 261*2826Swnj /* AND HANDLE ALA rk.c OR up.c */ 262*2826Swnj while (hpaddr->hpds & HP_PIP) 263*2826Swnj ; 264*2826Swnj mbclrattn(mi); 26521Sbill } 266*2826Swnj if (retry) 267*2826Swnj return (MBD_RETRY); 268*2826Swnj } 2692383Swnj bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff; 270*2826Swnj if (mi->mi_tab.b_errcnt > 16) { 2712624Swnj hpaddr->hpcs1 = HP_RTC|HP_GO; 2722624Swnj while (hpaddr->hpds & HP_PIP) 2732383Swnj ; 2742383Swnj mbclrattn(mi); 27521Sbill } 2762624Swnj hpaddr->hpcs1 = HP_RELEASE|HP_GO; 2772383Swnj return (MBD_DONE); 27821Sbill } 27921Sbill 28021Sbill hpread(dev) 2812624Swnj dev_t dev; 28221Sbill { 2832624Swnj register int unit = minor(dev) >> 3; 28421Sbill 2852624Swnj if (unit >= NHP) 2862624Swnj u.u_error = ENXIO; 2872624Swnj else 2882624Swnj physio(hpstrategy, &rhpbuf[unit], dev, B_READ, minphys); 28921Sbill } 29021Sbill 29121Sbill hpwrite(dev) 2922624Swnj dev_t dev; 29321Sbill { 2942624Swnj register int unit = minor(dev) >> 3; 29521Sbill 2962624Swnj if (unit >= NHP) 2972624Swnj u.u_error = ENXIO; 2982624Swnj else 2992624Swnj physio(hpstrategy, &rhpbuf[unit], dev, B_WRITE, minphys); 30021Sbill } 30121Sbill 3022383Swnj hpecc(mi) 3032383Swnj register struct mba_info *mi; 30421Sbill { 3052383Swnj register struct mba_regs *mbp = mi->mi_mba; 3062624Swnj register struct hpdevice *rp = (struct hpdevice *)mi->mi_drv; 3072383Swnj register struct buf *bp = mi->mi_tab.b_actf; 3082383Swnj register struct hpst *st; 309420Sbill register int i; 310420Sbill caddr_t addr; 311420Sbill int reg, bit, byte, npf, mask, o; 3122383Swnj int bn, cn, tn, sn; 313420Sbill struct pte mpte; 314914Sbill int bcr; 31521Sbill 316914Sbill bcr = mbp->mba_bcr & 0xffff; 317914Sbill if (bcr) 318914Sbill bcr |= 0xffff0000; /* sxt */ 319719Sbill npf = btop(bcr + bp->b_bcount) - 1; 3201413Sbill reg = npf; 321420Sbill o = (int)bp->b_un.b_addr & PGOFSET; 322*2826Swnj printf("SOFT ECC hp%d%c bn%d\n", dkunit(bp), 323*2826Swnj 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); 32421Sbill mask = rp->hpec2&0xffff; 325420Sbill i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */ 326719Sbill bit = i&07; 327420Sbill i = (i&~07)>>3; 328420Sbill byte = i + o; 329420Sbill while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 330420Sbill mpte = mbp->mba_map[reg+btop(byte)]; 331420Sbill addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); 332420Sbill putmemc(addr, getmemc(addr)^(mask<<bit)); 333420Sbill byte++; 334420Sbill i++; 335420Sbill bit -= 8; 33621Sbill } 337719Sbill if (bcr == 0) 338420Sbill return (0); 3392624Swnj #ifdef notdef 3402624Swnj rp->hper1 = 0; 3412624Swnj rp->hpcs1 = HP_RCOM|HP_GO; 3422624Swnj #else 3432624Swnj rp->hpcs1 = HP_DCLR|HP_GO; 344420Sbill bn = dkblock(bp); 3452383Swnj st = &hpst[mi->mi_type]; 346420Sbill cn = bp->b_cylin; 3472383Swnj sn = bn%(st->nspc) + npf + 1; 3482383Swnj tn = sn/st->nsect; 3492383Swnj sn %= st->nsect; 3502383Swnj cn += tn/st->ntrak; 3512383Swnj tn %= st->ntrak; 352420Sbill rp->hpdc = cn; 353420Sbill rp->hpda = (tn<<8) + sn; 354420Sbill mbp->mba_sr = -1; 355420Sbill mbp->mba_var = (int)ptob(reg+1) + o; 3562624Swnj rp->hpcs1 = HP_RCOM|HP_GO; 3572624Swnj #endif 358420Sbill return (1); 35921Sbill } 3602362Swnj 3612362Swnj #define DBSIZE 20 3622362Swnj 3632362Swnj hpdump(dev) 3642362Swnj dev_t dev; 3652362Swnj { 3662383Swnj register struct mba_info *mi; 3672383Swnj register struct mba_regs *mba; 3682624Swnj struct hpdevice *hpaddr; 3692362Swnj char *start; 3702383Swnj int num, unit; 3712383Swnj register struct hpst *st; 3722362Swnj 3732362Swnj num = maxfree; 3742362Swnj start = 0; 3752362Swnj unit = minor(dev) >> 3; 3762362Swnj if (unit >= NHP) { 3772362Swnj printf("bad unit\n"); 3782362Swnj return (-1); 3792362Swnj } 3802383Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 3812383Swnj mi = phys(hpinfo[unit],struct mba_info *); 3822624Swnj if (mi == 0 || mi->mi_alive == 0) { 3832383Swnj printf("dna\n"); 3842383Swnj return (-1); 3852383Swnj } 3862383Swnj mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 3872383Swnj mba->mba_cr = MBAINIT; 3882624Swnj hpaddr = (struct hpdevice *)&mba->mba_drv[mi->mi_drive]; 3892624Swnj if ((hpaddr->hpds & HP_VV) == 0) { 3902624Swnj hpaddr->hpcs1 = HP_DCLR|HP_GO; 3912624Swnj hpaddr->hpcs1 = HP_PRESET|HP_GO; 3922624Swnj hpaddr->hpof = HP_FMT22; 3932362Swnj } 3942383Swnj st = &hpst[mi->mi_type]; 3952383Swnj if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks) { 3962383Swnj printf("oor\n"); 3972362Swnj return (-1); 3982362Swnj } 3992362Swnj while (num > 0) { 4002383Swnj register struct pte *hpte = mba->mba_map; 4012362Swnj register int i; 4022383Swnj int blk, cn, sn, tn; 4032362Swnj daddr_t bn; 4042362Swnj 4052362Swnj blk = num > DBSIZE ? DBSIZE : num; 4062362Swnj bn = dumplo + btop(start); 4072383Swnj cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; 4082383Swnj sn = bn%st->nspc; 4092383Swnj tn = sn/st->nsect; 4102383Swnj sn = sn%st->nsect; 4112362Swnj hpaddr->hpdc = cn; 4122362Swnj hpaddr->hpda = (tn << 8) + sn; 4132362Swnj for (i = 0; i < blk; i++) 4142362Swnj *(int *)hpte++ = (btop(start)+i) | PG_V; 4152383Swnj mba->mba_sr = -1; 4162383Swnj mba->mba_bcr = -(blk*NBPG); 4172383Swnj mba->mba_var = 0; 4182624Swnj hpaddr->hpcs1 = HP_WCOM | HP_GO; 4192624Swnj while ((hpaddr->hpds & HP_DRY) == 0) 4202362Swnj ; 4212624Swnj if (hpaddr->hpds&HP_ERR) { 4222383Swnj printf("dskerr: (%d,%d,%d) ds=%x er=%x\n", 4232362Swnj cn, tn, sn, hpaddr->hpds, hpaddr->hper1); 4242362Swnj return (-1); 4252362Swnj } 4262362Swnj start += blk*NBPG; 4272362Swnj num -= blk; 4282362Swnj } 4292362Swnj return (0); 4302362Swnj } 4311565Sbill #endif 432