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*45803Sbostic * @(#)hp.c 7.12 (Berkeley) 12/16/90 723225Smckusick */ 810334Shelge 910334Shelge /* 1033545Sbostic * RP??/RM?? disk driver with ECC handling and bad block forwarding. 1133545Sbostic * Also supports header io operations and commands to write check 1233545Sbostic * header and data. 1310334Shelge */ 14*45803Sbostic #include "sys/param.h" 15*45803Sbostic #include "sys/dkbad.h" 16*45803Sbostic #include "sys/disklabel.h" 1710334Shelge 18*45803Sbostic #include "../include/pte.h" 1933409Skarels 20*45803Sbostic #include "../mba/hpreg.h" 21*45803Sbostic #include "../mba/mbareg.h" 2210334Shelge 23*45803Sbostic #include "stand/saio.h" 2410334Shelge #include "savax.h" 2510334Shelge 2625439Skarels #define RETRIES 27 2725439Skarels 2810334Shelge #define MASKREG(reg) ((reg)&0xffff) 2910334Shelge 3011366Ssam #define MAXBADDESC 126 3111366Ssam #define SECTSIZ 512 /* sector size in bytes */ 3211366Ssam #define HDRSIZ 4 /* number of bytes in sector header */ 3310334Shelge 3430547Skarels char lbuf[SECTSIZ]; 3510334Shelge 3630547Skarels #define RP06(type) ((type) == MBDT_RP06 || (type) == MBDT_RP05 \ 3730547Skarels || (type) == MBDT_RP04) 3830547Skarels #define ML11(type) ((type) == MBDT_ML11A) 3930547Skarels #define RM80(type) ((type) == MBDT_RM80) 4010334Shelge 4110334Shelge u_char hp_offset[16] = { 4233545Sbostic HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 4333545Sbostic HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 4433545Sbostic HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 4533545Sbostic 0, 0, 0, 0, 4610334Shelge }; 4710334Shelge 4833545Sbostic #define MAXUNIT 8 4933545Sbostic struct disklabel hplabel[MAXNMBA][MAXUNIT]; 5030547Skarels #ifndef SMALL 5133545Sbostic struct dkbad hpbad[MAXNMBA][MAXUNIT]; 5230547Skarels int sectsiz; 5330547Skarels #endif 5410334Shelge 5525439Skarels struct hp_softc { 5625439Skarels char type; 5725439Skarels char gottype; 5833545Sbostic char ssect; /* 1 when on track w/skip sector */ 5925439Skarels char debug; 6025439Skarels # define HPF_BSEDEBUG 01 /* debugging bad sector forwarding */ 6125439Skarels # define HPF_ECCDEBUG 02 /* debugging ecc correction */ 6225439Skarels int ecclim; 6325439Skarels int retries; 6433545Sbostic } hp_softc[MAXNMBA][MAXUNIT]; 6511366Ssam 6610864Ssam /* 6733545Sbostic * When awaiting command completion, don't hang on to the status register 6833545Sbostic * since this ties up some controllers. 6910864Ssam */ 7011366Ssam #define HPWAIT(addr) \ 7133545Sbostic while ((((addr)->hpds)&HPDS_DRY) == 0) \ 7233545Sbostic DELAY(500); 7310864Ssam 7410334Shelge hpopen(io) 7510334Shelge register struct iob *io; 7610334Shelge { 7710334Shelge register unit = io->i_unit; 7833545Sbostic register struct hp_softc *sc; 7933545Sbostic register struct disklabel *lp; 8033545Sbostic struct hpdevice *hpaddr; 8133041Skarels struct disklabel *dlp; 8234519Skarels int error = 0; 8310334Shelge 8434982Skarels /* 8534982Skarels * Accept adaptor number as either controller or adaptor, 8634982Skarels * but not both. 8734982Skarels */ 8834982Skarels if (io->i_ctlr) { 8934982Skarels if (io->i_adapt == 0) 9034982Skarels io->i_adapt = io->i_ctlr; 9134982Skarels else 9234982Skarels return (ECTLR); 9334982Skarels } 9433545Sbostic if ((u_int)io->i_adapt >= MAXNMBA || !mbainit(io->i_adapt)) 9533545Sbostic return (EADAPT); 9633545Sbostic if ((u_int)unit >= MAXUNIT) 9733545Sbostic return (EUNIT); 9833545Sbostic hpaddr = (struct hpdevice *)mbadrv(io->i_adapt, unit); 9933545Sbostic sc = &hp_softc[io->i_adapt][unit]; 10033545Sbostic lp = &hplabel[io->i_adapt][unit]; 10125439Skarels if (sc->gottype == 0) { 10233545Sbostic register int i; 10310334Shelge struct iob tio; 10410334Shelge 10530547Skarels #ifndef SMALL 10625439Skarels sc->retries = RETRIES; 10725439Skarels sc->ecclim = 11; 10825439Skarels sc->debug = 0; 10930547Skarels #endif 11010647Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; /* init drive */ 11110647Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 11230547Skarels #ifndef SMALL 11333547Sbostic if ((hpaddr->hpds & HPDS_DPR) == 0) 11433409Skarels return (ENXIO); 11530547Skarels sc->type = hpaddr->hpdt & MBDT_TYPE; 11630547Skarels if (sc->type == MBDT_ML11B) 11733409Skarels sc->type = MBDT_ML11A; 11830547Skarels if (!ML11(sc->type)) 11930547Skarels #endif 12010647Shelge hpaddr->hpof = HPOF_FMT22; 12110334Shelge /* 12230547Skarels * Read in the pack label. 12330547Skarels */ 12430547Skarels lp->d_nsectors = 32; 12530547Skarels lp->d_secpercyl = 20*32; 12630547Skarels tio = *io; 12730547Skarels tio.i_bn = LABELSECTOR; 12830547Skarels tio.i_ma = lbuf; 12930547Skarels tio.i_cc = SECTSIZ; 13030547Skarels tio.i_flgs |= F_RDDATA; 13133635Sbostic if (hpstrategy(&tio, READ) != SECTSIZ) 13234519Skarels error = ERDLAB; 13333041Skarels dlp = (struct disklabel *)(lbuf + LABELOFFSET); 13434519Skarels if (error == 0 && (dlp->d_magic != DISKMAGIC || 13534519Skarels dlp->d_magic2 != DISKMAGIC)) 13634519Skarels error = EUNLAB; 13734519Skarels if (error == 0) 13834519Skarels *lp = *dlp; 13934519Skarels else 14033635Sbostic #ifdef COMPAT_42 14134519Skarels if (hpmaptype(hpaddr, hpaddr->hpdt & MBDT_TYPE, unit, lp) == 0) 14230547Skarels #endif 14334519Skarels return (error); 14434519Skarels 14533041Skarels #ifndef SMALL 14630547Skarels /* 14711366Ssam * Read in the bad sector table. 14810334Shelge */ 14930547Skarels tio.i_bn = lp->d_secpercyl * lp->d_ncylinders - lp->d_nsectors; 15033545Sbostic tio.i_ma = (char *)&hpbad[io->i_adapt][unit]; 15133545Sbostic tio.i_cc = sizeof(struct dkbad); 15210334Shelge for (i = 0; i < 5; i++) { 15333545Sbostic if (hpstrategy(&tio, READ) == sizeof(struct dkbad)) 15410334Shelge break; 15510334Shelge tio.i_bn += 2; 15610334Shelge } 15710334Shelge if (i == 5) { 15833545Sbostic printf("hp: can't read bad sector table\n"); 15910334Shelge for (i = 0; i < MAXBADDESC; i++) { 16033545Sbostic hpbad[io->i_adapt][unit].bt_bad[i].bt_cyl = -1; 16133545Sbostic hpbad[io->i_adapt][unit].bt_bad[i].bt_trksec = -1; 16210334Shelge } 16325439Skarels } 16433041Skarels #endif 16525439Skarels sc->gottype = 1; 16610334Shelge } 16733545Sbostic if (io->i_part >= lp->d_npartitions || 16833545Sbostic lp->d_partitions[io->i_part].p_size == 0) 16933545Sbostic return (EPART); 17033545Sbostic io->i_boff = lp->d_partitions[io->i_part].p_offset; 17130547Skarels return (0); 17210334Shelge } 17310334Shelge 17410334Shelge hpstrategy(io, func) 17510334Shelge register struct iob *io; 17610334Shelge { 17733545Sbostic register int unit = io->i_unit; 17833545Sbostic register struct hp_softc *sc; 17933545Sbostic register struct disklabel *lp; 18033545Sbostic struct mba_regs *mba; 18133545Sbostic struct hpdevice *hpaddr; 18211366Ssam daddr_t bn, startblock; 18333409Skarels int cn, tn, sn, bytecnt, bytesleft, rv; 18433545Sbostic int er1, er2, hprecal; 18510334Shelge char *membase; 18610334Shelge 18733545Sbostic mba = mbamba(io->i_adapt); 18833545Sbostic hpaddr = (struct hpdevice *)mbadrv(io->i_adapt, unit); 18933545Sbostic sc = &hp_softc[io->i_adapt][unit]; 19033545Sbostic lp = &hplabel[io->i_adapt][unit]; 19130547Skarels #ifndef SMALL 19210334Shelge sectsiz = SECTSIZ; 19310334Shelge if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0) 19410334Shelge sectsiz += HDRSIZ; 19510334Shelge if ((hpaddr->hpds & HPDS_VV) == 0) { 19610334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 19710334Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 19830547Skarels if (!ML11(sc->type)) 19910334Shelge hpaddr->hpof = HPOF_FMT22; 20010334Shelge } 20110334Shelge io->i_errcnt = 0; 20225439Skarels sc->ssect = 0; 20325439Skarels rv = bytecnt = io->i_cc; 20410334Shelge membase = io->i_ma; 20510334Shelge startblock = io->i_bn; 20610608Ssam hprecal = 0; 20730547Skarels #endif 20811140Ssam 20910626Shelge restart: 21010334Shelge bn = io->i_bn; 21130547Skarels cn = bn / lp->d_secpercyl; 21230547Skarels sn = bn % lp->d_secpercyl; 21330547Skarels tn = sn / lp->d_nsectors; 21430547Skarels sn = sn % lp->d_nsectors + sc->ssect; 21510334Shelge 21610864Ssam HPWAIT(hpaddr); 21710626Shelge mba->mba_sr = -1; 21830547Skarels if (ML11(sc->type)) 21910334Shelge hpaddr->hpda = bn; 22010334Shelge else { 22110334Shelge hpaddr->hpdc = cn; 22210334Shelge hpaddr->hpda = (tn << 8) + sn; 22310334Shelge } 22430547Skarels #ifdef SMALL 22533545Sbostic mbastart(io, io->i_unit, func); /* start transfer */ 22630547Skarels HPWAIT(hpaddr); 22730547Skarels if (hpaddr->hpds & HPDS_ERR) { 22830547Skarels printf("hp error: sn [%d-%d) ds=%b er1=%b\n", 22930547Skarels bn, bn + io->i_cc/SECTSIZ, MASKREG(hpaddr->hpds), HPDS_BITS, 23030547Skarels MASKREG(hpaddr->hper1), HPER1_BITS); 23130547Skarels return (-1); 23230547Skarels } 23330547Skarels return (io->i_cc); 23430547Skarels #else 23533545Sbostic if (mbastart(io, io->i_unit, func) != 0) { /* start transfer */ 23625439Skarels rv = -1; 23725439Skarels goto done; 23825439Skarels } 23910864Ssam HPWAIT(hpaddr); 24011366Ssam /* 24111366Ssam * Successful data transfer, return. 24211366Ssam */ 24315068Skarels if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0) 24415068Skarels goto done; 24510334Shelge 24611366Ssam /* 24711366Ssam * Error handling. Calculate location of error. 24811366Ssam */ 24911366Ssam bytesleft = MASKREG(mba->mba_bcr); 25011366Ssam if (bytesleft) 25111366Ssam bytesleft |= 0xffff0000; /* sxt */ 25211366Ssam bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz; 25315052Skarels er1 = MASKREG(hpaddr->hper1); 25415052Skarels er2 = MASKREG(hpaddr->hper2); 25515052Skarels if (er1 & (HPER1_DCK|HPER1_ECH)) 25615052Skarels bn--; /* Error is in Prev block */ 25730547Skarels cn = bn/lp->d_secpercyl; 25830547Skarels sn = bn%lp->d_secpercyl; 25930547Skarels tn = sn/lp->d_nsectors; 26030547Skarels sn = sn%lp->d_nsectors; 26125439Skarels if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) { 26225439Skarels printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b\n", 26325439Skarels bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 26411366Ssam printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS); 26511366Ssam printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft, 26611366Ssam hpaddr->hpof, hpaddr->hpda); 26711366Ssam } 26810334Shelge if (er1 & HPER1_HCRC) { 26910334Shelge er1 &= ~(HPER1_HCE|HPER1_FER); 27010334Shelge er2 &= ~HPER2_BSE; 27125439Skarels if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0) 27225439Skarels goto success; 27310334Shelge } 27411140Ssam /* 27511140Ssam * Give up early if drive write locked. 27611140Ssam */ 27710334Shelge if (er1&HPER1_WLE) { 27810334Shelge printf("hp%d: write locked\n", unit); 27925439Skarels rv = -1; 28025439Skarels goto done; 28111084Ssam } 28211140Ssam /* 28325439Skarels * Skip sector handling. 28411140Ssam */ 28530547Skarels if (RM80(sc->type) && (er2 & HPER2_SSE)) { 28625439Skarels (void) hpecc(io, SSE); 28725439Skarels sc->ssect = 1; 28825439Skarels goto restart; 28911084Ssam } 29011140Ssam /* 29125439Skarels * Attempt to forward bad sectors on anything but an ML11. 29225439Skarels * Interpret format error bit as a bad block on RP06's. 29311140Ssam */ 29430547Skarels if (((er2 & HPER2_BSE) && !ML11(sc->type)) || 29530547Skarels (MASKREG(er1) == HPER1_FER && RP06(sc->type))) { 29611084Ssam if (io->i_flgs & F_NBSF) { 29733545Sbostic io->i_error = EBSE; 29810334Shelge goto hard; 29910334Shelge } 30010334Shelge if (hpecc(io, BSE) == 0) 30110334Shelge goto success; 30211084Ssam io->i_error = EBSE; 30311084Ssam goto hard; 30411084Ssam } 30511140Ssam /* 30611366Ssam * ECC correction? 30711140Ssam */ 30811084Ssam if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) { 30910864Ssam if (hpecc(io, ECC) == 0) 31010334Shelge goto success; 31111084Ssam io->i_error = EECC; 31225439Skarels goto hard; 31310608Ssam } 31425439Skarels 31525439Skarels /* 31625439Skarels * If a hard error, or maximum retry count 31725439Skarels * exceeded, clear controller state and 31825439Skarels * pass back error to caller. 31925439Skarels */ 32025439Skarels if (++io->i_errcnt > sc->retries || (er1 & HPER1_HARD) || 32130547Skarels (!ML11(sc->type) && (er2 & HPER2_HARD)) || 32230547Skarels (ML11(sc->type) && (io->i_errcnt >= 16))) { 32325439Skarels io->i_error = EHER; 32425439Skarels if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR)) 32525439Skarels io->i_error = EWCK; 32625439Skarels hard: 32725439Skarels io->i_errblk = bn + sc->ssect; 32825439Skarels if (sc->debug & (HPF_BSEDEBUG|HPF_ECCDEBUG)) 32925439Skarels printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc), 33025439Skarels MASKREG(hpaddr->hpda)); 33125439Skarels else { 33225439Skarels printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", 33325439Skarels bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 33425439Skarels printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS); 33525439Skarels } 33625439Skarels hpaddr->hpcs1 = HP_DCLR|HP_GO; 33725439Skarels printf("\n"); 33825439Skarels rv = -1; 33925439Skarels goto done; 34025439Skarels 34125439Skarels } 34210608Ssam /* fall thru to retry */ 34310334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 34410864Ssam HPWAIT(hpaddr); 34511140Ssam 34611140Ssam /* 34711140Ssam * Every fourth retry recalibrate. 34811140Ssam */ 34911366Ssam if (((io->i_errcnt & 07) == 4) ) { 35010334Shelge hpaddr->hpcs1 = HP_RECAL|HP_GO; 35115052Skarels HPWAIT(hpaddr); 35210334Shelge hpaddr->hpdc = cn; 35310334Shelge hpaddr->hpcs1 = HP_SEEK|HP_GO; 35415052Skarels HPWAIT(hpaddr); 35515052Skarels } 35610864Ssam 35715052Skarels if (io->i_errcnt >= 16 && (io->i_flgs & F_READ)) { 35810334Shelge hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22; 35910334Shelge hpaddr->hpcs1 = HP_OFFSET|HP_GO; 36015052Skarels HPWAIT(hpaddr); 36110334Shelge } 36225439Skarels if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 36315052Skarels printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 36415052Skarels io->i_bn, io->i_cc, io->i_ma, hprecal); 36525439Skarels goto restart; 36611084Ssam 36711140Ssam success: 36811140Ssam /* 36911140Ssam * On successful error recovery, bump 37011140Ssam * block number to advance to next portion 37111140Ssam * of i/o transfer. 37211140Ssam */ 37310334Shelge bn++; 37410334Shelge if ((bn-startblock) * sectsiz < bytecnt) { 37510334Shelge io->i_bn = bn; 37610334Shelge io->i_ma = membase + (io->i_bn - startblock)*sectsiz; 37710334Shelge io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz; 37825439Skarels if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 37911366Ssam printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 38011366Ssam io->i_bn, io->i_cc, io->i_ma, hprecal); 38110626Shelge goto restart; 38210334Shelge } 38315068Skarels done: 38415052Skarels if (io->i_errcnt >= 16) { 38515052Skarels hpaddr->hpcs1 = HP_RTC|HP_GO; 38615052Skarels while (hpaddr->hpds & HPDS_PIP) 38715052Skarels ; 38815052Skarels } 38925439Skarels io->i_bn = startblock; /*reset i_bn to original */ 39018515Smiriam io->i_cc = bytecnt; /*reset i_cc to total count xfered*/ 39125439Skarels io->i_ma = membase; /*reset i_ma to original */ 39225439Skarels return (rv); 39330547Skarels #endif 39410334Shelge } 39510864Ssam 39630547Skarels #ifndef SMALL 39710334Shelge hpecc(io, flag) 39810334Shelge register struct iob *io; 39910334Shelge int flag; 40010334Shelge { 40133545Sbostic register int unit = io->i_unit; 40233545Sbostic register struct mba_regs *mbp; 40333545Sbostic register struct hpdevice *rp; 40433545Sbostic register struct hp_softc *sc; 40533545Sbostic register struct disklabel *lp; 40611084Ssam int npf, bn, cn, tn, sn, bcr; 40710334Shelge 40833545Sbostic mbp = mbamba(io->i_adapt); 40933545Sbostic rp = (struct hpdevice *)mbadrv(io->i_adapt, unit); 41033545Sbostic sc = &hp_softc[io->i_adapt][unit]; 41133545Sbostic lp = &hplabel[io->i_adapt][unit]; 41211366Ssam bcr = MASKREG(mbp->mba_bcr); 41311366Ssam if (bcr) 41411366Ssam bcr |= 0xffff0000; /* sxt */ 41511084Ssam npf = (bcr + io->i_cc) / sectsiz; /* # sectors read */ 41615052Skarels if (flag == ECC) 41715052Skarels npf--; /* Error is in prev block --ghg */ 41825439Skarels bn = io->i_bn + npf + sc->ssect; /* physical block #*/ 41925439Skarels if (sc->debug & HPF_ECCDEBUG) 42011366Ssam printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n", 42125439Skarels bcr, npf, sc->ssect, sectsiz, io->i_cc); 42211140Ssam /* 42311140Ssam * ECC correction logic. 42411140Ssam */ 42511140Ssam if (flag == ECC) { 42610334Shelge register int i; 42710334Shelge caddr_t addr; 42825439Skarels int bit, o, mask; 42910334Shelge 43010413Shelge printf("hp%d: soft ecc sn%d\n", unit, bn); 43110334Shelge mask = MASKREG(rp->hpec2); 43225439Skarels for (i = mask, bit = 0; i; i >>= 1) 43325439Skarels if (i & 1) 43425439Skarels bit++; 43525439Skarels if (bit > sc->ecclim) { 43625439Skarels printf("%d-bit error\n", bit); 43725439Skarels return (1); 43825439Skarels } 43911084Ssam i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 44010334Shelge bit = i&07; 44111366Ssam o = (i & ~07) >> 3; 44210334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 44311179Ssam while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) { 44411179Ssam addr = io->i_ma + (npf*sectsiz) + o; 44511179Ssam /* 44611179Ssam * No data transfer occurs with a write check, 44711179Ssam * so don't correct the resident copy of data. 44811179Ssam */ 44911366Ssam if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { 45025439Skarels if (sc->debug & HPF_ECCDEBUG) 45111366Ssam printf("addr=%x old=%x ", addr, 45211366Ssam (*addr & 0xff)); 45311140Ssam *addr ^= (mask << bit); 45425439Skarels if (sc->debug & HPF_ECCDEBUG) 45511366Ssam printf("new=%x\n",(*addr & 0xff)); 45611366Ssam } 45711179Ssam o++, bit -= 8; 45810334Shelge } 45911179Ssam return (0); 46011084Ssam } 46110334Shelge 46211084Ssam /* 46311084Ssam * Skip sector error. 46411084Ssam * Set skip-sector-inhibit and 46511084Ssam * read next sector 46611084Ssam */ 46711140Ssam if (flag == SSE) { 46810334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 46910864Ssam HPWAIT(rp); 47010334Shelge rp->hpof |= HPOF_SSEI; 47133545Sbostic return (0); 47211140Ssam } 47310334Shelge 47411140Ssam /* 47511140Ssam * Bad block forwarding. 47611140Ssam */ 47711140Ssam if (flag == BSE) { 47810626Shelge int bbn; 47911084Ssam 48010626Shelge rp->hpcs1 = HP_DCLR | HP_GO; 48125439Skarels if (sc->debug & HPF_BSEDEBUG) 48211366Ssam printf("hpecc: BSE @ bn %d\n", bn); 48330547Skarels cn = bn / lp->d_secpercyl; 48430547Skarels sn = bn % lp->d_secpercyl; 48530547Skarels tn = sn / lp->d_nsectors; 48630547Skarels sn = sn % lp->d_nsectors; 48710626Shelge bcr += sectsiz; 48833545Sbostic if ((bbn = isbad(&hpbad[io->i_adapt][unit], cn, tn, sn)) < 0) 48911084Ssam return (1); 49030547Skarels bbn = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors - 1 49130547Skarels - bbn; 49230547Skarels cn = bbn / lp->d_secpercyl; 49330547Skarels sn = bbn % lp->d_secpercyl; 49430547Skarels tn = sn / lp->d_nsectors; 49533409Skarels sn = sn % lp->d_nsectors; 49610626Shelge io->i_cc = sectsiz; 49730547Skarels io->i_ma += npf * sectsiz; 49825439Skarels if (sc->debug & HPF_BSEDEBUG) 49911366Ssam printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 50011366Ssam rp->hpof &= ~HPOF_SSEI; 50110626Shelge mbp->mba_sr = -1; 50210334Shelge rp->hpdc = cn; 50310334Shelge rp->hpda = (tn<<8) + sn; 50433545Sbostic mbastart(io, io->i_unit, io->i_flgs); 50511366Ssam io->i_errcnt = 0; 50610864Ssam HPWAIT(rp); 50710864Ssam return (rp->hpds&HPDS_ERR); 50810334Shelge } 50911084Ssam printf("hpecc: flag=%d\n", flag); 51011084Ssam return (1); 51110334Shelge } 51211140Ssam 51310334Shelge /*ARGSUSED*/ 51410334Shelge hpioctl(io, cmd, arg) 51510334Shelge struct iob *io; 51610334Shelge int cmd; 51710334Shelge caddr_t arg; 51810334Shelge { 51910647Shelge register unit = io->i_unit; 52033545Sbostic register struct hp_softc *sc = &hp_softc[io->i_adapt][unit]; 52133545Sbostic register struct disklabel *lp = &hplabel[io->i_adapt][unit]; 52233545Sbostic struct mba_drv *drv = mbadrv(io->i_adapt, unit); 52310334Shelge 52410334Shelge switch(cmd) { 52510334Shelge 52611366Ssam case SAIODEBUG: 52725439Skarels sc->debug = (int)arg; 52825439Skarels break; 52911366Ssam 53010334Shelge case SAIODEVDATA: 53125439Skarels if (drv->mbd_dt&MBDT_TAP) 53225439Skarels return (ECMD); 53330547Skarels *(struct disklabel *)arg = *lp; 53425439Skarels break; 53510334Shelge 53625439Skarels case SAIOGBADINFO: 53725439Skarels if (drv->mbd_dt&MBDT_TAP) 53825439Skarels return (ECMD); 53933545Sbostic *(struct dkbad *)arg = hpbad[io->i_adapt][unit]; 54025439Skarels break; 54125439Skarels 54225439Skarels case SAIOECCLIM: 54325439Skarels sc->ecclim = (int)arg; 54425439Skarels break; 54525439Skarels 54625439Skarels case SAIORETRIES: 54725439Skarels sc->retries = (int)arg; 54825439Skarels break; 54925439Skarels 55011084Ssam case SAIOSSI: /* skip-sector-inhibit */ 55111084Ssam if (drv->mbd_dt&MBDT_TAP) 55211084Ssam return (ECMD); 55311084Ssam if ((io->i_flgs&F_SSI) == 0) { 55411084Ssam /* make sure this is done once only */ 55511084Ssam io->i_flgs |= F_SSI; 55630547Skarels lp->d_nsectors++; 55730547Skarels lp->d_secpercyl += lp->d_ntracks; 55810864Ssam } 55925439Skarels break; 56010626Shelge 56111084Ssam case SAIONOSSI: /* remove skip-sector-inhibit */ 56210626Shelge if (io->i_flgs & F_SSI) { 56310626Shelge io->i_flgs &= ~F_SSI; 56410626Shelge drv->mbd_of &= ~HPOF_SSEI; 56530547Skarels lp->d_nsectors--; 56630547Skarels lp->d_secpercyl -= lp->d_ntracks; 56710626Shelge } 56825439Skarels break; 56910626Shelge 57010864Ssam case SAIOSSDEV: /* drive have skip sector? */ 57130547Skarels return (RM80(sc->type) ? 0 : ECMD); 57225439Skarels 57325439Skarels default: 57425439Skarels return (ECMD); 57510334Shelge } 57625439Skarels return (0); 57710334Shelge } 57833545Sbostic #endif /* !SMALL */ 579