Commit | Line | Data |
---|---|---|
da7c5cc6 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 | * | |
31fec9db | 6 | * @(#)up.c 6.5 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
258a5c40 | 8 | |
0839bdeb SL |
9 | /* |
10 | * UNIBUS peripheral standalone driver | |
11 | * with ECC correction and bad block forwarding. | |
12 | * Also supports header operation and write | |
13 | * check for data and/or header. | |
14 | */ | |
258a5c40 SL |
15 | #include "../h/param.h" |
16 | #include "../h/inode.h" | |
17 | #include "../h/fs.h" | |
18 | #include "../h/dkbad.h" | |
19 | #include "../h/vmmac.h" | |
20 | ||
21 | #include "../vax/pte.h" | |
22 | #include "../vaxuba/upreg.h" | |
23 | #include "../vaxuba/ubareg.h" | |
24 | ||
0839bdeb | 25 | #include "saio.h" |
258a5c40 SL |
26 | #include "savax.h" |
27 | ||
31fec9db MK |
28 | #define RETRIES 27 |
29 | ||
b8ca3ab9 HS |
30 | #define MAXBADDESC 126 /* max number of bad sectors recorded */ |
31 | #define SECTSIZ 512 /* sector size in bytes */ | |
32 | #define HDRSIZ 4 /* number of bytes in sector header */ | |
dda2842d | 33 | |
258a5c40 | 34 | u_short ubastd[] = { 0776700 }; |
0839bdeb | 35 | |
b4736392 | 36 | extern struct st upst[]; |
0839bdeb | 37 | |
dda2842d SL |
38 | struct dkbad upbad[MAXNUBA*8]; /* bad sector table */ |
39 | int sectsiz; /* real sector size */ | |
31fec9db MK |
40 | |
41 | struct up_softc { | |
42 | char gottype; | |
43 | char type; | |
44 | char debug; | |
45 | # define UPF_BSEDEBUG 01 /* debugging bad sector forwarding */ | |
46 | # define UPF_ECCDEBUG 02 /* debugging ecc correction */ | |
47 | int retries; | |
48 | int ecclim; | |
49 | } up_softc[MAXNUBA * 8]; | |
dda2842d | 50 | |
258a5c40 SL |
51 | u_char up_offset[16] = { |
52 | UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400, | |
53 | UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800, | |
54 | UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200, | |
55 | 0, 0, 0, 0 | |
56 | }; | |
57 | ||
58 | upopen(io) | |
59 | register struct iob *io; | |
60 | { | |
b8ca3ab9 | 61 | register unit = io->i_unit; |
0839bdeb | 62 | register struct updevice *upaddr; |
31fec9db | 63 | register struct up_softc *sc = &up_softc[unit]; |
31fa9244 | 64 | register struct st *st; |
258a5c40 | 65 | |
b4736392 | 66 | if (io->i_boff < 0 || io->i_boff > 7) |
0839bdeb | 67 | _stop("up bad unit"); |
b8ca3ab9 | 68 | upaddr = (struct updevice *)ubamem(unit, ubastd[0]); |
73abfe3c | 69 | upaddr->upcs2 = unit % 8; |
3ab40097 | 70 | while ((upaddr->upcs1 & UP_DVA) == 0) |
258a5c40 | 71 | ; |
31fec9db | 72 | if (sc->gottype == 0) { |
0839bdeb SL |
73 | register int i; |
74 | struct iob tio; | |
75 | ||
31fec9db MK |
76 | sc->retries = RETRIES; |
77 | sc->ecclim = 11; | |
78 | sc->debug = 0; | |
79 | sc->type = upmaptype(unit, upaddr); | |
80 | if (sc->type < 0) | |
0839bdeb | 81 | _stop("unknown drive type"); |
31fec9db | 82 | st = &upst[sc->type]; |
b4736392 SL |
83 | if (st->off[io->i_boff] == -1) |
84 | _stop("up bad unit"); | |
0839bdeb | 85 | /* |
dda2842d | 86 | * Read in the bad sector table. |
0839bdeb SL |
87 | */ |
88 | tio = *io; | |
89 | tio.i_bn = st->nspc * st->ncyl - st->nsect; | |
258a5c40 | 90 | tio.i_ma = (char *)&upbad[tio.i_unit]; |
960ade39 | 91 | tio.i_cc = sizeof (struct dkbad); |
0839bdeb SL |
92 | tio.i_flgs |= F_RDDATA; |
93 | for (i = 0; i < 5; i++) { | |
960ade39 | 94 | if (upstrategy(&tio, READ) == sizeof (struct dkbad)) |
0839bdeb | 95 | break; |
258a5c40 SL |
96 | tio.i_bn += 2; |
97 | } | |
98 | if (i == 5) { | |
0839bdeb | 99 | printf("Unable to read bad sector table\n"); |
b8ca3ab9 HS |
100 | for (i = 0; i < MAXBADDESC; i++) { |
101 | upbad[unit].bt_bad[i].bt_cyl = -1; | |
102 | upbad[unit].bt_bad[i].bt_trksec = -1; | |
258a5c40 SL |
103 | } |
104 | } | |
31fec9db | 105 | sc->gottype = 1; |
258a5c40 | 106 | } |
31fec9db | 107 | st = &upst[sc->type]; |
258a5c40 | 108 | io->i_boff = st->off[io->i_boff] * st->nspc; |
0839bdeb | 109 | io->i_flgs &= ~F_TYPEMASK; |
258a5c40 SL |
110 | } |
111 | ||
112 | upstrategy(io, func) | |
113 | register struct iob *io; | |
114 | { | |
1f4919da | 115 | int cn, tn, sn, o; |
b8ca3ab9 | 116 | register unit = io->i_unit; |
258a5c40 SL |
117 | daddr_t bn; |
118 | int recal, info, waitdry; | |
119 | register struct updevice *upaddr = | |
b8ca3ab9 | 120 | (struct updevice *)ubamem(unit, ubastd[0]); |
31fec9db MK |
121 | struct up_softc *sc = &up_softc[unit]; |
122 | register struct st *st = &upst[sc->type]; | |
123 | int doprintf = 0, error, rv = io->i_cc; | |
258a5c40 | 124 | |
b8ca3ab9 | 125 | sectsiz = SECTSIZ; |
3ab40097 | 126 | if (io->i_flgs & (F_HDR|F_HCHECK)) |
b8ca3ab9 | 127 | sectsiz += HDRSIZ; |
dda2842d | 128 | upaddr->upcs2 = unit % 8; |
258a5c40 SL |
129 | if ((upaddr->upds & UPDS_VV) == 0) { |
130 | upaddr->upcs1 = UP_DCLR|UP_GO; | |
131 | upaddr->upcs1 = UP_PRESET|UP_GO; | |
132 | upaddr->upof = UPOF_FMT22; | |
133 | } | |
31fec9db MK |
134 | if ((upaddr->upds & UPDS_DREADY) == 0) { |
135 | printf("up%d not ready", unit); | |
136 | return (-1); | |
137 | } | |
258a5c40 SL |
138 | info = ubasetup(io, 1); |
139 | upaddr->upwc = -io->i_cc / sizeof (short); | |
3ab40097 SL |
140 | recal = 0; |
141 | io->i_errcnt = 0; | |
142 | ||
960ade39 | 143 | restart: |
31fec9db | 144 | error = 0; |
1f4919da SL |
145 | o = io->i_cc + (upaddr->upwc * sizeof (short)); |
146 | upaddr->upba = info + o; | |
147 | bn = io->i_bn + o / sectsiz; | |
31fec9db | 148 | if (doprintf && sc->debug & (UPF_ECCDEBUG|UPF_BSEDEBUG)) |
3beb607b | 149 | printf("wc=%d o=%d i_bn=%d bn=%d\n", |
dda2842d | 150 | upaddr->upwc, o, io->i_bn, bn); |
0839bdeb SL |
151 | while((upaddr->upds & UPDS_DRY) == 0) |
152 | ; | |
b8ca3ab9 | 153 | if (upstart(io, bn) != 0) { |
31fec9db MK |
154 | rv = -1; |
155 | goto done; | |
b8ca3ab9 | 156 | } |
258a5c40 SL |
157 | do { |
158 | DELAY(25); | |
159 | } while ((upaddr->upcs1 & UP_RDY) == 0); | |
3ab40097 SL |
160 | /* |
161 | * If transfer has completed, free UNIBUS | |
162 | * resources and return transfer size. | |
163 | */ | |
73abfe3c MK |
164 | if ((upaddr->upds&UPDS_ERR) == 0 && (upaddr->upcs1&UP_TRE) == 0) |
165 | goto done; | |
31fec9db MK |
166 | bn = io->i_bn + |
167 | (io->i_cc + upaddr->upwc * sizeof (short)) / sectsiz; | |
168 | if (upaddr->uper1 & (UPER1_DCK|UPER1_ECH)) | |
169 | bn--; | |
170 | cn = bn/st->nspc; | |
171 | sn = bn%st->nspc; | |
172 | tn = sn/st->nsect; | |
173 | sn = sn%st->nsect; | |
174 | if (sc->debug & (UPF_ECCDEBUG|UPF_BSEDEBUG)) { | |
175 | printf("up error: sn%d (cyl,trk,sec)=(%d,%d,%d) ", | |
176 | bn, cn, tn, sn); | |
3beb607b | 177 | printf("cs2=%b er1=%b er2=%b wc=%d\n", |
dda2842d | 178 | upaddr->upcs2, UPCS2_BITS, upaddr->uper1, |
3beb607b | 179 | UPER1_BITS, upaddr->uper2, UPER2_BITS, upaddr->upwc); |
dda2842d | 180 | } |
258a5c40 | 181 | waitdry = 0; |
3beb607b | 182 | while ((upaddr->upds&UPDS_DRY) == 0 && ++waitdry < sectsiz) |
0839bdeb | 183 | DELAY(5); |
3ab40097 SL |
184 | if (upaddr->uper1&UPER1_WLE) { |
185 | /* | |
186 | * Give up on write locked devices immediately. | |
187 | */ | |
188 | printf("up%d: write locked\n", unit); | |
31fec9db MK |
189 | rv = -1; |
190 | goto done; | |
3ab40097 | 191 | } |
31fec9db MK |
192 | if (upaddr->uper2 & UPER2_BSE) { |
193 | if ((io->i_flgs&F_NBSF) == 0 && upecc(io, BSE) == 0) | |
194 | goto success; | |
195 | error = EBSE; | |
196 | goto hard; | |
197 | } | |
198 | /* | |
199 | * ECC error. If a soft error, correct it; | |
200 | * if correction is too large, no more retries. | |
201 | */ | |
202 | if ((upaddr->uper1 & (UPER1_DCK|UPER1_ECH|UPER1_HCRC)) == UPER1_DCK) { | |
203 | if (upecc(io, ECC) == 0) | |
204 | goto success; | |
205 | error = EECC; | |
206 | goto hard; | |
207 | } | |
208 | /* | |
209 | * If the error is a header CRC, | |
210 | * check if a replacement sector exists in | |
211 | * the bad sector table. | |
212 | */ | |
213 | if ((upaddr->uper1&UPER1_HCRC) && (io->i_flgs&F_NBSF) == 0 && | |
214 | upecc(io, BSE) == 0) | |
215 | goto success; | |
216 | if (++io->i_errcnt > sc->retries) { | |
258a5c40 SL |
217 | /* |
218 | * After 28 retries (16 without offset, and | |
219 | * 12 with offset positioning) give up. | |
220 | */ | |
b8ca3ab9 | 221 | hard: |
31fec9db MK |
222 | if (error == 0) { |
223 | error = EHER; | |
224 | if (upaddr->upcs2 & UPCS2_WCE) | |
225 | error = EWCK; | |
226 | } | |
227 | printf("up error: sn%d (cyl,trk,sec)=(%d,%d,%d) ", | |
228 | bn, cn, tn, sn); | |
229 | printf("cs2=%b er1=%b er2=%b\n", | |
3ab40097 SL |
230 | upaddr->upcs2, UPCS2_BITS, upaddr->uper1, |
231 | UPER1_BITS, upaddr->uper2, UPER2_BITS); | |
258a5c40 | 232 | upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO; |
b8ca3ab9 | 233 | io->i_errblk = bn; |
73abfe3c MK |
234 | if (io->i_errcnt >= 16) { |
235 | upaddr->upof = UPOF_FMT22; | |
236 | upaddr->upcs1 = UP_RTC|UP_GO; | |
237 | while ((upaddr->upds&UPDS_DRY) == 0) | |
238 | DELAY(25); | |
239 | } | |
31fec9db MK |
240 | rv = -1; |
241 | goto done; | |
258a5c40 | 242 | } |
258a5c40 SL |
243 | /* |
244 | * Clear drive error and, every eight attempts, | |
245 | * (starting with the fourth) | |
246 | * recalibrate to clear the slate. | |
247 | */ | |
248 | upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO; | |
960ade39 | 249 | if ((io->i_errcnt&07) == 4 ) { |
258a5c40 | 250 | upaddr->upcs1 = UP_RECAL|UP_GO; |
73abfe3c MK |
251 | while ((upaddr->upds&UPDS_DRY) == 0) |
252 | DELAY(25); | |
258a5c40 SL |
253 | upaddr->updc = cn; |
254 | upaddr->upcs1 = UP_SEEK|UP_GO; | |
73abfe3c MK |
255 | while ((upaddr->upds&UPDS_DRY) == 0) |
256 | DELAY(25); | |
257 | } | |
258 | if (io->i_errcnt >= 16 && (func & READ)) { | |
258a5c40 SL |
259 | upaddr->upof = up_offset[io->i_errcnt & 017] | UPOF_FMT22; |
260 | upaddr->upcs1 = UP_OFFSET|UP_GO; | |
960ade39 HS |
261 | while ((upaddr->upds&UPDS_DRY) == 0) |
262 | DELAY(25); | |
258a5c40 | 263 | } |
960ade39 | 264 | goto restart; |
3ab40097 | 265 | |
258a5c40 | 266 | success: |
3beb607b SL |
267 | #define rounddown(x, y) (((x) / (y)) * (y)) |
268 | upaddr->upwc = rounddown(upaddr->upwc, sectsiz / sizeof (short)); | |
269 | if (upaddr->upwc) { | |
1f4919da | 270 | doprintf++; |
960ade39 | 271 | goto restart; |
1f4919da | 272 | } |
73abfe3c | 273 | done: |
258a5c40 | 274 | /* |
dda2842d | 275 | * Release UNIBUS |
258a5c40 SL |
276 | */ |
277 | ubafree(io, info); | |
73abfe3c MK |
278 | /* |
279 | * If we were offset positioning, | |
280 | * return to centerline. | |
281 | */ | |
282 | if (io->i_errcnt >= 16) { | |
283 | upaddr->upof = UPOF_FMT22; | |
284 | upaddr->upcs1 = UP_RTC|UP_GO; | |
285 | while ((upaddr->upds&UPDS_DRY) == 0) | |
286 | DELAY(25); | |
287 | } | |
31fec9db | 288 | return (rv); |
258a5c40 SL |
289 | } |
290 | ||
291 | /* | |
b4736392 SL |
292 | * Correct an ECC error, and restart the |
293 | * i/o to complete the transfer (if necessary). | |
294 | * This is quite complicated because the transfer | |
295 | * may be going to an odd memory address base and/or | |
258a5c40 SL |
296 | * across a page boundary. |
297 | */ | |
0839bdeb | 298 | upecc(io, flag) |
258a5c40 SL |
299 | register struct iob *io; |
300 | int flag; | |
301 | { | |
dda2842d | 302 | register i, unit = io->i_unit; |
31fec9db | 303 | register struct up_softc *sc = &up_softc[unit]; |
258a5c40 | 304 | register struct updevice *up = |
dda2842d | 305 | (struct updevice *)ubamem(unit, ubastd[0]); |
b8ca3ab9 | 306 | register struct st *st; |
258a5c40 | 307 | caddr_t addr; |
6796f4df | 308 | int bn, twc, npf, mask, cn, tn, sn; |
b8ca3ab9 | 309 | daddr_t bbn; |
258a5c40 SL |
310 | |
311 | /* | |
b4736392 SL |
312 | * Npf is the number of sectors transferred |
313 | * before the sector containing the ECC error; | |
314 | * bn is the current block number. | |
258a5c40 | 315 | */ |
b8ca3ab9 | 316 | twc = up->upwc; |
b4736392 | 317 | npf = ((twc * sizeof(short)) + io->i_cc) / sectsiz; |
73abfe3c MK |
318 | if (flag == ECC) |
319 | npf--; | |
31fec9db | 320 | if (sc->debug & UPF_ECCDEBUG) |
3beb607b SL |
321 | printf("npf=%d mask=0x%x ec1=%d wc=%d\n", |
322 | npf, up->upec2, up->upec1, twc); | |
1f4919da | 323 | bn = io->i_bn + npf; |
31fec9db | 324 | st = &upst[sc->type]; |
6796f4df HS |
325 | cn = bn/st->nspc; |
326 | sn = bn%st->nspc; | |
327 | tn = sn/st->nsect; | |
328 | sn = sn%st->nsect; | |
b4736392 | 329 | |
258a5c40 | 330 | /* |
b4736392 | 331 | * ECC correction. |
258a5c40 SL |
332 | */ |
333 | if (flag == ECC) { | |
31fec9db | 334 | int bit, o; |
3ab40097 | 335 | |
258a5c40 | 336 | mask = up->upec2; |
dda2842d | 337 | printf("up%d: soft ecc sn%d\n", unit, bn); |
31fec9db MK |
338 | for (i = mask, bit = 0; i; i >>= 1) |
339 | if (i & 1) | |
340 | bit++; | |
341 | if (bit > sc->ecclim) { | |
342 | printf("%d-bit error\n", bit); | |
343 | return (1); | |
344 | } | |
258a5c40 | 345 | /* |
1f4919da SL |
346 | * Compute the byte and bit position of |
347 | * the error. o is the byte offset in | |
348 | * the transfer at which the correction | |
349 | * applied. | |
258a5c40 SL |
350 | */ |
351 | i = up->upec1 - 1; /* -1 makes 0 origin */ | |
3beb607b SL |
352 | bit = i & 07; |
353 | o = (i & ~07) >> 3; | |
258a5c40 SL |
354 | up->upcs1 = UP_TRE|UP_DCLR|UP_GO; |
355 | /* | |
b4736392 SL |
356 | * Correct while possible bits remain of mask. |
357 | * Since mask contains 11 bits, we continue while | |
358 | * the bit offset is > -11. Also watch out for | |
359 | * end of this block and the end of the transfer. | |
258a5c40 | 360 | */ |
1f4919da | 361 | while (o < sectsiz && (npf*sectsiz)+o < io->i_cc && bit > -11) { |
258a5c40 | 362 | /* |
b4736392 | 363 | * addr = |
1f4919da | 364 | * (base address of transfer) + |
b4736392 SL |
365 | * (# sectors transferred before the error) * |
366 | * (sector size) + | |
1f4919da | 367 | * (byte offset to incorrect data) |
258a5c40 | 368 | */ |
1f4919da | 369 | addr = io->i_ma + (npf * sectsiz) + o; |
1f4919da SL |
370 | /* |
371 | * No data transfer occurs with a write check, | |
372 | * so don't correct the resident copy of data. | |
373 | */ | |
dda2842d | 374 | if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { |
31fec9db | 375 | if (sc->debug & UPF_ECCDEBUG) |
dda2842d SL |
376 | printf("addr=0x%x old=0x%x ", addr, |
377 | (*addr&0xff)); | |
b8ca3ab9 | 378 | *addr ^= (mask << bit); |
31fec9db | 379 | if (sc->debug & UPF_ECCDEBUG) |
dda2842d SL |
380 | printf("new=0x%x\n", (*addr&0xff)); |
381 | } | |
1f4919da | 382 | o++, bit -= 8; |
73abfe3c | 383 | } |
3ab40097 SL |
384 | return (0); |
385 | } | |
b4736392 SL |
386 | |
387 | /* | |
388 | * Bad sector forwarding. | |
389 | */ | |
3ab40097 | 390 | if (flag == BSE) { |
258a5c40 | 391 | /* |
b4736392 SL |
392 | * If not in bad sector table, |
393 | * indicate a hard error to caller. | |
258a5c40 | 394 | */ |
258a5c40 | 395 | up->upcs1 = UP_TRE|UP_DCLR|UP_GO; |
dda2842d | 396 | if ((bbn = isbad(&upbad[unit], cn, tn, sn)) < 0) |
3ab40097 | 397 | return (1); |
3beb607b | 398 | bbn = (st->ncyl * st->nspc) - st->nsect - 1 - bbn; |
b8ca3ab9 | 399 | twc = up->upwc + sectsiz; |
3ab40097 | 400 | up->upwc = - (sectsiz / sizeof (short)); |
31fec9db | 401 | if (sc->debug & UPF_BSEDEBUG) |
dda2842d | 402 | printf("revector sn %d to %d\n", sn, bbn); |
258a5c40 | 403 | /* |
b4736392 SL |
404 | * Clear the drive & read the replacement |
405 | * sector. If this is in the middle of a | |
406 | * transfer, then set up the controller | |
407 | * registers in a normal fashion. | |
408 | * The UNIBUS address need not be changed. | |
409 | */ | |
3beb607b | 410 | while ((up->upcs1 & UP_RDY) == 0) |
258a5c40 | 411 | ; |
3beb607b | 412 | if (upstart(io, bbn)) |
b8ca3ab9 HS |
413 | return (1); /* error */ |
414 | io->i_errcnt = 0; /* success */ | |
258a5c40 SL |
415 | do { |
416 | DELAY(25); | |
3beb607b SL |
417 | } while ((up->upcs1 & UP_RDY) == 0) ; |
418 | if ((up->upds & UPDS_ERR) || (up->upcs1 & UP_TRE)) { | |
419 | up->upwc = twc - sectsiz; | |
b8ca3ab9 | 420 | return (1); |
258a5c40 SL |
421 | } |
422 | } | |
960ade39 | 423 | if (twc) |
258a5c40 | 424 | up->upwc = twc; |
b8ca3ab9 | 425 | return (0); |
258a5c40 | 426 | } |
258a5c40 SL |
427 | |
428 | upstart(io, bn) | |
0839bdeb SL |
429 | register struct iob *io; |
430 | daddr_t bn; | |
258a5c40 SL |
431 | { |
432 | register struct updevice *upaddr = | |
0839bdeb | 433 | (struct updevice *)ubamem(io->i_unit, ubastd[0]); |
31fec9db MK |
434 | register struct up_softc *sc = &up_softc[io->i_unit]; |
435 | register struct st *st = &upst[sc->type]; | |
258a5c40 SL |
436 | int sn, tn; |
437 | ||
438 | sn = bn%st->nspc; | |
439 | tn = sn/st->nsect; | |
440 | sn %= st->nsect; | |
441 | upaddr->updc = bn/st->nspc; | |
442 | upaddr->upda = (tn << 8) + sn; | |
b8ca3ab9 | 443 | switch (io->i_flgs & F_TYPEMASK) { |
0839bdeb SL |
444 | |
445 | case F_RDDATA: | |
446 | upaddr->upcs1 = UP_RCOM|UP_GO; | |
447 | break; | |
448 | ||
449 | case F_WRDATA: | |
450 | upaddr->upcs1 = UP_WCOM|UP_GO; | |
258a5c40 | 451 | break; |
0839bdeb SL |
452 | |
453 | case F_HDR|F_RDDATA: | |
454 | upaddr->upcs1 = UP_RHDR|UP_GO; | |
455 | break; | |
456 | ||
457 | case F_HDR|F_WRDATA: | |
458 | upaddr->upcs1 = UP_WHDR|UP_GO; | |
258a5c40 | 459 | break; |
0839bdeb SL |
460 | |
461 | case F_CHECK|F_WRDATA: | |
462 | case F_CHECK|F_RDDATA: | |
258a5c40 SL |
463 | upaddr->upcs1 = UP_WCDATA|UP_GO; |
464 | break; | |
0839bdeb SL |
465 | |
466 | case F_HCHECK|F_WRDATA: | |
467 | case F_HCHECK|F_RDDATA: | |
258a5c40 SL |
468 | upaddr->upcs1 = UP_WCHDR|UP_GO; |
469 | break; | |
0839bdeb | 470 | |
258a5c40 | 471 | default: |
0839bdeb SL |
472 | io->i_error = ECMD; |
473 | io->i_flgs &= ~F_TYPEMASK; | |
474 | return (1); | |
258a5c40 | 475 | } |
0839bdeb | 476 | return (0); |
258a5c40 SL |
477 | } |
478 | ||
0839bdeb SL |
479 | /*ARGSUSED*/ |
480 | upioctl(io, cmd, arg) | |
481 | struct iob *io; | |
482 | int cmd; | |
483 | caddr_t arg; | |
484 | { | |
31fec9db MK |
485 | int unit = io->i_unit; |
486 | register struct up_softc *sc = &up_softc[unit]; | |
487 | struct st *st = &upst[sc->type]; | |
b8ca3ab9 HS |
488 | |
489 | switch(cmd) { | |
490 | ||
dda2842d | 491 | case SAIODEBUG: |
31fec9db MK |
492 | sc->debug = (int)arg; |
493 | break; | |
dda2842d | 494 | |
b8ca3ab9 | 495 | case SAIODEVDATA: |
31fec9db MK |
496 | *(struct st *)arg = *st; |
497 | break; | |
498 | ||
499 | case SAIOGBADINFO: | |
500 | *(struct dkbad *)arg = upbad[unit]; | |
501 | break; | |
502 | ||
503 | case SAIOECCLIM: | |
504 | sc->ecclim = (int)arg; | |
505 | break; | |
506 | ||
507 | case SAIORETRIES: | |
508 | sc->retries = (int)arg; | |
509 | break; | |
510 | ||
511 | default: | |
512 | return (ECMD); | |
b8ca3ab9 | 513 | } |
31fec9db | 514 | return (0); |
b8ca3ab9 | 515 | } |