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