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