123225Smckusick /* 223225Smckusick * Copyright (c) 1982 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*25439Skarels * @(#)hp.c 6.8 (Berkeley) 11/08/85 723225Smckusick */ 810334Shelge 910334Shelge /* 1010334Shelge * RP??/RM?? disk driver 1110334Shelge * with ECC handling and bad block forwarding. 1210334Shelge * Also supports header io operations and 1310334Shelge * commands to write check header and data. 1410334Shelge */ 1510334Shelge #include "../h/param.h" 1610334Shelge #include "../h/inode.h" 1710334Shelge #include "../h/fs.h" 1810334Shelge #include "../h/dkbad.h" 1910334Shelge 2010334Shelge #include "../vax/pte.h" 2110334Shelge #include "../vaxmba/hpreg.h" 2210334Shelge #include "../vaxmba/mbareg.h" 2310334Shelge 2410334Shelge #include "saio.h" 2510334Shelge #include "savax.h" 2610334Shelge 27*25439Skarels #define RETRIES 27 28*25439Skarels 2910334Shelge #define MASKREG(reg) ((reg)&0xffff) 3010334Shelge 3111366Ssam #define MAXBADDESC 126 3211366Ssam #define SECTSIZ 512 /* sector size in bytes */ 3311366Ssam #define HDRSIZ 4 /* number of bytes in sector header */ 3410334Shelge 3511140Ssam extern struct st hpst[]; 36*25439Skarels extern short hptypes[]; 3710334Shelge 38*25439Skarels #define RP06 (hptypes[sc->type] == MBDT_RP06 || hptypes[sc->type] == MBDT_RP05 \ 39*25439Skarels || hptypes[sc->type] == MBDT_RP04) 40*25439Skarels #define ML11 (hptypes[sc->type] == MBDT_ML11A) 41*25439Skarels #define RM80 (hptypes[sc->type] == MBDT_RM80) 4210334Shelge 4310334Shelge u_char hp_offset[16] = { 4410334Shelge HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 4510334Shelge HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 4610334Shelge HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 4710334Shelge 0, 0, 0, 0, 4810334Shelge }; 4910334Shelge 5011366Ssam struct dkbad hpbad[MAXNMBA*8]; 5110334Shelge 52*25439Skarels struct hp_softc { 53*25439Skarels char type; 54*25439Skarels char gottype; 55*25439Skarels char ssect; /* 1 when on track w/skip sector */ 56*25439Skarels char debug; 57*25439Skarels # define HPF_BSEDEBUG 01 /* debugging bad sector forwarding */ 58*25439Skarels # define HPF_ECCDEBUG 02 /* debugging ecc correction */ 59*25439Skarels int ecclim; 60*25439Skarels int retries; 61*25439Skarels } hp_softc[MAXNMBA * 8]; 6211366Ssam 6311366Ssam int sectsiz; 6411366Ssam 6510864Ssam /* 6610864Ssam * When awaiting command completion, don't 6710864Ssam * hang on to the status register since 6811366Ssam * this ties up some controllers. 6910864Ssam */ 7011366Ssam #define HPWAIT(addr) \ 7111366Ssam while ((((addr)->hpds)&HPDS_DRY)==0) DELAY(500); 7210864Ssam 7310334Shelge hpopen(io) 7410334Shelge register struct iob *io; 7510334Shelge { 7610334Shelge register unit = io->i_unit; 7710334Shelge struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 7810353Shelge register struct st *st; 79*25439Skarels register struct hp_softc *sc = &hp_softc[unit]; 8010334Shelge 8110334Shelge mbainit(UNITTOMBA(unit)); 82*25439Skarels if (sc->gottype == 0) { 8311366Ssam register i, type = hpaddr->hpdt & MBDT_TYPE; 8410334Shelge struct iob tio; 8510334Shelge 8610334Shelge for (i = 0; hptypes[i]; i++) 8710334Shelge if (hptypes[i] == type) 8810334Shelge goto found; 8910334Shelge _stop("unknown drive type"); 9010334Shelge found: 91*25439Skarels sc->retries = RETRIES; 92*25439Skarels sc->ecclim = 11; 93*25439Skarels sc->debug = 0; 9410647Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; /* init drive */ 9510647Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 9610647Shelge if (!ML11) 9710647Shelge hpaddr->hpof = HPOF_FMT22; 98*25439Skarels sc->type = hpmaptype(hpaddr, i, UNITTODRIVE(unit)); 9910334Shelge /* 10011366Ssam * Read in the bad sector table. 10110334Shelge */ 102*25439Skarels st = &hpst[sc->type]; 10310334Shelge tio = *io; 10410334Shelge tio.i_bn = st->nspc * st->ncyl - st->nsect; 10510626Shelge tio.i_ma = (char *)&hpbad[unit]; 10610628Shelge tio.i_cc = sizeof (struct dkbad); 10710334Shelge tio.i_flgs |= F_RDDATA; 10810334Shelge for (i = 0; i < 5; i++) { 10910628Shelge if (hpstrategy(&tio, READ) == sizeof (struct dkbad)) 11010334Shelge break; 11110334Shelge tio.i_bn += 2; 11210334Shelge } 11310334Shelge if (i == 5) { 11410334Shelge printf("Unable to read bad sector table\n"); 11510334Shelge for (i = 0; i < MAXBADDESC; i++) { 11610334Shelge hpbad[unit].bt_bad[i].bt_cyl = -1; 11710334Shelge hpbad[unit].bt_bad[i].bt_trksec = -1; 11810334Shelge } 119*25439Skarels } 120*25439Skarels sc->gottype = 1; 12110334Shelge } 122*25439Skarels st = &hpst[sc->type]; 12310334Shelge if (io->i_boff < 0 || io->i_boff > 7 || 12410334Shelge st->off[io->i_boff]== -1) 12510334Shelge _stop("hp bad minor"); 12610334Shelge io->i_boff = st->off[io->i_boff] * st->nspc; 12710334Shelge } 12810334Shelge 12910334Shelge hpstrategy(io, func) 13010334Shelge register struct iob *io; 13110334Shelge { 13210334Shelge register unit = io->i_unit; 13310334Shelge struct mba_regs *mba = mbamba(unit); 13411366Ssam daddr_t bn, startblock; 13510334Shelge struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 136*25439Skarels register struct hp_softc *sc = &hp_softc[unit]; 137*25439Skarels struct st *st = &hpst[sc->type]; 138*25439Skarels int cn, tn, sn, bytecnt, bytesleft, rv; 13910334Shelge char *membase; 14010334Shelge int er1, er2, hprecal; 14110334Shelge 14210334Shelge sectsiz = SECTSIZ; 14310334Shelge if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0) 14410334Shelge sectsiz += HDRSIZ; 14510334Shelge if ((hpaddr->hpds & HPDS_VV) == 0) { 14610334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 14710334Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 14811084Ssam if (!ML11) 14910334Shelge hpaddr->hpof = HPOF_FMT22; 15010334Shelge } 15110334Shelge io->i_errcnt = 0; 152*25439Skarels sc->ssect = 0; 153*25439Skarels rv = bytecnt = io->i_cc; 15410334Shelge membase = io->i_ma; 15510334Shelge startblock = io->i_bn; 15610608Ssam hprecal = 0; 15711140Ssam 15810626Shelge restart: 15910334Shelge bn = io->i_bn; 16010334Shelge cn = bn/st->nspc; 16110334Shelge sn = bn%st->nspc; 16210334Shelge tn = sn/st->nsect; 163*25439Skarels sn = sn%st->nsect + sc->ssect; 16410334Shelge 16510864Ssam HPWAIT(hpaddr); 16610626Shelge mba->mba_sr = -1; 16710647Shelge if (ML11) 16810334Shelge hpaddr->hpda = bn; 16910334Shelge else { 17010334Shelge hpaddr->hpdc = cn; 17110334Shelge hpaddr->hpda = (tn << 8) + sn; 17210334Shelge } 173*25439Skarels if (mbastart(io, func) != 0) { /* start transfer */ 174*25439Skarels rv = -1; 175*25439Skarels goto done; 176*25439Skarels } 17710864Ssam HPWAIT(hpaddr); 17811366Ssam /* 17911366Ssam * Successful data transfer, return. 18011366Ssam */ 18115068Skarels if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0) 18215068Skarels goto done; 18310334Shelge 18411366Ssam /* 18511366Ssam * Error handling. Calculate location of error. 18611366Ssam */ 18711366Ssam bytesleft = MASKREG(mba->mba_bcr); 18811366Ssam if (bytesleft) 18911366Ssam bytesleft |= 0xffff0000; /* sxt */ 19011366Ssam bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz; 19115052Skarels er1 = MASKREG(hpaddr->hper1); 19215052Skarels er2 = MASKREG(hpaddr->hper2); 19315052Skarels if (er1 & (HPER1_DCK|HPER1_ECH)) 19415052Skarels bn--; /* Error is in Prev block */ 19510334Shelge cn = bn/st->nspc; 19610334Shelge sn = bn%st->nspc; 19710334Shelge tn = sn/st->nsect; 19810334Shelge sn = sn%st->nsect; 199*25439Skarels if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) { 200*25439Skarels printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b\n", 201*25439Skarels bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 20211366Ssam printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS); 20311366Ssam printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft, 20411366Ssam hpaddr->hpof, hpaddr->hpda); 20511366Ssam } 20610334Shelge if (er1 & HPER1_HCRC) { 20710334Shelge er1 &= ~(HPER1_HCE|HPER1_FER); 20810334Shelge er2 &= ~HPER2_BSE; 209*25439Skarels if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0) 210*25439Skarels goto success; 21110334Shelge } 21211140Ssam /* 21311140Ssam * Give up early if drive write locked. 21411140Ssam */ 21510334Shelge if (er1&HPER1_WLE) { 21610334Shelge printf("hp%d: write locked\n", unit); 217*25439Skarels rv = -1; 218*25439Skarels goto done; 21911084Ssam } 22011140Ssam /* 221*25439Skarels * Skip sector handling. 22211140Ssam */ 223*25439Skarels if (RM80 && (er2 & HPER2_SSE)) { 224*25439Skarels (void) hpecc(io, SSE); 225*25439Skarels sc->ssect = 1; 226*25439Skarels goto restart; 22711084Ssam } 22811140Ssam /* 229*25439Skarels * Attempt to forward bad sectors on anything but an ML11. 230*25439Skarels * Interpret format error bit as a bad block on RP06's. 23111140Ssam */ 232*25439Skarels if (((er2 & HPER2_BSE) && !ML11) || 233*25439Skarels (MASKREG(er1) == HPER1_FER && RP06)) { 23411084Ssam if (io->i_flgs & F_NBSF) { 23510334Shelge io->i_error = EBSE; 23610334Shelge goto hard; 23710334Shelge } 23810334Shelge if (hpecc(io, BSE) == 0) 23910334Shelge goto success; 24011084Ssam io->i_error = EBSE; 24111084Ssam goto hard; 24211084Ssam } 24311140Ssam /* 24411366Ssam * ECC correction? 24511140Ssam */ 24611084Ssam if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) { 24710864Ssam if (hpecc(io, ECC) == 0) 24810334Shelge goto success; 24911084Ssam io->i_error = EECC; 250*25439Skarels goto hard; 25110608Ssam } 252*25439Skarels 253*25439Skarels /* 254*25439Skarels * If a hard error, or maximum retry count 255*25439Skarels * exceeded, clear controller state and 256*25439Skarels * pass back error to caller. 257*25439Skarels */ 258*25439Skarels if (++io->i_errcnt > sc->retries || (er1 & HPER1_HARD) || 259*25439Skarels (!ML11 && (er2 & HPER2_HARD)) || (ML11 && (io->i_errcnt >= 16))) { 260*25439Skarels io->i_error = EHER; 261*25439Skarels if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR)) 262*25439Skarels io->i_error = EWCK; 263*25439Skarels hard: 264*25439Skarels io->i_errblk = bn + sc->ssect; 265*25439Skarels if (sc->debug & (HPF_BSEDEBUG|HPF_ECCDEBUG)) 266*25439Skarels printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc), 267*25439Skarels MASKREG(hpaddr->hpda)); 268*25439Skarels else { 269*25439Skarels printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", 270*25439Skarels bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 271*25439Skarels printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS); 272*25439Skarels } 273*25439Skarels hpaddr->hpcs1 = HP_DCLR|HP_GO; 274*25439Skarels printf("\n"); 275*25439Skarels rv = -1; 276*25439Skarels goto done; 277*25439Skarels 278*25439Skarels } 27910608Ssam /* fall thru to retry */ 28010334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 28110864Ssam HPWAIT(hpaddr); 28211140Ssam 28311140Ssam /* 28411140Ssam * Every fourth retry recalibrate. 28511140Ssam */ 28611366Ssam if (((io->i_errcnt & 07) == 4) ) { 28710334Shelge hpaddr->hpcs1 = HP_RECAL|HP_GO; 28815052Skarels HPWAIT(hpaddr); 28910334Shelge hpaddr->hpdc = cn; 29010334Shelge hpaddr->hpcs1 = HP_SEEK|HP_GO; 29115052Skarels HPWAIT(hpaddr); 29215052Skarels } 29310864Ssam 29415052Skarels if (io->i_errcnt >= 16 && (io->i_flgs & F_READ)) { 29510334Shelge hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22; 29610334Shelge hpaddr->hpcs1 = HP_OFFSET|HP_GO; 29715052Skarels HPWAIT(hpaddr); 29810334Shelge } 299*25439Skarels if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 30015052Skarels printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 30115052Skarels io->i_bn, io->i_cc, io->i_ma, hprecal); 302*25439Skarels goto restart; 30311084Ssam 30411140Ssam success: 30511140Ssam /* 30611140Ssam * On successful error recovery, bump 30711140Ssam * block number to advance to next portion 30811140Ssam * of i/o transfer. 30911140Ssam */ 31010334Shelge bn++; 31110334Shelge if ((bn-startblock) * sectsiz < bytecnt) { 31210334Shelge io->i_bn = bn; 31310334Shelge io->i_ma = membase + (io->i_bn - startblock)*sectsiz; 31410334Shelge io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz; 315*25439Skarels if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 31611366Ssam printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 31711366Ssam io->i_bn, io->i_cc, io->i_ma, hprecal); 31810626Shelge goto restart; 31910334Shelge } 32015068Skarels done: 32115052Skarels if (io->i_errcnt >= 16) { 32215052Skarels hpaddr->hpcs1 = HP_RTC|HP_GO; 32315052Skarels while (hpaddr->hpds & HPDS_PIP) 32415052Skarels ; 32515052Skarels } 326*25439Skarels io->i_bn = startblock; /*reset i_bn to original */ 32718515Smiriam io->i_cc = bytecnt; /*reset i_cc to total count xfered*/ 328*25439Skarels io->i_ma = membase; /*reset i_ma to original */ 329*25439Skarels return (rv); 33010334Shelge } 33110864Ssam 33210334Shelge hpecc(io, flag) 33310334Shelge register struct iob *io; 33410334Shelge int flag; 33510334Shelge { 33610334Shelge register unit = io->i_unit; 33710334Shelge register struct mba_regs *mbp = mbamba(unit); 33810334Shelge register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit); 339*25439Skarels register struct hp_softc *sc = &hp_softc[unit]; 340*25439Skarels register struct st *st = &hpst[sc->type]; 34111084Ssam int npf, bn, cn, tn, sn, bcr; 34210334Shelge 34311366Ssam bcr = MASKREG(mbp->mba_bcr); 34411366Ssam if (bcr) 34511366Ssam bcr |= 0xffff0000; /* sxt */ 34611084Ssam npf = (bcr + io->i_cc) / sectsiz; /* # sectors read */ 34715052Skarels if (flag == ECC) 34815052Skarels npf--; /* Error is in prev block --ghg */ 349*25439Skarels bn = io->i_bn + npf + sc->ssect; /* physical block #*/ 350*25439Skarels if (sc->debug & HPF_ECCDEBUG) 35111366Ssam printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n", 352*25439Skarels bcr, npf, sc->ssect, sectsiz, io->i_cc); 35311140Ssam /* 35411140Ssam * ECC correction logic. 35511140Ssam */ 35611140Ssam if (flag == ECC) { 35710334Shelge register int i; 35810334Shelge caddr_t addr; 359*25439Skarels int bit, o, mask; 36010334Shelge 36110413Shelge printf("hp%d: soft ecc sn%d\n", unit, bn); 36210334Shelge mask = MASKREG(rp->hpec2); 363*25439Skarels for (i = mask, bit = 0; i; i >>= 1) 364*25439Skarels if (i & 1) 365*25439Skarels bit++; 366*25439Skarels if (bit > sc->ecclim) { 367*25439Skarels printf("%d-bit error\n", bit); 368*25439Skarels return (1); 369*25439Skarels } 37011084Ssam i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 37110334Shelge bit = i&07; 37211366Ssam o = (i & ~07) >> 3; 37310334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 37411179Ssam while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) { 37511179Ssam addr = io->i_ma + (npf*sectsiz) + o; 37611179Ssam /* 37711179Ssam * No data transfer occurs with a write check, 37811179Ssam * so don't correct the resident copy of data. 37911179Ssam */ 38011366Ssam if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { 381*25439Skarels if (sc->debug & HPF_ECCDEBUG) 38211366Ssam printf("addr=%x old=%x ", addr, 38311366Ssam (*addr & 0xff)); 38411140Ssam *addr ^= (mask << bit); 385*25439Skarels if (sc->debug & HPF_ECCDEBUG) 38611366Ssam printf("new=%x\n",(*addr & 0xff)); 38711366Ssam } 38811179Ssam o++, bit -= 8; 38910334Shelge } 39011179Ssam return (0); 39111084Ssam } 39210334Shelge 39311084Ssam /* 39411084Ssam * Skip sector error. 39511084Ssam * Set skip-sector-inhibit and 39611084Ssam * read next sector 39711084Ssam */ 39811140Ssam if (flag == SSE) { 39910334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 40010864Ssam HPWAIT(rp); 40110334Shelge rp->hpof |= HPOF_SSEI; 40211084Ssam return (0); 40311140Ssam } 40410334Shelge 40511140Ssam /* 40611140Ssam * Bad block forwarding. 40711140Ssam */ 40811140Ssam if (flag == BSE) { 40910626Shelge int bbn; 41011084Ssam 41110626Shelge rp->hpcs1 = HP_DCLR | HP_GO; 412*25439Skarels if (sc->debug & HPF_BSEDEBUG) 41311366Ssam printf("hpecc: BSE @ bn %d\n", bn); 41410334Shelge cn = bn/st->nspc; 41510334Shelge sn = bn%st->nspc; 41610334Shelge tn = sn/st->nsect; 41710626Shelge sn = sn%st->nsect; 41810626Shelge bcr += sectsiz; 41910626Shelge if ((bbn = isbad(&hpbad[unit], cn, tn, sn)) < 0) 42011084Ssam return (1); 42110626Shelge bbn = st->ncyl*st->nspc - st->nsect - 1 - bbn; 42210626Shelge cn = bbn/st->nspc; 42310626Shelge sn = bbn%st->nspc; 42410626Shelge tn = sn/st->nsect; 42510626Shelge sn = sn%st->nsect; 42610626Shelge io->i_cc = sectsiz; 42710626Shelge io->i_ma += npf*sectsiz; 428*25439Skarels if (sc->debug & HPF_BSEDEBUG) 42911366Ssam printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 43011366Ssam rp->hpof &= ~HPOF_SSEI; 43110626Shelge mbp->mba_sr = -1; 43210334Shelge rp->hpdc = cn; 43310334Shelge rp->hpda = (tn<<8) + sn; 43410334Shelge mbastart(io,io->i_flgs); 43511366Ssam io->i_errcnt = 0; 43610864Ssam HPWAIT(rp); 43710864Ssam return (rp->hpds&HPDS_ERR); 43810334Shelge } 43911084Ssam printf("hpecc: flag=%d\n", flag); 44011084Ssam return (1); 44110334Shelge } 44211140Ssam 44310334Shelge /*ARGSUSED*/ 44410334Shelge hpioctl(io, cmd, arg) 44510334Shelge struct iob *io; 44610334Shelge int cmd; 44710334Shelge caddr_t arg; 44810334Shelge { 44910647Shelge register unit = io->i_unit; 450*25439Skarels register struct hp_softc *sc = &hp_softc[unit]; 451*25439Skarels struct st *st = &hpst[sc->type]; 45210647Shelge struct mba_drv *drv = mbadrv(unit); 45310334Shelge 45410334Shelge switch(cmd) { 45510334Shelge 45611366Ssam case SAIODEBUG: 457*25439Skarels sc->debug = (int)arg; 458*25439Skarels break; 45911366Ssam 46010334Shelge case SAIODEVDATA: 461*25439Skarels if (drv->mbd_dt&MBDT_TAP) 462*25439Skarels return (ECMD); 463*25439Skarels *(struct st *)arg = *st; 464*25439Skarels break; 46510334Shelge 466*25439Skarels case SAIOGBADINFO: 467*25439Skarels if (drv->mbd_dt&MBDT_TAP) 468*25439Skarels return (ECMD); 469*25439Skarels *(struct dkbad *)arg = hpbad[unit]; 470*25439Skarels break; 471*25439Skarels 472*25439Skarels case SAIOECCLIM: 473*25439Skarels sc->ecclim = (int)arg; 474*25439Skarels break; 475*25439Skarels 476*25439Skarels case SAIORETRIES: 477*25439Skarels sc->retries = (int)arg; 478*25439Skarels break; 479*25439Skarels 48011084Ssam case SAIOSSI: /* skip-sector-inhibit */ 48111084Ssam if (drv->mbd_dt&MBDT_TAP) 48211084Ssam return (ECMD); 48311084Ssam if ((io->i_flgs&F_SSI) == 0) { 48411084Ssam /* make sure this is done once only */ 48511084Ssam io->i_flgs |= F_SSI; 48611084Ssam st->nsect++; 48711084Ssam st->nspc += st->ntrak; 48810864Ssam } 489*25439Skarels break; 49010626Shelge 49111084Ssam case SAIONOSSI: /* remove skip-sector-inhibit */ 49210626Shelge if (io->i_flgs & F_SSI) { 49310626Shelge io->i_flgs &= ~F_SSI; 49410626Shelge drv->mbd_of &= ~HPOF_SSEI; 49510626Shelge st->nsect--; 49610626Shelge st->nspc -= st->ntrak; 49710626Shelge } 498*25439Skarels break; 49910626Shelge 50010864Ssam case SAIOSSDEV: /* drive have skip sector? */ 50111084Ssam return (RM80 ? 0 : ECMD); 502*25439Skarels 503*25439Skarels default: 504*25439Skarels return (ECMD); 50510334Shelge } 506*25439Skarels return (0); 50710334Shelge } 508