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

📄 hd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	register int unit;	daddr_t sn, sz, maxsz;	int part, s;	vi = hddinfo[unit = hdunit(bp->b_dev)];	if (unit >= NHD || vi == 0 || vi->ui_alive == 0) {		bp->b_error = ENXIO;		goto bad;	}	dk = &dksoftc[unit];	if (dk->dk_state < OPEN)		goto q;	if (dk->dk_state != OPEN && (bp->b_flags & B_READ) == 0) {		bp->b_error = EROFS;		goto bad;	}	part = hdpart(bp->b_dev);	if ((dk->dk_openpart & (1 << part)) == 0) {		bp->b_error = ENODEV;		goto bad;	}	lp = &dk->dk_label;	sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize;	maxsz = lp->d_partitions[part].p_size;	sn = bp->b_blkno << dk->dk_bshift;	if (sn + lp->d_partitions[part].p_offset <= LABELSECTOR &&#if LABELSECTOR != 0	    sn + lp->d_partitions[part].p_offset + sz > LABELSECTOR &&#endif	    (bp->b_flags & B_READ) == 0 && dk->dk_wlabel == 0) {		bp->b_error = EROFS;		goto bad;	}	if (sn < 0 || sn + sz > maxsz) {		if (sn == maxsz) {			bp->b_resid = bp->b_bcount;			goto done;		}		sz = maxsz - sn;		if (sz <= 0) {			bp->b_error = EINVAL;			goto bad;		}		bp->b_bcount = sz * lp->d_secsize;	}	bp->b_cylin = (sn + lp->d_partitions[part].p_offset) / lp->d_secpercyl;q:	s = spl7();	dp = &dk->dk_utab;	disksort(dp, bp);	if (!dp->b_active) {		(void)hdustart(vi);		if (!vi->ui_mi->um_tab.b_active)			hdcstart(vi->ui_mi);	}	splx(s);	return;bad:	bp->b_flags |= B_ERROR;done:	biodone(bp);}hdustart(vi)	register struct vba_device *vi;{	register struct buf *bp, *dp;	register struct vba_ctlr *vm;	register struct dksoftc *dk;	dk = &dksoftc[vi->ui_unit];	dp = &dk->dk_utab;	/* if queue empty, nothing to do.  impossible? */	if (dp->b_actf == NULL)		return;	/* place on controller transfer queue */	vm = vi->ui_mi;	if (vm->um_tab.b_actf == NULL)		vm->um_tab.b_actf = dp;	else		vm->um_tab.b_actl->b_forw = dp;	vm->um_tab.b_actl = dp;	dp->b_forw = NULL;	dp->b_active++;}hdcstart(vm)	register struct vba_ctlr *vm;{	register struct buf *bp;	register struct dksoftc *dk;	register struct disklabel *lp;	register struct master_mcb *master;	register struct mcb *mcb;	struct vba_device *vi;	struct hdcsoftc *hdc;	struct buf *dp;	int sn;	/* pull a request off the controller queue */	for (;;) {		if ((dp = vm->um_tab.b_actf) == NULL)			return;		if (bp = dp->b_actf)			break;		vm->um_tab.b_actf = dp->b_forw;	}	/* mark controller active */	vm->um_tab.b_active++;	vi = hddinfo[hdunit(bp->b_dev)];	dk = &dksoftc[vi->ui_unit];	lp = &dk->dk_label;	sn = bp->b_blkno << dk->dk_bshift;	/* fill in mcb */	mcb = &dk->dk_mcb;	mcb->forw_phaddr = 0;	/* mcb->priority = 0; */	mcb->interrupt = 1;	mcb->command = (bp->b_flags & B_READ) ? HCMD_READ:HCMD_WRITE;	mcb->cyl = bp->b_cylin;/* assumes partition starts on cylinder boundary */	mcb->head = (sn / lp->d_nsectors) % lp->d_ntracks;	mcb->sector = sn % lp->d_nsectors;	mcb->drive = vi->ui_slave;	/* mcb->context = 0;		/* what do we want on interrupt? */	hdc = &hdcsoftc[vm->um_ctlr];	if (!hd_sgsetup(bp, &hdc->hdc_rbuf, mcb->chain)) {		mcb->chain[0].wcount = (bp->b_bcount+3) >> 2;		mcb->chain[0].memadr =		    vbasetup(bp, &hdc->hdc_rbuf, (int)lp->d_secsize);	}	if (vi->ui_dk >= 0) {		dk_busy |= 1<<vi->ui_dk;		dk_xfer[vi->ui_dk]++;		dk_wds[vi->ui_dk] += bp->b_bcount>>6;	}	master = &hdc->hdc_mcb;	master->mcw = MCL_QUEUED;	master->interrupt = HDCINTERRUPT + vm->um_ctlr;	master->forw_phaddr = (u_long)vtoph((struct proc *)NULL, mcb);	hdc->hdc_reg->master_mcb = (u_long)hdc->hdc_mcbp;}/* * Wait for controller to finish current operation * so that direct controller accesses can be done. */hdclock(ctlr)	int ctlr;{	register struct vba_ctlr *vm = hdcminfo[ctlr];	register struct hdcsoftc *hdc;	int s;	hdc = &hdcsoftc[ctlr];	s = spl7();	while (vm->um_tab.b_active || hdc->hdc_flags & HDC_LOCKED) {		hdc->hdc_flags |= HDC_WAIT;		sleep((caddr_t)hdc, PRIBIO);	}	hdc->hdc_flags |= HDC_LOCKED;	splx(s);}/* * Continue normal operations after pausing for  * munging the controller directly. */hdcunlock(ctlr)	int ctlr;{	register struct vba_ctlr *vm;	register struct hdcsoftc *hdc = &hdcsoftc[ctlr];	hdc->hdc_flags &= ~HDC_LOCKED;	if (hdc->hdc_flags & HDC_WAIT) {		hdc->hdc_flags &= ~HDC_WAIT;		wakeup((caddr_t)hdc);	} else {		vm = hdcminfo[ctlr];		if (vm->um_tab.b_actf)			hdcstart(vm);	}}hdintr(ctlr)	int ctlr;{	register struct buf *bp, *dp;	register struct vba_ctlr *vm;	register struct vba_device *vi;	register struct hdcsoftc *hdc;	register struct mcb *mcb;	struct master_mcb *master;	register int status;	int timedout;	struct dksoftc *dk;	hdc = &hdcsoftc[ctlr];	master = &hdc->hdc_mcb;	uncache(&master->mcs);	uncache(&master->context);	vm = hdcminfo[ctlr];	if (!vm->um_tab.b_active || !(master->mcs&MCS_DONE)) {		printf("hd%d: stray interrupt\n", ctlr);		return;	}	dp = vm->um_tab.b_actf;	bp = dp->b_actf;	vi = hddinfo[hdunit(bp->b_dev)];	dk = &dksoftc[vi->ui_unit];	if (vi->ui_dk >= 0)		dk_busy &= ~(1<<vi->ui_dk);	timedout = (hdc->hdc_wticks >= HDCMAXTIME);	mcb = &dk->dk_mcb;	if (master->mcs & (MCS_SOFTERROR | MCS_FATALERROR) || timedout)		hdcerror(ctlr, *(u_long *)master->xstatus);	else 		hdc->hdc_wticks = 0;	if (vm->um_tab.b_active) {		vm->um_tab.b_active = 0;		vm->um_tab.b_actf = dp->b_forw;		dp->b_active = 0;		dp->b_errcnt = 0;		dp->b_actf = bp->av_forw;		bp->b_resid = 0;		vbadone(bp, &hdc->hdc_rbuf);		biodone(bp);		/* start up now, if more work to do */		if (dp->b_actf)			hdustart(vi);		else if (dk->dk_openpart == 0)			wakeup((caddr_t)dk);	}	/* if there are devices ready to transfer, start the controller. */	if (hdc->hdc_flags & HDC_WAIT) {		hdc->hdc_flags &= ~HDC_WAIT;		wakeup((caddr_t)hdc);	} else if (vm->um_tab.b_actf)		hdcstart(vm);}hdioctl(dev, cmd, data, flag)	dev_t dev;	int cmd, flag;	caddr_t data;{	register int unit;	register struct dksoftc *dk;	register struct disklabel *lp;	int error;	unit = hdunit(dev);	dk = &dksoftc[unit];	lp = &dk->dk_label;	error = 0;	switch (cmd) {	case DIOCGDINFO:		*(struct disklabel *)data = *lp;		break;	case DIOCGPART:		((struct partinfo *)data)->disklab = lp;		((struct partinfo *)data)->part =		    &lp->d_partitions[hdpart(dev)];		break;	case DIOCSDINFO:		if ((flag & FWRITE) == 0)			error = EBADF;		else			error = setdisklabel(lp, (struct disklabel *)data,			    (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart);		if (error == 0 && dk->dk_state == OPENRAW)			dk->dk_state = OPEN;		break;	case DIOCWLABEL:		if ((flag & FWRITE) == 0)			error = EBADF;		else			dk->dk_wlabel = *(int *)data;		break;	case DIOCWDINFO:		if ((flag & FWRITE) == 0)			error = EBADF;		else if ((error = setdisklabel(lp, (struct disklabel *)data,		    (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart)) == 0) {			int wlab;			if (error == 0 && dk->dk_state == OPENRAW)				dk->dk_state = OPEN;			/* simulate opening partition 0 so write succeeds */			dk->dk_openpart |= (1 << 0);		/* XXX */			wlab = dk->dk_wlabel;			dk->dk_wlabel = 1;			error = writedisklabel(dev, hdstrategy, lp);			dk->dk_openpart = dk->dk_copenpart | dk->dk_bopenpart;			dk->dk_wlabel = wlab;		}		break;	default:		error = ENOTTY;		break;	}	return (error);}/* * Watch for lost interrupts. */hdcwatch(){	register struct hdcsoftc *hdc;	register struct vba_ctlr **vmp;	register int ctlr;	int s;	timeout(hdcwatch, (caddr_t)0, hz);	for (vmp = hdcminfo, hdc = hdcsoftc, ctlr = 0; ctlr < NHDC;	    ++ctlr, ++vmp, ++hdc) {		if (*vmp == 0 || (*vmp)->um_alive == 0)			continue;		s = spl7();		if ((*vmp)->um_tab.b_active &&		    hdc->hdc_wticks++ >= HDCMAXTIME) {			printf("hd%d: lost interrupt\n", ctlr);			hdintr(ctlr);		}		splx(s);	}}hddump(dev)	dev_t dev;{	return(ENXIO);}hdsize(dev)	dev_t dev;{	register int unit = hdunit(dev);	register struct dksoftc *dk;	struct vba_device *vi;	struct disklabel *lp;	if (unit >= NHD || (vi = hddinfo[unit]) == 0 || vi->ui_alive == 0 ||	    (dk = &dksoftc[unit])->dk_state != OPEN)		return (-1);	lp = &dk->dk_label;	return ((int)lp->d_partitions[hdpart(dev)].p_size >> dk->dk_bshift);}hdimcb(dk)	register struct dksoftc *dk;{	register struct master_mcb *master;	register struct mcb *mcb;	register struct hdcsoftc *hdc;	int timeout;	/* fill in mcb */	mcb = &dk->dk_mcb;	mcb->interrupt = 0;	mcb->forw_phaddr = 0;	mcb->drive = dk->dk_unit;	hdc = &hdcsoftc[dk->dk_ctlr];	master = &hdc->hdc_mcb;	/* fill in master mcb */	master->mcw = MCL_IMMEDIATE;	master->forw_phaddr = (u_long)vtoph((struct proc *)NULL, mcb);	master->mcs = 0;	/* kick controller and wait */	hdc->hdc_reg->master_mcb = (u_long)hdc->hdc_mcbp;	for (timeout = 15000; timeout; --timeout) {		DELAY(1000);		mtpr(PADC, 0);		if (master->mcs&MCS_FATALERROR) {			printf("hdc%d: fatal error\n", dk->dk_ctlr);			hdcerror(dk->dk_ctlr, *(u_long *)master->xstatus);			return(1);		}		if (master->mcs&MCS_DONE)			return(0);	}	printf("hdc%d: timed out\n", dk->dk_ctlr);	return(1);}hdcerror(ctlr, code)	int ctlr;	u_long code;{	printf("hd%d: error %lx\n", ctlr, code);}#ifdef COMPAT_42hdreadgeometry(dk)	struct dksoftc *dk;{	static geometry_sector geometry;	register struct mcb *mcb;	register struct disklabel *lp;	geometry_block *geo;	int cnt;	/*	 * Read the geometry block (at head = 0 sector = 0 of the drive	 * definition cylinder), validate it (must have the correct version	 * number, header, and checksum).	 */	mcb = &dk->dk_mcb;	mcb->command = HCMD_READ;	mcb->cyl = dk->dk_def_cyl;	mcb->head = 0;	mcb->sector = 0;	mcb->chain[0].wcount = sizeof(geometry_sector) / sizeof(long);	mcb->chain[0].memadr  = (u_long)vtoph((struct process *)0, &geometry);	/* mcb->chain[0].memadr = (long)&geometry; */	if (hdimcb(dk)) { 		printf("hd%d: can't read default geometry.\n", dk->dk_unit);		return(1);	}	geo = &geometry.geometry_block; 	if (geo->version > 64000  ||  geo->version < 0) { 		printf("hd%d: bad default geometry version#.\n", dk->dk_unit);		return(1);	} 	if (bcmp(&geo->id[0], GB_ID, GB_ID_LEN)) { 		printf("hd%d: bad default geometry header.\n", dk->dk_unit);		return(1);	}	GB_CHECKSUM(geo, cnt);	if (geometry.checksum != cnt) {		printf("hd%d: bad default geometry checksum.\n", dk->dk_unit);		return(1);	}	lp = &dk->dk_label;	/* 1K block in Harris geometry; convert to sectors for disklabels */	for (cnt = 0; cnt < GB_MAXPART; cnt++) {		lp->d_partitions[cnt].p_offset =		    geo->partition[cnt].start * (1024 / lp->d_secsize);		lp->d_partitions[cnt].p_size =		    geo->partition[cnt].length * (1024 / lp->d_secsize);	}	lp->d_npartitions = GB_MAXPART;	return(0);}#endif /* COMPAT_42 */#endif /* NHD */

⌨️ 快捷键说明

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