diff --git a/include/cdio/mmc.h b/include/cdio/mmc.h index 2f6a1f22..971d089e 100644 --- a/include/cdio/mmc.h +++ b/include/cdio/mmc.h @@ -160,8 +160,7 @@ extern "C" { */ typedef enum { - CDIO_MMC_TEST_UNIT_READY = 0x00, /**< Request drive - information. */ + CDIO_MMC_GPCMD_TEST_UNIT_READY = 0x00, /**< test if drive ready. */ CDIO_MMC_GPCMD_INQUIRY = 0x12, /**< Request drive information. */ CDIO_MMC_GPCMD_MODE_SELECT_6 = 0x15, /**< Select medium diff --git a/include/cdio/mmc_cmds.h b/include/cdio/mmc_cmds.h index 8fde0c98..55ae0303 100644 --- a/include/cdio/mmc_cmds.h +++ b/include/cdio/mmc_cmds.h @@ -41,29 +41,57 @@ extern "C" { /** Return results of media status + @param p_cdio the CD object to be acted upon. + @param out_buf media status code from operation - @return DRIVER_OP_SUCCESS (0) if we got the status. - return codes are the same as driver_return_code_t + + @return DRIVER_OP_SUCCESS (0) if we got the status. Return codes + are the same as driver_return_code_t */ driver_return_code_t mmc_get_event_status(const CdIo_t *p_cdio, uint8_t out_buf[2]); + /** + Run a SCSI-MMC MODE SELECT (10-byte) command + and put the results in p_buf. + + @param p_cdio the CD object to be acted upon. + + @param p_buf pointer to location to store mode sense information + + @param i_size number of bytes allocated to p_buf + + @param page which "page" of the mode sense command we are interested in + + @param i_timeout value in milliseconds to use on timeout. Setting + to 0 uses the default time-out value stored in + mmc_timeout_ms. + + @return DRIVER_OP_SUCCESS if we ran the command ok. + */ + driver_return_code_t mmc_mode_select_10(CdIo_t *p_cdio, /*out*/ void *p_buf, + unsigned int i_size, int page, + unsigned int i_timeout); /** - Run a MODE_SENSE command (6- or 10-byte version) + Run a SCSI-MMC MODE_SENSE command (6- or 10-byte version) and put the results in p_buf @param p_cdio the CD object to be acted upon. + @param p_buf pointer to location to store mode sense information + @param i_size number of bytes allocated to p_buf + @param page which "page" of the mode sense command we are interested in + @return DRIVER_OP_SUCCESS if we ran the command ok. */ driver_return_code_t mmc_mode_sense( CdIo_t *p_cdio, /*out*/ void *p_buf, - int i_size, int page); + unsigned int i_size, int page); /** - Run a MODE_SENSE command (10-byte version) + Run a SCSI-MMC MODE SENSE command (10-byte version) and put the results in p_buf @param p_cdio the CD object to be acted upon. @param p_buf pointer to location to store mode sense information @@ -72,10 +100,10 @@ extern "C" { @return DRIVER_OP_SUCCESS if we ran the command ok. */ driver_return_code_t mmc_mode_sense_10( CdIo_t *p_cdio, /*out*/ void *p_buf, - int i_size, int page); + unsigned int i_size, int page); /** - Run a MODE_SENSE command (6-byte version) + Run a SCSI-MMC MODE SENSE command (6-byte version) and put the results in p_buf @param p_cdio the CD object to be acted upon. @param p_buf pointer to location to store mode sense information @@ -84,7 +112,7 @@ extern "C" { @return DRIVER_OP_SUCCESS if we ran the command ok. */ driver_return_code_t mmc_mode_sense_6( CdIo_t *p_cdio, /*out*/ void *p_buf, - int i_size, int page); + unsigned int i_size, int page); /** Issue a MMC READ_CD command. @@ -185,6 +213,8 @@ extern "C" { @param i_blocksize size of the a block expected to be returned @param i_blocks number of blocks expected to be returned. + + @return DRIVER_OP_SUCCESS if we ran the command ok. */ driver_return_code_t mmc_read_cd ( const CdIo_t *p_cdio, void *p_buf, lsn_t i_lsn, @@ -223,16 +253,30 @@ extern "C" { Load or Unload media using a MMC START STOP UNIT command. @param p_cdio the CD object to be acted upon. + @param b_eject eject if true and close tray if false + @param b_immediate wait or don't wait for operation to complete + @param power_condition Set CD-ROM to idle/standby/sleep. If nonzero, eject/load is ignored, so set to 0 if you want to eject or load. + @return DRIVER_OP_SUCCESS if we ran the command ok. + @see mmc_eject_media or mmc_close_tray */ - driver_return_code_t - mmc_start_stop_unit(const CdIo_t *p_cdio, bool b_eject, bool b_immediate, - uint8_t power_condition); + driver_return_code_t mmc_start_stop_unit(const CdIo_t *p_cdio, bool b_eject, + bool b_immediate, uint8_t power_condition); + + /** + Check if drive is ready using SCSI-MMC TEST UNIT READY command. + + @param p_cdio the CD object to be acted upon. + + @return DRIVER_OP_SUCCESS if we ran the command ok. + */ + driver_return_code_t mmc_test_unit_ready(const CdIo_t *p_cdio); + #ifndef DO_NOT_WANT_OLD_MMC_COMPATIBILITY #define mmc_start_stop_media mmc_start_stop_unit diff --git a/lib/driver/mmc_cmds.c b/lib/driver/mmc_cmds.c index ad46a83d..4c9a66da 100644 --- a/lib/driver/mmc_cmds.c +++ b/lib/driver/mmc_cmds.c @@ -66,9 +66,9 @@ 'direction' is the SCSI direction (read, write, none) of the command. */ -#define MMC_RUN_CMD(direction) \ +#define MMC_RUN_CMD(direction, i_timeout) \ p_cdio->op.run_mmc_cmd(p_cdio->env, \ - mmc_timeout_ms, \ + i_timeout, \ mmc_get_cmd_len(cdb.field[0]), \ &cdb, \ direction, i_size, p_buf) @@ -93,7 +93,7 @@ mmc_get_event_status(const CdIo_t *p_cdio, uint8_t out_buf[2]) cdb.field[1] = 1; /* We poll for info */ cdb.field[4] = 1 << 4; /* We want Media events */ - i_status = MMC_RUN_CMD(SCSI_MMC_DATA_READ); + i_status = MMC_RUN_CMD(SCSI_MMC_DATA_READ, mmc_timeout_ms); if (i_status == DRIVER_OP_SUCCESS) { out_buf[0] = buf[4]; out_buf[1] = buf[5]; @@ -102,7 +102,36 @@ mmc_get_event_status(const CdIo_t *p_cdio, uint8_t out_buf[2]) } /** - Run a MODE_SENSE command (6- or 10-byte version) + Run a SCSI-MMC MODE SELECT (10-byte) command + and put the results in p_buf. + + @param p_cdio the CD object to be acted upon. + + @param p_buf pointer to location to store mode sense information + + @param i_size number of bytes allocated to p_buf + + @param page which "page" of the mode sense command we are interested in + + @param i_timeout value in milliseconds to use on timeout. Setting + to 0 uses the default time-out value stored in + mmc_timeout_ms. + + @return DRIVER_OP_SUCCESS if we ran the command ok. + + */ +driver_return_code_t +mmc_mode_select_10(CdIo_t *p_cdio, /*out*/ void *p_buf, unsigned int i_size, + int page, unsigned int i_timeout) +{ + if (0 == i_timeout) i_timeout = mmc_timeout_ms; + MMC_CMD_SETUP_READ16(CDIO_MMC_GPCMD_MODE_SELECT_10); + cdb.field[1] = page; + return MMC_RUN_CMD(SCSI_MMC_DATA_WRITE, i_timeout); +} + +/** + Run a SCSI-MMC MMC MODE SENSE command (6- or 10-byte version) and put the results in p_buf @param p_cdio the CD object to be acted upon. @param p_buf pointer to location to store mode sense information @@ -111,8 +140,8 @@ mmc_get_event_status(const CdIo_t *p_cdio, uint8_t out_buf[2]) @return DRIVER_OP_SUCCESS if we ran the command ok. */ driver_return_code_t -mmc_mode_sense( CdIo_t *p_cdio, /*out*/ void *p_buf, int i_size, - int page) +mmc_mode_sense(CdIo_t *p_cdio, /*out*/ void *p_buf, unsigned int i_size, + int page) { /* We used to make a choice as to which routine we'd use based cdio_have_atapi(). But since that calls this in its determination, @@ -125,7 +154,7 @@ mmc_mode_sense( CdIo_t *p_cdio, /*out*/ void *p_buf, int i_size, } /** - Run a MODE_SENSE command (10-byte version) + Run a SCSI-MMC MODE SENSE command (10-byte version) and put the results in p_buf @param p_cdio the CD object to be acted upon. @param p_buf pointer to location to store mode sense information @@ -134,15 +163,15 @@ mmc_mode_sense( CdIo_t *p_cdio, /*out*/ void *p_buf, int i_size, @return DRIVER_OP_SUCCESS if we ran the command ok. */ driver_return_code_t -mmc_mode_sense_10( CdIo_t *p_cdio, void *p_buf, int i_size, int page) +mmc_mode_sense_10(CdIo_t *p_cdio, void *p_buf, unsigned int i_size, int page) { MMC_CMD_SETUP_READ16(CDIO_MMC_GPCMD_MODE_SENSE_10); cdb.field[2] = CDIO_MMC_ALL_PAGES & page; - return MMC_RUN_CMD(SCSI_MMC_DATA_READ); + return MMC_RUN_CMD(SCSI_MMC_DATA_READ, mmc_timeout_ms); } /** - Run a MODE_SENSE command (6-byte version) + Run a SCSI-MMC MODE SENSE command (6-byte version) and put the results in p_buf @param p_cdio the CD object to be acted upon. @param p_buf pointer to location to store mode sense information @@ -151,21 +180,20 @@ mmc_mode_sense_10( CdIo_t *p_cdio, void *p_buf, int i_size, int page) @return DRIVER_OP_SUCCESS if we ran the command ok. */ driver_return_code_t -mmc_mode_sense_6( CdIo_t *p_cdio, void *p_buf, int i_size, int page) +mmc_mode_sense_6(CdIo_t *p_cdio, void *p_buf, unsigned int i_size, int page) { MMC_CMD_SETUP(CDIO_MMC_GPCMD_MODE_SENSE_6); cdb.field[4] = i_size; cdb.field[2] = CDIO_MMC_ALL_PAGES & page; - return MMC_RUN_CMD(SCSI_MMC_DATA_READ); + return MMC_RUN_CMD(SCSI_MMC_DATA_READ, mmc_timeout_ms); } /* Maximum blocks to retrieve. Would be nice to customize this based on drive capabilities. */ #define MAX_CD_READ_BLOCKS 16 -#define CD_READ_TIMEOUT_MS mmc_timeout_ms * (MAX_CD_READ_BLOCKS/2) /** Issue a MMC READ_CD command. @@ -265,6 +293,8 @@ mmc_mode_sense_6( CdIo_t *p_cdio, void *p_buf, int i_size, int page) @param i_blocksize size of the a block expected to be returned @param i_blocks number of blocks expected to be returned. + + @return DRIVER_OP_SUCCESS if we ran the command ok. */ driver_return_code_t mmc_read_cd(const CdIo_t *p_cdio, void *p_buf1, lsn_t i_lsn, @@ -277,6 +307,7 @@ mmc_read_cd(const CdIo_t *p_cdio, void *p_buf1, lsn_t i_lsn, void *p_buf = p_buf1; uint8_t cdb9 = 0; const unsigned int i_size = i_blocksize * i_blocks; + const unsigned int i_timeout = mmc_timeout_ms * (MAX_CD_READ_BLOCKS/2); MMC_CMD_SETUP(CDIO_MMC_GPCMD_READ_CD); @@ -305,7 +336,7 @@ mmc_read_cd(const CdIo_t *p_cdio, void *p_buf1, lsn_t i_lsn, CDIO_MMC_SET_READ_LBA (cdb.field, (i_lsn+j)); CDIO_MMC_SET_READ_LENGTH24(cdb.field, i_blocks2); - i_status = MMC_RUN_CMD(SCSI_MMC_DATA_READ); + i_status = MMC_RUN_CMD(SCSI_MMC_DATA_READ, i_timeout); if (i_status) return i_status; @@ -338,6 +369,8 @@ mmc_read_cd(const CdIo_t *p_cdio, void *p_buf1, lsn_t i_lsn, driver. @see cdio_set_speed and mmc_set_drive_speed + + @return DRIVER_OP_SUCCESS if we ran the command ok. */ int mmc_set_speed(const CdIo_t *p_cdio, int i_Kbs_speed) @@ -362,11 +395,11 @@ mmc_set_speed(const CdIo_t *p_cdio, int i_Kbs_speed) the maximum allowable speed. */ CDIO_MMC_SET_LEN16(cdb.field, 4, 0xffff); - return MMC_RUN_CMD(SCSI_MMC_DATA_WRITE); + return MMC_RUN_CMD(SCSI_MMC_DATA_WRITE, mmc_timeout_ms); } /** - Load or Unload media using a MMC START/STOP UNIT command. + Load or Unload media using a SCSI-MMC START/STOP UNIT command. @param p_cdio the CD object to be acted upon. @param b_eject eject if true and close tray if false @@ -397,5 +430,21 @@ mmc_start_stop_unit(const CdIo_t *p_cdio, bool b_eject, bool b_immediate, cdb.field[4] = 3; /* close tray for tray-type */ } - return MMC_RUN_CMD(SCSI_MMC_DATA_WRITE); + return MMC_RUN_CMD(SCSI_MMC_DATA_WRITE, mmc_timeout_ms); +} + +/** + Check if drive is ready using SCSI-MMC TEST UNIT READY command. + + @param p_cdio the CD object to be acted upon. + + @return DRIVER_OP_SUCCESS if we ran the command ok. + */ +driver_return_code_t +mmc_test_unit_ready(const CdIo_t *p_cdio) +{ + const unsigned int i_size = 0; + void * p_buf = NULL; + MMC_CMD_SETUP_READ16(CDIO_MMC_GPCMD_TEST_UNIT_READY); + return MMC_RUN_CMD(SCSI_MMC_DATA_NONE, mmc_timeout_ms); } diff --git a/test/driver/mmc.c b/test/driver/mmc.c index 1a3b5791..e72acfee 100644 --- a/test/driver/mmc.c +++ b/test/driver/mmc.c @@ -61,7 +61,7 @@ static int tmmc_load_eject(CdIo_t *p_cdio, int *sense_avail, unsigned char sense_reply[18], int flag); static int tmmc_mode_select(CdIo_t *p_cdio, int *sense_avail, unsigned char sense_reply[18], - unsigned char *buf, int buf_fill, int flag); + unsigned char *p_buf, unsigned int i_size, int flag); static int tmmc_mode_sense(CdIo_t *p_cdio, int *sense_avail, unsigned char sense_reply[18], @@ -148,15 +148,10 @@ tmmc_test_unit_ready(CdIo_t *p_cdio, int *sense_avail, unsigned char sense_reply[18], int flag) { int i_status; - mmc_cdb_t cdb = {{0, }}; - char buf[1]; /* just to have an address to pass to mmc_run_cmd() */ - - memset(cdb.field, 0, 6); - cdb.field[0] = CDIO_MMC_TEST_UNIT_READY; /* SPC-3 6.33 */ if (flag & 1) fprintf(stderr, "tmmc_test_unit_ready ... "); - i_status = mmc_run_cmd(p_cdio, 10000, &cdb, SCSI_MMC_DATA_NONE, 0, buf); + i_status = mmc_test_unit_ready(p_cdio); return tmmc_handle_outcome(p_cdio, i_status, sense_avail, sense_reply, flag & 1); @@ -213,17 +208,15 @@ tmmc_mode_sense(CdIo_t *p_cdio, int *sense_avail,unsigned char sense_reply[18], unsigned char *buf, int *buf_fill, int flag) { driver_return_code_t i_status; - mmc_cdb_t cdb = {{0, }}; if (alloc_len < 10) return DRIVER_OP_BAD_PARAMETER; - mmc_mode_sense_10(p_cdio, buf, alloc_len, page_code); if (flag & 1) fprintf(stderr, "tmmc_mode_sense(0x%X, %X, %d) ... ", (unsigned int) page_code, (unsigned int) subpage_code, alloc_len); - i_status = mmc_run_cmd(p_cdio, 10000, &cdb, SCSI_MMC_DATA_READ, - alloc_len, buf); + + i_status = mmc_mode_sense_10(p_cdio, buf, alloc_len, page_code); tmmc_handle_outcome(p_cdio, i_status, sense_avail, sense_reply, flag & 1); if (DRIVER_OP_SUCCESS != i_status) return i_status; @@ -251,38 +244,43 @@ tmmc_mode_sense(CdIo_t *p_cdio, int *sense_avail,unsigned char sense_reply[18], static int tmmc_mode_select(CdIo_t *p_cdio, int *sense_avail, unsigned char sense_reply[18], - unsigned char *buf, int buf_fill, int flag) + unsigned char *p_buf, unsigned int i_size, int flag) { - int i_status, i; - mmc_cdb_t cdb = {{0, }}; + int i_status, i; +#ifndef MODE_SELECT_FIXED + mmc_cdb_t cdb = {{0, }}; +#endif - if (buf_fill < 10) - return DRIVER_OP_BAD_PARAMETER; - - if (flag & 1) { - printf("tmmc_mode_select to drive: %d bytes\n", buf_fill); - for (i = 0; i < buf_fill; i++) { - printf("%2.2X ", (unsigned int) buf[i]); - if ((i % 20) == 19) - printf("\n"); + if (i_size < 10) + return DRIVER_OP_BAD_PARAMETER; + + if (flag & 1) { + printf("tmmc_mode_select to drive: %d bytes\n", i_size); + for (i = 0; i < i_size; i++) { + printf("%2.2X ", (unsigned int) p_buf[i]); + if ((i % 20) == 19) + printf("\n"); + } + if ((i % 20)) + printf("\n"); } - if ((i % 20)) - printf("\n"); - } - - CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_MODE_SELECT_10); /* SPC-3 6.8 */ - cdb.field[1] = 0x10; /* PF = 1 : official SCSI mode page */ - CDIO_MMC_SET_READ_LENGTH16(cdb.field, buf_fill); - if (flag & 1) - fprintf(stderr, "tmmc_mode_select(0x%X, %d, %d) ... ", - (unsigned int) buf[8], (unsigned int) buf[9], buf_fill); - i_status = mmc_run_cmd(p_cdio, 10000, &cdb, SCSI_MMC_DATA_WRITE, - buf_fill, buf); - return tmmc_handle_outcome(p_cdio, i_status, sense_avail, sense_reply, + + if (flag & 1) + fprintf(stderr, "tmmc_mode_select(0x%X, %d, %d) ... ", + (unsigned int) p_buf[8], (unsigned int) p_buf[9], i_size); +#ifdef MODE_SELECT_FIXED + i_status = mmc_mode_select_10(p_cdio, p_buf, i_size, 0x10, 10000); +#else + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_MODE_SELECT_10); /* SPC-3 6.8 */ + cdb.field[1] = 0x10; /* PF = 1 : official SCSI mode page */ + CDIO_MMC_SET_READ_LENGTH16(cdb.field, i_size); + i_status = mmc_run_cmd(p_cdio, 10000, &cdb, SCSI_MMC_DATA_WRITE, + i_size, p_buf); +#endif + return tmmc_handle_outcome(p_cdio, i_status, sense_avail, sense_reply, flag & 1); } - /* --------------------------- Larger gestures ----------------------------- */