9 #include <sys/ioccom.h>
14 #include <minix/bpf.h>
17 static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t
*out
,
18 i2c_ioctl_exec_t
*in
);
19 static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t
*out
,
20 minix_i2c_ioctl_exec_t
*in
);
22 static void rewrite_i2c_netbsd_to_minix(minix_i2c_ioctl_exec_t
*out
,
25 memset(out
, '\0', sizeof(minix_i2c_ioctl_exec_t
));
27 out
->iie_op
= in
->iie_op
;
28 out
->iie_addr
= in
->iie_addr
;
29 out
->iie_cmdlen
= I2C_EXEC_MAX_CMDLEN
< in
->iie_cmdlen
?
30 I2C_EXEC_MAX_CMDLEN
: in
->iie_cmdlen
;
31 out
->iie_buflen
= I2C_EXEC_MAX_BUFLEN
< in
->iie_buflen
?
32 I2C_EXEC_MAX_BUFLEN
: in
->iie_buflen
;
34 if (in
->iie_cmdlen
> 0 && in
->iie_cmd
!= NULL
) {
35 memcpy(out
->iie_cmd
, in
->iie_cmd
, in
->iie_cmdlen
);
38 if (in
->iie_buflen
> 0 && in
->iie_buf
!= NULL
) {
39 memcpy(out
->iie_buf
, in
->iie_buf
, in
->iie_buflen
);
43 static void rewrite_i2c_minix_to_netbsd(i2c_ioctl_exec_t
*out
,
44 minix_i2c_ioctl_exec_t
*in
)
46 /* the only field that changes is iie_buf, everything else is the same */
47 if (in
->iie_buflen
> 0 ) {
48 memcpy(out
->iie_buf
, in
->iie_buf
, in
->iie_buflen
);
53 * Convert a network interface related IOCTL with pointers to a flat format
54 * suitable for MINIX3. Return a pointer to the new data on success, or zero
55 * (with errno set) on failure. The original request code is given in
56 * 'request' and must be replaced by the new request code to be used.
59 ioctl_convert_if_to_minix(void * data
, unsigned long * request
)
61 struct minix_ifmediareq
*mifm
;
62 struct ifmediareq
*ifm
;
63 struct minix_if_clonereq
*mifcr
;
64 struct if_clonereq
*ifcr
;
68 ifm
= (struct ifmediareq
*)data
;
70 mifm
= (struct minix_ifmediareq
*)malloc(sizeof(*mifm
));
73 * The count may exceed MINIX_IF_MAXMEDIA, and should
74 * be truncated as needed by the IF implementation.
76 memcpy(&mifm
->mifm_ifm
, ifm
, sizeof(*ifm
));
78 *request
= MINIX_SIOCGIFMEDIA
;
82 return (vir_bytes
)mifm
;
85 ifcr
= (struct if_clonereq
*)data
;
87 mifcr
= (struct minix_if_clonereq
*)malloc(sizeof(*mifcr
));
90 * The count may exceed MINIX_IF_MAXCLONERS, and should
91 * be truncated as needed by the IF implementation.
93 memcpy(&mifcr
->mifcr_ifcr
, ifcr
, sizeof(*ifcr
));
95 *request
= MINIX_SIOCIFGCLONERS
;
99 return (vir_bytes
)mifcr
;
110 * Convert a the result of a network interface related IOCTL with pointers from
111 * the flat format used to make the call to MINIX3. Called on success only.
112 * The given request code is that of the (NetBSD-type) original.
115 ioctl_convert_if_from_minix(vir_bytes addr
, void * data
, unsigned long request
)
117 struct minix_ifmediareq
*mifm
;
118 struct ifmediareq
*ifm
;
119 struct minix_if_clonereq
*mifcr
;
120 struct if_clonereq
*ifcr
;
125 mifm
= (struct minix_ifmediareq
*)addr
;
126 ifm
= (struct ifmediareq
*)data
;
128 memcpy(ifm
, &mifm
->mifm_ifm
, sizeof(*ifm
));
130 if (ifm
->ifm_ulist
!= NULL
&& ifm
->ifm_count
> 0)
131 memcpy(ifm
->ifm_ulist
, mifm
->mifm_list
,
132 ifm
->ifm_count
* sizeof(ifm
->ifm_ulist
[0]));
137 mifcr
= (struct minix_if_clonereq
*)addr
;
138 ifcr
= (struct if_clonereq
*)data
;
140 memcpy(ifcr
, &mifcr
->mifcr_ifcr
, sizeof(*ifcr
));
142 count
= (ifcr
->ifcr_count
< ifcr
->ifcr_total
) ?
143 ifcr
->ifcr_count
: ifcr
->ifcr_total
;
144 if (ifcr
->ifcr_buffer
!= NULL
&& count
> 0)
145 memcpy(ifcr
->ifcr_buffer
, mifcr
->mifcr_buffer
,
156 * Convert a BPF (Berkeley Packet Filter) related IOCTL with pointers to a flat
157 * format suitable for MINIX3. Return a pointer to the new data on success, or
158 * zero (with errno set) on failure. The original request code is given in
159 * 'request' and must be replaced by the new request code to be used.
162 ioctl_convert_bpf_to_minix(void * data
, unsigned long * request
)
164 struct minix_bpf_program
*mbf
;
165 struct bpf_program
*bf
;
166 struct minix_bpf_dltlist
*mbfl
;
167 struct bpf_dltlist
*bfl
;
171 bf
= (struct bpf_program
*)data
;
173 if (bf
->bf_len
> __arraycount(mbf
->mbf_insns
)) {
178 mbf
= (struct minix_bpf_program
*)malloc(sizeof(*mbf
));
180 mbf
->mbf_len
= bf
->bf_len
;
181 memcpy(mbf
->mbf_insns
, bf
->bf_insns
,
182 bf
->bf_len
* sizeof(mbf
->mbf_insns
[0]));
184 *request
= MINIX_BIOCSETF
;
188 return (vir_bytes
)mbf
;
191 bfl
= (struct bpf_dltlist
*)data
;
193 mbfl
= (struct minix_bpf_dltlist
*)malloc(sizeof(*mbfl
));
196 * The length may exceed MINIX_BPF_MAXDLT, and should
197 * be truncated as needed by the BPF implementation.
199 memcpy(&mbfl
->mbfl_dltlist
, bfl
, sizeof(*bfl
));
201 *request
= MINIX_BIOCGDLTLIST
;
205 return (vir_bytes
)mbfl
;
216 * Convert a the result of BPF (Berkeley Packet Filter) related IOCTL with
217 * pointers from the flat format used to make the call to MINIX3. Called on
218 * success only. The given request code is that of the (NetBSD-type) original.
221 ioctl_convert_bpf_from_minix(vir_bytes addr
, void * data
,
222 unsigned long request
)
224 struct minix_bpf_dltlist
*mbfl
;
225 struct bpf_dltlist
*bfl
;
229 mbfl
= (struct minix_bpf_dltlist
*)addr
;
230 bfl
= (struct bpf_dltlist
*)data
;
232 memcpy(bfl
, &mbfl
->mbfl_dltlist
, sizeof(*bfl
));
234 if (bfl
->bfl_list
!= NULL
&& bfl
->bfl_len
> 0)
235 memcpy(bfl
->bfl_list
, mbfl
->mbfl_list
,
236 bfl
->bfl_len
* sizeof(bfl
->bfl_list
[0]));
246 * Library implementation of FIOCLEX and FIONCLEX.
249 ioctl_to_setfd(int fd
, int mask
, int val
)
253 if ((fl
= fcntl(fd
, F_GETFD
)) == -1)
256 fl
= (fl
& ~mask
) | val
;
258 return fcntl(fd
, F_SETFD
, fl
);
262 * Library implementation of FIONBIO and FIOASYNC.
265 ioctl_to_setfl(int fd
, void * data
, int sfl
)
271 if ((fl
= fcntl(fd
, F_GETFL
)) == -1)
279 return fcntl(fd
, F_SETFL
, fl
& ~O_ACCMODE
);
283 * Library implementation of various deprecated IOCTLs. These particular IOCTL
284 * calls change how the file descriptors behave, and have nothing to do with
285 * the actual open file. They should therefore be handled by VFS rather than
286 * individual device drivers. We rewrite them to use fcntl(2) instead here.
289 ioctl_to_fcntl(int fd
, unsigned long request
, void * data
)
293 return ioctl_to_setfd(fd
, FD_CLOEXEC
, FD_CLOEXEC
);
295 return ioctl_to_setfd(fd
, FD_CLOEXEC
, 0);
297 return ioctl_to_setfl(fd
, data
, O_NONBLOCK
);
299 return ioctl_to_setfl(fd
, data
, O_ASYNC
);
300 case FIOSETOWN
: /* XXX TODO */
301 case FIOGETOWN
: /* XXX TODO */
308 int ioctl(int fd
, unsigned long request
, ...)
310 minix_i2c_ioctl_exec_t i2c
;
317 va_start(ap
, request
);
318 data
= va_arg(ap
, void *);
322 * To support compatibility with interfaces on other systems, certain
323 * requests are re-written to flat structures (i.e. without pointers).
325 request_save
= request
;
334 return ioctl_to_fcntl(fd
, request
, data
);
337 rewrite_i2c_netbsd_to_minix(&i2c
, data
);
338 addr
= (vir_bytes
) &i2c
;
339 request
= MINIX_I2C_IOCTL_EXEC
;
344 if ((addr
= ioctl_convert_if_to_minix(data
, &request
)) == 0)
345 return -1; /* errno has already been set */
350 if ((addr
= ioctl_convert_bpf_to_minix(data
, &request
)) == 0)
351 return -1; /* errno has already been set */
355 /* Keep original as-is */
356 addr
= (vir_bytes
)data
;
360 memset(&m
, 0, sizeof(m
));
361 m
.m_lc_vfs_ioctl
.fd
= fd
;
362 m
.m_lc_vfs_ioctl
.req
= request
;
363 m
.m_lc_vfs_ioctl
.arg
= addr
;
365 r
= _syscall(VFS_PROC_NR
, VFS_IOCTL
, &m
);
368 * Translate back to original form. Do this on failure as well, as
369 * temporarily allocated resources may have to be freed up again.
371 switch (request_save
) {
373 rewrite_i2c_minix_to_netbsd(data
, &i2c
);
379 ioctl_convert_if_from_minix(addr
, data
, request_save
);
385 ioctl_convert_bpf_from_minix(addr
, data
, request_save
);