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