Solaris patch from Thomas Schmitt to make the Solaris driver capable
of detecting drives without vold, and how to implement access mode MMC_RDWR.
This commit is contained in:
@@ -61,6 +61,7 @@ static const char _rcsid[] = "$Id: solaris.c,v 1.12 2008/04/22 15:29:12 karl Exp
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <dirent.h>
|
||||||
#include "cdtext_private.h"
|
#include "cdtext_private.h"
|
||||||
|
|
||||||
/* not defined in dkio.h yet */
|
/* not defined in dkio.h yet */
|
||||||
@@ -71,7 +72,9 @@ static const char _rcsid[] = "$Id: solaris.c,v 1.12 2008/04/22 15:29:12 karl Exp
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
_AM_NONE,
|
_AM_NONE,
|
||||||
_AM_SUN_CTRL_ATAPI,
|
_AM_SUN_CTRL_ATAPI,
|
||||||
_AM_SUN_CTRL_SCSI
|
_AM_SUN_CTRL_SCSI,
|
||||||
|
_AM_MMC_RDWR,
|
||||||
|
_AM_MMC_RDWR_EXCL
|
||||||
#if FINISHED
|
#if FINISHED
|
||||||
_AM_READ_CD,
|
_AM_READ_CD,
|
||||||
_AM_READ_10
|
_AM_READ_10
|
||||||
@@ -97,6 +100,8 @@ typedef struct {
|
|||||||
static track_format_t get_track_format_solaris(void *p_user_data,
|
static track_format_t get_track_format_solaris(void *p_user_data,
|
||||||
track_t i_track);
|
track_t i_track);
|
||||||
|
|
||||||
|
static char ** cdio_get_devices_solaris_cXtYdZs2(int flag);
|
||||||
|
|
||||||
static access_mode_t
|
static access_mode_t
|
||||||
str_to_access_mode_solaris(const char *psz_access_mode)
|
str_to_access_mode_solaris(const char *psz_access_mode)
|
||||||
{
|
{
|
||||||
@@ -108,6 +113,10 @@ str_to_access_mode_solaris(const char *psz_access_mode)
|
|||||||
return _AM_SUN_CTRL_SCSI; /* force ATAPI to be SCSI */
|
return _AM_SUN_CTRL_SCSI; /* force ATAPI to be SCSI */
|
||||||
else if (!strcmp(psz_access_mode, "SCSI"))
|
else if (!strcmp(psz_access_mode, "SCSI"))
|
||||||
return _AM_SUN_CTRL_SCSI;
|
return _AM_SUN_CTRL_SCSI;
|
||||||
|
else if (!strcmp(psz_access_mode, "MMC_RDWR"))
|
||||||
|
return _AM_MMC_RDWR;
|
||||||
|
else if (!strcmp(psz_access_mode, "MMC_RDWR_EXCL"))
|
||||||
|
return _AM_MMC_RDWR_EXCL;
|
||||||
else {
|
else {
|
||||||
cdio_warn ("unknown access type: %s. Default SCSI used.",
|
cdio_warn ("unknown access type: %s. Default SCSI used.",
|
||||||
psz_access_mode);
|
psz_access_mode);
|
||||||
@@ -249,17 +258,86 @@ audio_stop_solaris (void *p_user_data)
|
|||||||
return ioctl(p_env->gen.fd, CDROMSTOP);
|
return ioctl(p_env->gen.fd, CDROMSTOP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
cdio_decode_btl_number(char **cpt, int stopper, int *no)
|
||||||
|
{
|
||||||
|
*no = 0;
|
||||||
|
for ((*cpt)++; **cpt != stopper; (*cpt)++) {
|
||||||
|
if (**cpt < '0' || **cpt > '9')
|
||||||
|
return 0;
|
||||||
|
*no = *no * 10 + **cpt - '0';
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Read bus, target, lun from name "cXtYdZs2".
|
||||||
|
Return 0 if name is not of the desired form.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
cdio_decode_btl_solaris(char *name, int *busno, int *tgtno, int *lunno,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
char *cpt;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
*busno = *tgtno = *lunno = -1;
|
||||||
|
cpt = name;
|
||||||
|
if (*cpt != 'c')
|
||||||
|
return 0;
|
||||||
|
ret = cdio_decode_btl_number(&cpt, 't', busno);
|
||||||
|
if (ret <= 0)
|
||||||
|
return ret;
|
||||||
|
ret = cdio_decode_btl_number(&cpt, 'd', tgtno);
|
||||||
|
if (ret <= 0)
|
||||||
|
return ret;
|
||||||
|
ret = cdio_decode_btl_number(&cpt, 's', lunno);
|
||||||
|
if (ret <= 0)
|
||||||
|
return ret;
|
||||||
|
cpt++;
|
||||||
|
if (*cpt != '2' || *(cpt + 1) != 0)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_scsi_tuple_solaris (_img_private_t *p_env)
|
||||||
|
{
|
||||||
|
int bus_no = -1, host_no = -1, channel_no = -1, target_no = -1, lun_no = -1;
|
||||||
|
int ret;
|
||||||
|
char tuple[160], *cpt;
|
||||||
|
|
||||||
|
cpt = strrchr(p_env->gen.source_name, '/');
|
||||||
|
if (cpt == NULL)
|
||||||
|
cpt = p_env->gen.source_name;
|
||||||
|
else
|
||||||
|
cpt++;
|
||||||
|
ret = cdio_decode_btl_solaris(cpt, &bus_no, &target_no, &lun_no, 0);
|
||||||
|
if (ret <= 0)
|
||||||
|
return(ret);
|
||||||
|
host_no = bus_no;
|
||||||
|
channel_no = 0;
|
||||||
|
sprintf(tuple, "%d,%d,%d,%d,%d",
|
||||||
|
bus_no, host_no, channel_no, target_no, lun_no);
|
||||||
|
p_env->gen.scsi_tuple = strdup(tuple);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Initialize CD device.
|
Initialize CD device.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
init_solaris (_img_private_t *p_env)
|
init_solaris (_img_private_t *p_env)
|
||||||
{
|
{
|
||||||
|
int open_flags = O_RDONLY | O_NDELAY;
|
||||||
|
|
||||||
if (!cdio_generic_init(p_env, O_RDONLY)) return false;
|
if (_AM_MMC_RDWR != p_env->access_mode &&
|
||||||
|
_AM_MMC_RDWR_EXCL != p_env->access_mode)
|
||||||
|
/* (was once set to _AM_SUN_CTRL_SCSI unconditionally) */
|
||||||
p_env->access_mode = _AM_SUN_CTRL_SCSI;
|
p_env->access_mode = _AM_SUN_CTRL_SCSI;
|
||||||
|
|
||||||
|
if (!cdio_generic_init(p_env, open_flags))
|
||||||
|
return false;
|
||||||
|
set_scsi_tuple_solaris(p_env);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -281,22 +359,51 @@ run_mmc_cmd_solaris(void *p_user_data, unsigned int i_timeout_ms,
|
|||||||
cdio_mmc_direction_t e_direction,
|
cdio_mmc_direction_t e_direction,
|
||||||
unsigned int i_buf, /*in/out*/ void *p_buf)
|
unsigned int i_buf, /*in/out*/ void *p_buf)
|
||||||
{
|
{
|
||||||
const _img_private_t *p_env = p_user_data;
|
_img_private_t *p_env = p_user_data;
|
||||||
struct uscsi_cmd cgc;
|
struct uscsi_cmd cgc;
|
||||||
int i_rc;
|
int i_rc;
|
||||||
|
cdio_mmc_request_sense_t sense;
|
||||||
|
unsigned char *u_sense = (unsigned char *) &sense;
|
||||||
|
|
||||||
memset (&cgc, 0, sizeof (struct uscsi_cmd));
|
memset (&cgc, 0, sizeof (struct uscsi_cmd));
|
||||||
cgc.uscsi_cdb = (caddr_t) p_cdb;
|
cgc.uscsi_cdb = (caddr_t) p_cdb;
|
||||||
|
|
||||||
cgc.uscsi_flags = SCSI_MMC_DATA_READ == e_direction ?
|
/* See: man uscsi
|
||||||
USCSI_READ : USCSI_WRITE;
|
http://docs.sun.com/app/docs/doc/816-5177/uscsi-7i?a=view
|
||||||
|
*/
|
||||||
|
p_env->gen.scsi_mmc_sense_valid = 0;
|
||||||
|
memset(u_sense, 0, sizeof(sense));
|
||||||
|
cgc.uscsi_rqbuf = (caddr_t) u_sense;
|
||||||
|
cgc.uscsi_rqlen = sizeof(sense);
|
||||||
|
|
||||||
|
/* No error messages, no retries, do not execute with other commands,
|
||||||
|
request sense data
|
||||||
|
*/
|
||||||
|
cgc.uscsi_flags = USCSI_SILENT | USCSI_DIAGNOSE | USCSI_ISOLATE
|
||||||
|
| USCSI_RQENABLE;
|
||||||
|
|
||||||
|
if (SCSI_MMC_DATA_READ == e_direction)
|
||||||
|
cgc.uscsi_flags |= USCSI_READ;
|
||||||
|
else if (SCSI_MMC_DATA_WRITE == e_direction)
|
||||||
|
cgc.uscsi_flags |= USCSI_WRITE;
|
||||||
cgc.uscsi_timeout = msecs2secs(i_timeout_ms);
|
cgc.uscsi_timeout = msecs2secs(i_timeout_ms);
|
||||||
cgc.uscsi_bufaddr = p_buf;
|
cgc.uscsi_bufaddr = p_buf;
|
||||||
cgc.uscsi_buflen = i_buf;
|
cgc.uscsi_buflen = i_buf;
|
||||||
cgc.uscsi_cdblen = i_cdb;
|
cgc.uscsi_cdblen = i_cdb;
|
||||||
|
|
||||||
i_rc = ioctl(p_env->gen.fd, USCSICMD, &cgc);
|
i_rc = ioctl(p_env->gen.fd, USCSICMD, &cgc);
|
||||||
|
|
||||||
|
/* Record SCSI sense reply for API call mmc_last_cmd_sense().
|
||||||
|
*/
|
||||||
|
if (sense.additional_sense_len) { /* sense data available */
|
||||||
|
int sense_size = sense.additional_sense_len + 8;
|
||||||
|
|
||||||
|
if (sense_size > sizeof(sense))
|
||||||
|
sense_size = sizeof(sense);
|
||||||
|
memcpy((void *) p_env->gen.scsi_mmc_sense, &sense, sense_size);
|
||||||
|
p_env->gen.scsi_mmc_sense_valid = sense_size;
|
||||||
|
}
|
||||||
|
|
||||||
if (0 == i_rc) return DRIVER_OP_SUCCESS;
|
if (0 == i_rc) return DRIVER_OP_SUCCESS;
|
||||||
if (-1 == i_rc) {
|
if (-1 == i_rc) {
|
||||||
cdio_info ("ioctl USCSICMD failed: %s", strerror(errno));
|
cdio_info ("ioctl USCSICMD failed: %s", strerror(errno));
|
||||||
@@ -629,6 +736,13 @@ eject_media_solaris (void *p_user_data) {
|
|||||||
return DRIVER_OP_ERROR;
|
return DRIVER_OP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
is_mmc_supported(void *user_data)
|
||||||
|
{
|
||||||
|
_img_private_t *env = user_data;
|
||||||
|
return (_AM_NONE == env->access_mode) ? false : true;
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Return the value associated with the key "arg".
|
Return the value associated with the key "arg".
|
||||||
*/
|
*/
|
||||||
@@ -645,9 +759,17 @@ get_arg_solaris (void *p_user_data, const char key[])
|
|||||||
return "ATAPI";
|
return "ATAPI";
|
||||||
case _AM_SUN_CTRL_SCSI:
|
case _AM_SUN_CTRL_SCSI:
|
||||||
return "SCSI";
|
return "SCSI";
|
||||||
|
case _AM_MMC_RDWR:
|
||||||
|
return "MMC_RDWR";
|
||||||
|
case _AM_MMC_RDWR_EXCL:
|
||||||
|
return "MMC_RDWR_EXCL";
|
||||||
case _AM_NONE:
|
case _AM_NONE:
|
||||||
return "no access method";
|
return "no access method";
|
||||||
}
|
}
|
||||||
|
} else if (!strcmp (key, "scsi-tuple")) {
|
||||||
|
return p_env->gen.scsi_tuple;
|
||||||
|
} else if (!strcmp (key, "mmc-supported?")) {
|
||||||
|
return is_mmc_supported(p_user_data) ? "true" : "false";
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -672,6 +794,27 @@ get_blocksize_solaris (void *p_user_data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Return a string containing the default CD device if none is specified.
|
||||||
|
This call does not assume a fixed default drive address but rather uses
|
||||||
|
the first drive that gets enumerated by cdio_get_devices_solaris_cXtYdZs2().
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
cdio_get_default_cXtYdZs2(void)
|
||||||
|
{
|
||||||
|
char **devlist, *result = NULL;
|
||||||
|
|
||||||
|
devlist = cdio_get_devices_solaris_cXtYdZs2(1);
|
||||||
|
if(devlist != NULL) {
|
||||||
|
if(devlist[0] != NULL)
|
||||||
|
result = strdup(devlist[0]);
|
||||||
|
free(devlist);
|
||||||
|
}
|
||||||
|
if(result != NULL)
|
||||||
|
return result;
|
||||||
|
return strdup(DEFAULT_CDIO_DEVICE);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Return a string containing the default CD device if none is specified.
|
Return a string containing the default CD device if none is specified.
|
||||||
*/
|
*/
|
||||||
@@ -684,6 +827,14 @@ cdio_get_default_device_solaris(void)
|
|||||||
char *device;
|
char *device;
|
||||||
struct stat stb;
|
struct stat stb;
|
||||||
|
|
||||||
|
/* vold and its directory /vol have been replaced by "Tamarack" which
|
||||||
|
is based on hald. This happened in 2006.
|
||||||
|
*/
|
||||||
|
if(stat("/vol", &stb) == -1)
|
||||||
|
return cdio_get_default_cXtYdZs2();
|
||||||
|
if((stb.st_mode & S_IFMT) != S_IFDIR)
|
||||||
|
return cdio_get_default_cXtYdZs2();
|
||||||
|
|
||||||
if ((volume_device = getenv("VOLUME_DEVICE")) != NULL &&
|
if ((volume_device = getenv("VOLUME_DEVICE")) != NULL &&
|
||||||
(volume_name = getenv("VOLUME_NAME")) != NULL &&
|
(volume_name = getenv("VOLUME_NAME")) != NULL &&
|
||||||
(volume_action = getenv("VOLUME_ACTION")) != NULL &&
|
(volume_action = getenv("VOLUME_ACTION")) != NULL &&
|
||||||
@@ -1013,6 +1164,117 @@ close_tray_solaris (const char *psz_device)
|
|||||||
#endif /*HAVE_SOLARIS_CDROM*/
|
#endif /*HAVE_SOLARIS_CDROM*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Return an array of strings giving possible CD devices.
|
||||||
|
New method after demise of vold in 2006.
|
||||||
|
*/
|
||||||
|
/* flag bit0= need only the first drive
|
||||||
|
*/
|
||||||
|
static char **
|
||||||
|
cdio_get_devices_solaris_cXtYdZs2(int flag)
|
||||||
|
{
|
||||||
|
#ifndef HAVE_SOLARIS_CDROM
|
||||||
|
return NULL;
|
||||||
|
#else
|
||||||
|
int busno, tgtno, lunno, ret;
|
||||||
|
char volpath[160];
|
||||||
|
char **drives = NULL;
|
||||||
|
unsigned int i_files=0;
|
||||||
|
DIR *dir = NULL;
|
||||||
|
struct dirent *entry;
|
||||||
|
|
||||||
|
#ifdef LIBCDIO_SOLARIS_WITH_CD_INQUIRY
|
||||||
|
CdIo_t *cdio = NULL;
|
||||||
|
mmc_cdb_t cdb = {{0, }};
|
||||||
|
int timeout_ms;
|
||||||
|
driver_return_code_t i_status;
|
||||||
|
char reply[36];
|
||||||
|
static unsigned char spc_inquiry[] = { 0x12, 0, 0, 0, 36, 0 };
|
||||||
|
#else
|
||||||
|
struct dk_cinfo cinfo;
|
||||||
|
int fd = -1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int recursion = 0;
|
||||||
|
|
||||||
|
if (recursion) {
|
||||||
|
fprintf(stderr, "Program error ! Recursion of cdio_get_devices_solaris_cXtYdZs2()\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
recursion = 1;
|
||||||
|
|
||||||
|
dir = opendir("/dev/rdsk");
|
||||||
|
if (dir == NULL) {
|
||||||
|
cdio_warn ("opendir(\"/dev/rdsk\") failed: %s\n", strerror(errno));
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
while (1) {
|
||||||
|
entry = readdir(dir);
|
||||||
|
if (entry == NULL) {
|
||||||
|
if (errno) {
|
||||||
|
cdio_warn ("readdir(/dev/rdsk) failed: %s\n", strerror(errno));
|
||||||
|
goto ex;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret = cdio_decode_btl_solaris(entry->d_name, &busno, &tgtno, &lunno, 0);
|
||||||
|
if (ret < 0)
|
||||||
|
goto ex;
|
||||||
|
if (ret == 0)
|
||||||
|
continue; /* not cXtYdZs2 */
|
||||||
|
|
||||||
|
if (strlen(entry->d_name) > sizeof(volpath) - 11)
|
||||||
|
continue;
|
||||||
|
sprintf(volpath, "/dev/rdsk/%s", entry->d_name);
|
||||||
|
|
||||||
|
#ifdef LIBCDIO_SOLARIS_WITH_CD_INQUIRY
|
||||||
|
|
||||||
|
cdio = cdio_open_am_solaris(volpath, "MMC_RDWR");
|
||||||
|
if(cdio == NULL)
|
||||||
|
continue;
|
||||||
|
memcpy(cdb.field, spc_inquiry, 6);
|
||||||
|
timeout_ms = 10000;
|
||||||
|
i_status = run_mmc_cmd_solaris(cdio->env, timeout_ms,
|
||||||
|
6, &cdb, SCSI_MMC_DATA_READ,
|
||||||
|
(unsigned int) spc_inquiry[4], reply);
|
||||||
|
cdio_destroy(cdio);
|
||||||
|
cdio = NULL;
|
||||||
|
if (i_status != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* SBC-3 , table 83 , PERIPHERAL DEVICE TYPE : 5 = CD/DVD device */
|
||||||
|
if((reply[0] & 0x1F) != 5)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#else /* LIBCDIO_SOLARIS_WITH_CD_INQUIRY */
|
||||||
|
|
||||||
|
fd = open(volpath, O_RDONLY | O_NDELAY);
|
||||||
|
if (fd < 0)
|
||||||
|
continue;
|
||||||
|
/* See man dkio */
|
||||||
|
ret = ioctl(fd, DKIOCINFO, &cinfo);
|
||||||
|
close(fd);
|
||||||
|
fd = -1;
|
||||||
|
if (ret < 0)
|
||||||
|
continue;
|
||||||
|
if (cinfo.dki_ctype != DKC_CDROM)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
#endif /* ! LIBCDIO_SOLARIS_WITH_CD_INQUIRY */
|
||||||
|
|
||||||
|
cdio_add_device_list(&drives, volpath, &i_files);
|
||||||
|
if(flag & 1)
|
||||||
|
goto ex; /* Only the first drive is desired */
|
||||||
|
}
|
||||||
|
ex:;
|
||||||
|
recursion = 0;
|
||||||
|
if(dir != NULL)
|
||||||
|
closedir(dir);
|
||||||
|
cdio_add_device_list(&drives, NULL, &i_files);
|
||||||
|
return drives;
|
||||||
|
#endif /*HAVE_SOLARIS_CDROM*/
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Return an array of strings giving possible CD devices.
|
Return an array of strings giving possible CD devices.
|
||||||
*/
|
*/
|
||||||
@@ -1029,6 +1291,17 @@ cdio_get_devices_solaris (void)
|
|||||||
#ifdef HAVE_GLOB_H
|
#ifdef HAVE_GLOB_H
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
glob_t globbuf;
|
glob_t globbuf;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* vold and its directory /vol have been replaced by "Tamarack" which
|
||||||
|
is based on hald. This happened in 2006.
|
||||||
|
*/
|
||||||
|
if(stat("/vol", &st) == -1)
|
||||||
|
return cdio_get_devices_solaris_cXtYdZs2(0);
|
||||||
|
if((st.st_mode & S_IFMT) != S_IFDIR)
|
||||||
|
return cdio_get_devices_solaris_cXtYdZs2(0);
|
||||||
|
|
||||||
|
#ifdef HAVE_GLOB_H
|
||||||
|
|
||||||
globbuf.gl_offs = 0;
|
globbuf.gl_offs = 0;
|
||||||
glob("/vol/dev/aliases/cdrom*", GLOB_DOOFFS, NULL, &globbuf);
|
glob("/vol/dev/aliases/cdrom*", GLOB_DOOFFS, NULL, &globbuf);
|
||||||
@@ -1144,7 +1417,7 @@ cdio_open_am_solaris (const char *psz_orig_source, const char *access_mode)
|
|||||||
|
|
||||||
_data = calloc(1, sizeof (_img_private_t));
|
_data = calloc(1, sizeof (_img_private_t));
|
||||||
|
|
||||||
_data->access_mode = _AM_SUN_CTRL_SCSI;
|
_data->access_mode = str_to_access_mode_solaris(access_mode);
|
||||||
_data->gen.init = false;
|
_data->gen.init = false;
|
||||||
_data->gen.fd = -1;
|
_data->gen.fd = -1;
|
||||||
_data->gen.toc_init = false;
|
_data->gen.toc_init = false;
|
||||||
|
|||||||
Reference in New Issue
Block a user