This mega-commit brings the following:

. It makes cd9660 root f/s working again.
. It makes CD9660 a new-style option.
. It adds support to mount an ISO9660 multi-session CD-ROM as the root
  filesystem (the last session actually, but that's what is expected
  behaviour).

Sigh.  The CDIOREADTOCENTRYS did a copyout() of its own, and thus has
been unusable for me for this work.  Too bad it didn't simply stuff
the max 100 entries into the struct ioc_read_toc_entry, but relied on
a user supplied data buffer instead. :-(  I now had to reinvent the
wheel, and created a CDIOREADTOCENTRY ioctl command that can be used
in a kernel context.

While doing this, i noticed the following bogosities in existing CD-ROM
drivers:

wcd:	This driver is likely to be totally bogus when someone tries
	two succeeding CDIOREADTOCENTRYS (or now CDIOREADTOCENTRY)
	commands with requesting MSF format, since it apparently
	operates on an internal table.

scd:	This driver apparently returns just a single TOC entry only for
	the CDIOREADTOCENTRYS command.

I have only been able to test the CDIOREADTOCENTRY command with the
cd(4) driver.  I hereby request the respective maintainers of the
other CD-ROM drivers to verify my code for their driver.  When it
comes to merging this CD-ROM multisession stuff into RELENG_2_2 i will
only consider drivers where i've got a confirmation that it actually
works.
This commit is contained in:
Joerg Wunsch 1997-05-04 15:24:23 +00:00
parent 8189ded32e
commit 5a9714de76
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=25460
18 changed files with 621 additions and 78 deletions

View file

@ -34,7 +34,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
* $Id: autoconf.c,v 1.65 1997/04/26 11:45:02 peter Exp $ * $Id: autoconf.c,v 1.66 1997/04/26 18:57:34 peter Exp $
*/ */
/* /*
@ -46,6 +46,7 @@
* and the drivers are initialized. * and the drivers are initialized.
*/ */
#include "opt_smp.h" #include "opt_smp.h"
#include "opt_cd9660.h"
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -101,9 +102,17 @@ static void setroot __P((void));
#ifdef CD9660 #ifdef CD9660
#include <sys/fcntl.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <machine/clock.h>
#include <isofs/cd9660/iso.h> #include <isofs/cd9660/iso.h>
/* We need to try out all our potential CDROM drives, so we need a table. */ /*
* XXX All this CD-ROM root stuff is fairly messy. Ick.
*
* We need to try out all our potential CDROM drives, so we need a table.
*/
static struct { static struct {
char *name; char *name;
int major; int major;
@ -112,25 +121,44 @@ static struct {
{ "mcd", 7 }, { "mcd", 7 },
{ "scd", 16 }, { "scd", 16 },
{ "matcd", 17 }, { "matcd", 17 },
{ "wcd", 19 },
{ 0, 0} { 0, 0}
}; };
static int find_cdrom_root __P((void *)); static int find_cdrom_root __P((void));
static int static int
find_cdrom_root(dummy) find_cdrom_root()
void *dummy;
{ {
int i,j,k; int i, j, error;
struct bdevsw *bd;
dev_t orootdev;
for (j = 0 ; j < 2; j++) #if CD9660_ROOTDELAY > 0
for (k = 0 ; try_cdrom[k].name ; k++) { DELAY(CD9660_ROOTDELAY * 1000000);
rootdev = makedev(try_cdrom[k].major,j*8); #endif
printf("trying rootdev=0x%lx (%s%d)\n", orootdev = rootdev;
rootdev, try_cdrom[k].name,j); for (i = 0 ; i < 2; i++)
i = (*cd9660_mountroot)(); for (j = 0 ; try_cdrom[j].name ; j++) {
if (!i) return i; if (try_cdrom[j].major >= nblkdev)
continue;
rootdev = makedev(try_cdrom[j].major, i * 8);
bd = bdevsw[major(rootdev)];
if (bd == NULL || bd->d_open == NULL)
continue;
if (bootverbose)
printf("trying %s%d as rootdev (0x%x)\n",
try_cdrom[j].name, i, rootdev);
error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc);
if (error == 0) {
if (bd->d_close != NULL)
(bd->d_close)(rootdev, FREAD, S_IFBLK,
curproc);
return 0;
}
} }
rootdev = orootdev;
return EINVAL; return EINVAL;
} }
#endif /* CD9660 */ #endif /* CD9660 */
@ -233,7 +261,11 @@ configure(dummy)
if ((boothowto & RB_CDROM)) { if ((boothowto & RB_CDROM)) {
if (bootverbose) if (bootverbose)
printf("Considering CD-ROM root f/s.\n"); printf("Considering CD-ROM root f/s.\n");
mountrootfsname = "cd9660"; /* NB: find_cdrom_root() sets rootdev if successful. */
if (find_cdrom_root() == 0)
mountrootfsname = "cd9660";
else if (bootverbose)
printf("No CD-ROM available as root f/s.\n");
} }
#endif #endif

View file

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in # LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can. # as much of the source tree as it can.
# #
# $Id: LINT,v 1.328 1997/04/26 11:44:55 peter Exp $ # $Id: LINT,v 1.329 1997/04/28 00:24:26 fsmp Exp $
# #
# NB: You probably don't want to try running a kernel built from this # NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from # file. Instead, you should start from GENERIC, and add options from
@ -439,6 +439,13 @@ options QUOTA #enable disk quotas
#options UMAPFS_DIAGNOSTIC #options UMAPFS_DIAGNOSTIC
#options UNION_DIAGNOSTIC #options UNION_DIAGNOSTIC
# In particular multi-session CD-Rs might require a huge amount of
# time in order to "settle". If we are about mounting them as the
# root f/s, we gotta wait a little.
#
# The number is supposed to be in seconds.
options "CD9660_ROOTDELAY=20"
# Add some error checking code to the null_bypass routine # Add some error checking code to the null_bypass routine
# in the NULL filesystem # in the NULL filesystem
#options SAFETY #options SAFETY

View file

@ -1,4 +1,4 @@
# $Id$ # $Id: options,v 1.29 1997/02/22 09:28:14 peter Exp $
# Format: # Format:
# Option name filename # Option name filename
@ -29,6 +29,18 @@ PORTAL opt_dontuse.h
PROCFS opt_dontuse.h PROCFS opt_dontuse.h
UMAPFS opt_dontuse.h UMAPFS opt_dontuse.h
# The cd9660 static filesystem has one slightly bogus static dependency
# in sys/i386/i386/autoconf.c. If this filesystem is statically
# compiled into the kernel, code for mounting a CD-ROM root filesystem
# will be enabled. This is purposely unavailable for the LKM-based
# version.
CD9660
# In particular multi-session CD-Rs might require a huge amount of
# time in order to "settle". If we are about mounting them as the
# root f/s, we gotta wait a little.
CD9660_ROOTDELAY opt_cd9660.h
# The union static file system has bogus static dependencies, so it isn't # The union static file system has bogus static dependencies, so it isn't
# hidden yet. # hidden yet.
UNION UNION

View file

@ -40,7 +40,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: mcd.c,v 1.87 1997/03/24 11:23:55 bde Exp $ * $Id: mcd.c,v 1.88 1997/04/20 17:26:54 bde Exp $
*/ */
static const char COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore"; static const char COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore";
@ -195,6 +195,7 @@ static int mcd_subchan(int unit, struct ioc_read_subchannel *sc);
static int mcd_toc_header(int unit, struct ioc_toc_header *th); static int mcd_toc_header(int unit, struct ioc_toc_header *th);
static int mcd_read_toc(int unit); static int mcd_read_toc(int unit);
static int mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te); static int mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te);
static int mcd_toc_entry(int unit, struct ioc_read_toc_single_entry *te);
static int mcd_stop(int unit); static int mcd_stop(int unit);
static int mcd_eject(int unit); static int mcd_eject(int unit);
static int mcd_inject(int unit); static int mcd_inject(int unit);
@ -1426,6 +1427,57 @@ mcd_read_toc(int unit)
return 0; return 0;
} }
static int
mcd_toc_entry(int unit, struct ioc_read_toc_single_entry *te)
{
struct mcd_data *cd = mcd_data + unit;
struct ioc_toc_header th;
int rc, trk;
if (te->address_format != CD_MSF_FORMAT
&& te->address_format != CD_LBA_FORMAT)
return EINVAL;
/* Copy the toc header */
if ((rc = mcd_toc_header(unit, &th)) != 0)
return rc;
/* verify starting track */
trk = te->track;
if (trk == 0)
trk = th.starting_track;
else if (trk == MCD_LASTPLUS1)
trk = th.ending_track + 1;
else if (trk < th.starting_track || trk > th.ending_track + 1)
return EINVAL;
/* Make sure we have a valid toc */
if ((rc=mcd_read_toc(unit)) != 0)
return rc;
/* Copy the TOC data. */
if (cd->toc[trk].idx_no == 0)
return EIO;
te->entry.control = cd->toc[trk].control;
te->entry.addr_type = cd->toc[trk].addr_type;
te->entry.track =
cd->toc[trk].idx_no > 0x99 ? cd->toc[trk].idx_no :
bcd2bin(cd->toc[trk].idx_no);
switch (te->address_format) {
case CD_MSF_FORMAT:
te->entry.addr.msf.unused = 0;
te->entry.addr.msf.minute = bcd2bin(cd->toc[trk].hd_pos_msf[0]);
te->entry.addr.msf.second = bcd2bin(cd->toc[trk].hd_pos_msf[1]);
te->entry.addr.msf.frame = bcd2bin(cd->toc[trk].hd_pos_msf[2]);
break;
case CD_LBA_FORMAT:
te->entry.addr.lba = htonl(msf2hsg(cd->toc[trk].hd_pos_msf, 0));
break;
}
return 0;
}
static int static int
mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te) mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te)
{ {

View file

@ -41,7 +41,7 @@
*/ */
/* $Id: scd.c,v 1.28 1997/03/24 11:24:01 bde Exp $ */ /* $Id: scd.c,v 1.29 1997/04/20 17:26:55 bde Exp $ */
/* Please send any comments to micke@dynas.se */ /* Please send any comments to micke@dynas.se */
@ -180,6 +180,7 @@ static int read_subcode(int unit, struct sony_subchannel_position_data *sc);
/* for xcdplayer */ /* for xcdplayer */
static int scd_toc_header(int unit, struct ioc_toc_header *th); static int scd_toc_header(int unit, struct ioc_toc_header *th);
static int scd_toc_entrys(int unit, struct ioc_read_toc_entry *te); static int scd_toc_entrys(int unit, struct ioc_read_toc_entry *te);
static int scd_toc_entry(int unit, struct ioc_read_toc_single_entry *te);
#define SCD_LASTPLUS1 170 /* don't ask, xcdplayer passes this in */ #define SCD_LASTPLUS1 170 /* don't ask, xcdplayer passes this in */
static int scd_probe(struct isa_device *dev); static int scd_probe(struct isa_device *dev);
@ -456,6 +457,8 @@ scdioctl(dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p)
return scd_toc_header (unit, (struct ioc_toc_header *) addr); return scd_toc_header (unit, (struct ioc_toc_header *) addr);
case CDIOREADTOCENTRYS: case CDIOREADTOCENTRYS:
return scd_toc_entrys (unit, (struct ioc_read_toc_entry*) addr); return scd_toc_entrys (unit, (struct ioc_read_toc_entry*) addr);
case CDIOREADTOCENTRY:
return scd_toc_entry (unit, (struct ioc_read_toc_single_entry*) addr);
case CDIOCSETPATCH: case CDIOCSETPATCH:
case CDIOCGETVOL: case CDIOCGETVOL:
case CDIOCSETVOL: case CDIOCSETVOL:
@ -1517,6 +1520,45 @@ scd_toc_entrys (int unit, struct ioc_read_toc_entry *te)
} }
static int
scd_toc_entry (int unit, struct ioc_read_toc_single_entry *te)
{
struct scd_data *cd = scd_data + unit;
struct cd_toc_entry toc_entry;
int rc, i;
if (!(cd->flags & SCDTOC) && (rc = read_toc(unit)) != 0) {
print_error(unit, rc);
return EIO;
}
/* find the toc to copy*/
i = te->track;
if (i == SCD_LASTPLUS1)
i = cd->last_track + 1;
/* verify starting track */
if (i < cd->first_track || i > cd->last_track+1)
return EINVAL;
/* copy the toc data */
toc_entry.control = cd->toc[i].ctl;
toc_entry.addr_type = te->address_format;
toc_entry.track = i;
if (te->address_format == CD_MSF_FORMAT) {
toc_entry.addr.msf.unused = 0;
toc_entry.addr.msf.minute = bcd2bin(cd->toc[i].start_msf[0]);
toc_entry.addr.msf.second = bcd2bin(cd->toc[i].start_msf[1]);
toc_entry.addr.msf.frame = bcd2bin(cd->toc[i].start_msf[2]);
}
/* copy the data back */
bcopy(&toc_entry, &te->entry, sizeof(struct cd_toc_entry));
return 0;
}
static scd_devsw_installed = 0; static scd_devsw_installed = 0;
static void scd_drvinit(void *unused) static void scd_drvinit(void *unused)

View file

@ -36,7 +36,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95 * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
* $Id: cd9660_vfsops.c,v 1.23 1997/04/29 15:52:53 joerg Exp $ * $Id: cd9660_vfsops.c,v 1.24 1997/04/29 17:11:51 joerg Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -48,6 +48,8 @@
#include <miscfs/specfs/specdev.h> #include <miscfs/specfs/specdev.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/buf.h> #include <sys/buf.h>
#include <sys/cdio.h>
#include <sys/conf.h>
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include <sys/errno.h> #include <sys/errno.h>
#include <sys/malloc.h> #include <sys/malloc.h>
@ -94,40 +96,77 @@ VFS_SET(cd9660_vfsops, cd9660, MOUNT_CD9660, VFCF_READONLY);
* Called by vfs_mountroot when iso is going to be mounted as root. * Called by vfs_mountroot when iso is going to be mounted as root.
*/ */
static int iso_get_ssector __P((dev_t dev, struct proc *p));
static int iso_mountfs __P((struct vnode *devvp, struct mount *mp, static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
struct proc *p, struct iso_args *argp)); struct proc *p, struct iso_args *argp));
static int iso_mountroot __P((struct mount *mp, struct proc *p));
int /*
cd9660_mountroot() * Try to find the start of the last data track on this CD-ROM. This
* is used to mount the last session of a multi-session CD. Bail out
* and return 0 if we fail, this is always a safe bet.
*/
static int
iso_get_ssector(dev, p)
dev_t dev;
struct proc *p;
{ {
struct ioc_toc_header h;
struct ioc_read_toc_single_entry t;
int i;
struct bdevsw *bd;
d_ioctl_t *ioctlp;
bd = bdevsw[major(dev)];
ioctlp = bd->d_ioctl;
if (ioctlp == NULL)
return 0;
if (ioctlp(dev, CDIOREADTOCHEADER, (caddr_t)&h, FREAD, p) == -1)
return 0;
for (i = h.ending_track; i >= 0; i--) {
t.address_format = CD_LBA_FORMAT;
t.track = i;
if (ioctlp(dev, CDIOREADTOCENTRY, (caddr_t)&t, FREAD, p) == -1)
return 0;
if ((t.entry.control & 4) != 0)
/* found a data track */
break;
}
if (i < 0)
return 0;
return ntohl(t.entry.addr.lba);
}
static int
iso_mountroot(mp, p)
struct mount *mp; struct mount *mp;
struct proc *p = curproc; /* XXX */ struct proc *p;
{
struct iso_args args; struct iso_args args;
int error; int error;
/* /*
* Get vnode for rootdev. * Get vnode for rootdev.
*/ */
if ((error = bdevvp(swapdev, &swapdev_vp)) || if ((error = bdevvp(swapdev, &swapdev_vp)) ||
(error = bdevvp(rootdev, &rootvp))) { (error = bdevvp(rootdev, &rootvp))) {
printf("cd9660_mountroot: can't setup bdevvp's"); printf("iso_mountroot: can't setup bdevvp's");
return (error); return (error);
} }
if (error = vfs_rootmountalloc("cd9660", "root_device", &mp))
return (error);
args.flags = ISOFSMNT_ROOT; args.flags = ISOFSMNT_ROOT;
if (error = iso_mountfs(rootvp, mp, p, &args)) { args.ssector = iso_get_ssector(rootdev, p);
mp->mnt_vfc->vfc_refcount--; if (bootverbose)
vfs_unbusy(mp, p); printf("iso_mountroot(): using session at block %d\n",
free(mp, M_MOUNT); args.ssector);
if (error = iso_mountfs(rootvp, mp, p, &args))
return (error); return (error);
}
simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
simple_unlock(&mountlist_slock);
(void)cd9660_statfs(mp, &mp->mnt_stat, p); (void)cd9660_statfs(mp, &mp->mnt_stat, p);
vfs_unbusy(mp, p);
return (0); return (0);
} }
@ -150,6 +189,9 @@ cd9660_mount(mp, path, data, ndp, p)
int error; int error;
struct iso_mnt *imp = 0; struct iso_mnt *imp = 0;
if ((mp->mnt_flag & MNT_ROOTFS) != 0)
return (iso_mountroot(mp, p));
if ((error = copyin(data, (caddr_t)&args, sizeof (struct iso_args)))) if ((error = copyin(data, (caddr_t)&args, sizeof (struct iso_args))))
return (error); return (error);

View file

@ -36,7 +36,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)iso.h 8.6 (Berkeley) 5/10/95 * @(#)iso.h 8.6 (Berkeley) 5/10/95
* $Id$ * $Id: iso.h,v 1.13 1997/02/22 09:38:52 peter Exp $
*/ */
#define ISODCL(from, to) (to - from + 1) #define ISODCL(from, to) (to - from + 1)
@ -215,7 +215,7 @@ int cd9660_init __P((struct vfsconf *));
#define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \ #define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
size_t, struct proc *)))eopnotsupp) size_t, struct proc *)))eopnotsupp)
int cd9660_mountroot __P((void)); int cd9660_mountroot __P((int ssector));
extern vop_t **cd9660_vnodeop_p; extern vop_t **cd9660_vnodeop_p;
extern vop_t **cd9660_specop_p; extern vop_t **cd9660_specop_p;

View file

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in # LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can. # as much of the source tree as it can.
# #
# $Id: LINT,v 1.328 1997/04/26 11:44:55 peter Exp $ # $Id: LINT,v 1.329 1997/04/28 00:24:26 fsmp Exp $
# #
# NB: You probably don't want to try running a kernel built from this # NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from # file. Instead, you should start from GENERIC, and add options from
@ -439,6 +439,13 @@ options QUOTA #enable disk quotas
#options UMAPFS_DIAGNOSTIC #options UMAPFS_DIAGNOSTIC
#options UNION_DIAGNOSTIC #options UNION_DIAGNOSTIC
# In particular multi-session CD-Rs might require a huge amount of
# time in order to "settle". If we are about mounting them as the
# root f/s, we gotta wait a little.
#
# The number is supposed to be in seconds.
options "CD9660_ROOTDELAY=20"
# Add some error checking code to the null_bypass routine # Add some error checking code to the null_bypass routine
# in the NULL filesystem # in the NULL filesystem
#options SAFETY #options SAFETY

View file

@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in # LINT -- config file for checking all the sources, tries to pull in
# as much of the source tree as it can. # as much of the source tree as it can.
# #
# $Id: LINT,v 1.328 1997/04/26 11:44:55 peter Exp $ # $Id: LINT,v 1.329 1997/04/28 00:24:26 fsmp Exp $
# #
# NB: You probably don't want to try running a kernel built from this # NB: You probably don't want to try running a kernel built from this
# file. Instead, you should start from GENERIC, and add options from # file. Instead, you should start from GENERIC, and add options from
@ -439,6 +439,13 @@ options QUOTA #enable disk quotas
#options UMAPFS_DIAGNOSTIC #options UMAPFS_DIAGNOSTIC
#options UNION_DIAGNOSTIC #options UNION_DIAGNOSTIC
# In particular multi-session CD-Rs might require a huge amount of
# time in order to "settle". If we are about mounting them as the
# root f/s, we gotta wait a little.
#
# The number is supposed to be in seconds.
options "CD9660_ROOTDELAY=20"
# Add some error checking code to the null_bypass routine # Add some error checking code to the null_bypass routine
# in the NULL filesystem # in the NULL filesystem
#options SAFETY #options SAFETY

View file

@ -34,7 +34,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91
* $Id: autoconf.c,v 1.65 1997/04/26 11:45:02 peter Exp $ * $Id: autoconf.c,v 1.66 1997/04/26 18:57:34 peter Exp $
*/ */
/* /*
@ -46,6 +46,7 @@
* and the drivers are initialized. * and the drivers are initialized.
*/ */
#include "opt_smp.h" #include "opt_smp.h"
#include "opt_cd9660.h"
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
@ -101,9 +102,17 @@ static void setroot __P((void));
#ifdef CD9660 #ifdef CD9660
#include <sys/fcntl.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <machine/clock.h>
#include <isofs/cd9660/iso.h> #include <isofs/cd9660/iso.h>
/* We need to try out all our potential CDROM drives, so we need a table. */ /*
* XXX All this CD-ROM root stuff is fairly messy. Ick.
*
* We need to try out all our potential CDROM drives, so we need a table.
*/
static struct { static struct {
char *name; char *name;
int major; int major;
@ -112,25 +121,44 @@ static struct {
{ "mcd", 7 }, { "mcd", 7 },
{ "scd", 16 }, { "scd", 16 },
{ "matcd", 17 }, { "matcd", 17 },
{ "wcd", 19 },
{ 0, 0} { 0, 0}
}; };
static int find_cdrom_root __P((void *)); static int find_cdrom_root __P((void));
static int static int
find_cdrom_root(dummy) find_cdrom_root()
void *dummy;
{ {
int i,j,k; int i, j, error;
struct bdevsw *bd;
dev_t orootdev;
for (j = 0 ; j < 2; j++) #if CD9660_ROOTDELAY > 0
for (k = 0 ; try_cdrom[k].name ; k++) { DELAY(CD9660_ROOTDELAY * 1000000);
rootdev = makedev(try_cdrom[k].major,j*8); #endif
printf("trying rootdev=0x%lx (%s%d)\n", orootdev = rootdev;
rootdev, try_cdrom[k].name,j); for (i = 0 ; i < 2; i++)
i = (*cd9660_mountroot)(); for (j = 0 ; try_cdrom[j].name ; j++) {
if (!i) return i; if (try_cdrom[j].major >= nblkdev)
continue;
rootdev = makedev(try_cdrom[j].major, i * 8);
bd = bdevsw[major(rootdev)];
if (bd == NULL || bd->d_open == NULL)
continue;
if (bootverbose)
printf("trying %s%d as rootdev (0x%x)\n",
try_cdrom[j].name, i, rootdev);
error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc);
if (error == 0) {
if (bd->d_close != NULL)
(bd->d_close)(rootdev, FREAD, S_IFBLK,
curproc);
return 0;
}
} }
rootdev = orootdev;
return EINVAL; return EINVAL;
} }
#endif /* CD9660 */ #endif /* CD9660 */
@ -233,7 +261,11 @@ configure(dummy)
if ((boothowto & RB_CDROM)) { if ((boothowto & RB_CDROM)) {
if (bootverbose) if (bootverbose)
printf("Considering CD-ROM root f/s.\n"); printf("Considering CD-ROM root f/s.\n");
mountrootfsname = "cd9660"; /* NB: find_cdrom_root() sets rootdev if successful. */
if (find_cdrom_root() == 0)
mountrootfsname = "cd9660";
else if (bootverbose)
printf("No CD-ROM available as root f/s.\n");
} }
#endif #endif

View file

@ -76,7 +76,7 @@
Dedicated to: My family, my Grandfather, Dedicated to: My family, my Grandfather,
and Max, my Golden Retriever and Max, my Golden Retriever
Thanks to: Jordon Hubbard (jkh) for getting me ramped-up to 2.x system Thanks to: Jordan Hubbard (jkh) for getting me ramped-up to 2.x system
quickly enough to make the 2.1 release. He put up with quickly enough to make the 2.1 release. He put up with
plenty of silly questions and might get the post of plenty of silly questions and might get the post of
ambassador some day. ambassador some day.
@ -337,7 +337,7 @@ static char MATCDVERSION[]="Version 1(26) 18-Oct-95";
static char MATCDCOPYRIGHT[] = "Matsushita CD-ROM driver, Copr. 1994,1995 Frank Durda IV"; static char MATCDCOPYRIGHT[] = "Matsushita CD-ROM driver, Copr. 1994,1995 Frank Durda IV";
/* The proceeding strings may not be changed*/ /* The proceeding strings may not be changed*/
/* $Id: matcd.c,v 1.24 1997/03/24 11:24:22 bde Exp $ */ /* $Id: matcd.c,v 1.25 1997/04/20 18:02:40 bde Exp $ */
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Include declarations Include declarations
@ -572,6 +572,9 @@ static int matcd_toc_header(int ldrive, int cdrive, int controller,
static int matcd_toc_entries(int ldrive, int cdrive, static int matcd_toc_entries(int ldrive, int cdrive,
int controller, int controller,
struct ioc_read_toc_entry *ioc_entry); struct ioc_read_toc_entry *ioc_entry);
static int matcd_toc_entry(int ldrive, int cdrive,
int controller,
struct ioc_read_toc_single_entry *ioc_entry);
static int matcd_read_subq(int ldrive, int cdrive, int controller, static int matcd_read_subq(int ldrive, int cdrive, int controller,
struct ioc_read_subchannel * sqp); struct ioc_read_subchannel * sqp);
static int matcd_igot(struct ioc_capability * sqp); static int matcd_igot(struct ioc_capability * sqp);
@ -1099,6 +1102,10 @@ int matcdioctl(dev_t dev, int command, caddr_t addr,
return(matcd_toc_entries(ldrive, cdrive, controller, return(matcd_toc_entries(ldrive, cdrive, controller,
(struct ioc_read_toc_entry *) addr)); (struct ioc_read_toc_entry *) addr));
case CDIOREADTOCENTRY:
return(matcd_toc_entry(ldrive, cdrive, controller,
(struct ioc_read_toc_single_entry *) addr));
case CDIOCREADSUBCHANNEL: case CDIOCREADSUBCHANNEL:
return(matcd_read_subq(ldrive, cdrive, controller, return(matcd_read_subq(ldrive, cdrive, controller,
(struct ioc_read_subchannel *) addr)); (struct ioc_read_subchannel *) addr));
@ -2502,6 +2509,73 @@ static int matcd_toc_entries(int ldrive, int cdrive, int controller,
} }
/*---------------------------------------------------------------------------
matcd_toc_entriy - Read a single TOC entry
---------------------------------------------------------------------------*/
static int matcd_toc_entry(int ldrive, int cdrive, int controller,
struct ioc_read_toc_single_entry * ioc_entry)
{
struct matcd_data *cd;
struct cd_toc_entry *from;
struct cd_toc_entry *to;
int trk,origtrk,i,z,port;
unsigned char cmd[MAXCMDSIZ];
unsigned char data[5];
cd=&matcd_data[ldrive];
port=cd->iobase;
if ((cd->flags & MATCDLABEL)==0)
return(EIO); /*Refuse after chg error*/
zero_cmd(cmd);
cmd[0]=READTOC;
origtrk=trk=ioc_entry->track;
if (trk == 0xaa)
/* leadout */
trk=cd->volinfo.trk_high-1;
cmd[2]=trk+1;
lockbus(controller, ldrive); /*Request bus*/
matcd_slowcmd(port,ldrive,cdrive,cmd);
i=waitforit(10*TICKRES,DTEN,port,"mats1");
matcd_pread(port, 8, data); /*Read data returned*/
z=get_stat(port,ldrive); /*Read status byte*/
if ((z & MATCD_ST_ERROR)) { /*Something went wrong*/
i=get_error(port, ldrive, cdrive);
unlockbus(controller, ldrive); /*Release bus*/
return(EIO);
}
unlockbus(controller, ldrive); /*Release bus*/
#ifdef DEBUGIOCTL
printf("Track %d addr/ctrl %x m %x s %x f %x\n",data[2],
data[1],data[4],data[5],data[6]);
#endif /*DEBUGIOCTL*/
ioc_entry->entry.control=data[1]; /*Track type*/
ioc_entry->entry.addr_type=ioc_entry->address_format;/*Type*/
ioc_entry->entry.track=data[2]; /*Track #, can be Out of Order*/
if (ioc_entry->address_format == CD_MSF_FORMAT) {
ioc_entry->entry.addr.msf.unused=0;
ioc_entry->entry.addr.msf.minute=data[4]; /*Min*/
ioc_entry->entry.addr.msf.second=data[5]; /*Sec*/
ioc_entry->entry.addr.msf.frame=data[6]; /*Frame*/
}
if (origtrk == 0xaa) {
/* Handle leadout */
ioc_entry->entry.control=data[2]; /*Copy from last valid track*/
ioc_entry->entry.track=0xaa; /*Lead-out*/
ioc_entry->entry.addr.msf.unused=0; /*Fill*/
ioc_entry->entry.addr.msf.minute=cd->volinfo.vol_msf[0];
ioc_entry->entry.addr.msf.second=cd->volinfo.vol_msf[1];
ioc_entry->entry.addr.msf.frame=cd->volinfo.vol_msf[2];
}
return(0);
}
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
matcd_subq - Read the Sub-Q packet - (where are we?) matcd_subq - Read the Sub-Q packet - (where are we?)

View file

@ -40,7 +40,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* $Id: mcd.c,v 1.87 1997/03/24 11:23:55 bde Exp $ * $Id: mcd.c,v 1.88 1997/04/20 17:26:54 bde Exp $
*/ */
static const char COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore"; static const char COPYRIGHT[] = "mcd-driver (C)1993 by H.Veit & B.Moore";
@ -195,6 +195,7 @@ static int mcd_subchan(int unit, struct ioc_read_subchannel *sc);
static int mcd_toc_header(int unit, struct ioc_toc_header *th); static int mcd_toc_header(int unit, struct ioc_toc_header *th);
static int mcd_read_toc(int unit); static int mcd_read_toc(int unit);
static int mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te); static int mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te);
static int mcd_toc_entry(int unit, struct ioc_read_toc_single_entry *te);
static int mcd_stop(int unit); static int mcd_stop(int unit);
static int mcd_eject(int unit); static int mcd_eject(int unit);
static int mcd_inject(int unit); static int mcd_inject(int unit);
@ -1426,6 +1427,57 @@ mcd_read_toc(int unit)
return 0; return 0;
} }
static int
mcd_toc_entry(int unit, struct ioc_read_toc_single_entry *te)
{
struct mcd_data *cd = mcd_data + unit;
struct ioc_toc_header th;
int rc, trk;
if (te->address_format != CD_MSF_FORMAT
&& te->address_format != CD_LBA_FORMAT)
return EINVAL;
/* Copy the toc header */
if ((rc = mcd_toc_header(unit, &th)) != 0)
return rc;
/* verify starting track */
trk = te->track;
if (trk == 0)
trk = th.starting_track;
else if (trk == MCD_LASTPLUS1)
trk = th.ending_track + 1;
else if (trk < th.starting_track || trk > th.ending_track + 1)
return EINVAL;
/* Make sure we have a valid toc */
if ((rc=mcd_read_toc(unit)) != 0)
return rc;
/* Copy the TOC data. */
if (cd->toc[trk].idx_no == 0)
return EIO;
te->entry.control = cd->toc[trk].control;
te->entry.addr_type = cd->toc[trk].addr_type;
te->entry.track =
cd->toc[trk].idx_no > 0x99 ? cd->toc[trk].idx_no :
bcd2bin(cd->toc[trk].idx_no);
switch (te->address_format) {
case CD_MSF_FORMAT:
te->entry.addr.msf.unused = 0;
te->entry.addr.msf.minute = bcd2bin(cd->toc[trk].hd_pos_msf[0]);
te->entry.addr.msf.second = bcd2bin(cd->toc[trk].hd_pos_msf[1]);
te->entry.addr.msf.frame = bcd2bin(cd->toc[trk].hd_pos_msf[2]);
break;
case CD_LBA_FORMAT:
te->entry.addr.lba = htonl(msf2hsg(cd->toc[trk].hd_pos_msf, 0));
break;
}
return 0;
}
static int static int
mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te) mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te)
{ {

View file

@ -41,7 +41,7 @@
*/ */
/* $Id: scd.c,v 1.28 1997/03/24 11:24:01 bde Exp $ */ /* $Id: scd.c,v 1.29 1997/04/20 17:26:55 bde Exp $ */
/* Please send any comments to micke@dynas.se */ /* Please send any comments to micke@dynas.se */
@ -180,6 +180,7 @@ static int read_subcode(int unit, struct sony_subchannel_position_data *sc);
/* for xcdplayer */ /* for xcdplayer */
static int scd_toc_header(int unit, struct ioc_toc_header *th); static int scd_toc_header(int unit, struct ioc_toc_header *th);
static int scd_toc_entrys(int unit, struct ioc_read_toc_entry *te); static int scd_toc_entrys(int unit, struct ioc_read_toc_entry *te);
static int scd_toc_entry(int unit, struct ioc_read_toc_single_entry *te);
#define SCD_LASTPLUS1 170 /* don't ask, xcdplayer passes this in */ #define SCD_LASTPLUS1 170 /* don't ask, xcdplayer passes this in */
static int scd_probe(struct isa_device *dev); static int scd_probe(struct isa_device *dev);
@ -456,6 +457,8 @@ scdioctl(dev_t dev, int cmd, caddr_t addr, int flags, struct proc *p)
return scd_toc_header (unit, (struct ioc_toc_header *) addr); return scd_toc_header (unit, (struct ioc_toc_header *) addr);
case CDIOREADTOCENTRYS: case CDIOREADTOCENTRYS:
return scd_toc_entrys (unit, (struct ioc_read_toc_entry*) addr); return scd_toc_entrys (unit, (struct ioc_read_toc_entry*) addr);
case CDIOREADTOCENTRY:
return scd_toc_entry (unit, (struct ioc_read_toc_single_entry*) addr);
case CDIOCSETPATCH: case CDIOCSETPATCH:
case CDIOCGETVOL: case CDIOCGETVOL:
case CDIOCSETVOL: case CDIOCSETVOL:
@ -1517,6 +1520,45 @@ scd_toc_entrys (int unit, struct ioc_read_toc_entry *te)
} }
static int
scd_toc_entry (int unit, struct ioc_read_toc_single_entry *te)
{
struct scd_data *cd = scd_data + unit;
struct cd_toc_entry toc_entry;
int rc, i;
if (!(cd->flags & SCDTOC) && (rc = read_toc(unit)) != 0) {
print_error(unit, rc);
return EIO;
}
/* find the toc to copy*/
i = te->track;
if (i == SCD_LASTPLUS1)
i = cd->last_track + 1;
/* verify starting track */
if (i < cd->first_track || i > cd->last_track+1)
return EINVAL;
/* copy the toc data */
toc_entry.control = cd->toc[i].ctl;
toc_entry.addr_type = te->address_format;
toc_entry.track = i;
if (te->address_format == CD_MSF_FORMAT) {
toc_entry.addr.msf.unused = 0;
toc_entry.addr.msf.minute = bcd2bin(cd->toc[i].start_msf[0]);
toc_entry.addr.msf.second = bcd2bin(cd->toc[i].start_msf[1]);
toc_entry.addr.msf.frame = bcd2bin(cd->toc[i].start_msf[2]);
}
/* copy the data back */
bcopy(&toc_entry, &te->entry, sizeof(struct cd_toc_entry));
return 0;
}
static scd_devsw_installed = 0; static scd_devsw_installed = 0;
static void scd_drvinit(void *unused) static void scd_drvinit(void *unused)

View file

@ -766,6 +766,41 @@ int wcdioctl (dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p)
return copyout (toc->tab + starting_track - return copyout (toc->tab + starting_track -
toc->hdr.starting_track, te->data, len); toc->hdr.starting_track, te->data, len);
} }
case CDIOREADTOCENTRY: {
struct ioc_read_toc_single_entry *te =
(struct ioc_read_toc_single_entry*) addr;
struct toc *toc = &t->toc;
struct toc buf;
u_char track = te->track;
if (! t->toc.hdr.ending_track)
return (EIO);
if (te->address_format != CD_MSF_FORMAT
&& te->address_format != CD_LBA_FORMAT)
return EINVAL;
if (track == 0)
track = toc->hdr.starting_track;
else if (track == 170) /* Handle leadout request */
track = toc->hdr.ending_track + 1;
else if (track < toc->hdr.starting_track ||
track > toc->hdr.ending_track + 1)
return (EINVAL);
/* Convert to MSF format, if needed. */
if (te->address_format == CD_MSF_FORMAT) {
struct cd_toc_entry *e;
buf = t->toc;
toc = &buf;
e = toc->tab + (track - toc->hdr.starting_track);
lba2msf (ntohl(e->addr.lba), &e->addr.msf.minute,
&e->addr.msf.second, &e->addr.msf.frame);
}
bcopy(toc->tab + track - toc->hdr.starting_track,
&te->entry, sizeof(struct cd_toc_entry));
}
case CDIOCREADSUBCHANNEL: { case CDIOCREADSUBCHANNEL: {
struct ioc_read_subchannel *args = struct ioc_read_subchannel *args =
(struct ioc_read_subchannel*) addr; (struct ioc_read_subchannel*) addr;

View file

@ -36,7 +36,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95 * @(#)cd9660_vfsops.c 8.18 (Berkeley) 5/22/95
* $Id: cd9660_vfsops.c,v 1.23 1997/04/29 15:52:53 joerg Exp $ * $Id: cd9660_vfsops.c,v 1.24 1997/04/29 17:11:51 joerg Exp $
*/ */
#include <sys/param.h> #include <sys/param.h>
@ -48,6 +48,8 @@
#include <miscfs/specfs/specdev.h> #include <miscfs/specfs/specdev.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/buf.h> #include <sys/buf.h>
#include <sys/cdio.h>
#include <sys/conf.h>
#include <sys/fcntl.h> #include <sys/fcntl.h>
#include <sys/errno.h> #include <sys/errno.h>
#include <sys/malloc.h> #include <sys/malloc.h>
@ -94,40 +96,77 @@ VFS_SET(cd9660_vfsops, cd9660, MOUNT_CD9660, VFCF_READONLY);
* Called by vfs_mountroot when iso is going to be mounted as root. * Called by vfs_mountroot when iso is going to be mounted as root.
*/ */
static int iso_get_ssector __P((dev_t dev, struct proc *p));
static int iso_mountfs __P((struct vnode *devvp, struct mount *mp, static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
struct proc *p, struct iso_args *argp)); struct proc *p, struct iso_args *argp));
static int iso_mountroot __P((struct mount *mp, struct proc *p));
int /*
cd9660_mountroot() * Try to find the start of the last data track on this CD-ROM. This
* is used to mount the last session of a multi-session CD. Bail out
* and return 0 if we fail, this is always a safe bet.
*/
static int
iso_get_ssector(dev, p)
dev_t dev;
struct proc *p;
{ {
struct ioc_toc_header h;
struct ioc_read_toc_single_entry t;
int i;
struct bdevsw *bd;
d_ioctl_t *ioctlp;
bd = bdevsw[major(dev)];
ioctlp = bd->d_ioctl;
if (ioctlp == NULL)
return 0;
if (ioctlp(dev, CDIOREADTOCHEADER, (caddr_t)&h, FREAD, p) == -1)
return 0;
for (i = h.ending_track; i >= 0; i--) {
t.address_format = CD_LBA_FORMAT;
t.track = i;
if (ioctlp(dev, CDIOREADTOCENTRY, (caddr_t)&t, FREAD, p) == -1)
return 0;
if ((t.entry.control & 4) != 0)
/* found a data track */
break;
}
if (i < 0)
return 0;
return ntohl(t.entry.addr.lba);
}
static int
iso_mountroot(mp, p)
struct mount *mp; struct mount *mp;
struct proc *p = curproc; /* XXX */ struct proc *p;
{
struct iso_args args; struct iso_args args;
int error; int error;
/* /*
* Get vnode for rootdev. * Get vnode for rootdev.
*/ */
if ((error = bdevvp(swapdev, &swapdev_vp)) || if ((error = bdevvp(swapdev, &swapdev_vp)) ||
(error = bdevvp(rootdev, &rootvp))) { (error = bdevvp(rootdev, &rootvp))) {
printf("cd9660_mountroot: can't setup bdevvp's"); printf("iso_mountroot: can't setup bdevvp's");
return (error); return (error);
} }
if (error = vfs_rootmountalloc("cd9660", "root_device", &mp))
return (error);
args.flags = ISOFSMNT_ROOT; args.flags = ISOFSMNT_ROOT;
if (error = iso_mountfs(rootvp, mp, p, &args)) { args.ssector = iso_get_ssector(rootdev, p);
mp->mnt_vfc->vfc_refcount--; if (bootverbose)
vfs_unbusy(mp, p); printf("iso_mountroot(): using session at block %d\n",
free(mp, M_MOUNT); args.ssector);
if (error = iso_mountfs(rootvp, mp, p, &args))
return (error); return (error);
}
simple_lock(&mountlist_slock);
CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
simple_unlock(&mountlist_slock);
(void)cd9660_statfs(mp, &mp->mnt_stat, p); (void)cd9660_statfs(mp, &mp->mnt_stat, p);
vfs_unbusy(mp, p);
return (0); return (0);
} }
@ -150,6 +189,9 @@ cd9660_mount(mp, path, data, ndp, p)
int error; int error;
struct iso_mnt *imp = 0; struct iso_mnt *imp = 0;
if ((mp->mnt_flag & MNT_ROOTFS) != 0)
return (iso_mountroot(mp, p));
if ((error = copyin(data, (caddr_t)&args, sizeof (struct iso_args)))) if ((error = copyin(data, (caddr_t)&args, sizeof (struct iso_args))))
return (error); return (error);

View file

@ -36,7 +36,7 @@
* SUCH DAMAGE. * SUCH DAMAGE.
* *
* @(#)iso.h 8.6 (Berkeley) 5/10/95 * @(#)iso.h 8.6 (Berkeley) 5/10/95
* $Id$ * $Id: iso.h,v 1.13 1997/02/22 09:38:52 peter Exp $
*/ */
#define ISODCL(from, to) (to - from + 1) #define ISODCL(from, to) (to - from + 1)
@ -215,7 +215,7 @@ int cd9660_init __P((struct vfsconf *));
#define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \ #define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
size_t, struct proc *)))eopnotsupp) size_t, struct proc *)))eopnotsupp)
int cd9660_mountroot __P((void)); int cd9660_mountroot __P((int ssector));
extern vop_t **cd9660_vnodeop_p; extern vop_t **cd9660_vnodeop_p;
extern vop_t **cd9660_specop_p; extern vop_t **cd9660_specop_p;

View file

@ -14,7 +14,7 @@
* *
* Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992 * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
* *
* $Id: cd.c,v 1.81 1997/03/24 11:24:54 bde Exp $ * $Id: cd.c,v 1.82 1997/04/02 09:05:38 jmg Exp $
*/ */
#include "opt_bounce.h" #include "opt_bounce.h"
@ -834,6 +834,63 @@ cd_ioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p,
error = copyout(data.entries, te->data, len); error = copyout(data.entries, te->data, len);
} }
break; break;
case CDIOREADTOCENTRY:
{
struct {
struct ioc_toc_header header;
struct cd_toc_entry entry;
} data;
struct ioc_read_toc_single_entry *te =
(struct ioc_read_toc_single_entry *) addr;
struct ioc_toc_header *th;
u_int32_t track;
if (te->address_format != CD_MSF_FORMAT
&& te->address_format != CD_LBA_FORMAT) {
error = EINVAL;
break;
}
th = &data.header;
error = cd_read_toc(unit, 0, 0,
(struct cd_toc_entry *)th, sizeof (*th));
if (error)
break;
if (sc_link->quirks & CD_Q_BCD_TRACKS) {
/* we are going to have to convert the BCD
* encoding on the cd to what is expected
*/
th->starting_track =
bcd2bin(th->starting_track);
th->ending_track = bcd2bin(th->ending_track);
}
track = te->track;
if (track == 0)
track = th->starting_track;
else if (track == LEADOUT)
/* OK */;
else if (track < th->starting_track ||
track > th->ending_track + 1) {
error = EINVAL;
break;
}
error = cd_read_toc(unit, te->address_format,
track,
(struct cd_toc_entry *)&data,
sizeof data);
if (error)
break;
if (sc_link->quirks & CD_Q_BCD_TRACKS)
data.entry.track = bcd2bin(data.entry.track);
bcopy(&data.entry, &te->entry,
sizeof(struct cd_toc_entry));
}
break;
case CDIOCSETPATCH: case CDIOCSETPATCH:
{ {
struct ioc_patch *arg = (struct ioc_patch *) addr; struct ioc_patch *arg = (struct ioc_patch *) addr;

View file

@ -1,7 +1,7 @@
/* /*
* 16 Feb 93 Julian Elischer (julian@dialix.oz.au) * 16 Feb 93 Julian Elischer (julian@dialix.oz.au)
* *
* $Id$ * $Id: cdio.h,v 1.16 1997/02/22 09:44:53 peter Exp $
*/ */
/* /*
@ -158,6 +158,14 @@ struct ioc_read_toc_entry {
#define CDIOREADTOCENTRYS _IOWR('c',5,struct ioc_read_toc_entry) #define CDIOREADTOCENTRYS _IOWR('c',5,struct ioc_read_toc_entry)
struct ioc_read_toc_single_entry {
u_char address_format;
u_char track;
struct cd_toc_entry entry;
};
#define CDIOREADTOCENTRY _IOWR('c',6,struct ioc_read_toc_single_entry)
struct ioc_patch struct ioc_patch
{ {
u_char patch[4]; /* one for each channel */ u_char patch[4]; /* one for each channel */