Work on SCSI MMC layer. Some things may be broken.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: scsi_mmc.h,v 1.11 2004/07/21 11:07:27 rocky Exp $
|
||||
$Id: scsi_mmc.h,v 1.12 2004/07/22 09:52:17 rocky Exp $
|
||||
|
||||
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
|
||||
@@ -20,14 +20,19 @@
|
||||
|
||||
/*!
|
||||
\file scsi_mmc.h
|
||||
\brief Common definitions for SCSI MMC (Multimedia commands).
|
||||
\brief Common definitions for SCSI MMC (Multi-Media Commands).
|
||||
*/
|
||||
|
||||
#ifndef __SCSI_MMC_H__
|
||||
#define __SCSI_MMC_H__
|
||||
|
||||
#include <cdio/cdio.h>
|
||||
#include <cdio/types.h>
|
||||
|
||||
/*! The generic packet command opcodes for CD/DVD Logical Units. */
|
||||
|
||||
#define CDIO_MMC_GPCMD_INQUIRY 0x12
|
||||
#define CDIO_MMC_GPCMD_MODE_SELECT_6 0x15
|
||||
#define CDIO_MMC_GPCMD_MODE_SENSE 0x1a
|
||||
#define CDIO_MMC_GPCMD_START_STOP 0x1b
|
||||
#define CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL 0x1e
|
||||
@@ -39,23 +44,22 @@
|
||||
#define CDIO_MMC_GPCMD_READ_SUBCHANNEL 0x42
|
||||
#define CDIO_MMC_GPCMD_READ_TOC 0x43
|
||||
#define CDIO_MMC_GPCMD_READ_HEADER 0x44
|
||||
#define CDIO_MMC_GPCMD_PLAYAUDIO10 0x45
|
||||
#define CDIO_MMC_GPCMD_PLAYAUDIO_MSF 0x47
|
||||
#define CDIO_MMC_GPCMD_PLAYAUDIO_TI 0x48
|
||||
#define CDIO_MMC_GPCMD_PLAYTRACK_REL10 0x49
|
||||
#define CDIO_MMC_GPCMD_PLAY_AUDIO_10 0x45
|
||||
#define CDIO_MMC_GPCMD_PLAY_AUDIO_MSF 0x47
|
||||
#define CDIO_MMC_GPCMD_PLAY_AUDIO_TI 0x48
|
||||
#define CDIO_MMC_GPCMD_PLAY_TRACK_REL_10 0x49
|
||||
#define CDIO_MMC_GPCMD_PAUSE_RESUME 0x4b
|
||||
|
||||
#define CDIO_MMC_GPCMD_READ_DISC_INFO 0x51
|
||||
#define CDIO_MMC_GPCMD_MODE_SELECT 0x55
|
||||
#define CDIO_MMC_GPCMD_MODE_SELECT_6 0x15
|
||||
#define CDIO_MMC_GPCMD_MODE_SENSE_10 0x5a
|
||||
|
||||
/*!
|
||||
Group 5 Commands
|
||||
*/
|
||||
#define CDIO_MMC_GPCMD_PLAYAUDIO_12 0xa5
|
||||
#define CDIO_MMC_GPCMD_PLAY_AUDIO_12 0xa5
|
||||
#define CDIO_MMC_GPCMD_READ_12 0xa8
|
||||
#define CDIO_MMC_GPCMD_PLAYTRACK_REL12 0xa9
|
||||
#define CDIO_MMC_GPCMD_PLAY_TRACK_REL_12 0xa9
|
||||
#define CDIO_MMC_GPCMD_READ_CD 0xbe
|
||||
#define CDIO_MMC_GPCMD_READ_MSF 0xb9
|
||||
|
||||
@@ -106,38 +110,86 @@
|
||||
#define CDIO_MMC_GPCMD_SET_SPEED 0xbb
|
||||
|
||||
|
||||
#define CDIO_MMC_SET_COMMAND(rec, command) \
|
||||
rec[0] = command
|
||||
/*! The largest Command Descriptor Buffer (CDB) size.
|
||||
The possible sizes are 6, 10, and 12 bytes.
|
||||
*/
|
||||
#define MAX_CDB_LEN 12
|
||||
|
||||
#define CDIO_MMC_SET_READ_TYPE(rec, sector_type) \
|
||||
rec[1] = (sector_type << 2)
|
||||
/*! A Command Descriptor Buffer (CDB) used in sending SCSI MMC
|
||||
commands.
|
||||
*/
|
||||
typedef struct scsi_mmc_cdb {
|
||||
uint8_t field[MAX_CDB_LEN];
|
||||
} scsi_mmc_cdb_t;
|
||||
|
||||
/*! An enumeration indicating whether a SCSI MMC command is sending
|
||||
data or getting data.
|
||||
*/
|
||||
typedef enum scsi_mmc_direction {
|
||||
SCSI_MMC_DATA_READ,
|
||||
SCSI_MMC_DATA_WRITE
|
||||
} scsi_mmc_direction_t;
|
||||
|
||||
#define CDIO_MMC_SET_COMMAND(cdb, command) \
|
||||
cdb[0] = command
|
||||
|
||||
#define CDIO_MMC_SET_READ_TYPE(cdb, sector_type) \
|
||||
cdb[1] = (sector_type << 2)
|
||||
|
||||
|
||||
#define CDIO_MMC_SET_READ_LBA(rec, lba) \
|
||||
rec[2] = (lba >> 24) & 0xff; \
|
||||
rec[3] = (lba >> 16) & 0xff; \
|
||||
rec[4] = (lba >> 8) & 0xff; \
|
||||
rec[5] = (lba ) & 0xff
|
||||
#define CDIO_MMC_SET_READ_LBA(cdb, lba) \
|
||||
cdb[2] = (lba >> 24) & 0xff; \
|
||||
cdb[3] = (lba >> 16) & 0xff; \
|
||||
cdb[4] = (lba >> 8) & 0xff; \
|
||||
cdb[5] = (lba ) & 0xff
|
||||
|
||||
#define CDIO_MMC_SET_START_TRACK(rec, command) \
|
||||
rec[6] = command
|
||||
#define CDIO_MMC_SET_START_TRACK(cdb, command) \
|
||||
cdb[6] = command
|
||||
|
||||
#define CDIO_MMC_SET_READ_LENGTH(rec, len) \
|
||||
rec[6] = (len >> 16) & 0xff; \
|
||||
rec[7] = (len >> 8) & 0xff; \
|
||||
rec[8] = (len ) & 0xff
|
||||
#define CDIO_MMC_SET_READ_LENGTH(cdb, len) \
|
||||
cdb[6] = (len >> 16) & 0xff; \
|
||||
cdb[7] = (len >> 8) & 0xff; \
|
||||
cdb[8] = (len ) & 0xff
|
||||
|
||||
#define CDIO_MMC_MCSB_ALL_HEADERS 0x78
|
||||
|
||||
#define CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(rec, val) \
|
||||
rec[9] = val;
|
||||
#define CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb, val) \
|
||||
cdb[9] = val;
|
||||
|
||||
/*!
|
||||
Return the number of length in bytes of the Command Descriptor
|
||||
buffer (CDB) for a given SCSI MMC command. The length will be
|
||||
either 6, 10, or 12.
|
||||
*/
|
||||
uint8_t scsi_mmc_get_cmd_len(uint8_t scsi_cmd);
|
||||
|
||||
|
||||
/*!
|
||||
Run a SCSI MMC command.
|
||||
|
||||
cdio CD structure set by cdio_open().
|
||||
i_timeout time in milliseconds we will wait for the command
|
||||
to complete. If this value is -1, use the default
|
||||
time-out value.
|
||||
p_buf Buffer for data, both sending and receiving.
|
||||
i_buf Size of buffer
|
||||
e_direction direction the transfer is to go.
|
||||
cdb CDB bytes. All values that are needed should be set on
|
||||
input. We'll figure out what the right CDB length should be.
|
||||
|
||||
Returns 0 if command completed successfully.
|
||||
*/
|
||||
int scsi_mmc_run_cmd( const CdIo *cdio, int t_timeout,
|
||||
const scsi_mmc_cdb_t *p_cdb,
|
||||
scsi_mmc_direction_t e_direction, unsigned int i_buf,
|
||||
/*in/out*/ void *p_buf );
|
||||
|
||||
/*!
|
||||
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
|
||||
capabilities.
|
||||
*/
|
||||
void cdio_get_drive_cap_mmc(const uint8_t *p,
|
||||
void scsi_mmc_get_drive_cap(const uint8_t *p,
|
||||
/*out*/ cdio_drive_read_cap_t *p_read_cap,
|
||||
/*out*/ cdio_drive_write_cap_t *p_write_cap,
|
||||
/*out*/ cdio_drive_misc_cap_t *p_misc_cap);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
/*
|
||||
$Id: sector.h,v 1.20 2004/07/21 10:29:00 rocky Exp $
|
||||
$Id: sector.h,v 1.21 2004/07/22 09:52:17 rocky Exp $
|
||||
|
||||
Copyright (C) 2000 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
@@ -82,8 +82,8 @@ typedef enum {
|
||||
MODE2_RAW /**< 2352 byte block length */
|
||||
} trackmode_t;
|
||||
|
||||
/*! disc modes. The first combined from MMC-3 5.29.2.8 and
|
||||
GNU/Linux /usr/include/linux/cdrom.h and we've added DVD.
|
||||
/*! disc modes. The first combined from MMC-3 5.29.2.8 (Send CUESHEET)
|
||||
and GNU/Linux /usr/include/linux/cdrom.h and we've added DVD.
|
||||
*/
|
||||
typedef enum {
|
||||
CDIO_DISC_MODE_CD_DA, /**< CD-DA */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: freebsd_cam.c,v 1.20 2004/07/19 01:29:04 rocky Exp $
|
||||
$Id: freebsd_cam.c,v 1.21 2004/07/22 09:52:17 rocky Exp $
|
||||
|
||||
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static const char _rcsid[] = "$Id: freebsd_cam.c,v 1.20 2004/07/19 01:29:04 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: freebsd_cam.c,v 1.21 2004/07/22 09:52:17 rocky Exp $";
|
||||
|
||||
#ifdef HAVE_FREEBSD_CDROM
|
||||
|
||||
@@ -210,7 +210,7 @@ get_drive_cap_freebsd_cam (img_private_t *env,
|
||||
*p_read_cap = 0;
|
||||
*p_write_cap = 0;
|
||||
*p_misc_cap = 0;
|
||||
cdio_get_drive_cap_mmc(&(buf[n], p_read_cap, p_write_cap, p_misc_cap));
|
||||
scsi_mmc_get_drive_cap(&(buf[n], p_read_cap, p_write_cap, p_misc_cap));
|
||||
} else {
|
||||
*p_read_cap = CDIO_DRIVE_CAP_ERROR;
|
||||
*p_write_cap = CDIO_DRIVE_CAP_ERROR;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: aspi32.c,v 1.30 2004/07/19 01:13:32 rocky Exp $
|
||||
$Id: aspi32.c,v 1.31 2004/07/22 09:52:17 rocky Exp $
|
||||
|
||||
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static const char _rcsid[] = "$Id: aspi32.c,v 1.30 2004/07/19 01:13:32 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: aspi32.c,v 1.31 2004/07/22 09:52:17 rocky Exp $";
|
||||
|
||||
#include <cdio/cdio.h>
|
||||
#include <cdio/sector.h>
|
||||
@@ -773,7 +773,7 @@ get_drive_cap_aspi (const _img_private_t *env,
|
||||
/* Don't handle these yet. */
|
||||
break;
|
||||
case CDIO_MMC_CAPABILITIES_PAGE:
|
||||
cdio_get_drive_cap_mmc(p, p_read_cap, p_write_cap, p_misc_cap);
|
||||
scsi_mmc_get_drive_cap(p, p_read_cap, p_write_cap, p_misc_cap);
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: win32_ioctl.c,v 1.19 2004/07/19 01:13:32 rocky Exp $
|
||||
$Id: win32_ioctl.c,v 1.20 2004/07/22 09:52:17 rocky Exp $
|
||||
|
||||
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static const char _rcsid[] = "$Id: win32_ioctl.c,v 1.19 2004/07/19 01:13:32 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: win32_ioctl.c,v 1.20 2004/07/22 09:52:17 rocky Exp $";
|
||||
|
||||
#include <cdio/cdio.h>
|
||||
#include <cdio/sector.h>
|
||||
@@ -569,7 +569,7 @@ get_drive_cap_win32ioctl (const _img_private_t *env,
|
||||
FALSE) ) {
|
||||
unsigned int n=sptwb.DataBuf[3]+4;
|
||||
/* Reader? */
|
||||
cdio_get_drive_cap_mmc(&(sptwb.DataBuf[n]), p_read_cap,
|
||||
scsi_mmc_get_drive_cap(&(sptwb.DataBuf[n]), p_read_cap,
|
||||
p_write_cap, p_misc_cap);
|
||||
} else {
|
||||
*p_read_cap = CDIO_DRIVE_CAP_UNKNOWN;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: _cdio_linux.c,v 1.71 2004/07/21 10:19:21 rocky Exp $
|
||||
$Id: _cdio_linux.c,v 1.72 2004/07/22 09:52:17 rocky Exp $
|
||||
|
||||
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
@@ -27,12 +27,13 @@
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.71 2004/07/21 10:19:21 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.72 2004/07/22 09:52:17 rocky Exp $";
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <cdio/sector.h>
|
||||
#include <cdio/util.h>
|
||||
#include <cdio/types.h>
|
||||
#include <cdio/scsi_mmc.h>
|
||||
#include <cdio/cdtext.h>
|
||||
#include "cdtext_private.h"
|
||||
@@ -69,10 +70,12 @@ static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.71 2004/07/21 10:19:21 rock
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
typedef struct cdrom_generic_command cgc_t;
|
||||
/* Default value in milliseconds we will wait for a command to
|
||||
complete. */
|
||||
#define DEFAULT_TIMEOUT 500
|
||||
|
||||
#define TOTAL_TRACKS (env->tochdr.cdth_trk1)
|
||||
#define FIRST_TRACK_NUM (env->tochdr.cdth_trk0)
|
||||
#define TOTAL_TRACKS (p_env->tochdr.cdth_trk1)
|
||||
#define FIRST_TRACK_NUM (p_env->tochdr.cdth_trk0)
|
||||
|
||||
typedef enum {
|
||||
_AM_NONE,
|
||||
@@ -93,6 +96,7 @@ typedef struct {
|
||||
|
||||
access_mode_t access_mode;
|
||||
bool b_cdtext_init;
|
||||
bool b_cdtext_error;
|
||||
|
||||
/* Some of the more OS specific things. */
|
||||
cdtext_t cdtext_track[CDIO_CD_MAX_TRACKS+1]; /*CD-TEXT for each track*/
|
||||
@@ -159,12 +163,12 @@ cdio_is_cdrom(char *drive, char *mnttype)
|
||||
Get disc tyhpe associated with cd_obj.
|
||||
*/
|
||||
static discmode_t
|
||||
_get_discmode_linux (void *user_data)
|
||||
_get_discmode_linux (void *p_user_data)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
int32_t i_discmode;
|
||||
i_discmode = ioctl (env->gen.fd, CDROM_DISC_STATUS);
|
||||
i_discmode = ioctl (p_env->gen.fd, CDROM_DISC_STATUS);
|
||||
|
||||
if (i_discmode < 0) return CDIO_DISC_MODE_ERROR;
|
||||
|
||||
@@ -255,10 +259,46 @@ cdio_check_mounts(const char *mtab)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
_set_bsize (int fd, unsigned int bsize)
|
||||
/*!
|
||||
Run a SCSI MMC command.
|
||||
|
||||
cdio CD structure set by cdio_open().
|
||||
i_timeout time in milliseconds we will wait for the command
|
||||
to complete. If this value is -1, use the default
|
||||
time-out value.
|
||||
p_buf Buffer for data, both sending and receiving
|
||||
i_buf Size of buffer
|
||||
e_direction direction the transfer is to go.
|
||||
cdb CDB bytes. All values that are needed should be set on
|
||||
input. We'll figure out what the right CDB length should be.
|
||||
|
||||
We return true if command completed successfully and false if not.
|
||||
*/
|
||||
static int
|
||||
scsi_mmc_run_cmd_linux( const _img_private_t *p_env, int i_timeout,
|
||||
unsigned int i_cdb, const scsi_mmc_cdb_t *p_cdb,
|
||||
scsi_mmc_direction_t e_direction,
|
||||
unsigned int i_buf, /*out*/ void *p_buf )
|
||||
{
|
||||
struct cdrom_generic_command cgc;
|
||||
memset (&cgc, 0, sizeof (struct cdrom_generic_command));
|
||||
memcpy(&cgc.cmd, p_cdb, i_cdb);
|
||||
cgc.buflen = i_buf;
|
||||
cgc.buffer = p_buf;
|
||||
cgc.data_direction = SCSI_MMC_DATA_READ ? CGC_DATA_READ : CGC_DATA_WRITE;
|
||||
|
||||
#ifdef HAVE_LINUX_CDROM_TIMEOUT
|
||||
if (i_timeout >= 0)
|
||||
cgc.timeout = i_timeout;
|
||||
#endif
|
||||
|
||||
return ioctl (p_env->gen.fd, CDROM_SEND_PACKET, &cgc);
|
||||
}
|
||||
|
||||
static int
|
||||
_set_bsize (_img_private_t *p_env, unsigned int bsize)
|
||||
{
|
||||
scsi_mmc_cdb_t cdb;
|
||||
|
||||
struct
|
||||
{
|
||||
@@ -277,65 +317,57 @@ _set_bsize (int fd, unsigned int bsize)
|
||||
} mh;
|
||||
|
||||
memset (&mh, 0, sizeof (mh));
|
||||
memset (&cgc, 0, sizeof (struct cdrom_generic_command));
|
||||
|
||||
CDIO_MMC_SET_COMMAND(cgc.cmd, CDIO_MMC_GPCMD_MODE_SELECT_6);
|
||||
|
||||
cgc.cmd[1] = 1 << 4;
|
||||
cgc.cmd[4] = 12;
|
||||
|
||||
cgc.buflen = sizeof (mh);
|
||||
cgc.buffer = (void *) &mh;
|
||||
|
||||
cgc.data_direction = CGC_DATA_WRITE;
|
||||
|
||||
mh.block_desc_length = 0x08;
|
||||
mh.block_length_hi = (bsize >> 16) & 0xff;
|
||||
mh.block_length_med = (bsize >> 8) & 0xff;
|
||||
mh.block_length_lo = (bsize >> 0) & 0xff;
|
||||
|
||||
return ioctl (fd, CDROM_SEND_PACKET, &cgc);
|
||||
memset (&cdb, 0, sizeof (cdb));
|
||||
|
||||
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_MODE_SELECT_6);
|
||||
|
||||
cdb.field[1] = 1 << 4;
|
||||
cdb.field[4] = 12;
|
||||
|
||||
return scsi_mmc_run_cmd_linux (p_env, DEFAULT_TIMEOUT,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_WRITE, sizeof(mh), &mh);
|
||||
}
|
||||
|
||||
/* Packet driver to read mode2 sectors.
|
||||
Can read only up to 25 blocks.
|
||||
*/
|
||||
static int
|
||||
_read_sectors_mmc (int fd, void *buf, lba_t lba, int sector_type,
|
||||
unsigned int nblocks)
|
||||
_read_sectors_mmc (_img_private_t *p_env, void *p_buf, lba_t lba,
|
||||
int sector_type, unsigned int nblocks)
|
||||
{
|
||||
cgc_t cgc;
|
||||
scsi_mmc_cdb_t cdb;
|
||||
|
||||
memset (&cgc, 0, sizeof (cgc_t));
|
||||
memset (&cdb, 0, sizeof (scsi_mmc_cdb_t));
|
||||
|
||||
cgc.cmd[0] = CDIO_MMC_GPCMD_READ_CD;
|
||||
CDIO_MMC_SET_READ_TYPE (cgc.cmd, sector_type);
|
||||
CDIO_MMC_SET_READ_LBA (cgc.cmd, lba);
|
||||
CDIO_MMC_SET_READ_LENGTH(cgc.cmd, nblocks);
|
||||
CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cgc.cmd, CDIO_MMC_MCSB_ALL_HEADERS);
|
||||
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD);
|
||||
CDIO_MMC_SET_READ_TYPE (cdb.field, sector_type);
|
||||
CDIO_MMC_SET_READ_LBA (cdb.field, lba);
|
||||
CDIO_MMC_SET_READ_LENGTH(cdb.field, nblocks);
|
||||
CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb.field,
|
||||
CDIO_MMC_MCSB_ALL_HEADERS);
|
||||
|
||||
cgc.buflen = CDIO_CD_FRAMESIZE_RAW * nblocks;
|
||||
cgc.buffer = buf;
|
||||
|
||||
#ifdef HAVE_LINUX_CDROM_TIMEOUT
|
||||
cgc.timeout = 500;
|
||||
#endif
|
||||
cgc.data_direction = CGC_DATA_READ;
|
||||
|
||||
return ioctl (fd, CDROM_SEND_PACKET, &cgc);
|
||||
|
||||
return 0;
|
||||
return scsi_mmc_run_cmd_linux (p_env, DEFAULT_TIMEOUT,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_READ,
|
||||
CDIO_CD_FRAMESIZE_RAW * nblocks,
|
||||
p_buf);
|
||||
}
|
||||
|
||||
/* MMC driver to read audio sectors.
|
||||
Can read only up to 25 blocks.
|
||||
*/
|
||||
static int
|
||||
_read_audio_sectors_linux (void *user_data, void *buf, lsn_t lsn,
|
||||
_read_audio_sectors_linux (void *p_user_data, void *buf, lsn_t lsn,
|
||||
unsigned int nblocks)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
return _read_sectors_mmc( env->gen.fd, buf, lsn,
|
||||
_img_private_t *p_env = p_user_data;
|
||||
return _read_sectors_mmc( p_env, buf, lsn,
|
||||
CDIO_MMC_READ_TYPE_CDDA, nblocks);
|
||||
}
|
||||
|
||||
@@ -343,56 +375,52 @@ _read_audio_sectors_linux (void *user_data, void *buf, lsn_t lsn,
|
||||
Can read only up to 25 blocks.
|
||||
*/
|
||||
static int
|
||||
_read_mode2_sectors_mmc (int fd, void *buf, lba_t lba,
|
||||
_read_mode2_sectors_mmc (_img_private_t *p_env, void *p_buf, lba_t lba,
|
||||
unsigned int nblocks, bool b_read_10)
|
||||
{
|
||||
struct cdrom_generic_command cgc;
|
||||
scsi_mmc_cdb_t cdb;
|
||||
|
||||
memset (&cgc, 0, sizeof (struct cdrom_generic_command));
|
||||
memset (&cdb, 0, sizeof (scsi_mmc_cdb_t));
|
||||
|
||||
CDIO_MMC_SET_COMMAND(cgc.cmd, b_read_10
|
||||
CDIO_MMC_SET_COMMAND(cdb.field, b_read_10
|
||||
? CDIO_MMC_GPCMD_READ_10 : CDIO_MMC_GPCMD_READ_CD);
|
||||
|
||||
CDIO_MMC_SET_READ_LBA(cgc.cmd, lba);
|
||||
CDIO_MMC_SET_READ_LENGTH(cgc.cmd, nblocks);
|
||||
CDIO_MMC_SET_READ_LBA(cdb.field, lba);
|
||||
CDIO_MMC_SET_READ_LENGTH(cdb.field, nblocks);
|
||||
|
||||
if (!b_read_10) {
|
||||
cgc.cmd[1] = 0; /* sector size mode2 */
|
||||
cgc.cmd[9] = 0x58; /* 2336 mode2 */
|
||||
cdb.field[1] = 0; /* sector size mode2 */
|
||||
cdb.field[9] = 0x58; /* 2336 mode2 */
|
||||
}
|
||||
|
||||
cgc.buflen = M2RAW_SECTOR_SIZE * nblocks;
|
||||
cgc.buffer = buf;
|
||||
|
||||
#ifdef HAVE_LINUX_CDROM_TIMEOUT
|
||||
cgc.timeout = 500;
|
||||
#endif
|
||||
cgc.data_direction = CGC_DATA_READ;
|
||||
|
||||
if (b_read_10)
|
||||
{
|
||||
int retval;
|
||||
|
||||
if ((retval = _set_bsize (fd, M2RAW_SECTOR_SIZE)))
|
||||
if (b_read_10) {
|
||||
int retval;
|
||||
|
||||
if ((retval = _set_bsize (p_env, M2RAW_SECTOR_SIZE)))
|
||||
return retval;
|
||||
|
||||
if ((retval = scsi_mmc_run_cmd_linux (p_env, 0,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_READ,
|
||||
M2RAW_SECTOR_SIZE * nblocks, p_buf)))
|
||||
{
|
||||
_set_bsize (p_env, CDIO_CD_FRAMESIZE);
|
||||
return retval;
|
||||
|
||||
if ((retval = ioctl (fd, CDROM_SEND_PACKET, &cgc)))
|
||||
{
|
||||
_set_bsize (fd, CDIO_CD_FRAMESIZE);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if ((retval = _set_bsize (fd, CDIO_CD_FRAMESIZE)))
|
||||
return retval;
|
||||
}
|
||||
else
|
||||
return ioctl (fd, CDROM_SEND_PACKET, &cgc);
|
||||
}
|
||||
|
||||
if ((retval = _set_bsize (p_env, CDIO_CD_FRAMESIZE)))
|
||||
return retval;
|
||||
} else
|
||||
return scsi_mmc_run_cmd_linux (p_env, 0,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_READ,
|
||||
M2RAW_SECTOR_SIZE * nblocks, p_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
_read_mode2_sectors (int fd, void *buf, lba_t lba,
|
||||
_read_mode2_sectors (_img_private_t *p_env, void *p_buf, lba_t lba,
|
||||
unsigned int nblocks, bool b_read_10)
|
||||
{
|
||||
unsigned int l = 0;
|
||||
@@ -401,10 +429,10 @@ _read_mode2_sectors (int fd, void *buf, lba_t lba,
|
||||
while (nblocks > 0)
|
||||
{
|
||||
const unsigned nblocks2 = (nblocks > 25) ? 25 : nblocks;
|
||||
void *buf2 = ((char *)buf ) + (l * M2RAW_SECTOR_SIZE);
|
||||
void *p_buf2 = ((char *)p_buf ) + (l * M2RAW_SECTOR_SIZE);
|
||||
|
||||
retval |= _read_mode2_sectors_mmc (fd, buf2, lba + l, nblocks2,
|
||||
b_read_10);
|
||||
retval |= _read_mode2_sectors_mmc (p_env, p_buf2, lba + l,
|
||||
nblocks2, b_read_10);
|
||||
|
||||
if (retval)
|
||||
break;
|
||||
@@ -421,16 +449,16 @@ _read_mode2_sectors (int fd, void *buf, lba_t lba,
|
||||
from lsn. Returns 0 if no error.
|
||||
*/
|
||||
static int
|
||||
_read_mode1_sector_linux (void *env, void *data, lsn_t lsn,
|
||||
_read_mode1_sector_linux (void *p_user_data, void *p_data, lsn_t lsn,
|
||||
bool b_form2)
|
||||
{
|
||||
|
||||
#if FIXED
|
||||
char buf[M2RAW_SECTOR_SIZE] = { 0, };
|
||||
struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
|
||||
struct cdrom_msf *p_msf = (struct cdrom_msf *) &buf;
|
||||
msf_t _msf;
|
||||
|
||||
_img_private_t *_obj = env;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
|
||||
msf->cdmsf_min0 = from_bcd8(_msf.m);
|
||||
@@ -446,7 +474,7 @@ _read_mode1_sector_linux (void *env, void *data, lsn_t lsn,
|
||||
break;
|
||||
|
||||
case _AM_IOCTL:
|
||||
if (ioctl (_obj->gen.fd, CDROMREADMODE1, &buf) == -1)
|
||||
if (ioctl (p_env->gen.fd, CDROMREADMODE1, &buf) == -1)
|
||||
{
|
||||
perror ("ioctl()");
|
||||
return 1;
|
||||
@@ -456,20 +484,20 @@ _read_mode1_sector_linux (void *env, void *data, lsn_t lsn,
|
||||
|
||||
case _AM_READ_CD:
|
||||
case _AM_READ_10:
|
||||
if (_read_mode2_sectors (_obj->gen.fd, buf, lsn, 1,
|
||||
(_obj->access_mode == _AM_READ_10)))
|
||||
if (_read_mode2_sectors (p_env->gen.fd, buf, lsn, 1,
|
||||
(p_env->access_mode == _AM_READ_10)))
|
||||
{
|
||||
perror ("ioctl()");
|
||||
if (_obj->access_mode == _AM_READ_CD)
|
||||
if (p_env->access_mode == _AM_READ_CD)
|
||||
{
|
||||
cdio_info ("READ_CD failed; switching to READ_10 mode...");
|
||||
_obj->access_mode = _AM_READ_10;
|
||||
p_env->access_mode = _AM_READ_10;
|
||||
goto retry;
|
||||
}
|
||||
else
|
||||
{
|
||||
cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode...");
|
||||
_obj->access_mode = _AM_IOCTL;
|
||||
p_env->access_mode = _AM_IOCTL;
|
||||
goto retry;
|
||||
}
|
||||
return 1;
|
||||
@@ -481,7 +509,7 @@ _read_mode1_sector_linux (void *env, void *data, lsn_t lsn,
|
||||
b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE);
|
||||
|
||||
#else
|
||||
return cdio_generic_read_form1_sector(env, data, lsn);
|
||||
return cdio_generic_read_form1_sector(p_user_data, p_data, lsn);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -492,17 +520,17 @@ _read_mode1_sector_linux (void *env, void *data, lsn_t lsn,
|
||||
Returns 0 if no error.
|
||||
*/
|
||||
static int
|
||||
_read_mode1_sectors_linux (void *user_data, void *data, lsn_t lsn,
|
||||
_read_mode1_sectors_linux (void *p_user_data, void *p_data, lsn_t lsn,
|
||||
bool b_form2, unsigned int nblocks)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
unsigned int i;
|
||||
int retval;
|
||||
unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
|
||||
|
||||
for (i = 0; i < nblocks; i++) {
|
||||
if ( (retval = _read_mode1_sector_linux (env,
|
||||
((char *)data) + (blocksize * i),
|
||||
if ( (retval = _read_mode1_sector_linux (p_env,
|
||||
((char *)p_data) + (blocksize * i),
|
||||
lsn + i, b_form2)) )
|
||||
return retval;
|
||||
}
|
||||
@@ -514,14 +542,14 @@ _read_mode1_sectors_linux (void *user_data, void *data, lsn_t lsn,
|
||||
from lsn. Returns 0 if no error.
|
||||
*/
|
||||
static int
|
||||
_read_mode2_sector_linux (void *user_data, void *data, lsn_t lsn,
|
||||
_read_mode2_sector_linux (void *p_user_data, void *p_data, lsn_t lsn,
|
||||
bool b_form2)
|
||||
{
|
||||
char buf[M2RAW_SECTOR_SIZE] = { 0, };
|
||||
struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
|
||||
msf_t _msf;
|
||||
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
|
||||
msf->cdmsf_min0 = from_bcd8(_msf.m);
|
||||
@@ -529,7 +557,7 @@ _read_mode2_sector_linux (void *user_data, void *data, lsn_t lsn,
|
||||
msf->cdmsf_frame0 = from_bcd8(_msf.f);
|
||||
|
||||
retry:
|
||||
switch (env->access_mode)
|
||||
switch (p_env->access_mode)
|
||||
{
|
||||
case _AM_NONE:
|
||||
cdio_warn ("no way to read mode2");
|
||||
@@ -537,7 +565,7 @@ _read_mode2_sector_linux (void *user_data, void *data, lsn_t lsn,
|
||||
break;
|
||||
|
||||
case _AM_IOCTL:
|
||||
if (ioctl (env->gen.fd, CDROMREADMODE2, &buf) == -1)
|
||||
if (ioctl (p_env->gen.fd, CDROMREADMODE2, &buf) == -1)
|
||||
{
|
||||
perror ("ioctl()");
|
||||
return 1;
|
||||
@@ -547,20 +575,20 @@ _read_mode2_sector_linux (void *user_data, void *data, lsn_t lsn,
|
||||
|
||||
case _AM_READ_CD:
|
||||
case _AM_READ_10:
|
||||
if (_read_mode2_sectors (env->gen.fd, buf, lsn, 1,
|
||||
(env->access_mode == _AM_READ_10)))
|
||||
if (_read_mode2_sectors (p_env, buf, lsn, 1,
|
||||
(p_env->access_mode == _AM_READ_10)))
|
||||
{
|
||||
perror ("ioctl()");
|
||||
if (env->access_mode == _AM_READ_CD)
|
||||
if (p_env->access_mode == _AM_READ_CD)
|
||||
{
|
||||
cdio_info ("READ_CD failed; switching to READ_10 mode...");
|
||||
env->access_mode = _AM_READ_10;
|
||||
p_env->access_mode = _AM_READ_10;
|
||||
goto retry;
|
||||
}
|
||||
else
|
||||
{
|
||||
cdio_info ("READ_10 failed; switching to ioctl(CDROMREADMODE2) mode...");
|
||||
env->access_mode = _AM_IOCTL;
|
||||
p_env->access_mode = _AM_IOCTL;
|
||||
goto retry;
|
||||
}
|
||||
return 1;
|
||||
@@ -569,9 +597,9 @@ _read_mode2_sector_linux (void *user_data, void *data, lsn_t lsn,
|
||||
}
|
||||
|
||||
if (b_form2)
|
||||
memcpy (data, buf, M2RAW_SECTOR_SIZE);
|
||||
memcpy (p_data, buf, M2RAW_SECTOR_SIZE);
|
||||
else
|
||||
memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE);
|
||||
memcpy (((char *)p_data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -582,17 +610,17 @@ _read_mode2_sector_linux (void *user_data, void *data, lsn_t lsn,
|
||||
Returns 0 if no error.
|
||||
*/
|
||||
static int
|
||||
_read_mode2_sectors_linux (void *user_data, void *data, lsn_t lsn,
|
||||
_read_mode2_sectors_linux (void *p_user_data, void *data, lsn_t lsn,
|
||||
bool b_form2, unsigned int nblocks)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
unsigned int i;
|
||||
unsigned int i_blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
|
||||
|
||||
/* For each frame, pick out the data part we need */
|
||||
for (i = 0; i < nblocks; i++) {
|
||||
int retval;
|
||||
if ( (retval = _read_mode2_sector_linux (env,
|
||||
if ( (retval = _read_mode2_sector_linux (p_env,
|
||||
((char *)data) + (i_blocksize * i),
|
||||
lsn + i, b_form2)) )
|
||||
return retval;
|
||||
@@ -604,16 +632,16 @@ _read_mode2_sectors_linux (void *user_data, void *data, lsn_t lsn,
|
||||
Return the size of the CD in logical block address (LBA) units.
|
||||
*/
|
||||
static uint32_t
|
||||
_stat_size_linux (void *user_data)
|
||||
_stat_size_linux (void *p_user_data)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
struct cdrom_tocentry tocent;
|
||||
uint32_t size;
|
||||
|
||||
tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK;
|
||||
tocent.cdte_format = CDROM_LBA;
|
||||
if (ioctl (env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1)
|
||||
if (ioctl (p_env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1)
|
||||
{
|
||||
perror ("ioctl(CDROMREADTOCENTRY)");
|
||||
exit (EXIT_FAILURE);
|
||||
@@ -633,18 +661,18 @@ _stat_size_linux (void *user_data)
|
||||
0 is returned if no error was found, and nonzero if there as an error.
|
||||
*/
|
||||
static int
|
||||
_set_arg_linux (void *user_data, const char key[], const char value[])
|
||||
_set_arg_linux (void *p_user_data, const char key[], const char value[])
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
if (!strcmp (key, "source"))
|
||||
{
|
||||
if (!value)
|
||||
return -2;
|
||||
|
||||
free (env->gen.source_name);
|
||||
free (p_env->gen.source_name);
|
||||
|
||||
env->gen.source_name = strdup (value);
|
||||
p_env->gen.source_name = strdup (value);
|
||||
}
|
||||
else if (!strcmp (key, "access-mode"))
|
||||
{
|
||||
@@ -661,12 +689,12 @@ _set_arg_linux (void *user_data, const char key[], const char value[])
|
||||
Return false if successful or true if an error.
|
||||
*/
|
||||
static bool
|
||||
_cdio_read_toc (_img_private_t *env)
|
||||
_cdio_read_toc (_img_private_t *p_env)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* read TOC header */
|
||||
if ( ioctl(env->gen.fd, CDROMREADTOCHDR, &env->tochdr) == -1 ) {
|
||||
if ( ioctl(p_env->gen.fd, CDROMREADTOCHDR, &p_env->tochdr) == -1 ) {
|
||||
cdio_warn("%s: %s\n",
|
||||
"error in ioctl CDROMREADTOCHDR", strerror(errno));
|
||||
return false;
|
||||
@@ -674,10 +702,10 @@ _cdio_read_toc (_img_private_t *env)
|
||||
|
||||
/* read individual tracks */
|
||||
for (i= FIRST_TRACK_NUM; i<=TOTAL_TRACKS; i++) {
|
||||
env->tocent[i-FIRST_TRACK_NUM].cdte_track = i;
|
||||
env->tocent[i-FIRST_TRACK_NUM].cdte_format = CDROM_MSF;
|
||||
if ( ioctl(env->gen.fd, CDROMREADTOCENTRY,
|
||||
&env->tocent[i-FIRST_TRACK_NUM]) == -1 ) {
|
||||
p_env->tocent[i-FIRST_TRACK_NUM].cdte_track = i;
|
||||
p_env->tocent[i-FIRST_TRACK_NUM].cdte_format = CDROM_MSF;
|
||||
if ( ioctl(p_env->gen.fd, CDROMREADTOCENTRY,
|
||||
&p_env->tocent[i-FIRST_TRACK_NUM]) == -1 ) {
|
||||
cdio_warn("%s %d: %s\n",
|
||||
"error in ioctl CDROMREADTOCENTRY for track",
|
||||
i, strerror(errno));
|
||||
@@ -693,11 +721,11 @@ _cdio_read_toc (_img_private_t *env)
|
||||
}
|
||||
|
||||
/* read the lead-out track */
|
||||
env->tocent[TOTAL_TRACKS].cdte_track = CDIO_CDROM_LEADOUT_TRACK;
|
||||
env->tocent[TOTAL_TRACKS].cdte_format = CDROM_MSF;
|
||||
p_env->tocent[TOTAL_TRACKS].cdte_track = CDIO_CDROM_LEADOUT_TRACK;
|
||||
p_env->tocent[TOTAL_TRACKS].cdte_format = CDROM_MSF;
|
||||
|
||||
if (ioctl(env->gen.fd, CDROMREADTOCENTRY,
|
||||
&env->tocent[TOTAL_TRACKS]) == -1 ) {
|
||||
if (ioctl(p_env->gen.fd, CDROMREADTOCENTRY,
|
||||
&p_env->tocent[TOTAL_TRACKS]) == -1 ) {
|
||||
cdio_warn("%s: %s\n",
|
||||
"error in ioctl CDROMREADTOCENTRY for lead-out",
|
||||
strerror(errno));
|
||||
@@ -711,7 +739,7 @@ _cdio_read_toc (_img_private_t *env)
|
||||
i, msf->minute, msf->second, msf->frame);
|
||||
*/
|
||||
|
||||
env->gen.toc_init = true;
|
||||
p_env->gen.toc_init = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -739,35 +767,31 @@ set_cdtext_field_linux(void *user_data, track_t i_track,
|
||||
not exist.
|
||||
*/
|
||||
static bool
|
||||
_init_cdtext_linux (_img_private_t *env)
|
||||
_init_cdtext_linux (_img_private_t *p_env)
|
||||
{
|
||||
|
||||
struct cdrom_generic_command cdc;
|
||||
struct request_sense sense;
|
||||
scsi_mmc_cdb_t cdb;
|
||||
unsigned char wdata[2000]= {0, }; /* Data read from device starts here */
|
||||
int status;
|
||||
|
||||
memset(&cdc, 0, sizeof(struct cdrom_generic_command));
|
||||
memset(&sense, 0, sizeof(struct request_sense));
|
||||
memset (&cdb, 0, sizeof (scsi_mmc_cdb_t));
|
||||
|
||||
/* Operation code */
|
||||
CDIO_MMC_SET_COMMAND(cdc.cmd, CDIO_MMC_GPCMD_READ_TOC);
|
||||
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC);
|
||||
|
||||
/* Format */
|
||||
cdc.cmd[2] = CDIO_MMC_READTOC_FMT_CDTEXT;
|
||||
cdb.field[2] = CDIO_MMC_READTOC_FMT_CDTEXT;
|
||||
|
||||
cdc.buffer = wdata;
|
||||
cdc.buflen = sizeof(wdata);
|
||||
cdc.stat = 0;
|
||||
cdc.sense = &sense;
|
||||
cdc.data_direction = CGC_DATA_READ;
|
||||
status = scsi_mmc_run_cmd_linux (p_env, DEFAULT_TIMEOUT,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_READ, sizeof(wdata), &wdata);
|
||||
|
||||
status = ioctl(env->gen.fd, CDROM_SEND_PACKET, (void *)&cdc);
|
||||
if (status < 0) {
|
||||
cdio_info ("CDTEXT reading failed\n");
|
||||
cdio_info ("CD-TEXT reading failed\n");
|
||||
p_env->b_cdtext_error = true;
|
||||
return false;
|
||||
} else {
|
||||
return cdtext_data_init(env, FIRST_TRACK_NUM, wdata,
|
||||
return cdtext_data_init(p_env, FIRST_TRACK_NUM, wdata,
|
||||
set_cdtext_field_linux);
|
||||
}
|
||||
}
|
||||
@@ -780,78 +804,63 @@ _init_cdtext_linux (_img_private_t *env)
|
||||
or CD-TEXT information does not exist.
|
||||
*/
|
||||
static const cdtext_t *
|
||||
_get_cdtext_linux (void *user_data, track_t i_track)
|
||||
_get_cdtext_linux (void *p_user_data, track_t i_track)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
if ( NULL == env ||
|
||||
if ( NULL == p_env ||
|
||||
(0 != i_track
|
||||
&& i_track >= TOTAL_TRACKS+FIRST_TRACK_NUM ) )
|
||||
return NULL;
|
||||
|
||||
env->b_cdtext_init = _init_cdtext_linux(env);
|
||||
if (!env->b_cdtext_init) return NULL;
|
||||
p_env->b_cdtext_init = _init_cdtext_linux(p_env);
|
||||
if (!p_env->b_cdtext_init || p_env->b_cdtext_error) return NULL;
|
||||
|
||||
if (0 == i_track)
|
||||
return &(env->cdtext);
|
||||
return &(p_env->cdtext);
|
||||
else
|
||||
return &(env->cdtext_track[i_track-FIRST_TRACK_NUM]);
|
||||
return &(p_env->cdtext_track[i_track-FIRST_TRACK_NUM]);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Eject using SCSI commands. Return 1 if successful, 0 otherwise.
|
||||
* Eject using SCSI MMC commands. Return 1 if successful, 0 otherwise.
|
||||
*/
|
||||
static int
|
||||
_eject_media_mmc(int fd)
|
||||
_eject_media_mmc(_img_private_t *p_env)
|
||||
{
|
||||
int status;
|
||||
struct sdata {
|
||||
unsigned int inlen; /* Length of data written to device */
|
||||
unsigned int outlen; /* Length of data read from device */
|
||||
char cdb[10]; /* SCSI command bytes (6 <= x <= 16) */
|
||||
} scsi_cmd;
|
||||
int i_status;
|
||||
scsi_mmc_cdb_t cdb;
|
||||
uint8_t buf[1];
|
||||
|
||||
CDIO_MMC_SET_COMMAND(scsi_cmd.cdb, CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL);
|
||||
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL);
|
||||
|
||||
scsi_cmd.inlen = 0;
|
||||
scsi_cmd.outlen = 0;
|
||||
scsi_cmd.cdb[1] = 0;
|
||||
scsi_cmd.cdb[2] = 0;
|
||||
scsi_cmd.cdb[3] = 0;
|
||||
scsi_cmd.cdb[4] = 0;
|
||||
scsi_cmd.cdb[5] = 0;
|
||||
status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd);
|
||||
if (status != 0)
|
||||
return status;
|
||||
i_status = scsi_mmc_run_cmd_linux (p_env, DEFAULT_TIMEOUT,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_WRITE, 0, &buf);
|
||||
if (0 != i_status)
|
||||
return i_status;
|
||||
|
||||
scsi_cmd.inlen = 0;
|
||||
scsi_cmd.outlen = 0;
|
||||
CDIO_MMC_SET_COMMAND(scsi_cmd.cdb, CDIO_MMC_GPCMD_START_STOP);
|
||||
scsi_cmd.cdb[1] = 0;
|
||||
scsi_cmd.cdb[2] = 0;
|
||||
scsi_cmd.cdb[3] = 0;
|
||||
scsi_cmd.cdb[4] = 1;
|
||||
scsi_cmd.cdb[5] = 0;
|
||||
status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd);
|
||||
if (status != 0)
|
||||
return status;
|
||||
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP);
|
||||
cdb.field[4] = 1;
|
||||
i_status = scsi_mmc_run_cmd_linux (p_env, DEFAULT_TIMEOUT,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_WRITE, 0, &buf);
|
||||
if (0 != i_status)
|
||||
return i_status;
|
||||
|
||||
scsi_cmd.inlen = 0;
|
||||
scsi_cmd.outlen = 0;
|
||||
CDIO_MMC_SET_COMMAND(scsi_cmd.cdb, CDIO_MMC_GPCMD_START_STOP);
|
||||
scsi_cmd.cdb[1] = 0;
|
||||
scsi_cmd.cdb[2] = 0;
|
||||
scsi_cmd.cdb[3] = 0;
|
||||
scsi_cmd.cdb[4] = 2; /* eject */
|
||||
scsi_cmd.cdb[5] = 0;
|
||||
status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd);
|
||||
if (status != 0)
|
||||
return status;
|
||||
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP);
|
||||
cdb.field[4] = 2; /* eject */
|
||||
|
||||
i_status = scsi_mmc_run_cmd_linux (p_env, DEFAULT_TIMEOUT,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_WRITE, 0, &buf);
|
||||
if (0 != i_status)
|
||||
return i_status;
|
||||
|
||||
/* force kernel to reread partition table when new disc inserted */
|
||||
status = ioctl(fd, BLKRRPART);
|
||||
return (status);
|
||||
i_status = ioctl(p_env->gen.fd, BLKRRPART);
|
||||
return (i_status);
|
||||
|
||||
}
|
||||
|
||||
@@ -860,16 +869,14 @@ _eject_media_mmc(int fd)
|
||||
Return 0 if success and 1 for failure, and 2 if no routine.
|
||||
*/
|
||||
static int
|
||||
_eject_media_linux (void *user_data) {
|
||||
_eject_media_linux (void *p_user_data) {
|
||||
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
int ret=2;
|
||||
int status;
|
||||
int fd;
|
||||
|
||||
close(env->gen.fd);
|
||||
env->gen.fd = -1;
|
||||
if ((fd = open (env->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) {
|
||||
if ((fd = open (p_env->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) {
|
||||
if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) {
|
||||
switch(status) {
|
||||
case CDS_TRAY_OPEN:
|
||||
@@ -882,7 +889,7 @@ _eject_media_linux (void *user_data) {
|
||||
if((ret = ioctl(fd, CDROMEJECT)) != 0) {
|
||||
int eject_error = errno;
|
||||
/* Try ejecting the MMC way... */
|
||||
ret = _eject_media_mmc(fd);
|
||||
ret = _eject_media_mmc(p_env);
|
||||
if (0 != ret) {
|
||||
cdio_warn("ioctl CDROMEJECT failed: %s\n", strerror(eject_error));
|
||||
ret = 1;
|
||||
@@ -898,9 +905,11 @@ _eject_media_linux (void *user_data) {
|
||||
ret=1;
|
||||
}
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
return 2;
|
||||
} else
|
||||
ret = 2;
|
||||
close(p_env->gen.fd);
|
||||
p_env->gen.fd = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -933,11 +942,11 @@ _get_arg_linux (void *env, const char key[])
|
||||
CDIO_INVALID_TRACK is returned on error.
|
||||
*/
|
||||
static track_t
|
||||
_get_first_track_num_linux(void *user_data)
|
||||
_get_first_track_num_linux(void *p_user_data)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
if (!env->gen.toc_init) _cdio_read_toc (env) ;
|
||||
if (!p_env->gen.toc_init) _cdio_read_toc (p_env) ;
|
||||
|
||||
return FIRST_TRACK_NUM;
|
||||
}
|
||||
@@ -1031,11 +1040,11 @@ _get_drive_cap_linux (const void *env,
|
||||
CDIO_INVALID_TRACK is returned on error.
|
||||
*/
|
||||
static track_t
|
||||
_get_num_tracks_linux(void *user_data)
|
||||
_get_num_tracks_linux(void *p_user_data)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
if (!env->gen.toc_init) _cdio_read_toc (env) ;
|
||||
if (!p_env->gen.toc_init) _cdio_read_toc (p_env) ;
|
||||
|
||||
return TOTAL_TRACKS;
|
||||
}
|
||||
@@ -1044,9 +1053,9 @@ _get_num_tracks_linux(void *user_data)
|
||||
Get format of track.
|
||||
*/
|
||||
static track_format_t
|
||||
_get_track_format_linux(void *user_data, track_t i_track)
|
||||
_get_track_format_linux(void *p_user_data, track_t i_track)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
if (i_track > (TOTAL_TRACKS+FIRST_TRACK_NUM) || i_track < FIRST_TRACK_NUM)
|
||||
return TRACK_FORMAT_ERROR;
|
||||
@@ -1056,10 +1065,10 @@ _get_track_format_linux(void *user_data, track_t i_track)
|
||||
/* This is pretty much copied from the "badly broken" cdrom_count_tracks
|
||||
in linux/cdrom.c.
|
||||
*/
|
||||
if (env->tocent[i_track].cdte_ctrl & CDIO_CDROM_DATA_TRACK) {
|
||||
if (env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK)
|
||||
if (p_env->tocent[i_track].cdte_ctrl & CDIO_CDROM_DATA_TRACK) {
|
||||
if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK)
|
||||
return TRACK_FORMAT_CDI;
|
||||
else if (env->tocent[i_track].cdte_format == CDIO_CDROM_XA_TRACK)
|
||||
else if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_XA_TRACK)
|
||||
return TRACK_FORMAT_XA;
|
||||
else
|
||||
return TRACK_FORMAT_DATA;
|
||||
@@ -1077,11 +1086,11 @@ _get_track_format_linux(void *user_data, track_t i_track)
|
||||
FIXME: there's gotta be a better design for this and get_track_format?
|
||||
*/
|
||||
static bool
|
||||
_get_track_green_linux(void *user_data, track_t i_track)
|
||||
_get_track_green_linux(void *p_user_data, track_t i_track)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
if (!env->gen.toc_init) _cdio_read_toc (env) ;
|
||||
if (!p_env->gen.toc_init) _cdio_read_toc (p_env) ;
|
||||
|
||||
if (i_track >= (TOTAL_TRACKS+FIRST_TRACK_NUM) || i_track < FIRST_TRACK_NUM)
|
||||
return false;
|
||||
@@ -1091,7 +1100,7 @@ _get_track_green_linux(void *user_data, track_t i_track)
|
||||
/* FIXME: Dunno if this is the right way, but it's what
|
||||
I was using in cd-info for a while.
|
||||
*/
|
||||
return ((env->tocent[i_track].cdte_ctrl & 2) != 0);
|
||||
return ((p_env->tocent[i_track].cdte_ctrl & 2) != 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1104,13 +1113,13 @@ _get_track_green_linux(void *user_data, track_t i_track)
|
||||
False is returned if there is no track entry.
|
||||
*/
|
||||
static bool
|
||||
_get_track_msf_linux(void *user_data, track_t i_track, msf_t *msf)
|
||||
_get_track_msf_linux(void *p_user_data, track_t i_track, msf_t *msf)
|
||||
{
|
||||
_img_private_t *env = user_data;
|
||||
_img_private_t *p_env = p_user_data;
|
||||
|
||||
if (NULL == msf) return false;
|
||||
|
||||
if (!env->gen.toc_init) _cdio_read_toc (env) ;
|
||||
if (!p_env->gen.toc_init) _cdio_read_toc (p_env) ;
|
||||
|
||||
if (i_track == CDIO_CDROM_LEADOUT_TRACK)
|
||||
i_track = TOTAL_TRACKS + FIRST_TRACK_NUM;
|
||||
@@ -1118,7 +1127,8 @@ _get_track_msf_linux(void *user_data, track_t i_track, msf_t *msf)
|
||||
if (i_track > (TOTAL_TRACKS+FIRST_TRACK_NUM) || i_track < FIRST_TRACK_NUM) {
|
||||
return false;
|
||||
} else {
|
||||
struct cdrom_msf0 *msf0= &env->tocent[i_track-FIRST_TRACK_NUM].cdte_addr.msf;
|
||||
struct cdrom_msf0 *msf0=
|
||||
&p_env->tocent[i_track-FIRST_TRACK_NUM].cdte_addr.msf;
|
||||
msf->m = to_bcd8(msf0->minute);
|
||||
msf->s = to_bcd8(msf0->second);
|
||||
msf->f = to_bcd8(msf0->frame);
|
||||
@@ -1307,6 +1317,7 @@ cdio_open_am_linux (const char *psz_orig_source, const char *access_mode)
|
||||
_data->gen.init = false;
|
||||
_data->gen.fd = -1;
|
||||
_data->b_cdtext_init = false;
|
||||
_data->b_cdtext_error = false;
|
||||
|
||||
if (NULL == psz_orig_source) {
|
||||
psz_source=cdio_get_default_device_linux();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: _cdio_sunos.c,v 1.56 2004/07/19 01:29:04 rocky Exp $
|
||||
$Id: _cdio_sunos.c,v 1.57 2004/07/22 09:52:17 rocky Exp $
|
||||
|
||||
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
#ifdef HAVE_SOLARIS_CDROM
|
||||
|
||||
static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.56 2004/07/19 01:29:04 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.57 2004/07/22 09:52:17 rocky Exp $";
|
||||
|
||||
#ifdef HAVE_GLOB_H
|
||||
#include <glob.h>
|
||||
@@ -649,7 +649,7 @@ _get_drive_cap_solaris (const void *user_data,
|
||||
/* Don't handle these yet. */
|
||||
break;
|
||||
case CDIO_MMC_CAPABILITIES_PAGE:
|
||||
cdio_get_drive_cap_mmc(p, p_read_cap, p_write_cap, p_misc_cap);
|
||||
scsi_mmc_get_drive_cap(p, p_read_cap, p_write_cap, p_misc_cap);
|
||||
break;
|
||||
default: ;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: cdio_private.h,v 1.31 2004/07/21 10:19:21 rocky Exp $
|
||||
$Id: cdio_private.h,v 1.32 2004/07/22 09:52:17 rocky Exp $
|
||||
|
||||
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <cdio/cdio.h>
|
||||
#include <cdio/cdtext.h>
|
||||
#include <cdio/scsi_mmc.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -198,6 +199,29 @@ extern "C" {
|
||||
int (*read_mode1_sectors) (void *env, void *buf, lsn_t lsn,
|
||||
bool mode1_form2, unsigned int nblocks);
|
||||
|
||||
/*!
|
||||
Run a SCSI MMC command.
|
||||
|
||||
cdio CD structure set by cdio_open().
|
||||
i_timeout time in milliseconds we will wait for the command
|
||||
to complete. If this value is -1, use the default
|
||||
time-out value.
|
||||
cdb_len number of bytes in cdb (6, 10, or 12).
|
||||
cdb CDB bytes. All values that are needed should be set on
|
||||
input.
|
||||
b_return_data TRUE if the command expects data to be returned in
|
||||
the buffer
|
||||
len Size of buffer
|
||||
buf Buffer for data, both sending and receiving
|
||||
|
||||
Returns 0 if command completed successfully.
|
||||
*/
|
||||
int (*run_scsi_mmc_cmd) ( const CdIo *cdio, unsigned int i_timeout,
|
||||
unsigned int cdb_len,
|
||||
const scsi_mmc_cdb_t *p_cdb,
|
||||
scsi_mmc_direction_t e_direction,
|
||||
unsigned int len, /*in/out*/ void *p_buf );
|
||||
|
||||
/*!
|
||||
Set the arg "key" with "value" in the source device.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* Common MMC routines.
|
||||
|
||||
$Id: scsi_mmc.c,v 1.6 2004/07/19 01:13:32 rocky Exp $
|
||||
$Id: scsi_mmc.c,v 1.7 2004/07/22 09:52:17 rocky Exp $
|
||||
|
||||
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <cdio/cdio.h>
|
||||
#include <cdio/scsi_mmc.h>
|
||||
#include "cdio_private.h"
|
||||
|
||||
/*!
|
||||
On input a MODE_SENSE command was issued and we have the results
|
||||
@@ -32,7 +33,7 @@
|
||||
capabilities.
|
||||
*/
|
||||
void
|
||||
cdio_get_drive_cap_mmc(const uint8_t *p,
|
||||
scsi_mmc_get_drive_cap(const uint8_t *p,
|
||||
/*out*/ cdio_drive_read_cap_t *p_read_cap,
|
||||
/*out*/ cdio_drive_write_cap_t *p_write_cap,
|
||||
/*out*/ cdio_drive_misc_cap_t *p_misc_cap)
|
||||
@@ -59,3 +60,43 @@ cdio_get_drive_cap_mmc(const uint8_t *p,
|
||||
if (p[6] >> 5 != 0)
|
||||
*p_misc_cap |= CDIO_DRIVE_CAP_MISC_CLOSE_TRAY;
|
||||
}
|
||||
|
||||
/*!
|
||||
Return the number of length in bytes of the Command Descriptor
|
||||
buffer (CDB) for a given SCSI MMC command. The length will be
|
||||
either 6, 10, or 12.
|
||||
*/
|
||||
uint8_t
|
||||
scsi_mmc_get_cmd_len(uint8_t scsi_cmd)
|
||||
{
|
||||
static const uint8_t scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10};
|
||||
return scsi_cdblen[((scsi_cmd >> 5) & 7)];
|
||||
}
|
||||
|
||||
/*!
|
||||
Run a SCSI MMC command.
|
||||
|
||||
cdio CD structure set by cdio_open().
|
||||
i_timeout time in milliseconds we will wait for the command
|
||||
to complete. If this value is -1, use the default
|
||||
time-out value.
|
||||
buf Buffer for data, both sending and receiving
|
||||
len Size of buffer
|
||||
e_direction direction the transfer is to go
|
||||
cdb CDB bytes. All values that are needed should be set on
|
||||
input. We'll figure out what the right CDB length should be.
|
||||
|
||||
We return 0 if command completed successfully and 1 if not.
|
||||
*/
|
||||
int
|
||||
scsi_mmc_run_cmd( const CdIo *cdio, int i_timeout, const scsi_mmc_cdb_t *p_cdb,
|
||||
scsi_mmc_direction_t e_direction, unsigned int i_buf,
|
||||
/*in/out*/ void *p_buf )
|
||||
{
|
||||
if (cdio && cdio->op.run_scsi_mmc_cmd) {
|
||||
return cdio->op.run_scsi_mmc_cmd(cdio, i_timeout,
|
||||
scsi_mmc_get_cmd_len(p_cdb->field[0]),
|
||||
p_cdb, e_direction, i_buf, p_buf);
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user