From 2334c3c7ccdbd1361cb48c55047ce531dfa08688 Mon Sep 17 00:00:00 2001 From: rocky Date: Sat, 4 Dec 2004 11:50:40 +0000 Subject: [PATCH] Move scsi mmc discmode determination to scsi-mmc. Add discmode for CD-i. --- include/cdio/scsi_mmc.h | 33 ++++++++++------ include/cdio/sector.h | 6 ++- lib/_cdio_linux.c | 85 ++++++++++++++++------------------------- lib/cdio.c | 7 ++-- lib/scsi_mmc.c | 58 ++++++++++++++++++++++------ 5 files changed, 110 insertions(+), 79 deletions(-) diff --git a/include/cdio/scsi_mmc.h b/include/cdio/scsi_mmc.h index 78704f5e..ef2d17e5 100644 --- a/include/cdio/scsi_mmc.h +++ b/include/cdio/scsi_mmc.h @@ -1,5 +1,5 @@ /* - $Id: scsi_mmc.h,v 1.33 2004/09/04 23:49:47 rocky Exp $ + $Id: scsi_mmc.h,v 1.34 2004/12/04 11:50:40 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein @@ -360,23 +360,22 @@ int scsi_mmc_run_cmd( const CdIo *p_cdio, unsigned int i_timeout_ms, const scsi_mmc_cdb_t *p_cdb, scsi_mmc_direction_t e_direction, unsigned int i_buf, /*in/out*/ void *p_buf ); - /*! * Eject using SCSI MMC commands. Return 0 if successful. */ int scsi_mmc_eject_media( const CdIo *p_cdio); -/*! Packet driver to read mode2 sectors. - Can read only up to 25 blocks. -*/ -int scsi_mmc_read_sectors ( const CdIo *p_cdio, void *p_buf, lba_t lba, - int sector_type, unsigned int nblocks); +/*! + Return the discmode as reported by the SCSI-MMC Read (FULL) TOC + command. -/*! - Set the block size for subsequest read requests, via a SCSI MMC - MODE_SELECT 6 command. + Information was obtained from Section 5.1.13 (Read TOC/PMA/ATIP) + pages 56-62 from the SCSI MMC draft specification, revision 10a + at http://www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf See + especially tables 72, 73 and 75. */ -int scsi_mmc_set_blocksize ( const CdIo *p_cdio, unsigned int bsize); +discmode_t scsi_mmc_get_discmode( const CdIo *p_cdio ); + /*! Return the the kind of drive capabilities of device. @@ -412,4 +411,16 @@ bool scsi_mmc_get_hwinfo ( const CdIo *p_cdio, */ char *scsi_mmc_get_mcn ( const CdIo *p_cdio ); +/*! Packet driver to read mode2 sectors. + Can read only up to 25 blocks. +*/ +int scsi_mmc_read_sectors ( const CdIo *p_cdio, void *p_buf, lba_t lba, + int sector_type, unsigned int nblocks); + +/*! + Set the block size for subsequest read requests, via a SCSI MMC + MODE_SELECT 6 command. + */ +int scsi_mmc_set_blocksize ( const CdIo *p_cdio, unsigned int bsize); + #endif /* __SCSI_MMC_H__ */ diff --git a/include/cdio/sector.h b/include/cdio/sector.h index 1d754129..c4cc509b 100644 --- a/include/cdio/sector.h +++ b/include/cdio/sector.h @@ -1,5 +1,5 @@ /* - $Id: sector.h,v 1.28 2004/08/30 01:01:14 rocky Exp $ + $Id: sector.h,v 1.29 2004/12/04 11:50:40 rocky Exp $ Copyright (C) 2000 Herbert Valerio Riedel Copyright (C) 2003, 2004 Rocky Bernstein @@ -97,7 +97,8 @@ typedef enum { CDIO_DISC_MODE_DVD_PRW, /**< DVD+RW */ CDIO_DISC_MODE_DVD_OTHER, /**< Unknown/unclassified DVD type */ CDIO_DISC_MODE_NO_INFO, - CDIO_DISC_MODE_ERROR + CDIO_DISC_MODE_ERROR, + CDIO_DISC_MODE_CD_I /**< CD-i. */ } discmode_t; /*! Information that can be obtained through a Read Subchannel @@ -291,6 +292,7 @@ static inline bool discmode_is_cd(discmode_t discmode) case CDIO_DISC_MODE_CD_DATA: case CDIO_DISC_MODE_CD_XA: case CDIO_DISC_MODE_CD_MIXED: + case CDIO_DISC_MODE_CD_I: return true; default: return false; diff --git a/lib/_cdio_linux.c b/lib/_cdio_linux.c index 80081acf..1cd8bf1f 100644 --- a/lib/_cdio_linux.c +++ b/lib/_cdio_linux.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_linux.c,v 1.100 2004/12/04 05:49:25 rocky Exp $ + $Id: _cdio_linux.c,v 1.101 2004/12/04 11:50:40 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002, 2003, 2004 Rocky Bernstein @@ -27,7 +27,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.100 2004/12/04 05:49:25 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.101 2004/12/04 11:50:40 rocky Exp $"; #include @@ -458,7 +458,7 @@ get_discmode_linux (void *p_user_data) { _img_private_t *p_env = p_user_data; - int32_t i_discmode; + discmode_t discmode = CDIO_DISC_MODE_NO_INFO; /* See if this is a DVD. */ cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */ @@ -477,58 +477,39 @@ get_discmode_linux (void *p_user_data) } } - uint32_t bufsize = 14; - uint8_t buf[bufsize]; - memset(buf, 0, bufsize); - scsi_mmc_cdb_t cdb; - - - /* Justin B Ruggles reports: - GNU/Linux ioctl(.., CDROM_DISC_STATUS does not return "CD DATA Form - 2" for SVCD's when I know they are form 2, so we read a FULL TOC in - an attempt to make it more accurate. Most of the info was obtained - the SCSI MMC draft spec revision 10a from - http://www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf - - Pages 56 to 62 give more details. Libcdio does not have CD-i as a - discmode, so I just have it treat CD-i as if it is CD-XA. + /* + Justin B Ruggles reports that the + GNU/Linux ioctl(.., CDROM_DISC_STATUS) does not return "CD DATA + Form 2" for SVCD's even though they are are form 2. There we + issue a SCSI MMC-2 FULL TOC command first to try get more + accurate information. */ + discmode = scsi_mmc_get_discmode(p_env->gen.cdio); + if (CDIO_DISC_MODE_NO_INFO != discmode) + return discmode; + else { + int32_t i_discmode = ioctl (p_env->gen.fd, CDROM_DISC_STATUS); - memset(&cdb, 0, sizeof(scsi_mmc_cdb_t)); - CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); - cdb.field[2] = CDIO_MMC_READTOC_FMT_FULTOC; - CDIO_MMC_SET_READ_LENGTH8(cdb.field, bufsize); - scsi_mmc_run_cmd(p_env->gen.cdio, 2000, &cdb, SCSI_MMC_DATA_READ, - bufsize, buf); - i_discmode = -1; - if (buf[7] == 0xA0) { - if (buf[13] == 0x00) { - if (buf[5] & 0x04) i_discmode = CDS_DATA_1; - else i_discmode = CDS_AUDIO; + if (i_discmode < 0) return CDIO_DISC_MODE_ERROR; + + /* FIXME Need to add getting DVD types. */ + switch(i_discmode) { + case CDS_AUDIO: + return CDIO_DISC_MODE_CD_DA; + case CDS_DATA_1: + case CDS_DATA_2: /* Actually, recent GNU/Linux kernels don't return + CDS_DATA_2, but just in case. */ + return CDIO_DISC_MODE_CD_DATA; + case CDS_MIXED: + return CDIO_DISC_MODE_CD_MIXED; + case CDS_XA_2_1: + case CDS_XA_2_2: + return CDIO_DISC_MODE_CD_XA; + case CDS_NO_INFO: + return CDIO_DISC_MODE_NO_INFO; + default: + return CDIO_DISC_MODE_ERROR; } - else if (buf[13] == 0x10 || buf[13] == 0x20) i_discmode = CDS_XA_2_1; - } - if (i_discmode < 0) - i_discmode = ioctl (p_env->gen.fd, CDROM_DISC_STATUS); - - if (i_discmode < 0) return CDIO_DISC_MODE_ERROR; - - /* FIXME Need to add getting DVD types. */ - switch(i_discmode) { - case CDS_AUDIO: - return CDIO_DISC_MODE_CD_DA; - case CDS_DATA_1: - case CDS_DATA_2: - return CDIO_DISC_MODE_CD_DATA; - case CDS_MIXED: - return CDIO_DISC_MODE_CD_MIXED; - case CDS_XA_2_1: - case CDS_XA_2_2: - return CDIO_DISC_MODE_CD_XA; - case CDS_NO_INFO: - return CDIO_DISC_MODE_NO_INFO; - default: - return CDIO_DISC_MODE_ERROR; } } diff --git a/lib/cdio.c b/lib/cdio.c index 4d46d74e..9ff656b0 100644 --- a/lib/cdio.c +++ b/lib/cdio.c @@ -1,5 +1,5 @@ /* - $Id: cdio.c,v 1.75 2004/10/26 01:21:05 rocky Exp $ + $Id: cdio.c,v 1.76 2004/12/04 11:50:40 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein Copyright (C) 2001 Herbert Valerio Riedel @@ -39,7 +39,7 @@ #include #include "cdio_private.h" -static const char _rcsid[] = "$Id: cdio.c,v 1.75 2004/10/26 01:21:05 rocky Exp $"; +static const char _rcsid[] = "$Id: cdio.c,v 1.76 2004/12/04 11:50:40 rocky Exp $"; const char *track_format2str[6] = @@ -61,7 +61,8 @@ const char *discmode2str[] = { "DVD+RW", "Unknown/unclassified DVD", "No information", - "Error in getting information" + "Error in getting information", + "CD-i" }; diff --git a/lib/scsi_mmc.c b/lib/scsi_mmc.c index eaced795..55326942 100644 --- a/lib/scsi_mmc.c +++ b/lib/scsi_mmc.c @@ -1,6 +1,6 @@ /* Common SCSI Multimedia Command (MMC) routines. - $Id: scsi_mmc.c,v 1.30 2004/10/31 17:18:08 rocky Exp $ + $Id: scsi_mmc.c,v 1.31 2004/12/04 11:50:40 rocky Exp $ Copyright (C) 2004 Rocky Bernstein @@ -40,6 +40,42 @@ #include #endif +/*! + Return the discmode as reported by the SCSI-MMC Read (FULL) TOC + command. + + Information was obtained from Section 5.1.13 (Read TOC/PMA/ATIP) + pages 56-62 from the SCSI MMC draft specification, revision 10a + at http://www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf See + especially tables 72, 73 and 75. + */ +discmode_t +scsi_mmc_get_discmode( const CdIo *p_cdio ) + +{ + uint8_t buf[14] = { 0, }; + scsi_mmc_cdb_t cdb; + + memset(&cdb, 0, sizeof(scsi_mmc_cdb_t)); + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); + cdb.field[2] = CDIO_MMC_READTOC_FMT_FULTOC; + CDIO_MMC_SET_READ_LENGTH8(cdb.field, sizeof(buf)); + scsi_mmc_run_cmd(p_cdio, 2000, &cdb, SCSI_MMC_DATA_READ, sizeof(buf), buf); + if (buf[7] == 0xA0) { + if (buf[13] == 0x00) { + if (buf[5] & 0x04) + return CDIO_DISC_MODE_CD_DATA; + else + return CDIO_DISC_MODE_CD_DA; + } + else if (buf[13] == 0x10) + return CDIO_DISC_MODE_CD_I; + else if (buf[13] == 0x20) + return CDIO_DISC_MODE_CD_XA; + } + return CDIO_DISC_MODE_NO_INFO; +} + /*! On input a MODE_SENSE command was issued and we have the results in p. We interpret this and return a bit mask set according to the @@ -121,21 +157,21 @@ scsi_mmc_run_cmd( const CdIo *p_cdio, unsigned int i_timeout_ms, * Eject using SCSI MMC commands. Return 0 if successful. */ int -scsi_mmc_eject_media( const CdIo *cdio ) +scsi_mmc_eject_media( const CdIo *p_cdio ) { int i_status; scsi_mmc_cdb_t cdb = {{0, }}; uint8_t buf[1]; scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; - if ( ! cdio || ! cdio->op.run_scsi_mmc_cmd ) + if ( ! p_cdio || ! p_cdio->op.run_scsi_mmc_cmd ) return -2; - run_scsi_mmc_cmd = cdio->op.run_scsi_mmc_cmd; + run_scsi_mmc_cmd = p_cdio->op.run_scsi_mmc_cmd; CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL); - i_status = run_scsi_mmc_cmd (cdio->env, DEFAULT_TIMEOUT_MS, + i_status = run_scsi_mmc_cmd (p_cdio->env, DEFAULT_TIMEOUT_MS, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_WRITE, 0, &buf); if (0 != i_status) @@ -143,7 +179,7 @@ scsi_mmc_eject_media( const CdIo *cdio ) CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP); cdb.field[4] = 1; - i_status = run_scsi_mmc_cmd (cdio->env, DEFAULT_TIMEOUT_MS, + i_status = run_scsi_mmc_cmd (p_cdio->env, DEFAULT_TIMEOUT_MS, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_WRITE, 0, &buf); if (0 != i_status) @@ -152,7 +188,7 @@ scsi_mmc_eject_media( const CdIo *cdio ) CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP); cdb.field[4] = 2; /* eject */ - return run_scsi_mmc_cmd (cdio->env, DEFAULT_TIMEOUT_MS, + return run_scsi_mmc_cmd (p_cdio->env, DEFAULT_TIMEOUT_MS, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_WRITE, 0, &buf); @@ -162,17 +198,17 @@ scsi_mmc_eject_media( const CdIo *cdio ) Can read only up to 25 blocks. */ int -scsi_mmc_read_sectors ( const CdIo *cdio, void *p_buf, lba_t lba, +scsi_mmc_read_sectors ( const CdIo *p_cdio, void *p_buf, lba_t lba, int sector_type, unsigned int nblocks ) { scsi_mmc_cdb_t cdb = {{0, }}; scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; - if ( ! cdio || ! cdio->op.run_scsi_mmc_cmd ) + if ( ! p_cdio || ! p_cdio->op.run_scsi_mmc_cmd ) return -2; - run_scsi_mmc_cmd = cdio->op.run_scsi_mmc_cmd; + run_scsi_mmc_cmd = p_cdio->op.run_scsi_mmc_cmd; CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD); CDIO_MMC_SET_READ_TYPE (cdb.field, sector_type); @@ -181,7 +217,7 @@ scsi_mmc_read_sectors ( const CdIo *cdio, void *p_buf, lba_t lba, CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb.field, CDIO_MMC_MCSB_ALL_HEADERS); - return run_scsi_mmc_cmd (cdio->env, DEFAULT_TIMEOUT_MS, + return run_scsi_mmc_cmd (p_cdio->env, DEFAULT_TIMEOUT_MS, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_READ, CDIO_CD_FRAMESIZE_RAW * nblocks,