Create uniform scsi_mmc_run_cmd routine and use this more pervasively.

This commit is contained in:
rocky
2004-07-23 10:59:15 +00:00
parent 3fe90481c1
commit 091a486c8e

View File

@@ -1,5 +1,5 @@
/*
$Id: aspi32.c,v 1.31 2004/07/22 09:52:17 rocky Exp $
$Id: aspi32.c,v 1.32 2004/07/23 10:59:15 rocky Exp $
Copyright (C) 2004 Rocky Bernstein <rocky@panix.com>
@@ -23,11 +23,11 @@
Inspired by vlc's cdrom.h code
*/
#ifdef HAVE_CONFIG_H
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
static const char _rcsid[] = "$Id: aspi32.c,v 1.31 2004/07/22 09:52:17 rocky Exp $";
static const char _rcsid[] = "$Id: aspi32.c,v 1.32 2004/07/23 10:59:15 rocky Exp $";
#include <cdio/cdio.h>
#include <cdio/sector.h>
@@ -382,14 +382,28 @@ init_aspi (_img_private_t *env)
return false;
}
/*!
Issue a SCSI passthrough command.
/*!
Run a SCSI MMC command.
env private CD structure
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 bool
scsi_passthrough_aspi( const _img_private_t *env,
void * scsi_cdb, unsigned int i_scsi_cdb,
void * outdata, unsigned int i_outdata )
static int
scsi_mmc_run_cmd_aspi( 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 )
{
const _img_private_t *p_env = p_user_data;
HANDLE hEvent;
struct SRB_ExecSCSICmd ssc;
@@ -403,25 +417,26 @@ scsi_passthrough_aspi( const _img_private_t *env,
memset( &ssc, 0, sizeof( ssc ) );
ssc.SRB_Cmd = SC_EXEC_SCSI_CMD;
ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
ssc.SRB_HaId = LOBYTE( env->i_sid );
ssc.SRB_Target = HIBYTE( env->i_sid );
ssc.SRB_Lun = env->i_lun;
ssc.SRB_Flags = SCSI_MMC_DATA_READ == e_direction ?
SRB_DIR_IN | SRB_EVENT_NOTIFY : SRB_DIR_OUT | SRB_EVENT_NOTIFY;
ssc.SRB_HaId = LOBYTE( p_env->i_sid );
ssc.SRB_Target = HIBYTE( p_env->i_sid );
ssc.SRB_Lun = p_env->i_lun;
ssc.SRB_SenseLen = SENSE_LEN;
ssc.SRB_PostProc = (LPVOID) hEvent;
ssc.SRB_CDBLen = i_scsi_cdb;
ssc.SRB_CDBLen = i_cdb;
ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
/* Result buffer */
ssc.SRB_BufPointer = outdata;
ssc.SRB_BufLen = i_outdata;
ssc.SRB_BufPointer = p_buf;
ssc.SRB_BufLen = i_buf;
memcpy( ssc.CDBByte, scsi_cdb, i_scsi_cdb );
memcpy( ssc.CDBByte, p_cdb, i_cdb );
ResetEvent( hEvent );
env->lpSendCommand( (void*) &ssc );
p_env->lpSendCommand( (void*) &ssc );
/* If the command has still not been processed, wait until it's
* finished */
@@ -433,10 +448,10 @@ scsi_passthrough_aspi( const _img_private_t *env,
/* check that the transfer went as planned */
if( ssc.SRB_Status != SS_COMP ) {
cdio_info("ASPI: %s", aspierror(ssc.SRB_Status));
return false;
return 0;
}
return true;
return 1;
}
@@ -448,8 +463,8 @@ static int
read_sectors_aspi (const _img_private_t *env, void *data, lsn_t lsn,
int sector_type, unsigned int nblocks)
{
uint8_t cmd[10] = {0, };
unsigned int i_outdata;
scsi_mmc_cdb_t cdb = {{0, }};
unsigned int i_buf;
int sync = 0;
int header_code = 2;
@@ -462,13 +477,13 @@ read_sectors_aspi (const _img_private_t *env, void *data, lsn_t lsn,
#endif
/* Set up passthrough command */
CDIO_MMC_SET_COMMAND(cmd, CDIO_MMC_GPCMD_READ_CD);
CDIO_MMC_SET_READ_TYPE(cmd, sector_type);
CDIO_MMC_SET_READ_LBA(cmd, lsn);
CDIO_MMC_SET_READ_LENGTH(cmd, nblocks);
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, lsn);
CDIO_MMC_SET_READ_LENGTH(cdb.field, nblocks);
#if 1
cmd[ 9 ] = (sync << 7) |
cdb.field[ 9 ] = (sync << 7) |
(header_code << 5) |
(i_user_data << 4) |
(edc_ecc << 3) |
@@ -482,25 +497,24 @@ read_sectors_aspi (const _img_private_t *env, void *data, lsn_t lsn,
switch (sector_type) {
case CDIO_MMC_READ_TYPE_ANY:
case CDIO_MMC_READ_TYPE_CDDA:
i_outdata = CDIO_CD_FRAMESIZE_RAW;
i_buf = CDIO_CD_FRAMESIZE_RAW;
break;
case CDIO_MMC_READ_TYPE_M2F1:
i_outdata = CDIO_CD_FRAMESIZE;
i_buf = CDIO_CD_FRAMESIZE;
break;
case CDIO_MMC_READ_TYPE_M2F2:
i_outdata = 2324;
i_buf = 2324;
break;
case CDIO_MMC_READ_TYPE_MODE1:
i_outdata = CDIO_CD_FRAMESIZE;
i_buf = CDIO_CD_FRAMESIZE;
break;
default:
i_outdata = CDIO_CD_FRAMESIZE_RAW;
i_buf = CDIO_CD_FRAMESIZE_RAW;
}
if (scsi_passthrough_aspi(env, cmd, sizeof(cmd), data, i_outdata*nblocks))
return 0;
else
return 1;
return scsi_mmc_run_cmd_aspi(env, OP_TIMEOUT_MS,
scsi_mmc_get_cmd_len(cdb.field[0]),
&cdb, SCSI_MMC_DATA_READ, i_buf*nblocks, data);
}
/*!
@@ -547,119 +561,73 @@ read_mode1_sector_aspi (const _img_private_t *env, void *data, lsn_t lsn,
Return true if successful or false if an error.
*/
bool
read_toc_aspi (_img_private_t *env)
read_toc_aspi (_img_private_t *p_env)
{
HANDLE hEvent;
struct SRB_ExecSCSICmd ssc;
unsigned char p_tocheader[ 4 ];
/* Create the transfer completion event */
hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
if( hEvent == NULL ) {
return false;
}
memset( &ssc, 0, sizeof( ssc ) );
ssc.SRB_Cmd = SC_EXEC_SCSI_CMD;
ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
ssc.SRB_HaId = LOBYTE( env->i_sid );
ssc.SRB_Target = HIBYTE( env->i_sid );
ssc.SRB_Lun = env->i_lun;
ssc.SRB_SenseLen = SENSE_LEN;
ssc.SRB_PostProc = (LPVOID) hEvent;
/* Sizes for command descriptor buffer (CDB) are set by the SCSI opcode.
The size for READ TOC is 10. */
ssc.SRB_CDBLen = 10;
scsi_mmc_cdb_t cdb = {{0, }};
unsigned char tocheader[ 4 ];
int i_status;
/* Operation code */
CDIO_MMC_SET_COMMAND(ssc.CDBByte, CDIO_MMC_GPCMD_READ_TOC);
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC);
/* Format */
ssc.CDBByte[ 2 ] = CDIO_MMC_READTOC_FMT_TOC;
cdb.field[ 2 ] = CDIO_MMC_READTOC_FMT_TOC;
/* Starting track */
CDIO_MMC_SET_START_TRACK(ssc.CDBByte, 0);
CDIO_MMC_SET_START_TRACK(cdb.field, 0);
/* Allocation length and buffer */
ssc.SRB_BufLen = sizeof( p_tocheader );
ssc.SRB_BufPointer = p_tocheader;
CDIO_MMC_SET_READ_LENGTH(ssc.CDBByte, ssc.SRB_BufLen);
CDIO_MMC_SET_READ_LENGTH(cdb.field, sizeof(tocheader));
i_status = scsi_mmc_run_cmd_aspi (p_env, OP_TIMEOUT_MS,
scsi_mmc_get_cmd_len(cdb.field[0]),
&cdb, SCSI_MMC_DATA_READ,
sizeof(tocheader), &tocheader);
/* Initiate transfer */
ResetEvent( hEvent );
env->lpSendCommand( (void*) &ssc );
if (0 != i_status) return false;
/* If the command has still not been processed, wait until it's
* finished */
if( ssc.SRB_Status == SS_PENDING )
WaitForSingleObject( hEvent, OP_TIMEOUT_MS );
/* check that the transfer went as planned */
if( ssc.SRB_Status != SS_COMP ) {
cdio_info("ASPI: %s", aspierror(ssc.SRB_Status));
CloseHandle( hEvent );
return false;
}
env->i_first_track = p_tocheader[2];
env->i_tracks = p_tocheader[3] - p_tocheader[2] + 1;
p_env->i_first_track = tocheader[2];
p_env->i_tracks = tocheader[3] - tocheader[2] + 1;
{
int i, i_toclength;
unsigned char *p_fulltoc;
i_toclength = 4 /* header */ + p_tocheader[0] +
((unsigned int)p_tocheader[1] << 8);
i_toclength = 4 /* header */ + tocheader[0] +
((unsigned int) tocheader[1] << 8);
p_fulltoc = malloc( i_toclength );
if( p_fulltoc == NULL ) {
cdio_error( "out of memory" );
CloseHandle( hEvent );
return false;
}
/* Allocation length and buffer */
ssc.SRB_BufLen = i_toclength;
ssc.SRB_BufPointer = p_fulltoc;
ssc.CDBByte[ 7 ] = (unsigned char) ( ssc.SRB_BufLen >> 8 ) & 0xff;
ssc.CDBByte[ 8 ] = (unsigned char) ( ssc.SRB_BufLen ) & 0xff;
/* Initiate transfer */
ResetEvent( hEvent );
env->lpSendCommand( (void*) &ssc );
/* If the command has still not been processed, wait until it's
* finished */
if( ssc.SRB_Status == SS_PENDING )
WaitForSingleObject( hEvent, OP_TIMEOUT_MS );
/* check that the transfer went as planned */
if( ssc.SRB_Status != SS_COMP ) {
cdio_info("ASPI: %s", aspierror(ssc.SRB_Status));
env->i_tracks = 0;
CDIO_MMC_SET_READ_LENGTH(cdb.field, i_toclength);
i_status = scsi_mmc_run_cmd_aspi (p_env, OP_TIMEOUT_MS,
scsi_mmc_get_cmd_len(cdb.field[0]),
&cdb, SCSI_MMC_DATA_READ,
i_toclength, p_fulltoc);
if( 0 == i_status ) {
p_env->i_tracks = 0;
}
for( i = 0 ; i <= env->i_tracks ; i++ ) {
for( i = 0 ; i <= p_env->i_tracks ; i++ ) {
int i_index = 8 + 8 * i;
env->tocent[ i ].start_lsn = ((int)p_fulltoc[ i_index ] << 24) +
p_env->tocent[ i ].start_lsn = ((int)p_fulltoc[ i_index ] << 24) +
((int)p_fulltoc[ i_index+1 ] << 16) +
((int)p_fulltoc[ i_index+2 ] << 8) +
(int)p_fulltoc[ i_index+3 ];
env->tocent[ i ].Control = (UCHAR)p_fulltoc[ 1 + 8 * i ];
p_env->tocent[ i ].Control = (UCHAR)p_fulltoc[ 1 + 8 * i ];
cdio_debug( "p_sectors: %i %lu",
i, (unsigned long int) env->tocent[i].start_lsn );
i, (unsigned long int) p_env->tocent[i].start_lsn );
}
free( p_fulltoc );
}
CloseHandle( hEvent );
env->gen.toc_init = true;
p_env->gen.toc_init = true;
return true;
}
@@ -711,22 +679,32 @@ wnaspi32_eject_media (void *user_data) {
not exist.
*/
bool
init_cdtext_aspi (_img_private_t *env)
init_cdtext_aspi (_img_private_t *p_env)
{
scsi_mmc_cdb_t cdb = {{ 0, }};
uint8_t wdata[5000] = { 0, };
uint8_t scsi_cdb[10] = { 0, };
int i_status;
CDIO_MMC_SET_COMMAND(scsi_cdb, CDIO_MMC_GPCMD_READ_TOC);
scsi_cdb[1] = 0x02; /* MSF mode */
scsi_cdb[2] = 0x05; /* CD text */
CDIO_MMC_SET_READ_LENGTH(scsi_cdb, sizeof(wdata));
/* Operation code */
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC);
if (!scsi_passthrough_aspi(env, scsi_cdb, sizeof(scsi_cdb),
wdata, sizeof(wdata)))
return false;
else
return cdtext_data_init(env, env->i_first_track, wdata,
/* Format */
cdb.field[2] = CDIO_MMC_READTOC_FMT_CDTEXT;
CDIO_MMC_SET_READ_LENGTH(cdb.field, sizeof(wdata));
i_status = scsi_mmc_run_cmd_aspi (p_env, OP_TIMEOUT_MS,
scsi_mmc_get_cmd_len(cdb.field[0]),
&cdb, SCSI_MMC_DATA_READ,
sizeof(wdata), &wdata);
if (0 != i_status) {
cdio_info ("CD-TEXT reading failed\n");
return false;
} else {
return cdtext_data_init(p_env, p_env->i_first_track, wdata,
set_cdtext_field_win32);
}
}
/*!
@@ -734,35 +712,39 @@ init_cdtext_aspi (_img_private_t *env)
*/
void
get_drive_cap_aspi (const _img_private_t *env,
get_drive_cap_aspi (const _img_private_t *p_env,
cdio_drive_read_cap_t *p_read_cap,
cdio_drive_write_cap_t *p_write_cap,
cdio_drive_misc_cap_t *p_misc_cap)
{
uint8_t scsi_cdb[10] = { 0, };
scsi_mmc_cdb_t cdb = {{0, }};
uint8_t buf[256] = { 0, };
int i_status;
/* Set up passthrough command */
CDIO_MMC_SET_COMMAND(scsi_cdb, CDIO_MMC_GPCMD_MODE_SENSE_10);
scsi_cdb[1] = 0x0;
scsi_cdb[2] = CDIO_MMC_ALL_PAGES;
scsi_cdb[7] = 0x01;
scsi_cdb[8] = 0x00;
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_MODE_SENSE_10);
cdb.field[1] = 0x0;
cdb.field[2] = CDIO_MMC_ALL_PAGES;
cdb.field[7] = 0x01;
cdb.field[8] = 0x00;
if (!scsi_passthrough_aspi(env, scsi_cdb, sizeof(scsi_cdb),
buf, sizeof(buf))) {
*p_read_cap = CDIO_DRIVE_CAP_UNKNOWN;
*p_write_cap = CDIO_DRIVE_CAP_UNKNOWN;
*p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN;
} else {
BYTE *p;
i_status = scsi_mmc_run_cmd_aspi(p_env, OP_TIMEOUT_MS,
scsi_mmc_get_cmd_len(cdb.field[0]),
&cdb, SCSI_MMC_DATA_READ,
sizeof(buf), buf);
if (0 == i_status) {
uint8_t *p;
int lenData = ((unsigned int)buf[0] << 8) + buf[1];
BYTE *pMax = buf + 256;
uint8_t *pMax = buf + 256;
*p_read_cap = 0;
*p_write_cap = 0;
*p_misc_cap = 0;
/* set to first sense mask, and then walk through the masks */
p = buf + 8;
while( (p < &(buf[2+lenData])) && (p < pMax) ) {
BYTE which;
uint8_t which;
which = p[0] & 0x3F;
switch( which )
@@ -779,6 +761,11 @@ get_drive_cap_aspi (const _img_private_t *env,
}
p += (p[1] + 2);
}
} else {
cdio_info("error in aspi USCSICMD MODE_SELECT");
*p_read_cap = CDIO_DRIVE_CAP_UNKNOWN;
*p_write_cap = CDIO_DRIVE_CAP_UNKNOWN;
*p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN;
}
}
@@ -790,34 +777,26 @@ get_drive_cap_aspi (const _img_private_t *env,
*/
char *
get_mcn_aspi (const _img_private_t *env)
get_mcn_aspi (const _img_private_t *p_env)
{
#if 1
char buf[192] = { 0, };
scsi_mmc_cdb_t cdb = {{0, }};
char buf[28] = { 0, };
int i_status;
/* Sizes for commands are set by the SCSI opcode. *
The size for READ SUBCHANNEL is 10. */
unsigned char scsi_cdb[10] = {0, };
CDIO_MMC_SET_COMMAND(scsi_cdb, CDIO_MMC_GPCMD_READ_SUBCHANNEL);
scsi_cdb[1] = 0x0;
scsi_cdb[2] = 0x40;
scsi_cdb[3] = CDIO_SUBCHANNEL_MEDIA_CATALOG;
scsi_cdb[4] = 0; /* Not used */
scsi_cdb[5] = 0; /* Not used */
scsi_cdb[6] = 0; /* Not used */
scsi_cdb[7] = 0; /* Not used */
scsi_cdb[8] = 28;
scsi_cdb[9] = 0; /* Not used */
if (!scsi_passthrough_aspi(env, scsi_cdb, sizeof(scsi_cdb),
buf, sizeof(buf)))
return NULL;
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_SUBCHANNEL);
cdb.field[1] = 0x0;
cdb.field[2] = 0x40;
cdb.field[3] = CDIO_SUBCHANNEL_MEDIA_CATALOG;
CDIO_MMC_SET_READ_LENGTH(cdb.field, sizeof(buf));
return strdup(&buf[9]);
#else
i_status = scsi_mmc_run_cmd_aspi(p_env, OP_TIMEOUT_MS,
scsi_mmc_get_cmd_len(cdb.field[0]),
&cdb, SCSI_MMC_DATA_READ,
sizeof(buf), buf);
if(i_status == 0) {
return strdup(&buf[9]);
}
return NULL;
#endif
}
/*!