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

📄 sd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1992 OMRON Corporation. * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * OMRON Corporation. * * 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. * *	@(#)sd.c	8.3 (Berkeley) 12/7/93 *//* * sd.c -- SCSI Disk Device Driver * remaked by A.Fujita, MAR-22-1992 *//* * SCSI CCS (Command Command Set) disk driver. */#include "sd.h"#if NSD > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/buf.h>#include <sys/dkstat.h>#include <sys/proc.h>#include <sys/disklabel.h>#include <luna68k/dev/device.h>#include <luna68k/dev/screg.h>#include <luna68k/dev/scvar.h>int	sdinit(), sdstrategy(), sdstart(), sdintr();struct	driver sddriver = {	sdinit, "sd", sdstart, (int (*)()) 0, sdintr, (int (*)()) 0};struct	disklabel sdlabel[NSD];struct	sd_softc {	struct	hp_device *sc_hd;	struct	scsi_queue sc_dq;	short	sc_flags;	short	sc_type;	/* drive type */	short	sc_punit;	/* physical unit (scsi lun) */	u_int	sc_blks;	/* number of blocks on device */	int	sc_blksize;	/* device block size in bytes */	u_int	sc_wpms;	/* average xfer rate in 16 bit wds/sec. */} sd_softc[NSD];/* sc_flags values */#define	SDF_ALIVE	0x1struct	buf sdtab[NSD];struct	scsi_fmt_sense sdsense[NSD];static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };#define	sdunit(x)	((minor(x) >> 3) & 0x7)#define sdpart(x)	(minor(x) & 0x7)#define	sdpunit(x)	((x) & 7)#define sdminor(unit, part)	(((unit) << 3) | (part))#define	b_lba		b_resid#define	SDRETRY		3	/* IO retry count */struct sd_iostat {	int imax;	int imin;	int omax;	int omin;};struct sd_iostat sd_iostat[NSD] = {	{ 14000, -1, 100, -1 },};/* * Initialize */intsdinit(hd)	register struct hp_device *hd;{	register struct sd_softc *sc = &sd_softc[hd->hp_unit];	register struct disklabel *lp;	char *msg, *sdreadlabel();	sc->sc_hd = hd;	sc->sc_punit = sdpunit(hd->hp_flags);	sc->sc_type = sdident(sc, hd);	if (sc->sc_type < 0)		return(0);	sc->sc_dq.dq_ctlr = hd->hp_ctlr;	sc->sc_dq.dq_unit = hd->hp_unit;	sc->sc_dq.dq_slave = hd->hp_slave;	sc->sc_dq.dq_driver = &sddriver;	/*	 * Use the default sizes until we've read the label,	 * or longer if there isn't one there.	 */	lp = &sdlabel[hd->hp_unit];	if (lp->d_secpercyl == 0) {		lp->d_secsize = DEV_BSIZE;		lp->d_nsectors = 32;		lp->d_ntracks = 20;		lp->d_secpercyl = 32*20;		lp->d_npartitions = 1;		lp->d_partitions[0].p_offset = 0;		lp->d_partitions[0].p_size = LABELSECTOR + 1;	}	/*	 * read disklabel	 */	if (msg = sdreadlabel(makedev(4, (hd->hp_unit<<3)), sdstrategy, lp)) {		if (msg != NULL) {			printf("sd%d: %s\n", hd->hp_unit, msg);			return(0);		}	}	sc->sc_flags = SDF_ALIVE;	return(1);}static struct scsi_inquiry inqbuf;static struct scsi_fmt_cdb inq = {	6,	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0};static u_long capbuf[2];struct scsi_fmt_cdb cap = {	10,	CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0};intsdident(sc, hd)	struct sd_softc *sc;	struct hp_device *hd;{	char idstr[32];	int unit;	register int ctlr, slave;	register int i;	register int tries = 10;	ctlr = hd->hp_ctlr;	slave = hd->hp_slave;	unit = sc->sc_punit;	/*	 * See if unit exists and is a disk then read block size & nblocks.	 */	while ((i = sc_test_unit_rdy(ctlr, slave, unit)) != 0) {		if (i < 0 || --tries < 0)			return (-1);		if (i == STS_CHECKCOND) {			u_char sensebuf[8];			struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;			sc_request_sense(ctlr, slave, unit, sensebuf, 8);			if (sp->class == 7 && sp->key == 6)				/* drive doing an RTZ -- give it a while */				DELAY(1000000);		}		DELAY(1000);	}	if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf,			       sizeof(inqbuf)) ||	    scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf,			       sizeof(capbuf)))		/* doesn't exist or not a CCS device */		return (-1);	switch (inqbuf.type) {	case 0:		/* disk */	case 4:		/* WORM */	case 5:		/* CD-ROM */	case 7:		/* Magneto-optical */		break;	default:	/* not a disk */		return (-1);	}	sc->sc_blks    = capbuf[0];	sc->sc_blksize = capbuf[1];	bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);	for (i = 27; i > 23; --i)		if (idstr[i] != ' ')			break;	idstr[i+1] = 0;	for (i = 23; i > 7; --i)		if (idstr[i] != ' ')			break;	idstr[i+1] = 0;	for (i = 7; i >= 0; --i)		if (idstr[i] != ' ')			break;	idstr[i+1] = 0;	printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],	       &idstr[24]);	printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);	if (sc->sc_blksize != DEV_BSIZE) {		printf("sd%d: need %d byte blocks - drive ignored\n", unit, DEV_BSIZE);		return(1);	}	sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2);	/* XXX */	return(inqbuf.type);}/* * Open */intsdopen(dev, flags, mode, p)	dev_t dev;	int flags, mode;	struct proc *p;{	register int unit = sdunit(dev);	register struct sd_softc *sc = &sd_softc[unit];	if (unit >= NSD)		return(ENXIO);	if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))		return(ENXIO);	if (sc->sc_hd->hp_dk >= 0)		dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms;	return(0);}/* * Close */intsdclose(dev, flag, mode, p)	dev_t dev;	int flag, mode;	struct proc *p;{	return(0);}/* * Strategy */intsdstrategy(bp)	register struct buf *bp;{	register int unit = sdunit(bp->b_dev);	register int part = sdpart(bp->b_dev);	register struct sd_softc *sc = &sd_softc[unit];	register struct disklabel *lp = &sdlabel[unit];	register struct partition *pp = &(lp->d_partitions[part]);	register struct buf *dp = &sdtab[unit];	register daddr_t bn;	register int sz, s;	bn = bp->b_blkno;	sz = howmany(bp->b_bcount, DEV_BSIZE);	/* check that tracsfer is within a drive's partition */	if (bn < 0 || (bn + sz) > pp->p_size) {		sz = pp->p_size - bn;		if (sz == 0) {			bp->b_resid = bp->b_bcount;			goto done;		}		if (sz < 0) {			bp->b_error = EINVAL;			bp->b_flags |= B_ERROR;			goto done;		}		bp->b_bcount = dbtob(sz);	}	/* calculate LBA for transfer */	bp->b_lba = bn + pp->p_offset;	/* raise priority to block sdintr */	s = splbio();	/* call disksort to sort request into drive queue */	disksort(dp, bp);	if (dp->b_active == 0) {			/*  */		dp->b_active = 1;		sdustart(unit);	}	/* lower priority */	splx(s);	return;done:	biodone(bp);}intsdustart(unit)	register int unit;{	register struct sd_softc *sc = &sd_softc[unit];	register struct hp_device *hp = sc->sc_hd;	register struct scsi_queue *dq = &sc->sc_dq;	register struct buf *bp = sdtab[unit].b_actf;	register struct scsi_fmt_cdb *cmd;	cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;	*(int *)(&cmd->cdb[2]) = bp->b_lba;	*(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE);	dq->dq_cdb   = cmd;	dq->dq_bp    = bp;	dq->dq_flags = DQ_DISCONNECT;	/* SCSI Disconnect */	if (screq(dq))		sdstart(unit);}intsdstart(unit)	register int unit;

⌨️ 快捷键说明

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