1*2383Swnj /* hp.c 4.7 81/02/08 */ 221Sbill 31939Swnj #include "hp.h" 41565Sbill #if NHP > 0 521Sbill /* 6*2383Swnj * RP/RM disk driver 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 23*2383Swnj #include "../h/hpreg.h" 2421Sbill 25*2383Swnj /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ 26*2383Swnj struct size { 2721Sbill daddr_t nblocks; 2821Sbill int cyloff; 29*2383Swnj } 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 */ 56*2383Swnj }, rm80_sizes[8] = { 57*2383Swnj 15884, 0, /* A=cyl 0 thru 36 */ 58*2383Swnj 33440, 37, /* B=cyl 37 thru 114 */ 59*2383Swnj 242606, 0, /* C=cyl 0 thru 558 */ 60*2383Swnj 0, 0, 61*2383Swnj 0, 0, 62*2383Swnj 0, 0, 63*2383Swnj 82080, 115, /* G=cyl 115 thru 304 */ 64*2383Swnj 110236, 305, /* H=cyl 305 thru 558 */ 6521Sbill }; 66*2383Swnj /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ 6721Sbill 68*2383Swnj #define _hpSDIST 2 69*2383Swnj #define _hpRDIST 3 70*2383Swnj 71*2383Swnj int hpSDIST = _hpSDIST; 72*2383Swnj int hpRDIST = _hpRDIST; 73*2383Swnj 74*2383Swnj short hptypes[] = 75*2383Swnj { MBDT_RM03, MBDT_RM05, MBDT_RP06, MBDT_RM80, 0 }; 76*2383Swnj struct mba_info *hpinfo[NHP]; 77*2383Swnj int hpdkinit(),hpustart(),hpstart(),hpdtint(); 78*2383Swnj struct mba_driver hpdriver = 79*2383Swnj { hpdkinit, hpustart, hpstart, hpdtint, 0, hptypes, hpinfo }; 80*2383Swnj 81*2383Swnj struct hpst { 82*2383Swnj short nsect; 83*2383Swnj short ntrak; 84*2383Swnj short nspc; 85*2383Swnj short ncyl; 86*2383Swnj struct size *sizes; 87*2383Swnj } hpst[] = { 88*2383Swnj 32, 5, 32*5, 823, rm_sizes, /* RM03 */ 89*2383Swnj 32, 19, 32*19, 823, rm5_sizes, /* RM05 */ 90*2383Swnj 22, 19, 22*19, 815, hp_sizes, /* RP06 */ 91*2383Swnj 31, 14, 31*14, 559, rm80_sizes /* RM80 */ 92*2383Swnj }; 93*2383Swnj 94*2383Swnj int hp_offset[16] = { 9521Sbill P400, M400, P400, M400, 9621Sbill P800, M800, P800, M800, 9721Sbill P1200, M1200, P1200, M1200, 9821Sbill 0, 0, 0, 0, 9921Sbill }; 10021Sbill 10121Sbill struct buf rhpbuf; 10221Sbill 10321Sbill #define b_cylin b_resid 10421Sbill 10521Sbill #ifdef INTRLVE 10621Sbill daddr_t dkblock(); 10721Sbill #endif 10821Sbill 10921Sbill hpstrategy(bp) 110*2383Swnj register struct buf *bp; 11121Sbill { 112*2383Swnj register struct mba_info *mi; 113*2383Swnj register struct hpst *st; 114*2383Swnj register int unit; 11521Sbill long sz, bn; 116*2383Swnj int xunit = minor(bp->b_dev) & 07; 11721Sbill 11821Sbill sz = bp->b_bcount; 11921Sbill sz = (sz+511) >> 9; 12021Sbill unit = dkunit(bp); 121*2383Swnj if (unit >= NHP) 122*2383Swnj goto bad; 123*2383Swnj mi = hpinfo[unit]; 124*2383Swnj if (mi->mi_alive == 0) 125*2383Swnj goto bad; 126*2383Swnj st = &hpst[mi->mi_type]; 127*2383Swnj if (bp->b_blkno < 0 || 128*2383Swnj (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) 129*2383Swnj goto bad; 130*2383Swnj bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; 131127Sbill (void) spl5(); 132*2383Swnj disksort(&mi->mi_tab, bp); 133*2383Swnj if (mi->mi_tab.b_active == 0) 134*2383Swnj mbustart(mi); 135127Sbill (void) spl0(); 136*2383Swnj return; 137*2383Swnj 138*2383Swnj bad: 139*2383Swnj bp->b_flags |= B_ERROR; 140*2383Swnj iodone(bp); 141*2383Swnj return; 14221Sbill } 14321Sbill 144*2383Swnj hpustart(mi) 145*2383Swnj register struct mba_info *mi; 14621Sbill { 147*2383Swnj register struct device *hpaddr = (struct device *)mi->mi_drv; 148*2383Swnj register struct buf *bp = mi->mi_tab.b_actf; 149*2383Swnj register struct hpst *st; 15021Sbill daddr_t bn; 151*2383Swnj int sn, dist, flags; 15221Sbill 153*2383Swnj if ((hpaddr->hpcs1&DVA) == 0) 154*2383Swnj return (MBU_BUSY); 155*2383Swnj if ((hpaddr->hpds & VV) == 0) { 1562298Skre hpaddr->hpcs1 = DCLR|GO; 15721Sbill hpaddr->hpcs1 = PRESET|GO; 15821Sbill hpaddr->hpof = FMT22; 15921Sbill } 160*2383Swnj if (mi->mi_tab.b_active) 161*2383Swnj return (MBU_DODATA); 16221Sbill if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) 163*2383Swnj return (MBU_DODATA); 164*2383Swnj hpaddr->hpdc = bp->b_cylin; 165*2383Swnj flags = mi->mi_hd->mh_flags; 166*2383Swnj if (flags&MH_NOSEEK) 167*2383Swnj return (MBU_DODATA); 168*2383Swnj if (bp->b_cylin == (hpaddr->hpdc & 0xffff)) { 169*2383Swnj if (flags&MH_NOSEARCH) 170*2383Swnj return (MBU_DODATA); 171*2383Swnj bn = dkblock(bp); 172*2383Swnj st = &hpst[mi->mi_type]; 173*2383Swnj sn = bn%st->nspc; 174*2383Swnj sn = (sn+st->nsect-hpSDIST)%st->nsect; 175*2383Swnj dist = ((hpaddr->hpla & 0xffff)>>6) - st->nsect + 1; 176*2383Swnj if (dist < 0) 177*2383Swnj dist += st->nsect; 178*2383Swnj if (dist > st->nsect - hpRDIST) 179*2383Swnj return (MBU_DODATA); 18021Sbill } 181*2383Swnj if (flags&MH_NOSEARCH) 182305Sbill hpaddr->hpcs1 = SEEK|GO; 183305Sbill else { 184305Sbill hpaddr->hpda = sn; 185305Sbill hpaddr->hpcs1 = SEARCH|GO; 186305Sbill } 187*2383Swnj return (MBU_STARTED); 18821Sbill } 18921Sbill 190*2383Swnj hpstart(mi) 191*2383Swnj register struct mba_info *mi; 19221Sbill { 193*2383Swnj register struct device *hpaddr = (struct device *)mi->mi_drv; 194*2383Swnj register struct buf *bp = mi->mi_tab.b_actf; 195*2383Swnj register struct hpst *st = &hpst[mi->mi_type]; 19621Sbill daddr_t bn; 197*2383Swnj int sn, tn; 19821Sbill 19921Sbill bn = dkblock(bp); 200*2383Swnj sn = bn%st->nspc; 201*2383Swnj tn = sn/st->nsect; 202*2383Swnj sn = sn%st->nsect; 203*2383Swnj if (mi->mi_tab.b_errcnt >= 16 && (bp->b_flags&B_READ) != 0) { 204*2383Swnj hpaddr->hpof = hp_offset[mi->mi_tab.b_errcnt & 017] | FMT22; 20521Sbill hpaddr->hpcs1 = OFFSET|GO; 206*2383Swnj while (hpaddr->hpds & PIP) 20721Sbill ; 208*2383Swnj mbclrattn(mi); 20921Sbill } 210*2383Swnj hpaddr->hpdc = bp->b_cylin; 21121Sbill hpaddr->hpda = (tn << 8) + sn; 21221Sbill } 21321Sbill 214*2383Swnj hpdtint(mi, mbastat) 215*2383Swnj register struct mba_info *mi; 216*2383Swnj int mbastat; 21721Sbill { 218*2383Swnj register struct device *hpaddr = (struct device *)mi->mi_drv; 219*2383Swnj register struct buf *bp = mi->mi_tab.b_actf; 22021Sbill 221*2383Swnj while ((hpaddr->hpds & DRY) == 0) /* shouldn't happen */ 222*2383Swnj printf("hp dry not set\n"); 223*2383Swnj if (hpaddr->hpds & ERR || mbastat & MBAEBITS) 224*2383Swnj if (++mi->mi_tab.b_errcnt < 28 && (hpaddr->hper1&WLE) == 0) { 225*2383Swnj if ((hpaddr->hper1&0xffff) != DCK) { 226*2383Swnj hpaddr->hpcs1 = DCLR|GO; 227*2383Swnj if ((mi->mi_tab.b_errcnt&07) == 4) { 228*2383Swnj hpaddr->hpcs1 = RECAL|GO; 229*2383Swnj while (hpaddr->hpds & PIP) 230*2383Swnj ; 231*2383Swnj mbclrattn(mi); 232*2383Swnj } 233*2383Swnj return (MBD_RETRY); 234*2383Swnj } else if (hpecc(mi)) 235*2383Swnj return (MBD_RESTARTED); 236*2383Swnj } else { 237*2383Swnj deverror(bp, mbastat, hpaddr->hper1); 238*2383Swnj bp->b_flags |= B_ERROR; 23921Sbill } 240*2383Swnj bp->b_resid = -(mi->mi_mba->mba_bcr) & 0xffff; 241*2383Swnj if (mi->mi_tab.b_errcnt) { 242*2383Swnj hpaddr->hpcs1 = RTC|GO; 243*2383Swnj while (hpaddr->hpds & PIP) 244*2383Swnj ; 245*2383Swnj mbclrattn(mi); 24621Sbill } 247*2383Swnj hpaddr->hpcs1 = RELEASE|GO; 248*2383Swnj return (MBD_DONE); 24921Sbill } 25021Sbill 25121Sbill hpread(dev) 25221Sbill { 25321Sbill 25421Sbill physio(hpstrategy, &rhpbuf, dev, B_READ, minphys); 25521Sbill } 25621Sbill 25721Sbill hpwrite(dev) 25821Sbill { 25921Sbill 26021Sbill physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys); 26121Sbill } 26221Sbill 263*2383Swnj hpecc(mi) 264*2383Swnj register struct mba_info *mi; 26521Sbill { 266*2383Swnj register struct mba_regs *mbp = mi->mi_mba; 267*2383Swnj register struct device *rp = (struct device *)mi->mi_drv; 268*2383Swnj register struct buf *bp = mi->mi_tab.b_actf; 269*2383Swnj register struct hpst *st; 270420Sbill register int i; 271420Sbill caddr_t addr; 272420Sbill int reg, bit, byte, npf, mask, o; 273*2383Swnj int bn, cn, tn, sn; 274420Sbill struct pte mpte; 275914Sbill int bcr; 27621Sbill 277420Sbill /* 278420Sbill * Npf is the number of sectors transferred before the sector 279420Sbill * containing the ECC error, and reg is the MBA register 280420Sbill * mapping (the first part of)the transfer. 281420Sbill * O is offset within a memory page of the first byte transferred. 282420Sbill */ 283914Sbill bcr = mbp->mba_bcr & 0xffff; 284914Sbill if (bcr) 285914Sbill bcr |= 0xffff0000; /* sxt */ 286719Sbill npf = btop(bcr + bp->b_bcount) - 1; 2871413Sbill reg = npf; 288420Sbill o = (int)bp->b_un.b_addr & PGOFSET; 289420Sbill printf("%D ", bp->b_blkno + npf); 29021Sbill prdev("ECC", bp->b_dev); 29121Sbill mask = rp->hpec2&0xffff; 29221Sbill if (mask == 0) { 29321Sbill rp->hpof = FMT22; 294420Sbill return (0); 29521Sbill } 296420Sbill 297420Sbill /* 298420Sbill * Compute the byte and bit position of the error. 299420Sbill * The variable i is the byte offset in the transfer, 300420Sbill * the variable byte is the offset from a page boundary 301420Sbill * in main memory. 302420Sbill */ 303420Sbill i = (rp->hpec1&0xffff) - 1; /* -1 makes 0 origin */ 304719Sbill bit = i&07; 305420Sbill i = (i&~07)>>3; 306420Sbill byte = i + o; 307420Sbill /* 308420Sbill * Correct while possible bits remain of mask. Since mask 309420Sbill * contains 11 bits, we continue while the bit offset is > -11. 310420Sbill * Also watch out for end of this block and the end of the whole 311420Sbill * transfer. 312420Sbill */ 313420Sbill while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { 314420Sbill mpte = mbp->mba_map[reg+btop(byte)]; 315420Sbill addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET); 316420Sbill putmemc(addr, getmemc(addr)^(mask<<bit)); 317420Sbill byte++; 318420Sbill i++; 319420Sbill bit -= 8; 32021Sbill } 321*2383Swnj mi->mi_hd->mh_active++; /* Either complete or continuing */ 322719Sbill if (bcr == 0) 323420Sbill return (0); 324420Sbill /* 325420Sbill * Have to continue the transfer... clear the drive, 326420Sbill * and compute the position where the transfer is to continue. 327420Sbill * We have completed npf+1 sectores of the transfer already; 328420Sbill * restart at offset o of next sector (i.e. in MBA register reg+1). 329420Sbill */ 330420Sbill rp->hpcs1 = DCLR|GO; 331420Sbill bn = dkblock(bp); 332*2383Swnj st = &hpst[mi->mi_type]; 333420Sbill cn = bp->b_cylin; 334*2383Swnj sn = bn%(st->nspc) + npf + 1; 335*2383Swnj tn = sn/st->nsect; 336*2383Swnj sn %= st->nsect; 337*2383Swnj cn += tn/st->ntrak; 338*2383Swnj tn %= st->ntrak; 339420Sbill rp->hpdc = cn; 340420Sbill rp->hpda = (tn<<8) + sn; 341420Sbill mbp->mba_sr = -1; 342420Sbill mbp->mba_var = (int)ptob(reg+1) + o; 343420Sbill rp->hpcs1 = RCOM|GO; 344420Sbill return (1); 34521Sbill } 3462362Swnj 3472362Swnj #define DBSIZE 20 3482362Swnj 3492362Swnj hpdump(dev) 3502362Swnj dev_t dev; 3512362Swnj { 352*2383Swnj register struct mba_info *mi; 353*2383Swnj register struct mba_regs *mba; 3542362Swnj struct device *hpaddr; 3552362Swnj char *start; 356*2383Swnj int num, unit; 357*2383Swnj register struct hpst *st; 3582362Swnj 3592362Swnj num = maxfree; 3602362Swnj start = 0; 3612362Swnj unit = minor(dev) >> 3; 3622362Swnj if (unit >= NHP) { 3632362Swnj printf("bad unit\n"); 3642362Swnj return (-1); 3652362Swnj } 366*2383Swnj #define phys(a,b) ((b)((int)(a)&0x7fffffff)) 367*2383Swnj mi = phys(hpinfo[unit],struct mba_info *); 368*2383Swnj if (mi->mi_alive == 0) { 369*2383Swnj printf("dna\n"); 370*2383Swnj return (-1); 371*2383Swnj } 372*2383Swnj mba = phys(mi->mi_hd, struct mba_hd *)->mh_physmba; 373*2383Swnj mba->mba_cr = MBAINIT; 374*2383Swnj hpaddr = (struct device *)&mba->mba_drv[mi->mi_drive]; 375*2383Swnj if ((hpaddr->hpds & VV) == 0) { 376*2383Swnj hpaddr->hpcs1 = DCLR|GO; 3772362Swnj hpaddr->hpcs1 = PRESET|GO; 3782362Swnj hpaddr->hpof = FMT22; 3792362Swnj } 380*2383Swnj st = &hpst[mi->mi_type]; 381*2383Swnj if (dumplo < 0 || dumplo + num >= st->sizes[minor(dev)&07].nblocks) { 382*2383Swnj printf("oor\n"); 3832362Swnj return (-1); 3842362Swnj } 3852362Swnj while (num > 0) { 386*2383Swnj register struct pte *hpte = mba->mba_map; 3872362Swnj register int i; 388*2383Swnj int blk, cn, sn, tn; 3892362Swnj daddr_t bn; 3902362Swnj 3912362Swnj blk = num > DBSIZE ? DBSIZE : num; 3922362Swnj bn = dumplo + btop(start); 393*2383Swnj cn = bn/st->nspc + st->sizes[minor(dev)&07].cyloff; 394*2383Swnj sn = bn%st->nspc; 395*2383Swnj tn = sn/st->nsect; 396*2383Swnj sn = sn%st->nsect; 3972362Swnj hpaddr->hpdc = cn; 3982362Swnj hpaddr->hpda = (tn << 8) + sn; 3992362Swnj for (i = 0; i < blk; i++) 4002362Swnj *(int *)hpte++ = (btop(start)+i) | PG_V; 401*2383Swnj mba->mba_sr = -1; 402*2383Swnj mba->mba_bcr = -(blk*NBPG); 403*2383Swnj mba->mba_var = 0; 4042362Swnj hpaddr->hpcs1 = WCOM | GO; 4052362Swnj while ((hpaddr->hpds & DRY) == 0) 4062362Swnj ; 4072362Swnj if (hpaddr->hpds&ERR) { 408*2383Swnj printf("dskerr: (%d,%d,%d) ds=%x er=%x\n", 4092362Swnj cn, tn, sn, hpaddr->hpds, hpaddr->hper1); 4102362Swnj return (-1); 4112362Swnj } 4122362Swnj start += blk*NBPG; 4132362Swnj num -= blk; 4142362Swnj } 4152362Swnj return (0); 4162362Swnj } 417*2383Swnj 418*2383Swnj hpdkinit() 419*2383Swnj { 420*2383Swnj /* I don't really care what this does .. kre */ 421*2383Swnj } 4221565Sbill #endif 423