raise enlastdel to 50
[unix-history] / usr / src / sys / vax / uba / idc.c
CommitLineData
6c163e27
SL
1/* idc.c 4.1 82/05/26 */
2
3#include "rb.h"
4#if NIDC > 0
5int idcdebug = 0;
6#define printd if(idcdebug)printf
7int idctrb[1000];
8int *trp = idctrb;
9#define trace(a,b) {*trp++ = (int)a; *trp++ = (int)b; if(trp>&idctrb[998])trp=idctrb;}
10/*
11 * IDC (RB730) disk driver
12 *
13 * There can only ever be one IDC on a machine,
14 * and only on a VAX-11/730. We take advantage
15 * of that to simplify the driver.
16 *
17 * TODO:
18 * dk_busy
19 * ecc
20 * dump
21 */
22#include "../h/param.h"
23#include "../h/systm.h"
24#include "../h/buf.h"
25#include "../h/conf.h"
26#include "../h/dir.h"
27#include "../h/user.h"
28#include "../h/pte.h"
29#include "../h/map.h"
30#include "../h/vm.h"
31#include "../h/ubareg.h"
32#include "../h/ubavar.h"
33#include "../h/dk.h"
34#include "../h/cpu.h"
35#include "../h/cmap.h"
36#include "../h/dkbad.h"
37
38#include "../h/idcreg.h"
39
40struct idc_softc {
41 int sc_bcnt; /* number of bytes to transfer */
42 int sc_resid; /* total number of bytes to transfer */
43 int sc_ubaddr; /* Unibus address of data */
44 short sc_unit; /* unit doing transfer */
45 short sc_softas; /* software attention summary bits */
46 union idc_dar {
47 long dar_l;
48 u_short dar_w[2];
49 u_char dar_b[4];
50 } sc_un; /* prototype disk address register */
51} idc_softc;
52
53#define dar_dar dar_l /* the whole disk address */
54#define dar_cyl dar_w[1] /* cylinder address */
55#define dar_trk dar_b[1] /* track */
56#define dar_sect dar_b[0] /* sector */
57#define sc_dar sc_un.dar_dar
58#define sc_cyl sc_un.dar_cyl
59#define sc_trk sc_un.dar_trk
60#define sc_sect sc_un.dar_sect
61
62/* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
63struct size {
64 daddr_t nblocks;
65 int cyloff;
66} rb02_sizes[8] ={
67 15884, 0, /* A=cyl 0 thru 399 */
68 4480, 400, /* B=cyl 400 thru 510 */
69 20480, 0, /* C=cyl 0 thru 511 */
70 0, 0,
71 0, 0,
72 0, 0,
73 0, 0,
74 0, 0,
75}, rb80_sizes[8] ={
76 15884, 0, /* A=cyl 0 thru 36 */
77 33440, 37, /* B=cyl 37 thru 114 */
78 242606, 0, /* C=cyl 0 thru 558 */
79 0, 0,
80 0, 0,
81 0, 0,
82 82080, 115, /* G=cyl 115 thru 304 */
83 110143, 305, /* H=cyl 305 thru 558 */
84};
85/* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
86
87int idcprobe(), idcslave(), idcattach(), idcdgo(), idcintr();
88struct uba_ctlr *idcminfo[NIDC];
89struct uba_device *idcdinfo[NRB];
90
91u_short idcstd[] = { 0174400, 0};
92struct uba_driver idcdriver =
93 { idcprobe, idcslave, idcattach, idcdgo, idcstd, "rb", idcdinfo, "idc", idcminfo, 0 };
94struct buf idcutab[NRB];
95union idc_dar idccyl[NRB];
96
97struct idcst {
98 short nbps;
99 short nsect;
100 short ntrak;
101 short nspc;
102 short ncyl;
103 struct size *sizes;
104} idcst[] = {
105 256, NRB02SECT, NRB02TRK, NRB02SECT*NRB02TRK, NRB02CYL, rb02_sizes,
106 512, NRB80SECT, NRB80TRK, NRB80SECT*NRB80TRK, NRB80CYL, rb80_sizes,
107};
108
109struct buf ridcbuf[NRB];
110
111#define b_cylin b_resid
112
113#ifdef INTRLVE
114daddr_t dkblock();
115#endif
116
117int idcwstart, idcwticks, idcwatch();
118
119idcprobe(reg)
120 caddr_t reg;
121{
122 register int br, cvec;
123 register struct idcdevice *idcaddr;
124
125#ifdef lint
126 br = 0; cvec = br; br = cvec;
127#endif
128 idcaddr = (struct idcdevice *)((caddr_t)uba_hd[0].uh_uba + 0x200);
129 idcaddr->idccsr = IDC_ATTN|IDC_IE;
130 while ((idcaddr->idccsr & IDC_CRDY) == 0)
131 ;
132 idcaddr->idccsr = IDC_ATTN|IDC_CRDY;
133 return (1);
134}
135
136idcslave(ui, reg)
137 struct uba_device *ui;
138 caddr_t reg;
139{
140 register struct idcdevice *idcaddr;
141 register int i;
142
143 idcaddr = (struct idcdevice *)((caddr_t)uba_hd[0].uh_uba + 0x200);
144 ui->ui_type = 0;
145 idcaddr->idcmpr = IDCGS_GETSTAT;
146 idcaddr->idccsr = IDC_GETSTAT|(ui->ui_slave<<8);
147 idcwait(idcaddr, 0);
148 i = idcaddr->idcmpr;
149 idcaddr->idccsr = IDC_CRDY|(1<<(ui->ui_slave+16));
150 /* read header to synchronize microcode */
151 idcwait(idcaddr, 0);
152 idcaddr->idccsr = (ui->ui_slave<<8)|IDC_RHDR;
153 idcwait(idcaddr, 0);
154 if (idcaddr->idccsr & IDC_ERR)
155 return (0);
156 i = idcaddr->idcmpr; /* read header word 1 */
157 i = idcaddr->idcmpr; /* read header word 2 */
158 if (idcaddr->idccsr&IDC_R80)
159 ui->ui_type = 1;
160 return (1);
161}
162
163idcattach(ui)
164 register struct uba_device *ui;
165{
166
167 /*
168 * Fix all addresses to correspond
169 * to the "real" IDC address.
170 */
171 ui->ui_mi->um_addr = ui->ui_addr = (caddr_t)uba_hd[0].uh_uba + 0x200;
172 ui->ui_physaddr = (caddr_t)uba_hd[0].uh_physuba + 0x200;
173 if (idcwstart == 0) {
174 timeout(idcwatch, (caddr_t)0, hz);
175 idcwstart++;
176 }
177 if (ui->ui_dk >= 0)
178 if (ui->ui_type)
179 dk_mspw[ui->ui_dk] = 1.0 / (60 * NRB80SECT * 256);
180 else
181 dk_mspw[ui->ui_dk] = 1.0 / (60 * NRB02SECT * 128);
182 idccyl[ui->ui_unit].dar_dar = -1;
183 ui->ui_flags = 0;
184}
185
186idcstrategy(bp)
187 register struct buf *bp;
188{
189 register struct uba_device *ui;
190 register struct idcst *st;
191 register int unit;
192 register struct buf *dp;
193 int xunit = minor(bp->b_dev) & 07;
194 long bn, sz;
195
196 sz = (bp->b_bcount+511) >> 9;
197 unit = dkunit(bp);
198 if (unit >= NRB)
199 goto bad;
200 ui = idcdinfo[unit];
201 if (ui == 0 || ui->ui_alive == 0)
202 goto bad;
203 st = &idcst[ui->ui_type];
204 if (bp->b_blkno < 0 ||
205 (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
206 goto bad;
207 if (ui->ui_type == 0)
208 bn *= 2;
209 bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
210 (void) spl5();
211 trace('strt',bp);
212 dp = &idcutab[ui->ui_unit];
213 disksort(dp, bp);
214 if (dp->b_active == 0) {
215 trace('!act',dp);
216 (void) idcustart(ui);
217 bp = &ui->ui_mi->um_tab;
218 if (bp->b_actf && bp->b_active == 0)
219 (void) idcstart(ui->ui_mi);
220 }
221 (void) spl0();
222 return;
223
224bad:
225 bp->b_flags |= B_ERROR;
226 iodone(bp);
227 return;
228}
229
230idcustart(ui)
231 register struct uba_device *ui;
232{
233 register struct buf *bp, *dp;
234 register struct uba_ctlr *um;
235 register struct idcdevice *idcaddr;
236 register struct idcst *st;
237 union idc_dar cyltrk;
238 daddr_t bn;
239 int unit;
240
241 if (ui == 0)
242 return (0);
243 dk_busy &= ~(1<<ui->ui_dk);
244 dp = &idcutab[ui->ui_unit];
245 um = ui->ui_mi;
246 unit = ui->ui_slave;
247 trace('ust', dp);
248 idcaddr = (struct idcdevice *)um->um_addr;
249 if (um->um_tab.b_active) {
250 idc_softc.sc_softas |= 1<<unit;
251 trace('umac',idc_softc.sc_softas);
252 return (0);
253 }
254 if ((bp = dp->b_actf) == NULL) {
255 trace('!bp',0);
256 return (0);
257 }
258 if (dp->b_active) {
259 trace('dpac',dp->b_active);
260 goto done;
261 }
262 dp->b_active = 1;
263 /* CHECK DRIVE READY? */
264 bn = dkblock(bp);
265 trace('seek', bn);
266 if (ui->ui_type == 0)
267 bn *= 2;
268 st = &idcst[ui->ui_type];
269 cyltrk.dar_cyl = bp->b_cylin;
270 cyltrk.dar_trk = (bn / st->nsect) % st->ntrak;
271 cyltrk.dar_sect = 0;
272 printd("idcustart, unit %d, cyltrk 0x%x\n", unit, cyltrk.dar_dar);
273 /*
274 * If on cylinder, no need to seek.
275 */
276 if (cyltrk.dar_dar == idccyl[ui->ui_unit].dar_dar)
277 goto done;
278 /*
279 * RB80 can change heads (tracks) just by loading
280 * the disk address register, perform optimization
281 * here instead of doing a full seek.
282 */
283 if (ui->ui_type && cyltrk.dar_cyl == idccyl[ui->ui_unit].dar_cyl) {
284 idcaddr->idccsr = IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8);
285 idcaddr->idcdar = cyltrk.dar_dar;
286 idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar;
287 goto done;
288 }
289 /*
290 * Need to do a full seek. Select the unit, clear
291 * its attention bit, set the command, load the
292 * disk address register, and then go.
293 */
294 idcaddr->idccsr =
295 IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16));
296 idcaddr->idcdar = cyltrk.dar_dar;
297 idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar;
298 printd(" seek");
299 idcaddr->idccsr = IDC_IE|IDC_SEEK|(unit<<8);
300 if (ui->ui_dk >= 0) {
301 dk_busy |= 1<<ui->ui_dk;
302 dk_seek[ui->ui_dk]++;
303 }
304 /*
305 * RB80's initiate seeks very quickly. Wait for it
306 * to come ready rather than taking the interrupt.
307 */
308 if (ui->ui_type) {
309 if (idcwait(idcaddr, 10) == 0)
310 return (1);
311 idcaddr->idccsr &= ~IDC_ATTN;
312 /* has the seek completed? */
313 if (idcaddr->idccsr & IDC_DRDY) {
314 printd(", drdy");
315 idcaddr->idccsr =
316 IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16));
317 goto done;
318 }
319 }
320 printd(", idccsr = 0x%x\n", idcaddr->idccsr);
321 return (1);
322done:
323 if (dp->b_active != 2) {
324 trace('!=2',dp->b_active);
325 dp->b_forw = NULL;
326 if (um->um_tab.b_actf == NULL)
327 um->um_tab.b_actf = dp;
328 else {
329 trace('!NUL',um->um_tab.b_actl);
330 um->um_tab.b_actl->b_forw = dp;
331 }
332 um->um_tab.b_actl = dp;
333 dp->b_active = 2;
334 }
335 return (0);
336}
337
338idcstart(um)
339 register struct uba_ctlr *um;
340{
341 register struct buf *bp, *dp;
342 register struct uba_device *ui;
343 register struct idcdevice *idcaddr;
344 register struct idc_softc *sc;
345 struct idcst *st;
346 daddr_t bn;
347 int sn, tn, cmd;
348
349loop:
350 if ((dp = um->um_tab.b_actf) == NULL) {
351 trace('nodp',um);
352 return (0);
353 }
354 if ((bp = dp->b_actf) == NULL) {
355 trace('nobp', dp);
356 um->um_tab.b_actf = dp->b_forw;
357 goto loop;
358 }
359 um->um_tab.b_active = 1;
360 ui = idcdinfo[dkunit(bp)];
361 bn = dkblock(bp);
362 trace('star',bp);
363 if (ui->ui_type == 0)
364 bn *= 2;
365 sc = &idc_softc;
366 st = &idcst[ui->ui_type];
367 sn = bn%st->nspc;
368 tn = sn/st->nsect;
369 sn %= st->nsect;
370 sc->sc_sect = sn;
371 sc->sc_trk = tn;
372 sc->sc_cyl = bp->b_cylin;
373 idcaddr = (struct idcdevice *)ui->ui_addr;
374 printd("idcstart, unit %d, dar 0x%x", ui->ui_slave, sc->sc_dar);
375 if (bp->b_flags & B_READ)
376 cmd = IDC_IE|IDC_READ|(ui->ui_slave<<8);
377 else
378 cmd = IDC_IE|IDC_WRITE|(ui->ui_slave<<8);
379 idcaddr->idccsr = IDC_CRDY|cmd;
380 if ((idcaddr->idccsr&IDC_DRDY) == 0) {
381 printf("rb%d: not ready\n", dkunit(bp));
382 um->um_tab.b_active = 0;
383 um->um_tab.b_errcnt = 0;
384 dp->b_actf = bp->av_forw;
385 dp->b_active = 0;
386 bp->b_flags |= B_ERROR;
387 iodone(bp);
388 goto loop;
389 }
390 idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
391 idccyl[ui->ui_unit].dar_sect = 0;
392 sn = (st->nsect - sn) * st->nbps;
393 if (sn > bp->b_bcount)
394 sn = bp->b_bcount;
395 sc->sc_bcnt = sn;
396 sc->sc_resid = bp->b_bcount;
397 sc->sc_unit = ui->ui_slave;
398 printd(", bcr 0x%x, cmd 0x%x\n", sn, cmd);
399 um->um_cmd = cmd;
400 (void) ubago(ui);
401 return (1);
402}
403
404idcdgo(um)
405 register struct uba_ctlr *um;
406{
407 register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr;
408 register struct idc_softc *sc = &idc_softc;
409
410 /*
411 * VERY IMPORTANT: must load registers in this order.
412 */
413 idcaddr->idcbar = sc->sc_ubaddr = um->um_ubinfo&0x3ffff;
414 idcaddr->idcbcr = -sc->sc_bcnt;
415 idcaddr->idcdar = sc->sc_dar;
416 printd("idcdgo, ubinfo 0x%x, cmd 0x%x\n", um->um_ubinfo, um->um_cmd);
417 idcaddr->idccsr = um->um_cmd;
418 trace('go', um);
419 um->um_tab.b_active = 2;
420 /*** CLEAR SPURIOUS ATTN ON R80? ***/
421}
422
423idcintr(idc)
424 int idc;
425{
426 register struct uba_ctlr *um = idcminfo[idc];
427 register struct uba_device *ui;
428 register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr;
429 register struct idc_softc *sc = &idc_softc;
430 register struct buf *bp, *dp;
431 struct idcst *st;
432 int unit, as, er, cmd, ds = 0;
433
434 printd("idcintr, idccsr 0x%x", idcaddr->idccsr);
435top:
436 idcwticks = 0;
437 trace('intr', um->um_tab.b_active);
438 if (um->um_tab.b_active == 2) {
439 /*
440 * Process a data transfer complete interrupt.
441 */
442 um->um_tab.b_active = 1;
443 dp = um->um_tab.b_actf;
444 bp = dp->b_actf;
445 ui = idcdinfo[dkunit(bp)];
446 unit = ui->ui_slave;
447 st = &idcst[ui->ui_type];
448 idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8);
449 if ((er = idcaddr->idccsr) & IDC_ERR) {
450 if (er & IDC_DE) {
451 idcaddr->idcmpr = IDCGS_GETSTAT;
452 idcaddr->idccsr = IDC_GETSTAT|(unit<<8);
453 idcwait(idcaddr, 0);
454 ds = idcaddr->idcmpr;
455 idcaddr->idccsr =
456 IDC_IE|IDC_CRDY|(1<<(unit+16));
457 }
458 printd(", er 0x%x, ds 0x%x", er, ds);
459 if (ds & IDCDS_WL) {
460 printf("rb%d: write locked\n", dkunit(bp));
461 bp->b_flags |= B_ERROR;
462 } else if (++um->um_tab.b_errcnt > 28 || er&IDC_HARD) {
463hard:
464 harderr(bp, "rb");
465 printf("csr=%b ds=%b\n", er, IDCCSR_BITS, ds,
466 ui->ui_type?IDCRB80DS_BITS:IDCRB02DS_BITS);
467 bp->b_flags |= B_ERROR;
468 } else if (er & IDC_DCK) {
469 switch (er & IDC_ECS) {
470 case IDC_ECS_NONE:
471 break;
472 case IDC_ECS_SOFT:
473 idcecc(ui);
474 break;
475 case IDC_ECS_HARD:
476 default:
477 goto hard;
478 }
479 } else
480 /* recoverable error, set up for retry */
481 goto seek;
482 }
483 if ((sc->sc_resid -= sc->sc_bcnt) != 0) {
484 sc->sc_ubaddr += sc->sc_bcnt;
485 /*
486 * Current transfer is complete, have
487 * we overflowed to the next track?
488 */
489 if ((sc->sc_sect += sc->sc_bcnt/st->nbps) == st->nsect) {
490 sc->sc_sect = 0;
491 if (++sc->sc_trk == st->ntrak) {
492 sc->sc_trk = 0;
493 sc->sc_cyl++;
494 } else if (ui->ui_type) {
495 /*
496 * RB80 can change heads just by
497 * loading the disk address register.
498 */
499 idcaddr->idccsr = IDC_SEEK|IDC_CRDY|
500 IDC_IE|(unit<<8);
501 printd(", change to track 0x%x", sc->sc_dar);
502 idcaddr->idcdar = sc->sc_dar;
503 idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
504 idccyl[ui->ui_unit].dar_sect = 0;
505 goto cont;
506 }
507 /*
508 * Changing tracks on RB02 or cylinders
509 * on RB80, start a seek.
510 */
511seek:
512 cmd = IDC_IE|IDC_SEEK|(unit<<8);
513 idcaddr->idccsr = cmd|IDC_CRDY;
514 idcaddr->idcdar = sc->sc_dar;
515 printd(", seek to 0x%x\n", sc->sc_dar);
516 idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
517 idccyl[ui->ui_unit].dar_sect = 0;
518 sc->sc_bcnt = 0;
519 idcaddr->idccsr = cmd;
520 if (ui->ui_type) {
521 if (idcwait(idcaddr, 10) == 0)
522 return;
523 idcaddr->idccsr &= ~IDC_ATTN;
524 if (idcaddr->idccsr & IDC_DRDY)
525 goto top;
526 }
527 } else {
528 /*
529 * Continue transfer on current track.
530 */
531cont:
532 sc->sc_bcnt = (st->nsect-sc->sc_sect)*st->nbps;
533 if (sc->sc_bcnt > sc->sc_resid)
534 sc->sc_bcnt = sc->sc_resid;
535 if (bp->b_flags & B_READ)
536 cmd = IDC_IE|IDC_READ|(unit<<8);
537 else
538 cmd = IDC_IE|IDC_WRITE|(unit<<8);
539 idcaddr->idccsr = cmd|IDC_CRDY;
540 idcaddr->idcbar = sc->sc_ubaddr;
541 idcaddr->idcbcr = -sc->sc_bcnt;
542 idcaddr->idcdar = sc->sc_dar;
543 printd(", continue I/O 0x%x, 0x%x\n", sc->sc_dar, sc->sc_bcnt);
544 idcaddr->idccsr = cmd;
545 um->um_tab.b_active = 2;
546 }
547 return;
548 }
549 /*
550 * Entire transfer is done, clean up.
551 */
552 ubadone(um);
553 dk_busy &= ~(1 << ui->ui_dk);
554 um->um_tab.b_active = 0;
555 um->um_tab.b_errcnt = 0;
556 um->um_tab.b_actf = dp->b_forw;
557 dp->b_active = 0;
558 dp->b_errcnt = 0;
559 dp->b_actf = bp->av_forw;
560 trace('done', dp); trace(um->um_tab.b_actf, dp->b_actf);
561 bp->b_resid = sc->sc_resid;
562 printd(", iodone, resid 0x%x\n", bp->b_resid);
563 iodone(bp);
564 if (dp->b_actf)
565 if (idcustart(ui))
566 return;
567 } else if (um->um_tab.b_active == 1) {
568 /*
569 * Got an interrupt while setting up for a command
570 * or doing a mid-transfer seek. Save any attentions
571 * for later and process a mid-transfer seek complete.
572 */
573 as = idcaddr->idccsr;
574 idcaddr->idccsr = IDC_IE|IDC_CRDY|(as&IDC_ATTN);
575 as = (as >> 16) & 0xf;
576 unit = sc->sc_unit;
577 sc->sc_softas |= as & ~(1<<unit);
578 if (as & (1<<unit)) {
579 printd(", seek1 complete");
580 um->um_tab.b_active = 2;
581 goto top;
582 }
583 printd(", as1 %o\n", as);
584 return;
585 }
586 /*
587 * Process any seek initiated or complete interrupts.
588 */
589 as = idcaddr->idccsr;
590 idcaddr->idccsr = IDC_IE|IDC_CRDY|(as&IDC_ATTN);
591 as = ((as >> 16) & 0xf) | sc->sc_softas;
592 sc->sc_softas = 0;
593 trace('as', as);
594 printd(", as %o", as);
595 for (unit = 0; unit < NRB; unit++)
596 if (as & (1<<unit)) {
597 as &= ~(1<<unit);
598 idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8);
599 ui = idcdinfo[unit];
600 if (ui) {
601 printd(", attn unit %d", unit);
602 if (idcaddr->idccsr & IDC_DRDY)
603 if (idcustart(ui)) {
604 sc->sc_softas = as;
605 return;
606 }
607 } else {
608 printd(", unsol. intr. unit %d", unit);
609 }
610 }
611 printd("\n");
612 if (um->um_tab.b_actf && um->um_tab.b_active == 0) {
613 trace('stum',um->um_tab.b_actf);
614 idcstart(um);
615 }
616}
617
618idcwait(addr, cnt)
619 register struct idcdevice *addr;
620 register int cnt;
621{
622 register int i;
623
624 while (--cnt && (addr->idccsr & IDC_CRDY) == 0)
625 for (i = 10; i; i--)
626 ;
627 return (cnt);
628}
629
630idcread(dev)
631 dev_t dev;
632{
633 register int unit = minor(dev) >> 3;
634
635 if (unit >= NRB)
636 u.u_error = ENXIO;
637 else
638 physio(idcstrategy, &ridcbuf[unit], dev, B_READ, minphys);
639}
640
641idcwrite(dev)
642 dev_t dev;
643{
644 register int unit = minor(dev) >> 3;
645
646 if (unit >= NRB)
647 u.u_error = ENXIO;
648 else
649 physio(idcstrategy, &ridcbuf[unit], dev, B_WRITE, minphys);
650}
651
652idcecc(ui)
653 register struct uba_device *ui;
654{
655 register struct idcdevice *idc = (struct idcdevice *)ui->ui_addr;
656 register struct buf *bp = idcutab[ui->ui_unit].b_actf;
657 register struct uba_ctlr *um = ui->ui_mi;
658 register struct idcst *st;
659 register int i;
660 struct uba_regs *ubp = ui->ui_hd->uh_uba;
661 int bit, byte, mask;
662 caddr_t addr;
663 int reg, npf, o;
664 int cn, tn, sn;
665
666 printf("idcecc: HELP!\n");
667 npf = btop(idc->idcbcr + idc_softc.sc_bcnt) - 1;;
668 reg = btop(idc_softc.sc_ubaddr) + npf;
669 o = (int)bp->b_un.b_addr & PGOFSET;
670 st = &idcst[ui->ui_type];
671 cn = idc_softc.sc_cyl;
672 tn = idc_softc.sc_trk;
673 sn = idc_softc.sc_sect;
674 um->um_tab.b_active = 1; /* Either complete or continuing... */
675 printf("rb%d%c: soft ecc sn%d\n", dkunit(bp),
676 'a'+(minor(bp->b_dev)&07),
677 (cn*st->ntrak + tn) * st->nsect + sn + npf);
678 mask = idc->idceccpat;
679 i = idc->idceccpos - 1; /* -1 makes 0 origin */
680 bit = i&07;
681 i = (i&~07)>>3;
682 byte = i + o;
683 while (i < 512 && (int)ptob(npf)+i < idc_softc.sc_bcnt && bit > -11) {
684 addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
685 (byte & PGOFSET);
686 putmemc(addr, getmemc(addr)^(mask<<bit));
687 byte++;
688 i++;
689 bit -= 8;
690 }
691 idc_softc.sc_bcnt += idc->idcbcr;
692 um->um_tab.b_errcnt = 0; /* error has been corrected */
693 return;
694}
695
696idcreset(uban)
697 int uban;
698{
699 register struct uba_ctlr *um;
700 register struct uba_device *ui;
701 register unit;
702
703 if ((um = idcminfo[0]) == 0 || um->um_ubanum != uban ||
704 um->um_alive == 0)
705 return;
706 printf(" idc0");
707 um->um_tab.b_active = 0;
708 um->um_tab.b_actf = um->um_tab.b_actl = 0;
709 if (um->um_ubinfo) {
710 printf("<%d>", (um->um_ubinfo>>28)&0xf);
711 ubadone(um);
712 }
713 for (unit = 0; unit < NRB; unit++) {
714 if ((ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
715 continue;
716 idcutab[unit].b_active = 0;
717 (void) idcustart(ui);
718 }
719 (void) idcstart(um);
720}
721
722idcwatch()
723{
724 register struct uba_ctlr *um;
725 register unit;
726
727 timeout(idcwatch, (caddr_t)0, hz);
728 um = idcminfo[0];
729 if (um == 0 || um->um_alive == 0)
730 return;
731 if (um->um_tab.b_active == 0) {
732 for (unit = 0; unit < NRB; unit++)
733 if (idcutab[unit].b_active)
734 goto active;
735 idcwticks = 0;
736 return;
737 }
738active:
739 idcwticks++;
740 if (idcwticks >= 20) {
741 idcwticks = 0;
742 printf("idc0: lost interrupt\n");
743 idcintr(0);
744 }
745}
746
747idcdump(dev)
748 dev_t dev;
749{
750#ifdef notdef
751 struct idcdevice *idcaddr;
752 char *start;
753 int num, blk, unit, dbsize;
754 struct size *sizes;
755 register struct uba_regs *uba;
756 register struct uba_device *ui;
757 struct idcst *st;
758
759 unit = minor(dev) >> 3;
760 if (unit >= NRB)
761 return (ENXIO);
762#define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
763 ui = phys(struct uba_device *, idcdinfo[unit]);
764 if (ui->ui_alive == 0)
765 return (ENXIO);
766 uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
767 ubainit(uba);
768 idcaddr = (struct idcdevice *)ui->ui_physaddr;
769 num = maxfree;
770 start = 0;
771/***
772 idcaddr->idccs1 = IDC_CCLR;
773 idcaddr->idccs2 = unit;
774 idcaddr->idccs1 = idctypes[ui->ui_type]|IDC_DCLR|IDC_GO;
775 idcwait(idcaddr);
776 dbsize = 20 or 31;
777***/
778 st = &idcst[ui->ui_type];
779 sizes = phys(struct size *, st->sizes);
780 if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
781 return (EINVAL);
782 while (num > 0) {
783 register struct pte *io;
784 register int i;
785 int cn, sn, tn;
786 daddr_t bn;
787
788 blk = num > dbsize ? dbsize : num;
789 io = uba->uba_map;
790 for (i = 0; i < blk; i++)
791 *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
792 *(int *)io = 0;
793 bn = dumplo + btop(start);
794 cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
795 sn = bn%st->nspc;
796 tn = sn/st->nsect;
797 sn = sn%st->nsect;
798/***
799 idcaddr->idccyl = cn;
800 rp = (short *) &idcaddr->idcda;
801 *rp = (tn << 8) + sn;
802 *--rp = 0;
803 *--rp = -blk*NBPG / sizeof (short);
804 *--rp = idctypes[ui->ui_type]|IDC_GO|IDC_WRITE;
805 idcwait(idcaddr);
806***/
807 if (idcaddr->idccsr & IDC_ERR)
808 return (EIO);
809 start += blk*NBPG;
810 num -= blk;
811 }
812 return (0);
813#else
814 return (ENXIO);
815#endif
816}
817#endif