diff --git a/sys/amd64/amd64/autoconf.c b/sys/amd64/amd64/autoconf.c index 7fad268092f6..d18fb01d89ff 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 #include @@ -101,9 +102,17 @@ static void setroot __P((void)); #ifdef CD9660 +#include +#include +#include +#include #include -/* 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; + int i, j, error; + struct bdevsw *bd; + dev_t orootdev; - 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; +#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 026e9d5abbad..7fc4aa70de8b 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 4fe0c0a96ef7..ff394b49f793 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 6a7adb397933..f7eecb8c5584 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); @@ -1426,6 +1427,57 @@ mcd_read_toc(int unit) 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 mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te) { diff --git a/sys/dev/scd/scd.c b/sys/dev/scd/scd.c index 33d77f8c3240..acd1968bd17b 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 a875434990af..a61ccfc99dd7 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 @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #include #include @@ -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 d7fc57998d53..24375348ee44 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 026e9d5abbad..7fc4aa70de8b 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 026e9d5abbad..7fc4aa70de8b 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 7fad268092f6..d18fb01d89ff 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 #include @@ -101,9 +102,17 @@ static void setroot __P((void)); #ifdef CD9660 +#include +#include +#include +#include #include -/* 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; + int i, j, error; + struct bdevsw *bd; + dev_t orootdev; - 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; +#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 945152a7c0b7..0ed243f60670 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)); @@ -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?) diff --git a/sys/i386/isa/mcd.c b/sys/i386/isa/mcd.c index 6a7adb397933..f7eecb8c5584 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); @@ -1426,6 +1427,57 @@ mcd_read_toc(int unit) 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 mcd_toc_entrys(int unit, struct ioc_read_toc_entry *te) { diff --git a/sys/i386/isa/scd.c b/sys/i386/isa/scd.c index 33d77f8c3240..acd1968bd17b 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 702c7f24a04d..39d030f91ef4 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 a875434990af..a61ccfc99dd7 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 @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #include #include @@ -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 d7fc57998d53..24375348ee44 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 f643c37212dc..00df2f7ca829 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 5edc4bada27f..c0379987fee5 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 */