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

📄 sd.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	caddr_t cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK);	register int bn, resid;	register caddr_t addr;	bzero((caddr_t)cbp, sizeof(*cbp));	cbp->b_proc = curproc;		/* XXX */	cbp->b_dev = bp->b_dev;	bn = bp->b_blkno;	resid = bp->b_bcount;	addr = bp->b_un.b_addr;#ifdef DEBUG	if (sddebug & SDB_PARTIAL)		printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n",		       bp, bp->b_flags, bn, resid, addr);#endif	while (resid > 0) {		register int boff = dbtob(bn) & (bsize - 1);		register int count;		if (boff || resid < bsize) {			sdstats[sdunit(bp->b_dev)].sdpartials++;			count = min(resid, bsize - boff);			cbp->b_flags = B_BUSY | B_PHYS | B_READ;			cbp->b_blkno = bn - btodb(boff);			cbp->b_un.b_addr = cbuf;			cbp->b_bcount = bsize;#ifdef DEBUG			if (sddebug & SDB_PARTIAL)				printf(" readahead: bn %x cnt %x off %x addr %x\n",				       cbp->b_blkno, count, boff, addr);#endif			sdstrategy(cbp);			biowait(cbp);			if (cbp->b_flags & B_ERROR) {				bp->b_flags |= B_ERROR;				bp->b_error = cbp->b_error;				break;			}			if (bp->b_flags & B_READ) {				bcopy(&cbuf[boff], addr, count);				goto done;			}			bcopy(addr, &cbuf[boff], count);#ifdef DEBUG			if (sddebug & SDB_PARTIAL)				printf(" writeback: bn %x cnt %x off %x addr %x\n",				       cbp->b_blkno, count, boff, addr);#endif		} else {			count = resid & ~(bsize - 1);			cbp->b_blkno = bn;			cbp->b_un.b_addr = addr;			cbp->b_bcount = count;#ifdef DEBUG			if (sddebug & SDB_PARTIAL)				printf(" fulltrans: bn %x cnt %x addr %x\n",				       cbp->b_blkno, count, addr);#endif		}		cbp->b_flags = B_BUSY | B_PHYS | (bp->b_flags & B_READ);		sdstrategy(cbp);		biowait(cbp);		if (cbp->b_flags & B_ERROR) {			bp->b_flags |= B_ERROR;			bp->b_error = cbp->b_error;			break;		}done:		bn += btodb(count);		resid -= count;		addr += count;#ifdef DEBUG		if (sddebug & SDB_PARTIAL)			printf(" done: bn %x resid %x addr %x\n",			       bn, resid, addr);#endif	}	free(cbuf, M_DEVBUF);	free(cbp, M_DEVBUF);}voidsdstrategy(bp)	register struct buf *bp;{	int unit = sdunit(bp->b_dev);	register struct sd_softc *sc = &sd_softc[unit];	register struct buf *dp = &sdtab[unit];	register struct partition *pinfo;	register daddr_t bn;	register int sz, s;	if (sc->sc_format_pid >= 0) {		if (sc->sc_format_pid != curproc->p_pid) {	/* XXX */			bp->b_error = EPERM;			goto bad;		}		bp->b_cylin = 0;	} else {		if (sc->sc_flags & SDF_ERROR) {			bp->b_error = EIO;			goto bad;		}		bn = bp->b_blkno;		sz = howmany(bp->b_bcount, DEV_BSIZE);		pinfo = &sc->sc_info.si_label.d_partitions[sdpart(bp->b_dev)];		if (bn < 0 || bn + sz > pinfo->p_size) {			sz = pinfo->p_size - bn;			if (sz == 0) {				bp->b_resid = bp->b_bcount;				goto done;			}			if (sz < 0) {				bp->b_error = EINVAL;				goto bad;			}			bp->b_bcount = dbtob(sz);		}		/*		 * Check for write to write protected label		 */		if (bn + pinfo->p_offset <= LABELSECTOR &&#if LABELSECTOR != 0		    bn + pinfo->p_offset + sz > LABELSECTOR &&#endif		    !(bp->b_flags & B_READ) && !(sc->sc_flags & SDF_WLABEL)) {			bp->b_error = EROFS;			goto bad;		}		/*		 * Non-aligned or partial-block transfers handled specially.		 */		s = sc->sc_blksize - 1;		if ((dbtob(bn) & s) || (bp->b_bcount & s)) {			sdlblkstrat(bp, sc->sc_blksize);			goto done;		}		bp->b_cylin = (bn + pinfo->p_offset) >> sc->sc_bshift;	}	s = splbio();	disksort(dp, bp);	if (dp->b_active == 0) {		dp->b_active = 1;		sdustart(unit);	}	splx(s);	return;bad:	bp->b_flags |= B_ERROR;done:	biodone(bp);}voidsdustart(unit)	register int unit;{	if (scsireq(&sd_softc[unit].sc_dq))		sdstart(unit);}/* * Return: *	0	if not really an error *	<0	if we should do a retry *	>0	if a fatal error */static intsderror(unit, sc, hp, stat)	int unit, stat;	register struct sd_softc *sc;	register struct hp_device *hp;{	int cond = 1;	sdsense[unit].status = stat;	if (stat & STS_CHECKCOND) {		struct scsi_xsense *sp;		scsi_request_sense(hp->hp_ctlr, hp->hp_slave,				   sc->sc_punit, sdsense[unit].sense,				   sizeof(sdsense[unit].sense));		sp = (struct scsi_xsense *)sdsense[unit].sense;		printf("sd%d: scsi sense class %d, code %d", unit,			sp->class, sp->code);		if (sp->class == 7) {			printf(", key %d", sp->key);			if (sp->valid)				printf(", blk %d", *(int *)&sp->info1);			switch (sp->key) {			/* no sense, try again */			case 0:				cond = -1;				break;			/* recovered error, not a problem */			case 1:				cond = 0;				break;			/* possible media change */			case 6:				/*				 * For removable media, if we are doing the				 * first open (i.e. reading the label) go				 * ahead and retry, otherwise someone has				 * changed the media out from under us and				 * we should abort any further operations				 * until a close is done.				 */				if (sc->sc_flags & SDF_RMEDIA) {					if (sc->sc_flags & SDF_OPENING)						cond = -1;					else						sc->sc_flags |= SDF_ERROR;				}				break;			}		}		printf("\n");	}	return(cond);}static voidsdfinish(unit, sc, bp)	int unit;	register struct sd_softc *sc;	register struct buf *bp;{	register struct buf *dp = &sdtab[unit];	dp->b_errcnt = 0;	dp->b_actf = bp->b_actf;	bp->b_resid = 0;	biodone(bp);	scsifree(&sc->sc_dq);	if (dp->b_actf)		sdustart(unit);	else {		dp->b_active = 0;		if (sc->sc_flags & SDF_WANTED) {			sc->sc_flags &= ~SDF_WANTED;			wakeup((caddr_t)dp);		}	}}voidsdstart(unit)	register int unit;{	register struct sd_softc *sc = &sd_softc[unit];	register struct hp_device *hp = sc->sc_hd;	/*	 * we have the SCSI bus -- in format mode, we may or may not need dma	 * so check now.	 */	if (sc->sc_format_pid >= 0 && legal_cmds[sdcmd[unit].cdb[0]] > 0) {		register struct buf *bp = sdtab[unit].b_actf;		register int sts;		sdtab[unit].b_errcnt = 0;		while (1) {			sts = scsi_immed_command(hp->hp_ctlr, hp->hp_slave,						 sc->sc_punit, &sdcmd[unit],						 bp->b_un.b_addr, bp->b_bcount,						 bp->b_flags & B_READ);			sdsense[unit].status = sts;			if ((sts & 0xfe) == 0 ||			    (sts = sderror(unit, sc, hp, sts)) == 0)				break;			if (sts > 0 || sdtab[unit].b_errcnt++ >= SDRETRY) {				bp->b_flags |= B_ERROR;				bp->b_error = EIO;				break;			}		}		sdfinish(unit, sc, bp);	} else if (scsiustart(hp->hp_ctlr))		sdgo(unit);}voidsdgo(unit)	register int unit;{	register struct sd_softc *sc = &sd_softc[unit];	register struct hp_device *hp = sc->sc_hd;	register struct buf *bp = sdtab[unit].b_actf;	register int pad;	register struct scsi_fmt_cdb *cmd;	if (sc->sc_format_pid >= 0) {		cmd = &sdcmd[unit];		pad = 0;	} else {		/*		 * Drive is in an error state, abort all operations		 */		if (sc->sc_flags & SDF_ERROR) {			bp->b_flags |= B_ERROR;			bp->b_error = EIO;			sdfinish(unit, sc, bp);			return;		}		cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;		*(int *)(&cmd->cdb[2]) = bp->b_cylin;		pad = howmany(bp->b_bcount, sc->sc_blksize);		*(u_short *)(&cmd->cdb[7]) = pad;		pad = (bp->b_bcount & (sc->sc_blksize - 1)) != 0;#ifdef DEBUG		if (pad)			printf("sd%d: partial block xfer -- %x bytes\n",			       unit, bp->b_bcount);#endif		sdstats[unit].sdtransfers++;	}#ifdef USELEDS	if (inledcontrol == 0)		ledcontrol(0, 0, LED_DISK);#endif	if (scsigo(hp->hp_ctlr, hp->hp_slave, sc->sc_punit, bp, cmd, pad) == 0) {		if (hp->hp_dk >= 0) {			dk_busy |= 1 << hp->hp_dk;			++dk_seek[hp->hp_dk];			++dk_xfer[hp->hp_dk];			dk_wds[hp->hp_dk] += bp->b_bcount >> 6;		}		return;	}#ifdef DEBUG	if (sddebug & SDB_ERROR)		printf("sd%d: sdstart: %s adr %d blk %d len %d ecnt %d\n",		       unit, bp->b_flags & B_READ? "read" : "write",		       bp->b_un.b_addr, bp->b_cylin, bp->b_bcount,		       sdtab[unit].b_errcnt);#endif	bp->b_flags |= B_ERROR;	bp->b_error = EIO;	sdfinish(unit, sc, bp);}voidsdintr(unit, stat)	register int unit;	int stat;{	register struct sd_softc *sc = &sd_softc[unit];	register struct buf *bp = sdtab[unit].b_actf;	register struct hp_device *hp = sc->sc_hd;	int cond;		if (bp == NULL) {		printf("sd%d: bp == NULL\n", unit);		return;	}	if (hp->hp_dk >= 0)		dk_busy &=~ (1 << hp->hp_dk);	if (stat) {#ifdef DEBUG		if (sddebug & SDB_ERROR)			printf("sd%d: sdintr: bad scsi status 0x%x\n",				unit, stat);#endif		cond = sderror(unit, sc, hp, stat);		if (cond) {			if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) {#ifdef DEBUG				if (sddebug & SDB_ERROR)					printf("sd%d: retry #%d\n",					       unit, sdtab[unit].b_errcnt);#endif				sdstart(unit);				return;			}			bp->b_flags |= B_ERROR;			bp->b_error = EIO;		}	}	sdfinish(unit, sc, bp);}intsdread(dev, uio, flags)	dev_t dev;	struct uio *uio;	int flags;{	register int unit = sdunit(dev);	register int pid;	if ((pid = sd_softc[unit].sc_format_pid) >= 0 &&	    pid != uio->uio_procp->p_pid)		return (EPERM);			return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio));}intsdwrite(dev, uio, flags)	dev_t dev;	struct uio *uio;	int flags;{	register int unit = sdunit(dev);	register int pid;	if ((pid = sd_softc[unit].sc_format_pid) >= 0 &&	    pid != uio->uio_procp->p_pid)		return (EPERM);			return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio));}intsdioctl(dev, cmd, data, flag, p)	dev_t dev;	int cmd;	caddr_t data;	int flag;	struct proc *p;{	int unit = sdunit(dev);	register struct sd_softc *sc = &sd_softc[unit];	register struct disklabel *lp = &sc->sc_info.si_label;	int error, flags;	switch (cmd) {	default:		return (EINVAL);	case DIOCGDINFO:		*(struct disklabel *)data = *lp;		return (0);	case DIOCGPART:		((struct partinfo *)data)->disklab = lp;		((struct partinfo *)data)->part =			&lp->d_partitions[sdpart(dev)];		return (0);        case DIOCWLABEL:                if ((flag & FWRITE) == 0)                        return (EBADF);		if (*(int *)data)			sc->sc_flags |= SDF_WLABEL;		else			sc->sc_flags &= ~SDF_WLABEL;		return (0);        case DIOCSDINFO:                if ((flag & FWRITE) == 0)                        return (EBADF);		error = setdisklabel(lp, (struct disklabel *)data,				     (sc->sc_flags & SDF_WLABEL) ? 0				     : sc->sc_info.si_open);		return (error);        case DIOCWDINFO:		if ((flag & FWRITE) == 0)			return (EBADF);		error = setdisklabel(lp, (struct disklabel *)data,				     (sc->sc_flags & SDF_WLABEL) ? 0				     : sc->sc_info.si_open);		if (error)			return (error);		flags = sc->sc_flags;		sc->sc_flags = SDF_ALIVE | SDF_WLABEL;		error = writedisklabel(sdlabdev(dev), sdstrategy, lp);		sc->sc_flags = flags;		return (error);	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 >= 0)				return (EPERM);			sc->sc_format_pid = p->p_pid;		} else			sc->sc_format_pid = -1;		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)&sdcmd[unit], sizeof(sdcmd[0]));		return (0);	case SDIOCSENSE:		/*		 * return the SCSI sense data saved after the last		 * operation that completed with "check condition" status.		 */		bcopy((caddr_t)&sdsense[unit], data, sizeof(sdsense[0]));		return (0);			}	/*NOTREACHED*/}intsdsize(dev)	dev_t dev;{	register int unit = sdunit(dev);	register struct sd_softc *sc = &sd_softc[unit];	int psize, didopen = 0;	if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)		return(-1);	/*	 * We get called very early on (via swapconf)	 * without the device being open so we may need	 * to handle it here.	 */	if (sc->sc_info.si_open == 0) {		if (sdopen(dev, FREAD|FWRITE, S_IFBLK, NULL))			return(-1);		didopen = 1;	}	psize = sc->sc_info.si_label.d_partitions[sdpart(dev)].p_size;	if (didopen)		(void) sdclose(dev, FREAD|FWRITE, S_IFBLK, NULL);	return (psize);}/* * Non-interrupt driven, non-dma dump routine. */intsddump(dev)	dev_t dev;{	int part = sdpart(dev);	int unit = sdunit(dev);	register struct sd_softc *sc = &sd_softc[unit];	register struct hp_device *hp = sc->sc_hd;	register struct partition *pinfo;	register daddr_t baddr;	register int maddr;	register int pages, i;	int stat;	extern int lowram, dumpsize;	/* is drive ok? */	if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)		return (ENXIO);	pinfo = &sc->sc_info.si_label.d_partitions[part];	/* dump parameters in range? */	if (dumplo < 0 || dumplo >= pinfo->p_size ||	    pinfo->p_fstype != FS_SWAP)		return (EINVAL);	pages = dumpsize;	if (dumplo + ctod(pages) > pinfo->p_size)		pages = dtoc(pinfo->p_size - dumplo);	maddr = lowram;	baddr = dumplo + pinfo->p_offset;	/* scsi bus idle? */	if (!scsireq(&sc->sc_dq)) {		scsireset(hp->hp_ctlr);		sdreset(sc, sc->sc_hd);		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		pmap_enter(kernel_pmap, (vm_offset_t)vmmap, maddr,		    VM_PROT_READ, TRUE);		stat = scsi_tt_write(hp->hp_ctlr, hp->hp_slave, sc->sc_punit,				     vmmap, NBPG, baddr, sc->sc_bshift);		if (stat) {			printf("sddump: scsi write error 0x%x\n", stat);			return (EIO);		}		maddr += NBPG;		baddr += ctod(1);	}	return (0);}#endif

⌨️ 快捷键说明

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