123225Smckusick /* 233409Skarels * Copyright (c) 1982, 1986 Regents of the University of California. 323225Smckusick * All rights reserved. The Berkeley software License Agreement 423225Smckusick * specifies the terms and conditions for redistribution. 523225Smckusick * 6*33545Sbostic * @(#)hp.c 7.6 (Berkeley) 02/23/88 723225Smckusick */ 810334Shelge 910334Shelge /* 10*33545Sbostic * RP??/RM?? disk driver with ECC handling and bad block forwarding. 11*33545Sbostic * Also supports header io operations and commands to write check 12*33545Sbostic * header and data. 1310334Shelge */ 1433409Skarels #include "param.h" 1533409Skarels #include "inode.h" 1633409Skarels #include "fs.h" 1733409Skarels #include "dkbad.h" 1833409Skarels #include "disklabel.h" 1910334Shelge 2010334Shelge #include "../vax/pte.h" 2133409Skarels 2210334Shelge #include "../vaxmba/hpreg.h" 2310334Shelge #include "../vaxmba/mbareg.h" 2410334Shelge 2510334Shelge #include "saio.h" 2610334Shelge #include "savax.h" 2710334Shelge 2825439Skarels #define RETRIES 27 2925439Skarels 3010334Shelge #define MASKREG(reg) ((reg)&0xffff) 3110334Shelge 3211366Ssam #define MAXBADDESC 126 3311366Ssam #define SECTSIZ 512 /* sector size in bytes */ 3411366Ssam #define HDRSIZ 4 /* number of bytes in sector header */ 3510334Shelge 3630547Skarels char lbuf[SECTSIZ]; 3710334Shelge 3830547Skarels #define RP06(type) ((type) == MBDT_RP06 || (type) == MBDT_RP05 \ 3930547Skarels || (type) == MBDT_RP04) 4030547Skarels #define ML11(type) ((type) == MBDT_ML11A) 4130547Skarels #define RM80(type) ((type) == MBDT_RM80) 4210334Shelge 4310334Shelge u_char hp_offset[16] = { 44*33545Sbostic HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 45*33545Sbostic HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 46*33545Sbostic HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 47*33545Sbostic 0, 0, 0, 0, 4810334Shelge }; 4910334Shelge 50*33545Sbostic #define MAXUNIT 8 51*33545Sbostic struct disklabel hplabel[MAXNMBA][MAXUNIT]; 5230547Skarels #ifndef SMALL 53*33545Sbostic struct dkbad hpbad[MAXNMBA][MAXUNIT]; 5430547Skarels int sectsiz; 5530547Skarels #endif 5610334Shelge 5725439Skarels struct hp_softc { 5825439Skarels char type; 5925439Skarels char gottype; 60*33545Sbostic char ssect; /* 1 when on track w/skip sector */ 6125439Skarels char debug; 6225439Skarels # define HPF_BSEDEBUG 01 /* debugging bad sector forwarding */ 6325439Skarels # define HPF_ECCDEBUG 02 /* debugging ecc correction */ 6425439Skarels int ecclim; 6525439Skarels int retries; 66*33545Sbostic } hp_softc[MAXNMBA][MAXUNIT]; 6711366Ssam 6810864Ssam /* 69*33545Sbostic * When awaiting command completion, don't hang on to the status register 70*33545Sbostic * since this ties up some controllers. 7110864Ssam */ 7211366Ssam #define HPWAIT(addr) \ 73*33545Sbostic while ((((addr)->hpds)&HPDS_DRY) == 0) \ 74*33545Sbostic DELAY(500); 7510864Ssam 7610334Shelge hpopen(io) 7710334Shelge register struct iob *io; 7810334Shelge { 7910334Shelge register unit = io->i_unit; 80*33545Sbostic register struct hp_softc *sc; 81*33545Sbostic register struct disklabel *lp; 82*33545Sbostic struct hpdevice *hpaddr; 8333041Skarels struct disklabel *dlp; 8410334Shelge 85*33545Sbostic if ((u_int)io->i_adapt >= MAXNMBA || !mbainit(io->i_adapt)) 86*33545Sbostic return (EADAPT); 87*33545Sbostic if ((u_int)io->i_ctlr) 88*33545Sbostic return (ECTLR); 89*33545Sbostic if ((u_int)unit >= MAXUNIT) 90*33545Sbostic return (EUNIT); 91*33545Sbostic hpaddr = (struct hpdevice *)mbadrv(io->i_adapt, unit); 92*33545Sbostic sc = &hp_softc[io->i_adapt][unit]; 93*33545Sbostic lp = &hplabel[io->i_adapt][unit]; 9425439Skarels if (sc->gottype == 0) { 95*33545Sbostic register int i; 9610334Shelge struct iob tio; 9710334Shelge 9830547Skarels #ifndef SMALL 9925439Skarels sc->retries = RETRIES; 10025439Skarels sc->ecclim = 11; 10125439Skarels sc->debug = 0; 10230547Skarels #endif 10310647Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; /* init drive */ 10410647Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 10530547Skarels #ifndef SMALL 10633409Skarels if ((hpaddr->hpds & HPDS_DPR) == 0) { 107*33545Sbostic printf("hp: drive nonexistent\n"); 10833409Skarels return (ENXIO); 10933409Skarels } 11030547Skarels sc->type = hpaddr->hpdt & MBDT_TYPE; 11130547Skarels if (sc->type == MBDT_ML11B) 11233409Skarels sc->type = MBDT_ML11A; 11330547Skarels if (!ML11(sc->type)) 11430547Skarels #endif 11510647Shelge hpaddr->hpof = HPOF_FMT22; 11610334Shelge /* 11730547Skarels * Read in the pack label. 11830547Skarels */ 11930547Skarels lp->d_nsectors = 32; 12030547Skarels lp->d_secpercyl = 20*32; 12130547Skarels tio = *io; 12230547Skarels tio.i_bn = LABELSECTOR; 12330547Skarels tio.i_ma = lbuf; 12430547Skarels tio.i_cc = SECTSIZ; 12530547Skarels tio.i_flgs |= F_RDDATA; 12630547Skarels if (hpstrategy(&tio, READ) != SECTSIZ) { 127*33545Sbostic printf("hp: can't read disk label\n"); 12830547Skarels return (EIO); 12930547Skarels } 13033041Skarels dlp = (struct disklabel *)(lbuf + LABELOFFSET); 13133041Skarels if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { 13230547Skarels printf("hp%d: unlabeled\n", unit); 13333409Skarels #if defined(COMPAT_42) /* && !defined(SMALL) */ 134*33545Sbostic hpmaptype(hpaddr, hpaddr->hpdt & MBDT_TYPE, unit, lp); 13530547Skarels #else 13630547Skarels return (ENXIO); 13730547Skarels #endif 13833041Skarels } else 13933041Skarels *lp = *dlp; 14033041Skarels #ifndef SMALL 14130547Skarels /* 14211366Ssam * Read in the bad sector table. 14310334Shelge */ 14430547Skarels tio.i_bn = lp->d_secpercyl * lp->d_ncylinders - lp->d_nsectors; 145*33545Sbostic tio.i_ma = (char *)&hpbad[io->i_adapt][unit]; 146*33545Sbostic tio.i_cc = sizeof(struct dkbad); 14710334Shelge for (i = 0; i < 5; i++) { 148*33545Sbostic if (hpstrategy(&tio, READ) == sizeof(struct dkbad)) 14910334Shelge break; 15010334Shelge tio.i_bn += 2; 15110334Shelge } 15210334Shelge if (i == 5) { 153*33545Sbostic printf("hp: can't read bad sector table\n"); 15410334Shelge for (i = 0; i < MAXBADDESC; i++) { 155*33545Sbostic hpbad[io->i_adapt][unit].bt_bad[i].bt_cyl = -1; 156*33545Sbostic hpbad[io->i_adapt][unit].bt_bad[i].bt_trksec = -1; 15710334Shelge } 15825439Skarels } 15933041Skarels #endif 16025439Skarels sc->gottype = 1; 16110334Shelge } 162*33545Sbostic if (io->i_part >= lp->d_npartitions || 163*33545Sbostic lp->d_partitions[io->i_part].p_size == 0) 164*33545Sbostic return (EPART); 165*33545Sbostic io->i_boff = lp->d_partitions[io->i_part].p_offset; 16630547Skarels return (0); 16710334Shelge } 16810334Shelge 16910334Shelge hpstrategy(io, func) 17010334Shelge register struct iob *io; 17110334Shelge { 172*33545Sbostic register int unit = io->i_unit; 173*33545Sbostic register struct hp_softc *sc; 174*33545Sbostic register struct disklabel *lp; 175*33545Sbostic struct mba_regs *mba; 176*33545Sbostic struct hpdevice *hpaddr; 17711366Ssam daddr_t bn, startblock; 17833409Skarels int cn, tn, sn, bytecnt, bytesleft, rv; 179*33545Sbostic int er1, er2, hprecal; 18010334Shelge char *membase; 18110334Shelge 182*33545Sbostic mba = mbamba(io->i_adapt); 183*33545Sbostic hpaddr = (struct hpdevice *)mbadrv(io->i_adapt, unit); 184*33545Sbostic sc = &hp_softc[io->i_adapt][unit]; 185*33545Sbostic lp = &hplabel[io->i_adapt][unit]; 18630547Skarels #ifndef SMALL 18710334Shelge sectsiz = SECTSIZ; 18810334Shelge if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0) 18910334Shelge sectsiz += HDRSIZ; 19010334Shelge if ((hpaddr->hpds & HPDS_VV) == 0) { 19110334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 19210334Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 19330547Skarels if (!ML11(sc->type)) 19410334Shelge hpaddr->hpof = HPOF_FMT22; 19510334Shelge } 19610334Shelge io->i_errcnt = 0; 19725439Skarels sc->ssect = 0; 19825439Skarels rv = bytecnt = io->i_cc; 19910334Shelge membase = io->i_ma; 20010334Shelge startblock = io->i_bn; 20110608Ssam hprecal = 0; 20230547Skarels #endif 20311140Ssam 20410626Shelge restart: 20510334Shelge bn = io->i_bn; 20630547Skarels cn = bn / lp->d_secpercyl; 20730547Skarels sn = bn % lp->d_secpercyl; 20830547Skarels tn = sn / lp->d_nsectors; 20930547Skarels sn = sn % lp->d_nsectors + sc->ssect; 21010334Shelge 21110864Ssam HPWAIT(hpaddr); 21210626Shelge mba->mba_sr = -1; 21330547Skarels if (ML11(sc->type)) 21410334Shelge hpaddr->hpda = bn; 21510334Shelge else { 21610334Shelge hpaddr->hpdc = cn; 21710334Shelge hpaddr->hpda = (tn << 8) + sn; 21810334Shelge } 21930547Skarels #ifdef SMALL 220*33545Sbostic mbastart(io, io->i_unit, func); /* start transfer */ 22130547Skarels HPWAIT(hpaddr); 22230547Skarels if (hpaddr->hpds & HPDS_ERR) { 22330547Skarels printf("hp error: sn [%d-%d) ds=%b er1=%b\n", 22430547Skarels bn, bn + io->i_cc/SECTSIZ, MASKREG(hpaddr->hpds), HPDS_BITS, 22530547Skarels MASKREG(hpaddr->hper1), HPER1_BITS); 22630547Skarels return (-1); 22730547Skarels } 22830547Skarels return (io->i_cc); 22930547Skarels #else 230*33545Sbostic if (mbastart(io, io->i_unit, func) != 0) { /* start transfer */ 23125439Skarels rv = -1; 23225439Skarels goto done; 23325439Skarels } 23410864Ssam HPWAIT(hpaddr); 23511366Ssam /* 23611366Ssam * Successful data transfer, return. 23711366Ssam */ 23815068Skarels if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0) 23915068Skarels goto done; 24010334Shelge 24111366Ssam /* 24211366Ssam * Error handling. Calculate location of error. 24311366Ssam */ 24411366Ssam bytesleft = MASKREG(mba->mba_bcr); 24511366Ssam if (bytesleft) 24611366Ssam bytesleft |= 0xffff0000; /* sxt */ 24711366Ssam bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz; 24815052Skarels er1 = MASKREG(hpaddr->hper1); 24915052Skarels er2 = MASKREG(hpaddr->hper2); 25015052Skarels if (er1 & (HPER1_DCK|HPER1_ECH)) 25115052Skarels bn--; /* Error is in Prev block */ 25230547Skarels cn = bn/lp->d_secpercyl; 25330547Skarels sn = bn%lp->d_secpercyl; 25430547Skarels tn = sn/lp->d_nsectors; 25530547Skarels sn = sn%lp->d_nsectors; 25625439Skarels if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) { 25725439Skarels printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b\n", 25825439Skarels bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 25911366Ssam printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS); 26011366Ssam printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft, 26111366Ssam hpaddr->hpof, hpaddr->hpda); 26211366Ssam } 26310334Shelge if (er1 & HPER1_HCRC) { 26410334Shelge er1 &= ~(HPER1_HCE|HPER1_FER); 26510334Shelge er2 &= ~HPER2_BSE; 26625439Skarels if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0) 26725439Skarels goto success; 26810334Shelge } 26911140Ssam /* 27011140Ssam * Give up early if drive write locked. 27111140Ssam */ 27210334Shelge if (er1&HPER1_WLE) { 27310334Shelge printf("hp%d: write locked\n", unit); 27425439Skarels rv = -1; 27525439Skarels goto done; 27611084Ssam } 27711140Ssam /* 27825439Skarels * Skip sector handling. 27911140Ssam */ 28030547Skarels if (RM80(sc->type) && (er2 & HPER2_SSE)) { 28125439Skarels (void) hpecc(io, SSE); 28225439Skarels sc->ssect = 1; 28325439Skarels goto restart; 28411084Ssam } 28511140Ssam /* 28625439Skarels * Attempt to forward bad sectors on anything but an ML11. 28725439Skarels * Interpret format error bit as a bad block on RP06's. 28811140Ssam */ 28930547Skarels if (((er2 & HPER2_BSE) && !ML11(sc->type)) || 29030547Skarels (MASKREG(er1) == HPER1_FER && RP06(sc->type))) { 29111084Ssam if (io->i_flgs & F_NBSF) { 292*33545Sbostic io->i_error = EBSE; 29310334Shelge goto hard; 29410334Shelge } 29510334Shelge if (hpecc(io, BSE) == 0) 29610334Shelge goto success; 29711084Ssam io->i_error = EBSE; 29811084Ssam goto hard; 29911084Ssam } 30011140Ssam /* 30111366Ssam * ECC correction? 30211140Ssam */ 30311084Ssam if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) { 30410864Ssam if (hpecc(io, ECC) == 0) 30510334Shelge goto success; 30611084Ssam io->i_error = EECC; 30725439Skarels goto hard; 30810608Ssam } 30925439Skarels 31025439Skarels /* 31125439Skarels * If a hard error, or maximum retry count 31225439Skarels * exceeded, clear controller state and 31325439Skarels * pass back error to caller. 31425439Skarels */ 31525439Skarels if (++io->i_errcnt > sc->retries || (er1 & HPER1_HARD) || 31630547Skarels (!ML11(sc->type) && (er2 & HPER2_HARD)) || 31730547Skarels (ML11(sc->type) && (io->i_errcnt >= 16))) { 31825439Skarels io->i_error = EHER; 31925439Skarels if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR)) 32025439Skarels io->i_error = EWCK; 32125439Skarels hard: 32225439Skarels io->i_errblk = bn + sc->ssect; 32325439Skarels if (sc->debug & (HPF_BSEDEBUG|HPF_ECCDEBUG)) 32425439Skarels printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc), 32525439Skarels MASKREG(hpaddr->hpda)); 32625439Skarels else { 32725439Skarels printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", 32825439Skarels bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 32925439Skarels printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS); 33025439Skarels } 33125439Skarels hpaddr->hpcs1 = HP_DCLR|HP_GO; 33225439Skarels printf("\n"); 33325439Skarels rv = -1; 33425439Skarels goto done; 33525439Skarels 33625439Skarels } 33710608Ssam /* fall thru to retry */ 33810334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 33910864Ssam HPWAIT(hpaddr); 34011140Ssam 34111140Ssam /* 34211140Ssam * Every fourth retry recalibrate. 34311140Ssam */ 34411366Ssam if (((io->i_errcnt & 07) == 4) ) { 34510334Shelge hpaddr->hpcs1 = HP_RECAL|HP_GO; 34615052Skarels HPWAIT(hpaddr); 34710334Shelge hpaddr->hpdc = cn; 34810334Shelge hpaddr->hpcs1 = HP_SEEK|HP_GO; 34915052Skarels HPWAIT(hpaddr); 35015052Skarels } 35110864Ssam 35215052Skarels if (io->i_errcnt >= 16 && (io->i_flgs & F_READ)) { 35310334Shelge hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22; 35410334Shelge hpaddr->hpcs1 = HP_OFFSET|HP_GO; 35515052Skarels HPWAIT(hpaddr); 35610334Shelge } 35725439Skarels if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 35815052Skarels printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 35915052Skarels io->i_bn, io->i_cc, io->i_ma, hprecal); 36025439Skarels goto restart; 36111084Ssam 36211140Ssam success: 36311140Ssam /* 36411140Ssam * On successful error recovery, bump 36511140Ssam * block number to advance to next portion 36611140Ssam * of i/o transfer. 36711140Ssam */ 36810334Shelge bn++; 36910334Shelge if ((bn-startblock) * sectsiz < bytecnt) { 37010334Shelge io->i_bn = bn; 37110334Shelge io->i_ma = membase + (io->i_bn - startblock)*sectsiz; 37210334Shelge io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz; 37325439Skarels if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 37411366Ssam printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 37511366Ssam io->i_bn, io->i_cc, io->i_ma, hprecal); 37610626Shelge goto restart; 37710334Shelge } 37815068Skarels done: 37915052Skarels if (io->i_errcnt >= 16) { 38015052Skarels hpaddr->hpcs1 = HP_RTC|HP_GO; 38115052Skarels while (hpaddr->hpds & HPDS_PIP) 38215052Skarels ; 38315052Skarels } 38425439Skarels io->i_bn = startblock; /*reset i_bn to original */ 38518515Smiriam io->i_cc = bytecnt; /*reset i_cc to total count xfered*/ 38625439Skarels io->i_ma = membase; /*reset i_ma to original */ 38725439Skarels return (rv); 38830547Skarels #endif 38910334Shelge } 39010864Ssam 39130547Skarels #ifndef SMALL 39210334Shelge hpecc(io, flag) 39310334Shelge register struct iob *io; 39410334Shelge int flag; 39510334Shelge { 396*33545Sbostic register int unit = io->i_unit; 397*33545Sbostic register struct mba_regs *mbp; 398*33545Sbostic register struct hpdevice *rp; 399*33545Sbostic register struct hp_softc *sc; 400*33545Sbostic register struct disklabel *lp; 40111084Ssam int npf, bn, cn, tn, sn, bcr; 40210334Shelge 403*33545Sbostic mbp = mbamba(io->i_adapt); 404*33545Sbostic rp = (struct hpdevice *)mbadrv(io->i_adapt, unit); 405*33545Sbostic sc = &hp_softc[io->i_adapt][unit]; 406*33545Sbostic lp = &hplabel[io->i_adapt][unit]; 40711366Ssam bcr = MASKREG(mbp->mba_bcr); 40811366Ssam if (bcr) 40911366Ssam bcr |= 0xffff0000; /* sxt */ 41011084Ssam npf = (bcr + io->i_cc) / sectsiz; /* # sectors read */ 41115052Skarels if (flag == ECC) 41215052Skarels npf--; /* Error is in prev block --ghg */ 41325439Skarels bn = io->i_bn + npf + sc->ssect; /* physical block #*/ 41425439Skarels if (sc->debug & HPF_ECCDEBUG) 41511366Ssam printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n", 41625439Skarels bcr, npf, sc->ssect, sectsiz, io->i_cc); 41711140Ssam /* 41811140Ssam * ECC correction logic. 41911140Ssam */ 42011140Ssam if (flag == ECC) { 42110334Shelge register int i; 42210334Shelge caddr_t addr; 42325439Skarels int bit, o, mask; 42410334Shelge 42510413Shelge printf("hp%d: soft ecc sn%d\n", unit, bn); 42610334Shelge mask = MASKREG(rp->hpec2); 42725439Skarels for (i = mask, bit = 0; i; i >>= 1) 42825439Skarels if (i & 1) 42925439Skarels bit++; 43025439Skarels if (bit > sc->ecclim) { 43125439Skarels printf("%d-bit error\n", bit); 43225439Skarels return (1); 43325439Skarels } 43411084Ssam i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 43510334Shelge bit = i&07; 43611366Ssam o = (i & ~07) >> 3; 43710334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 43811179Ssam while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) { 43911179Ssam addr = io->i_ma + (npf*sectsiz) + o; 44011179Ssam /* 44111179Ssam * No data transfer occurs with a write check, 44211179Ssam * so don't correct the resident copy of data. 44311179Ssam */ 44411366Ssam if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { 44525439Skarels if (sc->debug & HPF_ECCDEBUG) 44611366Ssam printf("addr=%x old=%x ", addr, 44711366Ssam (*addr & 0xff)); 44811140Ssam *addr ^= (mask << bit); 44925439Skarels if (sc->debug & HPF_ECCDEBUG) 45011366Ssam printf("new=%x\n",(*addr & 0xff)); 45111366Ssam } 45211179Ssam o++, bit -= 8; 45310334Shelge } 45411179Ssam return (0); 45511084Ssam } 45610334Shelge 45711084Ssam /* 45811084Ssam * Skip sector error. 45911084Ssam * Set skip-sector-inhibit and 46011084Ssam * read next sector 46111084Ssam */ 46211140Ssam if (flag == SSE) { 46310334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 46410864Ssam HPWAIT(rp); 46510334Shelge rp->hpof |= HPOF_SSEI; 466*33545Sbostic return (0); 46711140Ssam } 46810334Shelge 46911140Ssam /* 47011140Ssam * Bad block forwarding. 47111140Ssam */ 47211140Ssam if (flag == BSE) { 47310626Shelge int bbn; 47411084Ssam 47510626Shelge rp->hpcs1 = HP_DCLR | HP_GO; 47625439Skarels if (sc->debug & HPF_BSEDEBUG) 47711366Ssam printf("hpecc: BSE @ bn %d\n", bn); 47830547Skarels cn = bn / lp->d_secpercyl; 47930547Skarels sn = bn % lp->d_secpercyl; 48030547Skarels tn = sn / lp->d_nsectors; 48130547Skarels sn = sn % lp->d_nsectors; 48210626Shelge bcr += sectsiz; 483*33545Sbostic if ((bbn = isbad(&hpbad[io->i_adapt][unit], cn, tn, sn)) < 0) 48411084Ssam return (1); 48530547Skarels bbn = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors - 1 48630547Skarels - bbn; 48730547Skarels cn = bbn / lp->d_secpercyl; 48830547Skarels sn = bbn % lp->d_secpercyl; 48930547Skarels tn = sn / lp->d_nsectors; 49033409Skarels sn = sn % lp->d_nsectors; 49110626Shelge io->i_cc = sectsiz; 49230547Skarels io->i_ma += npf * sectsiz; 49325439Skarels if (sc->debug & HPF_BSEDEBUG) 49411366Ssam printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 49511366Ssam rp->hpof &= ~HPOF_SSEI; 49610626Shelge mbp->mba_sr = -1; 49710334Shelge rp->hpdc = cn; 49810334Shelge rp->hpda = (tn<<8) + sn; 499*33545Sbostic mbastart(io, io->i_unit, io->i_flgs); 50011366Ssam io->i_errcnt = 0; 50110864Ssam HPWAIT(rp); 50210864Ssam return (rp->hpds&HPDS_ERR); 50310334Shelge } 50411084Ssam printf("hpecc: flag=%d\n", flag); 50511084Ssam return (1); 50610334Shelge } 50711140Ssam 50810334Shelge /*ARGSUSED*/ 50910334Shelge hpioctl(io, cmd, arg) 51010334Shelge struct iob *io; 51110334Shelge int cmd; 51210334Shelge caddr_t arg; 51310334Shelge { 51410647Shelge register unit = io->i_unit; 515*33545Sbostic register struct hp_softc *sc = &hp_softc[io->i_adapt][unit]; 516*33545Sbostic register struct disklabel *lp = &hplabel[io->i_adapt][unit]; 517*33545Sbostic struct mba_drv *drv = mbadrv(io->i_adapt, unit); 51810334Shelge 51910334Shelge switch(cmd) { 52010334Shelge 52111366Ssam case SAIODEBUG: 52225439Skarels sc->debug = (int)arg; 52325439Skarels break; 52411366Ssam 52510334Shelge case SAIODEVDATA: 52625439Skarels if (drv->mbd_dt&MBDT_TAP) 52725439Skarels return (ECMD); 52830547Skarels *(struct disklabel *)arg = *lp; 52925439Skarels break; 53010334Shelge 53125439Skarels case SAIOGBADINFO: 53225439Skarels if (drv->mbd_dt&MBDT_TAP) 53325439Skarels return (ECMD); 534*33545Sbostic *(struct dkbad *)arg = hpbad[io->i_adapt][unit]; 53525439Skarels break; 53625439Skarels 53725439Skarels case SAIOECCLIM: 53825439Skarels sc->ecclim = (int)arg; 53925439Skarels break; 54025439Skarels 54125439Skarels case SAIORETRIES: 54225439Skarels sc->retries = (int)arg; 54325439Skarels break; 54425439Skarels 54511084Ssam case SAIOSSI: /* skip-sector-inhibit */ 54611084Ssam if (drv->mbd_dt&MBDT_TAP) 54711084Ssam return (ECMD); 54811084Ssam if ((io->i_flgs&F_SSI) == 0) { 54911084Ssam /* make sure this is done once only */ 55011084Ssam io->i_flgs |= F_SSI; 55130547Skarels lp->d_nsectors++; 55230547Skarels lp->d_secpercyl += lp->d_ntracks; 55310864Ssam } 55425439Skarels break; 55510626Shelge 55611084Ssam case SAIONOSSI: /* remove skip-sector-inhibit */ 55710626Shelge if (io->i_flgs & F_SSI) { 55810626Shelge io->i_flgs &= ~F_SSI; 55910626Shelge drv->mbd_of &= ~HPOF_SSEI; 56030547Skarels lp->d_nsectors--; 56130547Skarels lp->d_secpercyl -= lp->d_ntracks; 56210626Shelge } 56325439Skarels break; 56410626Shelge 56510864Ssam case SAIOSSDEV: /* drive have skip sector? */ 56630547Skarels return (RM80(sc->type) ? 0 : ECMD); 56725439Skarels 56825439Skarels default: 56925439Skarels return (ECMD); 57010334Shelge } 57125439Skarels return (0); 57210334Shelge } 573*33545Sbostic #endif /* !SMALL */ 574