root/arch/alpha/kernel/osf_sys.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. osf_filldir
  2. osf_getdirentries
  3. osf_getpriority
  4. sys_madvise
  5. sys_getxuid
  6. sys_getxgid
  7. sys_getxpid
  8. osf_mmap
  9. osf_statfs
  10. osf_fstatfs
  11. getdev
  12. putdev
  13. osf_ufs_mount
  14. osf_cdfs_mount
  15. osf_procfs_mount
  16. osf_mount
  17. osf_umount
  18. osf_usleep_thread
  19. osf_utsname
  20. osf_swapon
  21. sys_getpagesize
  22. sys_getdtablesize
  23. sys_pipe
  24. osf_getdomainname
  25. osf_shmat
  26. osf_proplist_syscall
  27. alpha_create_module
  28. osf_getsysinfo
  29. osf_setsysinfo

   1 /*
   2  *  linux/arch/alpha/kernel/osf_sys.c
   3  *
   4  *  Copyright (C) 1995  Linus Torvalds
   5  */
   6 
   7 /*
   8  * This file handles some of the stranger OSF/1 system call interfaces.
   9  * Some of the system calls expect a non-C calling standard, others have
  10  * special parameter blocks..
  11  */
  12 
  13 #include <linux/errno.h>
  14 #include <linux/sched.h>
  15 #include <linux/kernel.h>
  16 #include <linux/mm.h>
  17 #include <linux/stddef.h>
  18 #include <linux/unistd.h>
  19 #include <linux/ptrace.h>
  20 #include <linux/malloc.h>
  21 #include <linux/ldt.h>
  22 #include <linux/user.h>
  23 #include <linux/a.out.h>
  24 #include <linux/utsname.h>
  25 #include <linux/time.h>
  26 #include <linux/major.h>
  27 #include <linux/stat.h>
  28 #include <linux/mman.h>
  29 #include <linux/shm.h>
  30 
  31 #include <asm/fpu.h>
  32 #include <asm/io.h>
  33 #include <asm/segment.h>
  34 #include <asm/system.h>
  35 
  36 extern int do_mount(kdev_t, const char *, const char *, char *, int, void *);
  37 extern int do_pipe(int *);
  38 
  39 extern struct file_operations * get_blkfops(unsigned int);
  40 extern struct file_operations * get_chrfops(unsigned int);
  41 
  42 extern kdev_t get_unnamed_dev(void);
  43 extern void put_unnamed_dev(kdev_t);
  44 
  45 extern asmlinkage int sys_umount(char *);
  46 extern asmlinkage int sys_swapon(const char *specialfile, int swap_flags);
  47 
  48 /*
  49  * OSF/1 directory handling functions...
  50  *
  51  * The "getdents()" interface is much more sane: the "basep" stuff is
  52  * braindamage (it can't really handle filesystems where the directory
  53  * offset differences aren't the same as "d_reclen").
  54  */
  55 #define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
  56 #define ROUND_UP(x) (((x)+3) & ~3)
  57 
  58 struct osf_dirent {
  59         unsigned int    d_ino;
  60         unsigned short  d_reclen;
  61         unsigned short  d_namlen;
  62         char            d_name[1];
  63 };
  64 
  65 struct osf_dirent_callback {
  66         struct osf_dirent * dirent;
  67         long *basep;
  68         int count;
  69         int error;
  70 };
  71 
  72 static int osf_filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino)
     /* [previous][next][first][last][top][bottom][index][help] */
  73 {
  74         struct osf_dirent * dirent;
  75         struct osf_dirent_callback * buf = (struct osf_dirent_callback *) __buf;
  76         int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
  77 
  78         buf->error = -EINVAL;           /* unly used if we fail */
  79         if (reclen > buf->count)
  80                 return -EINVAL;
  81         if (buf->basep) {
  82                 put_user(offset, buf->basep);
  83                 buf->basep = NULL;
  84         }
  85         dirent = buf->dirent;
  86         put_user(ino, &dirent->d_ino);
  87         put_user(namlen, &dirent->d_namlen);
  88         put_user(reclen, &dirent->d_reclen);
  89         memcpy_tofs(dirent->d_name, name, namlen);
  90         put_fs_byte(0, dirent->d_name + namlen);
  91         ((char *) dirent) += reclen;
  92         buf->dirent = dirent;
  93         buf->count -= reclen;
  94         return 0;
  95 }
  96 
  97 asmlinkage int osf_getdirentries(unsigned int fd, struct osf_dirent * dirent,
     /* [previous][next][first][last][top][bottom][index][help] */
  98         unsigned int count, long *basep)
  99 {
 100         int error;
 101         struct file * file;
 102         struct osf_dirent_callback buf;
 103 
 104         if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 105                 return -EBADF;
 106         if (!file->f_op || !file->f_op->readdir)
 107                 return -ENOTDIR;
 108         error = verify_area(VERIFY_WRITE, dirent, count);
 109         if (error)
 110                 return error;
 111         if (basep) {
 112                 error = verify_area(VERIFY_WRITE, basep, sizeof(long));
 113                 if (error)
 114                         return error;
 115         }
 116         buf.dirent = dirent;
 117         buf.basep = basep;
 118         buf.count = count;
 119         buf.error = 0;
 120         error = file->f_op->readdir(file->f_inode, file, &buf, osf_filldir);
 121         if (error < 0)
 122                 return error;
 123         if (count == buf.count)
 124                 return buf.error;
 125         return count - buf.count;
 126 }
 127 
 128 asmlinkage int osf_getpriority(int which, int who)
     /* [previous][next][first][last][top][bottom][index][help] */
 129 {
 130         extern int sys_getpriority(int, int);
 131         /*
 132          * Alpha syscall convention has no problem returning negative
 133          * values:
 134          */
 135         return 20 - sys_getpriority(which, who);
 136 }
 137 
 138 
 139 /*
 140  * Heh. As documented by DEC..
 141  */
 142 asmlinkage unsigned long sys_madvise(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 143 {
 144         return 0;
 145 }
 146 
 147 asmlinkage unsigned long sys_getxuid(int a0, int a1, int a2, int a3, int a4, int a5,
     /* [previous][next][first][last][top][bottom][index][help] */
 148         struct pt_regs regs)
 149 {
 150         (&regs)->r20 = current->euid;
 151         return current->uid;
 152 }
 153 
 154 asmlinkage unsigned long sys_getxgid(int a0, int a1, int a2, int a3, int a4, int a5,
     /* [previous][next][first][last][top][bottom][index][help] */
 155         struct pt_regs regs)
 156 {
 157         (&regs)->r20 = current->egid;
 158         return current->gid;
 159 }
 160 
 161 asmlinkage unsigned long sys_getxpid(int a0, int a1, int a2, int a3, int a4, int a5,
     /* [previous][next][first][last][top][bottom][index][help] */
 162         struct pt_regs regs)
 163 {
 164         (&regs)->r20 = current->p_opptr->pid;
 165         return current->pid;
 166 }
 167 
 168 asmlinkage unsigned long osf_mmap(unsigned long addr, unsigned long len,
     /* [previous][next][first][last][top][bottom][index][help] */
 169         unsigned long prot, unsigned long flags, unsigned long fd,
 170         unsigned long off)
 171 {
 172         struct file * file = NULL;
 173 
 174         if (flags & (MAP_HASSEMAPHORE | MAP_INHERIT | MAP_UNALIGNED))
 175                 printk("%s: unimplemented OSF mmap flags %04lx\n", current->comm, flags);
 176         if (!(flags & MAP_ANONYMOUS)) {
 177                 if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 178                         return -EBADF;
 179         }
 180         return do_mmap(file, addr, len, prot, flags, off);
 181 }
 182 
 183 asmlinkage int osf_statfs(char * path, struct statfs * buffer, unsigned long bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 184 {
 185         struct inode * inode;
 186         int retval;
 187 
 188         if (bufsiz > sizeof(struct statfs))
 189                 bufsiz = sizeof(struct statfs);
 190         retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 191         if (retval)
 192                 return retval;
 193         retval = namei(path, &inode);
 194         if (retval)
 195                 return retval;
 196         if (!inode->i_sb->s_op->statfs) {
 197                 iput(inode);
 198                 return -ENOSYS;
 199         }
 200         inode->i_sb->s_op->statfs(inode->i_sb, buffer, bufsiz);
 201         iput(inode);
 202         return 0;
 203 }
 204 
 205 asmlinkage int osf_fstatfs(unsigned long fd, struct statfs * buffer, unsigned long bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 206 {
 207         struct file * file;
 208         struct inode * inode;
 209         int retval;
 210 
 211         retval = verify_area(VERIFY_WRITE, buffer, bufsiz);
 212         if (retval)
 213                 return retval;
 214         if (bufsiz > sizeof(struct statfs))
 215                 bufsiz = sizeof(struct statfs);
 216         if (fd >= NR_OPEN || !(file = current->files->fd[fd]))
 217                 return -EBADF;
 218         if (!(inode = file->f_inode))
 219                 return -ENOENT;
 220         if (!inode->i_sb->s_op->statfs)
 221                 return -ENOSYS;
 222         inode->i_sb->s_op->statfs(inode->i_sb, buffer, bufsiz);
 223         return 0;
 224 }
 225 
 226 /*
 227  * Uhh.. OSF/1 mount parameters aren't exactly obvious..
 228  *
 229  * Although to be frank, neither are the native Linux/i386 ones..
 230  */
 231 struct ufs_args {
 232         char * devname;
 233         int flags;
 234         uid_t exroot;
 235 };
 236 
 237 struct cdfs_args {
 238         char * devname;
 239         int flags;
 240         uid_t exroot;
 241 /*
 242  * this has lots more here, which linux handles with the option block
 243  * but I'm too lazy to do the translation into ascii..
 244  */
 245 };
 246 
 247 struct procfs_args {
 248         char * devname;
 249         int flags;
 250         uid_t exroot;
 251 };
 252 
 253 static int getdev(const char * name, int rdonly, struct inode ** ino)
     /* [previous][next][first][last][top][bottom][index][help] */
 254 {
 255         kdev_t dev;
 256         struct inode * inode;
 257         struct file_operations * fops;
 258         int retval;
 259 
 260         retval = namei(name, &inode);
 261         if (retval)
 262                 return retval;
 263         if (!S_ISBLK(inode->i_mode)) {
 264                 iput(inode);
 265                 return -ENOTBLK;
 266         }
 267         if (IS_NODEV(inode)) {
 268                 iput(inode);
 269                 return -EACCES;
 270         }
 271         dev = inode->i_rdev;
 272         if (MAJOR(dev) >= MAX_BLKDEV) {
 273                 iput(inode);
 274                 return -ENXIO;
 275         }
 276         fops = get_blkfops(MAJOR(dev));
 277         if (!fops) {
 278                 iput(inode);
 279                 return -ENODEV;
 280         }
 281         if (fops->open) {
 282                 struct file dummy;
 283                 memset(&dummy, 0, sizeof(dummy));
 284                 dummy.f_inode = inode;
 285                 dummy.f_mode = rdonly ? 1 : 3;
 286                 retval = fops->open(inode, &dummy);
 287                 if (retval) {
 288                         iput(inode);
 289                         return retval;
 290                 }
 291         }
 292         *ino = inode;
 293         return 0;
 294 }
 295 
 296 static void putdev(struct inode * inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 297 {
 298         struct file_operations * fops;
 299 
 300         fops = get_blkfops(MAJOR(inode->i_rdev));
 301         if (fops->release)
 302                 fops->release(inode, NULL);
 303 }
 304 
 305 /*
 306  * We can't actually handle ufs yet, so we translate UFS mounts to
 307  * ext2fs mounts... I wouldn't mind a USF filesystem, but the UFS
 308  * layout is so braindead it's a major headache doing it..
 309  */
 310 static int osf_ufs_mount(char * dirname, struct ufs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 311 {
 312         int retval;
 313         struct inode * inode;
 314         struct cdfs_args tmp;
 315 
 316         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 317         if (retval)
 318                 return retval;
 319         memcpy_fromfs(&tmp, args, sizeof(tmp));
 320         retval = getdev(tmp.devname, 0, &inode);
 321         if (retval)
 322                 return retval;
 323         retval = do_mount(inode->i_rdev, tmp.devname, dirname, "ext2", flags, NULL);
 324         if (retval)
 325                 putdev(inode);
 326         iput(inode);
 327         return retval;
 328 }
 329 
 330 static int osf_cdfs_mount(char * dirname, struct cdfs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 331 {
 332         int retval;
 333         struct inode * inode;
 334         struct cdfs_args tmp;
 335 
 336         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 337         if (retval)
 338                 return retval;
 339         memcpy_fromfs(&tmp, args, sizeof(tmp));
 340         retval = getdev(tmp.devname, 1, &inode);
 341         if (retval)
 342                 return retval;
 343         retval = do_mount(inode->i_rdev, tmp.devname, dirname, "iso9660", flags, NULL);
 344         if (retval)
 345                 putdev(inode);
 346         iput(inode);
 347         return retval;
 348 }
 349 
 350 static int osf_procfs_mount(char * dirname, struct procfs_args * args, int flags)
     /* [previous][next][first][last][top][bottom][index][help] */
 351 {
 352         kdev_t dev;
 353         int retval;
 354         struct procfs_args tmp;
 355 
 356         retval = verify_area(VERIFY_READ, args, sizeof(*args));
 357         if (retval)
 358                 return retval;
 359         memcpy_fromfs(&tmp, args, sizeof(tmp));
 360         dev = get_unnamed_dev();
 361         if (!dev)
 362                 return -ENODEV;
 363         retval = do_mount(dev, "", dirname, "proc", flags, NULL);
 364         if (retval)
 365                 put_unnamed_dev(dev);
 366         return retval;
 367 }
 368 
 369 asmlinkage int osf_mount(unsigned long typenr, char * path, int flag, void * data)
     /* [previous][next][first][last][top][bottom][index][help] */
 370 {
 371         int retval;
 372 
 373         retval = -EINVAL;
 374         switch (typenr) {
 375                 case 1:
 376                         retval = osf_ufs_mount(path, (struct ufs_args *) data, flag);
 377                         break;
 378                 case 6:
 379                         retval = osf_cdfs_mount(path, (struct cdfs_args *) data, flag);
 380                         break;
 381                 case 9:
 382                         retval = osf_procfs_mount(path, (struct procfs_args *) data, flag);
 383                         break;
 384                 default:
 385                         printk("osf_mount(%ld, %x)\n", typenr, flag);
 386         }
 387         return retval;
 388 }
 389 
 390 asmlinkage int osf_umount(char * path, int flag)
     /* [previous][next][first][last][top][bottom][index][help] */
 391 {
 392         return sys_umount(path);
 393 }
 394 
 395 /*
 396  * I don't know what the parameters are: the first one
 397  * seems to be a timeval pointer, and I suspect the second
 398  * one is the time remaining.. Ho humm.. No documentation.
 399  */
 400 asmlinkage int osf_usleep_thread(struct timeval * sleep, struct timeval * remain)
     /* [previous][next][first][last][top][bottom][index][help] */
 401 {
 402         struct timeval tmp;
 403         unsigned long ticks;
 404         int retval;
 405 
 406         retval = verify_area(VERIFY_READ, sleep, sizeof(*sleep));
 407         if (retval)
 408                 return retval;
 409         if (remain && (retval = verify_area(VERIFY_WRITE, remain, sizeof(*remain))))
 410                 return retval;
 411         memcpy_fromfs(&tmp, sleep, sizeof(*sleep));
 412         ticks = tmp.tv_usec;
 413         ticks = (ticks + (1000000 / HZ) - 1) / (1000000 / HZ);
 414         ticks += tmp.tv_sec * HZ;
 415         current->timeout = ticks + jiffies;
 416         current->state = TASK_INTERRUPTIBLE;
 417         schedule();
 418         if (!remain)
 419                 return 0;
 420         ticks = jiffies;
 421         if (ticks < current->timeout)
 422                 ticks = current->timeout - ticks;
 423         else
 424                 ticks = 0;
 425         current->timeout = 0;
 426         tmp.tv_sec = ticks / HZ;
 427         tmp.tv_usec = ticks % HZ;
 428         memcpy_tofs(remain, &tmp, sizeof(*remain));
 429         return 0;
 430 }
 431 
 432 asmlinkage int osf_utsname(char * name)
     /* [previous][next][first][last][top][bottom][index][help] */
 433 {
 434         int error = verify_area(VERIFY_WRITE, name, 5*32);
 435         if (error)
 436                 return error;
 437         memcpy_tofs(name +   0, system_utsname.sysname, 32);
 438         memcpy_tofs(name +  32, system_utsname.nodename, 32);
 439         memcpy_tofs(name +  64, system_utsname.release, 32);
 440         memcpy_tofs(name +  96, system_utsname.version, 32);
 441         memcpy_tofs(name + 128, system_utsname.machine, 32);
 442         return 0;
 443 }
 444 
 445 asmlinkage int osf_swapon(const char * path, int flags, int lowat, int hiwat)
     /* [previous][next][first][last][top][bottom][index][help] */
 446 {
 447         /* for now, simply ignore lowat and hiwat... */
 448         return sys_swapon(path, flags);
 449 }
 450 
 451 asmlinkage unsigned long sys_getpagesize(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 452 {
 453         return PAGE_SIZE;
 454 }
 455 
 456 asmlinkage unsigned long sys_getdtablesize(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 457 {
 458         return NR_OPEN;
 459 }
 460 
 461 asmlinkage int sys_pipe(int a0, int a1, int a2, int a3, int a4, int a5,
     /* [previous][next][first][last][top][bottom][index][help] */
 462         struct pt_regs regs)
 463 {
 464         int fd[2];
 465         int error;
 466 
 467         error = do_pipe(fd);
 468         if (error)
 469                 return error;
 470         (&regs)->r20 = fd[1];
 471         return fd[0];
 472 }
 473 
 474 /*
 475  * For compatibility with OSF/1 only.  Use utsname(2) instead.
 476  */
 477 asmlinkage int osf_getdomainname(char *name, int namelen)
     /* [previous][next][first][last][top][bottom][index][help] */
 478 {
 479         unsigned len;
 480         int i, error;
 481 
 482         error = verify_area(VERIFY_WRITE, name, namelen);
 483         if (error)
 484                 return error;
 485 
 486         len = namelen;
 487         if (namelen > 32)
 488           len = 32;
 489 
 490         for (i = 0; i < len; ++i) {
 491                 put_user(system_utsname.domainname[i], name + i);
 492                 if (system_utsname.domainname[i] == '\0')
 493                   break;
 494         }
 495         return 0;
 496 }
 497 
 498 
 499 asmlinkage long osf_shmat(int shmid, void *shmaddr, int shmflg)
     /* [previous][next][first][last][top][bottom][index][help] */
 500 {
 501         unsigned long raddr;
 502         int err;
 503 
 504         err = sys_shmat(shmid, shmaddr, shmflg, &raddr);
 505         if (err)
 506                 return err;
 507         /*
 508          * This works because all user-level addresses are
 509          * non-negative longs!
 510          */
 511         return raddr;
 512 }
 513 
 514 
 515 /*
 516  * The following stuff should move into a header file should it ever
 517  * be labeled "officially supported."  Right now, there is just enough
 518  * support to avoid applications (such as tar) printing error
 519  * messages.  The attributes are not really implemented.
 520  */
 521 
 522 /*
 523  * Values for Property list entry flag
 524  */
 525 #define PLE_PROPAGATE_ON_COPY           0x1     /* cp(1) will copy entry
 526                                                    by default */
 527 #define PLE_FLAG_MASK                   0x1     /* Valid flag values */
 528 #define PLE_FLAG_ALL                    -1      /* All flag value */
 529 
 530 struct proplistname_args {
 531         unsigned int    pl_mask;
 532         unsigned int    pl_numnames;
 533         char            **pl_names;
 534 };
 535 
 536 union pl_args {
 537         struct setargs {
 538                 char *path;
 539                 long follow;
 540                 long nbytes;
 541                 char *buf;
 542         } set;
 543         struct fsetargs {
 544                 long fd;
 545                 long nbytes;
 546                 char *buf;
 547         } fset;
 548         struct getargs {
 549                 char *path;
 550                 long follow;
 551                 struct proplistname_args *name_args;
 552                 long nbytes;
 553                 char *buf;
 554                 int *min_buf_size;
 555         } get;
 556         struct fgetargs {
 557                 long fd;
 558                 struct proplistname_args *name_args;
 559                 long nbytes;
 560                 char *buf;
 561                 int *min_buf_size;
 562         } fget;
 563         struct delargs {
 564                 char *path;
 565                 long follow;
 566                 struct proplistname_args *name_args;
 567         } del;
 568         struct fdelargs {
 569                 long fd;
 570                 struct proplistname_args *name_args;
 571         } fdel;
 572 };
 573 
 574 enum pl_code {
 575         PL_SET  = 1,    PL_FSET = 2,
 576         PL_GET  = 3,    PL_FGET = 4,
 577         PL_DEL  = 5,    PL_FDEL = 6
 578 };
 579 
 580 asmlinkage long osf_proplist_syscall (enum pl_code code, union pl_args *args)
     /* [previous][next][first][last][top][bottom][index][help] */
 581 {
 582         long error;
 583         int *min_buf_size_ptr;
 584 
 585         switch (code) {
 586               case PL_SET:
 587                 error = verify_area(VERIFY_READ, &args->set.nbytes,
 588                                     sizeof(args->set.nbytes));
 589                 if (error)
 590                   return error;
 591                 return args->set.nbytes;
 592 
 593               case PL_FSET:
 594                 error = verify_area(VERIFY_READ, &args->fset.nbytes,
 595                                     sizeof(args->fset.nbytes));
 596                 if (error)
 597                   return error;
 598                 return args->fset.nbytes;
 599 
 600               case PL_GET:
 601                 error = verify_area(VERIFY_READ, &args->get.min_buf_size,
 602                                     sizeof(args->get.min_buf_size));
 603                 if (error)
 604                   return error;
 605                 min_buf_size_ptr = get_user(&args->get.min_buf_size);
 606                 error = verify_area(VERIFY_WRITE, min_buf_size_ptr,
 607                                     sizeof(*min_buf_size_ptr));
 608                 if (error)
 609                   return error;
 610                 put_user(0, min_buf_size_ptr);
 611                 return 0;
 612 
 613               case PL_FGET:
 614                 error = verify_area(VERIFY_READ, &args->fget.min_buf_size,
 615                                     sizeof(args->fget.min_buf_size));
 616                 if (error)
 617                   return error;
 618                 min_buf_size_ptr = get_user(&args->fget.min_buf_size);
 619                 error = verify_area(VERIFY_WRITE, min_buf_size_ptr,
 620                                     sizeof(*min_buf_size_ptr));
 621                 if (error)
 622                   return error;
 623                 put_user(0, min_buf_size_ptr);
 624                 return 0;
 625 
 626               case PL_DEL:
 627               case PL_FDEL:
 628                 return 0;
 629 
 630               default:
 631                 return -EOPNOTSUPP;
 632         }
 633 }
 634 
 635 /*
 636  * The Linux kernel isn't good at returning values that look
 637  * like negative longs (they are mistaken as error values).
 638  * Until that is fixed, we need this little workaround for
 639  * create_module() because it's one of the few system calls
 640  * that return kernel addresses (which are negative).
 641  */
 642 asmlinkage unsigned long
 643 alpha_create_module (char * module_name, unsigned long size,
     /* [previous][next][first][last][top][bottom][index][help] */
 644                      int a3, int a4, int a5, int a6,
 645                      struct pt_regs regs)
 646 {
 647         asmlinkage unsigned long sys_create_module (char *, unsigned long);
 648         long retval;
 649 
 650         retval = sys_create_module(module_name, size);
 651         /*
 652          * we get either a module address or an error number,
 653          * and we know the error number is a small negative
 654          * number, while the address is always negative but
 655          * much larger.
 656          */
 657         if (retval + 1000 > 0)
 658           return retval;
 659 
 660         /* tell entry.S:syscall_error that this is NOT an error: */
 661         regs.r0 = 0;
 662         return retval;
 663 }
 664 
 665 
 666 asmlinkage unsigned long
 667 osf_getsysinfo (unsigned long op, void * buffer, unsigned long nbytes,
     /* [previous][next][first][last][top][bottom][index][help] */
 668                 int * start, void *arg)
 669 {
 670     extern unsigned long rdfpcr (void);
 671     unsigned long fpcw;
 672 
 673     switch (op) {
 674       case 45:  /* GSI_IEEE_FP_CONTROL */
 675           /* build and return current fp control word: */
 676           fpcw = current->tss.flags & IEEE_TRAP_ENABLE_MASK;
 677           fpcw |= ((rdfpcr() >> 52) << 17) & IEEE_STATUS_MASK;
 678           put_user(fpcw, (unsigned long *) buffer);
 679           return 0;
 680 
 681       case 46:  /* GSI_IEEE_STATE_AT_SIGNAL */
 682           /*
 683            * Not sure anybody will ever use this weird stuff.  These
 684            * ops can be used (under OSF/1) to set the fpcr that should
 685            * be used when a signal handler starts executing.
 686            */
 687           break;
 688 
 689       default:
 690           break;
 691     }
 692     return -EOPNOTSUPP;
 693 }
 694 
 695 
 696 asmlinkage unsigned long
 697 osf_setsysinfo (unsigned long op, void * buffer, unsigned long nbytes,
     /* [previous][next][first][last][top][bottom][index][help] */
 698                 int * start, void *arg)
 699 {
 700     unsigned long fpcw;
 701 
 702     switch (op) {
 703       case 14:  /* SSI_IEEE_FP_CONTROL */
 704           /* update trap enable bits: */
 705           fpcw = get_user((unsigned long *) buffer);
 706           current->tss.flags &= ~IEEE_TRAP_ENABLE_MASK;
 707           current->tss.flags |= (fpcw & IEEE_TRAP_ENABLE_MASK);
 708           return 0;
 709 
 710       case 15:  /* SSI_IEEE_STATE_AT_SIGNAL */
 711       case 16:  /* SSI_IEEE_IGNORE_STATE_AT_SIGNAL */
 712           /*
 713            * Not sure anybody will ever use this weird stuff.  These
 714            * ops can be used (under OSF/1) to set the fpcr that should
 715            * be used when a signal handler starts executing.
 716            */
 717       default:
 718           break;
 719     }
 720     return -EOPNOTSUPP;
 721 }

/* [previous][next][first][last][top][bottom][index][help] */