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

📄 sys_sunos32.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 3 页
字号:
/* $Id: sys_sunos32.c,v 1.61 2001/08/13 14:40:07 davem Exp $ * sys_sunos32.c: SunOS binary compatability layer on sparc64. * * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) * * Based upon preliminary work which is: * * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/mman.h>#include <linux/mm.h>#include <linux/swap.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/resource.h>#include <linux/ipc.h>#include <linux/shm.h>#include <linux/msg.h>#include <linux/sem.h>#include <linux/signal.h>#include <linux/uio.h>#include <linux/utsname.h>#include <linux/major.h>#include <linux/stat.h>#include <linux/slab.h>#include <linux/pagemap.h>#include <linux/errno.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <asm/uaccess.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/pconf.h>#include <asm/idprom.h> /* for gethostid() */#include <asm/unistd.h>#include <asm/system.h>/* For the nfs mount emulation */#include <linux/socket.h>#include <linux/in.h>#include <linux/nfs.h>#include <linux/nfs2.h>#include <linux/nfs_mount.h>/* for sunos_select */#include <linux/time.h>#include <linux/personality.h>/* Use this to get at 32-bit user passed pointers. */#define A(__x)				\({	unsigned long __ret;		\	__asm__ ("srl	%0, 0, %0"	\		 : "=r" (__ret)		\		 : "0" (__x));		\	__ret;				\})#define SUNOS_NR_OPEN	256asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off){	struct file *file = NULL;	unsigned long retval, ret_type;	if(flags & MAP_NORESERVE) {		static int cnt;		if (cnt++ < 10)			printk("%s:  unimplemented SunOS MAP_NORESERVE mmap() flag\n",			       current->comm);		flags &= ~MAP_NORESERVE;	}	retval = -EBADF;	if(!(flags & MAP_ANONYMOUS)) {		struct inode * inode;		if(fd >= SUNOS_NR_OPEN)			goto out; 		file = fget(fd);		if (!file)			goto out;		inode = file->f_dentry->d_inode;		if(MAJOR(inode->i_rdev)==MEM_MAJOR && MINOR(inode->i_rdev)==5) {			flags |= MAP_ANONYMOUS;			fput(file);			file = NULL;		}	}	retval = -EINVAL;	if(!(flags & MAP_FIXED))		addr = 0;	else if (len > 0xf0000000 || addr > 0xf0000000 - len)		goto out_putf;	ret_type = flags & _MAP_NEW;	flags &= ~_MAP_NEW;	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);	down_write(&current->mm->mmap_sem);	retval = do_mmap(file,			 (unsigned long) addr, (unsigned long) len,			 (unsigned long) prot, (unsigned long) flags,			 (unsigned long) off);	up_write(&current->mm->mmap_sem);	if(!ret_type)		retval = ((retval < 0xf0000000) ? 0 : retval);out_putf:	if (file)		fput(file);out:	return (u32) retval;}asmlinkage int sunos_mctl(u32 addr, u32 len, int function, u32 arg){	return 0;}asmlinkage int sunos_brk(u32 baddr){	int freepages, retval = -ENOMEM;	unsigned long rlim;	unsigned long newbrk, oldbrk, brk = (unsigned long) baddr;	down_write(&current->mm->mmap_sem);	if (brk < current->mm->end_code)		goto out;	newbrk = PAGE_ALIGN(brk);	oldbrk = PAGE_ALIGN(current->mm->brk);	retval = 0;	if (oldbrk == newbrk) {		current->mm->brk = brk;		goto out;	}	/* Always allow shrinking brk. */	if (brk <= current->mm->brk) {		current->mm->brk = brk;		do_munmap(current->mm, newbrk, oldbrk-newbrk);		goto out;	}	/* Check against rlimit and stack.. */	retval = -ENOMEM;	rlim = current->rlim[RLIMIT_DATA].rlim_cur;	if (rlim >= RLIM_INFINITY)		rlim = ~0;	if (brk - current->mm->end_code > rlim)		goto out;	/* Check against existing mmap mappings. */	if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))		goto out;	/* stupid algorithm to decide if we have enough memory: while	 * simple, it hopefully works in most obvious cases.. Easy to	 * fool it, but this should catch most mistakes.	 */	freepages = atomic_read(&buffermem_pages) >> PAGE_SHIFT;	freepages += atomic_read(&page_cache_size);	freepages >>= 1;	freepages += nr_free_pages();	freepages += nr_swap_pages;	freepages -= num_physpages >> 4;	freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;	if (freepages < 0)		goto out;	/* Ok, we have probably got enough memory - let it rip. */	current->mm->brk = brk;	do_brk(oldbrk, newbrk-oldbrk);	retval = 0;out:	up_write(&current->mm->mmap_sem);	return retval;}asmlinkage u32 sunos_sbrk(int increment){	int error, oldbrk;	/* This should do it hopefully... */	oldbrk = (int)current->mm->brk;	error = sunos_brk(((int) current->mm->brk) + increment);	if(!error)		error = oldbrk;	return error;}asmlinkage u32 sunos_sstk(int increment){	printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",	       current->comm, increment);	return (u32)-1;}/* Give hints to the kernel as to what paging strategy to use... * Completely bogus, don't remind me. */#define VA_NORMAL     0 /* Normal vm usage expected */#define VA_ABNORMAL   1 /* Abnormal/random vm usage probable */#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */static char *vstrings[] = {	"VA_NORMAL",	"VA_ABNORMAL",	"VA_SEQUENTIAL",	"VA_INVALIDATE",};asmlinkage void sunos_vadvise(u32 strategy){	static int count = 0;	/* I wanna see who uses this... */	if (count++ < 5)		printk("%s: Advises us to use %s paging strategy\n",		       current->comm,		       strategy <= 3 ? vstrings[strategy] : "BOGUS");}/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE * resource limit and is for backwards compatibility with older sunos * revs. */asmlinkage int sunos_getdtablesize(void){	return SUNOS_NR_OPEN;}#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))asmlinkage u32 sunos_sigblock(u32 blk_mask){	u32 old;	spin_lock_irq(&current->sigmask_lock);	old = (u32) current->blocked.sig[0];	current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	return old;}asmlinkage u32 sunos_sigsetmask(u32 newmask){	u32 retval;	spin_lock_irq(&current->sigmask_lock);	retval = (u32) current->blocked.sig[0];	current->blocked.sig[0] = (newmask & _BLOCKABLE);	recalc_sigpending(current);	spin_unlock_irq(&current->sigmask_lock);	return retval;}/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant)    *//* getdents system call, the format of the structure just has a different *//* layout (d_off+d_ino instead of d_ino+d_off) */struct sunos_dirent {    s32		d_off;    u32		d_ino;    u16		d_reclen;    u16		d_namlen;    char	d_name[1];};struct sunos_dirent_callback {    struct sunos_dirent *curr;    struct sunos_dirent *previous;    int count;    int error;};#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))#define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1))static int sunos_filldir(void * __buf, const char * name, int namlen,			 loff_t offset, ino_t ino, unsigned int d_type){	struct sunos_dirent * dirent;	struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf;	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);	buf->error = -EINVAL;	/* only used if we fail.. */	if (reclen > buf->count)		return -EINVAL;	dirent = buf->previous;	if (dirent)		put_user(offset, &dirent->d_off);	dirent = buf->curr;	buf->previous = dirent;	put_user(ino, &dirent->d_ino);	put_user(namlen, &dirent->d_namlen);	put_user(reclen, &dirent->d_reclen);	copy_to_user(dirent->d_name, name, namlen);	put_user(0, dirent->d_name + namlen);	((char *) dirent) += reclen;	buf->curr = dirent;	buf->count -= reclen;	return 0;}asmlinkage int sunos_getdents(unsigned int fd, u32 u_dirent, int cnt){	struct file * file;	struct sunos_dirent * lastdirent;	struct sunos_dirent_callback buf;	int error = -EBADF;	void *dirent = (void *)A(u_dirent);	if(fd >= SUNOS_NR_OPEN)		goto out;	file = fget(fd);	if(!file)		goto out;	error = -EINVAL;	if(cnt < (sizeof(struct sunos_dirent) + 255))		goto out_putf;	buf.curr = (struct sunos_dirent *) dirent;	buf.previous = NULL;	buf.count = cnt;	buf.error = 0;	error = vfs_readdir(file, sunos_filldir, &buf);	if (error < 0)		goto out_putf;	lastdirent = buf.previous;	error = buf.error;	if (lastdirent) {		put_user(file->f_pos, &lastdirent->d_off);		error = cnt - buf.count;	}out_putf:	fput(file);out:	return error;}/* Old sunos getdirentries, severely broken compatibility stuff here. */struct sunos_direntry {    u32		d_ino;    u16		d_reclen;    u16		d_namlen;    char	d_name[1];};struct sunos_direntry_callback {    struct sunos_direntry *curr;    struct sunos_direntry *previous;    int count;    int error;};static int sunos_filldirentry(void * __buf, const char * name, int namlen,			      loff_t offset, ino_t ino, unsigned int d_type){	struct sunos_direntry * dirent;	struct sunos_direntry_callback * buf = (struct sunos_direntry_callback *) __buf;	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);	buf->error = -EINVAL;	/* only used if we fail.. */	if (reclen > buf->count)		return -EINVAL;	dirent = buf->previous;	dirent = buf->curr;	buf->previous = dirent;	put_user(ino, &dirent->d_ino);	put_user(namlen, &dirent->d_namlen);	put_user(reclen, &dirent->d_reclen);	copy_to_user(dirent->d_name, name, namlen);	put_user(0, dirent->d_name + namlen);	((char *) dirent) += reclen;	buf->curr = dirent;	buf->count -= reclen;	return 0;}asmlinkage int sunos_getdirentries(unsigned int fd, u32 u_dirent,				   int cnt, u32 u_basep){	void *dirent = (void *) A(u_dirent);	unsigned int *basep = (unsigned int *)A(u_basep);	struct file * file;	struct sunos_direntry * lastdirent;	int error = -EBADF;	struct sunos_direntry_callback buf;	if(fd >= SUNOS_NR_OPEN)		goto out;	file = fget(fd);	if(!file)		goto out;	error = -EINVAL;	if(cnt < (sizeof(struct sunos_direntry) + 255))		goto out_putf;	buf.curr = (struct sunos_direntry *) dirent;	buf.previous = NULL;	buf.count = cnt;	buf.error = 0;	error = vfs_readdir(file, sunos_filldirentry, &buf);	if (error < 0)		goto out_putf;	lastdirent = buf.previous;	error = buf.error;	if (lastdirent) {		put_user(file->f_pos, basep);		error = cnt - buf.count;	}out_putf:	fput(file);out:	return error;}struct sunos_utsname {	char sname[9];	char nname[9];	char nnext[56];	char rel[9];	char ver[9];	char mach[9];};asmlinkage int sunos_uname(struct sunos_utsname *name){	int ret;	down_read(&uts_sem);	ret = copy_to_user(&name->sname[0], &system_utsname.sysname[0], sizeof(name->sname) - 1);	ret |= copy_to_user(&name->nname[0], &system_utsname.nodename[0], sizeof(name->nname) - 1);	ret |= put_user('\0', &name->nname[8]);	ret |= copy_to_user(&name->rel[0], &system_utsname.release[0], sizeof(name->rel) - 1);	ret |= copy_to_user(&name->ver[0], &system_utsname.version[0], sizeof(name->ver) - 1);	ret |= copy_to_user(&name->mach[0], &system_utsname.machine[0], sizeof(name->mach) - 1);	up_read(&uts_sem);	return ret;}asmlinkage int sunos_nosys(void){	struct pt_regs *regs;

⌨️ 快捷键说明

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