Index: sys/cam/cam_compat.c =================================================================== --- sys/cam/cam_compat.c +++ sys/cam/cam_compat.c @@ -54,6 +54,12 @@ #include "opt_cam.h" +/* + * Note: struct cdev *dev parameter here is simply passed through. For cdioctl + * we need to pass down a struct disk * which has been cast to a cdev and that + * is cast back again in cdioctl_dev(). + */ + static int cam_compat_handle_0x17(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td, d_ioctl_t *cbfnp); static int cam_compat_handle_0x18(struct cdev *dev, u_long cmd, caddr_t addr, Index: sys/cam/scsi/scsi_cd.c =================================================================== --- sys/cam/scsi/scsi_cd.c +++ sys/cam/scsi/scsi_cd.c @@ -76,6 +76,7 @@ #include #include #include +#include #include #include @@ -1752,6 +1753,18 @@ } } +static int +cdioctl_dev(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) +{ + struct disk *dp; + /* + * For compat, we need to cast struct disk * into struct cdev *dev and + * then back + */ + dp = (struct disk *)(void *)dev; + return (cdioctl(dp, cmd, (void *)addr, flag, td)); +} + static int cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td) { @@ -2608,6 +2621,16 @@ default: cam_periph_lock(periph); error = cam_periph_ioctl(periph, cmd, addr, cderror); + if (error == ENOTTY) { + /* + * We need to fixup the call, maybe, so try again. This + * assumes that the the first arg is passed through w/o + * any interpretation by the cam_compat.c layer, which + * it currently is... + */ + error = cam_compat_ioctl((struct cdev *)(void *)dp, cmd, + addr, flag, td, cdioctl_dev); + } cam_periph_unlock(periph); break; }