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

📄 sd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
			}			sdi = &sddevinfo[ii->ii_type];		}		/*		 * Mode Select		 *	Error Recovery Parameters set		 */		i = *(sdi->ERP_page +1) + 2;	/* page length */		bzero(sdtmp, i + 4);		bcopy(sdi->ERP_page, (caddr_t)&sdtmp[4], i);		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 		uscsi.sc_cpoint = sdtmp;		uscsi.sc_ctrnscnt = i + 4;		uscsi.sc_opcode = SCOP_MSELECT;		uscsi.sc_lad = (SDM_PF << 16);		uscsi.sc_count = i + 4;		(void) sdcmd(dev, &uscsi);		/*		 * Read Grown Defect list		 */		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 		uscsi.sc_cpoint = sdtmp;		uscsi.sc_ctrnscnt = 4;		uscsi.sc_opcode = SCOP_RDL;		uscsi.sc_cdb.un_type1.t1_ladhi = (SDDL_GLIST|SDDL_PHYSFMT) << 8;		uscsi.sc_cdb.un_type1.t1_p3 = 4;		(void) sdcmd(dev, &uscsi);		i = *(short *)&sdtmp[2] / 8;		if (i > (1024*9/10))			printf("sd%d: WARNING: DEFECT SPARE LOCATION < 10%\n",				unit);mo_check_done:		/*		 * Read Capacity		 */		bzero((caddr_t)sdtmp, 8);		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 		uscsi.sc_cpoint = sdtmp;		uscsi.sc_ctrnscnt = 8;		uscsi.sc_opcode = SCOP_RCAP;		(void) sdcmd(dev, &uscsi);		sdd->sdd_nsect = *(int *)&sdtmp[0] + 1;		sdd->sdd_sectsize = *(int *)&sdtmp[4];		if ((sdd->sdd_sectsize != DEV_BSIZE)				&& (sdd->sdd_sectsize != SDBSIZE1K))			sdd->sdd_sectsize = DEV_BSIZE;	}	if ((sdd->sdd_flags & SDDF_WPROTECT) && (flag & FWRITE))		stat = EROFS;pre_open_done:	if (stat == 0) {		if ((isalone(unit) == ONLY_ONE) || media_changed) {			/*			 * read partition information from sector zero.			 */			sdrpartinfo(ii);			if (ii->ii_dk >= 0) {				dk_wpms[ii->ii_dk] =					sdd->sdd_sectsize * sdstdrv[unit].rps					* sdstdrv[unit].nsect / (2 * 1000000);			}		}	} else {		/*		 * open error		 */		*sdopfp = old_sdopf;		if ((sdd->sdd_flags & SDDF_INHRMV) && (isalone(unit) == 0)) {			sdd->sdd_flags &= ~SDDF_INHRMV;			scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 			uscsi.sc_opcode = SCOP_MEDRMV;			uscsi.sc_count = SDRMV_ALLOW;			(void) sdcmd(dev, &uscsi);		}	}	/*	 * UNLOCK open	 */	s = splclock();	sdd->sdd_flags &= ~SDDF_GETTMP;	if (sdtmp_stat & B_WANTED)		wakeup((caddr_t)sdtmp);	sdtmp_stat &= ~(B_BUSY|B_WANTED);	splx(s);	return (stat);}int sd_access_check_on;		/* Common flags for sd_access_check() */sd_access_check(bp)	register struct buf *bp;{	register struct iop/**/_device *ii;	register struct sdd_softc *sdd;	int unit;	int check_part;	int limit;	int over;	register struct size *sizes;	register int lba;	/* logical block address */	register int sz;	register int i;	check_part = 0;	unit = dev2unit(bp->b_dev);	ii = sddinfo[unit];	sdd = &sdd_softc[unit];	sizes = sdstdrv[unit].sizes;	lba = sizes[dev2part(bp->b_dev)].sd_blkoff + dkblock(bp);	sz = howmany(bp->b_bcount, sdd->sdd_sectsize);	/*	 * When block device is used,	 *	inhibit raw device write operation.	 */	if ((major(bp->b_dev) == sd_c_major)			/* RAW I/O */	    && ((bp->b_flags & B_READ) == 0)			/* WRITE */	    && ((ii->ii_flags & SD_F_ENW) == 0)			/* INHIBIT */	    && ((sd_access_check_on & SD_F_ENW) == 0)) {		for (i = 0; i < PNUM; i++) {			if (sd_b_openf[unit][i] == 0)				continue;			/*			 *   |----|========|---|======|-------|			 * 1 |---+++--------------------------| CUT OFF			 * 2 |---++++++++++++-----------------| CUT OFF			 * 3 |---++++++++++++++++-------------| CUT OFF			 * 4 |---++++++++++++++++++++++++-----| CUT OFF			 * 5 |-------+++----------------------| ERROR			 * 6 |------------+++-----------------| ERROR			 * 7 |------------+++++++-------------| ERROR			 * 8 |------------+++++++++++++++-----| ERROR			 */			if ((lba < (sizes[i].sd_blkoff + sizes[i].sd_nblocks))			    && ((lba + sz) > sizes[i].sd_blkoff))				check_part |= (1 << i);		}	}	if (check_part) {		limit = 0x7fffffff;	/* XXX */		for (i = 0; i < PNUM; i++) {			if ((check_part & (1 << i)) == 0)				continue;			if (lba >= sizes[i].sd_blkoff) {				bp->b_flags |= B_ERROR;				bp->b_error = EIO;				bp->b_resid = bp->b_bcount;				printf("sd%d%c: RAW DEVICE WRITE PROTECTED: ",					unit, pname[dev2part(bp->b_dev)]);				printf("sn = 0x%x(%d), off = 0x%x(%d)\n",					dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize,					dkblock(bp)*DEV_BSIZE/sdd->sdd_sectsize,					sizes[dev2part(bp->b_dev)].sd_blkoff,					sizes[dev2part(bp->b_dev)].sd_blkoff);				return (-1);			}			if (sizes[i].sd_blkoff < limit)				limit = sizes[i].sd_blkoff;		}	} else {		limit = sizes[dev2part(bp->b_dev)].sd_blkoff			+ sizes[dev2part(bp->b_dev)].sd_nblocks;	}	if ((over = (lba + sz) - limit) > 0) {		/*		 * Logical Block Address is outside the valid area.		 */		if (((ii->ii_flags & SD_F_EOLBA) != 0)			|| ((sd_access_check_on & SD_F_EOLBA) != 0)) {			/*			 * error if outside LBA			 */			return(-1);		}		bp->b_resid = bp->b_bcount - (sz - over) * sdd->sdd_sectsize;		if (bp->b_resid >= bp->b_bcount) {			bp->b_resid = bp->b_bcount;			return(-1);		}	}	return (0);}sd_b_close(dev, flag)	dev_t dev;	int flag;{	return (_sdclose(dev, flag, S_IFBLK));}sd_c_close(dev, flag)	dev_t dev;	int flag;{	return (_sdclose(dev, flag, S_IFCHR));}_sdclose(dev, flag, fmt)	register dev_t dev;	int flag;	int fmt;{	register struct iop/**/_device *ii;	register struct sdd_softc *sdd;	register int unit;	struct sdc_softc *sdc;	struct scsi uscsi;	struct sc_extnd *sce;	unit = dev2unit(dev);	if (unit >= nsd || (ii = sddinfo[unit]) == 0 || ii->ii_alive == 0)		return (ENXIO);	sdd = &sdd_softc[unit];	sdc = &sdc_softc[ii->ii_ctlr];	sce = (struct sc_extnd *)&sdc_rsense[ii->ii_ctlr][0];	/*	 * still remain jobs	 *	sleep about 10ms -> 1sec	 */	while (ii->ii_mi->im_tab.b_actf != NULL)		sleep((caddr_t)&lbolt, PRIBIO);	if ((fmt & S_IFMT) == S_IFBLK)		sd_b_openf[unit][dev2part(dev)] = 0;	else		sd_c_openf[unit][dev2part(dev)] = 0;	sdd->sdd_flags &= ~SDDF_XUSE;	if ((sdc->sdc_firmware & SDCFW_RMB) && (isalone(unit) == 0)) {		sdd->sdd_flags &= ~SDDF_INHRMV;		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 		uscsi.sc_opcode = SCOP_MEDRMV;		uscsi.sc_count = SDRMV_ALLOW;		(void) sdcmd(dev, &uscsi);	}	return (0);}sdcmd(dev, usc)	dev_t dev;	struct scsi *usc;{	register struct buf *bp;	register struct scsi *ksc;	register u_char *point;	register int unit;	int error;	int s;	int cnt;	if (usc == 0)		return (ENXIO);	error = 0;	unit = dev2unit(dev);	bp = &csdbuf[unit];	/*	 * LOCK csdbuf	 */	s = splclock();	while (bp->b_flags & B_BUSY) {		bp->b_flags |= B_WANTED;		sleep((caddr_t)bp, PRIBIO);	}	bzero((caddr_t)bp, sizeof(struct buf));	bp->b_flags = B_BUSY|B_READ;	splx(s);	ksc = &kernscsi[unit];	bcopy((caddr_t)usc, (caddr_t)ksc, sizeof(struct scsi));	/*	 * setup command buffer	 */	bp->b_dev = dev;	bp->b_proc = curproc;	cnt = ksc->sc_ctrnscnt;	bp->b_bcount = cnt;	point = ksc->sc_cpoint;	bp->b_un.b_addr = (caddr_t)point;	if (cnt > 0) {		if (point == NULL) {			ksc->sc_cpoint = point = get_scsi(unit)->sc_param;			if (cnt > 20) {				error = EFAULT;				goto done;			}		}		if (point < (u_char *)KERNBASE) {			if (useracc(point, cnt, B_WRITE) == NULL) {				error = EFAULT;				goto done;			}			curproc->p_flag |= P_PHYSIO;			vslock(point, cnt);			bp->b_flags |= B_PHYS;		}#ifndef mips		else {			if (kernacc(point, cnt, B_WRITE) == NULL) {				error = EFAULT;				goto done;			}		}#endif		ksc->sc_tstatus = TS_MAPPED_PIO;	/* XXX */	}	/*	 * call strategy entry, and wait command done.	 */	sdstrategy(bp);	iowait(bp);	if ((cnt > 0) && (point < (u_char *)KERNBASE)) {		vsunlock(point, cnt, B_READ);		curproc->p_flag &= ~P_PHYSIO;	}	if ((bp->b_flags & B_ERROR) == 0)		error = 0;	else {		if (bp->b_error)			error = bp->b_error;		else			error = EIO;	}	bcopy((caddr_t)ksc, (caddr_t)usc, sizeof(struct scsi));done:	/*	 * UNLOCK csdbuf	 */	s = splclock();	if (bp->b_flags & B_WANTED)		wakeup((caddr_t)bp);	bp->b_flags = 0;	splx(s);	return (error);}/* * read partition information from sector zero. */sdrpartinfo(ii)	register struct iop/**/_device *ii;{	register struct disklabel *dlp;	register struct sdst *hsp;	register struct sdst *st;	register int unit;	register int i;	struct firstsector *fsp;	struct sdc_softc *sdc;	struct sdd_softc *sdd;	struct sddevinfo *sdi;	struct scsi uscsi;	int s;	sdi = &sddevinfo[ii->ii_type];	unit = ii->ii_unit;	sdd = &sdd_softc[unit];	sdc = &sdc_softc[ii->ii_ctlr];	if ((sdd->sdd_flags & (SDDF_NONFMT|SDDF_FMTDONE)) == 0) {		register struct sc_rcap *scr = (struct sc_rcap *)sdtmp;		sdd->sdd_flags |= SDDF_FMTDONE;		bzero((caddr_t)sdtmp, 8);		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 		uscsi.sc_cpoint = (u_char *)scr;		uscsi.sc_ctrnscnt = 8;		uscsi.sc_opcode = SCOP_RCAP;		(void) sdcmd(unit << 3, &uscsi);		sdd->sdd_nsect = scr->scr_nblock + 1;		sdd->sdd_sectsize = scr->scr_blocklen;		if (sdd->sdd_sectsize == 0)			sdd->sdd_sectsize = SDBSIZE1K;	}	bzero(sdtmp, DEV_BSIZE);	if ((sdd->sdd_flags & SDDF_NONFMT) == 0) {		scinit(&uscsi, ii->ii_slave, sdd->sdd_sectsize); 		uscsi.sc_cpoint = sdtmp;		uscsi.sc_ctrnscnt = DEV_BSIZE;		uscsi.sc_opcode = SCOP_READ;		uscsi.sc_lad = 0;		uscsi.sc_count = 1;		(void) sdcmd(unit << 3, &uscsi);		sdd->sdd_flags &= ~SDDF_SKIPCHECK;	}	fsp = (struct firstsector *)sdtmp;	dlp = (struct disklabel *)(sdtmp + LABELOFFSET);	s = splclock();	hsp = &sdstdrv[unit];	bzero((caddr_t)hsp, sizeof (struct sdst));	bzero(&sdlabel[unit], sizeof (struct disklabel));	if ((dlp->d_magic == DISKMAGIC)	    && ((ii->ii_flags & SD_F_IGNLABEL) == 0)) {		sdlabel[unit] = *dlp;		disklabel2sdst(unit, dlp, hsp);	} else {		if ((ii->ii_type == UNKNOWN_DISK)				|| (sdi->sdstp->sizes == calc_disk_sizes)) {			/*			 * If device is UNKNOWN PARTITION SIZE,			 *	calculate default partition from capacity.			 */			st = sdi->sdstp;			hsp->nsect = st->nsect;		/* # sectors/track */			hsp->ntrak = st->ntrak;		/* # tracks/cylinder */			hsp->nspc = st->nspc;		/* # sectors/cylinder */			hsp->ncyl = st->ncyl;		/* # cylinders */			hsp->rps = st->rps;		/* # revolutions/sec */			hsp->sizes = sdsizedrv[unit];	/* partition table */			sd_calcpart(ii, hsp->sizes,					sdd->sdd_nsect, sdd->sdd_sectsize);			sdst2disklabel(unit, hsp, &sdlabel[unit]);		} else {			/*			 * If device is support disk,			 *	copy default partition from size table.			 */			st = sdi->sdstp;			hsp->nsect = st->nsect;	/* # sectors/track */			hsp->ntrak = st->ntrak;	/* # tracks/cylinder */			hsp->nspc = st->nspc;	/* # sectors/cylinder */			hsp->ncyl = st->ncyl;	/* # cylinders */			hsp->rps = st->rps;	/* # revolutions / second */			hsp->sizes = sdsizedrv[unit];	/* partition table */			for (i = 0; i < PNUM; i++) {			    hsp->sizes[i].sd_nblocks = st->sizes[i].sd_nblocks;			    hsp->sizes[i].sd_blkoff = st->sizes[i].sd_blkoff;			}			sdst2disklabel(unit, hsp, &sdlabel[unit]);		}	}	/* BEGIN XXX*/	if (hsp->rps == 0) {		/*		 * If device is support disk,		 *	copy default partition from size table.		 */		st = sdi->sdstp;		hsp->nsect = st->nsect;		/* # sectors/track */		hsp->ntrak = st->ntrak;		/* # tracks/cylinder */		hsp->nspc = st->nspc;		/* # sectors/cylinder */		hsp->ncyl = st->ncyl;		/* # cylinders */		hsp->rps = st->rps;		/* # revolutions / second */		sdst2disklabel(unit, hsp, &sdlabel[unit]);	}	/* END XXX*/	(void)splx(s);}static char Warn_Part[] = "sd%d: PARTITION TABLE CHANGED\n";static char Pr_Part_Fmt[] = "sd%d%c: nblk=%d, off=%d\n";#define stsz(N) st->sizes[(N)].sd_nblocks#define stof(N) st->sizes[(N)].sd_blkoff#define dlsz(N) dlp->d_partitions[(N)].p_size#define dlof(N) dlp->d_partitions[(N)].p_offset#define disz(N) dip->di_part[(N)].dp_nblocks#define diof(N) dip->di_part[(N)].dp_blkoff#ifndef BBSIZE#define BBSIZE 8192#endifstaticcheck_sdst(unit, st)	int unit;	struct sdst *st;{	if (st->nsect == 0) {		st->nsect = 1;		printf("sd%d: nsect SHOULD BE != 0, 1 assumed\n", unit);	}	if (st->rps == 0) {		st->rps = 60;		printf("sd%d: rps SHOULD BE != 0, 60 assumed\n", unit);	}}staticdisklabel2sdst(unit, dlp, st)	int unit;	register struct disklabel *dlp;	register struct sdst *st;{	register int i;	int msg_header_printed;	msg_header_printed = 0;	st->nsect = dlp->d_nsectors;	/* # sectors/track */	st->ntrak = dlp->d_ntracks;	/* # tracks/cylinder */	st->nspc = dlp->d_secpercyl;	/* # sectors/cylinder */	st->ncyl = dlp->d_ncylinders;	/* # cylinders */	st->rps = dlp->d_rpm / 60;	/* # revolutions / second */	st->sizes = sdsizedrv[unit];	/* partition table */	check_sdst(unit, st);	for (i = 0; i < PNUM; i++) {		if (msg_header_printed == 0) {			if (((stsz(i) != 0) || (stof(i) != 0))			    && ((stsz(i) != dlsz(i)) || (stof(i) != dlof(i)))) {				msg_header_printed = 1;			}		}	}	for (i = 0; i < PNUM; i++) {		stsz(i) = dlsz(i);		stof(i) = dlof(i);	}	if (msg_header_printed) {		printf(Warn_Part, unit);		for (i = 0; i < PNUM; i++)			printf(Pr_Part_Fmt, unit, pname[i], stsz(i), stof(i));	}}staticsdst2disklabel(unit, st, dlp)	int unit;	/*XXX*/

⌨️ 快捷键说明

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