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