diff options
author | mav <mav@FreeBSD.org> | 2014-07-02 10:16:12 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2014-07-02 10:16:12 +0000 |
commit | 927a52fbbfa5d8d56eec3abf498e8d21614347b3 (patch) | |
tree | 09e7599c2534a64015e00045f4f1f3d425ecbdde /sys/compat/freebsd32 | |
parent | d0f1ea0d9e0d37768f65929fa6c904891670c408 (diff) | |
download | FreeBSD-src-927a52fbbfa5d8d56eec3abf498e8d21614347b3.zip FreeBSD-src-927a52fbbfa5d8d56eec3abf498e8d21614347b3.tar.gz |
MFC r266981:
Overhaul CAM SG driver IOCTL interfaces.
Make it really work for native FreeBSD programs. Before this it was broken
for years due to different number of pointer dereferences in Linux and
FreeBSD IOCTL paths, permanently returning errors to FreeBSD programs.
This change breaks the driver FreeBSD IOCTL ABI, making it more strict,
but since it was not working any way -- who bother.
Add shims for 32-bit programs on 64-bit host, translating the argument
of the SG_IO IOCTL for both FreeBSD and Linux ABIs.
With this change I was able to run 32-bit Linux sg3_utils tools and simple
32 and 64-bit FreeBSD test tools on both 32 and 64-bit FreeBSD systems.
Diffstat (limited to 'sys/compat/freebsd32')
-rw-r--r-- | sys/compat/freebsd32/freebsd32_ioctl.c | 69 | ||||
-rw-r--r-- | sys/compat/freebsd32/freebsd32_ioctl.h | 3 |
2 files changed, 72 insertions, 0 deletions
diff --git a/sys/compat/freebsd32/freebsd32_ioctl.c b/sys/compat/freebsd32/freebsd32_ioctl.c index 1f90e58..552b26a 100644 --- a/sys/compat/freebsd32/freebsd32_ioctl.c +++ b/sys/compat/freebsd32/freebsd32_ioctl.c @@ -344,6 +344,71 @@ cleanup: return (error); } +static int +freebsd32_ioctl_sg(struct thread *td, + struct freebsd32_ioctl_args *uap, struct file *fp) +{ + struct sg_io_hdr io; + struct sg_io_hdr32 io32; + int error; + + if ((error = copyin(uap->data, &io32, sizeof(io32))) != 0) + return (error); + + CP(io32, io, interface_id); + CP(io32, io, dxfer_direction); + CP(io32, io, cmd_len); + CP(io32, io, mx_sb_len); + CP(io32, io, iovec_count); + CP(io32, io, dxfer_len); + PTRIN_CP(io32, io, dxferp); + PTRIN_CP(io32, io, cmdp); + PTRIN_CP(io32, io, sbp); + CP(io32, io, timeout); + CP(io32, io, flags); + CP(io32, io, pack_id); + PTRIN_CP(io32, io, usr_ptr); + CP(io32, io, status); + CP(io32, io, masked_status); + CP(io32, io, msg_status); + CP(io32, io, sb_len_wr); + CP(io32, io, host_status); + CP(io32, io, driver_status); + CP(io32, io, resid); + CP(io32, io, duration); + CP(io32, io, info); + + if ((error = fo_ioctl(fp, SG_IO, (caddr_t)&io, td->td_ucred, td)) != 0) + return (error); + + CP(io, io32, interface_id); + CP(io, io32, dxfer_direction); + CP(io, io32, cmd_len); + CP(io, io32, mx_sb_len); + CP(io, io32, iovec_count); + CP(io, io32, dxfer_len); + PTROUT_CP(io, io32, dxferp); + PTROUT_CP(io, io32, cmdp); + PTROUT_CP(io, io32, sbp); + CP(io, io32, timeout); + CP(io, io32, flags); + CP(io, io32, pack_id); + PTROUT_CP(io, io32, usr_ptr); + CP(io, io32, status); + CP(io, io32, masked_status); + CP(io, io32, msg_status); + CP(io, io32, sb_len_wr); + CP(io, io32, host_status); + CP(io, io32, driver_status); + CP(io, io32, resid); + CP(io, io32, duration); + CP(io, io32, info); + + error = copyout(&io32, uap->data, sizeof(io32)); + + return (error); +} + int freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap) { @@ -393,6 +458,10 @@ freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap) error = freebsd32_ioctl_pciocgetconf(td, uap, fp); break; + case SG_IO_32: + error = freebsd32_ioctl_sg(td, uap, fp); + break; + default: fdrop(fp, td); ap.fd = uap->fd; diff --git a/sys/compat/freebsd32/freebsd32_ioctl.h b/sys/compat/freebsd32/freebsd32_ioctl.h index e0beb73..18cfc95 100644 --- a/sys/compat/freebsd32/freebsd32_ioctl.h +++ b/sys/compat/freebsd32/freebsd32_ioctl.h @@ -32,6 +32,8 @@ #ifndef _COMPAT_FREEBSD32_IOCTL_H_ #define _COMPAT_FREEBSD32_IOCTL_H_ +#include <cam/scsi/scsi_sg.h> + typedef __uint32_t caddr_t32; struct ioc_toc_header32 { @@ -122,5 +124,6 @@ struct pci_conf_io32 { #define MEMRANGE_GET32 _IOWR('m', 50, struct mem_range_op32) #define MEMRANGE_SET32 _IOW('m', 51, struct mem_range_op32) #define PCIOCGETCONF_32 _IOWR('p', 5, struct pci_conf_io32) +#define SG_IO_32 _IOWR(SGIOC, 0x85, struct sg_io_hdr32) #endif /* _COMPAT_FREEBSD32_IOCTL_H_ */ |