This repository has been archived on 2025-05-24. You can view files and clone it, but cannot push or open issues or pull requests.
Files
libcdio-osx/lib/_cdio_sunos.c

984 lines
25 KiB
C
Raw Normal View History

2003-03-24 19:01:09 +00:00
/*
$Id: _cdio_sunos.c,v 1.59 2004/07/23 02:54:34 rocky Exp $
2003-03-24 19:01:09 +00:00
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2002, 2003, 2004 Rocky Bernstein <rocky@panix.com>
2003-03-24 19:01:09 +00:00
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
2003-10-03 02:35:33 +00:00
#ifdef HAVE_STRING_H
#include <string.h>
2003-10-03 02:35:33 +00:00
#endif
#include <cdio/logging.h>
#include <cdio/sector.h>
#include <cdio/util.h>
2004-05-10 03:28:51 +00:00
#include <cdio/scsi_mmc.h>
2003-03-24 19:01:09 +00:00
#include "cdio_assert.h"
#include "cdio_private.h"
#define DEFAULT_CDIO_DEVICE "/vol/dev/aliases/cdrom0"
2003-03-24 19:01:09 +00:00
#ifdef HAVE_SOLARIS_CDROM
static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.59 2004/07/23 02:54:34 rocky Exp $";
#ifdef HAVE_GLOB_H
#include <glob.h>
#endif
2003-03-24 19:01:09 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#ifdef HAVE_SYS_CDIO_H
# include <sys/cdio.h> /* CDIOCALLOW etc... */
#else
#error "You need <sys/cdio.h> to have CDROM support"
#endif
#include <sys/dkio.h>
#include <sys/scsi/generic/commands.h>
#include <sys/scsi/impl/uscsi.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
2004-07-15 04:03:52 +00:00
#include "cdtext_private.h"
2003-03-24 19:01:09 +00:00
/* Number of seconds we wait for a SCSI MMC command to complete. */
#define DEFAULT_TIMEOUT 30
#define TOTAL_TRACKS (p_env->tochdr.cdth_trk1)
#define FIRST_TRACK_NUM (p_env->tochdr.cdth_trk0)
2003-03-24 19:01:09 +00:00
/* reader */
typedef enum {
2003-03-24 19:01:09 +00:00
_AM_NONE,
_AM_SUN_CTRL_ATAPI,
_AM_SUN_CTRL_SCSI
#if FINISHED
_AM_READ_CD,
_AM_READ_10
#endif
} access_mode_t;
2003-03-24 19:01:09 +00:00
typedef struct {
/* Things common to all drivers like this.
This must be first. */
generic_img_private_t gen;
2004-07-15 04:03:52 +00:00
/* Entry info for each track, add 1 for leadout. */
struct cdrom_tocentry tocent[CDIO_CD_MAX_TRACKS+1];
cdtext_t cdtext; /* CD-TEXT */
access_mode_t access_mode;
2004-07-15 04:03:52 +00:00
bool b_cdtext_init;
bool b_cdtext_error;
2004-07-15 04:03:52 +00:00
/* Some of the more OS specific things. */
cdtext_t cdtext_track[CDIO_CD_MAX_TRACKS+1]; /*CD-TEXT for each track*/
2003-03-24 19:01:09 +00:00
/* Track information */
struct cdrom_tochdr tochdr;
} _img_private_t;
static access_mode_t
str_to_access_mode_sunos(const char *psz_access_mode)
{
2004-04-30 07:07:49 +00:00
const access_mode_t default_access_mode = _AM_SUN_CTRL_SCSI;
if (NULL==psz_access_mode) return default_access_mode;
2004-04-30 07:07:49 +00:00
if (!strcmp(psz_access_mode, "ATAPI"))
return _AM_SUN_CTRL_SCSI; /* force ATAPI to be SCSI */
else if (!strcmp(psz_access_mode, "SCSI"))
return _AM_SUN_CTRL_SCSI;
else {
cdio_warn ("unknown access type: %s. Default SCSI used.",
psz_access_mode);
return default_access_mode;
}
}
2003-03-24 19:01:09 +00:00
/*!
Initialize CD device.
*/
static bool
init_solaris (_img_private_t *env)
2003-03-24 19:01:09 +00:00
{
if (!cdio_generic_init(env)) return false;
env->access_mode = _AM_SUN_CTRL_SCSI;
2003-03-24 19:01:09 +00:00
return true;
}
/*!
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.
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 int
scsi_mmc_run_cmd_solaris( 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, /*out*/ void *p_buf )
{
const _img_private_t *p_env = p_user_data;
struct uscsi_cmd cgc;
memset (&cgc, 0, sizeof (struct uscsi_cmd));
cgc.uscsi_cdb = (caddr_t) p_cdb;
cgc.uscsi_flags = SCSI_MMC_DATA_READ == e_direction ?
USCSI_READ : USCSI_WRITE;
cgc.uscsi_timeout = i_timeout; /* # of seconds for completion */
cgc.uscsi_bufaddr = p_buf;
cgc.uscsi_buflen = i_buf;
cgc.uscsi_cdblen = i_cdb;
return ioctl(p_env->gen.fd, USCSICMD, &cgc);
}
2003-03-24 19:01:09 +00:00
/*!
Reads audio sectors from CD device into data starting from lsn.
2003-03-24 19:01:09 +00:00
Returns 0 if no error.
May have to check size of nblocks. There may be a limit that
can be read in one go, e.g. 25 blocks.
*/
2003-03-24 19:01:09 +00:00
static int
_read_audio_sectors_solaris (void *p_user_data, void *data, lsn_t lsn,
unsigned int nblocks)
2003-03-24 19:01:09 +00:00
{
char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
2003-03-24 19:01:09 +00:00
struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
msf_t _msf;
struct cdrom_cdda cdda;
2003-03-24 19:01:09 +00:00
_img_private_t *env = p_user_data;
2003-03-24 19:01:09 +00:00
cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
msf->cdmsf_min0 = from_bcd8(_msf.m);
msf->cdmsf_sec0 = from_bcd8(_msf.s);
2003-03-24 19:01:09 +00:00
msf->cdmsf_frame0 = from_bcd8(_msf.f);
if (env->gen.ioctls_debugged == 75)
2003-03-24 19:01:09 +00:00
cdio_debug ("only displaying every 75th ioctl from now on");
if (env->gen.ioctls_debugged == 30 * 75)
2003-03-24 19:01:09 +00:00
cdio_debug ("only displaying every 30*75th ioctl from now on");
if (env->gen.ioctls_debugged < 75
|| (env->gen.ioctls_debugged < (30 * 75)
&& env->gen.ioctls_debugged % 75 == 0)
|| env->gen.ioctls_debugged % (30 * 75) == 0)
cdio_debug ("reading %d", lsn);
2003-03-24 19:01:09 +00:00
env->gen.ioctls_debugged++;
2003-03-24 19:01:09 +00:00
cdda.cdda_addr = lsn;
cdda.cdda_length = nblocks;
cdda.cdda_data = (caddr_t) data;
if (ioctl (env->gen.fd, CDROMCDDA, &cdda) == -1) {
perror ("ioctl(..,CDROMCDDA,..)");
return 1;
/* exit (EXIT_FAILURE); */
}
memcpy (data, buf, CDIO_CD_FRAMESIZE_RAW);
2003-03-24 19:01:09 +00:00
return 0;
}
2003-09-26 09:11:19 +00:00
/*!
Reads a single mode1 sector from cd device into data starting
from lsn. Returns 0 if no error.
*/
static int
_read_mode1_sector_solaris (void *env, void *data, lsn_t lsn,
bool b_form2)
{
#if FIXED
do something here.
#else
return cdio_generic_read_form1_sector(env, data, lsn);
#endif
return 0;
}
/*!
Reads nblocks of mode2 sectors from cd device into data starting
from lsn.
2003-09-26 09:11:19 +00:00
Returns 0 if no error.
*/
static int
_read_mode1_sectors_solaris (void *p_user_data, void *p_data, lsn_t lsn,
bool b_form2, unsigned int nblocks)
{
_img_private_t *p_env = p_user_data;
unsigned int i;
int retval;
unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
2003-09-26 09:11:19 +00:00
for (i = 0; i < nblocks; i++) {
if ( (retval = _read_mode1_sector_solaris (p_env,
((char *)p_data) + (blocksize * i),
lsn + i, b_form2)) )
return retval;
}
return 0;
}
2003-09-26 09:11:19 +00:00
/*!
Reads a single mode2 sector from cd device into data starting from lsn.
Returns 0 if no error.
*/
static int
_read_mode2_sector_solaris (void *p_user_data, void *p_data, lsn_t lsn,
bool b_form2)
{
char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, };
struct cdrom_msf *msf = (struct cdrom_msf *) &buf;
msf_t _msf;
int offset = 0;
struct cdrom_cdxa cd_read;
_img_private_t *p_env = p_user_data;
cdio_lba_to_msf (cdio_lsn_to_lba(lsn), &_msf);
msf->cdmsf_min0 = from_bcd8(_msf.m);
msf->cdmsf_sec0 = from_bcd8(_msf.s);
msf->cdmsf_frame0 = from_bcd8(_msf.f);
if (p_env->gen.ioctls_debugged == 75)
cdio_debug ("only displaying every 75th ioctl from now on");
if (p_env->gen.ioctls_debugged == 30 * 75)
cdio_debug ("only displaying every 30*75th ioctl from now on");
if (p_env->gen.ioctls_debugged < 75
|| (p_env->gen.ioctls_debugged < (30 * 75)
&& p_env->gen.ioctls_debugged % 75 == 0)
|| p_env->gen.ioctls_debugged % (30 * 75) == 0)
cdio_debug ("reading %2.2d:%2.2d:%2.2d",
msf->cdmsf_min0, msf->cdmsf_sec0, msf->cdmsf_frame0);
p_env->gen.ioctls_debugged++;
/* Using CDROMXA ioctl will actually use the same uscsi command
* as ATAPI, except we don't need to be root
*/
offset = CDIO_CD_XA_SYNC_HEADER;
cd_read.cdxa_addr = lsn;
cd_read.cdxa_data = buf;
cd_read.cdxa_length = 1;
cd_read.cdxa_format = CDROM_XA_SECTOR_DATA;
if (ioctl (p_env->gen.fd, CDROMCDXA, &cd_read) == -1) {
perror ("ioctl(..,CDROMCDXA,..)");
return 1;
/* exit (EXIT_FAILURE); */
}
if (b_form2)
memcpy (p_data, buf + (offset-CDIO_CD_SUBHEADER_SIZE), M2RAW_SECTOR_SIZE);
else
memcpy (((char *)p_data), buf + offset, CDIO_CD_FRAMESIZE);
return 0;
}
2003-03-24 19:01:09 +00:00
/*!
Reads nblocks of mode2 sectors from cd device into data starting
from lsn.
Returns 0 if no error.
*/
static int
_read_mode2_sectors_solaris (void *p_user_data, void *data, lsn_t lsn,
bool b_form2, unsigned int nblocks)
2003-03-24 19:01:09 +00:00
{
_img_private_t *env = p_user_data;
2003-09-26 09:11:19 +00:00
unsigned int i;
2003-03-24 19:01:09 +00:00
int retval;
unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE;
2003-03-24 19:01:09 +00:00
for (i = 0; i < nblocks; i++) {
if ( (retval = _read_mode2_sector_solaris (env,
((char *)data) + (blocksize * i),
lsn + i, b_form2)) )
return retval;
2003-03-24 19:01:09 +00:00
}
return 0;
}
2003-03-24 19:01:09 +00:00
/*!
Return the size of the CD in logical block address (LBA) units.
*/
static uint32_t
_cdio_stat_size (void *p_user_data)
2003-03-24 19:01:09 +00:00
{
_img_private_t *env = p_user_data;
2003-03-24 19:01:09 +00:00
struct cdrom_tocentry tocent;
uint32_t size;
tocent.cdte_track = CDIO_CDROM_LEADOUT_TRACK;
tocent.cdte_format = CDIO_CDROM_LBA;
if (ioctl (env->gen.fd, CDROMREADTOCENTRY, &tocent) == -1)
2003-03-24 19:01:09 +00:00
{
perror ("ioctl(CDROMREADTOCENTRY)");
exit (EXIT_FAILURE);
}
size = tocent.cdte_addr.lba;
return size;
}
/*!
Set the arg "key" with "value" in the source device.
Currently "source" and "access-mode" are valid keys.
"source" sets the source device in I/O operations
"access-mode" sets the the method of CD access
0 is returned if no error was found, and nonzero if there as an error.
2003-03-24 19:01:09 +00:00
*/
static int
_set_arg_solaris (void *p_user_data, const char key[], const char value[])
2003-03-24 19:01:09 +00:00
{
_img_private_t *env = p_user_data;
2003-03-24 19:01:09 +00:00
if (!strcmp (key, "source"))
{
if (!value)
return -2;
free (env->gen.source_name);
2003-03-24 19:01:09 +00:00
env->gen.source_name = strdup (value);
2003-03-24 19:01:09 +00:00
}
else if (!strcmp (key, "access-mode"))
{
env->access_mode = str_to_access_mode_sunos(key);
2003-03-24 19:01:09 +00:00
}
else
return -1;
return 0;
}
/*!
Read and cache the CD's Track Table of Contents and track info.
Return true if successful or false if an error.
*/
static bool
_cdio_read_toc (_img_private_t *env)
2003-03-24 19:01:09 +00:00
{
int i;
/* read TOC header */
if ( ioctl(env->gen.fd, CDROMREADTOCHDR, &env->tochdr) == -1 ) {
cdio_warn("%s: %s\n",
2003-03-24 19:01:09 +00:00
"error in ioctl CDROMREADTOCHDR", strerror(errno));
return false;
}
/* read individual tracks */
for (i=env->tochdr.cdth_trk0; i<=env->tochdr.cdth_trk1; i++) {
env->tocent[i-1].cdte_track = i;
env->tocent[i-1].cdte_format = CDIO_CDROM_MSF;
if ( ioctl(env->gen.fd, CDROMREADTOCENTRY, &env->tocent[i-1]) == -1 ) {
cdio_warn("%s %d: %s\n",
2003-03-24 19:01:09 +00:00
"error in ioctl CDROMREADTOCENTRY for track",
i, strerror(errno));
return false;
}
}
/* read the lead-out track */
env->tocent[env->tochdr.cdth_trk1].cdte_track = CDIO_CDROM_LEADOUT_TRACK;
env->tocent[env->tochdr.cdth_trk1].cdte_format = CDIO_CDROM_MSF;
2003-03-24 19:01:09 +00:00
if (ioctl(env->gen.fd, CDROMREADTOCENTRY,
&env->tocent[env->tochdr.cdth_trk1]) == -1 ) {
cdio_warn("%s: %s\n",
2003-03-24 19:01:09 +00:00
"error in ioctl CDROMREADTOCENTRY for lead-out",
strerror(errno));
return false;
}
env->gen.toc_init = true;
2003-03-24 19:01:09 +00:00
return true;
}
2004-07-17 09:35:00 +00:00
static void
set_cdtext_field_solaris(void *p_user_data, track_t i_track,
2004-07-17 09:35:00 +00:00
track_t i_first_track,
cdtext_field_t e_field, const char *psz_value)
{
char **pp_field;
_img_private_t *env = p_user_data;
2004-07-17 09:35:00 +00:00
if( i_track == 0 )
pp_field = &(env->cdtext.field[e_field]);
else
pp_field = &(env->cdtext_track[i_track-i_first_track].field[e_field]);
*pp_field = strdup(psz_value);
}
2004-07-15 04:03:52 +00:00
/*
Read cdtext information for a CdIo object .
2004-07-15 04:03:52 +00:00
return true on success, false on error or CD-TEXT information does
not exist.
2004-07-15 04:03:52 +00:00
*/
2004-07-17 09:35:00 +00:00
static bool
_init_cdtext_solaris (_img_private_t *p_env)
2004-07-15 04:03:52 +00:00
{
scsi_mmc_cdb_t cdb = {{0, }};
char wdata[5000] = { 0, };
int i_status;
2004-07-15 04:03:52 +00:00
2004-07-19 01:13:31 +00:00
/* Operation code */
CDIO_MMC_SET_COMMAND(cdb.field, CDIO_MMC_GPCMD_READ_TOC);
/* Format */
cdb.field[2] = CDIO_MMC_READTOC_FMT_CDTEXT;
errno = 0;
i_status = scsi_mmc_run_cmd_solaris (p_env, DEFAULT_TIMEOUT,
scsi_mmc_get_cmd_len(cdb.field[0]),
&cdb, SCSI_MMC_DATA_READ,
sizeof(wdata), &wdata);
if(i_status != 0) {
cdio_info ("CD-TEXT reading failed: %s\n", strerror(errno));
return false;
2004-07-15 04:03:52 +00:00
} else {
return cdtext_data_init(p_env, FIRST_TRACK_NUM, wdata,
2004-07-17 09:35:00 +00:00
set_cdtext_field_solaris);
2004-07-15 04:03:52 +00:00
}
}
/*!
Get cdtext information for a CdIo object .
@param obj the CD object that may contain CD-TEXT information.
@return the CD-TEXT object or NULL if obj is NULL
or CD-TEXT information does not exist.
*/
static const cdtext_t *
_get_cdtext_solaris (void *p_user_data, track_t i_track)
{
_img_private_t *p_env = p_user_data;
2004-07-17 09:35:00 +00:00
if ( NULL == p_env ||
(0 != i_track
&& i_track >= TOTAL_TRACKS+FIRST_TRACK_NUM )
|| p_env ->b_cdtext_error )
return NULL;
if (!p_env->b_cdtext_init)
p_env->b_cdtext_init = _init_cdtext_solaris(p_env);
if (!p_env->b_cdtext_init) return NULL;
if (0 == i_track)
return &(p_env->cdtext);
else
return &(p_env->cdtext_track[i_track-FIRST_TRACK_NUM]);
2004-07-15 04:03:52 +00:00
}
2003-03-24 19:01:09 +00:00
/*!
Eject media in CD drive. If successful, as a side effect we
also free obj.
*/
static int
_eject_media_solaris (void *p_user_data) {
2003-03-24 19:01:09 +00:00
_img_private_t *env = p_user_data;
2003-03-24 19:01:09 +00:00
int ret;
close(env->gen.fd);
env->gen.fd = -1;
if (env->gen.fd > -1) {
if ((ret = ioctl(env->gen.fd, CDROMEJECT)) != 0) {
cdio_generic_free((void *) env);
cdio_warn ("CDROMEJECT failed: %s\n", strerror(errno));
2003-03-24 19:01:09 +00:00
return 1;
} else {
return 0;
}
}
return 2;
}
static void *
_cdio_malloc_and_zero(size_t size) {
void *ptr;
if( !size ) size++;
if((ptr = malloc(size)) == NULL) {
cdio_warn("malloc() failed: %s", strerror(errno));
2003-03-24 19:01:09 +00:00
return NULL;
}
memset(ptr, 0, size);
return ptr;
}
/*!
Return the value associated with the key "arg".
*/
static const char *
_get_arg_solaris (void *p_user_data, const char key[])
2003-03-24 19:01:09 +00:00
{
_img_private_t *env = p_user_data;
2003-03-24 19:01:09 +00:00
if (!strcmp (key, "source")) {
return env->gen.source_name;
2003-03-24 19:01:09 +00:00
} else if (!strcmp (key, "access-mode")) {
switch (env->access_mode) {
2003-03-24 19:01:09 +00:00
case _AM_SUN_CTRL_ATAPI:
return "ATAPI";
case _AM_SUN_CTRL_SCSI:
return "SCSI";
case _AM_NONE:
return "no access method";
}
}
return NULL;
}
/*!
2003-09-26 09:11:19 +00:00
Return a string containing the default CD device if none is specified.
2003-03-24 19:01:09 +00:00
*/
char *
cdio_get_default_device_solaris(void)
2003-03-24 19:01:09 +00:00
{
char *volume_device;
char *volume_name;
char *volume_action;
char *device;
struct stat stb;
if ((volume_device = getenv("VOLUME_DEVICE")) != NULL &&
(volume_name = getenv("VOLUME_NAME")) != NULL &&
(volume_action = getenv("VOLUME_ACTION")) != NULL &&
strcmp(volume_action, "insert") == 0) {
device = _cdio_malloc_and_zero(strlen(volume_device)
+ strlen(volume_name) + 2);
if (device == NULL)
return strdup(DEFAULT_CDIO_DEVICE);
sprintf(device, "%s/%s", volume_device, volume_name);
if (stat(device, &stb) != 0 || !S_ISCHR(stb.st_mode)) {
free(device);
return strdup(DEFAULT_CDIO_DEVICE);
}
return device;
}
return strdup(DEFAULT_CDIO_DEVICE);
}
/*!
Return the the kind of drive capabilities of device.
Note: string is malloc'd so caller should free() then returned
string when done with it.
*/
static void
_get_drive_cap_solaris (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 _img_private_t *p_env = p_user_data;
scsi_mmc_cdb_t cdb = {{0, }};
int i_status;
uint8_t buf[192] = { 0, };
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;
i_status = scsi_mmc_run_cmd_solaris (p_env, DEFAULT_TIMEOUT,
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];
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) ) {
uint8_t which;
which = p[0] & 0x3F;
switch( which )
{
case CDIO_MMC_AUDIO_CTL_PAGE:
case CDIO_MMC_R_W_ERROR_PAGE:
case CDIO_MMC_CDR_PARMS_PAGE:
/* Don't handle these yet. */
break;
case CDIO_MMC_CAPABILITIES_PAGE:
scsi_mmc_get_drive_cap(p, p_read_cap, p_write_cap, p_misc_cap);
break;
default: ;
}
p += (p[1] + 2);
}
} else {
cdio_info("%s: %s\n",
"error in ioctl USCSICMD MODE_SELECT", strerror(errno));
*p_read_cap = CDIO_DRIVE_CAP_ERROR;
*p_write_cap = CDIO_DRIVE_CAP_ERROR;
*p_misc_cap = CDIO_DRIVE_CAP_ERROR;
}
return;
}
/*!
Return the the kind of drive capabilities of device.
Note: string is malloc'd so caller should free() then returned
string when done with it.
*/
static char *
_get_mcn_solaris (const void *p_user_data)
{
const _img_private_t *p_env = p_user_data;
scsi_mmc_cdb_t cdb = {{0, }};
char buf[25] = { 0, };
int i_status;
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;
cdb.field[8] = 28;
i_status = scsi_mmc_run_cmd_solaris (p_env, DEFAULT_TIMEOUT,
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;
}
2003-03-24 19:01:09 +00:00
/*!
Return the number of of the first track.
CDIO_INVALID_TRACK is returned on error.
*/
static track_t
_cdio_get_first_track_num(void *p_user_data)
2003-03-24 19:01:09 +00:00
{
_img_private_t *p_env = p_user_data;
2003-03-24 19:01:09 +00:00
if (!p_env->gen.toc_init) _cdio_read_toc (p_env) ;
2003-03-24 19:01:09 +00:00
return FIRST_TRACK_NUM;
}
2003-03-24 19:01:09 +00:00
/*!
Return the number of tracks in the current medium.
*/
static track_t
_cdio_get_num_tracks(void *p_user_data)
2003-03-24 19:01:09 +00:00
{
_img_private_t *p_env = p_user_data;
2003-03-24 19:01:09 +00:00
return TOTAL_TRACKS;
}
/*!
Get format of track.
*/
static track_format_t
_cdio_get_track_format(void *p_user_data, track_t i_track)
2003-03-24 19:01:09 +00:00
{
_img_private_t *p_env = p_user_data;
2003-03-24 19:01:09 +00:00
if ( (i_track > TOTAL_TRACKS+FIRST_TRACK_NUM) || i_track < FIRST_TRACK_NUM)
2003-03-24 19:01:09 +00:00
return TRACK_FORMAT_ERROR;
i_track -= FIRST_TRACK_NUM;
2003-03-24 19:01:09 +00:00
/* This is pretty much copied from the "badly broken" cdrom_count_tracks
in linux/cdrom.c.
*/
if (p_env->tocent[i_track].cdte_ctrl & CDROM_DATA_TRACK) {
if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_CDI_TRACK)
2003-03-24 19:01:09 +00:00
return TRACK_FORMAT_CDI;
else if (p_env->tocent[i_track].cdte_format == CDIO_CDROM_XA_TRACK)
2003-03-24 19:01:09 +00:00
return TRACK_FORMAT_XA;
else
return TRACK_FORMAT_DATA;
} else
return TRACK_FORMAT_AUDIO;
}
/*!
Return true if we have XA data (green, mode2 form1) or
XA data (green, mode2 form2). That is track begins:
sync - header - subheader
12 4 - 8
FIXME: there's gotta be a better design for this and get_track_format?
*/
static bool
_cdio_get_track_green(void *p_user_data, track_t i_track)
2003-03-24 19:01:09 +00:00
{
_img_private_t *p_env = p_user_data;
2003-03-24 19:01:09 +00:00
if (!p_env->gen.init) init_solaris(p_env);
if (!p_env->gen.toc_init) _cdio_read_toc (p_env) ;
2003-03-24 19:01:09 +00:00
if (i_track >= TOTAL_TRACKS+FIRST_TRACK_NUM || i_track < FIRST_TRACK_NUM)
2003-03-24 19:01:09 +00:00
return false;
i_track -= FIRST_TRACK_NUM;
2003-03-24 19:01:09 +00:00
/* FIXME: Dunno if this is the right way, but it's what
I was using in cd-info for a while.
2003-03-24 19:01:09 +00:00
*/
return ((p_env->tocent[i_track].cdte_ctrl & 2) != 0);
2003-03-24 19:01:09 +00:00
}
/*!
Return the starting MSF (minutes/secs/frames) for track number
2004-06-06 11:44:51 +00:00
track_num in obj. Track numbers usually start at something
greater than 0, usually 1.
2003-03-24 19:01:09 +00:00
The "leadout" track is specified either by
using track_num LEADOUT_TRACK or the total tracks+1.
False is returned if there is no entry.
2003-03-24 19:01:09 +00:00
*/
static bool
_cdio_get_track_msf(void *p_user_data, track_t i_track, msf_t *msf)
2003-03-24 19:01:09 +00:00
{
_img_private_t *p_env = p_user_data;
2003-03-24 19:01:09 +00:00
if (NULL == msf) return false;
if (!p_env->gen.init) init_solaris(p_env);
if (!p_env->gen.toc_init) _cdio_read_toc (p_env) ;
2003-03-24 19:01:09 +00:00
if (i_track == CDIO_CDROM_LEADOUT_TRACK)
i_track = TOTAL_TRACKS + FIRST_TRACK_NUM;
2003-03-24 19:01:09 +00:00
if (i_track > (TOTAL_TRACKS+FIRST_TRACK_NUM) || i_track < FIRST_TRACK_NUM) {
2003-03-24 19:01:09 +00:00
return false;
} else {
struct cdrom_tocentry *msf0 = &p_env->tocent[i_track-1];
2003-03-24 19:01:09 +00:00
msf->m = to_bcd8(msf0->cdte_addr.msf.minute);
msf->s = to_bcd8(msf0->cdte_addr.msf.second);
msf->f = to_bcd8(msf0->cdte_addr.msf.frame);
return true;
}
}
#else
/*!
Return a string containing the default VCD device if none is specified.
*/
char *
cdio_get_default_device_solaris(void)
{
return strdup(DEFAULT_CDIO_DEVICE);
}
2003-03-24 19:01:09 +00:00
#endif /* HAVE_SOLARIS_CDROM */
/*!
Return an array of strings giving possible CD devices.
*/
char **
cdio_get_devices_solaris (void)
{
#ifndef HAVE_SOLARIS_CDROM
return NULL;
#else
char **drives = NULL;
unsigned int num_files=0;
#ifdef HAVE_GLOB_H
unsigned int i;
glob_t globbuf;
globbuf.gl_offs = 0;
glob("/vol/dev/aliases/cdrom*", GLOB_DOOFFS, NULL, &globbuf);
for (i=0; i<globbuf.gl_pathc; i++) {
cdio_add_device_list(&drives, globbuf.gl_pathv[i], &num_files);
}
globfree(&globbuf);
#else
cdio_add_device_list(&drives, DEFAULT_CDIO_DEVICE, &num_files);
#endif /*HAVE_GLOB_H*/
cdio_add_device_list(&drives, NULL, &num_files);
return drives;
#endif /*HAVE_SOLARIS_CDROM*/
}
2003-03-24 19:01:09 +00:00
/*!
Initialization routine. This is the only thing that doesn't
get called via a function pointer. In fact *we* are the
ones to set that up.
*/
CdIo *
cdio_open_solaris (const char *psz_source_name)
{
return cdio_open_am_solaris(psz_source_name, NULL);
}
/*!
Initialization routine. This is the only thing that doesn't
get called via a function pointer. In fact *we* are the
ones to set that up.
*/
CdIo *
cdio_open_am_solaris (const char *psz_orig_source, const char *access_mode)
2003-03-24 19:01:09 +00:00
{
#ifdef HAVE_SOLARIS_CDROM
CdIo *ret;
_img_private_t *_data;
char *psz_source;
2003-03-24 19:01:09 +00:00
cdio_funcs _funcs = {
.eject_media = _eject_media_solaris,
.free = cdio_generic_free,
.get_arg = _get_arg_solaris,
2004-07-15 04:03:52 +00:00
.get_cdtext = _get_cdtext_solaris,
2003-10-03 02:35:33 +00:00
.get_devices = cdio_get_devices_solaris,
.get_default_device = cdio_get_default_device_solaris,
.get_drive_cap = _get_drive_cap_solaris,
2003-03-24 19:01:09 +00:00
.get_first_track_num= _cdio_get_first_track_num,
.get_mcn = _get_mcn_solaris,
2003-03-24 19:01:09 +00:00
.get_num_tracks = _cdio_get_num_tracks,
.get_track_format = _cdio_get_track_format,
.get_track_green = _cdio_get_track_green,
.get_track_lba = NULL, /* This could be implemented if need be. */
2003-03-24 19:01:09 +00:00
.get_track_msf = _cdio_get_track_msf,
.lseek = cdio_generic_lseek,
.read = cdio_generic_read,
.read_audio_sectors = _read_audio_sectors_solaris,
.read_mode1_sector = _read_mode1_sector_solaris,
.read_mode1_sectors = _read_mode1_sectors_solaris,
.read_mode2_sector = _read_mode2_sector_solaris,
.read_mode2_sectors = _read_mode2_sectors_solaris,
.run_scsi_mmc_cmd = scsi_mmc_run_cmd_solaris,
2003-03-24 19:01:09 +00:00
.stat_size = _cdio_stat_size,
.set_arg = _set_arg_solaris
2003-03-24 19:01:09 +00:00
};
_data = _cdio_malloc (sizeof (_img_private_t));
2004-04-30 07:07:49 +00:00
_data->access_mode = _AM_SUN_CTRL_SCSI;
_data->gen.init = false;
_data->gen.fd = -1;
2004-07-15 04:03:52 +00:00
_data->b_cdtext_init = false;
_data->b_cdtext_error = false;
2003-03-24 19:01:09 +00:00
if (NULL == psz_orig_source) {
psz_source = cdio_get_default_device_solaris();
if (NULL == psz_source) return NULL;
_set_arg_solaris(_data, "source", psz_source);
free(psz_source);
} else {
if (cdio_is_device_generic(psz_orig_source))
_set_arg_solaris(_data, "source", psz_orig_source);
else {
/* The below would be okay if all device drivers worked this way. */
#if 0
cdio_info ("source %s is a not a device", psz_orig_source);
#endif
return NULL;
}
}
2003-03-24 19:01:09 +00:00
ret = cdio_new (_data, &_funcs);
if (ret == NULL) return NULL;
if (init_solaris(_data))
2003-03-24 19:01:09 +00:00
return ret;
else {
cdio_generic_free (_data);
2003-03-24 19:01:09 +00:00
return NULL;
}
#else
return NULL;
#endif /* HAVE_SOLARIS_CDROM */
}
bool
cdio_have_solaris (void)
{
#ifdef HAVE_SOLARIS_CDROM
return true;
#else
return false;
#endif /* HAVE_SOLARIS_CDROM */
}