Commit | Line | Data |
---|---|---|
cc7ff771 | 1 | /* rk.c 4.39 82/03/29 */ |
d483c58c | 2 | |
66b4fb09 | 3 | #include "rk.h" |
872b4e09 | 4 | #if NHK > 0 |
a0eab615 BJ |
5 | int rkpip; /* DEBUG */ |
6 | int rknosval; /* DEBUG */ | |
b4208137 | 7 | #ifdef RKDEBUG |
535f6684 | 8 | int rkdebug; |
b4208137 BJ |
9 | #endif |
10 | #ifdef RKBDEBUG | |
11 | int rkbdebug; | |
12 | #endif | |
d483c58c | 13 | /* |
535f6684 | 14 | * RK611/RK0[67] disk driver |
9037157b BJ |
15 | * |
16 | * This driver mimics up.c; see it for an explanation of common code. | |
ed687006 | 17 | * |
c9e9b65b | 18 | * TODO: |
777e0613 | 19 | * Learn why we lose an interrupt sometime when spinning drives down |
d483c58c | 20 | */ |
d483c58c BJ |
21 | #include "../h/param.h" |
22 | #include "../h/systm.h" | |
23 | #include "../h/buf.h" | |
24 | #include "../h/conf.h" | |
25 | #include "../h/dir.h" | |
26 | #include "../h/user.h" | |
27 | #include "../h/pte.h" | |
28 | #include "../h/map.h" | |
0801d37f | 29 | #include "../h/vm.h" |
89bd2f01 BJ |
30 | #include "../h/ubareg.h" |
31 | #include "../h/ubavar.h" | |
d483c58c | 32 | #include "../h/dk.h" |
0801d37f BJ |
33 | #include "../h/cpu.h" |
34 | #include "../h/cmap.h" | |
b4208137 | 35 | #include "../h/dkbad.h" |
0801d37f BJ |
36 | |
37 | #include "../h/rkreg.h" | |
d483c58c | 38 | |
0801d37f BJ |
39 | struct rk_softc { |
40 | int sc_softas; | |
41 | int sc_ndrive; | |
42 | int sc_wticks; | |
43 | int sc_recal; | |
872b4e09 | 44 | } rk_softc[NHK]; |
0801d37f BJ |
45 | |
46 | /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ | |
c84ff1f9 | 47 | struct size { |
0801d37f | 48 | daddr_t nblocks; |
d483c58c | 49 | int cyloff; |
b4208137 | 50 | } rk7_sizes[8] ={ |
0801d37f | 51 | 15884, 0, /* A=cyl 0 thru 240 */ |
22717fbb BJ |
52 | 10032, 241, /* B=cyl 241 thru 392 */ |
53 | 53790, 0, /* C=cyl 0 thru 814 */ | |
d483c58c BJ |
54 | 0, 0, |
55 | 0, 0, | |
56 | 0, 0, | |
0801d37f | 57 | 27786, 393, /* G=cyl 393 thru 813 */ |
d483c58c | 58 | 0, 0, |
b4208137 BJ |
59 | }, rk6_sizes[8] ={ |
60 | 15884, 0, /* A=cyl 0 thru 240 */ | |
61 | 11154, 241, /* B=cyl 241 thru 409 */ | |
62 | 27126, 0, /* C=cyl 0 thru 410 */ | |
63 | 0, 0, | |
64 | 0, 0, | |
65 | 0, 0, | |
66 | 0, 0, | |
67 | 0, 0, | |
d483c58c | 68 | }; |
0801d37f BJ |
69 | /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ |
70 | ||
b4208137 BJ |
71 | short rktypes[] = { RK_CDT, 0 }; |
72 | ||
0801d37f | 73 | int rkprobe(), rkslave(), rkattach(), rkdgo(), rkintr(); |
89bd2f01 BJ |
74 | struct uba_ctlr *rkminfo[NHK]; |
75 | struct uba_device *rkdinfo[NRK]; | |
76 | struct uba_device *rkip[NHK][4]; | |
0801d37f BJ |
77 | |
78 | u_short rkstd[] = { 0777440, 0 }; | |
79 | struct uba_driver hkdriver = | |
9037157b | 80 | { rkprobe, rkslave, rkattach, rkdgo, rkstd, "rk", rkdinfo, "hk", rkminfo, 1 }; |
872b4e09 BJ |
81 | struct buf rkutab[NRK]; |
82 | short rkcyl[NRK]; | |
616c2a83 | 83 | #ifndef NOBADSECT |
b4208137 BJ |
84 | struct dkbad rkbad[NRK]; |
85 | struct buf brkbuf[NRK]; | |
86 | #endif | |
0801d37f BJ |
87 | |
88 | struct rkst { | |
89 | short nsect; | |
90 | short ntrak; | |
91 | short nspc; | |
92 | short ncyl; | |
93 | struct size *sizes; | |
94 | } rkst[] = { | |
95 | NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK7CYL, rk7_sizes, | |
b4208137 | 96 | NRKSECT, NRKTRK, NRKSECT*NRKTRK, NRK6CYL, rk6_sizes, |
0801d37f BJ |
97 | }; |
98 | ||
99 | u_char rk_offset[16] = | |
535f6684 BJ |
100 | { RKAS_P400,RKAS_M400,RKAS_P400,RKAS_M400,RKAS_P800,RKAS_M800,RKAS_P800, |
101 | RKAS_M800,RKAS_P1200,RKAS_M1200,RKAS_P1200,RKAS_M1200,0,0,0,0 | |
102 | }; | |
0801d37f | 103 | |
872b4e09 | 104 | struct buf rrkbuf[NRK]; |
0801d37f BJ |
105 | |
106 | #define b_cylin b_resid | |
107 | ||
108 | #ifdef INTRLVE | |
109 | daddr_t dkblock(); | |
110 | #endif | |
111 | ||
112 | int rkwstart, rkwatch(); | |
113 | ||
114 | rkprobe(reg) | |
115 | caddr_t reg; | |
116 | { | |
117 | register int br, cvec; | |
118 | ||
119 | #ifdef lint | |
120 | br = 0; cvec = br; br = cvec; | |
89b8a44c | 121 | rkintr(0); |
0801d37f BJ |
122 | #endif |
123 | ((struct rkdevice *)reg)->rkcs1 = RK_CDT|RK_IE|RK_CRDY; | |
124 | DELAY(10); | |
125 | ((struct rkdevice *)reg)->rkcs1 = RK_CDT; | |
126 | return (1); | |
127 | } | |
128 | ||
129 | rkslave(ui, reg) | |
89bd2f01 | 130 | struct uba_device *ui; |
0801d37f BJ |
131 | caddr_t reg; |
132 | { | |
133 | register struct rkdevice *rkaddr = (struct rkdevice *)reg; | |
134 | ||
b4208137 BJ |
135 | ui->ui_type = 0; |
136 | rkaddr->rkcs1 = RK_CCLR; | |
0801d37f | 137 | rkaddr->rkcs2 = ui->ui_slave; |
29a0409f | 138 | rkaddr->rkcs1 = RK_CDT|RK_DCLR|RK_GO; |
9037157b | 139 | rkwait(rkaddr); |
28de6ed0 | 140 | DELAY(50); |
535f6684 | 141 | if (rkaddr->rkcs2&RKCS2_NED || (rkaddr->rkds&RKDS_SVAL) == 0) { |
b4208137 | 142 | rkaddr->rkcs1 = RK_CCLR; |
0801d37f BJ |
143 | return (0); |
144 | } | |
b4208137 BJ |
145 | if (rkaddr->rkcs1&RK_CERR && rkaddr->rker&RKER_DTYE) { |
146 | ui->ui_type = 1; | |
147 | rkaddr->rkcs1 = RK_CCLR; | |
148 | } | |
0801d37f BJ |
149 | return (1); |
150 | } | |
d483c58c | 151 | |
0801d37f | 152 | rkattach(ui) |
89bd2f01 | 153 | register struct uba_device *ui; |
0801d37f BJ |
154 | { |
155 | ||
156 | if (rkwstart == 0) { | |
7780575a | 157 | timeout(rkwatch, (caddr_t)0, hz); |
0801d37f BJ |
158 | rkwstart++; |
159 | } | |
160 | if (ui->ui_dk >= 0) | |
7780575a | 161 | dk_mspw[ui->ui_dk] = 1.0 / (60 * NRKSECT * 256); |
0801d37f BJ |
162 | rkip[ui->ui_ctlr][ui->ui_slave] = ui; |
163 | rk_softc[ui->ui_ctlr].sc_ndrive++; | |
164 | rkcyl[ui->ui_unit] = -1; | |
b4208137 | 165 | ui->ui_flags = 0; |
0801d37f BJ |
166 | } |
167 | ||
d483c58c | 168 | rkstrategy(bp) |
0801d37f | 169 | register struct buf *bp; |
d483c58c | 170 | { |
89bd2f01 | 171 | register struct uba_device *ui; |
0801d37f BJ |
172 | register struct rkst *st; |
173 | register int unit; | |
174 | register struct buf *dp; | |
175 | int xunit = minor(bp->b_dev) & 07; | |
176 | long bn, sz; | |
530d0032 | 177 | int s; |
0801d37f BJ |
178 | |
179 | sz = (bp->b_bcount+511) >> 9; | |
180 | unit = dkunit(bp); | |
872b4e09 | 181 | if (unit >= NRK) |
0801d37f BJ |
182 | goto bad; |
183 | ui = rkdinfo[unit]; | |
184 | if (ui == 0 || ui->ui_alive == 0) | |
185 | goto bad; | |
186 | st = &rkst[ui->ui_type]; | |
187 | if (bp->b_blkno < 0 || | |
188 | (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks) | |
189 | goto bad; | |
190 | bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff; | |
530d0032 | 191 | s = spl5(); |
0801d37f BJ |
192 | dp = &rkutab[ui->ui_unit]; |
193 | disksort(dp, bp); | |
194 | if (dp->b_active == 0) { | |
195 | (void) rkustart(ui); | |
196 | bp = &ui->ui_mi->um_tab; | |
197 | if (bp->b_actf && bp->b_active == 0) | |
198 | (void) rkstart(ui->ui_mi); | |
d483c58c | 199 | } |
530d0032 | 200 | splx(s); |
0801d37f BJ |
201 | return; |
202 | ||
203 | bad: | |
204 | bp->b_flags |= B_ERROR; | |
205 | iodone(bp); | |
206 | return; | |
d483c58c BJ |
207 | } |
208 | ||
0801d37f | 209 | rkustart(ui) |
89bd2f01 | 210 | register struct uba_device *ui; |
0801d37f BJ |
211 | { |
212 | register struct buf *bp, *dp; | |
89bd2f01 | 213 | register struct uba_ctlr *um; |
0801d37f | 214 | register struct rkdevice *rkaddr; |
0801d37f BJ |
215 | |
216 | if (ui == 0) | |
cc7ff771 | 217 | return; |
0801d37f BJ |
218 | dk_busy &= ~(1<<ui->ui_dk); |
219 | dp = &rkutab[ui->ui_unit]; | |
0801d37f | 220 | um = ui->ui_mi; |
28de6ed0 | 221 | rkaddr = (struct rkdevice *)um->um_addr; |
0801d37f BJ |
222 | if (um->um_tab.b_active) { |
223 | rk_softc[um->um_ctlr].sc_softas |= 1<<ui->ui_slave; | |
cc7ff771 | 224 | return; |
0801d37f | 225 | } |
cc7ff771 BJ |
226 | if ((bp = dp->b_actf) == NULL) |
227 | return; | |
b4208137 | 228 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_CERR; |
0801d37f | 229 | rkaddr->rkcs2 = ui->ui_slave; |
b4208137 | 230 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; |
0801d37f | 231 | rkwait(rkaddr); |
b4208137 | 232 | if ((rkaddr->rkds & RKDS_VV) == 0 || ui->ui_flags == 0) { |
0801d37f | 233 | /* SHOULD WARN SYSTEM THAT THIS HAPPENED */ |
616c2a83 | 234 | #ifndef NOBADSECT |
b4208137 BJ |
235 | struct rkst *st = &rkst[ui->ui_type]; |
236 | struct buf *bbp = &brkbuf[ui->ui_unit]; | |
237 | #endif | |
238 | ||
239 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_PACK|RK_GO; | |
240 | ui->ui_flags = 1; | |
616c2a83 | 241 | #ifndef NOBADSECT |
b4208137 BJ |
242 | bbp->b_flags = B_READ|B_BUSY; |
243 | bbp->b_dev = bp->b_dev; | |
244 | bbp->b_bcount = 512; | |
245 | bbp->b_un.b_addr = (caddr_t)&rkbad[ui->ui_unit]; | |
246 | bbp->b_blkno = st->ncyl*st->nspc - st->nsect; | |
247 | bbp->b_cylin = st->ncyl - 1; | |
248 | dp->b_actf = bbp; | |
249 | bbp->av_forw = bp; | |
250 | bp = bbp; | |
251 | #endif | |
0801d37f | 252 | rkwait(rkaddr); |
0801d37f | 253 | } |
736f0c13 BJ |
254 | if (dp->b_active) |
255 | goto done; | |
256 | dp->b_active = 1; | |
535f6684 | 257 | if ((rkaddr->rkds & RKDS_DREADY) != RKDS_DREADY) |
28de6ed0 | 258 | goto done; |
0801d37f BJ |
259 | if (rk_softc[um->um_ctlr].sc_ndrive == 1) |
260 | goto done; | |
261 | if (bp->b_cylin == rkcyl[ui->ui_unit]) | |
262 | goto done; | |
263 | rkaddr->rkcyl = bp->b_cylin; | |
264 | rkcyl[ui->ui_unit] = bp->b_cylin; | |
b4208137 | 265 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; |
0801d37f BJ |
266 | if (ui->ui_dk >= 0) { |
267 | dk_busy |= 1<<ui->ui_dk; | |
268 | dk_seek[ui->ui_dk]++; | |
269 | } | |
270 | goto out; | |
271 | done: | |
272 | if (dp->b_active != 2) { | |
273 | dp->b_forw = NULL; | |
274 | if (um->um_tab.b_actf == NULL) | |
275 | um->um_tab.b_actf = dp; | |
276 | else | |
277 | um->um_tab.b_actl->b_forw = dp; | |
278 | um->um_tab.b_actl = dp; | |
279 | dp->b_active = 2; | |
280 | } | |
281 | out: | |
cc7ff771 | 282 | return; |
0801d37f | 283 | } |
d483c58c | 284 | |
0801d37f | 285 | rkstart(um) |
89bd2f01 | 286 | register struct uba_ctlr *um; |
d483c58c | 287 | { |
0801d37f | 288 | register struct buf *bp, *dp; |
89bd2f01 | 289 | register struct uba_device *ui; |
0801d37f BJ |
290 | register struct rkdevice *rkaddr; |
291 | struct rkst *st; | |
d483c58c | 292 | daddr_t bn; |
0801d37f BJ |
293 | int sn, tn, cmd; |
294 | ||
295 | loop: | |
296 | if ((dp = um->um_tab.b_actf) == NULL) | |
cc7ff771 | 297 | return; |
0801d37f BJ |
298 | if ((bp = dp->b_actf) == NULL) { |
299 | um->um_tab.b_actf = dp->b_forw; | |
300 | goto loop; | |
d483c58c | 301 | } |
0801d37f BJ |
302 | um->um_tab.b_active++; |
303 | ui = rkdinfo[dkunit(bp)]; | |
304 | bn = dkblock(bp); | |
305 | st = &rkst[ui->ui_type]; | |
306 | sn = bn%st->nspc; | |
307 | tn = sn/st->nsect; | |
308 | sn %= st->nsect; | |
309 | rkaddr = (struct rkdevice *)ui->ui_addr; | |
29a0409f | 310 | retry: |
b4208137 | 311 | rkaddr->rkcs1 = RK_CCLR; |
0801d37f | 312 | rkaddr->rkcs2 = ui->ui_slave; |
b4208137 | 313 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; |
0801d37f | 314 | rkwait(rkaddr); |
535f6684 | 315 | if ((rkaddr->rkds&RKDS_SVAL) == 0) { |
29a0409f BJ |
316 | rknosval++; |
317 | goto nosval; | |
318 | } | |
535f6684 | 319 | if (rkaddr->rkds&RKDS_PIP) { |
29a0409f BJ |
320 | rkpip++; |
321 | goto retry; | |
28de6ed0 | 322 | } |
535f6684 | 323 | if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { |
68347e63 | 324 | printf("rk%d: not ready", dkunit(bp)); |
535f6684 | 325 | if ((rkaddr->rkds&RKDS_DREADY) != RKDS_DREADY) { |
28de6ed0 | 326 | printf("\n"); |
b4208137 | 327 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; |
28de6ed0 | 328 | rkwait(rkaddr); |
b4208137 | 329 | rkaddr->rkcs1 = RK_CCLR; |
28de6ed0 BJ |
330 | rkwait(rkaddr); |
331 | um->um_tab.b_active = 0; | |
332 | um->um_tab.b_errcnt = 0; | |
333 | dp->b_actf = bp->av_forw; | |
334 | dp->b_active = 0; | |
335 | bp->b_flags |= B_ERROR; | |
336 | iodone(bp); | |
337 | goto loop; | |
338 | } | |
339 | printf(" (came back!)\n"); | |
340 | } | |
29a0409f | 341 | nosval: |
0801d37f BJ |
342 | rkaddr->rkcyl = bp->b_cylin; |
343 | rkcyl[ui->ui_unit] = bp->b_cylin; | |
344 | rkaddr->rkda = (tn << 8) + sn; | |
345 | rkaddr->rkwc = -bp->b_bcount / sizeof (short); | |
346 | if (bp->b_flags & B_READ) | |
b4208137 | 347 | cmd = rktypes[ui->ui_type]|RK_IE|RK_READ|RK_GO; |
0801d37f | 348 | else |
b4208137 | 349 | cmd = rktypes[ui->ui_type]|RK_IE|RK_WRITE|RK_GO; |
0801d37f | 350 | um->um_cmd = cmd; |
a0eab615 | 351 | (void) ubago(ui); |
d483c58c BJ |
352 | } |
353 | ||
0801d37f | 354 | rkdgo(um) |
89bd2f01 | 355 | register struct uba_ctlr *um; |
d483c58c | 356 | { |
0801d37f BJ |
357 | register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; |
358 | ||
cc7ff771 | 359 | um->um_tab.b_active++; /* should now be 2 */ |
0801d37f BJ |
360 | rkaddr->rkba = um->um_ubinfo; |
361 | rkaddr->rkcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300); | |
362 | } | |
363 | ||
443c8066 | 364 | rkintr(rk11) |
0801d37f BJ |
365 | int rk11; |
366 | { | |
89bd2f01 BJ |
367 | register struct uba_ctlr *um = rkminfo[rk11]; |
368 | register struct uba_device *ui; | |
0801d37f BJ |
369 | register struct rkdevice *rkaddr = (struct rkdevice *)um->um_addr; |
370 | register struct buf *bp, *dp; | |
371 | int unit; | |
372 | struct rk_softc *sc = &rk_softc[um->um_ctlr]; | |
373 | int as = (rkaddr->rkatt >> 8) | sc->sc_softas; | |
374 | int needie = 1; | |
375 | ||
376 | sc->sc_wticks = 0; | |
377 | sc->sc_softas = 0; | |
cc7ff771 | 378 | if (um->um_tab.b_active == 2 || sc->sc_recal) { |
0801d37f BJ |
379 | dp = um->um_tab.b_actf; |
380 | bp = dp->b_actf; | |
381 | ui = rkdinfo[dkunit(bp)]; | |
382 | dk_busy &= ~(1 << ui->ui_dk); | |
616c2a83 | 383 | #ifndef NOBADSECT |
b4208137 BJ |
384 | if (bp->b_flags&B_BAD) |
385 | if (rkecc(ui, CONT)) | |
386 | return; | |
387 | #endif | |
0801d37f BJ |
388 | if (rkaddr->rkcs1 & RK_CERR) { |
389 | int recal; | |
390 | u_short ds = rkaddr->rkds; | |
391 | u_short cs2 = rkaddr->rkcs2; | |
392 | u_short er = rkaddr->rker; | |
b4208137 | 393 | #ifdef RKDEBUG |
535f6684 BJ |
394 | if (rkdebug) { |
395 | printf("cs2=%b ds=%b er=%b\n", | |
396 | cs2, RKCS2_BITS, ds, | |
397 | RKDS_BITS, er, RKER_BITS); | |
398 | } | |
b4208137 | 399 | #endif |
535f6684 | 400 | if (er & RKER_WLE) { |
68347e63 | 401 | printf("rk%d: write locked\n", dkunit(bp)); |
ed687006 BJ |
402 | bp->b_flags |= B_ERROR; |
403 | } else if (++um->um_tab.b_errcnt > 28 || | |
736772ef | 404 | ds&RKDS_HARD || er&RKER_HARD || cs2&RKCS2_HARD) { |
b4208137 | 405 | hard: |
68347e63 BJ |
406 | harderr(bp, "rk"); |
407 | printf("cs2=%b ds=%b er=%b\n", | |
28de6ed0 | 408 | cs2, RKCS2_BITS, ds, |
736772ef | 409 | RKDS_BITS, er, RKER_BITS); |
a306546d BJ |
410 | bp->b_flags |= B_ERROR; |
411 | sc->sc_recal = 0; | |
b4208137 | 412 | } else if (er & RKER_BSE) { |
616c2a83 | 413 | #ifndef NOBADSECT |
b4208137 BJ |
414 | if (rkecc(ui, BSE)) |
415 | return; | |
416 | else | |
417 | #endif | |
418 | goto hard; | |
736772ef | 419 | } else |
0801d37f | 420 | um->um_tab.b_active = 0; |
535f6684 BJ |
421 | if (cs2&RKCS2_MDS) { |
422 | rkaddr->rkcs2 = RKCS2_SCLR; | |
0801d37f BJ |
423 | goto retry; |
424 | } | |
425 | recal = 0; | |
535f6684 | 426 | if (ds&RKDS_DROT || er&(RKER_OPI|RKER_SKI|RKER_UNS) || |
0801d37f BJ |
427 | (um->um_tab.b_errcnt&07) == 4) |
428 | recal = 1; | |
535f6684 | 429 | if ((er & (RKER_DCK|RKER_ECH)) == RKER_DCK) |
b4208137 | 430 | if (rkecc(ui, ECC)) |
0801d37f | 431 | return; |
b4208137 | 432 | rkaddr->rkcs1 = RK_CCLR; |
0801d37f | 433 | rkaddr->rkcs2 = ui->ui_slave; |
b4208137 | 434 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; |
0801d37f BJ |
435 | rkwait(rkaddr); |
436 | if (recal && um->um_tab.b_active == 0) { | |
b4208137 | 437 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_RECAL|RK_GO; |
0801d37f | 438 | rkcyl[ui->ui_unit] = -1; |
29a0409f BJ |
439 | sc->sc_recal = 0; |
440 | goto nextrecal; | |
d483c58c | 441 | } |
d483c58c | 442 | } |
0801d37f | 443 | retry: |
29a0409f BJ |
444 | switch (sc->sc_recal) { |
445 | ||
446 | case 1: | |
447 | rkaddr->rkcyl = bp->b_cylin; | |
448 | rkcyl[ui->ui_unit] = bp->b_cylin; | |
b4208137 | 449 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_SEEK|RK_GO; |
29a0409f | 450 | goto nextrecal; |
29a0409f BJ |
451 | case 2: |
452 | if (um->um_tab.b_errcnt < 16 || | |
6ac24ecd | 453 | (bp->b_flags&B_READ) == 0) |
a6442a2f | 454 | goto donerecal; |
29a0409f | 455 | rkaddr->rkatt = rk_offset[um->um_tab.b_errcnt & 017]; |
b4208137 | 456 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_OFFSET|RK_GO; |
29a0409f BJ |
457 | /* fall into ... */ |
458 | nextrecal: | |
459 | sc->sc_recal++; | |
460 | rkwait(rkaddr); | |
461 | um->um_tab.b_active = 1; | |
462 | return; | |
a6442a2f | 463 | donerecal: |
29a0409f | 464 | case 3: |
0801d37f BJ |
465 | sc->sc_recal = 0; |
466 | um->um_tab.b_active = 0; | |
29a0409f | 467 | break; |
d483c58c | 468 | } |
b4208137 | 469 | ubadone(um); |
0801d37f BJ |
470 | if (um->um_tab.b_active) { |
471 | um->um_tab.b_active = 0; | |
472 | um->um_tab.b_errcnt = 0; | |
473 | um->um_tab.b_actf = dp->b_forw; | |
474 | dp->b_active = 0; | |
475 | dp->b_errcnt = 0; | |
476 | dp->b_actf = bp->av_forw; | |
477 | bp->b_resid = -rkaddr->rkwc * sizeof(short); | |
478 | iodone(bp); | |
479 | if (dp->b_actf) | |
cc7ff771 | 480 | rkustart(ui); |
d483c58c | 481 | } |
0801d37f | 482 | as &= ~(1<<ui->ui_slave); |
d483c58c | 483 | } |
0801d37f | 484 | for (unit = 0; as; as >>= 1, unit++) |
89bd2f01 BJ |
485 | if (as & 1) { |
486 | ui = rkip[rk11][unit]; | |
487 | if (ui) { | |
cc7ff771 | 488 | rkustart(rkip[rk11][unit]); |
89bd2f01 | 489 | } else { |
b4208137 | 490 | rkaddr->rkcs1 = RK_CCLR; |
89bd2f01 | 491 | rkaddr->rkcs2 = unit; |
b4208137 | 492 | rkaddr->rkcs1 = RK_DCLR|RK_GO; |
89bd2f01 | 493 | rkwait(rkaddr); |
b4208137 | 494 | rkaddr->rkcs1 = RK_CCLR; |
89bd2f01 BJ |
495 | } |
496 | } | |
0801d37f | 497 | if (um->um_tab.b_actf && um->um_tab.b_active == 0) |
cc7ff771 BJ |
498 | rkstart(um); |
499 | if (((needie = rkaddr->rkcs1) & RK_IE) == 0) | |
b4208137 | 500 | rkaddr->rkcs1 = RK_IE; |
d483c58c BJ |
501 | } |
502 | ||
0801d37f BJ |
503 | rkwait(addr) |
504 | register struct rkdevice *addr; | |
505 | { | |
506 | ||
507 | while ((addr->rkcs1 & RK_CRDY) == 0) | |
508 | ; | |
509 | } | |
d483c58c | 510 | |
0801d37f BJ |
511 | rkread(dev) |
512 | dev_t dev; | |
d483c58c | 513 | { |
0801d37f BJ |
514 | register int unit = minor(dev) >> 3; |
515 | ||
872b4e09 | 516 | if (unit >= NRK) |
0801d37f BJ |
517 | u.u_error = ENXIO; |
518 | else | |
519 | physio(rkstrategy, &rrkbuf[unit], dev, B_READ, minphys); | |
d483c58c BJ |
520 | } |
521 | ||
0801d37f BJ |
522 | rkwrite(dev) |
523 | dev_t dev; | |
d483c58c | 524 | { |
0801d37f | 525 | register int unit = minor(dev) >> 3; |
d483c58c | 526 | |
872b4e09 | 527 | if (unit >= NRK) |
0801d37f BJ |
528 | u.u_error = ENXIO; |
529 | else | |
530 | physio(rkstrategy, &rrkbuf[unit], dev, B_WRITE, minphys); | |
d483c58c BJ |
531 | } |
532 | ||
b4208137 | 533 | rkecc(ui, flag) |
89bd2f01 | 534 | register struct uba_device *ui; |
d483c58c | 535 | { |
0801d37f BJ |
536 | register struct rkdevice *rk = (struct rkdevice *)ui->ui_addr; |
537 | register struct buf *bp = rkutab[ui->ui_unit].b_actf; | |
89bd2f01 | 538 | register struct uba_ctlr *um = ui->ui_mi; |
0801d37f BJ |
539 | register struct rkst *st; |
540 | struct uba_regs *ubp = ui->ui_hd->uh_uba; | |
0801d37f | 541 | caddr_t addr; |
b4208137 | 542 | int reg, npf, o, cmd, ubaddr; |
0801d37f | 543 | int bn, cn, tn, sn; |
d483c58c | 544 | |
616c2a83 | 545 | #ifndef NOBADSECT |
b4208137 BJ |
546 | if (flag == CONT) |
547 | npf = bp->b_error; | |
548 | else | |
549 | #endif | |
550 | npf = btop((rk->rkwc * sizeof(short)) + bp->b_bcount); | |
0801d37f BJ |
551 | reg = btop(um->um_ubinfo&0x3ffff) + npf; |
552 | o = (int)bp->b_un.b_addr & PGOFSET; | |
0801d37f BJ |
553 | bn = dkblock(bp); |
554 | st = &rkst[ui->ui_type]; | |
555 | cn = bp->b_cylin; | |
b4208137 | 556 | sn = bn%st->nspc + npf; |
0801d37f BJ |
557 | tn = sn/st->nsect; |
558 | sn %= st->nsect; | |
559 | cn += tn/st->ntrak; | |
560 | tn %= st->ntrak; | |
b4208137 | 561 | ubapurge(um); |
cc7ff771 | 562 | um->um_tab.b_active = 2; /* Either complete or continuing... */ |
b4208137 BJ |
563 | switch (flag) { |
564 | case ECC: | |
565 | { | |
566 | register int i; | |
567 | int bit, byte, mask; | |
568 | ||
569 | npf--; | |
570 | reg--; | |
571 | printf("rk%d%c: soft ecc sn%d\n", dkunit(bp), | |
572 | 'a'+(minor(bp->b_dev)&07), bp->b_blkno + npf); | |
573 | mask = rk->rkec2; | |
574 | i = rk->rkec1 - 1; /* -1 makes 0 origin */ | |
575 | bit = i&07; | |
576 | i = (i&~07)>>3; | |
577 | byte = i + o; | |
578 | while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) { | |
579 | addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+ | |
580 | (byte & PGOFSET); | |
581 | putmemc(addr, getmemc(addr)^(mask<<bit)); | |
582 | byte++; | |
583 | i++; | |
584 | bit -= 8; | |
585 | } | |
586 | if (rk->rkwc == 0) | |
587 | return (0); | |
588 | npf++; | |
589 | reg++; | |
590 | break; | |
591 | } | |
592 | ||
616c2a83 | 593 | #ifndef NOBADSECT |
b4208137 BJ |
594 | case BSE: |
595 | #ifdef RKBDEBUG | |
596 | if (rkbdebug) | |
597 | printf("rkecc, BSE: bn %d cn %d tn %d sn %d\n", bn, cn, tn, sn); | |
598 | #endif | |
599 | if ((bn = isbad(&rkbad[ui->ui_unit], cn, tn, sn)) < 0) | |
600 | return(0); | |
601 | bp->b_flags |= B_BAD; | |
602 | bp->b_error = npf + 1; | |
603 | bn = st->ncyl*st->nspc - st->nsect - 1 - bn; | |
604 | cn = bn/st->nspc; | |
605 | sn = bn%st->nspc; | |
606 | tn = sn/st->nsect; | |
607 | sn %= st->nsect; | |
608 | #ifdef RKBDEBUG | |
609 | if (rkbdebug) | |
610 | printf("revector to cn %d tn %d sn %d\n", cn, tn, sn); | |
611 | #endif | |
612 | rk->rkwc = -(512 / sizeof (short)); | |
613 | break; | |
614 | ||
615 | case CONT: | |
616 | #ifdef RKBDEBUG | |
617 | if (rkbdebug) | |
618 | printf("rkecc, CONT: bn %d cn %d tn %d sn %d\n", bn,cn,tn,sn); | |
619 | #endif | |
620 | bp->b_flags &= ~B_BAD; | |
621 | rk->rkwc = -((bp->b_bcount - (int)ptob(npf)) / sizeof (short)); | |
622 | if (rk->rkwc == 0) | |
623 | return(0); | |
624 | break; | |
625 | #endif | |
626 | } | |
627 | rk->rkcs1 = RK_CCLR; | |
628 | rk->rkcs2 = ui->ui_slave; | |
629 | rk->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; | |
630 | rkwait(rk); | |
0801d37f BJ |
631 | rk->rkcyl = cn; |
632 | rk->rkda = (tn << 8) | sn; | |
b4208137 | 633 | ubaddr = (int)ptob(reg) + o; |
0801d37f | 634 | rk->rkba = ubaddr; |
b4208137 BJ |
635 | cmd = (bp->b_flags&B_READ ? RK_READ : RK_WRITE)|RK_IE|RK_GO; |
636 | cmd |= (ubaddr >> 8) & 0x300; | |
637 | cmd |= rktypes[ui->ui_type]; | |
0801d37f | 638 | rk->rkcs1 = cmd; |
b4208137 | 639 | um->um_tab.b_errcnt = 0; /* error has been corrected */ |
0801d37f | 640 | return (1); |
d483c58c BJ |
641 | } |
642 | ||
0801d37f | 643 | rkreset(uban) |
68347e63 | 644 | int uban; |
0801d37f | 645 | { |
89bd2f01 BJ |
646 | register struct uba_ctlr *um; |
647 | register struct uba_device *ui; | |
0801d37f | 648 | register rk11, unit; |
0801d37f | 649 | |
872b4e09 | 650 | for (rk11 = 0; rk11 < NHK; rk11++) { |
0801d37f BJ |
651 | if ((um = rkminfo[rk11]) == 0 || um->um_ubanum != uban || |
652 | um->um_alive == 0) | |
653 | continue; | |
68347e63 | 654 | printf(" hk%d", rk11); |
0801d37f BJ |
655 | um->um_tab.b_active = 0; |
656 | um->um_tab.b_actf = um->um_tab.b_actl = 0; | |
657 | rk_softc[um->um_ctlr].sc_recal = 0; | |
cc7ff771 | 658 | rk_softc[um->um_ctlr].sc_wticks = 0; |
0801d37f BJ |
659 | if (um->um_ubinfo) { |
660 | printf("<%d>", (um->um_ubinfo>>28)&0xf); | |
661 | ubadone(um); | |
662 | } | |
e1c5f66d | 663 | for (unit = 0; unit < NRK; unit++) { |
0801d37f BJ |
664 | if ((ui = rkdinfo[unit]) == 0) |
665 | continue; | |
e1c5f66d | 666 | if (ui->ui_alive == 0 || ui->ui_mi != um) |
0801d37f BJ |
667 | continue; |
668 | rkutab[unit].b_active = 0; | |
669 | (void) rkustart(ui); | |
670 | } | |
671 | (void) rkstart(um); | |
672 | } | |
673 | } | |
674 | ||
0801d37f | 675 | rkwatch() |
d483c58c | 676 | { |
89bd2f01 | 677 | register struct uba_ctlr *um; |
0801d37f BJ |
678 | register rk11, unit; |
679 | register struct rk_softc *sc; | |
d483c58c | 680 | |
7780575a | 681 | timeout(rkwatch, (caddr_t)0, hz); |
872b4e09 | 682 | for (rk11 = 0; rk11 < NHK; rk11++) { |
0801d37f BJ |
683 | um = rkminfo[rk11]; |
684 | if (um == 0 || um->um_alive == 0) | |
685 | continue; | |
686 | sc = &rk_softc[rk11]; | |
687 | if (um->um_tab.b_active == 0) { | |
872b4e09 | 688 | for (unit = 0; unit < NRK; unit++) |
9037157b BJ |
689 | if (rkutab[unit].b_active && |
690 | rkdinfo[unit]->ui_mi == um) | |
0801d37f BJ |
691 | goto active; |
692 | sc->sc_wticks = 0; | |
693 | continue; | |
694 | } | |
695 | active: | |
696 | sc->sc_wticks++; | |
697 | if (sc->sc_wticks >= 20) { | |
698 | sc->sc_wticks = 0; | |
68347e63 | 699 | printf("hk%d: lost interrupt\n", rk11); |
872b4e09 | 700 | ubareset(um->um_ubanum); |
0801d37f BJ |
701 | } |
702 | } | |
d483c58c | 703 | } |
0ff318b2 | 704 | |
0801d37f BJ |
705 | #define DBSIZE 20 |
706 | ||
707 | rkdump(dev) | |
708 | dev_t dev; | |
0ff318b2 | 709 | { |
0801d37f BJ |
710 | struct rkdevice *rkaddr; |
711 | char *start; | |
712 | int num, blk, unit; | |
713 | struct size *sizes; | |
714 | register struct uba_regs *uba; | |
89bd2f01 | 715 | register struct uba_device *ui; |
0801d37f BJ |
716 | register short *rp; |
717 | struct rkst *st; | |
718 | ||
719 | unit = minor(dev) >> 3; | |
c9e9b65b BJ |
720 | if (unit >= NRK) |
721 | return (ENXIO); | |
0801d37f | 722 | #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) |
89bd2f01 | 723 | ui = phys(struct uba_device *, rkdinfo[unit]); |
c9e9b65b BJ |
724 | if (ui->ui_alive == 0) |
725 | return (ENXIO); | |
0801d37f | 726 | uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; |
a53e803c | 727 | ubainit(uba); |
0801d37f BJ |
728 | rkaddr = (struct rkdevice *)ui->ui_physaddr; |
729 | num = maxfree; | |
730 | start = 0; | |
b4208137 | 731 | rkaddr->rkcs1 = RK_CCLR; |
0801d37f | 732 | rkaddr->rkcs2 = unit; |
b4208137 | 733 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_DCLR|RK_GO; |
0801d37f | 734 | rkwait(rkaddr); |
535f6684 | 735 | if ((rkaddr->rkds & RKDS_VV) == 0) { |
b4208137 | 736 | rkaddr->rkcs1 = rktypes[ui->ui_type]|RK_IE|RK_PACK|RK_GO; |
0801d37f BJ |
737 | rkwait(rkaddr); |
738 | } | |
739 | st = &rkst[ui->ui_type]; | |
740 | sizes = phys(struct size *, st->sizes); | |
c9e9b65b BJ |
741 | if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks) |
742 | return (EINVAL); | |
0801d37f BJ |
743 | while (num > 0) { |
744 | register struct pte *io; | |
745 | register int i; | |
746 | int cn, sn, tn; | |
747 | daddr_t bn; | |
0ff318b2 | 748 | |
0801d37f BJ |
749 | blk = num > DBSIZE ? DBSIZE : num; |
750 | io = uba->uba_map; | |
751 | for (i = 0; i < blk; i++) | |
89bd2f01 | 752 | *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV; |
0801d37f BJ |
753 | *(int *)io = 0; |
754 | bn = dumplo + btop(start); | |
755 | cn = bn/st->nspc + sizes[minor(dev)&07].cyloff; | |
756 | sn = bn%st->nspc; | |
757 | tn = sn/st->nsect; | |
758 | sn = sn%st->nsect; | |
759 | rkaddr->rkcyl = cn; | |
760 | rp = (short *) &rkaddr->rkda; | |
761 | *rp = (tn << 8) + sn; | |
762 | *--rp = 0; | |
763 | *--rp = -blk*NBPG / sizeof (short); | |
b4208137 | 764 | *--rp = rktypes[ui->ui_type]|RK_GO|RK_WRITE; |
0801d37f | 765 | rkwait(rkaddr); |
c9e9b65b BJ |
766 | if (rkaddr->rkcs1 & RK_CERR) |
767 | return (EIO); | |
0801d37f BJ |
768 | start += blk*NBPG; |
769 | num -= blk; | |
770 | } | |
771 | return (0); | |
0ff318b2 | 772 | } |
d483c58c | 773 | #endif |