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

📄 wd.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		goto exit;		}#endif	case ATAIOCCOMMAND:		/*		 * Make sure this command is (relatively) safe first		 */		if ((((atareq_t *) addr)->flags & ATACMD_READ) == 0 &&		    (flag & FWRITE) == 0) {			error = EBADF;			goto exit;		}		{		struct wd_ioctl *wi;		atareq_t *atareq = (atareq_t *) addr;		int error;		wi = wi_get();		wi->wi_softc = wd;		wi->wi_atareq = *atareq;		if (atareq->datalen && atareq->flags &		    (ATACMD_READ | ATACMD_WRITE)) {			wi->wi_iov.iov_base = atareq->databuf;			wi->wi_iov.iov_len = atareq->datalen;			wi->wi_uio.uio_iov = &wi->wi_iov;			wi->wi_uio.uio_iovcnt = 1;			wi->wi_uio.uio_resid = atareq->datalen;			wi->wi_uio.uio_offset = 0;			wi->wi_uio.uio_segflg = UIO_USERSPACE;			wi->wi_uio.uio_rw =			    (atareq->flags & ATACMD_READ) ? B_READ : B_WRITE;			wi->wi_uio.uio_procp = p;			error = physio(wdioctlstrategy, &wi->wi_bp, dev,			    (atareq->flags & ATACMD_READ) ? B_READ : B_WRITE,			    minphys, &wi->wi_uio);		} else {			/* No need to call physio if we don't have any			   user data */			wi->wi_bp.b_flags = 0;			wi->wi_bp.b_data = 0;			wi->wi_bp.b_bcount = 0;			wi->wi_bp.b_dev = 0;			wi->wi_bp.b_proc = p;			wdioctlstrategy(&wi->wi_bp);			error = wi->wi_bp.b_error;		}		*atareq = wi->wi_atareq;		wi_free(wi);		goto exit;		}#endif /* PMON */	default:		error = ENOTTY;		goto exit;	}#ifdef DIAGNOSTIC	panic("wdioctl: impossible");#endif exit:	device_unref(&wd->sc_dev);	return (error);}#ifdef B_FORMATintwdformat(struct buf *bp){	bp->b_flags |= B_FORMAT;	return wdstrategy(bp);}#endifintwdsize(dev)	dev_t dev;{	struct wd_softc *wd;	int part, omask;	int size;	WDCDEBUG_PRINT(("wdsize\n"), DEBUG_FUNCS);	wd = wdlookup(WDUNIT(dev));	if (wd == NULL)		return (-1);	part = WDPART(dev);	omask = wd->sc_dk.dk_openmask & (1 << part);	if (omask == 0 && wdopen(dev, 0, S_IFBLK, NULL) != 0) {		size = -1;		goto exit;	}	if (wd->sc_dk.dk_label->d_partitions[part].p_fstype != FS_SWAP)		size = -1;	else		size = wd->sc_dk.dk_label->d_partitions[part].p_size *		    (wd->sc_dk.dk_label->d_secsize / DEV_BSIZE);	if (omask == 0 && wdclose(dev, 0, S_IFBLK, NULL) != 0)		size = -1; exit:	device_unref(&wd->sc_dev);	return (size);}#ifndef __BDEVSW_DUMP_OLD_TYPE/* #define WD_DUMP_NOT_TRUSTED if you just want to watch */static int wddoingadump = 0;static int wddumprecalibrated = 0;static int wddumpmulti = 1;/* * Dump core after a system crash. */intwddump(dev, blkno, va, size)	dev_t dev;	daddr_t blkno;	caddr_t va;	size_t size;{	struct wd_softc *wd;	/* disk unit to do the I/O */	struct disklabel *lp;   /* disk's disklabel */	int unit, part;	int nblks;	/* total number of sectors left to write */	int err;	char errbuf[256];	/* Check if recursive dump; if so, punt. */	if (wddoingadump)		return EFAULT;	wddoingadump = 1;	unit = WDUNIT(dev);	wd = wdlookup(unit);	if (wd == NULL)		return ENXIO;	part = WDPART(dev);	/* Make sure it was initialized. */	if (wd->drvp->state < READY)		return ENXIO;	/* Convert to disk sectors.  Request must be a multiple of size. */	lp = wd->sc_dk.dk_label;	if ((size % lp->d_secsize) != 0)		return EFAULT;	nblks = size / lp->d_secsize;	blkno = blkno / (lp->d_secsize / DEV_BSIZE);	/* Check transfer bounds against partition size. */	if ((blkno < 0) || ((blkno + nblks) > lp->d_partitions[part].p_size))		return EINVAL;  	/* Offset block number to start of partition. */	blkno += lp->d_partitions[part].p_offset;	/* Recalibrate, if first dump transfer. */	if (wddumprecalibrated == 0) {		wddumpmulti = wd->sc_multi;		wddumprecalibrated = 1;		wd->drvp->state = RECAL;	}  	while (nblks > 0) {again:		wd->sc_wdc_bio.blkno = blkno;		wd->sc_wdc_bio.flags = ATA_POLL;		if (wddumpmulti == 1)			wd->sc_wdc_bio.flags |= ATA_SINGLE;		if (wd->sc_flags & WDF_LBA)			wd->sc_wdc_bio.flags |= ATA_LBA;		wd->sc_wdc_bio.bcount =			min(nblks, wddumpmulti) * lp->d_secsize;		wd->sc_wdc_bio.databuf = va;		wd->sc_wdc_bio.wd = wd;#ifndef WD_DUMP_NOT_TRUSTED		switch (wdc_ata_bio(wd->drvp, &wd->sc_wdc_bio)) {		case WDC_TRY_AGAIN:			panic("wddump: try again");			break;		case WDC_QUEUED:			panic("wddump: polled command has been queued");			break;		case WDC_COMPLETE:			break;		}		switch(wd->sc_wdc_bio.error) {		case TIMEOUT:			printf("wddump: device timed out");			err = EIO;			break;		case ERR_DF:			printf("wddump: drive fault");			err = EIO;			break;		case ERR_DMA:			printf("wddump: DMA error");			err = EIO;			break;		case ERROR:			errbuf[0] = '\0';			ata_perror(wd->drvp, wd->sc_wdc_bio.r_error, errbuf);			printf("wddump: %s", errbuf);			err = EIO;			break;		case NOERROR: 			err = 0;			break;		default:			panic("wddump: unknown error type");		}		if (err != 0) {			if (wddumpmulti != 1) {				wddumpmulti = 1; /* retry in single-sector */				printf(", retrying\n");				goto again;			}			printf("\n");			return err;		}#else	/* WD_DUMP_NOT_TRUSTED */		/* Let's just talk about this first... */		printf("wd%d: dump addr 0x%x, cylin %d, head %d, sector %d\n",		    unit, va, cylin, head, sector);		delay(500 * 1000);	/* half a second */#endif		/* update block count */		nblks -= min(nblks, wddumpmulti);		blkno += min(nblks, wddumpmulti);		va += min(nblks, wddumpmulti) * lp->d_secsize;	}	wddoingadump = 0;	return 0;}#else /* __BDEVSW_DUMP_NEW_TYPE */intwddump(dev, blkno, va, size)	dev_t dev;	daddr_t blkno;	caddr_t va;	size_t size;{	/* Not implemented. */	return ENXIO;}#endif /* __BDEVSW_DUMP_NEW_TYPE */#ifdef DKBAD/* * Internalize the bad sector table. */voidbad144intern(wd)	struct wd_softc *wd;{	struct dkbad *bt = &DKBAD(wd->sc_dk.dk_cpulabel);	struct disklabel *lp = wd->sc_dk.dk_label;	int i = 0;	WDCDEBUG_PRINT(("bad144intern\n"), DEBUG_XFERS);	for (; i < NBT_BAD; i++) {		if (bt->bt_bad[i].bt_cyl == 0xffff)			break;		wd->sc_badsect[i] =		    bt->bt_bad[i].bt_cyl * lp->d_secpercyl +		    (bt->bt_bad[i].bt_trksec >> 8) * lp->d_nsectors +		    (bt->bt_bad[i].bt_trksec & 0xff);	}	for (; i < NBT_BAD+1; i++)		wd->sc_badsect[i] = -1;}#endifintwd_get_params(wd, flags, params)	struct wd_softc *wd;	u_int8_t flags;	struct ataparams *params;{	switch (ata_get_params(wd->drvp, flags, params)) {	case CMD_AGAIN:		return 1;	case CMD_ERR:		/*		 * We `know' there's a drive here; just assume it's old.		 * This geometry is only used to read the MBR and print a		 * (false) attach message.		 */		strncpy(params->atap_model, "ST506",		    sizeof params->atap_model);		params->atap_config = ATA_CFG_FIXED;		params->atap_cylinders = 1024;		params->atap_heads = 8;		params->atap_sectors = 17;		params->atap_multi = 1;		params->atap_capabilities1 = params->atap_capabilities2 = 0;		wd->drvp->ata_vers = -1; /* Mark it as pre-ATA */		return 0;	case CMD_OK:		return 0;	default:		panic("wd_get_params: bad return code from ata_get_params");		/* NOTREACHED */	}}voidwd_flushcache(wd, flags)	struct wd_softc *wd;	int flags;{	struct wdc_command wdc_c;	if (wd->drvp->ata_vers < 4) /* WDCC_FLUSHCACHE is here since ATA-4 */		return;	bzero(&wdc_c, sizeof(struct wdc_command));	wdc_c.r_command = WDCC_FLUSHCACHE;	wdc_c.r_st_bmask = WDCS_DRDY;	wdc_c.r_st_pmask = WDCS_DRDY;	wdc_c.flags = flags | AT_WAIT;	wdc_c.timeout = 30000; /* 30s timeout */	if (wdc_exec_command(wd->drvp, &wdc_c) != WDC_COMPLETE) {		printf("%s: flush cache command didn't complete\n",		    wd->sc_dev.dv_xname);	}	if (wdc_c.flags & AT_TIMEOU) {		printf("%s: flush cache command timeout\n",		    wd->sc_dev.dv_xname);	}	if (wdc_c.flags & AT_DF) {		printf("%s: flush cache command: drive fault\n",		    wd->sc_dev.dv_xname);	}	/*	 * Ignore error register, it shouldn't report anything else	 * than COMMAND ABORTED, which means the device doesn't support	 * flush cache	 */}voidwd_shutdown(arg)	void *arg;{	struct wd_softc *wd = arg;	wd_flushcache(wd, ATA_POLL);}/* * Allocate space for a ioctl queue structure.  Mostly taken from * scsipi_ioctl.c */struct wd_ioctl *wi_get(){	struct wd_ioctl *wi;	int s;	wi = malloc(sizeof(struct wd_ioctl), M_TEMP, M_WAITOK);	bzero(wi, sizeof (struct wd_ioctl));	s = splbio();	LIST_INSERT_HEAD(&wi_head, wi, wi_list);	splx(s);	return (wi);}/* * Free an ioctl structure and remove it from our list */voidwi_free(wi)	struct wd_ioctl *wi;{	int s;	s = splbio();	LIST_REMOVE(wi, wi_list);	splx(s);	free(wi, M_TEMP);}/* * Find a wd_ioctl structure based on the struct buf. */struct wd_ioctl *wi_find(bp)	struct buf *bp;{	struct wd_ioctl *wi;	int s;	s = splbio();	for (wi = wi_head.lh_first; wi != 0; wi = wi->wi_list.le_next)		if (bp == &wi->wi_bp)			break;	splx(s);	return (wi);}/* * Ioctl pseudo strategy routine * * This is mostly stolen from scsipi_ioctl.c:scsistrategy().  What * happens here is: * * - wdioctl() queues a wd_ioctl structure. * * - wdioctl() calls physio/wdioctlstrategy based on whether or not *   user space I/O is required.  If physio() is called, physio() eventually *   calls wdioctlstrategy(). * * - In either case, wdioctlstrategy() calls wdc_exec_command() *   to perform the actual command * * The reason for the use of the pseudo strategy routine is because * when doing I/O to/from user space, physio _really_ wants to be in * the loop.  We could put the entire buffer into the ioctl request * structure, but that won't scale if we want to do things like download * microcode. */voidwdioctlstrategy(bp)	struct buf *bp;{	struct wd_ioctl *wi;	struct wdc_command wdc_c;	int error = 0;	wi = wi_find(bp);	if (wi == NULL) {		printf("user_strat: No ioctl\n");		error = EINVAL;		goto bad;	}	bzero(&wdc_c, sizeof(wdc_c));	/*	 * Abort if physio broke up the transfer	 */	if (bp->b_bcount != wi->wi_atareq.datalen) {		printf("physio split wd ioctl request... cannot proceed\n");		error = EIO;		goto bad;	}	/*	 * Abort if we didn't get a buffer size that was a multiple of	 * our sector size (or was larger than NBBY)	 */	if ((bp->b_bcount % wi->wi_softc->sc_dk.dk_label->d_secsize) != 0 ||	    (bp->b_bcount / wi->wi_softc->sc_dk.dk_label->d_secsize) >=	     (1 << NBBY)) {		error = EINVAL;		goto bad;	}	/*	 * Make sure a timeout was supplied in the ioctl request	 */	if (wi->wi_atareq.timeout == 0) {		error = EINVAL;		goto bad;	}	if (wi->wi_atareq.flags & ATACMD_READ)		wdc_c.flags |= AT_READ;	else if (wi->wi_atareq.flags & ATACMD_WRITE)		wdc_c.flags |= AT_WRITE;	if (wi->wi_atareq.flags & ATACMD_READREG)		wdc_c.flags |= AT_READREG;	wdc_c.flags |= AT_WAIT;	wdc_c.timeout = wi->wi_atareq.timeout;	wdc_c.r_command = wi->wi_atareq.command;	wdc_c.r_head = wi->wi_atareq.head & 0x0f;	wdc_c.r_cyl = wi->wi_atareq.cylinder;	wdc_c.r_sector = wi->wi_atareq.sec_num;	wdc_c.r_count = wi->wi_atareq.sec_count;	wdc_c.r_precomp = wi->wi_atareq.features;	wdc_c.r_st_bmask = WDCS_DRDY;	wdc_c.r_st_pmask = WDCS_DRDY;	wdc_c.data = wi->wi_bp.b_data;	wdc_c.bcount = wi->wi_bp.b_bcount;	if (wdc_exec_command(wi->wi_softc->drvp, &wdc_c) != WDC_COMPLETE) {		wi->wi_atareq.retsts = ATACMD_ERROR;		goto bad;	}	if (wdc_c.flags & (AT_ERROR | AT_TIMEOU | AT_DF)) {		if (wdc_c.flags & AT_ERROR) {			wi->wi_atareq.retsts = ATACMD_ERROR;			wi->wi_atareq.error = wdc_c.r_error;		} else if (wdc_c.flags & AT_DF)			wi->wi_atareq.retsts = ATACMD_DF;		else			wi->wi_atareq.retsts = ATACMD_TIMEOUT;	} else {		wi->wi_atareq.retsts = ATACMD_OK;		if (wi->wi_atareq.flags & ATACMD_READREG) {			wi->wi_atareq.head = wdc_c.r_head ;			wi->wi_atareq.cylinder = wdc_c.r_cyl;			wi->wi_atareq.sec_num = wdc_c.r_sector;			wi->wi_atareq.sec_count = wdc_c.r_count; 			wi->wi_atareq.features = wdc_c.r_precomp; 			wi->wi_atareq.error = wdc_c.r_error; 		}	}	bp->b_error = 0;	biodone(bp);	return;bad:	bp->b_flags |= B_ERROR;	bp->b_error = error;	biodone(bp);}

⌨️ 快捷键说明

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