aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/sys_sunos.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/sys_sunos.c')
-rw-r--r--arch/sparc/kernel/sys_sunos.c1194
1 files changed, 1194 insertions, 0 deletions
const struct usb_device_id *id) { struct usb_device *udev = interface_to_usbdev(intf); struct net_device *ndev = NULL; struct mcs_cb *mcs; int ret = -ENOMEM; ndev = alloc_irdadev(sizeof(*mcs)); if (!ndev) goto error1; IRDA_DEBUG(1, "MCS7780 USB-IrDA bridge found at %d.\n", udev->devnum); /* what is it realy for? */ SET_MODULE_OWNER(ndev); SET_NETDEV_DEV(ndev, &intf->dev); ret = usb_reset_configuration(udev); if (ret != 0) { IRDA_ERROR("mcs7780: usb reset configuration failed\n"); goto error2; } mcs = netdev_priv(ndev); mcs->usbdev = udev; mcs->netdev = ndev; spin_lock_init(&mcs->lock); /* Initialize QoS for this device */ irda_init_max_qos_capabilies(&mcs->qos); /* That's the Rx capability. */ mcs->qos.baud_rate.bits &= IR_2400 | IR_9600 | IR_19200 | IR_38400 | IR_57600 | IR_115200 | IR_576000 | IR_1152000 | (IR_4000000 << 8); mcs->qos.min_turn_time.bits &= qos_mtt_bits; irda_qos_bits_to_value(&mcs->qos); /* Speed change work initialisation*/ INIT_WORK(&mcs->work, mcs_speed_work); /* Override the network functions we need to use */ ndev->hard_start_xmit = mcs_hard_xmit; ndev->open = mcs_net_open; ndev->stop = mcs_net_close; ndev->get_stats = mcs_net_get_stats; ndev->do_ioctl = mcs_net_ioctl; if (!intf->cur_altsetting) goto error2; ret = mcs_find_endpoints(mcs, intf->cur_altsetting->endpoint, intf->cur_altsetting->desc.bNumEndpoints); if (!ret) { ret = -ENODEV; goto error2; } ret = register_netdev(ndev); if (ret != 0) goto error2; IRDA_DEBUG(1, "IrDA: Registered MosChip MCS7780 device as %s\n", ndev->name); mcs->transceiver_type = transceiver_type; mcs->sir_tweak = sir_tweak; mcs->receive_mode = receive_mode; usb_set_intfdata(intf, mcs); return 0; error2: free_netdev(ndev); error1: return ret; } /* The current device is removed, the USB layer tells us to shut down. */ static void mcs_disconnect(struct usb_interface *intf) { struct mcs_cb *mcs = usb_get_intfdata(intf); if (!mcs) return; flush_scheduled_work(); unregister_netdev(mcs->netdev); free_netdev(mcs->netdev); usb_set_intfdata(intf, NULL); IRDA_DEBUG(0, "MCS7780 now disconnected.\n"); } /* Module insertion */ static int __init mcs_init(void) { int result; /* register this driver with the USB subsystem */ result = usb_register(&mcs_driver); if (result) IRDA_ERROR("usb_register failed. Error number %d\n", result); return result; } module_init(mcs_init); /* Module removal */ static void __exit mcs_exit(void) { /* deregister this driver with the USB subsystem */ usb_deregister(&mcs_driver); } module_exit(mcs_exit);
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
new file mode 100644
index 0000000000..81c894acd0
--- /dev/null
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -0,0 +1,1194 @@
1/* $Id: sys_sunos.c,v 1.137 2002/02/08 03:57:14 davem Exp $
2 * sys_sunos.c: SunOS specific syscall compatibility support.
3 *
4 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
5 * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 *
7 * Based upon preliminary work which is:
8 *
9 * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
10 *
11 */
12
13#include <linux/kernel.h>
14#include <linux/sched.h>
15#include <linux/types.h>
16#include <linux/mman.h>
17#include <linux/mm.h>
18#include <linux/swap.h>
19#include <linux/fs.h>
20#include <linux/file.h>
21#include <linux/resource.h>
22#include <linux/ipc.h>
23#include <linux/shm.h>
24#include <linux/msg.h>
25#include <linux/sem.h>
26#include <linux/signal.h>
27#include <linux/uio.h>
28#include <linux/utsname.h>
29#include <linux/major.h>
30#include <linux/stat.h>
31#include <linux/slab.h>
32#include <linux/pagemap.h>
33#include <linux/errno.h>
34#include <linux/smp.h>
35#include <linux/smp_lock.h>
36#include <linux/syscalls.h>
37
38#include <net/sock.h>
39
40#include <asm/uaccess.h>
41#ifndef KERNEL_DS
42#include <linux/segment.h>
43#endif
44
45#include <asm/page.h>
46#include <asm/pgtable.h>
47#include <asm/pconf.h>
48#include <asm/idprom.h> /* for gethostid() */
49#include <asm/unistd.h>
50#include <asm/system.h>
51
52/* For the nfs mount emulation */
53#include <linux/socket.h>
54#include <linux/in.h>
55#include <linux/nfs.h>
56#include <linux/nfs2.h>
57#include <linux/nfs_mount.h>
58
59/* for sunos_select */
60#include <linux/time.h>
61#include <linux/personality.h>
62
63/* NR_OPEN is now larger and dynamic in recent kernels. */
64#define SUNOS_NR_OPEN 256
65
66/* We use the SunOS mmap() semantics. */
67asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len,
68 unsigned long prot, unsigned long flags,
69 unsigned long fd, unsigned long off)
70{
71 struct file * file = NULL;
72 unsigned long retval, ret_type;
73
74 if (flags & MAP_NORESERVE) {
75 static int cnt;
76 if (cnt++ < 10)
77 printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n",
78 current->comm);
79 flags &= ~MAP_NORESERVE;
80 }
81 retval = -EBADF;
82 if (!(flags & MAP_ANONYMOUS)) {
83 if (fd >= SUNOS_NR_OPEN)
84 goto out;
85 file = fget(fd);
86 if (!file)
87 goto out;
88 }
89
90 retval = -EINVAL;
91 /* If this is ld.so or a shared library doing an mmap
92 * of /dev/zero, transform it into an anonymous mapping.
93 * SunOS is so stupid some times... hmph!
94 */
95 if (file) {
96 if (imajor(file->f_dentry->d_inode) == MEM_MAJOR &&
97 iminor(file->f_dentry->d_inode) == 5) {
98 flags |= MAP_ANONYMOUS;
99 fput(file);
100 file = NULL;
101 }
102 }
103 ret_type = flags & _MAP_NEW;
104 flags &= ~_MAP_NEW;
105
106 if (!(flags & MAP_FIXED))
107 addr = 0;
108 else {
109 if (ARCH_SUN4C_SUN4 &&
110 (len > 0x20000000 ||
111 ((flags & MAP_FIXED) &&
112 addr < 0xe0000000 && addr + len > 0x20000000)))
113 goto out_putf;
114
115 /* See asm-sparc/uaccess.h */
116 if (len > TASK_SIZE - PAGE_SIZE ||
117 addr + len > TASK_SIZE - PAGE_SIZE)
118 goto out_putf;
119 }
120
121 flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
122 down_write(&current->mm->mmap_sem);
123 retval = do_mmap(file, addr, len, prot, flags, off);
124 up_write(&current->mm->mmap_sem);
125 if (!ret_type)
126 retval = ((retval < PAGE_OFFSET) ? 0 : retval);
127
128out_putf:
129 if (file)
130 fput(file);
131out:
132 return retval;
133}
134
135/* lmbench calls this, just say "yeah, ok" */
136asmlinkage int sunos_mctl(unsigned long addr, unsigned long len, int function, char *arg)
137{
138 return 0;
139}
140
141/* SunOS is completely broken... it returns 0 on success, otherwise
142 * ENOMEM. For sys_sbrk() it wants the old brk value as a return
143 * on success and ENOMEM as before on failure.
144 */
145asmlinkage int sunos_brk(unsigned long brk)
146{
147 int freepages, retval = -ENOMEM;
148 unsigned long rlim;
149 unsigned long newbrk, oldbrk;
150
151 down_write(&current->mm->mmap_sem);
152 if (ARCH_SUN4C_SUN4) {
153 if (brk >= 0x20000000 && brk < 0xe0000000) {
154 goto out;
155 }
156 }
157
158 if (brk < current->mm->end_code)
159 goto out;
160
161 newbrk = PAGE_ALIGN(brk);
162 oldbrk = PAGE_ALIGN(current->mm->brk);
163 retval = 0;
164 if (oldbrk == newbrk) {
165 current->mm->brk = brk;
166 goto out;
167 }
168
169 /*
170 * Always allow shrinking brk
171 */
172 if (brk <= current->mm->brk) {
173 current->mm->brk = brk;
174 do_munmap(current->mm, newbrk, oldbrk-newbrk);
175 goto out;
176 }
177 /*
178 * Check against rlimit and stack..
179 */
180 retval = -ENOMEM;
181 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
182 if (rlim >= RLIM_INFINITY)
183 rlim = ~0;
184 if (brk - current->mm->end_code > rlim)
185 goto out;
186
187 /*
188 * Check against existing mmap mappings.
189 */
190 if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE))
191 goto out;
192
193 /*
194 * stupid algorithm to decide if we have enough memory: while
195 * simple, it hopefully works in most obvious cases.. Easy to
196 * fool it, but this should catch most mistakes.
197 */
198 freepages = get_page_cache_size();
199 freepages >>= 1;
200 freepages += nr_free_pages();
201 freepages += nr_swap_pages;
202 freepages -= num_physpages >> 4;
203 freepages -= (newbrk-oldbrk) >> PAGE_SHIFT;
204 if (freepages < 0)
205 goto out;
206 /*
207 * Ok, we have probably got enough memory - let it rip.
208 */
209 current->mm->brk = brk;
210 do_brk(oldbrk, newbrk-oldbrk);
211 retval = 0;
212out:
213 up_write(&current->mm->mmap_sem);
214 return retval;
215}
216
217asmlinkage unsigned long sunos_sbrk(int increment)
218{
219 int error;
220 unsigned long oldbrk;
221
222 /* This should do it hopefully... */
223 lock_kernel();
224 oldbrk = current->mm->brk;
225 error = sunos_brk(((int) current->mm->brk) + increment);
226 if (!error)
227 error = oldbrk;
228 unlock_kernel();
229 return error;
230}
231
232/* XXX Completely undocumented, and completely magic...
233 * XXX I believe it is to increase the size of the stack by
234 * XXX argument 'increment' and return the new end of stack
235 * XXX area. Wheee...
236 */
237asmlinkage unsigned long sunos_sstk(int increment)
238{
239 lock_kernel();
240 printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n",
241 current->comm, increment);
242 unlock_kernel();
243 return -1;
244}
245
246/* Give hints to the kernel as to what paging strategy to use...
247 * Completely bogus, don't remind me.
248 */
249#define VA_NORMAL 0 /* Normal vm usage expected */
250#define VA_ABNORMAL 1 /* Abnormal/random vm usage probable */
251#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */
252#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */
253static char *vstrings[] = {
254 "VA_NORMAL",
255 "VA_ABNORMAL",
256 "VA_SEQUENTIAL",
257 "VA_INVALIDATE",
258};
259
260asmlinkage void sunos_vadvise(unsigned long strategy)
261{
262 /* I wanna see who uses this... */
263 lock_kernel();
264 printk("%s: Advises us to use %s paging strategy\n",
265 current->comm,
266 strategy <= 3 ? vstrings[strategy] : "BOGUS");
267 unlock_kernel();
268}
269
270/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE
271 * resource limit and is for backwards compatibility with older sunos
272 * revs.
273 */
274asmlinkage long sunos_getdtablesize(void)
275{
276 return SUNOS_NR_OPEN;
277}
278
279#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
280
281asmlinkage unsigned long sunos_sigblock(unsigned long blk_mask)
282{
283 unsigned long old;
284
285 spin_lock_irq(&current->sighand->siglock);
286 old = current->blocked.sig[0];
287 current->blocked.sig[0] |= (blk_mask & _BLOCKABLE);
288 recalc_sigpending();
289 spin_unlock_irq(&current->sighand->siglock);
290 return old;
291}
292
293asmlinkage unsigned long sunos_sigsetmask(unsigned long newmask)
294{
295 unsigned long retval;
296
297 spin_lock_irq(&current->sighand->siglock);
298 retval = current->blocked.sig[0];
299 current->blocked.sig[0] = (newmask & _BLOCKABLE);
300 recalc_sigpending();
301 spin_unlock_irq(&current->sighand->siglock);
302 return retval;
303}
304
305/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant) */
306/* getdents system call, the format of the structure just has a different */
307/* layout (d_off+d_ino instead of d_ino+d_off) */
308struct sunos_dirent {
309 long d_off;
310 unsigned long d_ino;
311 unsigned short d_reclen;
312 unsigned short d_namlen;
313 char d_name[1];
314};
315
316struct sunos_dirent_callback {
317 struct sunos_dirent __user *curr;
318 struct sunos_dirent __user *previous;
319 int count;
320 int error;
321};
322
323#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))
324#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1))
325
326static int sunos_filldir(void * __buf, const char * name, int namlen,
327 loff_t offset, ino_t ino, unsigned int d_type)
328{
329 struct sunos_dirent __user *dirent;
330 struct sunos_dirent_callback * buf = __buf;
331 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
332
333 buf->error = -EINVAL; /* only used if we fail.. */
334 if (reclen > buf->count)
335 return -EINVAL;
336 dirent = buf->previous;
337 if (dirent)
338 put_user(offset, &dirent->d_off);
339 dirent = buf->curr;
340 buf->previous = dirent;
341 put_user(ino, &dirent->d_ino);
342 put_user(namlen, &dirent->d_namlen);
343 put_user(reclen, &dirent->d_reclen);
344 copy_to_user(dirent->d_name, name, namlen);
345 put_user(0, dirent->d_name + namlen);
346 dirent = (void __user *) dirent + reclen;
347 buf->curr = dirent;
348 buf->count -= reclen;
349 return 0;
350}
351
352asmlinkage int sunos_getdents(unsigned int fd, void __user *dirent, int cnt)
353{
354 struct file * file;
355 struct sunos_dirent __user *lastdirent;
356 struct sunos_dirent_callback buf;
357 int error = -EBADF;
358
359 if (fd >= SUNOS_NR_OPEN)
360 goto out;
361
362 file = fget(fd);
363 if (!file)
364 goto out;
365
366 error = -EINVAL;
367 if (cnt < (sizeof(struct sunos_dirent) + 255))
368 goto out_putf;
369
370 buf.curr = (struct sunos_dirent __user *) dirent;
371 buf.previous = NULL;
372 buf.count = cnt;
373 buf.error = 0;
374
375 error = vfs_readdir(file, sunos_filldir, &buf);
376 if (error < 0)
377 goto out_putf;
378
379 lastdirent = buf.previous;
380 error = buf.error;
381 if (lastdirent) {
382 put_user(file->f_pos, &lastdirent->d_off);
383 error = cnt - buf.count;
384 }
385
386out_putf:
387 fput(file);
388out:
389 return error;
390}
391
392/* Old sunos getdirentries, severely broken compatibility stuff here. */
393struct sunos_direntry {
394 unsigned long d_ino;
395 unsigned short d_reclen;
396 unsigned short d_namlen;
397 char d_name[1];
398};
399
400struct sunos_direntry_callback {
401 struct sunos_direntry __user *curr;
402 struct sunos_direntry __user *previous;
403 int count;
404 int error;
405};
406
407static int sunos_filldirentry(void * __buf, const char * name, int namlen,
408 loff_t offset, ino_t ino, unsigned int d_type)
409{
410 struct sunos_direntry __user *dirent;
411 struct sunos_direntry_callback *buf = __buf;
412 int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
413
414 buf->error = -EINVAL; /* only used if we fail.. */
415 if (reclen > buf->count)
416 return -EINVAL;
417 dirent = buf->previous;
418 dirent = buf->curr;
419 buf->previous = dirent;
420 put_user(ino, &dirent->d_ino);
421 put_user(namlen, &dirent->d_namlen);
422 put_user(reclen, &dirent->d_reclen);
423 copy_to_user(dirent->d_name, name, namlen);
424 put_user(0, dirent->d_name + namlen);
425 dirent = (void __user *) dirent + reclen;
426 buf->curr = dirent;
427 buf->count -= reclen;
428 return 0;
429}
430
431asmlinkage int sunos_getdirentries(unsigned int fd, void __user *dirent,
432 int cnt, unsigned int __user *basep)
433{
434 struct file * file;
435 struct sunos_direntry __user *lastdirent;
436 struct sunos_direntry_callback buf;
437 int error = -EBADF;
438
439 if (fd >= SUNOS_NR_OPEN)
440 goto out;
441
442 file = fget(fd);
443 if (!file)
444 goto out;
445
446 error = -EINVAL;
447 if (cnt < (sizeof(struct sunos_direntry) + 255))
448 goto out_putf;
449
450 buf.curr = (struct sunos_direntry __user *) dirent;
451 buf.previous = NULL;
452 buf.count = cnt;
453 buf.error = 0;
454
455 error = vfs_readdir(file, sunos_filldirentry, &buf);
456 if (error < 0)
457 goto out_putf;
458
459 lastdirent = buf.previous;
460 error = buf.error;
461 if (lastdirent) {
462 put_user(file->f_pos, basep);
463 error = cnt - buf.count;
464 }
465
466out_putf:
467 fput(file);
468out:
469 return error;
470}
471
class='lineno'> 513 (int) regs->u_regs[UREG_G1]); 514 show_regs(regs); 515 } 516 unlock_kernel(); 517 return -ENOSYS; 518} 519 520/* This is not a real and complete implementation yet, just to keep 521 * the easy SunOS binaries happy. 522 */ 523asmlinkage int sunos_fpathconf(int fd, int name) 524{ 525 int ret; 526 527 switch(name) { 528 case _PCONF_LINK: 529 ret = LINK_MAX; 530 break; 531 case _PCONF_CANON: 532 ret = MAX_CANON; 533 break; 534 case _PCONF_INPUT: 535 ret = MAX_INPUT; 536 break; 537 case _PCONF_NAME: 538 ret = NAME_MAX; 539 break; 540 case _PCONF_PATH: 541 ret = PATH_MAX; 542 break; 543 case _PCONF_PIPE: 544 ret = PIPE_BUF; 545 break; 546 case _PCONF_CHRESTRICT: /* XXX Investigate XXX */ 547 ret = 1; 548 break; 549 case _PCONF_NOTRUNC: /* XXX Investigate XXX */ 550 case _PCONF_VDISABLE: 551 ret = 0; 552 break; 553 default: 554 ret = -EINVAL; 555 break; 556 } 557 return ret; 558} 559 560asmlinkage int sunos_pathconf(char __user *path, int name) 561{ 562 int ret; 563 564 ret = sunos_fpathconf(0, name); /* XXX cheese XXX */ 565 return ret; 566} 567 568/* SunOS mount system call emulation */ 569 570asmlinkage int sunos_select(int width, fd_set __user *inp, fd_set __user *outp, 571 fd_set __user *exp, struct timeval __user *tvp) 572{ 573 int ret; 574 575 /* SunOS binaries expect that select won't change the tvp contents */ 576 ret = sys_select (width, inp, outp, exp, tvp); 577 if (ret == -EINTR && tvp) { 578 time_t sec, usec; 579 580 __get_user(sec, &tvp->tv_sec); 581 __get_user(usec, &tvp->tv_usec); 582 583 if (sec == 0 && usec == 0) 584 ret = 0; 585 } 586 return ret; 587} 588 589asmlinkage void sunos_nop(void) 590{ 591 return; 592} 593 594/* SunOS mount/umount. */ 595#define SMNT_RDONLY 1 596#define SMNT_NOSUID 2 597#define SMNT_NEWTYPE 4 598#define SMNT_GRPID 8 599#define SMNT_REMOUNT 16 600#define SMNT_NOSUB 32 601#define SMNT_MULTI 64 602#define SMNT_SYS5 128 603 604struct sunos_fh_t { 605 char fh_data [NFS_FHSIZE]; 606}; 607 608struct sunos_nfs_mount_args { 609 struct sockaddr_in __user *addr; /* file server address */ 610 struct nfs_fh __user *fh; /* File handle to be mounted */ 611 int flags; /* flags */ 612 int wsize; /* write size in bytes */ 613 int rsize; /* read size in bytes */ 614 int timeo; /* initial timeout in .1 secs */ 615 int retrans; /* times to retry send */ 616 char __user *hostname; /* server's hostname */ 617 int acregmin; /* attr cache file min secs */ 618 int acregmax; /* attr cache file max secs */ 619 int acdirmin; /* attr cache dir min secs */ 620 int acdirmax; /* attr cache dir max secs */ 621 char __user *netname; /* server's netname */ 622}; 623 624 625/* Bind the socket on a local reserved port and connect it to the 626 * remote server. This on Linux/i386 is done by the mount program, 627