/* $Id: misc.c,v 1.36 2002/02/09 19:49:31 davem Exp $
* misc.c: Miscellaneous syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/smp_lock.h>
#include <linux/utsname.h>
#include <linux/limits.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/mman.h>
#include <linux/file.h>
#include <linux/timex.h>
#include <linux/major.h>
#include <linux/compat.h>
#include <asm/uaccess.h>
#include <asm/string.h>
#include <asm/oplib.h>
#include <asm/idprom.h>
#include <asm/smp.h>
#include "conv.h"
/* Conversion from Linux to Solaris errnos. 0-34 are identity mapped.
Some Linux errnos (EPROCLIM, EDOTDOT, ERREMOTE, EUCLEAN, ENOTNAM,
ENAVAIL, EISNAM, EREMOTEIO, ENOMEDIUM, EMEDIUMTYPE) have no Solaris
equivalents. I return EINVAL in that case, which is very wrong. If
someone suggest a better value for them, you're welcomed.
On the other side, Solaris ECANCELED and ENOTSUP have no Linux equivalents,
but that doesn't matter here. --jj */
int solaris_err_table[] = {
/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
/* 10 */ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
/* 20 */ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
/* 30 */ 30, 31, 32, 33, 34, 22, 150, 149, 95, 96,
/* 40 */ 97, 98, 99, 120, 121, 122, 123, 124, 125, 126,
/* 50 */ 127, 128, 129, 130, 131, 132, 133, 134, 143, 144,
/* 60 */ 145, 146, 90, 78, 147, 148, 93, 22, 94, 49,
/* 70 */ 151, 66, 60, 62, 63, 35, 77, 36, 45, 46,
/* 80 */ 64, 22, 67, 68, 69, 70, 71, 74, 22, 82,
/* 90 */ 89, 92, 79, 81, 37, 38, 39, 40, 41, 42,
/* 100 */ 43, 44, 50, 51, 52, 53, 54, 55, 56, 57,
/* 110 */ 87, 61, 84, 65, 83, 80, 91, 22, 22, 22,
/* 120 */ 22, 22, 88, 86, 85, 22, 22,
};
#define SOLARIS_NR_OPEN 256
static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 off)
{
struct file *file = NULL;
unsigned long retval, ret_type;
/* Do we need it here? */
set_personality(PER_SVR4);
if (flags & MAP_NORESERVE) {
static int cnt;
if (cnt < 5) {
printk("%s: unimplemented Solaris MAP_NORESERVE mmap() flag\n",
current->comm);
cnt++;
}
flags &= ~MAP_NORESERVE;
}
retval = -EBADF;
if(!(flags & MAP_ANONYMOUS)) {
if(fd >= SOLARIS_NR_OPEN)
goto out;
file = fget(fd);
if (!file)
goto out;
else {
struct inode * inode = file->f_dentry->d_inode;
if(imajor(inode) == MEM_MAJOR &&
iminor(inode) == 5) {
flags |= MAP_ANONYMOUS;
fput(file);
file = NULL;
}
}
}
retval = -EINVAL;
len = PAGE_ALIGN(len);
if(!(flags & MAP_FIXED))
addr = 0;
else if (len > 0xf0000000UL || addr > 0xf0000000UL - len)
goto out_putf;
ret_type = flags & _MAP_NEW;
flags &= ~_MAP_NEW;
down_write(¤t->mm->mmap_sem);
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
retval = do_mmap(file,
(unsigned long) addr, (unsigned long) len,
(unsigned long) prot, (unsigned long) flags, off);
up_write(¤t->mm->mmap_sem);
if(!ret_type)
retval = ((retval < 0xf0000000) ? 0 : retval);
out_putf:
if (file)
fput(file);
out:
return (u32) retval;
}
asmlinkage u32 solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off)
{
return do_solaris_mmap(addr, len, prot, flags, fd, (u64) off);
}
asmlinkage u32 solaris_mmap64(struct pt_regs *regs, u32 len, u32 prot, u32 flags, u32 fd, u32 offhi)
{
u32 offlo;
if (regs->u_regs[UREG_G1]) {
if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x5c)))
return -EFAULT;
} else {
if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[