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

📄 wd.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	biodone(bp);	if (wd != NULL)		device_unref(&wd->sc_dev);}/* * Queue a drive for I/O. */voidwdstart(arg)	void *arg;{	struct wd_softc *wd = arg;	struct buf *dp, *bp=0;	WDCDEBUG_PRINT(("wdstart %s\n", wd->sc_dev.dv_xname),	    DEBUG_XFERS);	while (wd->openings > 0) {		/* Is there a buf for us ? */		dp = &wd->sc_q;		if ((bp = dp->b_actf) == NULL)  /* yes, an assign */			 return;		dp->b_actf = bp->b_actf;			/* 		 * Make the command. First lock the device		 */		wd->openings--;		wd->retries = 0;		__wdstart(wd, bp);	}}void__wdstart(wd, bp)	struct wd_softc *wd;	struct buf *bp;{	daddr_t p_offset;	if (WDPART(bp->b_dev) != RAW_PART)		p_offset =		    wd->sc_dk.dk_label->d_partitions[WDPART(bp->b_dev)].p_offset;	else		p_offset = 0;	wd->sc_wdc_bio.lp=wd->sc_dk.dk_label;	wd->sc_wdc_bio.blkno = bp->b_blkno + p_offset;	wd->sc_wdc_bio.blkno /= (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);	wd->sc_wdc_bio.blkdone =0;	wd->sc_bp = bp;	/*	 * If we're retrying, retry in single-sector mode. This will give us	 * the sector number of the problem, and will eventually allow the	 * transfer to succeed.	 */	if (wd->sc_multi == 1 || wd->retries >= WDIORETRIES_SINGLE)		wd->sc_wdc_bio.flags = ATA_SINGLE | ATA_POLL;	else		wd->sc_wdc_bio.flags = ATA_POLL;	if (wd->sc_flags & WDF_LBA)		wd->sc_wdc_bio.flags |= ATA_LBA;	if (bp->b_flags & B_READ)		wd->sc_wdc_bio.flags |= ATA_READ;	wd->sc_wdc_bio.bcount = bp->b_bcount;	wd->sc_wdc_bio.databuf = bp->b_data;	wd->sc_wdc_bio.wd = wd;#ifndef PMON	/* Instrumentation. */	disk_busy(&wd->sc_dk);#endif	switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) {	case WDC_TRY_AGAIN:		timeout(wdrestart, wd, hz);		break;	case WDC_QUEUED:		break;	case WDC_COMPLETE:		wddone(wd);		break;	default:		panic("__wdstart: bad return code from wdc_ata_bio()");	}}voidwddone(v)	void *v;{	struct wd_softc *wd = v;	struct buf *bp = wd->sc_bp;	char buf[256], *errbuf = buf;	WDCDEBUG_PRINT(("wddone %s\n", wd->sc_dev.dv_xname),	    DEBUG_XFERS);	bp->b_resid = wd->sc_wdc_bio.bcount;	errbuf[0] = '\0';	switch (wd->sc_wdc_bio.error) {	case ERR_NODEV:		bp->b_flags |= B_ERROR;		bp->b_error = ENXIO;		break;	case ERR_DMA:		errbuf = "DMA error";		goto retry;	case ERR_DF:		errbuf = "device fault";		goto retry;	case TIMEOUT:		errbuf = "device timeout";		goto retry;	case ERROR:		/* Don't care about media change bits */		if (wd->sc_wdc_bio.r_error != 0 &&		    (wd->sc_wdc_bio.r_error & ~(WDCE_MC | WDCE_MCR)) == 0)			goto noerror;		ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf);retry:		/* Just reset and retry. Can we do more ? */		wdc_reset_channel(wd->drvp);#ifndef PMON		diskerr(bp, "wd", errbuf, LOG_PRINTF,		    wd->sc_wdc_bio.blkdone, wd->sc_dk.dk_label);#endif		if (wd->retries++ < WDIORETRIES) {			printf(", retrying\n");			timeout(wdrestart, wd, RECOVERYTIME);			return;		}		printf("\n");		bp->b_flags |= B_ERROR;		bp->b_error = EIO;		break;	case NOERROR:noerror:	if ((wd->sc_wdc_bio.flags & ATA_CORR) || wd->retries > 0)			printf("%s: soft error (corrected)\n",			    wd->sc_dev.dv_xname);	}#ifndef PMON	disk_unbusy(&wd->sc_dk, (bp->b_bcount - bp->b_resid));#if NRND > 0	rnd_add_uint32(&wd->rnd_source, bp->b_blkno);#endif#endif	biodone(bp);	wd->openings++;	wdstart(wd);}voidwdrestart(v)	void *v;{	struct wd_softc *wd = v;	struct buf *bp = wd->sc_bp;	int s;	WDCDEBUG_PRINT(("wdrestart %s\n", wd->sc_dev.dv_xname),	    DEBUG_XFERS);	s = splbio();	__wdstart(v, bp);	splx(s);}intwdread(dev, uio, flags)	dev_t dev;	struct uio *uio;	int flags;{	WDCDEBUG_PRINT(("wdread\n"), DEBUG_XFERS);	return (physio(wdstrategy, NULL, dev, B_READ, minphys, uio));}intwdwrite(dev, uio, flags)	dev_t dev;	struct uio *uio;	int flags;{	WDCDEBUG_PRINT(("wdwrite\n"), DEBUG_XFERS);	return (physio(wdstrategy, NULL, dev, B_WRITE, minphys, uio));}intwdopen(dev, flag, fmt, p)	dev_t dev;	int flag, fmt;	struct proc *p;{	struct wd_softc *wd;	int unit, part;	int error;	WDCDEBUG_PRINT(("wdopen\n"), DEBUG_FUNCS);	unit = WDUNIT(dev);	wd = wdlookup(unit);	if (wd == NULL)		return ENXIO;	/*	 * If this is the first open of this device, add a reference	 * to the adapter.	 */#ifndef __OpenBSD__	if (wd->sc_dk.dk_openmask == 0 &&	    (error = wdc_ata_addref(wd->drvp)) != 0)		return (error);#endif	if ((error = wdlock(wd)) != 0)		goto bad4;	if (wd->sc_dk.dk_openmask != 0) {		/*		 * If any partition is open, but the disk has been invalidated,		 * disallow further opens.		 */		if ((wd->sc_flags & WDF_LOADED) == 0) {			error = EIO;			goto bad3;		}	} else {		if ((wd->sc_flags & WDF_LOADED) == 0) {			wd->sc_flags |= WDF_LOADED;			wd_get_params(wd, AT_WAIT, &wd->sc_params);			/* Load the physical device parameters. */			if(wd->sc_dk.dk_cpulabel==NULL)				wd->sc_dk.dk_cpulabel=(struct cpu_disklabel *)malloc(sizeof(struct cpu_disklabel),M_DEVBUF,M_NOWAIT);			if(wd->sc_dk.dk_label==NULL)				wd->sc_dk.dk_label=(struct disklabel *)malloc(sizeof(struct disklabel),M_DEVBUF,M_NOWAIT);			/* Load the partition info if not already loaded. */			wdgetdisklabel(dev, wd, wd->sc_dk.dk_label,				       wd->sc_dk.dk_cpulabel, 0);		}	}	part = WDPART(dev);	/* Check that the partition exists. */	if (part != RAW_PART &&	    (part >= wd->sc_dk.dk_label->d_npartitions ||	     wd->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {		error = ENXIO;		goto bad;	}		/* Insure only one open at a time. */	switch (fmt) {	case S_IFCHR:		wd->sc_dk.dk_copenmask |= (1 << part);		break;	case S_IFBLK:		wd->sc_dk.dk_bopenmask |= (1 << part);		break;	}	wd->sc_dk.dk_openmask =	    wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;	wdunlock(wd);	device_unref(&wd->sc_dev);	return 0;bad:	if (wd->sc_dk.dk_openmask == 0) {	}bad3:	wdunlock(wd);bad4:#ifndef __OpenBSD__	if (wd->sc_dk.dk_openmask == 0)		wdc_ata_delref(wd->drvp);#endif	device_unref(&wd->sc_dev);	return error;}intwdclose(dev, flag, fmt, p)	dev_t dev;	int flag, fmt;	struct proc *p;{	struct wd_softc *wd;	int part = WDPART(dev);	int error = 0;	wd = wdlookup(WDUNIT(dev));	if (wd == NULL)		return ENXIO;		WDCDEBUG_PRINT(("wdclose\n"), DEBUG_FUNCS);	if ((error = wdlock(wd)) != 0)		goto exit;	switch (fmt) {	case S_IFCHR:		wd->sc_dk.dk_copenmask &= ~(1 << part);		break;	case S_IFBLK:		wd->sc_dk.dk_bopenmask &= ~(1 << part);		break;	}	wd->sc_dk.dk_openmask =	    wd->sc_dk.dk_copenmask | wd->sc_dk.dk_bopenmask;	if (wd->sc_dk.dk_openmask == 0) {		wd_flushcache(wd,0);		/* XXXX Must wait for I/O to complete! */#ifndef __OpenBSD__		wdc_ata_delref(wd->drvp);#endif	}	wdunlock(wd); exit:	device_unref(&wd->sc_dev);	return (error);}voidwdgetdefaultlabel(wd, lp)	struct wd_softc *wd;	struct disklabel *lp;{	WDCDEBUG_PRINT(("wdgetdefaultlabel\n"), DEBUG_FUNCS);	bzero(lp, sizeof(struct disklabel));	lp->d_secsize = DEV_BSIZE;	lp->d_ntracks = wd->sc_params.atap_heads;	lp->d_nsectors = wd->sc_params.atap_sectors;	lp->d_ncylinders = wd->sc_params.atap_cylinders;	lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;	if (wd->drvp->ata_vers == -1) {		lp->d_type = DTYPE_ST506;		strncpy(lp->d_typename, "ST506/MFM/RLL", 16);	} else {		lp->d_type = DTYPE_ESDI;		strncpy(lp->d_typename, "ESDI/IDE disk", 16);	}	/* XXX - user viscopy() like sd.c */	strncpy(lp->d_packname, wd->sc_params.atap_model, 16);	lp->d_secperunit = wd->sc_capacity;	lp->d_rpm = 3600;	lp->d_interleave = 1;	lp->d_flags = 0;	lp->d_partitions[RAW_PART].p_offset = 0;	lp->d_partitions[RAW_PART].p_size =	lp->d_secperunit * (lp->d_secsize / DEV_BSIZE);	lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;	lp->d_npartitions = RAW_PART + 1;	lp->d_magic = DISKMAGIC;	lp->d_magic2 = DISKMAGIC;#ifndef PMON	lp->d_checksum = dkcksum(lp);#endif}/* * Fabricate a default disk label, and try to read the correct one. */voidwdgetdisklabel(dev, wd, lp, clp, spoofonly)	dev_t  dev;	struct wd_softc *wd;	struct disklabel *lp;	struct cpu_disklabel *clp;	int spoofonly;{	char *errstring;	WDCDEBUG_PRINT(("wdgetdisklabel\n"), DEBUG_FUNCS);	bzero(clp, sizeof(struct cpu_disklabel));	wdgetdefaultlabel(wd, lp);	wd->sc_badsect[0] = -1;	if (wd->drvp->state > RECAL)		wd->drvp->drive_flags |= DRIVE_RESET;	errstring = readdisklabel(WDLABELDEV(dev),	    wdstrategy, lp, clp, spoofonly);	if (errstring) {		/*		 * This probably happened because the drive's default		 * geometry doesn't match the DOS geometry.  We		 * assume the DOS geometry is now in the label and try		 * again.  XXX This is a kluge.		 */		if (wd->drvp->state > RECAL)			wd->drvp->drive_flags |= DRIVE_RESET;		errstring = readdisklabel(WDLABELDEV(dev),		    wdstrategy, lp, clp, spoofonly);	}#ifndef PMON	if (errstring) {		printf("%s: %s\n", wd->sc_dev.dv_xname, errstring);		return;	}#endif	if (wd->drvp->state > RECAL)		wd->drvp->drive_flags |= DRIVE_RESET;#ifdef DKBAD	if ((lp->d_flags & D_BADSECT) != 0)		bad144intern(wd);#endif}intwdioctl(dev, xfer, addr, flag, p)	dev_t dev;	u_long xfer;	caddr_t addr;	int flag;	struct proc *p;{	struct wd_softc *wd;	int error = 0;	WDCDEBUG_PRINT(("wdioctl\n"), DEBUG_FUNCS);	wd = wdlookup(WDUNIT(dev));	if (wd == NULL)		return ENXIO;		if ((wd->sc_flags & WDF_LOADED) == 0) {		error = EIO;		goto exit;	}	switch (xfer) {#ifndef PMON#ifdef DKBAD	case DIOCSBAD:		if ((flag & FWRITE) == 0)			return EBADF;		DKBAD(wd->sc_dk.dk_cpulabel) = *(struct dkbad *)addr;		wd->sc_dk.dk_label->d_flags |= D_BADSECT;		bad144intern(wd);		goto exit;#endif	case DIOCRLDINFO:		wdgetdisklabel(dev, wd, wd->sc_dk.dk_label,		    wd->sc_dk.dk_cpulabel, 0);		goto exit;	case DIOCGPDINFO: {			struct cpu_disklabel osdep;			wdgetdisklabel(dev, wd, (struct disklabel *)addr,			    &osdep, 1);			goto exit;		}	case DIOCGDINFO:		*(struct disklabel *)addr = *(wd->sc_dk.dk_label);		goto exit;		case DIOCGPART:		((struct partinfo *)addr)->disklab = wd->sc_dk.dk_label;		((struct partinfo *)addr)->part =		    &wd->sc_dk.dk_label->d_partitions[WDPART(dev)];		goto exit;		case DIOCWDINFO:	case DIOCSDINFO:		if ((flag & FWRITE) == 0) {			error = EBADF;			goto exit;		}		if ((error = wdlock(wd)) != 0)			goto exit;		wd->sc_flags |= WDF_LABELLING;		error = setdisklabel(wd->sc_dk.dk_label,		    (struct disklabel *)addr, /*wd->sc_dk.dk_openmask : */0,		    wd->sc_dk.dk_cpulabel);		if (error == 0) {			if (wd->drvp->state > RECAL)				wd->drvp->drive_flags |= DRIVE_RESET;			if (xfer == DIOCWDINFO)				error = writedisklabel(WDLABELDEV(dev),				    wdstrategy, wd->sc_dk.dk_label,				    wd->sc_dk.dk_cpulabel);		}		wd->sc_flags &= ~WDF_LABELLING;		wdunlock(wd);		goto exit;		case DIOCWLABEL:		if ((flag & FWRITE) == 0) {			error = EBADF;			goto exit;		}		if (*(int *)addr)			wd->sc_flags |= WDF_WLABEL;		else			wd->sc_flags &= ~WDF_WLABEL;		goto exit;#ifndef __OpenBSD__	case DIOCGDEFLABEL:		wdgetdefaultlabel(wd, (struct disklabel *)addr);		goto exit;#endif#ifdef notyet	case DIOCWFORMAT:		if ((flag & FWRITE) == 0)			return EBADF;		{		register struct format_op *fop;		struct iovec aiov;		struct uio auio;			fop = (struct format_op *)addr;		aiov.iov_base = fop->df_buf;		aiov.iov_len = fop->df_count;		auio.uio_iov = &aiov;		auio.uio_iovcnt = 1;		auio.uio_resid = fop->df_count;		auio.uio_segflg = 0;		auio.uio_offset =			fop->df_startblk * wd->sc_dk.dk_label->d_secsize;		auio.uio_procp = p;		error = physio(wdformat, NULL, dev, B_WRITE, minphys,		    &auio);		fop->df_count -= auio.uio_resid;		fop->df_reg[0] = wdc->sc_status;		fop->df_reg[1] = wdc->sc_error;

⌨️ 快捷键说明

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