Big change!
We now are starting to have universal MMC routines. To do this we need to have function pointers to the OS-specific MMC send/run command. Expect some breakage. Down the line though this will increase code reuse, reliabilty, and make the library more user-customizable.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: scsi_mmc.h,v 1.15 2004/07/25 16:38:05 rocky Exp $
|
||||
$Id: scsi_mmc.h,v 1.16 2004/07/26 02:54:37 rocky Exp $
|
||||
|
||||
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
|
||||
@@ -195,4 +195,18 @@ void scsi_mmc_get_drive_cap(const uint8_t *p,
|
||||
/*out*/ cdio_drive_write_cap_t *p_write_cap,
|
||||
/*out*/ cdio_drive_misc_cap_t *p_misc_cap);
|
||||
|
||||
/*!
|
||||
* Eject using SCSI MMC commands. Return 0 if successful.
|
||||
*/
|
||||
int scsi_mmc_eject_media( const CdIo *cdio);
|
||||
|
||||
/*! Packet driver to read mode2 sectors.
|
||||
Can read only up to 25 blocks.
|
||||
*/
|
||||
int scsi_mmc_read_sectors ( const CdIo *cdio, void *p_buf, lba_t lba,
|
||||
int sector_type, unsigned int nblocks);
|
||||
|
||||
int scsi_mmc_set_bsize ( const CdIo *cdio, unsigned int bsize);
|
||||
|
||||
|
||||
#endif /* __SCSI_MMC_H__ */
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# $Id: Makefile.am,v 1.42 2004/07/10 02:17:58 rocky Exp $
|
||||
# $Id: Makefile.am,v 1.43 2004/07/26 02:54:37 rocky Exp $
|
||||
#
|
||||
# Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
#
|
||||
@@ -89,6 +89,7 @@ libcdio_sources = \
|
||||
MSWindows/win32.h \
|
||||
sector.c \
|
||||
scsi_mmc.c \
|
||||
scsi_mmc_private.h \
|
||||
util.c
|
||||
|
||||
lib_LTLIBRARIES = libcdio.la libiso9660.la
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: _cdio_linux.c,v 1.80 2004/07/25 18:37:09 rocky Exp $
|
||||
$Id: _cdio_linux.c,v 1.81 2004/07/26 02:54:37 rocky Exp $
|
||||
|
||||
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
@@ -27,7 +27,7 @@
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.80 2004/07/25 18:37:09 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.81 2004/07/26 02:54:37 rocky Exp $";
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -118,7 +118,6 @@ static int scsi_mmc_run_cmd_linux( const void *p_user_data, int i_timeout,
|
||||
scsi_mmc_direction_t e_direction,
|
||||
unsigned int i_buf,
|
||||
/*in/out*/ void *p_buf );
|
||||
static int set_bsize (_img_private_t *p_env, unsigned int bsize);
|
||||
static access_mode_t
|
||||
|
||||
str_to_access_mode_linux(const char *psz_access_mode)
|
||||
@@ -431,47 +430,6 @@ _get_track_msf_linux(void *p_user_data, track_t i_track, msf_t *msf)
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Eject using SCSI MMC commands. Return 0 if successful.
|
||||
*/
|
||||
static int
|
||||
eject_media_mmc(_img_private_t *p_env)
|
||||
{
|
||||
int i_status;
|
||||
scsi_mmc_cdb_t cdb = {{0, }};
|
||||
uint8_t buf[1];
|
||||
|
||||
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL);
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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 */
|
||||
i_status = ioctl(p_env->gen.fd, BLKRRPART);
|
||||
return (i_status);
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
Eject media in CD drive.
|
||||
Return 0 if success and 1 for failure, and 2 if no routine.
|
||||
@@ -497,13 +455,15 @@ eject_media_linux (void *p_user_data) {
|
||||
if((ret = ioctl(fd, CDROMEJECT)) != 0) {
|
||||
int eject_error = errno;
|
||||
/* Try ejecting the MMC way... */
|
||||
ret = eject_media_mmc(p_env);
|
||||
ret = scsi_mmc_eject_media(p_env->gen.cdio);
|
||||
if (0 != ret) {
|
||||
cdio_warn("ioctl CDROMEJECT failed: %s\n",
|
||||
strerror(eject_error));
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
/* force kernel to reread partition table when new disc inserted */
|
||||
ret = ioctl(p_env->gen.fd, BLKRRPART);
|
||||
break;
|
||||
default:
|
||||
cdio_warn ("Unknown CD-ROM (%d)\n", status);
|
||||
@@ -602,29 +562,6 @@ is_cdrom_linux(const char *drive, char *mnttype)
|
||||
return(is_cd);
|
||||
}
|
||||
|
||||
/* Packet driver to read mode2 sectors.
|
||||
Can read only up to 25 blocks.
|
||||
*/
|
||||
static int
|
||||
_read_sectors_mmc (_img_private_t *p_env, void *p_buf, lba_t lba,
|
||||
int sector_type, unsigned int nblocks)
|
||||
{
|
||||
scsi_mmc_cdb_t cdb = {{0, }};
|
||||
|
||||
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);
|
||||
|
||||
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.
|
||||
*/
|
||||
@@ -633,7 +570,7 @@ _read_audio_sectors_linux (void *p_user_data, void *buf, lsn_t lsn,
|
||||
unsigned int nblocks)
|
||||
{
|
||||
_img_private_t *p_env = p_user_data;
|
||||
return _read_sectors_mmc( p_env, buf, lsn,
|
||||
return scsi_mmc_read_sectors( p_env->gen.cdio, buf, lsn,
|
||||
CDIO_MMC_READ_TYPE_CDDA, nblocks);
|
||||
}
|
||||
|
||||
@@ -660,7 +597,7 @@ _read_mode2_sectors_mmc (_img_private_t *p_env, void *p_buf, lba_t lba,
|
||||
if (b_read_10) {
|
||||
int retval;
|
||||
|
||||
if ((retval = set_bsize (p_env, M2RAW_SECTOR_SIZE)))
|
||||
if ((retval = scsi_mmc_set_bsize (p_env->gen.cdio, M2RAW_SECTOR_SIZE)))
|
||||
return retval;
|
||||
|
||||
if ((retval = scsi_mmc_run_cmd_linux (p_env, 0,
|
||||
@@ -670,11 +607,11 @@ _read_mode2_sectors_mmc (_img_private_t *p_env, void *p_buf, lba_t lba,
|
||||
M2RAW_SECTOR_SIZE * nblocks,
|
||||
p_buf)))
|
||||
{
|
||||
set_bsize (p_env, CDIO_CD_FRAMESIZE);
|
||||
scsi_mmc_set_bsize (p_env->gen.cdio, CDIO_CD_FRAMESIZE);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if ((retval = set_bsize (p_env, CDIO_CD_FRAMESIZE)))
|
||||
if ((retval = scsi_mmc_set_bsize (p_env->gen.cdio, CDIO_CD_FRAMESIZE)))
|
||||
return retval;
|
||||
} else
|
||||
return scsi_mmc_run_cmd_linux (p_env, 0,
|
||||
@@ -991,43 +928,6 @@ scsi_mmc_run_cmd_linux( const void *p_user_data, int i_timeout,
|
||||
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 = {{0, }};
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t reserved1;
|
||||
uint8_t medium;
|
||||
uint8_t reserved2;
|
||||
uint8_t block_desc_length;
|
||||
uint8_t density;
|
||||
uint8_t number_of_blocks_hi;
|
||||
uint8_t number_of_blocks_med;
|
||||
uint8_t number_of_blocks_lo;
|
||||
uint8_t reserved3;
|
||||
uint8_t block_length_hi;
|
||||
uint8_t block_length_med;
|
||||
uint8_t block_length_lo;
|
||||
} mh;
|
||||
|
||||
memset (&mh, 0, sizeof (mh));
|
||||
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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*!
|
||||
Return the size of the CD in logical block address (LBA) units.
|
||||
*/
|
||||
@@ -1362,12 +1262,12 @@ cdio_open_am_linux (const char *psz_orig_source, const char *access_mode)
|
||||
}
|
||||
}
|
||||
|
||||
ret = cdio_new (_data, &_funcs);
|
||||
ret = cdio_new ((void *)_data, &_funcs);
|
||||
if (ret == NULL) return NULL;
|
||||
|
||||
if (cdio_generic_init(_data))
|
||||
if (cdio_generic_init(_data)) {
|
||||
return ret;
|
||||
else {
|
||||
} else {
|
||||
cdio_generic_free (_data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
21
lib/cdio.c
21
lib/cdio.c
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: cdio.c,v 1.65 2004/07/21 11:28:32 rocky Exp $
|
||||
$Id: cdio.c,v 1.66 2004/07/26 02:54:37 rocky Exp $
|
||||
|
||||
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <cdio/logging.h>
|
||||
#include "cdio_private.h"
|
||||
|
||||
static const char _rcsid[] = "$Id: cdio.c,v 1.65 2004/07/21 11:28:32 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: cdio.c,v 1.66 2004/07/26 02:54:37 rocky Exp $";
|
||||
|
||||
|
||||
const char *track_format2str[6] =
|
||||
@@ -721,16 +721,19 @@ cdio_init(void)
|
||||
}
|
||||
|
||||
CdIo *
|
||||
cdio_new (void *env, const cdio_funcs *funcs)
|
||||
cdio_new (generic_img_private_t *p_env, cdio_funcs *p_funcs)
|
||||
{
|
||||
CdIo *new_cdio;
|
||||
CdIo *p_new_cdio = _cdio_malloc (sizeof (CdIo));
|
||||
|
||||
new_cdio = _cdio_malloc (sizeof (CdIo));
|
||||
if (NULL == p_new_cdio) return NULL;
|
||||
|
||||
new_cdio->env = env;
|
||||
new_cdio->op = *funcs;
|
||||
|
||||
return new_cdio;
|
||||
p_new_cdio->env = p_env; /* This is the private "environment" that
|
||||
driver-dependent routines use. */
|
||||
p_new_cdio->op = *p_funcs;
|
||||
p_env->cdio = p_new_cdio; /* A way for the driver-dependent routines
|
||||
to access the higher-level general cdio
|
||||
object. */
|
||||
return p_new_cdio;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: cdio_private.h,v 1.33 2004/07/22 11:00:59 rocky Exp $
|
||||
$Id: cdio_private.h,v 1.34 2004/07/26 02:54:37 rocky Exp $
|
||||
|
||||
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#include <cdio/cdio.h>
|
||||
#include <cdio/cdtext.h>
|
||||
#include <cdio/scsi_mmc.h>
|
||||
#include "scsi_mmc_private.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -216,11 +216,7 @@ extern "C" {
|
||||
|
||||
Returns 0 if command completed successfully.
|
||||
*/
|
||||
int (*run_scsi_mmc_cmd) ( const void *env, 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 );
|
||||
scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd;
|
||||
|
||||
/*!
|
||||
Set the arg "key" with "value" in the source device.
|
||||
@@ -232,6 +228,9 @@ extern "C" {
|
||||
*/
|
||||
uint32_t (*stat_size) (void *env);
|
||||
|
||||
/*! Pointer to parent container object. */
|
||||
CdIo *cdio;
|
||||
|
||||
} cdio_funcs;
|
||||
|
||||
|
||||
@@ -249,16 +248,17 @@ extern "C" {
|
||||
code.
|
||||
*/
|
||||
typedef struct {
|
||||
char *source_name; /* Name used in open. */
|
||||
bool init; /* True if structure has been initialized */
|
||||
bool toc_init; /* True TOC read in */
|
||||
int ioctls_debugged; /* for debugging */
|
||||
char *source_name; /**< Name used in open. */
|
||||
bool init; /**< True if structure has been initialized */
|
||||
bool toc_init; /**< True TOC read in */
|
||||
int ioctls_debugged; /**< for debugging */
|
||||
|
||||
/* Only one of the below is used. The first is for CD-ROM devices
|
||||
and the second for stream reading (bincue, nrg, toc, network).
|
||||
*/
|
||||
int fd; /* File descriptor of device */
|
||||
int fd; /**< File descriptor of device */
|
||||
CdioDataSource *data_source;
|
||||
CdIo *cdio; /**< a way to call general cdio routines. */
|
||||
} generic_img_private_t;
|
||||
|
||||
/* This is used in drivers that must keep their own internal
|
||||
@@ -272,7 +272,7 @@ extern "C" {
|
||||
lba_t lba; /* Current LBA */
|
||||
} internal_position_t;
|
||||
|
||||
CdIo * cdio_new (void *env, const cdio_funcs *funcs);
|
||||
CdIo * cdio_new (generic_img_private_t *p_env, cdio_funcs *funcs);
|
||||
|
||||
/* The below structure describes a specific CD Input driver */
|
||||
typedef struct
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: bincue.c,v 1.37 2004/07/25 18:37:09 rocky Exp $
|
||||
$Id: bincue.c,v 1.38 2004/07/26 02:54:37 rocky Exp $
|
||||
|
||||
Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
@@ -26,7 +26,7 @@
|
||||
(*.cue).
|
||||
*/
|
||||
|
||||
static const char _rcsid[] = "$Id: bincue.c,v 1.37 2004/07/25 18:37:09 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: bincue.c,v 1.38 2004/07/26 02:54:37 rocky Exp $";
|
||||
|
||||
#include "image.h"
|
||||
#include "cdio_assert.h"
|
||||
@@ -1167,7 +1167,7 @@ cdio_open_cue (const char *psz_cue_name)
|
||||
_data->gen.init = false;
|
||||
_data->psz_cue_name = NULL;
|
||||
|
||||
ret = cdio_new (_data, &_funcs);
|
||||
ret = cdio_new ((void *)_data, &_funcs);
|
||||
|
||||
if (ret == NULL) {
|
||||
free(_data);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: cdrdao.c,v 1.22 2004/07/25 18:37:09 rocky Exp $
|
||||
$Id: cdrdao.c,v 1.23 2004/07/26 02:54:37 rocky Exp $
|
||||
|
||||
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
|
||||
toc reading routine adapted from cuetools
|
||||
@@ -25,7 +25,7 @@
|
||||
(*.cue).
|
||||
*/
|
||||
|
||||
static const char _rcsid[] = "$Id: cdrdao.c,v 1.22 2004/07/25 18:37:09 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: cdrdao.c,v 1.23 2004/07/26 02:54:37 rocky Exp $";
|
||||
|
||||
#include "image.h"
|
||||
#include "cdio_assert.h"
|
||||
@@ -1149,7 +1149,7 @@ cdio_open_cdrdao (const char *psz_cue_name)
|
||||
_data->gen.data_source = NULL;
|
||||
_data->gen.source_name = NULL;
|
||||
|
||||
ret = cdio_new (_data, &_funcs);
|
||||
ret = cdio_new ((void *)_data, &_funcs);
|
||||
|
||||
if (ret == NULL) {
|
||||
free(_data);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: nrg.c,v 1.34 2004/07/25 18:37:09 rocky Exp $
|
||||
$Id: nrg.c,v 1.35 2004/07/26 02:54:37 rocky Exp $
|
||||
|
||||
Copyright (C) 2003, 2004 Rocky Bernstein <rocky@panix.com>
|
||||
Copyright (C) 2001, 2003 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
@@ -45,7 +45,7 @@
|
||||
#include "_cdio_stdio.h"
|
||||
#include "nrg.h"
|
||||
|
||||
static const char _rcsid[] = "$Id: nrg.c,v 1.34 2004/07/25 18:37:09 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: nrg.c,v 1.35 2004/07/26 02:54:37 rocky Exp $";
|
||||
|
||||
|
||||
/* reader */
|
||||
@@ -1220,7 +1220,7 @@ cdio_open_nrg (const char *psz_source)
|
||||
_data->is_dao = false;
|
||||
_data->is_cues = false; /* FIXME: remove is_cues. */
|
||||
|
||||
ret = cdio_new (_data, &_funcs);
|
||||
ret = cdio_new ((void *)_data, &_funcs);
|
||||
|
||||
if (ret == NULL) {
|
||||
free(_data);
|
||||
|
||||
128
lib/scsi_mmc.c
128
lib/scsi_mmc.c
@@ -1,6 +1,6 @@
|
||||
/* Common MMC routines.
|
||||
/* Common SCSI Multimedia Command (MMC) routines.
|
||||
|
||||
$Id: scsi_mmc.c,v 1.7 2004/07/22 09:52:17 rocky Exp $
|
||||
$Id: scsi_mmc.c,v 1.8 2004/07/26 02:54:37 rocky Exp $
|
||||
|
||||
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
#include <cdio/scsi_mmc.h>
|
||||
#include "cdio_private.h"
|
||||
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/*!
|
||||
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
|
||||
@@ -89,7 +93,8 @@ scsi_mmc_get_cmd_len(uint8_t scsi_cmd)
|
||||
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_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 )
|
||||
{
|
||||
@@ -100,3 +105,120 @@ scsi_mmc_run_cmd( const CdIo *cdio, int i_timeout, const scsi_mmc_cdb_t *p_cdb,
|
||||
} else
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define DEFAULT_TIMEOUT_MS 6000
|
||||
|
||||
/*!
|
||||
* Eject using SCSI MMC commands. Return 0 if successful.
|
||||
*/
|
||||
int
|
||||
scsi_mmc_eject_media( const CdIo *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 )
|
||||
return -2;
|
||||
|
||||
run_scsi_mmc_cmd = 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,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_WRITE, 0, &buf);
|
||||
if (0 != i_status)
|
||||
return i_status;
|
||||
|
||||
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,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_WRITE, 0, &buf);
|
||||
if (0 != i_status)
|
||||
return i_status;
|
||||
|
||||
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,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_WRITE, 0, &buf);
|
||||
|
||||
}
|
||||
|
||||
/*! Packet driver to read mode2 sectors.
|
||||
Can read only up to 25 blocks.
|
||||
*/
|
||||
int
|
||||
scsi_mmc_read_sectors ( const CdIo *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 )
|
||||
return -2;
|
||||
|
||||
run_scsi_mmc_cmd = 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);
|
||||
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);
|
||||
|
||||
return run_scsi_mmc_cmd (cdio->env, DEFAULT_TIMEOUT_MS,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_READ,
|
||||
CDIO_CD_FRAMESIZE_RAW * nblocks,
|
||||
p_buf);
|
||||
}
|
||||
|
||||
int
|
||||
scsi_mmc_set_bsize ( const CdIo *cdio, unsigned int bsize)
|
||||
{
|
||||
scsi_mmc_cdb_t cdb = {{0, }};
|
||||
|
||||
struct
|
||||
{
|
||||
uint8_t reserved1;
|
||||
uint8_t medium;
|
||||
uint8_t reserved2;
|
||||
uint8_t block_desc_length;
|
||||
uint8_t density;
|
||||
uint8_t number_of_blocks_hi;
|
||||
uint8_t number_of_blocks_med;
|
||||
uint8_t number_of_blocks_lo;
|
||||
uint8_t reserved3;
|
||||
uint8_t block_length_hi;
|
||||
uint8_t block_length_med;
|
||||
uint8_t block_length_lo;
|
||||
} mh;
|
||||
|
||||
scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd;
|
||||
|
||||
if ( ! cdio || ! cdio->op.run_scsi_mmc_cmd )
|
||||
return -2;
|
||||
|
||||
run_scsi_mmc_cmd = cdio->op.run_scsi_mmc_cmd;
|
||||
|
||||
memset (&mh, 0, sizeof (mh));
|
||||
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;
|
||||
|
||||
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_MODE_SELECT_6);
|
||||
|
||||
cdb.field[1] = 1 << 4;
|
||||
cdb.field[4] = 12;
|
||||
|
||||
return run_scsi_mmc_cmd (cdio->env, DEFAULT_TIMEOUT_MS,
|
||||
scsi_mmc_get_cmd_len(cdb.field[0]), &cdb,
|
||||
SCSI_MMC_DATA_WRITE, sizeof(mh), &mh);
|
||||
}
|
||||
|
||||
30
lib/scsi_mmc_private.h
Normal file
30
lib/scsi_mmc_private.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/* private MMC helper routines.
|
||||
|
||||
$Id: scsi_mmc_private.h,v 1.1 2004/07/26 02:54:37 rocky Exp $
|
||||
|
||||
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <cdio/scsi_mmc.h>
|
||||
|
||||
typedef
|
||||
int (*scsi_mmc_run_cmd_fn_t) ( const void *p_user_data, int i_timeout,
|
||||
unsigned int i_cdb,
|
||||
const scsi_mmc_cdb_t *p_cdb,
|
||||
scsi_mmc_direction_t e_direction,
|
||||
unsigned int i_buf, /*in/out*/ void *p_buf );
|
||||
|
||||
Reference in New Issue
Block a user