2 * IA32 Architecture-specific ioctl shim code
4 * Copyright (C) 2000 VA Linux Co
5 * Copyright (C) 2000 Don Dugger <n0ano@valinux.com>
6 * Copyright (C) 2001-2003 Hewlett-Packard Co
7 * David Mosberger-Tang <davidm@hpl.hp.com>
10 #include <linux/types.h>
11 #include <linux/dirent.h>
12 #include <linux/fs.h> /* argh, msdos_fs.h isn't self-contained... */
13 #include <linux/signal.h> /* argh, msdos_fs.h isn't self-contained... */
17 #include <linux/msdos_fs.h>
18 #include <linux/mtio.h>
19 #include <linux/ncp_fs.h>
20 #include <linux/capi.h>
21 #include <linux/videodev.h>
22 #include <linux/synclink.h>
23 #include <linux/atmdev.h>
24 #include <linux/atm_eni.h>
25 #include <linux/atm_nicstar.h>
26 #include <linux/atm_zatm.h>
27 #include <linux/atm_idt77105.h>
28 #include <linux/ppp_defs.h>
29 #include <linux/if_ppp.h>
30 #include <linux/ixjuser.h>
31 #include <linux/i2o-dev.h>
32 #include <scsi/scsi.h>
35 #include <scsi/scsi_ioctl.h>
39 #include <../drivers/char/drm/drm.h>
40 #include <../drivers/char/drm/mga_drm.h>
41 #include <../drivers/char/drm/i810_drm.h>
44 #define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
46 #define DO_IOCTL(fd, cmd, arg) ({ \
48 mm_segment_t _old_fs = get_fs(); \
51 _ret = sys_ioctl(fd, cmd, (unsigned long)arg); \
56 #define P(i) ((void *)(unsigned long)(i))
58 asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
61 put_dirent32 (struct dirent *d, struct linux32_dirent *d32)
63 size_t namelen = strlen(d->d_name);
65 return (put_user(d->d_ino, &d32->d_ino)
66 || put_user(d->d_off, &d32->d_off)
67 || put_user(d->d_reclen, &d32->d_reclen)
68 || copy_to_user(d32->d_name, d->d_name, namelen + 1));
71 * The transform code for the SG_IO ioctl was brazenly lifted from
72 * the Sparc64 port in the file `arch/sparc64/kernel/ioctl32.c'.
73 * Thanks to Jakub Jelinek & Eddie C. Dost.
75 typedef struct sg_io_hdr32 {
76 int interface_id; /* [i] 'S' for SCSI generic (required) */
77 int dxfer_direction; /* [i] data transfer direction */
78 char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */
79 char mx_sb_len; /* [i] max length to write to sbp */
80 short iovec_count; /* [i] 0 implies no scatter gather */
81 int dxfer_len; /* [i] byte count of data transfer */
82 int dxferp; /* [i], [*io] points to data transfer memory
83 or scatter gather list */
84 int cmdp; /* [i], [*i] points to command to perform */
85 int sbp; /* [i], [*o] points to sense_buffer memory */
86 int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */
87 int flags; /* [i] 0 -> default, see SG_FLAG... */
88 int pack_id; /* [i->o] unused internally (normally) */
89 int usr_ptr; /* [i->o] unused internally */
90 char status; /* [o] scsi status */
91 char masked_status; /* [o] shifted, masked scsi status */
92 char msg_status; /* [o] messaging level data (optional) */
93 char sb_len_wr; /* [o] byte count actually written to sbp */
94 short host_status; /* [o] errors from host adapter */
95 short driver_status; /* [o] errors from software driver */
96 int resid; /* [o] dxfer_len - actual_transferred */
97 int duration; /* [o] time taken by cmd (unit: millisec) */
98 int info; /* [o] auxiliary information */
99 } sg_io_hdr32_t; /* 64 bytes long (on IA32) */
101 static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
103 struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
107 sgp->dxferp = kmalloc(sgp->iovec_count *
108 sizeof(sg_iovec_t), GFP_KERNEL);
111 memset(sgp->dxferp, 0,
112 sgp->iovec_count * sizeof(sg_iovec_t));
114 kiov = (sg_iovec_t *) sgp->dxferp;
115 for (i = 0; i < sgp->iovec_count; i++) {
117 if (__get_user(iov_base32, &uiov->iov_base) ||
118 __get_user(kiov->iov_len, &uiov->iov_len))
121 kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL);
124 if (copy_from_user(kiov->iov_base,
125 (void *) P(iov_base32),
136 static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
138 struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
139 sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
142 for (i = 0; i < sgp->iovec_count; i++) {
145 if (__get_user(iov_base32, &uiov->iov_base))
148 if (copy_to_user((void *) P(iov_base32),
160 static void free_sg_iovec(sg_io_hdr_t *sgp)
162 sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
165 for (i = 0; i < sgp->iovec_count; i++) {
166 if (kiov->iov_base) {
167 kfree(kiov->iov_base);
168 kiov->iov_base = NULL;
176 static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
178 sg_io_hdr32_t *sg_io32;
180 int dxferp32, cmdp32, sbp32;
184 sg_io32 = (sg_io_hdr32_t *)arg;
185 err = __get_user(sg_io64.interface_id, &sg_io32->interface_id);
186 err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction);
187 err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len);
188 err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len);
189 err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count);
190 err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len);
191 err |= __get_user(sg_io64.timeout, &sg_io32->timeout);
192 err |= __get_user(sg_io64.flags, &sg_io32->flags);
193 err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id);
195 sg_io64.dxferp = NULL;
199 err |= __get_user(cmdp32, &sg_io32->cmdp);
200 sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL);
205 if (copy_from_user(sg_io64.cmdp,
212 err |= __get_user(sbp32, &sg_io32->sbp);
213 sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL);
218 if (copy_from_user(sg_io64.sbp,
220 sg_io64.mx_sb_len)) {
225 err |= __get_user(dxferp32, &sg_io32->dxferp);
226 if (sg_io64.iovec_count) {
229 if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) {
234 sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL);
235 if (!sg_io64.dxferp) {
239 if (copy_from_user(sg_io64.dxferp,
240 (void *) P(dxferp32),
241 sg_io64.dxfer_len)) {
247 /* Unused internally, do not even bother to copy it over. */
248 sg_io64.usr_ptr = NULL;
255 err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64);
261 err = __put_user(sg_io64.pack_id, &sg_io32->pack_id);
262 err |= __put_user(sg_io64.status, &sg_io32->status);
263 err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status);
264 err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status);
265 err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr);
266 err |= __put_user(sg_io64.host_status, &sg_io32->host_status);
267 err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status);
268 err |= __put_user(sg_io64.resid, &sg_io32->resid);
269 err |= __put_user(sg_io64.duration, &sg_io32->duration);
270 err |= __put_user(sg_io64.info, &sg_io32->info);
271 err |= copy_to_user((void *)P(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
272 if (sg_io64.dxferp) {
273 if (sg_io64.iovec_count)
274 err |= copy_back_sg_iovec(&sg_io64, dxferp32);
276 err |= copy_to_user((void *)P(dxferp32),
288 if (sg_io64.dxferp) {
289 if (sg_io64.iovec_count) {
290 free_sg_iovec(&sg_io64);
292 kfree(sg_io64.dxferp);