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