matt@oddjob.UChicago.UUCP (Matt Crawford) (06/22/84)
Lately the system keeps crashing after several days of uptime. The console messages are always like this: uba0: too many zero vectors uba0: reset dz0 dz1 dz2 uda0 ec0 uba0: uba error sr=1<UBSSYNTO> fmer=0 fubar=0 uba0: uba error sr=10<IVMR> fmer=40 fubar=772150 uba0: uba error sr=1<UBSSYNTO> fmer=0 fubar=0 ... ( 7 more repetitions of that line, and then ) ... ERROR LIMIT uba0: reset dz0 dz1 dz2 uda0 and it crashes. Our load average is usually high ( 7.00 to 25.00 or so ). We have one UBA, which holds 3 dz11's, a 3COM ethernet board, an RX211 floppy disk controller (seldom used), and a UDA50 with 2 RA81's Is this a known bug? We don't get a core dump, so I don't know where to begin looking. Oh yeah, it's a 780. ___________________________________________________________ Matt University ARPA: crawford@anl-mcs.arpa Crawford of Chicago UUCP: ihnp4!oddjob!matt
chris@umcp-cs.UUCP (06/23/84)
uda.c (the UDA50 driver) needs to clear the sc_mapped field in uda_softc[d] anywhere within udreset()'s ``for'' loop that runs over the NUDA UDA50s. (This doesn't explain why you're getting all the zero vectors though.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland
dave@RIACS.ARPA (06/25/84)
From: "David L. Gehrt" <dave@RIACS.ARPA> I can't help you with the "why" but if you use the attached driver for your uda50, you will have a dump, the dump code exists here. Also, as a side light, you will get better performance on your ra81's. Oh, beware, our ra_sizes is decidedly non standard. dave /sys/vaxuba/uda.c: ______________________________________________________________________ /*--------------------------------------------------------------------------- * $Header: /usr/src/sys/vaxuba/RCS/uda.c,v 2.1 84/03/05 17:42:06 root Exp $ * * $Log: uda.c,v $ * Revision 2.1 84/03/05 17:42:06 root * Incorporates Berkeley bug fix sys/67. This repairs the problem caused * if there is no unit zero. STCON end messages are not processed because * the cntrlr interrupts as unit zero, and the modified test returns before * the STCON end message is processed. * * Revision 2.0 84/03/01 16:35:35 root * This version fixes the M_OP_GTUNT glut in the uda 50 command * ring. * * *--------------------------------------------------------------------------- */ /* uda.c 6.1 83/07/29 */ #include "ra.h" #if NUDA > 0 /* * UDA50/RAxx disk device driver * * Restrictions: * Unit numbers must be less than 8. * * TO DO: * write the bad block forwarding code */ #define UDEBUG #include "../machine/pte.h" #include "../h/param.h" #include "../h/systm.h" #include "../h/buf.h" #include "../h/conf.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/map.h" #include "../h/vm.h" #include "../h/dk.h" #include "../h/cmap.h" #include "../h/uio.h" #include "../vax/cpu.h" #include "../vaxuba/ubareg.h" #include "../vaxuba/ubavar.h" #ifdef UDEBUG #include "../h/kernel.h" #endif #define NRSPL2 3 #define NCMDL2 3 /* log2 number of command packets */ #define NRSP (1<<NRSPL2) #define NCMD (1<<NCMDL2) #include "../vaxuba/udareg.h" #include "../vax/mscp.h" struct uda_softc { short sc_state; /* state of controller */ short sc_mapped; /* Unibus map allocated for uda struct? */ int sc_ubainfo; /* Unibus mapping info */ struct uda *sc_uda; /* Unibus address of uda struct */ int sc_ivec; /* interrupt vector address */ short sc_credits; /* transfer credits */ short sc_lastcmd; /* pointer into command ring */ short sc_lastrsp; /* pointer into response ring */ struct mscp sc_GTUNT[NRA]; /* reply to "M_OP_GTUNT" operation */ } uda_softc[NUDA]; struct uda_softcmd { long cmd_cmdref; struct timeval cmd_time; short cmd_unit; }uda_softcmdt[NCMD],uda_softrspt[NRSP]; /* * Controller states */ #define S_IDLE 0 /* hasn't been initialized */ #define S_STEP1 1 /* doing step 1 init */ #define S_STEP2 2 /* doing step 2 init */ #define S_STEP3 3 /* doing step 3 init */ #define S_SCHAR 4 /* doing "set controller characteristics" */ #define S_RUN 5 /* running */ struct uda { struct udaca uda_ca; /* communications area */ struct mscp uda_rsp[NRSP]; /* response packets */ struct mscp uda_cmd[NCMD]; /* command packets */ } uda[NUDA]; /* THIS SHOULD BE READ OFF THE PACK, PER DRIVE */ /* ** These were changed from the original so that, other than A, they are ** an integer number of cylinders and start on a cylinder boundary */ struct size { daddr_t nblocks; daddr_t blkoff; } ra_sizes[8] ={ 15884, 0, /* A 0-15883 cyl 0-XXX (22.24) */ 33440, 15884, /* B 15884-49979 cyl XXX- 69 (46.83) */ 891072, 0, /* C 0-891071 cyl 0-1247 (1247) */ 16422, 342006, /* D 342006-358427 cyl 479-501 (23) */ 307734, 358428, /* E 358428-666161 cyl 502-932 (431) */ 224910, 666162, /* F 666162-891071 cyl 933-1247 (315) */ 549066, 342006, /* G 342006-891071 cyl 479-1247 (769) */ 292026, 49980, /* H 49980-342005 cyl 70-478 (409) */ }; /* END OF STUFF WHICH SHOULD BE READ IN PER DISK */ int udaerror = 0; /* causes hex dump of packets */ int udadebug = 0; int udacmdtmo = 0; #define printd if (udadebug) printf daddr_t radsize[NRA]; /* disk size, from ONLINE end packet */ int udprobe(), udslave(), udattach(), udintr(); struct mscp *udgetcp(); struct uba_ctlr *udminfo[NUDA]; struct uba_device *uddinfo[NRA]; struct uba_device *udip[NUDA][8]; /* 8 == max number of drives */ u_short udstd[] = { 0772150, 0772550, 0777550, 0 }; struct uba_driver udadriver = { udprobe, udslave, udattach, 0, udstd, "ra", uddinfo, "uda", udminfo, 0 }; struct buf rudbuf[NRA]; struct buf udutab[NRA]; struct buf udwtab[NUDA]; /* I/O wait queue, per controller */ #define b_qsize b_resid /* queue size per drive, in udutab */ #define b_ubinfo b_resid /* Unibus mapping info, per buffer */ udprobe(reg, ctlr) caddr_t reg; int ctlr; { register int br, cvec; register struct uda_softc *sc = &uda_softc[ctlr]; #ifdef lint br = 0; cvec = br; br = cvec; reg = reg; udreset(0); udintr(0); #endif /* SHOULD CHECK THAT IT REALLY IS A UDA */ br = 0x15; cvec = sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4); return(sizeof (struct udadevice)); } udslave(ui, reg) struct uba_device *ui; caddr_t reg; { /* * TOO HARD TO FIND OUT IF DISK IS THERE UNTIL * INITIALIZED. WE'LL FIND OUT WHEN WE FIRST * TRY TO ACCESS IT. */ #ifdef lint ui = ui; reg = reg; #endif return(1); } udattach(ui) register struct uba_device *ui; { if (ui->ui_dk >= 0) dk_mspw[ui->ui_dk] = 1.0 / (60 * 31 * 256); /* approx */ ui->ui_flags = 0; udip[ui->ui_ctlr][ui->ui_slave] = ui; radsize[ui->ui_unit] = (daddr_t)0xffffff; /* max possible size */ } /* * Open a UDA. Initialize the device and * set the unit online. */ udopen(dev, flag) dev_t dev; int flag; { register int unit; register struct uba_device *ui; register struct uda_softc *sc; int s; #ifdef lint flag = flag; #endif unit = minor(dev) >> 3; if (unit >= NRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0) return (ENXIO); sc = &uda_softc[ui->ui_ctlr]; s = spl5(); if (sc->sc_state != S_RUN) { if (sc->sc_state == S_IDLE) udinit(ui->ui_ctlr); /* wait for initialization to complete */ sleep((caddr_t)ui->ui_mi, 0); if (sc->sc_state != S_RUN) { splx(s); /* oops */ return (EIO); } } splx(s); /* SHOULD PROBABLY FORCE AN ONLINE ATTEMPT TO SEE IF DISK IS REALLY THERE */ return (0); } /* * Initialize a UDA. Set up UBA mapping registers, * initialize data structures, and start hardware * initialization sequence. */ udinit(d) int d; { register struct uda_softc *sc; register struct uda *ud; struct udadevice *udaddr; struct uba_ctlr *um; sc = &uda_softc[d]; um = udminfo[d]; um->um_tab.b_active++; ud = &uda[d]; udaddr = (struct udadevice *)um->um_addr; if (sc->sc_mapped == 0) { /* * Map the communications area and command * and response packets into Unibus address * space. */ sc->sc_ubainfo = uballoc(um->um_ubanum, (caddr_t)ud, sizeof (struct uda), 0); sc->sc_uda = (struct uda *)(sc->sc_ubainfo & 0x3ffff); sc->sc_mapped = 1; } /* * Start the hardware initialization sequence. */ udaddr->udaip = 0; /* start initialization */ while ((udaddr->udasa & UDA_STEP1) == 0) ; udaddr->udasa = UDA_ERR|(NCMDL2<<11)|(NRSPL2<<8)|UDA_IE|(sc->sc_ivec/4); /* * Initialization continues in interrupt routine. */ sc->sc_state = S_STEP1; sc->sc_credits = 0; } udstrategy(bp) register struct buf *bp; { register struct uba_device *ui; register struct uba_ctlr *um; register struct buf *dp; register int unit; int xunit = minor(bp->b_dev) & 07; daddr_t sz, maxsz; int s; sz = (bp->b_bcount+511) >> 9; unit = dkunit(bp); if (unit >= NRA) goto bad; ui = uddinfo[unit]; um = ui->ui_mi; if (ui == 0 || ui->ui_alive == 0) goto bad; if ((maxsz = ra_sizes[xunit].nblocks) < 0) maxsz = radsize[unit] - ra_sizes[xunit].blkoff; if (bp->b_blkno < 0 || bp->b_blkno+sz > maxsz || ra_sizes[xunit].blkoff >= radsize[unit]) goto bad; s = spl5(); /* * Link the buffer onto the drive queue */ dp = &udutab[ui->ui_unit]; if (dp->b_actf == 0) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; bp->av_forw = 0; /* * Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (um->um_tab.b_actf == NULL) um->um_tab.b_actf = dp; else um->um_tab.b_actl->b_forw = dp; um->um_tab.b_actl = dp; dp->b_active = 1; } if (um->um_tab.b_active == 0) { #if defined(VAX750) if (cpu == VAX_750 && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) { if (um->um_ubinfo != 0) printf("udastrat: ubinfo 0x%x\n",um->um_ubinfo); else um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); } #endif (void) udstart(um); } splx(s); return; bad: bp->b_flags |= B_ERROR; iodone(bp); return; } udstart(um) register struct uba_ctlr *um; { register struct buf *bp, *dp; register struct mscp *mp; register struct uda_softc *sc; register struct uba_device *ui; struct udadevice *udaddr; int i; sc = &uda_softc[um->um_ctlr]; loop: if ((dp = um->um_tab.b_actf) == NULL) { /* * Release uneeded UBA resources and return */ um->um_tab.b_active = 0; return (0); } if ((bp = dp->b_actf) == NULL) { /* * No more requests for this drive, remove * from controller queue and look at next drive. * We know we're at the head of the controller queue. */ dp->b_active = 0; um->um_tab.b_actf = dp->b_forw; goto loop; } um->um_tab.b_active++; udaddr = (struct udadevice *)um->um_addr; if ((udaddr->udasa&UDA_ERR) || sc->sc_state != S_RUN) { harderr(bp, "ra"); printf("udasa %o, state %d\n", udaddr->udasa&0xffff, sc->sc_state); udinit(um->um_ctlr); /* SHOULD REQUEUE OUTSTANDING REQUESTS, LIKE UDRESET */ return (0); } ui = uddinfo[dkunit(bp)]; /* * If no credits, can't issue any commands * until some outstanding commands complete. */ if (sc->sc_credits < 2) return (0); sc->sc_credits--; /* committed to issuing a command */ if (ui->ui_flags == 0) { /* not online */ if ((mp = udgetcp(um)) == NULL) return (0); mp->mscp_opcode = M_OP_ONLIN; mp->mscp_unit = ui->ui_slave; dp->b_active = 2; um->um_tab.b_actf = dp->b_forw; /* remove from controller q */ printd("uda: bring unit %d online\n", ui->ui_slave); *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; i = udaddr->udaip; goto loop; } switch (cpu) { case VAX_780: i = UBA_NEEDBDP|UBA_CANTWAIT; break; case VAX_750: i = um->um_ubinfo|UBA_HAVEBDP|UBA_CANTWAIT; break; case VAX_730: i = UBA_CANTWAIT; break; } if ((i = ubasetup(um->um_ubanum, bp, i)) == 0) { if (dp->b_qsize > 0) { /* * We are getting buried in GTUNT commands so we ain't * gonna issue unless diaster arrives. */ sc->sc_credits++; return; } if ((mp = udgetcp(um)) == NULL) return (0); mp->mscp_opcode = M_OP_GTUNT; mp->mscp_unit = ui->ui_slave; *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; i = udaddr->udaip; /* initiate polling */ return(1); /* wait for interrupt */ } if ((mp = udgetcp(um)) == NULL) { sc->sc_credits++; ubarelse(um->um_ubanum, &i); return (0); } mp->mscp_cmdref = (long)bp; /* pointer to get back */ mp->mscp_opcode = bp->b_flags&B_READ ? M_OP_READ : M_OP_WRITE; mp->mscp_unit = ui->ui_slave; mp->mscp_lbn = bp->b_blkno + ra_sizes[minor(bp->b_dev)&7].blkoff; mp->mscp_bytecnt = bp->b_bcount; mp->mscp_buffer = (i & 0x3ffff) | (((i>>28)&0xf)<<24); #if defined(VAX750) if (cpu == VAX_750) i &= 0xfffffff; /* mask off bdp */ #endif bp->b_ubinfo = i; /* save mapping info */ *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; i = udaddr->udaip; /* initiate polling */ if (ui->ui_dk >= 0) { dk_busy |= 1<<ui->ui_dk; dk_xfer[ui->ui_dk]++; dk_wds[ui->ui_dk] += bp->b_bcount>>6; } dp->b_qsize++; /* * Move drive to the end of the controller queue */ if (dp->b_forw != NULL) { um->um_tab.b_actf = dp->b_forw; um->um_tab.b_actl->b_forw = dp; um->um_tab.b_actl = dp; dp->b_forw = NULL; } /* * Move buffer to I/O wait queue */ dp->b_actf = bp->av_forw; dp = &udwtab[um->um_ctlr]; bp->av_forw = dp; bp->av_back = dp->av_back; dp->av_back->av_forw = bp; dp->av_back = bp; goto loop; } /* * UDA interrupt routine. */ udintr(d) int d; { register struct uba_ctlr *um = udminfo[d]; register struct udadevice *udaddr = (struct udadevice *)um->um_addr; struct buf *bp; register int i,j; register struct uda_softc *sc = &uda_softc[d]; register struct uda *ud = &uda[d]; struct uda *uud; struct mscp *mp; printd("udintr: state %d, udasa %o\n", sc->sc_state, udaddr->udasa); switch (sc->sc_state) { case S_IDLE: printf("uda%d: random interrupt ignored\n", d); return; case S_STEP1: #define STEP1MASK 0174377 #define STEP1GOOD (UDA_STEP2|UDA_IE|(NCMDL2<<3)|NRSPL2) if ((udaddr->udasa&STEP1MASK) != STEP1GOOD) { sc->sc_state = S_IDLE; wakeup((caddr_t)um); return; } udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)| (cpu == VAX_780 ? UDA_PI : 0); sc->sc_state = S_STEP2; return; case S_STEP2: #define STEP2MASK 0174377 #define STEP2GOOD (UDA_STEP3|UDA_IE|(sc->sc_ivec/4)) if ((udaddr->udasa&STEP2MASK) != STEP2GOOD) { sc->sc_state = S_IDLE; wakeup((caddr_t)um); return; } udaddr->udasa = ((int)&sc->sc_uda->uda_ca.ca_ringbase)>>16; sc->sc_state = S_STEP3; return; case S_STEP3: #define STEP3MASK 0174000 #define STEP3GOOD UDA_STEP4 if ((udaddr->udasa&STEP3MASK) != STEP3GOOD) { sc->sc_state = S_IDLE; wakeup((caddr_t)um); return; } udaddr->udasa = UDA_GO; sc->sc_state = S_SCHAR; /* * Initialize the data structures. */ uud = sc->sc_uda; for (i = 0; i < NRSP; i++) { #ifdef UDEBUG register struct uda_softcmd *rsp; rsp = &uda_softrspt[i]; rsp->cmd_cmdref = (long)&uud->uda_rsp[i].mscp_cmdref; rsp->cmd_time.tv_sec = rsp->cmd_time.tv_usec = 0; #endif ud->uda_ca.ca_rspdsc[i] = UDA_OWN|UDA_INT| (long)&uud->uda_rsp[i].mscp_cmdref; ud->uda_rsp[i].mscp_dscptr = &ud->uda_ca.ca_rspdsc[i]; ud->uda_rsp[i].mscp_header.uda_msglen = sizeof(struct mscp); } for (i = 0; i < NCMD; i++) { #ifdef UDEBUG register struct uda_softcmd *cmp; cmp = &uda_softcmdt[i]; cmp->cmd_cmdref = (long)&uud->uda_cmd[i].mscp_cmdref; cmp->cmd_time.tv_sec = cmp->cmd_time.tv_usec = 0; #endif ud->uda_ca.ca_cmddsc[i] = UDA_INT| (long)&uud->uda_cmd[i].mscp_cmdref; ud->uda_cmd[i].mscp_dscptr = &ud->uda_ca.ca_cmddsc[i]; ud->uda_cmd[i].mscp_header.uda_msglen = sizeof (struct mscp); } bp = &udwtab[d]; bp->av_forw = bp->av_back = bp; sc->sc_lastcmd = 0; sc->sc_lastrsp = 0; if ((mp = udgetcp(um)) == NULL) { sc->sc_state = S_IDLE; wakeup((caddr_t)um); return; } mp->mscp_opcode = M_OP_STCON; mp->mscp_cntflgs = M_CF_ATTN|M_CF_MISC|M_CF_THIS; *((long *)mp->mscp_dscptr) |= UDA_OWN|UDA_INT; i = udaddr->udaip; /* initiate polling */ return; case S_SCHAR: case S_RUN: break; default: printf("uda%d: interrupt in unknown state %d ignored\n", d, sc->sc_state); return; } if (udaddr->udasa&UDA_ERR) { printf("uda%d: fatal error (%o)\n", d, udaddr->udasa&0xffff); udaddr->udaip = 0; wakeup((caddr_t)um); } /* * Check for a buffer purge request. */ if (ud->uda_ca.ca_bdp) { /* * THIS IS A KLUDGE. * Maybe we should change the entire * UBA interface structure. */ int s = spl7(); i = um->um_ubinfo; printd("uda: purge bdp %d\n", ud->uda_ca.ca_bdp); um->um_ubinfo = ud->uda_ca.ca_bdp<<28; ubapurge(um); um->um_ubinfo = i; (void) splx(s); ud->uda_ca.ca_bdp = 0; udaddr->udasa = 0; /* signal purge complete */ } /* * Check for response ring transition. */ if (ud->uda_ca.ca_rspint) { int count; ud->uda_ca.ca_rspint = 0; for (i = sc->sc_lastrsp;; i++) { i %= NRSP; if (ud->uda_ca.ca_rspdsc[i]&UDA_OWN) break; udrsp(um, ud, sc, i); ud->uda_ca.ca_rspdsc[i] |= UDA_OWN; count++; } sc->sc_lastrsp = i; printd("uda: %d response packets processed\n",count); } /* * Check for command ring transition. */ if (ud->uda_ca.ca_cmdint) { printd("uda: command ring transition\n"); ud->uda_ca.ca_cmdint = 0; } (void) udstart(um); } /* * Process a response packet */ udrsp(um, ud, sc, i) register struct uba_ctlr *um; register struct uda *ud; register struct uda_softc *sc; int i; { register struct mscp *mp; struct uba_device *ui; struct buf *dp, *bp; int st; register long *p; register int k; #ifdef UDEBUG register struct uda_softcmd *rs; #endif UDEBUG mp = &ud->uda_rsp[i]; #ifdef UDEBUG rs = &uda_softrspt[i]; rs->cmd_time.tv_sec = time.tv_sec; rs->cmd_time.tv_usec = time.tv_usec; rs->cmd_cmdref = mp->mscp_cmdref; #endif UDEBUG mp->mscp_header.uda_msglen = sizeof (struct mscp); sc->sc_credits += mp->mscp_header.uda_credits & 0xf; if ((mp->mscp_header.uda_credits & 0xf0) > 0x10) return; /* * If it's an error log message (datagram), * pass it on for more extensive processing. */ if ((mp->mscp_header.uda_credits & 0xf0) == 0x10) { uderror(um, (struct mslg *)mp); return; } if (mp->mscp_unit >= 8) return; if ((ui = udip[um->um_ctlr][mp->mscp_unit]) == 0 && ((mp->mscp_opcode&0xff) != (M_OP_STCON|M_OP_END))) return; st = mp->mscp_status&M_ST_MASK; switch (mp->mscp_opcode) { case M_OP_STCON|M_OP_END: printf("STCON: status=0x%x endcode=0x%x cntflgs=0x%x vers=0x%x tmout=%d\n", mp->mscp_modifier,mp->mscp_flags,mp->mscp_opcode, mp->mscp_cntflgs,mp->mscp_version,mp->mscp_hsttmo); if (st == M_ST_SUCC) sc->sc_state = S_RUN; else sc->sc_state = S_IDLE; um->um_tab.b_active = 0; wakeup((caddr_t)um); break; case M_OP_ONLIN|M_OP_END: /* * Link the drive onto the controller queue */ printf("UDA ONLIN: unit %d\n",mp->mscp_unit); dp = &udutab[ui->ui_unit]; dp->b_forw = NULL; if (um->um_tab.b_actf == NULL) um->um_tab.b_actf = dp; else um->um_tab.b_actl->b_forw = dp; um->um_tab.b_actl = dp; if (st == M_ST_SUCC) { ui->ui_flags = 1; /* mark it online */ radsize[ui->ui_unit] = (daddr_t)mp->mscp_untsize; printd("uda: unit %d online\n", mp->mscp_unit); #ifdef notdef printf("uda%d: online, size=%d\n", mp->mscp_unit, (daddr_t)mp->mscp_untsize); #endif } else { harderr(dp->b_actf, "ra"); printf("OFFLINE\n"); while (bp = dp->b_actf) { dp->b_actf = bp->av_forw; bp->b_flags |= B_ERROR; iodone(bp); } } dp->b_active = 1; break; case M_OP_AVATN: printd("uda: unit %d attention\n", mp->mscp_unit); ui->ui_flags = 0; /* it went offline and we didn't notice */ break; case M_OP_READ|M_OP_END: case M_OP_WRITE|M_OP_END: bp = (struct buf *)mp->mscp_cmdref; ubarelse(um->um_ubanum, (int *)&bp->b_ubinfo); /* * Unlink buffer from I/O wait queue. */ bp->av_back->av_forw = bp->av_forw; bp->av_forw->av_back = bp->av_back; #if defined(VAX750) if (cpu == VAX_750 && udwtab[um->um_ctlr].av_forw == &udwtab[um->um_ctlr]) { if (um->um_ubinfo == 0) printf("udintr: um_ubinfo == 0\n"); else ubarelse(um->um_ubanum, &um->um_ubinfo); } #endif if (mp->mscp_flags) { printf("ra%d: XFER EF: ",mp->mscp_unit); if ( mp->mscp_flags & M_EF_BBLKR ) { printf("bad block report: %d%s", mp->mscp_lbn, mp->mscp_flags & M_EF_BBLKU ? " + others " : " "); } if ( mp->mscp_flags & M_EF_SEREX ) printf("serious exception reported"); printf("%s", mp->mscp_flags & M_EF_ERLOG ? "logged\n" : "\n"); } dp = &udutab[ui->ui_unit]; dp->b_qsize--; if (ui->ui_dk >= 0) if (dp->b_qsize == 0) dk_busy &= ~(1<<ui->ui_dk); if (st == M_ST_OFFLN || st == M_ST_AVLBL) { ui->ui_flags = 0; /* mark unit offline */ /* * Link the buffer onto the front of the drive queue */ if ((bp->av_forw = dp->b_actf) == 0) dp->b_actl = bp; dp->b_actf = bp; /* * Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (um->um_tab.b_actf == NULL) um->um_tab.b_actf = dp; else um->um_tab.b_actl->b_forw = dp; um->um_tab.b_actl = dp; dp->b_active = 1; } #if defined(VAX750) if (cpu == VAX750 && um->um_ubinfo == 0) um->um_ubinfo = uballoc(um->um_ubanum, (caddr_t)0, 0, UBA_NEEDBDP); #endif return; } if (st != M_ST_SUCC) { harderr(bp, "ra"); printf("xfer status code 0%o subcode 0%o\n", mp->mscp_status&M_ST_MASK, (mp->mscp_status >> 5)); bp->b_flags |= B_ERROR; } bp->b_resid = bp->b_bcount - mp->mscp_bytecnt; iodone(bp); break; case M_OP_GTUNT|M_OP_END: printd("UDA GTUNT: unit=%d op=0x%x flgs=0x%x stat=0x%x unit flgs=0x%0 \n\tsizes: trk=%d grp=%d cyl=%d RCT=%d RCT #=%d RBN/trk=%d\n", mp->mscp_unit,mp->mscp_opcode,mp->mscp_flags,mp->mscp_modifier, mp->mscp_unitflgs,mp->mscp_track,mp->mscp_group, mp->mscp_cylinder,mp->mscp_rctsize,mp->mscp_rctcpys, mp->mscp_rbns); sc -> sc_GTUNT[mp->mscp_unit] = *mp; break; default: p = (long *)mp; printf("uda: unknown packet\n"); for (k = 0; k < mp->mscp_header.uda_msglen; k += sizeof(*p)) printf("%08x ", *p++); printf("\n"); } } /* * Process an error log message * * For now, just log the error on the console. * Only minimal decoding is done, only "useful" * information is printed. Eventually should * send message to an error logger. */ uderror(um, mp) register struct uba_ctlr *um; register struct mslg *mp; { printf("uda%d: %s error, ", um->um_ctlr, mp->mslg_flags & ( M_LF_CONT | M_LF_SUCC ) ? "soft" : "hard"); switch (mp->mslg_format) { case M_FM_CNTERR: printf("controller error, event 0%o", mp->mslg_event); break; case M_FM_BUSADDR: printf("host memory access error, event 0%o, addr 0%o", mp->mslg_event, mp->mslg_busaddr); break; case M_FM_DISKTRN: printf("disk transfer error, unit %d, grp 0x%x, hdr 0x%x", mp->mslg_unit, mp->mslg_group, mp->mslg_hdr); break; case M_FM_SDI: printf("SDI error, unit %d, event 0%o, hdr 0x%x", mp->mslg_unit, mp->mslg_event, mp->mslg_hdr); break; case M_FM_SMLDSK: printf("small disk error, unit %d, event 0%o, cyl %d", mp->mslg_unit, mp->mslg_event, mp->mslg_sdecyl); break; default: printf("unknown error, unit %d, format 0%o, event 0%o\n", mp->mslg_unit, mp->mslg_format, mp->mslg_event); break; } printf("%s",mp->mslg_flags & M_LF_CONT ? " - continuing\n" : "\n"); if (udaerror) { register long *p = (long *)mp; register int i; for (i = 0; i < mp->mslg_header.uda_msglen; i += sizeof(*p)) printf("%08x ", *p++); printf("\n"); } } /* * Find an unused command packet */ struct mscp * udgetcp(um) struct uba_ctlr *um; { register struct mscp *mp; register struct udaca *cp; register struct uda_softc *sc; register int i; cp = &uda[um->um_ctlr].uda_ca; sc = &uda_softc[um->um_ctlr]; i = sc->sc_lastcmd; if ((cp->ca_cmddsc[i] & (UDA_OWN|UDA_INT)) == UDA_INT) { cp->ca_cmddsc[i] &= ~UDA_INT; mp = &uda[um->um_ctlr].uda_cmd[i]; mp->mscp_unit = mp->mscp_modifier = 0; mp->mscp_opcode = mp->mscp_flags = 0; mp->mscp_bytecnt = mp->mscp_buffer = 0; mp->mscp_errlgfl = mp->mscp_copyspd = 0; sc->sc_lastcmd = (i + 1) % NCMD; return(mp); } return(NULL); } udread(dev, uio) dev_t dev; struct uio *uio; { register int unit = minor(dev) >> 3; if (unit >= NRA) return (ENXIO); return (physio(udstrategy, &rudbuf[unit], dev, B_READ, minphys, uio)); } udwrite(dev, uio) dev_t dev; struct uio *uio; { register int unit = minor(dev) >> 3; if (unit >= NRA) return (ENXIO); return (physio(udstrategy, &rudbuf[unit], dev, B_WRITE, minphys, uio)); } udreset(uban) int uban; { register struct uba_ctlr *um; register struct uba_device *ui; register struct buf *bp, *dp; register int unit; struct buf *nbp; int d; for (d = 0; d < NUDA; d++) { if ((um = udminfo[d]) == 0 || um->um_ubanum != uban || um->um_alive == 0) continue; printf(" uda%d", d); um->um_tab.b_active = 0; um->um_tab.b_actf = um->um_tab.b_actl = 0; uda_softc[d].sc_state = S_IDLE; uda_softc[d].sc_mapped = 0; for (unit = 0; unit < NRA; unit++) { if ((ui = uddinfo[unit]) == 0) continue; if (ui->ui_alive == 0 || ui->ui_mi != um) continue; udutab[unit].b_active = 0; udutab[unit].b_qsize = 0; } for (bp = udwtab[d].av_forw; bp != &udwtab[d]; bp = nbp) { nbp = bp->av_forw; bp->b_ubinfo = 0; /* * Link the buffer onto the drive queue */ dp = &udutab[dkunit(bp)]; if (dp->b_actf == 0) dp->b_actf = bp; else dp->b_actl->av_forw = bp; dp->b_actl = bp; bp->av_forw = 0; /* * Link the drive onto the controller queue */ if (dp->b_active == 0) { dp->b_forw = NULL; if (um->um_tab.b_actf == NULL) um->um_tab.b_actf = dp; else um->um_tab.b_actl->b_forw = dp; um->um_tab.b_actl = dp; dp->b_active = 1; } } udinit(d); } } /* ** RA81 dump code ** ** The kludge is that I redefine udaca with NRSP and NCMD set to one, ** this made it possible to lift almost everything out of the stand-alone ** driver. (Bob Brown) */ #define DBSIZE 20 struct sa_udaca { short ca_xxx1; /* unused */ char ca_xxx2; /* unused */ char ca_bdp; /* BDP to purge */ short ca_cmdint; /* command queue transition interrupt flag */ short ca_rspint; /* response queue transition interrupt flag */ long ca_rspdsc[1]; /* response descriptors */ long ca_cmddsc[1]; /* command descriptors */ }; struct sa_uda { struct sa_udaca uda_ca; /* communications area */ struct mscp uda_rsp[1]; /* response packets */ struct mscp uda_cmd[1]; /* command packets */ } sa_uda[NUDA]; uddump(dev) dev_t dev; { int pages, blk, unit, offset, i; char *start; struct uba_regs *uba; struct uba_device *ui; struct udadevice *udaddr; struct sa_uda *comarea, *udaptr; struct pte *ubapte; struct mscp *udcmd(); /* ** Compute the base address of the UBA and initialize it. */ unit = minor(dev) >> 3; if (unit >= NUDA) return ENXIO; #define phys(cast, addr) ((cast)((int)addr & 0x7fffffff)) ui = phys(struct uba_device *, uddinfo[unit]); if (ui->ui_alive == 0) return ENXIO; uba = phys(struct uba_hd *, ui->ui_hd)->uh_physuba; /* eg 20006000 */ ubainit(uba); udaddr = (struct udadevice *)ui->ui_physaddr; /* eg 2013f468 */ DELAY(5000000); /* ** map the uda communications area (comarea) into the beginning of the ** UNIBUS memory. */ udaptr = &sa_uda[ui->ui_ctlr]; offset = ((int)udaptr) & PGOFSET; ubapte = &uba->uba_map[0]; /* eg 2000680c */ comarea = (struct sa_uda *)(((ubapte-uba->uba_map)<<9) | offset); for ( i=0 ; i<btoc(sizeof(struct sa_uda)+offset)+1 ; i++ ) *(int *)ubapte++ = UBAMR_MRV | (btop(phys(unsigned,udaptr))+i); *(int *)ubapte++ = 0; /* ** Do device initialization */ udaddr->udaip = 0; while ((udaddr->udasa & UDA_STEP1) == 0) continue; udaddr->udasa = UDA_ERR; while ((udaddr->udasa & (UDA_STEP2|UDA_ERR)) == 0) ; if (udaddr->udasa & UDA_ERR) { printf("failed in STEP1..."); return EIO; } udaddr->udasa = (short)&comarea->uda_ca.ca_ringbase; while ((udaddr->udasa & (UDA_STEP3|UDA_ERR)) == 0) ; if (udaddr->udasa & UDA_ERR) { printf("failed in STEP2..."); return EIO; } udaddr->udasa = (short)(((int)&comarea->uda_ca.ca_ringbase) >> 16); while ((udaddr->udasa & (UDA_STEP4|UDA_ERR)) == 0) ; if (udaddr->udasa & UDA_ERR) { printf("failed in STEP3..."); return EIO; } udaddr->udasa = UDA_GO; udaptr->uda_ca.ca_rspdsc[0] = (long)&comarea->uda_rsp[0].mscp_cmdref; udaptr->uda_ca.ca_cmddsc[0] = (long)&comarea->uda_cmd[0].mscp_cmdref; udaptr->uda_cmd[0].mscp_cntflgs = 0; if (udcmd(udaptr, udaddr, M_OP_STCON) == 0) { printf("uddump: STCON failed\n"); return EIO; } udaptr->uda_cmd[0].mscp_unit = unit; if (udcmd(udaptr, udaddr,M_OP_ONLIN) == 0) { printf("uddump: ONLIN failed\n"); return EIO; } /* ** Determine if enough space exists on the disk */ start = 0; pages = maxfree; if (dumplo < 0 || dumplo + pages >= udsize(dev)) return EINVAL; /* ** Write out physical memory, page by page. ** UNIBUS UBAMR_BO is always zero. */ while (pages > 0) { struct mscp *mp; register struct pte *io; register int i; blk = pages > DBSIZE ? DBSIZE : pages; io = ubapte; for (i = 0; i < blk; i++) *(int *)io++ = (btop(start)+i)|(1<<UBAMR_DPSHIFT)|UBAMR_MRV; *(int *)io = 0; mp = &udaptr->uda_cmd[0]; mp->mscp_lbn = dumplo+btop(start)+ra_sizes[minor(dev)&07].blkoff; mp->mscp_unit = unit; mp->mscp_bytecnt = blk*NBPG; mp->mscp_buffer = ((ubapte-uba->uba_map)<<9) | (1<<24); if ((mp = udcmd(udaptr, udaddr,M_OP_WRITE)) == 0) { printf("uddump: I/O error\n"); return EIO; } start += blk*NBPG; pages -= blk; } return (0); } struct mscp * udcmd(udaptr, udaddr,op) struct sa_uda *udaptr; struct udadevice *udaddr; int op; { struct mscp *mp; int i; udaptr->uda_cmd[0].mscp_opcode = op; udaptr->uda_rsp[0].mscp_header.uda_msglen = sizeof (struct mscp); udaptr->uda_cmd[0].mscp_header.uda_msglen = sizeof (struct mscp); udaptr->uda_ca.ca_rspdsc[0] |= UDA_OWN; udaptr->uda_ca.ca_cmddsc[0] |= UDA_OWN; i = udaddr->udaip; for ( ;; ) { while ( udaptr->uda_ca.ca_rspdsc[0] & UDA_OWN ) DELAY(1000); mp = &udaptr->uda_rsp[0]; if ( mp->mscp_opcode == (op|M_OP_END) && mp->mscp_status == M_ST_SUCC ) break; printf("udcmd: unsolicited packet status 0%o opcode 0%o\n",mp->mscp_status,mp->mscp_opcode); } udaptr->uda_ca.ca_rspdsc[0] &= ~UDA_INT; udaptr->uda_ca.ca_cmddsc[0] &= ~UDA_INT; return mp; } udsize(dev) dev_t dev; { int unit = minor(dev) >> 3; struct uba_device *ui; if (unit >= NRA || (ui = uddinfo[unit]) == 0 || ui->ui_alive == 0) return (-1); return (ra_sizes[minor(dev) & 07].nblocks); /* xxx */ } #endif ----------