diff --git a/NEWS b/NEWS index ccce885c..388fb9db 100644 --- a/NEWS +++ b/NEWS @@ -8,7 +8,7 @@ - cd-info now shows the total disc size. - Filesystem reorganization to better support growth and paranoia inclusion - FreeBSD 6 tolerated, CAM audio read mode works. -- improve Win32 driver +- improve Win32 driver, e.g. audio read mode works better for ioctl. - mode detection fixes - all read routines check and adjust the lsn so we don't try to access beyond the end of the disc @@ -171,4 +171,4 @@ 0.1 Routines split off from VCDImager. -$Id: NEWS,v 1.62 2005/01/23 00:02:15 rocky Exp $ +$Id: NEWS,v 1.63 2005/01/24 00:06:31 rocky Exp $ diff --git a/include/cdio/disc.h b/include/cdio/disc.h index f12012bb..f8ffb7c8 100644 --- a/include/cdio/disc.h +++ b/include/cdio/disc.h @@ -1,5 +1,5 @@ /* -*- c -*- - $Id: disc.h,v 1.3 2005/01/09 16:07:46 rocky Exp $ + $Id: disc.h,v 1.4 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2004, 2005 Rocky Bernstein @@ -40,9 +40,9 @@ extern "C" { /*! Get the lsn of the end of the CD - @return the leadout LSN or CDIO_INVALID_LSN if there is an error. + @return the lsn. On error 0 or CDIO_INVALD_LSN. */ - unsigned int cdio_get_disc_last_lsn(const CdIo_t *p_cdio); + lsn_t cdio_get_disc_last_lsn(const CdIo_t *p_cdio); /*! @@ -70,13 +70,8 @@ extern "C" { */ track_t cdio_get_num_tracks (const CdIo_t *p_cdio); - /*! - Get the size of the CD in logical block address (LBA) units. - - @param p_cdio the CD object queried - @return the size or 0 if there was an error. - */ - uint32_t cdio_stat_size (const CdIo_t *p_cdio); + /*! cdio_stat_size is deprecated. @see cdio_get_disc_last_lsn */ +#define cdio_stat_size cdio_get_disc_last_lsn #ifdef __cplusplus } diff --git a/include/cdio/scsi_mmc.h b/include/cdio/scsi_mmc.h index 4d886c0b..740aed59 100644 --- a/include/cdio/scsi_mmc.h +++ b/include/cdio/scsi_mmc.h @@ -1,5 +1,5 @@ /* - $Id: scsi_mmc.h,v 1.40 2005/01/20 04:46:25 rocky Exp $ + $Id: scsi_mmc.h,v 1.41 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein @@ -378,8 +378,15 @@ int scsi_mmc_run_cmd( const CdIo_t *p_cdio, unsigned int i_timeout_ms, @return 0 if successful. */ -int scsi_mmc_eject_media( const CdIo_t *p_cdio); +int scsi_mmc_eject_media( const CdIo_t *p_cdio ); +/*! + Get the lsn of the end of the CD + + @return the lsn. On error return CDIO_INVALID_LSN. +*/ +lsn_t scsi_mmc_get_disc_last_lsn( const CdIo_t *p_cdio ); + /*! Return the discmode as reported by the SCSI-MMC Read (FULL) TOC command. diff --git a/lib/driver/FreeBSD/freebsd.c b/lib/driver/FreeBSD/freebsd.c index 98c45805..05d86b1c 100644 --- a/lib/driver/FreeBSD/freebsd.c +++ b/lib/driver/FreeBSD/freebsd.c @@ -1,5 +1,5 @@ /* - $Id: freebsd.c,v 1.11 2005/01/23 19:16:58 rocky Exp $ + $Id: freebsd.c,v 1.12 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein @@ -27,7 +27,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: freebsd.c,v 1.11 2005/01/23 19:16:58 rocky Exp $"; +static const char _rcsid[] = "$Id: freebsd.c,v 1.12 2005/01/24 00:06:31 rocky Exp $"; #include "freebsd.h" @@ -142,18 +142,19 @@ _read_mode2_sectors_freebsd (void *user_data, void *data, lsn_t lsn, /*! Return the size of the CD in logical block address (LBA) units. + @return the lsn. On error return CDIO_INVALID_LSN. */ -static uint32_t -_stat_size_freebsd (void *p_obj) +static lsn_t +get_disc_last_lsn_freebsd (void *p_obj) { _img_private_t *p_env = p_obj; - if (NULL == p_env) return CDIO_INVALID_LBA; + if (!p_env) return CDIO_INVALID_LSN; if (_AM_CAM == p_env->access_mode) - return stat_size_freebsd_cam(p_env); + return get_disc_last_lsn_mmc(p_env); else - return stat_size_freebsd_ioctl(p_env); + return get_disc_last_lsn_freebsd_ioctl(p_env); } /*! @@ -582,6 +583,7 @@ cdio_open_am_freebsd (const char *psz_orig_source_name, .get_cdtext = get_cdtext_generic, .get_default_device = cdio_get_default_device_freebsd, .get_devices = cdio_get_devices_freebsd, + .get_disc_last_lsn = get_disc_last_lsn_freebsd .get_discmode = get_discmode_generic, .get_drive_cap = get_drive_cap_freebsd, .get_first_track_num = get_first_track_num_generic, @@ -604,7 +606,6 @@ cdio_open_am_freebsd (const char *psz_orig_source_name, .set_arg = _set_arg_freebsd, .set_blocksize = set_blocksize_mmc, .set_speed = set_speed_freebsd, - .stat_size = _stat_size_freebsd }; _data = _cdio_malloc (sizeof (_img_private_t)); diff --git a/lib/driver/FreeBSD/freebsd_cam.c b/lib/driver/FreeBSD/freebsd_cam.c index 24c882b2..66912919 100644 --- a/lib/driver/FreeBSD/freebsd_cam.c +++ b/lib/driver/FreeBSD/freebsd_cam.c @@ -1,7 +1,7 @@ /* - $Id: freebsd_cam.c,v 1.2 2005/01/20 05:07:00 rocky Exp $ + $Id: freebsd_cam.c,v 1.3 2005/01/24 00:06:31 rocky Exp $ - Copyright (C) 2004 Rocky Bernstein + Copyright (C) 2004, 2005 Rocky Bernstein 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 @@ -26,7 +26,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: freebsd_cam.c,v 1.2 2005/01/20 05:07:00 rocky Exp $"; +static const char _rcsid[] = "$Id: freebsd_cam.c,v 1.3 2005/01/24 00:06:31 rocky Exp $"; #ifdef HAVE_FREEBSD_CDROM @@ -155,7 +155,7 @@ free_freebsd_cam (void *user_data) free (p_env); } -int +static driver_return_code_t read_mode2_sector_freebsd_cam (_img_private_t *p_env, void *data, lsn_t lsn, bool b_form2) { @@ -167,7 +167,7 @@ read_mode2_sector_freebsd_cam (_img_private_t *p_env, void *data, lsn_t lsn, int retval = read_mode2_sectors_freebsd_cam(p_env, buf, lsn, 1); if ( retval ) return retval; memcpy (((char *)data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); - return 0; + return DRIVER_OP_SUCCESS; } } @@ -195,19 +195,18 @@ read_mode2_sectors_freebsd_cam (_img_private_t *p_env, void *p_buf, return retval; if ((retval = run_scsi_cmd_freebsd_cam (p_env, 0, - scsi_mmc_get_cmd_len(cdb.field[0]), - &cdb, - SCSI_MMC_DATA_READ, - M2RAW_SECTOR_SIZE * nblocks, - p_buf))) + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, + SCSI_MMC_DATA_READ, + M2RAW_SECTOR_SIZE * nblocks, + p_buf))) { scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE); return retval; } - if ((retval = scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE))) - return retval; - } else + return scsi_mmc_set_blocksize (p_env->gen.cdio, CDIO_CD_FRAMESIZE); + } else { CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_CD); CDIO_MMC_SET_READ_LENGTH24(cdb.field, nblocks); cdb.field[1] = 0; /* sector size mode2 */ @@ -217,56 +216,8 @@ read_mode2_sectors_freebsd_cam (_img_private_t *p_env, void *p_buf, &cdb, SCSI_MMC_DATA_READ, M2RAW_SECTOR_SIZE * nblocks, p_buf); - - return 0; -} - -/*! - Return the size of the CD in logical block address (LBA) units. - */ -uint32_t -stat_size_freebsd_cam (_img_private_t *p_env) -{ - scsi_mmc_cdb_t cdb = {{0, }}; - uint8_t buf[12] = { 0, }; - - uint32_t retval; - int i_status; - - /* Operation code */ - CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); - - cdb.field[1] = 0; /* lba; msf: 0x2 */ - - /* Format */ - cdb.field[2] = CDIO_MMC_READTOC_FMT_TOC; - - CDIO_MMC_SET_START_TRACK(cdb.field, CDIO_CDROM_LEADOUT_TRACK); - - CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(buf)); - - p_env->ccb.csio.data_ptr = buf; - p_env->ccb.csio.dxfer_len = sizeof (buf); - - i_status = run_scsi_cmd_freebsd_cam(p_env, DEFAULT_TIMEOUT_MSECS, - scsi_mmc_get_cmd_len(cdb.field[0]), - &cdb, SCSI_MMC_DATA_READ, - sizeof(buf), buf); - if (0 != i_status) - return 0; - - { - int i; - - retval = 0; - for (i = 8; i < 12; i++) - { - retval <<= 8; - retval += buf[i]; - } + } - - return retval; } /*! @@ -284,23 +235,21 @@ eject_media_freebsd_cam (_img_private_t *p_env) i_status = run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_WRITE, 0, &buf); - if (0 != i_status) - return i_status; + if (i_status) return i_status; cdb.field[4] = 1; i_status = run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS, scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, SCSI_MMC_DATA_WRITE, 0, &buf); - if (0 != i_status) - return i_status; + if (i_status) return i_status; CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_START_STOP); cdb.field[4] = 2; /* eject */ return run_scsi_cmd_freebsd_cam (p_env, DEFAULT_TIMEOUT_MSECS, - scsi_mmc_get_cmd_len(cdb.field[0]), - &cdb, - SCSI_MMC_DATA_WRITE, 0, &buf); + scsi_mmc_get_cmd_len(cdb.field[0]), + &cdb, + SCSI_MMC_DATA_WRITE, 0, &buf); } #endif /* HAVE_FREEBSD_CDROM */ diff --git a/lib/driver/FreeBSD/freebsd_ioctl.c b/lib/driver/FreeBSD/freebsd_ioctl.c index eb0673cd..30fabd62 100644 --- a/lib/driver/FreeBSD/freebsd_ioctl.c +++ b/lib/driver/FreeBSD/freebsd_ioctl.c @@ -1,5 +1,5 @@ /* - $Id: freebsd_ioctl.c,v 1.1 2004/12/18 17:29:32 rocky Exp $ + $Id: freebsd_ioctl.c,v 1.2 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2003, 2004 Rocky Bernstein @@ -27,7 +27,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: freebsd_ioctl.c,v 1.1 2004/12/18 17:29:32 rocky Exp $"; +static const char _rcsid[] = "$Id: freebsd_ioctl.c,v 1.2 2005/01/24 00:06:31 rocky Exp $"; #ifdef HAVE_FREEBSD_CDROM @@ -120,8 +120,8 @@ read_mode2_sector_freebsd_ioctl (_img_private_t *env, void *data, lsn_t lsn, /*! Return the size of the CD in logical block address (LBA) units. */ -uint32_t -stat_size_freebsd_ioctl (_img_private_t *_obj) +lsn_t +get_disc_last_lsn_freebsd_ioctl (_img_private_t *_obj) { struct ioc_read_toc_single_entry tocent; uint32_t size; diff --git a/lib/driver/MSWindows/win32.c b/lib/driver/MSWindows/win32.c index 7411b50b..d114fa6c 100644 --- a/lib/driver/MSWindows/win32.c +++ b/lib/driver/MSWindows/win32.c @@ -1,5 +1,5 @@ /* - $Id: win32.c,v 1.11 2005/01/23 17:14:33 rocky Exp $ + $Id: win32.c,v 1.12 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein @@ -26,7 +26,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: win32.c,v 1.11 2005/01/23 17:14:33 rocky Exp $"; +static const char _rcsid[] = "$Id: win32.c,v 1.12 2005/01/24 00:06:31 rocky Exp $"; #include #include @@ -381,7 +381,7 @@ _cdio_read_mode2_sectors (void *p_user_data, void *data, lsn_t lsn, Return the size of the CD in logical block address (LBA) units. */ static uint32_t -stat_size_win32 (void *p_user_data) +get_disc_last_lsn_win32 (void *p_user_data) { _img_private_t *p_env = p_user_data; @@ -741,6 +741,7 @@ cdio_open_am_win32 (const char *psz_orig_source, const char *psz_access_mode) _funcs.get_cdtext = get_cdtext_generic; _funcs.get_default_device = cdio_get_default_device_win32; _funcs.get_devices = cdio_get_devices_win32; + _funcs.get_disc_last_lsn = get_disc_last_lsn_win32; _funcs.get_discmode = get_discmode_win32; _funcs.get_drive_cap = get_drive_cap_mmc; _funcs.get_first_track_num = get_first_track_num_generic; @@ -766,7 +767,6 @@ cdio_open_am_win32 (const char *psz_orig_source, const char *psz_access_mode) _funcs.set_arg = set_arg_win32; _funcs.set_blocksize = set_blocksize_mmc; _funcs.set_speed = set_speed_mmc; - _funcs.stat_size = stat_size_win32; _data = _cdio_malloc (sizeof (_img_private_t)); _data->access_mode = str_to_access_mode_win32(psz_access_mode); diff --git a/lib/driver/_cdio_aix.c b/lib/driver/_cdio_aix.c index 6b244f51..15d3dac3 100644 --- a/lib/driver/_cdio_aix.c +++ b/lib/driver/_cdio_aix.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_aix.c,v 1.6 2005/01/23 19:16:58 rocky Exp $ + $Id: _cdio_aix.c,v 1.7 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2004 Rocky Bernstein @@ -37,7 +37,7 @@ #ifdef HAVE_AIX_CDROM -static const char _rcsid[] = "$Id: _cdio_aix.c,v 1.6 2005/01/23 19:16:58 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_aix.c,v 1.7 2005/01/24 00:06:31 rocky Exp $"; #ifdef HAVE_GLOB_H #include @@ -413,7 +413,7 @@ _read_mode2_sectors_aix (void *p_user_data, void *data, lsn_t lsn, Return the size of the CD in logical block address (LBA) units. */ static uint32_t -_cdio_stat_size (void *p_user_data) +get_disc_last_lsn_aix (void *p_user_data) { uint32_t i_size=0; #ifdef FINISHED @@ -941,6 +941,7 @@ cdio_open_am_aix (const char *psz_orig_source, const char *access_mode) _funcs.get_cdtext = get_cdtext_generic; _funcs.get_default_device = cdio_get_default_device_aix; _funcs.get_devices = cdio_get_devices_aix; + _funcs.get_disc_last_lsn = get_disc_last_lsn_aix; _funcs.get_discmode = get_discmode_aix; _funcs.get_drive_cap = get_drive_cap_mmc; _funcs.get_first_track_num= get_first_track_num_generic; @@ -960,7 +961,6 @@ cdio_open_am_aix (const char *psz_orig_source, const char *access_mode) _funcs.read_mode2_sectors = _read_mode2_sectors_aix; _funcs.read_toc = read_toc_aix; _funcs.run_scsi_mmc_cmd = run_scsi_cmd_aix; - _funcs.stat_size = _cdio_stat_size; _funcs.set_arg = _set_arg_aix; _data = _cdio_malloc (sizeof (_img_private_t)); diff --git a/lib/driver/_cdio_bsdi.c b/lib/driver/_cdio_bsdi.c index 47e537b5..1d4c0c21 100644 --- a/lib/driver/_cdio_bsdi.c +++ b/lib/driver/_cdio_bsdi.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_bsdi.c,v 1.8 2005/01/23 19:16:58 rocky Exp $ + $Id: _cdio_bsdi.c,v 1.9 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002, 2003, 2004, 2005 Rocky Bernstein @@ -27,7 +27,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.8 2005/01/23 19:16:58 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.9 2005/01/24 00:06:31 rocky Exp $"; #include #include @@ -271,7 +271,7 @@ _read_audio_sectors_bsdi (void *user_data, void *data, lsn_t lsn, } } - return 0; + return DRIVER_OP_SUCCESS; } /*! @@ -289,7 +289,6 @@ _read_mode1_sector_bsdi (void *user_data, void *data, lsn_t lsn, #else return cdio_generic_read_form1_sector(user_data, data, lsn); #endif - return 0; } /*! @@ -312,7 +311,7 @@ _read_mode1_sectors_bsdi (void *p_user_data, void *p_data, lsn_t lsn, lsn + i, b_form2)) ) return retval; } - return 0; + return DRIVER_OP_SUCCESS; } /*! @@ -371,7 +370,7 @@ _read_mode2_sector_bsdi (void *p_user_data, void *p_data, lsn_t lsn, else memcpy (((char *)p_data), buf + CDIO_CD_SUBHEADER_SIZE, CDIO_CD_FRAMESIZE); - return 0; + return DRIVER_OP_SUCCESS; } /*! @@ -395,14 +394,14 @@ _read_mode2_sectors_bsdi (void *user_data, void *data, lsn_t lsn, lsn + i, b_form2); if (retval) return retval; } - return 0; + return DRIVER_OP_SUCCESS; } /*! Return the size of the CD in logical block address (LBA) units. */ static uint32_t -_stat_size_bsdi (void *user_data) +get_disc_last_lsn_bsdi (void *user_data) { _img_private_t *p_env = user_data; @@ -767,6 +766,7 @@ cdio_open_bsdi (const char *psz_orig_source) .get_default_device = cdio_get_default_device_bsdi, .get_devices = cdio_get_devices_bsdi, .get_drive_cap = get_drive_cap_mmc, + .get_disc_last_lsn = get_disc_last_lsn_bsdi .get_discmode = get_discmode_generic, .get_first_track_num= get_first_track_num_generic, .get_hwinfo = NULL, @@ -786,7 +786,6 @@ cdio_open_bsdi (const char *psz_orig_source) .read_toc = &read_toc_bsdi, .run_scsi_mmc_cmd = &run_scsi_cmd_bsdi, .set_arg = _set_arg_bsdi, - .stat_size = _stat_size_bsdi }; _data = _cdio_malloc (sizeof (_img_private_t)); diff --git a/lib/driver/_cdio_linux.c b/lib/driver/_cdio_linux.c index 19da99cc..7593dc2c 100644 --- a/lib/driver/_cdio_linux.c +++ b/lib/driver/_cdio_linux.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_linux.c,v 1.18 2005/01/23 19:16:58 rocky Exp $ + $Id: _cdio_linux.c,v 1.19 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002, 2003, 2004, 2005 Rocky Bernstein @@ -27,7 +27,7 @@ # include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.18 2005/01/23 19:16:58 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.19 2005/01/24 00:06:31 rocky Exp $"; #include @@ -921,9 +921,10 @@ run_scsi_cmd_linux( void *p_user_data, /*! Return the size of the CD in logical block address (LBA) units. + @return the lsn. On error return CDIO_INVALID_LSN. */ -static uint32_t -stat_size_linux (void *p_user_data) +static lsn_t +get_disc_last_lsn_linux (void *p_user_data) { _img_private_t *p_env = p_user_data; @@ -935,7 +936,7 @@ stat_size_linux (void *p_user_data) if (ioctl (p_env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1) { perror ("ioctl(CDROMREADTOCENTRY)"); - exit (EXIT_FAILURE); + return CDIO_INVALID_LSN; } i_size = tocent.cdte_addr.lba; @@ -1138,6 +1139,7 @@ cdio_open_am_linux (const char *psz_orig_source, const char *access_mode) .get_cdtext = get_cdtext_generic, .get_default_device = cdio_get_default_device_linux, .get_devices = cdio_get_devices_linux, + .get_disc_last_lsn = get_disc_last_lsn_linux, .get_discmode = get_discmode_linux, #if USE_LINUX_CAP .get_drive_cap = get_drive_cap_linux, @@ -1167,7 +1169,6 @@ cdio_open_am_linux (const char *psz_orig_source, const char *access_mode) .set_arg = set_arg_linux, .set_blocksize = set_blocksize_mmc, .set_speed = set_speed_linux, - .stat_size = stat_size_linux }; _data = _cdio_malloc (sizeof (_img_private_t)); diff --git a/lib/driver/_cdio_osx.c b/lib/driver/_cdio_osx.c index 6f0f5508..1db34710 100644 --- a/lib/driver/_cdio_osx.c +++ b/lib/driver/_cdio_osx.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_osx.c,v 1.10 2005/01/21 23:12:54 rocky Exp $ + $Id: _cdio_osx.c,v 1.11 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein from vcdimager code: @@ -34,7 +34,7 @@ #include "config.h" #endif -static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.10 2005/01/21 23:12:54 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_osx.c,v 1.11 2005/01/24 00:06:31 rocky Exp $"; #include #include @@ -1321,7 +1321,7 @@ _eject_media_osx (void *user_data) { Return the size of the CD in logical block address (LBA) units. */ static uint32_t -_stat_size_osx (void *user_data) +_get_disc_last_lsn_osx (void *user_data) { return get_track_lba_osx(user_data, CDIO_CDROM_LEADOUT_TRACK); } @@ -1667,6 +1667,7 @@ cdio_open_osx (const char *psz_orig_source) .get_cdtext = get_cdtext_osx, .get_default_device = cdio_get_default_device_osx, .get_devices = cdio_get_devices_osx, + .get_disc_last_lsn = _get_disc_last_lsn_osx .get_discmode = get_discmode_osx, .get_drive_cap = get_drive_cap_osx, .get_first_track_num = get_first_track_num_generic, @@ -1691,7 +1692,6 @@ cdio_open_osx (const char *psz_orig_source) .run_scsi_mmc_cmd = run_scsi_cmd_osx, .set_arg = _set_arg_osx, .set_speed = set_speed_osx, - .stat_size = _stat_size_osx }; _data = _cdio_malloc (sizeof (_img_private_t)); diff --git a/lib/driver/_cdio_sunos.c b/lib/driver/_cdio_sunos.c index a71867d5..5000b6cf 100644 --- a/lib/driver/_cdio_sunos.c +++ b/lib/driver/_cdio_sunos.c @@ -1,5 +1,5 @@ /* - $Id: _cdio_sunos.c,v 1.15 2005/01/23 19:16:58 rocky Exp $ + $Id: _cdio_sunos.c,v 1.16 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2001 Herbert Valerio Riedel Copyright (C) 2002, 2003, 2004, 2005 Rocky Bernstein @@ -38,7 +38,7 @@ #ifdef HAVE_SOLARIS_CDROM -static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.15 2005/01/23 19:16:58 rocky Exp $"; +static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.16 2005/01/24 00:06:31 rocky Exp $"; #ifdef HAVE_GLOB_H #include @@ -346,7 +346,7 @@ _read_mode2_sectors_solaris (void *p_user_data, void *data, lsn_t lsn, Return the size of the CD in logical block address (LBA) units. */ static uint32_t -_cdio_stat_size (void *p_user_data) +get_disc_last_lsn_sunos (void *p_user_data) { _img_private_t *p_env = p_user_data; @@ -865,6 +865,7 @@ cdio_open_am_solaris (const char *psz_orig_source, const char *access_mode) _funcs.get_cdtext = get_cdtext_generic; _funcs.get_default_device = cdio_get_default_device_solaris; _funcs.get_devices = cdio_get_devices_solaris; + _funcs.get_disc_last_lsn = get_disc_last_lsn_sunos; _funcs.get_discmode = get_discmode_solaris; _funcs.get_drive_cap = get_drive_cap_mmc; _funcs.get_first_track_num = get_first_track_num_generic; @@ -887,11 +888,9 @@ cdio_open_am_solaris (const char *psz_orig_source, const char *access_mode) _funcs.read_mode2_sectors = _read_mode2_sectors_solaris; _funcs.read_toc = read_toc_solaris; _funcs.run_scsi_mmc_cmd = run_scsi_cmd_solaris; - _funcs.stat_size = _cdio_stat_size; _funcs.set_arg = _set_arg_solaris; _funcs.set_blocksize = set_blocksize_mmc; _funcs.set_speed = set_speed_solaris; - _funcs.stat_size = _cdio_stat_size; _data = _cdio_malloc (sizeof (_img_private_t)); diff --git a/lib/driver/cdio_private.h b/lib/driver/cdio_private.h index b912ea27..4e4f72fa 100644 --- a/lib/driver/cdio_private.h +++ b/lib/driver/cdio_private.h @@ -1,5 +1,5 @@ /* - $Id: cdio_private.h,v 1.9 2005/01/21 02:59:32 rocky Exp $ + $Id: cdio_private.h,v 1.10 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein @@ -101,6 +101,12 @@ extern "C" { */ char * (*get_default_device)(void); + /*! + Return the size of the CD in logical block address (LBA) units. + @return the lsn. On error 0 or CDIO_INVALD_LSN. + */ + lsn_t (*get_disc_last_lsn) (void *p_env); + /*! Get disc mode associated with cd_obj. */ @@ -170,7 +176,7 @@ extern "C" { Set the drive speed. -1 is returned if we had an error. -2 is returned if this is not implemented for the current driver. */ - int (*p_get_speed) (void *p_env); + int (*get_speed) (void *p_env); /*! Return true if we have XA data (green, mode2 form1) or @@ -290,11 +296,6 @@ extern "C" { */ int (*set_speed) ( void *p_env, int i_speed ); - /*! - Return the size of the CD in logical block address (LBA) units. - */ - uint32_t (*stat_size) (void *p_env); - } cdio_funcs_t; diff --git a/lib/driver/disc.c b/lib/driver/disc.c index 1971f16b..746b2e84 100644 --- a/lib/driver/disc.c +++ b/lib/driver/disc.c @@ -1,5 +1,5 @@ /* - $Id: disc.c,v 1.3 2005/01/09 16:07:46 rocky Exp $ + $Id: disc.c,v 1.4 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein Copyright (C) 2001 Herbert Valerio Riedel @@ -45,19 +45,26 @@ const char *discmode2str[] = { "CD-i" }; -unsigned int -cdio_get_disc_last_lsn(const CdIo *p_cdio) +/*! + Get the size of the CD in logical block address (LBA) units. + + @param p_cdio the CD object queried + @return the lsn. On error 0 or CDIO_INVALD_LSN. +*/ +lsn_t +cdio_get_disc_last_lsn(const CdIo_t *p_cdio) { - return cdio_get_track_lsn(p_cdio, CDIO_CDROM_LEADOUT_TRACK); + if (!p_cdio) return CDIO_INVALID_LSN; + return p_cdio->op.get_disc_last_lsn (p_cdio->env); } /*! Get medium associated with cd_obj. */ discmode_t -cdio_get_discmode (CdIo *cd_obj) +cdio_get_discmode (CdIo_t *cd_obj) { - if (cd_obj == NULL) return CDIO_DISC_MODE_ERROR; + if (!cd_obj) return CDIO_DISC_MODE_ERROR; if (cd_obj->op.get_discmode) { return cd_obj->op.get_discmode (cd_obj->env); @@ -72,7 +79,7 @@ cdio_get_discmode (CdIo *cd_obj) then return NULL. */ char * -cdio_get_mcn (const CdIo *p_cdio) +cdio_get_mcn (const CdIo_t *p_cdio) { if (p_cdio->op.get_mcn) { return p_cdio->op.get_mcn (p_cdio->env); @@ -80,17 +87,3 @@ cdio_get_mcn (const CdIo *p_cdio) return NULL; } } - -/*! - Get the size of the CD in logical block address (LBA) units. - - @param p_cdio the CD object queried - @return the size or 0 if there was an error. -*/ -uint32_t -cdio_stat_size (const CdIo_t *p_cdio) -{ - if (!p_cdio) return 0; - - return p_cdio->op.stat_size (p_cdio->env); -} diff --git a/lib/driver/image/bincue.c b/lib/driver/image/bincue.c index bf8c1939..f74356d3 100644 --- a/lib/driver/image/bincue.c +++ b/lib/driver/image/bincue.c @@ -1,5 +1,5 @@ /* - $Id: bincue.c,v 1.6 2005/01/23 19:16:58 rocky Exp $ + $Id: bincue.c,v 1.7 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2002, 2003, 2004, 2005 Rocky Bernstein Copyright (C) 2001 Herbert Valerio Riedel @@ -26,7 +26,7 @@ (*.cue). */ -static const char _rcsid[] = "$Id: bincue.c,v 1.6 2005/01/23 19:16:58 rocky Exp $"; +static const char _rcsid[] = "$Id: bincue.c,v 1.7 2005/01/24 00:06:31 rocky Exp $"; #include "image.h" #include "cdio_assert.h" @@ -63,7 +63,7 @@ static const char _rcsid[] = "$Id: bincue.c,v 1.6 2005/01/23 19:16:58 rocky Exp #define DEFAULT_CDIO_DEVICE "videocd.bin" #define DEFAULT_CDIO_CUE "videocd.cue" -static uint32_t _stat_size_bincue (void *user_data); +static lsn_t get_disc_last_lsn_bincue (void *user_data); #include "image_common.h" static bool parse_cuefile (_img_private_t *cd, const char *toc_name); @@ -83,7 +83,7 @@ _init_bincue (_img_private_t *env) return false; } - /* Have to set init before calling _stat_size_bincue() or we will + /* Have to set init before calling get_disc_last_lsn_bincue() or we will get into infinite recursion calling passing right here. */ env->gen.init = true; @@ -93,7 +93,7 @@ _init_bincue (_img_private_t *env) cdtext_init (&(env->gen.cdtext)); - lead_lsn = _stat_size_bincue( (_img_private_t *) env); + lead_lsn = get_disc_last_lsn_bincue( (_img_private_t *) env); if (-1 == lead_lsn) return false; @@ -216,10 +216,10 @@ _read_bincue (void *user_data, void *data, size_t size) /*! Return the size of the CD in logical block address (LBA) units. */ -static uint32_t -_stat_size_bincue (void *user_data) +static lsn_t +get_disc_last_lsn_bincue (void *p_user_data) { - _img_private_t *env = user_data; + _img_private_t *env = p_user_data; long size; size = cdio_stream_stat (env->gen.data_source); @@ -1140,6 +1140,7 @@ cdio_open_cue (const char *psz_cue_name) _funcs.get_cdtext = get_cdtext_generic; _funcs.get_devices = cdio_get_devices_bincue; _funcs.get_default_device = cdio_get_default_device_bincue; + _funcs.get_disc_last_lsn = get_disc_last_lsn_bincue; _funcs.get_discmode = _get_discmode_image; _funcs.get_drive_cap = _get_drive_cap_image; _funcs.get_first_track_num = _get_first_track_num_image; @@ -1161,7 +1162,6 @@ cdio_open_cue (const char *psz_cue_name) _funcs.read_mode2_sector = _read_mode2_sector_bincue; _funcs.read_mode2_sectors = _read_mode2_sectors_bincue; _funcs.set_arg = _set_arg_image; - _funcs.stat_size = _stat_size_bincue; if (NULL == psz_cue_name) return NULL; diff --git a/lib/driver/image/cdrdao.c b/lib/driver/image/cdrdao.c index 720f0d97..dda0f495 100644 --- a/lib/driver/image/cdrdao.c +++ b/lib/driver/image/cdrdao.c @@ -1,5 +1,5 @@ /* - $Id: cdrdao.c,v 1.10 2005/01/23 19:16:58 rocky Exp $ + $Id: cdrdao.c,v 1.11 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2004, 2005 Rocky Bernstein toc reading routine adapted from cuetools @@ -25,7 +25,7 @@ (*.cue). */ -static const char _rcsid[] = "$Id: cdrdao.c,v 1.10 2005/01/23 19:16:58 rocky Exp $"; +static const char _rcsid[] = "$Id: cdrdao.c,v 1.11 2005/01/24 00:06:31 rocky Exp $"; #include "image.h" #include "cdio_assert.h" @@ -66,7 +66,7 @@ static const char _rcsid[] = "$Id: cdrdao.c,v 1.10 2005/01/23 19:16:58 rocky Exp #include "image_common.h" -static uint32_t _stat_size_cdrdao (void *p_user_data); +static lsn_t get_disc_last_lsn_cdrdao (void *p_user_data); static bool parse_tocfile (_img_private_t *cd, const char *p_toc_name); @@ -100,7 +100,7 @@ _init_cdrdao (_img_private_t *env) if (env->gen.init) return false; - /* Have to set init before calling _stat_size_cdrdao() or we will + /* Have to set init before calling get_disc_last_lsn_cdrdao() or we will get into infinite recursion calling passing right here. */ env->gen.init = true; @@ -113,7 +113,7 @@ _init_cdrdao (_img_private_t *env) /* Read in TOC sheet. */ if ( !parse_tocfile(env, env->psz_cue_name) ) return false; - lead_lsn = _stat_size_cdrdao( (_img_private_t *) env); + lead_lsn = get_disc_last_lsn_cdrdao( (_img_private_t *) env); if (-1 == lead_lsn) return false; @@ -231,8 +231,8 @@ _read_cdrdao (void *user_data, void *data, size_t size) /*! Return the size of the CD in logical block address (LBA) units. */ -static uint32_t -_stat_size_cdrdao (void *p_user_data) +static lsn_t +get_disc_last_lsn_cdrdao (void *p_user_data) { _img_private_t *p_env = p_user_data; track_t i_leadout = p_env->gen.i_tracks; @@ -1268,6 +1268,7 @@ cdio_open_cdrdao (const char *psz_cue_name) _funcs.get_cdtext = get_cdtext_generic; _funcs.get_devices = cdio_get_devices_cdrdao; _funcs.get_default_device = cdio_get_default_device_cdrdao; + _funcs.get_disc_last_lsn = get_disc_last_lsn_cdrdao; _funcs.get_discmode = _get_discmode_image; _funcs.get_drive_cap = _get_drive_cap_image; _funcs.get_first_track_num = _get_first_track_num_image; @@ -1291,7 +1292,6 @@ cdio_open_cdrdao (const char *psz_cue_name) _funcs.set_arg = _set_arg_image; _funcs.set_speed = cdio_generic_unimplemented_set_speed; _funcs.set_blocksize = cdio_generic_unimplemented_set_blocksize; - _funcs.stat_size = _stat_size_cdrdao; if (NULL == psz_cue_name) return NULL; diff --git a/lib/driver/image/nrg.c b/lib/driver/image/nrg.c index 8bee119a..9e38878e 100644 --- a/lib/driver/image/nrg.c +++ b/lib/driver/image/nrg.c @@ -1,5 +1,5 @@ /* - $Id: nrg.c,v 1.8 2005/01/23 19:16:58 rocky Exp $ + $Id: nrg.c,v 1.9 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2003, 2004, 2005 Rocky Bernstein Copyright (C) 2001, 2003 Herbert Valerio Riedel @@ -46,7 +46,7 @@ #include "_cdio_stdio.h" #include "nrg.h" -static const char _rcsid[] = "$Id: nrg.c,v 1.8 2005/01/23 19:16:58 rocky Exp $"; +static const char _rcsid[] = "$Id: nrg.c,v 1.9 2005/01/24 00:06:31 rocky Exp $"; /* reader */ @@ -68,8 +68,8 @@ typedef struct { #define NEED_NERO_STRUCT #include "image_common.h" -static bool parse_nrg (_img_private_t *env, const char *psz_cue_name); -static uint32_t _stat_size_nrg (void *p_user_data); +static bool parse_nrg (_img_private_t *env, const char *psz_cue_name); +static lsn_t get_disc_last_lsn_nrg (void *p_user_data); /* Updates internal track TOC, so we can later simulate ioctl(CDROMREADTOCENTRY). @@ -730,7 +730,7 @@ parse_nrg (_img_private_t *p_env, const char *psz_nrg_name) } /* Fake out leadout track. */ - /* Don't use _stat_size_nrg since that will lead to recursion since + /* Don't use get_disc_last_lsn_nrg since that will lead to recursion since we haven't fully initialized things yet. */ cdio_lsn_to_msf (p_env->size, &p_env->tocent[p_env->gen.i_tracks].start_msf); @@ -835,8 +835,14 @@ _read_nrg (void *p_user_data, void *buf, size_t size) return cdio_stream_read(p_env->gen.data_source, buf, size, 1); } -static uint32_t -_stat_size_nrg (void *p_user_data) +/*! + Get the size of the CD in logical block address (LBA) units. + + @param p_cdio the CD object queried + @return the lsn. On error 0 or CDIO_INVALD_LSN. +*/ +static lsn_t +get_disc_last_lsn_nrg (void *p_user_data) { _img_private_t *p_env = p_user_data; @@ -1209,6 +1215,7 @@ cdio_open_nrg (const char *psz_source) _funcs.get_cdtext = get_cdtext_generic; _funcs.get_devices = cdio_get_devices_nrg; _funcs.get_default_device = cdio_get_default_device_nrg; + _funcs.get_disc_last_lsn = get_disc_last_lsn_nrg; _funcs.get_discmode = _get_discmode_image; _funcs.get_drive_cap = _get_drive_cap_image; _funcs.get_first_track_num = _get_first_track_num_image; @@ -1230,7 +1237,6 @@ cdio_open_nrg (const char *psz_source) _funcs.read_mode2_sector = _read_mode2_sector_nrg; _funcs.read_mode2_sectors = _read_mode2_sectors_nrg; _funcs.set_arg = _set_arg_image; - _funcs.stat_size = _stat_size_nrg; _data = _cdio_malloc (sizeof (_img_private_t)); _data->gen.init = false; diff --git a/lib/driver/libcdio.sym b/lib/driver/libcdio.sym index 1b8a1cce..3a2bfe4d 100644 --- a/lib/driver/libcdio.sym +++ b/lib/driver/libcdio.sym @@ -131,7 +131,6 @@ cdio_read_mode2_sectors cdio_set_arg cdio_set_blocksize cdio_set_speed -cdio_stat_size cdio_stdio_destroy cdio_stdio_new cdio_stream_read diff --git a/lib/driver/scsi_mmc.c b/lib/driver/scsi_mmc.c index e75ef473..a5b53d47 100644 --- a/lib/driver/scsi_mmc.c +++ b/lib/driver/scsi_mmc.c @@ -1,6 +1,6 @@ /* Common SCSI Multimedia Command (MMC) routines. - $Id: scsi_mmc.c,v 1.10 2005/01/23 19:16:58 rocky Exp $ + $Id: scsi_mmc.c,v 1.11 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2004, 2005 Rocky Bernstein @@ -40,151 +40,79 @@ #include #endif -/*! - Return the discmode as reported by the SCSI-MMC Read (FULL) TOC - command. +#define DEFAULT_TIMEOUT_MS 6000 + +/************************************************************************* + MMC CdIo Operations which a driver may use. + These are not accessible directly. - Information was obtained from Section 5.1.13 (Read TOC/PMA/ATIP) - pages 56-62 from the SCSI MMC draft specification, revision 10a - at http://www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf See - especially tables 72, 73 and 75. - */ -discmode_t -scsi_mmc_get_discmode( const CdIo_t *p_cdio ) + Most of these routines just pick out the cdio pointer and call the + corresponding publically-accessible routine. +*************************************************************************/ +/* Set read blocksize (via MMC) */ +driver_return_code_t +get_blocksize_mmc (void *p_user_data) { - uint8_t buf[14] = { 0, }; - scsi_mmc_cdb_t cdb; - - memset(&cdb, 0, sizeof(scsi_mmc_cdb_t)); - CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); - cdb.field[1] = CDIO_CDROM_MSF; /* The MMC-5 spec may require this. */ - cdb.field[2] = CDIO_MMC_READTOC_FMT_FULTOC; - CDIO_MMC_SET_READ_LENGTH8(cdb.field, sizeof(buf)); - scsi_mmc_run_cmd(p_cdio, 2000, &cdb, SCSI_MMC_DATA_READ, sizeof(buf), buf); - if (buf[7] == 0xA0) { - if (buf[13] == 0x00) { - if (buf[5] & 0x04) - return CDIO_DISC_MODE_CD_DATA; - else - return CDIO_DISC_MODE_CD_DA; - } - else if (buf[13] == 0x10) - return CDIO_DISC_MODE_CD_I; - else if (buf[13] == 0x20) - return CDIO_DISC_MODE_CD_XA; - } - return CDIO_DISC_MODE_NO_INFO; -} - -/*! - Set the drive speed. - - @return the drive speed if greater than 0. -1 if we had an error. is -2 - returned if this is not implemented for the current driver. - - @see scsi_mmc_set_speed -*/ -int -scsi_mmc_set_speed( const CdIo_t *p_cdio, int i_speed ) - -{ - uint8_t buf[14] = { 0, }; - scsi_mmc_cdb_t cdb; - - /* If the requested speed is less than 1x 176 kb/s this command - will return an error - it's part of the ATAPI specs. Therefore, - test and stop early. */ - - if ( i_speed < 1 ) return -1; - - memset(&cdb, 0, sizeof(scsi_mmc_cdb_t)); - CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_SET_SPEED); - CDIO_MMC_SET_LEN16(cdb.field, 2, i_speed); - /* Some drives like the Creative 24x CDRW require one to set a nonzero - write speed. So we set to the maximum value. */ - CDIO_MMC_SET_LEN16(cdb.field, 4, 0xffff); - return scsi_mmc_run_cmd(p_cdio, 2000, &cdb, SCSI_MMC_DATA_READ, - sizeof(buf), buf); -} - -/*! - 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 - capabilities. - */ -void -scsi_mmc_get_drive_cap_buf(const uint8_t *p, - /*out*/ cdio_drive_read_cap_t *p_read_cap, - /*out*/ cdio_drive_write_cap_t *p_write_cap, - /*out*/ cdio_drive_misc_cap_t *p_misc_cap) -{ - /* Reader */ - if (p[2] & 0x01) *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_R; - if (p[2] & 0x02) *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_RW; - if (p[2] & 0x08) *p_read_cap |= CDIO_DRIVE_CAP_READ_DVD_ROM; - if (p[4] & 0x01) *p_read_cap |= CDIO_DRIVE_CAP_READ_AUDIO; - if (p[4] & 0x10) *p_read_cap |= CDIO_DRIVE_CAP_READ_MODE2_FORM1; - if (p[4] & 0x20) *p_read_cap |= CDIO_DRIVE_CAP_READ_MODE2_FORM2; - if (p[5] & 0x01) *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_DA; - if (p[5] & 0x10) *p_read_cap |= CDIO_DRIVE_CAP_READ_C2_ERRS; - if (p[5] & 0x20) *p_read_cap |= CDIO_DRIVE_CAP_READ_ISRC; - - /* Writer */ - if (p[3] & 0x01) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_R; - if (p[3] & 0x02) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_RW; - if (p[3] & 0x10) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_R; - if (p[3] & 0x20) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RAM; - if (p[4] & 0x80) *p_misc_cap |= CDIO_DRIVE_CAP_WRITE_BURN_PROOF; - - /* Misc */ - if (p[4] & 0x40) *p_misc_cap |= CDIO_DRIVE_CAP_MISC_MULTI_SESSION; - if (p[6] & 0x01) *p_misc_cap |= CDIO_DRIVE_CAP_MISC_LOCK; - if (p[6] & 0x08) *p_misc_cap |= CDIO_DRIVE_CAP_MISC_EJECT; - if (p[6] >> 5 != 0) - *p_misc_cap |= CDIO_DRIVE_CAP_MISC_CLOSE_TRAY; + generic_img_private_t *p_env = p_user_data; + if (!p_env) return DRIVER_OP_UNINIT; + return scsi_mmc_get_blocksize(p_env->cdio); } /*! - Return the number of length in bytes of the Command Descriptor - buffer (CDB) for a given SCSI MMC command. The length will be - either 6, 10, or 12. -*/ -uint8_t -scsi_mmc_get_cmd_len(uint8_t scsi_cmd) -{ - static const uint8_t scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10}; - return scsi_cdblen[((scsi_cmd >> 5) & 7)]; -} - -/*! - Run a SCSI MMC command. - - cdio CD structure set by cdio_open(). - i_timeout time in milliseconds we will wait for the command - to complete. If this value is -1, use the default - time-out value. - buf Buffer for data, both sending and receiving - len 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. - */ -driver_return_code_t -scsi_mmc_run_cmd( const CdIo_t *p_cdio, unsigned int i_timeout_ms, - const scsi_mmc_cdb_t *p_cdb, - scsi_mmc_direction_t e_direction, unsigned int i_buf, - /*in/out*/ void *p_buf ) -{ - if (!p_cdio) return DRIVER_OP_UNINIT; - if (!p_cdio->op.run_scsi_mmc_cmd) return DRIVER_OP_UNSUPPORTED; - return p_cdio->op.run_scsi_mmc_cmd(p_cdio->env, i_timeout_ms, - scsi_mmc_get_cmd_len(p_cdb->field[0]), - p_cdb, e_direction, i_buf, p_buf); -} - -#define DEFAULT_TIMEOUT_MS 6000 + Get the lsn of the end of the CD (via MMC). + @return the lsn. On error return CDIO_INVALID_LSN. +*/ +lsn_t +get_disc_last_lsn_mmc (void *p_user_data) +{ + generic_img_private_t *p_env = p_user_data; + if (!p_env) return CDIO_INVALID_LSN; + return scsi_mmc_get_disc_last_lsn(p_env->cdio); +} + +void +get_drive_cap_mmc (const void *p_user_data, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap) +{ + const generic_img_private_t *p_env = p_user_data; + scsi_mmc_get_drive_cap( p_env->cdio, + p_read_cap, p_write_cap, p_misc_cap ); +} + +char * +get_mcn_mmc (const void *p_user_data) +{ + const generic_img_private_t *p_env = p_user_data; + return scsi_mmc_get_mcn( p_env->cdio ); +} + +/* Set read blocksize (via MMC) */ +driver_return_code_t +set_blocksize_mmc (void *p_user_data, int i_blocksize) +{ + generic_img_private_t *p_env = p_user_data; + if (!p_env) return DRIVER_OP_UNINIT; + return scsi_mmc_set_blocksize(p_env->cdio, i_blocksize); +} + +/* Set CD-ROM drive speed (via MMC) */ +driver_return_code_t +set_speed_mmc (void *p_user_data, int i_speed) +{ + generic_img_private_t *p_env = p_user_data; + if (!p_env) return DRIVER_OP_UNINIT; + return scsi_mmc_set_speed( p_env->cdio, i_speed ); +} + +/************************************************************************* + Miscellaenous other "private" routines. Probably need to better + classify these. +*************************************************************************/ + int scsi_mmc_get_blocksize_private ( void *p_env, const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd) @@ -228,138 +156,43 @@ scsi_mmc_get_blocksize_private ( void *p_env, return CDIO_MMC_GET_LEN16(p); } -int -scsi_mmc_get_blocksize ( const CdIo_t *p_cdio) -{ - if ( ! p_cdio ) return DRIVER_OP_UNINIT; - return - scsi_mmc_get_blocksize_private (p_cdio->env, p_cdio->op.run_scsi_mmc_cmd); - -} - - /*! - * Eject using SCSI MMC commands. Return 0 if successful. + 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 + capabilities. */ -driver_return_code_t -scsi_mmc_eject_media( const CdIo_t *p_cdio ) +void +scsi_mmc_get_drive_cap_buf(const uint8_t *p, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap) { - int i_status = 0; - scsi_mmc_cdb_t cdb = {{0, }}; - uint8_t buf[1]; - scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; - - if ( ! p_cdio ) return DRIVER_OP_UNINIT; - if ( ! p_cdio->op.run_scsi_mmc_cmd ) return DRIVER_OP_UNSUPPORTED; - - run_scsi_mmc_cmd = p_cdio->op.run_scsi_mmc_cmd; + /* Reader */ + if (p[2] & 0x01) *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_R; + if (p[2] & 0x02) *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_RW; + if (p[2] & 0x08) *p_read_cap |= CDIO_DRIVE_CAP_READ_DVD_ROM; + if (p[4] & 0x01) *p_read_cap |= CDIO_DRIVE_CAP_READ_AUDIO; + if (p[4] & 0x10) *p_read_cap |= CDIO_DRIVE_CAP_READ_MODE2_FORM1; + if (p[4] & 0x20) *p_read_cap |= CDIO_DRIVE_CAP_READ_MODE2_FORM2; + if (p[5] & 0x01) *p_read_cap |= CDIO_DRIVE_CAP_READ_CD_DA; + if (p[5] & 0x10) *p_read_cap |= CDIO_DRIVE_CAP_READ_C2_ERRS; + if (p[5] & 0x20) *p_read_cap |= CDIO_DRIVE_CAP_READ_ISRC; - CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL); + /* Writer */ + if (p[3] & 0x01) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_R; + if (p[3] & 0x02) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_CD_RW; + if (p[3] & 0x10) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_R; + if (p[3] & 0x20) *p_write_cap |= CDIO_DRIVE_CAP_WRITE_DVD_RAM; + if (p[4] & 0x80) *p_misc_cap |= CDIO_DRIVE_CAP_WRITE_BURN_PROOF; - i_status = run_scsi_mmc_cmd (p_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 (p_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 (p_cdio->env, DEFAULT_TIMEOUT_MS, - scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, - SCSI_MMC_DATA_WRITE, 0, &buf); - + /* Misc */ + if (p[4] & 0x40) *p_misc_cap |= CDIO_DRIVE_CAP_MISC_MULTI_SESSION; + if (p[6] & 0x01) *p_misc_cap |= CDIO_DRIVE_CAP_MISC_LOCK; + if (p[6] & 0x08) *p_misc_cap |= CDIO_DRIVE_CAP_MISC_EJECT; + if (p[6] >> 5 != 0) + *p_misc_cap |= CDIO_DRIVE_CAP_MISC_CLOSE_TRAY; } -/*! Read sectors using SCSI-MMC GPCMD_READ_CD. - Can read only up to 25 blocks. -*/ -driver_return_code_t -scsi_mmc_read_sectors ( const CdIo_t *p_cdio, void *p_buf, lba_t lba, - int sector_type, unsigned int i_blocks ) -{ - scsi_mmc_cdb_t cdb = {{0, }}; - - scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; - - if (!p_cdio) return DRIVER_OP_UNINIT; - if (!p_cdio->op.run_scsi_mmc_cmd ) return DRIVER_OP_UNSUPPORTED; - - run_scsi_mmc_cmd = p_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_LENGTH24(cdb.field, i_blocks); - CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb.field, - CDIO_MMC_MCSB_ALL_HEADERS); - - return run_scsi_mmc_cmd (p_cdio->env, DEFAULT_TIMEOUT_MS, - scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, - SCSI_MMC_DATA_READ, - CDIO_CD_FRAMESIZE_RAW * i_blocks, - p_buf); -} - -driver_return_code_t -scsi_mmc_set_blocksize_private ( void *p_env, - const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, - unsigned int i_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; - - if ( ! p_env ) return DRIVER_OP_UNINIT; - if ( ! run_scsi_mmc_cmd ) return DRIVER_OP_UNSUPPORTED; - - memset (&mh, 0, sizeof (mh)); - mh.block_desc_length = 0x08; - mh.block_length_hi = (i_bsize >> 16) & 0xff; - mh.block_length_med = (i_bsize >> 8) & 0xff; - mh.block_length_lo = (i_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 (p_env, DEFAULT_TIMEOUT_MS, - scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, - SCSI_MMC_DATA_WRITE, sizeof(mh), &mh); -} - -driver_return_code_t -scsi_mmc_set_blocksize ( const CdIo_t *p_cdio, unsigned int i_blocksize) -{ - if ( ! p_cdio ) return DRIVER_OP_UNINIT; - return - scsi_mmc_set_blocksize_private (p_cdio->env, p_cdio->op.run_scsi_mmc_cmd, - i_blocksize); -} - - /*! Return the the kind of drive capabilities of device. */ @@ -451,18 +284,6 @@ scsi_mmc_get_drive_cap_private (void *p_env, return; } -void -scsi_mmc_get_drive_cap (const CdIo_t *p_cdio, - /*out*/ cdio_drive_read_cap_t *p_read_cap, - /*out*/ cdio_drive_write_cap_t *p_write_cap, - /*out*/ cdio_drive_misc_cap_t *p_misc_cap) -{ - if ( ! p_cdio ) return; - scsi_mmc_get_drive_cap_private (p_cdio->env, - p_cdio->op.run_scsi_mmc_cmd, - p_read_cap, p_write_cap, p_misc_cap); -} - /*! Get the DVD type associated with cd object. */ @@ -521,59 +342,6 @@ scsi_mmc_get_dvd_struct_physical_private ( void *p_env, const return DRIVER_OP_SUCCESS; } - -/*! - Get the DVD type associated with cd object. -*/ -discmode_t -scsi_mmc_get_dvd_struct_physical ( const CdIo_t *p_cdio, cdio_dvd_struct_t *s) -{ - if ( ! p_cdio ) return -2; - return - scsi_mmc_get_dvd_struct_physical_private (p_cdio->env, - p_cdio->op.run_scsi_mmc_cmd, - s); -} - -/*! - Get the CD-ROM hardware info via a SCSI MMC INQUIRY command. - False is returned if we had an error getting the information. -*/ -bool -scsi_mmc_get_hwinfo ( const CdIo_t *p_cdio, - /*out*/ cdio_hwinfo_t *hw_info ) -{ - int i_status; /* Result of SCSI MMC command */ - char buf[36] = { 0, }; /* Place to hold returned data */ - scsi_mmc_cdb_t cdb = {{0, }}; /* Command Descriptor Block */ - - CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_INQUIRY); - cdb.field[4] = sizeof(buf); - - if (! p_cdio || ! hw_info ) return false; - - i_status = scsi_mmc_run_cmd(p_cdio, DEFAULT_TIMEOUT_MS, - &cdb, SCSI_MMC_DATA_READ, - sizeof(buf), &buf); - if (i_status == 0) { - - memcpy(hw_info->psz_vendor, - buf + 8, - sizeof(hw_info->psz_vendor)-1); - hw_info->psz_vendor[sizeof(hw_info->psz_vendor)-1] = '\0'; - memcpy(hw_info->psz_model, - buf + 8 + CDIO_MMC_HW_VENDOR_LEN, - sizeof(hw_info->psz_model)-1); - hw_info->psz_model[sizeof(hw_info->psz_model)-1] = '\0'; - memcpy(hw_info->psz_revision, - buf + 8 + CDIO_MMC_HW_VENDOR_LEN + CDIO_MMC_HW_MODEL_LEN, - sizeof(hw_info->psz_revision)-1); - hw_info->psz_revision[sizeof(hw_info->psz_revision)-1] = '\0'; - return true; - } - return false; -} - /*! Return the media catalog number MCN. @@ -609,14 +377,6 @@ scsi_mmc_get_mcn_private ( void *p_env, return NULL; } -char * -scsi_mmc_get_mcn ( const CdIo_t *p_cdio ) -{ - if ( ! p_cdio ) return NULL; - return scsi_mmc_get_mcn_private (p_cdio->env, - p_cdio->op.run_scsi_mmc_cmd ); -} - /* Read cdtext information for a CdIo_t object . @@ -688,49 +448,362 @@ scsi_mmc_init_cdtext_private ( void *p_user_data, } } -/* Set read blocksize (via MMC) */ driver_return_code_t -get_blocksize_mmc (void *p_user_data) +scsi_mmc_set_blocksize_private ( void *p_env, + const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, + unsigned int i_bsize) { - generic_img_private_t *p_env = p_user_data; - if (!p_env) return DRIVER_OP_UNINIT; - return scsi_mmc_get_blocksize(p_env->cdio); + 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; + + if ( ! p_env ) return DRIVER_OP_UNINIT; + if ( ! run_scsi_mmc_cmd ) return DRIVER_OP_UNSUPPORTED; + + memset (&mh, 0, sizeof (mh)); + mh.block_desc_length = 0x08; + mh.block_length_hi = (i_bsize >> 16) & 0xff; + mh.block_length_med = (i_bsize >> 8) & 0xff; + mh.block_length_lo = (i_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 (p_env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, + SCSI_MMC_DATA_WRITE, sizeof(mh), &mh); +} + +/*********************************************************** + User-accessible Operations. +************************************************************/ +/*! + Return the number of length in bytes of the Command Descriptor + buffer (CDB) for a given SCSI MMC command. The length will be + either 6, 10, or 12. +*/ +uint8_t +scsi_mmc_get_cmd_len(uint8_t scsi_cmd) +{ + static const uint8_t scsi_cdblen[8] = {6, 10, 10, 12, 12, 12, 10, 10}; + return scsi_cdblen[((scsi_cmd >> 5) & 7)]; +} + +/*! + Return the size of the CD in logical block address (LBA) units. + @return the lsn. On error 0 or CDIO_INVALD_LSN. + */ +lsn_t +scsi_mmc_get_disc_last_lsn ( const CdIo_t *p_cdio ) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + uint8_t buf[12] = { 0, }; + + lsn_t retval = 0; + int i_status; + + /* Operation code */ + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); + + cdb.field[1] = 0; /* lba; msf: 0x2 */ + + /* Format */ + cdb.field[2] = CDIO_MMC_READTOC_FMT_TOC; + + CDIO_MMC_SET_START_TRACK(cdb.field, CDIO_CDROM_LEADOUT_TRACK); + + CDIO_MMC_SET_READ_LENGTH16(cdb.field, sizeof(buf)); + + i_status = scsi_mmc_run_cmd(p_cdio, DEFAULT_TIMEOUT_MS, &cdb, + SCSI_MMC_DATA_READ, + sizeof(buf), buf); + + if (i_status) return CDIO_INVALID_LSN; + + { + int i; + for (i = 8; i < 12; i++) { + retval <<= 8; + retval += buf[i]; + } + } + + return retval; +} + +/*! + Return the discmode as reported by the SCSI-MMC Read (FULL) TOC + command. + + Information was obtained from Section 5.1.13 (Read TOC/PMA/ATIP) + pages 56-62 from the SCSI MMC draft specification, revision 10a + at http://www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf See + especially tables 72, 73 and 75. + */ +discmode_t +scsi_mmc_get_discmode( const CdIo_t *p_cdio ) + +{ + uint8_t buf[14] = { 0, }; + scsi_mmc_cdb_t cdb; + + memset(&cdb, 0, sizeof(scsi_mmc_cdb_t)); + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC); + cdb.field[1] = CDIO_CDROM_MSF; /* The MMC-5 spec may require this. */ + cdb.field[2] = CDIO_MMC_READTOC_FMT_FULTOC; + CDIO_MMC_SET_READ_LENGTH8(cdb.field, sizeof(buf)); + scsi_mmc_run_cmd(p_cdio, 2000, &cdb, SCSI_MMC_DATA_READ, sizeof(buf), buf); + if (buf[7] == 0xA0) { + if (buf[13] == 0x00) { + if (buf[5] & 0x04) + return CDIO_DISC_MODE_CD_DATA; + else + return CDIO_DISC_MODE_CD_DA; + } + else if (buf[13] == 0x10) + return CDIO_DISC_MODE_CD_I; + else if (buf[13] == 0x20) + return CDIO_DISC_MODE_CD_XA; + } + return CDIO_DISC_MODE_NO_INFO; } void -get_drive_cap_mmc (const void *p_user_data, - /*out*/ cdio_drive_read_cap_t *p_read_cap, - /*out*/ cdio_drive_write_cap_t *p_write_cap, - /*out*/ cdio_drive_misc_cap_t *p_misc_cap) +scsi_mmc_get_drive_cap (const CdIo_t *p_cdio, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap) { - const generic_img_private_t *p_env = p_user_data; - scsi_mmc_get_drive_cap( p_env->cdio, - p_read_cap, p_write_cap, p_misc_cap ); + if ( ! p_cdio ) return; + scsi_mmc_get_drive_cap_private (p_cdio->env, + p_cdio->op.run_scsi_mmc_cmd, + p_read_cap, p_write_cap, p_misc_cap); +} + +/*! + Get the DVD type associated with cd object. +*/ +discmode_t +scsi_mmc_get_dvd_struct_physical ( const CdIo_t *p_cdio, cdio_dvd_struct_t *s) +{ + if ( ! p_cdio ) return -2; + return + scsi_mmc_get_dvd_struct_physical_private (p_cdio->env, + p_cdio->op.run_scsi_mmc_cmd, + s); +} + +/*! + Get the CD-ROM hardware info via a SCSI MMC INQUIRY command. + False is returned if we had an error getting the information. +*/ +bool +scsi_mmc_get_hwinfo ( const CdIo_t *p_cdio, + /*out*/ cdio_hwinfo_t *hw_info ) +{ + int i_status; /* Result of SCSI MMC command */ + char buf[36] = { 0, }; /* Place to hold returned data */ + scsi_mmc_cdb_t cdb = {{0, }}; /* Command Descriptor Block */ + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_INQUIRY); + cdb.field[4] = sizeof(buf); + + if (! p_cdio || ! hw_info ) return false; + + i_status = scsi_mmc_run_cmd(p_cdio, DEFAULT_TIMEOUT_MS, + &cdb, SCSI_MMC_DATA_READ, + sizeof(buf), &buf); + if (i_status == 0) { + + memcpy(hw_info->psz_vendor, + buf + 8, + sizeof(hw_info->psz_vendor)-1); + hw_info->psz_vendor[sizeof(hw_info->psz_vendor)-1] = '\0'; + memcpy(hw_info->psz_model, + buf + 8 + CDIO_MMC_HW_VENDOR_LEN, + sizeof(hw_info->psz_model)-1); + hw_info->psz_model[sizeof(hw_info->psz_model)-1] = '\0'; + memcpy(hw_info->psz_revision, + buf + 8 + CDIO_MMC_HW_VENDOR_LEN + CDIO_MMC_HW_MODEL_LEN, + sizeof(hw_info->psz_revision)-1); + hw_info->psz_revision[sizeof(hw_info->psz_revision)-1] = '\0'; + return true; + } + return false; } char * -get_mcn_mmc (const void *p_user_data) +scsi_mmc_get_mcn ( const CdIo_t *p_cdio ) { - const generic_img_private_t *p_env = p_user_data; - return scsi_mmc_get_mcn( p_env->cdio ); + if ( ! p_cdio ) return NULL; + return scsi_mmc_get_mcn_private (p_cdio->env, + p_cdio->op.run_scsi_mmc_cmd ); } -/* Set read blocksize (via MMC) */ +/*! + Run a SCSI MMC command. + + cdio CD structure set by cdio_open(). + i_timeout time in milliseconds we will wait for the command + to complete. If this value is -1, use the default + time-out value. + buf Buffer for data, both sending and receiving + len 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. + */ driver_return_code_t -set_blocksize_mmc (void *p_user_data, int i_blocksize) +scsi_mmc_run_cmd( const CdIo_t *p_cdio, unsigned int i_timeout_ms, + const scsi_mmc_cdb_t *p_cdb, + scsi_mmc_direction_t e_direction, unsigned int i_buf, + /*in/out*/ void *p_buf ) { - generic_img_private_t *p_env = p_user_data; - if (!p_env) return DRIVER_OP_UNINIT; - return scsi_mmc_set_blocksize(p_env->cdio, i_blocksize); + if (!p_cdio) return DRIVER_OP_UNINIT; + if (!p_cdio->op.run_scsi_mmc_cmd) return DRIVER_OP_UNSUPPORTED; + return p_cdio->op.run_scsi_mmc_cmd(p_cdio->env, i_timeout_ms, + scsi_mmc_get_cmd_len(p_cdb->field[0]), + p_cdb, e_direction, i_buf, p_buf); } -/* Set CD-ROM drive speed (via MMC) */ -driver_return_code_t -set_speed_mmc (void *p_user_data, int i_speed) +int +scsi_mmc_get_blocksize ( const CdIo_t *p_cdio) { - generic_img_private_t *p_env = p_user_data; - if (!p_env) return DRIVER_OP_UNINIT; - return scsi_mmc_set_speed( p_env->cdio, i_speed ); + if ( ! p_cdio ) return DRIVER_OP_UNINIT; + return + scsi_mmc_get_blocksize_private (p_cdio->env, p_cdio->op.run_scsi_mmc_cmd); + +} + + +/*! + * Eject using SCSI MMC commands. Return 0 if successful. + */ +driver_return_code_t +scsi_mmc_eject_media( const CdIo_t *p_cdio ) +{ + int i_status = 0; + scsi_mmc_cdb_t cdb = {{0, }}; + uint8_t buf[1]; + scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; + + if ( ! p_cdio ) return DRIVER_OP_UNINIT; + if ( ! p_cdio->op.run_scsi_mmc_cmd ) return DRIVER_OP_UNSUPPORTED; + + run_scsi_mmc_cmd = p_cdio->op.run_scsi_mmc_cmd; + + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_ALLOW_MEDIUM_REMOVAL); + + i_status = run_scsi_mmc_cmd (p_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 (p_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 (p_cdio->env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, + SCSI_MMC_DATA_WRITE, 0, &buf); + +} + +/*! Read sectors using SCSI-MMC GPCMD_READ_CD. + Can read only up to 25 blocks. +*/ +driver_return_code_t +scsi_mmc_read_sectors ( const CdIo_t *p_cdio, void *p_buf, lba_t lba, + int sector_type, unsigned int i_blocks ) +{ + scsi_mmc_cdb_t cdb = {{0, }}; + + scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd; + + if (!p_cdio) return DRIVER_OP_UNINIT; + if (!p_cdio->op.run_scsi_mmc_cmd ) return DRIVER_OP_UNSUPPORTED; + + run_scsi_mmc_cmd = p_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_LENGTH24(cdb.field, i_blocks); + CDIO_MMC_SET_MAIN_CHANNEL_SELECTION_BITS(cdb.field, + CDIO_MMC_MCSB_ALL_HEADERS); + + return run_scsi_mmc_cmd (p_cdio->env, DEFAULT_TIMEOUT_MS, + scsi_mmc_get_cmd_len(cdb.field[0]), &cdb, + SCSI_MMC_DATA_READ, + CDIO_CD_FRAMESIZE_RAW * i_blocks, + p_buf); +} + +driver_return_code_t +scsi_mmc_set_blocksize ( const CdIo_t *p_cdio, unsigned int i_blocksize) +{ + if ( ! p_cdio ) return DRIVER_OP_UNINIT; + return + scsi_mmc_set_blocksize_private (p_cdio->env, p_cdio->op.run_scsi_mmc_cmd, + i_blocksize); +} + + +/*! + Set the drive speed. + + @return the drive speed if greater than 0. -1 if we had an error. is -2 + returned if this is not implemented for the current driver. + + @see scsi_mmc_set_speed +*/ +int +scsi_mmc_set_speed( const CdIo_t *p_cdio, int i_speed ) + +{ + uint8_t buf[14] = { 0, }; + scsi_mmc_cdb_t cdb; + + /* If the requested speed is less than 1x 176 kb/s this command + will return an error - it's part of the ATAPI specs. Therefore, + test and stop early. */ + + if ( i_speed < 1 ) return -1; + + memset(&cdb, 0, sizeof(scsi_mmc_cdb_t)); + CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_SET_SPEED); + CDIO_MMC_SET_LEN16(cdb.field, 2, i_speed); + /* Some drives like the Creative 24x CDRW require one to set a + nonzero write speed or else one gets an error back. Some + specifications have setting the value 0xfffff indicate setting to + the maximum allowable speed. + */ + CDIO_MMC_SET_LEN16(cdb.field, 4, 0xffff); + return scsi_mmc_run_cmd(p_cdio, 2000, &cdb, SCSI_MMC_DATA_READ, + sizeof(buf), buf); } diff --git a/lib/driver/scsi_mmc_private.h b/lib/driver/scsi_mmc_private.h index 2d29c96e..5c98860c 100644 --- a/lib/driver/scsi_mmc_private.h +++ b/lib/driver/scsi_mmc_private.h @@ -1,6 +1,6 @@ /* private MMC helper routines. - $Id: scsi_mmc_private.h,v 1.4 2005/01/23 19:16:58 rocky Exp $ + $Id: scsi_mmc_private.h,v 1.5 2005/01/24 00:06:31 rocky Exp $ Copyright (C) 2004, 2005 Rocky Bernstein @@ -33,13 +33,48 @@ msecs2secs(unsigned int msecs) } #undef SECS2MSECS -typedef -int (*scsi_mmc_run_cmd_fn_t) ( void *p_user_data, - unsigned int i_timeout_ms, - 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 ); +/*********************************************************** + MMC CdIo Operations which a driver may use. + These are not directly user-accessible. +************************************************************/ +/*! + Get the block size for subsequest read requests, via a SCSI MMC + MODE_SENSE 6 command. +*/ +int get_blocksize_mmc (void *p_user_data); + +/*! + Get the lsn of the end of the CD + + @return the lsn. On error return CDIO_INVALID_LSN. +*/ +lsn_t get_disc_last_lsn_mmc( void *p_user_data ); + +void get_drive_cap_mmc (const void *p_user_data, + /*out*/ cdio_drive_read_cap_t *p_read_cap, + /*out*/ cdio_drive_write_cap_t *p_write_cap, + /*out*/ cdio_drive_misc_cap_t *p_misc_cap); + +char *get_mcn_mmc (const void *p_user_data); + +/* Set read blocksize (via MMC) */ +driver_return_code_t set_blocksize_mmc (void *p_user_data, int i_blocksize); + +/* Set CD-ROM drive speed (via MMC) */ +driver_return_code_t set_speed_mmc (void *p_user_data, int i_speed); + +/*********************************************************** + Miscellaenous other "private" routines. Probably need + to better classify these. +************************************************************/ + +typedef driver_return_code_t (*scsi_mmc_run_cmd_fn_t) + ( void *p_user_data, + unsigned int i_timeout_ms, + 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 ); int scsi_mmc_set_blocksize_mmc_private ( const void *p_env, const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, @@ -94,22 +129,3 @@ driver_return_code_t scsi_mmc_set_blocksize_private ( void *p_env, const scsi_mmc_run_cmd_fn_t run_scsi_mmc_cmd, unsigned int i_bsize); - -/*! - Get the block size for subsequest read requests, via a SCSI MMC - MODE_SENSE 6 command. -*/ -int get_blocksize_mmc (void *p_user_data); - -void get_drive_cap_mmc (const void *p_user_data, - /*out*/ cdio_drive_read_cap_t *p_read_cap, - /*out*/ cdio_drive_write_cap_t *p_write_cap, - /*out*/ cdio_drive_misc_cap_t *p_misc_cap); - -char *get_mcn_mmc (const void *p_user_data); - -/* Set read blocksize (via MMC) */ -driver_return_code_t set_blocksize_mmc (void *p_user_data, int i_blocksize); - -/* Set CD-ROM drive speed (via MMC) */ -driver_return_code_t set_speed_mmc (void *p_user_data, int i_speed);