summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux/linux_ioctl.c
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2007-04-07 19:40:58 +0000
committerscottl <scottl@FreeBSD.org>2007-04-07 19:40:58 +0000
commit1320f9f144d11efc5e2e12e3ab69a5a4559b06fe (patch)
treef3bff966194b6ef5bf3c76fcbd41adc4ff98caa6 /sys/compat/linux/linux_ioctl.c
parent9a4581bab30ccb9819a6020d5156ef862a0613f1 (diff)
downloadFreeBSD-src-1320f9f144d11efc5e2e12e3ab69a5a4559b06fe.zip
FreeBSD-src-1320f9f144d11efc5e2e12e3ab69a5a4559b06fe.tar.gz
Add the CAM 'SG' peripheral device. This device implements a subset of the
Linux SCSI SG passthrough device API. The intention is to allow for both running of Linux apps that want to talk to /dev/sg* nodes, and to facilitate porting of apps from Linux to FreeBSD. As such, both native and linuxolator entry points and definitions are provided. Caveats: - This does not support the procfs and sysfs nodes that the Linux SG driver provides. Some Linux apps may rely on these for operation, others may only use them for informational purposes. - More ioctls need to be implemented. - Linux uses a naming scheme of "sg[a-z]" for devices, while FreeBSD uses a scheme of "sg[0-9]". Devfs aliasis (symlinks) are automatically created to link the two together. However, tools like camcontrol only see the native names. - Some operations were originally designed to return byte counts or other data directly as the syscall return value. The linuxolator doesn't appear to support this well, so this driver just punts for these cases. Now that the driver is in place, others are welcome to add missing functionality. Thanks to Roman Divacky for pushing this work along.
Diffstat (limited to 'sys/compat/linux/linux_ioctl.c')
-rw-r--r--sys/compat/linux/linux_ioctl.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index 09e1cc0..9583551 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -86,6 +86,7 @@ static linux_ioctl_function_t linux_ioctl_sound;
static linux_ioctl_function_t linux_ioctl_termio;
static linux_ioctl_function_t linux_ioctl_private;
static linux_ioctl_function_t linux_ioctl_drm;
+static linux_ioctl_function_t linux_ioctl_sg;
static linux_ioctl_function_t linux_ioctl_special;
static struct linux_ioctl_handler cdrom_handler =
@@ -108,6 +109,8 @@ static struct linux_ioctl_handler private_handler =
{ linux_ioctl_private, LINUX_IOCTL_PRIVATE_MIN, LINUX_IOCTL_PRIVATE_MAX };
static struct linux_ioctl_handler drm_handler =
{ linux_ioctl_drm, LINUX_IOCTL_DRM_MIN, LINUX_IOCTL_DRM_MAX };
+static struct linux_ioctl_handler sg_handler =
+{ linux_ioctl_sg, LINUX_IOCTL_SG_MIN, LINUX_IOCTL_SG_MAX };
DATA_SET(linux_ioctl_handler_set, cdrom_handler);
DATA_SET(linux_ioctl_handler_set, vfat_handler);
@@ -119,6 +122,7 @@ DATA_SET(linux_ioctl_handler_set, sound_handler);
DATA_SET(linux_ioctl_handler_set, termio_handler);
DATA_SET(linux_ioctl_handler_set, private_handler);
DATA_SET(linux_ioctl_handler_set, drm_handler);
+DATA_SET(linux_ioctl_handler_set, sg_handler);
struct handler_element
{
@@ -1583,6 +1587,11 @@ linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
break;
}
+ case LINUX_SCSI_GET_BUS_NUMBER:
+ case LINUX_SCSI_GET_IDLUN:
+ error = linux_ioctl_sg(td, args);
+ break;
+
/* LINUX_CDROM_SEND_PACKET */
/* LINUX_CDROM_NEXT_WRITABLE */
/* LINUX_CDROM_LAST_WRITTEN */
@@ -2522,6 +2531,24 @@ linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args)
return ioctl(td, (struct ioctl_args *)args);
}
+static int
+linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ u_long cmd;
+ int error;
+
+ if ((error = fget(td, args->fd, &fp)) != 0) {
+ printf("sg_linux_ioctl: fget returned %d\n", error);
+ return (error);
+ }
+ cmd = args->cmd;
+
+ error = (fo_ioctl(fp, cmd, (caddr_t)args->arg, td->td_ucred, td));
+ fdrop(fp, td);
+ return (error);
+}
+
/*
* Special ioctl handler
*/
OpenPOWER on IntegriCloud