Hi,

Enclosed is a patch against kernel 2.2.11 that offers some improvements to
the solaris emulation. This patch was tested on a Sun Ultra 5 workstation. 

-implemented F_FREESP (truncate) fcntl op
-socketpair seems to take just one arg on solairs, emul code was taking
three
-converted solaris socket options to linux equivalents (for setsockopt and
getsockopt). SO_STATE isn't emulated correctly, but for the app I was
working with it worked fine. If SO_STATE were documented.... 
-added MTIO (magnetic tape) ioctls
-added openprom ioctls (solaris eeprom works as expected)

The way I fixed socketpair is certainly not the right way to do it, but I
haven't figured out how change the number of arguments a syscall
takes...if someone would point me in the right direction I'd be happy to
fix it...I'm just not sure where to start. 

Jason



--- v2.2.11/arch/sparc64/solaris/fs.c   Wed Jun  2 12:55:38 1999
+++ linux/arch/sparc64/solaris/fs.c     Thu Aug 19 16:50:29 1999
@@ -2,6 +2,9 @@
  * fs.c: fs related syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek ([EMAIL PROTECTED])
+ *
+ * 1999-08-19 Implemented solaris F_FREESP (truncate)
+ *            fcntl, by Jason Rappleye ([EMAIL PROTECTED])
  */
 
 #include <linux/types.h>
@@ -19,6 +22,8 @@
 #include <asm/string.h>
 #include <asm/ptrace.h>
 
+#include <sys/syscall.h>
+
 #include "conv.h"
 
 extern char * getname32(u32 filename);
@@ -635,7 +640,7 @@
        case SOL_F_GETLK:
        case SOL_F_SETLK:
        case SOL_F_SETLKW:
-               {
+               {
                        struct flock f;
                        mm_segment_t old_fs = get_fs();
 
@@ -660,6 +665,15 @@
                        __put_user_ret (f.l_pid, &((struct sol_flock *)A(arg))->l_pid, 
-EFAULT);
                        __put_user_ret (0, &((struct sol_flock *)A(arg))->l_sysid, 
-EFAULT);
                        return ret;
+               }
+       case SOL_F_FREESP:
+               { 
+                   int length;
+                   int (*sys_newftruncate)(unsigned int, unsigned long)=
+                           (int (*)(unsigned int, unsigned long))SYS(ftruncate);
+
+                   get_user_ret(length, &((struct sol_flock*)A(arg))->l_start, 
+-EFAULT);
+                   return sys_newftruncate(fd, length);
                }
        }
        return -EINVAL;
--- v2.2.11/arch/sparc64/solaris/ioctl.c        Tue Apr 14 20:44:21 1998
+++ linux/arch/sparc64/solaris/ioctl.c  Thu Aug 19 16:50:46 1999
@@ -7,6 +7,9 @@
  * Streams & timod emulation based on code
  * Copyright (C) 1995, 1996 Mike Jagdis ([EMAIL PROTECTED])
  *
+ * 1999-08-19 Implemented solaris 'm' (mag tape) and
+ *            'O' (openprom) ioctls, by Jason Rappleye
+ *             ([EMAIL PROTECTED])
  */
 
 #include <linux/types.h>
@@ -18,9 +21,12 @@
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/netdevice.h>
+#include <linux/mtio.h>
+#include <linux/time.h>
 
 #include <asm/uaccess.h>
 #include <asm/termios.h>
+#include <asm/openpromio.h>
 
 #include "conv.h"
 #include "socksys.h"
@@ -675,7 +681,7 @@
        case 87: /* SIOCGIFNUM */
                {
                        struct device *d;
-                       int i = 0;
+                       int i = 0;
                        
                        for (d = dev_base; d; d = d->next) i++;
                        if (put_user (i, (int *)A(arg)))
@@ -688,6 +694,72 @@
 
 /* }}} */
 
+static inline int solaris_m(unsigned int fd, unsigned int cmd, u32 arg)
+{
+
+       struct file * flip;
+       flip=fget(fd);
+
+       switch (cmd & 0xff) {
+       case 1: /* MTIOCTOP */
+               return sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg);
+       case 2: /* MTIOCGET */
+               return sys_ioctl(fd, MTIOCGET, (unsigned long)&arg);
+       case 3: /* MTIOCGETDRIVETYPE */
+       case 4: /* MTIOCPERSISTENT */
+       case 5: /* MTIOCPERSISTENTSTATUS */
+       case 6: /* MTIOCLRERR */
+       case 7: /* MTIOCGUARANTEEDORDER */
+       case 8: /* MTIOCRESERVE */
+       case 9: /* MTIOCRELEASE */
+       case 10: /* MTIOCFORCERESERVE */
+       case 13: /* MTIOCSTATE */
+       case 14: /* MTIOCREADIGNOREILI */
+       case 15: /* MTIOCREADIGNOREEOFS */
+       case 16: /* MTIOCSHORTFMK */
+               return -ENOSYS; /* linux doesn't support these */
+       }
+
+       return -ENOSYS;
+}
+
+static inline int solaris_O(unsigned int fd, unsigned int cmd, u32 arg)
+{
+       switch (cmd & 0xff) {
+       case 1: /* OPROMGETOPT */
+               return sys_ioctl(fd, OPROMGETOPT, arg);
+       case 2: /* OPROMSETOPT */
+               return sys_ioctl(fd, OPROMSETOPT, arg);
+       case 3: /* OPROMNXTOPT */
+               return sys_ioctl(fd, OPROMNXTOPT, arg);
+       case 4: /* OPROMSETOPT2 */
+               return sys_ioctl(fd, OPROMSETOPT2, arg);
+       case 5: /* OPROMNEXT */
+               return sys_ioctl(fd, OPROMNEXT, arg);
+       case 6: /* OPROMCHILD */
+               return sys_ioctl(fd, OPROMCHILD, arg);
+       case 7: /* OPROMGETPROP */
+               return sys_ioctl(fd, OPROMGETPROP, arg);
+       case 8: /* OPROMNXTPROP */
+               return sys_ioctl(fd, OPROMNXTPROP, arg);
+       case 9: /* OPROMU2P */
+               return sys_ioctl(fd, OPROMU2P, arg);
+       case 10: /* OPROMGETCONS */
+               return sys_ioctl(fd, OPROMGETCONS, arg);
+       case 11: /* OPROMGETFBNAME */
+               return sys_ioctl(fd, OPROMGETFBNAME, arg);
+       case 12: /* OPROMGETBOOTARGS */
+               return sys_ioctl(fd, OPROMGETBOOTARGS, arg);
+       case 13: /* OPROMGETVERSION */
+       case 14: /* OPROMPATH2DRV */
+       case 15: /* OPROMDEV2PROMNAME */
+       case 16: /* OPROMPROM2DEVNAME */
+       case 17: /* OPROMGETPROPLEN */
+               return -EINVAL;
+       }
+       return -EINVAL;
+}
+
 asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg)
 {
        struct file *filp;
@@ -695,6 +767,7 @@
 
        lock_kernel();
        filp = fcheck(fd);
+
        if (!filp)
                goto out;
 
@@ -707,19 +780,24 @@
        case 's': error = solaris_s(fd, cmd, arg); break;
        case 't': error = solaris_t(fd, cmd, arg); break;
        case 'f': error = sys_ioctl(fd, cmd, arg); break;
+       case 'm': error = solaris_m(fd, cmd, arg); break;
+       case 'O': error = solaris_O(fd, cmd, arg); break;
        default:
                error = -ENOSYS;
                break;
        }
+
 out:
        if (error == -ENOSYS) {
                unsigned char c = cmd>>8;
-               
+
                if (c < ' ' || c > 126) c = '.';
                printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)\n",
                       (int)fd, (unsigned int)cmd, c, (unsigned int)arg);
                error = -EINVAL;
        }
+
        unlock_kernel();
        return error;
 }
+
--- v2.2.11/arch/sparc64/solaris/socket.c       Mon Nov 16 13:37:28 1998
+++ linux/arch/sparc64/solaris/socket.c Thu Aug 19 16:50:58 1999
@@ -2,6 +2,9 @@
  * socket.c: Socket syscall emulation for Solaris 2.6+
  *
  * Copyright (C) 1998 Jakub Jelinek ([EMAIL PROTECTED])
+ *
+ * 1999-08-19 Fixed socketpair code 
+ *            Jason Rappleye ([EMAIL PROTECTED])
  */
 
 #include <linux/types.h>
@@ -25,6 +28,18 @@
 #define SOCK_SOL_RDM           5
 #define SOCK_SOL_SEQPACKET     6
 
+#define SOL_SO_SNDLOWAT                0x1003
+#define SOL_SO_RCVLOWAT                0x1004
+#define SOL_SO_SNDTIMEO                0x1005
+#define SOL_SO_RCVTIMEO                0x1006
+#define SOL_SO_STATE           0x2000
+
+#define SOL_SS_NDELAY          0x040
+#define SOL_SS_NONBLOCK                0x080
+#define SOL_SS_ASYNC           0x100
+
+#define SO_STATE               0x000e
+
 static int socket_check(int family, int type)
 {
        if (family != PF_UNIX && family != PF_INET)
@@ -40,6 +55,19 @@
        return type;
 }
 
+static int solaris_to_linux_sockopt(int optname) 
+{
+       switch (optname) {
+       case SOL_SO_SNDLOWAT: optname = SO_SNDLOWAT; break;
+       case SOL_SO_RCVLOWAT: optname = SO_RCVLOWAT; break;
+       case SOL_SO_SNDTIMEO: optname = SO_SNDTIMEO; break;
+       case SOL_SO_RCVTIMEO: optname = SO_RCVTIMEO; break;
+       case SOL_SO_STATE: optname = SO_STATE; break;
+       }
+       
+       return optname;
+}
+       
 asmlinkage int solaris_socket(int family, int type, int protocol)
 {
        int (*sys_socket)(int, int, int) =
@@ -55,9 +83,12 @@
        int (*sys_socketpair)(int, int, int, int *) =
                (int (*)(int, int, int, int *))SYS(socketpair);
 
-       type = socket_check (family, type);
-       if (type < 0) return type;
-       return sys_socketpair(family, type, protocol, usockvec);
+       /* solaris socketpair really only takes one arg at the syscall
+          level, int * usockvec. The libs apparently take care of 
+          making sure that family==AF_UNIX and type==SOCK_STREAM. The 
+          pointer we really want ends up residing in family */
+
+       return sys_socketpair(AF_UNIX, SOCK_STREAM, 0, (int *)family);
 }
 
 asmlinkage int solaris_bind(int fd, struct sockaddr *addr, int addrlen)
@@ -68,10 +99,19 @@
        return sys_bind(fd, addr, addrlen);
 }
 
+
 asmlinkage int solaris_setsockopt(int fd, int level, int optname, u32 optval, int 
optlen)
 {
        int (*sunos_setsockopt)(int, int, int, u32, int) =
                (int (*)(int, int, int, u32, int))SUNOS(105);
+       int val;
+
+       optname = solaris_to_linux_sockopt(optname);
+       get_user_ret(val, (int *)A(optval), -EFAULT);
+       printk("solaris_setsockopt: optname (%#x) optval (%#x)\n", optname, val);
+
+       if (optname < 0) return optname;
+       if (optname == SO_STATE) return 0;
 
        return sunos_setsockopt(fd, level, optname, optval, optlen);
 }
@@ -80,6 +120,11 @@
 {
        int (*sunos_getsockopt)(int, int, int, u32, u32) =
                (int (*)(int, int, int, u32, u32))SUNOS(118);
+
+       optname = solaris_to_linux_sockopt(optname);
+       if (optname < 0) return optname;        
+
+       if (optname == SO_STATE) optname = SOL_SO_STATE;
 
        return sunos_getsockopt(fd, level, optname, optval, optlen);
 }
--- v2.2.11/drivers/sbus/char/openprom.c        Mon Aug 24 16:14:09 1998
+++ linux/drivers/sbus/char/openprom.c  Thu Aug 19 15:55:12 1999
@@ -70,10 +70,22 @@
                return -EFAULT;
 
        get_user_ret(bufsize, &info->oprom_size, -EFAULT);
-
-       if (bufsize == 0 || bufsize > OPROMMAXPARAM)
+#if 0
+       if (bufsize == 0 || bufsize > OPROMMAXPARAM) 
+               return -EINVAL;
+#endif
+       if (bufsize == 0) 
                return -EINVAL;
 
+       /* max buf size is higher on solaris...maybe the right way to
+          do this is to change the value of OPROMMAXPARAM in the
+          header file ? */
+
+       if (bufsize > OPROMMAXPARAM) {
+               /* printk(KERN_DEBUG "openprom.c: bufsize hack\n"); */
+               bufsize = OPROMMAXPARAM;
+       }
+
        if (!(*opp_p = kmalloc(sizeof(int) + bufsize + 1, GFP_KERNEL)))
                return -ENOMEM;
        memset(*opp_p, 0, sizeof(int) + bufsize + 1);
@@ -144,7 +156,7 @@
        else
                bufsize = copyin((void *)arg, &opp);
 
-       if (bufsize < 0)
+       if (bufsize < 0) 
                return bufsize;
 
        switch (cmd) {



-
To unsubscribe from this list: send the line "unsubscribe sparclinux" in
the body of the message to [EMAIL PROTECTED]

Reply via email to