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