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-2002 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... */
14 #include <linux/msdos_fs.h>
15 #include <linux/mtio.h>
16 #include <linux/ncp_fs.h>
17 #include <linux/capi.h>
18 #include <linux/videodev.h>
19 #include <linux/synclink.h>
20 #include <linux/atmdev.h>
21 #include <linux/atm_eni.h>
22 #include <linux/atm_nicstar.h>
23 #include <linux/atm_zatm.h>
24 #include <linux/atm_idt77105.h>
25 #include <linux/ppp_defs.h>
26 #include <linux/if_ppp.h>
27 #include <linux/ixjuser.h>
28 #include <linux/i2o-dev.h>
29 #include <scsi/scsi.h>
32 #include <scsi/scsi_ioctl.h>
38 #include <../drivers/char/drm/drm.h>
39 #include <../drivers/char/drm/mga_drm.h>
40 #include <../drivers/char/drm/i810_drm.h>
43 #define IOCTL_NR(a) ((a) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))
45 #define DO_IOCTL(fd, cmd, arg) ({ \
47 mm_segment_t _old_fs = get_fs(); \
50 _ret = sys_ioctl(fd, cmd, (unsigned long)arg); \
55 #define P(i) ((void *)(unsigned long)(i))
57 asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
60 put_dirent32 (struct dirent *d, struct linux32_dirent *d32)
62 size_t namelen = strlen(d->d_name);
64 return (put_user(d->d_ino, &d32->d_ino)
65 || put_user(d->d_off, &d32->d_off)
66 || put_user(d->d_reclen, &d32->d_reclen)
67 || copy_to_user(d32->d_name, d->d_name, namelen + 1));
70 * The transform code for the SG_IO ioctl was brazenly lifted from
71 * the Sparc64 port in the file `arch/sparc64/kernel/ioctl32.c'.
72 * Thanks to Jakub Jelinek & Eddie C. Dost.
74 typedef struct sg_io_hdr32 {
75 int interface_id; /* [i] 'S' for SCSI generic (required) */
76 int dxfer_direction; /* [i] data transfer direction */
77 char cmd_len; /* [i] SCSI command length ( <= 16 bytes) */
78 char mx_sb_len; /* [i] max length to write to sbp */
79 short iovec_count; /* [i] 0 implies no scatter gather */
80 int dxfer_len; /* [i] byte count of data transfer */
81 int dxferp; /* [i], [*io] points to data transfer memory
82 or scatter gather list */
83 int cmdp; /* [i], [*i] points to command to perform */
84 int sbp; /* [i], [*o] points to sense_buffer memory */
85 int timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */
86 int flags; /* [i] 0 -> default, see SG_FLAG... */
87 int pack_id; /* [i->o] unused internally (normally) */
88 int usr_ptr; /* [i->o] unused internally */
89 char status; /* [o] scsi status */
90 char masked_status; /* [o] shifted, masked scsi status */
91 char msg_status; /* [o] messaging level data (optional) */
92 char sb_len_wr; /* [o] byte count actually written to sbp */
93 short host_status; /* [o] errors from host adapter */
94 short driver_status; /* [o] errors from software driver */
95 int resid; /* [o] dxfer_len - actual_transferred */
96 int duration; /* [o] time taken by cmd (unit: millisec) */
97 int info; /* [o] auxiliary information */
98 } sg_io_hdr32_t; /* 64 bytes long (on IA32) */
100 static int alloc_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
102 struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
106 sgp->dxferp = kmalloc(sgp->iovec_count *
107 sizeof(sg_iovec_t), GFP_KERNEL);
110 memset(sgp->dxferp, 0,
111 sgp->iovec_count * sizeof(sg_iovec_t));
113 kiov = (sg_iovec_t *) sgp->dxferp;
114 for (i = 0; i < sgp->iovec_count; i++) {
116 if (__get_user(iov_base32, &uiov->iov_base) ||
117 __get_user(kiov->iov_len, &uiov->iov_len))
120 kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL);
123 if (copy_from_user(kiov->iov_base,
124 (void *) P(iov_base32),
135 static int copy_back_sg_iovec(sg_io_hdr_t *sgp, int uptr32)
137 struct compat_iovec *uiov = (struct compat_iovec *) P(uptr32);
138 sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
141 for (i = 0; i < sgp->iovec_count; i++) {
144 if (__get_user(iov_base32, &uiov->iov_base))
147 if (copy_to_user((void *) P(iov_base32),
159 static void free_sg_iovec(sg_io_hdr_t *sgp)
161 sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp;
164 for (i = 0; i < sgp->iovec_count; i++) {
165 if (kiov->iov_base) {
166 kfree(kiov->iov_base);
167 kiov->iov_base = NULL;
175 static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg)
177 sg_io_hdr32_t *sg_io32;
179 int dxferp32, cmdp32, sbp32;
183 sg_io32 = (sg_io_hdr32_t *)arg;
184 err = __get_user(sg_io64.interface_id, &sg_io32->interface_id);
185 err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction);
186 err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len);
187 err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len);
188 err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count);
189 err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len);
190 err |= __get_user(sg_io64.timeout, &sg_io32->timeout);
191 err |= __get_user(sg_io64.flags, &sg_io32->flags);
192 err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id);
194 sg_io64.dxferp = NULL;
198 err |= __get_user(cmdp32, &sg_io32->cmdp);
199 sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL);
204 if (copy_from_user(sg_io64.cmdp,
211 err |= __get_user(sbp32, &sg_io32->sbp);
212 sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL);
217 if (copy_from_user(sg_io64.sbp,
219 sg_io64.mx_sb_len)) {
224 err |= __get_user(dxferp32, &sg_io32->dxferp);
225 if (sg_io64.iovec_count) {
228 if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) {
233 sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL);
234 if (!sg_io64.dxferp) {
238 if (copy_from_user(sg_io64.dxferp,
239 (void *) P(dxferp32),
240 sg_io64.dxfer_len)) {
246 /* Unused internally, do not even bother to copy it over. */
247 sg_io64.usr_ptr = NULL;
254 err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64);
260 err = __put_user(sg_io64.pack_id, &sg_io32->pack_id);
261 err |= __put_user(sg_io64.status, &sg_io32->status);
262 err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status);
263 err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status);
264 err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr);
265 err |= __put_user(sg_io64.host_status, &sg_io32->host_status);
266 err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status);
267 err |= __put_user(sg_io64.resid, &sg_io32->resid);
268 err |= __put_user(sg_io64.duration, &sg_io32->duration);
269 err |= __put_user(sg_io64.info, &sg_io32->info);
270 err |= copy_to_user((void *)P(sbp32), sg_io64.sbp, sg_io64.mx_sb_len);
271 if (sg_io64.dxferp) {
272 if (sg_io64.iovec_count)
273 err |= copy_back_sg_iovec(&sg_io64, dxferp32);
275 err |= copy_to_user((void *)P(dxferp32),
287 if (sg_io64.dxferp) {
288 if (sg_io64.iovec_count) {
289 free_sg_iovec(&sg_io64);
291 kfree(sg_io64.dxferp);