Split enumerate_common() into logic-layer, command-layer, transport-layer

This commit is contained in:
Thomas Schmitt 2006-10-21 18:51:35 +00:00
parent 6f0643b7cf
commit e5ed5f1856
13 changed files with 510 additions and 111 deletions

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2006.10.21.103653" #define Cdrskin_timestamP "2006.10.21.185102"

View File

@ -33,6 +33,16 @@ extern struct libdax_msgs *libdax_messenger;
static struct burn_drive drive_array[255]; static struct burn_drive drive_array[255];
static int drivetop = -1; static int drivetop = -1;
/* ts A61021 : the unspecific part of sg.c:enumerate_common()
*/
int burn_setup_drive(struct burn_drive *d, char *fname)
{
d->devname = burn_strdup(fname);
memset(&d->params, 0, sizeof(struct params));
d->released = 1;
d->status = BURN_DISC_UNREADY;
return 1;
}
/* ts A60904 : ticket 62, contribution by elmom */ /* ts A60904 : ticket 62, contribution by elmom */
/* splitting former burn_drive_free() (which freed all, into two calls) */ /* splitting former burn_drive_free() (which freed all, into two calls) */
@ -65,21 +75,8 @@ void burn_drive_free_all(void)
/* ts A60822 */ /* ts A60822 */
int burn_drive_is_open(struct burn_drive *d) int burn_drive_is_open(struct burn_drive *d)
{ {
#if defined(__FreeBSD__) /* ts A61021 : moved decision to sg.c */
return d->drive_is_open(d);
if (d->cam == NULL)
return 0;
#else /* __FreeBSD__ */
/* a bit more detailed case distinction than needed */
if (d->fd == -1337)
return 0;
if (d->fd < 0)
return 0;
#endif /* ! __FreeBSD__ */
return 1;
} }
@ -280,6 +277,39 @@ int burn_drive_unregister(struct burn_drive *d)
} }
/* ts A61021 : after-setup activities from sg.c:enumerate_common()
*/
struct burn_drive *burn_drive_finish_enum(struct burn_drive *d)
{
struct burn_drive *t;
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text);
t = burn_drive_register(d);
/* ts A60821 */
mmc_function_spy("enumerate_common : -------- doing grab");
/* try to get the drive info */
if (t->grab(t)) {
burn_print(2, "getting drive info\n");
t->getcaps(t);
t->unlock(t);
t->released = 1;
} else {
burn_print(2, "unable to grab new located drive\n");
burn_drive_unregister(t);
t = NULL;
}
/* ts A60821 */
mmc_function_spy("enumerate_common : ----- would release ");
return t;
}
void burn_drive_release(struct burn_drive *d, int le) void burn_drive_release(struct burn_drive *d, int le)
{ {
if (d->released) { if (d->released) {

View File

@ -61,4 +61,13 @@ int burn_drive_is_occupied(struct burn_drive *d);
int burn_drive_forget(struct burn_drive *d, int force); int burn_drive_forget(struct burn_drive *d, int force);
int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count); int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count);
/* ts A61021 : the unspecific part of sg.c:enumerate_common()
*/
int burn_setup_drive(struct burn_drive *d, char *fname);
/* ts A61021 : after-setup activities from sg.c:enumerate_common()
*/
struct burn_drive *burn_drive_finish_enum(struct burn_drive *d);
#endif /* __DRIVE */ #endif /* __DRIVE */

View File

@ -757,3 +757,27 @@ void mmc_sync_cache(struct burn_drive *d)
c.dir = NO_TRANSFER; c.dir = NO_TRANSFER;
d->issue_command(d, &c); d->issue_command(d, &c);
} }
/* ts A61021 : the mmc specific part of sg.c:enumerate_common()
*/
int mmc_setup_drive(struct burn_drive *d)
{
d->read_atip = mmc_read_atip;
d->read_toc = mmc_read_toc;
d->write = mmc_write;
d->erase = mmc_erase;
d->read_sectors = mmc_read_sectors;
d->perform_opc = mmc_perform_opc;
d->set_speed = mmc_set_speed;
d->send_cue_sheet = mmc_send_cue_sheet;
d->sync_cache = mmc_sync_cache;
d->get_nwa = mmc_get_nwa;
d->close_disc = mmc_close_disc;
d->close_session = mmc_close_session;
/* ts A61020 */
d->start_lba= -2000000000;
d->end_lba= -2000000000;
return 1;
}

View File

@ -39,4 +39,9 @@ void mmc_perform_opc(struct burn_drive *);
void mmc_get_configuration(struct burn_drive *); void mmc_get_configuration(struct burn_drive *);
int mmc_get_nwa(struct burn_drive *); int mmc_get_nwa(struct burn_drive *);
void mmc_send_cue_sheet(struct burn_drive *, struct cue_sheet *); void mmc_send_cue_sheet(struct burn_drive *, struct cue_sheet *);
/* ts A61021 : the mmc specific part of sg.c:enumerate_common()
*/
int mmc_setup_drive(struct burn_drive *d);
#endif /*__MMC*/ #endif /*__MMC*/

View File

@ -36,3 +36,13 @@ void sbc_eject(struct burn_drive *d)
c.dir = NO_TRANSFER; c.dir = NO_TRANSFER;
d->issue_command(d, &c); d->issue_command(d, &c);
} }
/* ts A61021 : the sbc specific part of sg.c:enumerate_common()
*/
int sbc_setup_drive(struct burn_drive *d)
{
d->eject = sbc_eject;
d->load = sbc_load;
return 1;
}

View File

@ -8,4 +8,8 @@ struct burn_drive;
void sbc_load(struct burn_drive *); void sbc_load(struct burn_drive *);
void sbc_eject(struct burn_drive *); void sbc_eject(struct burn_drive *);
/* ts A61021 : the sbc specific part of sg.c:enumerate_common()
*/
int sbc_setup_drive(struct burn_drive *d);
#endif /* __SBC */ #endif /* __SBC */

View File

@ -1,5 +1,21 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* >>> ts A61021 : for testing the new arrangement of code
please outcomment these defines : */
/* Keeps alive old enumerate_common(). New version delegates much work
to methods in drive, mmc, spc, and sbc .
*/
#define Scsi_freebsd_make_own_enumeratE 1
/* Keeps alive old sg_enumerate(). New version delegates most work to
sg_give_next_adr().
*/
#define Scsi_freebsd_old_sg_enumeratE 1
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
@ -37,33 +53,17 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* ts A51221 */ /* ts A51221 */
int burn_drive_is_banned(char *device_address); int burn_drive_is_banned(char *device_address);
/* ts A60813 : storage objects are in libburn/init.c
wether to use O_EXCL
wether to use O_NOBLOCK with open(2) on devices
wether to take O_EXCL rejection as fatal error */
extern int burn_sg_open_o_excl;
extern int burn_sg_open_o_nonblock;
extern int burn_sg_open_abort_busy;
/* ts A60821 /* ts A60821
<<< debug: for tracing calls which might use open drive fds */ <<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text); int mmc_function_spy(char * text);
/** Returns the next index number and the next enumerated drive address.
@param idx An opaque handle. Make no own theories about it. #ifdef Scsi_freebsd_old_sg_enumeratE
@param adr Takes the reply
@param adr_size Gives maximum size of reply including final 0
@param initialize 1 = start new,
0 = continue, use no other values for now
-1 = finish
@return 1 = reply is a valid address , 0 = no further address available
-1 = severe error (e.g. adr_size too small)
*/
int sg_give_next_adr(burn_drive_enumerator_t *idx, int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize) char adr[], int adr_size, int initialize)
{ {
return (0); return (0);
} }
@ -78,6 +78,208 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
return (0); return (0);
} }
#else /* Scsi_freebsd_old_sg_enumeratE */
/* ts A61021 : Moved most code from sg_enumerate under sg_give_next_adr() */
/* Some helper functions for sg_give_next_adr() */
static int sg_init_enumerator(burn_drive_enumerator_t *idx)
{
idx->skip_device = 0;
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
warn("couldn't open %s", XPT_DEVICE);
return -1;
}
bzero(&(idx->ccb), sizeof(union ccb));
idx->ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
idx->ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
idx->bufsize = sizeof(struct dev_match_result) * 100;
idx->ccb.cdm.match_buf_len = idx->bufsize;
idx->ccb.cdm.matches = (struct dev_match_result *)malloc(idx->bufsize);
if (idx->ccb.cdm.matches == NULL) {
warnx("can't malloc memory for matches");
close(idx->fd);
return -1;
}
idx->ccb.cdm.num_matches = 0;
idx->i = idx->ccb.cdm.num_matches; /* to trigger buffer load */
/*
* We fetch all nodes, since we display most of them in the default
* case, and all in the verbose case.
*/
idx->ccb.cdm.num_patterns = 0;
idx->ccb.cdm.pattern_buf_len = 0;
return 1;
}
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
{
/*
* We do the ioctl multiple times if necessary, in case there are
* more than 100 nodes in the EDT.
*/
if (ioctl(idx->fd, CAMIOCOMMAND, &(idx->ccb)) == -1) {
warn("error sending CAMIOCOMMAND ioctl");
return -1;
}
if ((idx->ccb.ccb_h.status != CAM_REQ_CMP)
|| ((idx->ccb.cdm.status != CAM_DEV_MATCH_LAST)
&& (idx->ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
warnx("got CAM error %#x, CDM error %d\n",
idx->ccb.ccb_h.status, idx->ccb.cdm.status);
return -1;
}
return 1;
}
/** Returns the next index number and the next enumerated drive address.
@param idx An opaque handle. Make no own theories about it.
@param adr Takes the reply
@param adr_size Gives maximum size of reply including final 0
@param initialize 1 = start new,
0 = continue, use no other values for now
-1 = finish
@return 1 = reply is a valid address , 0 = no further address available
-1 = severe error (e.g. adr_size too small)
*/
int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize)
{
int ret;
if (initialize == 1) {
ret = sg_init_enumerator(idx);
if (ret<=0)
return ret;
} else if (initialize == -1) {
if(idx->fd != -1)
close(idx->fd);
idx->fd = -1;
return 0;
}
try_item:; /* This spaghetti loop keeps the number of tabs small */
/* Loop content from old sg_enumerate() */
while (idx->i >= idx->ccb.cdm.num_matches) {
ret = sg_next_enumeration_buffer(idx);
if (ret<=0)
return -1;
if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP)
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) )
return 0;
idx->i = 0;
}
switch (idx->ccb.cdm.matches[idx->i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
result = &(idx->ccb.cdm.matches[i].result.device_result);
if (result->flags & DEV_RESULT_UNCONFIGURED)
idx->skip_device = 1;
else
idx->skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
char buf[64];
result = &(idx->ccb.cdm.matches[i].result.periph_result);
if (idx->skip_device ||
strcmp(result->periph_name, "pass") == 0)
break;
snprintf(buf, sizeof (buf), "/dev/%s%d",
result->periph_name, result->unit_number);
if(adr_size <= strlen(buf)
return -1;
strcpy(adr, buf);
/* Found next enumerable address */
return 1;
}
default:
/* printf(stderr, "unknown match type\n"); */
break;
}
(idx->i)++;
goto try_item; /* Regular function exit is return 1 above */
}
int sg_is_enumerable_adr(char* adr)
{
burn_drive_enumerator_t idx;
int initialize = 1;
char buf[64];
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
if (ret <= 0)
break;
if (strcmp(adr, buf) == 0) {
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return (0);
}
/** Try to obtain SCSI address parameters.
@return 1 is success , 0 is failure
*/
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
burn_drive_enumerator_t idx;
int initialize = 1;
char buf[64];
struct periph_match_result* result;
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
if (ret <= 0)
break;
if (strcmp(adr, buf) != 0)
continue;
result = &(idx->ccb.cdm.matches[i].result.periph_result);
*bus_no = result->path_id;
*host_no = result->path_id;
*channel_no = 0;
*target_no = result->target_id
*lun_no = result->target_lun;
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return (0);
}
#endif /* ! Scsi_freebsd_old_sg_enumeratE */
int sg_close_drive(struct burn_drive * d) int sg_close_drive(struct burn_drive * d)
{ {
if (d->cam != NULL) { if (d->cam != NULL) {
@ -87,13 +289,26 @@ int sg_close_drive(struct burn_drive * d)
return 0; return 0;
} }
int sg_drive_is_open(struct burn_drive * d)
{
return (d->cam != NULL);
}
void ata_enumerate(void) void ata_enumerate(void)
{ {
/* Do not supported */ /* ts A61021: Only a dummy function is needed in FreeBSD */
/* The difference between sg and ata should be encapsulated
in sg-linux.c */
;
} }
void sg_enumerate(void) void sg_enumerate(void)
{ {
#ifdef Scsi_freebsd_old_sg_enumeratE
union ccb ccb; union ccb ccb;
int bufsize, fd; int bufsize, fd;
unsigned int i; unsigned int i;
@ -188,8 +403,35 @@ void sg_enumerate(void)
&& (ccb.cdm.status == CAM_DEV_MATCH_MORE)); && (ccb.cdm.status == CAM_DEV_MATCH_MORE));
close(fd); close(fd);
#else /* Scsi_freebsd_old_sg_enumeratE */
burn_drive_enumerator_t idx;
int initialize = 1;
char buf[64];
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
if (ret <= 0)
break;
if (burn_drive_is_banned(buf))
continue;
enumerate_common(buf, idx.result->path_id, idx.result->path_id,
0, idx.result->target_id,
idx.result->target_lun);
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
#endif /* ! Scsi_freebsd_old_sg_enumeratE */
} }
#ifdef Scsi_freebsd_make_own_enumeratE
/* ts A61021: The old version which mixes SCSI and operating system adapter
*/
static void enumerate_common(char *fname, int bus_no, int host_no, static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no) int channel_no, int target_no, int lun_no)
{ {
@ -212,6 +454,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
out.grab = sg_grab; out.grab = sg_grab;
out.release = sg_release; out.release = sg_release;
out.drive_is_open= sg_drive_is_open;
out.issue_command = sg_issue_command; out.issue_command = sg_issue_command;
out.getcaps = spc_getcaps; out.getcaps = spc_getcaps;
out.released = 1; out.released = 1;
@ -271,7 +514,41 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
} }
/* #else /* Scsi_freebsd_make_own_enumeratE */
/* The new, more concise version of enumerate_common */
static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no)
{
int ret;
struct burn_drive out;
/* General libburn drive setup */
burn_setup_drive(&out, fname);
/* This transport adapter uses SCSI-family commands and models
(seems the adapter would know better than its boss, if ever) */
ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
target_no, lun_no, 0);
if (ret<=0)
return;
/* Operating system adapter is CAM */
/* Adapter specific handles and data */
out.cam = NULL;
/* Adapter specific functions */
out.grab = sg_grab;
out.release = sg_release;
out.drive_is_open = sg_drive_is_open;
out.issue_command = sg_issue_command;
/* Finally register drive and inquire drive information */
burn_drive_finish_enum(&out);
}
#endif /* ! Scsi_freebsd_make_own_enumeratE */
/* ts A61021: do not believe this:
we use the sg reference count to decide whether we can use the we use the sg reference count to decide whether we can use the
drive or not. drive or not.
if refcount is not one, drive is open somewhere else. if refcount is not one, drive is open somewhere else.
@ -305,6 +582,7 @@ int sg_grab(struct burn_drive *d)
return 0; return 0;
} }
/* /*
non zero return means you still have the drive and it's not non zero return means you still have the drive and it's not
in a state to be released? (is that even possible?) in a state to be released? (is that even possible?)

View File

@ -100,6 +100,15 @@ int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
return 0; return 0;
} }
int sg_drive_is_open(struct burn_drive * d)
{
/* a bit more detailed case distinction than needed */
if (d->fd == -1337)
return 0;
if (d->fd < 0)
return 0;
return 1;
}
/* ts A60924 */ /* ts A60924 */
int sg_handle_busy_device(char *fname, int os_errno) int sg_handle_busy_device(char *fname, int os_errno)
@ -420,94 +429,37 @@ void sg_enumerate(void)
} }
/* ts A60923 - A61005 : introduced new SCSI parameters */ /* ts A60923 - A61005 : introduced new SCSI parameters */
/* ts A61021 : moved non os-specific code to spc,sbc,mmc,drive */
static void enumerate_common(char *fname, int bus_no, int host_no, static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no) int channel_no, int target_no, int lun_no)
{ {
int i; int ret, i;
struct burn_drive *t;
struct burn_drive out; struct burn_drive out;
/* ts A60923 */ /* General libburn drive setup */
out.bus_no = bus_no; burn_setup_drive(&out, fname);
out.host = host_no;
out.id = target_no;
out.channel = channel_no;
out.lun = lun_no;
out.devname = burn_strdup(fname); /* This transport adapter uses SCSI-family commands and models
(seems the adapter would know better than its boss, if ever) */
ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
target_no, lun_no, 0);
if (ret<=0)
return;
/* Operating system adapter is Linux Generic SCSI (sg) */
/* Adapter specific handles and data */
out.fd = -1337; out.fd = -1337;
out.sibling_count = 0; out.sibling_count = 0;
for(i= 0; i<LIBBURN_SG_MAX_SIBLINGS; i++) for(i= 0; i<LIBBURN_SG_MAX_SIBLINGS; i++)
out.sibling_fds[i] = -1337; out.sibling_fds[i] = -1337;
/* Adapter specific functions */
/* ts A61020 */
out.start_lba= -2000000000;
out.end_lba= -2000000000;
out.read_atip = mmc_read_atip;
out.grab = sg_grab; out.grab = sg_grab;
out.release = sg_release; out.release = sg_release;
out.drive_is_open= sg_drive_is_open;
out.issue_command = sg_issue_command; out.issue_command = sg_issue_command;
out.getcaps = spc_getcaps;
out.released = 1;
out.status = BURN_DISC_UNREADY;
out.eject = sbc_eject;
out.load = sbc_load;
out.lock = spc_prevent;
out.unlock = spc_allow;
out.read_disc_info = spc_sense_write_params;
out.get_erase_progress = spc_get_erase_progress;
out.test_unit_ready = spc_test_unit_ready;
out.probe_write_modes = spc_probe_write_modes;
out.read_toc = mmc_read_toc;
out.write = mmc_write;
out.erase = mmc_erase;
out.read_sectors = mmc_read_sectors;
out.perform_opc = mmc_perform_opc;
out.set_speed = mmc_set_speed;
out.send_parameters = spc_select_error_params;
out.send_write_parameters = spc_select_write_params;
out.send_cue_sheet = mmc_send_cue_sheet;
out.sync_cache = mmc_sync_cache;
out.get_nwa = mmc_get_nwa;
out.close_disc = mmc_close_disc;
out.close_session = mmc_close_session;
out.idata = malloc(sizeof(struct burn_scsi_inquiry_data));
out.idata->valid = 0;
out.mdata = malloc(sizeof(struct scsi_mode_data));
out.mdata->valid = 0;
/* ts A61007 : obsolete Assert in drive_getcaps() */
if(out.idata == NULL || out.mdata == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020108,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Could not allocate new drive object", 0, 0);
return;
}
memset(&out.params, 0, sizeof(struct params));
t = burn_drive_register(&out);
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("enumerate_common : -------- doing grab");
/* try to get the drive info */
if (sg_grab(t)) {
burn_print(2, "getting drive info\n");
t->getcaps(t);
t->unlock(t);
t->released = 1;
} else {
burn_print(2, "unable to grab new located drive\n");
burn_drive_unregister(t);
}
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("enumerate_common : ----- would release ");
/* Finally register drive and inquire drive information */
burn_drive_finish_enum(&out);
} }
/* /*

View File

@ -9,7 +9,16 @@
which are now local in sg_enumerate() . So that sg_give_next_adr() which are now local in sg_enumerate() . So that sg_give_next_adr()
can work in BSD and sg_enumerate() can use it. */ can work in BSD and sg_enumerate() can use it. */
struct burn_drive_enumeration_state { struct burn_drive_enumeration_state {
#ifdef Scsi_freebsd_old_sg_enumeratE
int dummy; int dummy;
#else
union ccb ccb;
int bufsize, fd;
unsigned int i;
int skip_device;
#endif /* ! Scsi_freebsd_old_sg_enumeratE */
}; };
typedef struct burn_drive_enumeration_state burn_drive_enumerator_t; typedef struct burn_drive_enumeration_state burn_drive_enumerator_t;

View File

@ -23,6 +23,10 @@
#include "debug.h" #include "debug.h"
#include "options.h" #include "options.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* spc command set */ /* spc command set */
static unsigned char SPC_INQUIRY[] = { 0x12, 0, 0, 0, 255, 0 }; static unsigned char SPC_INQUIRY[] = { 0x12, 0, 0, 0, 255, 0 };
@ -433,3 +437,61 @@ int spc_block_type(enum burn_block_types b)
/* ts A61007 : already prevented in burn_write_opts_set_write_type() */ /* ts A61007 : already prevented in burn_write_opts_set_write_type() */
/* a ssert(0); */; /* a ssert(0); */;
} }
/* ts A61021 : the spc specific part of sg.c:enumerate_common()
*/
int spc_setup_drive(struct burn_drive *d)
{
d->getcaps = spc_getcaps;
d->lock = spc_prevent;
d->unlock = spc_allow;
d->read_disc_info = spc_sense_write_params;
d->get_erase_progress = spc_get_erase_progress;
d->test_unit_ready = spc_test_unit_ready;
d->probe_write_modes = spc_probe_write_modes;
d->send_parameters = spc_select_error_params;
d->send_write_parameters = spc_select_write_params;
return 1;
}
/* ts A61021 : the general SCSI specific part of sg.c:enumerate_common()
@param flag Bitfiled for control purposes
bit0= do not setup spc/sbc/mmc
*/
int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
int channel_no, int target_no, int lun_no, int flag)
{
int ret;
/* ts A60923 */
d->bus_no = bus_no;
d->host = host_no;
d->id = target_no;
d->channel = channel_no;
d->lun = lun_no;
d->idata = malloc(sizeof(struct burn_scsi_inquiry_data));
d->idata->valid = 0;
d->mdata = malloc(sizeof(struct scsi_mode_data));
d->mdata->valid = 0;
/* ts A61007 : obsolete Assert in drive_getcaps() */
if(d->idata == NULL || d->mdata == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020108,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Could not allocate new drive object", 0, 0);
return -1;
}
if(!(flag & 1)) {
ret = spc_setup_drive(d);
if (ret<=0)
return ret;
ret = sbc_setup_drive(d);
if (ret<=0)
return ret;
ret = mmc_setup_drive(d);
if (ret<=0)
return ret;
}
return 1;
}

View File

@ -22,4 +22,16 @@ int spc_block_type(enum burn_block_types b);
int spc_get_erase_progress(struct burn_drive *d); int spc_get_erase_progress(struct burn_drive *d);
int spc_test_unit_ready(struct burn_drive *d); int spc_test_unit_ready(struct burn_drive *d);
/* ts A61021 : the spc specific part of sg.c:enumerate_common()
*/
int spc_setup_drive(struct burn_drive *d);
/* ts A61021 : the general SCSI specific part of sg.c:enumerate_common()
@param flag Bitfield for control purposes
bit0= do not setup spc/sbc/mmc
*/
int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
int channel_no, int target_no, int lun_no, int flag);
#endif /*__SPC*/ #endif /*__SPC*/

View File

@ -145,6 +145,10 @@ struct burn_drive
/* transport functions */ /* transport functions */
int (*grab) (struct burn_drive *); int (*grab) (struct burn_drive *);
int (*release) (struct burn_drive *); int (*release) (struct burn_drive *);
/* ts A61021 */
int (*drive_is_open) (struct burn_drive *);
int (*issue_command) (struct burn_drive *, struct command *); int (*issue_command) (struct burn_drive *, struct command *);
/* lower level functions */ /* lower level functions */