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:
rocky
2004-07-26 02:54:37 +00:00
parent cf5ec43903
commit 20e8974df8
10 changed files with 220 additions and 150 deletions

View File

@@ -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__ */

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}
/*!

View File

@@ -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

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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
View 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 );