Restored FreeBSD backend.

This commit is contained in:
Alexander Nedotsukov 2007-01-24 12:44:22 +00:00
parent 814d8cc83d
commit 3aec7fdeda
2 changed files with 133 additions and 242 deletions

View File

@ -7,10 +7,6 @@
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/ */
#ifndef BURN_OS_H_INCLUDED
#define BURN_OS_H_INCLUDED 1
/** List of all signals which shall be caught by signal handlers and trigger /** List of all signals which shall be caught by signal handlers and trigger
a graceful abort of libburn. (See man 7 signal.) a graceful abort of libburn. (See man 7 signal.)
*/ */
@ -52,14 +48,9 @@ SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
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.
*/ */
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \ #define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
struct burn_drive_enumeration_state { \ struct burn_drive_enumeration_state; \
union ccb ccb; \ typedef struct burn_drive_enumeration_state *burn_drive_enumerator_t;
int bufsize, fd; \
unsigned int i; \
int skip_device; \
}; \
typedef struct burn_drive_enumeration_state burn_drive_enumerator_t;
/* The list of operating system dependent elements in struct burn_drive. /* The list of operating system dependent elements in struct burn_drive.
@ -68,6 +59,3 @@ typedef struct burn_drive_enumeration_state burn_drive_enumerator_t;
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \ #define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
struct cam_device* cam; struct cam_device* cam;
#endif /* ! BURN_OS_H_INCLUDED */

View File

@ -1,19 +1,5 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Revives old enumerate_common(). New version delegates much work
to methods in drive, mmc, spc, and sbc .
*/
#define Scsi_freebsd_make_own_enumeratE 1
/* Revives old scsi_enumerate_drives(). New version delegates most work to
sg_give_next_adr().
*/
#define Scsi_freebsd_old_scsi_enumeratE 1
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
@ -45,6 +31,13 @@
#include "libdax_msgs.h" #include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger; extern struct libdax_msgs *libdax_messenger;
struct burn_drive_enumeration_state {
int fd;
union ccb ccb;
unsigned int i;
int skip_device;
};
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);
@ -57,33 +50,20 @@ int burn_drive_is_banned(char *device_address);
int mmc_function_spy(char * text); int mmc_function_spy(char * text);
#ifdef Scsi_freebsd_old_scsi_enumeratE
int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize)
{
return (0);
}
int sg_is_enumerable_adr(char* adr)
{
return (0);
}
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
return (0);
}
#else /* Scsi_freebsd_old_scsi_enumeratE */
/* ts A61021 : Moved most code from scsi_enumerate_drives under /* ts A61021 : Moved most code from scsi_enumerate_drives under
sg_give_next_adr() */ sg_give_next_adr() */
/* Some helper functions for scsi_give_next_adr() */ /* Some helper functions for scsi_give_next_adr() */
static int sg_init_enumerator(burn_drive_enumerator_t *idx) static int sg_init_enumerator(burn_drive_enumerator_t *idx_)
{ {
struct burn_drive_enumeration_state *idx;
int bufsize;
idx = malloc(sizeof(*idx));
if (idx == NULL) {
warnx("can't malloc memory for enumerator");
return -1;
}
idx->skip_device = 0; idx->skip_device = 0;
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) { if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
@ -98,12 +78,13 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx)
idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD; idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
idx->ccb.ccb_h.func_code = XPT_DEV_MATCH; idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
idx->bufsize = sizeof(struct dev_match_result) * 100; bufsize = sizeof(struct dev_match_result) * 100;
idx->ccb.cdm.match_buf_len = idx->bufsize; idx->ccb.cdm.match_buf_len = bufsize;
idx->ccb.cdm.matches = (struct dev_match_result *)malloc(idx->bufsize); idx->ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
if (idx->ccb.cdm.matches == NULL) { if (idx->ccb.cdm.matches == NULL) {
warnx("can't malloc memory for matches"); warnx("can't malloc memory for matches");
close(idx->fd); close(idx->fd);
free(idx);
return -1; return -1;
} }
idx->ccb.cdm.num_matches = 0; idx->ccb.cdm.num_matches = 0;
@ -116,12 +97,28 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx)
idx->ccb.cdm.num_patterns = 0; idx->ccb.cdm.num_patterns = 0;
idx->ccb.cdm.pattern_buf_len = 0; idx->ccb.cdm.pattern_buf_len = 0;
*idx_ = idx;
return 1; return 1;
} }
static void sg_destroy_enumerator(burn_drive_enumerator_t *idx_)
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
{ {
struct burn_drive_enumeration_state *idx = *idx_;
if(idx->fd != -1)
close(idx->fd);
free(idx->ccb.cdm.matches);
free(idx);
*idx_ = NULL;
}
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx_)
{
struct burn_drive_enumeration_state *idx = *idx_;
/* /*
* We do the ioctl multiple times if necessary, in case there are * We do the ioctl multiple times if necessary, in case there are
* more than 100 nodes in the EDT. * more than 100 nodes in the EDT.
@ -152,95 +149,94 @@ static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
@return 1 = reply is a valid address , 0 = no further address available @return 1 = reply is a valid address , 0 = no further address available
-1 = severe error (e.g. adr_size too small) -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)
{ {
struct burn_drive_enumeration_state *idx;
int ret; int ret;
if (initialize == 1) { if (initialize == 1) {
ret = sg_init_enumerator(idx); ret = sg_init_enumerator(idx_);
if (ret<=0) if (ret<=0)
return ret; return ret;
} else if (initialize == -1) { } else if (initialize == -1) {
if(idx->fd != -1) sg_destroy_enumerator(idx_);
close(idx->fd);
idx->fd = -1;
return 0; return 0;
} }
idx = *idx_;
try_item:; /* This spaghetti loop keeps the number of tabs small */ do {
if (idx->i >= idx->ccb.cdm.num_matches) {
ret = sg_next_enumeration_buffer(idx_);
if (ret<=0)
return -1;
idx->i = 0;
} else
(idx->i)++;
/* Loop content from old scsi_enumerate_drives() */ while (idx->i < idx->ccb.cdm.num_matches) {
switch (idx->ccb.cdm.matches[idx->i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
while (idx->i >= idx->ccb.cdm.num_matches) { result = &(idx->ccb.cdm.matches[idx->i].result.device_result);
ret = sg_next_enumeration_buffer(idx); if (result->flags & DEV_RESULT_UNCONFIGURED)
if (ret<=0) idx->skip_device = 1;
return -1; else
if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP) idx->skip_device = 0;
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) ) break;
return 0; }
idx->i = 0; case DEV_MATCH_PERIPH: {
} struct periph_match_result* result;
switch (idx->ccb.cdm.matches[idx->i].type) { result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
case DEV_MATCH_BUS: if (idx->skip_device ||
break; strcmp(result->periph_name, "pass") == 0)
case DEV_MATCH_DEVICE: { break;
struct device_match_result* result; ret = snprintf(adr, adr_size, "/dev/%s%d",
result->periph_name, result->unit_number);
if(ret >= adr_size)
return -1;
result = &(idx->ccb.cdm.matches[i].result.device_result); /* Found next enumerable address */
if (result->flags & DEV_RESULT_UNCONFIGURED) return 1;
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 || default:
strcmp(result->periph_name, "pass") == 0) /* printf(stderr, "unknown match type\n"); */
break; break;
snprintf(buf, sizeof (buf), "/dev/%s%d", }
result->periph_name, result->unit_number); (idx->i)++;
if(adr_size <= strlen(buf) }
return -1; } while ((idx->ccb.ccb_h.status == CAM_REQ_CMP)
strcpy(adr, buf); && (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE));
/* Found next enumerable address */ return 0;
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) int sg_is_enumerable_adr(char* adr)
{ {
burn_drive_enumerator_t idx; burn_drive_enumerator_t idx;
int initialize = 1; int ret;
char buf[64]; char buf[64];
ret = sg_init_enumerator(&idx);
if (ret <= 0)
return 0;
while(1) { while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize); ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
initialize = 0;
if (ret <= 0) if (ret <= 0)
break; break;
if (strcmp(adr, buf) == 0) { if (strcmp(adr, buf) == 0) {
sg_give_next_adr(&idx, buf, sizeof(buf), -1); sg_destroy_enumerator(&idx);
return 1; return 1;
} }
} }
sg_give_next_adr(&idx, buf, sizeof(buf), -1); sg_destroy_enumerator(&idx);
return (0); return (0);
} }
@ -252,32 +248,32 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no) int *target_no, int *lun_no)
{ {
burn_drive_enumerator_t idx; burn_drive_enumerator_t idx;
int initialize = 1; int ret;
char buf[64]; char buf[64];
struct periph_match_result* result; struct periph_match_result* result;
ret = sg_init_enumerator(&idx);
if (ret <= 0)
return 0;
while(1) { while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize); ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
initialize = 0;
if (ret <= 0) if (ret <= 0)
break; break;
if (strcmp(adr, buf) != 0) if (strcmp(path, buf) == 0) {
continue; result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
result = &(idx->ccb.cdm.matches[i].result.periph_result); *bus_no = result->path_id;
*bus_no = result->path_id; *host_no = result->path_id;
*host_no = result->path_id; *channel_no = 0;
*channel_no = 0; *target_no = result->target_id;
*target_no = result->target_id *lun_no = result->target_lun;
*lun_no = result->target_lun; sg_destroy_enumerator(&idx);
sg_give_next_adr(&idx, buf, sizeof(buf), -1); return 1;
return 1; }
} }
sg_give_next_adr(&idx, buf, sizeof(buf), -1); sg_destroy_enumerator(&idx);
return (0); return (0);
} }
#endif /* ! Scsi_freebsd_old_scsi_enumeratE */
int sg_close_drive(struct burn_drive * d) int sg_close_drive(struct burn_drive * d)
{ {
@ -295,125 +291,28 @@ int sg_drive_is_open(struct burn_drive * d)
int scsi_enumerate_drives(void) int scsi_enumerate_drives(void)
{ {
#ifdef Scsi_freebsd_old_scsi_enumeratE
union ccb ccb;
int bufsize, fd;
unsigned int i;
int skip_device = 0;
if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
warn("couldn't open %s", XPT_DEVICE);
return;
}
bzero(&ccb, sizeof(union ccb));
ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
ccb.ccb_h.func_code = XPT_DEV_MATCH;
bufsize = sizeof(struct dev_match_result) * 100;
ccb.cdm.match_buf_len = bufsize;
ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
if (ccb.cdm.matches == NULL) {
warnx("can't malloc memory for matches");
close(fd);
return;
}
ccb.cdm.num_matches = 0;
/*
* We fetch all nodes, since we display most of them in the default
* case, and all in the verbose case.
*/
ccb.cdm.num_patterns = 0;
ccb.cdm.pattern_buf_len = 0;
/*
* We do the ioctl multiple times if necessary, in case there are
* more than 100 nodes in the EDT.
*/
do {
if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
warn("error sending CAMIOCOMMAND ioctl");
break;
}
if ((ccb.ccb_h.status != CAM_REQ_CMP)
|| ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
&& (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
warnx("got CAM error %#x, CDM error %d\n",
ccb.ccb_h.status, ccb.cdm.status);
break;
}
for (i = 0; i < ccb.cdm.num_matches; i++) {
switch (ccb.cdm.matches[i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
result = &ccb.cdm.matches[i].result.device_result;
if (result->flags & DEV_RESULT_UNCONFIGURED)
skip_device = 1;
else
skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
char buf[64];
result = &ccb.cdm.matches[i].result.periph_result;
if (skip_device || strcmp(result->periph_name, "pass") == 0)
break;
snprintf(buf, sizeof (buf), "/dev/%s%d", result->periph_name, result->unit_number);
/* ts A51221 */
if (burn_drive_is_banned(buf))
break;
enumerate_common(buf, result->path_id, result->path_id, 0,
result->target_id, result->target_lun);
break;
}
default:
fprintf(stdout, "unknown match type\n");
break;
}
}
} while ((ccb.ccb_h.status == CAM_REQ_CMP)
&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
close(fd);
#else /* Scsi_freebsd_old_scsi_enumeratE */
burn_drive_enumerator_t idx; burn_drive_enumerator_t idx;
int initialize = 1; int ret;
char buf[64]; char buf[64];
struct periph_match_result* result;
ret = sg_init_enumerator(&idx);
if (ret <= 0)
return 0;
while(1) { while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize); ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
initialize = 0;
if (ret <= 0) if (ret <= 0)
break; break;
if (burn_drive_is_banned(buf)) if (burn_drive_is_banned(buf))
continue; continue;
enumerate_common(buf, idx.result->path_id, idx.result->path_id, result = &idx->ccb.cdm.matches[idx->i].result.periph_result;
0, idx.result->target_id, enumerate_common(buf, result->path_id, result->path_id,
idx.result->target_lun); 0, result->target_id,
result->target_lun);
} }
sg_give_next_adr(&idx, buf, sizeof(buf), -1); sg_destroy_enumerator(&idx);
#endif /* ! Scsi_freebsd_old_scsi_enumeratE */
return 1;
} }
@ -551,7 +450,10 @@ int sg_grab(struct burn_drive *d)
mmc_function_spy("sg_grab"); mmc_function_spy("sg_grab");
assert(d->cam == NULL); if (burn_drive_is_open(d)) {
d->released = 0;
return 1;
}
cam = cam_open_device(d->devname, O_RDWR); cam = cam_open_device(d->devname, O_RDWR);
if (cam == NULL) { if (cam == NULL) {
@ -591,6 +493,7 @@ int sg_release(struct burn_drive *d)
mmc_function_spy("sg_release ----------- closing."); mmc_function_spy("sg_release ----------- closing.");
sg_close_drive(d); sg_close_drive(d);
d->released = 1;
return 0; return 0;
} }