summaryrefslogtreecommitdiffstats
path: root/sys/compat/freebsd32
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2014-07-02 10:16:12 +0000
committermav <mav@FreeBSD.org>2014-07-02 10:16:12 +0000
commit927a52fbbfa5d8d56eec3abf498e8d21614347b3 (patch)
tree09e7599c2534a64015e00045f4f1f3d425ecbdde /sys/compat/freebsd32
parentd0f1ea0d9e0d37768f65929fa6c904891670c408 (diff)
downloadFreeBSD-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.c69
-rw-r--r--sys/compat/freebsd32/freebsd32_ioctl.h3
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_ */
OpenPOWER on IntegriCloud