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