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

📄 devfs.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
字号:
/* $Id: devfs.c,v 1.3 2003/06/05 21:50:22 patrik Exp $ *//* * Copyright (c) 1998-2003 Opsycon AB (www.opsycon.se) *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Opsycon AB, Sweden. * 4. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * *//* *	_Very_ simplified support functions to i/o subsystem. */#include <sys/param.h>#include <sys/proc.h>#include <sys/stat.h>#include <sys/buf.h>#include <sys/device.h>#include <string.h>#include <pmon.h>#include <file.h>#include "cd.h"#include "sd.h"#include "wd.h"extern int errno;struct devsw {	char	*name;	int	(*open) __P((dev_t, int flags, int mode, void *));	int	(*read) __P((dev_t dev, void *uio, int flag));	int	(*write) __P((dev_t dev, void *uio, int flag));	int	(*close) __P((dev_t dev, int flag, int mode, void *));};extern int sdopen __P((dev_t dev, int flags, int mode, void *));extern int sdread __P((dev_t dev, void *uio, int flag));extern int sdwrite __P((dev_t dev, void *uio, int flag));extern int sdclose __P((dev_t dev, int flag, int mode, void *));extern int cdopen __P((dev_t dev, int flags, int mode, void *));extern int cdread __P((dev_t dev, void *uio, int flag));extern int cdwrite __P((dev_t dev, void *uio, int flag));extern int cdclose __P((dev_t dev, int flag, int mode, void *));extern int wdopen __P((dev_t dev, int flags, int mode, void *));extern int wdread __P((dev_t dev, void *uio, int flag));extern int wdwrite __P((dev_t dev, void *uio, int flag));extern int wdclose __P((dev_t dev, int flag, int mode, void *));/* * Check for and add any target specific declarations from "pmon_target.h" */#if defined(TGT_DEV_DECL)TGT_DEV_DECL#endifvoid disksort __P((struct buf *, struct buf *));struct devsw devswitch[] = {	{ "console" },#if NSD > 0	{ "sd", sdopen, sdread, sdwrite, sdclose },#endif#if NWD > 0	{ "wd", wdopen, wdread, wdwrite, wdclose },#endif#if NCD > 0	{ "cd", cdopen, cdread, cdwrite, cdclose },#endif/* Add any target specific devices. See "pmon_target.h" */#if defined(TGT_DEV_SWITCH)	TGT_DEV_SWITCH#endif	{ NULL},};static struct biodev {	dev_t	devno;	off_t	offs;	off_t	base;	off_t	end;	int	*maptab;} opendevs[OPEN_MAX];int   devio_open (int, const char *, int, int);int   devio_close (int);int   devio_read (int, void *, size_t);int   devio_write (int, const void *, size_t);off_t devio_lseek (int, off_t, int);/* Forward */dev_t find_device (const char **name);/* *  No need to sort really. We can only have one request at a time. */voiddisksort(ap, bp)	struct buf *ap, *bp;{	bp->b_actf = NULL;	ap->b_actf = bp;	return;}/* *  Bio done. Nothing to do, we run polled... */voidbiodone(buf)	struct buf *buf;{	buf->b_flags &= ~B_BUSY;	wakeup(buf);}/* *  Very simplified PHYSIO. Adjust and pass on. */intphysio(strategy, bp, dev, flags, minphys, uio)	void (*strategy) __P((struct buf *));	struct buf *bp;	dev_t dev;	int flags;	void (*minphys) __P((struct buf *));	struct uio *uio;{	int error = 0;	struct buf lbp;	int s;	if(bp == NULL) {		memset((void *)&lbp, 0, sizeof(struct buf));		bp = &lbp;	}	bp->b_dev    = dev;	bp->b_error  = 0;	bp->b_bcount = uio->uio_iov[0].iov_len;	bp->b_data   = uio->uio_iov[0].iov_base;	bp->b_blkno  = btodb(uio->uio_offset);	bp->b_flags = B_BUSY | B_PHYS | B_RAW | flags;	(*strategy)(bp);	if (!(bp->b_flags & B_ERROR)) {		s = splbio();		while (!(bp->b_flags & B_ERROR) && bp->b_flags & B_BUSY) {			tsleep(bp, PRIBIO + 1, "biowait", 0);		}	}	splx(s);	if (bp->b_flags & B_ERROR) {		error = (bp->b_error ? bp->b_error : EIO);	}	return(error);}/* *  Open a disk device. *  Look for /[dev/][disk/]<devname>[@start[,size][/...]] *  The construct /[dev/][disk/]<devname>/<path> is not *  allowed since it reference a file structured device *  and not a raw device. */intdevio_open(fd, name, flags, mode)	int fd;	const char *name;	int flags, mode;{	int mj;	u_int32_t v;	dev_t dev;	struct biodev *devstat;	char strbuf[64], *strp, *p;	dev = find_device(&name);	if(dev == NULL || *name == '/') {		errno = ENOENT;		return -1;	}	mj = dev >> 8;	devstat = &opendevs[fd];	devstat->devno = dev;	devstat->offs = 0;	devstat->base = 0;	devstat->maptab = 0;	devstat->end = 0x10000000000;	/* Check for any subsize specification */	if (*name == '@') {		name++;		strncpy(strbuf, name, sizeof(strbuf));		strp = strpbrk(strbuf, "/,:");		if(!strp) {			strp = strbuf + sizeof(strbuf);		}		else if(*strp != '/') {			*strp++ = '\0';			if((p = index(strp, '/')))				*p = 0;			if(!get_rsa(&v, strp)) {				errno = EBADF;				return -1;			}			else				devstat->end = (off_t)v << DEV_BSHIFT;		}		*strp++ = '\0';		if(!get_rsa(&v, strbuf)) {			errno = EBADF;			return -1;		}		else {			devstat->base = (off_t)v << DEV_BSHIFT;			devstat->offs = (off_t)v << DEV_BSHIFT;			devstat->end += (off_t)v << DEV_BSHIFT;		}	}	else if (*name != '\0') {		errno = EBADF;		return -1;	}	/* Now call the physical device open function */	curproc->p_stat = SRUN;	errno = (*devswitch[mj].open)(dev, 0, S_IFCHR, NULL);	curproc->p_stat = SNOTKERN;	if(errno) {		return -1;	}	return(fd);}/* *  Lookup and 'close' a disk device. (we are not counting...) */intdevio_close(fd)	int fd;{	int mj;	mj = opendevs[fd].devno >> 8;	curproc->p_stat = SRUN;	errno = (*devswitch[mj].close)(opendevs[fd].devno, 0, S_IFCHR, NULL);	curproc->p_stat = SNOTKERN;	opendevs[fd].devno = 0;	if(errno) {		return(-1);	}	return(0);}/* *  Read data from a device. */intdevio_read(fd, buf, blen)	int fd;	void *buf;	size_t blen;{	int mj;	struct uio uio;	struct iovec iovec;static char lbuff[DEV_BSIZE];	if(opendevs[fd].offs < opendevs[fd].base ||	   opendevs[fd].offs > opendevs[fd].end) {		errno = EINVAL;		return(-1);	}	if(blen > (opendevs[fd].end - opendevs[fd].offs))		blen = opendevs[fd].end - opendevs[fd].offs;	if (blen == 0)		return(0);	/* Check for unaligned read, eg we need to buffer */	if (opendevs[fd].offs & (DEV_BSIZE - 1) || blen < DEV_BSIZE) {		int suboffs = opendevs[fd].offs & (DEV_BSIZE - 1);		char *p = &lbuff[suboffs];		int c, n = 0;		opendevs[fd].offs &= ~(DEV_BSIZE - 1);		if (devio_read(fd, lbuff, DEV_BSIZE) < 0) {			opendevs[fd].offs += suboffs;			return(-1);		}		while(blen && suboffs < DEV_BSIZE) {			*((char *)buf)++ = *p++;			blen--;			suboffs++;			n++;		}		opendevs[fd].offs -= (DEV_BSIZE - suboffs);		c = devio_read(fd, buf, blen);		if (c >= 0)			return(c + n);		else			return(-1);	}	else if(blen & (DEV_BSIZE - 1)) {		int c, n;		c = devio_read(fd, buf, blen & ~(DEV_BSIZE - 1));		if (c < 0)			return(-1);		buf += c;		blen -= c;		n = devio_read(fd, buf, blen);		if (n >= 0)			return(n + c);		else			return(-1);	}	if (blen > MAXPHYS) {		int c, n = 0;		do {			c = devio_read(fd, buf, min(MAXPHYS, blen));			if (c < 0)				return(-1);			n += c;			blen -= c;			buf += c;		} while (blen > 0);		return(n);	}	else {		mj = opendevs[fd].devno >> 8;		uio.uio_iovcnt = 1;		uio.uio_iov = &iovec;		uio.uio_rw = UIO_READ;		uio.uio_offset = opendevs[fd].offs;			iovec.iov_base = buf;		iovec.iov_len = blen;		curproc->p_stat = SRUN;		errno = (*devswitch[mj].read)(opendevs[fd].devno, &uio, 0);		curproc->p_stat = SNOTKERN;	}	if(errno) {		return(-1);	}	opendevs[fd].offs += blen;	return(blen);}/* *  Write data to a device. */intdevio_write(fd, buf, blen)	int fd;	const void *buf;	size_t blen;{	int mj;	struct uio uio;	struct iovec iovec;	if (blen == 0)		return(0);	mj = opendevs[fd].devno >> 8;	uio.uio_iovcnt = 1;	uio.uio_iov = &iovec;	uio.uio_rw = UIO_WRITE;	uio.uio_offset = opendevs[fd].offs;		iovec.iov_base = (void *)buf;	iovec.iov_len = blen;	curproc->p_stat = SRUN;	errno = (*devswitch[mj].write)(opendevs[fd].devno, &uio, 0);	curproc->p_stat = SNOTKERN;	if(errno) {		return(-1);	}	return(blen);}/* *  Move current pointer on device. */off_tdevio_lseek(fd, offs, whence)	int fd;	off_t offs;	int whence;{	if(whence == 0)		opendevs[fd].offs = opendevs[fd].base + offs;	else		opendevs[fd].offs += offs;	if(opendevs[fd].offs > opendevs[fd].end)		opendevs[fd].offs = opendevs[fd].end;	return(opendevs[fd].offs - opendevs[fd].base);}/* *  Lookup a phys device in the phys dev table. */extern struct cfdata cfdata[];dev_tfind_device(name)	const char **name;{	struct cfdata *cf;	struct cfdriver *cd;	struct device *dv;	dev_t dev;	int i;	struct devsw *devsw;	const char *pname;	/* Discard /dev/ and disk/ from name */	pname = *name;	if (strncmp(pname, "/dev/", 5) == 0)		pname += 5;	if (strncmp(pname, "disk", 4) == 0) {		pname += 4;	}	if (*pname == '/')		pname++;	/* Skip over leading slash if dev is first */	if (*pname == '@')		pname++;	/* Skip over leading @ if dev is first */	for(devsw = devswitch; devsw->name != NULL; devsw++) {		if(!strbequ(pname, devsw->name)) {			continue;		}		break;	}	if(devsw->name == NULL) {		return NULL;		/* Not found */	}	dev = devsw - devswitch;	/* Major number in dispatch table */	for(cf = cfdata; (cd = cf->cf_driver); cf++) {		if(cd->cd_devs == NULL)			continue;		for(i = 0; i < cd->cd_ndevs; i++) {			if((dv = cd->cd_devs[i]) == NULL)				continue;			if(!strbequ(pname, dv->dv_xname))				continue;			dev = (dev << 8) | i;			*name = pname + strlen(dv->dv_xname);			return(dev);		}	}	return NULL;}/* *  File system registration info. */static FileSystem diskfs = {	"disk", FS_DEV,	devio_open,	devio_read,	devio_write,	devio_lseek,	devio_close,	NULL};static void init_fs(void) __attribute__ ((constructor));static voidinit_fs(){	filefs_init(&diskfs);}

⌨️ 快捷键说明

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