Commit | Line | Data |
---|---|---|
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 | 37 | char 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 | |
44 | u_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 |
51 | struct disklabel hplabel[MAXNMBA*8]; |
52 | #ifndef SMALL | |
356d90a8 | 53 | struct dkbad hpbad[MAXNMBA*8]; |
80c81fbf MK |
54 | int sectsiz; |
55 | #endif | |
356d90a8 | 56 | |
f834e141 MK |
57 | struct 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 |
76 | hpopen(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 | ||
165 | hpstrategy(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 | 196 | restart: |
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; | |
313 | hard: | |
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 |
354 | success: |
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 | 370 | done: |
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 |
384 | hpecc(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*/ |
498 | hpioctl(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 | } |