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

📄 uda.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Chris Torek. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *	@(#)uda.c	7.32 (Berkeley) 2/13/91 *//* * UDA50/MSCP device driver */#define	POLLSTATS/* * TODO *	write bad block forwarding code */#include "ra.h"#if NUDA > 0/* * CONFIGURATION OPTIONS.  The next three defines are tunable -- tune away! * * COMPAT_42 enables 4.2/4.3 compatibility (label mapping) * * NRSPL2 and NCMDL2 control the number of response and command * packets respectively.  They may be any value from 0 to 7, though * setting them higher than 5 is unlikely to be of any value. * If you get warnings about your command ring being too small, * try increasing the values by one. * * MAXUNIT controls the maximum unit number (number of drives per * controller) we are prepared to handle. * * DEFAULT_BURST must be at least 1. */#define	COMPAT_42#define	NRSPL2	5		/* log2 number of response packets */#define NCMDL2	5		/* log2 number of command packets */#define	MAXUNIT	8		/* maximum allowed unit number */#define	DEFAULT_BURST	4	/* default DMA burst size */#include "sys/param.h"#include "sys/systm.h"#include "sys/buf.h"#include "sys/conf.h"#include "sys/file.h"#include "sys/ioctl.h"#include "sys/user.h"#include "sys/map.h"#include "sys/vm.h"#include "sys/dkstat.h"#include "sys/cmap.h"#include "sys/disklabel.h"#include "sys/syslog.h"#include "sys/stat.h"#include "../include/pte.h"#include "../include/cpu.h"#include "ubareg.h"#include "ubavar.h"#define	NRSP	(1 << NRSPL2)#define	NCMD	(1 << NCMDL2)#include "udareg.h"#include "../vax/mscp.h"#include "../vax/mscpvar.h"#include "../include/mtpr.h"/* * UDA communications area and MSCP packet pools, per controller. */struct	uda {	struct	udaca uda_ca;		/* communications area */	struct	mscp uda_rsp[NRSP];	/* response packets */	struct	mscp uda_cmd[NCMD];	/* command packets */} uda[NUDA];/* * Software status, per controller. */struct	uda_softc {	struct	uda *sc_uda;	/* Unibus address of uda struct */	short	sc_state;	/* UDA50 state; see below */	short	sc_flags;	/* flags; see below */	int	sc_micro;	/* microcode revision */	int	sc_ivec;	/* interrupt vector address */	short	sc_ipl;		/* interrupt priority, Q-bus */	struct	mscp_info sc_mi;/* MSCP info (per mscpvar.h) */#ifndef POLLSTATS	int	sc_wticks;	/* watchdog timer ticks */#else	short	sc_wticks;	short	sc_ncmd;#endif} uda_softc[NUDA];#ifdef POLLSTATSstruct udastats {	int	ncmd;	int	cmd[NCMD + 1];} udastats = { NCMD + 1 };#endif/* * Controller states */#define	ST_IDLE		0	/* uninitialised */#define	ST_STEP1	1	/* in `STEP 1' */#define	ST_STEP2	2	/* in `STEP 2' */#define	ST_STEP3	3	/* in `STEP 3' */#define	ST_SETCHAR	4	/* in `Set Controller Characteristics' */#define	ST_RUN		5	/* up and running *//* * Flags */#define	SC_MAPPED	0x01	/* mapped in Unibus I/O space */#define	SC_INSTART	0x02	/* inside udastart() */#define	SC_GRIPED	0x04	/* griped about cmd ring too small */#define	SC_INSLAVE	0x08	/* inside udaslave() */#define	SC_DOWAKE	0x10	/* wakeup when ctlr init done */#define	SC_STARTPOLL	0x20	/* need to initiate polling *//* * Device to unit number and partition and back */#define	UNITSHIFT	3#define	UNITMASK	7#define	udaunit(dev)	(minor(dev) >> UNITSHIFT)#define	udapart(dev)	(minor(dev) & UNITMASK)#define	udaminor(u, p)	(((u) << UNITSHIFT) | (p))/* * Drive status, per drive */struct ra_info {	daddr_t	ra_dsize;	/* size in sectors *//*	u_long	ra_type;	/* drive type */	u_long	ra_mediaid;	/* media id */	int	ra_state;	/* open/closed state */	struct	ra_geom {	/* geometry information */		u_short	rg_nsectors;	/* sectors/track */		u_short	rg_ngroups;	/* track groups */		u_short	rg_ngpc;	/* groups/cylinder */		u_short	rg_ntracks;	/* ngroups*ngpc */		u_short	rg_ncyl;	/* ra_dsize/ntracks/nsectors */#ifdef notyet		u_short	rg_rctsize;	/* size of rct */		u_short	rg_rbns;	/* replacement blocks per track */		u_short	rg_nrct;	/* number of rct copies */#endif	} ra_geom;	int	ra_wlabel;	/* label sector is currently writable */	u_long	ra_openpart;	/* partitions open */	u_long	ra_bopenpart;	/* block partitions open */	u_long	ra_copenpart;	/* character partitions open */} ra_info[NRA];/* * Software state, per drive */#define	CLOSED		0#define	WANTOPEN	1#define	RDLABEL		2#define	OPEN		3#define	OPENRAW		4/* * Definition of the driver for autoconf. */int	udaprobe(), udaslave(), udaattach(), udadgo(), udaintr();struct	uba_ctlr *udaminfo[NUDA];struct	uba_device *udadinfo[NRA];struct	disklabel udalabel[NRA];u_short	udastd[] = { 0772150, 0772550, 0777550, 0 };struct	uba_driver udadriver = { udaprobe, udaslave, udaattach, udadgo, udastd, "ra", udadinfo, "uda",   udaminfo };/* * More driver definitions, for generic MSCP code. */int	udadgram(), udactlrdone(), udaunconf(), udaiodone();int	udaonline(), udagotstatus(), udaioerror(), udareplace(), udabb();struct	buf udautab[NRA];	/* per drive transfer queue */struct	mscp_driver udamscpdriver = { MAXUNIT, NRA, UNITSHIFT, udautab, udalabel, udadinfo,   udadgram, udactlrdone, udaunconf, udaiodone,   udaonline, udagotstatus, udareplace, udaioerror, udabb,   "uda", "ra" };/* * Miscellaneous private variables. */char	udasr_bits[] = UDASR_BITS;struct	uba_device *udaip[NUDA][MAXUNIT];				/* inverting pointers: ctlr & unit => Unibus				   device pointer */int	udaburst[NUDA] = { 0 };	/* burst size, per UDA50, zero => default;				   in data space so patchable via adb */struct	mscp udaslavereply;	/* get unit status response packet, set				   for udaslave by udaunconf, via udaintr */static struct uba_ctlr *probeum;/* this is a hack---autoconf should pass ctlr				   info to slave routine; instead, we remember				   the last ctlr argument to probe */int	udawstart, udawatch();	/* watchdog timer *//* * Externals */int	wakeup();int	hz;/* * Poke at a supposed UDA50 to see if it is there. * This routine duplicates some of the code in udainit() only * because autoconf has not set up the right information yet. * We have to do everything `by hand'. */udaprobe(reg, ctlr, um)	caddr_t reg;	int ctlr;	struct uba_ctlr *um;{	register int br, cvec;	register struct uda_softc *sc;	register struct udadevice *udaddr;	register struct mscp_info *mi;	int timeout, tries;#ifdef QBA	int s;#endif#ifdef VAX750	/*	 * The UDA50 wants to share BDPs on 750s, but not on 780s or	 * 8600s.  (730s have no BDPs anyway.)  Toward this end, we	 * here set the `keep bdp' flag in the per-driver information	 * if this is a 750.  (We just need to do it once, but it is	 * easiest to do it now, for each UDA50.)	 */	if (cpu == VAX_750)		udadriver.ud_keepbdp = 1;#endif	probeum = um;			/* remember for udaslave() */#ifdef lint	br = 0; cvec = br; br = cvec; udaintr(0);#endif	/*	 * Set up the controller-specific generic MSCP driver info.	 * Note that this should really be done in the (nonexistent)	 * controller attach routine.	 */	sc = &uda_softc[ctlr];	mi = &sc->sc_mi;	mi->mi_md = &udamscpdriver;	mi->mi_ctlr = um->um_ctlr;	mi->mi_tab = &um->um_tab;	mi->mi_ip = udaip[ctlr];	mi->mi_cmd.mri_size = NCMD;	mi->mi_cmd.mri_desc = uda[ctlr].uda_ca.ca_cmddsc;	mi->mi_cmd.mri_ring = uda[ctlr].uda_cmd;	mi->mi_rsp.mri_size = NRSP;	mi->mi_rsp.mri_desc = uda[ctlr].uda_ca.ca_rspdsc;	mi->mi_rsp.mri_ring = uda[ctlr].uda_rsp;	mi->mi_wtab.av_forw = mi->mi_wtab.av_back = &mi->mi_wtab;	/*	 * More controller specific variables.  Again, this should	 * be in the controller attach routine.	 */	if (udaburst[ctlr] == 0)		udaburst[ctlr] = DEFAULT_BURST;			/*	 * Get an interrupt vector.  Note that even if the controller	 * does not respond, we keep the vector.  This is not a serious	 * problem; but it would be easily fixed if we had a controller	 * attach routine.  Sigh.	 */	sc->sc_ivec = (uba_hd[numuba].uh_lastiv -= 4);	udaddr = (struct udadevice *) reg;	/*	 * Initialise the controller (partially).  The UDA50 programmer's	 * manual states that if initialisation fails, it should be retried	 * at least once, but after a second failure the port should be	 * considered `down'; it also mentions that the controller should	 * initialise within ten seconds.  Or so I hear; I have not seen	 * this manual myself.	 */#if defined(QBA) && !defined(GENERIC)	s = spl6();#endif	tries = 0;again:	udaddr->udaip = 0;		/* start initialisation */	timeout = todr() + 1000;	/* timeout in 10 seconds */	while ((udaddr->udasa & UDA_STEP1) == 0)		if (todr() > timeout)			goto bad;	udaddr->udasa = UDA_ERR | (NCMDL2 << 11) | (NRSPL2 << 8) | UDA_IE |		(sc->sc_ivec >> 2);	while ((udaddr->udasa & UDA_STEP2) == 0)		if (todr() > timeout)			goto bad;	/* should have interrupted by now */#ifdef QBA#ifndef GENERIC	sc->sc_ipl = br = qbgetpri();#else	sc->sc_ipl = br = 0x15;#endif#endif	return (sizeof (struct udadevice));bad:	if (++tries < 2)		goto again;#if defined(QBA) && !defined(GENERIC)	splx(s);#endif	return (0);}/* * Find a slave.  We allow wildcard slave numbers (something autoconf * is not really prepared to deal with); and we need to know the * controller number to talk to the UDA.  For the latter, we keep * track of the last controller probed, since a controller probe * immediately precedes all slave probes for that controller.  For the * former, we simply put the unit number into ui->ui_slave after we * have found one. * * Note that by the time udaslave is called, the interrupt vector * for the UDA50 has been set up (so that udaunconf() will be called). */udaslave(ui, reg)	register struct uba_device *ui;	caddr_t reg;{	register struct uba_ctlr *um = probeum;	register struct mscp *mp;	register struct uda_softc *sc;	int next = 0, timeout, tries, i;#ifdef lint	i = 0; i = i;#endif	/*	 * Make sure the controller is fully initialised, by waiting	 * for it if necessary.	 */	sc = &uda_softc[um->um_ctlr];	if (sc->sc_state == ST_RUN)		goto findunit;	tries = 0;again:	if (udainit(ui->ui_ctlr))		return (0);	timeout = todr() + 1000;		/* 10 seconds */	while (todr() < timeout)		if (sc->sc_state == ST_RUN)	/* made it */			goto findunit;	if (++tries < 2)		goto again;	printf("uda%d: controller hung\n", um->um_ctlr);	return (0);	/*	 * The controller is all set; go find the unit.  Grab an	 * MSCP packet and send out a Get Unit Status command, with	 * the `next unit' modifier if we are looking for a generic	 * unit.  We set the `in slave' flag so that udaunconf()	 * knows to copy the response to `udaslavereply'.	 */findunit:	udaslavereply.mscp_opcode = 0;	sc->sc_flags |= SC_INSLAVE;	if ((mp = mscp_getcp(&sc->sc_mi, MSCP_DONTWAIT)) == NULL)		panic("udaslave");		/* `cannot happen' */	mp->mscp_opcode = M_OP_GETUNITST;	if (ui->ui_slave == '?') {		mp->mscp_unit = next;		mp->mscp_modifier = M_GUM_NEXTUNIT;	} else {		mp->mscp_unit = ui->ui_slave;		mp->mscp_modifier = 0;	}	*mp->mscp_addr |= MSCP_OWN | MSCP_INT;	i = ((struct udadevice *) reg)->udaip;	/* initiate polling */	mp = &udaslavereply;	timeout = todr() + 1000;	while (todr() < timeout)		if (mp->mscp_opcode)			goto gotit;	printf("uda%d: no response to Get Unit Status request\n",		um->um_ctlr);	sc->sc_flags &= ~SC_INSLAVE;	return (0);gotit:	sc->sc_flags &= ~SC_INSLAVE;	/*	 * Got a slave response.  If the unit is there, use it.	 */	switch (mp->mscp_status & M_ST_MASK) {	case M_ST_SUCCESS:	/* worked */	case M_ST_AVAILABLE:	/* found another drive */		break;		/* use it */	case M_ST_OFFLINE:		/*		 * Figure out why it is off line.  It may be because

⌨️ 快捷键说明

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