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