Subject: port-i386/4794: Linux emulation doesn't support CD Audio
To: None <gnats-bugs@gnats.netbsd.org>
From: Urban Boquist <boquist@cs.chalmers.se>
List: netbsd-bugs
Date: 01/08/1998 23:43:39
>Number: 4794
>Category: port-i386
>Synopsis: Linux cdrom ioctls are all missing
>Confidential: no
>Severity: non-critical
>Priority: high
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Jan 8 14:50:01 1998
>Last-Modified:
>Originator: Urban Boquist
>Organization:
Dept. of CS, Chalmers, Sweden
>Release: NetBSD-1.3
>Environment:
System: NetBSD beavis 1.3 NetBSD 1.3 (BEAVIS) #0: Tue Dec 30 21:55:43 CET 1997 root@beavis:/usr/src/sys/arch/i386/compile/BEAVIS i386
>Description:
Linux programs that try to use CD Audio ioctls don't work.
>How-To-Repeat:
Try to play Linux Quake with the CD in the drive.
>Fix:
Apply the patches below (essentially 2 new files in sys/compat/linux).
With these applied Quake CD music works for me.
diff -u -N -r src/sys/compat/linux/files.linux src2/sys/compat/linux/files.linux
--- src/sys/compat/linux/files.linux Mon Jul 21 13:20:45 1997
+++ src2/sys/compat/linux/files.linux Tue Nov 4 19:30:17 1997
@@ -6,6 +6,7 @@
# ports should define any machine-specific files they need in their
# own file lists.
+file compat/linux/linux_cdrom.c compat_linux
file compat/linux/linux_error.c compat_linux
file compat/linux/linux_exec.c compat_linux
file compat/linux/linux_file.c compat_linux
diff -u -N -r src/sys/compat/linux/linux_cdrom.c src2/sys/compat/linux/linux_cdrom.c
--- src/sys/compat/linux/linux_cdrom.c Thu Jan 1 01:00:00 1970
+++ src2/sys/compat/linux/linux_cdrom.c Sun Dec 28 15:53:18 1997
@@ -0,0 +1,337 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/ioctl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/mount.h>
+#include <sys/proc.h>
+#include <sys/cdio.h>
+
+#include <compat/linux/linux_types.h>
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_signal.h>
+#include <compat/linux/linux_syscallargs.h>
+#include <compat/linux/linux_util.h>
+#include <compat/linux/linux_cdrom.h>
+
+#if 0
+#define DPRINTF(x) printf x
+#else
+#define DPRINTF(x)
+#endif
+
+int
+linux_ioctl_cdrom(p, uap, retval)
+ struct proc *p;
+ struct linux_sys_ioctl_args /* {
+ syscallarg(int) fd;
+ syscallarg(u_long) com;
+ syscallarg(caddr_t) data;
+ } */ *uap;
+ register_t *retval;
+{
+ int error, idata;
+ u_long com, ncom;
+ caddr_t sg;
+ struct file *fp;
+ struct filedesc *fdp;
+ int (*ioctlf) __P((struct file *, u_long, caddr_t, struct proc *));
+
+ struct linux_cdrom_blk l_blk;
+ struct linux_cdrom_msf l_msf;
+ struct linux_cdrom_ti l_ti;
+ struct linux_cdrom_tochdr l_tochdr;
+ struct linux_cdrom_tocentry l_tocentry;
+ struct linux_cdrom_subchnl l_subchnl;
+ struct linux_cdrom_volctrl l_volctrl;
+
+ struct ioc_play_blocks t_blocks;
+ struct ioc_play_msf t_msf;
+ struct ioc_play_track t_track;
+ struct ioc_toc_header t_header;
+ struct cd_toc_entry *entry, t_entry;
+ struct ioc_read_toc_entry t_toc_entry;
+ struct cd_sub_channel_info *info, t_info;
+ struct ioc_read_subchannel t_subchannel;
+ struct ioc_vol t_vol;
+
+ fdp = p->p_fd;
+ if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
+ (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL)
+ return (EBADF);
+
+ com = SCARG(uap, com);
+ ioctlf = fp->f_ops->fo_ioctl;
+ retval[0] = 0;
+
+ switch(com) {
+ case LINUX_CDROMPLAYMSF:
+ error = copyin(SCARG(uap, data), &l_msf, sizeof l_msf);
+ if (error)
+ return error;
+
+ t_msf.start_m = l_msf.cdmsf_min0;
+ t_msf.start_s = l_msf.cdmsf_sec0;
+ t_msf.start_f = l_msf.cdmsf_frame0;
+ t_msf.end_m = l_msf.cdmsf_min1;
+ t_msf.end_s = l_msf.cdmsf_sec1;
+ t_msf.end_f = l_msf.cdmsf_frame1;
+
+ return ioctlf(fp, CDIOCPLAYMSF, (caddr_t)&t_msf, p);
+
+ case LINUX_CDROMPLAYTRKIND:
+ error = copyin(SCARG(uap, data), &l_ti, sizeof l_ti);
+ if (error)
+ return error;
+
+ t_track.start_track = l_ti.cdti_trk0;
+ t_track.start_index = l_ti.cdti_ind0;
+ t_track.end_track = l_ti.cdti_trk1;
+ t_track.end_index = l_ti.cdti_ind1;
+
+ return ioctlf(fp, CDIOCPLAYTRACKS, (caddr_t)&t_track, p);
+
+ case LINUX_CDROMREADTOCHDR:
+ error = ioctlf(fp, CDIOREADTOCHEADER, (caddr_t)&t_header, p);
+ if (error)
+ return error;
+
+ l_tochdr.cdth_trk0 = t_header.starting_track;
+ l_tochdr.cdth_trk1 = t_header.ending_track;
+
+ return copyout(&l_tochdr, SCARG(uap, data), sizeof l_tochdr);
+
+ case LINUX_CDROMREADTOCENTRY:
+ error = copyin(SCARG(uap, data), &l_tocentry,
+ sizeof l_tocentry);
+ if (error)
+ return error;
+
+ sg = stackgap_init(p->p_emul);
+ entry = stackgap_alloc(&sg, sizeof *entry);
+ t_toc_entry.address_format = l_tocentry.cdte_format;
+ t_toc_entry.starting_track = l_tocentry.cdte_track;
+ t_toc_entry.data_len = sizeof *entry;
+ t_toc_entry.data = entry;
+
+ error = ioctlf(fp, CDIOREADTOCENTRYS, (caddr_t)&t_toc_entry,
+ p);
+ if (error)
+ return error;
+
+ error = copyin(entry, &t_entry, sizeof t_entry);
+ if (error)
+ return error;
+
+ l_tocentry.cdte_adr = t_entry.addr_type;
+ l_tocentry.cdte_ctrl = t_entry.control;
+ switch (t_toc_entry.address_format) {
+ case CD_LBA_FORMAT:
+ l_tocentry.cdte_addr.lba = t_entry.addr.lba;
+ break;
+ case CD_MSF_FORMAT:
+ l_tocentry.cdte_addr.msf.minute =
+ t_entry.addr.msf.minute;
+ l_tocentry.cdte_addr.msf.second =
+ t_entry.addr.msf.second;
+ l_tocentry.cdte_addr.msf.frame =
+ t_entry.addr.msf.frame;
+ break;
+ default:
+ printf("linux_ioctl: unknown format msf/lba\n");
+ return EINVAL;
+ }
+
+ return copyout(&l_tocentry, SCARG(uap, data),
+ sizeof l_tocentry);
+
+ case LINUX_CDROMVOLCTRL:
+ error = copyin(SCARG(uap, data), &l_volctrl, sizeof l_volctrl);
+ if (error)
+ return error;
+
+ t_vol.vol[0] = l_volctrl.channel0;
+ t_vol.vol[1] = l_volctrl.channel1;
+ t_vol.vol[2] = l_volctrl.channel2;
+ t_vol.vol[3] = l_volctrl.channel3;
+
+ return ioctlf(fp, CDIOCSETVOL, (caddr_t)&t_vol, p);
+
+ case LINUX_CDROMVOLREAD:
+ error = ioctlf(fp, CDIOCGETVOL, (caddr_t)&t_vol, p);
+ if (error)
+ return error;
+
+ l_volctrl.channel0 = t_vol.vol[0];
+ l_volctrl.channel1 = t_vol.vol[1];
+ l_volctrl.channel2 = t_vol.vol[2];
+ l_volctrl.channel3 = t_vol.vol[3];
+
+ return copyout(&l_volctrl, SCARG(uap, data), sizeof l_volctrl);
+
+ case LINUX_CDROMSUBCHNL:
+ error = copyin(SCARG(uap, data), &l_subchnl, sizeof l_subchnl);
+ if (error)
+ return error;
+
+ sg = stackgap_init(p->p_emul);
+ info = stackgap_alloc(&sg, sizeof *info);
+ t_subchannel.address_format = l_subchnl.cdsc_format;
+ t_subchannel.data_format = CD_CURRENT_POSITION;
+ t_subchannel.track = l_subchnl.cdsc_trk;
+ t_subchannel.data_len = sizeof *info;
+ t_subchannel.data = info;
+ DPRINTF(("linux_ioctl: CDROMSUBCHNL %d %d\n",
+ l_subchnl.cdsc_format, l_subchnl.cdsc_trk));
+
+ error = ioctlf(fp, CDIOCREADSUBCHANNEL, (caddr_t)&t_subchannel,
+ p);
+ if (error)
+ return error;
+
+ error = copyin(info, &t_info, sizeof t_info);
+ if (error)
+ return error;
+
+ l_subchnl.cdsc_audiostatus = t_info.header.audio_status;
+ l_subchnl.cdsc_adr = t_info.what.position.addr_type;
+ l_subchnl.cdsc_ctrl = t_info.what.position.control;
+ l_subchnl.cdsc_ind = t_info.what.position.index_number;
+
+ DPRINTF(("linux_ioctl: CDIOCREADSUBCHANNEL %d %d %d\n",
+ t_info.header.audio_status,
+ t_info.header.data_len[0],
+ t_info.header.data_len[1]));
+ DPRINTF(("(more) %d %d %d %d %d\n",
+ t_info.what.position.data_format,
+ t_info.what.position.control,
+ t_info.what.position.addr_type,
+ t_info.what.position.track_number,
+ t_info.what.position.index_number));
+
+ switch (t_subchannel.address_format) {
+ case CD_LBA_FORMAT:
+ l_subchnl.cdsc_absaddr.lba =
+ t_info.what.position.absaddr.lba;
+ l_subchnl.cdsc_reladdr.lba =
+ t_info.what.position.reladdr.lba;
+ DPRINTF(("LBA: %d %d\n",
+ t_info.what.position.absaddr.lba,
+ t_info.what.position.reladdr.lba));
+ break;
+
+ case CD_MSF_FORMAT:
+ l_subchnl.cdsc_absaddr.msf.minute =
+ t_info.what.position.absaddr.msf.minute;
+ l_subchnl.cdsc_absaddr.msf.second =
+ t_info.what.position.absaddr.msf.second;
+ l_subchnl.cdsc_absaddr.msf.frame =
+ t_info.what.position.absaddr.msf.frame;
+
+ l_subchnl.cdsc_reladdr.msf.minute =
+ t_info.what.position.reladdr.msf.minute;
+ l_subchnl.cdsc_reladdr.msf.second =
+ t_info.what.position.reladdr.msf.second;
+ l_subchnl.cdsc_reladdr.msf.frame =
+ t_info.what.position.reladdr.msf.frame;
+ DPRINTF(("MSF: %d %d %d %d\n",
+ t_info.what.position.absaddr.msf.minute,
+ t_info.what.position.absaddr.msf.second,
+ t_info.what.position.reladdr.msf.minute,
+ t_info.what.position.reladdr.msf.second));
+ break;
+
+ default:
+ printf("linux_ioctl: unknown format msf/lba\n");
+ return EINVAL;
+ }
+
+ return copyout(&l_subchnl, SCARG(uap, data), sizeof l_subchnl);
+
+ case LINUX_CDROMPLAYBLK:
+ error = copyin(SCARG(uap, data), &l_blk, sizeof l_blk);
+ if (error)
+ return error;
+
+ t_blocks.blk = l_blk.from;
+ t_blocks.len = l_blk.len;
+
+ return ioctlf(fp, CDIOCPLAYBLOCKS, (caddr_t)&t_blocks, p);
+
+ case LINUX_CDROMEJECT_SW:
+ error = copyin(SCARG(uap, data), &idata, sizeof idata);
+ if (error)
+ return error;
+
+ if (idata == 1)
+ ncom = CDIOCALLOW;
+ else
+ ncom = CDIOCPREVENT;
+ break;
+
+ case LINUX_CDROMPAUSE:
+ ncom = CDIOCPAUSE;
+ break;
+
+ case LINUX_CDROMRESUME:
+ ncom = CDIOCRESUME;
+ break;
+
+ case LINUX_CDROMSTOP:
+ ncom = CDIOCSTOP;
+ break;
+
+ case LINUX_CDROMSTART:
+ ncom = CDIOCSTART;
+ break;
+
+ case LINUX_CDROMEJECT:
+ ncom = CDIOCEJECT;
+ break;
+
+ case LINUX_CDROMRESET:
+ ncom = CDIOCRESET;
+ break;
+
+ default:
+ printf("linux_ioctl: unimplemented ioctl %08lx\n", com);
+ return EINVAL;
+ }
+
+ return ioctlf(fp, ncom, NULL, p);
+}
diff -u -N -r src/sys/compat/linux/linux_cdrom.h src2/sys/compat/linux/linux_cdrom.h
--- src/sys/compat/linux/linux_cdrom.h Thu Jan 1 01:00:00 1970
+++ src2/sys/compat/linux/linux_cdrom.h Fri Nov 7 00:16:39 1997
@@ -0,0 +1,114 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define LINUX_CDROMPAUSE 0x5301
+#define LINUX_CDROMRESUME 0x5302
+#define LINUX_CDROMPLAYMSF 0x5303 /* (struct linux_cdrom_msf) */
+#define LINUX_CDROMPLAYTRKIND 0x5304 /* (struct linux_cdrom_ti) */
+#define LINUX_CDROMREADTOCHDR 0x5305 /* (struct linux_cdrom_tochdr) */
+#define LINUX_CDROMREADTOCENTRY 0x5306 /* (struct linux_cdrom_tocentry) */
+#define LINUX_CDROMSTOP 0x5307
+#define LINUX_CDROMSTART 0x5308
+#define LINUX_CDROMEJECT 0x5309
+#define LINUX_CDROMVOLCTRL 0x530a /* (struct linux_cdrom_volctrl) */
+#define LINUX_CDROMSUBCHNL 0x530b /* (struct linux_cdrom_subchnl) */
+#define LINUX_CDROMEJECT_SW 0x530f /* arg: 0 or 1 */
+#define LINUX_CDROMRESET 0x5312
+#define LINUX_CDROMVOLREAD 0x5313 /* (struct linux_cdrom_volctrl) */
+#define LINUX_CDROMPLAYBLK 0x5317 /* (struct linux_cdrom_blk) */
+
+struct linux_cdrom_blk {
+ unsigned from;
+ unsigned short len;
+};
+
+struct linux_cdrom_msf {
+ u_char cdmsf_min0; /* start minute */
+ u_char cdmsf_sec0; /* start second */
+ u_char cdmsf_frame0; /* start frame */
+ u_char cdmsf_min1; /* end minute */
+ u_char cdmsf_sec1; /* end second */
+ u_char cdmsf_frame1; /* end frame */
+};
+
+struct linux_cdrom_ti {
+ u_char cdti_trk0; /* start track */
+ u_char cdti_ind0; /* start index */
+ u_char cdti_trk1; /* end track */
+ u_char cdti_ind1; /* end index */
+};
+
+struct linux_cdrom_tochdr {
+ u_char cdth_trk0; /* start track */
+ u_char cdth_trk1; /* end track */
+};
+
+struct linux_cdrom_msf0 {
+ u_char minute;
+ u_char second;
+ u_char frame;
+};
+
+union linux_cdrom_addr {
+ struct linux_cdrom_msf0 msf;
+ int lba;
+};
+
+struct linux_cdrom_tocentry {
+ u_char cdte_track;
+ u_char cdte_adr :4;
+ u_char cdte_ctrl :4;
+ u_char cdte_format;
+ union linux_cdrom_addr cdte_addr;
+ u_char cdte_datamode;
+};
+
+struct linux_cdrom_subchnl {
+ u_char cdsc_format;
+ u_char cdsc_audiostatus;
+ u_char cdsc_adr: 4;
+ u_char cdsc_ctrl: 4;
+ u_char cdsc_trk;
+ u_char cdsc_ind;
+ union linux_cdrom_addr cdsc_absaddr;
+ union linux_cdrom_addr cdsc_reladdr;
+};
+
+struct linux_cdrom_volctrl {
+ u_char channel0;
+ u_char channel1;
+ u_char channel2;
+ u_char channel3;
+};
diff -u -N -r src/sys/compat/linux/linux_ioctl.c src2/sys/compat/linux/linux_ioctl.c
--- src/sys/compat/linux/linux_ioctl.c Sat Apr 5 15:02:31 1997
+++ src2/sys/compat/linux/linux_ioctl.c Tue Nov 4 19:44:10 1997
@@ -77,6 +77,8 @@
return oss_ioctl_sequencer(p, LINUX_TO_OSS(v), retval);
case 'P':
return oss_ioctl_audio(p, LINUX_TO_OSS(v), retval);
+ case 'S':
+ return linux_ioctl_cdrom(p, uap, retval);
case 'T':
return linux_ioctl_termios(p, uap, retval);
case 0x89:
diff -u -N -r src/sys/compat/linux/linux_ioctl.h src2/sys/compat/linux/linux_ioctl.h
--- src/sys/compat/linux/linux_ioctl.h Sat Apr 5 15:02:31 1997
+++ src2/sys/compat/linux/linux_ioctl.h Tue Nov 4 19:44:51 1997
@@ -36,6 +36,8 @@
struct linux_sys_ioctl_args;
int linux_machdepioctl __P((struct proc *, void *, register_t *));
+int linux_ioctl_cdrom __P((struct proc *, struct linux_sys_ioctl_args *,
+ register_t *));
int linux_ioctl_termios __P((struct proc *, struct linux_sys_ioctl_args *,
register_t *));
int linux_ioctl_socket __P((struct proc *, struct linux_sys_ioctl_args *,
>Audit-Trail:
>Unformatted: