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

📄 hd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1988 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Harris Corp. * * 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. * *	@(#)hd.c	7.12 (Berkeley) 12/16/90 */#include "hd.h"#if NHD > 0#include "sys/param.h"#include "sys/buf.h"#include "sys/conf.h"#include "sys/dkstat.h"#include "sys/disklabel.h"#include "sys/file.h"#include "sys/systm.h"#include "sys/vmmac.h"#include "sys/time.h"#include "sys/proc.h"#include "sys/uio.h"#include "sys/syslog.h"#include "sys/kernel.h"#include "sys/ioctl.h"#include "sys/stat.h"#include "sys/errno.h"#include "../include/cpu.h"#include "../include/mtpr.h"#include "../vba/vbavar.h"#include "../vba/hdreg.h"#define	b_cylin	b_resid#define	hdunit(dev)		(minor(dev)>>3)#define	hdpart(dev)		(minor(dev)&0x07)#define	hdminor(unit, part)	(((unit)<<3)|(part))struct vba_ctlr *hdcminfo[NHDC];struct vba_device *hddinfo[NHD];int hdcprobe(), hdslave(), hdattach(), hddgo(), hdstrategy();long hdstd[] = { 0 };struct vba_driver hdcdriver =    { hdcprobe, hdslave, hdattach, hddgo, hdstd, "hd", hddinfo, "hdc", hdcminfo };/* * Per-controller state. */struct hdcsoftc {	u_short	hdc_flags;#define	HDC_INIT	0x01	/* controller initialized */#define	HDC_STARTED	0x02	/* start command issued */#define	HDC_LOCKED	0x04	/* locked for direct controller access */#define	HDC_WAIT	0x08	/* someone needs direct controller access */	u_short	hdc_wticks;		/* timeout */	struct master_mcb *hdc_mcbp;	/* address of controller mcb */	struct registers *hdc_reg;	/* base address of i/o regs */	struct vb_buf hdc_rbuf;		/* vba resources */	struct master_mcb hdc_mcb;	/* controller mcb */} hdcsoftc[NHDC];#define	HDCMAXTIME	20		/* max time for operation, sec. */#define	HDCINTERRUPT	0xf0		/* interrupt vector *//* * Per-drive state; probably everything should be "hd_", not "dk_", * but it's not worth it, and dk is a better mnemonic for disk anyway. */struct dksoftc {#ifdef COMPAT_42	u_short	dk_def_cyl;	/* definition track cylinder address */#endif	int	dk_state;	/* open fsm */	u_short	dk_bshift;	/* shift for * (DEV_BSIZE / sectorsize) XXX */	int	dk_wlabel;	/* if label sector is writeable */	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 */	int	dk_unit;	/* unit# */	int	dk_ctlr;	/* controller# */	int	dk_format;	/* if format program is using disk */	struct buf dk_utab;		/* i/o queue header */	struct disklabel dk_label;	/* disklabel for this disk */	struct mcb dk_mcb;		/* disk mcb */} dksoftc[NHD];/* * 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 */int hdcwstart, hdcwatch();/* see if the controller is really there, if so, init it. *//* ARGSUSED */hdcprobe(reg, vm)	caddr_t reg;	/* register */ struct vba_ctlr *vm;{	register int br, cvec;		/* must be r12, r11 */	register struct hdcsoftc *hdc;	static struct module_id id;	struct pte *dummypte;	caddr_t putl;	/* initialize the hdc controller structure. */	hdc = &hdcsoftc[vm->um_ctlr];	if (!vbmemalloc(1, reg, &dummypte, &putl)) {		printf("hdc%d: vbmemalloc failed.\n", vm->um_ctlr);		return(0);	}	hdc->hdc_reg = (struct registers *)putl;	/*	 * try and ping the MID register; side effect of wbadaddr is to read	 * the module id; the controller is bad if it's not an hdc, the hdc's	 * writeable control store is not loaded, or the hdc failed the	 * functional integrity test;	 */	if (wbadaddr(&hdc->hdc_reg->module_id, 4,	    vtoph((struct process *)NULL, &id)))		return(0);	DELAY(10000);	mtpr(PADC, 0);	if (id.module_id != (u_char)HDC_MID) {		printf("hdc%d: bad module id; id = %x.\n",		    vm->um_ctlr, id.module_id);		return(0);	}	if (id.code_rev == (u_char)0xff) {		printf("hdc%d: micro-code not loaded.\n", vm->um_ctlr);		return(0);	}	if (id.fit != (u_char)0xff) {		printf("hdc%d: FIT test failed.\n", vm->um_ctlr);		return(0);	}	/* reset that pup; flag as inited */	hdc->hdc_reg->soft_reset = 0;	DELAY(1000000);	hdc->hdc_flags |= HDC_INIT;	/* allocate page tables and i/o buffer. */	if (!vbainit(&hdc->hdc_rbuf, MAXPHYS, VB_32BIT|VB_SCATTER)) {		printf("hdc%d: vbainit failed\n", vm->um_ctlr);		return (0);	}	/* set pointer to master control block */	hdc->hdc_mcbp =	    (struct master_mcb *)vtoph((struct proc *)NULL, &hdc->hdc_mcb);	br = 0x17, cvec = HDCINTERRUPT + vm->um_ctlr;		/* XXX */	return(sizeof(struct registers));}/* ARGSUSED */hdslave(vi, vdaddr)	struct vba_device *vi;	struct vddevice *vdaddr;{	register struct mcb *mcb;	register struct disklabel *lp;	register struct dksoftc *dk;	static struct status status;	dk = &dksoftc[vi->ui_unit];	dk->dk_unit = vi->ui_unit;	dk->dk_ctlr = vi->ui_ctlr;	mcb = &dk->dk_mcb;	mcb->command = HCMD_STATUS;	mcb->chain[0].wcount = sizeof(struct status) / sizeof(long);	mcb->chain[0].memadr  = (u_long)vtoph((struct process *)0, &status);	if (hdimcb(dk)) {		printf(" (no status)\n");		return(0);	}	/*	 * Report the drive down if anything in the drive status looks bad.	 * If the drive is offline and it is not on cylinder, then the drive	 * is not there.  If there is a fault condition, the hdc will try to	 * clear it when we read the disklabel information.	 */	if (!(status.drs&DRS_ONLINE)) {		if (status.drs&DRS_ON_CYLINDER)			printf(" (not online)\n");		return(0);	}	if (status.drs&DRS_FAULT)		printf(" (clearing fault)");	lp = &dk->dk_label;#ifdef RAW_SIZE	lp->d_secsize = status.bytes_per_sec;#else	lp->d_secsize = 512;#endif	lp->d_nsectors = status.max_sector + 1;	lp->d_ntracks = status.max_head + 1;	lp->d_ncylinders = status.max_cyl + 1;	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;	lp->d_npartitions = 1;	lp->d_partitions[0].p_offset = 0;	lp->d_partitions[0].p_size = LABELSECTOR + 1;	lp->d_rpm = status.rpm;	lp->d_typename[0] = 'h';	lp->d_typename[1] = 'd';	lp->d_typename[2] = '\0';#ifdef COMPAT_42	dk->dk_def_cyl = status.def_cyl;#endif	return(1);}hdattach(vi)	register struct vba_device *vi;{	register struct dksoftc *dk;	register struct disklabel *lp;	register int unit;	unit = vi->ui_unit;	if (hdinit(hdminor(unit, 0), 0)) {		printf(": unknown drive type");		return;	}	dk = &dksoftc[unit];	lp = &dk->dk_label;	hd_setsecsize(dk, lp);	if (dk->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(HDMAJOR, hdminor(unit, 0)), lp);#endif}hdopen(dev, flags, fmt)	dev_t dev;	int flags, fmt;{	register struct disklabel *lp;	register struct dksoftc *dk;	register struct partition *pp;	register int unit;	struct vba_device *vi;	int s, error, part = hdpart(dev), mask = 1 << part;	daddr_t start, end;	unit = hdunit(dev);	if (unit >= NHD || (vi = hddinfo[unit]) == 0 || vi->ui_alive == 0)		return(ENXIO);	dk = &dksoftc[unit];	lp = &dk->dk_label;	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)) {			splx(s);			return (error);		}	splx(s);	if (dk->dk_state != OPEN && dk->dk_state != OPENRAW)		if (error = hdinit(dev, flags))			return(error);	if (hdcwstart == 0) {		timeout(hdcwatch, (caddr_t)0, hz);		hdcwstart++;	}	/*	 * 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,				    "hd%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 */hdclose(dev, flags, fmt)	dev_t dev;	int flags, fmt;{	register struct dksoftc *dk;	int mask;	dk = &dksoftc[hdunit(dev)];	mask = 1 << hdpart(dev);	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 (dk->dk_utab.b_actf)			sleep((caddr_t)dk, PZERO-1);		splx(s);		dk->dk_state = CLOSED;		dk->dk_wlabel = 0;	}	return(0);}hdinit(dev, flags)	dev_t dev;	int flags;{	register struct dksoftc *dk;	register struct disklabel *lp;	struct vba_device *vi;	int error, unit;	char *msg, *readdisklabel();	extern int cold;	vi = hddinfo[unit = hdunit(dev)];	dk = &dksoftc[unit];	dk->dk_unit = vi->ui_slave;	dk->dk_ctlr = vi->ui_ctlr;	if (flags & O_NDELAY) {		dk->dk_state = OPENRAW;		return(0);	}	error = 0;	lp = &dk->dk_label;	dk->dk_state = RDLABEL;	if (msg = readdisklabel(dev, hdstrategy, lp)) {		if (cold) {			printf(": %s\n", msg);			dk->dk_state = CLOSED;		} else {			log(LOG_ERR, "hd%d: %s\n", unit, msg);			dk->dk_state = OPENRAW;		}#ifdef COMPAT_42		hdclock(vi->ui_ctlr);		if (!(error = hdreadgeometry(dk)))			dk->dk_state = OPEN;		hdcunlock(vi->ui_ctlr);#endif	} else		dk->dk_state = OPEN;	wakeup((caddr_t)dk);	return(error);}hd_setsecsize(dk, lp)	register struct dksoftc *dk;	struct disklabel *lp;{	register 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++;}/* ARGSUSED */hddgo(vm)	struct vba_device *vm;{}extern int name_ext;hdstrategy(bp)	register struct buf *bp;{	register struct vba_device *vi;	register struct disklabel *lp;	register struct dksoftc *dk;	struct buf *dp;

⌨️ 快捷键说明

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