|
|
1.1 root 1: /* uda.c 6.1 83/07/29 */
2:
3: #include "ra.h"
4: #if NUDA > 0
5: /*
6: * UDA50/RAxx disk device driver
7: *
8: * Restrictions:
9: * Unit numbers must be less than 8.
10: *
11: * TO DO:
12: * write dump code
13: */
14: #include "../machine/pte.h"
15:
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/map.h"
23: #include "../h/vm.h"
24: #include "../h/dk.h"
25: #include "../h/cmap.h"
26: #include "../h/uio.h"
27:
28: #include "../vax/cpu.h"
29: #include "../vaxuba/ubareg.h"
30: #include "../vaxuba/ubavar.h"
31:
32: #define NRSPL2 3 /* log2 number of response packets */
33: #define NCMDL2 3 /* log2 number of command packets */
34: #define NRSP (1<<NRSPL2)
35: #define NCMD (1<<NCMDL2)
36:
37: #include "../vaxuba/udareg.h"
38: #include "../vax/mscp.h"
39:
40: struct uda_softc {
41: short sc_state; /* state of controller */
42: short sc_mapped; /* Unibus map allocated for uda struct? */
43: int sc_ubainfo; /* Unibus mapping info */
44: struct uda *sc_uda; /* Unibus address of uda struct */
45: int sc_ivec; /* interrupt vector address */
46: short sc_credits; /* transfer credits */
47: short sc_lastcmd; /* pointer into command ring */
48: short sc_lastrsp; /* pointer into response ring */
49: } uda_softc[NUDA];
50:
51: /*
52: * Controller states
53: */
54: #define S_IDLE 0 /* hasn't been initialized */
55: #define S_STEP1 1 /* doing step 1 init */
56: #define S_STEP2 2 /* doing step 2 init */
57: #define S_STEP3 3 /* doing step 3 init */
58: #define S_SCHAR 4 /* doing "set controller characteristics" */
59: #define S_RUN 5 /* running */
60:
61: struct uda {
62: struct udaca uda_ca; /* communications area */
63: struct mscp uda_rsp[NRSP]; /* response packets */
64: struct mscp uda_cmd[NCMD]; /* command packets */
65: } uda[NUDA];
66:
67: /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */
68: struct size {
69: daddr_t nblocks;
70: daddr_t blkoff;
71: } ra_sizes[8] ={
72: 15884, 0, /* A=blk 0 thru 15883 */
73: 33440, 15884, /* B=blk 15884 thru 49323 */
74: -1, 0, /* C=blk 0 thru end */
75: 15884, 340670, /* D=blk 340670 thru 356553 */
76: 55936, 356554, /* E=blk 356554 thru 412489 */
77: -1, 412490, /* F=blk 412490 thru end */
78: 82080, 49324, /* G=blk 49324 thru 131403 */
79: -1, 131404, /* H=blk 131404 thru end */
80: };
81: /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */
82:
83: int udaerror = 0; /* causes hex dump of packets */
84: int udadebug = 0;
85: #define printd if (udadebug) printf
86:
87: daddr_t radsize[NRA]; /* disk size, from ONLINE end packet */
88:
89: int udprobe(), udslave(), udattach(), udintr();
90: struct mscp *udgetcp();
91: struct uba_ctlr *udminfo[NUDA];
92: struct uba_device *uddinfo[NRA];
93: struct uba_device *udip[NUDA][8]; /* 8 == max number of drives */
94:
95: u_short udstd[] = { 0772150, 0772550, 0777550, 0 };
96: struct uba_driver udadriver =
97: { udprobe, udslave, udattach, 0, udstd, "ra", uddinfo, "uda", udminfo, 0 };
98: struct buf rudbuf[NRA];
99: struct buf udutab[NRA];
100: struct buf udwtab[NUDA]; /* I/O wait queue, per controller */
101:
102: #define b_qsize b_resid /* queue size per drive, in udutab */
103: #define b_ubinfo b_resid /* Unibus mapping info, per buffer */
104:
105: udprobe(reg, ctlr)
106: caddr_t reg;
107: int ctlr;
108: {
109: register int br, cvec;
110: register struct uda_softc *sc = &uda_softc[ctlr];
111:
112: #ifdef lint
113: br = 0; cvec = br; br = cvec; reg = reg;
114: udreset(0); udintr(0);
115: #endif
116: /* SHOULD CHECK THAT IT REALLY IS A UDA */
117: br = 0x15;
118: cvec = sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4);
119: return(sizeof (struct udadevice));
120: }
121:
122: udslave(ui, reg)
123: struct uba_device *ui;
124: caddr_t reg;
125: {
126: /*
127: * TOO HARD TO FIND OUT IF DISK IS THERE UNTIL
128: * INITIALIZED. WE'LL FIND OUT WHEN WE FIRST
129: * TRY TO ACCESS IT.
130: */
131: #ifdef lint
132: ui = ui; reg = reg;
133: #endif
134: return(1);
135: }
136:
137: udattach(ui)
138: register struct uba_device *ui;
139: {
140:
141: if (ui->ui_dk >= 0)
142: dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256); /* approx */
143: ui->ui_flags = 0;
144: udip[ui->ui_ctlr][ui->ui_slave] = ui;
145: radsize[ui->ui_unit] = (daddr_t)0xffffff; /* max possible size */
146: }
147:
148: /*
149: * Open a UDA. Initialize the device and
150: * set the unit online.
151: */
152: udopen(dev, flag)
153: dev_t dev;
154: int flag;
155: {
156: register int unit;
157: register struct uba_device *ui;
158: register struct uda_softc *sc;
159: int s;
160:
161: #ifdef lint
162: flag = flag;
163: #endif
164: unit = minor(dev) >> 3;
165: if (unit >= NRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0)
166: return (ENXIO);
167: sc = &uda_softc[ui->ui_ctlr];
168: s = spl5();
169: if (sc->sc_state != S_RUN) {
170: if (sc->sc_state == S_IDLE)
171: udinit(ui->ui_ctlr);
172: /* wait for initialization to complete */
173: sleep((caddr_t)ui->ui_mi, 0);
174: if (sc->sc_state != S_RUN)
175: return (EIO);
176: }
177: splx(s);
178: /* SHOULD PROBABLY FORCE AN ONLINE ATTEMPT
179: TO SEE IF DISK IS REALLY THERE */
180: return (0);
181: }
182:
183: /*
184: * Initialize a UDA. Set up UBA mapping registers,
185: * initialize data structures, and start hardware
186: * initialization sequence.
187: */
188: udinit(d)
189: int d;
190: {
191: register struct uda_softc *sc;
192: register struct uda *ud;
193: struct udadevice *udaddr;
194: struct uba_ctlr *um;
195:
196: sc = &uda_softc[d];
197: um = udminfo[d];
198: um->um_tab.b_active++;
199: ud = &uda[d];
200: udaddr = (struct udadevice *)um->um_addr;
201: if (sc->sc_mapped == 0) {
202: /*
203: * Map the communications area and command
204: * and response packets into Unibus address
205: * space.
206: */
207: sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)ud,
208: sizeof (struct uda), 0);
209: sc->sc_uda = (struct uda *)(sc->sc_ubainfo & 0x3ffff);
210: sc->sc_mapped = 1;
211: }
212:
213: /*
214: * Start the hardware initialization sequence.
215: */
216: udaddr->udaip = 0; /* start initialization */
217: while ((udaddr->udasa & UDA_STEP1) == 0)
218: ;
219: udaddr->udasa = UDA_ERR|(NCMDL2<<11)|(NRSPL2<<8)|UDA_IE|(sc->sc_ivec/4);
220: /*
221: * Initialization continues in interrupt routine.
222: */
223: sc->sc_state = S_STEP1;
224: sc->sc_credits = 0;
225: }
226:
227: udstrategy(bp)
228: register struct buf *bp;
229: {
230: register struct uba_device *ui;
231: register struct uba_ctlr *um;
232: register struct buf *dp;
233: register int unit;
234: int xunit = minor(bp->b_dev) & 07;
235: daddr_t sz, maxsz;
236: int s;
237:
238: sz = (bp->b_bcount+511) >> 9;
239: unit = dkunit(bp);
240: if (unit >= NRA)
241: goto bad;
242: ui = uddinfo[unit];
243: um = ui->ui_mi;
244: if (ui == 0 || ui->ui_alive == 0)
245: goto bad;
246: if ((maxsz = ra_sizes[xunit].nblocks) < 0)
247: maxsz = radsize[unit] - ra_sizes[xunit].blkoff;
248: if (bp->b_blkno < 0 || bp->b_blkno+sz > maxsz ||
249: ra_sizes[xunit].blkoff >= radsize[unit])
250: goto bad;
251: s = spl5();
252: /*
253: * Link the buffer onto the drive queue
254: */
255: dp = &udutab[ui->ui_unit];
256: if (dp->b_actf == 0)
257: dp->b_actf = bp;
258: else
259: dp->b_actl->av_forw = bp;
260: dp->b_actl = bp;
261: bp->av_forw = 0;
262: /*
263: * Link the drive onto the controller queue
264: */
265: if (dp->b_active == 0) {
266: dp->b_forw = NULL;
267: if (um->um_tab.b_actf == NULL)
268: um->um_tab.b_actf = dp;
269: else
270: um->um_tab.b_actl->b_forw = dp;
271: um->um_tab.b_actl = dp;
272: dp->b_active = 1;
273: }
274: if (um->um_tab.b_active == 0) {
275: #if defined(VAX750)
276: if (cpu == VAX_750
277: && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) {
278: if (um->um_ubinfo != 0)
279: printf("udastrat: ubinfo 0x%x\n",um->um_ubinfo);
280: else
281: um->um_ubinfo =
282: uballoc(um->um_ubanum, (caddr_t)0, 0,
283: UBA_NEEDBDP);
284: }
285: #endif
286: (void) udstart(um);
287: }
288: splx(s);
289: return;
290:
291: bad:
292: bp->b_flags |= B_ERROR;
293: iodone(bp);
294: return;
295: }
296:
297: udstart(um)
298: register struct uba_ctlr *um;
299: {
300: register struct buf *bp, *dp;
301: register struct mscp *mp;
302: register struct uda_softc *sc;
303: register struct uba_device *ui;
304: struct udadevice *udaddr;
305: int i;
306:
307: sc = &uda_softc[um->um_ctlr];
308:
309: loop:
310: if ((dp = um->um_tab.b_actf) == NULL) {
311: /*
312: * Release uneeded UBA resources and return
313: */
314: um->um_tab.b_active = 0;
315: return (0);
316: }
317: if ((bp = dp->b_actf) == NULL) {
318: /*
319: * No more requests for this drive, remove
320: * from controller queue and look at next drive.
321: * We know we're at the head of the controller queue.
322: */
323: dp->b_active = 0;
324: um->um_tab.b_actf = dp->b_forw;
325: goto loop;
326: }
327: um->um_tab.b_active++;
328: udaddr = (struct udadevice *)um->um_addr;
329: if ((udaddr->udasa&UDA_ERR) || sc->sc_state != S_RUN) {
330: harderr(bp, "ra");
331: printf("udasa %o, state %d\n", udaddr->udasa&0xffff, sc->sc_state);
332: udinit(um->um_ctlr);
333: /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE UDRESET */
334: return (0);
335: }
336: ui = uddinfo[dkunit(bp)];
337: /*
338: * If no credits, can't issue any commands
339: * until some outstanding commands complete.
340: */
341: if (sc->sc_credits < 2)
342: return (0);
343: if ((mp = udgetcp(um)) == NULL)
344: return (0);
345: sc->sc_credits--; /* committed to issuing a command */
346: if (ui->ui_flags == 0) { /* not online */
347: mp->mscp_opcode = M_OP_ONLIN;
348: mp->mscp_unit = ui->ui_slave;
349: dp->b_active = 2;
350: um->um_tab.b_actf = dp->b_forw; /* remove from controller q */
351: printd("uda: bring unit %d online\n", ui->ui_slave);
352: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT;
353: i = udaddr->udaip;
354: goto loop;
355: }
356: switch (cpu) {
357: case VAX_780:
358: i = UBA_NEEDBDP|UBA_CANTWAIT;
359: break;
360:
361: case VAX_750:
362: i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT;
363: break;
364:
365: case VAX_730:
366: i = UBA_CANTWAIT;
367: break;
368: }
369: if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) {
370: mp->mscp_opcode = M_OP_GTUNT;
371: mp->mscp_unit = ui->ui_slave;
372: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT;
373: i = udaddr->udaip; /* initiate polling */
374: return(1); /* wait for interrupt */
375: }
376: mp->mscp_cmdref = (long)bp; /* pointer to get back */
377: mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE;
378: mp->mscp_unit = ui->ui_slave;
379: mp->mscp_lbn = bp->b_blkno + ra_sizes[minor(bp->b_dev)&7].blkoff;
380: mp->mscp_bytecnt = bp->b_bcount;
381: mp->mscp_buffer = (i & 0x3ffff) | (((i>>28)&0xf)<<24);
382: #if defined(VAX750)
383: if (cpu == VAX_750)
384: i &= 0xfffffff; /* mask off bdp */
385: #endif
386: bp->b_ubinfo = i; /* save mapping info */
387: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT;
388: i = udaddr->udaip; /* initiate polling */
389: if (ui->ui_dk >= 0) {
390: dk_busy |= 1<<ui->ui_dk;
391: dp->b_qsize++;
392: dk_xfer[ui->ui_dk]++;
393: dk_wds[ui->ui_dk] += bp->b_bcount>>6;
394: }
395:
396: /*
397: * Move drive to the end of the controller queue
398: */
399: if (dp->b_forw != NULL) {
400: um->um_tab.b_actf = dp->b_forw;
401: um->um_tab.b_actl->b_forw = dp;
402: um->um_tab.b_actl = dp;
403: dp->b_forw = NULL;
404: }
405: /*
406: * Move buffer to I/O wait queue
407: */
408: dp->b_actf = bp->av_forw;
409: dp = &udwtab[um->um_ctlr];
410: bp->av_forw = dp;
411: bp->av_back = dp->av_back;
412: dp->av_back->av_forw = bp;
413: dp->av_back = bp;
414: goto loop;
415: }
416:
417: /*
418: * UDA interrupt routine.
419: */
420: udintr(d)
421: int d;
422: {
423: register struct uba_ctlr *um = udminfo[d];
424: register struct udadevice *udaddr = (struct udadevice *)um->um_addr;
425: struct buf *bp;
426: register int i;
427: register struct uda_softc *sc = &uda_softc[d];
428: register struct uda *ud = &uda[d];
429: struct uda *uud;
430: struct mscp *mp;
431:
432: printd("udintr: state %d, udasa %o\n", sc->sc_state, udaddr->udasa);
433: switch (sc->sc_state) {
434: case S_IDLE:
435: printf("uda%d: random interrupt ignored\n", d);
436: return;
437:
438: case S_STEP1:
439: #define STEP1MASK 0174377
440: #define STEP1GOOD (UDA_STEP2|UDA_IE|(NCMDL2<<3)|NRSPL2)
441: if ((udaddr->udasa&STEP1MASK) != STEP1GOOD) {
442: sc->sc_state = S_IDLE;
443: wakeup((caddr_t)um);
444: return;
445: }
446: udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)|
447: (cpu == VAX_780 ? UDA_PI : 0);
448: sc->sc_state = S_STEP2;
449: return;
450:
451: case S_STEP2:
452: #define STEP2MASK 0174377
453: #define STEP2GOOD (UDA_STEP3|UDA_IE|(sc->sc_ivec/4))
454: if ((udaddr->udasa&STEP2MASK) != STEP2GOOD) {
455: sc->sc_state = S_IDLE;
456: wakeup((caddr_t)um);
457: return;
458: }
459: udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)>>16;
460: sc->sc_state = S_STEP3;
461: return;
462:
463: case S_STEP3:
464: #define STEP3MASK 0174000
465: #define STEP3GOOD UDA_STEP4
466: if ((udaddr->udasa&STEP3MASK) != STEP3GOOD) {
467: sc->sc_state = S_IDLE;
468: wakeup((caddr_t)um);
469: return;
470: }
471: udaddr->udasa = UDA_GO;
472: sc->sc_state = S_SCHAR;
473:
474: /*
475: * Initialize the data structures.
476: */
477: uud = sc->sc_uda;
478: for (i = 0; i < NRSP; i++) {
479: ud->uda_ca.ca_rspdsc[i] = UDA_OWN|UDA_INT|
480: (long)&uud->uda_rsp[i].mscp_cmdref;
481: ud->uda_rsp[i].mscp_dscptr = &ud->uda_ca.ca_rspdsc[i];
482: ud->uda_rsp[i].mscp_header.uda_msglen = sizeof (struct mscp);
483: }
484: for (i = 0; i < NCMD; i++) {
485: ud->uda_ca.ca_cmddsc[i] = UDA_INT|
486: (long)&uud->uda_cmd[i].mscp_cmdref;
487: ud->uda_cmd[i].mscp_dscptr = &ud->uda_ca.ca_cmddsc[i];
488: ud->uda_cmd[i].mscp_header.uda_msglen = sizeof (struct mscp);
489: }
490: bp = &udwtab[d];
491: bp->av_forw = bp->av_back = bp;
492: sc->sc_lastcmd = 0;
493: sc->sc_lastrsp = 0;
494: if ((mp = udgetcp(um)) == NULL) {
495: sc->sc_state = S_IDLE;
496: wakeup((caddr_t)um);
497: return;
498: }
499: mp->mscp_opcode = M_OP_STCON;
500: mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS;
501: *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT;
502: i = udaddr->udaip; /* initiate polling */
503: return;
504:
505: case S_SCHAR:
506: case S_RUN:
507: break;
508:
509: default:
510: printf("uda%d: interrupt in unknown state %d ignored\n",
511: d, sc->sc_state);
512: return;
513: }
514:
515: if (udaddr->udasa&UDA_ERR) {
516: printf("uda%d: fatal error (%o)\n", d, udaddr->udasa&0xffff);
517: udaddr->udaip = 0;
518: wakeup((caddr_t)um);
519: }
520:
521: /*
522: * Check for a buffer purge request.
523: */
524: if (ud->uda_ca.ca_bdp) {
525: /*
526: * THIS IS A KLUDGE.
527: * Maybe we should change the entire
528: * UBA interface structure.
529: */
530: int s = spl7();
531:
532: i = um->um_ubinfo;
533: printd("uda: purge bdp %d\n", ud->uda_ca.ca_bdp);
534: um->um_ubinfo = ud->uda_ca.ca_bdp<<28;
535: ubapurge(um);
536: um->um_ubinfo = i;
537: (void) splx(s);
538: ud->uda_ca.ca_bdp = 0;
539: udaddr->udasa = 0; /* signal purge complete */
540: }
541:
542: /*
543: * Check for response ring transition.
544: */
545: if (ud->uda_ca.ca_rspint) {
546: ud->uda_ca.ca_rspint = 0;
547: for (i = sc->sc_lastrsp;; i++) {
548: i %= NRSP;
549: if (ud->uda_ca.ca_rspdsc[i]&UDA_OWN)
550: break;
551: udrsp(um, ud, sc, i);
552: ud->uda_ca.ca_rspdsc[i] |= UDA_OWN;
553: }
554: sc->sc_lastrsp = i;
555: }
556:
557: /*
558: * Check for command ring transition.
559: */
560: if (ud->uda_ca.ca_cmdint) {
561: printd("uda: command ring transition\n");
562: ud->uda_ca.ca_cmdint = 0;
563: }
564: (void) udstart(um);
565: }
566:
567: /*
568: * Process a response packet
569: */
570: udrsp(um, ud, sc, i)
571: register struct uba_ctlr *um;
572: register struct uda *ud;
573: register struct uda_softc *sc;
574: int i;
575: {
576: register struct mscp *mp;
577: struct uba_device *ui;
578: struct buf *dp, *bp;
579: int st;
580:
581: mp = &ud->uda_rsp[i];
582: mp->mscp_header.uda_msglen = sizeof (struct mscp);
583: sc->sc_credits += mp->mscp_header.uda_credits & 0xf;
584: if ((mp->mscp_header.uda_credits & 0xf0) > 0x10)
585: return;
586: /*
587: * If it's an error log message (datagram),
588: * pass it on for more extensive processing.
589: */
590: if ((mp->mscp_header.uda_credits & 0xf0) == 0x10) {
591: uderror(um, (struct mslg *)mp);
592: return;
593: }
594: if (mp->mscp_unit >= 8)
595: return;
596: if ((ui = udip[um->um_ctlr][mp->mscp_unit]) == 0)
597: return;
598: st = mp->mscp_status&M_ST_MASK;
599: switch (mp->mscp_opcode) {
600: case M_OP_STCON|M_OP_END:
601: if (st == M_ST_SUCC)
602: sc->sc_state = S_RUN;
603: else
604: sc->sc_state = S_IDLE;
605: um->um_tab.b_active = 0;
606: wakeup((caddr_t)um);
607: break;
608:
609: case M_OP_ONLIN|M_OP_END:
610: /*
611: * Link the drive onto the controller queue
612: */
613: dp = &udutab[ui->ui_unit];
614: dp->b_forw = NULL;
615: if (um->um_tab.b_actf == NULL)
616: um->um_tab.b_actf = dp;
617: else
618: um->um_tab.b_actl->b_forw = dp;
619: um->um_tab.b_actl = dp;
620: if (st == M_ST_SUCC) {
621: ui->ui_flags = 1; /* mark it online */
622: radsize[ui->ui_unit] = (daddr_t)mp->mscp_untsize;
623: printd("uda: unit %d online\n", mp->mscp_unit);
624: #ifdef notdef
625: printf("uda%d: online, size=%d\n",
626: mp->mscp_unit, (daddr_t)mp->mscp_untsize);
627: #endif
628: } else {
629: harderr(dp->b_actf, "ra");
630: printf("OFFLINE\n");
631: while (bp = dp->b_actf) {
632: dp->b_actf = bp->av_forw;
633: bp->b_flags |= B_ERROR;
634: iodone(bp);
635: }
636: }
637: dp->b_active = 1;
638: break;
639:
640: case M_OP_AVATN:
641: printd("uda: unit %d attention\n", mp->mscp_unit);
642: ui->ui_flags = 0; /* it went offline and we didn't notice */
643: break;
644:
645: case M_OP_READ|M_OP_END:
646: case M_OP_WRITE|M_OP_END:
647: bp = (struct buf *)mp->mscp_cmdref;
648: ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo);
649: /*
650: * Unlink buffer from I/O wait queue.
651: */
652: bp->av_back->av_forw = bp->av_forw;
653: bp->av_forw->av_back = bp->av_back;
654: #if defined(VAX750)
655: if (cpu == VAX_750
656: && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) {
657: if (um->um_ubinfo == 0)
658: printf("udintr: um_ubinfo == 0\n");
659: else
660: ubarelse(um->um_ubanum, &um->um_ubinfo);
661: }
662: #endif
663: dp = &udutab[ui->ui_unit];
664: if (ui->ui_dk >= 0)
665: if (--dp->b_qsize == 0)
666: dk_busy &= ~(1<<ui->ui_dk);
667: if (st == M_ST_OFFLN || st == M_ST_AVLBL) {
668: ui->ui_flags = 0; /* mark unit offline */
669: /*
670: * Link the buffer onto the front of the drive queue
671: */
672: if ((bp->av_forw = dp->b_actf) == 0)
673: dp->b_actl = bp;
674: dp->b_actf = bp;
675: /*
676: * Link the drive onto the controller queue
677: */
678: if (dp->b_active == 0) {
679: dp->b_forw = NULL;
680: if (um->um_tab.b_actf == NULL)
681: um->um_tab.b_actf = dp;
682: else
683: um->um_tab.b_actl->b_forw = dp;
684: um->um_tab.b_actl = dp;
685: dp->b_active = 1;
686: }
687: #if defined(VAX750)
688: if (cpu == VAX750 && um->um_ubinfo == 0)
689: um->um_ubinfo =
690: uballoc(um->um_ubanum, (caddr_t)0, 0,
691: UBA_NEEDBDP);
692: #endif
693: return;
694: }
695: if (st != M_ST_SUCC) {
696: harderr(bp, "ra");
697: printf("status %o\n", mp->mscp_status);
698: bp->b_flags |= B_ERROR;
699: }
700: bp->b_resid = bp->b_bcount - mp->mscp_bytecnt;
701: iodone(bp);
702: break;
703:
704: case M_OP_GTUNT|M_OP_END:
705: break;
706:
707: default:
708: printf("uda: unknown packet\n");
709: }
710: }
711:
712:
713: /*
714: * Process an error log message
715: *
716: * For now, just log the error on the console.
717: * Only minimal decoding is done, only "useful"
718: * information is printed. Eventually should
719: * send message to an error logger.
720: */
721: uderror(um, mp)
722: register struct uba_ctlr *um;
723: register struct mslg *mp;
724: {
725: printf("uda%d: %s error, ", um->um_ctlr,
726: mp->mslg_flags&M_LF_SUCC ? "soft" : "hard");
727: switch (mp->mslg_format) {
728: case M_FM_CNTERR:
729: printf("controller error, event 0%o\n", mp->mslg_event);
730: break;
731:
732: case M_FM_BUSADDR:
733: printf("host memory access error, event 0%o, addr 0%o\n",
734: mp->mslg_event, mp->mslg_busaddr);
735: break;
736:
737: case M_FM_DISKTRN:
738: printf("disk transfer error, unit %d, grp 0x%x, hdr 0x%x\n",
739: mp->mslg_unit, mp->mslg_group, mp->mslg_hdr);
740: break;
741:
742: case M_FM_SDI:
743: printf("SDI error, unit %d, event 0%o, hdr 0x%x\n",
744: mp->mslg_unit, mp->mslg_event, mp->mslg_hdr);
745: break;
746:
747: case M_FM_SMLDSK:
748: printf("small disk error, unit %d, event 0%o, cyl %d\n",
749: mp->mslg_unit, mp->mslg_event, mp->mslg_sdecyl);
750: break;
751:
752: default:
753: printf("unknown error, unit %d, format 0%o, event 0%o\n",
754: mp->mslg_unit, mp->mslg_format, mp->mslg_event);
755: }
756:
757: if (udaerror) {
758: register long *p = (long *)mp;
759: register int i;
760:
761: for (i = 0; i < mp->mslg_header.uda_msglen; i += sizeof(*p))
762: printf("%x ", *p++);
763: printf("\n");
764: }
765: }
766:
767:
768: /*
769: * Find an unused command packet
770: */
771: struct mscp *
772: udgetcp(um)
773: struct uba_ctlr *um;
774: {
775: register struct mscp *mp;
776: register struct udaca *cp;
777: register struct uda_softc *sc;
778: register int i;
779:
780: cp = &uda[um->um_ctlr].uda_ca;
781: sc = &uda_softc[um->um_ctlr];
782: i = sc->sc_lastcmd;
783: if ((cp->ca_cmddsc[i] & (UDA_OWN|UDA_INT)) == UDA_INT) {
784: cp->ca_cmddsc[i] &= ~UDA_INT;
785: mp = &uda[um->um_ctlr].uda_cmd[i];
786: mp->mscp_unit = mp->mscp_modifier = 0;
787: mp->mscp_opcode = mp->mscp_flags = 0;
788: mp->mscp_bytecnt = mp->mscp_buffer = 0;
789: mp->mscp_errlgfl = mp->mscp_copyspd = 0;
790: sc->sc_lastcmd = (i + 1) % NCMD;
791: return(mp);
792: }
793: return(NULL);
794: }
795:
796: udread(dev, uio)
797: dev_t dev;
798: struct uio *uio;
799: {
800: register int unit = minor(dev) >> 3;
801:
802: if (unit >= NRA)
803: return (ENXIO);
804: return (physio(udstrategy, &rudbuf[unit], dev, B_READ, minphys, uio));
805: }
806:
807: udwrite(dev, uio)
808: dev_t dev;
809: struct uio *uio;
810: {
811: register int unit = minor(dev) >> 3;
812:
813: if (unit >= NRA)
814: return (ENXIO);
815: return (physio(udstrategy, &rudbuf[unit], dev, B_WRITE, minphys, uio));
816: }
817:
818: udreset(uban)
819: int uban;
820: {
821: register struct uba_ctlr *um;
822: register struct uba_device *ui;
823: register struct buf *bp, *dp;
824: register int unit;
825: struct buf *nbp;
826: int d;
827:
828: for (d = 0; d < NUDA; d++) {
829: if ((um = udminfo[d]) == 0 || um->um_ubanum != uban ||
830: um->um_alive == 0)
831: continue;
832: printf(" uda%d", d);
833: um->um_tab.b_active = 0;
834: um->um_tab.b_actf = um->um_tab.b_actl = 0;
835: uda_softc[d].sc_state = S_IDLE;
836: for (unit = 0; unit < NRA; unit++) {
837: if ((ui = uddinfo[unit]) == 0)
838: continue;
839: if (ui->ui_alive == 0 || ui->ui_mi != um)
840: continue;
841: udutab[unit].b_active = 0;
842: udutab[unit].b_qsize = 0;
843: }
844: for (bp = udwtab[d].av_forw; bp != &udwtab[d]; bp = nbp) {
845: nbp = bp->av_forw;
846: bp->b_ubinfo = 0;
847: /*
848: * Link the buffer onto the drive queue
849: */
850: dp = &udutab[dkunit(bp)];
851: if (dp->b_actf == 0)
852: dp->b_actf = bp;
853: else
854: dp->b_actl->av_forw = bp;
855: dp->b_actl = bp;
856: bp->av_forw = 0;
857: /*
858: * Link the drive onto the controller queue
859: */
860: if (dp->b_active == 0) {
861: dp->b_forw = NULL;
862: if (um->um_tab.b_actf == NULL)
863: um->um_tab.b_actf = dp;
864: else
865: um->um_tab.b_actl->b_forw = dp;
866: um->um_tab.b_actl = dp;
867: dp->b_active = 1;
868: }
869: }
870: udinit(d);
871: }
872: }
873:
874: uddump()
875: {
876: return(ENXIO);
877: }
878:
879: udsize(dev)
880: dev_t dev;
881: {
882: int unit = minor(dev) >> 3;
883: struct uba_device *ui;
884:
885: if (unit >= NRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0)
886: return (-1);
887: return (ra_sizes[minor(dev) & 07].nblocks); /* XXX */
888: }
889: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.