Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-5]: src/sys/compat/linux/arch/i386 Pull up revisions 1.52-1.60 ...



details:   https://anonhg.NetBSD.org/src/rev/6ff1997a283a
branches:  netbsd-1-5
changeset: 490980:6ff1997a283a
user:      he <he%NetBSD.org@localhost>
date:      Fri Mar 30 21:34:21 2001 +0000

description:
Pull up revisions 1.52-1.60 (via patch, requested by fvdl):
  Add some required Linux emulation bits to support the Linux
  version of VMware.

diffstat:

 sys/compat/linux/arch/i386/linux_machdep.c |  157 +++++++++++++++++++++++++++-
 1 files changed, 151 insertions(+), 6 deletions(-)

diffs (243 lines):

diff -r 1c5a50219e58 -r 6ff1997a283a sys/compat/linux/arch/i386/linux_machdep.c
--- a/sys/compat/linux/arch/i386/linux_machdep.c        Fri Mar 30 21:33:51 2001 +0000
+++ b/sys/compat/linux/arch/i386/linux_machdep.c        Fri Mar 30 21:34:21 2001 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: linux_machdep.c,v 1.50 2000/06/11 09:19:27 veego Exp $ */
+/*     $NetBSD: linux_machdep.c,v 1.50.2.1 2001/03/30 21:34:21 he Exp $        */
 
 /*-
- * Copyright (c) 1995 The NetBSD Foundation, Inc.
+ * Copyright (c) 1995, 2000 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -61,11 +61,14 @@
 #include <sys/syscallargs.h>
 #include <sys/filedesc.h>
 #include <sys/exec_elf.h>
+#include <sys/disklabel.h>
+#include <miscfs/specfs/specdev.h>
 
 #include <compat/linux/common/linux_types.h>
 #include <compat/linux/common/linux_signal.h>
 #include <compat/linux/common/linux_util.h>
 #include <compat/linux/common/linux_ioctl.h>
+#include <compat/linux/common/linux_hdio.h>
 #include <compat/linux/common/linux_exec.h>
 #include <compat/linux/common/linux_machdep.h>
 
@@ -87,6 +90,7 @@
 #include "wsdisplay.h"
 #if (NWSDISPLAY > 0)
 #include <sys/ioctl.h>
+#include <dev/wscons/wsconsio.h>
 #include <dev/wscons/wsdisplay_usl_io.h>
 #include "opt_xserver.h"
 #endif
@@ -99,6 +103,10 @@
     register_t *));
 #endif
 
+static struct biosdisk_info *fd2biosinfo __P((struct proc *, struct file *));
+extern struct disklist *i386_alldisks;
+extern const char *findblkname __P((int));
+
 /*
  * Deal with some i386-specific things in the Linux emulation code.
  */
@@ -532,6 +540,41 @@
 };
 #endif
 
+static struct biosdisk_info *
+fd2biosinfo(p, fp)
+       struct proc *p;
+       struct file *fp;
+{
+       struct vnode *vp;
+       const char *blkname;
+       char diskname[16];
+       int i;
+       struct nativedisk_info *nip;
+       struct disklist *dl = i386_alldisks;
+
+       if (fp->f_type != DTYPE_VNODE)
+               return NULL;
+       vp = (struct vnode *)fp->f_data;
+
+       if (vp->v_type != VBLK)
+               return NULL;
+
+       blkname = findblkname(major(vp->v_rdev));
+       snprintf(diskname, sizeof diskname, "%s%u", blkname,
+           DISKUNIT(vp->v_rdev));
+
+       for (i = 0; i < dl->dl_nnativedisks; i++) {
+               nip = &dl->dl_nativedisks[i];
+               if (strcmp(diskname, nip->ni_devname))
+                       continue;
+               if (nip->ni_nmatches != 0)
+                       return &dl->dl_biosdisks[nip->ni_biosmatches[0]];
+       }
+
+       return NULL;
+}
+
+
 /*
  * We come here in a last attempt to satisfy a Linux ioctl() call
  */
@@ -548,17 +591,38 @@
        } */ *uap = v;
        struct sys_ioctl_args bia;
        u_long com;
+       int error, error1;
 #if (NWSDISPLAY > 0)
-       int error;
        struct vt_mode lvt;
        caddr_t bvtp, sg;
        struct kbentry kbe;
 #endif
+       struct linux_hd_geometry hdg;
+       struct linux_hd_big_geometry hdg_big;
+       struct biosdisk_info *bip;
+       struct filedesc *fdp;
+       struct file *fp;
+       int fd;
+       struct disklabel label, *labp;
+       struct partinfo partp;
+       int (*ioctlf) __P((struct file *, u_long, caddr_t, struct proc *));
+       u_long start, biostotal, realtotal;
+       u_char heads, sectors;
+       u_int cylinders;
+       struct ioctl_pt pt;
 
-       SCARG(&bia, fd) = SCARG(uap, fd);
+       fd = SCARG(uap, fd);
+       SCARG(&bia, fd) = fd;
        SCARG(&bia, data) = SCARG(uap, data);
        com = SCARG(uap, com);
 
+       fdp = p->p_fd;
+
+       if ((u_int)fd >= fdp->fd_nfiles ||
+           (fp = fdp->fd_ofiles[fd]) == NULL ||
+           (fp->f_iflags & FIF_WANTCLOSE) != 0)
+               return (EBADF);
+
        switch (com) {
 #if (NWSDISPLAY > 0)
        case LINUX_KDGKBMODE:
@@ -569,12 +633,20 @@
                if ((unsigned)SCARG(uap, data) == LINUX_K_MEDIUMRAW)
                        SCARG(&bia, data) = (caddr_t)K_RAW;
                break;
+       case LINUX_KIOCSOUND:
+               SCARG(&bia, data) =
+                   (caddr_t)(((unsigned long)SCARG(&bia, data)) & 0xffff);
+               /* fall through */
        case LINUX_KDMKTONE:
                com = KDMKTONE;
                break;
        case LINUX_KDSETMODE:
                com = KDSETMODE;
                break;
+       case LINUX_KDGETMODE:
+               /* KD_* values are equal to the wscons numbers */
+               com = WSDISPLAYIO_GMODE;
+               break;
        case LINUX_KDENABIO:
                com = KDENABIO;
                break;
@@ -616,6 +688,9 @@
                        return error;
                SCARG(&bia, data) = bvtp;
                break;
+       case LINUX_VT_DISALLOCATE:
+               /* XXX should use WSDISPLAYIO_DELSCREEN */
+               return 0;
        case LINUX_VT_RELDISP:
                com = VT_RELDISP;
                break;
@@ -648,9 +723,79 @@
                return (copyout(&kbe, SCARG(uap, data),
                                sizeof(struct kbentry)));
 #endif
+       case LINUX_HDIO_GETGEO:
+       case LINUX_HDIO_GETGEO_BIG:
+               /*
+                * Try to mimic Linux behaviour: return the BIOS geometry
+                * if possible (extending its # of cylinders if it's beyond
+                * the 1023 limit), fall back to the MI geometry (i.e.
+                * the real geometry) if not found, by returning an
+                * error. See common/linux_hdio.c
+                */
+               FILE_USE(fp);
+               bip = fd2biosinfo(p, fp);
+               ioctlf = fp->f_ops->fo_ioctl;
+               error = ioctlf(fp, DIOCGDEFLABEL, (caddr_t)&label, p);
+               error1 = ioctlf(fp, DIOCGPART, (caddr_t)&partp, p);
+               FILE_UNUSE(fp, p);
+               if (error != 0 && error1 != 0)
+                       return error1;
+               labp = error != 0 ? &label : partp.disklab;
+               start = error1 != 0 ? partp.part->p_offset : 0;
+               if (bip != NULL && bip->bi_head != 0 && bip->bi_sec != 0
+                   && bip->bi_cyl != 0) {
+                       heads = bip->bi_head;
+                       sectors = bip->bi_sec;
+                       cylinders = bip->bi_cyl;
+                       biostotal = heads * sectors * cylinders;
+                       realtotal = labp->d_ntracks * labp->d_nsectors *
+                           labp->d_ncylinders;
+                       if (realtotal > biostotal)
+                               cylinders = realtotal / (heads * sectors);
+               } else {
+                       heads = labp->d_ntracks;
+                       cylinders = labp->d_ncylinders;
+                       sectors = labp->d_nsectors;
+               }
+               if (com == LINUX_HDIO_GETGEO) {
+                       hdg.start = start;
+                       hdg.heads = heads;
+                       hdg.cylinders = cylinders;
+                       hdg.sectors = sectors;
+                       return copyout(&hdg, SCARG(uap, data), sizeof hdg);
+               } else {
+                       hdg_big.start = start;
+                       hdg_big.heads = heads;
+                       hdg_big.cylinders = cylinders;
+                       hdg_big.sectors = sectors;
+                       return copyout(&hdg_big, SCARG(uap, data),
+                           sizeof hdg_big);
+               }
+               return 0;
+
        default:
-               printf("linux_machdepioctl: invalid ioctl %08lx\n", com);
-               return EINVAL;
+               /*
+                * Unknown to us. If it's on a device, just pass it through
+                * using PTIOCLINUX, the device itself might be able to
+                * make some sense of it.
+                * XXX hack: if the function returns EJUSTRETURN,
+                * it has stuffed a sysctl return value in pt.data.
+                */
+               FILE_USE(fp);
+               ioctlf = fp->f_ops->fo_ioctl;
+               pt.com = SCARG(uap, com);
+               pt.data = SCARG(uap, data);
+               error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p);
+               FILE_UNUSE(fp, p);
+               if (error == EJUSTRETURN) {
+                       retval[0] = (register_t)pt.data;
+                       error = 0;
+               }
+
+               if (error == ENOTTY)
+                       printf("linux_machdepioctl: invalid ioctl %08lx\n",
+                           com);
+               return error;
        }
        SCARG(&bia, com) = com;
        return sys_ioctl(p, &bia, retval);



Home | Main Index | Thread Index | Old Index