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