1*106Sbill /* hp.c 3.2 10/14/12 */ 221Sbill 321Sbill /* 421Sbill * RP04/RP06/RM03 disk driver 521Sbill */ 621Sbill 721Sbill #include "../h/param.h" 821Sbill #include "../h/systm.h" 921Sbill #include "../h/buf.h" 1021Sbill #include "../h/conf.h" 1121Sbill #include "../h/dir.h" 1221Sbill #include "../h/user.h" 1321Sbill #include "../h/map.h" 1421Sbill #include "../h/mba.h" 1521Sbill #include "../h/mtpr.h" 1621Sbill #include "../h/pte.h" 1721Sbill 1821Sbill #define DK_N 0 1921Sbill 2021Sbill struct device 2121Sbill { 2221Sbill int hpcs1; /* control and Status register 1 */ 2321Sbill int hpds; /* Drive Status */ 2421Sbill int hper1; /* Error register 1 */ 2521Sbill int hpmr; /* Maintenance */ 2621Sbill int hpas; /* Attention Summary */ 2721Sbill int hpda; /* Desired address register */ 2821Sbill int hpdt; /* Drive type */ 2921Sbill int hpla; /* Look ahead */ 3021Sbill int hpsn; /* serial number */ 3121Sbill int hpof; /* Offset register */ 3221Sbill int hpdc; /* Desired Cylinder address register */ 3321Sbill int hpcc; /* Current Cylinder */ 3421Sbill int hper2; /* Error register 2 */ 3521Sbill int hper3; /* Error register 3 */ 3621Sbill int hpec1; /* Burst error bit position */ 3721Sbill int hpec2; /* Burst error bit pattern */ 3821Sbill }; 3921Sbill 4021Sbill #define HPADDR ((struct device *)(MBA0 + MBA_ERB)) 4121Sbill #define NHP 1 4221Sbill #define RP 022 4321Sbill #define RM 024 4421Sbill #define NSECT 22 4521Sbill #define NTRAC 19 4621Sbill #define NRMSECT 32 4721Sbill #define NRMTRAC 5 4821Sbill #define SDIST 2 4921Sbill #define RDIST 6 5021Sbill 5121Sbill struct size 5221Sbill { 5321Sbill daddr_t nblocks; 5421Sbill int cyloff; 5521Sbill } hp_sizes[8] = 5621Sbill { 5721Sbill 15884, 0, /* cyl 0 thru 37 */ 5821Sbill 33440, 38, /* cyl 38 thru 117 */ 5921Sbill 8360, 98, /* cyl 98 thru 117 */ 6021Sbill #ifdef ERNIE 6121Sbill 15884, 118, /* cyl 118 thru 155 */ 6221Sbill 66880, 156, /* cyl 156 thru 315 */ 6321Sbill 0, 0, 6421Sbill 291346, 118, /* cyl 118 thru 814, (like distrib) */ 6521Sbill 208582, 316, /* cyl 316 thru 814 */ 6621Sbill #else 6721Sbill 0, 0, 6821Sbill 0, 0, 6921Sbill 0, 0, 7021Sbill 291346, 118, /* cyl 118 thru 814 */ 7121Sbill 0, 0, 7221Sbill #endif 7321Sbill }, rm_sizes[8] = { 7421Sbill 15884, 0, /* cyl 0 thru 99 */ 7521Sbill 33440, 100, /* cyl 100 thru 309 */ 7621Sbill 0, 0, 7721Sbill 0, 0, 7821Sbill 0, 0, 7921Sbill 0, 0, 8021Sbill 82080, 310, /* cyl 310 thru 822 */ 8121Sbill 0, 0, 8221Sbill }; 8321Sbill 8421Sbill #define P400 020 8521Sbill #define M400 0220 8621Sbill #define P800 040 8721Sbill #define M800 0240 8821Sbill #define P1200 060 8921Sbill #define M1200 0260 9021Sbill int hp_offset[16] = 9121Sbill { 9221Sbill P400, M400, P400, M400, 9321Sbill P800, M800, P800, M800, 9421Sbill P1200, M1200, P1200, M1200, 9521Sbill 0, 0, 0, 0, 9621Sbill }; 9721Sbill 9821Sbill struct buf hptab; 9921Sbill struct buf rhpbuf; 10021Sbill struct buf hputab[NHP]; 10121Sbill char hp_type[NHP]; /* drive type */ 10221Sbill 10321Sbill #define GO 01 10421Sbill #define PRESET 020 10521Sbill #define RTC 016 10621Sbill #define OFFSET 014 10721Sbill #define SEARCH 030 10821Sbill #define RECAL 06 10921Sbill #define DCLR 010 11021Sbill #define WCOM 060 11121Sbill #define RCOM 070 11221Sbill 11321Sbill #define IE 0100 11421Sbill #define PIP 020000 11521Sbill #define DRY 0200 11621Sbill #define ERR 040000 11721Sbill #define TRE 040000 11821Sbill #define DCK 0100000 11921Sbill #define WLE 04000 12021Sbill #define ECH 0100 12121Sbill #define VV 0100 12221Sbill #define DPR 0400 12321Sbill #define MOL 010000 12421Sbill #define FMT22 010000 12521Sbill 12621Sbill #define b_cylin b_resid 12721Sbill 12821Sbill #ifdef INTRLVE 12921Sbill daddr_t dkblock(); 13021Sbill #endif 13121Sbill 13221Sbill hpstrategy(bp) 13321Sbill register struct buf *bp; 13421Sbill { 13521Sbill register struct buf *dp; 13621Sbill register unit, xunit, nspc; 13721Sbill long sz, bn; 13821Sbill struct size *sizes; 13921Sbill 14021Sbill xunit = minor(bp->b_dev) & 077; 14121Sbill sz = bp->b_bcount; 14221Sbill sz = (sz+511) >> 9; 14321Sbill unit = dkunit(bp); 14421Sbill if (hp_type[unit] == 0) { 14521Sbill struct device *hpaddr; 14621Sbill 14721Sbill /* determine device type */ 14821Sbill hpaddr = (struct device *)((int*)HPADDR + 32*unit); 14921Sbill hp_type[unit] = hpaddr->hpdt; 15021Sbill } 15121Sbill if (hp_type[unit] == RM) { 15221Sbill sizes = rm_sizes; 15321Sbill nspc = NRMSECT*NRMTRAC; 15421Sbill } else { 15521Sbill sizes = hp_sizes; 15621Sbill nspc = NSECT*NTRAC; 15721Sbill } 15821Sbill if (unit >= NHP || 15921Sbill bp->b_blkno < 0 || 16021Sbill (bn = dkblock(bp))+sz > sizes[xunit&07].nblocks) { 16121Sbill bp->b_flags |= B_ERROR; 16221Sbill iodone(bp); 16321Sbill return; 16421Sbill } 16521Sbill bp->b_cylin = bn/nspc + sizes[xunit&07].cyloff; 16621Sbill dp = &hputab[unit]; 16721Sbill VOID spl5(); 16821Sbill disksort(dp, bp); 16921Sbill if (dp->b_active == 0) { 17021Sbill hpustart(unit); 17121Sbill if(hptab.b_active == 0) 17221Sbill hpstart(); 17321Sbill } 17421Sbill VOID spl0(); 17521Sbill } 17621Sbill 17721Sbill hpustart(unit) 17821Sbill register unit; 17921Sbill { 18021Sbill register struct buf *bp, *dp; 18121Sbill register struct device *hpaddr; 18221Sbill daddr_t bn; 18321Sbill int sn, cn, csn; 18421Sbill 18521Sbill ((struct mba_regs *)MBA0)->mba_cr |= MBAIE; 18621Sbill HPADDR->hpas = 1<<unit; 18721Sbill 18821Sbill if(unit >= NHP) 18921Sbill return; 19021Sbill /* 19121Sbill dk_busy &= ~(1<<(unit+DK_N)); 19221Sbill */ 19321Sbill dp = &hputab[unit]; 19421Sbill if((bp=dp->b_actf) == NULL) 19521Sbill return; 19621Sbill hpaddr = (struct device *)((int *)HPADDR + 32*unit); 19721Sbill if((hpaddr->hpds & VV) == 0) { 19821Sbill hpaddr->hpcs1 = PRESET|GO; 19921Sbill hpaddr->hpof = FMT22; 20021Sbill } 20121Sbill if(dp->b_active) 20221Sbill goto done; 20321Sbill dp->b_active++; 20421Sbill if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) 20521Sbill goto done; 20621Sbill 20721Sbill bn = dkblock(bp); 20821Sbill cn = bp->b_cylin; 20921Sbill if(hp_type[unit] == RM) { 21021Sbill sn = bn%(NRMSECT*NRMTRAC); 21121Sbill sn = (sn+NRMSECT-SDIST)%NRMSECT; 21221Sbill } else { 21321Sbill sn = bn%(NSECT*NTRAC); 21421Sbill sn = (sn+NSECT-SDIST)%NSECT; 21521Sbill } 21621Sbill 21721Sbill if(cn - (hpaddr->hpdc & 0xffff)) 21821Sbill goto search; 21921Sbill csn = ((hpaddr->hpla & 0xffff)>>6) - sn + SDIST - 1; 22021Sbill if(csn < 0) 22121Sbill csn += NSECT; 22221Sbill if(csn > NSECT-RDIST) 22321Sbill goto done; 22421Sbill 22521Sbill search: 22621Sbill hpaddr->hpdc = cn; 22721Sbill hpaddr->hpda = sn; 22821Sbill hpaddr->hpcs1 = SEARCH|GO; 22921Sbill /* 23021Sbill unit += DK_N; 23121Sbill dk_busy |= 1<<unit; 23221Sbill dk_numb[unit] += 1; 23321Sbill */ 23421Sbill return; 23521Sbill 23621Sbill done: 23721Sbill dp->b_forw = NULL; 23821Sbill if(hptab.b_actf == NULL) 23921Sbill hptab.b_actf = dp; else 24021Sbill hptab.b_actl->b_forw = dp; 24121Sbill hptab.b_actl = dp; 24221Sbill } 24321Sbill 24421Sbill hpstart() 24521Sbill { 24621Sbill register struct buf *bp, *dp; 24721Sbill register unit; 24821Sbill register struct device *hpaddr; 24921Sbill daddr_t bn; 25021Sbill int dn, sn, tn, cn, nspc, ns; 25121Sbill 25221Sbill loop: 25321Sbill if ((dp = hptab.b_actf) == NULL) 25421Sbill return; 25521Sbill if ((bp = dp->b_actf) == NULL) { 25621Sbill hptab.b_actf = dp->b_forw; 25721Sbill goto loop; 25821Sbill } 25921Sbill hptab.b_active++; 26021Sbill unit = minor(bp->b_dev) & 077; 26121Sbill dn = dkunit(bp); 26221Sbill bn = dkblock(bp); 26321Sbill if (hp_type[dn] == RM) { 26421Sbill nspc = NRMSECT*NRMTRAC; 26521Sbill ns = NRMSECT; 26621Sbill cn = rm_sizes[unit&07].cyloff; 26721Sbill } else { 26821Sbill nspc = NSECT*NTRAC; 26921Sbill ns = NSECT; 27021Sbill cn = hp_sizes[unit&07].cyloff; 27121Sbill } 27221Sbill cn += bn/nspc; 27321Sbill sn = bn%nspc; 27421Sbill tn = sn/ns; 27521Sbill sn = sn%ns; 27621Sbill 27721Sbill hpaddr = (struct device *)((int *)HPADDR + 32*dn); 27821Sbill if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) { 27921Sbill hptab.b_active = 0; 28021Sbill hptab.b_errcnt = 0; 28121Sbill dp->b_actf = bp->av_forw; 28221Sbill bp->b_flags |= B_ERROR; 28321Sbill iodone(bp); 28421Sbill goto loop; 28521Sbill } 28621Sbill if(hptab.b_errcnt >= 16) { 28721Sbill hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22; 28821Sbill ((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE; 28921Sbill hpaddr->hpcs1 = OFFSET|GO; 29021Sbill while(hpaddr->hpds & PIP) 29121Sbill ; 29221Sbill ((struct mba_regs *)MBA0)->mba_cr |= MBAIE; 29321Sbill } 29421Sbill hpaddr->hpdc = cn; 29521Sbill hpaddr->hpda = (tn << 8) + sn; 29621Sbill mbastart(bp, (int *)hpaddr); 29721Sbill 29821Sbill dk_busy |= 1<<(DK_N /*+NHP*/); 29921Sbill dk_numb[DK_N /*+NHP*/] += 1; 30021Sbill unit = bp->b_bcount>>6; 30121Sbill dk_wds[DK_N /*+NHP*/] += unit; 30221Sbill } 30321Sbill 30421Sbill hpintr(mbastat, as) 30521Sbill { 30621Sbill register struct buf *bp, *dp; 30721Sbill register unit; 30821Sbill register struct device *hpaddr; 30921Sbill 31021Sbill if(hptab.b_active) { 31121Sbill dk_busy &= ~(1<<(DK_N /*+NHP*/)); 31221Sbill dp = hptab.b_actf; 31321Sbill bp = dp->b_actf; 31421Sbill unit = dkunit(bp); 31521Sbill hpaddr = (struct device *)((int *)HPADDR + 32*unit); 31621Sbill if (hpaddr->hpds & ERR || mbastat & MBAEBITS) { /* error bit */ 31721Sbill while((hpaddr->hpds & DRY) == 0) 31821Sbill ; 31921Sbill if(++hptab.b_errcnt > 28 || hpaddr->hper1&WLE) 32021Sbill bp->b_flags |= B_ERROR; else 32121Sbill hptab.b_active = 0; 32221Sbill if(hptab.b_errcnt > 27) 32321Sbill deverror(bp, mbastat, hpaddr->hper1); 32421Sbill if ((hpaddr->hper1&0xffff) == DCK) { 32521Sbill if (hpecc(hpaddr, bp)) 32621Sbill return; 32721Sbill } 32821Sbill hpaddr->hpcs1 = DCLR|GO; 32921Sbill if((hptab.b_errcnt&07) == 4) { 33021Sbill ((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE; 33121Sbill hpaddr->hpcs1 = RECAL|GO; 33221Sbill while(hpaddr->hpds & PIP) 33321Sbill ; 33421Sbill ((struct mba_regs *)MBA0)->mba_cr |= MBAIE; 33521Sbill } 33621Sbill } 33721Sbill if(hptab.b_active) { 33821Sbill if(hptab.b_errcnt) { 33921Sbill ((struct mba_regs *)MBA0)->mba_cr &= ~MBAIE; 34021Sbill hpaddr->hpcs1 = RTC|GO; 34121Sbill while(hpaddr->hpds & PIP) 34221Sbill ; 34321Sbill ((struct mba_regs *)MBA0)->mba_cr |= MBAIE; 34421Sbill } 34521Sbill hptab.b_active = 0; 34621Sbill hptab.b_errcnt = 0; 34721Sbill hptab.b_actf = dp->b_forw; 34821Sbill dp->b_active = 0; 34921Sbill dp->b_errcnt = 0; 35021Sbill dp->b_actf = bp->av_forw; 35121Sbill bp->b_resid = -(((struct mba_regs *)MBA0)->mba_bcr) & 0xffff; 35221Sbill iodone(bp); 35321Sbill if(dp->b_actf) 35421Sbill hpustart(unit); 35521Sbill } 35621Sbill as &= ~(1<<unit); 35721Sbill } else { 35821Sbill if(as == 0) 35921Sbill ((struct mba_regs *)MBA0)->mba_cr |= MBAIE; 36021Sbill } 36121Sbill for(unit=0; unit<NHP; unit++) 36221Sbill if(as & (1<<unit)) 36321Sbill hpustart(unit); 36421Sbill hpstart(); 36521Sbill } 36621Sbill 36721Sbill hpread(dev) 36821Sbill { 36921Sbill 37021Sbill physio(hpstrategy, &rhpbuf, dev, B_READ, minphys); 37121Sbill } 37221Sbill 37321Sbill hpwrite(dev) 37421Sbill { 37521Sbill 37621Sbill physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys); 37721Sbill } 37821Sbill 37921Sbill hpecc(rp, bp) 38021Sbill register struct device *rp; 38121Sbill register struct buf *bp; 38221Sbill { 38321Sbill register i; 38421Sbill register b, n, map, mix; 38521Sbill register char *cp; 38621Sbill register mask; 38721Sbill short piget(); 388*106Sbill extern char buffers[NBUF][BSIZE]; 38921Sbill 39021Sbill b = (((((struct mba_regs *)MBA0)->mba_bcr&0xffff) + 39121Sbill (bp->b_bcount) - 1)>>9)&0177; 39221Sbill printf("%D ", bp->b_blkno+b); 39321Sbill prdev("ECC", bp->b_dev); 39421Sbill mask = rp->hpec2&0xffff; 39521Sbill if (mask == 0) { 39621Sbill rp->hpof = FMT22; 39721Sbill return(0); 39821Sbill } 39921Sbill i = (rp->hpec1&0xffff) - 1; 40021Sbill n = i&017; 40121Sbill i = (i&~017)>>3; 40221Sbill if (bp->b_flags&B_PHYS) 40321Sbill map = 128 + b; 40421Sbill else 40521Sbill map = ((bp->b_un.b_addr - (char *)buffers)>>9) + b; 40621Sbill mix = i + ((int)bp->b_un.b_addr&0x1ff); 40721Sbill i += b<<9; 40821Sbill if ( i < bp->b_bcount) { 40921Sbill cp = (char *)((((int *)MBA0_MAP)[map+(mix>>9)]&0x1fffff)<<9)+(mix&0x1ff); 41021Sbill piput((int)cp,piget((int)cp)^(mask<<n)); 41121Sbill } 41221Sbill mix += 2; 41321Sbill i += 2; 41421Sbill if (i < bp->b_bcount) { 41521Sbill cp = (char *)((((int *)MBA0_MAP)[map+(mix>>9)]&0x1fffff)<<9)+(mix&0x1ff); 41621Sbill piput((int)cp,piget((int)cp)^(mask>>(16-n))); 41721Sbill } 41821Sbill hptab.b_active++; 41921Sbill if (((struct mba_regs *)MBA0)->mba_bcr) { 42021Sbill i = bp->b_blkno%(NSECT*NTRAC); 42121Sbill i = ((i/NSECT)<<8)+(i%NSECT); 42221Sbill i = NSECT*(i>>8) + (i&0377) + b + 1; 42321Sbill if (i >= NSECT*NTRAC) { 42421Sbill i -= NSECT*NTRAC; 42521Sbill rp->hpdc = bp->b_cylin + 1; 42621Sbill } else 42721Sbill rp->hpdc = bp->b_cylin; 42821Sbill rp->hpda = ((i/NSECT)<<8) + (i%NSECT); 42921Sbill rp->hpcs1 = DCLR|GO; 43021Sbill ((struct mba_regs *)MBA0)->mba_sr = -1; 43121Sbill ((struct mba_regs *)MBA0)->mba_var = 43221Sbill ((map+1)<<9)|((int)bp->b_un.b_addr&0x1ff); 43321Sbill rp->hpcs1 = RCOM|GO; 43421Sbill return(1); 43521Sbill } else 43621Sbill return(0); 43721Sbill } 43821Sbill 43921Sbill short 44021Sbill piget(pad) 44121Sbill { 44221Sbill register b, savemap; 44321Sbill register short s; 44421Sbill 44521Sbill savemap = (int)mmap; 44621Sbill b = (pad>>9)&0x7fffff; 44721Sbill *(int *)mmap = b|(PG_V|PG_KR); 44821Sbill mtpr(TBIS, vmmap); 44921Sbill s = *(short *)&vmmap[pad&0x1ff]; 45021Sbill *(int *)mmap = savemap; 45121Sbill mtpr(TBIS, vmmap); 45221Sbill return(s); 45321Sbill } 45421Sbill 45521Sbill piput(pad, val) 45621Sbill { 45721Sbill register b, savemap; 45821Sbill register short *p; 45921Sbill 46021Sbill savemap = (int)mmap; 46121Sbill b = (pad>>9)&0x7fffff; 46221Sbill *(int *)mmap = b|(PG_V|PG_KW); 46321Sbill mtpr(TBIS, vmmap); 46421Sbill p = (short *)&vmmap[pad&0x1ff]; 46521Sbill *p = val; 46621Sbill *(int *)mmap = savemap; 46721Sbill mtpr(TBIS, vmmap); 46821Sbill } 469