1*16271Skarels /* hp.c 6.5 84/04/02 */ 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 2311366Ssam #define MAXBADDESC 126 2411366Ssam #define SECTSIZ 512 /* sector size in bytes */ 2511366Ssam #define HDRSIZ 4 /* number of bytes in sector header */ 2611366Ssam #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[] = { 3211366Ssam MBDT_RM03, 3311366Ssam MBDT_RM05, 3411366Ssam MBDT_RP06, 3511366Ssam MBDT_RM80, 3611366Ssam MBDT_RP05, 3711366Ssam MBDT_RP07, 3811366Ssam MBDT_ML11A, 3911366Ssam MBDT_ML11B, 4011366Ssam -1, /* 9755 */ 4111366Ssam -1, /* 9730 */ 4211366Ssam -1, /* Capricorn */ 4311366Ssam -1, /* Eagle */ 4411366Ssam MBDT_RM02, /* actually something else */ 4511366Ssam -1, /* 9300 */ 4611366Ssam 0 4711115Ssam }; 4810334Shelge 4911366Ssam #define RP06 (hptypes[hp_type[unit]] <= MBDT_RP06) 5011366Ssam #define ML11 (hptypes[hp_type[unit]] == MBDT_ML11A) 5111366Ssam #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 6011366Ssam struct dkbad hpbad[MAXNMBA*8]; 6111366Ssam int ssect[MAXNMBA*8]; /* 1 when on track w/skip sector */ 6210334Shelge 6311366Ssam int hpdebug[MAXNMBA*8]; 6411366Ssam #define HPF_BSEDEBUG 01 /* debugging bad sector forwarding */ 6511366Ssam #define HPF_ECCDEBUG 02 /* debugging ecc correction */ 6611366Ssam 6711366Ssam int sectsiz; 6811366Ssam 6910864Ssam /* 7010864Ssam * When awaiting command completion, don't 7110864Ssam * hang on to the status register since 7211366Ssam * this ties up some controllers. 7310864Ssam */ 7411366Ssam #define HPWAIT(addr) \ 7511366Ssam 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) { 8611366Ssam 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; 98*16271Skarels hp_type[unit] = hpmaptype(hpaddr, i, UNITTODRIVE(unit)); 9910334Shelge /* 10011366Ssam * 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 } 12115947Skarels st = &hpst[hp_type[unit]]; 12210334Shelge if (io->i_boff < 0 || io->i_boff > 7 || 12310334Shelge st->off[io->i_boff]== -1) 12410334Shelge _stop("hp bad minor"); 12510334Shelge io->i_boff = st->off[io->i_boff] * st->nspc; 12610334Shelge } 12710334Shelge 12810334Shelge hpstrategy(io, func) 12910334Shelge register struct iob *io; 13010334Shelge { 13110334Shelge register unit = io->i_unit; 13210334Shelge struct mba_regs *mba = mbamba(unit); 13311366Ssam daddr_t bn, startblock; 13410334Shelge struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 13510353Shelge struct st *st = &hpst[hp_type[unit]]; 13610334Shelge int cn, tn, sn, bytecnt, bytesleft; 13710334Shelge char *membase; 13810334Shelge int er1, er2, hprecal; 13910334Shelge 14010334Shelge sectsiz = SECTSIZ; 14110334Shelge if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0) 14210334Shelge sectsiz += HDRSIZ; 14310334Shelge if ((hpaddr->hpds & HPDS_VV) == 0) { 14410334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 14510334Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 14611084Ssam if (!ML11) 14710334Shelge hpaddr->hpof = HPOF_FMT22; 14810334Shelge } 14910334Shelge io->i_errcnt = 0; 15011366Ssam ssect[unit] = 0; 15110334Shelge bytecnt = io->i_cc; 15210334Shelge membase = io->i_ma; 15310334Shelge startblock = io->i_bn; 15410608Ssam hprecal = 0; 15511140Ssam 15610626Shelge restart: 15710334Shelge bn = io->i_bn; 15810334Shelge cn = bn/st->nspc; 15910334Shelge sn = bn%st->nspc; 16010334Shelge tn = sn/st->nsect; 16111366Ssam sn = sn%st->nsect + ssect[unit]; 16210334Shelge 16310864Ssam HPWAIT(hpaddr); 16410626Shelge mba->mba_sr = -1; 16510647Shelge if (ML11) 16610334Shelge hpaddr->hpda = bn; 16710334Shelge else { 16810334Shelge hpaddr->hpdc = cn; 16910334Shelge hpaddr->hpda = (tn << 8) + sn; 17010334Shelge } 17110334Shelge if (mbastart(io, func) != 0) /* start transfer */ 17210334Shelge return (-1); 17310864Ssam HPWAIT(hpaddr); 17411366Ssam /* 17511366Ssam * Successful data transfer, return. 17611366Ssam */ 17715068Skarels if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0) 17815068Skarels goto done; 17910334Shelge 18011366Ssam /* 18111366Ssam * Error handling. Calculate location of error. 18211366Ssam */ 18311366Ssam bytesleft = MASKREG(mba->mba_bcr); 18411366Ssam if (bytesleft) 18511366Ssam bytesleft |= 0xffff0000; /* sxt */ 18611366Ssam bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz; 18715052Skarels er1 = MASKREG(hpaddr->hper1); 18815052Skarels er2 = MASKREG(hpaddr->hper2); 18915052Skarels if (er1 & (HPER1_DCK|HPER1_ECH)) 19015052Skarels bn--; /* Error is in Prev block */ 19110334Shelge cn = bn/st->nspc; 19210334Shelge sn = bn%st->nspc; 19310334Shelge tn = sn/st->nsect; 19410334Shelge sn = sn%st->nsect; 19511366Ssam if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) { 19611366Ssam printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b\n", 19711366Ssam cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 19811366Ssam printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS); 19911366Ssam printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft, 20011366Ssam hpaddr->hpof, hpaddr->hpda); 20111366Ssam } 20210334Shelge if (er1 & HPER1_HCRC) { 20310334Shelge er1 &= ~(HPER1_HCE|HPER1_FER); 20410334Shelge er2 &= ~HPER2_BSE; 20510334Shelge } 20611140Ssam /* 20711140Ssam * Give up early if drive write locked. 20811140Ssam */ 20910334Shelge if (er1&HPER1_WLE) { 21010334Shelge printf("hp%d: write locked\n", unit); 21111084Ssam return (-1); 21211084Ssam } 21311140Ssam /* 21411366Ssam * Interpret format error bit as a bad block on RP06's. 21511140Ssam */ 21611084Ssam if (MASKREG(er1) == HPER1_FER && RP06) 21710334Shelge goto badsect; 21811140Ssam 21911140Ssam /* 22011140Ssam * If a hard error, or maximum retry count 22111140Ssam * exceeded, clear controller state and 22211140Ssam * pass back error to caller. 22311140Ssam */ 22411084Ssam if (++io->i_errcnt > 27 || (er1 & HPER1_HARD) || 22511084Ssam (!ML11 && (er2 & HPER2_HARD))) { 22615052Skarels /* 22715052Skarels * The last ditch effort to bad sector forward 22815052Skarels * below will probably fail since mba byte ctr 22915052Skarels * (bcr) is different for BSE and ECC errors and 23015052Skarels * the wrong block will be revectored to if one 23115052Skarels * has 2 contiguous bad blocks and reads the second. 23215052Skarels * For now, we can probably just let a header CRC 23315052Skarels * error be handled like a BSE since no data will 23415052Skarels * have been transferred and the bcr should the same 23515052Skarels * as it would with a BSE error. 23615052Skarels * --ghg. 23715052Skarels */ 23815052Skarels if (er1 & HPER1_HCRC) 23915052Skarels if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0) 24015052Skarels goto success; 24110608Ssam hard0: 24210334Shelge io->i_error = EHER; 24311084Ssam if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR)) 24410334Shelge io->i_error = EWCK; 24510334Shelge hard: 24611366Ssam io->i_errblk = bn + ssect[unit]; 24710334Shelge printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", 24810334Shelge cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 24911084Ssam printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS); 25010334Shelge if (hpaddr->hpmr) 25110626Shelge printf(" mr1=%o", MASKREG(hpaddr->hpmr)); 25210334Shelge if (hpaddr->hpmr2) 25310626Shelge printf(" mr2=%o", MASKREG(hpaddr->hpmr2)); 25411366Ssam if (hpdebug[unit] & (HPF_BSEDEBUG|HPF_ECCDEBUG)) 25511366Ssam printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc), 25611366Ssam MASKREG(hpaddr->hpda)); 25710626Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 25810334Shelge printf("\n"); 25915068Skarels bytecnt = -1; 26015068Skarels goto done; 26110334Shelge 26211084Ssam } 26311140Ssam /* 26411140Ssam * Attempt to forward bad sectors on 26511140Ssam * anything but an ML11. If drive 26611140Ssam * supports skip sector handling, try to 26711140Ssam * use it first; otherwise try the 26811140Ssam * bad sector table. 26911140Ssam */ 27011084Ssam if ((er2 & HPER2_BSE) && !ML11) { 27110334Shelge badsect: 27211366Ssam if (!ssect[unit] && (er2&HPER2_SSE)) 27310647Shelge goto skipsect; 27411084Ssam if (io->i_flgs & F_NBSF) { 27510334Shelge io->i_error = EBSE; 27610334Shelge goto hard; 27710334Shelge } 27810334Shelge if (hpecc(io, BSE) == 0) 27910334Shelge goto success; 28011084Ssam io->i_error = EBSE; 28111084Ssam goto hard; 28211084Ssam } 28311140Ssam 28411140Ssam /* 28511140Ssam * Skip sector handling. 28611140Ssam */ 28711366Ssam if (RM80 && (er2 & HPER2_SSE)) { 28810647Shelge skipsect: 28910334Shelge (void) hpecc(io, SSE); 29011366Ssam ssect[unit] = 1; 29110334Shelge goto success; 29211084Ssam } 29311140Ssam /* 29411366Ssam * ECC correction? 29511140Ssam */ 29611084Ssam if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) { 29710864Ssam if (hpecc(io, ECC) == 0) 29810334Shelge goto success; 29911084Ssam io->i_error = EECC; 30015052Skarels io->i_errblk = bn + ssect[unit]; 30111084Ssam return (-1); 30210608Ssam } 30315052Skarels #ifdef F_SEVRE 30415052Skarels if (io->i_flgs & F_SEVRE) 30515052Skarels goto hard; 30615052Skarels #endif 30710608Ssam if (ML11 && (io->i_errcnt >= 16)) 30811084Ssam goto hard0; 30910608Ssam /* fall thru to retry */ 31010334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 31110864Ssam HPWAIT(hpaddr); 31211140Ssam 31311140Ssam /* 31411140Ssam * Every fourth retry recalibrate. 31511140Ssam */ 31611366Ssam if (((io->i_errcnt & 07) == 4) ) { 31710334Shelge hpaddr->hpcs1 = HP_RECAL|HP_GO; 31815052Skarels HPWAIT(hpaddr); 31910334Shelge hpaddr->hpdc = cn; 32010334Shelge hpaddr->hpcs1 = HP_SEEK|HP_GO; 32115052Skarels HPWAIT(hpaddr); 32215052Skarels } 32310864Ssam 32415052Skarels if (io->i_errcnt >= 16 && (io->i_flgs & F_READ)) { 32510334Shelge hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22; 32610334Shelge hpaddr->hpcs1 = HP_OFFSET|HP_GO; 32715052Skarels HPWAIT(hpaddr); 32810334Shelge } 32915052Skarels if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 33015052Skarels printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 33115052Skarels io->i_bn, io->i_cc, io->i_ma, hprecal); 33215052Skarels goto restart; /* retry whole transfer --ghg */ 33311084Ssam 33411140Ssam success: 33511140Ssam /* 33611140Ssam * On successful error recovery, bump 33711140Ssam * block number to advance to next portion 33811140Ssam * of i/o transfer. 33911140Ssam */ 34010334Shelge bn++; 34110334Shelge if ((bn-startblock) * sectsiz < bytecnt) { 34210334Shelge io->i_bn = bn; 34310334Shelge io->i_ma = membase + (io->i_bn - startblock)*sectsiz; 34410334Shelge io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz; 34511366Ssam if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 34611366Ssam printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 34711366Ssam io->i_bn, io->i_cc, io->i_ma, hprecal); 34810626Shelge goto restart; 34910334Shelge } 35015068Skarels done: 35115052Skarels if (io->i_errcnt >= 16) { 35215052Skarels hpaddr->hpcs1 = HP_RTC|HP_GO; 35315052Skarels while (hpaddr->hpds & HPDS_PIP) 35415052Skarels ; 35515052Skarels } 35610334Shelge return (bytecnt); 35710334Shelge } 35810864Ssam 35910334Shelge hpecc(io, flag) 36010334Shelge register struct iob *io; 36110334Shelge int flag; 36210334Shelge { 36310334Shelge register unit = io->i_unit; 36410334Shelge register struct mba_regs *mbp = mbamba(unit); 36510334Shelge register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit); 36610353Shelge register struct st *st = &hpst[hp_type[unit]]; 36711084Ssam int npf, bn, cn, tn, sn, bcr; 36810334Shelge 36911366Ssam bcr = MASKREG(mbp->mba_bcr); 37011366Ssam if (bcr) 37111366Ssam bcr |= 0xffff0000; /* sxt */ 37211084Ssam npf = (bcr + io->i_cc) / sectsiz; /* # sectors read */ 37315052Skarels if (flag == ECC) 37415052Skarels npf--; /* Error is in prev block --ghg */ 37511366Ssam bn = io->i_bn + npf + ssect[unit]; /* physical block #*/ 37611366Ssam if (hpdebug[unit]&HPF_ECCDEBUG) 37711366Ssam printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n", 37811366Ssam bcr, npf, ssect[unit], sectsiz, io->i_cc); 37911140Ssam /* 38011140Ssam * ECC correction logic. 38111140Ssam */ 38211140Ssam if (flag == ECC) { 38310334Shelge register int i; 38410334Shelge caddr_t addr; 38511179Ssam int bit, o, mask, ecccnt = 0; 38610334Shelge 38710413Shelge printf("hp%d: soft ecc sn%d\n", unit, bn); 38810334Shelge mask = MASKREG(rp->hpec2); 38911084Ssam i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 39010334Shelge bit = i&07; 39111366Ssam o = (i & ~07) >> 3; 39210334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 39311179Ssam while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) { 39411179Ssam addr = io->i_ma + (npf*sectsiz) + o; 39511179Ssam /* 39611179Ssam * No data transfer occurs with a write check, 39711179Ssam * so don't correct the resident copy of data. 39811179Ssam */ 39911366Ssam if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { 40011366Ssam if (hpdebug[unit] & HPF_ECCDEBUG) 40111366Ssam printf("addr=%x old=%x ", addr, 40211366Ssam (*addr & 0xff)); 40311140Ssam *addr ^= (mask << bit); 40411366Ssam if (hpdebug[unit] & HPF_ECCDEBUG) 40511366Ssam printf("new=%x\n",(*addr & 0xff)); 40611366Ssam } 40711179Ssam o++, bit -= 8; 40811109Ssam if ((io->i_flgs & F_ECCLM) && ecccnt++ >= MAXECC) 40911084Ssam return (1); 41010334Shelge } 41115052Skarels #ifdef F_SEVRE 41215052Skarels if (io->i_flgs & F_SEVRE) 41315052Skarels return(1); 41415052Skarels #endif 41511179Ssam return (0); 41611084Ssam } 41710334Shelge 41811084Ssam /* 41911084Ssam * Skip sector error. 42011084Ssam * Set skip-sector-inhibit and 42111084Ssam * read next sector 42211084Ssam */ 42311140Ssam if (flag == SSE) { 42410334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 42510864Ssam HPWAIT(rp); 42610334Shelge rp->hpof |= HPOF_SSEI; 42711084Ssam return (0); 42811140Ssam } 42910334Shelge 43011140Ssam /* 43111140Ssam * Bad block forwarding. 43211140Ssam */ 43311140Ssam if (flag == BSE) { 43410626Shelge int bbn; 43511084Ssam 43610626Shelge rp->hpcs1 = HP_DCLR | HP_GO; 43711366Ssam if (hpdebug[unit] & HPF_BSEDEBUG) 43811366Ssam printf("hpecc: BSE @ bn %d\n", bn); 43910334Shelge cn = bn/st->nspc; 44010334Shelge sn = bn%st->nspc; 44110334Shelge tn = sn/st->nsect; 44210626Shelge sn = sn%st->nsect; 44310626Shelge bcr += sectsiz; 44410626Shelge if ((bbn = isbad(&hpbad[unit], cn, tn, sn)) < 0) 44511084Ssam return (1); 44610626Shelge bbn = st->ncyl*st->nspc - st->nsect - 1 - bbn; 44710626Shelge cn = bbn/st->nspc; 44810626Shelge sn = bbn%st->nspc; 44910626Shelge tn = sn/st->nsect; 45010626Shelge sn = sn%st->nsect; 45110626Shelge io->i_cc = sectsiz; 45210626Shelge io->i_ma += npf*sectsiz; 45311366Ssam if (hpdebug[unit] & HPF_BSEDEBUG) 45411366Ssam printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 45511366Ssam rp->hpof &= ~HPOF_SSEI; 45610626Shelge mbp->mba_sr = -1; 45710334Shelge rp->hpdc = cn; 45810334Shelge rp->hpda = (tn<<8) + sn; 45910334Shelge mbastart(io,io->i_flgs); 46011366Ssam io->i_errcnt = 0; 46110864Ssam HPWAIT(rp); 46210864Ssam return (rp->hpds&HPDS_ERR); 46310334Shelge } 46411084Ssam printf("hpecc: flag=%d\n", flag); 46511084Ssam return (1); 46610334Shelge } 46711140Ssam 46810334Shelge /*ARGSUSED*/ 46910334Shelge hpioctl(io, cmd, arg) 47010334Shelge struct iob *io; 47110334Shelge int cmd; 47210334Shelge caddr_t arg; 47310334Shelge { 47410647Shelge register unit = io->i_unit; 47510647Shelge struct st *st = &hpst[hp_type[unit]], *tmp; 47610647Shelge struct mba_drv *drv = mbadrv(unit); 47711366Ssam int flag; 47810334Shelge 47910334Shelge switch(cmd) { 48010334Shelge 48111366Ssam case SAIODEBUG: 48211366Ssam flag = (int)arg; 48311366Ssam if (flag > 0) 48411366Ssam hpdebug[unit] |= flag; 48511366Ssam else 48611366Ssam hpdebug[unit] &= ~flag; 48711366Ssam return (0); 48811366Ssam 48910334Shelge case SAIODEVDATA: 49010334Shelge if ((drv->mbd_dt&MBDT_TAP) == 0) { 49110353Shelge tmp = (struct st *)arg; 49210353Shelge *tmp = *st; 49311084Ssam return (0); 49410334Shelge } 49511084Ssam return (ECMD); 49610334Shelge 49711084Ssam case SAIOSSI: /* skip-sector-inhibit */ 49811084Ssam if (drv->mbd_dt&MBDT_TAP) 49911084Ssam return (ECMD); 50011084Ssam if ((io->i_flgs&F_SSI) == 0) { 50111084Ssam /* make sure this is done once only */ 50211084Ssam io->i_flgs |= F_SSI; 50311084Ssam st->nsect++; 50411084Ssam st->nspc += st->ntrak; 50510864Ssam } 50611084Ssam return (0); 50710626Shelge 50811084Ssam case SAIONOSSI: /* remove skip-sector-inhibit */ 50910626Shelge if (io->i_flgs & F_SSI) { 51010626Shelge io->i_flgs &= ~F_SSI; 51110626Shelge drv->mbd_of &= ~HPOF_SSEI; 51210626Shelge st->nsect--; 51310626Shelge st->nspc -= st->ntrak; 51410626Shelge } 51510626Shelge return(0); 51610626Shelge 51710864Ssam case SAIOSSDEV: /* drive have skip sector? */ 51811084Ssam return (RM80 ? 0 : ECMD); 51910334Shelge } 52011084Ssam return (ECMD); 52110334Shelge } 522