1*11366Ssam /* hp.c 4.17 83/03/01 */ 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 #include "../h/param.h" 1010334Shelge #include "../h/inode.h" 1110334Shelge #include "../h/fs.h" 1210334Shelge #include "../h/dkbad.h" 1310334Shelge 1410334Shelge #include "../vax/pte.h" 1510334Shelge #include "../vaxmba/hpreg.h" 1610334Shelge #include "../vaxmba/mbareg.h" 1710334Shelge 1810334Shelge #include "saio.h" 1910334Shelge #include "savax.h" 2010334Shelge 2110334Shelge #define MASKREG(reg) ((reg)&0xffff) 2210334Shelge 23*11366Ssam #define MAXBADDESC 126 24*11366Ssam #define SECTSIZ 512 /* sector size in bytes */ 25*11366Ssam #define HDRSIZ 4 /* number of bytes in sector header */ 26*11366Ssam #define MAXECC 5 /* max # bits allow in ecc error w/ F_ECCLM */ 2710334Shelge 2810334Shelge char hp_type[MAXNMBA*8] = { 0 }; 2911140Ssam extern struct st hpst[]; 3010334Shelge 3111115Ssam short hptypes[] = { 32*11366Ssam MBDT_RM03, 33*11366Ssam MBDT_RM05, 34*11366Ssam MBDT_RP06, 35*11366Ssam MBDT_RM80, 36*11366Ssam MBDT_RP05, 37*11366Ssam MBDT_RP07, 38*11366Ssam MBDT_ML11A, 39*11366Ssam MBDT_ML11B, 40*11366Ssam -1, /* 9755 */ 41*11366Ssam -1, /* 9730 */ 42*11366Ssam -1, /* Capricorn */ 43*11366Ssam -1, /* Eagle */ 44*11366Ssam MBDT_RM02, /* actually something else */ 45*11366Ssam -1, /* 9300 */ 46*11366Ssam 0 4711115Ssam }; 4810334Shelge 49*11366Ssam #define RP06 (hptypes[hp_type[unit]] <= MBDT_RP06) 50*11366Ssam #define ML11 (hptypes[hp_type[unit]] == MBDT_ML11A) 51*11366Ssam #define RM80 (hptypes[hp_type[unit]] == MBDT_RM80) 5210334Shelge 5310334Shelge u_char hp_offset[16] = { 5410334Shelge HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 5510334Shelge HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 5610334Shelge HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 5710334Shelge 0, 0, 0, 0, 5810334Shelge }; 5910334Shelge 60*11366Ssam struct dkbad hpbad[MAXNMBA*8]; 61*11366Ssam int ssect[MAXNMBA*8]; /* 1 when on track w/skip sector */ 6210334Shelge 63*11366Ssam int hpdebug[MAXNMBA*8]; 64*11366Ssam #define HPF_BSEDEBUG 01 /* debugging bad sector forwarding */ 65*11366Ssam #define HPF_ECCDEBUG 02 /* debugging ecc correction */ 66*11366Ssam 67*11366Ssam int sectsiz; 68*11366Ssam 6910864Ssam /* 7010864Ssam * When awaiting command completion, don't 7110864Ssam * hang on to the status register since 72*11366Ssam * this ties up some controllers. 7310864Ssam */ 74*11366Ssam #define HPWAIT(addr) \ 75*11366Ssam while ((((addr)->hpds)&HPDS_DRY)==0) DELAY(500); 7610864Ssam 7710334Shelge hpopen(io) 7810334Shelge register struct iob *io; 7910334Shelge { 8010334Shelge register unit = io->i_unit; 8110334Shelge struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 8210353Shelge register struct st *st; 8310334Shelge 8410334Shelge mbainit(UNITTOMBA(unit)); 8510334Shelge if (hp_type[unit] == 0) { 86*11366Ssam register i, type = hpaddr->hpdt & MBDT_TYPE; 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: 9410647Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; /* init drive */ 9510647Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 9610647Shelge if (!ML11) 9710647Shelge hpaddr->hpof = HPOF_FMT22; 9811113Shelge hp_type[unit] = hpmaptype(hpaddr, i, unit); 9910334Shelge /* 100*11366Ssam * Read in the bad sector table. 10110334Shelge */ 10211140Ssam st = &hpst[hp_type[unit]]; 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 } 11910334Shelge } 12010334Shelge } 12110334Shelge if (io->i_boff < 0 || io->i_boff > 7 || 12210334Shelge st->off[io->i_boff]== -1) 12310334Shelge _stop("hp bad minor"); 12410334Shelge io->i_boff = st->off[io->i_boff] * st->nspc; 12510334Shelge } 12610334Shelge 12710334Shelge hpstrategy(io, func) 12810334Shelge register struct iob *io; 12910334Shelge { 13010334Shelge register unit = io->i_unit; 13110334Shelge struct mba_regs *mba = mbamba(unit); 132*11366Ssam daddr_t bn, startblock; 13310334Shelge struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 13410353Shelge struct st *st = &hpst[hp_type[unit]]; 13510334Shelge int cn, tn, sn, bytecnt, bytesleft; 13610334Shelge char *membase; 13710334Shelge int er1, er2, hprecal; 13810334Shelge 13910334Shelge sectsiz = SECTSIZ; 14010334Shelge if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0) 14110334Shelge sectsiz += HDRSIZ; 14210334Shelge if ((hpaddr->hpds & HPDS_VV) == 0) { 14310334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 14410334Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 14511084Ssam if (!ML11) 14610334Shelge hpaddr->hpof = HPOF_FMT22; 14710334Shelge } 14810334Shelge io->i_errcnt = 0; 149*11366Ssam ssect[unit] = 0; 15010334Shelge bytecnt = io->i_cc; 15110334Shelge membase = io->i_ma; 15210334Shelge startblock = io->i_bn; 15310608Ssam hprecal = 0; 15411140Ssam 15510626Shelge restart: 15610334Shelge bn = io->i_bn; 15710334Shelge cn = bn/st->nspc; 15810334Shelge sn = bn%st->nspc; 15910334Shelge tn = sn/st->nsect; 160*11366Ssam sn = sn%st->nsect + ssect[unit]; 16110334Shelge 16210864Ssam HPWAIT(hpaddr); 16310626Shelge mba->mba_sr = -1; 16410647Shelge if (ML11) 16510334Shelge hpaddr->hpda = bn; 16610334Shelge else { 16710334Shelge hpaddr->hpdc = cn; 16810334Shelge hpaddr->hpda = (tn << 8) + sn; 16910334Shelge } 17010334Shelge if (mbastart(io, func) != 0) /* start transfer */ 17110334Shelge return (-1); 17210864Ssam HPWAIT(hpaddr); 173*11366Ssam /* 174*11366Ssam * Successful data transfer, return. 175*11366Ssam */ 17611084Ssam if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0) 17711084Ssam return (bytecnt); 17810334Shelge 179*11366Ssam /* 180*11366Ssam * Error handling. Calculate location of error. 181*11366Ssam */ 182*11366Ssam bytesleft = MASKREG(mba->mba_bcr); 183*11366Ssam if (bytesleft) 184*11366Ssam bytesleft |= 0xffff0000; /* sxt */ 185*11366Ssam bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz; 18610334Shelge cn = bn/st->nspc; 18710334Shelge sn = bn%st->nspc; 18810334Shelge tn = sn/st->nsect; 18910334Shelge sn = sn%st->nsect; 19010334Shelge er1 = MASKREG(hpaddr->hper1); 19110334Shelge er2 = MASKREG(hpaddr->hper2); 192*11366Ssam if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) { 193*11366Ssam printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b\n", 194*11366Ssam cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 195*11366Ssam printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS); 196*11366Ssam printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft, 197*11366Ssam hpaddr->hpof, hpaddr->hpda); 198*11366Ssam } 19910334Shelge if (er1 & HPER1_HCRC) { 20010334Shelge er1 &= ~(HPER1_HCE|HPER1_FER); 20110334Shelge er2 &= ~HPER2_BSE; 20210334Shelge } 20311140Ssam /* 20411140Ssam * Give up early if drive write locked. 20511140Ssam */ 20610334Shelge if (er1&HPER1_WLE) { 20710334Shelge printf("hp%d: write locked\n", unit); 20811084Ssam return (-1); 20911084Ssam } 21011140Ssam /* 211*11366Ssam * Interpret format error bit as a bad block on RP06's. 21211140Ssam */ 21311084Ssam if (MASKREG(er1) == HPER1_FER && RP06) 21410334Shelge goto badsect; 21511140Ssam 21611140Ssam /* 21711140Ssam * If a hard error, or maximum retry count 21811140Ssam * exceeded, clear controller state and 21911140Ssam * pass back error to caller. 22011140Ssam */ 22111084Ssam if (++io->i_errcnt > 27 || (er1 & HPER1_HARD) || 22211084Ssam (!ML11 && (er2 & HPER2_HARD))) { 22311179Ssam if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0) 22411179Ssam goto success; 22510608Ssam hard0: 22610334Shelge io->i_error = EHER; 22711084Ssam if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR)) 22810334Shelge io->i_error = EWCK; 22910334Shelge hard: 230*11366Ssam io->i_errblk = bn + ssect[unit]; 23110334Shelge printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", 23210334Shelge cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 23311084Ssam printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS); 23410334Shelge if (hpaddr->hpmr) 23510626Shelge printf(" mr1=%o", MASKREG(hpaddr->hpmr)); 23610334Shelge if (hpaddr->hpmr2) 23710626Shelge printf(" mr2=%o", MASKREG(hpaddr->hpmr2)); 238*11366Ssam if (hpdebug[unit] & (HPF_BSEDEBUG|HPF_ECCDEBUG)) 239*11366Ssam printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc), 240*11366Ssam MASKREG(hpaddr->hpda)); 24110626Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 24210334Shelge printf("\n"); 24311084Ssam return (-1); 24410334Shelge 24511084Ssam } 24611140Ssam /* 24711140Ssam * Attempt to forward bad sectors on 24811140Ssam * anything but an ML11. If drive 24911140Ssam * supports skip sector handling, try to 25011140Ssam * use it first; otherwise try the 25111140Ssam * bad sector table. 25211140Ssam */ 25311084Ssam if ((er2 & HPER2_BSE) && !ML11) { 25410334Shelge badsect: 255*11366Ssam if (!ssect[unit] && (er2&HPER2_SSE)) 25610647Shelge goto skipsect; 25711084Ssam if (io->i_flgs & F_NBSF) { 25810334Shelge io->i_error = EBSE; 25910334Shelge goto hard; 26010334Shelge } 26110334Shelge if (hpecc(io, BSE) == 0) 26210334Shelge goto success; 26311084Ssam io->i_error = EBSE; 26411084Ssam goto hard; 26511084Ssam } 26611140Ssam 26711140Ssam /* 26811140Ssam * Skip sector handling. 26911140Ssam */ 270*11366Ssam if (RM80 && (er2 & HPER2_SSE)) { 27110647Shelge skipsect: 27210334Shelge (void) hpecc(io, SSE); 273*11366Ssam ssect[unit] = 1; 27410334Shelge goto success; 27511084Ssam } 27611140Ssam /* 277*11366Ssam * ECC correction? 27811140Ssam */ 27911084Ssam if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) { 28010864Ssam if (hpecc(io, ECC) == 0) 28110334Shelge goto success; 28211084Ssam io->i_error = EECC; 28311084Ssam return (-1); 28410608Ssam } 28510608Ssam if (ML11 && (io->i_errcnt >= 16)) 28611084Ssam goto hard0; 28710608Ssam /* fall thru to retry */ 28810334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 28910864Ssam HPWAIT(hpaddr); 29011140Ssam 29111140Ssam /* 29211140Ssam * Every fourth retry recalibrate. 29311140Ssam */ 294*11366Ssam if (((io->i_errcnt & 07) == 4) ) { 29510334Shelge hpaddr->hpcs1 = HP_RECAL|HP_GO; 29610608Ssam hprecal = 1; 29711084Ssam goto again; 29810334Shelge } 29911140Ssam 30011140Ssam /* 30111140Ssam * Recalibration state machine. 30211140Ssam */ 30310334Shelge switch (hprecal) { 30410334Shelge 30510334Shelge case 1: 30610334Shelge hpaddr->hpdc = cn; 30710334Shelge hpaddr->hpcs1 = HP_SEEK|HP_GO; 30811084Ssam hprecal = 2; 30911084Ssam goto again; 31010864Ssam 31110334Shelge case 2: 31210608Ssam if (io->i_errcnt < 16 || (io->i_flgs & F_READ) == 0) 31310334Shelge goto donerecal; 31410334Shelge hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22; 31510334Shelge hpaddr->hpcs1 = HP_OFFSET|HP_GO; 31611084Ssam hprecal = 3; 31711084Ssam goto again; 31810864Ssam 31911084Ssam case 3: 32010334Shelge donerecal: 32110334Shelge hprecal = 0; 32211084Ssam goto again; 32310334Shelge } 32410608Ssam if (io->i_errcnt >= 16) { 32510608Ssam hpaddr->hpcs1 = HP_RTC|HP_GO; 32610608Ssam while (hpaddr->hpds & HPDS_PIP) 32710608Ssam ; 32810334Shelge } 32911084Ssam goto again; 33011084Ssam 33111140Ssam success: 33211140Ssam /* 33311140Ssam * On successful error recovery, bump 33411140Ssam * block number to advance to next portion 33511140Ssam * of i/o transfer. 33611140Ssam */ 33710334Shelge bn++; 33810334Shelge if ((bn-startblock) * sectsiz < bytecnt) { 33911140Ssam again: 34010334Shelge io->i_bn = bn; 34110334Shelge io->i_ma = membase + (io->i_bn - startblock)*sectsiz; 34210334Shelge io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz; 343*11366Ssam if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 344*11366Ssam printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 345*11366Ssam io->i_bn, io->i_cc, io->i_ma, hprecal); 34610626Shelge goto restart; 34710334Shelge } 34810334Shelge return (bytecnt); 34910334Shelge } 35010864Ssam 35110334Shelge hpecc(io, flag) 35210334Shelge register struct iob *io; 35310334Shelge int flag; 35410334Shelge { 35510334Shelge register unit = io->i_unit; 35610334Shelge register struct mba_regs *mbp = mbamba(unit); 35710334Shelge register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit); 35810353Shelge register struct st *st = &hpst[hp_type[unit]]; 35911084Ssam int npf, bn, cn, tn, sn, bcr; 36010334Shelge 361*11366Ssam bcr = MASKREG(mbp->mba_bcr); 362*11366Ssam if (bcr) 363*11366Ssam bcr |= 0xffff0000; /* sxt */ 36411084Ssam npf = (bcr + io->i_cc) / sectsiz; /* # sectors read */ 365*11366Ssam bn = io->i_bn + npf + ssect[unit]; /* physical block #*/ 366*11366Ssam if (hpdebug[unit]&HPF_ECCDEBUG) 367*11366Ssam printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n", 368*11366Ssam bcr, npf, ssect[unit], sectsiz, io->i_cc); 36911140Ssam /* 37011140Ssam * ECC correction logic. 37111140Ssam */ 37211140Ssam if (flag == ECC) { 37310334Shelge register int i; 37410334Shelge caddr_t addr; 37511179Ssam int bit, o, mask, ecccnt = 0; 37610334Shelge 37710413Shelge printf("hp%d: soft ecc sn%d\n", unit, bn); 37810334Shelge mask = MASKREG(rp->hpec2); 37911084Ssam i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 38010334Shelge bit = i&07; 381*11366Ssam o = (i & ~07) >> 3; 38210334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 38311179Ssam while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) { 38411179Ssam addr = io->i_ma + (npf*sectsiz) + o; 38511179Ssam /* 38611179Ssam * No data transfer occurs with a write check, 38711179Ssam * so don't correct the resident copy of data. 38811179Ssam */ 389*11366Ssam if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { 390*11366Ssam if (hpdebug[unit] & HPF_ECCDEBUG) 391*11366Ssam printf("addr=%x old=%x ", addr, 392*11366Ssam (*addr & 0xff)); 39311140Ssam *addr ^= (mask << bit); 394*11366Ssam if (hpdebug[unit] & HPF_ECCDEBUG) 395*11366Ssam printf("new=%x\n",(*addr & 0xff)); 396*11366Ssam } 39711179Ssam o++, bit -= 8; 39811109Ssam if ((io->i_flgs & F_ECCLM) && ecccnt++ >= MAXECC) 39911084Ssam return (1); 40010334Shelge } 40111179Ssam return (0); 40211084Ssam } 40310334Shelge 40411084Ssam /* 40511084Ssam * Skip sector error. 40611084Ssam * Set skip-sector-inhibit and 40711084Ssam * read next sector 40811084Ssam */ 40911140Ssam if (flag == SSE) { 41010334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 41110864Ssam HPWAIT(rp); 41210334Shelge rp->hpof |= HPOF_SSEI; 41311084Ssam return (0); 41411140Ssam } 41510334Shelge 41611140Ssam /* 41711140Ssam * Bad block forwarding. 41811140Ssam */ 41911140Ssam if (flag == BSE) { 42010626Shelge int bbn; 42111084Ssam 42210626Shelge rp->hpcs1 = HP_DCLR | HP_GO; 423*11366Ssam if (hpdebug[unit] & HPF_BSEDEBUG) 424*11366Ssam printf("hpecc: BSE @ bn %d\n", bn); 42510334Shelge cn = bn/st->nspc; 42610334Shelge sn = bn%st->nspc; 42710334Shelge tn = sn/st->nsect; 42810626Shelge sn = sn%st->nsect; 42910626Shelge bcr += sectsiz; 43010626Shelge if ((bbn = isbad(&hpbad[unit], cn, tn, sn)) < 0) 43111084Ssam return (1); 43210626Shelge bbn = st->ncyl*st->nspc - st->nsect - 1 - bbn; 43310626Shelge cn = bbn/st->nspc; 43410626Shelge sn = bbn%st->nspc; 43510626Shelge tn = sn/st->nsect; 43610626Shelge sn = sn%st->nsect; 43710626Shelge io->i_cc = sectsiz; 43810626Shelge io->i_ma += npf*sectsiz; 439*11366Ssam if (hpdebug[unit] & HPF_BSEDEBUG) 440*11366Ssam printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 441*11366Ssam rp->hpof &= ~HPOF_SSEI; 44210626Shelge mbp->mba_sr = -1; 44310334Shelge rp->hpdc = cn; 44410334Shelge rp->hpda = (tn<<8) + sn; 44510334Shelge mbastart(io,io->i_flgs); 446*11366Ssam io->i_errcnt = 0; 44710864Ssam HPWAIT(rp); 44810864Ssam return (rp->hpds&HPDS_ERR); 44910334Shelge } 45011084Ssam printf("hpecc: flag=%d\n", flag); 45111084Ssam return (1); 45210334Shelge } 45311140Ssam 45410334Shelge /*ARGSUSED*/ 45510334Shelge hpioctl(io, cmd, arg) 45610334Shelge struct iob *io; 45710334Shelge int cmd; 45810334Shelge caddr_t arg; 45910334Shelge { 46010647Shelge register unit = io->i_unit; 46110647Shelge struct st *st = &hpst[hp_type[unit]], *tmp; 46210647Shelge struct mba_drv *drv = mbadrv(unit); 463*11366Ssam int flag; 46410334Shelge 46510334Shelge switch(cmd) { 46610334Shelge 467*11366Ssam case SAIODEBUG: 468*11366Ssam flag = (int)arg; 469*11366Ssam if (flag > 0) 470*11366Ssam hpdebug[unit] |= flag; 471*11366Ssam else 472*11366Ssam hpdebug[unit] &= ~flag; 473*11366Ssam return (0); 474*11366Ssam 47510334Shelge case SAIODEVDATA: 47610334Shelge if ((drv->mbd_dt&MBDT_TAP) == 0) { 47710353Shelge tmp = (struct st *)arg; 47810353Shelge *tmp = *st; 47911084Ssam return (0); 48010334Shelge } 48111084Ssam return (ECMD); 48210334Shelge 48311084Ssam case SAIOSSI: /* skip-sector-inhibit */ 48411084Ssam if (drv->mbd_dt&MBDT_TAP) 48511084Ssam return (ECMD); 48611084Ssam if ((io->i_flgs&F_SSI) == 0) { 48711084Ssam /* make sure this is done once only */ 48811084Ssam io->i_flgs |= F_SSI; 48911084Ssam st->nsect++; 49011084Ssam st->nspc += st->ntrak; 49110864Ssam } 49211084Ssam return (0); 49310626Shelge 49411084Ssam case SAIONOSSI: /* remove skip-sector-inhibit */ 49510626Shelge if (io->i_flgs & F_SSI) { 49610626Shelge io->i_flgs &= ~F_SSI; 49710626Shelge drv->mbd_of &= ~HPOF_SSEI; 49810626Shelge st->nsect--; 49910626Shelge st->nspc -= st->ntrak; 50010626Shelge } 50110626Shelge return(0); 50210626Shelge 50310864Ssam case SAIOSSDEV: /* drive have skip sector? */ 50411084Ssam return (RM80 ? 0 : ECMD); 50510334Shelge } 50611084Ssam return (ECMD); 50710334Shelge } 508