1: /*
   2:  * Copyright (c) 1982, 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)hp.c	7.1 (Berkeley) 6/5/86
   7:  */
   8: 
   9: /*
  10:  * RP??/RM?? disk driver
  11:  * with ECC handling and bad block forwarding.
  12:  * Also supports header io operations and
  13:  * commands to write check header and data.
  14:  */
  15: #include "../h/param.h"
  16: #include "../h/inode.h"
  17: #include "../h/fs.h"
  18: #include "../h/dkbad.h"
  19: 
  20: #include "../vax/pte.h"
  21: #include "../vaxmba/hpreg.h"
  22: #include "../vaxmba/mbareg.h"
  23: 
  24: #include "saio.h"
  25: #include "savax.h"
  26: 
  27: #define RETRIES     27
  28: 
  29: #define MASKREG(reg)    ((reg)&0xffff)
  30: 
  31: #define MAXBADDESC  126
  32: #define SECTSIZ     512 /* sector size in bytes */
  33: #define HDRSIZ      4   /* number of bytes in sector header */
  34: 
  35: extern  struct st hpst[];
  36: extern  short hptypes[];
  37: 
  38: #define RP06 (hptypes[sc->type] == MBDT_RP06 || hptypes[sc->type] == MBDT_RP05 \
  39:     || hptypes[sc->type] == MBDT_RP04)
  40: #define ML11 (hptypes[sc->type] == MBDT_ML11A)
  41: #define RM80 (hptypes[sc->type] == MBDT_RM80)
  42: 
  43: u_char  hp_offset[16] = {
  44:     HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
  45:     HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
  46:     HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
  47:     0, 0, 0, 0,
  48: };
  49: 
  50: struct  dkbad hpbad[MAXNMBA*8];
  51: 
  52: struct  hp_softc {
  53:     char    type;
  54:     char    gottype;
  55:     char    ssect;      /* 1 when on track w/skip sector */
  56:     char    debug;
  57: #	define    HPF_BSEDEBUG    01  /* debugging bad sector forwarding */
  58: #	define    HPF_ECCDEBUG    02  /* debugging ecc correction */
  59:     int ecclim;
  60:     int retries;
  61: } hp_softc[MAXNMBA * 8];
  62: 
  63: int sectsiz;
  64: 
  65: /*
  66:  * When awaiting command completion, don't
  67:  * hang on to the status register since
  68:  * this ties up some controllers.
  69:  */
  70: #define HPWAIT(addr) \
  71:     while ((((addr)->hpds)&HPDS_DRY)==0) DELAY(500);
  72: 
  73: hpopen(io)
  74:     register struct iob *io;
  75: {
  76:     register unit = io->i_unit;
  77:     struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit);
  78:     register struct st *st;
  79:     register struct hp_softc *sc = &hp_softc[unit];
  80: 
  81:     mbainit(UNITTOMBA(unit));
  82:     if (sc->gottype == 0) {
  83:         register i, type = hpaddr->hpdt & MBDT_TYPE;
  84:         struct iob tio;
  85: 
  86:         for (i = 0; hptypes[i]; i++)
  87:             if (hptypes[i] == type)
  88:                 goto found;
  89:         _stop("unknown drive type");
  90: found:
  91:         sc->retries = RETRIES;
  92:         sc->ecclim = 11;
  93:         sc->debug = 0;
  94:         hpaddr->hpcs1 = HP_DCLR|HP_GO;      /* init drive */
  95:         hpaddr->hpcs1 = HP_PRESET|HP_GO;
  96:         if (!ML11)
  97:             hpaddr->hpof = HPOF_FMT22;
  98:         sc->type = hpmaptype(hpaddr, i, UNITTODRIVE(unit));
  99:         /*
 100: 		 * Read in the bad sector table.
 101: 		 */
 102:         st = &hpst[sc->type];
 103:         tio = *io;
 104:         tio.i_bn = st->nspc * st->ncyl - st->nsect;
 105:         tio.i_ma = (char *)&hpbad[unit];
 106:         tio.i_cc = sizeof (struct dkbad);
 107:         tio.i_flgs |= F_RDDATA;
 108:         for (i = 0; i < 5; i++) {
 109:             if (hpstrategy(&tio, READ) == sizeof (struct dkbad))
 110:                 break;
 111:             tio.i_bn += 2;
 112:         }
 113:         if (i == 5) {
 114:             printf("Unable to read bad sector table\n");
 115:             for (i = 0; i < MAXBADDESC; i++) {
 116:                 hpbad[unit].bt_bad[i].bt_cyl = -1;
 117:                 hpbad[unit].bt_bad[i].bt_trksec = -1;
 118:             }
 119:         }
 120:         sc->gottype = 1;
 121:     }
 122:     st = &hpst[sc->type];
 123:     if (io->i_boff < 0 || io->i_boff > 7 ||
 124:         st->off[io->i_boff]== -1)
 125:         _stop("hp bad minor");
 126:     io->i_boff = st->off[io->i_boff] * st->nspc;
 127: }
 128: 
 129: hpstrategy(io, func)
 130:     register struct iob *io;
 131: {
 132:     register unit = io->i_unit;
 133:     struct mba_regs *mba = mbamba(unit);
 134:     daddr_t bn, startblock;
 135:     struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit);
 136:     register struct hp_softc *sc = &hp_softc[unit];
 137:     struct st *st = &hpst[sc->type];
 138:     int cn, tn, sn, bytecnt, bytesleft, rv;
 139:     char *membase;
 140:     int er1, er2, hprecal;
 141: 
 142:     sectsiz = SECTSIZ;
 143:     if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0)
 144:         sectsiz += HDRSIZ;
 145:     if ((hpaddr->hpds & HPDS_VV) == 0) {
 146:         hpaddr->hpcs1 = HP_DCLR|HP_GO;
 147:         hpaddr->hpcs1 = HP_PRESET|HP_GO;
 148:         if (!ML11)
 149:             hpaddr->hpof = HPOF_FMT22;
 150:     }
 151:     io->i_errcnt = 0;
 152:     sc->ssect = 0;
 153:     rv = bytecnt = io->i_cc;
 154:     membase = io->i_ma;
 155:     startblock = io->i_bn;
 156:     hprecal = 0;
 157: 
 158: restart:
 159:     bn = io->i_bn;
 160:     cn = bn/st->nspc;
 161:     sn = bn%st->nspc;
 162:     tn = sn/st->nsect;
 163:     sn = sn%st->nsect + sc->ssect;
 164: 
 165:     HPWAIT(hpaddr);
 166:     mba->mba_sr = -1;
 167:     if (ML11)
 168:         hpaddr->hpda = bn;
 169:     else {
 170:         hpaddr->hpdc = cn;
 171:         hpaddr->hpda = (tn << 8) + sn;
 172:     }
 173:     if (mbastart(io, func) != 0) {      /* start transfer */
 174:         rv = -1;
 175:         goto done;
 176:     }
 177:     HPWAIT(hpaddr);
 178:     /*
 179: 	 * Successful data transfer, return.
 180: 	 */
 181:     if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0)
 182:         goto done;
 183: 
 184:     /*
 185: 	 * Error handling.  Calculate location of error.
 186: 	 */
 187:     bytesleft = MASKREG(mba->mba_bcr);
 188:     if (bytesleft)
 189:         bytesleft |= 0xffff0000;    /* sxt */
 190:     bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz;
 191:     er1 = MASKREG(hpaddr->hper1);
 192:     er2 = MASKREG(hpaddr->hper2);
 193:     if (er1 & (HPER1_DCK|HPER1_ECH))
 194:         bn--;   /* Error is in Prev block */
 195:     cn = bn/st->nspc;
 196:     sn = bn%st->nspc;
 197:     tn = sn/st->nsect;
 198:     sn = sn%st->nsect;
 199:     if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) {
 200:         printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b\n",
 201:             bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS);
 202:         printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS);
 203:         printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft,
 204:             hpaddr->hpof, hpaddr->hpda);
 205:     }
 206:     if (er1 & HPER1_HCRC) {
 207:         er1 &= ~(HPER1_HCE|HPER1_FER);
 208:         er2 &= ~HPER2_BSE;
 209:         if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0)
 210:             goto success;
 211:     }
 212:     /*
 213: 	 * Give up early if drive write locked.
 214: 	 */
 215:     if (er1&HPER1_WLE) {
 216:         printf("hp%d: write locked\n", unit);
 217:         rv = -1;
 218:         goto done;
 219:     }
 220:     /*
 221: 	 * Skip sector handling.
 222: 	 */
 223:     if (RM80 && (er2 & HPER2_SSE)) {
 224:         (void) hpecc(io, SSE);
 225:         sc->ssect = 1;
 226:         goto restart;
 227:     }
 228:     /*
 229: 	 * Attempt to forward bad sectors on anything but an ML11.
 230: 	 * Interpret format error bit as a bad block on RP06's.
 231: 	 */
 232:     if (((er2 & HPER2_BSE) && !ML11) ||
 233:         (MASKREG(er1) == HPER1_FER && RP06)) {
 234:         if (io->i_flgs & F_NBSF) {
 235:             io->i_error = EBSE;
 236:             goto hard;
 237:         }
 238:         if (hpecc(io, BSE) == 0)
 239:             goto success;
 240:         io->i_error = EBSE;
 241:         goto hard;
 242:     }
 243:     /*
 244: 	 * ECC correction?
 245: 	 */
 246:     if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) {
 247:         if (hpecc(io, ECC) == 0)
 248:             goto success;
 249:         io->i_error = EECC;
 250:         goto hard;
 251:     }
 252: 
 253:     /*
 254: 	 * If a hard error, or maximum retry count
 255: 	 * exceeded, clear controller state and
 256: 	 * pass back error to caller.
 257: 	 */
 258:     if (++io->i_errcnt > sc->retries || (er1 & HPER1_HARD) ||
 259:         (!ML11 && (er2 & HPER2_HARD)) || (ML11 && (io->i_errcnt >= 16))) {
 260:         io->i_error = EHER;
 261:         if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR))
 262:             io->i_error = EWCK;
 263: hard:
 264:         io->i_errblk = bn + sc->ssect;
 265:         if (sc->debug & (HPF_BSEDEBUG|HPF_ECCDEBUG))
 266:             printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc),
 267:               MASKREG(hpaddr->hpda));
 268:         else {
 269:             printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b \n",
 270:                bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS);
 271:             printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS);
 272:         }
 273:         hpaddr->hpcs1 = HP_DCLR|HP_GO;
 274:         printf("\n");
 275:         rv = -1;
 276:         goto done;
 277: 
 278:     }
 279:     /* fall thru to retry */
 280:     hpaddr->hpcs1 = HP_DCLR|HP_GO;
 281:     HPWAIT(hpaddr);
 282: 
 283:     /*
 284: 	 * Every fourth retry recalibrate.
 285: 	 */
 286:     if (((io->i_errcnt & 07) == 4) ) {
 287:         hpaddr->hpcs1 = HP_RECAL|HP_GO;
 288:         HPWAIT(hpaddr);
 289:         hpaddr->hpdc = cn;
 290:         hpaddr->hpcs1 = HP_SEEK|HP_GO;
 291:         HPWAIT(hpaddr);
 292:     }
 293: 
 294:     if (io->i_errcnt >= 16 && (io->i_flgs & F_READ)) {
 295:         hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22;
 296:         hpaddr->hpcs1 = HP_OFFSET|HP_GO;
 297:         HPWAIT(hpaddr);
 298:     }
 299:     if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG))
 300:         printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n",
 301:           io->i_bn, io->i_cc, io->i_ma, hprecal);
 302:     goto restart;
 303: 
 304: success:
 305:     /*
 306: 	 * On successful error recovery, bump
 307: 	 * block number to advance to next portion
 308: 	 * of i/o transfer.
 309: 	 */
 310:     bn++;
 311:     if ((bn-startblock) * sectsiz < bytecnt) {
 312:         io->i_bn = bn;
 313:         io->i_ma = membase + (io->i_bn - startblock)*sectsiz;
 314:         io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz;
 315:         if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG))
 316:             printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n",
 317:               io->i_bn, io->i_cc, io->i_ma, hprecal);
 318:         goto restart;
 319:     }
 320: done:
 321:     if (io->i_errcnt >= 16) {
 322:         hpaddr->hpcs1 = HP_RTC|HP_GO;
 323:         while (hpaddr->hpds & HPDS_PIP)
 324:             ;
 325:     }
 326:     io->i_bn = startblock;      /*reset i_bn to original */
 327:     io->i_cc = bytecnt;     /*reset i_cc to total count xfered*/
 328:     io->i_ma = membase;     /*reset i_ma to original */
 329:     return (rv);
 330: }
 331: 
 332: hpecc(io, flag)
 333:     register struct iob *io;
 334:     int flag;
 335: {
 336:     register unit = io->i_unit;
 337:     register struct mba_regs *mbp = mbamba(unit);
 338:     register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit);
 339:     register struct hp_softc *sc = &hp_softc[unit];
 340:     register struct st *st = &hpst[sc->type];
 341:     int npf, bn, cn, tn, sn, bcr;
 342: 
 343:     bcr = MASKREG(mbp->mba_bcr);
 344:     if (bcr)
 345:         bcr |= 0xffff0000;      /* sxt */
 346:     npf = (bcr + io->i_cc) / sectsiz;   /* # sectors read */
 347:     if (flag == ECC)
 348:         npf--;      /* Error is in prev block --ghg */
 349:     bn = io->i_bn + npf + sc->ssect;    /* physical block #*/
 350:     if (sc->debug & HPF_ECCDEBUG)
 351:         printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n",
 352:             bcr, npf, sc->ssect, sectsiz, io->i_cc);
 353:     /*
 354: 	 * ECC correction logic.
 355: 	 */
 356:     if (flag == ECC) {
 357:         register int i;
 358:         caddr_t addr;
 359:         int bit, o, mask;
 360: 
 361:         printf("hp%d: soft ecc sn%d\n", unit, bn);
 362:         mask = MASKREG(rp->hpec2);
 363:         for (i = mask, bit = 0; i; i >>= 1)
 364:             if (i & 1)
 365:                 bit++;
 366:         if (bit > sc->ecclim) {
 367:             printf("%d-bit error\n", bit);
 368:             return (1);
 369:         }
 370:         i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */
 371:         bit = i&07;
 372:         o = (i & ~07) >> 3;
 373:         rp->hpcs1 = HP_DCLR | HP_GO;
 374:         while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) {
 375:             addr = io->i_ma + (npf*sectsiz) + o;
 376:             /*
 377: 			 * No data transfer occurs with a write check,
 378: 			 * so don't correct the resident copy of data.
 379: 			 */
 380:             if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) {
 381:                 if (sc->debug & HPF_ECCDEBUG)
 382:                     printf("addr=%x old=%x ", addr,
 383:                         (*addr & 0xff));
 384:                 *addr ^= (mask << bit);
 385:                 if (sc->debug & HPF_ECCDEBUG)
 386:                     printf("new=%x\n",(*addr & 0xff));
 387:             }
 388:             o++, bit -= 8;
 389:         }
 390:         return (0);
 391:     }
 392: 
 393:     /*
 394: 	 * Skip sector error.
 395: 	 * Set skip-sector-inhibit and
 396: 	 * read next sector
 397: 	 */
 398:     if (flag == SSE) {
 399:         rp->hpcs1 = HP_DCLR | HP_GO;
 400:         HPWAIT(rp);
 401:         rp->hpof |= HPOF_SSEI;
 402:         return (0);
 403:     }
 404: 
 405:     /*
 406: 	 * Bad block forwarding.
 407: 	 */
 408:      if (flag == BSE) {
 409:         int bbn;
 410: 
 411:         rp->hpcs1 = HP_DCLR | HP_GO;
 412:         if (sc->debug & HPF_BSEDEBUG)
 413:             printf("hpecc: BSE @ bn %d\n", bn);
 414:         cn = bn/st->nspc;
 415:         sn = bn%st->nspc;
 416:         tn = sn/st->nsect;
 417:         sn = sn%st->nsect;
 418:         bcr += sectsiz;
 419:         if ((bbn = isbad(&hpbad[unit], cn, tn, sn)) < 0)
 420:             return (1);
 421:         bbn = st->ncyl*st->nspc - st->nsect - 1 - bbn;
 422:         cn = bbn/st->nspc;
 423:         sn = bbn%st->nspc;
 424:         tn = sn/st->nsect;
 425:         sn = sn%st->nsect;
 426:         io->i_cc = sectsiz;
 427:         io->i_ma += npf*sectsiz;
 428:         if (sc->debug & HPF_BSEDEBUG)
 429:             printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
 430:         rp->hpof &= ~HPOF_SSEI;
 431:         mbp->mba_sr = -1;
 432:         rp->hpdc = cn;
 433:         rp->hpda = (tn<<8) + sn;
 434:         mbastart(io,io->i_flgs);
 435:         io->i_errcnt = 0;
 436:         HPWAIT(rp);
 437:         return (rp->hpds&HPDS_ERR);
 438:     }
 439:     printf("hpecc: flag=%d\n", flag);
 440:     return (1);
 441: }
 442: 
 443: /*ARGSUSED*/
 444: hpioctl(io, cmd, arg)
 445:     struct iob *io;
 446:     int cmd;
 447:     caddr_t arg;
 448: {
 449:     register unit = io->i_unit;
 450:     register struct hp_softc *sc = &hp_softc[unit];
 451:     struct st *st = &hpst[sc->type];
 452:     struct mba_drv *drv = mbadrv(unit);
 453: 
 454:     switch(cmd) {
 455: 
 456:     case SAIODEBUG:
 457:         sc->debug = (int)arg;
 458:         break;
 459: 
 460:     case SAIODEVDATA:
 461:         if (drv->mbd_dt&MBDT_TAP)
 462:             return (ECMD);
 463:         *(struct st *)arg = *st;
 464:         break;
 465: 
 466:     case SAIOGBADINFO:
 467:         if (drv->mbd_dt&MBDT_TAP)
 468:             return (ECMD);
 469:         *(struct dkbad *)arg = hpbad[unit];
 470:         break;
 471: 
 472:     case SAIOECCLIM:
 473:         sc->ecclim = (int)arg;
 474:         break;
 475: 
 476:     case SAIORETRIES:
 477:         sc->retries = (int)arg;
 478:         break;
 479: 
 480:     case SAIOSSI:           /* skip-sector-inhibit */
 481:         if (drv->mbd_dt&MBDT_TAP)
 482:             return (ECMD);
 483:         if ((io->i_flgs&F_SSI) == 0) {
 484:             /* make sure this is done once only */
 485:             io->i_flgs |= F_SSI;
 486:             st->nsect++;
 487:             st->nspc += st->ntrak;
 488:         }
 489:         break;
 490: 
 491:     case SAIONOSSI:         /* remove skip-sector-inhibit */
 492:         if (io->i_flgs & F_SSI) {
 493:             io->i_flgs &= ~F_SSI;
 494:             drv->mbd_of &= ~HPOF_SSEI;
 495:             st->nsect--;
 496:             st->nspc -= st->ntrak;
 497:         }
 498:         break;
 499: 
 500:     case SAIOSSDEV:         /* drive have skip sector? */
 501:         return (RM80 ? 0 : ECMD);
 502: 
 503:     default:
 504:         return (ECMD);
 505:     }
 506:     return (0);
 507: }

Defined functions

hpecc defined in line 332; used 4 times
hpioctl defined in line 444; never used
hpopen defined in line 73; never used
hpstrategy defined in line 129; used 1 times

Defined variables

hp_offset defined in line 43; used 1 times
hp_softc defined in line 61; used 4 times
hpbad defined in line 50; used 5 times
sectsiz defined in line 63; used 14 times

Defined struct's

hp_softc defined in line 52; used 8 times

Defined macros

HDRSIZ defined in line 33; used 1 times
HPF_BSEDEBUG defined in line 57; used 6 times
HPF_ECCDEBUG defined in line 58; used 7 times
HPWAIT defined in line 70; used 8 times
MASKREG defined in line 29; used 11 times
MAXBADDESC defined in line 31; used 1 times
ML11 defined in line 40; used 6 times
RETRIES defined in line 27; used 1 times
  • in line 91
RM80 defined in line 41; used 2 times
RP06 defined in line 38; used 1 times
SECTSIZ defined in line 32; used 1 times
Last modified: 1986-06-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1523
Valid CSS Valid XHTML 1.0 Strict