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

📄 rd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1988 University of Utah. * Copyright (c) 1982, 1990, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * the Systems Programming Group of the University of Utah Computer * Science Department. * * 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. * * from: Utah $Hdr: rd.c 1.44 92/12/26$ * *	@(#)rd.c	8.1 (Berkeley) 6/10/93 *//* * CS80/SS80 disk driver */#include "rd.h"#if NRD > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/buf.h>#include <sys/stat.h>#include <sys/dkstat.h>#include <sys/disklabel.h>#include <sys/ioctl.h>#include <sys/fcntl.h>#include <hp/dev/device.h>#include <hp300/dev/rdreg.h>#include <hp300/dev/rdvar.h>#ifdef USELEDS#include <hp300/hp300/led.h>#endif#include <vm/vm_param.h>#include <vm/lock.h>#include <vm/vm_prot.h>#include <vm/pmap.h>int	rdinit(), rdstart(), rdgo(), rdintr();void	rdstrategy();struct	driver rddriver = {	rdinit, "rd", rdstart, rdgo, rdintr,};struct	rd_softc rd_softc[NRD];struct	buf rdtab[NRD];int	rderrthresh = RDRETRY-1;	/* when to start reporting errors */#ifdef DEBUG/* error message tables */char *err_reject[] = {	0, 0,	"channel parity error",		/* 0x2000 */	0, 0,	"illegal opcode",		/* 0x0400 */	"module addressing",		/* 0x0200 */	"address bounds",		/* 0x0100 */	"parameter bounds",		/* 0x0080 */	"illegal parameter",		/* 0x0040 */	"message sequence",		/* 0x0020 */	0,	"message length",		/* 0x0008 */	0, 0, 0};char *err_fault[] = {	0,	"cross unit",			/* 0x4000 */	0,	"controller fault",		/* 0x1000 */	0, 0,	"unit fault",			/* 0x0200 */	0,	"diagnostic result",		/* 0x0080 */	0,	"operator release request",	/* 0x0020 */	"diagnostic release request",	/* 0x0010 */	"internal maintenance release request",	/* 0x0008 */	0,	"power fail",			/* 0x0002 */	"retransmit"			/* 0x0001 */};char *err_access[] = {	"illegal parallel operation",	/* 0x8000 */	"uninitialized media",		/* 0x4000 */	"no spares available",		/* 0x2000 */	"not ready",			/* 0x1000 */	"write protect",		/* 0x0800 */	"no data found",		/* 0x0400 */	0, 0,	"unrecoverable data overflow",	/* 0x0080 */	"unrecoverable data",		/* 0x0040 */	0,	"end of file",			/* 0x0010 */	"end of volume",		/* 0x0008 */	0, 0, 0};char *err_info[] = {	"operator release request",	/* 0x8000 */	"diagnostic release request",	/* 0x4000 */	"internal maintenance release request",	/* 0x2000 */	"media wear",			/* 0x1000 */	"latency induced",		/* 0x0800 */	0, 0,	"auto sparing invoked",		/* 0x0100 */	0,	"recoverable data overflow",	/* 0x0040 */	"marginal data",		/* 0x0020 */	"recoverable data",		/* 0x0010 */	0,	"maintenance track overflow",	/* 0x0004 */	0, 0};struct	rdstats rdstats[NRD];int	rddebug = 0x80;#define RDB_FOLLOW	0x01#define RDB_STATUS	0x02#define RDB_IDENT	0x04#define RDB_IO		0x08#define RDB_ASYNC	0x10#define RDB_ERROR	0x80#endif/* * Misc. HW description, indexed by sc_type. * Nothing really critical here, could do without it. */struct rdidentinfo rdidentinfo[] = {	{ RD7946AID,	0,	"7945A",	 108416 },	{ RD9134DID,	1,	"9134D",	  29088 },	{ RD9134LID,	1,	"9122S",	   1232 },	{ RD7912PID,	0,	"7912P",	 128128 },	{ RD7914PID,	0,	"7914P",	 258048 },	{ RD7958AID,	0,	"7958A",	 255276 },	{ RD7957AID,	0,	"7957A",	 159544 },	{ RD7933HID,	0,	"7933H",	 789958 },	{ RD9134LID,	1,	"9134L",	  77840 },	{ RD7936HID,	0,	"7936H",	 600978 },	{ RD7937HID,	0,	"7937H",	1116102 },	{ RD7914CTID,	0,	"7914CT",	 258048 },	{ RD7946AID,	0,	"7946A",	 108416 },	{ RD9134LID,	1,	"9122D",	   1232 },	{ RD7957BID,	0,	"7957B",	 159894 },	{ RD7958BID,	0,	"7958B",	 297108 },	{ RD7959BID,	0,	"7959B",	 594216 },	{ RD2200AID,	0,	"2200A",	 654948 },	{ RD2203AID,	0,	"2203A",	1309896 }};int numrdidentinfo = sizeof(rdidentinfo) / sizeof(rdidentinfo[0]);rdinit(hd)	register struct hp_device *hd;{	register struct rd_softc *rs = &rd_softc[hd->hp_unit];	rs->sc_hd = hd;	rs->sc_punit = rdpunit(hd->hp_flags);	rs->sc_type = rdident(rs, hd);	if (rs->sc_type < 0)		return(0);	rs->sc_dq.dq_ctlr = hd->hp_ctlr;	rs->sc_dq.dq_unit = hd->hp_unit;	rs->sc_dq.dq_slave = hd->hp_slave;	rs->sc_dq.dq_driver = &rddriver;	rs->sc_flags = RDF_ALIVE;#ifdef DEBUG	/* always report errors */	if (rddebug & RDB_ERROR)		rderrthresh = 0;#endif	return(1);}rdident(rs, hd)	struct rd_softc *rs;	struct hp_device *hd;{	struct rd_describe desc;	u_char stat, cmd[3];	int unit, lunit;	char name[7];	register int ctlr, slave, id, i;	ctlr = hd->hp_ctlr;	slave = hd->hp_slave;	unit = rs->sc_punit;	lunit = hd->hp_unit;	/*	 * Grab device id and make sure:	 * 1. It is a CS80 device.	 * 2. It is one of the types we support.	 * 3. If it is a 7946, we are accessing the disk unit (0)	 */	id = hpibid(ctlr, slave);#ifdef DEBUG	if (rddebug & RDB_IDENT)		printf("hpibid(%d, %d) -> %x\n", ctlr, slave, id);#endif	if ((id & 0x200) == 0)		return(-1);	for (i = 0; i < numrdidentinfo; i++)		if (id == rdidentinfo[i].ri_hwid)			break;	if (i == numrdidentinfo || unit > rdidentinfo[i].ri_maxunum)		return(-1);	id = i;	/*	 * Reset drive and collect device description.	 * Don't really use the description info right now but	 * might come in handy in the future (for disk labels).	 */	rdreset(rs, hd);	cmd[0] = C_SUNIT(unit);	cmd[1] = C_SVOL(0);	cmd[2] = C_DESC;	hpibsend(ctlr, slave, C_CMD, cmd, sizeof(cmd));	hpibrecv(ctlr, slave, C_EXEC, &desc, 37);	hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));	bzero(name, sizeof(name));	if (!stat) {		register int n = desc.d_name;		for (i = 5; i >= 0; i--) {			name[i] = (n & 0xf) + '0';			n >>= 4;		}		/* use drive characteristics to calculate xfer rate */		rs->sc_wpms = 1000000 * (desc.d_sectsize/2) / desc.d_blocktime;	}#ifdef DEBUG	if (rddebug & RDB_IDENT) {		printf("rd%d: name: %x ('%s')\n",		       lunit, desc.d_name, name);		printf("  iuw %x, maxxfr %d, ctype %d\n",		       desc.d_iuw, desc.d_cmaxxfr, desc.d_ctype);		printf("  utype %d, bps %d, blkbuf %d, burst %d, blktime %d\n",		       desc.d_utype, desc.d_sectsize,		       desc.d_blkbuf, desc.d_burstsize, desc.d_blocktime);		printf("  avxfr %d, ort %d, atp %d, maxint %d, fv %x, rv %x\n",		       desc.d_uavexfr, desc.d_retry, desc.d_access,		       desc.d_maxint, desc.d_fvbyte, desc.d_rvbyte);		printf("  maxcyl/head/sect %d/%d/%d, maxvsect %d, inter %d\n",		       desc.d_maxcyl, desc.d_maxhead, desc.d_maxsect,		       desc.d_maxvsectl, desc.d_interleave);	}#endif	/*	 * Take care of a couple of anomolies:	 * 1. 7945A and 7946A both return same HW id	 * 2. 9122S and 9134D both return same HW id	 * 3. 9122D and 9134L both return same HW id	 */	switch (rdidentinfo[id].ri_hwid) {	case RD7946AID:		if (bcmp(name, "079450", 6) == 0)			id = RD7945A;		else			id = RD7946A;		break;	case RD9134LID:		if (bcmp(name, "091340", 6) == 0)			id = RD9134L;		else			id = RD9122D;		break;	case RD9134DID:		if (bcmp(name, "091220", 6) == 0)			id = RD9122S;		else			id = RD9134D;		break;	}	printf("rd%d: %s\n", lunit, rdidentinfo[id].ri_desc);	return(id);}rdreset(rs, hd)	register struct rd_softc *rs;	register struct hp_device *hd;{	u_char stat;	rs->sc_clear.c_unit = C_SUNIT(rs->sc_punit);	rs->sc_clear.c_cmd = C_CLEAR;	hpibsend(hd->hp_ctlr, hd->hp_slave, C_TCMD, &rs->sc_clear,		sizeof(rs->sc_clear));	hpibswait(hd->hp_ctlr, hd->hp_slave);	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));	rs->sc_src.c_unit = C_SUNIT(RDCTLR);	rs->sc_src.c_nop = C_NOP;	rs->sc_src.c_cmd = C_SREL;	rs->sc_src.c_param = C_REL;	hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_src,		sizeof(rs->sc_src));	hpibswait(hd->hp_ctlr, hd->hp_slave);	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));	rs->sc_ssmc.c_unit = C_SUNIT(rs->sc_punit);	rs->sc_ssmc.c_cmd = C_SSM;	rs->sc_ssmc.c_refm = REF_MASK;	rs->sc_ssmc.c_fefm = FEF_MASK;	rs->sc_ssmc.c_aefm = AEF_MASK;	rs->sc_ssmc.c_iefm = IEF_MASK;	hpibsend(hd->hp_ctlr, hd->hp_slave, C_CMD, &rs->sc_ssmc,		sizeof(rs->sc_ssmc));	hpibswait(hd->hp_ctlr, hd->hp_slave);	hpibrecv(hd->hp_ctlr, hd->hp_slave, C_QSTAT, &stat, sizeof(stat));#ifdef DEBUG	rdstats[hd->hp_unit].rdresets++;#endif}/* * Read or constuct a disklabel */intrdgetinfo(dev)	dev_t dev;{	int unit = rdunit(dev);	register struct rd_softc *rs = &rd_softc[unit];	register struct disklabel *lp = &rs->sc_info.ri_label;	register struct partition *pi;	char *msg, *readdisklabel();	/*	 * Set some default values to use while reading the label	 * or to use if there isn't a label.	 */	bzero((caddr_t)lp, sizeof *lp);	lp->d_type = DTYPE_HPIB;	lp->d_secsize = DEV_BSIZE;	lp->d_nsectors = 32;	lp->d_ntracks = 20;	lp->d_ncylinders = 1;	lp->d_secpercyl = 32*20;	lp->d_npartitions = 3;	lp->d_partitions[2].p_offset = 0;	lp->d_partitions[2].p_size = LABELSECTOR+1;	/*	 * Now try to read the disklabel	 */	msg = readdisklabel(rdlabdev(dev), rdstrategy, lp);	if (msg == NULL)		return(0);	pi = lp->d_partitions;	printf("rd%d: WARNING: %s, ", unit, msg);#ifdef COMPAT_NOLABEL	printf("using old default partitioning\n");	rdmakedisklabel(unit, lp);#else	printf("defining `c' partition as entire disk\n");	pi[2].p_size = rdidentinfo[rs->sc_type].ri_nblocks;#endif	return(0);}intrdopen(dev, flags, mode, p)	dev_t dev;	int flags, mode;	struct proc *p;{	register int unit = rdunit(dev);	register struct rd_softc *rs = &rd_softc[unit];	int error, mask;	if (unit >= NRD || (rs->sc_flags & RDF_ALIVE) == 0)		return(ENXIO);	/*	 * Wait for any pending opens/closes to complete	 */	while (rs->sc_flags & (RDF_OPENING|RDF_CLOSING))		sleep((caddr_t)rs, PRIBIO);	/*	 * On first open, get label and partition info.	 * We may block reading the label, so be careful	 * to stop any other opens.	 */	if (rs->sc_info.ri_open == 0) {		rs->sc_flags |= RDF_OPENING;		error = rdgetinfo(dev);		rs->sc_flags &= ~RDF_OPENING;		wakeup((caddr_t)rs);		if (error)			return(error);	}	if (rs->sc_hd->hp_dk >= 0) {		/* guess at xfer rate based on 3600 rpm (60 rps) */		if (rs->sc_wpms == 0)			rs->sc_wpms = 60 * rs->sc_info.ri_label.d_nsectors				* DEV_BSIZE / 2;		dk_wpms[rs->sc_hd->hp_dk] = rs->sc_wpms;	}	mask = 1 << rdpart(dev);	if (mode == S_IFCHR)		rs->sc_info.ri_copen |= mask;	else		rs->sc_info.ri_bopen |= mask;	rs->sc_info.ri_open |= mask;	return(0);}intrdclose(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;{	int unit = rdunit(dev);	register struct rd_softc *rs = &rd_softc[unit];	register struct rdinfo *ri = &rs->sc_info;	int mask, s;	mask = 1 << rdpart(dev);	if (mode == S_IFCHR)		ri->ri_copen &= ~mask;	else		ri->ri_bopen &= ~mask;	ri->ri_open = ri->ri_bopen | ri->ri_copen;	/*	 * On last close, we wait for all activity to cease since	 * the label/parition info will become invalid.  Since we	 * might sleep, we must block any opens while we are here.	 * Note we don't have to about other closes since we know	 * we are the last one.	 */	if (ri->ri_open == 0) {		rs->sc_flags |= RDF_CLOSING;		s = splbio();		while (rdtab[unit].b_active) {			rs->sc_flags |= RDF_WANTED;			sleep((caddr_t)&rdtab[unit], PRIBIO);		}		splx(s);		rs->sc_flags &= ~(RDF_CLOSING|RDF_WLABEL);		wakeup((caddr_t)rs);	}	return(0);}voidrdstrategy(bp)	register struct buf *bp;{	int unit = rdunit(bp->b_dev);	register struct rd_softc *rs = &rd_softc[unit];	register struct buf *dp = &rdtab[unit];	register struct partition *pinfo;	register daddr_t bn;	register int sz, s;#ifdef DEBUG	if (rddebug & RDB_FOLLOW)		printf("rdstrategy(%x): dev %x, bn %x, bcount %x, %c\n",		       bp, bp->b_dev, bp->b_blkno, bp->b_bcount,		       (bp->b_flags & B_READ) ? 'R' : 'W');#endif	bn = bp->b_blkno;	sz = howmany(bp->b_bcount, DEV_BSIZE);	pinfo = &rs->sc_info.ri_label.d_partitions[rdpart(bp->b_dev)];	if (bn < 0 || bn + sz > pinfo->p_size) {		sz = pinfo->p_size - bn;		if (sz == 0) {			bp->b_resid = bp->b_bcount;			goto done;		}		if (sz < 0) {			bp->b_error = EINVAL;			goto bad;		}		bp->b_bcount = dbtob(sz);	}	/*	 * Check for write to write protected label	 */	if (bn + pinfo->p_offset <= LABELSECTOR &&#if LABELSECTOR != 0	    bn + pinfo->p_offset + sz > LABELSECTOR &&#endif	    !(bp->b_flags & B_READ) && !(rs->sc_flags & RDF_WLABEL)) {		bp->b_error = EROFS;		goto bad;	}	bp->b_cylin = bn + pinfo->p_offset;	s = splbio();	disksort(dp, bp);	if (dp->b_active == 0) {		dp->b_active = 1;		rdustart(unit);	}	splx(s);	return;bad:	bp->b_flags |= B_ERROR;done:	biodone(bp);}/* * Called from timeout() when handling maintenance releases */voidrdrestart(arg)	void *arg;{	int s = splbio();	rdustart((int)arg);	splx(s);}rdustart(unit)

⌨️ 快捷键说明

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