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

📄 vd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Computer Consoles Inc. * * 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. * *	@(#)vd.c	7.15 (Berkeley) 7/23/92 */#include "dk.h"#if NVD > 0/* * Versabus VDDC/SMDE driver. */#include "sys/param.h"#include "sys/buf.h"#include "sys/cmap.h"#include "sys/conf.h"#include "sys/dkstat.h"#include "sys/disklabel.h"#include "sys/map.h"#include "sys/file.h"#include "sys/systm.h"#include "sys/user.h"#include "sys/vmmac.h"#include "sys/proc.h"#include "sys/syslog.h"#include "sys/kernel.h"#include "sys/ioctl.h"#include "sys/stat.h"#include "../include/cpu.h"#include "../include/mtpr.h"#include "../include/pte.h"#include "../vba/vbavar.h"#include "../vba/vdreg.h"#ifndef	COMPAT_42#define	COMPAT_42#endif#define	B_FORMAT	B_XXX		/* XXX */#define vdunit(dev)	(minor(dev) >> 3)#define vdpart(dev)	(minor(dev) & 0x07)#define	vdminor(unit,part)	(((unit) << 3) | (part))struct	vba_ctlr *vdminfo[NVD];struct  vba_device *vddinfo[NDK];int	vdprobe(), vdslave(), vdattach(), vddgo(), vdstrategy();long	vdstd[] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300, 0 };struct	vba_driver vddriver =  { vdprobe, vdslave, vdattach, vddgo, vdstd, "dk", vddinfo, "vd", vdminfo };/* * Per-controller state. */struct vdsoftc {	u_short	vd_flags;#define	VD_PRINT	0x1	/* controller info printed */#define	VD_STARTED	0x2	/* start command issued */#define	VD_DOSEEKS	0x4	/* should overlap seeks */#define	VD_SCATGATH	0x8	/* can do scatter-gather commands (correctly) */#define	VD_LOCKED	0x10	/* locked for direct controller access */#define	VD_WAIT		0x20	/* someone needs direct controller access */	u_short	vd_type;	/* controller type */	u_short	vd_wticks;	/* timeout */	u_short	vd_secsize;	/* sector size for controller */	struct	mdcb vd_mdcb;	/* master command block */	u_long	vd_mdcbphys;	/* physical address of vd_mdcb */	struct	dcb vd_dcb;	/* i/o command block */	u_long	vd_dcbphys;	/* physical address of vd_dcb */	struct	vb_buf vd_rbuf;	/* vba resources */} vdsoftc[NVD];#define	VDMAXTIME	20	/* max time for operation, sec. *//* * Per-drive state. */struct	dksoftc {	int	dk_state;	/* open fsm */#ifndef SECSIZE	u_short	dk_bshift;	/* shift for * (DEV_BSIZE / sectorsize) XXX */#endif SECSIZE	int	dk_wlabel;	/* label sector is currently writable */	u_long	dk_copenpart;	/* character units open on this drive */	u_long	dk_bopenpart;	/* block units open on this drive */	u_long	dk_openpart;	/* all units open on this drive */	u_int	dk_curcyl;	/* last selected cylinder */	struct	skdcb dk_dcb;	/* seek command block */	u_long	dk_dcbphys;	/* physical address of dk_dcb */	int	df_reg[3];	/* for formatting, in-out parameters */} dksoftc[NDK];/* * Drive states.  Used during steps of open/initialization. * States < OPEN (> 0) are transient, during an open operation. * OPENRAW is used for unlabeled disks, to allow format operations. */#define	CLOSED		0		/* disk is closed */#define	WANTOPEN	1		/* open requested, not started */#define	WANTOPENRAW	2		/* open requested, no label */#define	RDLABEL		3		/* reading pack label */#define	OPEN		4		/* intialized and ready */#define	OPENRAW		5		/* open, no label */struct	buf dkutab[NDK];	/* i/o queue headers */struct	disklabel dklabel[NDK];	/* pack labels */#define b_cylin	b_resid#define	b_track	b_error		/* used for seek commands */#define	b_seekf	b_forw		/* second queue on um_tab */#define	b_seekl	b_back		/* second queue on um_tab */int	vdwstart, vdwatch();/* * See if the controller is really there; if so, initialize it. */vdprobe(reg, vm)	caddr_t reg;	struct vba_ctlr *vm;{	register br, cvec;		/* must be r12, r11 */	register struct vddevice *vdaddr = (struct vddevice *)reg;	struct vdsoftc *vd;	int s;#ifdef lint	br = 0; cvec = br; br = cvec;	vdintr(0);#endif	if (badaddr((caddr_t)reg, 2))		return (0);	vd = &vdsoftc[vm->um_ctlr];	vdaddr->vdreset = 0xffffffff;	DELAY(1000000);	if (vdaddr->vdreset != (unsigned)0xffffffff) {		vd->vd_type = VDTYPE_VDDC;		vd->vd_flags &= ~VD_DOSEEKS;		DELAY(1000000);	} else {		vd->vd_type = VDTYPE_SMDE;		vd->vd_flags |= VD_DOSEEKS;		vdaddr->vdrstclr = 0;		DELAY(3000000);	}	vd->vd_mdcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_mdcb);	vd->vd_dcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_dcb);	vm->um_addr = reg;		/* XXX */	s = spl7();	if (vdinit_ctlr(vm, vd) == 0) {		splx(s);		return (0);	}	if (vd->vd_type == VDTYPE_SMDE) {#ifdef notdef		/*		 * Attempt PROBE to get all drive status;		 * we take advantage of this in vdreset_drive		 * to try to avoid guessing games.		 */		(void) vdcmd(vm, VDOP_PROBE, 5, 0);#endif		/*		 * Check for scatter-gather by checking firmware date		 * with IDENT command.  The date is printed when		 * vdslave is first called, thus this must be		 * the last controller operation in vdprobe.		 */		vd->vd_dcb.trail.idtrail.date = 0;		if (vdcmd(vm, VDOP_IDENT, 10, 0)) {			uncache(&vd->vd_dcb.trail.idtrail.date);			if (vd->vd_dcb.trail.idtrail.date != 0)				vd->vd_flags |= VD_SCATGATH;		}	}	splx(s);	/*	 * Allocate page tables and i/o buffer.	 */	if (vbainit(&vd->vd_rbuf, MAXPHYS,	    vd->vd_type == VDTYPE_VDDC ? VB_24BIT : VB_32BIT) == 0) {		printf("vd%d: vbainit failed\n", vm->um_ctlr);		return (0);	}	br = 0x17, cvec = 0xe0 + vm->um_ctlr;	/* XXX */	return (sizeof (struct vddevice));}/* * See if a drive is really there. * * Can't read pack label here as various data structures * aren't setup for doing a read in a straightforward * manner.  Instead just probe for the drive and leave * the pack label stuff to the attach routine. *//* ARGSUSED */vdslave(vi, vdaddr)	register struct vba_device *vi;	struct vddevice *vdaddr;{	register struct disklabel *lp = &dklabel[vi->ui_unit];	register struct dksoftc *dk = &dksoftc[vi->ui_unit];	struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];	int bcd();	if ((vd->vd_flags&VD_PRINT) == 0) {		printf("vd%d: %s controller", vi->ui_ctlr,		    vd->vd_type == VDTYPE_VDDC ? "VDDC" : "SMDE");		if (vd->vd_flags & VD_SCATGATH) {			char rev[5];			bcopy((caddr_t)&vd->vd_dcb.trail.idtrail.rev, rev,			    sizeof(vd->vd_dcb.trail.idtrail.rev));			printf(" firmware rev %s (%d-%d-%d)", rev,			    bcd((vd->vd_dcb.trail.idtrail.date >> 8) & 0xff),			    bcd(vd->vd_dcb.trail.idtrail.date & 0xff),			    bcd((vd->vd_dcb.trail.idtrail.date >> 16)&0xffff));		}		printf("\n");		vd->vd_flags |= VD_PRINT;	}	/*	 * Initialize label enough to do a reset on	 * the drive.  The remainder of the default	 * label values will be filled in in vdinit	 * at attach time.	 */	if (vd->vd_type == VDTYPE_SMDE)		lp->d_secsize = VD_MAXSECSIZE;	else		lp->d_secsize = VDDC_SECSIZE;	lp->d_nsectors = 66;		/* only used on smd-e */	lp->d_ntracks = 23;	lp->d_ncylinders = 850;	lp->d_secpercyl = 66*23;	lp->d_rpm = 3600;	lp->d_npartitions = 1;	lp->d_partitions[0].p_offset = 0;	lp->d_partitions[0].p_size = LABELSECTOR + 1;	/*	 * Initialize invariant portion of	 * dcb used for overlapped seeks.	 */	dk->dk_dcb.opcode = VDOP_SEEK;	dk->dk_dcb.intflg = DCBINT_NONE | DCBINT_PBA;	dk->dk_dcb.devselect = vi->ui_slave;	dk->dk_dcb.trailcnt = sizeof (struct trseek) / sizeof (long);	dk->dk_dcb.trail.sktrail.skaddr.sector = 0;	dk->dk_dcbphys = vtoph((struct proc *)0, (unsigned)&dk->dk_dcb);#ifndef SECSIZE	vd_setsecsize(dk, lp);#endif	return (vdreset_drive(vi));}static intbcd(n)	register u_int n;{	register int bin = 0;	register int mul = 1;	while (n) {		bin += (n & 0xf) * mul;		n >>= 4;		mul *= 10;	}	return (bin);}vdattach(vi)	register struct vba_device *vi;{	register int unit = vi->ui_unit;	register struct disklabel *lp = &dklabel[unit];	/*	 * Try to initialize device and read pack label.	 */	if (vdinit(vdminor(unit, 0), 0) != 0) {		printf(": unknown drive type");		return;	}	if (dksoftc[unit].dk_state == OPEN)		printf(": %s <secsize %d, ntrak %d, ncyl %d, nsec %d>",		    lp->d_typename, lp->d_secsize,		    lp->d_ntracks, lp->d_ncylinders, lp->d_nsectors);	/*	 * (60 / rpm) / (sectors per track * (bytes per sector / 2))	 */	if (vi->ui_dk >= 0)		dk_wpms[vi->ui_dk] =		    (lp->d_rpm * lp->d_nsectors * lp->d_secsize) / 120;#ifdef notyet	addswap(makedev(VDMAJOR, vdminor(unit, 0)), lp);#endif}vdopen(dev, flags, fmt)	dev_t dev;	int flags, fmt;{	register unit = vdunit(dev);	register struct disklabel *lp;	register struct dksoftc *dk;	register struct partition *pp;	struct vba_device *vi;	int s, error = 0, part = vdpart(dev), mask = 1 << part;	daddr_t start, end;	if (unit >= NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)		return (ENXIO);	lp = &dklabel[unit];	dk = &dksoftc[unit];	s = spl7();	while (dk->dk_state != OPEN && dk->dk_state != OPENRAW &&	    dk->dk_state != CLOSED)		if (error = tsleep((caddr_t)dk, (PZERO+1) | PCATCH, devopn, 0))			break;	splx(s);	if (error)		return (error);	if (dk->dk_state != OPEN && dk->dk_state != OPENRAW)		if (error = vdinit(dev, flags))			return (error);	if (vdwstart == 0) {		timeout(vdwatch, (caddr_t)0, hz);		vdwstart++;	}	/*	 * Warn if a partion is opened	 * that overlaps another partition which is open	 * unless one is the "raw" partition (whole disk).	 */#define	RAWPART		8		/* 'x' partition */	/* XXX */	if ((dk->dk_openpart & mask) == 0 && part != RAWPART) {		pp = &lp->d_partitions[part];		start = pp->p_offset;		end = pp->p_offset + pp->p_size;		for (pp = lp->d_partitions;		     pp < &lp->d_partitions[lp->d_npartitions]; pp++) {			if (pp->p_offset + pp->p_size <= start ||			    pp->p_offset >= end)				continue;			if (pp - lp->d_partitions == RAWPART)				continue;			if (dk->dk_openpart & (1 << (pp - lp->d_partitions)))				log(LOG_WARNING,				    "dk%d%c: overlaps open partition (%c)\n",				    unit, part + 'a',				    pp - lp->d_partitions + 'a');		}	}	if (part >= lp->d_npartitions)		return (ENXIO);	dk->dk_openpart |= mask;	switch (fmt) {	case S_IFCHR:		dk->dk_copenpart |= mask;		break;	case S_IFBLK:		dk->dk_bopenpart |= mask;		break;	}	return (0);}/* ARGSUSED */vdclose(dev, flags, fmt)	dev_t dev;	int flags, fmt;{	register int unit = vdunit(dev);	register struct dksoftc *dk = &dksoftc[unit];	int part = vdpart(dev), mask = 1 << part;	switch (fmt) {	case S_IFCHR:		dk->dk_copenpart &= ~mask;		break;	case S_IFBLK:		dk->dk_bopenpart &= ~mask;		break;	}	if (((dk->dk_copenpart | dk->dk_bopenpart) & mask) == 0)		dk->dk_openpart &= ~mask;	/*	 * Should wait for i/o to complete on this partition	 * even if others are open, but wait for work on blkflush().	 */	if (dk->dk_openpart == 0) {		int s = spl7();		while (dkutab[unit].b_actf)			sleep((caddr_t)dk, PZERO-1);		splx(s);		dk->dk_state = CLOSED;		dk->dk_wlabel = 0;	}	return (0);}vdinit(dev, flags)	dev_t dev;	int flags;{	register struct disklabel *lp;	register struct dksoftc *dk;	struct vba_device *vi;	int unit = vdunit(dev), error = 0;	char *msg, *readdisklabel();	extern int cold;	dk = &dksoftc[unit];	if (flags & O_NDELAY) {		dk->dk_state = OPENRAW;		return (0);	}	dk->dk_state = RDLABEL;	lp = &dklabel[unit];	vi = vddinfo[unit];	if (msg = readdisklabel(dev, vdstrategy, lp)) {		if (cold) {			printf(": %s", msg);			dk->dk_state = CLOSED;		} else {			log(LOG_ERR, "dk%d: %s\n", unit, msg);			dk->dk_state = OPENRAW;		}#ifdef COMPAT_42		vdlock(vi->ui_ctlr);		if (vdmaptype(vi, lp))			dk->dk_state = OPEN;		vdunlock(vi->ui_ctlr);#endif	} else {		/*		 * Now that we have the label, configure		 * the correct drive parameters.		 */		vdlock(vi->ui_ctlr);		if (vdreset_drive(vi))			dk->dk_state = OPEN;		else {			dk->dk_state = CLOSED;			error = ENXIO;		}		vdunlock(vi->ui_ctlr);	}#ifndef SECSIZE	vd_setsecsize(dk, lp);#endif	wakeup((caddr_t)dk);	return (error);}#ifndef SECSIZEvd_setsecsize(dk, lp)	register struct dksoftc *dk;	register struct disklabel *lp;{	int mul;	/*	 * Calculate scaling shift for mapping	 * DEV_BSIZE blocks to drive sectors.	 */	mul = DEV_BSIZE / lp->d_secsize;	dk->dk_bshift = 0;	while ((mul >>= 1) > 0)		dk->dk_bshift++;}#endif SECSIZE/*ARGSUSED*/vddgo(vm)	struct vba_device *vm;{}vdstrategy(bp)	register struct buf *bp;{	register struct vba_device *vi;	register struct disklabel *lp;	register struct dksoftc *dk;	register int unit;	register daddr_t sn;	struct buf *dp;	daddr_t sz, maxsz;	int part, s;	unit = vdunit(bp->b_dev);	if (unit >= NDK) {

⌨️ 快捷键说明

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