ioctl/open return errors, not u.u_error; remove ubarelses (it is
[unix-history] / usr / src / sys / vax / uba / idc.c
CommitLineData
7da157da 1/* idc.c 4.7 82/10/17 */
6c163e27
SL
2
3#include "rb.h"
4#if NIDC > 0
7da157da
BJ
5int idcdebug = 0;
6#define printd if(idcdebug)printf
7int idctrb[1000];
8int *trp = idctrb;
6c163e27
SL
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"
6c163e27 31#include "../h/dk.h"
6c163e27
SL
32#include "../h/cmap.h"
33#include "../h/dkbad.h"
740e4029 34#include "../h/uio.h"
6c163e27 35
896962b1
BJ
36#include "../vax/cpu.h"
37#include "../vaxuba/ubareg.h"
38#include "../vaxuba/ubavar.h"
39#include "../vaxuba/idcreg.h"
6c163e27
SL
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}
7da157da
BJ
186
187idcopen(dev)
188 dev_t dev;
189{
190 register int unit = minor(dev) >> 3;
191 register struct uba_device *ui;
192
193 if (unit >= NRB || (ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
194 return (ENXIO);
195 return (0);
196}
6c163e27
SL
197
198idcstrategy(bp)
199 register struct buf *bp;
200{
201 register struct uba_device *ui;
202 register struct idcst *st;
203 register int unit;
204 register struct buf *dp;
205 int xunit = minor(bp->b_dev) & 07;
206 long bn, sz;
207
208 sz = (bp->b_bcount+511) >> 9;
209 unit = dkunit(bp);
210 if (unit >= NRB)
211 goto bad;
212 ui = idcdinfo[unit];
213 if (ui == 0 || ui->ui_alive == 0)
214 goto bad;
215 st = &idcst[ui->ui_type];
216 if (bp->b_blkno < 0 ||
217 (bn = dkblock(bp))+sz > st->sizes[xunit].nblocks)
218 goto bad;
219 if (ui->ui_type == 0)
220 bn *= 2;
221 bp->b_cylin = bn/st->nspc + st->sizes[xunit].cyloff;
222 (void) spl5();
223 trace('strt',bp);
224 dp = &idcutab[ui->ui_unit];
225 disksort(dp, bp);
226 if (dp->b_active == 0) {
227 trace('!act',dp);
228 (void) idcustart(ui);
229 bp = &ui->ui_mi->um_tab;
230 if (bp->b_actf && bp->b_active == 0)
231 (void) idcstart(ui->ui_mi);
232 }
233 (void) spl0();
234 return;
235
236bad:
237 bp->b_flags |= B_ERROR;
238 iodone(bp);
239 return;
240}
241
242idcustart(ui)
243 register struct uba_device *ui;
244{
245 register struct buf *bp, *dp;
246 register struct uba_ctlr *um;
247 register struct idcdevice *idcaddr;
248 register struct idcst *st;
249 union idc_dar cyltrk;
250 daddr_t bn;
251 int unit;
252
253 if (ui == 0)
254 return (0);
255 dk_busy &= ~(1<<ui->ui_dk);
256 dp = &idcutab[ui->ui_unit];
257 um = ui->ui_mi;
258 unit = ui->ui_slave;
259 trace('ust', dp);
260 idcaddr = (struct idcdevice *)um->um_addr;
261 if (um->um_tab.b_active) {
262 idc_softc.sc_softas |= 1<<unit;
263 trace('umac',idc_softc.sc_softas);
264 return (0);
265 }
266 if ((bp = dp->b_actf) == NULL) {
267 trace('!bp',0);
268 return (0);
269 }
270 if (dp->b_active) {
271 trace('dpac',dp->b_active);
272 goto done;
273 }
274 dp->b_active = 1;
275 /* CHECK DRIVE READY? */
276 bn = dkblock(bp);
277 trace('seek', bn);
278 if (ui->ui_type == 0)
279 bn *= 2;
280 st = &idcst[ui->ui_type];
281 cyltrk.dar_cyl = bp->b_cylin;
282 cyltrk.dar_trk = (bn / st->nsect) % st->ntrak;
283 cyltrk.dar_sect = 0;
284 printd("idcustart, unit %d, cyltrk 0x%x\n", unit, cyltrk.dar_dar);
285 /*
286 * If on cylinder, no need to seek.
287 */
288 if (cyltrk.dar_dar == idccyl[ui->ui_unit].dar_dar)
289 goto done;
290 /*
291 * RB80 can change heads (tracks) just by loading
292 * the disk address register, perform optimization
293 * here instead of doing a full seek.
294 */
295 if (ui->ui_type && cyltrk.dar_cyl == idccyl[ui->ui_unit].dar_cyl) {
296 idcaddr->idccsr = IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8);
297 idcaddr->idcdar = cyltrk.dar_dar;
298 idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar;
299 goto done;
300 }
301 /*
302 * Need to do a full seek. Select the unit, clear
303 * its attention bit, set the command, load the
304 * disk address register, and then go.
305 */
306 idcaddr->idccsr =
307 IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16));
308 idcaddr->idcdar = cyltrk.dar_dar;
309 idccyl[ui->ui_unit].dar_dar = cyltrk.dar_dar;
310 printd(" seek");
311 idcaddr->idccsr = IDC_IE|IDC_SEEK|(unit<<8);
312 if (ui->ui_dk >= 0) {
313 dk_busy |= 1<<ui->ui_dk;
314 dk_seek[ui->ui_dk]++;
315 }
316 /*
317 * RB80's initiate seeks very quickly. Wait for it
318 * to come ready rather than taking the interrupt.
319 */
320 if (ui->ui_type) {
321 if (idcwait(idcaddr, 10) == 0)
322 return (1);
323 idcaddr->idccsr &= ~IDC_ATTN;
324 /* has the seek completed? */
325 if (idcaddr->idccsr & IDC_DRDY) {
326 printd(", drdy");
327 idcaddr->idccsr =
328 IDC_CRDY|IDC_IE|IDC_SEEK|(unit<<8)|(1<<(unit+16));
329 goto done;
330 }
331 }
332 printd(", idccsr = 0x%x\n", idcaddr->idccsr);
333 return (1);
334done:
335 if (dp->b_active != 2) {
336 trace('!=2',dp->b_active);
337 dp->b_forw = NULL;
338 if (um->um_tab.b_actf == NULL)
339 um->um_tab.b_actf = dp;
340 else {
341 trace('!NUL',um->um_tab.b_actl);
342 um->um_tab.b_actl->b_forw = dp;
343 }
344 um->um_tab.b_actl = dp;
345 dp->b_active = 2;
346 }
347 return (0);
348}
349
350idcstart(um)
351 register struct uba_ctlr *um;
352{
353 register struct buf *bp, *dp;
354 register struct uba_device *ui;
355 register struct idcdevice *idcaddr;
356 register struct idc_softc *sc;
357 struct idcst *st;
358 daddr_t bn;
359 int sn, tn, cmd;
360
361loop:
362 if ((dp = um->um_tab.b_actf) == NULL) {
363 trace('nodp',um);
364 return (0);
365 }
366 if ((bp = dp->b_actf) == NULL) {
367 trace('nobp', dp);
368 um->um_tab.b_actf = dp->b_forw;
369 goto loop;
370 }
371 um->um_tab.b_active = 1;
372 ui = idcdinfo[dkunit(bp)];
373 bn = dkblock(bp);
374 trace('star',bp);
375 if (ui->ui_type == 0)
376 bn *= 2;
377 sc = &idc_softc;
378 st = &idcst[ui->ui_type];
379 sn = bn%st->nspc;
380 tn = sn/st->nsect;
381 sn %= st->nsect;
382 sc->sc_sect = sn;
383 sc->sc_trk = tn;
384 sc->sc_cyl = bp->b_cylin;
385 idcaddr = (struct idcdevice *)ui->ui_addr;
386 printd("idcstart, unit %d, dar 0x%x", ui->ui_slave, sc->sc_dar);
387 if (bp->b_flags & B_READ)
388 cmd = IDC_IE|IDC_READ|(ui->ui_slave<<8);
389 else
390 cmd = IDC_IE|IDC_WRITE|(ui->ui_slave<<8);
391 idcaddr->idccsr = IDC_CRDY|cmd;
392 if ((idcaddr->idccsr&IDC_DRDY) == 0) {
393 printf("rb%d: not ready\n", dkunit(bp));
394 um->um_tab.b_active = 0;
395 um->um_tab.b_errcnt = 0;
396 dp->b_actf = bp->av_forw;
397 dp->b_active = 0;
398 bp->b_flags |= B_ERROR;
399 iodone(bp);
400 goto loop;
401 }
402 idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
403 idccyl[ui->ui_unit].dar_sect = 0;
404 sn = (st->nsect - sn) * st->nbps;
405 if (sn > bp->b_bcount)
406 sn = bp->b_bcount;
407 sc->sc_bcnt = sn;
408 sc->sc_resid = bp->b_bcount;
409 sc->sc_unit = ui->ui_slave;
410 printd(", bcr 0x%x, cmd 0x%x\n", sn, cmd);
411 um->um_cmd = cmd;
412 (void) ubago(ui);
413 return (1);
414}
415
416idcdgo(um)
417 register struct uba_ctlr *um;
418{
419 register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr;
420 register struct idc_softc *sc = &idc_softc;
421
422 /*
423 * VERY IMPORTANT: must load registers in this order.
424 */
425 idcaddr->idcbar = sc->sc_ubaddr = um->um_ubinfo&0x3ffff;
426 idcaddr->idcbcr = -sc->sc_bcnt;
427 idcaddr->idcdar = sc->sc_dar;
428 printd("idcdgo, ubinfo 0x%x, cmd 0x%x\n", um->um_ubinfo, um->um_cmd);
429 idcaddr->idccsr = um->um_cmd;
430 trace('go', um);
431 um->um_tab.b_active = 2;
432 /*** CLEAR SPURIOUS ATTN ON R80? ***/
433}
434
435idcintr(idc)
436 int idc;
437{
438 register struct uba_ctlr *um = idcminfo[idc];
439 register struct uba_device *ui;
440 register struct idcdevice *idcaddr = (struct idcdevice *)um->um_addr;
441 register struct idc_softc *sc = &idc_softc;
442 register struct buf *bp, *dp;
443 struct idcst *st;
444 int unit, as, er, cmd, ds = 0;
445
446 printd("idcintr, idccsr 0x%x", idcaddr->idccsr);
447top:
448 idcwticks = 0;
449 trace('intr', um->um_tab.b_active);
450 if (um->um_tab.b_active == 2) {
451 /*
452 * Process a data transfer complete interrupt.
453 */
454 um->um_tab.b_active = 1;
455 dp = um->um_tab.b_actf;
456 bp = dp->b_actf;
457 ui = idcdinfo[dkunit(bp)];
458 unit = ui->ui_slave;
459 st = &idcst[ui->ui_type];
460 idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8);
461 if ((er = idcaddr->idccsr) & IDC_ERR) {
462 if (er & IDC_DE) {
463 idcaddr->idcmpr = IDCGS_GETSTAT;
464 idcaddr->idccsr = IDC_GETSTAT|(unit<<8);
465 idcwait(idcaddr, 0);
466 ds = idcaddr->idcmpr;
467 idcaddr->idccsr =
468 IDC_IE|IDC_CRDY|(1<<(unit+16));
469 }
470 printd(", er 0x%x, ds 0x%x", er, ds);
471 if (ds & IDCDS_WL) {
472 printf("rb%d: write locked\n", dkunit(bp));
473 bp->b_flags |= B_ERROR;
474 } else if (++um->um_tab.b_errcnt > 28 || er&IDC_HARD) {
475hard:
476 harderr(bp, "rb");
477 printf("csr=%b ds=%b\n", er, IDCCSR_BITS, ds,
478 ui->ui_type?IDCRB80DS_BITS:IDCRB02DS_BITS);
479 bp->b_flags |= B_ERROR;
480 } else if (er & IDC_DCK) {
481 switch (er & IDC_ECS) {
482 case IDC_ECS_NONE:
483 break;
484 case IDC_ECS_SOFT:
485 idcecc(ui);
486 break;
487 case IDC_ECS_HARD:
488 default:
489 goto hard;
490 }
491 } else
492 /* recoverable error, set up for retry */
493 goto seek;
494 }
495 if ((sc->sc_resid -= sc->sc_bcnt) != 0) {
496 sc->sc_ubaddr += sc->sc_bcnt;
497 /*
498 * Current transfer is complete, have
499 * we overflowed to the next track?
500 */
501 if ((sc->sc_sect += sc->sc_bcnt/st->nbps) == st->nsect) {
502 sc->sc_sect = 0;
503 if (++sc->sc_trk == st->ntrak) {
504 sc->sc_trk = 0;
505 sc->sc_cyl++;
506 } else if (ui->ui_type) {
507 /*
508 * RB80 can change heads just by
509 * loading the disk address register.
510 */
511 idcaddr->idccsr = IDC_SEEK|IDC_CRDY|
512 IDC_IE|(unit<<8);
513 printd(", change to track 0x%x", sc->sc_dar);
514 idcaddr->idcdar = sc->sc_dar;
515 idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
516 idccyl[ui->ui_unit].dar_sect = 0;
517 goto cont;
518 }
519 /*
520 * Changing tracks on RB02 or cylinders
521 * on RB80, start a seek.
522 */
523seek:
524 cmd = IDC_IE|IDC_SEEK|(unit<<8);
525 idcaddr->idccsr = cmd|IDC_CRDY;
526 idcaddr->idcdar = sc->sc_dar;
527 printd(", seek to 0x%x\n", sc->sc_dar);
528 idccyl[ui->ui_unit].dar_dar = sc->sc_dar;
529 idccyl[ui->ui_unit].dar_sect = 0;
530 sc->sc_bcnt = 0;
531 idcaddr->idccsr = cmd;
532 if (ui->ui_type) {
533 if (idcwait(idcaddr, 10) == 0)
534 return;
535 idcaddr->idccsr &= ~IDC_ATTN;
536 if (idcaddr->idccsr & IDC_DRDY)
537 goto top;
538 }
539 } else {
540 /*
541 * Continue transfer on current track.
542 */
543cont:
544 sc->sc_bcnt = (st->nsect-sc->sc_sect)*st->nbps;
545 if (sc->sc_bcnt > sc->sc_resid)
546 sc->sc_bcnt = sc->sc_resid;
547 if (bp->b_flags & B_READ)
548 cmd = IDC_IE|IDC_READ|(unit<<8);
549 else
550 cmd = IDC_IE|IDC_WRITE|(unit<<8);
551 idcaddr->idccsr = cmd|IDC_CRDY;
552 idcaddr->idcbar = sc->sc_ubaddr;
553 idcaddr->idcbcr = -sc->sc_bcnt;
554 idcaddr->idcdar = sc->sc_dar;
555 printd(", continue I/O 0x%x, 0x%x\n", sc->sc_dar, sc->sc_bcnt);
556 idcaddr->idccsr = cmd;
557 um->um_tab.b_active = 2;
558 }
559 return;
560 }
561 /*
562 * Entire transfer is done, clean up.
563 */
564 ubadone(um);
565 dk_busy &= ~(1 << ui->ui_dk);
566 um->um_tab.b_active = 0;
567 um->um_tab.b_errcnt = 0;
568 um->um_tab.b_actf = dp->b_forw;
569 dp->b_active = 0;
570 dp->b_errcnt = 0;
571 dp->b_actf = bp->av_forw;
572 trace('done', dp); trace(um->um_tab.b_actf, dp->b_actf);
573 bp->b_resid = sc->sc_resid;
574 printd(", iodone, resid 0x%x\n", bp->b_resid);
575 iodone(bp);
576 if (dp->b_actf)
577 if (idcustart(ui))
578 return;
579 } else if (um->um_tab.b_active == 1) {
580 /*
581 * Got an interrupt while setting up for a command
582 * or doing a mid-transfer seek. Save any attentions
583 * for later and process a mid-transfer seek complete.
584 */
585 as = idcaddr->idccsr;
586 idcaddr->idccsr = IDC_IE|IDC_CRDY|(as&IDC_ATTN);
587 as = (as >> 16) & 0xf;
588 unit = sc->sc_unit;
589 sc->sc_softas |= as & ~(1<<unit);
590 if (as & (1<<unit)) {
591 printd(", seek1 complete");
592 um->um_tab.b_active = 2;
593 goto top;
594 }
595 printd(", as1 %o\n", as);
596 return;
597 }
598 /*
599 * Process any seek initiated or complete interrupts.
600 */
601 as = idcaddr->idccsr;
602 idcaddr->idccsr = IDC_IE|IDC_CRDY|(as&IDC_ATTN);
603 as = ((as >> 16) & 0xf) | sc->sc_softas;
604 sc->sc_softas = 0;
605 trace('as', as);
606 printd(", as %o", as);
607 for (unit = 0; unit < NRB; unit++)
608 if (as & (1<<unit)) {
609 as &= ~(1<<unit);
610 idcaddr->idccsr = IDC_IE|IDC_CRDY|(unit<<8);
611 ui = idcdinfo[unit];
612 if (ui) {
613 printd(", attn unit %d", unit);
614 if (idcaddr->idccsr & IDC_DRDY)
615 if (idcustart(ui)) {
616 sc->sc_softas = as;
617 return;
618 }
619 } else {
620 printd(", unsol. intr. unit %d", unit);
621 }
622 }
623 printd("\n");
624 if (um->um_tab.b_actf && um->um_tab.b_active == 0) {
625 trace('stum',um->um_tab.b_actf);
626 idcstart(um);
627 }
628}
629
630idcwait(addr, cnt)
631 register struct idcdevice *addr;
632 register int cnt;
633{
634 register int i;
635
636 while (--cnt && (addr->idccsr & IDC_CRDY) == 0)
637 for (i = 10; i; i--)
638 ;
639 return (cnt);
640}
641
740e4029 642idcread(dev, uio)
6c163e27 643 dev_t dev;
740e4029 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_READ, minphys, uio));
6c163e27
SL
651}
652
406ddcbe 653idcwrite(dev, uio)
6c163e27 654 dev_t dev;
406ddcbe 655 struct uio *uio;
6c163e27
SL
656{
657 register int unit = minor(dev) >> 3;
658
659 if (unit >= NRB)
aa890753
BJ
660 return (ENXIO);
661 return (physio(idcstrategy, &ridcbuf[unit], dev, B_WRITE, minphys, uio));
6c163e27
SL
662}
663
664idcecc(ui)
665 register struct uba_device *ui;
666{
667 register struct idcdevice *idc = (struct idcdevice *)ui->ui_addr;
668 register struct buf *bp = idcutab[ui->ui_unit].b_actf;
669 register struct uba_ctlr *um = ui->ui_mi;
670 register struct idcst *st;
671 register int i;
672 struct uba_regs *ubp = ui->ui_hd->uh_uba;
673 int bit, byte, mask;
674 caddr_t addr;
675 int reg, npf, o;
676 int cn, tn, sn;
677
678 printf("idcecc: HELP!\n");
679 npf = btop(idc->idcbcr + idc_softc.sc_bcnt) - 1;;
680 reg = btop(idc_softc.sc_ubaddr) + npf;
681 o = (int)bp->b_un.b_addr & PGOFSET;
682 st = &idcst[ui->ui_type];
683 cn = idc_softc.sc_cyl;
684 tn = idc_softc.sc_trk;
685 sn = idc_softc.sc_sect;
686 um->um_tab.b_active = 1; /* Either complete or continuing... */
687 printf("rb%d%c: soft ecc sn%d\n", dkunit(bp),
688 'a'+(minor(bp->b_dev)&07),
689 (cn*st->ntrak + tn) * st->nsect + sn + npf);
690 mask = idc->idceccpat;
691 i = idc->idceccpos - 1; /* -1 makes 0 origin */
692 bit = i&07;
693 i = (i&~07)>>3;
694 byte = i + o;
695 while (i < 512 && (int)ptob(npf)+i < idc_softc.sc_bcnt && bit > -11) {
696 addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
697 (byte & PGOFSET);
698 putmemc(addr, getmemc(addr)^(mask<<bit));
699 byte++;
700 i++;
701 bit -= 8;
702 }
703 idc_softc.sc_bcnt += idc->idcbcr;
704 um->um_tab.b_errcnt = 0; /* error has been corrected */
705 return;
706}
707
708idcreset(uban)
709 int uban;
710{
711 register struct uba_ctlr *um;
712 register struct uba_device *ui;
713 register unit;
714
715 if ((um = idcminfo[0]) == 0 || um->um_ubanum != uban ||
716 um->um_alive == 0)
717 return;
718 printf(" idc0");
719 um->um_tab.b_active = 0;
720 um->um_tab.b_actf = um->um_tab.b_actl = 0;
721 if (um->um_ubinfo) {
722 printf("<%d>", (um->um_ubinfo>>28)&0xf);
723 ubadone(um);
724 }
725 for (unit = 0; unit < NRB; unit++) {
726 if ((ui = idcdinfo[unit]) == 0 || ui->ui_alive == 0)
727 continue;
728 idcutab[unit].b_active = 0;
729 (void) idcustart(ui);
730 }
731 (void) idcstart(um);
732}
733
734idcwatch()
735{
736 register struct uba_ctlr *um;
737 register unit;
738
739 timeout(idcwatch, (caddr_t)0, hz);
740 um = idcminfo[0];
741 if (um == 0 || um->um_alive == 0)
742 return;
743 if (um->um_tab.b_active == 0) {
744 for (unit = 0; unit < NRB; unit++)
745 if (idcutab[unit].b_active)
746 goto active;
747 idcwticks = 0;
748 return;
749 }
750active:
751 idcwticks++;
752 if (idcwticks >= 20) {
753 idcwticks = 0;
754 printf("idc0: lost interrupt\n");
755 idcintr(0);
756 }
757}
758
759idcdump(dev)
760 dev_t dev;
761{
762#ifdef notdef
763 struct idcdevice *idcaddr;
764 char *start;
765 int num, blk, unit, dbsize;
766 struct size *sizes;
767 register struct uba_regs *uba;
768 register struct uba_device *ui;
769 struct idcst *st;
770
771 unit = minor(dev) >> 3;
772 if (unit >= NRB)
773 return (ENXIO);
774#define phys(cast, addr) ((cast)((int)addr & 0x7fffffff))
775 ui = phys(struct uba_device *, idcdinfo[unit]);
776 if (ui->ui_alive == 0)
777 return (ENXIO);
778 uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba;
779 ubainit(uba);
780 idcaddr = (struct idcdevice *)ui->ui_physaddr;
781 num = maxfree;
782 start = 0;
783/***
784 idcaddr->idccs1 = IDC_CCLR;
785 idcaddr->idccs2 = unit;
786 idcaddr->idccs1 = idctypes[ui->ui_type]|IDC_DCLR|IDC_GO;
787 idcwait(idcaddr);
788 dbsize = 20 or 31;
789***/
790 st = &idcst[ui->ui_type];
791 sizes = phys(struct size *, st->sizes);
792 if (dumplo < 0 || dumplo + num >= sizes[minor(dev)&07].nblocks)
793 return (EINVAL);
794 while (num > 0) {
795 register struct pte *io;
796 register int i;
797 int cn, sn, tn;
798 daddr_t bn;
799
800 blk = num > dbsize ? dbsize : num;
801 io = uba->uba_map;
802 for (i = 0; i < blk; i++)
803 *(int *)io++ = (btop(start)+i) | (1<<21) | UBAMR_MRV;
804 *(int *)io = 0;
805 bn = dumplo + btop(start);
806 cn = bn/st->nspc + sizes[minor(dev)&07].cyloff;
807 sn = bn%st->nspc;
808 tn = sn/st->nsect;
809 sn = sn%st->nsect;
810/***
811 idcaddr->idccyl = cn;
812 rp = (short *) &idcaddr->idcda;
813 *rp = (tn << 8) + sn;
814 *--rp = 0;
815 *--rp = -blk*NBPG / sizeof (short);
816 *--rp = idctypes[ui->ui_type]|IDC_GO|IDC_WRITE;
817 idcwait(idcaddr);
818***/
819 if (idcaddr->idccsr & IDC_ERR)
820 return (EIO);
821 start += blk*NBPG;
822 num -= blk;
823 }
824 return (0);
825#else
826 return (ENXIO);
827#endif
828}
829#endif