aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/cam/scsi/scsi_cd.c14
-rw-r--r--sys/compat/linux/linux_ioctl.c27
-rw-r--r--sys/dev/ata/atapi-cd.c13
-rw-r--r--sys/dev/mcd/mcd.c14
-rw-r--r--sys/dev/scd/scd.c16
-rw-r--r--sys/sys/cdio.h7
6 files changed, 63 insertions, 28 deletions
diff --git a/sys/cam/scsi/scsi_cd.c b/sys/cam/scsi/scsi_cd.c
index 012e3a27a5b2..11a64a752e1b 100644
--- a/sys/cam/scsi/scsi_cd.c
+++ b/sys/cam/scsi/scsi_cd.c
@@ -1909,7 +1909,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
struct cam_periph *periph;
struct cd_softc *softc;
- int error;
+ int error, nocopyout;
periph = (struct cam_periph *)dp->d_drv1;
if (periph == NULL)
@@ -1940,6 +1940,7 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
}
}
+ nocopyout = 0;
switch (cmd) {
case CDIOCPLAYTRACKS:
@@ -2098,6 +2099,9 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
error = cdplay(periph, args->blk, args->len);
}
break;
+ case CDIOCREADSUBCHANNEL_SYSSPACE:
+ nocopyout = 1;
+ /* Fallthrough */
case CDIOCREADSUBCHANNEL:
{
struct ioc_read_subchannel *args
@@ -2138,8 +2142,12 @@ cdioctl(struct disk *dp, u_long cmd, void *addr, int flag, struct thread *td)
len = min(len, ((data->header.data_len[0] << 8) +
data->header.data_len[1] +
sizeof(struct cd_sub_channel_header)));
- if (copyout(data, args->data, len) != 0) {
- error = EFAULT;
+ if (nocopyout == 0) {
+ if (copyout(data, args->data, len) != 0) {
+ error = EFAULT;
+ }
+ } else {
+ bcopy(data, args->data, len);
}
free(data, M_TEMP);
}
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index beb9e0c0aea6..20a2aa92f1b5 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -1490,30 +1490,29 @@ linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
case LINUX_CDROMSUBCHNL: {
struct linux_cdrom_subchnl sc;
struct ioc_read_subchannel bsdsc;
- struct cd_sub_channel_info *bsdinfo;
- caddr_t sg = stackgap_init();
- bsdinfo = stackgap_alloc(&sg, sizeof(*bsdinfo));
+ struct cd_sub_channel_info bsdinfo;
+
bsdsc.address_format = CD_LBA_FORMAT;
bsdsc.data_format = CD_CURRENT_POSITION;
bsdsc.track = 0;
- bsdsc.data_len = sizeof(*bsdinfo);
- bsdsc.data = bsdinfo;
- error = fo_ioctl(fp, CDIOCREADSUBCHANNEL, (caddr_t)&bsdsc,
- td->td_ucred, td);
+ bsdsc.data_len = sizeof(bsdinfo);
+ bsdsc.data = &bsdinfo;
+ error = fo_ioctl(fp, CDIOCREADSUBCHANNEL_SYSSPACE,
+ (caddr_t)&bsdsc, td->td_ucred, td);
if (error)
break;
error = copyin((void *)args->arg, &sc, sizeof(sc));
if (error)
break;
- sc.cdsc_audiostatus = bsdinfo->header.audio_status;
- sc.cdsc_adr = bsdinfo->what.position.addr_type;
- sc.cdsc_ctrl = bsdinfo->what.position.control;
- sc.cdsc_trk = bsdinfo->what.position.track_number;
- sc.cdsc_ind = bsdinfo->what.position.index_number;
+ sc.cdsc_audiostatus = bsdinfo.header.audio_status;
+ sc.cdsc_adr = bsdinfo.what.position.addr_type;
+ sc.cdsc_ctrl = bsdinfo.what.position.control;
+ sc.cdsc_trk = bsdinfo.what.position.track_number;
+ sc.cdsc_ind = bsdinfo.what.position.index_number;
set_linux_cdrom_addr(&sc.cdsc_absaddr, sc.cdsc_format,
- bsdinfo->what.position.absaddr.lba);
+ bsdinfo.what.position.absaddr.lba);
set_linux_cdrom_addr(&sc.cdsc_reladdr, sc.cdsc_format,
- bsdinfo->what.position.reladdr.lba);
+ bsdinfo.what.position.reladdr.lba);
error = copyout(&sc, (void *)args->arg, sizeof(sc));
break;
}
diff --git a/sys/dev/ata/atapi-cd.c b/sys/dev/ata/atapi-cd.c
index 9b86948c4ffc..4a7df8083459 100644
--- a/sys/dev/ata/atapi-cd.c
+++ b/sys/dev/ata/atapi-cd.c
@@ -553,7 +553,7 @@ static int
acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct thread *td)
{
struct acd_softc *cdp = pp->geom->softc;
- int error = 0;
+ int error = 0, nocopyout;
if (!cdp)
return ENXIO;
@@ -574,6 +574,7 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
cdp->flags |= F_LOCKED;
break;
}
+ nocopyout = 0;
switch (cmd) {
case CDIOCRESUME:
@@ -738,6 +739,9 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
}
break;
+ case CDIOCREADSUBCHANNEL_SYSSPACE:
+ nocopyout = 1;
+ /* Fallthrough */
case CDIOCREADSUBCHANNEL:
{
struct ioc_read_subchannel *args =
@@ -782,7 +786,12 @@ acd_geom_ioctl(struct g_provider *pp, u_long cmd, void *addr, int fflag, struct
break;
}
}
- error = copyout(&cdp->subchan, args->data, args->data_len);
+ if (nocopyout == 0) {
+ error = copyout(&cdp->subchan, args->data, args->data_len);
+ } else {
+ error = 0;
+ bcopy(&cdp->subchan, args->data, args->data_len);
+ }
}
break;
diff --git a/sys/dev/mcd/mcd.c b/sys/dev/mcd/mcd.c
index db351909c652..e9cc575ecf2a 100644
--- a/sys/dev/mcd/mcd.c
+++ b/sys/dev/mcd/mcd.c
@@ -135,7 +135,8 @@ static void mcd_soft_reset(struct mcd_softc *);
static int mcd_hard_reset(struct mcd_softc *);
static int mcd_setmode(struct mcd_softc *, int mode);
static int mcd_getqchan(struct mcd_softc *, struct mcd_qchninfo *q);
-static int mcd_subchan(struct mcd_softc *, struct ioc_read_subchannel *sc);
+static int mcd_subchan(struct mcd_softc *, struct ioc_read_subchannel *sc,
+ int nocopyout);
static int mcd_toc_header(struct mcd_softc *, struct ioc_toc_header *th);
static int mcd_read_toc(struct mcd_softc *);
static int mcd_toc_entrys(struct mcd_softc *, struct ioc_read_toc_entry *te);
@@ -440,8 +441,10 @@ MCD_TRACE("ioctl called 0x%lx\n", cmd);
return mcd_playblocks(sc, (struct ioc_play_blocks *) addr);
case CDIOCPLAYMSF:
return mcd_playmsf(sc, (struct ioc_play_msf *) addr);
+ case CDIOCREADSUBCHANNEL_SYSSPACE:
+ return mcd_subchan(sc, (struct ioc_read_subchannel *) addr, 1);
case CDIOCREADSUBCHANNEL:
- return mcd_subchan(sc, (struct ioc_read_subchannel *) addr);
+ return mcd_subchan(sc, (struct ioc_read_subchannel *) addr, 0);
case CDIOREADTOCHEADER:
return mcd_toc_header(sc, (struct ioc_toc_header *) addr);
case CDIOREADTOCENTRYS:
@@ -1357,7 +1360,7 @@ mcd_getqchan(struct mcd_softc *sc, struct mcd_qchninfo *q)
}
static int
-mcd_subchan(struct mcd_softc *sc, struct ioc_read_subchannel *sch)
+mcd_subchan(struct mcd_softc *sc, struct ioc_read_subchannel *sch, int nocopyout)
{
struct mcd_qchninfo q;
struct cd_sub_channel_info data;
@@ -1423,7 +1426,10 @@ mcd_subchan(struct mcd_softc *sc, struct ioc_read_subchannel *sch)
break;
}
- return copyout(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len));
+ if (nocopyout == 0)
+ return copyout(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len));
+ bcopy(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len));
+ return (0)
}
static int
diff --git a/sys/dev/scd/scd.c b/sys/dev/scd/scd.c
index 1b00e02d2ae2..2c5f7966f506 100644
--- a/sys/dev/scd/scd.c
+++ b/sys/dev/scd/scd.c
@@ -131,7 +131,7 @@ static int scd_resume(struct scd_softc *);
static int scd_playtracks(struct scd_softc *, struct ioc_play_track *pt);
static int scd_playmsf(struct scd_softc *, struct ioc_play_msf *msf);
static int scd_play(struct scd_softc *, struct ioc_play_msf *msf);
-static int scd_subchan(struct scd_softc *, struct ioc_read_subchannel *sch);
+static int scd_subchan(struct scd_softc *, struct ioc_read_subchannel *sch, int nocopyout);
static int read_subcode(struct scd_softc *, struct sony_subchannel_position_data *sch);
/* for xcdplayer */
@@ -350,8 +350,10 @@ scdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *t
return (EINVAL);
case CDIOCPLAYMSF:
return scd_playmsf(sc, (struct ioc_play_msf *) addr);
+ case CDIOCREADSUBCHANNEL_SYSSPACE:
+ return scd_subchan(sc, (struct ioc_read_subchannel *) addr, 1);
case CDIOCREADSUBCHANNEL:
- return scd_subchan(sc, (struct ioc_read_subchannel *) addr);
+ return scd_subchan(sc, (struct ioc_read_subchannel *) addr, 0);
case CDIOREADTOCHEADER:
return scd_toc_header (sc, (struct ioc_toc_header *) addr);
case CDIOREADTOCENTRYS:
@@ -544,7 +546,7 @@ scd_eject(struct scd_softc *sc)
}
static int
-scd_subchan(struct scd_softc *sc, struct ioc_read_subchannel *sch)
+scd_subchan(struct scd_softc *sc, struct ioc_read_subchannel *sch, int nocopyout)
{
struct sony_subchannel_position_data q;
struct cd_sub_channel_info data;
@@ -573,8 +575,12 @@ scd_subchan(struct scd_softc *sc, struct ioc_read_subchannel *sch)
data.what.position.absaddr.msf.second = bcd2bin(q.abs_msf[1]);
data.what.position.absaddr.msf.frame = bcd2bin(q.abs_msf[2]);
- if (copyout(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len))!=0)
- return (EFAULT);
+ if (nocopyout == 0) {
+ if (copyout(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len))!=0)
+ return (EFAULT);
+ } else {
+ bcopy(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len));
+ }
return (0);
}
diff --git a/sys/sys/cdio.h b/sys/sys/cdio.h
index a3eb271a7514..3614d19ee0d2 100644
--- a/sys/sys/cdio.h
+++ b/sys/sys/cdio.h
@@ -274,4 +274,11 @@ struct ioc_capability { /*<2>*/
#define CDIOCCAPABILITY _IOR('c',30,struct ioc_capability) /*<2>*/
+/*
+ * Special version of CDIOCREADSUBCHANNEL which assumes that
+ * ioc_read_subchannel->data points to the kernel memory. For
+ * use in compatibility layers.
+ */
+#define CDIOCREADSUBCHANNEL_SYSSPACE _IOWR('c', 31, struct ioc_read_subchannel)
+
#endif /* !_SYS_CDIO_H_ */