uvax changes; fix devsw index in confxx; header updates
[unix-history] / usr / src / sys / vax / stand / hp.c
CommitLineData
8ae0e4b4 1/*
39c71180 2 * Copyright (c) 1982, 1986 Regents of the University of California.
8ae0e4b4
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
39c71180 6 * @(#)hp.c 7.5 (Berkeley) %G%
8ae0e4b4 7 */
63c82e3f
HS
8
9/*
10 * RP??/RM?? disk driver
11 * with ECC handling and bad block forwarding.
12 * Also supports header io operations and
13 * commands to write check header and data.
14 */
39c71180
MK
15#include "param.h"
16#include "inode.h"
17#include "fs.h"
18#include "dkbad.h"
19#include "disklabel.h"
63c82e3f
HS
20
21#include "../vax/pte.h"
39c71180 22
63c82e3f
HS
23#include "../vaxmba/hpreg.h"
24#include "../vaxmba/mbareg.h"
25
26#include "saio.h"
27#include "savax.h"
28
f834e141
MK
29#define RETRIES 27
30
63c82e3f
HS
31#define MASKREG(reg) ((reg)&0xffff)
32
356d90a8
SL
33#define MAXBADDESC 126
34#define SECTSIZ 512 /* sector size in bytes */
35#define HDRSIZ 4 /* number of bytes in sector header */
63c82e3f 36
80c81fbf 37char lbuf[SECTSIZ];
63c82e3f 38
80c81fbf
MK
39#define RP06(type) ((type) == MBDT_RP06 || (type) == MBDT_RP05 \
40 || (type) == MBDT_RP04)
41#define ML11(type) ((type) == MBDT_ML11A)
42#define RM80(type) ((type) == MBDT_RM80)
63c82e3f
HS
43
44u_char hp_offset[16] = {
45 HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
46 HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
47 HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
48 0, 0, 0, 0,
49};
50
80c81fbf
MK
51struct disklabel hplabel[MAXNMBA*8];
52#ifndef SMALL
356d90a8 53struct dkbad hpbad[MAXNMBA*8];
80c81fbf
MK
54int sectsiz;
55#endif
356d90a8 56
f834e141
MK
57struct hp_softc {
58 char type;
59 char gottype;
60 char ssect; /* 1 when on track w/skip sector */
61 char debug;
62# define HPF_BSEDEBUG 01 /* debugging bad sector forwarding */
63# define HPF_ECCDEBUG 02 /* debugging ecc correction */
64 int ecclim;
65 int retries;
66} hp_softc[MAXNMBA * 8];
356d90a8 67
4b5bcdd9
SL
68/*
69 * When awaiting command completion, don't
70 * hang on to the status register since
356d90a8 71 * this ties up some controllers.
4b5bcdd9 72 */
356d90a8
SL
73#define HPWAIT(addr) \
74 while ((((addr)->hpds)&HPDS_DRY)==0) DELAY(500);
4b5bcdd9 75
63c82e3f
HS
76hpopen(io)
77 register struct iob *io;
78{
79 register unit = io->i_unit;
80 struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit);
f834e141 81 register struct hp_softc *sc = &hp_softc[unit];
80c81fbf 82 register struct disklabel *lp = &hplabel[unit];
60bc077a 83 struct disklabel *dlp;
63c82e3f 84
39c71180 85 if (mbainit(UNITTOMBA(unit)) == 0)
80c81fbf 86 return (ENXIO);
f834e141 87 if (sc->gottype == 0) {
80c81fbf 88 register i;
63c82e3f
HS
89 struct iob tio;
90
80c81fbf 91#ifndef SMALL
f834e141
MK
92 sc->retries = RETRIES;
93 sc->ecclim = 11;
94 sc->debug = 0;
80c81fbf 95#endif
7fc00e31
HS
96 hpaddr->hpcs1 = HP_DCLR|HP_GO; /* init drive */
97 hpaddr->hpcs1 = HP_PRESET|HP_GO;
80c81fbf 98#ifndef SMALL
39c71180
MK
99 if ((hpaddr->hpds & HPDS_DPR) == 0) {
100 printf("drive nonexistent\n");
101 return (ENXIO);
102 }
80c81fbf
MK
103 sc->type = hpaddr->hpdt & MBDT_TYPE;
104 if (sc->type == MBDT_ML11B)
39c71180 105 sc->type = MBDT_ML11A;
80c81fbf
MK
106 if (!ML11(sc->type))
107#endif
7fc00e31 108 hpaddr->hpof = HPOF_FMT22;
63c82e3f 109 /*
80c81fbf 110 * Read in the pack label.
63c82e3f 111 */
80c81fbf
MK
112 lp->d_nsectors = 32;
113 lp->d_secpercyl = 20*32;
63c82e3f 114 tio = *io;
80c81fbf
MK
115 tio.i_bn = LABELSECTOR;
116 tio.i_ma = lbuf;
117 tio.i_cc = SECTSIZ;
118 tio.i_flgs |= F_RDDATA;
119 if (hpstrategy(&tio, READ) != SECTSIZ) {
39c71180 120 printf("can't read disk label\n");
80c81fbf
MK
121 return (EIO);
122 }
60bc077a
MK
123 dlp = (struct disklabel *)(lbuf + LABELOFFSET);
124 if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
80c81fbf 125 printf("hp%d: unlabeled\n", unit);
39c71180 126#if defined(COMPAT_42) /* && !defined(SMALL) */
80c81fbf
MK
127 hpmaptype(hpaddr, hpaddr->hpdt & MBDT_TYPE,
128 UNITTODRIVE(unit), lp);
129#else
130 return (ENXIO);
131#endif
60bc077a
MK
132 } else
133 *lp = *dlp;
134#ifndef SMALL
80c81fbf
MK
135 /*
136 * Read in the bad sector table.
137 */
138 tio.i_bn = lp->d_secpercyl * lp->d_ncylinders - lp->d_nsectors;
ccc991c5 139 tio.i_ma = (char *)&hpbad[unit];
711717bf 140 tio.i_cc = sizeof (struct dkbad);
63c82e3f 141 for (i = 0; i < 5; i++) {
711717bf 142 if (hpstrategy(&tio, READ) == sizeof (struct dkbad))
63c82e3f
HS
143 break;
144 tio.i_bn += 2;
145 }
146 if (i == 5) {
39c71180 147 printf("can't read bad sector table\n");
63c82e3f
HS
148 for (i = 0; i < MAXBADDESC; i++) {
149 hpbad[unit].bt_bad[i].bt_cyl = -1;
150 hpbad[unit].bt_bad[i].bt_trksec = -1;
151 }
f834e141 152 }
80c81fbf 153#endif
60bc077a 154 sc->gottype = 1;
63c82e3f 155 }
39c71180 156 if ((unsigned)io->i_boff >= lp->d_npartitions ||
80c81fbf 157 lp->d_partitions[io->i_boff].p_size == 0) {
39c71180 158 printf("hp bad minor\n");
80c81fbf
MK
159 return (EUNIT);
160 }
161 io->i_boff = lp->d_partitions[io->i_boff].p_offset;
162 return (0);
63c82e3f
HS
163}
164
165hpstrategy(io, func)
166 register struct iob *io;
167{
168 register unit = io->i_unit;
169 struct mba_regs *mba = mbamba(unit);
356d90a8 170 daddr_t bn, startblock;
63c82e3f 171 struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit);
f834e141 172 register struct hp_softc *sc = &hp_softc[unit];
80c81fbf 173 register struct disklabel *lp = &hplabel[unit];
39c71180 174 int cn, tn, sn, bytecnt, bytesleft, rv;
63c82e3f
HS
175 char *membase;
176 int er1, er2, hprecal;
177
80c81fbf 178#ifndef SMALL
63c82e3f
HS
179 sectsiz = SECTSIZ;
180 if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0)
181 sectsiz += HDRSIZ;
182 if ((hpaddr->hpds & HPDS_VV) == 0) {
183 hpaddr->hpcs1 = HP_DCLR|HP_GO;
184 hpaddr->hpcs1 = HP_PRESET|HP_GO;
80c81fbf 185 if (!ML11(sc->type))
63c82e3f
HS
186 hpaddr->hpof = HPOF_FMT22;
187 }
188 io->i_errcnt = 0;
f834e141
MK
189 sc->ssect = 0;
190 rv = bytecnt = io->i_cc;
63c82e3f
HS
191 membase = io->i_ma;
192 startblock = io->i_bn;
308847fc 193 hprecal = 0;
80c81fbf 194#endif
86bcc486 195
ccc991c5 196restart:
63c82e3f 197 bn = io->i_bn;
80c81fbf
MK
198 cn = bn / lp->d_secpercyl;
199 sn = bn % lp->d_secpercyl;
200 tn = sn / lp->d_nsectors;
201 sn = sn % lp->d_nsectors + sc->ssect;
63c82e3f 202
4b5bcdd9 203 HPWAIT(hpaddr);
ccc991c5 204 mba->mba_sr = -1;
80c81fbf 205 if (ML11(sc->type))
63c82e3f
HS
206 hpaddr->hpda = bn;
207 else {
208 hpaddr->hpdc = cn;
209 hpaddr->hpda = (tn << 8) + sn;
210 }
80c81fbf
MK
211#ifdef SMALL
212 mbastart(io, func); /* start transfer */
213 HPWAIT(hpaddr);
214 if (hpaddr->hpds & HPDS_ERR) {
215 printf("hp error: sn [%d-%d) ds=%b er1=%b\n",
216 bn, bn + io->i_cc/SECTSIZ, MASKREG(hpaddr->hpds), HPDS_BITS,
217 MASKREG(hpaddr->hper1), HPER1_BITS);
218 return (-1);
219 }
220 return (io->i_cc);
221#else
f834e141
MK
222 if (mbastart(io, func) != 0) { /* start transfer */
223 rv = -1;
224 goto done;
225 }
4b5bcdd9 226 HPWAIT(hpaddr);
356d90a8
SL
227 /*
228 * Successful data transfer, return.
229 */
c5fc2df8
MK
230 if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0)
231 goto done;
63c82e3f 232
356d90a8
SL
233 /*
234 * Error handling. Calculate location of error.
235 */
236 bytesleft = MASKREG(mba->mba_bcr);
237 if (bytesleft)
238 bytesleft |= 0xffff0000; /* sxt */
239 bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz;
71da8ead
MK
240 er1 = MASKREG(hpaddr->hper1);
241 er2 = MASKREG(hpaddr->hper2);
242 if (er1 & (HPER1_DCK|HPER1_ECH))
243 bn--; /* Error is in Prev block */
80c81fbf
MK
244 cn = bn/lp->d_secpercyl;
245 sn = bn%lp->d_secpercyl;
246 tn = sn/lp->d_nsectors;
247 sn = sn%lp->d_nsectors;
f834e141
MK
248 if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) {
249 printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b\n",
250 bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS);
356d90a8
SL
251 printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS);
252 printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft,
253 hpaddr->hpof, hpaddr->hpda);
254 }
63c82e3f
HS
255 if (er1 & HPER1_HCRC) {
256 er1 &= ~(HPER1_HCE|HPER1_FER);
257 er2 &= ~HPER2_BSE;
f834e141
MK
258 if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0)
259 goto success;
63c82e3f 260 }
86bcc486
SL
261 /*
262 * Give up early if drive write locked.
263 */
63c82e3f
HS
264 if (er1&HPER1_WLE) {
265 printf("hp%d: write locked\n", unit);
f834e141
MK
266 rv = -1;
267 goto done;
9d78a350 268 }
86bcc486 269 /*
f834e141 270 * Skip sector handling.
86bcc486 271 */
80c81fbf 272 if (RM80(sc->type) && (er2 & HPER2_SSE)) {
f834e141
MK
273 (void) hpecc(io, SSE);
274 sc->ssect = 1;
275 goto restart;
9d78a350 276 }
86bcc486 277 /*
f834e141
MK
278 * Attempt to forward bad sectors on anything but an ML11.
279 * Interpret format error bit as a bad block on RP06's.
86bcc486 280 */
80c81fbf
MK
281 if (((er2 & HPER2_BSE) && !ML11(sc->type)) ||
282 (MASKREG(er1) == HPER1_FER && RP06(sc->type))) {
9d78a350 283 if (io->i_flgs & F_NBSF) {
63c82e3f
HS
284 io->i_error = EBSE;
285 goto hard;
286 }
287 if (hpecc(io, BSE) == 0)
288 goto success;
9d78a350
SL
289 io->i_error = EBSE;
290 goto hard;
291 }
86bcc486 292 /*
356d90a8 293 * ECC correction?
86bcc486 294 */
9d78a350 295 if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) {
4b5bcdd9 296 if (hpecc(io, ECC) == 0)
63c82e3f 297 goto success;
9d78a350 298 io->i_error = EECC;
71da8ead 299 goto hard;
f834e141
MK
300 }
301
302 /*
303 * If a hard error, or maximum retry count
304 * exceeded, clear controller state and
305 * pass back error to caller.
306 */
307 if (++io->i_errcnt > sc->retries || (er1 & HPER1_HARD) ||
80c81fbf
MK
308 (!ML11(sc->type) && (er2 & HPER2_HARD)) ||
309 (ML11(sc->type) && (io->i_errcnt >= 16))) {
f834e141
MK
310 io->i_error = EHER;
311 if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR))
312 io->i_error = EWCK;
313hard:
314 io->i_errblk = bn + sc->ssect;
315 if (sc->debug & (HPF_BSEDEBUG|HPF_ECCDEBUG))
316 printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc),
317 MASKREG(hpaddr->hpda));
318 else {
319 printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b \n",
320 bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS);
321 printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS);
322 }
323 hpaddr->hpcs1 = HP_DCLR|HP_GO;
324 printf("\n");
325 rv = -1;
326 goto done;
327
328 }
308847fc 329 /* fall thru to retry */
63c82e3f 330 hpaddr->hpcs1 = HP_DCLR|HP_GO;
4b5bcdd9 331 HPWAIT(hpaddr);
86bcc486
SL
332
333 /*
334 * Every fourth retry recalibrate.
335 */
356d90a8 336 if (((io->i_errcnt & 07) == 4) ) {
63c82e3f 337 hpaddr->hpcs1 = HP_RECAL|HP_GO;
71da8ead 338 HPWAIT(hpaddr);
63c82e3f
HS
339 hpaddr->hpdc = cn;
340 hpaddr->hpcs1 = HP_SEEK|HP_GO;
71da8ead
MK
341 HPWAIT(hpaddr);
342 }
4b5bcdd9 343
71da8ead 344 if (io->i_errcnt >= 16 && (io->i_flgs & F_READ)) {
63c82e3f
HS
345 hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22;
346 hpaddr->hpcs1 = HP_OFFSET|HP_GO;
71da8ead 347 HPWAIT(hpaddr);
63c82e3f 348 }
f834e141 349 if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG))
71da8ead
MK
350 printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n",
351 io->i_bn, io->i_cc, io->i_ma, hprecal);
f834e141 352 goto restart;
9d78a350 353
86bcc486
SL
354success:
355 /*
356 * On successful error recovery, bump
357 * block number to advance to next portion
358 * of i/o transfer.
359 */
63c82e3f
HS
360 bn++;
361 if ((bn-startblock) * sectsiz < bytecnt) {
63c82e3f 362 io->i_bn = bn;
63c82e3f
HS
363 io->i_ma = membase + (io->i_bn - startblock)*sectsiz;
364 io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz;
f834e141 365 if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG))
356d90a8
SL
366 printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n",
367 io->i_bn, io->i_cc, io->i_ma, hprecal);
ccc991c5 368 goto restart;
63c82e3f 369 }
c5fc2df8 370done:
71da8ead
MK
371 if (io->i_errcnt >= 16) {
372 hpaddr->hpcs1 = HP_RTC|HP_GO;
373 while (hpaddr->hpds & HPDS_PIP)
374 ;
375 }
f834e141 376 io->i_bn = startblock; /*reset i_bn to original */
2f1563bc 377 io->i_cc = bytecnt; /*reset i_cc to total count xfered*/
f834e141
MK
378 io->i_ma = membase; /*reset i_ma to original */
379 return (rv);
80c81fbf 380#endif
63c82e3f 381}
4b5bcdd9 382
80c81fbf 383#ifndef SMALL
63c82e3f
HS
384hpecc(io, flag)
385 register struct iob *io;
386 int flag;
387{
388 register unit = io->i_unit;
389 register struct mba_regs *mbp = mbamba(unit);
390 register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit);
f834e141 391 register struct hp_softc *sc = &hp_softc[unit];
80c81fbf 392 register struct disklabel *lp = &hplabel[unit];
9d78a350 393 int npf, bn, cn, tn, sn, bcr;
63c82e3f 394
356d90a8
SL
395 bcr = MASKREG(mbp->mba_bcr);
396 if (bcr)
397 bcr |= 0xffff0000; /* sxt */
9d78a350 398 npf = (bcr + io->i_cc) / sectsiz; /* # sectors read */
71da8ead
MK
399 if (flag == ECC)
400 npf--; /* Error is in prev block --ghg */
f834e141
MK
401 bn = io->i_bn + npf + sc->ssect; /* physical block #*/
402 if (sc->debug & HPF_ECCDEBUG)
356d90a8 403 printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n",
f834e141 404 bcr, npf, sc->ssect, sectsiz, io->i_cc);
86bcc486
SL
405 /*
406 * ECC correction logic.
407 */
408 if (flag == ECC) {
63c82e3f
HS
409 register int i;
410 caddr_t addr;
f834e141 411 int bit, o, mask;
63c82e3f 412
0cd55454 413 printf("hp%d: soft ecc sn%d\n", unit, bn);
63c82e3f 414 mask = MASKREG(rp->hpec2);
f834e141
MK
415 for (i = mask, bit = 0; i; i >>= 1)
416 if (i & 1)
417 bit++;
418 if (bit > sc->ecclim) {
419 printf("%d-bit error\n", bit);
420 return (1);
421 }
9d78a350 422 i = MASKREG(rp->hpec1) - 1; /* -1 makes 0 origin */
63c82e3f 423 bit = i&07;
356d90a8 424 o = (i & ~07) >> 3;
63c82e3f 425 rp->hpcs1 = HP_DCLR | HP_GO;
10860662
SL
426 while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) {
427 addr = io->i_ma + (npf*sectsiz) + o;
10860662
SL
428 /*
429 * No data transfer occurs with a write check,
430 * so don't correct the resident copy of data.
431 */
356d90a8 432 if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) {
f834e141 433 if (sc->debug & HPF_ECCDEBUG)
356d90a8
SL
434 printf("addr=%x old=%x ", addr,
435 (*addr & 0xff));
86bcc486 436 *addr ^= (mask << bit);
f834e141 437 if (sc->debug & HPF_ECCDEBUG)
356d90a8
SL
438 printf("new=%x\n",(*addr & 0xff));
439 }
10860662 440 o++, bit -= 8;
63c82e3f 441 }
10860662 442 return (0);
9d78a350 443 }
63c82e3f 444
9d78a350
SL
445 /*
446 * Skip sector error.
447 * Set skip-sector-inhibit and
448 * read next sector
449 */
86bcc486 450 if (flag == SSE) {
63c82e3f 451 rp->hpcs1 = HP_DCLR | HP_GO;
4b5bcdd9 452 HPWAIT(rp);
63c82e3f 453 rp->hpof |= HPOF_SSEI;
9d78a350 454 return (0);
86bcc486 455 }
63c82e3f 456
86bcc486
SL
457 /*
458 * Bad block forwarding.
459 */
460 if (flag == BSE) {
ccc991c5 461 int bbn;
9d78a350 462
ccc991c5 463 rp->hpcs1 = HP_DCLR | HP_GO;
f834e141 464 if (sc->debug & HPF_BSEDEBUG)
356d90a8 465 printf("hpecc: BSE @ bn %d\n", bn);
80c81fbf
MK
466 cn = bn / lp->d_secpercyl;
467 sn = bn % lp->d_secpercyl;
468 tn = sn / lp->d_nsectors;
469 sn = sn % lp->d_nsectors;
ccc991c5
HS
470 bcr += sectsiz;
471 if ((bbn = isbad(&hpbad[unit], cn, tn, sn)) < 0)
9d78a350 472 return (1);
80c81fbf
MK
473 bbn = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors - 1
474 - bbn;
475 cn = bbn / lp->d_secpercyl;
476 sn = bbn % lp->d_secpercyl;
477 tn = sn / lp->d_nsectors;
39c71180 478 sn = sn % lp->d_nsectors;
ccc991c5 479 io->i_cc = sectsiz;
80c81fbf 480 io->i_ma += npf * sectsiz;
f834e141 481 if (sc->debug & HPF_BSEDEBUG)
356d90a8
SL
482 printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
483 rp->hpof &= ~HPOF_SSEI;
ccc991c5 484 mbp->mba_sr = -1;
63c82e3f
HS
485 rp->hpdc = cn;
486 rp->hpda = (tn<<8) + sn;
63c82e3f 487 mbastart(io,io->i_flgs);
356d90a8 488 io->i_errcnt = 0;
4b5bcdd9
SL
489 HPWAIT(rp);
490 return (rp->hpds&HPDS_ERR);
63c82e3f 491 }
9d78a350
SL
492 printf("hpecc: flag=%d\n", flag);
493 return (1);
63c82e3f 494}
80c81fbf 495#endif
86bcc486 496
63c82e3f
HS
497/*ARGSUSED*/
498hpioctl(io, cmd, arg)
499 struct iob *io;
500 int cmd;
501 caddr_t arg;
502{
80c81fbf
MK
503#ifdef SMALL
504 return (ECMD);
505#else
7fc00e31 506 register unit = io->i_unit;
f834e141 507 register struct hp_softc *sc = &hp_softc[unit];
80c81fbf 508 register struct disklabel *lp = &hplabel[unit];
7fc00e31 509 struct mba_drv *drv = mbadrv(unit);
63c82e3f
HS
510
511 switch(cmd) {
512
356d90a8 513 case SAIODEBUG:
f834e141
MK
514 sc->debug = (int)arg;
515 break;
356d90a8 516
63c82e3f 517 case SAIODEVDATA:
f834e141
MK
518 if (drv->mbd_dt&MBDT_TAP)
519 return (ECMD);
80c81fbf 520 *(struct disklabel *)arg = *lp;
f834e141
MK
521 break;
522
523 case SAIOGBADINFO:
524 if (drv->mbd_dt&MBDT_TAP)
525 return (ECMD);
526 *(struct dkbad *)arg = hpbad[unit];
527 break;
528
529 case SAIOECCLIM:
530 sc->ecclim = (int)arg;
531 break;
532
533 case SAIORETRIES:
534 sc->retries = (int)arg;
535 break;
63c82e3f 536
9d78a350
SL
537 case SAIOSSI: /* skip-sector-inhibit */
538 if (drv->mbd_dt&MBDT_TAP)
539 return (ECMD);
540 if ((io->i_flgs&F_SSI) == 0) {
541 /* make sure this is done once only */
542 io->i_flgs |= F_SSI;
80c81fbf
MK
543 lp->d_nsectors++;
544 lp->d_secpercyl += lp->d_ntracks;
4b5bcdd9 545 }
f834e141 546 break;
ccc991c5 547
9d78a350 548 case SAIONOSSI: /* remove skip-sector-inhibit */
ccc991c5
HS
549 if (io->i_flgs & F_SSI) {
550 io->i_flgs &= ~F_SSI;
551 drv->mbd_of &= ~HPOF_SSEI;
80c81fbf
MK
552 lp->d_nsectors--;
553 lp->d_secpercyl -= lp->d_ntracks;
ccc991c5 554 }
f834e141 555 break;
ccc991c5 556
4b5bcdd9 557 case SAIOSSDEV: /* drive have skip sector? */
80c81fbf 558 return (RM80(sc->type) ? 0 : ECMD);
f834e141
MK
559
560 default:
561 return (ECMD);
63c82e3f 562 }
f834e141 563 return (0);
80c81fbf 564#endif
63c82e3f 565}