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