1*23225Smckusick /* 2*23225Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23225Smckusick * All rights reserved. The Berkeley software License Agreement 4*23225Smckusick * specifies the terms and conditions for redistribution. 5*23225Smckusick * 6*23225Smckusick * @(#)hp.c 6.7 (Berkeley) 06/08/85 7*23225Smckusick */ 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 2710334Shelge #define MASKREG(reg) ((reg)&0xffff) 2810334Shelge 2911366Ssam #define MAXBADDESC 126 3011366Ssam #define SECTSIZ 512 /* sector size in bytes */ 3111366Ssam #define HDRSIZ 4 /* number of bytes in sector header */ 3211366Ssam #define MAXECC 5 /* max # bits allow in ecc error w/ F_ECCLM */ 3310334Shelge 3410334Shelge char hp_type[MAXNMBA*8] = { 0 }; 3511140Ssam extern struct st hpst[]; 3610334Shelge 3711115Ssam short hptypes[] = { 3811366Ssam MBDT_RM03, 3911366Ssam MBDT_RM05, 4011366Ssam MBDT_RP06, 4111366Ssam MBDT_RM80, 4211366Ssam MBDT_RP05, 4311366Ssam MBDT_RP07, 4411366Ssam MBDT_ML11A, 4511366Ssam MBDT_ML11B, 4611366Ssam -1, /* 9755 */ 4711366Ssam -1, /* 9730 */ 4811366Ssam -1, /* Capricorn */ 4911366Ssam -1, /* Eagle */ 5011366Ssam MBDT_RM02, /* actually something else */ 5111366Ssam -1, /* 9300 */ 5211366Ssam 0 5311115Ssam }; 5410334Shelge 5511366Ssam #define RP06 (hptypes[hp_type[unit]] <= MBDT_RP06) 5611366Ssam #define ML11 (hptypes[hp_type[unit]] == MBDT_ML11A) 5711366Ssam #define RM80 (hptypes[hp_type[unit]] == MBDT_RM80) 5810334Shelge 5910334Shelge u_char hp_offset[16] = { 6010334Shelge HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400, 6110334Shelge HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 6210334Shelge HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200, 6310334Shelge 0, 0, 0, 0, 6410334Shelge }; 6510334Shelge 6611366Ssam struct dkbad hpbad[MAXNMBA*8]; 6711366Ssam int ssect[MAXNMBA*8]; /* 1 when on track w/skip sector */ 6810334Shelge 6911366Ssam int hpdebug[MAXNMBA*8]; 7011366Ssam #define HPF_BSEDEBUG 01 /* debugging bad sector forwarding */ 7111366Ssam #define HPF_ECCDEBUG 02 /* debugging ecc correction */ 7211366Ssam 7311366Ssam int sectsiz; 7411366Ssam 7510864Ssam /* 7610864Ssam * When awaiting command completion, don't 7710864Ssam * hang on to the status register since 7811366Ssam * this ties up some controllers. 7910864Ssam */ 8011366Ssam #define HPWAIT(addr) \ 8111366Ssam while ((((addr)->hpds)&HPDS_DRY)==0) DELAY(500); 8210864Ssam 8310334Shelge hpopen(io) 8410334Shelge register struct iob *io; 8510334Shelge { 8610334Shelge register unit = io->i_unit; 8710334Shelge struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 8810353Shelge register struct st *st; 8910334Shelge 9010334Shelge mbainit(UNITTOMBA(unit)); 9110334Shelge if (hp_type[unit] == 0) { 9211366Ssam register i, type = hpaddr->hpdt & MBDT_TYPE; 9310334Shelge struct iob tio; 9410334Shelge 9510334Shelge for (i = 0; hptypes[i]; i++) 9610334Shelge if (hptypes[i] == type) 9710334Shelge goto found; 9810334Shelge _stop("unknown drive type"); 9910334Shelge found: 10010647Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; /* init drive */ 10110647Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 10210647Shelge if (!ML11) 10310647Shelge hpaddr->hpof = HPOF_FMT22; 10416271Skarels hp_type[unit] = hpmaptype(hpaddr, i, UNITTODRIVE(unit)); 10510334Shelge /* 10611366Ssam * Read in the bad sector table. 10710334Shelge */ 10811140Ssam st = &hpst[hp_type[unit]]; 10910334Shelge tio = *io; 11010334Shelge tio.i_bn = st->nspc * st->ncyl - st->nsect; 11110626Shelge tio.i_ma = (char *)&hpbad[unit]; 11210628Shelge tio.i_cc = sizeof (struct dkbad); 11310334Shelge tio.i_flgs |= F_RDDATA; 11410334Shelge for (i = 0; i < 5; i++) { 11510628Shelge if (hpstrategy(&tio, READ) == sizeof (struct dkbad)) 11610334Shelge break; 11710334Shelge tio.i_bn += 2; 11810334Shelge } 11910334Shelge if (i == 5) { 12010334Shelge printf("Unable to read bad sector table\n"); 12110334Shelge for (i = 0; i < MAXBADDESC; i++) { 12210334Shelge hpbad[unit].bt_bad[i].bt_cyl = -1; 12310334Shelge hpbad[unit].bt_bad[i].bt_trksec = -1; 12410334Shelge } 12510334Shelge } 12610334Shelge } 12715947Skarels st = &hpst[hp_type[unit]]; 12810334Shelge if (io->i_boff < 0 || io->i_boff > 7 || 12910334Shelge st->off[io->i_boff]== -1) 13010334Shelge _stop("hp bad minor"); 13110334Shelge io->i_boff = st->off[io->i_boff] * st->nspc; 13210334Shelge } 13310334Shelge 13410334Shelge hpstrategy(io, func) 13510334Shelge register struct iob *io; 13610334Shelge { 13710334Shelge register unit = io->i_unit; 13810334Shelge struct mba_regs *mba = mbamba(unit); 13911366Ssam daddr_t bn, startblock; 14010334Shelge struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit); 14110353Shelge struct st *st = &hpst[hp_type[unit]]; 14210334Shelge int cn, tn, sn, bytecnt, bytesleft; 14310334Shelge char *membase; 14410334Shelge int er1, er2, hprecal; 14510334Shelge 14610334Shelge sectsiz = SECTSIZ; 14710334Shelge if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0) 14810334Shelge sectsiz += HDRSIZ; 14910334Shelge if ((hpaddr->hpds & HPDS_VV) == 0) { 15010334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 15110334Shelge hpaddr->hpcs1 = HP_PRESET|HP_GO; 15211084Ssam if (!ML11) 15310334Shelge hpaddr->hpof = HPOF_FMT22; 15410334Shelge } 15510334Shelge io->i_errcnt = 0; 15611366Ssam ssect[unit] = 0; 15710334Shelge bytecnt = io->i_cc; 15810334Shelge membase = io->i_ma; 15910334Shelge startblock = io->i_bn; 16010608Ssam hprecal = 0; 16111140Ssam 16210626Shelge restart: 16310334Shelge bn = io->i_bn; 16410334Shelge cn = bn/st->nspc; 16510334Shelge sn = bn%st->nspc; 16610334Shelge tn = sn/st->nsect; 16711366Ssam sn = sn%st->nsect + ssect[unit]; 16810334Shelge 16910864Ssam HPWAIT(hpaddr); 17010626Shelge mba->mba_sr = -1; 17110647Shelge if (ML11) 17210334Shelge hpaddr->hpda = bn; 17310334Shelge else { 17410334Shelge hpaddr->hpdc = cn; 17510334Shelge hpaddr->hpda = (tn << 8) + sn; 17610334Shelge } 17710334Shelge if (mbastart(io, func) != 0) /* start transfer */ 17810334Shelge return (-1); 17910864Ssam HPWAIT(hpaddr); 18011366Ssam /* 18111366Ssam * Successful data transfer, return. 18211366Ssam */ 18315068Skarels if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0) 18415068Skarels goto done; 18510334Shelge 18611366Ssam /* 18711366Ssam * Error handling. Calculate location of error. 18811366Ssam */ 18911366Ssam bytesleft = MASKREG(mba->mba_bcr); 19011366Ssam if (bytesleft) 19111366Ssam bytesleft |= 0xffff0000; /* sxt */ 19211366Ssam bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz; 19315052Skarels er1 = MASKREG(hpaddr->hper1); 19415052Skarels er2 = MASKREG(hpaddr->hper2); 19515052Skarels if (er1 & (HPER1_DCK|HPER1_ECH)) 19615052Skarels bn--; /* Error is in Prev block */ 19710334Shelge cn = bn/st->nspc; 19810334Shelge sn = bn%st->nspc; 19910334Shelge tn = sn/st->nsect; 20010334Shelge sn = sn%st->nsect; 20111366Ssam if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) { 20211366Ssam printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b\n", 20311366Ssam cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 20411366Ssam printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS); 20511366Ssam printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft, 20611366Ssam hpaddr->hpof, hpaddr->hpda); 20711366Ssam } 20810334Shelge if (er1 & HPER1_HCRC) { 20910334Shelge er1 &= ~(HPER1_HCE|HPER1_FER); 21010334Shelge er2 &= ~HPER2_BSE; 21110334Shelge } 21211140Ssam /* 21311140Ssam * Give up early if drive write locked. 21411140Ssam */ 21510334Shelge if (er1&HPER1_WLE) { 21610334Shelge printf("hp%d: write locked\n", unit); 21711084Ssam return (-1); 21811084Ssam } 21911140Ssam /* 22011366Ssam * Interpret format error bit as a bad block on RP06's. 22111140Ssam */ 22211084Ssam if (MASKREG(er1) == HPER1_FER && RP06) 22310334Shelge goto badsect; 22411140Ssam 22511140Ssam /* 22611140Ssam * If a hard error, or maximum retry count 22711140Ssam * exceeded, clear controller state and 22811140Ssam * pass back error to caller. 22911140Ssam */ 23011084Ssam if (++io->i_errcnt > 27 || (er1 & HPER1_HARD) || 23111084Ssam (!ML11 && (er2 & HPER2_HARD))) { 23215052Skarels /* 23315052Skarels * The last ditch effort to bad sector forward 23415052Skarels * below will probably fail since mba byte ctr 23515052Skarels * (bcr) is different for BSE and ECC errors and 23615052Skarels * the wrong block will be revectored to if one 23715052Skarels * has 2 contiguous bad blocks and reads the second. 23815052Skarels * For now, we can probably just let a header CRC 23915052Skarels * error be handled like a BSE since no data will 24015052Skarels * have been transferred and the bcr should the same 24115052Skarels * as it would with a BSE error. 24215052Skarels * --ghg. 24315052Skarels */ 24415052Skarels if (er1 & HPER1_HCRC) 24515052Skarels if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0) 24615052Skarels goto success; 24710608Ssam hard0: 24810334Shelge io->i_error = EHER; 24911084Ssam if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR)) 25010334Shelge io->i_error = EWCK; 25110334Shelge hard: 25211366Ssam io->i_errblk = bn + ssect[unit]; 25310334Shelge printf("hp error: (cyl,trk,sec)=(%d,%d,%d) ds=%b \n", 25410334Shelge cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS); 25511084Ssam printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS); 25610334Shelge if (hpaddr->hpmr) 25710626Shelge printf(" mr1=%o", MASKREG(hpaddr->hpmr)); 25810334Shelge if (hpaddr->hpmr2) 25910626Shelge printf(" mr2=%o", MASKREG(hpaddr->hpmr2)); 26011366Ssam if (hpdebug[unit] & (HPF_BSEDEBUG|HPF_ECCDEBUG)) 26111366Ssam printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc), 26211366Ssam MASKREG(hpaddr->hpda)); 26310626Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 26410334Shelge printf("\n"); 26515068Skarels bytecnt = -1; 26615068Skarels goto done; 26710334Shelge 26811084Ssam } 26911140Ssam /* 27011140Ssam * Attempt to forward bad sectors on 27118515Smiriam * anything but an ML11. 27211140Ssam */ 27311084Ssam if ((er2 & HPER2_BSE) && !ML11) { 27410334Shelge badsect: 27511366Ssam if (!ssect[unit] && (er2&HPER2_SSE)) 27610647Shelge goto skipsect; 27711084Ssam if (io->i_flgs & F_NBSF) { 27810334Shelge io->i_error = EBSE; 27910334Shelge goto hard; 28010334Shelge } 28110334Shelge if (hpecc(io, BSE) == 0) 28210334Shelge goto success; 28311084Ssam io->i_error = EBSE; 28411084Ssam goto hard; 28511084Ssam } 28611140Ssam /* 28711140Ssam * Skip sector handling. 28811140Ssam */ 28911366Ssam if (RM80 && (er2 & HPER2_SSE)) { 29010647Shelge skipsect: 29110334Shelge (void) hpecc(io, SSE); 29211366Ssam ssect[unit] = 1; 29318515Smiriam goto restart; 29411084Ssam } 29511140Ssam /* 29611366Ssam * ECC correction? 29711140Ssam */ 29811084Ssam if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) { 29910864Ssam if (hpecc(io, ECC) == 0) 30010334Shelge goto success; 30111084Ssam io->i_error = EECC; 30215052Skarels io->i_errblk = bn + ssect[unit]; 30311084Ssam return (-1); 30410608Ssam } 30515052Skarels #ifdef F_SEVRE 30615052Skarels if (io->i_flgs & F_SEVRE) 30715052Skarels goto hard; 30815052Skarels #endif 30910608Ssam if (ML11 && (io->i_errcnt >= 16)) 31011084Ssam goto hard0; 31110608Ssam /* fall thru to retry */ 31210334Shelge hpaddr->hpcs1 = HP_DCLR|HP_GO; 31310864Ssam HPWAIT(hpaddr); 31411140Ssam 31511140Ssam /* 31611140Ssam * Every fourth retry recalibrate. 31711140Ssam */ 31811366Ssam if (((io->i_errcnt & 07) == 4) ) { 31910334Shelge hpaddr->hpcs1 = HP_RECAL|HP_GO; 32015052Skarels HPWAIT(hpaddr); 32110334Shelge hpaddr->hpdc = cn; 32210334Shelge hpaddr->hpcs1 = HP_SEEK|HP_GO; 32315052Skarels HPWAIT(hpaddr); 32415052Skarels } 32510864Ssam 32615052Skarels if (io->i_errcnt >= 16 && (io->i_flgs & F_READ)) { 32710334Shelge hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22; 32810334Shelge hpaddr->hpcs1 = HP_OFFSET|HP_GO; 32915052Skarels HPWAIT(hpaddr); 33010334Shelge } 33115052Skarels if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 33215052Skarels printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 33315052Skarels io->i_bn, io->i_cc, io->i_ma, hprecal); 33415052Skarels goto restart; /* retry whole transfer --ghg */ 33511084Ssam 33611140Ssam success: 33711140Ssam /* 33811140Ssam * On successful error recovery, bump 33911140Ssam * block number to advance to next portion 34011140Ssam * of i/o transfer. 34111140Ssam */ 34210334Shelge bn++; 34310334Shelge if ((bn-startblock) * sectsiz < bytecnt) { 34410334Shelge io->i_bn = bn; 34510334Shelge io->i_ma = membase + (io->i_bn - startblock)*sectsiz; 34610334Shelge io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz; 34711366Ssam if (hpdebug[unit] & (HPF_ECCDEBUG|HPF_BSEDEBUG)) 34811366Ssam printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n", 34911366Ssam io->i_bn, io->i_cc, io->i_ma, hprecal); 35010626Shelge goto restart; 35110334Shelge } 35215068Skarels done: 35315052Skarels if (io->i_errcnt >= 16) { 35415052Skarels hpaddr->hpcs1 = HP_RTC|HP_GO; 35515052Skarels while (hpaddr->hpds & HPDS_PIP) 35615052Skarels ; 35715052Skarels } 35818515Smiriam io->i_cc = bytecnt; /*reset i_cc to total count xfered*/ 35910334Shelge return (bytecnt); 36010334Shelge } 36110864Ssam 36210334Shelge hpecc(io, flag) 36310334Shelge register struct iob *io; 36410334Shelge int flag; 36510334Shelge { 36610334Shelge register unit = io->i_unit; 36710334Shelge register struct mba_regs *mbp = mbamba(unit); 36810334Shelge register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit); 36910353Shelge register struct st *st = &hpst[hp_type[unit]]; 37011084Ssam int npf, bn, cn, tn, sn, bcr; 37110334Shelge 37211366Ssam bcr = MASKREG(mbp->mba_bcr); 37311366Ssam if (bcr) 37411366Ssam bcr |= 0xffff0000; /* sxt */ 37511084Ssam npf = (bcr + io->i_cc) / sectsiz; /* # sectors read */ 37615052Skarels if (flag == ECC) 37715052Skarels npf--; /* Error is in prev block --ghg */ 37811366Ssam bn = io->i_bn + npf + ssect[unit]; /* physical block #*/ 37911366Ssam if (hpdebug[unit]&HPF_ECCDEBUG) 38011366Ssam printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n", 38111366Ssam bcr, npf, ssect[unit], sectsiz, io->i_cc); 38211140Ssam /* 38311140Ssam * ECC correction logic. 38411140Ssam */ 38511140Ssam if (flag == ECC) { 38610334Shelge register int i; 38710334Shelge caddr_t addr; 38811179Ssam int bit, o, mask, ecccnt = 0; 38910334Shelge 39010413Shelge printf("hp%d: soft ecc sn%d\n", unit, bn); 39110334Shelge mask = MASKREG(rp->hpec2); 39211084Ssam i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */ 39310334Shelge bit = i&07; 39411366Ssam o = (i & ~07) >> 3; 39510334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 39611179Ssam while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) { 39711179Ssam addr = io->i_ma + (npf*sectsiz) + o; 39811179Ssam /* 39911179Ssam * No data transfer occurs with a write check, 40011179Ssam * so don't correct the resident copy of data. 40111179Ssam */ 40211366Ssam if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { 40311366Ssam if (hpdebug[unit] & HPF_ECCDEBUG) 40411366Ssam printf("addr=%x old=%x ", addr, 40511366Ssam (*addr & 0xff)); 40611140Ssam *addr ^= (mask << bit); 40711366Ssam if (hpdebug[unit] & HPF_ECCDEBUG) 40811366Ssam printf("new=%x\n",(*addr & 0xff)); 40911366Ssam } 41011179Ssam o++, bit -= 8; 41111109Ssam if ((io->i_flgs & F_ECCLM) && ecccnt++ >= MAXECC) 41211084Ssam return (1); 41310334Shelge } 41415052Skarels #ifdef F_SEVRE 41515052Skarels if (io->i_flgs & F_SEVRE) 41615052Skarels return(1); 41715052Skarels #endif 41811179Ssam return (0); 41911084Ssam } 42010334Shelge 42111084Ssam /* 42211084Ssam * Skip sector error. 42311084Ssam * Set skip-sector-inhibit and 42411084Ssam * read next sector 42511084Ssam */ 42611140Ssam if (flag == SSE) { 42710334Shelge rp->hpcs1 = HP_DCLR | HP_GO; 42810864Ssam HPWAIT(rp); 42910334Shelge rp->hpof |= HPOF_SSEI; 43011084Ssam return (0); 43111140Ssam } 43210334Shelge 43311140Ssam /* 43411140Ssam * Bad block forwarding. 43511140Ssam */ 43611140Ssam if (flag == BSE) { 43710626Shelge int bbn; 43811084Ssam 43910626Shelge rp->hpcs1 = HP_DCLR | HP_GO; 44011366Ssam if (hpdebug[unit] & HPF_BSEDEBUG) 44111366Ssam printf("hpecc: BSE @ bn %d\n", bn); 44210334Shelge cn = bn/st->nspc; 44310334Shelge sn = bn%st->nspc; 44410334Shelge tn = sn/st->nsect; 44510626Shelge sn = sn%st->nsect; 44610626Shelge bcr += sectsiz; 44710626Shelge if ((bbn = isbad(&hpbad[unit], cn, tn, sn)) < 0) 44811084Ssam return (1); 44910626Shelge bbn = st->ncyl*st->nspc - st->nsect - 1 - bbn; 45010626Shelge cn = bbn/st->nspc; 45110626Shelge sn = bbn%st->nspc; 45210626Shelge tn = sn/st->nsect; 45310626Shelge sn = sn%st->nsect; 45410626Shelge io->i_cc = sectsiz; 45510626Shelge io->i_ma += npf*sectsiz; 45611366Ssam if (hpdebug[unit] & HPF_BSEDEBUG) 45711366Ssam printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); 45811366Ssam rp->hpof &= ~HPOF_SSEI; 45910626Shelge mbp->mba_sr = -1; 46010334Shelge rp->hpdc = cn; 46110334Shelge rp->hpda = (tn<<8) + sn; 46210334Shelge mbastart(io,io->i_flgs); 46311366Ssam io->i_errcnt = 0; 46410864Ssam HPWAIT(rp); 46510864Ssam return (rp->hpds&HPDS_ERR); 46610334Shelge } 46711084Ssam printf("hpecc: flag=%d\n", flag); 46811084Ssam return (1); 46910334Shelge } 47011140Ssam 47110334Shelge /*ARGSUSED*/ 47210334Shelge hpioctl(io, cmd, arg) 47310334Shelge struct iob *io; 47410334Shelge int cmd; 47510334Shelge caddr_t arg; 47610334Shelge { 47710647Shelge register unit = io->i_unit; 47810647Shelge struct st *st = &hpst[hp_type[unit]], *tmp; 47910647Shelge struct mba_drv *drv = mbadrv(unit); 48011366Ssam int flag; 48110334Shelge 48210334Shelge switch(cmd) { 48310334Shelge 48411366Ssam case SAIODEBUG: 48511366Ssam flag = (int)arg; 48611366Ssam if (flag > 0) 48711366Ssam hpdebug[unit] |= flag; 48811366Ssam else 48911366Ssam hpdebug[unit] &= ~flag; 49011366Ssam return (0); 49111366Ssam 49210334Shelge case SAIODEVDATA: 49310334Shelge if ((drv->mbd_dt&MBDT_TAP) == 0) { 49410353Shelge tmp = (struct st *)arg; 49510353Shelge *tmp = *st; 49611084Ssam return (0); 49710334Shelge } 49811084Ssam return (ECMD); 49910334Shelge 50011084Ssam case SAIOSSI: /* skip-sector-inhibit */ 50111084Ssam if (drv->mbd_dt&MBDT_TAP) 50211084Ssam return (ECMD); 50311084Ssam if ((io->i_flgs&F_SSI) == 0) { 50411084Ssam /* make sure this is done once only */ 50511084Ssam io->i_flgs |= F_SSI; 50611084Ssam st->nsect++; 50711084Ssam st->nspc += st->ntrak; 50810864Ssam } 50911084Ssam return (0); 51010626Shelge 51111084Ssam case SAIONOSSI: /* remove skip-sector-inhibit */ 51210626Shelge if (io->i_flgs & F_SSI) { 51310626Shelge io->i_flgs &= ~F_SSI; 51410626Shelge drv->mbd_of &= ~HPOF_SSEI; 51510626Shelge st->nsect--; 51610626Shelge st->nspc -= st->ntrak; 51710626Shelge } 51810626Shelge return(0); 51910626Shelge 52010864Ssam case SAIOSSDEV: /* drive have skip sector? */ 52111084Ssam return (RM80 ? 0 : ECMD); 52210334Shelge } 52311084Ssam return (ECMD); 52410334Shelge } 525