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