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