1 /* $OpenBSD: bsdos_ioctl.c,v 1.4 2003/06/17 21:56:25 millert Exp $ */
2
3 /*
4 * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <sys/param.h>
20 #include <sys/systm.h>
21 #include <sys/proc.h>
22 #include <sys/mount.h>
23
24 #include <sys/syscallargs.h>
25
26 #include <compat/bsdos/bsdos_syscallargs.h>
27 #include <compat/bsdos/bsdos_ioctl.h>
28
29 #include <compat/ossaudio/ossaudio.h>
30 #include <compat/ossaudio/ossaudiovar.h>
31
32 #include <compat/common/compat_util.h>
33
34 static void bsdos_to_oss(struct bsdos_sys_ioctl_args *, struct oss_sys_ioctl_args *);
35
36 /*
37 * BSD/OS and OSS have different values for IOC_*. Also,
38 * sizeof(bsdos_audio_buf_info) != sizeof(oss_audio_buf_info) which
39 * is encoded in OSS_SNDCTL_DSP_GETOSPACE and OSS_SNDCTL_DSP_GETISPACE.
40 */
41 static void
42 bsdos_to_oss(bap, oap)
43 struct bsdos_sys_ioctl_args *bap;
44 struct oss_sys_ioctl_args *oap;
45 {
46 u_long bcom, ocom;
47
48 bcom = SCARG(bap, com);
49 ocom = bcom & ~BSDOS_IOC_DIRMASK;
50 switch (bcom & BSDOS_IOC_DIRMASK) {
51 case BSDOS_IOC_VOID:
52 ocom |= OSS_IOC_VOID;
53 break;
54 case BSDOS_IOC_OUT:
55 if (bcom == BSDOS_SNDCTL_DSP_GETOSPACE)
56 ocom = OSS_SNDCTL_DSP_GETOSPACE;
57 else if (bcom == BSDOS_SNDCTL_DSP_GETISPACE)
58 ocom = OSS_SNDCTL_DSP_GETISPACE;
59 else
60 ocom |= OSS_IOC_OUT;
61 break;
62 case BSDOS_IOC_IN:
63 ocom |= OSS_IOC_IN;
64 break;
65 case BSDOS_IOC_INOUT:
66 ocom |= OSS_IOC_INOUT;
67 break;
68 }
69 SCARG(oap, fd) = SCARG(bap, fd);
70 SCARG(oap, com) = ocom;
71 SCARG(oap, data) = SCARG(bap, data);
72 }
73
74 int
75 bsdos_sys_ioctl(p, v, retval)
76 struct proc *p;
77 void *v;
78 register_t *retval;
79 {
80 struct bsdos_sys_ioctl_args /* {
81 syscallarg(int) fd;
82 syscallarg(u_long) com;
83 syscallarg(caddr_t) data;
84 } */ *uap = v;
85 struct oss_sys_ioctl_args ap;
86
87 /*
88 * XXX should support 'T' timer ioctl's
89 * XXX also /dev/sequencer and /dev/patmgr#
90 */
91 switch (BSDOS_IOCGROUP(SCARG(uap, com))) {
92 case 'M':
93 bsdos_to_oss(uap, &ap);
94 return (oss_ioctl_mixer(p, &ap, retval));
95 case 'Q':
96 bsdos_to_oss(uap, &ap);
97 return (oss_ioctl_sequencer(p, &ap, retval));
98 case 'P':
99 bsdos_to_oss(uap, &ap);
100 /*
101 * Special handling since the BSD/OS audio_buf_info
102 * struct lacks a fragstotal member.
103 */
104 if (SCARG(uap, com) == BSDOS_SNDCTL_DSP_GETOSPACE ||
105 SCARG(uap, com) == BSDOS_SNDCTL_DSP_GETISPACE)
106 {
107 struct oss_audio_buf_info oss_buf, *oss_bufp;
108 struct bsdos_audio_buf_info bsdos_buf;
109 caddr_t sg = stackgap_init(p->p_emul);
110 int error;
111
112 oss_bufp = stackgap_alloc(&sg, sizeof(*oss_bufp));
113 SCARG(&ap, data) = (void *) oss_bufp;
114 error = oss_ioctl_audio(p, &ap, retval);
115 if (error)
116 return (error);
117 error = copyin(oss_bufp, &oss_buf, sizeof(oss_buf));
118 if (error)
119 return (error);
120 bsdos_buf.fragments = oss_buf.fragstotal;
121 bsdos_buf.fragsize = oss_buf.fragsize;
122 bsdos_buf.bytes = oss_buf.bytes;
123 error = copyout(&bsdos_buf, SCARG(uap, data),
124 sizeof(bsdos_buf));
125 if (error)
126 return (error);
127 } else
128 return (oss_ioctl_audio(p, &ap, retval));
129 }
130 return (sys_ioctl(p, uap, retval));
131 }