⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 uda.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
			sc->sc_micro = i;			printf("uda%d: version %d model %d\n",				ctlr, i & 0xf, i >> 4);		}		/*		 * Present the burst size, then remove it.  Why this		 * should be done this way, I have no idea.		 *		 * Note that this assumes udaburst[ctlr] > 0.		 */		udaddr->udasa = UDA_GO | (udaburst[ctlr] - 1) << 2;		udaddr->udasa = UDA_GO;		printf("uda%d: DMA burst size set to %d\n",			ctlr, udaburst[ctlr]);		udainitds(ctlr);	/* initialise data structures */		/*		 * Before we can get a command packet, we need some		 * credits.  Fake some up to keep mscp_getcp() happy,		 * get a packet, and cancel all credits (the right		 * number should come back in the response to the		 * SCC packet).		 */		sc->sc_mi.mi_credits = MSCP_MINCREDITS + 1;		mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT);		if (mp == NULL)	/* `cannot happen' */			panic("udaintr");		sc->sc_mi.mi_credits = 0;		mp->mscp_opcode = M_OP_SETCTLRC;		mp->mscp_unit = 0;		mp->mscp_sccc.sccc_ctlrflags = M_CF_ATTN | M_CF_MISC |			M_CF_THIS;		*mp->mscp_addr |= MSCP_OWN | MSCP_INT;		i = udaddr->udaip;		sc->sc_state = ST_SETCHAR;		return;	case ST_SETCHAR:	case ST_RUN:		/*		 * Handle Set Ctlr Characteristics responses and operational		 * responses (via mscp_dorsp).		 */		break;	default:		printf("uda%d: driver bug, state %d\n", ctlr, sc->sc_state);		panic("udastate");	}	if (udaddr->udasa & UDA_ERR) {	/* ctlr fatal error */		udasaerror(um, 1);		return;	}	ud = &uda[ctlr];	/*	 * Handle buffer purge requests.	 */	if (ud->uda_ca.ca_bdp) {		UBAPURGE(um->um_hd->uh_uba, ud->uda_ca.ca_bdp);		ud->uda_ca.ca_bdp = 0;		udaddr->udasa = 0;	/* signal purge complete */	}	/*	 * Check for response and command ring transitions.	 */	if (ud->uda_ca.ca_rspint) {		ud->uda_ca.ca_rspint = 0;		mscp_dorsp(&sc->sc_mi);	}	if (ud->uda_ca.ca_cmdint) {		ud->uda_ca.ca_cmdint = 0;		MSCP_DOCMD(&sc->sc_mi);	}	udastart(um);}/* * Initialise the various data structures that control the UDA50. */udainitds(ctlr)	int ctlr;{	register struct uda *ud = &uda[ctlr];	register struct uda *uud = uda_softc[ctlr].sc_uda;	register struct mscp *mp;	register int i;	for (i = 0, mp = ud->uda_rsp; i < NRSP; i++, mp++) {		ud->uda_ca.ca_rspdsc[i] = MSCP_OWN | MSCP_INT |			(long)&uud->uda_rsp[i].mscp_cmdref;		mp->mscp_addr = &ud->uda_ca.ca_rspdsc[i];		mp->mscp_msglen = MSCP_MSGLEN;	}	for (i = 0, mp = ud->uda_cmd; i < NCMD; i++, mp++) {		ud->uda_ca.ca_cmddsc[i] = MSCP_INT |			(long)&uud->uda_cmd[i].mscp_cmdref;		mp->mscp_addr = &ud->uda_ca.ca_cmddsc[i];		mp->mscp_msglen = MSCP_MSGLEN;	}}/* * Handle an error datagram. */udadgram(mi, mp)	struct mscp_info *mi;	struct mscp *mp;{	mscp_decodeerror(mi->mi_md->md_mname, mi->mi_ctlr, mp);	/*	 * SDI status information bytes 10 and 11 are the microprocessor	 * error code and front panel code respectively.  These vary per	 * drive type and are printed purely for field service information.	 */	if (mp->mscp_format == M_FM_SDI)		printf("\tsdi uproc error code 0x%x, front panel code 0x%x\n",			mp->mscp_erd.erd_sdistat[10],			mp->mscp_erd.erd_sdistat[11]);}/* * The Set Controller Characteristics command finished. * Record the new state of the controller. */udactlrdone(mi, mp)	register struct mscp_info *mi;	struct mscp *mp;{	register struct uda_softc *sc = &uda_softc[mi->mi_ctlr];	if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS)		sc->sc_state = ST_RUN;	else {		printf("uda%d: SETCTLRC failed: ",			mi->mi_ctlr, mp->mscp_status);		mscp_printevent(mp);		sc->sc_state = ST_IDLE;	}	if (sc->sc_flags & SC_DOWAKE) {		sc->sc_flags &= ~SC_DOWAKE;		wakeup((caddr_t)sc);	}}/* * Received a response from an as-yet unconfigured drive.  Configure it * in, if possible. */udaunconf(mi, mp)	struct mscp_info *mi;	register struct mscp *mp;{	/*	 * If it is a slave response, copy it to udaslavereply for	 * udaslave() to look at.	 */	if (mp->mscp_opcode == (M_OP_GETUNITST | M_OP_END) &&	    (uda_softc[mi->mi_ctlr].sc_flags & SC_INSLAVE) != 0) {		udaslavereply = *mp;		return (MSCP_DONE);	}	/*	 * Otherwise, it had better be an available attention response.	 */	if (mp->mscp_opcode != M_OP_AVAILATTN)		return (MSCP_FAILED);	/* do what autoconf does */	return (MSCP_FAILED);	/* not yet, arwhite, not yet */}/* * A drive came on line.  Check its type and size.  Return DONE if * we think the drive is truly on line.  In any case, awaken anyone * sleeping on the drive on-line-ness. */udaonline(ui, mp)	register struct uba_device *ui;	struct mscp *mp;{	register struct ra_info *ra = &ra_info[ui->ui_unit];	wakeup((caddr_t)&ui->ui_flags);	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {		if (!cold)			printf("uda%d: ra%d", ui->ui_ctlr, ui->ui_unit);		printf(": attempt to bring on line failed: ");		mscp_printevent(mp);		ra->ra_state = CLOSED;		return (MSCP_FAILED);	}	ra->ra_state = OPENRAW;	ra->ra_dsize = (daddr_t)mp->mscp_onle.onle_unitsize;	if (!cold)		printf("ra%d: uda%d, unit %d, size = %d sectors\n", ui->ui_unit,		    ui->ui_ctlr, mp->mscp_unit, ra->ra_dsize);	/* can now compute ncyl */	ra->ra_geom.rg_ncyl = ra->ra_dsize / ra->ra_geom.rg_ntracks /		ra->ra_geom.rg_nsectors;	return (MSCP_DONE);}/* * We got some (configured) unit's status.  Return DONE if it succeeded. */udagotstatus(ui, mp)	register struct uba_device *ui;	register struct mscp *mp;{	if ((mp->mscp_status & M_ST_MASK) != M_ST_SUCCESS) {		printf("uda%d: attempt to get status for ra%d failed: ",			ui->ui_ctlr, ui->ui_unit);		mscp_printevent(mp);		return (MSCP_FAILED);	}	/* record for (future) bad block forwarding and whatever else */	uda_rasave(ui->ui_unit, mp, 1);	return (MSCP_DONE);}/* * A transfer failed.  We get a chance to fix or restart it. * Need to write the bad block forwaring code first.... *//*ARGSUSED*/udaioerror(ui, mp, bp)	register struct uba_device *ui;	register struct mscp *mp;	struct buf *bp;{	if (mp->mscp_flags & M_EF_BBLKR) {		/*		 * A bad block report.  Eventually we will		 * restart this transfer, but for now, just		 * log it and give up.		 */		log(LOG_ERR, "ra%d: bad block report: %d%s\n",			ui->ui_unit, mp->mscp_seq.seq_lbn,			mp->mscp_flags & M_EF_BBLKU ? " + others" : "");	} else {		/*		 * What the heck IS a `serious exception' anyway?		 * IT SURE WOULD BE NICE IF DEC SOLD DOCUMENTATION		 * FOR THEIR OWN CONTROLLERS.		 */		if (mp->mscp_flags & M_EF_SEREX)			log(LOG_ERR, "ra%d: serious exception reported\n",				ui->ui_unit);	}	return (MSCP_FAILED);}/* * A replace operation finished. *//*ARGSUSED*/udareplace(ui, mp)	struct uba_device *ui;	struct mscp *mp;{	panic("udareplace");}/* * A bad block related operation finished. *//*ARGSUSED*/udabb(ui, mp, bp)	struct uba_device *ui;	struct mscp *mp;	struct buf *bp;{	panic("udabb");}/* * I/O controls. */udaioctl(dev, cmd, data, flag)	dev_t dev;	int cmd;	caddr_t data;	int flag;{	register int unit = udaunit(dev);	register struct disklabel *lp;	register struct ra_info *ra = &ra_info[unit];	int error = 0;	lp = &udalabel[unit];	switch (cmd) {	case DIOCGDINFO:		*(struct disklabel *)data = *lp;		break;	case DIOCGPART:		((struct partinfo *)data)->disklab = lp;		((struct partinfo *)data)->part =		    &lp->d_partitions[udapart(dev)];		break;	case DIOCSDINFO:		if ((flag & FWRITE) == 0)			error = EBADF;		else			error = setdisklabel(lp, (struct disklabel *)data,			    (ra->ra_state == OPENRAW) ? 0 : ra->ra_openpart);		break;	case DIOCWLABEL:		if ((flag & FWRITE) == 0)			error = EBADF;		else			ra->ra_wlabel = *(int *)data;		break;	case DIOCWDINFO:		if ((flag & FWRITE) == 0)			error = EBADF;		else if ((error = setdisklabel(lp, (struct disklabel *)data,		    (ra->ra_state == OPENRAW) ? 0 : ra->ra_openpart)) == 0) {			int wlab;			ra->ra_state = OPEN;			/* simulate opening partition 0 so write succeeds */			ra->ra_openpart |= (1 << 0);		/* XXX */			wlab = ra->ra_wlabel;			ra->ra_wlabel = 1;			error = writedisklabel(dev, udastrategy, lp);			ra->ra_openpart = ra->ra_copenpart | ra->ra_bopenpart;			ra->ra_wlabel = wlab;		}		break;#ifdef notyet	case UDAIOCREPLACE:		/*		 * Initiate bad block replacement for the given LBN.		 * (Should we allow modifiers?)		 */		error = EOPNOTSUPP;		break;	case UDAIOCGMICRO:		/*		 * Return the microcode revision for the UDA50 running		 * this drive.		 */		*(int *)data = uda_softc[uddinfo[unit]->ui_ctlr].sc_micro;		break;#endif	default:		error = ENOTTY;		break;	}	return (error);}/* * A Unibus reset has occurred on UBA uban.  Reinitialise the controller(s) * on that Unibus, and requeue outstanding I/O. */udareset(uban)	int uban;{	register struct uba_ctlr *um;	register struct uda_softc *sc;	register int ctlr;	for (ctlr = 0, sc = uda_softc; ctlr < NUDA; ctlr++, sc++) {		if ((um = udaminfo[ctlr]) == NULL || um->um_ubanum != uban ||		    um->um_alive == 0)			continue;		printf(" uda%d", ctlr);		/*		 * Our BDP (if any) is gone; our command (if any) is		 * flushed; the device is no longer mapped; and the		 * UDA50 is not yet initialised.		 */		if (um->um_bdp) {			printf("<%d>", UBAI_BDP(um->um_bdp));			um->um_bdp = 0;		}		um->um_ubinfo = 0;		um->um_cmd = 0;		sc->sc_flags &= ~SC_MAPPED;		sc->sc_state = ST_IDLE;		/* reset queues and requeue pending transfers */		mscp_requeue(&sc->sc_mi);		/*		 * If it fails to initialise we will notice later and		 * try again (and again...).  Do not call udastart()		 * here; it will be done after the controller finishes		 * initialisation.		 */		if (udainit(ctlr))			printf(" (hung)");	}}/* * Watchdog timer:  If the controller is active, and no interrupts * have occurred for 30 seconds, assume it has gone away. */udawatch(){	register int i;	register struct uba_ctlr *um;	register struct uda_softc *sc;	timeout(udawatch, (caddr_t) 0, hz);	/* every second */	for (i = 0, sc = uda_softc; i < NUDA; i++, sc++) {		if ((um = udaminfo[i]) == 0 || !um->um_alive)			continue;		if (sc->sc_state == ST_IDLE)			continue;		if (sc->sc_state == ST_RUN && !um->um_tab.b_active)			sc->sc_wticks = 0;		else if (++sc->sc_wticks >= 30) {			sc->sc_wticks = 0;			printf("uda%d: lost interrupt\n", i);			ubareset(um->um_ubanum);		}	}}/* * Do a panic dump.  We set up the controller for one command packet * and one response packet, for which we use `struct uda1'. */struct	uda1 {	struct	uda1ca uda1_ca;	/* communications area */	struct	mscp uda1_rsp;	/* response packet */	struct	mscp uda1_cmd;	/* command packet */} uda1;#define	DBSIZE	32		/* dump 16K at a time */udadump(dev)	dev_t dev;{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -