1 /* hp.c 4.4 83/01/23 */ 2 3 /* 4 * RP??/RM?? disk driver 5 * with ECC handling and bad block forwarding. 6 * Also supports header io operations and 7 * commands to write check header and data. 8 */ 9 10 #include "../h/param.h" 11 #include "../h/inode.h" 12 #include "../h/fs.h" 13 #include "../h/dkbad.h" 14 15 #include "../vax/pte.h" 16 #include "../vaxmba/hpreg.h" 17 #include "../vaxmba/mbareg.h" 18 19 #include "saio.h" 20 #include "savax.h" 21 22 #define MASKREG(reg) ((reg)&0xffff) 23 24 #define MAXBADDESC 126 25 #define SECTSIZ 512 /* sector size in bytes */ 26 #define HDRSIZ 4 /* number of bytes in sector header */ 27 #define MAXECC 5 /* the maximum number of bad bits accepted in 28 * an ecc error when F_ECCLM is set */ 29 30 char hp_type[MAXNMBA*8] = { 0 }; 31 32 /* THIS SHOULD BE READ IN OFF THE PACK, PER DRIVE */ 33 short hp6_off[8] = { 0, 38, 0, -1, -1, -1, 118, -1 }; 34 short rm3_off[8] = { 0, 100, 0, -1, -1, -1, 310, -1 }; 35 short rm5_off[8] = { 0, 27, 0, 562, 589, 681, 562, 82 }; 36 short rm80_off[8] = { 0, 37, 0, -1, -1, -1, 115, 305 }; 37 short hp7_off[8] = { 0, 10, 0, 330, 340, 500, 330, 50 }; 38 short ml_off[8] = { 0, -1, -1, -1, -1, -1, -1, -1 }; 39 short si9775_off[8] = { 0, 13, 0, -1, -1, -1, 40, 441 }; 40 short si9730_off[8] = { 0, 50, 0, -1, -1, -1, -1, 155 }; 41 short hpam_off[8] = { 0, 32, 0, 668, 723, 778, 668, 98 }; 42 /* END SHOULD BE READ IN */ 43 44 short hptypes[] = 45 { MBDT_RM03, MBDT_RM05, MBDT_RP06, MBDT_RM80, MBDT_RP05, MBDT_RP07, 46 MBDT_ML11A, MBDT_ML11B, -1/*9755*/, -1/*9730*/, -1/*Capr*/, MBDT_RM02, 0}; 47 48 #define RP06 (hptypes[UNITTODRIVE(unit)] <= MBDT_RP06) 49 #define ML11 (hptypes[UNITTODRIVE(unit)] <= MBDT_ML11A) 50 #define RM80 (hptypes[UNITTODRIVE(unit)] <= MBDT_RM80) 51 52 u_char hp_offset[16] = { 53 HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 54 HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 55 HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 56 0, 0, 0, 0, 57 }; 58 59 struct st hpst[] = { 60 32, 5, 32*5, 823, rm3_off, /* RM03 */ 61 32, 19, 32*19, 823, rm5_off, /* RM05 */ 62 22, 19, 22*19, 815, hp6_off, /* RP06 */ 63 31, 14, 31*14, 559, rm80_off, /* RM80 */ 64 22, 19, 22*19, 411, hp6_off, /* RP06 */ 65 50, 32, 50*32, 630, hp7_off, /* RP07 */ 66 1, 1, 1, 1, ml_off, /* ML11A */ 67 1, 1, 1, 1, ml_off, /* ML11B */ 68 32, 40, 32*40, 843, si9775_off, /* 9775 */ 69 32, 10, 32*10, 823, si9730_off, /* 9730 */ 70 32, 16, 32*16, 1024, hpam_off, /* AMPEX capricorn */ 71 1, 1, 1, 1, 0, /* rm02 - not used */ 72 }; 73 struct dkbad hpbad[MAXNMBA*8]; 74 int sectsiz; 75 76 hpopen(io) 77 register struct iob *io; 78 { 79 register unit = io->i_unit; 80 struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 81 register struct st *st; 82 83 mbainit(UNITTOMBA(unit)); 84 if (hp_type[unit] == 0) { 85 register type = hpaddr->hpdt & MBDT_TYPE; 86 register int i; 87 struct iob tio; 88 89 for (i = 0; hptypes[i]; i++) 90 if (hptypes[i] == type) 91 goto found; 92 _stop("unknown drive type"); 93 found: 94 switch (i) { 95 case 0: case 1: { /* rm03 or rm05 */ 96 register hpsn = hpaddr->hpsn; 97 98 if ((hpsn & SIMB_LU) != unit) 99 break; 100 switch ((hpsn & SIMB_MB) &~ (SIMB_S6|SIRM03|SIRM05)) { 101 case SI9775D: 102 i = 8; /* si9775 */ 103 break; 104 case SI9730D: 105 i = 9; /* si9730 */ 106 break; 107 case SI9766: 108 i = 1; /* rm05 */ 109 hpaddr->hpcs1 = HP_RECAL|HP_GO; 110 DELAY(100000); 111 break; 112 case SI9762: 113 i = 0; /* rm03 */ 114 break; 115 } 116 break; 117 } 118 119 case 11: /* rm02 */ 120 hpaddr->hpcs1 = HP_NOP; 121 hpaddr->hphr = HPHR_MAXTRAK; 122 if (MASKREG(hpaddr->hphr) == 15) 123 i = 10; /* ampex capricorn */ 124 else 125 i = 0; /* rm03 */ 126 break; 127 128 case 6: case 7: /* ml11a ml11b */ 129 i = 6; /* ml11a */ 130 break; 131 } 132 hp_type[unit] = i; 133 /* 134 * Read in the bad sector table: 135 * copy the contents of the io structure 136 * to tio for use during the bb pointer 137 * read operation. 138 */ 139 st = &hpst[hp_type[unit]]; 140 tio = *io; 141 tio.i_bn = st->nspc * st->ncyl - st->nsect; 142 tio.i_ma = (char *)&hpbad[tio.i_unit]; 143 tio.i_cc = sizeof (hpbad); 144 tio.i_flgs |= F_RDDATA; 145 for (i = 0; i < 5; i++) { 146 if (hpstrategy(&tio, READ) == sizeof (hpbad)) 147 break; 148 tio.i_bn += 2; 149 } 150 if (i == 5) { 151 printf("Unable to read bad sector table\n"); 152 for (i = 0; i < MAXBADDESC; i++) { 153 hpbad[unit].bt_bad[i].bt_cyl = -1; 154 hpbad[unit].bt_bad[i].bt_trksec = -1; 155 } 156 } 157 } 158 if (io->i_boff < 0 || io->i_boff > 7 || 159 st->off[io->i_boff]== -1) 160 _stop("hp bad minor"); 161 io->i_boff = st->off[io->i_boff] * st->nspc; 162 } 163 164 hpstrategy(io, func) 165 register struct iob *io; 166 { 167 register unit = io->i_unit; 168 struct mba_regs *mba = mbamba(unit); 169 daddr_t bn; 170 struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 171 struct st *st = &hpst[hp_type[unit]]; 172 int cn, tn, sn, bytecnt, bytesleft; 173 daddr_t startblock; 174 char *membase; 175 int er1, er2, hprecal; 176 177 sectsiz = SECTSIZ; 178 if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0) 179 sectsiz += HDRSIZ; 180 if ((hpaddr->hpds & HPDS_VV) == 0) { 181 hpaddr->hpcs1 = HP_DCLR|HP_GO; 182 hpaddr->hpcs1 = HP_PRESET|HP_GO; 183 if (hp_type[unit] != 6) /* any but ml11 */ 184 hpaddr->hpof = HPOF_FMT22; 185 } 186 io->i_errcnt = 0; 187 bytecnt = io->i_cc; 188 membase = io->i_ma; 189 startblock = io->i_bn; 190 hprecal = 0; 191 readmore: 192 bn = io->i_bn; 193 cn = bn/st->nspc; 194 sn = bn%st->nspc; 195 tn = sn/st->nsect; 196 sn = sn%st->nsect; 197 198 while ((hpaddr->hpds & HPDS_DRY) == 0) 199 ; 200 if (hp_type[unit] == 6) /* ml11 */ 201 hpaddr->hpda = bn; 202 else { 203 hpaddr->hpdc = cn; 204 hpaddr->hpda = (tn << 8) + sn; 205 } 206 if (mbastart(io, func) != 0) /* start transfer */ 207 return (-1); 208 209 while ((hpaddr->hpds & HPDS_DRY) == 0) 210 ; 211 if (((hpaddr->hpds&HPDS_ERR) | (mba->mba_sr&MBSR_EBITS)) == 0 ) 212 return(bytecnt); 213 214 /* ------- error handling ------- */ 215 216 if (bytesleft = MASKREG(mba->mba_bcr>>16)) 217 bytesleft |= 0xffff0000; /* sign ext */ 218 bn = io->i_bn + (io->i_cc + bytesleft)/sectsiz; 219 cn = bn/st->nspc; 220 sn = bn%st->nspc; 221 tn = sn/st->nsect; 222 sn = sn%st->nsect; 223 er1 = MASKREG(hpaddr->hper1); 224 er2 = MASKREG(hpaddr->hper2); 225 #ifdef HPDEBUG 226 printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", 227 cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 228 printf("er1=%b er2=%b", 229 er1, HPER1_BITS, 230 er2, HPER2_BITS); 231 printf("\n"); 232 #endif 233 if (er1 & HPER1_HCRC) { 234 er1 &= ~(HPER1_HCE|HPER1_FER); 235 er2 &= ~HPER2_BSE; 236 } 237 if (er1&HPER1_WLE) { 238 printf("hp%d: write locked\n", unit); 239 return(-1); 240 } else if ((er1&0xffff) == HPER1_FER && RP06) { 241 goto badsect; 242 243 } else if (++io->i_errcnt > 27 || 244 er1 & HPER1_HARD || 245 (!ML11 && (er2 & HPER2_HARD))) { 246 hard0: 247 io->i_error = EHER; 248 if ((mba->mba_sr & (MBSR_WCKUP | MBSR_WCKLWR)) != 0) 249 io->i_error = EWCK; 250 hard: 251 io->i_errblk = bn; 252 printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", 253 cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 254 printf("er1=%b er2=%b", 255 er1, HPER1_BITS, 256 er2, HPER2_BITS); 257 if (hpaddr->hpmr) 258 printf(" mr=%o", hpaddr->hpmr&0xffff); 259 if (hpaddr->hpmr2) 260 printf(" mr2=%o", hpaddr->hpmr2&0xffff); 261 printf("\n"); 262 return(-1); 263 264 } else if ((er2 & HPER2_BSE) && !ML11) { 265 badsect: 266 if ((io->i_flgs & F_NBSF) != 0) { 267 io->i_error = EBSE; 268 goto hard; 269 } 270 if (hpecc(io, BSE) == 0) 271 goto success; 272 else { 273 io->i_error = EBSE; 274 goto hard; 275 } 276 } else if (RM80 && er2&HPER2_SSE) { 277 /* skip sector error */ 278 (void) hpecc(io, SSE); 279 startblock++; /* since one sector was skipped */ 280 goto success; 281 } else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) { 282 if ( hpecc(io, ECC) == 0) 283 goto success; 284 else { 285 io->i_error = EECC; 286 return(1); 287 } 288 } 289 290 if (ML11 && (io->i_errcnt >= 16)) 291 goto hard0; 292 293 /* fall thru to retry */ 294 295 hpaddr->hpcs1 = HP_DCLR|HP_GO; 296 while ((hpaddr->hpds & HPDS_DRY) == 0) 297 ; 298 if (((io->i_errcnt&07) == 4) ) { 299 hpaddr->hpcs1 = HP_RECAL|HP_GO; 300 hprecal = 1; 301 goto try_again; 302 } 303 switch (hprecal) { 304 305 case 1: 306 hpaddr->hpdc = cn; 307 hpaddr->hpcs1 = HP_SEEK|HP_GO; 308 hprecal++; 309 goto try_again; 310 case 2: 311 if (io->i_errcnt < 16 || (io->i_flgs & F_READ) == 0) 312 goto donerecal; 313 hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22; 314 hpaddr->hpcs1 = HP_OFFSET|HP_GO; 315 hprecal++; 316 goto try_again; 317 donerecal: 318 case 3: 319 hprecal = 0; 320 goto try_again; 321 } 322 if (io->i_errcnt >= 16) { 323 hpaddr->hpcs1 = HP_RTC|HP_GO; 324 while (hpaddr->hpds & HPDS_PIP) 325 ; 326 } 327 goto try_again; 328 success: /* continue with the next block */ 329 bn++; 330 if ((bn-startblock) * sectsiz < bytecnt) { 331 332 try_again: /* re-read same block */ 333 io->i_bn = bn; 334 mba->mba_sr = -1; 335 io->i_ma = membase + (io->i_bn - startblock)*sectsiz; 336 io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz; 337 #ifdef HPDEBUG 338 printf("restart: bl %d, byte %d, mem 0x%x hprecal %d\n", 339 io->i_bn, io->i_cc, io->i_ma, hprecal); 340 #endif 341 goto readmore; 342 } 343 return (bytecnt); 344 } 345 hpecc(io, flag) 346 register struct iob *io; 347 int flag; 348 { 349 register unit = io->i_unit; 350 register struct mba_regs *mbp = mbamba(unit); 351 register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit); 352 register struct st *st = &hpst[hp_type[unit]]; 353 int npf; 354 int bn, cn, tn, sn; 355 int bcr, tad; 356 357 if (bcr = MASKREG(mbp->mba_bcr>>16)) 358 bcr |= 0xffff0000; /* sxt */ 359 npf = (bcr + io->i_cc)/sectsiz; /* number of sectors read */ 360 bn = io->i_bn + npf; 361 switch (flag) { 362 case ECC: 363 { 364 register int i; 365 caddr_t addr; 366 int bit, byte, mask, ecccnt = 0; 367 368 printf("hp%d: soft ecc sn%d\n", unit, bn); 369 mask = MASKREG(rp->hpec2); 370 i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 371 bit = i&07; 372 i = (i&~07)>>3; 373 byte = i; 374 rp->hpcs1 = HP_DCLR | HP_GO; 375 while (i <sectsiz && npf*sectsiz + i < io->i_cc && bit > -11) { 376 addr = io->i_ma + (npf*sectsiz) + byte; 377 #ifdef HPECCDEBUG 378 printf("addr %x old:%x ",addr, (*addr&0xff)); 379 #endif 380 if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) 381 *addr ^= (mask << bit); /* don't 'correct' mem- 382 * ory during Wcheck */ 383 #ifdef HPECCDEBUG 384 printf("new:%x\n",(*addr&0xff)); 385 #endif 386 byte++; 387 i++; 388 bit -= 8; 389 if ((ecccnt++>=MAXECC) && ((io->i_flgs&F_ECCLM) != 0)) 390 return(1); 391 } 392 return(0); 393 } 394 395 case SSE: /* skip sector error */ 396 /* set skip-sector-inhibit and read next sector */ 397 rp->hpcs1 = HP_DCLR | HP_GO; 398 while(rp->hpds & HPDS_DRY == 0) 399 ; /* avoid RMR error */ 400 rp->hpof |= HPOF_SSEI; 401 return(0); 402 403 #ifndef NOBADSECT 404 case BSE: 405 #ifdef HPDEBUG 406 printf("hpecc: BSE @ bn %d\n", bn); 407 #endif 408 rp->hpcs1 = HP_DCLR | HP_GO; 409 bcr += sectsiz; 410 tad = rp->hpda; 411 if ((bn = isbad(&hpbad[unit], bn/st->nspc,tad>>8,tad&0x7f)) < 0) 412 return(1); 413 bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 414 cn = bn/st->nspc; 415 sn = bn%st->nspc; 416 tn = sn/st->nsect; 417 sn %= st->nsect; 418 io->i_cc = -sectsiz; 419 io->i_ma += ((io->i_bn + npf -1)*sectsiz); 420 #ifdef HPDEBUG 421 printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 422 #endif 423 rp->hpdc = cn; 424 rp->hpda = (tn<<8) + sn; 425 mbp->mba_sr = -1; 426 mbastart(io,io->i_flgs); 427 io->i_errcnt = 0; /* error has been corrected */ 428 if (rp->hpds&HPDS_ERR) 429 return(1); 430 else 431 return(0); 432 } 433 } 434 /*ARGSUSED*/ 435 hpioctl(io, cmd, arg) 436 struct iob *io; 437 int cmd; 438 caddr_t arg; 439 { 440 441 struct st *st = &hpst[hp_type[io->i_unit]], *tmp; 442 struct mba_drv *drv = mbadrv(io->i_unit); 443 444 switch(cmd) { 445 446 case SAIODEVDATA: 447 if ((drv->mbd_dt&MBDT_TAP) == 0) { 448 tmp = (struct st *)arg; 449 *tmp = *st; 450 return(0); 451 } 452 else 453 return(ECMD); 454 455 default: 456 return (ECMD); 457 } 458 } 459 460