1*21Sbill /* hp.c 3.1 10/14/12 */ 2*21Sbill 3*21Sbill /* 4*21Sbill * RP04/RP06/RM03 disk driver 5*21Sbill */ 6*21Sbill 7*21Sbill #include "../h/param.h" 8*21Sbill #include "../h/systm.h" 9*21Sbill #include "../h/buf.h" 10*21Sbill #include "../h/conf.h" 11*21Sbill #include "../h/dir.h" 12*21Sbill #include "../h/user.h" 13*21Sbill #include "../h/map.h" 14*21Sbill #include "../h/mba.h" 15*21Sbill #include "../h/mtpr.h" 16*21Sbill #include "../h/pte.h" 17*21Sbill 18*21Sbill #define DK_N 0 19*21Sbill 20*21Sbill struct device 21*21Sbill { 22*21Sbill int hpcs1; /* control and Status register 1 */ 23*21Sbill int hpds; /* Drive Status */ 24*21Sbill int hper1; /* Error register 1 */ 25*21Sbill int hpmr; /* Maintenance */ 26*21Sbill int hpas; /* Attention Summary */ 27*21Sbill int hpda; /* Desired address register */ 28*21Sbill int hpdt; /* Drive type */ 29*21Sbill int hpla; /* Look ahead */ 30*21Sbill int hpsn; /* serial number */ 31*21Sbill int hpof; /* Offset register */ 32*21Sbill int hpdc; /* Desired Cylinder address register */ 33*21Sbill int hpcc; /* Current Cylinder */ 34*21Sbill int hper2; /* Error register 2 */ 35*21Sbill int hper3; /* Error register 3 */ 36*21Sbill int hpec1; /* Burst error bit position */ 37*21Sbill int hpec2; /* Burst error bit pattern */ 38*21Sbill }; 39*21Sbill 40*21Sbill #define HPADDR ((struct device *)(MBA0 + MBA_ERB)) 41*21Sbill #define NHP 1 42*21Sbill #define RP 022 43*21Sbill #define RM 024 44*21Sbill #define NSECT 22 45*21Sbill #define NTRAC 19 46*21Sbill #define NRMSECT 32 47*21Sbill #define NRMTRAC 5 48*21Sbill #define SDIST 2 49*21Sbill #define RDIST 6 50*21Sbill 51*21Sbill struct size 52*21Sbill { 53*21Sbill daddr_t nblocks; 54*21Sbill int cyloff; 55*21Sbill } hp_sizes[8] = 56*21Sbill { 57*21Sbill 15884, 0, /* cyl 0 thru 37 */ 58*21Sbill 33440, 38, /* cyl 38 thru 117 */ 59*21Sbill 8360, 98, /* cyl 98 thru 117 */ 60*21Sbill #ifdef ERNIE 61*21Sbill 15884, 118, /* cyl 118 thru 155 */ 62*21Sbill 66880, 156, /* cyl 156 thru 315 */ 63*21Sbill 0, 0, 64*21Sbill 291346, 118, /* cyl 118 thru 814, (like distrib) */ 65*21Sbill 208582, 316, /* cyl 316 thru 814 */ 66*21Sbill #else 67*21Sbill 0, 0, 68*21Sbill 0, 0, 69*21Sbill 0, 0, 70*21Sbill 291346, 118, /* cyl 118 thru 814 */ 71*21Sbill 0, 0, 72*21Sbill #endif 73*21Sbill }, rm_sizes[8] = { 74*21Sbill 15884, 0, /* cyl 0 thru 99 */ 75*21Sbill 33440, 100, /* cyl 100 thru 309 */ 76*21Sbill 0, 0, 77*21Sbill 0, 0, 78*21Sbill 0, 0, 79*21Sbill 0, 0, 80*21Sbill 82080, 310, /* cyl 310 thru 822 */ 81*21Sbill 0, 0, 82*21Sbill }; 83*21Sbill 84*21Sbill #define P400 020 85*21Sbill #define M400 0220 86*21Sbill #define P800 040 87*21Sbill #define M800 0240 88*21Sbill #define P1200 060 89*21Sbill #define M1200 0260 90*21Sbill int hp_offset[16] = 91*21Sbill { 92*21Sbill P400, M400, P400, M400, 93*21Sbill P800, M800, P800, M800, 94*21Sbill P1200, M1200, P1200, M1200, 95*21Sbill 0, 0, 0, 0, 96*21Sbill }; 97*21Sbill 98*21Sbill struct buf hptab; 99*21Sbill struct buf rhpbuf; 100*21Sbill struct buf hputab[NHP]; 101*21Sbill char hp_type[NHP]; /* drive type */ 102*21Sbill 103*21Sbill #define GO 01 104*21Sbill #define PRESET 020 105*21Sbill #define RTC 016 106*21Sbill #define OFFSET 014 107*21Sbill #define SEARCH 030 108*21Sbill #define RECAL 06 109*21Sbill #define DCLR 010 110*21Sbill #define WCOM 060 111*21Sbill #define RCOM 070 112*21Sbill 113*21Sbill #define IE 0100 114*21Sbill #define PIP 020000 115*21Sbill #define DRY 0200 116*21Sbill #define ERR 040000 117*21Sbill #define TRE 040000 118*21Sbill #define DCK 0100000 119*21Sbill #define WLE 04000 120*21Sbill #define ECH 0100 121*21Sbill #define VV 0100 122*21Sbill #define DPR 0400 123*21Sbill #define MOL 010000 124*21Sbill #define FMT22 010000 125*21Sbill 126*21Sbill #define b_cylin b_resid 127*21Sbill 128*21Sbill #ifdef INTRLVE 129*21Sbill daddr_t dkblock(); 130*21Sbill #endif 131*21Sbill 132*21Sbill hpstrategy(bp) 133*21Sbill register struct buf *bp; 134*21Sbill { 135*21Sbill register struct buf *dp; 136*21Sbill register unit, xunit, nspc; 137*21Sbill long sz, bn; 138*21Sbill struct size *sizes; 139*21Sbill 140*21Sbill xunit = minor(bp->b_dev) & 077; 141*21Sbill sz = bp->b_bcount; 142*21Sbill sz = (sz+511) >> 9; 143*21Sbill unit = dkunit(bp); 144*21Sbill if (hp_type[unit] == 0) { 145*21Sbill struct device *hpaddr; 146*21Sbill 147*21Sbill /* determine device type */ 148*21Sbill hpaddr = (struct device *)((int*)HPADDR + 32*unit); 149*21Sbill hp_type[unit] = hpaddr->hpdt; 150*21Sbill } 151*21Sbill if (hp_type[unit] == RM) { 152*21Sbill sizes = rm_sizes; 153*21Sbill nspc = NRMSECT*NRMTRAC; 154*21Sbill } else { 155*21Sbill sizes = hp_sizes; 156*21Sbill nspc = NSECT*NTRAC; 157*21Sbill } 158*21Sbill if (unit >= NHP || 159*21Sbill bp->b_blkno < 0 || 160*21Sbill (bn = dkblock(bp))+sz > sizes[xunit&07].nblocks) { 161*21Sbill bp->b_flags |= B_ERROR; 162*21Sbill iodone(bp); 163*21Sbill return; 164*21Sbill } 165*21Sbill bp->b_cylin = bn/nspc + sizes[xunit&07].cyloff; 166*21Sbill dp = &hputab[unit]; 167*21Sbill VOID spl5(); 168*21Sbill disksort(dp, bp); 169*21Sbill if (dp->b_active == 0) { 170*21Sbill hpustart(unit); 171*21Sbill if(hptab.b_active == 0) 172*21Sbill hpstart(); 173*21Sbill } 174*21Sbill VOID spl0(); 175*21Sbill } 176*21Sbill 177*21Sbill hpustart(unit) 178*21Sbill register unit; 179*21Sbill { 180*21Sbill register struct buf *bp, *dp; 181*21Sbill register struct device *hpaddr; 182*21Sbill daddr_t bn; 183*21Sbill int sn, cn, csn; 184*21Sbill 185*21Sbill ((struct mba_regs *)MBA0)->mba_cr |= MBAIE; 186*21Sbill HPADDR->hpas = 1<<unit; 187*21Sbill 188*21Sbill if(unit >= NHP) 189*21Sbill return; 190*21Sbill /* 191*21Sbill dk_busy &= ~(1<<(unit+DK_N)); 192*21Sbill */ 193*21Sbill dp = &hputab[unit]; 194*21Sbill if((bp=dp->b_actf) == NULL) 195*21Sbill return; 196*21Sbill hpaddr = (struct device *)((int *)HPADDR + 32*unit); 197*21Sbill if((hpaddr->hpds & VV) == 0) { 198*21Sbill hpaddr->hpcs1 = PRESET|GO; 199*21Sbill hpaddr->hpof = FMT22; 200*21Sbill } 201*21Sbill if(dp->b_active) 202*21Sbill goto done; 203*21Sbill dp->b_active++; 204*21Sbill if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) 205*21Sbill goto done; 206*21Sbill 207*21Sbill bn = dkblock(bp); 208*21Sbill cn = bp->b_cylin; 209*21Sbill if(hp_type[unit] == RM) { 210*21Sbill sn = bn%(NRMSECT*NRMTRAC); 211*21Sbill sn = (sn+NRMSECT-SDIST)%NRMSECT; 212*21Sbill } else { 213*21Sbill sn = bn%(NSECT*NTRAC); 214*21Sbill sn = (sn+NSECT-SDIST)%NSECT; 215*21Sbill } 216*21Sbill 217*21Sbill if(cn - (hpaddr->hpdc & 0xffff)) 218*21Sbill goto search; 219*21Sbill csn = ((hpaddr->hpla & 0xffff)>>6) - sn + SDIST - 1; 220*21Sbill if(csn < 0) 221*21Sbill csn += NSECT; 222*21Sbill if(csn > NSECT-RDIST) 223*21Sbill goto done; 224*21Sbill 225*21Sbill search: 226*21Sbill hpaddr->hpdc = cn; 227*21Sbill hpaddr->hpda = sn; 228*21Sbill hpaddr->hpcs1 = SEARCH|GO; 229*21Sbill /* 230*21Sbill unit += DK_N; 231*21Sbill dk_busy |= 1<<unit; 232*21Sbill dk_numb[unit] += 1; 233*21Sbill */ 234*21Sbill return; 235*21Sbill 236*21Sbill done: 237*21Sbill dp->b_forw = NULL; 238*21Sbill if(hptab.b_actf == NULL) 239*21Sbill hptab.b_actf = dp; else 240*21Sbill hptab.b_actl->b_forw = dp; 241*21Sbill hptab.b_actl = dp; 242*21Sbill } 243*21Sbill 244*21Sbill hpstart() 245*21Sbill { 246*21Sbill register struct buf *bp, *dp; 247*21Sbill register unit; 248*21Sbill register struct device *hpaddr; 249*21Sbill daddr_t bn; 250*21Sbill int dn, sn, tn, cn, nspc, ns; 251*21Sbill 252*21Sbill loop: 253*21Sbill if ((dp = hptab.b_actf) == NULL) 254*21Sbill return; 255*21Sbill if ((bp = dp->b_actf) == NULL) { 256*21Sbill hptab.b_actf = dp->b_forw; 257*21Sbill goto loop; 258*21Sbill } 259*21Sbill hptab.b_active++; 260*21Sbill unit = minor(bp->b_dev) & 077; 261*21Sbill dn = dkunit(bp); 262*21Sbill bn = dkblock(bp); 263*21Sbill if (hp_type[dn] == RM) { 264*21Sbill nspc = NRMSECT*NRMTRAC; 265*21Sbill ns = NRMSECT; 266*21Sbill cn = rm_sizes[unit&07].cyloff; 267*21Sbill } else { 268*21Sbill nspc = NSECT*NTRAC; 269*21Sbill ns = NSECT; 270*21Sbill cn = hp_sizes[unit&07].cyloff; 271*21Sbill } 272*21Sbill cn += bn/nspc; 273*21Sbill sn = bn%nspc; 274*21Sbill tn = sn/ns; 275*21Sbill sn = sn%ns; 276*21Sbill 277*21Sbill hpaddr = (struct device *)((int *)HPADDR + 32*dn); 278*21Sbill if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) { 279*21Sbill hptab.b_active = 0; 280*21Sbill hptab.b_errcnt = 0; 281*21Sbill dp->b_actf = bp->av_forw; 282*21Sbill bp->b_flags |= B_ERROR; 283*21Sbill iodone(bp); 284*21Sbill goto loop; 285*21Sbill } 286*21Sbill if(hptab.b_errcnt >= 16) { 287*21Sbill hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22; 288*21Sbill ((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE; 289*21Sbill hpaddr->hpcs1 = OFFSET|GO; 290*21Sbill while(hpaddr->hpds & PIP) 291*21Sbill ; 292*21Sbill ((struct mba_regs *)MBA0)->mba_cr |= MBAIE; 293*21Sbill } 294*21Sbill hpaddr->hpdc = cn; 295*21Sbill hpaddr->hpda = (tn << 8) + sn; 296*21Sbill mbastart(bp, (int *)hpaddr); 297*21Sbill 298*21Sbill dk_busy |= 1<<(DK_N /*+NHP*/); 299*21Sbill dk_numb[DK_N /*+NHP*/] += 1; 300*21Sbill unit = bp->b_bcount>>6; 301*21Sbill dk_wds[DK_N /*+NHP*/] += unit; 302*21Sbill } 303*21Sbill 304*21Sbill hpintr(mbastat, as) 305*21Sbill { 306*21Sbill register struct buf *bp, *dp; 307*21Sbill register unit; 308*21Sbill register struct device *hpaddr; 309*21Sbill 310*21Sbill if(hptab.b_active) { 311*21Sbill dk_busy &= ~(1<<(DK_N /*+NHP*/)); 312*21Sbill dp = hptab.b_actf; 313*21Sbill bp = dp->b_actf; 314*21Sbill unit = dkunit(bp); 315*21Sbill hpaddr = (struct device *)((int *)HPADDR + 32*unit); 316*21Sbill if (hpaddr->hpds & ERR || mbastat & MBAEBITS) { /* error bit */ 317*21Sbill while((hpaddr->hpds & DRY) == 0) 318*21Sbill ; 319*21Sbill if(++hptab.b_errcnt > 28 || hpaddr->hper1&WLE) 320*21Sbill bp->b_flags |= B_ERROR; else 321*21Sbill hptab.b_active = 0; 322*21Sbill if(hptab.b_errcnt > 27) 323*21Sbill deverror(bp, mbastat, hpaddr->hper1); 324*21Sbill if ((hpaddr->hper1&0xffff) == DCK) { 325*21Sbill if (hpecc(hpaddr, bp)) 326*21Sbill return; 327*21Sbill } 328*21Sbill hpaddr->hpcs1 = DCLR|GO; 329*21Sbill if((hptab.b_errcnt&07) == 4) { 330*21Sbill ((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE; 331*21Sbill hpaddr->hpcs1 = RECAL|GO; 332*21Sbill while(hpaddr->hpds & PIP) 333*21Sbill ; 334*21Sbill ((struct mba_regs *)MBA0)->mba_cr |= MBAIE; 335*21Sbill } 336*21Sbill } 337*21Sbill if(hptab.b_active) { 338*21Sbill if(hptab.b_errcnt) { 339*21Sbill ((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE; 340*21Sbill hpaddr->hpcs1 = RTC|GO; 341*21Sbill while(hpaddr->hpds & PIP) 342*21Sbill ; 343*21Sbill ((struct mba_regs *)MBA0)->mba_cr |= MBAIE; 344*21Sbill } 345*21Sbill hptab.b_active = 0; 346*21Sbill hptab.b_errcnt = 0; 347*21Sbill hptab.b_actf = dp->b_forw; 348*21Sbill dp->b_active = 0; 349*21Sbill dp->b_errcnt = 0; 350*21Sbill dp->b_actf = bp->av_forw; 351*21Sbill bp->b_resid = -(((struct mba_regs *)MBA0)->mba_bcr) & 0xffff; 352*21Sbill iodone(bp); 353*21Sbill if(dp->b_actf) 354*21Sbill hpustart(unit); 355*21Sbill } 356*21Sbill as &= ~(1<<unit); 357*21Sbill } else { 358*21Sbill if(as == 0) 359*21Sbill ((struct mba_regs *)MBA0)->mba_cr |= MBAIE; 360*21Sbill } 361*21Sbill for(unit=0; unit<NHP; unit++) 362*21Sbill if(as & (1<<unit)) 363*21Sbill hpustart(unit); 364*21Sbill hpstart(); 365*21Sbill } 366*21Sbill 367*21Sbill hpread(dev) 368*21Sbill { 369*21Sbill 370*21Sbill physio(hpstrategy, &rhpbuf, dev, B_READ, minphys); 371*21Sbill } 372*21Sbill 373*21Sbill hpwrite(dev) 374*21Sbill { 375*21Sbill 376*21Sbill physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys); 377*21Sbill } 378*21Sbill 379*21Sbill hpecc(rp, bp) 380*21Sbill register struct device *rp; 381*21Sbill register struct buf *bp; 382*21Sbill { 383*21Sbill register i; 384*21Sbill register b, n, map, mix; 385*21Sbill register char *cp; 386*21Sbill register mask; 387*21Sbill short piget(); 388*21Sbill extern char buffers[][]; 389*21Sbill 390*21Sbill b = (((((struct mba_regs *)MBA0)->mba_bcr&0xffff) + 391*21Sbill (bp->b_bcount) - 1)>>9)&0177; 392*21Sbill printf("%D ", bp->b_blkno+b); 393*21Sbill prdev("ECC", bp->b_dev); 394*21Sbill mask = rp->hpec2&0xffff; 395*21Sbill if (mask == 0) { 396*21Sbill rp->hpof = FMT22; 397*21Sbill return(0); 398*21Sbill } 399*21Sbill i = (rp->hpec1&0xffff) - 1; 400*21Sbill n = i&017; 401*21Sbill i = (i&~017)>>3; 402*21Sbill if (bp->b_flags&B_PHYS) 403*21Sbill map = 128 + b; 404*21Sbill else 405*21Sbill map = ((bp->b_un.b_addr - (char *)buffers)>>9) + b; 406*21Sbill mix = i + ((int)bp->b_un.b_addr&0x1ff); 407*21Sbill i += b<<9; 408*21Sbill if ( i < bp->b_bcount) { 409*21Sbill cp = (char *)((((int *)MBA0_MAP)[map+(mix>>9)]&0x1fffff)<<9)+(mix&0x1ff); 410*21Sbill piput((int)cp,piget((int)cp)^(mask<<n)); 411*21Sbill } 412*21Sbill mix += 2; 413*21Sbill i += 2; 414*21Sbill if (i < bp->b_bcount) { 415*21Sbill cp = (char *)((((int *)MBA0_MAP)[map+(mix>>9)]&0x1fffff)<<9)+(mix&0x1ff); 416*21Sbill piput((int)cp,piget((int)cp)^(mask>>(16-n))); 417*21Sbill } 418*21Sbill hptab.b_active++; 419*21Sbill if (((struct mba_regs *)MBA0)->mba_bcr) { 420*21Sbill i = bp->b_blkno%(NSECT*NTRAC); 421*21Sbill i = ((i/NSECT)<<8)+(i%NSECT); 422*21Sbill i = NSECT*(i>>8) + (i&0377) + b + 1; 423*21Sbill if (i >= NSECT*NTRAC) { 424*21Sbill i -= NSECT*NTRAC; 425*21Sbill rp->hpdc = bp->b_cylin + 1; 426*21Sbill } else 427*21Sbill rp->hpdc = bp->b_cylin; 428*21Sbill rp->hpda = ((i/NSECT)<<8) + (i%NSECT); 429*21Sbill rp->hpcs1 = DCLR|GO; 430*21Sbill ((struct mba_regs *)MBA0)->mba_sr = -1; 431*21Sbill ((struct mba_regs *)MBA0)->mba_var = 432*21Sbill ((map+1)<<9)|((int)bp->b_un.b_addr&0x1ff); 433*21Sbill rp->hpcs1 = RCOM|GO; 434*21Sbill return(1); 435*21Sbill } else 436*21Sbill return(0); 437*21Sbill } 438*21Sbill 439*21Sbill short 440*21Sbill piget(pad) 441*21Sbill { 442*21Sbill register b, savemap; 443*21Sbill register short s; 444*21Sbill 445*21Sbill savemap = (int)mmap; 446*21Sbill b = (pad>>9)&0x7fffff; 447*21Sbill *(int *)mmap = b|(PG_V|PG_KR); 448*21Sbill mtpr(TBIS, vmmap); 449*21Sbill s = *(short *)&vmmap[pad&0x1ff]; 450*21Sbill *(int *)mmap = savemap; 451*21Sbill mtpr(TBIS, vmmap); 452*21Sbill return(s); 453*21Sbill } 454*21Sbill 455*21Sbill piput(pad, val) 456*21Sbill { 457*21Sbill register b, savemap; 458*21Sbill register short *p; 459*21Sbill 460*21Sbill savemap = (int)mmap; 461*21Sbill b = (pad>>9)&0x7fffff; 462*21Sbill *(int *)mmap = b|(PG_V|PG_KW); 463*21Sbill mtpr(TBIS, vmmap); 464*21Sbill p = (short *)&vmmap[pad&0x1ff]; 465*21Sbill *p = val; 466*21Sbill *(int *)mmap = savemap; 467*21Sbill mtpr(TBIS, vmmap); 468*21Sbill } 469