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

📄 rz.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	bp->b_flags |= B_ERROR;done:	biodone(bp);}voidrzstart(unit)	int unit;{	register struct rz_softc *sc = &rz_softc[unit];	register struct buf *bp = sc->sc_tab.b_actf;	register int n;	sc->sc_cmd.buf = bp->b_un.b_addr;	sc->sc_cmd.buflen = bp->b_bcount;	if (sc->sc_format_pid || (sc->sc_flags & RZF_SENSEINPROGRESS)) {		sc->sc_cmd.flags = !(bp->b_flags & B_READ) ?			SCSICMD_DATA_TO_DEVICE : 0;		sc->sc_cmd.cmd = sc->sc_cdb.cdb;		sc->sc_cmd.cmdlen = sc->sc_cdb.len;	} else {		if (bp->b_flags & B_READ) {			sc->sc_cmd.flags = 0;			sc->sc_rwcmd.command = SCSI_READ_EXT;		} else {			sc->sc_cmd.flags = SCSICMD_DATA_TO_DEVICE;			sc->sc_rwcmd.command = SCSI_WRITE_EXT;		}		sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd;		sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd);		n = bp->b_cylin;		sc->sc_rwcmd.highAddr = n >> 24;		sc->sc_rwcmd.midHighAddr = n >> 16;		sc->sc_rwcmd.midLowAddr = n >> 8;		sc->sc_rwcmd.lowAddr = n;		n = howmany(bp->b_bcount, sc->sc_blksize);		sc->sc_rwcmd.highBlockCount = n >> 8;		sc->sc_rwcmd.lowBlockCount = n;#ifdef DEBUG		if ((bp->b_bcount & (sc->sc_blksize - 1)) != 0)			printf("rz%d: partial block xfer -- %x bytes\n",				unit, bp->b_bcount);#endif		sc->sc_stats.rztransfers++;		if ((n = sc->sc_sd->sd_dk) >= 0) {			dk_busy |= 1 << n;			++dk_seek[n];			++dk_xfer[n];			dk_wds[n] += bp->b_bcount >> 6;		}	}	/* tell controller to start this command */	(*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd);}/* * This is called by the controller driver when the command is done. */voidrzdone(unit, error, resid, status)	register int unit;	int error;		/* error number from errno.h */	int resid;		/* amount not transfered */	int status;		/* SCSI status byte */{	register struct rz_softc *sc = &rz_softc[unit];	register struct buf *bp = sc->sc_tab.b_actf;	register struct scsi_device *sd = sc->sc_sd;	extern int cold;	if (bp == NULL) {		printf("rz%d: bp == NULL\n", unit);		return;	}	if (sd->sd_dk >= 0)		dk_busy &= ~(1 << sd->sd_dk);	if (sc->sc_flags & RZF_SENSEINPROGRESS) {		sc->sc_flags &= ~RZF_SENSEINPROGRESS;		sc->sc_tab.b_actf = bp = bp->b_actf;	/* remove sc_errbuf */		if (error || (status & SCSI_STATUS_CHECKCOND)) {#ifdef DEBUG			if (rzdebug & RZB_ERROR)				printf("rz%d: error reading sense data: error %d scsi status 0x%x\n",					unit, error, status);#endif			/*			 * We got an error during the REQUEST_SENSE,			 * fill in no sense for data.			 */			sc->sc_sense.sense[0] = 0x70;			sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE;		} else if (!cold) {			printf("rz%d: ", unit);			scsiPrintSense((ScsiClass7Sense *)sc->sc_sense.sense,				sizeof(sc->sc_sense.sense) - resid);		}	} else if (error || (status & SCSI_STATUS_CHECKCOND)) {#ifdef DEBUG		if (!cold && (rzdebug & RZB_ERROR))			printf("rz%d: error %d scsi status 0x%x\n",				unit, error, status);#endif		/* save error info */		sc->sc_sense.status = status;		bp->b_flags |= B_ERROR;		bp->b_error = error;		bp->b_resid = resid;		if (status & SCSI_STATUS_CHECKCOND) {			/*			 * Start a REQUEST_SENSE command.			 * Since we are called at interrupt time, we can't			 * wait for the command to finish; that's why we use			 * the sc_flags field.			 */			sc->sc_flags |= RZF_SENSEINPROGRESS;			sc->sc_cdb.len = sizeof(ScsiGroup0Cmd);			scsiGroup0Cmd(SCSI_REQUEST_SENSE, sd->sd_slave, 0,				sizeof(sc->sc_sense.sense),				(ScsiGroup0Cmd *)sc->sc_cdb.cdb);			sc->sc_errbuf.b_flags = B_BUSY | B_PHYS | B_READ;			sc->sc_errbuf.b_bcount = sizeof(sc->sc_sense.sense);			sc->sc_errbuf.b_un.b_addr = (caddr_t)sc->sc_sense.sense;			sc->sc_errbuf.b_actf = bp;			sc->sc_tab.b_actf = &sc->sc_errbuf;			rzstart(unit);			return;		}	} else {		sc->sc_sense.status = status;		bp->b_resid = resid;	}	sc->sc_tab.b_actf = bp->b_actf;	biodone(bp);	if (sc->sc_tab.b_actf)		rzstart(unit);	else {		sc->sc_tab.b_active = 0;		/* finish close protocol */		if (sc->sc_openpart == 0)			wakeup((caddr_t)&sc->sc_tab);	}}/* * Read or constuct a disklabel */voidrzgetinfo(dev)	dev_t dev;{	register int unit = rzunit(dev);	register struct rz_softc *sc = &rz_softc[unit];	register struct disklabel *lp = &sc->sc_label;	register int i;	char *msg;	int part;	extern char *readdisklabel();	part = rzpart(dev);	sc->sc_flags |= RZF_HAVELABEL;	lp->d_type = DTYPE_SCSI;	lp->d_secsize = DEV_BSIZE;	lp->d_secpercyl = 1 << sc->sc_bshift;	lp->d_npartitions = MAXPARTITIONS;	lp->d_partitions[part].p_offset = 0;	lp->d_partitions[part].p_size = sc->sc_blks;	/*	 * Now try to read the disklabel	 */	msg = readdisklabel(dev, rzstrategy, lp);	if (msg == NULL)		return;	printf("rz%d: WARNING: %s\n", unit, msg);	sc->sc_label.d_magic = DISKMAGIC;	sc->sc_label.d_magic2 = DISKMAGIC;	sc->sc_label.d_type = DTYPE_SCSI;	sc->sc_label.d_subtype = 0;	sc->sc_label.d_typename[0] = '\0';	sc->sc_label.d_secsize = DEV_BSIZE;	sc->sc_label.d_secperunit = sc->sc_blks;	sc->sc_label.d_npartitions = MAXPARTITIONS;	sc->sc_label.d_bbsize = BBSIZE;	sc->sc_label.d_sbsize = SBSIZE;	for (i = 0; i < MAXPARTITIONS; i++) {		sc->sc_label.d_partitions[i].p_size =			rzdefaultpart[i].nblocks;		sc->sc_label.d_partitions[i].p_offset =			rzdefaultpart[i].strtblk;	}	sc->sc_label.d_partitions[RAWPART].p_size = sc->sc_blks;}intrzopen(dev, flags, mode, p)	dev_t dev;	int flags, mode;	struct proc *p;{	register int unit = rzunit(dev);	register struct rz_softc *sc = &rz_softc[unit];	register struct disklabel *lp;	register int i;	int part;	u_long mask;	if (unit >= NRZ || !(sc->sc_flags & RZF_ALIVE))		return (ENXIO);	/* try to read disk label and partition table information */	part = rzpart(dev);	if (!(sc->sc_flags & RZF_HAVELABEL))		rzgetinfo(dev);	lp = &sc->sc_label;	if (part >= lp->d_npartitions || lp->d_partitions[part].p_size == 0)		return (ENXIO);	/*	 * Warn if a partition is opened that overlaps another	 * already open, unless either is the `raw' partition	 * (whole disk).	 */	mask = 1 << part;	if ((sc->sc_openpart & mask) == 0 && part != RAWPART) {		register struct partition *pp;		u_long start, end;		pp = &lp->d_partitions[part];		start = pp->p_offset;		end = pp->p_offset + pp->p_size;		for (pp = lp->d_partitions, i = 0;		     i < lp->d_npartitions; pp++, i++) {			if (pp->p_offset + pp->p_size <= start ||			    pp->p_offset >= end || i == RAWPART)				continue;			if (sc->sc_openpart & (1 << i))				log(LOG_WARNING,				    "rz%d%c: overlaps open partition (%c)\n",				    unit, part + 'a', i + 'a');		}	}	switch (mode) {	case S_IFCHR:		sc->sc_copenpart |= mask;		break;	case S_IFBLK:		sc->sc_bopenpart |= mask;		break;	}	sc->sc_openpart |= mask;	if (sc->sc_sd->sd_dk >= 0)		dk_wpms[sc->sc_sd->sd_dk] = sc->sc_wpms;	return (0);}rzclose(dev, flags, mode)	dev_t dev;	int flags, mode;{	register struct rz_softc *sc = &rz_softc[rzunit(dev)];	u_long mask = (1 << rzpart(dev));	int s;	switch (mode) {	case S_IFCHR:		sc->sc_copenpart &= ~mask;		break;	case S_IFBLK:		sc->sc_bopenpart &= ~mask;		break;	}	sc->sc_openpart = sc->sc_copenpart | sc->sc_bopenpart;	/*	 * Should wait for I/O to complete on this partition even if	 * others are open, but wait for work on blkflush().	 */	if (sc->sc_openpart == 0) {		s = splbio();		while (sc->sc_tab.b_actf)			sleep((caddr_t)&sc->sc_tab, PZERO - 1);		splx(s);		sc->sc_flags &= ~RZF_WLABEL;	}	return (0);}intrzread(dev, uio)	dev_t dev;	struct uio *uio;{	register struct rz_softc *sc = &rz_softc[rzunit(dev)];	if (sc->sc_format_pid && sc->sc_format_pid != curproc->p_pid)		return (EPERM);	return (physio(rzstrategy, (struct buf *)0, dev,		B_READ, minphys, uio));}intrzwrite(dev, uio)	dev_t dev;	struct uio *uio;{	register struct rz_softc *sc = &rz_softc[rzunit(dev)];	if (sc->sc_format_pid && sc->sc_format_pid != curproc->p_pid)		return (EPERM);	return (physio(rzstrategy, (struct buf *)0, dev,		B_WRITE, minphys, uio));}intrzioctl(dev, cmd, data, flag, p)	dev_t dev;	int cmd;	caddr_t data;	int flag;	struct proc *p;{	register struct rz_softc *sc = &rz_softc[rzunit(dev)];	int error;	int flags;	switch (cmd) {	default:		return (EINVAL);	case SDIOCSFORMAT:		/* take this device into or out of "format" mode */		if (suser(p->p_ucred, &p->p_acflag))			return (EPERM);		if (*(int *)data) {			if (sc->sc_format_pid)				return (EPERM);			sc->sc_format_pid = p->p_pid;		} else			sc->sc_format_pid = 0;		return (0);	case SDIOCGFORMAT:		/* find out who has the device in format mode */		*(int *)data = sc->sc_format_pid;		return (0);	case SDIOCSCSICOMMAND:		/*		 * Save what user gave us as SCSI cdb to use with next		 * read or write to the char device.		 */		if (sc->sc_format_pid != p->p_pid)			return (EPERM);		if (legal_cmds[((struct scsi_fmt_cdb *)data)->cdb[0]] == 0)			return (EINVAL);		bcopy(data, (caddr_t)&sc->sc_cdb, sizeof(sc->sc_cdb));		return (0);	case SDIOCSENSE:		/*		 * return the SCSI sense data saved after the last		 * operation that completed with "check condition" status.		 */		bcopy((caddr_t)&sc->sc_sense, data, sizeof(sc->sc_sense));		return (0);	case DIOCGDINFO:		/* get the current disk label */		*(struct disklabel *)data = sc->sc_label;		return (0);	case DIOCSDINFO:		/* set the current disk label */		if (!(flag & FWRITE))			return (EBADF);		error = setdisklabel(&sc->sc_label,			(struct disklabel *)data,			(sc->sc_flags & RZF_WLABEL) ? 0 : sc->sc_openpart);		return (error);	case DIOCGPART:		/* return the disk partition data */		((struct partinfo *)data)->disklab = &sc->sc_label;		((struct partinfo *)data)->part =			&sc->sc_label.d_partitions[rzpart(dev)];		return (0);	case DIOCWLABEL:		if (!(flag & FWRITE))			return (EBADF);		if (*(int *)data)			sc->sc_flags |= RZF_WLABEL;		else			sc->sc_flags &= ~RZF_WLABEL;		return (0);	case DIOCWDINFO:		/* write the disk label to disk */		if (!(flag & FWRITE))			return (EBADF);		error = setdisklabel(&sc->sc_label,			(struct disklabel *)data,			(sc->sc_flags & RZF_WLABEL) ? 0 : sc->sc_openpart);		if (error)			return (error);		/* simulate opening partition 0 so write succeeds */		flags = sc->sc_flags;		sc->sc_flags = RZF_ALIVE | RZF_WLABEL;		error = writedisklabel(dev, rzstrategy, &sc->sc_label);		sc->sc_flags = flags;		return (error);	}	/*NOTREACHED*/}intrzsize(dev)	dev_t dev;{	register int unit = rzunit(dev);	register int part = rzpart(dev);	register struct rz_softc *sc = &rz_softc[unit];	if (unit >= NRZ || !(sc->sc_flags & RZF_ALIVE))		return (-1);	/*	 * We get called very early on (via swapconf)	 * without the device being open so we need to	 * read the disklabel here.	 */	if (!(sc->sc_flags & RZF_HAVELABEL))		rzgetinfo(dev);	if (part >= sc->sc_label.d_npartitions)		return (-1);	return (sc->sc_label.d_partitions[part].p_size);}/* * Non-interrupt driven, non-dma dump routine. */intrzdump(dev)	dev_t dev;{#ifdef notdef	int part = rzpart(dev);	int unit = rzunit(dev);	register struct rz_softc *sc = &rz_softc[unit];	register struct scsi_device *sd = sc->sc_hd;	register daddr_t baddr;	register int maddr;	register int pages, i;	int stat;	extern int lowram;	/*	 * Hmm... all vax drivers dump maxfree pages which is physmem minus	 * the message buffer.  Is there a reason for not dumping the	 * message buffer?  Savecore expects to read 'dumpsize' pages of	 * dump, where dumpsys() sets dumpsize to physmem!	 */	pages = physmem;	/* is drive ok? */	if (unit >= NRZ || (sc->sc_flags & RZF_ALIVE) == 0)		return (ENXIO);	/* dump parameters in range? */	if (dumplo < 0 || dumplo >= sc->sc_info.part[part].nblocks)		return (EINVAL);	if (dumplo + ctod(pages) > sc->sc_info.part[part].nblocks)		pages = dtoc(sc->sc_info.part[part].nblocks - dumplo);	maddr = lowram;	baddr = dumplo + sc->sc_info.part[part].strtblk;	/* scsi bus idle? */	if (!scsireq(&sc->sc_dq)) {		scsireset(sd->sd_ctlr);		sc->sc_stats.rzresets++;		printf("[ drive %d reset ] ", unit);	}	for (i = 0; i < pages; i++) {#define NPGMB	(1024*1024/NBPG)		/* print out how many Mbs we have dumped */		if (i && (i % NPGMB) == 0)			printf("%d ", i / NPGMB);#undef NPBMG		mapin(mmap, (u_int)vmmap, btop(maddr), PG_URKR|PG_CI|PG_V);		stat = scsi_tt_write(sd->sd_ctlr, sd->sd_drive, sd->sd_slave,				     vmmap, NBPG, baddr, sc->sc_bshift);		if (stat) {			printf("rzdump: scsi write error 0x%x\n", stat);			return (EIO);		}		maddr += NBPG;		baddr += ctod(1);	}	return (0);#else /* notdef */	return (ENXIO);#endif /* notdef */}#endif

⌨️ 快捷键说明

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