📄 ia32_ioctl.c
字号:
typedef struct sg_io_hdr32 { s32 interface_id; /* [i] 'S' for SCSI generic (required) */ s32 dxfer_direction; /* [i] data transfer direction */ u8 cmd_len; /* [i] SCSI command length ( <= 16 bytes) */ u8 mx_sb_len; /* [i] max length to write to sbp */ u16 iovec_count; /* [i] 0 implies no scatter gather */ u32 dxfer_len; /* [i] byte count of data transfer */ u32 dxferp; /* [i], [*io] points to data transfer memory or scatter gather list */ u32 cmdp; /* [i], [*i] points to command to perform */ u32 sbp; /* [i], [*o] points to sense_buffer memory */ u32 timeout; /* [i] MAX_UINT->no timeout (unit: millisec) */ u32 flags; /* [i] 0 -> default, see SG_FLAG... */ s32 pack_id; /* [i->o] unused internally (normally) */ u32 usr_ptr; /* [i->o] unused internally */ u8 status; /* [o] scsi status */ u8 masked_status; /* [o] shifted, masked scsi status */ u8 msg_status; /* [o] messaging level data (optional) */ u8 sb_len_wr; /* [o] byte count actually written to sbp */ u16 host_status; /* [o] errors from host adapter */ u16 driver_status; /* [o] errors from software driver */ s32 resid; /* [o] dxfer_len - actual_transferred */ u32 duration; /* [o] time taken by cmd (unit: millisec) */ u32 info; /* [o] auxiliary information */} sg_io_hdr32_t; /* 64 bytes long (on sparc32) */typedef struct sg_iovec32 { u32 iov_base; u32 iov_len;} sg_iovec32_t;static int alloc_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32){ sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); sg_iovec_t *kiov; int i; sgp->dxferp = kmalloc(sgp->iovec_count * sizeof(sg_iovec_t), GFP_KERNEL); if (!sgp->dxferp) return -ENOMEM; memset(sgp->dxferp, 0, sgp->iovec_count * sizeof(sg_iovec_t)); kiov = (sg_iovec_t *) sgp->dxferp; for (i = 0; i < sgp->iovec_count; i++) { u32 iov_base32; if (__get_user(iov_base32, &uiov->iov_base) || __get_user(kiov->iov_len, &uiov->iov_len)) return -EFAULT; kiov->iov_base = kmalloc(kiov->iov_len, GFP_KERNEL); if (!kiov->iov_base) return -ENOMEM; if (copy_from_user(kiov->iov_base, (void *) A(iov_base32), kiov->iov_len)) return -EFAULT; uiov++; kiov++; } return 0;}static int copy_back_sg_iovec(sg_io_hdr_t *sgp, u32 uptr32){ sg_iovec32_t *uiov = (sg_iovec32_t *) A(uptr32); sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; int i; for (i = 0; i < sgp->iovec_count; i++) { u32 iov_base32; if (__get_user(iov_base32, &uiov->iov_base)) return -EFAULT; if (copy_to_user((void *) A(iov_base32), kiov->iov_base, kiov->iov_len)) return -EFAULT; uiov++; kiov++; } return 0;}static void free_sg_iovec(sg_io_hdr_t *sgp){ sg_iovec_t *kiov = (sg_iovec_t *) sgp->dxferp; int i; for (i = 0; i < sgp->iovec_count; i++) { if (kiov->iov_base) { kfree(kiov->iov_base); kiov->iov_base = NULL; } kiov++; } kfree(sgp->dxferp); sgp->dxferp = NULL;}static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg){ sg_io_hdr32_t *sg_io32; sg_io_hdr_t sg_io64; u32 dxferp32, cmdp32, sbp32; mm_segment_t old_fs; int err = 0; sg_io32 = (sg_io_hdr32_t *)arg; err = __get_user(sg_io64.interface_id, &sg_io32->interface_id); err |= __get_user(sg_io64.dxfer_direction, &sg_io32->dxfer_direction); err |= __get_user(sg_io64.cmd_len, &sg_io32->cmd_len); err |= __get_user(sg_io64.mx_sb_len, &sg_io32->mx_sb_len); err |= __get_user(sg_io64.iovec_count, &sg_io32->iovec_count); err |= __get_user(sg_io64.dxfer_len, &sg_io32->dxfer_len); err |= __get_user(sg_io64.timeout, &sg_io32->timeout); err |= __get_user(sg_io64.flags, &sg_io32->flags); err |= __get_user(sg_io64.pack_id, &sg_io32->pack_id); sg_io64.dxferp = NULL; sg_io64.cmdp = NULL; sg_io64.sbp = NULL; err |= __get_user(cmdp32, &sg_io32->cmdp); sg_io64.cmdp = kmalloc(sg_io64.cmd_len, GFP_KERNEL); if (!sg_io64.cmdp) { err = -ENOMEM; goto out; } if (copy_from_user(sg_io64.cmdp, (void *) A(cmdp32), sg_io64.cmd_len)) { err = -EFAULT; goto out; } err |= __get_user(sbp32, &sg_io32->sbp); sg_io64.sbp = kmalloc(sg_io64.mx_sb_len, GFP_KERNEL); if (!sg_io64.sbp) { err = -ENOMEM; goto out; } if (copy_from_user(sg_io64.sbp, (void *) A(sbp32), sg_io64.mx_sb_len)) { err = -EFAULT; goto out; } err |= __get_user(dxferp32, &sg_io32->dxferp); if (sg_io64.iovec_count) { int ret; if ((ret = alloc_sg_iovec(&sg_io64, dxferp32))) { err = ret; goto out; } } else { sg_io64.dxferp = kmalloc(sg_io64.dxfer_len, GFP_KERNEL); if (!sg_io64.dxferp) { err = -ENOMEM; goto out; } if (copy_from_user(sg_io64.dxferp, (void *) A(dxferp32), sg_io64.dxfer_len)) { err = -EFAULT; goto out; } } /* Unused internally, do not even bother to copy it over. */ sg_io64.usr_ptr = NULL; if (err) return -EFAULT; old_fs = get_fs(); set_fs (KERNEL_DS); err = sys_ioctl (fd, cmd, (unsigned long) &sg_io64); set_fs (old_fs); if (err < 0) goto out; err = __put_user(sg_io64.pack_id, &sg_io32->pack_id); err |= __put_user(sg_io64.status, &sg_io32->status); err |= __put_user(sg_io64.masked_status, &sg_io32->masked_status); err |= __put_user(sg_io64.msg_status, &sg_io32->msg_status); err |= __put_user(sg_io64.sb_len_wr, &sg_io32->sb_len_wr); err |= __put_user(sg_io64.host_status, &sg_io32->host_status); err |= __put_user(sg_io64.driver_status, &sg_io32->driver_status); err |= __put_user(sg_io64.resid, &sg_io32->resid); err |= __put_user(sg_io64.duration, &sg_io32->duration); err |= __put_user(sg_io64.info, &sg_io32->info); err |= copy_to_user((void *)A(sbp32), sg_io64.sbp, sg_io64.mx_sb_len); if (sg_io64.dxferp) { if (sg_io64.iovec_count) err |= copy_back_sg_iovec(&sg_io64, dxferp32); else err |= copy_to_user((void *)A(dxferp32), sg_io64.dxferp, sg_io64.dxfer_len); } if (err) err = -EFAULT;out: if (sg_io64.cmdp) kfree(sg_io64.cmdp); if (sg_io64.sbp) kfree(sg_io64.sbp); if (sg_io64.dxferp) { if (sg_io64.iovec_count) { free_sg_iovec(&sg_io64); } else { kfree(sg_io64.dxferp); } } return err;}struct sock_fprog32 { __u16 len; __u32 filter;};#define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32)#define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32)static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg){ struct sock_fprog32 *u_fprog32 = (struct sock_fprog32 *) arg; struct sock_fprog *u_fprog64 = alloc_user_space(sizeof(struct sock_fprog)); void *fptr64; u32 fptr32; u16 flen; if (get_user(flen, &u_fprog32->len) || get_user(fptr32, &u_fprog32->filter)) return -EFAULT; fptr64 = (void *) A(fptr32); if (put_user(flen, &u_fprog64->len) || put_user(fptr64, &u_fprog64->filter)) return -EFAULT; if (cmd == PPPIOCSPASS32) cmd = PPPIOCSPASS; else cmd = PPPIOCSACTIVE; return sys_ioctl(fd, cmd, (unsigned long) u_fprog64);}struct ppp_option_data32 { __kernel_caddr_t32 ptr; __u32 length; int transmit;};#define PPPIOCSCOMPRESS32 _IOW('t', 77, struct ppp_option_data32)struct ppp_idle32 { __kernel_time_t32 xmit_idle; __kernel_time_t32 recv_idle;};#define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32)static int ppp_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg){ mm_segment_t old_fs = get_fs(); struct ppp_option_data32 data32; struct ppp_option_data data; struct ppp_idle32 idle32; struct ppp_idle idle; unsigned int kcmd; void *karg; int err = 0; switch (cmd) { case PPPIOCGIDLE32: kcmd = PPPIOCGIDLE; karg = &idle; break; case PPPIOCSCOMPRESS32: if (copy_from_user(&data32, (struct ppp_option_data32 *)arg, sizeof(struct ppp_option_data32))) return -EFAULT; data.ptr = kmalloc (data32.length, GFP_KERNEL); if (!data.ptr) return -ENOMEM; if (copy_from_user(data.ptr, (__u8 *)A(data32.ptr), data32.length)) { kfree(data.ptr); return -EFAULT; } data.length = data32.length; data.transmit = data32.transmit; kcmd = PPPIOCSCOMPRESS; karg = &data; break; default: do { static int count; if (++count <= 20) printk("ppp_ioctl: Unknown cmd fd(%d) " "cmd(%08x) arg(%08x)\n", (int)fd, (unsigned int)cmd, (unsigned int)arg); } while(0); return -EINVAL; } set_fs (KERNEL_DS); err = sys_ioctl (fd, kcmd, (unsigned long)karg); set_fs (old_fs); switch (cmd) { case PPPIOCGIDLE32: if (err) return err; idle32.xmit_idle = idle.xmit_idle; idle32.recv_idle = idle.recv_idle; if (copy_to_user((struct ppp_idle32 *)arg, &idle32, sizeof(struct ppp_idle32))) return -EFAULT; break; case PPPIOCSCOMPRESS32: kfree(data.ptr); break; default: break; } return err;}struct mtget32 { __u32 mt_type; __u32 mt_resid; __u32 mt_dsreg; __u32 mt_gstat; __u32 mt_erreg; __kernel_daddr_t32 mt_fileno; __kernel_daddr_t32 mt_blkno;};#define MTIOCGET32 _IOR('m', 2, struct mtget32)struct mtpos32 { __u32 mt_blkno;};#define MTIOCPOS32 _IOR('m', 3, struct mtpos32)struct mtconfiginfo32 { __u32 mt_type; __u32 ifc_type; __u16 irqnr; __u16 dmanr; __u16 port; __u32 debug; __u32 have_dens:1; __u32 have_bsf:1; __u32 have_fsr:1; __u32 have_bsr:1; __u32 have_eod:1; __u32 have_seek:1; __u32 have_tell:1; __u32 have_ras1:1; __u32 have_ras2:1; __u32 have_ras3:1; __u32 have_qfa:1; __u32 pad1:5; char reserved[10];};#define MTIOCGETCONFIG32 _IOR('m', 4, struct mtconfiginfo32)#define MTIOCSETCONFIG32 _IOW('m', 5, struct mtconfiginfo32)static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg){ mm_segment_t old_fs = get_fs(); struct mtconfiginfo info; struct mtget get; struct mtpos pos; unsigned long kcmd; void *karg; int err = 0; switch(cmd) { case MTIOCPOS32: kcmd = MTIOCPOS; karg = &pos; break; case MTIOCGET32: kcmd = MTIOCGET; karg = &get; break; case MTIOCGETCONFIG32: kcmd = MTIOCGETCONFIG; karg = &info; break; case MTIOCSETCONFIG32: kcmd = MTIOCSETCONFIG; karg = &info; err = __get_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); err |= __get_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type); err |= __get_user(info.irqnr, &((struct mtconfiginfo32 *)arg)->irqnr); err |= __get_user(info.dmanr, &((struct mtconfiginfo32 *)arg)->dmanr); err |= __get_user(info.port, &((struct mtconfiginfo32 *)arg)->port); err |= __get_user(info.debug, &((struct mtconfiginfo32 *)arg)->debug); err |= __copy_from_user((char *)&info.debug + sizeof(info.debug), (char *)&((struct mtconfiginfo32 *)arg)->debug + sizeof(((struct mtconfiginfo32 *)arg)->debug), sizeof(__u32)); if (err) return -EFAULT; break; default: do { static int count; if (++count <= 20) printk("mt_ioctl: Unknown cmd fd(%d) " "cmd(%08x) arg(%08x)\n", (int)fd, (unsigned int)cmd, (unsigned int)arg); } while(0); return -EINVAL; } set_fs (KERNEL_DS); err = sys_ioctl (fd, kcmd, (unsigned long)karg); set_fs (old_fs); if (err) return err; switch (cmd) { case MTIOCPOS32: err = __put_user(pos.mt_blkno, &((struct mtpos32 *)arg)->mt_blkno); break; case MTIOCGET32: err = __put_user(get.mt_type, &((struct mtget32 *)arg)->mt_type); err |= __put_user(get.mt_resid, &((struct mtget32 *)arg)->mt_resid); err |= __put_user(get.mt_dsreg, &((struct mtget32 *)arg)->mt_dsreg); err |= __put_user(get.mt_gstat, &((struct mtget32 *)arg)->mt_gstat); err |= __put_user(get.mt_erreg, &((struct mtget32 *)arg)->mt_erreg); err |= __put_user(get.mt_fileno, &((struct mtget32 *)arg)->mt_fileno); err |= __put_user(get.mt_blkno, &((struct mtget32 *)arg)->mt_blkno); break; case MTIOCGETCONFIG32: err = __put_user(info.mt_type, &((struct mtconfiginfo32 *)arg)->mt_type); err |= __put_user(info.ifc_type, &((struct mtconfiginfo32 *)arg)->ifc_type);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -