Move scsi mmc discmode determination to scsi-mmc.

Add discmode for CD-i.
This commit is contained in:
rocky
2004-12-04 11:50:40 +00:00
parent 16bc93f4e5
commit 2334c3c7cc
5 changed files with 110 additions and 79 deletions

View File

@@ -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 <rocky@panix.com> Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
@@ -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, const scsi_mmc_cdb_t *p_cdb,
scsi_mmc_direction_t e_direction, unsigned int i_buf, scsi_mmc_direction_t e_direction, unsigned int i_buf,
/*in/out*/ void *p_buf ); /*in/out*/ void *p_buf );
/*! /*!
* Eject using SCSI MMC commands. Return 0 if successful. * Eject using SCSI MMC commands. Return 0 if successful.
*/ */
int scsi_mmc_eject_media( const CdIo *p_cdio); int scsi_mmc_eject_media( const CdIo *p_cdio);
/*! Packet driver to read mode2 sectors. /*!
Can read only up to 25 blocks. Return the discmode as reported by the SCSI-MMC Read (FULL) TOC
*/ command.
int scsi_mmc_read_sectors ( const CdIo *p_cdio, void *p_buf, lba_t lba,
int sector_type, unsigned int nblocks);
/*! Information was obtained from Section 5.1.13 (Read TOC/PMA/ATIP)
Set the block size for subsequest read requests, via a SCSI MMC pages 56-62 from the SCSI MMC draft specification, revision 10a
MODE_SELECT 6 command. 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. 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 ); 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__ */ #endif /* __SCSI_MMC_H__ */

View File

@@ -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 <hvr@gnu.org> Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
@@ -97,7 +97,8 @@ typedef enum {
CDIO_DISC_MODE_DVD_PRW, /**< DVD+RW */ CDIO_DISC_MODE_DVD_PRW, /**< DVD+RW */
CDIO_DISC_MODE_DVD_OTHER, /**< Unknown/unclassified DVD type */ CDIO_DISC_MODE_DVD_OTHER, /**< Unknown/unclassified DVD type */
CDIO_DISC_MODE_NO_INFO, CDIO_DISC_MODE_NO_INFO,
CDIO_DISC_MODE_ERROR CDIO_DISC_MODE_ERROR,
CDIO_DISC_MODE_CD_I /**< CD-i. */
} discmode_t; } discmode_t;
/*! Information that can be obtained through a Read Subchannel /*! 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_DATA:
case CDIO_DISC_MODE_CD_XA: case CDIO_DISC_MODE_CD_XA:
case CDIO_DISC_MODE_CD_MIXED: case CDIO_DISC_MODE_CD_MIXED:
case CDIO_DISC_MODE_CD_I:
return true; return true;
default: default:
return false; return false;

View File

@@ -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 <hvr@gnu.org> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com> Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
@@ -27,7 +27,7 @@
# include "config.h" # include "config.h"
#endif #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 <string.h> #include <string.h>
@@ -458,7 +458,7 @@ get_discmode_linux (void *p_user_data)
{ {
_img_private_t *p_env = 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. */ /* See if this is a DVD. */
cdio_dvd_struct_t dvd; /* DVD READ STRUCT for layer 0. */ 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]; Justin B Ruggles <jruggle@earthlink.net> reports that the
memset(buf, 0, bufsize); GNU/Linux ioctl(.., CDROM_DISC_STATUS) does not return "CD DATA
scsi_mmc_cdb_t cdb; 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.
/* Justin B Ruggles <jruggle@earthlink.net> 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.
*/ */
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)); if (i_discmode < 0) return CDIO_DISC_MODE_ERROR;
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC);
cdb.field[2] = CDIO_MMC_READTOC_FMT_FULTOC; /* FIXME Need to add getting DVD types. */
CDIO_MMC_SET_READ_LENGTH8(cdb.field, bufsize); switch(i_discmode) {
scsi_mmc_run_cmd(p_env->gen.cdio, 2000, &cdb, SCSI_MMC_DATA_READ, case CDS_AUDIO:
bufsize, buf); return CDIO_DISC_MODE_CD_DA;
i_discmode = -1; case CDS_DATA_1:
if (buf[7] == 0xA0) { case CDS_DATA_2: /* Actually, recent GNU/Linux kernels don't return
if (buf[13] == 0x00) { CDS_DATA_2, but just in case. */
if (buf[5] & 0x04) i_discmode = CDS_DATA_1; return CDIO_DISC_MODE_CD_DATA;
else i_discmode = CDS_AUDIO; 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;
} }
} }

View File

@@ -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 <rocky@panix.com> Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
@@ -39,7 +39,7 @@
#include <cdio/logging.h> #include <cdio/logging.h>
#include "cdio_private.h" #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] = const char *track_format2str[6] =
@@ -61,7 +61,8 @@ const char *discmode2str[] = {
"DVD+RW", "DVD+RW",
"Unknown/unclassified DVD", "Unknown/unclassified DVD",
"No information", "No information",
"Error in getting information" "Error in getting information",
"CD-i"
}; };

View File

@@ -1,6 +1,6 @@
/* Common SCSI Multimedia Command (MMC) routines. /* 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 <rocky@panix.com> Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
@@ -40,6 +40,42 @@
#include <errno.h> #include <errno.h>
#endif #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 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 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. * Eject using SCSI MMC commands. Return 0 if successful.
*/ */
int int
scsi_mmc_eject_media( const CdIo *cdio ) scsi_mmc_eject_media( const CdIo *p_cdio )
{ {
int i_status; int i_status;
scsi_mmc_cdb_t cdb = {{0, }}; scsi_mmc_cdb_t cdb = {{0, }};
uint8_t buf[1]; uint8_t buf[1];
scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; 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; 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); 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_get_cmd_len(cdb.field[0]), &cdb,
SCSI_MMC_DATA_WRITE, 0, &buf); SCSI_MMC_DATA_WRITE, 0, &buf);
if (0 != i_status) 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); CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP);
cdb.field[4] = 1; 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_get_cmd_len(cdb.field[0]), &cdb,
SCSI_MMC_DATA_WRITE, 0, &buf); SCSI_MMC_DATA_WRITE, 0, &buf);
if (0 != i_status) 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); CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP);
cdb.field[4] = 2; /* eject */ 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_get_cmd_len(cdb.field[0]), &cdb,
SCSI_MMC_DATA_WRITE, 0, &buf); SCSI_MMC_DATA_WRITE, 0, &buf);
@@ -162,17 +198,17 @@ scsi_mmc_eject_media( const CdIo *cdio )
Can read only up to 25 blocks. Can read only up to 25 blocks.
*/ */
int 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 ) int sector_type, unsigned int nblocks )
{ {
scsi_mmc_cdb_t cdb = {{0, }}; scsi_mmc_cdb_t cdb = {{0, }};
scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; 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; 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_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD);
CDIO_MMC_SET_READ_TYPE (cdb.field, sector_type); 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_SET_MAIN_CHANNEL_SELECTION_BITS(cdb.field,
CDIO_MMC_MCSB_ALL_HEADERS); 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_get_cmd_len(cdb.field[0]), &cdb,
SCSI_MMC_DATA_READ, SCSI_MMC_DATA_READ,
CDIO_CD_FRAMESIZE_RAW * nblocks, CDIO_CD_FRAMESIZE_RAW * nblocks,