1*10413Shelge /* hp.c 4.3 83/01/18 */ 210334Shelge 310334Shelge /* 410334Shelge * RP??/RM?? disk driver 510334Shelge * with ECC handling and bad block forwarding. 610334Shelge * Also supports header io operations and 710334Shelge * commands to write check header and data. 810334Shelge */ 910334Shelge 1010334Shelge #include "../h/param.h" 1110334Shelge #include "../h/inode.h" 1210334Shelge #include "../h/fs.h" 1310334Shelge #include "../h/dkbad.h" 1410334Shelge 1510334Shelge #include "../vax/pte.h" 1610334Shelge #include "../vaxmba/hpreg.h" 1710334Shelge #include "../vaxmba/mbareg.h" 1810334Shelge 1910334Shelge #include "saio.h" 2010334Shelge #include "savax.h" 2110334Shelge 2210334Shelge #define MASKREG(reg) ((reg)&0xffff) 2310334Shelge 2410334Shelge #define MAXBADDESC 126 2510334Shelge #define SECTSIZ 512 /* sector size in bytes */ 2610334Shelge #define HDRSIZ 4 /* number of bytes in sector header */ 2710334Shelge #define MAXECC 5 /* the maximum number of bad bits accepted in 2810334Shelge * an ecc error when F_ECCLM is set */ 2910334Shelge 3010334Shelge char hp_type[MAXNMBA*8] = { 0 }; 3110334Shelge 3210334Shelge /* THIS SHOULD BE READ IN OFF THE PACK, PER DRIVE */ 3310334Shelge short hp6_off[8] = { 0, 38, 0, -1, -1, -1, 118, -1 }; 3410334Shelge short rm3_off[8] = { 0, 100, 0, -1, -1, -1, 310, -1 }; 3510334Shelge short rm5_off[8] = { 0, 27, 0, 562, 589, 681, 562, 82 }; 3610334Shelge short rm80_off[8] = { 0, 37, 0, -1, -1, -1, 115, 305 }; 3710334Shelge short hp7_off[8] = { 0, 10, 0, 330, 340, 500, 330, 50 }; 3810334Shelge short ml_off[8] = { 0, -1, -1, -1, -1, -1, -1, -1 }; 3910334Shelge short si9775_off[8] = { 0, 13, 0, -1, -1, -1, 40, 441 }; 4010334Shelge short si9730_off[8] = { 0, 50, 0, -1, -1, -1, -1, 155 }; 4110334Shelge short hpam_off[8] = { 0, 32, 0, 668, 723, 778, 668, 98 }; 4210334Shelge /* END SHOULD BE READ IN */ 4310334Shelge 4410334Shelge short hptypes[] = 4510334Shelge { MBDT_RM03, MBDT_RM05, MBDT_RP06, MBDT_RM80, MBDT_RP05, MBDT_RP07, 4610334Shelge MBDT_ML11A, MBDT_ML11B, -1/*9755*/, -1/*9730*/, -1/*Capr*/, MBDT_RM02, 0}; 4710334Shelge 4810334Shelge #define RP06 (hptypes[UNITTODRIVE(unit)] <= MBDT_RP06) 4910334Shelge #define ML11 (hptypes[UNITTODRIVE(unit)] <= MBDT_ML11A) 5010334Shelge #define RM80 (hptypes[UNITTODRIVE(unit)] <= MBDT_RM80) 5110334Shelge 5210334Shelge u_char hp_offset[16] = { 5310334Shelge HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 5410334Shelge HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 5510334Shelge HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 5610334Shelge 0, 0, 0, 0, 5710334Shelge }; 5810334Shelge 5910353Shelge struct st hpst[] = { 6010334Shelge 32, 5, 32*5, 823, rm3_off, /* RM03 */ 6110334Shelge 32, 19, 32*19, 823, rm5_off, /* RM05 */ 6210334Shelge 22, 19, 22*19, 815, hp6_off, /* RP06 */ 6310334Shelge 31, 14, 31*14, 559, rm80_off, /* RM80 */ 6410334Shelge 22, 19, 22*19, 411, hp6_off, /* RP06 */ 6510334Shelge 50, 32, 50*32, 630, hp7_off, /* RP07 */ 6610334Shelge 1, 1, 1, 1, ml_off, /* ML11A */ 6710334Shelge 1, 1, 1, 1, ml_off, /* ML11B */ 6810334Shelge 32, 40, 32*40, 843, si9775_off, /* 9775 */ 6910334Shelge 32, 10, 32*10, 823, si9730_off, /* 9730 */ 7010334Shelge 32, 16, 32*16, 1024, hpam_off, /* AMPEX capricorn */ 7110334Shelge 1, 1, 1, 1, 0, /* rm02 - not used */ 7210334Shelge }; 7310334Shelge struct dkbad hpbad[MAXNMBA*8]; 7410334Shelge int sectsiz; 7510334Shelge 7610334Shelge hpopen(io) 7710334Shelge register struct iob *io; 7810334Shelge { 7910334Shelge register unit = io->i_unit; 8010334Shelge struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 8110353Shelge register struct st *st; 8210334Shelge 8310334Shelge mbainit(UNITTOMBA(unit)); 8410334Shelge if (hp_type[unit] == 0) { 8510334Shelge register type = hpaddr->hpdt & MBDT_TYPE; 8610334Shelge register int i; 8710334Shelge struct iob tio; 8810334Shelge 8910334Shelge for (i = 0; hptypes[i]; i++) 9010334Shelge if (hptypes[i] == type) 9110334Shelge goto found; 9210334Shelge _stop("unknown drive type"); 9310334Shelge found: 9410334Shelge switch (i) { 9510334Shelge case 0: case 1: { /* rm03 or rm05 */ 9610334Shelge register hpsn = hpaddr->hpsn; 9710334Shelge 9810334Shelge if ((hpsn & SIMB_LU) != unit) 9910334Shelge break; 10010334Shelge switch ((hpsn & SIMB_MB) &~ (SIMB_S6|SIRM03|SIRM05)) { 10110334Shelge case SI9775D: 10210334Shelge i = 8; /* si9775 */ 10310334Shelge break; 10410334Shelge case SI9730D: 10510334Shelge i = 9; /* si9730 */ 10610334Shelge break; 10710334Shelge case SI9766: 10810334Shelge i = 1; /* rm05 */ 10910334Shelge hpaddr->hpcs1 = HP_RECAL|HP_GO; 11010334Shelge DELAY(100000); 11110334Shelge break; 11210334Shelge case SI9762: 11310334Shelge i = 0; /* rm03 */ 11410334Shelge break; 11510334Shelge } 11610334Shelge break; 11710334Shelge } 11810334Shelge 11910334Shelge case 11: /* rm02 */ 12010334Shelge hpaddr->hpcs1 = HP_NOP; 12110334Shelge hpaddr->hphr = HPHR_MAXTRAK; 12210334Shelge if (MASKREG(hpaddr->hphr) == 15) 12310334Shelge i = 10; /* ampex capricorn */ 12410334Shelge else 12510334Shelge i = 0; /* rm03 */ 12610334Shelge break; 12710334Shelge 12810334Shelge case 6: case 7: /* ml11a ml11b */ 12910334Shelge i = 6; /* ml11a */ 13010334Shelge break; 13110334Shelge } 13210334Shelge hp_type[unit] = i; 13310334Shelge /* 13410334Shelge * Read in the bad sector table: 13510334Shelge * copy the contents of the io structure 13610334Shelge * to tio for use during the bb pointer 13710334Shelge * read operation. 13810334Shelge */ 13910334Shelge st = &hpst[hp_type[unit]]; 14010334Shelge tio = *io; 14110334Shelge tio.i_bn = st->nspc * st->ncyl - st->nsect; 14210334Shelge tio.i_ma = (char *)&hpbad[tio.i_unit]; 14310334Shelge tio.i_cc = sizeof (hpbad); 14410334Shelge tio.i_flgs |= F_RDDATA; 14510334Shelge for (i = 0; i < 5; i++) { 14610334Shelge if (hpstrategy(&tio, READ) == sizeof (hpbad)) 14710334Shelge break; 14810334Shelge tio.i_bn += 2; 14910334Shelge } 15010334Shelge if (i == 5) { 15110334Shelge printf("Unable to read bad sector table\n"); 15210334Shelge for (i = 0; i < MAXBADDESC; i++) { 15310334Shelge hpbad[unit].bt_bad[i].bt_cyl = -1; 15410334Shelge hpbad[unit].bt_bad[i].bt_trksec = -1; 15510334Shelge } 15610334Shelge } 15710334Shelge } 15810334Shelge if (io->i_boff < 0 || io->i_boff > 7 || 15910334Shelge st->off[io->i_boff]== -1) 16010334Shelge _stop("hp bad minor"); 16110334Shelge io->i_boff = st->off[io->i_boff] * st->nspc; 16210334Shelge } 16310334Shelge 16410334Shelge hpstrategy(io, func) 16510334Shelge register struct iob *io; 16610334Shelge { 16710334Shelge register unit = io->i_unit; 16810334Shelge struct mba_regs *mba = mbamba(unit); 16910334Shelge daddr_t bn; 17010334Shelge struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 17110353Shelge struct st *st = &hpst[hp_type[unit]]; 17210334Shelge int cn, tn, sn, bytecnt, bytesleft; 17310334Shelge daddr_t startblock; 17410334Shelge char *membase; 17510334Shelge int er1, er2, hprecal; 17610334Shelge 17710334Shelge sectsiz = SECTSIZ; 17810334Shelge if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0) 17910334Shelge sectsiz += HDRSIZ; 18010334Shelge if ((hpaddr->hpds & HPDS_VV) == 0) { 18110334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 18210334Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 18310334Shelge if (hp_type[unit] != 6) /* any but ml11 */ 18410334Shelge hpaddr->hpof = HPOF_FMT22; 18510334Shelge } 18610334Shelge io->i_errcnt = 0; 18710334Shelge bytecnt = io->i_cc; 18810334Shelge membase = io->i_ma; 18910334Shelge startblock = io->i_bn; 19010334Shelge hprecal = 1; 19110334Shelge readmore: 19210334Shelge bn = io->i_bn; 19310334Shelge cn = bn/st->nspc; 19410334Shelge sn = bn%st->nspc; 19510334Shelge tn = sn/st->nsect; 19610334Shelge sn = sn%st->nsect; 19710334Shelge 19810334Shelge while ((hpaddr->hpds & HPDS_DRY) == 0) 19910334Shelge ; 20010334Shelge if (hp_type[unit] == 6) /* ml11 */ 20110334Shelge hpaddr->hpda = bn; 20210334Shelge else { 20310334Shelge hpaddr->hpdc = cn; 20410334Shelge hpaddr->hpda = (tn << 8) + sn; 20510334Shelge } 20610334Shelge if (mbastart(io, func) != 0) /* start transfer */ 20710334Shelge return (-1); 20810334Shelge 20910334Shelge while ((hpaddr->hpds & HPDS_DRY) == 0) 21010334Shelge ; 21110334Shelge if (((hpaddr->hpds&HPDS_ERR) | (mba->mba_sr&MBSR_EBITS)) == 0 ) 21210334Shelge return(bytecnt); 21310334Shelge 21410334Shelge /* ------- error handling ------- */ 21510334Shelge 21610334Shelge if (bytesleft = MASKREG(mba->mba_bcr>>16)) 21710334Shelge bytesleft |= 0xffff0000; /* sign ext */ 21810334Shelge bn = io->i_bn + (io->i_cc + bytesleft)/sectsiz; 21910334Shelge cn = bn/st->nspc; 22010334Shelge sn = bn%st->nspc; 22110334Shelge tn = sn/st->nsect; 22210334Shelge sn = sn%st->nsect; 22310334Shelge er1 = MASKREG(hpaddr->hper1); 22410334Shelge er2 = MASKREG(hpaddr->hper2); 22510334Shelge #ifdef HPDEBUG 22610334Shelge printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", 22710334Shelge cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 22810334Shelge printf("er1=%b er2=%b", 22910334Shelge er1, HPER1_BITS, 23010334Shelge er2, HPER2_BITS); 23110334Shelge printf("\n"); 23210334Shelge #endif 23310334Shelge if (er1 & HPER1_HCRC) { 23410334Shelge er1 &= ~(HPER1_HCE|HPER1_FER); 23510334Shelge er2 &= ~HPER2_BSE; 23610334Shelge } 23710334Shelge if (er1&HPER1_WLE) { 23810334Shelge printf("hp%d: write locked\n", unit); 23910334Shelge return(-1); 24010334Shelge } else if ((er1&0xffff) == HPER1_FER && RP06) { 24110334Shelge goto badsect; 24210334Shelge 24310334Shelge } else if (++io->i_errcnt > 27 || 24410334Shelge er1 & HPER1_HARD || 24510334Shelge (!ML11 && (er2 & HPER2_HARD))) { 24610334Shelge io->i_error = EHER; 24710334Shelge if ((mba->mba_sr & (MBSR_WCKUP | MBSR_WCKLWR)) != 0) 24810334Shelge io->i_error = EWCK; 24910334Shelge hard: 25010334Shelge io->i_errblk = bn; 25110334Shelge printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", 25210334Shelge cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 25310334Shelge printf("er1=%b er2=%b", 25410334Shelge er1, HPER1_BITS, 25510334Shelge er2, HPER2_BITS); 25610334Shelge if (hpaddr->hpmr) 25710334Shelge printf(" mr=%o", hpaddr->hpmr&0xffff); 25810334Shelge if (hpaddr->hpmr2) 25910334Shelge printf(" mr2=%o", hpaddr->hpmr2&0xffff); 26010334Shelge printf("\n"); 26110334Shelge return(-1); 26210334Shelge 26310334Shelge } else if ((er2 & HPER2_BSE) && !ML11) { 26410334Shelge badsect: 26510334Shelge if ((io->i_flgs & F_NBSF) != 0) { 26610334Shelge io->i_error = EBSE; 26710334Shelge goto hard; 26810334Shelge } 26910334Shelge if (hpecc(io, BSE) == 0) 27010334Shelge goto success; 27110334Shelge else { 27210334Shelge io->i_error = EBSE; 27310334Shelge goto hard; 27410334Shelge } 27510334Shelge } else if (RM80 && er2&HPER2_SSE) { 27610334Shelge /* skip sector error */ 27710334Shelge (void) hpecc(io, SSE); 278*10413Shelge startblock++; /* since one sector was skipped */ 27910334Shelge goto success; 28010334Shelge } else if ((er1&(HPER1_DCK|HPER1_ECH))==HPER1_DCK) { 28110334Shelge if ( hpecc(io, ECC) == 0) 28210334Shelge goto success; 28310334Shelge else { 28410334Shelge io->i_error = EECC; 28510334Shelge return(1); 28610334Shelge } 28710334Shelge } else 28810334Shelge io->i_active = 0; /* force retry */ 28910334Shelge 29010334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 29110334Shelge while ((hpaddr->hpds & HPDS_DRY) == 0) 29210334Shelge ; 29310334Shelge if (ML11) { 29410334Shelge if (io->i_errcnt >= 16) 29510334Shelge goto hard; 29610334Shelge } else if (((io->i_errcnt&07) == 4) && (io->i_active == 0)) { 29710334Shelge hpaddr->hpcs1 = HP_RECAL|HP_GO; 29810334Shelge hprecal = 0; 29910334Shelge goto nextrecal; 30010334Shelge } 30110334Shelge switch (hprecal) { 30210334Shelge 30310334Shelge case 1: 30410334Shelge hpaddr->hpdc = cn; 30510334Shelge hpaddr->hpcs1 = HP_SEEK|HP_GO; 30610334Shelge goto nextrecal; 30710334Shelge case 2: 30810334Shelge if (io->i_errcnt < 16 || (func & READ) == 0) 30910334Shelge goto donerecal; 31010334Shelge hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22; 31110334Shelge hpaddr->hpcs1 = HP_OFFSET|HP_GO; 31210334Shelge nextrecal: 31310334Shelge hprecal++; 31410334Shelge io->i_active = 1; 31510334Shelge goto try_again; 31610334Shelge donerecal: 31710334Shelge case 3: 31810334Shelge hprecal = 0; 31910334Shelge io->i_active = 0; 32010334Shelge goto try_again; 32110334Shelge } 32210334Shelge if (io->i_active) { 32310334Shelge if (io->i_errcnt >= 16) { 32410334Shelge hpaddr->hpcs1 = HP_RTC|HP_GO; 32510334Shelge while (hpaddr->hpds & HPDS_PIP) 32610334Shelge ; 32710334Shelge } 32810334Shelge } 32910334Shelge success: /* continue with the next block */ 33010334Shelge bn++; 33110334Shelge if ((bn-startblock) * sectsiz < bytecnt) { 33210334Shelge 33310334Shelge try_again: /* re-read same block */ 33410334Shelge io->i_bn = bn; 33510334Shelge mba->mba_sr = -1; 33610334Shelge io->i_ma = membase + (io->i_bn - startblock)*sectsiz; 33710334Shelge io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz; 33810334Shelge #ifdef HPDEBUG 33910334Shelge printf("restart: bl %d, byte %d, mem 0x%x %d\n", 34010334Shelge io->i_bn, io->i_cc, io->i_ma, io->i_ma); 34110334Shelge #endif 34210334Shelge goto readmore; 34310334Shelge } 34410334Shelge return (bytecnt); 34510334Shelge } 34610334Shelge hpecc(io, flag) 34710334Shelge register struct iob *io; 34810334Shelge int flag; 34910334Shelge { 35010334Shelge register unit = io->i_unit; 35110334Shelge register struct mba_regs *mbp = mbamba(unit); 35210334Shelge register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit); 35310353Shelge register struct st *st = &hpst[hp_type[unit]]; 35410334Shelge int npf; 35510334Shelge int bn, cn, tn, sn; 35610334Shelge int bcr, tad; 35710334Shelge 35810334Shelge if (bcr = MASKREG(mbp->mba_bcr>>16)) 35910334Shelge bcr |= 0xffff0000; /* sxt */ 36010334Shelge npf = (bcr + io->i_cc)/sectsiz; /* number of sectors read */ 361*10413Shelge bn = io->i_bn + npf; 36210334Shelge switch (flag) { 36310334Shelge case ECC: 36410334Shelge { 36510334Shelge register int i; 36610334Shelge caddr_t addr; 36710334Shelge int bit, byte, mask, ecccnt = 0; 36810334Shelge 369*10413Shelge printf("hp%d: soft ecc sn%d\n", unit, bn); 37010334Shelge mask = MASKREG(rp->hpec2); 37110334Shelge i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 37210334Shelge bit = i&07; 37310334Shelge i = (i&~07)>>3; 37410334Shelge byte = i; 37510334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 37610334Shelge while (i <sectsiz && npf*sectsiz + i < io->i_cc && bit > -11) { 37710334Shelge addr = io->i_ma + (npf*sectsiz) + byte; 37810334Shelge #ifdef HPECCDEBUG 37910334Shelge printf("addr %x old:%x ",addr, (*addr&0xff)); 38010334Shelge #endif 38110334Shelge if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) 38210334Shelge *addr ^= (mask << bit); /* don't 'correct' mem- 38310334Shelge * ory during Wcheck */ 38410334Shelge #ifdef HPECCDEBUG 38510334Shelge printf("new:%x\n",(*addr&0xff)); 38610334Shelge #endif 38710334Shelge byte++; 38810334Shelge i++; 38910334Shelge bit -= 8; 39010334Shelge if ((ecccnt++>=MAXECC) && ((io->i_flgs&F_ECCLM) != 0)) 39110334Shelge return(1); 39210334Shelge } 39310334Shelge return(0); 39410334Shelge } 39510334Shelge 396*10413Shelge case SSE: /* skip sector error */ 397*10413Shelge /* set skip-sector-inhibit and read next sector */ 39810334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 399*10413Shelge while(rp->hpds & HPDS_DRY == 0) 400*10413Shelge ; /* avoid RMR error */ 40110334Shelge rp->hpof |= HPOF_SSEI; 40210334Shelge return(0); 40310334Shelge 40410334Shelge #ifndef NOBADSECT 40510334Shelge case BSE: 40610334Shelge #ifdef HPDEBUG 40710334Shelge printf("hpecc: BSE @ bn %d\n", bn); 40810334Shelge #endif 40910334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 410*10413Shelge bcr += sectsiz; 41110334Shelge tad = rp->hpda; 412*10413Shelge if ((bn = isbad(&hpbad[unit], bn/st->nspc,tad>>8,tad&0x7f)) < 0) 41310334Shelge return(1); 41410334Shelge bn = st->ncyl*st->nspc - st->nsect - 1 - bn; 41510334Shelge cn = bn/st->nspc; 41610334Shelge sn = bn%st->nspc; 41710334Shelge tn = sn/st->nsect; 41810334Shelge sn %= st->nsect; 419*10413Shelge io->i_cc = -sectsiz; 420*10413Shelge io->i_ma += ((io->i_bn + npf -1)*sectsiz); 42110334Shelge #ifdef HPDEBUG 42210334Shelge printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 42310334Shelge #endif 42410334Shelge rp->hpdc = cn; 42510334Shelge rp->hpda = (tn<<8) + sn; 42610334Shelge mbp->mba_sr = -1; 42710334Shelge mbastart(io,io->i_flgs); 42810334Shelge io->i_errcnt = 0; /* error has been corrected */ 42910334Shelge if (rp->hpds&HPDS_ERR) 43010334Shelge return(1); 43110334Shelge else 43210334Shelge return(0); 43310334Shelge } 43410334Shelge } 43510334Shelge /*ARGSUSED*/ 43610334Shelge hpioctl(io, cmd, arg) 43710334Shelge struct iob *io; 43810334Shelge int cmd; 43910334Shelge caddr_t arg; 44010334Shelge { 44110334Shelge 44210353Shelge struct st *st = &hpst[hp_type[io->i_unit]], *tmp; 44310334Shelge struct mba_drv *drv = mbadrv(io->i_unit); 44410334Shelge 44510334Shelge switch(cmd) { 44610334Shelge 44710334Shelge case SAIODEVDATA: 44810334Shelge if ((drv->mbd_dt&MBDT_TAP) == 0) { 44910353Shelge tmp = (struct st *)arg; 45010353Shelge *tmp = *st; 45110334Shelge return(0); 45210334Shelge } 45310334Shelge else 45410334Shelge return(ECMD); 45510334Shelge 45610334Shelge default: 45710334Shelge return (ECMD); 45810334Shelge } 45910334Shelge } 46010334Shelge 461