For Linux 2.4, USB : Carefully avoided to inquire more data than available
This commit is contained in:
parent
41f2a40a58
commit
79adcb520b
@ -1 +1 @@
|
||||
#define Cdrskin_timestamP "2007.05.21.184334"
|
||||
#define Cdrskin_timestamP "2007.05.21.185450"
|
||||
|
377
libburn/mmc.c
377
libburn/mmc.c
@ -92,6 +92,11 @@ extern struct libdax_msgs *libdax_messenger;
|
||||
ts A70330 : Allowed finalizing of DVD+R.
|
||||
*/
|
||||
|
||||
/* ts A70519 : With MMC commands of data direction FROM_DRIVE:
|
||||
Made struct command.dxfer_len equal to Allocation Length
|
||||
of MMC commands. Made sure that not more bytes are allowed
|
||||
for transfer than there are available.
|
||||
*/
|
||||
|
||||
static unsigned char MMC_GET_MSINFO[] =
|
||||
{ 0x43, 0, 1, 0, 0, 0, 0, 16, 0, 0 };
|
||||
@ -116,6 +121,7 @@ static unsigned char MMC_SYNC_CACHE[] = { 0x35, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
static unsigned char MMC_GET_EVENT[] = { 0x4A, 1, 0, 0, 16, 0, 0, 0, 8, 0 };
|
||||
static unsigned char MMC_CLOSE[] = { 0x5B, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
static unsigned char MMC_TRACK_INFO[] = { 0x52, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
|
||||
|
||||
static unsigned char MMC_SEND_CUE_SHEET[] =
|
||||
{ 0x5D, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
@ -188,9 +194,13 @@ void mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
|
||||
|
||||
|
||||
mmc_function_spy("mmc_send_cue_sheet");
|
||||
c.retry = 1;
|
||||
|
||||
scsi_init_command(&c, MMC_SEND_CUE_SHEET, sizeof(MMC_SEND_CUE_SHEET));
|
||||
/*
|
||||
c.oplen = sizeof(MMC_SEND_CUE_SHEET);
|
||||
memcpy(c.opcode, MMC_SEND_CUE_SHEET, sizeof(MMC_SEND_CUE_SHEET));
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.page = &buf;
|
||||
c.page->bytes = s->count * 8;
|
||||
c.page->sectors = 0;
|
||||
@ -214,10 +224,12 @@ int mmc_reserve_track(struct burn_drive *d, off_t size)
|
||||
char msg[80];
|
||||
|
||||
mmc_function_spy("mmc_reserve_track");
|
||||
c.retry = 1;
|
||||
scsi_init_command(&c, MMC_RESERVE_TRACK, sizeof(MMC_RESERVE_TRACK));
|
||||
/*
|
||||
c.oplen = sizeof(MMC_RESERVE_TRACK);
|
||||
memcpy(c.opcode, MMC_RESERVE_TRACK, sizeof(MMC_RESERVE_TRACK));
|
||||
|
||||
*/
|
||||
c.retry = 1;
|
||||
/* Round to 32 KiB and divide by 2048
|
||||
(by nice binary rounding trick learned from dvd+rw-tools) */
|
||||
lba = ((size + (off_t) 0x7fff) >> 11) & ~0xf;
|
||||
@ -238,14 +250,22 @@ int mmc_reserve_track(struct burn_drive *d, off_t size)
|
||||
/* ts A70201 :
|
||||
Common track info fetcher for mmc_get_nwa() and mmc_fake_toc()
|
||||
*/
|
||||
int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf)
|
||||
int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf,
|
||||
int alloc_len)
|
||||
{
|
||||
struct command c;
|
||||
|
||||
mmc_function_spy("mmc_read_track_info");
|
||||
c.retry = 1;
|
||||
|
||||
scsi_init_command(&c, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO));
|
||||
/*
|
||||
c.oplen = sizeof(MMC_TRACK_INFO);
|
||||
memcpy(c.opcode, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO));
|
||||
*/
|
||||
c.dxfer_len = alloc_len;
|
||||
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8] = c.dxfer_len & 0xff;
|
||||
c.retry = 1;
|
||||
c.opcode[1] = 1;
|
||||
if(trackno<=0) {
|
||||
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
|
||||
@ -278,12 +298,12 @@ int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf)
|
||||
int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
|
||||
{
|
||||
struct buffer buf;
|
||||
int ret, num;
|
||||
int ret, num, alloc_len = 20;
|
||||
unsigned char *data;
|
||||
|
||||
mmc_function_spy("mmc_get_nwa");
|
||||
|
||||
ret = mmc_read_track_info(d, trackno, &buf);
|
||||
ret = mmc_read_track_info(d, trackno, &buf, alloc_len);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
data = buf.data;
|
||||
@ -368,9 +388,12 @@ void mmc_close(struct burn_drive *d, int session, int track)
|
||||
|
||||
mmc_function_spy("mmc_close");
|
||||
|
||||
c.retry = 1;
|
||||
scsi_init_command(&c, MMC_CLOSE, sizeof(MMC_CLOSE));
|
||||
/*
|
||||
c.oplen = sizeof(MMC_CLOSE);
|
||||
memcpy(c.opcode, MMC_CLOSE, sizeof(MMC_CLOSE));
|
||||
*/
|
||||
c.retry = 1;
|
||||
|
||||
/* (ts A61030 : shifted !!session rather than or-ing plain session ) */
|
||||
c.opcode[2] = ((session & 3) << 1) | !!track;
|
||||
@ -385,11 +408,19 @@ void mmc_get_event(struct burn_drive *d)
|
||||
{
|
||||
struct buffer buf;
|
||||
struct command c;
|
||||
int alloc_len= 8;
|
||||
|
||||
mmc_function_spy("mmc_get_event");
|
||||
c.retry = 1;
|
||||
|
||||
scsi_init_command(&c, MMC_GET_EVENT, sizeof(MMC_GET_EVENT));
|
||||
/*
|
||||
c.oplen = sizeof(MMC_GET_EVENT);
|
||||
memcpy(c.opcode, MMC_GET_EVENT, sizeof(MMC_GET_EVENT));
|
||||
*/
|
||||
c.dxfer_len = alloc_len;
|
||||
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8] = c.dxfer_len & 0xff;
|
||||
c.retry = 1;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
c.page->sectors = 0;
|
||||
@ -415,9 +446,13 @@ void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf)
|
||||
/* a ssert(buf->bytes >= buf->sectors);*/ /* can be == at 0... */
|
||||
|
||||
burn_print(100, "trying to write %d at %d\n", len, start);
|
||||
|
||||
scsi_init_command(&c, MMC_WRITE_12, sizeof(MMC_WRITE_12));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_WRITE_12, sizeof(MMC_WRITE_12));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_WRITE_12);
|
||||
*/
|
||||
c.retry = 1;
|
||||
mmc_int_to_four_char(c.opcode + 2, start);
|
||||
mmc_int_to_four_char(c.opcode + 6, len);
|
||||
c.page = buf;
|
||||
@ -469,9 +504,13 @@ int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
|
||||
/* a ssert(buf->bytes >= buf->sectors);*/ /* can be == at 0... */
|
||||
|
||||
burn_print(100, "trying to write %d at %d\n", len, start);
|
||||
|
||||
scsi_init_command(&c, MMC_WRITE_10, sizeof(MMC_WRITE_10));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_WRITE_10, sizeof(MMC_WRITE_10));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_WRITE_10);
|
||||
*/
|
||||
c.retry = 1;
|
||||
mmc_int_to_four_char(c.opcode + 2, start);
|
||||
c.opcode[6] = 0;
|
||||
c.opcode[7] = (len >> 8) & 0xFF;
|
||||
@ -570,7 +609,7 @@ int mmc_fake_toc(struct burn_drive *d)
|
||||
struct burn_session *session;
|
||||
struct burn_toc_entry *entry;
|
||||
struct buffer buf;
|
||||
int i, session_number, prev_session = -1, ret, lba;
|
||||
int i, session_number, prev_session = -1, ret, lba, alloc_len = 34;
|
||||
unsigned char *tdata, size_data[4], start_data[4];
|
||||
char msg[160];
|
||||
|
||||
@ -618,7 +657,7 @@ int mmc_fake_toc(struct burn_drive *d)
|
||||
leadout X entry i+X
|
||||
*/
|
||||
for (i = 0; i < d->last_track_no; i++) {
|
||||
ret = mmc_read_track_info(d, i+1, &buf);
|
||||
ret = mmc_read_track_info(d, i+1, &buf, alloc_len);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
tdata = buf.data;
|
||||
@ -687,7 +726,7 @@ int mmc_fake_toc(struct burn_drive *d)
|
||||
}
|
||||
|
||||
|
||||
void mmc_read_toc(struct burn_drive *d)
|
||||
static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
|
||||
{
|
||||
/* read full toc, all sessions, in m/s/f form, 4k buffer */
|
||||
/* ts A70201 : or fake a toc from track information */
|
||||
@ -696,10 +735,14 @@ void mmc_read_toc(struct burn_drive *d)
|
||||
struct buffer buf;
|
||||
struct command c;
|
||||
int dlen;
|
||||
int i, bpl= 12;
|
||||
int i, bpl= 12, old_alloc_len;
|
||||
unsigned char *tdata;
|
||||
|
||||
mmc_function_spy("mmc_read_toc");
|
||||
|
||||
if (*alloc_len < 4)
|
||||
return 0;
|
||||
|
||||
if (!(d->current_profile == -1 || d->current_is_cd_profile)) {
|
||||
/* ts A70131 : MMC_GET_TOC uses Response Format 2
|
||||
For DVD this fails with 5,24,00 */
|
||||
@ -715,11 +758,17 @@ void mmc_read_toc(struct burn_drive *d)
|
||||
|
||||
if (d->status == BURN_DISC_UNREADY)
|
||||
d->status = BURN_DISC_FULL;
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
scsi_init_command(&c, MMC_GET_TOC, sizeof(MMC_GET_TOC));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_GET_TOC, sizeof(MMC_GET_TOC));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_GET_TOC);
|
||||
*/
|
||||
c.dxfer_len = *alloc_len;
|
||||
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8] = c.dxfer_len & 0xff;
|
||||
c.retry = 1;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
c.page->sectors = 0;
|
||||
@ -746,11 +795,19 @@ void mmc_read_toc(struct burn_drive *d)
|
||||
d->toc_entry = malloc(sizeof(struct burn_toc_entry));
|
||||
memset(&(d->toc_entry[0]), 0, sizeof(struct burn_toc_entry));
|
||||
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
dlen = c.page->data[0] * 256 + c.page->data[1];
|
||||
old_alloc_len = *alloc_len;
|
||||
*alloc_len = dlen + 2;
|
||||
if (old_alloc_len < 15)
|
||||
return 1;
|
||||
if (dlen + 2 > old_alloc_len)
|
||||
dlen = old_alloc_len - 2;
|
||||
d->toc_entries = (dlen - 2) / 11;
|
||||
if (d->toc_entries < 1)
|
||||
return 0;
|
||||
/*
|
||||
some drives fail this check.
|
||||
|
||||
@ -839,6 +896,22 @@ void mmc_read_toc(struct burn_drive *d)
|
||||
if (d->status == BURN_DISC_UNREADY)
|
||||
d->status = BURN_DISC_FULL;
|
||||
toc_find_modes(d);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void mmc_read_toc(struct burn_drive *d)
|
||||
{
|
||||
int alloc_len = 4, ret;
|
||||
|
||||
ret = mmc_read_toc_al(d, &alloc_len);
|
||||
/*
|
||||
fprintf(stderr,
|
||||
"LIBBURN_DEBUG: 43h READ TOC alloc_len = %d , ret = %d\n",
|
||||
alloc_len, ret);
|
||||
*/
|
||||
if (alloc_len >= 15)
|
||||
ret = mmc_read_toc_al(d, &alloc_len);
|
||||
}
|
||||
|
||||
|
||||
@ -852,7 +925,7 @@ int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start)
|
||||
struct buffer buf;
|
||||
struct command c;
|
||||
unsigned char *tdata;
|
||||
int num_sessions, session_no, num_tracks;
|
||||
int num_sessions, session_no, num_tracks, alloc_len = 12;
|
||||
struct burn_disc *disc;
|
||||
struct burn_session **sessions;
|
||||
struct burn_track **tracks;
|
||||
@ -895,9 +968,15 @@ inquire_drive:;
|
||||
MMC-3 states that DVD had no tracks. So maybe this mandatory fake
|
||||
is a forgotten legacy ?
|
||||
*/
|
||||
scsi_init_command(&c, MMC_GET_MSINFO, sizeof(MMC_GET_MSINFO));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_GET_MSINFO, sizeof(MMC_GET_MSINFO));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_GET_MSINFO);
|
||||
*/
|
||||
c.dxfer_len = alloc_len;
|
||||
c.opcode[7]= (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8]= c.dxfer_len & 0xff;
|
||||
c.retry = 1;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
c.page->sectors = 0;
|
||||
@ -914,14 +993,14 @@ inquire_drive:;
|
||||
}
|
||||
|
||||
|
||||
void mmc_read_disc_info(struct burn_drive *d)
|
||||
static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
|
||||
{
|
||||
struct buffer buf;
|
||||
unsigned char *data;
|
||||
struct command c;
|
||||
char msg[160];
|
||||
/* ts A70131 : had to move mmc_read_toc() to end of function */
|
||||
int do_read_toc = 0, session_state, disc_status;
|
||||
int do_read_toc = 0, session_state, disc_status, len, old_alloc_len;
|
||||
|
||||
/* ts A61020 */
|
||||
d->start_lba = d->end_lba = -2000000000;
|
||||
@ -935,14 +1014,23 @@ void mmc_read_disc_info(struct burn_drive *d)
|
||||
/* ts A61202 */
|
||||
d->toc_entries = 0;
|
||||
if (d->status == BURN_DISC_EMPTY)
|
||||
return;
|
||||
return 1;
|
||||
|
||||
mmc_get_configuration(d);
|
||||
|
||||
if (*alloc_len < 2)
|
||||
|
||||
mmc_function_spy("mmc_read_disc_info");
|
||||
|
||||
scsi_init_command(&c, MMC_GET_DISC_INFO, sizeof(MMC_GET_DISC_INFO));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_GET_DISC_INFO, sizeof(MMC_GET_DISC_INFO));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_GET_DISC_INFO);
|
||||
*/
|
||||
c.dxfer_len = *alloc_len;
|
||||
c.opcode[7]= (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8]= c.dxfer_len & 0xff;
|
||||
c.retry = 1;
|
||||
c.page = &buf;
|
||||
c.page->sectors = 0;
|
||||
c.page->bytes = 0;
|
||||
@ -951,10 +1039,20 @@ void mmc_read_disc_info(struct burn_drive *d)
|
||||
|
||||
if (c.error) {
|
||||
d->busy = BURN_DRIVE_IDLE;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = c.page->data;
|
||||
len = (data[0] << 8) | data[1];
|
||||
old_alloc_len = *alloc_len;
|
||||
*alloc_len = len + 2;
|
||||
if (old_alloc_len < 34)
|
||||
return 1;
|
||||
if (*alloc_len < 24) /* data[23] is the last byte used her */
|
||||
return 0;
|
||||
if (len + 2 > old_alloc_len)
|
||||
len = old_alloc_len - 2;
|
||||
|
||||
d->erasable = !!(data[2] & 16);
|
||||
|
||||
disc_status = data[2] & 3;
|
||||
@ -997,7 +1095,7 @@ void mmc_read_disc_info(struct burn_drive *d)
|
||||
msg, 0,0);
|
||||
}
|
||||
d->status = BURN_DISC_UNSUITABLE;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* >>> ts A61217 : Note for future
|
||||
@ -1042,12 +1140,28 @@ void mmc_read_disc_info(struct burn_drive *d)
|
||||
|
||||
if (do_read_toc)
|
||||
mmc_read_toc(d);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void mmc_read_disc_info(struct burn_drive *d)
|
||||
{
|
||||
int alloc_len = 34, ret;
|
||||
|
||||
ret = mmc_read_disc_info_al(d, &alloc_len);
|
||||
/*
|
||||
fprintf(stderr,"LIBBURN_DEBUG: 51h alloc_len = %d , ret = %d\n",
|
||||
alloc_len, ret);
|
||||
*/
|
||||
/* for now there is no need to inquire the variable lenght part */
|
||||
}
|
||||
|
||||
|
||||
void mmc_read_atip(struct burn_drive *d)
|
||||
{
|
||||
struct buffer buf;
|
||||
struct command c;
|
||||
int alloc_len = 28;
|
||||
|
||||
/* ts A61021 */
|
||||
unsigned char *data;
|
||||
@ -1063,9 +1177,16 @@ void mmc_read_atip(struct burn_drive *d)
|
||||
/* 24, 32, 40, 48, -, -, -, - */
|
||||
|
||||
mmc_function_spy("mmc_read_atip");
|
||||
|
||||
scsi_init_command(&c, MMC_GET_ATIP, sizeof(MMC_GET_ATIP));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_GET_ATIP, sizeof(MMC_GET_ATIP));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_GET_ATIP);
|
||||
*/
|
||||
c.dxfer_len = alloc_len;
|
||||
c.opcode[7]= (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8]= c.dxfer_len & 0xff;
|
||||
c.retry = 1;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
c.page->sectors = 0;
|
||||
@ -1221,9 +1342,13 @@ void mmc_read_sectors(struct burn_drive *d,
|
||||
/* a ssert(d->busy); */
|
||||
|
||||
burn_print(12, "reading %d from %d\n", len, start);
|
||||
|
||||
scsi_init_command(&c, MMC_READ_CD, sizeof(MMC_READ_CD));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_READ_CD, sizeof(MMC_READ_CD));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_READ_CD);
|
||||
*/
|
||||
c.retry = 1;
|
||||
temp = start;
|
||||
c.opcode[5] = temp & 0xFF;
|
||||
temp >>= 8;
|
||||
@ -1277,11 +1402,15 @@ void mmc_erase(struct burn_drive *d, int fast)
|
||||
struct command c;
|
||||
|
||||
mmc_function_spy("mmc_erase");
|
||||
|
||||
scsi_init_command(&c, MMC_BLANK, sizeof(MMC_BLANK));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_BLANK, sizeof(MMC_BLANK));
|
||||
c.oplen = sizeof(MMC_BLANK);
|
||||
*/
|
||||
c.opcode[1] = 16; /* IMMED set to 1 */
|
||||
c.opcode[1] |= !!fast;
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_BLANK);
|
||||
c.page = NULL;
|
||||
c.dir = NO_TRANSFER;
|
||||
d->issue_command(d, &c);
|
||||
@ -1294,9 +1423,12 @@ void mmc_read_lead_in(struct burn_drive *d, struct buffer *buf)
|
||||
|
||||
mmc_function_spy("mmc_read_lead_in");
|
||||
len = buf->sectors;
|
||||
scsi_init_command(&c, MMC_READ_CD, sizeof(MMC_READ_CD));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_READ_CD, sizeof(MMC_READ_CD));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_READ_CD);
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.opcode[5] = 0;
|
||||
c.opcode[4] = 0;
|
||||
c.opcode[3] = 0;
|
||||
@ -1316,9 +1448,13 @@ void mmc_perform_opc(struct burn_drive *d)
|
||||
struct command c;
|
||||
|
||||
mmc_function_spy("mmc_perform_opc");
|
||||
|
||||
scsi_init_command(&c, MMC_SEND_OPC, sizeof(MMC_SEND_OPC));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_SEND_OPC, sizeof(MMC_SEND_OPC));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_SEND_OPC);
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.opcode[1] = 1;
|
||||
c.page = NULL;
|
||||
c.dir = NO_TRANSFER;
|
||||
@ -1343,9 +1479,12 @@ int mmc_set_streaming(struct burn_drive *d, int r_speed, int w_speed)
|
||||
r_speed = 0x10000000; /* ~ 2 TB/s */
|
||||
if (w_speed <= 0)
|
||||
w_speed = 0x10000000; /* ~ 2 TB/s */
|
||||
c.retry = 1;
|
||||
scsi_init_command(&c, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING));
|
||||
/*
|
||||
c.oplen = sizeof(MMC_SET_STREAMING);
|
||||
memcpy(c.opcode, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING));
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 28;
|
||||
c.opcode[9] = (c.page->bytes >> 8) & 0xff;
|
||||
@ -1427,9 +1566,12 @@ void mmc_set_speed(struct burn_drive *d, int r, int w)
|
||||
if (w<=0 || w>0xffff)
|
||||
w = 0xffff;
|
||||
|
||||
scsi_init_command(&c, MMC_SET_SPEED, sizeof(MMC_SET_SPEED));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_SET_SPEED, sizeof(MMC_SET_SPEED));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_SET_SPEED);
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.opcode[2] = r >> 8;
|
||||
c.opcode[3] = r & 0xFF;
|
||||
c.opcode[4] = w >> 8;
|
||||
@ -1483,16 +1625,21 @@ static char *mmc_obtain_profile_name(int profile_number)
|
||||
}
|
||||
|
||||
|
||||
/* ts A61201 : found in unfunctional state */
|
||||
void mmc_get_configuration(struct burn_drive *d)
|
||||
/* ts A61201 : found in unfunctional state
|
||||
*/
|
||||
static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
|
||||
{
|
||||
struct buffer buf;
|
||||
int len, cp, descr_len = 0, feature_code, prf_number, only_current = 1;
|
||||
int old_alloc_len;
|
||||
unsigned char *descr, *prf, *up_to, *prf_end;
|
||||
struct command c;
|
||||
int phys_if_std = 0;
|
||||
char *phys_name = "";
|
||||
|
||||
if (*alloc_len < 8)
|
||||
return 0;
|
||||
|
||||
d->current_profile = 0;
|
||||
d->current_profile_text[0] = 0;
|
||||
d->current_is_cd_profile = 0;
|
||||
@ -1502,9 +1649,17 @@ void mmc_get_configuration(struct burn_drive *d)
|
||||
d->current_feat2fh_byte4 = -1;
|
||||
|
||||
mmc_function_spy("mmc_get_configuration");
|
||||
|
||||
scsi_init_command(&c, MMC_GET_CONFIGURATION,
|
||||
sizeof(MMC_GET_CONFIGURATION));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_GET_CONFIGURATION, sizeof(MMC_GET_CONFIGURATION));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_GET_CONFIGURATION);
|
||||
*/
|
||||
c.dxfer_len= *alloc_len;
|
||||
c.retry = 1;
|
||||
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8] = c.dxfer_len & 0xff;
|
||||
c.page = &buf;
|
||||
c.page->sectors = 0;
|
||||
c.page->bytes = 0;
|
||||
@ -1512,11 +1667,13 @@ void mmc_get_configuration(struct burn_drive *d)
|
||||
d->issue_command(d, &c);
|
||||
|
||||
if (c.error)
|
||||
return;
|
||||
len = mmc_four_char_to_int(c.page->data);
|
||||
|
||||
return 0;
|
||||
old_alloc_len = *alloc_len;
|
||||
*alloc_len = len = mmc_four_char_to_int(c.page->data);
|
||||
if (len > old_alloc_len)
|
||||
len = old_alloc_len;
|
||||
if (len < 8 || len > 4096)
|
||||
return;
|
||||
return 0;
|
||||
cp = (c.page->data[6]<<8) | c.page->data[7];
|
||||
d->current_profile = cp;
|
||||
strcpy(d->current_profile_text, mmc_obtain_profile_name(cp));
|
||||
@ -1671,15 +1828,34 @@ void mmc_get_configuration(struct burn_drive *d)
|
||||
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void mmc_get_configuration(struct burn_drive *d)
|
||||
{
|
||||
int alloc_len = 8, ret;
|
||||
|
||||
/* first command execution to learn Allocation Length */
|
||||
ret = mmc_get_configuration_al(d, &alloc_len);
|
||||
/*
|
||||
fprintf(stderr,"LIBBURN_DEBUG: 46h alloc_len = %d , ret = %d\n",
|
||||
alloc_len, ret);
|
||||
*/
|
||||
if (alloc_len > 8 && ret > 0)
|
||||
/* second execution with announced length */
|
||||
mmc_get_configuration_al(d, &alloc_len);
|
||||
}
|
||||
|
||||
|
||||
/* ts A70108 */
|
||||
/* mmc5r03c.pdf 6.24 */
|
||||
int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
|
||||
static int mmc_read_format_capacities_al(struct burn_drive *d,
|
||||
int *alloc_len, int top_wanted)
|
||||
{
|
||||
struct buffer buf;
|
||||
int len, type, score, num_descr, max_score = -2000000000, i, sign = 1;
|
||||
int old_alloc_len;
|
||||
off_t size, num_blocks;
|
||||
struct command c;
|
||||
unsigned char *dpt;
|
||||
@ -1689,18 +1865,26 @@ int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
|
||||
|
||||
mmc_function_spy("mmc_read_format_capacities");
|
||||
|
||||
if (*alloc_len < 4)
|
||||
return 0;
|
||||
|
||||
d->format_descr_type = 3;
|
||||
d->format_curr_max_size = 0;
|
||||
d->format_curr_blsas = 0;
|
||||
d->best_format_type = -1;
|
||||
d->best_format_size = 0;
|
||||
|
||||
scsi_init_command(&c, MMC_READ_FORMAT_CAPACITIES,
|
||||
sizeof(MMC_READ_FORMAT_CAPACITIES));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_READ_FORMAT_CAPACITIES,
|
||||
sizeof(MMC_READ_FORMAT_CAPACITIES));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_READ_FORMAT_CAPACITIES);
|
||||
c.opcode[7]= 0x02;
|
||||
c.opcode[8]= 0x00; /* accept 512 bytes (not more than 260 possible) */
|
||||
*/
|
||||
c.dxfer_len = *alloc_len;
|
||||
c.retry = 1;
|
||||
c.opcode[7]= (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8]= c.dxfer_len & 0xff;
|
||||
c.page = &buf;
|
||||
c.page->sectors = 0;
|
||||
c.page->bytes = 0;
|
||||
@ -1711,6 +1895,12 @@ int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
|
||||
return 0;
|
||||
|
||||
len = c.page->data[3];
|
||||
old_alloc_len = *alloc_len;
|
||||
*alloc_len = len + 4;
|
||||
if (old_alloc_len < 12)
|
||||
return 1;
|
||||
if (len + 4 > old_alloc_len)
|
||||
len = old_alloc_len - 4;
|
||||
if (len < 8)
|
||||
return 0;
|
||||
|
||||
@ -1807,14 +1997,34 @@ int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
|
||||
}
|
||||
|
||||
|
||||
int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
|
||||
{
|
||||
int alloc_len = 4, ret;
|
||||
|
||||
ret = mmc_read_format_capacities_al(d, &alloc_len, top_wanted);
|
||||
/*
|
||||
fprintf(stderr,"LIBBURN_DEBUG: 23h alloc_len = %d , ret = %d\n",
|
||||
alloc_len, ret);
|
||||
*/
|
||||
if (alloc_len >= 12 && ret > 0)
|
||||
ret = mmc_read_format_capacities_al(d, &alloc_len, top_wanted);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void mmc_sync_cache(struct burn_drive *d)
|
||||
{
|
||||
struct command c;
|
||||
|
||||
mmc_function_spy("mmc_sync_cache");
|
||||
|
||||
scsi_init_command(&c, MMC_SYNC_CACHE, sizeof(MMC_SYNC_CACHE));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_SYNC_CACHE, sizeof(MMC_SYNC_CACHE));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_SYNC_CACHE);
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.page = NULL;
|
||||
c.dir = NO_TRANSFER;
|
||||
|
||||
@ -1834,12 +2044,21 @@ int mmc_read_buffer_capacity(struct burn_drive *d)
|
||||
struct buffer buf;
|
||||
struct command c;
|
||||
unsigned char *data;
|
||||
int alloc_len = 12;
|
||||
|
||||
mmc_function_spy("mmc_read_buffer_capacity");
|
||||
|
||||
scsi_init_command(&c, MMC_READ_BUFFER_CAPACITY,
|
||||
sizeof(MMC_READ_BUFFER_CAPACITY));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_READ_BUFFER_CAPACITY,
|
||||
sizeof(MMC_READ_BUFFER_CAPACITY));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_READ_BUFFER_CAPACITY);
|
||||
*/
|
||||
c.dxfer_len = alloc_len;
|
||||
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8] = c.dxfer_len & 0xff;
|
||||
c.retry = 1;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
c.page->sectors = 0;
|
||||
@ -1889,9 +2108,13 @@ int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
|
||||
int full_format_type = 0x00; /* Full Format (or 0x10 for DVD-RW ?) */
|
||||
|
||||
mmc_function_spy("mmc_format_unit");
|
||||
c.retry = 1;
|
||||
|
||||
scsi_init_command(&c, MMC_FORMAT_UNIT, sizeof(MMC_FORMAT_UNIT));
|
||||
/*
|
||||
c.oplen = sizeof(MMC_FORMAT_UNIT);
|
||||
memcpy(c.opcode, MMC_FORMAT_UNIT, sizeof(MMC_FORMAT_UNIT));
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 12;
|
||||
c.page->sectors = 0;
|
||||
@ -2099,10 +2322,11 @@ unsuitable_media:;
|
||||
|
||||
|
||||
/* ts A61225 */
|
||||
int mmc_get_write_performance(struct burn_drive *d)
|
||||
static int mmc_get_write_performance_al(struct burn_drive *d,
|
||||
int *alloc_len, int *max_descr)
|
||||
{
|
||||
struct buffer buf;
|
||||
int len, i, b, max_descr, num_descr, ret;
|
||||
int len, i, b, num_descr, ret, old_alloc_len;
|
||||
int exact_bit, read_speed, write_speed;
|
||||
/* if this call delivers usable data then they should override
|
||||
previously recorded min/max speed and not compete with them */
|
||||
@ -2121,19 +2345,29 @@ int mmc_get_write_performance(struct burn_drive *d)
|
||||
if (d->current_profile <= 0)
|
||||
mmc_get_configuration(d);
|
||||
|
||||
if (*alloc_len < 8)
|
||||
return 0;
|
||||
|
||||
scsi_init_command(&c, MMC_GET_PERFORMANCE,
|
||||
sizeof(MMC_GET_PERFORMANCE));
|
||||
/*
|
||||
memcpy(c.opcode, MMC_GET_PERFORMANCE, sizeof(MMC_GET_PERFORMANCE));
|
||||
c.oplen = sizeof(MMC_GET_PERFORMANCE);
|
||||
*/
|
||||
/* ts A70519 : now controlled externally
|
||||
max_descr = ( BUFFER_SIZE - 8 ) / 16 - 1;
|
||||
*/
|
||||
|
||||
/* >>> future: maintain a list of write descriptors
|
||||
if (max_descr > d->max_write_descr - d->num_write_descr)
|
||||
max_descr = d->max_write_descr;
|
||||
*/
|
||||
c.dxfer_len = *alloc_len;
|
||||
|
||||
c.opcode[8] = ( max_descr >> 8 ) & 0xff;
|
||||
c.opcode[9] = ( max_descr >> 0 ) & 0xff;
|
||||
c.opcode[8] = ( *max_descr >> 8 ) & 0xff;
|
||||
c.opcode[9] = ( *max_descr >> 0 ) & 0xff;
|
||||
c.opcode[10] = 3;
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(MMC_GET_PERFORMANCE);
|
||||
c.page = &buf;
|
||||
c.page->sectors = 0;
|
||||
c.page->bytes = 0;
|
||||
@ -2141,17 +2375,24 @@ int mmc_get_write_performance(struct burn_drive *d)
|
||||
d->issue_command(d, &c);
|
||||
if (c.error)
|
||||
return 0;
|
||||
len = (c.page->data[0] << 24)
|
||||
+ (c.page->data[1] << 16)
|
||||
+ (c.page->data[2] << 8)
|
||||
+ c.page->data[3];
|
||||
len = mmc_four_char_to_int(c.page->data);
|
||||
old_alloc_len = *alloc_len;
|
||||
*alloc_len = len + 4;
|
||||
if (len + 4 > old_alloc_len)
|
||||
len = old_alloc_len - 4;
|
||||
num_descr = ( *alloc_len - 8 ) / 16;
|
||||
if (*max_descr == 0) {
|
||||
*max_descr = num_descr;
|
||||
return 1;
|
||||
}
|
||||
if (old_alloc_len < 16)
|
||||
return 1;
|
||||
if (len < 12)
|
||||
return 0;
|
||||
|
||||
pd = c.page->data;
|
||||
num_descr = ( len - 4 ) / 16;
|
||||
if (num_descr > max_descr)
|
||||
num_descr = max_descr;
|
||||
if (num_descr > *max_descr)
|
||||
num_descr = *max_descr;
|
||||
for (i = 0; i < num_descr; i++) {
|
||||
exact_bit = !!(pd[8 + i*16] & 2);
|
||||
end_lba = read_speed = write_speed = 0;
|
||||
@ -2214,6 +2455,24 @@ int mmc_get_write_performance(struct burn_drive *d)
|
||||
}
|
||||
|
||||
|
||||
int mmc_get_write_performance(struct burn_drive *d)
|
||||
{
|
||||
int alloc_len = 8, max_descr = 0, ret;
|
||||
|
||||
/* first command execution to learn number of descriptors and
|
||||
dxfer_len */
|
||||
ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr);
|
||||
/*
|
||||
fprintf(stderr,"LIBBURN_DEBUG: ACh alloc_len = %d , ret = %d\n",
|
||||
alloc_len, ret);
|
||||
*/
|
||||
if (max_descr > 0 && ret > 0)
|
||||
/* second execution with announced length */
|
||||
ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61021 : the mmc specific part of sg.c:enumerate_common()
|
||||
*/
|
||||
int mmc_setup_drive(struct burn_drive *d)
|
||||
|
@ -11,19 +11,22 @@
|
||||
#include "options.h"
|
||||
|
||||
/* spc command set */
|
||||
static char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
|
||||
static char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
|
||||
static char SBC_START_UNIT[] = { 0x1b, 0, 0, 0, 1, 0 };
|
||||
static unsigned char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
|
||||
static unsigned char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
|
||||
static unsigned char SBC_START_UNIT[] = { 0x1b, 0, 0, 0, 1, 0 };
|
||||
|
||||
void sbc_load(struct burn_drive *d)
|
||||
{
|
||||
struct command c;
|
||||
|
||||
scsi_init_command(&c, SBC_LOAD, sizeof(SBC_LOAD));
|
||||
/*
|
||||
memcpy(c.opcode, SBC_LOAD, sizeof(SBC_LOAD));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SBC_LOAD);
|
||||
c.dir = NO_TRANSFER;
|
||||
c.page = NULL;
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.dir = NO_TRANSFER;
|
||||
d->issue_command(d, &c);
|
||||
spc_wait_unit_attention(d, 60);
|
||||
}
|
||||
@ -32,11 +35,13 @@ void sbc_eject(struct burn_drive *d)
|
||||
{
|
||||
struct command c;
|
||||
|
||||
c.page = NULL;
|
||||
scsi_init_command(&c, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
||||
/*
|
||||
memcpy(c.opcode, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
||||
c.oplen = 1;
|
||||
c.oplen = sizeof(SBC_UNLOAD);
|
||||
c.page = NULL;
|
||||
*/
|
||||
c.page = NULL;
|
||||
c.dir = NO_TRANSFER;
|
||||
d->issue_command(d, &c);
|
||||
}
|
||||
@ -46,11 +51,14 @@ int sbc_start_unit(struct burn_drive *d)
|
||||
{
|
||||
struct command c;
|
||||
|
||||
scsi_init_command(&c, SBC_START_UNIT, sizeof(SBC_START_UNIT));
|
||||
/*
|
||||
memcpy(c.opcode, SBC_START_UNIT, sizeof(SBC_START_UNIT));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SBC_START_UNIT);
|
||||
c.dir = NO_TRANSFER;
|
||||
c.page = NULL;
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.dir = NO_TRANSFER;
|
||||
d->issue_command(d, &c);
|
||||
return (c.error==0);
|
||||
}
|
||||
|
148
libburn/spc.c
148
libburn/spc.c
@ -29,7 +29,8 @@ extern struct libdax_msgs *libdax_messenger;
|
||||
|
||||
|
||||
/* spc command set */
|
||||
static unsigned char SPC_INQUIRY[] = { 0x12, 0, 0, 0, 255, 0 };
|
||||
/* ts A70519 : allocation length byte 3+4 was 0,255 */
|
||||
static unsigned char SPC_INQUIRY[] = { 0x12, 0, 0, 0, 36, 0 };
|
||||
|
||||
/*static char SPC_TEST[]={0,0,0,0,0,0};*/
|
||||
static unsigned char SPC_PREVENT[] = { 0x1e, 0, 0, 0, 1, 0 };
|
||||
@ -40,14 +41,35 @@ static unsigned char SPC_MODE_SELECT[] =
|
||||
static unsigned char SPC_REQUEST_SENSE[] = { 0x03, 0, 0, 0, 18, 0 };
|
||||
static unsigned char SPC_TEST_UNIT_READY[] = { 0x00, 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
/* ts A70519 : An initializer for the abstract SCSI command structure */
|
||||
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen)
|
||||
{
|
||||
if (oplen > 16)
|
||||
return 0;
|
||||
memcpy(c->opcode, opcode, oplen);
|
||||
c->oplen = oplen;
|
||||
c->dir = NO_TRANSFER;
|
||||
c->dxfer_len = -1;
|
||||
memset(c->sense, 0, sizeof(c->sense));
|
||||
c->error = 0;
|
||||
c->retry = 0;
|
||||
c->page = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq)
|
||||
{
|
||||
struct command c;
|
||||
|
||||
c.retry = 0;
|
||||
scsi_init_command(&c, SPC_TEST_UNIT_READY,sizeof(SPC_TEST_UNIT_READY));
|
||||
/*
|
||||
c.oplen = sizeof(SPC_TEST_UNIT_READY);
|
||||
memcpy(c.opcode, SPC_TEST_UNIT_READY, sizeof(SPC_TEST_UNIT_READY));
|
||||
c.page = NULL;
|
||||
*/
|
||||
c.retry = 0;
|
||||
c.dir = NO_TRANSFER;
|
||||
d->issue_command(d, &c);
|
||||
if (c.error) {
|
||||
@ -68,7 +90,7 @@ int spc_test_unit_ready(struct burn_drive *d)
|
||||
|
||||
|
||||
/* ts A70315 */
|
||||
/** Wait until the drive state becomes clear in or until max_usec elapsed */
|
||||
/** Wait until the drive state becomes clear or until max_usec elapsed */
|
||||
int spc_wait_unit_attention(struct burn_drive *d, int max_sec)
|
||||
{
|
||||
int i, ret, key, asc, ascq;
|
||||
@ -89,9 +111,14 @@ void spc_request_sense(struct burn_drive *d, struct buffer *buf)
|
||||
{
|
||||
struct command c;
|
||||
|
||||
scsi_init_command(&c, SPC_REQUEST_SENSE, sizeof(SPC_REQUEST_SENSE));
|
||||
c.retry = 0;
|
||||
/*
|
||||
c.oplen = sizeof(SPC_REQUEST_SENSE);
|
||||
memcpy(c.opcode, SPC_REQUEST_SENSE, sizeof(SPC_REQUEST_SENSE));
|
||||
*/
|
||||
c.dxfer_len= c.opcode[4];
|
||||
c.retry = 0;
|
||||
c.page = buf;
|
||||
c.page->sectors = 0;
|
||||
c.page->bytes = 0;
|
||||
@ -113,24 +140,29 @@ void spc_inquiry(struct burn_drive *d)
|
||||
struct burn_scsi_inquiry_data *id;
|
||||
struct command c;
|
||||
|
||||
scsi_init_command(&c, SPC_INQUIRY, sizeof(SPC_INQUIRY));
|
||||
/*
|
||||
memcpy(c.opcode, SPC_INQUIRY, sizeof(SPC_INQUIRY));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SPC_INQUIRY);
|
||||
*/
|
||||
c.dxfer_len= (c.opcode[3] << 8) | c.opcode[4];
|
||||
c.retry = 1;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
c.page->sectors = 0;
|
||||
c.dir = FROM_DRIVE;
|
||||
d->issue_command(d, &c);
|
||||
|
||||
id = (struct burn_scsi_inquiry_data *)d->idata;
|
||||
id->vendor[8] = 0;
|
||||
id->product[16] = 0;
|
||||
id->revision[4] = 0;
|
||||
|
||||
memset(id->vendor, 0, 9);
|
||||
memset(id->product, 0, 17);
|
||||
memset(id->revision, 0, 5);
|
||||
if (c.error) {
|
||||
id->valid = -1;
|
||||
return;
|
||||
}
|
||||
memcpy(id->vendor, c.page->data + 8, 8);
|
||||
memcpy(id->product, c.page->data + 16, 16);
|
||||
memcpy(id->revision, c.page->data + 32, 4);
|
||||
|
||||
id->valid = 1;
|
||||
return;
|
||||
}
|
||||
@ -139,10 +171,13 @@ void spc_prevent(struct burn_drive *d)
|
||||
{
|
||||
struct command c;
|
||||
|
||||
scsi_init_command(&c, SPC_PREVENT, sizeof(SPC_PREVENT));
|
||||
/*
|
||||
memcpy(c.opcode, SPC_PREVENT, sizeof(SPC_PREVENT));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SPC_PREVENT);
|
||||
c.page = NULL;
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.dir = NO_TRANSFER;
|
||||
d->issue_command(d, &c);
|
||||
}
|
||||
@ -151,19 +186,27 @@ void spc_allow(struct burn_drive *d)
|
||||
{
|
||||
struct command c;
|
||||
|
||||
scsi_init_command(&c, SPC_ALLOW, sizeof(SPC_ALLOW));
|
||||
/*
|
||||
memcpy(c.opcode, SPC_ALLOW, sizeof(SPC_ALLOW));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SPC_ALLOW);
|
||||
c.page = NULL;
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.dir = NO_TRANSFER;
|
||||
d->issue_command(d, &c);
|
||||
}
|
||||
|
||||
void spc_sense_caps(struct burn_drive *d)
|
||||
/*
|
||||
ts A70518 : Do not call with *alloc_len < 8
|
||||
*/
|
||||
/** flag&1= do only inquire alloc_len */
|
||||
static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
|
||||
{
|
||||
struct buffer buf;
|
||||
struct scsi_mode_data *m;
|
||||
int size, page_length, num_write_speeds = 0, i, speed, ret;
|
||||
int old_alloc_len, was_error = 0;
|
||||
unsigned char *page;
|
||||
struct command c;
|
||||
struct burn_speed_descriptor *sd;
|
||||
@ -171,18 +214,30 @@ void spc_sense_caps(struct burn_drive *d)
|
||||
/* ts A61225 : 1 = report about post-MMC-1 speed descriptors */
|
||||
static int speed_debug = 0;
|
||||
|
||||
if (*alloc_len < 8)
|
||||
return 0;
|
||||
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||
/*
|
||||
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SPC_MODE_SENSE);
|
||||
*/
|
||||
c.dxfer_len = *alloc_len;
|
||||
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8] = c.dxfer_len & 0xff;
|
||||
c.retry = 1;
|
||||
c.opcode[2] = 0x2A;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
c.page->sectors = 0;
|
||||
c.dir = FROM_DRIVE;
|
||||
d->issue_command(d, &c);
|
||||
if (c.error)
|
||||
if (c.error) {
|
||||
memset(&buf, 0, sizeof(buf));
|
||||
d->mdata->valid = -1;
|
||||
was_error = 1;
|
||||
}
|
||||
|
||||
size = c.page->data[0] * 256 + c.page->data[1];
|
||||
m = d->mdata;
|
||||
@ -195,6 +250,14 @@ void spc_sense_caps(struct burn_drive *d)
|
||||
set of speed descriptors. In MMC-5 E.11 it is declared "legacy".
|
||||
*/
|
||||
page_length = page[1];
|
||||
old_alloc_len = *alloc_len;
|
||||
*alloc_len = page_length + 8;
|
||||
if (flag & 1)
|
||||
return !was_error;
|
||||
if (page_length + 8 > old_alloc_len)
|
||||
page_length = old_alloc_len - 8;
|
||||
if (page_length < 22)
|
||||
return 0;
|
||||
|
||||
m->valid = 0;
|
||||
burn_mdata_free_subs(m);
|
||||
@ -253,7 +316,7 @@ void spc_sense_caps(struct burn_drive *d)
|
||||
0x0002013c,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, 0, 0);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_write_speeds; i++) {
|
||||
@ -297,6 +360,24 @@ try_mmc_get_performance:;
|
||||
fprintf(stderr,
|
||||
"LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n",
|
||||
m->min_write_speed, m->max_write_speed);
|
||||
return !was_error;
|
||||
}
|
||||
|
||||
|
||||
void spc_sense_caps(struct burn_drive *d)
|
||||
{
|
||||
int alloc_len, start_len = 22, ret;
|
||||
|
||||
/* first command execution to learn Allocation Length */
|
||||
alloc_len = start_len;
|
||||
ret = spc_sense_caps_al(d, &alloc_len, 1);
|
||||
/*
|
||||
fprintf(stderr,"LIBBURN_DEBUG: 5Ah alloc_len = %d , ret = %d\n",
|
||||
alloc_len, ret);
|
||||
*/
|
||||
if (alloc_len >= start_len && ret > 0)
|
||||
/* second execution with announced length */
|
||||
spc_sense_caps_al(d, &alloc_len, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -304,13 +385,19 @@ void spc_sense_error_params(struct burn_drive *d)
|
||||
{
|
||||
struct buffer buf;
|
||||
struct scsi_mode_data *m;
|
||||
int size;
|
||||
int size, alloc_len = 12 ;
|
||||
unsigned char *page;
|
||||
struct command c;
|
||||
|
||||
scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||
/*
|
||||
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SPC_MODE_SENSE);
|
||||
*/
|
||||
c.dxfer_len = alloc_len;
|
||||
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8] = c.dxfer_len & 0xff;
|
||||
c.retry = 1;
|
||||
c.opcode[2] = 0x01;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
@ -332,9 +419,12 @@ void spc_select_error_params(struct burn_drive *d,
|
||||
struct buffer buf;
|
||||
struct command c;
|
||||
|
||||
scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||
/*
|
||||
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SPC_MODE_SELECT);
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.opcode[8] = 8 + 2 + d->mdata->retry_page_length;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
@ -363,7 +453,7 @@ void spc_sense_write_params(struct burn_drive *d)
|
||||
{
|
||||
struct buffer buf;
|
||||
struct scsi_mode_data *m;
|
||||
int size, dummy;
|
||||
int size, dummy, alloc_len = 10;
|
||||
unsigned char *page;
|
||||
struct command c;
|
||||
|
||||
@ -371,9 +461,15 @@ void spc_sense_write_params(struct burn_drive *d)
|
||||
/* a ssert(d->mdata->cdr_write || d->mdata->cdrw_write ||
|
||||
d->mdata->dvdr_write || d->mdata->dvdram_write); */
|
||||
|
||||
scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||
/*
|
||||
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SPC_MODE_SENSE);
|
||||
*/
|
||||
c.dxfer_len = alloc_len;
|
||||
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||
c.opcode[8] = c.dxfer_len & 0xff;
|
||||
c.retry = 1;
|
||||
c.opcode[2] = 0x05;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
@ -428,9 +524,12 @@ void spc_select_write_params(struct burn_drive *d,
|
||||
o->block_type,spc_block_type(o->block_type));
|
||||
*/
|
||||
|
||||
scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||
/*
|
||||
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SPC_MODE_SELECT);
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.opcode[8] = 8 + 2 + d->mdata->write_page_length;
|
||||
c.page = &buf;
|
||||
c.page->bytes = 0;
|
||||
@ -488,9 +587,12 @@ void spc_probe_write_modes(struct burn_drive *d)
|
||||
try_block_type = useable_block_type;
|
||||
last_try= 1;
|
||||
}
|
||||
scsi_init_command(&c, SPC_MODE_SELECT,sizeof(SPC_MODE_SELECT));
|
||||
/*
|
||||
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SPC_MODE_SELECT);
|
||||
*/
|
||||
c.retry = 1;
|
||||
c.opcode[8] = 8 + 2 + 0x32;
|
||||
c.page = &buf;
|
||||
|
||||
|
@ -55,4 +55,7 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
|
||||
int scsi_notify_error(struct burn_drive *, struct command *c,
|
||||
unsigned char *sense, int senselen, int flag);
|
||||
|
||||
/* ts A70519 */
|
||||
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen);
|
||||
|
||||
#endif /*__SPC*/
|
||||
|
@ -128,9 +128,14 @@ void toc_find_modes(struct burn_drive *d)
|
||||
if (e && !(e->control & 4)) {
|
||||
t->mode = BURN_AUDIO;
|
||||
} else {
|
||||
|
||||
t->mode = BURN_MODE1;
|
||||
/* ts A70519 : this does not work with Linux 2.4 USB because one cannot
|
||||
predict the exact dxfer_size without knowing the sector type.
|
||||
mem.sectors = 1;
|
||||
d->read_sectors(d, lba, mem.sectors, &o, &mem);
|
||||
t->mode = sector_identify(mem.data);
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,7 @@ struct command
|
||||
unsigned char opcode[16];
|
||||
int oplen;
|
||||
int dir;
|
||||
int dxfer_len;
|
||||
unsigned char sense[128];
|
||||
int error;
|
||||
int retry;
|
||||
|
Loading…
Reference in New Issue
Block a user