summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/amd64/amd64/autoconf.c62
-rw-r--r--sys/conf/NOTES9
-rw-r--r--sys/conf/options14
-rw-r--r--sys/dev/mcd/mcd.c54
-rw-r--r--sys/dev/scd/scd.c44
-rw-r--r--sys/fs/cd9660/cd9660_vfsops.c76
-rw-r--r--sys/fs/cd9660/iso.h4
-rw-r--r--sys/i386/conf/LINT9
-rw-r--r--sys/i386/conf/NOTES9
-rw-r--r--sys/i386/i386/autoconf.c62
-rw-r--r--sys/i386/isa/matcd/matcd.c78
-rw-r--r--sys/i386/isa/mcd.c54
-rw-r--r--sys/i386/isa/scd.c44
-rw-r--r--sys/i386/isa/wcd.c35
-rw-r--r--sys/isofs/cd9660/cd9660_vfsops.c76
-rw-r--r--sys/isofs/cd9660/iso.h4
-rw-r--r--sys/scsi/cd.c59
-rw-r--r--sys/sys/cdio.h10
18 files changed, 623 insertions, 80 deletions
diff --git a/sys/amd64/amd64/autoconf.c b/sys/amd64/amd64/autoconf.c
index 7fad268..d18fb01 100644
--- a/sys/amd64/amd64/autoconf.c
+++ b/sys/amd64/amd64/autoconf.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* 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.
*/
#include "opt_smp.h"
+#include "opt_cd9660.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -101,9 +102,17 @@ static void setroot __P((void));
#ifdef CD9660
+#include <sys/fcntl.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <machine/clock.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 {
char *name;
int major;
@@ -112,25 +121,44 @@ static struct {
{ "mcd", 7 },
{ "scd", 16 },
{ "matcd", 17 },
+ { "wcd", 19 },
{ 0, 0}
};
-static int find_cdrom_root __P((void *));
+static int find_cdrom_root __P((void));
static int
-find_cdrom_root(dummy)
- void *dummy;
+find_cdrom_root()
{
- int i,j,k;
-
- for (j = 0 ; j < 2; j++)
- for (k = 0 ; try_cdrom[k].name ; k++) {
- rootdev = makedev(try_cdrom[k].major,j*8);
- printf("trying rootdev=0x%lx (%s%d)\n",
- rootdev, try_cdrom[k].name,j);
- i = (*cd9660_mountroot)();
- if (!i) return i;
+ int i, j, error;
+ struct bdevsw *bd;
+ dev_t orootdev;
+
+#if CD9660_ROOTDELAY > 0
+ DELAY(CD9660_ROOTDELAY * 1000000);
+#endif
+ orootdev = rootdev;
+ for (i = 0 ; i < 2; i++)
+ for (j = 0 ; try_cdrom[j].name ; j++) {
+ 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;
}
#endif /* CD9660 */
@@ -233,7 +261,11 @@ configure(dummy)
if ((boothowto & RB_CDROM)) {
if (bootverbose)
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
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index 026e9d5..7fc4aa7 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# 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
# file. Instead, you should start from GENERIC, and add options from
@@ -439,6 +439,13 @@ options QUOTA #enable disk quotas
#options UMAPFS_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
# in the NULL filesystem
#options SAFETY
diff --git a/sys/conf/options b/sys/conf/options
index 4fe0c0a..ff394b4 100644
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -1,4 +1,4 @@
-# $Id$
+# $Id: options,v 1.29 1997/02/22 09:28:14 peter Exp $
# Format:
# Option name filename
@@ -29,6 +29,18 @@ PORTAL opt_dontuse.h
PROCFS 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
# hidden yet.
UNION
diff --git a/sys/dev/mcd/mcd.c b/sys/dev/mcd/mcd.c
index 6a7adb3..f7eecb8 100644
--- a/sys/dev/mcd/mcd.c
+++ b/sys/dev/mcd/mcd.c
@@ -40,7 +40,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* 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";
@@ -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_read_toc(int unit);
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_eject(int unit);
static int mcd_inject(int unit);
@@ -1427,6 +1428,57 @@ mcd_read_toc(int unit)
}
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
mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te)
{
struct mcd_data *cd = mcd_data + unit;
diff --git a/sys/dev/scd/scd.c b/sys/dev/scd/scd.c
index 33d77f8..acd1968 100644
--- a/sys/dev/scd/scd.c
+++ b/sys/dev/scd/scd.c
@@ -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 */
@@ -180,6 +180,7 @@ static int read_subcode(int unit, struct sony_subchannel_position_data *sc);
/* for xcdplayer */
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_entry(int unit, struct ioc_read_toc_single_entry *te);
#define SCD_LASTPLUS1 170 /* don't ask, xcdplayer passes this in */
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);
case CDIOREADTOCENTRYS:
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 CDIOCGETVOL:
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 void scd_drvinit(void *unused)
diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c
index a875434..a61ccfc 100644
--- a/sys/fs/cd9660/cd9660_vfsops.c
+++ b/sys/fs/cd9660/cd9660_vfsops.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)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>
@@ -48,6 +48,8 @@
#include <miscfs/specfs/specdev.h>
#include <sys/mount.h>
#include <sys/buf.h>
+#include <sys/cdio.h>
+#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/errno.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.
*/
+static int iso_get_ssector __P((dev_t dev, struct proc *p));
static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
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 proc *p = curproc; /* XXX */
+ struct proc *p;
+{
struct iso_args args;
int error;
-
+
/*
* Get vnode for rootdev.
*/
if ((error = bdevvp(swapdev, &swapdev_vp)) ||
(error = bdevvp(rootdev, &rootvp))) {
- printf("cd9660_mountroot: can't setup bdevvp's");
+ printf("iso_mountroot: can't setup bdevvp's");
return (error);
}
- if (error = vfs_rootmountalloc("cd9660", "root_device", &mp))
- return (error);
args.flags = ISOFSMNT_ROOT;
- if (error = iso_mountfs(rootvp, mp, p, &args)) {
- mp->mnt_vfc->vfc_refcount--;
- vfs_unbusy(mp, p);
- free(mp, M_MOUNT);
+ args.ssector = iso_get_ssector(rootdev, p);
+ if (bootverbose)
+ printf("iso_mountroot(): using session at block %d\n",
+ args.ssector);
+ if (error = iso_mountfs(rootvp, mp, p, &args))
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);
- vfs_unbusy(mp, p);
return (0);
}
@@ -150,6 +189,9 @@ cd9660_mount(mp, path, data, ndp, p)
int error;
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))))
return (error);
diff --git a/sys/fs/cd9660/iso.h b/sys/fs/cd9660/iso.h
index d7fc579..2437534 100644
--- a/sys/fs/cd9660/iso.h
+++ b/sys/fs/cd9660/iso.h
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)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)
@@ -215,7 +215,7 @@ int cd9660_init __P((struct vfsconf *));
#define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
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_specop_p;
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index 026e9d5..7fc4aa7 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# 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
# file. Instead, you should start from GENERIC, and add options from
@@ -439,6 +439,13 @@ options QUOTA #enable disk quotas
#options UMAPFS_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
# in the NULL filesystem
#options SAFETY
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 026e9d5..7fc4aa7 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -2,7 +2,7 @@
# LINT -- config file for checking all the sources, tries to pull in
# 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
# file. Instead, you should start from GENERIC, and add options from
@@ -439,6 +439,13 @@ options QUOTA #enable disk quotas
#options UMAPFS_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
# in the NULL filesystem
#options SAFETY
diff --git a/sys/i386/i386/autoconf.c b/sys/i386/i386/autoconf.c
index 7fad268..d18fb01 100644
--- a/sys/i386/i386/autoconf.c
+++ b/sys/i386/i386/autoconf.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* 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.
*/
#include "opt_smp.h"
+#include "opt_cd9660.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -101,9 +102,17 @@ static void setroot __P((void));
#ifdef CD9660
+#include <sys/fcntl.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <machine/clock.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 {
char *name;
int major;
@@ -112,25 +121,44 @@ static struct {
{ "mcd", 7 },
{ "scd", 16 },
{ "matcd", 17 },
+ { "wcd", 19 },
{ 0, 0}
};
-static int find_cdrom_root __P((void *));
+static int find_cdrom_root __P((void));
static int
-find_cdrom_root(dummy)
- void *dummy;
+find_cdrom_root()
{
- int i,j,k;
-
- for (j = 0 ; j < 2; j++)
- for (k = 0 ; try_cdrom[k].name ; k++) {
- rootdev = makedev(try_cdrom[k].major,j*8);
- printf("trying rootdev=0x%lx (%s%d)\n",
- rootdev, try_cdrom[k].name,j);
- i = (*cd9660_mountroot)();
- if (!i) return i;
+ int i, j, error;
+ struct bdevsw *bd;
+ dev_t orootdev;
+
+#if CD9660_ROOTDELAY > 0
+ DELAY(CD9660_ROOTDELAY * 1000000);
+#endif
+ orootdev = rootdev;
+ for (i = 0 ; i < 2; i++)
+ for (j = 0 ; try_cdrom[j].name ; j++) {
+ 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;
}
#endif /* CD9660 */
@@ -233,7 +261,11 @@ configure(dummy)
if ((boothowto & RB_CDROM)) {
if (bootverbose)
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
diff --git a/sys/i386/isa/matcd/matcd.c b/sys/i386/isa/matcd/matcd.c
index 945152a..0ed243f 100644
--- a/sys/i386/isa/matcd/matcd.c
+++ b/sys/i386/isa/matcd/matcd.c
@@ -76,7 +76,7 @@
Dedicated to: My family, my Grandfather,
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
plenty of silly questions and might get the post of
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";
/* 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
@@ -572,6 +572,9 @@ static int matcd_toc_header(int ldrive, int cdrive, int controller,
static int matcd_toc_entries(int ldrive, int cdrive,
int controller,
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,
struct ioc_read_subchannel * 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,
(struct ioc_read_toc_entry *) addr));
+ case CDIOREADTOCENTRY:
+ return(matcd_toc_entry(ldrive, cdrive, controller,
+ (struct ioc_read_toc_single_entry *) addr));
+
case CDIOCREADSUBCHANNEL:
return(matcd_read_subq(ldrive, cdrive, controller,
(struct ioc_read_subchannel *) addr));
@@ -2503,6 +2510,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?)
This call gives a snapshot state of where the optical
diff --git a/sys/i386/isa/mcd.c b/sys/i386/isa/mcd.c
index 6a7adb3..f7eecb8 100644
--- a/sys/i386/isa/mcd.c
+++ b/sys/i386/isa/mcd.c
@@ -40,7 +40,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* 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";
@@ -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_read_toc(int unit);
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_eject(int unit);
static int mcd_inject(int unit);
@@ -1427,6 +1428,57 @@ mcd_read_toc(int unit)
}
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
mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te)
{
struct mcd_data *cd = mcd_data + unit;
diff --git a/sys/i386/isa/scd.c b/sys/i386/isa/scd.c
index 33d77f8..acd1968 100644
--- a/sys/i386/isa/scd.c
+++ b/sys/i386/isa/scd.c
@@ -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 */
@@ -180,6 +180,7 @@ static int read_subcode(int unit, struct sony_subchannel_position_data *sc);
/* for xcdplayer */
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_entry(int unit, struct ioc_read_toc_single_entry *te);
#define SCD_LASTPLUS1 170 /* don't ask, xcdplayer passes this in */
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);
case CDIOREADTOCENTRYS:
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 CDIOCGETVOL:
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 void scd_drvinit(void *unused)
diff --git a/sys/i386/isa/wcd.c b/sys/i386/isa/wcd.c
index 702c7f2..39d030f 100644
--- a/sys/i386/isa/wcd.c
+++ b/sys/i386/isa/wcd.c
@@ -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 -
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: {
struct ioc_read_subchannel *args =
(struct ioc_read_subchannel*) addr;
diff --git a/sys/isofs/cd9660/cd9660_vfsops.c b/sys/isofs/cd9660/cd9660_vfsops.c
index a875434..a61ccfc 100644
--- a/sys/isofs/cd9660/cd9660_vfsops.c
+++ b/sys/isofs/cd9660/cd9660_vfsops.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)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>
@@ -48,6 +48,8 @@
#include <miscfs/specfs/specdev.h>
#include <sys/mount.h>
#include <sys/buf.h>
+#include <sys/cdio.h>
+#include <sys/conf.h>
#include <sys/fcntl.h>
#include <sys/errno.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.
*/
+static int iso_get_ssector __P((dev_t dev, struct proc *p));
static int iso_mountfs __P((struct vnode *devvp, struct mount *mp,
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 proc *p = curproc; /* XXX */
+ struct proc *p;
+{
struct iso_args args;
int error;
-
+
/*
* Get vnode for rootdev.
*/
if ((error = bdevvp(swapdev, &swapdev_vp)) ||
(error = bdevvp(rootdev, &rootvp))) {
- printf("cd9660_mountroot: can't setup bdevvp's");
+ printf("iso_mountroot: can't setup bdevvp's");
return (error);
}
- if (error = vfs_rootmountalloc("cd9660", "root_device", &mp))
- return (error);
args.flags = ISOFSMNT_ROOT;
- if (error = iso_mountfs(rootvp, mp, p, &args)) {
- mp->mnt_vfc->vfc_refcount--;
- vfs_unbusy(mp, p);
- free(mp, M_MOUNT);
+ args.ssector = iso_get_ssector(rootdev, p);
+ if (bootverbose)
+ printf("iso_mountroot(): using session at block %d\n",
+ args.ssector);
+ if (error = iso_mountfs(rootvp, mp, p, &args))
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);
- vfs_unbusy(mp, p);
return (0);
}
@@ -150,6 +189,9 @@ cd9660_mount(mp, path, data, ndp, p)
int error;
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))))
return (error);
diff --git a/sys/isofs/cd9660/iso.h b/sys/isofs/cd9660/iso.h
index d7fc579..2437534 100644
--- a/sys/isofs/cd9660/iso.h
+++ b/sys/isofs/cd9660/iso.h
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)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)
@@ -215,7 +215,7 @@ int cd9660_init __P((struct vfsconf *));
#define cd9660_sysctl ((int (*) __P((int *, u_int, void *, size_t *, void *, \
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_specop_p;
diff --git a/sys/scsi/cd.c b/sys/scsi/cd.c
index f643c37..00df2f7 100644
--- a/sys/scsi/cd.c
+++ b/sys/scsi/cd.c
@@ -14,7 +14,7 @@
*
* 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"
@@ -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);
}
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:
{
struct ioc_patch *arg = (struct ioc_patch *) addr;
diff --git a/sys/sys/cdio.h b/sys/sys/cdio.h
index 5edc4ba..c037998 100644
--- a/sys/sys/cdio.h
+++ b/sys/sys/cdio.h
@@ -1,7 +1,7 @@
/*
* 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)
+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
{
u_char patch[4]; /* one for each channel */
OpenPOWER on IntegriCloud