1 /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
2 
3 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
4    Copyright (c) 2006 - 2016 Thomas Schmitt <scdbackup@gmx.net>
5    Provided under GPL version 2 or later.
6 */
7 
8 #ifdef HAVE_CONFIG_H
9 #include "../config.h"
10 #endif
11 
12 
13 /* ts A61009 */
14 /* #include <a ssert.h> */
15 
16 #include <stdio.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <stdlib.h>
20 #include <sys/time.h>
21 #include <pthread.h>
22 #include <ctype.h>
23 
24 /* ts B41126 : O_BINARY is needed for Cygwin but undefined elsewhere */
25 #ifndef O_BINARY
26 #define O_BINARY 0
27 #endif
28 
29 #include "error.h"
30 #include "sector.h"
31 #include "libburn.h"
32 #include "transport.h"
33 #include "mmc.h"
34 #include "spc.h"
35 #include "drive.h"
36 #include "debug.h"
37 #include "toc.h"
38 #include "structure.h"
39 #include "options.h"
40 #include "util.h"
41 #include "init.h"
42 
43 
44 /* ts A70223 : in init.c */
45 extern int burn_support_untested_profiles;
46 
47 static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len);
48 
49 
50 #ifdef Libburn_log_in_and_out_streaM
51 /* <<< ts A61031 */
52 #include <sys/types.h>
53 #include <sys/stat.h>
54 #include <fcntl.h>
55 #endif /* Libburn_log_in_and_out_streaM */
56 
57 
58 /* ts A61005 */
59 #include "libdax_msgs.h"
60 extern struct libdax_msgs *libdax_messenger;
61 
62 
63 /* ts A61219 : Based on knowledge from dvd+rw-tools-7.0 and mmc5r03c.pdf */
64 #define Libburn_support_dvd_plus_rW 1
65 
66 /* ts A61229 */
67 #define Libburn_support_dvd_minusrw_overW 1
68 
69 /* ts A70112 */
70 /* ts A80410 : applies to BD-RE too */
71 #define Libburn_support_dvd_raM 1
72 
73 /* ts A70129 */
74 #define Libburn_support_dvd_r_seQ 1
75 
76 /* ts A70306 */
77 #define Libburn_support_dvd_plus_R 1
78 
79 /* ts A70509 : handling 0x41 as read-only type */
80 #define Libburn_support_bd_r_readonlY 1
81 
82 /* ts A81208 */
83 #define Libburn_support_bd_plus_r_srM 1
84 
85 
86 /* ts A80410 : <<< Dangerous experiment: Pretend that DVD-RAM is BD-RE
87  # define Libburn_dvd_ram_as_bd_rE yes
88 */
89 /* ts A80509 : <<< Experiment: pretend that DVD-ROM and CD-ROM are other media
90                    like BD-ROM (0x40), BD-R seq (0x41), BD-R random (0x42)
91  # define Libburn_rom_as_profilE 0x40
92 */
93 
94 
95 /* ts A80425 : Prevents command FORMAT UNIT for DVD-RAM or BD-RE.
96                Useful only to test the selection of format descriptors without
97                actually formatting the media.
98  # define Libburn_do_not_format_dvd_ram_or_bd_rE 1
99 */
100 
101 
102 /* ts A90603 : Simulate the command restrictions of an old MMC-1 drive
103  # define Libisofs_simulate_old_mmc1_drivE 1
104 */
105 
106 
107 /* DVD/BD progress report:
108    ts A61219 : It seems to work with a used (i.e. thoroughly formatted) DVD+RW.
109                Error messages of class DEBUG appear because of inability to
110                read TOC or track info. Nevertheless, the written images verify.
111    ts A61220 : Burned to a virgin DVD+RW by help of new mmc_format_unit()
112                (did not test whether it would work without). Burned to a
113                not completely formatted DVD+RW. (Had worked before without
114                mmc_format_unit() but i did not exceed the formatted range
115                as reported by dvd+rw-mediainfo.)
116    ts A61221 : Speed setting now works for both of my drives. The according
117                functions in dvd+rw-tools are a bit intimidating to the reader.
118                I hope it is possible to leave much of this to the drive.
119                And if it fails ... well, it's only speed setting. :))
120    ts A61229 : Burned to several DVD-RW formatted to mode Restricted Overwrite
121                by dvd+rw-format. Needs Libburn_support_dvd_minusrw_overW.
122    ts A61230 : Other than growisofs, libburn does not send a mode page 5 for
123                such DVD-RW (which the MMC-5 standard does deprecate) and it
124                really seems to work without such a page.
125    ts A70101 : Formatted DVD-RW media. Success is varying with media, but
126                dvd+rw-format does not do better with the same media.
127    ts A70112 : Support for writing to DVD-RAM.
128    ts A70130 : Burned a first non-multi sequential DVD-RW. Feature 0021h
129                Incremental Recording vanishes after that and media thus gets
130                not recognized as suitable any more.
131                After a run with -multi another disc still offers 0021h .
132                dvd+rw-mediainfo shows two tracks. The second, an afio archive
133                is readable by afio. Third and forth veryfy too. Suddenly
134                dvd+rw-mediainfo sees lba 0 with track 2. But #2 still verifies
135                if one knows its address.
136    ts A70203 : DVD-RW need to get blanked fully. Then feature 0021h persists.
137                Meanwhile Incremental streaming is supported like CD TAO:
138                with unpredicted size, multi-track, multi-session.
139    ts A70205 : Beginning to implement DVD-R[W] DAO : single track and session,
140                size prediction mandatory.
141    ts A70208 : Finally made tests with DVD-R. Worked exactly as new DVD-RW.
142    ts A70306 : Implemented DVD+R (always -multi for now)
143    ts A70330 : Allowed finalizing of DVD+R.
144    ts A80228 : Made DVD+R/DL support official after nightmorph reported success
145                in http://libburnia-project.org/ticket/13
146    ts A80416 : drive->do_stream_recording brings DVD-RAM to full nominal
147                writing speed at cost of no defect management.
148    ts A80416 : Giulio Orsero reports success with BD-RE writing. With
149                drive->do_stream_recording it does full nominal speed.
150    ts A80506 : Giulio Orsero reports success with BD-RE formatting.
151                BD-RE is now an officially supported profile.
152    ts A81209 : The first two sessions have been written to BD-R SRM
153                (auto formatted without Defect Management).
154    ts A90107 : BD-R is now supported media type
155 */
156 
157 /* ts A70519 : With MMC commands of data direction FROM_DRIVE:
158                Made struct command.dxfer_len equal to Allocation Length
159                of MMC commands. Made sure that not more bytes are allowed
160                for transfer than there are available.
161 */
162 
163 
164 /* ts A70711 Trying to keep writing from clogging the SCSI driver due to
165              full buffer at burner drive: 0=waiting disabled, 1=enabled
166              These are only defaults which can be overwritten by
167              burn_drive_set_buffer_waiting()
168 */
169 #define Libburn_wait_for_buffer_freE          0
170 #define Libburn_wait_for_buffer_min_useC        10000
171 #define Libburn_wait_for_buffer_max_useC       100000
172 #define Libburn_wait_for_buffer_tio_seC     120
173 #define Libburn_wait_for_buffer_min_perC     65
174 #define Libburn_wait_for_buffer_max_perC     95
175 
176 /* ts B31107 The minimum values to be applied if maximum read speed is
177              requested. Some drives tell only the currently set speed and
178              thus cannot be made faster by using the highest told value.
179              (The fractions get added or subtracted to yield an integer
180               number on the safe side of the intended limit.)
181 */
182 #define Libburn_cd_max_read_speeD   (52 *  150)
183 #define Libburn_dvd_max_read_speeD  (24 * 1385)
184 #define Libburn_bd_max_read_speeD   (20 * 4495.625 + 0.5)
185 
186 /* ts B31114 The maximum values for minimum speed
187 */
188 #define Libburn_cd_min_read_speeD   ( 1 *  150)
189 #define Libburn_dvd_min_read_speeD  ( 1 * 1385)
190 #define Libburn_bd_min_read_speeD   ( 1 * 4495.625 - 0.625)
191 
192 
193 static unsigned char MMC_GET_MSINFO[] =
194 	{ 0x43, 0, 1, 0, 0, 0, 0, 16, 0, 0 };
195 static unsigned char MMC_GET_TOC[] = { 0x43, 2, 2, 0, 0, 0, 0, 16, 0, 0 };
196 static unsigned char MMC_GET_TOC_FMT0[] = { 0x43, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
197 static unsigned char MMC_GET_ATIP[] = { 0x43, 2, 4, 0, 0, 0, 0, 16, 0, 0 };
198 static unsigned char MMC_GET_LEADTEXT[] = { 0x43, 2, 5, 0, 0, 0, 0, 4, 0, 0 };
199 static unsigned char MMC_GET_DISC_INFO[] =
200 	{ 0x51, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
201 static unsigned char MMC_READ_CD[] = { 0xBE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
202 static unsigned char MMC_BLANK[] = { 0xA1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
203 static unsigned char MMC_SEND_OPC[] = { 0x54, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
204 static unsigned char MMC_SET_SPEED[] =
205 	{ 0xBB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
206 static unsigned char MMC_WRITE_12[] =
207 	{ 0xAA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
208 static unsigned char MMC_WRITE_10[] = { 0x2A, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
209 
210 /* ts A61201 : inserted 0, before 16, */
211 static unsigned char MMC_GET_CONFIGURATION[] =
212 	{ 0x46, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
213 
214 static unsigned char MMC_SYNC_CACHE[] = { 0x35, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
215 static unsigned char MMC_GET_EVENT[] = { 0x4A, 1, 0, 0, 0x7e, 0, 0, 0, 8, 0 };
216 static unsigned char MMC_CLOSE[] = { 0x5B, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
217 static unsigned char MMC_TRACK_INFO[] = { 0x52, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
218 
219 static unsigned char MMC_SEND_CUE_SHEET[] =
220 	{ 0x5D, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
221 
222 /* ts A61023 : get size and free space of drive buffer */
223 static unsigned char MMC_READ_BUFFER_CAPACITY[] =
224 	{ 0x5C, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
225 
226 /* ts A61219 : format DVD+RW (and various others) */
227 static unsigned char MMC_FORMAT_UNIT[] = { 0x04, 0x11, 0, 0, 0, 0 };
228 
229 /* ts A61221 :
230    To set speed for DVD media (0xBB is for CD but works on my LG GSA drive) */
231 static unsigned char MMC_SET_STREAMING[] =
232 	{ 0xB6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
233 
234 /* ts A61225 :
235    To obtain write speed descriptors (command can do other things too) */
236 static unsigned char MMC_GET_PERFORMANCE[] =
237 	{ 0xAC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
238 
239 /* ts A70108 : To obtain info about drive and media formatting opportunities */
240 static unsigned char MMC_READ_FORMAT_CAPACITIES[] =
241 	{ 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0};
242 
243 /* ts A70205 : To describe the layout of a DVD-R[W] DAO session */
244 static unsigned char MMC_RESERVE_TRACK[] =
245 	{ 0x53, 0, 0, 0, 0, 0, 0, 0, 0, 0};
246 
247 /* ts A70812 : Read data sectors (for types with 2048 bytes/sector only) */
248 static unsigned char MMC_READ_10[] =
249 	{ 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0};
250 
251 /* ts A81210 : Determine the upper limit of readable data size */
252 static unsigned char MMC_READ_CAPACITY[] =
253 	{ 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0};
254 
255 /* ts A90903 : Obtain media type specific information. E.g. manufacturer.
256 */
257 static unsigned char MMC_READ_DISC_STRUCTURE[] =
258 	{ 0xAD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
259 
260 /* ts B21125 : An alternative to BEh READ CD
261 */
262 static unsigned char MMC_READ_CD_MSF[] =
263 	{ 0xB9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
264 
265 static int mmc_function_spy_do_tell = 0;
266 
mmc_function_spy(struct burn_drive * d,char * text)267 int mmc_function_spy(struct burn_drive *d, char * text)
268 {
269 	if (mmc_function_spy_do_tell)
270 		fprintf(stderr,"libburn: experimental: mmc_function_spy: %s\n",
271 			text);
272 	if (d == NULL)
273 		return 1;
274 	if (d->drive_role != 1) {
275 		char msg[4096];
276 
277 		sprintf(msg, "Emulated drive caught in SCSI adapter \"%s\"",
278 				text);
279 		libdax_msgs_submit(libdax_messenger, d->global_index,
280 				0x0002014c,
281 				LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
282 				msg, 0, 0);
283 		d->cancel = 1;
284 		return 0;
285 	}
286 	return 1;
287 }
288 
mmc_function_spy_ctrl(int do_tell)289 int mmc_function_spy_ctrl(int do_tell)
290 {
291 	mmc_function_spy_do_tell= !!do_tell;
292 	return 1;
293 }
294 
295 
296 /* ts A70201 */
mmc_four_char_to_int(unsigned char * data)297 int mmc_four_char_to_int(unsigned char *data)
298 {
299 	return (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
300 }
301 
302 
303 /* ts A70201 */
mmc_int_to_four_char(unsigned char * data,int num)304 int mmc_int_to_four_char(unsigned char *data, int num)
305 {
306 	data[0] = (num >> 24) & 0xff;
307 	data[1] = (num >> 16) & 0xff;
308 	data[2] = (num >> 8) & 0xff;
309 	data[3] = num & 0xff;
310 	return 1;
311 }
312 
313 
314 static int mmc_start_for_bit0 = 0;
315 
316 /* @param flag bit0= the calling function should need no START UNIT.
317                      (Handling depends on mmc_start_for_bit0)
318 */
mmc_start_if_needed(struct burn_drive * d,int flag)319 int mmc_start_if_needed(struct burn_drive *d, int flag)
320 {
321 	if (!d->is_stopped)
322 		return 2;
323 	if ((flag & 1) && !mmc_start_for_bit0)
324 		return 2;
325 	d->start_unit(d);
326 	d->is_stopped = 0;
327 	return 1;
328 }
329 
330 
mmc_send_cue_sheet(struct burn_drive * d,struct cue_sheet * s)331 int mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
332 {
333 	struct buffer *buf = NULL;
334 	struct command *c;
335 
336 	c = &(d->casual_command);
337 	mmc_start_if_needed(d, 0);
338 	if (mmc_function_spy(d, "mmc_send_cue_sheet") <= 0)
339 		return 0;
340 	BURN_ALLOC_MEM_VOID(buf, struct buffer, 1);
341 	scsi_init_command(c, MMC_SEND_CUE_SHEET, sizeof(MMC_SEND_CUE_SHEET));
342 	c->retry = 1;
343 	c->page = buf;
344 	c->page->bytes = s->count * 8;
345 	c->page->sectors = 0;
346 	c->opcode[6] = (c->page->bytes >> 16) & 0xFF;
347 	c->opcode[7] = (c->page->bytes >> 8) & 0xFF;
348 	c->opcode[8] = c->page->bytes & 0xFF;
349 	c->dir = TO_DRIVE;
350 	memcpy(c->page->data, s->data, c->page->bytes);
351 	d->issue_command(d, c);
352 ex:;
353 	BURN_FREE_MEM(buf);
354 	if (c->error) {
355 		d->cancel = 1;
356 		scsi_notify_error(d, c, c->sense, 18, 2);
357 	}
358 	return !c->error;
359 }
360 
361 
362 /* ts A70205 : Announce size of a DVD-R[W] DAO session.
363    @param size The size in bytes to be announced to the drive.
364                It will get rounded up to align to 32 KiB.
365 */
mmc_reserve_track(struct burn_drive * d,off_t size)366 int mmc_reserve_track(struct burn_drive *d, off_t size)
367 {
368 	struct command *c;
369 	int lba;
370 	char msg[80];
371 
372 	c = &(d->casual_command);
373 	mmc_start_if_needed(d, 0);
374 	if (mmc_function_spy(d, "mmc_reserve_track") <= 0)
375 		return 0;
376 
377 	scsi_init_command(c, MMC_RESERVE_TRACK, sizeof(MMC_RESERVE_TRACK));
378 	c->retry = 1;
379 
380 	lba = size / 2048;
381 	if (size % 2048)
382 		lba++;
383 	mmc_int_to_four_char(c->opcode+5, lba);
384 
385 	sprintf(msg, "reserving track of %d blocks", lba);
386 	libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
387 			   LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
388 			   msg, 0, 0);
389 
390 	c->page = NULL;
391 	c->dir = NO_TRANSFER;
392 	c->timeout = Libburn_mmc_reserve_timeouT;
393 	d->issue_command(d, c);
394 	if (c->error) {
395 		d->cancel = 1;
396 		scsi_notify_error(d, c, c->sense, 18, 2);
397 	}
398 	return !c->error;
399 }
400 
401 
402 /* ts A70201 :
403    Common track info fetcher for mmc_get_nwa() and mmc_fake_toc()
404 */
mmc_read_track_info(struct burn_drive * d,int trackno,struct buffer * buf,int alloc_len)405 int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf,
406 			int alloc_len)
407 {
408 	struct command *c;
409 
410 	c = &(d->casual_command);
411 	mmc_start_if_needed(d, 1);
412 	if (mmc_function_spy(d, "mmc_read_track_info") <= 0)
413 		return 0;
414 
415 	scsi_init_command(c, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO));
416 	c->dxfer_len = alloc_len;
417 	c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
418 	c->opcode[8] = c->dxfer_len & 0xff;
419 	c->retry = 1;
420 	c->opcode[1] = 1;
421 	if(trackno<=0) {
422 		if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
423 		    d->current_profile == 0x12 || d->current_profile == 0x42 ||
424 		    d->current_profile == 0x43)
425 			 /* DVD+RW , DVD-RW restricted overwrite , DVD-RAM
426 			    BD-R random recording, BD-RE */
427 			trackno = 1;
428 		else if (d->current_profile == 0x10 ||
429 			 d->current_profile == 0x11 ||
430 			 d->current_profile == 0x14 ||
431 			 d->current_profile == 0x15 ||
432 			 d->current_profile == 0x40 ||
433 			 d->current_profile == 0x41)
434 			/* DVD-ROM ,  DVD-R[W] Sequential ,
435 			   BD-ROM , BD-R sequential */
436 			trackno = d->last_track_no;
437 		else /* mmc5r03c.pdf: valid only for CD, DVD+R, DVD+R DL */
438 			trackno = 0xFF;
439 	}
440 	mmc_int_to_four_char(c->opcode + 2, trackno);
441 	c->page = buf;
442 	memset(buf->data, 0, BUFFER_SIZE);
443 	c->dir = FROM_DRIVE;
444 	d->issue_command(d, c);
445 	if (c->error)
446 		return 0;
447 	return 1;
448 }
449 
450 
451 /* ts A61110 : added parameters trackno, lba, nwa. Redefined return value.
452    @return 1=nwa is valid , 0=nwa is not valid , -1=error */
453 /* ts A70201 : outsourced 52h READ TRACK INFO command */
mmc_get_nwa(struct burn_drive * d,int trackno,int * lba,int * nwa)454 int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
455 {
456 	struct buffer *buf = NULL;
457 	int ret, num, alloc_len = 20, err;
458 	unsigned char *data;
459 	char *msg = NULL;
460 
461 	if (trackno <= 0)
462 		d->next_track_damaged = 0;
463 	mmc_start_if_needed(d, 1);
464 	if (mmc_function_spy(d, "mmc_get_nwa") <= 0)
465 		{ret = -1; goto ex;}
466 
467 	/* ts B00327 : Avoid to inquire unsuitable media states */
468 	if (d->status != BURN_DISC_BLANK && d->status != BURN_DISC_APPENDABLE)
469 		{ret = 0; goto ex;}
470 
471 	BURN_ALLOC_MEM(buf, struct buffer, 1);
472 	ret = mmc_read_track_info(d, trackno, buf, alloc_len);
473 	if (ret <= 0)
474 		goto ex;
475 	data = buf->data;
476 	*lba = mmc_four_char_to_int(data + 8);
477 	*nwa = mmc_four_char_to_int(data + 12);
478 	num = mmc_four_char_to_int(data + 16);
479 
480 	/* Pioneer BD-RW BDR-205 and LITE-ON LTR-48125S return -150 as *nwa
481 	   of blank media */
482 	if (*nwa < *lba && d->status == BURN_DISC_BLANK)
483 		*nwa = *lba;
484 
485 #ifdef Libburn_pioneer_dvr_216d_load_mode5
486 	/* >>> memorize track mode : data[6] & 0xf */;
487 #endif
488 
489 { static int fake_damage = 0; /* bit0= damage on , bit1= NWA_V off */
490 
491 	if (fake_damage & 1)
492 		data[5] |= 32; /* Damage bit */
493 	if (fake_damage & 2)
494 		data[7] &= ~1;
495 
496 }
497 
498 	BURN_ALLOC_MEM(msg, char, 160);
499 	if (trackno > 0)
500 		sprintf(msg, "Track number %d: ", trackno);
501 	else
502 		sprintf(msg, "Upcoming track: ");
503 	if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
504 	    d->current_profile == 0x12 || d->current_profile == 0x43) {
505 		 /* overwritable */
506 		*lba = *nwa = num = 0;
507 
508 	} else if (data[5] & 32) { /* ts B10534 : MMC-5 6.27.3.7 Damage Bit */
509 		if (!(data[7] & 1)) { /* NWA_V is set to zero */
510 			/* "not closed due to an incomplete write" */
511 			strcat(msg, "Damaged, not closed and not writable");
512 			err= 0x00020185;
513 		} else {
514 			/* "may be recorded further in an incremental manner"*/
515 			strcat(msg, "Damaged and not closed");
516 			err= 0x00020186;
517 		}
518 		libdax_msgs_submit(libdax_messenger, d->global_index, err,
519 				LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
520 				msg, 0, 0);
521 		if (trackno <= 0)
522 			d->next_track_damaged |= ((!(data[7] & 1)) << 1) | 1;
523 		{ret = 0; goto ex;}
524 
525 	} else if (!(data[7] & 1)) {
526 		/* ts A61106 :  MMC-1 Table 142 : NWA_V = NWA Valid Flag */
527 		strcat(msg, "No Next-Writable-Address");
528 		libdax_msgs_submit(libdax_messenger, d->global_index,
529 				0x00020184,
530 				LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
531 				msg, 0, 0);
532 		if (trackno <= 0)
533 			d->next_track_damaged |= 2;
534 		{ret = 0; goto ex;}
535 
536 	}
537 	if (num > 0) {
538 		burn_drive_set_media_capacity_remaining(d,
539 					((off_t) num) * ((off_t) 2048));
540 		d->media_lba_limit = *nwa + num;
541 	} else
542 		d->media_lba_limit = 0;
543 
544 /*
545 	fprintf(stderr, "LIBBURN_DEBUG: media_lba_limit= %d\n",
546 		 d->media_lba_limit);
547 */
548 
549 	ret = 1;
550 ex:
551 	BURN_FREE_MEM(buf);
552 	BURN_FREE_MEM(msg);
553 	return ret;
554 }
555 
556 /* ts A61009 : function is obviously unused. */
557 /* void mmc_close_disc(struct burn_drive *d, struct burn_write_opts *o) */
mmc_close_disc(struct burn_write_opts * o)558 void mmc_close_disc(struct burn_write_opts *o)
559 {
560 	struct burn_drive *d = o->drive;
561 
562 	if (mmc_function_spy(d, "mmc_close_disc") <= 0)
563 		return;
564 
565 	libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
566 			   LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
567 			   "HOW THAT ? mmc_close_disc() was called", 0, 0);
568 
569 	/* ts A61009 : made impossible by removing redundant parameter d */
570 	/* a ssert(o->drive == d); */
571 
572 	o->multi = 0;
573 	spc_select_write_params(d, NULL, 0, o);
574 	mmc_close(d, 1, 0);
575 }
576 
577 /* ts A61009 : function is obviously unused. */
578 /* void mmc_close_session(struct burn_drive *d, struct burn_write_opts *o) */
mmc_close_session(struct burn_write_opts * o)579 void mmc_close_session(struct burn_write_opts *o)
580 {
581 	struct burn_drive *d = o->drive;
582 
583 	if (mmc_function_spy(d, "mmc_close_session") <= 0)
584 		return;
585 
586 	libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
587 			   LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
588 			   "HOW THAT ? mmc_close_session() was called", 0, 0);
589 
590 	/* ts A61009 : made impossible by removing redundant parameter d */
591 	/* a ssert(o->drive == d); */
592 
593 	o->multi = 3;
594 	spc_select_write_params(d, NULL, 0, o);
595 	mmc_close(d, 1, 0);
596 }
597 
598 /* ts A70227 : extended meaning of session to address all possible values
599                of 5Bh CLOSE TRACK SESSION to address any Close Function.
600                @param session contains the two high bits of Close Function
601                @param track if not 0: sets the lowest bit of Close Function
602 */
mmc_close(struct burn_drive * d,int session,int track)603 void mmc_close(struct burn_drive *d, int session, int track)
604 {
605 	struct command *c;
606 	char msg[256];
607 	int key, asc, ascq;
608 
609 	c = &(d->casual_command);
610 	if (mmc_function_spy(d, "mmc_close") <= 0)
611 		return;
612 
613 	scsi_init_command(c, MMC_CLOSE, sizeof(MMC_CLOSE));
614 	c->retry = 1;
615 
616 	if (!d->do_no_immed)
617 		c->opcode[1] |= 1; /* ts A70918 : Immed */
618 
619 	/* (ts A61030 : shifted !!session rather than or-ing plain session ) */
620 	c->opcode[2] = ((session & 3) << 1) | !!track;
621 	c->opcode[4] = track >> 8;
622 	c->opcode[5] = track & 0xFF;
623 	c->page = NULL;
624 	c->dir = NO_TRANSFER;
625 	if (d->do_no_immed)
626 		c->timeout = Libburn_mmc_close_noim_timeouT;
627 	else
628 		c->timeout = Libburn_mmc_close_timeouT;
629 	d->issue_command(d, c);
630 
631 	/* ts A70918 : Immed : wait for drive to complete command */
632 	if (c->error) {
633 		sprintf(msg, "Failed to close %s (%d)",
634 		      session > 1 ? "disc" : session > 0 ? "session" : "track",
635 		      ((session & 3) << 1) | !!track);
636 		sprintf(msg + strlen(msg), ". SCSI error : ");
637 		scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
638 					&key, &asc, &ascq);
639 		libdax_msgs_submit(libdax_messenger, d->global_index,
640 				0x0002017e,
641 				LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
642 				msg, 0, 0);
643 		d->cancel = 1;
644 		return;
645 	}
646 	spc_human_readable_cmd(c, msg, 160, 0);
647 	if (spc_wait_unit_attention(d, 3600, msg, 0) <= 0)
648 		d->cancel = 1;
649 }
650 
mmc_get_event(struct burn_drive * d)651 void mmc_get_event(struct burn_drive *d)
652 {
653 	struct buffer *buf = NULL;
654 	struct command *c;
655 	int alloc_len = 8, len, evt_code, loops = 0;
656 	unsigned char *evt;
657 
658 	c = &(d->casual_command);
659 	BURN_ALLOC_MEM_VOID(buf, struct buffer, 1);
660 	if (mmc_function_spy(d, "mmc_get_event") <= 0)
661 		goto ex;
662 
663 again:;
664 	scsi_init_command(c, MMC_GET_EVENT, sizeof(MMC_GET_EVENT));
665 	c->dxfer_len = 8;
666 
667 	/* >>> have a burn_drive element for Notification Class */;
668 	c->opcode[4] = 0x7e;
669 
670 	c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
671 	c->opcode[8] = c->dxfer_len & 0xff;
672 	c->retry = 1;
673 	c->page = buf;
674 	c->page->bytes = 0;
675 	c->page->sectors = 0;
676 	c->dir = FROM_DRIVE;
677 	d->issue_command(d, c);
678 	if (c->error)
679 		goto ex;
680 
681 	evt = c->page->data;
682 	len = ((evt[0] << 8) | evt[1]) + 2;
683 	if (len < 8)
684 		goto ex;
685 
686 	/* >>> memorize evt[3] in burn_drive element for Notification Class */;
687 	if (evt[3] == 0) /* No event */
688 		goto ex;
689 
690 	evt_code = evt[4] & 0xf;
691 	if (evt_code == 0) /* No change */
692 		goto ex;
693 
694 	switch (evt[2] & 7) {
695 	case 0: /* no events supported */
696 		goto ex;
697 	case 1: /* Operational change */
698 		if (((evt[6] << 8) | evt[7])) {
699 			alloc_len = 8;
700 			mmc_get_configuration_al(d, &alloc_len);
701 		}
702 		break;
703 	case 2: /* Power Management */
704 		if (evt[5] >= 2)
705 			d->start_unit(d);
706 		break;
707 	case 3: /* External request */
708 
709 		/* >>> report about external request */;
710 
711 		break;
712 	case 4: /* Media */
713 		if (evt_code == 2) {
714 			d->start_unit(d);
715 			alloc_len = 8;
716 			mmc_get_configuration_al(d, &alloc_len);
717 		}
718 		break;
719 	case 5: /* Multiple Host Events */
720 
721 		/* >>> report about foreign host interference */;
722 
723 		break;
724 
725 	case 6: /* Device busy */
726 		if (evt_code == 1 && evt[5]) {
727 
728 			/* >>> wait the time announced in evt[6],[7]
729 				 as 100ms units */;
730 		}
731 		break;
732 	default: /* reserved */
733 		break;
734 	}
735 	loops++;
736 	if (loops < 100)
737 		goto again;
738 ex:;
739 	BURN_FREE_MEM(buf);
740 }
741 
742 
743 /* ts A70711
744    This has become a little monster because of the creative buffer reports of
745    my LG GSA-4082B : Belated, possibly statistically dampened. But only with
746    DVD media. With CD it is ok.
747 */
mmc_wait_for_buffer_free(struct burn_drive * d,struct buffer * buf)748 static int mmc_wait_for_buffer_free(struct burn_drive *d, struct buffer *buf)
749 {
750 	int usec= 0, need, reported_3s = 0, first_wait = 1;
751 	struct timeval t0,tnow;
752 	double max_fac, min_fac, waiting;
753 
754 /* Enable to get reported waiting activities and total time.
755 #define Libburn_mmc_wfb_debuG 1
756 */
757 #ifdef Libburn_mmc_wfb_debuG
758 	char sleeplist[32768];
759 	static int buffer_still_invalid = 1;
760 #endif
761 
762 	max_fac = ((double) d->wfb_max_percent) / 100.0;
763 
764 	/* Buffer info from the drive is valid only after writing has begun.
765 	   Caring for buffer space makes sense mostly after max_percent of the
766 	   buffer was transmitted. */
767 	if (d->progress.buffered_bytes <= 0 ||
768 		d->progress.buffer_capacity <= 0 ||
769 		d->progress.buffered_bytes + buf->bytes <=
770  					d->progress.buffer_capacity * max_fac)
771 		return 2;
772 
773 #ifdef Libburn_mmc_wfb_debuG
774 	if (buffer_still_invalid)
775 			fprintf(stderr,
776 			"\nLIBBURN_DEBUG: Buffer considered valid now\n");
777 	buffer_still_invalid = 0;
778 #endif
779 
780 	/* The pessimistic counter does not assume any buffer consumption */
781 	if (d->pessimistic_buffer_free - buf->bytes >=
782 		( 1.0 - max_fac) * d->progress.buffer_capacity)
783 		return 1;
784 
785 	/* There is need to inquire the buffer fill */
786 	d->pessimistic_writes++;
787 	min_fac = ((double) d->wfb_min_percent) / 100.0;
788 	gettimeofday(&t0, NULL);
789 #ifdef Libburn_mmc_wfb_debuG
790 	sleeplist[0]= 0;
791 	sprintf(sleeplist,"(%d%s %d)",
792 		(int) (d->pessimistic_buffer_free - buf->bytes),
793 		(d->pbf_altered ? "? -" : " -"),
794 		(int) ((1.0 - max_fac) * d->progress.buffer_capacity));
795 #endif
796 
797 	while (1) {
798 		if ((!first_wait) || d->pbf_altered) {
799 			d->pbf_altered = 1;
800 			mmc_read_buffer_capacity(d);
801 		}
802 #ifdef Libburn_mmc_wfb_debuG
803 		if(strlen(sleeplist) < sizeof(sleeplist) - 80)
804 			sprintf(sleeplist+strlen(sleeplist)," (%d%s %d)",
805 			(int) (d->pessimistic_buffer_free - buf->bytes),
806 			(d->pbf_altered ? "? -" : " -"),
807 			(int) ((1.0 - min_fac) * d->progress.buffer_capacity));
808 #endif
809 		gettimeofday(&tnow, NULL);
810 		waiting = (tnow.tv_sec - t0.tv_sec) +
811 			  ((double) (tnow.tv_usec - t0.tv_usec)) / 1.0e6;
812 		if (d->pessimistic_buffer_free - buf->bytes >=
813 			(1.0 - min_fac) * d->progress.buffer_capacity) {
814 #ifdef Libburn_mmc_wfb_debuG
815 			if(strlen(sleeplist) >= sizeof(sleeplist) - 80)
816 				strcat(sleeplist," ...");
817 			sprintf(sleeplist+strlen(sleeplist)," -> %d [%.6f]",
818 				(int) (
819 				 d->pessimistic_buffer_free - buf->bytes -
820 				 (1.0 - min_fac) * d->progress.buffer_capacity
821 				), waiting);
822 			fprintf(stderr,
823 				"\nLIBBURN_DEBUG: sleeplist= %s\n",sleeplist);
824 #endif
825 			return 1;
826 		}
827 
828 		/* Waiting is needed */
829 		if (waiting >= 3 && !reported_3s) {
830 			libdax_msgs_submit(libdax_messenger, d->global_index,
831 				0x0002013d,
832 				LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
833 			"Waiting for free buffer takes more than 3 seconds",
834 				0,0);
835 			reported_3s = 1;
836 		} else if (d->wfb_timeout_sec > 0 &&
837 				waiting > d->wfb_timeout_sec) {
838 			d->wait_for_buffer_free = 0;
839 			libdax_msgs_submit(libdax_messenger, d->global_index,
840 				0x0002013d,
841 				LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
842 			"Timeout with waiting for free buffer. Now disabled.",
843 				0,0);
844 	break;
845 		}
846 
847 		need = (1.0 - min_fac) * d->progress.buffer_capacity +
848 			buf->bytes - d->pessimistic_buffer_free;
849 		usec = 0;
850 		if (d->nominal_write_speed > 0)
851 			usec = ((double) need) / 1000.0 /
852 				((double) d->nominal_write_speed) * 1.0e6;
853 		else
854 			usec = d->wfb_min_usec * 2;
855 
856 		/* >>> learn about buffer progress and adjust usec */
857 
858 		if (usec < (int) d->wfb_min_usec)
859 			usec = d->wfb_min_usec;
860 		else if (usec > (int) d->wfb_max_usec)
861 			usec = d->wfb_max_usec;
862 		usleep(usec);
863 		if (d->waited_usec < 0xf0000000)
864 			d->waited_usec += usec;
865 		d->waited_tries++;
866 		if(first_wait)
867 			d->waited_writes++;
868 #ifdef Libburn_mmc_wfb_debuG
869 		if(strlen(sleeplist) < sizeof(sleeplist) - 80)
870 			sprintf(sleeplist+strlen(sleeplist)," %d", usec);
871 #endif
872 		first_wait = 0;
873 	}
874 	return 0;
875 }
876 
877 
mmc_write_12(struct burn_drive * d,int start,struct buffer * buf)878 void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf)
879 {
880 	struct command *c;
881 	int len;
882 
883 	c = &(d->casual_command);
884 	mmc_start_if_needed(d, 0);
885 	if (mmc_function_spy(d, "mmc_write_12") <= 0)
886 		return;
887 
888 	len = buf->sectors;
889 
890 	scsi_init_command(c, MMC_WRITE_12, sizeof(MMC_WRITE_12));
891 	c->retry = 1;
892 	mmc_int_to_four_char(c->opcode + 2, start);
893 	mmc_int_to_four_char(c->opcode + 6, len);
894 	c->page = buf;
895 	c->dir = TO_DRIVE;
896 	c->timeout = Libburn_scsi_write_timeouT;
897 
898 	d->issue_command(d, c);
899 
900 	/* ts A70711 */
901 	d->pessimistic_buffer_free -= buf->bytes;
902 	d->pbf_altered = 1;
903 }
904 
905 
906 #ifdef Libburn_write_time_debuG
907 
print_time(int flag)908 static int print_time(int flag)
909 {
910 	static struct timeval prev = {0, 0};
911 	struct timeval now;
912 	int ret, diff;
913 
914 	ret = gettimeofday(&now, NULL);
915 	if (ret == -1)
916 		return 0;
917 	if (now.tv_sec - prev.tv_sec < Libburn_scsi_write_timeouT) {
918 		diff = (now.tv_sec - prev.tv_sec) * 1000000 +
919 			((int) (now.tv_usec) - (int) prev.tv_usec);
920 		fprintf(stderr, "\nlibburn_DEBUG:  %d.%-6d : %d\n", (int) now.tv_sec, (int) now.tv_usec, diff);
921 	}
922 	memcpy(&prev, &now, sizeof(struct timeval));
923 	return 1;
924 }
925 
926 #endif /* Libburn_write_time_debuG */
927 
928 
mmc_write(struct burn_drive * d,int start,struct buffer * buf)929 int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
930 {
931 	int cancelled;
932 	struct command *c;
933 	int len, key, asc, ascq;
934 	char *msg = NULL;
935 
936 #ifdef Libburn_write_time_debuG
937 	extern int burn_sg_log_scsi;
938 #endif
939 
940 /*
941 fprintf(stderr, "libburn_DEBUG: buffer sectors= %d  bytes= %d\n",
942         buf->sectors, buf->bytes);
943 */
944 
945 
946 	c = &(d->casual_command);
947 
948 #ifdef Libburn_log_in_and_out_streaM
949 	/* <<< ts A61031 */
950 	static int tee_fd= -1;
951 	if(tee_fd==-1)
952 		tee_fd= open("/tmp/libburn_sg_written",
953 			O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
954 			S_IRUSR | S_IWUSR);
955 #endif /* Libburn_log_in_and_out_streaM */
956 
957 	mmc_start_if_needed(d, 0);
958 	if (mmc_function_spy(d, "mmc_write") <= 0)
959 		return BE_CANCELLED;
960 
961 	cancelled = d->cancel;
962 	if (cancelled)
963 		return BE_CANCELLED;
964 
965 	/* ts A70215 */
966 	if (d->media_lba_limit > 0 && start >= d->media_lba_limit) {
967 
968 		msg = calloc(1, 320);
969 		if (msg != NULL) {
970 			sprintf(msg,
971 		"Exceeding range of permissible write addresses (%d >= %d)",
972 				start, d->media_lba_limit);
973 		libdax_msgs_submit(libdax_messenger, d->global_index,
974 				0x0002012d,
975 				LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
976 				msg, 0, 0);
977 			strcpy(msg, "CDB= ");
978 			if (spc_human_readable_cmd(c, msg + strlen(msg),
979 					320 - strlen(msg), 1) > 0) {
980 				libdax_msgs_submit(libdax_messenger,
981 					d->global_index, 0x0002012d,
982 					LIBDAX_MSGS_SEV_FATAL,
983 					LIBDAX_MSGS_PRIO_HIGH,
984 					msg, 0, 0);
985 			}
986 			free(msg);
987 		}
988 		d->cancel = 1; /* No need for mutexing because atomic */
989 		return BE_CANCELLED;
990 	}
991 
992 	len = buf->sectors;
993 
994 	/* ts A61009 : buffer fill problems are to be handled by caller */
995 	/* a ssert(buf->bytes >= buf->sectors);*/	/* can be == at 0... */
996 
997 	/* ts A70711 */
998 	if(d->wait_for_buffer_free)
999 		mmc_wait_for_buffer_free(d, buf);
1000 
1001 #ifdef Libburn_write_time_debuG
1002 	if (burn_sg_log_scsi & 3)
1003 		print_time(0);
1004 #endif
1005 
1006 	/* ts A80412 */
1007 	if(d->do_stream_recording > 0 && start >= d->stream_recording_start) {
1008 		scsi_init_command(c, MMC_WRITE_12, sizeof(MMC_WRITE_12));
1009 		mmc_int_to_four_char(c->opcode + 2, start);
1010 		mmc_int_to_four_char(c->opcode + 6, len);
1011 		c->opcode[10] = 1<<7; /* Streaming bit */
1012 	} else {
1013 		scsi_init_command(c, MMC_WRITE_10, sizeof(MMC_WRITE_10));
1014 		mmc_int_to_four_char(c->opcode + 2, start);
1015 		c->opcode[6] = 0;
1016 		c->opcode[7] = (len >> 8) & 0xFF;
1017 		c->opcode[8] = len & 0xFF;
1018 	}
1019 	c->retry = 1;
1020 	c->page = buf;
1021 	c->dir = TO_DRIVE;
1022 	c->timeout = Libburn_scsi_write_timeouT;
1023 
1024 #ifdef Libburn_log_in_and_out_streaM
1025 	/* <<< ts A61031 */
1026 	if(tee_fd!=-1) {
1027 		write(tee_fd, c->page->data, c->page->bytes);
1028 	}
1029 #endif /* Libburn_log_in_and_out_streaM */
1030 
1031 	d->issue_command(d, c);
1032 
1033 	/* ts A70711 */
1034 	d->pessimistic_buffer_free -= buf->bytes;
1035 	d->pbf_altered = 1;
1036 
1037 	/* ts A61112 : react on eventual error condition */
1038 	spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
1039 	if (c->error && key != 0) {
1040 		int key, asc, ascq;
1041 		int err_sev = LIBDAX_MSGS_SEV_FATAL;
1042 
1043 		msg = calloc(1, 320);
1044 		if (msg != NULL) {
1045 			sprintf(msg, "SCSI error on write(%d,%d): ",
1046 				 start, len);
1047 			scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
1048 						&key, &asc, &ascq);
1049 		}
1050 
1051 		/* ts B31023 */
1052 		/* Memorize if on DVD-RW write mode is TAO/Incremental and
1053 		   error [5 64 00] occurs within the first drive buffer fill.
1054 		*/
1055 		if (d->current_profile == 0x14 && d->write_opts != NULL &&
1056 		    (d->progress.buffer_capacity == 0 ||
1057 		     start < (int) d->progress.buffer_capacity / 2048) &&
1058 		    key == 5 && asc == 0x64 && ascq == 0) {
1059 			if (d->write_opts->write_type == BURN_WRITE_TAO) {
1060 				d->was_feat21h_failure = 1 + (start == 0);
1061 				if (d->write_opts->feat21h_fail_sev != 0)
1062 					err_sev =
1063 					    d->write_opts->feat21h_fail_sev;
1064 			}
1065 		}
1066 
1067 		if (msg != NULL) {
1068 			libdax_msgs_submit(libdax_messenger, d->global_index,
1069 				0x0002011d,
1070 				err_sev, LIBDAX_MSGS_PRIO_HIGH,
1071 				msg, 0, 0);
1072 			strcpy(msg, "CDB= ");
1073 			if (spc_human_readable_cmd(c, msg + strlen(msg),
1074 					320 - strlen(msg), 0) > 0) {
1075 				libdax_msgs_submit(libdax_messenger,
1076 					d->global_index, 0x0002011d,
1077 					err_sev, LIBDAX_MSGS_PRIO_HIGH,
1078 					msg, 0, 0);
1079 			}
1080 			free(msg);
1081 		}
1082 		d->cancel = 1;
1083 
1084 		return BE_CANCELLED;
1085 	}
1086 	d->write_retry_count += c->retry_count;
1087 
1088 	return 0;
1089 }
1090 
1091 
1092 /* ts A70201 : Set up an entry for mmc_fake_toc() */
mmc_fake_toc_entry(struct burn_toc_entry * entry,int session_number,int track_number,unsigned char * size_data,unsigned char * start_data,unsigned char * last_adr_data)1093 int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number,
1094 			 int track_number,
1095 			 unsigned char *size_data, unsigned char *start_data,
1096 			 unsigned char *last_adr_data)
1097 {
1098 	int min, sec, frames, num;
1099 
1100 	/* mark DVD extensions and Track Info extension as valid */
1101 	entry->extensions_valid |= (1 | 2);
1102 
1103 	/* defaults are as of mmc5r03.pdf 6.26.3.2.4 Fabricated TOC */
1104 	entry->session = session_number & 0xff;
1105 	entry->session_msb = (session_number >> 8) & 0xff;
1106 	entry->adr = 1;
1107 	entry->control = 4;
1108 	entry->tno = 0;
1109 	entry->point = track_number & 0xff;
1110 	entry->point_msb = (track_number >> 8) & 0xff;
1111 	num = mmc_four_char_to_int(size_data);
1112 	entry->track_blocks = num;
1113 	burn_lba_to_msf(num, &min, &sec, &frames);
1114 	if (min > 255) {
1115 		min = 255;
1116 		sec = 255;
1117 		frames = 255;
1118 	}
1119 	entry->min = min;
1120 	entry->sec = sec;
1121 	entry->frame = frames;
1122 	entry->zero = 0;
1123 	num = mmc_four_char_to_int(start_data);
1124 	entry->start_lba = num;
1125 	burn_lba_to_msf(num, &min, &sec, &frames);
1126 	if (min > 255) {
1127 		min = 255;
1128 		sec = 255;
1129 		frames = 255;
1130 	}
1131 	entry->pmin = min;
1132 	entry->psec = sec;
1133 	entry->pframe = frames;
1134 	entry->last_recorded_address = mmc_four_char_to_int(last_adr_data);
1135 	return 1;
1136 }
1137 
1138 
1139 /* ts A71128 : for DVD-ROM drives which offer no reliable track information */
mmc_read_toc_fmt0_al(struct burn_drive * d,int * alloc_len)1140 static int mmc_read_toc_fmt0_al(struct burn_drive *d, int *alloc_len)
1141 {
1142 	struct burn_track *track;
1143 	struct burn_session *session;
1144 	struct burn_toc_entry *entry;
1145 	struct buffer *buf = NULL;
1146 	struct command *c = NULL;
1147 	int dlen, i, old_alloc_len, session_number, prev_session = -1, ret;
1148 	int lba, size;
1149 	unsigned char *tdata, size_data[4], start_data[4], end_data[4];
1150 
1151 	if (*alloc_len < 4)
1152 		{ret = 0; goto ex;}
1153 
1154 	BURN_ALLOC_MEM(buf, struct buffer, 1);
1155 	BURN_ALLOC_MEM(c, struct command, 1);
1156 	scsi_init_command(c, MMC_GET_TOC_FMT0, sizeof(MMC_GET_TOC_FMT0));
1157 	c->dxfer_len = *alloc_len;
1158 	c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
1159 	c->opcode[8] = c->dxfer_len & 0xff;
1160 	c->retry = 1;
1161 	c->page = buf;
1162 	c->page->bytes = 0;
1163 	c->page->sectors = 0;
1164 	c->dir = FROM_DRIVE;
1165 	d->issue_command(d, c);
1166 
1167 	if (c->error) {
1168 err_ex:;
1169 		libdax_msgs_submit(libdax_messenger, d->global_index,
1170 			 0x0002010d,
1171 			 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
1172 			 "Could not inquire TOC", 0,0);
1173 		d->status = BURN_DISC_UNSUITABLE;
1174 		d->toc_entries = 0;
1175 		/* Preferring memory leaks over fandangos */
1176 		d->toc_entry = calloc(1, sizeof(struct burn_toc_entry));
1177 		{ret = 0; goto ex;}
1178 	}
1179 	dlen = c->page->data[0] * 256 + c->page->data[1];
1180 	old_alloc_len = *alloc_len;
1181 	*alloc_len = dlen + 2;
1182 	if (old_alloc_len < 12)
1183 		{ret = 1; goto ex;}
1184 	if (dlen + 2 > old_alloc_len)
1185 		dlen = old_alloc_len - 2;
1186 	d->complete_sessions = 1 + c->page->data[3] - c->page->data[2];
1187 
1188 #ifdef Libburn_disc_with_incomplete_sessioN
1189 	/* ts B30112 : number of open sessions */
1190 	d->incomplete_sessions = 0;
1191 #endif
1192 
1193 	d->last_track_no = d->complete_sessions;
1194 	if (dlen - 2 < (d->last_track_no + 1) * 8) {
1195 		libdax_msgs_submit(libdax_messenger, d->global_index,
1196 			 0x00020159,
1197 			 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
1198 			 "TOC Format 0 returns inconsistent data", 0,0);
1199 		goto err_ex;
1200 	}
1201 
1202 	d->toc_entries = d->last_track_no + d->complete_sessions;
1203 	if (d->toc_entries < 1)
1204 		{ret = 0; goto ex;}
1205 	d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry));
1206 	if(d->toc_entry == NULL)
1207 		{ret = 0; goto ex;}
1208 
1209 	d->disc = burn_disc_create();
1210 	if (d->disc == NULL)
1211 		{ret = 0; goto ex;}
1212 	for (i = 0; i < d->complete_sessions; i++) {
1213 		session = burn_session_create();
1214 		if (session == NULL)
1215 			{ret = 0; goto ex;}
1216 		burn_disc_add_session(d->disc, session, BURN_POS_END);
1217 		burn_session_free(session);
1218 	}
1219 
1220 
1221 	for (i = 0; i < d->last_track_no; i++) {
1222 		tdata = c->page->data + 4 + i * 8;
1223 		session_number = i + 1;
1224 		if (session_number != prev_session && prev_session > 0) {
1225 			/* leadout entry previous session */
1226 			entry = &(d->toc_entry[(i - 1) + prev_session]);
1227 			lba = mmc_four_char_to_int(start_data) +
1228 			      mmc_four_char_to_int(size_data);
1229 			mmc_int_to_four_char(start_data, lba);
1230 			mmc_int_to_four_char(size_data, 0);
1231 			mmc_int_to_four_char(end_data, lba - 1);
1232 			mmc_fake_toc_entry(entry, prev_session, 0xA2,
1233 					 size_data, start_data, end_data);
1234 			entry->min= entry->sec= entry->frame= 0;
1235 			d->disc->session[prev_session - 1]->leadout_entry =
1236 									entry;
1237 		}
1238 
1239 		/* ??? >>> d->media_capacity_remaining , d->media_lba_limit
1240 				as of mmc_fake_toc()
1241 		*/
1242 
1243 		entry = &(d->toc_entry[i + session_number - 1]);
1244  		track = burn_track_create();
1245 		if (track == NULL)
1246 			{ret = -1; goto ex;}
1247 		burn_session_add_track(
1248 			d->disc->session[session_number - 1],
1249 			track, BURN_POS_END);
1250 		track->entry = entry;
1251 		burn_track_free(track);
1252 
1253 		memcpy(start_data, tdata + 4, 4);
1254 			/* size_data are estimated from next track start */
1255 		memcpy(size_data, tdata + 8 + 4, 4);
1256 		mmc_int_to_four_char(end_data,
1257 				mmc_four_char_to_int(size_data) - 1);
1258 		size = mmc_four_char_to_int(size_data) -
1259 	      		mmc_four_char_to_int(start_data);
1260 		mmc_int_to_four_char(size_data, size);
1261 		mmc_fake_toc_entry(entry, session_number, i + 1,
1262 					 size_data, start_data, end_data);
1263 		if (prev_session != session_number)
1264 			d->disc->session[session_number - 1]->firsttrack = i+1;
1265 		d->disc->session[session_number - 1]->lasttrack = i+1;
1266 		prev_session = session_number;
1267 	}
1268 	if (prev_session > 0 && prev_session <= d->disc->sessions) {
1269 		/* leadout entry of last session of closed disc */
1270 		tdata = c->page->data + 4 + d->last_track_no * 8;
1271 		entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]);
1272 		memcpy(start_data, tdata + 4, 4);
1273 		mmc_int_to_four_char(size_data, 0);
1274 		mmc_int_to_four_char(end_data,
1275 					mmc_four_char_to_int(start_data) - 1);
1276 		mmc_fake_toc_entry(entry, prev_session, 0xA2,
1277 				 size_data, start_data, end_data);
1278 		entry->min= entry->sec= entry->frame= 0;
1279 		d->disc->session[prev_session - 1]->leadout_entry = entry;
1280 	}
1281 	ret = 1;
1282 ex:;
1283 	BURN_FREE_MEM(buf);
1284 	BURN_FREE_MEM(c);
1285 	return ret;
1286 }
1287 
1288 
1289 /* ts A71128 : for DVD-ROM drives which offer no reliable track information */
mmc_read_toc_fmt0(struct burn_drive * d)1290 static int mmc_read_toc_fmt0(struct burn_drive *d)
1291 {
1292 	int alloc_len = 4, ret;
1293 
1294 	mmc_start_if_needed(d, 1);
1295 	if (mmc_function_spy(d, "mmc_read_toc_fmt0") <= 0)
1296 		return -1;
1297 	ret = mmc_read_toc_fmt0_al(d, &alloc_len);
1298 	if (alloc_len >= 12)
1299 		ret = mmc_read_toc_fmt0_al(d, &alloc_len);
1300 	return ret;
1301 }
1302 
1303 
1304 /* ts A70131 : compose a disc TOC structure from d->complete_sessions
1305                and 52h READ TRACK INFORMATION */
mmc_fake_toc(struct burn_drive * d)1306 int mmc_fake_toc(struct burn_drive *d)
1307 {
1308 	struct burn_track *track;
1309 	struct burn_session *session;
1310 	struct burn_toc_entry *entry;
1311 	struct buffer *buf = NULL;
1312 	int i, session_number, prev_session = -1, ret, lba, alloc_len = 34;
1313 	unsigned char *tdata, size_data[4], start_data[4], end_data[4];
1314 	char *msg = NULL;
1315 
1316 	if (mmc_function_spy(d, "mmc_fake_toc") <= 0)
1317 		{ret = -1; goto ex;}
1318 	BURN_ALLOC_MEM(buf, struct buffer, 1);
1319 
1320 #ifdef Libburn_disc_with_incomplete_sessioN
1321 
1322 	if (d->last_track_no <= 0 ||
1323             d->complete_sessions  + d->incomplete_sessions <= 0 ||
1324 	    d->status == BURN_DISC_BLANK)
1325 		{ret = 2; goto ex;}
1326 
1327 #else
1328 
1329 	if (d->last_track_no <= 0 || d->complete_sessions <= 0 ||
1330 	    d->status == BURN_DISC_BLANK)
1331 		{ret = 2; goto ex;}
1332 
1333 #endif /* ! Libburn_disc_with_incomplete_sessioN */
1334 
1335 
1336 	if (d->last_track_no > BURN_MMC_FAKE_TOC_MAX_SIZE) {
1337 		msg = calloc(1, 160);
1338 		if (msg != NULL) {
1339 			sprintf(msg,
1340 			  "Too many logical tracks recorded (%d , max. %d)\n",
1341 			  d->last_track_no, BURN_MMC_FAKE_TOC_MAX_SIZE);
1342 			libdax_msgs_submit(libdax_messenger, d->global_index,
1343 				 0x0002012c,
1344 				 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
1345 				 msg, 0,0);
1346 			free(msg);
1347 		}
1348 		{ret = 0; goto ex;}
1349 	}
1350 	/* ts A71128 : My DVD-ROM drive issues no reliable track info.
1351 			One has to try 43h READ TOC/PMA/ATIP Form 0. */
1352 	if ((d->current_profile == 0x10) && d->last_track_no <= 1) {
1353 		ret = mmc_read_toc_fmt0(d);
1354 		goto ex;
1355 	}
1356 	d->disc = burn_disc_create();
1357 	if (d->disc == NULL)
1358 		{ret = -1; goto ex;}
1359 	d->toc_entries = d->last_track_no
1360 	                 + d->complete_sessions + d->incomplete_sessions;
1361 	d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry));
1362 	if (d->toc_entry == NULL)
1363 		{ret = -1; goto ex;}
1364 	memset(d->toc_entry, 0,d->toc_entries * sizeof(struct burn_toc_entry));
1365 
1366 #ifdef Libburn_disc_with_incomplete_sessioN
1367 
1368 	for (i = 0; i < d->complete_sessions + d->incomplete_sessions; i++) {
1369 
1370 #else
1371 
1372 	for (i = 0; i < d->complete_sessions; i++) {
1373 
1374 #endif
1375 
1376 		session = burn_session_create();
1377 		if (session == NULL)
1378 			{ret = -1; goto ex;}
1379 		burn_disc_add_session(d->disc, session, BURN_POS_END);
1380 		burn_session_free(session);
1381 	}
1382 
1383 #ifdef Libburn_disc_with_incomplete_sessioN
1384 	d->disc->incomplete_sessions = d->incomplete_sessions;
1385 #endif
1386 
1387 	memset(size_data, 0, 4);
1388 	memset(start_data, 0, 4);
1389 
1390 
1391 	/* Entry Layout :
1392 		session 1   track 1     entry 0
1393 		...
1394 		session 1   track N     entry N-1
1395 		leadout 1               entry N
1396 		session 2   track N+1   entry N+1
1397 		...
1398 		session 2   track M+1   entry M+1
1399 		leadout 2               entry M+2
1400 		session X   track K     entry (K-1)+(X-1)
1401 		...
1402 		session X   track i+1   entry i+(X-1)
1403 		leadout X               entry i+X
1404 	*/
1405 	for (i = 0; i < d->last_track_no; i++) {
1406 		ret = mmc_read_track_info(d, i+1, buf, alloc_len);
1407 		if (ret <= 0)
1408 			goto ex;
1409 		tdata = buf->data;
1410 		session_number = (tdata[33] << 8) | tdata[3];
1411 		if (session_number <= 0)
1412 	continue;
1413 
1414 		if (session_number != prev_session && prev_session > 0) {
1415 			/* leadout entry previous session */
1416 			entry = &(d->toc_entry[(i - 1) + prev_session]);
1417 			lba = mmc_four_char_to_int(start_data) +
1418 			      mmc_four_char_to_int(size_data);
1419 			mmc_int_to_four_char(start_data, lba);
1420 			mmc_int_to_four_char(size_data, 0);
1421 			mmc_int_to_four_char(end_data, lba - 1);
1422 			mmc_fake_toc_entry(entry, prev_session, 0xA2,
1423 					 size_data, start_data, end_data);
1424 			entry->min= entry->sec= entry->frame= 0;
1425 			d->disc->session[prev_session - 1]->leadout_entry =
1426 									entry;
1427 		}
1428 
1429 #ifdef Libburn_disc_with_incomplete_sessioN
1430 
1431 		if (session_number > d->complete_sessions) {
1432 
1433 #else
1434 
1435 		if (session_number > d->disc->sessions) {
1436 
1437 #endif
1438 
1439 			if (i == d->last_track_no - 1) {
1440 				/* ts A70212 : Last track field Free Blocks */
1441 				burn_drive_set_media_capacity_remaining(d,
1442 				  ((off_t) mmc_four_char_to_int(tdata + 16)) *
1443 				  ((off_t) 2048));
1444 				d->media_lba_limit = 0;
1445 			}
1446 
1447 #ifdef Libburn_disc_with_incomplete_sessioN
1448 
1449 			if (session_number > d->disc->sessions )
1450 	continue;
1451 
1452 #else
1453 
1454 	continue;
1455 
1456 #endif
1457 
1458 		}
1459 
1460 		entry = &(d->toc_entry[i + session_number - 1]);
1461  		track = burn_track_create();
1462 		if (track == NULL)
1463 			{ret = -1; goto ex;}
1464 		burn_session_add_track(
1465 			d->disc->session[session_number - 1],
1466 			track, BURN_POS_END);
1467 		track->entry = entry;
1468 		burn_track_free(track);
1469 
1470 		memcpy(size_data, tdata + 24, 4);
1471 		memcpy(start_data, tdata + 8, 4);
1472 		memcpy(end_data, tdata + 28, 4);
1473 		mmc_fake_toc_entry(entry, session_number, i + 1,
1474 					 size_data, start_data, end_data);
1475 		entry->track_status_bits = tdata[5] | (tdata[6] << 8) |
1476 		                           (tdata[7] << 16);
1477 		entry->extensions_valid |= 4;
1478 
1479 		if (prev_session != session_number)
1480 			d->disc->session[session_number - 1]->firsttrack = i+1;
1481 		d->disc->session[session_number - 1]->lasttrack = i+1;
1482 		prev_session = session_number;
1483 	}
1484 
1485 	if (prev_session > 0 && prev_session <= d->disc->sessions) {
1486 		/* leadout entry of last session of closed disc */
1487 		entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]);
1488 		lba = mmc_four_char_to_int(start_data) +
1489 		      mmc_four_char_to_int(size_data);
1490 		mmc_int_to_four_char(start_data, lba);
1491 		mmc_int_to_four_char(size_data, 0);
1492 		mmc_int_to_four_char(end_data, lba - 1);
1493 		mmc_fake_toc_entry(entry, prev_session, 0xA2,
1494 				 size_data, start_data, end_data);
1495 		entry->min= entry->sec= entry->frame= 0;
1496 		d->disc->session[prev_session - 1]->leadout_entry = entry;
1497 	}
1498 	ret = 1;
1499 ex:;
1500 	BURN_FREE_MEM(buf);
1501 	return ret;
1502 }
1503 
1504 
1505 static int mmc_register_leadout(struct burn_drive *d, int *highest_leadout,
1506                              int toc_idx)
1507 {
1508 	int lba;
1509 
1510 	lba = burn_msf_to_lba(d->toc_entry[toc_idx].pmin,
1511 				d->toc_entry[toc_idx].psec,
1512 				d->toc_entry[toc_idx].pframe);
1513 	if (lba > *highest_leadout)
1514 		*highest_leadout = lba;
1515 	return 1;
1516 }
1517 
1518 
1519 static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
1520 {
1521 /* read full toc, all sessions, in m/s/f form, 4k buffer */
1522 /* ts A70201 : or fake a toc from track information */
1523 	struct burn_track *track;
1524 	struct burn_session *session;
1525 	struct buffer *buf = NULL;
1526 	struct command *c = NULL;
1527 	int dlen;
1528 	int i, old_alloc_len, t_idx, ret, highest_leadout = -1;
1529 	unsigned char *tdata;
1530 	char *msg = NULL;
1531 
1532 	if (*alloc_len < 4)
1533 		{ret = 0; goto ex;}
1534 
1535 	BURN_ALLOC_MEM(buf, struct buffer, 1);
1536 	BURN_ALLOC_MEM(c, struct command, 1);
1537 	BURN_ALLOC_MEM(msg, char, 321);
1538 
1539 	if (!(d->current_profile == -1 || d->current_is_cd_profile)) {
1540 		/* ts A70131 : MMC_GET_TOC uses Response Format 2
1541 		   For DVD this fails with 5,24,00 */
1542 		/* mmc_read_toc_fmt0() uses
1543                    Response Format 0: mmc5r03.pdf 6.26.3.2
1544 		   which does not yield the same result with the same disc
1545 		   on different drives.
1546 		*/
1547 		/* ts A70201 :
1548 		   This uses the session count from 51h READ DISC INFORMATION
1549 		   and the track records from 52h READ TRACK INFORMATION.
1550 		   mmc_read_toc_fmt0() is used as fallback for dull DVD-ROM.
1551 		*/
1552 		mmc_fake_toc(d);
1553 
1554 		if (d->status == BURN_DISC_UNREADY)
1555 			d->status = BURN_DISC_FULL;
1556 		{ret = 1; goto ex;}
1557 	}
1558 
1559 	/* ts A90823:
1560 	   SanDisk Cruzer U3 memory stick stalls on format 2.
1561 	   Format 0 seems to be more conservative with read-only drives.
1562 	*/
1563 	if (!((d->mdata->p2a_valid > 0 && d->mdata->cdrw_write) ||
1564 	      d->current_profile != 0x08)) {
1565 		ret = mmc_read_toc_fmt0(d);
1566 		goto ex;
1567 	}
1568 
1569 	scsi_init_command(c, MMC_GET_TOC, sizeof(MMC_GET_TOC));
1570 	c->dxfer_len = *alloc_len;
1571 	c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
1572 	c->opcode[8] = c->dxfer_len & 0xff;
1573 	c->retry = 1;
1574 	c->page = buf;
1575 	c->page->bytes = 0;
1576 	c->page->sectors = 0;
1577 	c->dir = FROM_DRIVE;
1578 	d->issue_command(d, c);
1579 
1580 	if (c->error) {
1581 
1582 		/* ts A61020 : this snaps on non-blank DVD media */
1583 		/* ts A61106 : also snaps on CD with unclosed track/session */
1584 		/* Very unsure whether this old measure is ok.
1585 		   Obviously higher levels do not care about this.
1586 		   outdated info: DVD+RW burns go on after passing through here.
1587 
1588 		d->busy = BURN_DRIVE_IDLE;
1589 		*/
1590 		libdax_msgs_submit(libdax_messenger, d->global_index,
1591 			 0x0002010d,
1592 			 LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
1593 			 "Could not inquire TOC", 0,0);
1594 		d->status = BURN_DISC_UNSUITABLE;
1595 		d->toc_entries = 0;
1596 		/* Preferring memory leaks over fandangos */
1597 		d->toc_entry = calloc(1, sizeof(struct burn_toc_entry));
1598 		{ret = 0; goto ex;}
1599 	}
1600 
1601 	dlen = c->page->data[0] * 256 + c->page->data[1];
1602 	old_alloc_len = *alloc_len;
1603 	*alloc_len = dlen + 2;
1604 	if (old_alloc_len < 15)
1605 		{ret = 1; goto ex;}
1606 	if (dlen + 2 > old_alloc_len)
1607 		dlen = old_alloc_len - 2;
1608 	d->toc_entries = (dlen - 2) / 11;
1609 	if (d->toc_entries < 1)
1610 		{ret = 0; goto ex;}
1611 /*
1612 	some drives fail this check.
1613 
1614 	ts A61007 : if re-enabled then not via Assert.
1615 	a ssert(((dlen - 2) % 11) == 0);
1616 */
1617 	/* ts A81202: plus number of sessions as reserve for leadout default */
1618 	d->toc_entry = calloc(d->toc_entries + (unsigned char) c->page->data[3],
1619 				 sizeof(struct burn_toc_entry));
1620 	if(d->toc_entry == NULL) /* ts A70825 */
1621 		{ret = 0; goto ex;}
1622 	tdata = c->page->data + 4;
1623 
1624 	d->disc = burn_disc_create();
1625 	if (d->disc == NULL) /* ts A70825 */
1626 		{ret = 0; goto ex;}
1627 
1628 	for (i = 0; i < c->page->data[3]; i++) {
1629 		session = burn_session_create();
1630 		if (session == NULL) /* ts A70825 */
1631 			{ret = 0; goto ex;}
1632 		burn_disc_add_session(d->disc, session, BURN_POS_END);
1633 		burn_session_free(session);
1634 	}
1635 
1636 	/* ts A61022 */
1637 
1638 	for (i = 0; i < d->toc_entries; i++, tdata += 11) {
1639 
1640 /*
1641 		fprintf(stderr, "libburn_experimental: toc entry #%d : %d %d %d\n",i,tdata[8], tdata[9], tdata[10]);
1642 */
1643 
1644 #ifdef Libburn_allow_first_hiddeN
1645 		/* ts B00430 : this causes problems because the track has
1646 		               no entry. One would have to coordinate this
1647 		               with other parts of libburn.
1648 		*/
1649 		if (tdata[3] == 1) {
1650 			if (burn_msf_to_lba(tdata[8], tdata[9], tdata[10])) {
1651 				d->disc->session[0]->hidefirst = 1;
1652 				track = burn_track_create();
1653 				burn_session_add_track(d->disc->
1654 						       session[tdata[0] - 1],
1655 						       track, BURN_POS_END);
1656 				burn_track_free(track);
1657 			}
1658 		}
1659 #endif /* Libburn_allow_first_hiddeN */
1660 
1661 		if (tdata[0] <= 0 || tdata[0] > d->disc->sessions)
1662 			tdata[0] = d->disc->sessions;
1663 		if (tdata[3] < 100 && tdata[0] > 0) {
1664 			track = burn_track_create();
1665 			burn_session_add_track(d->disc->session[tdata[0] - 1],
1666 					       track, BURN_POS_END);
1667 			track->entry = &d->toc_entry[i];
1668 			burn_track_free(track);
1669 		}
1670 		d->toc_entry[i].session = tdata[0];
1671 		d->toc_entry[i].adr = tdata[1] >> 4;
1672 		d->toc_entry[i].control = tdata[1] & 0xF;
1673 		d->toc_entry[i].tno = tdata[2];
1674 		d->toc_entry[i].point = tdata[3];
1675 		d->toc_entry[i].min = tdata[4];
1676 		d->toc_entry[i].sec = tdata[5];
1677 		d->toc_entry[i].frame = tdata[6];
1678 		d->toc_entry[i].zero = tdata[7];
1679 		d->toc_entry[i].pmin = tdata[8];
1680 		d->toc_entry[i].psec = tdata[9];
1681 		d->toc_entry[i].pframe = tdata[10];
1682 		if (tdata[3] == 0xA0)
1683 			d->disc->session[tdata[0] - 1]->firsttrack = tdata[8];
1684 		if (tdata[3] == 0xA1)
1685 			d->disc->session[tdata[0] - 1]->lasttrack = tdata[8];
1686 		if (tdata[3] == 0xA2) {
1687 			d->disc->session[tdata[0] - 1]->leadout_entry =
1688 				&d->toc_entry[i];
1689 			/* ts B60305 */
1690 			mmc_register_leadout(d, &highest_leadout, i);
1691 		}
1692 	}
1693 
1694 	/* ts A70131 : was (d->status != BURN_DISC_BLANK) */
1695 	if (d->status == BURN_DISC_UNREADY)
1696 		d->status = BURN_DISC_FULL;
1697 	toc_find_modes(d);
1698 
1699 	/* ts A81202 ticket 146 : a drive reported a session with no leadout */
1700 	for (i = 0; i < d->disc->sessions; i++) {
1701 		if (d->disc->session[i]->leadout_entry != NULL)
1702 	continue;
1703 		sprintf(msg, "Session %d of %d encountered without leadout",
1704 			i + 1, d->disc->sessions);
1705 		libdax_msgs_submit(libdax_messenger, d->global_index,
1706 				0x00020160,
1707 				LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
1708 				msg, 0, 0);
1709 
1710 		/* Produce default leadout entry from last track of session
1711 		   which will thus get its size set to 0 */;
1712 		if (d->disc->session[i]->track != NULL &&
1713 		    d->disc->session[i]->tracks > 0) {
1714 			t_idx = d->toc_entries++;
1715 			memcpy(d->toc_entry + t_idx,
1716 				d->disc->session[i]->track[
1717 				       d->disc->session[i]->tracks - 1]->entry,
1718 				sizeof(struct burn_toc_entry));
1719 			d->toc_entry[t_idx].point = 0xA2;
1720 			d->disc->session[i]->leadout_entry =
1721 							 d->toc_entry + t_idx;
1722 		} else {
1723 			burn_disc_remove_session(d->disc, d->disc->session[i]);
1724 			sprintf(msg,
1725 				"Empty session %d deleted. Now %d sessions.",
1726 				i + 1, d->disc->sessions);
1727 			libdax_msgs_submit(libdax_messenger, d->global_index,
1728 				0x00020161,
1729 				LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
1730 				msg, 0, 0);
1731 			i--;
1732 		}
1733 	}
1734 
1735 	/* A80808 */
1736 	burn_disc_cd_toc_extensions(d, 0);
1737 
1738 	/* ts B60304
1739 	   Most drives report READ CAPACITY of TAO CD too high by 2 blocks.
1740 	   TOC format 2 always reports 2 blocks more than are readable.
1741 	   So here it is possible to check and mark as trusted.
1742 	*/
1743 	if (highest_leadout > 0 && d->media_read_capacity != 0x7fffffff &&
1744 	    !d->mr_capacity_trusted) {
1745 		if (highest_leadout - 3 == d->media_read_capacity) {
1746 			d->mr_capacity_trusted = 1;
1747 			libdax_msgs_submit(libdax_messenger, d->global_index,
1748 				 0x00000002, LIBDAX_MSGS_SEV_DEBUG,
1749 				 LIBDAX_MSGS_PRIO_ZERO,
1750 	      "Trusting READ CAPACITY by 2 extra blocks in TOC. Assuming TAO.",
1751 				 0, 0);
1752 		}
1753 	}
1754 
1755 	ret = 1;
1756 ex:;
1757 	BURN_FREE_MEM(msg);
1758 	BURN_FREE_MEM(c);
1759 	BURN_FREE_MEM(buf);
1760 	return ret;
1761 }
1762 
1763 
1764 void mmc_read_toc(struct burn_drive *d)
1765 {
1766 	int alloc_len = 4, ret;
1767 
1768 	mmc_start_if_needed(d, 1);
1769 	if (mmc_function_spy(d, "mmc_read_toc") <= 0)
1770 		return;
1771 
1772 	ret = mmc_read_toc_al(d, &alloc_len);
1773 /*
1774 	fprintf(stderr,
1775 		"LIBBURN_DEBUG: 43h READ TOC alloc_len = %d , ret = %d\n",
1776 		alloc_len, ret);
1777 */
1778 	if (alloc_len >= 15)
1779 		ret = mmc_read_toc_al(d, &alloc_len);
1780 	if (ret <= 0)
1781 		return;
1782 }
1783 
1784 
1785 /* ts A70131 : This tries to get the start of the last complete session */
1786 /* man mkisofs , option -C :
1787    The first number is the sector number of the first sector in
1788    the last session of the disk that should be appended to.
1789 */
1790 int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start)
1791 {
1792 	struct buffer *buf = NULL;
1793 	struct command *c = NULL;
1794 	unsigned char *tdata;
1795 	int num_sessions, session_no, num_tracks, alloc_len = 12, ret;
1796 	struct burn_disc *disc;
1797 	struct burn_session **sessions;
1798 	struct burn_track **tracks;
1799 	struct burn_toc_entry toc_entry;
1800 
1801 	BURN_ALLOC_MEM(buf, struct buffer, 1);
1802 	BURN_ALLOC_MEM(c, struct command, 1);
1803 	mmc_start_if_needed(d, 1);
1804 	if (mmc_function_spy(d, "mmc_read_multi_session_c1") <= 0)
1805 		{ret = 0; goto ex;}
1806 
1807 	/* First try to evaluate the possibly loaded TOC before issuing
1808 	   a MMC command. This search obtains the first track of the last
1809 	   complete session which has a track.
1810 	*/
1811 	*trackno = 0;
1812 	disc = burn_drive_get_disc(d);
1813 	if (disc == NULL)
1814 		goto inquire_drive;
1815 	sessions = burn_disc_get_sessions(disc, &num_sessions);
1816 	for (session_no = 0; session_no<num_sessions; session_no++) {
1817 		tracks = burn_session_get_tracks(sessions[session_no],
1818 						&num_tracks);
1819 		if (tracks == NULL || num_tracks <= 0)
1820 	continue;
1821 		burn_track_get_entry(tracks[0], &toc_entry);
1822 		if (toc_entry.extensions_valid & 1) { /* DVD extension valid */
1823 			*start = toc_entry.start_lba;
1824 			*trackno = (toc_entry.point_msb << 8)| toc_entry.point;
1825 		} else {
1826 			*start = burn_msf_to_lba(toc_entry.pmin,
1827 					toc_entry.psec, toc_entry.pframe);
1828 			*trackno = toc_entry.point;
1829 		}
1830 	}
1831 	burn_disc_free(disc);
1832 	if(*trackno > 0)
1833 		{ret = 1; goto ex;}
1834 
1835 inquire_drive:;
1836 	/* mmc5r03.pdf 6.26.3.3.3 states that with non-CD this would
1837 	   be a useless fake always starting at track 1, lba 0.
1838 	   My drives return useful data, though.
1839 	   MMC-3 states that DVD had no tracks. So maybe this mandatory fake
1840 	   is a forgotten legacy ?
1841 	*/
1842 	scsi_init_command(c, MMC_GET_MSINFO, sizeof(MMC_GET_MSINFO));
1843 	c->dxfer_len = alloc_len;
1844 	c->opcode[7]= (c->dxfer_len >> 8) & 0xff;
1845 	c->opcode[8]= c->dxfer_len & 0xff;
1846 	c->retry = 1;
1847 	c->page = buf;
1848 	c->page->bytes = 0;
1849 	c->page->sectors = 0;
1850 	c->dir = FROM_DRIVE;
1851 	d->issue_command(d, c);
1852 
1853 	if (c->error)
1854 		{ret = 0; goto ex;}
1855 
1856 	tdata = c->page->data + 4;
1857 	*trackno = tdata[2];
1858 	*start = mmc_four_char_to_int(tdata + 4);
1859 	ret = 1;
1860 ex:;
1861 	BURN_FREE_MEM(buf);
1862 	BURN_FREE_MEM(c);
1863 	return ret;
1864 }
1865 
1866 
1867 /* ts A61201 */
1868 char *mmc_obtain_profile_name(int profile_number)
1869 {
1870 	static char *texts[0x53] = {NULL};
1871 	int i, max_pno = 0x53;
1872 
1873 	if (texts[0] == NULL) {
1874 		for (i = 0; i<max_pno; i++)
1875 			texts[i] = "";
1876 		/* mmc5r03c.pdf , Table 89, Spelling: guessed cdrecord style */
1877 		texts[0x01] = "Non-removable disk";
1878 		texts[0x02] = "Removable disk";
1879 		texts[0x03] = "MO erasable";
1880 		texts[0x04] = "Optical write once";
1881 		texts[0x05] = "AS-MO";
1882 		texts[0x08] = "CD-ROM";
1883 		texts[0x09] = "CD-R";
1884 		texts[0x0a] = "CD-RW";
1885 		texts[0x10] = "DVD-ROM";
1886 		texts[0x11] = "DVD-R sequential recording";
1887 		texts[0x12] = "DVD-RAM";
1888 		texts[0x13] = "DVD-RW restricted overwrite";
1889 		texts[0x14] = "DVD-RW sequential recording";
1890 		texts[0x15] = "DVD-R/DL sequential recording";
1891 		texts[0x16] = "DVD-R/DL layer jump recording";
1892 		texts[0x1a] = "DVD+RW";
1893 		texts[0x1b] = "DVD+R";
1894 		texts[0x2a] = "DVD+RW/DL";
1895 		texts[0x2b] = "DVD+R/DL";
1896 		texts[0x40] = "BD-ROM";
1897 		texts[0x41] = "BD-R sequential recording";
1898 		texts[0x42] = "BD-R random recording";
1899 		texts[0x43] = "BD-RE";
1900 		texts[0x50] = "HD-DVD-ROM";
1901 		texts[0x51] = "HD-DVD-R";
1902 		texts[0x52] = "HD-DVD-RAM";
1903 	}
1904 	if (profile_number<0 || profile_number>=max_pno)
1905 		return "";
1906 	return texts[profile_number];
1907 }
1908 
1909 
1910 /* ts A90603 : to be used if the drive knows no GET CONFIGURATION
1911 */
1912 static int mmc_guess_profile(struct burn_drive *d, int flag)
1913 {
1914 	int cp;
1915 
1916 	cp = 0;
1917 	if (d->status == BURN_DISC_BLANK ||
1918 	    d->status == BURN_DISC_APPENDABLE) {
1919 		cp = 0x09;
1920 	} else if (d->status == BURN_DISC_FULL) {
1921 		cp = 0x08;
1922 	}
1923 	if (cp)
1924 		if (d->erasable)
1925 			cp = 0x0a;
1926 	d->current_profile = cp;
1927 	if (cp == 0)
1928 		return 0;
1929 	d->current_is_cd_profile = 1;
1930 	d->current_is_supported_profile = 1;
1931 	strcpy(d->current_profile_text, mmc_obtain_profile_name(cp));
1932 	return 1;
1933 }
1934 
1935 
1936 static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
1937 {
1938 	struct buffer *buf = NULL;
1939 	unsigned char *data;
1940 	struct command *c = NULL;
1941 	char *msg = NULL;
1942 	/* ts A70131 : had to move mmc_read_toc() to end of function */
1943 	int do_read_toc = 0, disc_status, len, old_alloc_len;
1944 	int ret, number_of_sessions = -1;
1945 	int key, asc, ascq;
1946 
1947 	BURN_ALLOC_MEM(buf, struct buffer, 1);
1948 	BURN_ALLOC_MEM(c, struct command, 1);
1949 
1950 	/* ts A61020 */
1951 	d->start_lba = d->end_lba = -2000000000;
1952 	d->erasable = 0;
1953 	d->last_track_no = 1;
1954 
1955 	/* ts B10730 */
1956 	d->sent_default_page_05 = 0;
1957 	/* ts A70212 - A70215 */
1958 	d->media_capacity_remaining = 0;
1959 	d->media_lba_limit = 0;
1960 
1961 	/* ts A81210 */
1962 	d->media_read_capacity = 0x7fffffff;
1963 	d->mr_capacity_trusted = -1;
1964 
1965 	/* ts A61202 */
1966 	d->toc_entries = 0;
1967 	if (d->status == BURN_DISC_EMPTY)
1968 		{ret = 1; goto ex;}
1969 
1970 	mmc_get_configuration(d);
1971 
1972 	scsi_init_command(c, MMC_GET_DISC_INFO, sizeof(MMC_GET_DISC_INFO));
1973 	c->dxfer_len = *alloc_len;
1974 	c->opcode[7]= (c->dxfer_len >> 8) & 0xff;
1975 	c->opcode[8]= c->dxfer_len & 0xff;
1976 	c->retry = 1;
1977 	c->page = buf;
1978 	c->page->sectors = 0;
1979 	c->page->bytes = 0;
1980 	c->dir = FROM_DRIVE;
1981 	d->issue_command(d, c);
1982 
1983 	if (c->error) {
1984 		spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
1985 		if (key == 5 && asc == 0x20 && ascq == 0) {
1986 			/* ts B11031 : qemu -cdrom does not know
1987 			               051h  READ DISC INFORMATION
1988 			*/
1989 			ret = mmc_read_toc_fmt0(d);
1990 			if (ret > 0) {
1991 
1992 				/* >>> ??? anything more to be set ? */;
1993 
1994 				mmc_read_capacity(d);
1995 				*alloc_len = 0;
1996 				goto ex;
1997 			}
1998 		}
1999 
2000 		d->busy = BURN_DRIVE_IDLE;
2001 		{ret = 0; goto ex;}
2002 	}
2003 
2004 	data = c->page->data;
2005 	len = (data[0] << 8) | data[1];
2006 	old_alloc_len = *alloc_len;
2007 	*alloc_len = len + 2;
2008 	if (old_alloc_len < 34)
2009 		{ret = 1; goto ex;}
2010 	if (*alloc_len < 24) /* data[23] is the last mandatory byte here */
2011 		{ret = 0; goto ex;}
2012 	if (len + 2 > old_alloc_len)
2013 		len = old_alloc_len - 2;
2014 
2015 	d->erasable = !!(data[2] & 16);
2016 
2017 	/* ts A90908 */
2018 	d->disc_type = data[8];
2019 	d->disc_info_valid = 1;
2020 	d->disc_id = mmc_four_char_to_int(data + 12);
2021 	d->disc_info_valid |= (!!(data[7] & 128)) << 1;
2022 	if (len + 2 > 31 && (data[7] & 64)) {
2023 		memcpy(d->disc_bar_code, data + 24, 8);
2024 		d->disc_bar_code[8] = 0;
2025 		d->disc_info_valid |= 4;
2026 	}
2027 	if (len + 2 > 32 && (data[7] & 16)) {
2028 		d->disc_app_code = data[32];
2029 		d->disc_info_valid |= 8;
2030 	}
2031 	if (data[7] & 32)
2032 		d->disc_info_valid |= 16;
2033 	if (data[2] & 16)
2034 		d->disc_info_valid |= 32;
2035 
2036  	disc_status = data[2] & 3;
2037 	d->state_of_last_session = (data[2] >> 2) & 3;
2038 	number_of_sessions = (data[9] << 8) | data[4];
2039 
2040 	if (d->current_profile == 0x10 || d->current_profile == 0x40) {
2041 							 /* DVD-ROM , BD-ROM */
2042 		disc_status = 2; /* always full and finalized */
2043 		d->erasable = 0; /* never erasable */
2044 	}
2045 
2046 #ifdef Libburn_support_bd_r_readonlY
2047 	/* <<< For now: declaring BD-R read-only
2048 	*/
2049 #ifndef Libburn_support_bd_plus_r_srM
2050 	if (d->current_profile == 0x41) {
2051 					/* BD-R seq as readonly dummy */
2052 		disc_status = 2; /* always full and finalized */
2053 		d->erasable = 0; /* never erasable */
2054 	}
2055 #endif
2056 	if (d->current_profile == 0x42) {
2057 						 /* BD-R rnd */
2058 		disc_status = 2; /* always full and finalized */
2059 		d->erasable = 0; /* never erasable */
2060 	}
2061 #endif /* Libburn_support_bd_r_readonlY */
2062 
2063 	/* MMC-5 6.22.3.1.16:
2064 	   Last Session Lead-in Start Address bytes 16 to 19
2065 	   Last Possible Lead-out Start Address bytes 20 to 23
2066 	   MSF for CD, LBA else
2067 	*/
2068 	if(d->current_profile == 0x08 || d->current_profile == 0x09 ||
2069 	   d->current_profile == 0x0a) {
2070 		d->last_lead_in =
2071 			burn_msf_to_lba(data[17], data[18], data[19]);
2072 		d->last_lead_out =
2073 			burn_msf_to_lba(data[21], data[22], data[23]);
2074 	} else {
2075 		d->last_lead_in = mmc_four_char_to_int(data + 16);
2076 		d->last_lead_out = mmc_four_char_to_int(data + 20);
2077 	}
2078 
2079 	switch (disc_status) {
2080 	case 0:
2081 regard_as_blank:;
2082 		d->toc_entries = 0;
2083 
2084 /*
2085 		fprintf(stderr, "libburn_experimental: start_lba = %d (%d %d %d) , end_lba = %d (%d %d %d)\n",
2086 			d->start_lba, data[17], data[18], data[19],
2087 			d->end_lba, data[21], data[22], data[23]);
2088 */
2089 
2090 		d->status = BURN_DISC_BLANK;
2091 		d->start_lba = d->last_lead_in;
2092 		d->end_lba = d->last_lead_out;
2093 		break;
2094 	case 1:
2095 	case 2:
2096 		if (disc_status == 2)
2097 			d->status = BURN_DISC_FULL;
2098 		else
2099 			d->status = BURN_DISC_APPENDABLE;
2100 
2101 		/* ts A81210 */
2102 		ret = mmc_read_capacity(d);
2103 		/* Freshly formatted, unwritten BD-R pretend to be appendable
2104 		   but in our model they need to be regarded as blank.
2105 		   Criterion: BD-R seq, read capacity known and 0,
2106 		              declared appendable, single empty session
2107 		*/
2108 		if (d->current_profile == 0x41 &&
2109 		    d->status == BURN_DISC_APPENDABLE &&
2110 		    ret > 0 && d->media_read_capacity == 0 &&
2111 		    d->state_of_last_session == 0 && number_of_sessions == 1)
2112 			goto regard_as_blank;
2113 
2114 		if (d->current_profile == 0x41 &&
2115 		    d->status == BURN_DISC_APPENDABLE &&
2116 		    d->state_of_last_session == 1) {
2117 
2118 			/* ??? apply this test to other media types ? */
2119 
2120 			libdax_msgs_submit(libdax_messenger, d->global_index,
2121 				 0x00020169,
2122 				 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
2123 				 "Last session on media is still open.", 0, 0);
2124 		}
2125 
2126 		do_read_toc = 1;
2127 		break;
2128 	case 3:
2129 		/* ts A91009 : DVD-RAM has disc status "others" */
2130 		mmc_read_capacity(d);
2131 		break;
2132 	}
2133 
2134 	/* ts A90603 : An MMC-1 drive might not know the media type yet */
2135 	if (d->current_is_guessed_profile && d->current_profile == 0)
2136 		mmc_guess_profile(d, 0);
2137 
2138 	if ((d->current_profile != 0 || d->status != BURN_DISC_UNREADY)
2139 		&& ! d->current_is_supported_profile) {
2140 		if (!(d->silent_on_scsi_error == 1 ||
2141 		      d->silent_on_scsi_error == 2)) {
2142 			msg = calloc(1, 160);
2143 			if (msg != NULL) {
2144 				sprintf(msg,
2145 				"Unsuitable media detected. Profile %4.4Xh  %s",
2146 				d->current_profile, d->current_profile_text);
2147 				libdax_msgs_submit(libdax_messenger,
2148 					d->global_index, 0x0002011e,
2149 					d->silent_on_scsi_error == 3 ?
2150 					  LIBDAX_MSGS_SEV_DEBUG :
2151 					  LIBDAX_MSGS_SEV_SORRY,
2152 					LIBDAX_MSGS_PRIO_HIGH, msg, 0,0);
2153 				free(msg);
2154 			}
2155 		}
2156 		d->status = BURN_DISC_UNSUITABLE;
2157 		{ret = 0; goto ex;}
2158 	}
2159 
2160 	/* ts A61217 :
2161 	   growisofs performs OPC if (data[0]<<8)|data[1]<=32
2162 	   which indicates no OPC entries are attached to the
2163 	   reply from the drive.
2164 	   ts A91104 :
2165 	   Actually growisofs performs OPC only on DVD-R[W].
2166 	*/
2167 	d->num_opc_tables = 0;
2168 	if(((data[0] << 8) | data[1]) > 32) /* i.e. > 34 bytes are available */
2169 		d->num_opc_tables = data[33];
2170 
2171 	/* ts A61219 : mmc5r03c.pdf 6.22.3.1.13 BG Format Status
2172 	   0=blank (not yet started)
2173            1=started but neither running nor complete
2174 	   2=in progress
2175 	   3=completed
2176 	*/
2177 	d->bg_format_status = data[7] & 3;
2178 
2179 	/* Preliminarily declare blank:
2180 	   ts A61219 : DVD+RW (is not bg_format_status==0 "blank")
2181 	   ts A61229 : same for DVD-RW Restricted overwrite
2182 	   ts A70112 : same for DVD-RAM
2183 	*/
2184 	if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
2185 	    d->current_profile == 0x12 || d->current_profile == 0x43)
2186 		d->status = BURN_DISC_BLANK;
2187 
2188 #ifdef Libburn_disc_with_incomplete_sessioN
2189 	/* ts B30112 : number of open sessions */
2190 	d->incomplete_sessions = 0;
2191 #endif
2192 
2193 	if (d->status == BURN_DISC_BLANK) {
2194                 d->last_track_no = 1; /* The "incomplete track" */
2195 		d->complete_sessions = 0;
2196 	} else {
2197 		/* ts A70131 : number of closed sessions */
2198 		d->complete_sessions = number_of_sessions;
2199 		/* mmc5r03c.pdf 6.22.3.1.3 State of Last Session: 3=complete */
2200 		if (d->state_of_last_session != 3 &&
2201 		    d->complete_sessions >= 1) {
2202 			d->complete_sessions--;
2203 
2204 #ifdef Libburn_disc_with_incomplete_sessioN
2205 			d->incomplete_sessions++;
2206 #endif
2207 
2208 		}
2209 
2210 		/* ts A70129 : mmc5r03c.pdf 6.22.3.1.7
2211 		   This includes the "incomplete track" if the disk is
2212 		   appendable. I.e number of complete tracks + 1. */
2213 		d->last_track_no = (data[11] << 8) | data[6];
2214 	}
2215 	if (d->current_profile != 0x0a && d->current_profile != 0x13 &&
2216 	    d->current_profile != 0x14 && d->status != BURN_DISC_FULL)
2217 		d->erasable = 0; /* stay in sync with burn_disc_erase() */
2218 
2219 	if (do_read_toc)
2220 		mmc_read_toc(d);
2221 	ret = 1;
2222 ex:
2223 	BURN_FREE_MEM(buf);
2224 	BURN_FREE_MEM(c);
2225 	return ret;
2226 }
2227 
2228 
2229 void mmc_read_disc_info(struct burn_drive *d)
2230 {
2231 	int alloc_len = 34, ret;
2232 
2233 	mmc_start_if_needed(d, 1);
2234 	if (mmc_function_spy(d, "mmc_read_disc_info") <= 0)
2235 		return;
2236 
2237 	ret = mmc_read_disc_info_al(d, &alloc_len);
2238 /*
2239 	fprintf(stderr,"LIBBURN_DEBUG: 51h alloc_len = %d , ret = %d\n",
2240 			alloc_len, ret);
2241 */
2242 	if (ret <= 0)
2243 		return;
2244 
2245 	/* for now there is no need to inquire the variable length part */
2246 }
2247 
2248 
2249 /* @param flag bit= do not allocate text_packs
2250 */
2251 static int mmc_get_leadin_text_al(struct burn_drive *d,
2252                                   unsigned char **text_packs, int *alloc_len,
2253                                   int flag)
2254 {
2255 	struct buffer *buf = NULL;
2256 	struct command *c = NULL;
2257 	unsigned char *data;
2258 	int ret, data_length;
2259 
2260 	*text_packs = NULL;
2261 
2262 	BURN_ALLOC_MEM(buf, struct buffer, 1);
2263 	BURN_ALLOC_MEM(c, struct command, 1);
2264 
2265 	scsi_init_command(c, MMC_GET_LEADTEXT, sizeof(MMC_GET_LEADTEXT));
2266 	c->dxfer_len = *alloc_len;
2267 	c->opcode[7]= (c->dxfer_len >> 8) & 0xff;
2268 	c->opcode[8]= c->dxfer_len & 0xff;
2269 	c->retry = 1;
2270 	c->page = buf;
2271 	c->page->bytes = 0;
2272 	c->page->sectors = 0;
2273 
2274 	c->dir = FROM_DRIVE;
2275 	d->issue_command(d, c);
2276 	if (c->error)
2277 		{ret = 0; goto ex;}
2278 
2279 	data = c->page->data;
2280 	data_length = (data[0] << 8) + data[1];
2281 	*alloc_len = data_length + 2;
2282 	if (*alloc_len >= 22 && !(flag & 1)) {
2283 		BURN_ALLOC_MEM(*text_packs, unsigned char, *alloc_len - 4);
2284 		memcpy(*text_packs, data + 4, *alloc_len - 4);
2285 	}
2286 	ret = 1;
2287 ex:;
2288 	BURN_FREE_MEM(c);
2289 	BURN_FREE_MEM(buf);
2290 	return ret;
2291 }
2292 
2293 
2294 /* ts B11201 */
2295 /* Read the CD-TEXT data from the Lead-in of an Audio CD
2296 */
2297 int mmc_get_leadin_text(struct burn_drive *d,
2298                         unsigned char **text_packs, int *num_packs, int flag)
2299 {
2300 	int alloc_len = 4, ret;
2301 
2302 	*num_packs = 0;
2303 	if (mmc_function_spy(d, "mmc_get_leadin_text") <= 0)
2304 		return -1;
2305 	ret = mmc_get_leadin_text_al(d, text_packs, &alloc_len, 1);
2306 	if (ret <= 0 || alloc_len < 22)
2307 		return (ret > 0 ? 0 : ret);
2308 	ret = mmc_get_leadin_text_al(d, text_packs, &alloc_len, 0);
2309 	if (ret <= 0 || alloc_len < 22) {
2310 		if (*text_packs != NULL)
2311 			free(*text_packs);
2312 		*text_packs = NULL;
2313 		return (ret > 0 ? 0 : ret);
2314 	}
2315 	*num_packs = (alloc_len - 4) / 18;
2316 	return ret;
2317 }
2318 
2319 
2320 void mmc_read_atip(struct burn_drive *d)
2321 {
2322 	struct buffer *buf = NULL;
2323 	struct command *c = NULL;
2324 	int alloc_len = 28;
2325 
2326 	/* ts A61021 */
2327 	unsigned char *data;
2328 	/* Speed values from A1:
2329 	   With 4 cdrecord tells "10" or "8" where MMC-1 says "8".
2330 	   cdrecord "8" appear on 4xCD-RW and thus seem to be quite invalid.
2331 	   My CD-R (>=24 speed) tell no A1.
2332 	   The higher non-MMC-1 values are hearsay.
2333 	*/
2334 	                          /*  0,   2,   4,    6,   10,  -,   16,  -, */
2335         static int speed_value[16]= { 0, 353, 706, 1059, 1764, -5, 2824, -7,
2336 	                   4234, 5646, 7056, 8468, -12, -13, -14, -15};
2337 	               /*    24,   32,   40,   48,   -,   -,   -,   - */
2338 
2339 	BURN_ALLOC_MEM_VOID(buf, struct buffer, 1);
2340 	BURN_ALLOC_MEM_VOID(c, struct command, 1);
2341 	mmc_start_if_needed(d, 1);
2342 	if (mmc_function_spy(d, "mmc_read_atip") <= 0)
2343 		goto ex;
2344 
2345 	scsi_init_command(c, MMC_GET_ATIP, sizeof(MMC_GET_ATIP));
2346 	c->dxfer_len = alloc_len;
2347 	c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
2348 	c->opcode[8] = c->dxfer_len & 0xff;
2349 	c->retry = 1;
2350 	c->page = buf;
2351 	c->page->bytes = 0;
2352 	c->page->sectors = 0;
2353 
2354 	c->dir = FROM_DRIVE;
2355 	d->issue_command(d, c);
2356 	/* ts B00501 : now caring for error */
2357 	if (c->error) {
2358 		d->erasable = 0;
2359 		d->start_lba = 0;
2360 		d->end_lba = 0;
2361 		goto ex;
2362 	}
2363 
2364 	/* ts A61021 */
2365 	data = c->page->data;
2366 	d->erasable = !!(data[6]&64);
2367 	d->start_lba = burn_msf_to_lba(data[8],data[9],data[10]);
2368 	d->end_lba = burn_msf_to_lba(data[12],data[13],data[14]);
2369 
2370 	/* ts B21124 : LITE-ON LTR-48125S returns crap on pressed
2371 	               audio CD and CD-ROM
2372 	*/
2373 	if (d->start_lba >= d->end_lba) {
2374 		d->start_lba = 0;
2375 		d->end_lba = 0;
2376 	}
2377 
2378 	if (data[6]&4) {
2379 		if (speed_value[(data[16]>>4)&7] > 0) {
2380 			d->mdata->min_write_speed =
2381 				speed_value[(data[16]>>4)&7];
2382 			if (speed_value[(data[16])&15] <= 0)
2383 				d->mdata->max_write_speed =
2384 					speed_value[(data[16]>>4)&7];
2385 		}
2386 		if (speed_value[(data[16])&15] > 0) {
2387 			d->mdata->max_write_speed =
2388 				speed_value[(data[16])&15];
2389 			if (speed_value[(data[16]>>4)&7] <= 0)
2390 				d->mdata->min_write_speed =
2391 					speed_value[(data[16])&15];
2392 		}
2393 	}
2394 
2395 #ifdef Burn_mmc_be_verbous_about_atiP
2396 	{ int i;
2397 	fprintf(stderr,"libburn_experimental: Returned ATIP Data\n");
2398 	for(i= 0; i<28; i++)
2399 		fprintf(stderr,"%3.3d (0x%2.2x)%s",
2400 			data[i],data[i],(((i + 1) % 5) ? "  " : "\n"));
2401 	fprintf(stderr,"\n");
2402 
2403 	fprintf(stderr,
2404 		"libburn_experimental: Indicative Target Writing Power= %d\n",
2405 		(data[4]>>4)&7);
2406 	fprintf(stderr,
2407 		"libburn_experimental: Reference speed= %d ->%d\n",
2408 		data[4]&7, speed_value[data[4]&7]);
2409 	fprintf(stderr,
2410 		"libburn_experimental: Is %sunrestricted\n",
2411 		(data[5]&64?"":"not "));
2412 	fprintf(stderr,
2413 		"libburn_experimental: Is %serasable, sub-type %d\n",
2414 		(data[6]&64?"":"not "),(data[6]>>3)&3);
2415 	fprintf(stderr,
2416 		"libburn_experimental: lead in: %d (%-2.2d:%-2.2d/%-2.2d)\n",
2417 		burn_msf_to_lba(data[8],data[9],data[10]),
2418 		data[8],data[9],data[10]);
2419 	fprintf(stderr,
2420 		"libburn_experimental: lead out: %d (%-2.2d:%-2.2d/%-2.2d)\n",
2421 		burn_msf_to_lba(data[12],data[13],data[14]),
2422 		data[12],data[13],data[14]);
2423 	if(data[6]&4)
2424 	  fprintf(stderr,
2425 		"libburn_experimental: A1 speed low %d   speed high %d\n",
2426 		speed_value[(data[16]>>4)&7], speed_value[(data[16])&7]);
2427 	if(data[6]&2)
2428 	  fprintf(stderr,
2429 		"libburn_experimental: A2 speed low %d   speed high %d\n",
2430 		speed_value[(data[20]>>4)&7], speed_value[(data[20])&7]);
2431 	if(data[6]&1)
2432 	  fprintf(stderr,
2433 		"libburn_experimental: A3 speed low %d   speed high %d\n",
2434 		speed_value[(data[24]>>4)&7], speed_value[(data[24])&7]);
2435 	}
2436 
2437 #endif /* Burn_mmc_be_verbous_about_atiP */
2438 
2439 /* ts A61020
2440 http://www.t10.org/ftp/t10/drafts/mmc/mmc-r10a.pdf , table 77 :
2441 
2442  0 ATIP Data Length MSB
2443  1 ATIP Data Length LSB
2444  2 Reserved
2445  3 Reserved
2446  4 bit7=1, bit4-6="Indicative Target Writing Power", bit3=reserved ,
2447    bit0-2="Reference speed"
2448  5 bit7=0, bit6="URU" , bit0-5=reserved
2449  6 bit7=1, bit6="Disc Type", bit3-4="Disc Sub-Type",
2450    bit2="A1", bit1="A2", bit0="A3"
2451  7 reserved
2452  8 ATIP Start Time of lead-in (Min)
2453  9 ATIP Start Time of lead-in (Sec)
2454 10 ATIP Start Time of lead-in (Frame)
2455 11 reserved
2456 12 ATIP Last Possible Start Time of lead-out (Min)
2457 13 ATIP Last Possible Start Time of lead-out (Sec)
2458 14 ATIP Last Possible Start Time of lead-out (Frame)
2459 15 reserved
2460 16 bit7=0, bit4-6="Lowest Usable CLV Recording speed"
2461    bit0-3="Highest Usable CLV Recording speed"
2462 17 bit7=0, bit4-6="Power Multiplication Factor p",
2463    bit1-3="Target y value of the Modulation/Power function", bit0=reserved
2464 18 bit7=1, bit4-6="Recommended Erase/Write Power Ratio (P(inf)/W(inf))"
2465    bit0-3=reserved
2466 19 reserved
2467 20-22 A2 Values
2468 23 reserved
2469 24-26 A3 Values
2470 27 reserved
2471 
2472 Disc Type - zero indicates CD-R media; one indicates CD-RW media.
2473 
2474 Disc Sub-Type - shall be set to zero.
2475 
2476 A1 - when set to one, indicates that bytes 16-18 are valid.
2477 
2478 Lowest Usable CLV Recording Speed
2479 000b Reserved
2480 001b 2X
2481 010b - 111b Reserved
2482 
2483 Highest CLV Recording Speeds
2484 000b Reserved
2485 001b 2X
2486 010b 4X
2487 011b 6X
2488 100b 8X
2489 101b - 111b Reserved
2490 
2491 MMC-3 seems to recommend MODE SENSE (5Ah) page 2Ah rather than A1, A2, A3.
2492 This page is loaded in libburn function  spc_sense_caps() .
2493 Speed is given in kbytes/sec there. But i suspect this to be independent
2494 of media. So one would habe to associate the speed descriptor blocks with
2495 the ATIP media characteristics ? How ?
2496 
2497 */
2498 
2499 ex:;
2500 	BURN_FREE_MEM(buf);
2501 	BURN_FREE_MEM(c);
2502 }
2503 
2504 
2505 int mmc_eval_read_error(struct burn_drive *d, struct command *c, char *what,
2506                         int start_m, int start_s, int start_f,
2507                         int end_m, int end_s, int end_f, int flag)
2508 {
2509 	char *msg = NULL;
2510 	int key, asc, ascq, silent;
2511 
2512 	if (!c->error)
2513 		return 0;
2514 
2515 	msg = calloc(1, 256);
2516 	if (msg != NULL) {
2517 		if (start_s < 0 || start_f < 0 || end_s < 0 || end_f < 0) {
2518 			sprintf(msg,
2519 		           "SCSI error on %s(%d,%d): ", what, start_m, end_m);
2520 		} else {
2521 			sprintf(msg, "SCSI error on %s(%dm%ds%df,%dm%ds%df): ",
2522 			      what,
2523 			      start_m, start_s, start_f, end_m, end_s, end_f);
2524 		}
2525 		scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
2526 				&key, &asc, &ascq);
2527 		silent = (d->silent_on_scsi_error == 1);
2528 		if (key == 5 && asc == 0x64 && ascq == 0x0) {
2529 			d->had_particular_error |= 1;
2530 			if (d->silent_on_scsi_error == 2)
2531 				silent = 1;
2532 		}
2533 		if(!silent)
2534 			libdax_msgs_submit(libdax_messenger,
2535 				d->global_index,
2536 				0x00020144,
2537 				d->silent_on_scsi_error == 3 ?
2538 				 LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
2539 				LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
2540 		free(msg);
2541 	}
2542 	return BE_CANCELLED;
2543 }
2544 
2545 
2546 /* ts B21119 : Derived from older mmc_read_sectors()
2547    @param flag bit0= set DAP bit (also with o->dap_bit)
2548 */
2549 int mmc_read_cd_msf(struct burn_drive *d,
2550 		int start_m, int start_s, int start_f,
2551 		int end_m, int end_s, int end_f,
2552 		int sec_type, int main_ch,
2553 		const struct burn_read_opts *o, struct buffer *buf, int flag)
2554 {
2555 	int req, ret, dap_bit;
2556 	int subcodes_audio = 0, subcodes_data = 0;
2557 	struct command *c;
2558 #ifdef Libburn_mmc_report_recovereD
2559 	int report_recovered_errors = 0;
2560 #endif
2561 
2562 	c = &(d->casual_command);
2563 	mmc_start_if_needed(d, 0);
2564 	if (mmc_function_spy(d, "mmc_read_cd_msf") <= 0)
2565 		return -1;
2566 
2567 	dap_bit = flag & 1;
2568 	if (o != NULL) {
2569 		subcodes_audio = o->subcodes_audio;
2570 		subcodes_data = o->subcodes_data;
2571 		dap_bit |= o->dap_bit;
2572 
2573 #ifdef Libburn_mmc_report_recovereD
2574 		report_recovered_errors = o->report_recovered_errors;
2575 #endif
2576 	}
2577 
2578 	scsi_init_command(c, MMC_READ_CD_MSF, sizeof(MMC_READ_CD_MSF));
2579 	c->retry = 1;
2580 	c->opcode[1] = ((sec_type & 7) << 2) | ((!!dap_bit) << 1);
2581 	c->opcode[3] = start_m;
2582 	c->opcode[4] = start_s;
2583 	c->opcode[5] = start_f;
2584 	c->opcode[6] = end_m;
2585 	c->opcode[7] = end_s;
2586 	c->opcode[8] = end_f;
2587 
2588 	req = main_ch & 0xf8;
2589 
2590 #ifdef Libburn_mmc_report_recovereD
2591 	/* ts A61106 : LG GSA-4082B dislikes this. key=5h asc=24h ascq=00h */
2592 	if (d->busy == BURN_DRIVE_GRABBING || report_recovered_errors)
2593 		req |= 2;
2594 #endif /* Libburn_mmc_report_recovereD */
2595 
2596 	c->opcode[9] = req;
2597 
2598 	c->opcode[10] = 0;
2599 /* always read the subcode, throw it away later, since we don't know
2600    what we're really reading
2601 */
2602 /* >>> ts B21125 : This is very obscure:
2603                    MMC-3 has sub channel selection 001b as "RAW"
2604                    MMC-5 does neither mention 001b nor "RAW".
2605                    And why should a non-grabbed drive get here ?
2606 */
2607 	if (d->busy == BURN_DRIVE_GRABBING || subcodes_audio || subcodes_data)
2608 		c->opcode[10] = 1;
2609 
2610 /* <<< ts B21125 : test with sub channel selection 100b
2611                    no data, only sub channel
2612 	c->opcode[9] = 0;
2613 	c->opcode[10] = 4;
2614 	Did not help either with reading before LBA -150
2615 */
2616 /* <<< ts B21125 : test with sub channel selection 001b and no user data
2617 	c->opcode[9] = 0;
2618 	c->opcode[10] = 1;
2619 */
2620 
2621 	c->page = buf;
2622 	c->dir = FROM_DRIVE;
2623 	d->issue_command(d, c);
2624 	ret = mmc_eval_read_error(d, c, "read_cd_msf",
2625 	                          start_m, start_s, start_f,
2626 				  end_m, end_s, end_f, 0);
2627 	return ret;
2628 }
2629 
2630 
2631 /* ts B21119 : Derived from older mmc_read_sectors()
2632    @param flag bit0= set DAP bit (also with o->dap_bit)
2633 */
2634 int mmc_read_cd(struct burn_drive *d, int start, int len,
2635                 int sec_type, int main_ch,
2636 		const struct burn_read_opts *o, struct buffer *buf, int flag)
2637 {
2638 	int temp, req, ret, dap_bit;
2639 	int subcodes_audio = 0, subcodes_data = 0;
2640 	struct command *c;
2641 
2642 #ifdef Libburn_mmc_report_recovereD
2643 	int report_recovered_errors = 0;
2644 #endif
2645 
2646 /* # define Libburn_read_cd_by_msF 1 */
2647 #ifdef Libburn_read_cd_by_msF
2648 
2649 	int start_m, start_s, start_f, end_m, end_s, end_f;
2650 
2651 	burn_lba_to_msf(start, &start_m, &start_s, &start_f);
2652 	burn_lba_to_msf(start + len, &end_m, &end_s, &end_f);
2653 	ret = mmc_read_cd_msf(d, start_m, start_s, start_f,
2654 	                      end_m, end_s, end_f,
2655 	                      sec_type, main_ch, o, buf, flag);
2656 	return ret;
2657 
2658 #endif /* Libburn_read_cd_by_msF */
2659 
2660 	c = &(d->casual_command);
2661 	mmc_start_if_needed(d, 0);
2662 	if (mmc_function_spy(d, "mmc_read_cd") <= 0)
2663 		return -1;
2664 
2665 	dap_bit = flag & 1;
2666 	if (o != NULL) {
2667 		subcodes_audio = o->subcodes_audio;
2668 		subcodes_data = o->subcodes_data;
2669 		dap_bit |= o->dap_bit;
2670 
2671 #ifdef Libburn_mmc_report_recovereD
2672 		report_recovered_errors = o->report_recovered_errors;
2673 #endif
2674 	}
2675 
2676 	scsi_init_command(c, MMC_READ_CD, sizeof(MMC_READ_CD));
2677 	c->retry = 1;
2678 	c->opcode[1] = ((sec_type & 7) << 2) | ((!!dap_bit) << 1);
2679 	temp = start;
2680 	c->opcode[5] = temp & 0xFF;
2681 	temp >>= 8;
2682 	c->opcode[4] = temp & 0xFF;
2683 	temp >>= 8;
2684 	c->opcode[3] = temp & 0xFF;
2685 	temp >>= 8;
2686 	c->opcode[2] = temp & 0xFF;
2687 	c->opcode[8] = len & 0xFF;
2688 	len >>= 8;
2689 	c->opcode[7] = len & 0xFF;
2690 	len >>= 8;
2691 	c->opcode[6] = len & 0xFF;
2692 	req = main_ch & 0xf8;
2693 
2694 #ifdef Libburn_mmc_report_recovereD
2695 	/* ts A61106 : LG GSA-4082B dislikes this. key=5h asc=24h ascq=00h */
2696 	if (d->busy == BURN_DRIVE_GRABBING || report_recovered_errors)
2697 		req |= 2;
2698 #endif /* Libburn_mmc_report_recovereD */
2699 
2700 	c->opcode[9] = req;
2701 	c->opcode[10] = 0;
2702 /* always read the subcode, throw it away later, since we don't know
2703    what we're really reading
2704 */
2705 /* >>> ts B21125 : This is very obscure:
2706                    MMC-3 has sub channel selection 001b as "RAW"
2707                    MMC-5 does neither mention 001b nor "RAW".
2708                    And why should a non-grabbed drive get here ?
2709 */
2710 	if (d->busy == BURN_DRIVE_GRABBING || subcodes_audio || subcodes_data)
2711 		c->opcode[10] = 1;
2712 
2713 /* <<< ts B21125 : test with sub channel selection 100b
2714 	c->opcode[10] = 4;
2715 */
2716 /* <<< ts B21125 : test with sub channel selection 001b and no user data
2717 	c->opcode[9] = 0;
2718 	c->opcode[10] = 1;
2719 */
2720 
2721 	c->page = buf;
2722 	c->dir = FROM_DRIVE;
2723 	d->issue_command(d, c);
2724 	ret = mmc_eval_read_error(d, c, "read_cd", start, -1, -1,
2725 	                          len, -1, -1, 0);
2726 	return ret;
2727 }
2728 
2729 void mmc_erase(struct burn_drive *d, int fast)
2730 {
2731 	struct command *c;
2732 
2733 	c = &(d->casual_command);
2734 	mmc_start_if_needed(d, 0);
2735 	if (mmc_function_spy(d, "mmc_erase") <= 0)
2736 		return;
2737 
2738 	scsi_init_command(c, MMC_BLANK, sizeof(MMC_BLANK));
2739 	if (!d->do_no_immed)
2740 		c->opcode[1] = 16;	/* IMMED set to 1 */
2741 	c->opcode[1] |= !!fast;
2742 	c->retry = 1;
2743 	c->page = NULL;
2744 	c->dir = NO_TRANSFER;
2745 	if (d->do_no_immed)
2746 		c->timeout = Libburn_mmc_blank_noim_timeouT;
2747 	else
2748 		c->timeout = Libburn_mmc_blank_timeouT;
2749 	d->issue_command(d, c);
2750 	if (c->error) {
2751 		d->cancel = 1;
2752 		scsi_notify_error(d, c, c->sense, 14, 2);
2753 	}
2754 }
2755 
2756 void mmc_read_lead_in(struct burn_drive *d, struct buffer *buf)
2757 {
2758 	struct command *c;
2759 
2760 	c = &(d->casual_command);
2761 	mmc_start_if_needed(d, 0);
2762 	if (mmc_function_spy(d, "mmc_read_lead_in") <= 0)
2763 		return;
2764 
2765 	scsi_init_command(c, MMC_READ_CD, sizeof(MMC_READ_CD));
2766 	c->retry = 1;
2767 	c->opcode[5] = 0;
2768 	c->opcode[4] = 0;
2769 	c->opcode[3] = 0;
2770 	c->opcode[2] = 0xF0;
2771 	c->opcode[8] = 1;
2772 	c->opcode[7] = 0;
2773 	c->opcode[6] = 0;
2774 	c->opcode[9] = 0;
2775 	c->opcode[10] = 2;
2776 	c->page = buf;
2777 	c->dir = FROM_DRIVE;
2778 	d->issue_command(d, c);
2779 }
2780 
2781 void mmc_perform_opc(struct burn_drive *d)
2782 {
2783 	struct command *c;
2784 
2785 	c = &(d->casual_command);
2786 	mmc_start_if_needed(d, 0);
2787 	if (mmc_function_spy(d, "mmc_perform_opc") <= 0)
2788 		return;
2789 
2790 	scsi_init_command(c, MMC_SEND_OPC, sizeof(MMC_SEND_OPC));
2791 	c->retry = 1;
2792 	c->opcode[1] = 1;
2793 	c->page = NULL;
2794 	c->dir = NO_TRANSFER;
2795 	c->timeout = Libburn_mmc_opc_timeouT;
2796 	d->issue_command(d, c);
2797 }
2798 
2799 
2800 /* ts A61221 : Learned much from dvd+rw-tools-7.0 set_speed_B6h() but then
2801    made own experiments on base of mmc5r03c.pdf 6.8.3 and 6.39 in the hope
2802    to achieve a leaner solution
2803    ts A70712 : That leaner solution does not suffice for my LG GSA-4082B.
2804    Meanwhile there is a speed descriptor list anyway.
2805 */
2806 int mmc_set_streaming(struct burn_drive *d,
2807 			 int r_speed, int w_speed, int end_lba)
2808 {
2809 	struct buffer *buf = NULL;
2810 	struct command *c = NULL;
2811 	int b, eff_end_lba, ret;
2812 	char *msg = NULL;
2813 	unsigned char *pd;
2814 	int key, asc, ascq;
2815 
2816 	BURN_ALLOC_MEM(buf, struct buffer, 1);
2817 	BURN_ALLOC_MEM(c, struct command, 1);
2818 	BURN_ALLOC_MEM(msg, char, 256);
2819 	mmc_start_if_needed(d, 1);
2820 	if (mmc_function_spy(d, "mmc_set_streaming") <= 0)
2821 		{ret = 0; goto ex;}
2822 
2823 	scsi_init_command(c, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING));
2824 	c->retry = 1;
2825 	c->page = buf;
2826 	c->page->bytes = 28;
2827 	c->opcode[9] = (c->page->bytes >> 8) & 0xff;
2828 	c->opcode[10] = c->page->bytes & 0xff;
2829 	c->page->sectors = 0;
2830 	c->dir = TO_DRIVE;
2831 	memset(c->page->data, 0, c->page->bytes);
2832 	pd = c->page->data;
2833 
2834 	pd[0] = 0; /* WRC=0 (Default Rotation Control), RDD=Exact=RA=0 */
2835 	if (d->set_streaming_exact_bit)
2836 		pd[0] |= 2; /* Exact= 1 */
2837 
2838 	if (w_speed == 0)
2839 		w_speed = 0x10000000; /* ~ 2 TB/s */
2840 	else if (w_speed < 0)
2841 		w_speed = 177; /* 1x CD */
2842 	if (r_speed == 0)
2843 		r_speed = 0x10000000; /* ~ 2 TB/s */
2844 	else if (r_speed < 0)
2845 		r_speed = 177; /* 1x CD */
2846 	if (end_lba == 0) {
2847 		/* Default computed from 4.7e9 */
2848 		eff_end_lba = 2294921 - 1;
2849 		if (d->mdata->max_end_lba > 0)
2850 			eff_end_lba = d->mdata->max_end_lba - 1;
2851 	} else
2852 		eff_end_lba = end_lba;
2853 
2854 	sprintf(msg,
2855 		"mmc_set_streaming: end_lba=%d ,  r=%d ,  w=%d ,  exact=%d",
2856 		eff_end_lba, r_speed, w_speed, !!(pd[0] & 2));
2857 	libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
2858 			   LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
2859 			   msg, 0, 0);
2860 
2861 	/* start_lba is 0 , 1000 = 1 second as base time for data rate */
2862 	for (b = 0; b < 4 ; b++) {
2863 		pd[8+b] = (eff_end_lba >> (24 - 8 * b)) & 0xff;
2864 		pd[12+b] = (r_speed >> (24 - 8 * b)) & 0xff;
2865 		pd[16+b] = (1000 >> (24 - 8 * b)) & 0xff;
2866 		pd[20+b] = (w_speed >> (24 - 8 * b)) & 0xff;
2867 		pd[24+b] = (1000 >> (24 - 8 * b)) & 0xff;
2868 	}
2869 
2870 /* <<<
2871 	fprintf(stderr,"LIBBURN_EXPERIMENTAL : B6h Performance descriptor:\n");
2872 	for (b = 0; b < 28 ; b++)
2873 		fprintf(stderr, "%2.2X%c", pd[b], ((b+1)%4 ? ' ' : '\n'));
2874 */
2875 
2876 
2877 	d->issue_command(d, c);
2878 	if (c->error) {
2879 		spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
2880 		if (key != 0 && d->silent_on_scsi_error != 1 &&
2881 		    d->silent_on_scsi_error != 2) {
2882 			sprintf(msg,
2883 				"SCSI error on set_streaming(%d): ", w_speed);
2884 			scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
2885 					&key, &asc, &ascq);
2886 			libdax_msgs_submit(libdax_messenger, d->global_index,
2887 				0x00020124,
2888 				d->silent_on_scsi_error == 3 ?
2889 				 LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
2890 				LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
2891 		}
2892 		if (key != 0)
2893 			d->set_streaming_err = 1;
2894 		{ret = 0; goto ex;}
2895 	}
2896 	ret = 1;
2897 ex:;
2898 	BURN_FREE_MEM(msg);
2899 	BURN_FREE_MEM(c);
2900 	BURN_FREE_MEM(buf);
2901 	return ret;
2902 }
2903 
2904 
2905 void mmc_set_speed(struct burn_drive *d, int r, int w)
2906 {
2907 	struct command *c;
2908 	int ret, end_lba = 0, get_max, get_min;
2909 	struct burn_speed_descriptor *best_sd = NULL;
2910 
2911 	c = &(d->casual_command);
2912 	mmc_start_if_needed(d, 1);
2913 	if (mmc_function_spy(d, "mmc_set_speed") <= 0)
2914 		return;
2915 
2916 	if (r <= 0 || w <= 0) {
2917 		/* ts A70712 : now searching for best speed descriptor */
2918 		/* ts B31030 : keeping max read speed from sinking too low */
2919 		if (r <= 0) {
2920 			get_max = (r == 0);
2921 			get_min = (r == -1);
2922 			burn_drive_get_best_speed(d, r, &best_sd, 1 | 2);
2923 			if (best_sd != NULL) {
2924 				r = best_sd->read_speed;
2925 				end_lba = best_sd->end_lba;
2926 			}
2927 			if (get_max) {
2928 				if (d->current_is_cd_profile) {
2929 					if (r < Libburn_cd_max_read_speeD)
2930 						r = Libburn_cd_max_read_speeD;
2931 				} else if (d->current_profile >= 0x10 &&
2932 				           d->current_profile <= 0x2f) {
2933 					if (r < Libburn_dvd_max_read_speeD)
2934 						r = Libburn_dvd_max_read_speeD;
2935 				} else if (d->current_profile >= 0x40 &&
2936 				           d->current_profile <= 0x43) {
2937 					if (r < Libburn_bd_max_read_speeD)
2938 						r = Libburn_bd_max_read_speeD;
2939 				}
2940 			} else if(get_min) {
2941 				if (d->current_is_cd_profile) {
2942 					if (r > Libburn_cd_min_read_speeD)
2943 						r = Libburn_cd_min_read_speeD;
2944 				} else if (d->current_profile >= 0x10 &&
2945 				           d->current_profile <= 0x2f) {
2946 					if (r > Libburn_dvd_min_read_speeD)
2947 						r = Libburn_dvd_min_read_speeD;
2948 				} else if (d->current_profile >= 0x40 &&
2949 				           d->current_profile <= 0x43) {
2950 					if (r > Libburn_bd_min_read_speeD)
2951 						r = Libburn_bd_min_read_speeD;
2952 				}
2953 			}
2954 		}
2955 		if (w <= 0) {
2956 			burn_drive_get_best_speed(d, w, &best_sd, 2);
2957 			if (best_sd != NULL) {
2958 				w = best_sd->write_speed;
2959 				d->nominal_write_speed = w;
2960 				if (end_lba < best_sd->end_lba)
2961 					end_lba = best_sd->end_lba;
2962 			}
2963 		}
2964 	}
2965 
2966 	/* A70711 */
2967 	d->nominal_write_speed = w;
2968 
2969 	/* ts A61221 : try to set DVD speed via command B6h */
2970 	if (strstr(d->current_profile_text, "DVD") == d->current_profile_text
2971 	    || strstr(d->current_profile_text, "BD") == d->current_profile_text
2972 	    || d->set_streaming_exact_bit) {
2973 		ret = mmc_set_streaming(d, r, w, end_lba);
2974 		if (ret != 0)
2975 			return; /* success or really fatal failure */
2976 	}
2977 
2978 	/* ts A61112 : MMC standards prescribe FFFFh as max speed.
2979 			But libburn.h prescribes 0.
2980 	   ts A70715 : <0 now means minimum speed */
2981 	if (r == 0 || r > 0xffff)
2982 		r = 0xffff;
2983 	else if (r < 0)
2984 		r = 177; /* 1x CD */
2985 	if (w == 0 || w > 0xffff)
2986 		w = 0xffff;
2987 	else if (w < 0)
2988 		w = 177; /* 1x CD */
2989 
2990 	scsi_init_command(c, MMC_SET_SPEED, sizeof(MMC_SET_SPEED));
2991 	c->retry = 1;
2992 	c->opcode[2] = r >> 8;
2993 	c->opcode[3] = r & 0xFF;
2994 	c->opcode[4] = w >> 8;
2995 	c->opcode[5] = w & 0xFF;
2996 	c->page = NULL;
2997 	c->dir = NO_TRANSFER;
2998 	d->issue_command(d, c);
2999 }
3000 
3001 
3002 /* ts A61201 : found in unfunctional state
3003  */
3004 static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
3005 {
3006 	struct buffer *buf = NULL;
3007 	int len, cp, descr_len = 0, feature_code, only_current = 1, i;
3008 	int old_alloc_len, key, asc, ascq, ret;
3009 	int feature_is_current;
3010 	unsigned char *descr, *prf, *up_to, *prf_end;
3011 	struct command *c = NULL;
3012 	int phys_if_std = 0;
3013 	char *phys_name = "";
3014 	struct burn_feature_descr *recent_feature = NULL, *new_feature;
3015 	char *msg = NULL;
3016 
3017 /* Enable this to get loud and repeated reports about the feature set :
3018  # define Libburn_print_feature_descriptorS 1
3019 */
3020 #ifdef Libburn_print_feature_descriptorS
3021 	int prf_number;
3022 
3023 	only_current = 0;
3024 #endif
3025 
3026 	if (*alloc_len < 8)
3027 		{ret = 0; goto ex;}
3028 
3029 	BURN_ALLOC_MEM(buf, struct buffer, 1);
3030 	BURN_ALLOC_MEM(c, struct command, 1);
3031 	d->current_profile = 0;
3032         d->current_profile_text[0] = 0;
3033 	d->current_is_cd_profile = 0;
3034 	d->current_is_supported_profile = 0;
3035         d->current_is_guessed_profile = 0;
3036 	d->num_profiles = 0;
3037 	if (d->features != NULL)
3038 		burn_feature_descr_free(&(d->features), 0);
3039 	d->current_has_feat21h = 0;
3040 	d->current_feat21h_link_size = -1;
3041 	d->current_feat23h_byte4 = 0;
3042 	d->current_feat23h_byte8 = 0;
3043 	d->current_feat2fh_byte4 = -1;
3044 
3045 	scsi_init_command(c, MMC_GET_CONFIGURATION,
3046 			 sizeof(MMC_GET_CONFIGURATION));
3047 	c->dxfer_len= *alloc_len;
3048 	c->retry = 1;
3049 	c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
3050 	c->opcode[8] = c->dxfer_len & 0xff;
3051 	c->page = buf;
3052 	c->page->sectors = 0;
3053 	c->page->bytes = 0;
3054 	c->dir = FROM_DRIVE;
3055 	d->issue_command(d, c);
3056 
3057 #ifdef Libisofs_simulate_old_mmc1_drivE
3058 	c->error = 1;
3059 	c->sense[0] = 0x70; /* Fixed format sense data */
3060 	c->sense[2] = 0x5;
3061 	c->sense[12] = 0x20;
3062 	c->sense[13] = 0x0;
3063 #endif /* Libisofs_simulate_old_mmc1_drivE */
3064 
3065 	if (c->error) {
3066 		/* ts A90603 : MMC-1 drive do not know 46h GET CONFIGURATION */
3067 		spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
3068 		if (key == 0x5 && asc == 0x20 && ascq == 0x0) {
3069 			d->current_is_guessed_profile = 1;
3070 			/* Will yield a non-zero profile only after
3071 			   mmc_read_disc_info_al() was called */
3072 			mmc_guess_profile(d, 0);
3073 		}
3074 		{ret = 0; goto ex;}
3075 	}
3076 	old_alloc_len = *alloc_len;
3077 	*alloc_len = len = mmc_four_char_to_int(c->page->data) + 4;
3078 	if (len > old_alloc_len)
3079 		len = old_alloc_len;
3080 	if (len < 8)
3081 		{ret = 0; goto ex;}
3082 	if (len > 4096) {
3083 		/* MMC-5 6.6.2.1, Note 11: The maximum is less than 1 KB */
3084 		BURN_ALLOC_MEM(msg, char, 256);
3085 		sprintf(msg, "Implausible length announcement from SCSI command GET CONFIGURATION: %d", *alloc_len);
3086 		libdax_msgs_submit(libdax_messenger, d->global_index,
3087 			   0x000201a9,
3088 			   LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_ZERO,
3089 			   msg, 0, 0);
3090 		ret = 0; goto ex;
3091 	}
3092 
3093 	cp = (c->page->data[6]<<8) | c->page->data[7];
3094 
3095 #ifdef Libburn_rom_as_profilE
3096 	if (cp == 0x08 || cp == 0x10 || cp==0x40)
3097 		cp = Libburn_rom_as_profilE;
3098 #endif /* Libburn_rom_as_profilE */
3099 
3100 	d->current_profile = cp;
3101 	strcpy(d->current_profile_text, mmc_obtain_profile_name(cp));
3102 
3103 	/* Read-only supported media */
3104 
3105 	if (cp == 0x08) /* CD-ROM */
3106 		d->current_is_supported_profile = d->current_is_cd_profile = 1;
3107 	if (cp == 0x10) /* DVD-ROM */
3108 		d->current_is_supported_profile = 1;
3109 	if (cp == 0x40) /* BD-ROM */
3110 		d->current_is_supported_profile = 1;
3111 
3112 #ifdef Libburn_support_bd_r_readonlY
3113 #ifndef Libburn_support_bd_plus_r_srM
3114 	if (cp == 0x41) /* BD-R sequential (here as read-only dummy) */
3115 		d->current_is_supported_profile = 1;
3116 #endif
3117 	if (cp == 0x42) /* BD-R random recording */
3118 		d->current_is_supported_profile = 1;
3119 #endif
3120 
3121 
3122 	/* Write supported media (they get declared suitable in
3123 	                          burn_disc_get_multi_caps) */
3124 
3125 	if (cp == 0x09 || cp == 0x0a)
3126 		d->current_is_supported_profile = d->current_is_cd_profile = 1;
3127 
3128 #ifdef Libburn_support_dvd_plus_rW
3129 	if (cp == 0x1a)
3130 		d->current_is_supported_profile = 1;
3131 #endif
3132 #ifdef Libburn_support_dvd_minusrw_overW
3133 	if (cp == 0x13)
3134 		d->current_is_supported_profile = 1;
3135 #endif
3136 #ifdef Libburn_support_dvd_raM
3137 	if (cp == 0x12 || cp == 0x43) {                  /* DVD-RAM , BD-RE */
3138 		d->current_is_supported_profile = 1;
3139 
3140 #ifdef Libburn_dvd_ram_as_bd_rE
3141 		cp = d->current_profile = 0x43;
3142 		strcpy(d->current_profile_text, mmc_obtain_profile_name(cp));
3143 #endif
3144 
3145 	}
3146 #endif
3147 #ifdef Libburn_support_dvd_r_seQ
3148 	if (cp == 0x11 || cp == 0x14) /* DVD-R, DVD-RW */
3149 		d->current_is_supported_profile = 1;
3150 	if (cp == 0x15) /* DVD-R/DL */
3151 		d->current_is_supported_profile = 1;
3152 #endif
3153 #ifdef Libburn_support_dvd_plus_R
3154 	if (cp == 0x1b || cp == 0x2b) /* DVD+R , DVD+R/DL */
3155 		d->current_is_supported_profile = 1;
3156 #endif
3157 #ifdef Libburn_support_bd_plus_r_srM
3158 	if (cp == 0x41) /* BD-R SRM */
3159 		d->current_is_supported_profile = 1;
3160 #endif
3161 
3162 	/* ts A70127 : Interpret list of profile and feature descriptors.
3163  	see mmc5r03c.pdf 5.2
3164 	*/
3165 	up_to = c->page->data + len;
3166 
3167 #ifdef Libburn_print_feature_descriptorS
3168 	fprintf(stderr,
3169 	"-----------------------------------------------------------------\n");
3170 	fprintf(stderr,
3171 	  "LIBBURN_EXPERIMENTAL : feature list length = %d , shown = %d\n",
3172 		len, (int) (up_to - c->page->data));
3173 #endif /* Libburn_print_feature_descriptorS */
3174 
3175 	for (descr = c->page->data + 8; descr + 3 < up_to; descr += descr_len){
3176 		descr_len = 4 + descr[3];
3177 		feature_code = (descr[0] << 8) | descr[1];
3178 		feature_is_current = descr[2] & 1;
3179 
3180 		ret = burn_feature_descr_new(&new_feature, descr,
3181 		                             up_to - descr, 0);
3182 		if (ret > 0) {
3183 			if (d->features == NULL)
3184 				d->features = new_feature;
3185 			else
3186 				recent_feature->next = new_feature;
3187 			recent_feature = new_feature;
3188 		}
3189 
3190 		if (only_current && !feature_is_current)
3191 	continue;
3192 
3193 #ifdef Libburn_print_feature_descriptorS
3194 		fprintf(stderr,
3195 			"LIBBURN_EXPERIMENTAL : %s feature %4.4Xh :",
3196 			(descr[2] & 1) ? "+" : "-",
3197 			feature_code);
3198 		if (feature_code != 0x00)
3199 			for (i = 2; i < descr_len; i++)
3200 				fprintf(stderr, " %2.2X", descr[i]);
3201 		fprintf(stderr, "\n");
3202 #endif /* Libburn_print_feature_descriptorS */
3203 
3204 		if (feature_code == 0x0) {
3205 			prf_end = descr + 4 + descr[3];
3206 			d->num_profiles = descr[3] / 4;
3207 			if (d->num_profiles > 64)
3208 				d->num_profiles = 64;
3209 			if (d->num_profiles > 0)
3210 				memcpy(d->all_profiles, descr + 4,
3211 							d->num_profiles * 4);
3212 			for (prf = descr + 4; prf + 2 < prf_end; prf += 4) {
3213 
3214 #ifdef Libburn_print_feature_descriptorS
3215 				prf_number =  (prf[0] << 8) | prf[1];
3216 				fprintf(stderr,
3217 			"LIBBURN_EXPERIMENTAL :   %s profile %4.4Xh  \"%s\"\n",
3218 					prf[2] & 1 ? "+" : "-",
3219 					prf_number,
3220 					mmc_obtain_profile_name(prf_number));
3221 #endif /* Libburn_print_feature_descriptorS */
3222 
3223 			}
3224 
3225 		} else if (feature_code == 0x21) {
3226 
3227 			d->current_has_feat21h = feature_is_current;
3228 			for (i = 0; i < descr[7]; i++) {
3229 				if (i == 0 || descr[8 + i] == 16)
3230 					d->current_feat21h_link_size =
3231 								descr[8 + i];
3232 
3233 #ifdef Libburn_print_feature_descriptorS
3234 				fprintf(stderr,
3235 				"LIBBURN_EXPERIMENTAL :   + Link Size = %d\n",
3236 					descr[8 + i]);
3237 #endif /* Libburn_print_feature_descriptorS */
3238 
3239 			}
3240 
3241 		} else if (feature_code == 0x23) {
3242 			if (feature_is_current) {
3243 				d->current_feat23h_byte4 = descr[4];
3244 				d->current_feat23h_byte8 = descr[8];
3245 			}
3246 #ifdef Libburn_print_feature_descriptorS
3247 			if (cp >= 0x41 && cp <= 0x43)
3248 				fprintf(stderr,
3249 			"LIBBURN_EXPERIMENTAL : BD formats: %s%s%s%s%s\n",
3250 					descr[4] & 1 ? " Cert" : "",
3251 					descr[4] & 2 ? " QCert" : "",
3252 					descr[4] & 4 ? " Expand" : "",
3253 					descr[4] & 8 ? " RENoSA" : "",
3254 					descr[8] & 1 ? " RRM" : "");
3255 #endif /* Libburn_print_feature_descriptorS */
3256 
3257 		} else if (feature_code == 0x2F) {
3258 			if (feature_is_current)
3259 				d->current_feat2fh_byte4 = descr[4];
3260 
3261 #ifdef Libburn_print_feature_descriptorS
3262 			fprintf(stderr, "LIBBURN_EXPERIMENTAL :     BUF = %d , Test Write = %d , DVD-RW = %d\n",
3263 				!!(descr[4] & 64), !!(descr[4] & 4),
3264 				!!(descr[4] & 2));
3265 #endif /* Libburn_print_feature_descriptorS */
3266 
3267 		} else if (feature_code == 0x01) {
3268 			phys_if_std = (descr[4] << 24) | (descr[5] << 16) |
3269 					(descr[6] << 8) | descr[7];
3270 			if (phys_if_std == 1)
3271 				phys_name = "SCSI Family";
3272 			else if(phys_if_std == 2)
3273 				phys_name = "ATAPI";
3274 			else if(phys_if_std == 3 || phys_if_std == 4 ||
3275 				 phys_if_std == 6)
3276 				phys_name = "IEEE 1394 FireWire";
3277 			else if(phys_if_std == 7)
3278 				phys_name = "Serial ATAPI";
3279 			else if(phys_if_std == 8)
3280 				phys_name = "USB";
3281 
3282 			d->phys_if_std = phys_if_std;
3283 			strcpy(d->phys_if_name, phys_name);
3284 
3285 #ifdef Libburn_print_feature_descriptorS
3286 
3287 			fprintf(stderr,
3288 	"LIBBURN_EXPERIMENTAL :     Phys. Interface Standard %Xh \"%s\"\n",
3289 				phys_if_std, phys_name);
3290 
3291 		} else if (feature_code == 0x107) {
3292 
3293 			fprintf(stderr, "LIBBURN_EXPERIMENTAL :     CD SPEED = %d , page 2Ah = %d , SET STREAMING = %d\n",
3294 				!!(descr[4] & 8), !!(descr[4] & 4),
3295 				!!(descr[4] & 2));
3296 
3297 #endif /* Libburn_print_feature_descriptorS */
3298 
3299 		} else if (feature_code == 0x108 || feature_code == 0x10c) {
3300 			int c_limit;
3301 
3302 #ifdef Libburn_print_feature_descriptorS
3303 			int i;
3304 			fprintf(stderr, "LIBBURN_EXPERIMENTAL :     %s = ",
3305 				feature_code == 0x108 ?
3306 				"Drive Serial Number" : "Drive Firmware Date");
3307 #endif /* Libburn_print_feature_descriptorS */
3308 
3309 			c_limit = descr[3] - 2 * (feature_code == 0x10c);
3310 			if (feature_code == 0x108) {
3311 				if (d->drive_serial_number != NULL)
3312 					BURN_FREE_MEM(d->drive_serial_number);
3313 				BURN_ALLOC_MEM(d->drive_serial_number,
3314 						char, c_limit + 1);
3315 				memcpy(d->drive_serial_number, descr + 4,
3316 					c_limit);
3317 				d->drive_serial_number[c_limit] = 0;
3318 				d->drive_serial_number_len = c_limit;
3319 			}
3320 
3321 #ifdef Libburn_print_feature_descriptorS
3322 			for (i = 0; i < c_limit; i++)
3323 				if (descr[4 + i] < 0x20 || descr[4 + i] > 0x7e
3324 					|| descr[4 + i] == '\\')
3325 					fprintf(stderr,"\\%2.2X",descr[4 + i]);
3326 				else
3327 					fprintf(stderr, "%c", descr[4 + i]);
3328 			fprintf(stderr, "\n");
3329 
3330 #endif /* Libburn_print_feature_descriptorS */
3331 
3332 		}
3333 	}
3334 	ret = 1;
3335 ex:
3336 	BURN_FREE_MEM(msg);
3337 	BURN_FREE_MEM(buf);
3338 	BURN_FREE_MEM(c);
3339 	return ret;
3340 }
3341 
3342 
3343 void mmc_get_configuration(struct burn_drive *d)
3344 {
3345 	int alloc_len = 8, ret;
3346 
3347 	if (d->current_profile > 0 && d->current_profile < 0xffff)
3348 		return;
3349 
3350 	mmc_start_if_needed(d, 1);
3351 	if (mmc_function_spy(d, "mmc_get_configuration") <= 0)
3352 		return;
3353 
3354 	/* first command execution to learn Allocation Length */
3355 	ret = mmc_get_configuration_al(d, &alloc_len);
3356 /*
3357 	fprintf(stderr,"LIBBURN_DEBUG: 46h alloc_len = %d , ret = %d\n",
3358 			alloc_len, ret);
3359 */
3360 	if (alloc_len > 8 && ret > 0) {
3361 		/* second execution with announced length */
3362 		mmc_get_configuration_al(d, &alloc_len);
3363 	}
3364 }
3365 
3366 
3367 /* ts A70108 */
3368 /* mmc5r03c.pdf 6.24 */
3369 static int mmc_read_format_capacities_al(struct burn_drive *d,
3370 					int *alloc_len, int top_wanted)
3371 {
3372 	struct buffer *buf = NULL;
3373 	int len, type, score, num_descr, max_score = -2000000000, i, sign = 1;
3374 	int old_alloc_len, ret;
3375 	off_t size, num_blocks;
3376 	struct command *c = NULL;
3377 	unsigned char *dpt;
3378 
3379 	BURN_ALLOC_MEM(buf, struct buffer, 1);
3380 	BURN_ALLOC_MEM(c, struct command, 1);
3381 	if (*alloc_len < 4)
3382 		{ret = 0; goto ex;}
3383 
3384 	d->format_descr_type = 3;
3385 	d->format_curr_max_size = 0;
3386 	d->format_curr_blsas = 0;
3387 	d->best_format_type = -1;
3388 	d->best_format_size = 0;
3389 
3390 	scsi_init_command(c, MMC_READ_FORMAT_CAPACITIES,
3391 			 sizeof(MMC_READ_FORMAT_CAPACITIES));
3392 	c->dxfer_len = *alloc_len;
3393 	c->retry = 1;
3394 	c->opcode[7]= (c->dxfer_len >> 8) & 0xff;
3395 	c->opcode[8]= c->dxfer_len & 0xff;
3396 	c->page = buf;
3397 	c->page->sectors = 0;
3398 	c->page->bytes = 0;
3399 	c->dir = FROM_DRIVE;
3400 
3401 	d->issue_command(d, c);
3402 	if (c->error)
3403 		{ret = 0; goto ex;}
3404 
3405 	len = c->page->data[3];
3406 	old_alloc_len = *alloc_len;
3407 	*alloc_len = len + 4;
3408 	if (old_alloc_len < 12)
3409 		{ret = 1; goto ex;}
3410 	if (len + 4 > old_alloc_len)
3411 		len = old_alloc_len - 4;
3412 	if (len < 8)
3413 		{ret = 0; goto ex;}
3414 
3415 	dpt = c->page->data + 4;
3416 	/* decode 6.24.3.2 Current/Maximum Capacity Descriptor */
3417 	d->format_descr_type = dpt[4] & 3;
3418 	d->format_curr_max_size = (((off_t) dpt[0]) << 24)
3419 		 		  + (dpt[1] << 16) + (dpt[2] << 8) + dpt[3];
3420 	if (d->format_descr_type == BURN_FORMAT_IS_UNKNOWN)
3421 		d->format_curr_max_size = 0;
3422 	d->format_curr_blsas = (dpt[5] << 16) + (dpt[6] << 8) + dpt[7];
3423 	d->format_curr_max_size *= (off_t) 2048;
3424 	if((d->current_profile == 0x12 || d->current_profile == 0x43)
3425 	   && d->media_capacity_remaining == 0) {
3426 		burn_drive_set_media_capacity_remaining(d,
3427 						d->format_curr_max_size);
3428 		d->media_lba_limit = d->format_curr_max_size / 2048;
3429 	}
3430 
3431 
3432 #ifdef Libburn_dvd_ram_as_bd_rE
3433 	/* <<< dummy format descriptor list as obtained from
3434 	       dvd+rw-mediainfo by Giulio Orsero in April 2008
3435 	*/
3436 	d->num_format_descr = 5;
3437 	d->format_descriptors[0].type = 0x00;
3438 	d->format_descriptors[0].size = (off_t) 11826176 * (off_t) 2048;
3439 	d->format_descriptors[0].tdp = 0x3000;
3440 	d->format_descriptors[1].type = 0x30;
3441 	d->format_descriptors[1].size = (off_t) 11826176 * (off_t) 2048;
3442 	d->format_descriptors[1].tdp = 0x3000;
3443 	d->format_descriptors[2].type = 0x30;
3444 	d->format_descriptors[2].size = (off_t) 11564032 * (off_t) 2048;
3445 	d->format_descriptors[2].tdp = 0x5000;
3446 	d->format_descriptors[3].type = 0x30;
3447 	d->format_descriptors[3].size = (off_t) 12088320 * (off_t) 2048;
3448 	d->format_descriptors[3].tdp = 0x1000;
3449 	d->format_descriptors[4].type = 0x31;
3450 	d->format_descriptors[4].size = (off_t) 12219392 * (off_t) 2048;
3451 	d->format_descriptors[4].tdp = 0x800;
3452 	d->best_format_type = 0x00;
3453 	d->best_format_size = (off_t) 11826176 * (off_t) 2048;
3454 
3455 	/* silencing compiler warnings about unused variables */
3456 	num_blocks = size = sign = i = max_score = num_descr = score = type = 0;
3457 
3458 	if (d->current_profile == 0x12 || d->current_profile == 0x43)
3459 		{ret = 1; goto ex;}
3460 	d->num_format_descr = 0;
3461 
3462 #endif /* Libburn_dvd_ram_as_bd_rE */
3463 
3464 	if (top_wanted == 0x00 || top_wanted == 0x10)
3465 		sign = -1; /* the caller clearly desires full format */
3466 
3467 	/* 6.24.3.3 Formattable Capacity Descriptors */
3468 	num_descr = (len - 8) / 8;
3469 	for (i = 0; i < num_descr; i++) {
3470 		dpt = c->page->data + 12 + 8 * i;
3471 		num_blocks = mmc_four_char_to_int(dpt);
3472 		size = num_blocks * (off_t) 2048;
3473 		type = dpt[4] >> 2;
3474 
3475 		if (i < 32) {
3476 			d->format_descriptors[i].type = type;
3477 			d->format_descriptors[i].size = size;
3478 			d->format_descriptors[i].tdp =
3479 				(dpt[5] << 16) + (dpt[6] << 8) + dpt[7];
3480 			d->num_format_descr = i + 1;
3481 		}
3482 		/* Criterion is proximity to quick intermediate state */
3483 		if (type == 0x00) { /* full format (with lead out) */
3484 			score = 1 * sign;
3485 		} else if (type == 0x10) { /* DVD-RW full format */
3486 			score = 10 * sign;
3487 		} else if(type == 0x13) { /* DVD-RW quick grow last session */
3488 			score = 100 * sign;
3489 		} else if(type == 0x15) { /* DVD-RW Quick */
3490 			score = 50 * sign;
3491 			if(d->current_profile == 0x13) {
3492 				burn_drive_set_media_capacity_remaining(d,
3493 									size);
3494 				d->media_lba_limit = num_blocks;
3495 			}
3496 		} else if(type == 0x26) { /* DVD+RW */
3497 			score = 1 * sign;
3498 			burn_drive_set_media_capacity_remaining(d, size);
3499 			d->media_lba_limit = num_blocks;
3500 		} else {
3501 	continue;
3502 		}
3503 		if (type == top_wanted)
3504 			score += 1000000000;
3505 		if (score > max_score) {
3506 			d->best_format_type = type;
3507 			d->best_format_size = size;
3508 			max_score = score;
3509 		}
3510 	}
3511 	ret = 1;
3512 ex:
3513 	BURN_FREE_MEM(buf);
3514 	BURN_FREE_MEM(c);
3515 	return ret;
3516 }
3517 
3518 
3519 int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
3520 {
3521 	int alloc_len = 4, ret;
3522 
3523 	mmc_start_if_needed(d, 1);
3524 	if (mmc_function_spy(d, "mmc_read_format_capacities") <= 0)
3525 		return 0;
3526 
3527 	ret = mmc_read_format_capacities_al(d, &alloc_len, top_wanted);
3528 /*
3529 	fprintf(stderr,"LIBBURN_DEBUG: 23h alloc_len = %d , ret = %d\n",
3530 		 alloc_len, ret);
3531 */
3532 	if (alloc_len >= 12 && ret > 0)
3533 		ret = mmc_read_format_capacities_al(d, &alloc_len, top_wanted);
3534 
3535 	return ret;
3536 }
3537 
3538 
3539 void mmc_sync_cache(struct burn_drive *d)
3540 {
3541 	struct command *c = NULL;
3542 	char *msg = NULL;
3543 	int key, asc, ascq;
3544 
3545 	if (mmc_function_spy(d, "mmc_sync_cache") <= 0)
3546 		goto ex;
3547 
3548 	BURN_ALLOC_MEM_VOID(c, struct command, 1);
3549 	BURN_ALLOC_MEM_VOID(msg, char, 256);
3550 
3551 	scsi_init_command(c, MMC_SYNC_CACHE, sizeof(MMC_SYNC_CACHE));
3552 	c->retry = 1;
3553 	if (!d->do_no_immed)
3554 		c->opcode[1] |= 2; /* ts A70918 : Immed */
3555 	c->page = NULL;
3556 	c->dir = NO_TRANSFER;
3557 	if (d->do_no_immed)
3558 		c->timeout = Libburn_mmc_sync_noim_timeouT;
3559 	else
3560 		c->timeout = Libburn_mmc_sync_timeouT;
3561 
3562 	libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
3563 			   LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
3564 			   "syncing cache", 0, 0);
3565 	if(d->wait_for_buffer_free) {
3566 		sprintf(msg,
3567 			"Checked buffer %u times. Waited %u+%u times = %.3f s",
3568 			d->pessimistic_writes, d->waited_writes,
3569 			d->waited_tries - d->waited_writes,
3570 			((double) d->waited_usec) / 1.0e6);
3571 		libdax_msgs_submit(libdax_messenger, d->global_index,
3572 				0x0002013f,
3573 				LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
3574 				msg, 0,0);
3575 	}
3576 
3577 	d->issue_command(d, c);
3578 
3579 	/* ts A70918 */
3580 	if (c->error) {
3581 		sprintf(msg, "Failed to synchronize drive cache");
3582 		sprintf(msg + strlen(msg), ". SCSI error : ");
3583 		scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
3584 					&key, &asc, &ascq);
3585 		libdax_msgs_submit(libdax_messenger, d->global_index,
3586 				0x0002017f,
3587 				LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
3588 				msg, 0, 0);
3589 		d->cancel = 1;
3590 		goto ex;
3591 	}
3592 
3593 	spc_human_readable_cmd(c, msg, 160, 0);
3594 	if (spc_wait_unit_attention(d, 3600, msg, 0) <= 0)
3595 		d->cancel = 1;
3596 	else
3597 		d->needs_sync_cache = 0;
3598 ex:
3599 	BURN_FREE_MEM(msg);
3600 	BURN_FREE_MEM(c);
3601 }
3602 
3603 
3604 /* ts A61023 : http://libburn.pykix.org/ticket/14
3605                get size and free space of drive buffer
3606 */
3607 int mmc_read_buffer_capacity(struct burn_drive *d)
3608 {
3609 	struct buffer *buf = NULL;
3610 	struct command *c = NULL;
3611 	unsigned char *data;
3612 	int alloc_len = 12, ret;
3613 
3614 	BURN_ALLOC_MEM(buf, struct buffer, 1);
3615 	BURN_ALLOC_MEM(c, struct command, 1);
3616 	if (mmc_function_spy(d, "mmc_read_buffer_capacity") <= 0)
3617 		{ret = 0; goto ex;}
3618 
3619 	scsi_init_command(c, MMC_READ_BUFFER_CAPACITY,
3620 			 sizeof(MMC_READ_BUFFER_CAPACITY));
3621 	c->dxfer_len = alloc_len;
3622 	c->opcode[7] = (c->dxfer_len >> 8) & 0xff;
3623 	c->opcode[8] = c->dxfer_len & 0xff;
3624 	c->retry = 1;
3625 	c->page = buf;
3626 	memset(c->page->data, 0, alloc_len);
3627 	c->page->bytes = 0;
3628 	c->page->sectors = 0;
3629 
3630 	c->dir = FROM_DRIVE;
3631 	d->issue_command(d, c);
3632 
3633 	/* >>> ??? error diagnostics */
3634 	if (c->error)
3635 		{ret = 0; goto ex;}
3636 
3637 	data = c->page->data;
3638 
3639 	d->progress.buffer_capacity =
3640 			(data[4]<<24)|(data[5]<<16)|(data[6]<<8)|data[7];
3641 	d->progress.buffer_available =
3642 			(data[8]<<24)|(data[9]<<16)|(data[10]<<8)|data[11];
3643 	if (d->progress.buffer_capacity < d->progress.buffer_available) {
3644 		/* Default mad buffer usage to 50 percent */
3645 		d->progress.buffer_available = d->progress.buffer_capacity / 2;
3646 	}
3647 	d->pessimistic_buffer_free = d->progress.buffer_available;
3648 	d->pbf_altered = 0;
3649 	if (d->progress.buffered_bytes >= d->progress.buffer_capacity){
3650 		double fill;
3651 
3652 		fill = d->progress.buffer_capacity
3653 			      - d->progress.buffer_available;
3654 		if (fill < d->progress.buffer_min_fill && fill>=0)
3655 			d->progress.buffer_min_fill = fill;
3656 	}
3657 	ret = 1;
3658 ex:;
3659 	BURN_FREE_MEM(c);
3660 	BURN_FREE_MEM(buf);
3661 	return ret;
3662 }
3663 
3664 
3665 /* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format()
3666                and mmc5r03c.pdf, 6.5 FORMAT UNIT */
3667 /*
3668    @param size The size (in bytes) to be sent with the FORMAT command
3669    @param flag bit1+2: size mode
3670                  0 = use parameter size as far as it makes sense
3671                  1 = insist in size 0 even if there is a better default known
3672                  2 = without bit7: format to maximum available size
3673                      with bit7   : take size from indexed format descriptor
3674                  3 = format to default size
3675                bit3= expand format up to at least size
3676                bit4= enforce re-format of (partly) formatted media
3677                bit5= try to disable eventual defect management
3678                bit6= try to avoid lengthy media certification
3679                bit7= bit8 to bit15 contain the index of the format to use
3680                bit8-bit15 = see bit7
3681               bit16= enable POW on blank BD-R
3682 */
3683 int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
3684 {
3685 	struct buffer *buf = NULL;
3686 	struct command *c = NULL;
3687 	int ret, tolerate_failure = 0, return_immediately = 0, i, format_type;
3688 	int index, format_sub_type = 0, format_00_index, size_mode;
3689 	int accept_count = 0;
3690 	off_t num_of_blocks = 0, diff, format_size, i_size, format_00_max_size;
3691 	off_t min_size = -1, max_size = -1;
3692 	char *msg = NULL, descr[80 + 10 + 22]; /* profile+filltext+index */
3693 	int key, asc, ascq;
3694 	int full_format_type = 0x00; /* Full Format (or 0x10 for DVD-RW ?) */
3695 
3696 	BURN_ALLOC_MEM(buf, struct buffer, 1);
3697 	BURN_ALLOC_MEM(c, struct command, 1);
3698 	BURN_ALLOC_MEM(msg, char, 256);
3699 	mmc_start_if_needed(d, 0);
3700 	if (mmc_function_spy(d, "mmc_format_unit") <= 0)
3701 		{ret = 0; goto ex;}
3702 	size_mode = (flag >> 1) & 3;
3703 
3704 	scsi_init_command(c, MMC_FORMAT_UNIT, sizeof(MMC_FORMAT_UNIT));
3705 	c->retry = 1;
3706 	c->page = buf;
3707 	c->page->bytes = 12;
3708 	c->page->sectors = 0;
3709 	c->dir = TO_DRIVE;
3710 	if (d->do_no_immed)
3711 		c->timeout = Libburn_mmc_blank_noim_timeouT;
3712 	else
3713 		c->timeout = Libburn_mmc_blank_timeouT;
3714 	memset(c->page->data, 0, c->page->bytes);
3715 
3716 	descr[0] = 0;
3717 	if (!d->do_no_immed)
3718 		c->page->data[1] = 0x02;          /* Immed */
3719 	c->page->data[3] = 8;                     /* Format descriptor length */
3720 	num_of_blocks = size / 2048;
3721 	mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
3722 
3723 	if (flag & 128) { /* explicitly chosen format descriptor */
3724 		/* use case: the app knows what to do */
3725 
3726 		ret = mmc_read_format_capacities(d, -1);
3727 		if (ret <= 0)
3728 			goto selected_not_suitable;
3729 		index = (flag >> 8) & 0xff;
3730 		if(index < 0 || index >= d->num_format_descr) {
3731 selected_not_suitable:;
3732 			libdax_msgs_submit(libdax_messenger, d->global_index,
3733 				0x00020132,
3734 				LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
3735 				"Selected format is not suitable for libburn",
3736 				0, 0);
3737 			{ret = 0; goto ex;}
3738 		}
3739 		if (!(d->current_profile == 0x13 ||
3740 			d->current_profile == 0x14 ||
3741 			d->current_profile == 0x1a ||
3742 			d->current_profile == 0x12 ||
3743 			d->current_profile == 0x41 ||
3744 			d->current_profile == 0x43))
3745 			goto unsuitable_media;
3746 
3747 		format_type = d->format_descriptors[index].type;
3748 		if (!(format_type == 0x00 || format_type == 0x01 ||
3749 		      format_type == 0x10 ||
3750 		      format_type == 0x11 || format_type == 0x13 ||
3751 		      format_type == 0x15 || format_type == 0x26 ||
3752  		      format_type == 0x30 || format_type == 0x31 ||
3753 		      format_type == 0x32))
3754 			goto selected_not_suitable;
3755 		if (flag & 4) {
3756 			num_of_blocks =
3757 				d->format_descriptors[index].size / 2048;
3758 			mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
3759 		}
3760 		if (format_type != 0x26)
3761 			for (i = 0; i < 3; i++)
3762 				 c->page->data[9 + i] =
3763 					( d->format_descriptors[index].tdp >>
3764 					  (16 - 8 * i)) & 0xff;
3765 		if (format_type == 0x30 || format_type == 0x31) {
3766 			format_sub_type = 0;
3767 			if (flag & 64) {
3768 				if (d->current_feat23h_byte4 & 2)
3769 					/* Quick certification */
3770 					format_sub_type = 3;
3771 			} else {
3772 				if (d->current_feat23h_byte4 & 1)
3773 					/* Full certification */
3774 					format_sub_type = 2;
3775 			}
3776 		} else if (format_type == 0x32 ||
3777 		         (format_type == 0x00 && d->current_profile == 0x41)) {
3778 			if (flag & (1 << 16))
3779 				format_sub_type = 0; /* SRM + POW  */
3780 			else
3781 				format_sub_type = 1; /* SRM  (- POW) */
3782 		}
3783 		if (d->current_profile == 0x12 && format_type !=0x01 &&
3784 		    (flag & 64)) {
3785 			/* DCRT and CmpList, see below */
3786 			c->page->data[1] |= 0x20;
3787 			c->opcode[1] |= 0x08;
3788 		}
3789 		c->page->data[1] |= 0x80; /* FOV = this flag vector is valid */
3790 		sprintf(descr, "%s (descr %d)", d->current_profile_text,index);
3791 		return_immediately = 1; /* caller must do the waiting */
3792 
3793 	} else if (d->current_profile == 0x1a) { /* DVD+RW */
3794 		/* use case: background formatting during write     !(flag&4)
3795 	                     de-icing as explicit formatting action (flag&4)
3796 		*/
3797 
3798 		/* mmc5r03c.pdf , 6.5.4.2.14, DVD+RW Basic Format */
3799 		format_type = 0x26;
3800 
3801 					/* >>> ??? is this "| 8" a bug ? */
3802 
3803 		if ((size <= 0 && !(flag & 2)) || (flag & (4 | 8))) {
3804 			/* maximum capacity */
3805 			memset(c->page->data + 4, 0xff, 4);
3806 			num_of_blocks = 0xffffffff;
3807 		}
3808 
3809 		if(d->bg_format_status == 2 ||
3810 			(d->bg_format_status == 3 && !(flag & 16))) {
3811 			sprintf(msg,"FORMAT UNIT ignored. Already %s.",
3812 				(d->bg_format_status == 2 ? "in progress" :
3813 							"completed"));
3814 			libdax_msgs_submit(libdax_messenger, d->global_index,
3815 				0x00020120,
3816 				LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
3817 				msg, 0,0);
3818 			{ret = 2; goto ex;}
3819 		}
3820 		if (!(flag & 16))             /* if not re-format is desired */
3821 			if (d->bg_format_status == 1) /* is partly formatted */
3822 				c->page->data[11] = 1;        /* Restart bit */
3823 		sprintf(descr, "DVD+RW (fs=%d,rs=%d)",
3824 			d->bg_format_status, (c->page->data[11] == 1));
3825 		if (flag & 4)
3826 			return_immediately = 1;/* caller must do the waiting */
3827 
3828 	} else if (d->current_profile == 0x13 && !(flag & 16)) {
3829 		/*DVD-RW restricted overwrite*/
3830 		/* use case: quick grow formatting during write */
3831 
3832 		ret = mmc_read_format_capacities(d, 0x13);
3833 		if (ret > 0) {
3834 			if (d->best_format_type == 0x13) {
3835 				if (d->best_format_size <= 0)
3836 					{ret = 1; goto ex;}
3837 			} else {
3838 				if (d->format_descr_type == 2) /* formatted */
3839 					{ret = 1; goto ex;}
3840 				if (d->format_descr_type == 3){/*intermediate*/
3841 					d->needs_close_session = 1;
3842 					{ret = 1; goto ex;}
3843 				}
3844 				/* does trying make sense at all ? */
3845 				tolerate_failure = 1;
3846 			}
3847 		}
3848 		if (d->best_format_type == 0x13 && (flag & (4 | 8))) {
3849 			num_of_blocks = d->best_format_size / 2048;
3850 			if (flag & 8) {
3851 				/* num_of_blocks needed to reach size */
3852 				diff = (size - d->format_curr_max_size) /32768;
3853 				if ((size - d->format_curr_max_size) % 32768)
3854 					diff++;
3855 				diff *= 16;
3856 				if (diff < num_of_blocks)
3857 					num_of_blocks = diff;
3858 			}
3859 			if (num_of_blocks > 0)
3860 				mmc_int_to_four_char(c->page->data + 4,
3861 							num_of_blocks);
3862 		}
3863 		/* 6.5.4.2.8 , DVD-RW Quick Grow Last Border */
3864 		format_type = 0x13;
3865 		c->page->data[11] = 16;              /* block size * 2k */
3866 		sprintf(descr, "DVD-RW quick grow");
3867 
3868 	} else if (d->current_profile == 0x14 ||
3869 			(d->current_profile == 0x13 && (flag & 16))) {
3870 		/* DVD-RW sequential recording (or Overwrite for re-format) */
3871 		/* use case : transition from Sequential to Overwrite
3872 	                      re-formatting of Overwrite media  */
3873 
3874 		/* To Restricted Overwrite */
3875 		/*    6.5.4.2.10 Format Type = 15h (DVD-RW Quick) */
3876 		/* or 6.5.4.2.1  Format Type = 00h (Full Format) */
3877 		/* or 6.5.4.2.5  Format Type = 10h (DVD-RW Full Format) */
3878 		mmc_read_format_capacities(d,
3879 					(flag & 4) ? full_format_type : 0x15);
3880 		if (d->best_format_type == 0x15 ||
3881 		    d->best_format_type == full_format_type) {
3882 			if ((flag & 4)
3883 				|| d->best_format_type == full_format_type) {
3884 				num_of_blocks = d->best_format_size / 2048;
3885 				mmc_int_to_four_char(c->page->data + 4,
3886 							num_of_blocks);
3887 			}
3888 
3889 		} else {
3890 no_suitable_formatting_type:;
3891 			libdax_msgs_submit(libdax_messenger, d->global_index,
3892 				0x00020131,
3893 				LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
3894 				"No suitable formatting type offered by drive",
3895 				0, 0);
3896 			{ret = 0; goto ex;}
3897 		}
3898 		format_type = d->best_format_type;
3899 		sprintf(descr, "DVD-RW %s",
3900 			format_type == 0x15 ? "quick" : "full");
3901 		return_immediately = 1; /* caller must do the waiting */
3902 
3903 	} else if (d->current_profile == 0x12) {
3904 		/* ts A80417 : DVD-RAM */
3905 		/*  6.5.4.2.1  Format Type = 00h (Full Format)
3906 		    6.5.4.2.2  Format Type = 01h (Spare Area Expansion)
3907 		*/
3908 		index = format_00_index = -1;
3909 		format_size = format_00_max_size = -1;
3910 		for (i = 0; i < d->num_format_descr; i++) {
3911 			format_type = d->format_descriptors[i].type;
3912 			i_size = d->format_descriptors[i].size;
3913 			if (format_type != 0x00 && format_type != 0x01)
3914 		continue;
3915 			if (flag & 32) { /* No defect mgt */
3916 				/* Search for largest 0x00 format descriptor */
3917 				if (format_type != 0x00)
3918 		continue;
3919 				if (i_size < format_size)
3920 		continue;
3921 				format_size = i_size;
3922 				index = i;
3923 		continue;
3924 			} else if (flag & 4) { /*Max or default size with mgt*/
3925 				/* Search for second largest 0x00
3926 				   format descriptor. For max size allow
3927 				   format type 0x01.
3928 				 */
3929 				if (format_type == 0x00) {
3930 					if (i_size < format_size)
3931 		continue;
3932 					if (i_size < format_00_max_size) {
3933 						format_size = i_size;
3934 						index = i;
3935 		continue;
3936 					}
3937 					format_size = format_00_max_size;
3938 					index = format_00_index;
3939 					format_00_max_size = i_size;
3940 					format_00_index = i;
3941 		continue;
3942 				}
3943 				if (size_mode==3)
3944 		continue;
3945 				if (i_size > format_size) {
3946 					format_size = i_size;
3947 					index = i;
3948 				}
3949 		continue;
3950 			}
3951 			/* Search for smallest 0x0 or 0x01
3952 			   descriptor >= size */;
3953 			if (d->format_descriptors[i].size >= size &&
3954 			    (format_size < 0 || i_size < format_size)
3955 			   ) {
3956 				format_size = i_size;
3957 				index = i;
3958 			}
3959 		}
3960 		if(index < 0 && (flag & 4) && !(flag & 32)) {
3961 			format_size = format_00_max_size;
3962 			index = format_00_index;
3963 		}
3964 		if(index < 0)
3965 			goto no_suitable_formatting_type;
3966 		format_type = d->format_descriptors[index].type;
3967 		num_of_blocks = d->format_descriptors[index].size / 2048;
3968 		mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
3969 		for (i = 0; i < 3; i++)
3970 			 c->page->data[9 + i] =
3971 				( d->format_descriptors[index].tdp >>
3972 					  (16 - 8 * i)) & 0xff;
3973 		sprintf(descr, "%s", d->current_profile_text);
3974 		return_immediately = 1; /* caller must do the waiting */
3975 		c->page->data[1] |= 0x80; /* FOV = this flag vector is valid */
3976 
3977 		if ((flag & 64) && format_type != 0x01) {
3978 			/* MMC-5 6.5.3.2 , 6.5.4.2.1.2
3979 			   DCRT: Disable Certification and maintain number
3980 			         of blocks
3981    		           CmpList: Override maintaining of number of blocks
3982 			            with DCRT
3983 			*/
3984 			/* ts A80426 : prevents change of formatted size
3985 		               with PHILIPS SPD3300L and Verbatim 3x DVD-RAM
3986 			       and format_type 0x00. Works on TSSTcorp SH-S203B
3987 			*/
3988 			c->page->data[1] |= 0x20;
3989 			c->opcode[1] |= 0x08;
3990 		}
3991 
3992 	} else if (d->current_profile == 0x41) {
3993 		/* BD-R SRM */
3994 
3995 		index = -1;
3996 		format_size = -1;
3997 		if (d->num_format_descr <= 0)
3998 			goto no_suitable_formatting_type;
3999 		if (d->format_descriptors[0].type != 0)
4000 			goto no_suitable_formatting_type;
4001 		for (i = 0; i < d->num_format_descr; i++) {
4002 			format_type = d->format_descriptors[i].type;
4003 			i_size = d->format_descriptors[i].size;
4004 			if (format_type != 0x00 && format_type != 0x32)
4005 		continue;
4006 			if (flag & 32) { /* No defect mgt */
4007 				/* ts A81211 : MMC-5 6.5.4.2.17.1
4008 				   When formatted with Format Type 32h,
4009 				   the BD-R disc is required to allocate
4010 				   a non-zero number of spares.
4011 				*/
4012 				goto no_suitable_formatting_type;
4013 
4014 			} else if(size_mode == 2) { /* max payload size */
4015 				/* search largest 0x32 format descriptor */
4016 				if(format_type != 0x32)
4017 		continue;
4018 			} else if(size_mode == 3) { /* default payload size */
4019 				if (format_type == 0x00) {
4020 					index = i;
4021 		break;
4022 				}
4023 		continue;
4024 			} else { /* defect managed format with size wish */
4025 
4026 #ifdef Libburn_bd_r_format_olD
4027 
4028 				/* search for smallest 0x32 >= size */
4029 				if(format_type != 0x32)
4030 		continue;
4031 				if (i_size < size)
4032 		continue;
4033 				if (format_size >= 0 && i_size >= format_size)
4034 		continue;
4035 				index = i;
4036 				format_size = i_size;
4037 		continue;
4038 
4039 #else /* Libburn_bd_r_format_olD */
4040 
4041 				/* search largest and smallest 0x32 */
4042 				if(format_type != 0x32)
4043 		continue;
4044 				if (i_size < min_size || min_size < 0)
4045 					min_size = i_size;
4046 				if (i_size > max_size)
4047 					max_size = i_size;
4048 
4049 #endif /* ! Libburn_bd_r_format_olD */
4050 
4051 			}
4052 			/* common for all cases which search largest
4053 			   descriptors */
4054 			if (i_size > format_size) {
4055 				format_size = i_size;
4056 				index = i;
4057 			}
4058 		}
4059 		if (size_mode == 2 && index < 0 && !(flag & 32))
4060 			index = 0;
4061 		if (index < 0)
4062 			goto no_suitable_formatting_type;
4063 		format_type = d->format_descriptors[index].type;
4064 		if (flag & (1 << 16))
4065 			format_sub_type = 0; /* SRM + POW  */
4066 		else
4067 			format_sub_type = 1; /* SRM  (- POW) */
4068 
4069 #ifdef Libburn_bd_r_format_olD
4070 		if (0) {
4071 #else
4072 		if (size_mode == 0 || size_mode == 1) {
4073 #endif /* ! Libburn_bd_r_format_olD */
4074 
4075 			if (min_size < 0 || max_size < 0)
4076 				goto no_suitable_formatting_type;
4077 			if (size <= 0)
4078 				size = min_size;
4079 			if (size % 0x10000)
4080 				size += 0x10000 - (size % 0x10000);
4081 			if (size < min_size)
4082 				goto no_suitable_formatting_type;
4083 			else if(size > max_size)
4084 				goto no_suitable_formatting_type;
4085 			num_of_blocks = size / 2048;
4086 			mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
4087 			for (i = 0; i < 3; i++)
4088 				 c->page->data[9 + i] = 0;
4089 		} else {
4090 			num_of_blocks =
4091 				d->format_descriptors[index].size / 2048;
4092 			mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
4093 			for (i = 0; i < 3; i++)
4094 				 c->page->data[9 + i] =
4095 					( d->format_descriptors[index].tdp >>
4096 						  (16 - 8 * i)) & 0xff;
4097 		}
4098 		sprintf(descr, "%s", d->current_profile_text);
4099 		return_immediately = 1; /* caller must do the waiting */
4100 		c->page->data[1] |= 0x80; /* FOV = this flag vector is valid */
4101 
4102 	} else if (d->current_profile == 0x43) {
4103 		/* BD-RE */
4104 		index = -1;
4105 		format_size = -1;
4106 		if (d->num_format_descr <= 0)
4107 			goto no_suitable_formatting_type;
4108 		if (d->format_descriptors[0].type != 0)
4109 			goto no_suitable_formatting_type;
4110 		for (i = 0; i < d->num_format_descr; i++) {
4111 			format_type = d->format_descriptors[i].type;
4112 			i_size = d->format_descriptors[i].size;
4113 			if (format_type != 0x00 && format_type != 0x30 &&
4114 			    format_type != 0x31)
4115 		continue;
4116 			if (flag & 32) { /* No defect mgt */
4117 				/* search largest format 0x31 */
4118 				if(format_type != 0x31)
4119 		continue;
4120 			} else if(size_mode == 2) { /* max payload size */
4121 				/* search largest 0x30 format descriptor */
4122 				if(format_type != 0x30)
4123 		continue;
4124 			} else if(size_mode == 3) { /* default payload size */
4125 				if (accept_count < 1)
4126 					index = 0; /* this cannot certify */
4127 
4128 				/* ts A81129
4129 				   LG GGW-H20L YL03 refuses on 0x30 with
4130 				   "Quick certification". dvd+rw-format
4131 				   does 0x00 by default and succeeds quickly.
4132 				*/
4133 				if ((flag & 64) && format_type == 0x00) {
4134 					index = i;
4135 		break;
4136 				}
4137 
4138 				if(format_type != 0x30)
4139 		continue;
4140 				accept_count++;
4141 				if (accept_count == 1)
4142 					index = i;
4143 		continue;
4144 			} else { /* defect managed format with size wish */
4145 
4146 #ifdef Libburn_bd_re_format_olD
4147 
4148 				/* search for smallest 0x30 >= size */
4149 				if(format_type != 0x30)
4150 		continue;
4151 				if (i_size < size)
4152 		continue;
4153 				if (format_size >= 0 && i_size >= format_size)
4154 		continue;
4155 				index = i;
4156 				format_size = i_size;
4157 		continue;
4158 
4159 #else /* Libburn_bd_re_format_olD */
4160 
4161 				/* search largest and smallest 0x30 */
4162 				if(format_type != 0x30)
4163 		continue;
4164 				if (i_size < min_size || min_size < 0)
4165 					min_size = i_size;
4166 				if (i_size > max_size)
4167 					max_size = i_size;
4168 
4169 #endif /* ! Libburn_bd_re_format_olD */
4170 
4171 			}
4172 			/* common for all cases which search largest
4173 			   descriptors */
4174 			if (i_size > format_size) {
4175 				format_size = i_size;
4176 				index = i;
4177 			}
4178 		}
4179 
4180 		if (size_mode == 2 && index < 0 && !(flag & 32))
4181 			index = 0;
4182 		if (index < 0)
4183 			goto no_suitable_formatting_type;
4184 		format_type = d->format_descriptors[index].type;
4185 		if (format_type == 0x30 || format_type == 0x31) {
4186 			if ((flag & 64) || !(d->current_feat23h_byte4 & 3)) {
4187 				format_sub_type = 0;
4188 				if (!(flag & 64))
4189 					libdax_msgs_submit(libdax_messenger,
4190 					    d->global_index, 0x0002019e,
4191 					    LIBDAX_MSGS_SEV_NOTE,
4192 					    LIBDAX_MSGS_PRIO_HIGH,
4193 				"Drive does not support media certification",
4194 					    0, 0);
4195 			} else {
4196 				/* With Certification */
4197 				if (d->current_feat23h_byte4 & 1)
4198 					format_sub_type = 2; /* Full */
4199 				else
4200 					format_sub_type = 3; /* Quick */
4201 			}
4202 		}
4203 
4204 #ifdef Libburn_bd_re_format_olD
4205 		if (0) {
4206 #else
4207 		if (size_mode == 0 || size_mode == 1) {
4208 #endif /* ! Libburn_bd_re_format_olD */
4209 
4210 			if (min_size < 0 || max_size < 0)
4211 				goto no_suitable_formatting_type;
4212 			if (size <= 0)
4213 				size = min_size;
4214 			if (size % 0x10000)
4215 				size += 0x10000 - (size % 0x10000);
4216 			if (size < min_size)
4217 				goto no_suitable_formatting_type;
4218 			else if(size > max_size)
4219 				goto no_suitable_formatting_type;
4220 			num_of_blocks = size / 2048;
4221 			mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
4222 			for (i = 0; i < 3; i++)
4223 				 c->page->data[9 + i] = 0;
4224 		} else {
4225 			num_of_blocks =
4226 				d->format_descriptors[index].size / 2048;
4227 			mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
4228 			for (i = 0; i < 3; i++)
4229 				 c->page->data[9 + i] =
4230 					( d->format_descriptors[index].tdp >>
4231 						  (16 - 8 * i)) & 0xff;
4232 		}
4233 		sprintf(descr, "%s", d->current_profile_text);
4234 		return_immediately = 1; /* caller must do the waiting */
4235 		c->page->data[1] |= 0x80; /* FOV = this flag vector is valid */
4236 
4237 	} else {
4238 
4239 		/* >>> other formattable types to come */
4240 
4241 unsuitable_media:;
4242 		sprintf(msg, "Unsuitable media detected. Profile %4.4Xh  %s",
4243 			d->current_profile, d->current_profile_text);
4244 		libdax_msgs_submit(libdax_messenger, d->global_index,
4245 			0x0002011e,
4246 			LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
4247 			msg, 0, 0);
4248 		{ret = 0; goto ex;}
4249 	}
4250 	c->page->data[8] = (format_type << 2) | (format_sub_type & 3);
4251 
4252 	/* MMC-5 Table 253 , column Type Dependent Parameter */
4253 	if (format_type == 0x00 || format_type == 0x01 ||
4254 	    format_type == 0x31) {
4255 		/* Block Length 0x0800 = 2k */
4256 		c->page->data[ 9] = 0x00;
4257 		c->page->data[10] = 0x08;
4258 		c->page->data[11] = 0x00;
4259 	} else if (format_type >= 0x10 && format_type <= 0x15) {
4260           	/* ECC block size = 16 * 2k */
4261 		c->page->data[ 9] =  0;
4262 		c->page->data[10] =  0;
4263 		c->page->data[11] = 16;
4264 	}
4265 
4266 	sprintf(msg, "Format type %2.2Xh \"%s\", blocks = %.f",
4267 		format_type, descr, (double) num_of_blocks);
4268 	libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
4269 			LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
4270 			msg, 0, 0);
4271 	sprintf(msg, "CDB: ");
4272 	for (i = 0; i < 6; i++)
4273 		sprintf(msg + strlen(msg), "%2.2X ", c->opcode[i]);
4274 	libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
4275 			LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
4276 			msg, 0, 0);
4277 	sprintf(msg, "Format list: ");
4278 	for (i = 0; i < 12; i++)
4279 		sprintf(msg + strlen(msg), "%2.2X ", c->page->data[i]);
4280 	strcat(msg, "\n");
4281 	libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
4282 			LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
4283 			msg, 0, 0);
4284 
4285 #ifdef Libburn_do_not_format_dvd_ram_or_bd_rE
4286 	if(d->current_profile == 0x43 || d->current_profile == 0x12) {
4287 		sprintf(msg,
4288 		   "Formatting of %s not implemented yet - This is a dummy",
4289 		   d->current_profile_text);
4290 		libdax_msgs_submit(libdax_messenger, d->global_index,
4291 			0x00000002,
4292 			LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_ZERO,
4293 			msg, 0, 0);
4294 		{ret = 1; goto ex;}
4295 	}
4296 #endif /* Libburn_do_not_format_dvd_ram_or_bd_rE */
4297 
4298 /* <<<
4299 fprintf(stderr, "\nlibburn_DEBUG: FORMAT UNIT temporarily disabled.\n");
4300 ret = 1; goto ex;
4301  */
4302 
4303 	d->issue_command(d, c);
4304 	if (c->error && !tolerate_failure) {
4305 		spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
4306 		if (key != 0) {
4307 			sprintf(msg, "SCSI error on format_unit(%s): ", descr);
4308 			scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
4309 					&key, &asc, &ascq);
4310 			libdax_msgs_submit(libdax_messenger, d->global_index,
4311 				0x00020122,
4312 				LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
4313 				msg, 0, 0);
4314 
4315 		}
4316 		{ret = 0; goto ex;}
4317 	} else if ((!c->error) && (format_type == 0x13 || format_type == 0x15))
4318 		d->needs_close_session = 1;
4319 	if (return_immediately)
4320 		{ret = 1; goto ex;}
4321 	usleep(1000000); /* there seems to be a little race condition */
4322 	for (ret = 0; ret <= 0 ;) {
4323 		usleep(50000);
4324 		ret = spc_test_unit_ready(d);
4325 	}
4326 	mmc_sync_cache(d);
4327 	ret = 1;
4328 ex:;
4329 	BURN_FREE_MEM(msg);
4330 	BURN_FREE_MEM(c);
4331 	BURN_FREE_MEM(buf);
4332 	return ret;
4333 }
4334 
4335 
4336 /* ts B40107 : Outsourced from mmc_get_performance_al()
4337 */
4338 static int new_burn_speed_descr(struct burn_drive *d, int sd_source,
4339                                struct burn_speed_descriptor **sd, int flag)
4340 {
4341 	int ret;
4342 
4343 	ret = burn_speed_descriptor_new(&(d->mdata->speed_descriptors),
4344 	                                NULL, d->mdata->speed_descriptors, 0);
4345 	if (ret <= 0)
4346 		return ret;
4347 
4348 	*sd = d->mdata->speed_descriptors;
4349 	(*sd)->source = sd_source;
4350 	if (d->current_profile > 0) {
4351 		(*sd)->profile_loaded = d->current_profile;
4352 		strcpy((*sd)->profile_name, d->current_profile_text);
4353 	}
4354 	return 1;
4355 }
4356 
4357 
4358 /* ts B40107 : Outsourced from mmc_get_performance_al()
4359                and extended for descr_type 0x00
4360    @param flag bit0= register speed descriptors
4361 */
4362 static int interpret_performance(struct burn_drive *d, struct command *c,
4363                                 int descr_type, int *alloc_len, int *max_descr,
4364                                 int *num_descr, int flag)
4365 {
4366 	int len, i, b, ret, old_alloc_len;
4367 	int exact_bit, read_speed, write_speed, start_speed;
4368 	int min_write_speed = 0x7fffffff, max_write_speed = 0;
4369 	int min_read_speed = 0x7fffffff, max_read_speed = 0;
4370 	unsigned long end_lba;
4371 	unsigned char *pd;
4372 	struct burn_speed_descriptor *sd;
4373 
4374 	/* ts A61225 : 1 = report about speed descriptors */
4375 	static int speed_debug = 0;
4376 
4377         len = mmc_four_char_to_int(c->page->data);
4378 	old_alloc_len = *alloc_len;
4379         *alloc_len = len + 4;
4380 	if (len + 4 > old_alloc_len)
4381 		len = old_alloc_len - 4;
4382 	*num_descr = ( *alloc_len - 8 ) / 16;
4383 	if (*max_descr == 0) {
4384 		*max_descr = *num_descr;
4385 		{ret = 1; goto ex;}
4386 	}
4387 	if (old_alloc_len < 16)
4388 		{ret = 1; goto ex;}
4389 	if (len < 12)
4390 		{ret = 0; goto ex;}
4391 
4392 	min_write_speed = d->mdata->min_write_speed;
4393 	max_write_speed = d->mdata->max_write_speed;
4394 	pd = c->page->data;
4395 	if (*num_descr > *max_descr)
4396 		*num_descr = *max_descr;
4397 	for (i = 0; i < *num_descr && (flag & 1); i++) {
4398 		end_lba = read_speed = write_speed = start_speed = 0;
4399 
4400 		if (descr_type == 0x03) {
4401 			exact_bit = !!(pd[8 + i*16] & 2);
4402 			for (b = 0; b < 4 ; b++) {
4403 				end_lba     += ((unsigned long int)
4404 						pd[8 + i*16 +  4 + b])
4405 				               << (24 - 8 * b);
4406 				read_speed  += pd[8 + i*16 +  8 + b]
4407 				               << (24 - 8 * b);
4408 				write_speed += pd[8 + i*16 + 12 + b]
4409 				               << (24 - 8 * b);
4410 			}
4411 			if (end_lba > 0x7ffffffe)
4412 				end_lba = 0x7ffffffe;
4413 
4414 			if (speed_debug)
4415 				fprintf(stderr,
4416 		"LIBBURN_DEBUG: kB/s: write=%d  read=%d  end=%lu  exact=%d\n",
4417 				        write_speed, read_speed,
4418 				        end_lba, exact_bit);
4419 
4420 			ret = new_burn_speed_descr(d, 2, &sd, 0);
4421 			if (ret > 0) {
4422 				sd->wrc = (pd[8 + i*16] >> 3 ) & 3;
4423 				sd->exact = exact_bit;
4424 				sd->mrw = pd[8 + i*16] & 1;
4425 				sd->end_lba = end_lba;
4426 				sd->write_speed = write_speed;
4427 				sd->read_speed = read_speed;
4428 			}
4429 
4430 		} else { /* descr_type == 0 */
4431 			for (b = 0; b < 4 ; b++) {
4432 				start_speed += pd[8 + i*16 +  4 + b]
4433 				               << (24 - 8 * b);
4434 				end_lba     += ((unsigned long int)
4435 				                pd[8 + i*16 +  8 + b])
4436 				               << (24 - 8 * b);
4437 				read_speed  += pd[8 + i*16 + 12 + b]
4438 				               << (24 - 8 * b);
4439 			}
4440 
4441 			if (speed_debug)
4442 				fprintf(stderr,
4443 		       "LIBBURN_DEBUG: start=%d  end=%d  lba=%lu\n",
4444 				        start_speed, read_speed, end_lba);
4445 
4446 			if (end_lba > 0x7ffffffe)
4447 				end_lba = 0x7ffffffe;
4448 			ret = new_burn_speed_descr(d, 3, &sd, 0);
4449 			if (ret > 0) {
4450 				sd->end_lba = end_lba;
4451 				sd->read_speed = start_speed;
4452 			}
4453 			if (start_speed > 0 && start_speed < min_read_speed)
4454 				min_read_speed = start_speed;
4455 			if (start_speed > max_read_speed)
4456                         	max_read_speed = start_speed;
4457 			ret = new_burn_speed_descr(d, 3, &sd, 0);
4458 			if (ret > 0) {
4459 				sd->end_lba = end_lba;
4460 				sd->read_speed = read_speed;
4461 			}
4462 		}
4463 
4464 		if ((int) end_lba > d->mdata->max_end_lba)
4465 			d->mdata->max_end_lba = end_lba;
4466 		if ((int) end_lba < d->mdata->min_end_lba)
4467 			d->mdata->min_end_lba = end_lba;
4468 		if (write_speed > 0 && write_speed < min_write_speed)
4469 			min_write_speed = write_speed;
4470 		if (write_speed > max_write_speed)
4471                         max_write_speed = write_speed;
4472 		if (read_speed > 0 && read_speed < min_read_speed)
4473 			min_read_speed = read_speed;
4474 		if (read_speed > max_read_speed)
4475                         max_read_speed = read_speed;
4476 	}
4477 	if (min_write_speed < 0x7fffffff)
4478 		d->mdata->min_write_speed = min_write_speed;
4479 	if (max_write_speed > 0)
4480 		d->mdata->max_write_speed = max_write_speed;
4481 	/* there is no mdata->min_read_speed yet
4482 	if (min_read_speed < 0x7fffffff)
4483 		d->mdata->min_read_speed = min_read_speed;
4484 	*/
4485 	if (max_read_speed > 0)
4486 		d->mdata->max_read_speed = max_read_speed;
4487 
4488         ret = 1;
4489 ex:;
4490 	return ret;
4491 }
4492 
4493 
4494 /* ts A61225 */
4495 /* @param flag bit0= register speed descriptors
4496 */
4497 static int mmc_get_performance_al(struct burn_drive *d, int descr_type,
4498 		 int *alloc_len, int *max_descr, int flag)
4499 {
4500 	int num_descr, ret;
4501 	struct buffer *buf = NULL;
4502 	struct command *c = NULL;
4503 
4504 	BURN_ALLOC_MEM(buf, struct buffer, 1);
4505 	BURN_ALLOC_MEM(c, struct command, 1);
4506 
4507 	if (d->current_profile < 0)
4508 		mmc_get_configuration(d);
4509 
4510 	if (*alloc_len < 8)
4511 		{ret = 0; goto ex;}
4512 	if (descr_type != 0x00 && descr_type != 0x03)
4513 		{ret = 0; goto ex;}
4514 
4515 	scsi_init_command(c, MMC_GET_PERFORMANCE,
4516 			 sizeof(MMC_GET_PERFORMANCE));
4517 
4518 	/* >>> future: maintain a list of write descriptors
4519 	if (max_descr > d->max_write_descr - d->num_write_descr)
4520 		max_descr = d->max_write_descr;
4521 	*/
4522 	c->dxfer_len = *alloc_len;
4523 
4524 	if (descr_type == 0x00)
4525 		c->opcode[1] = 0x10; /* Data Type: nominal read performance */
4526 	c->opcode[8] = ( *max_descr >> 8 ) & 0xff;
4527 	c->opcode[9] = ( *max_descr >> 0 ) & 0xff;
4528 	c->opcode[10] = descr_type;
4529 	c->retry = 1;
4530 	c->page = buf;
4531 	c->page->sectors = 0;
4532 	c->page->bytes = 0;
4533 	c->dir = FROM_DRIVE;
4534 	d->issue_command(d, c);
4535 
4536 #ifdef Libisofs_simulate_old_mmc1_drivE
4537 	c->error = 1;
4538 	c->sense[0] = 0x70; /* Fixed format sense data */
4539 	c->sense[2] = 0x5;
4540 	c->sense[12] = 0x20;
4541 	c->sense[13] = 0x0;
4542 #endif /* Libisofs_simulate_old_mmc1_drivE */
4543 
4544 	if (c->error)
4545 		{ret = 0; goto ex;}
4546 
4547 	ret = interpret_performance(d, c, descr_type, alloc_len, max_descr,
4548 	      	                    &num_descr, flag);
4549 	if (ret <= 0)
4550 		goto ex;
4551 
4552 	ret = num_descr;
4553 ex:;
4554 	BURN_FREE_MEM(buf);
4555 	BURN_FREE_MEM(c);
4556 	return ret;
4557 }
4558 
4559 
4560 int mmc_get_performance(struct burn_drive *d, int descr_type, int flag)
4561 {
4562 	int alloc_len = 8, max_descr = 0, ret;
4563 
4564 	mmc_start_if_needed(d, 1);
4565 	if (mmc_function_spy(d, "mmc_get_write_performance") <= 0)
4566 		return 0;
4567 
4568 	/* first command execution to learn number of descriptors and
4569            dxfer_len
4570 	*/
4571 	ret = mmc_get_performance_al(d, descr_type, &alloc_len, &max_descr, 0);
4572 	if (max_descr > 0 && ret > 0) {
4573 		/* Some drives announce only 1 descriptor if asked for 0.
4574 		   So ask twice for non-0 descriptors.
4575 		*/
4576 		ret = mmc_get_performance_al(d, descr_type,
4577 		                             &alloc_len, &max_descr, 0);
4578 	}
4579 /*
4580 	fprintf(stderr,"LIBBURN_DEBUG: ACh alloc_len = %d , ret = %d\n",
4581 			alloc_len, ret);
4582 */
4583 	if (max_descr > 0 && ret > 0) {
4584 		/* final execution with announced length */
4585 		max_descr = (alloc_len - 8) / 16;
4586 		ret = mmc_get_performance_al(d, descr_type,
4587 		                             &alloc_len, &max_descr, 1);
4588 	}
4589 	return ret;
4590 }
4591 
4592 
4593 int mmc_get_write_performance(struct burn_drive *d)
4594 {
4595 	int ret;
4596 
4597 	ret = mmc_get_performance(d, 0x03, 0);
4598 	return ret;
4599 }
4600 
4601 
4602 /* ts A61229 : outsourced from spc_select_write_params() */
4603 /* Note: Page data is not zeroed here in order not to overwrite preset
4604          defaults. Thus
4605            memset(pd, 0, 2 + d->mdata->write_page_length);
4606          is the eventual duty of the caller.
4607 */
4608 int mmc_compose_mode_page_5(struct burn_drive *d, struct burn_session *s,
4609 				int tnum, const struct burn_write_opts *o,
4610 				unsigned char *pd)
4611 {
4612 	unsigned char *catalog = NULL;
4613 	char isrc_text[13 + 21]; /* should suffice for 64 bit oversize */
4614 	struct isrc *isrc;
4615 
4616 	pd[0] = 5;
4617 	pd[1] = d->mdata->write_page_length;
4618 
4619 	if (d->current_profile == 0x13) {
4620 		/* A61229 : DVD-RW restricted overwrite */
4621 		/* learned from transport.hxx : page05_setup()
4622 		   and mmc3r10g.pdf table 347 */
4623  		/* BUFE (burnproof), no LS_V (i.e. default Link Size, i hope),
4624 		   no simulate, write type 0 = packet */
4625 		pd[2] = (1 << 6);
4626 		/* no multi, fixed packet, track mode 5 */
4627 		pd[3] = (1 << 5) | 5;
4628 		/* Data Block Type */
4629 		pd[4] = 8;
4630 		/* Link size dummy */
4631 		pd[5] = 0;
4632 	} else if ((d->current_profile == 0x14 || d->current_profile == 0x11 ||
4633 			d->current_profile == 0x15)
4634 			&& o->write_type == BURN_WRITE_SAO) {
4635 		/* ts A70205 : DVD-R[W][/DL] : Disc-at-once, DAO */
4636 		/* Learned from dvd+rw-tools and mmc5r03c.pdf .
4637 		   See doc/cookbook.txt for more detailed references. */
4638 
4639 		/* BUFE , LS_V = 0, Test Write, Write Type = 2 SAO (DAO) */
4640 		pd[2] = ((!!o->underrun_proof) << 6)
4641 			| ((!!o->simulate) << 4)
4642 			| 2;
4643 
4644 		/* No multi-session , FP = 0 , Copy = 0, Track Mode = 5 */
4645 		pd[3] = 5;
4646 
4647 #ifdef Libburn_pioneer_dvr_216d_load_mode5
4648 
4649 		/* >>> use track mode from mmc_get_nwa() */
4650 		/* >>> pd[3] = (pd[3] & ~0xf) | (d->track_inf[5] & 0xf); */
4651 
4652 #endif
4653 
4654 		/* Data Block Type = 8 */
4655 		pd[4] = 8;
4656 
4657 	} else if (d->current_profile == 0x14 || d->current_profile == 0x11 ||
4658 			d->current_profile == 0x15) {
4659 		/* ts A70128 : DVD-R[W][/DL] Incremental Streaming */
4660 		/* Learned from transport.hxx : page05_setup()
4661 		   and mmc5r03c.pdf 7.5, 4.2.3.4 Table 17
4662 		   and spc3r23.pdf 6.8, 7.4.3 */
4663 
4664 		/* BUFE , LS_V = 1, Test Write,
4665 		   Write Type = 0 Packet/Incremental */
4666 		pd[2] = ((!!o->underrun_proof) << 6)
4667 			| (1 << 5)
4668 			| ((!!o->simulate) << 4);
4669 		/* Multi-session , FP = 1 , Track Mode = 5 */
4670 		pd[3] = ((3 * !!o->multi) << 6) | (1 << 5) | 5;
4671 		/* Data Block Type = 8 */
4672 		pd[4] = 8;
4673 		/* Link Size */
4674 		if (d->current_feat21h_link_size >= 0)
4675 			pd[5] = d->current_feat21h_link_size;
4676 		else
4677 			pd[5] = 16;
4678 		if (d->current_feat21h_link_size != 16) {
4679 			char msg[80];
4680 
4681 			sprintf(msg,
4682 				"Feature 21h Link Size = %d (expected 16)\n",
4683 				d->current_feat21h_link_size);
4684 			libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
4685 				LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
4686 				msg, 0, 0);
4687 		}
4688 		/* Packet Size */
4689 		pd[13] = 16;
4690 
4691 	} else if (d->current_profile == 0x1a || d->current_profile == 0x1b ||
4692 	           d->current_profile == 0x2b || d->current_profile == 0x12 ||
4693 		   d->current_profile == 0x41 || d->current_profile == 0x42 ||
4694 		   d->current_profile == 0x43) {
4695 		/* not with DVD+R[W][/DL] or DVD-RAM or BD-R[E] */;
4696 		return 0;
4697 	} else {
4698 		/* Traditional setup for CD */
4699 
4700 		pd[2] = ((!!o->underrun_proof) << 6)
4701 			| ((!!o->simulate) << 4)
4702 			| (o->write_type & 0x0f);
4703 
4704 		/* ts A61106 : MMC-1 table 110 : multi==0 or multi==3 */
4705 		pd[3] = ((3 * !!o->multi) << 6) | (o->control & 0x0f);
4706 
4707 		pd[4] = spc_block_type(o->block_type);
4708 
4709 /*
4710 fprintf(stderr, "libburn_EXPERIMENTAL: block_type = %d, pd[4]= %u\n",
4711                  o->block_type, (unsigned int) pd[4]);
4712 */
4713 
4714 		/* ts A61104 */
4715 		if(!(o->control&4)) /* audio (MMC-1 table 61) */
4716 			if(o->write_type == BURN_WRITE_TAO)
4717 				pd[4] = 0; /* Data Block Type: Raw Data */
4718 
4719 		pd[14] = 0;     /* audio pause length MSB */
4720 		pd[15] = 150;	/* audio pause length LSB */
4721 
4722 /*XXX need session format! */
4723 /* ts A61229 : but session format (pd[8]) = 0 seems ok */
4724 
4725 		/* Media Catalog Number at byte 16 to 31,
4726 		   MMC-5, 7.5, Tables 664, 670
4727 		*/
4728 		if (o->has_mediacatalog)
4729 			catalog = (unsigned char *) o->mediacatalog;
4730 		else if (s != NULL) {
4731 			if (s->mediacatalog[0])
4732 				catalog = s->mediacatalog;
4733 		}
4734 		if (catalog != NULL && d->mdata->write_page_length >= 30) {
4735 			pd[16] = 0x80; /* MCVAL */
4736 			memcpy(pd + 17, catalog, 13);
4737 		}
4738 
4739 		/* ISRC at bytes 32 to 47. Tables 664, 671 */
4740 		/* SCMS at byte 3 bit 4 */
4741 		isrc_text[0] = 0;
4742 		if (s != NULL && o->write_type == BURN_WRITE_TAO) {
4743 			if (tnum >= 0 && tnum < s->tracks) {
4744 				if (s->track[tnum]->isrc.has_isrc) {
4745 					isrc = &(s->track[tnum]->isrc);
4746 					isrc_text[0] = isrc->country[0];
4747 					isrc_text[1] = isrc->country[1];
4748 					isrc_text[2] = isrc->owner[0];
4749 					isrc_text[3] = isrc->owner[1];
4750 					isrc_text[4] = isrc->owner[2];
4751 					sprintf(isrc_text + 5, "%-2.2u",
4752 						(unsigned int) isrc->year);
4753 					sprintf(isrc_text + 7, "%-5.5u",
4754 						isrc->serial);
4755 					isrc_text[12]= 0;
4756 				}
4757 				if ((s->track[tnum]->mode & BURN_SCMS) &&
4758 				    !(s->track[tnum]->mode & BURN_COPY))
4759 					pd[3] |= 0x10;
4760 			}
4761 		}
4762 		if (isrc_text[0] != 0 && d->mdata->write_page_length >= 46) {
4763 			pd[32] = 0x80; /* TCVAL */
4764 			memcpy(pd + 33, isrc_text, 12);
4765 		}
4766 	}
4767 	return 1;
4768 }
4769 
4770 
4771 /* A70812 ts */
4772 int mmc_read_10(struct burn_drive *d, int start,int amount, struct buffer *buf)
4773 {
4774 	struct command *c;
4775 	char *msg = NULL;
4776 	int key, asc, ascq, silent;
4777 
4778 	c = &(d->casual_command);
4779 	mmc_start_if_needed(d, 0);
4780 	if (mmc_function_spy(d, "mmc_read_10") <= 0)
4781 		return -1;
4782 
4783 	if (amount > BUFFER_SIZE / 2048)
4784 		return -1;
4785 
4786 	scsi_init_command(c, MMC_READ_10, sizeof(MMC_READ_10));
4787 	c->dxfer_len = amount * 2048;
4788 	c->retry = 1;
4789 	mmc_int_to_four_char(c->opcode + 2, start);
4790 	c->opcode[7] = (amount >> 8) & 0xFF;
4791 	c->opcode[8] = amount & 0xFF;
4792 	c->page = buf;
4793 	c->page->bytes = 0;
4794 	c->page->sectors = 0;
4795 	c->dir = FROM_DRIVE;
4796 	d->issue_command(d, c);
4797 
4798 	/* <<< replace by mmc_eval_read_error */;
4799 	if (c->error) {
4800 		msg = calloc(1, 256);
4801 		if (msg != NULL) {
4802 			sprintf(msg,
4803 			  "SCSI error on read_10(%d,%d): ", start, amount);
4804 			scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
4805 					&key, &asc, &ascq);
4806 			silent = (d->silent_on_scsi_error == 1);
4807 			if (key == 5 && asc == 0x64 && ascq == 0x0) {
4808 				d->had_particular_error |= 1;
4809 				if (d->silent_on_scsi_error == 2)
4810 					silent = 1;
4811 			}
4812 			if(!silent)
4813 				libdax_msgs_submit(libdax_messenger,
4814 				d->global_index,
4815 				0x00020144,
4816 				(d->silent_on_scsi_error == 3) ?
4817 				 LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
4818 				LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
4819 			free(msg);
4820 		}
4821 		return BE_CANCELLED;
4822 	}
4823 
4824 	buf->sectors = amount;
4825 	buf->bytes = amount * 2048;
4826 	return 0;
4827 }
4828 
4829 
4830 #ifdef Libburn_develop_quality_scaN
4831 
4832 /* B21108 ts : Vendor specific command REPORT ERROR RATE, see
4833                http://liggydee.cdfreaks.com/ddl/errorcheck.pdf
4834 */
4835 int mmc_nec_optiarc_f3(struct burn_drive *d, int sub_op,
4836                        int start_lba, int rate_period,
4837                        int *ret_lba, int *error_rate1, int *error_rate2)
4838 {
4839 	struct buffer *buf = NULL;
4840 	struct command *c;
4841 	char *msg = NULL;
4842 	int key, asc, ascq, ret;
4843 	static unsigned char MMC_NEC_OPTIARC_F3[] =
4844 		{ 0xF3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
4845 
4846 	BURN_ALLOC_MEM(buf, struct buffer, 1);
4847 	BURN_ALLOC_MEM(c, struct command, 1);
4848 	mmc_start_if_needed(d, 0);
4849 	if (mmc_function_spy(d, "mmc_nec_optiarc_f3") <= 0)
4850 		return -1;
4851 
4852 	scsi_init_command(c, MMC_NEC_OPTIARC_F3, sizeof(MMC_NEC_OPTIARC_F3));
4853 	if (sub_op == 3) {
4854 		c->dxfer_len = 8;
4855 		c->dir = FROM_DRIVE;
4856 	} else {
4857 		c->dxfer_len = 0;
4858 		c->dir = NO_TRANSFER;
4859 	}
4860 	c->retry = 0;
4861 	c->opcode[1] = sub_op;
4862 	mmc_int_to_four_char(c->opcode + 2, start_lba);
4863 	c->opcode[8] = rate_period;
4864 	c->page = buf;
4865 	c->page->bytes = 0;
4866 	c->page->sectors = 0;
4867 	d->issue_command(d, c);
4868 	if (c->error) {
4869 		msg = calloc(1, 256);
4870 		if (msg != NULL) {
4871 			sprintf(msg,
4872 			  "SCSI error on nec_optiarc_f3(%d, %d, %d): ",
4873                            sub_op, start_lba, rate_period);
4874 			scsi_error_msg(d, c->sense, 14, msg + strlen(msg),
4875 					&key, &asc, &ascq);
4876 			libdax_msgs_submit(libdax_messenger,
4877 				d->global_index, 0x00020144,
4878 				LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
4879 				msg, 0, 0);
4880 			free(msg);
4881 		}
4882 		return BE_CANCELLED;
4883 	}
4884 
4885 	if (sub_op == 3) {
4886 		*ret_lba = mmc_four_char_to_int(c->page->data);
4887 		*error_rate1 = c->page->data[4] * 256 + c->page->data[5];
4888 		*error_rate2 = c->page->data[6] * 256 + c->page->data[7];
4889 	}
4890 
4891 	ret = 1;
4892 ex:;
4893 	BURN_FREE_MEM(c);
4894 	BURN_FREE_MEM(buf);
4895 	return ret;
4896 }
4897 
4898 #endif /* Libburn_develop_quality_scaN */
4899 
4900 
4901 /* ts A81210 : Determine the upper limit of readable data size */
4902 int mmc_read_capacity(struct burn_drive *d)
4903 {
4904 	struct buffer *buf = NULL;
4905 	struct command *c = NULL;
4906 	int alloc_len= 8, ret;
4907 
4908 	BURN_ALLOC_MEM(buf, struct buffer, 1);
4909 	BURN_ALLOC_MEM(c, struct command, 1);
4910 	d->media_read_capacity = 0x7fffffff;
4911 	d->mr_capacity_trusted = -1;
4912 	mmc_start_if_needed(d, 1);
4913 	if (mmc_function_spy(d, "mmc_read_capacity") <= 0)
4914 		{ret = 0; goto ex;}
4915 
4916 	scsi_init_command(c, MMC_READ_CAPACITY, sizeof(MMC_READ_CAPACITY));
4917 	c->dxfer_len = alloc_len;
4918 	c->retry = 1;
4919 	c->page = buf;
4920 	c->page->bytes = 0;
4921 	c->page->sectors = 0;
4922 	c->dir = FROM_DRIVE;
4923 	d->issue_command(d, c);
4924 	d->media_read_capacity = mmc_four_char_to_int(c->page->data);
4925 	if (d->media_read_capacity < 0) {
4926 		d->media_read_capacity = 0x7fffffff;
4927 		{ret = 0; goto ex;}
4928 	}
4929 	if (d->current_profile >= 0x08 && d->current_profile <= 0x0A)
4930 		d->mr_capacity_trusted = 0;
4931 	else
4932 		d->mr_capacity_trusted = 1;
4933 	ret = 1;
4934 ex:;
4935 	BURN_FREE_MEM(c);
4936 	BURN_FREE_MEM(buf);
4937 	return ret;
4938 }
4939 
4940 
4941 /* ts A90903 */
4942 /* mmc5r03c.pdf 6.23 ADh READ DISC STRUCTURE obtains media specific information
4943 */
4944 static int mmc_read_disc_structure_al(struct burn_drive *d, int *alloc_len,
4945 				int media_type, int layer_number, int format,
4946 				int min_len, char **reply, int *reply_len,
4947 				int flag)
4948 {
4949 	struct buffer *buf = NULL;
4950 	int old_alloc_len, len, ret;
4951 	struct command *c = NULL;
4952 	unsigned char *dpt;
4953 
4954 	BURN_ALLOC_MEM(buf, struct buffer, 1);
4955 	BURN_ALLOC_MEM(c, struct command, 1);
4956 	*reply = NULL;
4957 	*reply_len = 0;
4958 
4959 	if (*alloc_len < 4)
4960 		{ret = 0; goto ex;}
4961 
4962 	scsi_init_command(c, MMC_READ_DISC_STRUCTURE,
4963 			 sizeof(MMC_READ_DISC_STRUCTURE));
4964 	c->dxfer_len = *alloc_len;
4965 	c->retry = 1;
4966 	c->opcode[1]= media_type;
4967 	c->opcode[7]= format;
4968 	c->opcode[8]= (c->dxfer_len >> 8) & 0xff;
4969 	c->opcode[9]= c->dxfer_len & 0xff;
4970 	c->page = buf;
4971 	c->page->sectors = 0;
4972 	c->page->bytes = 0;
4973 	c->dir = FROM_DRIVE;
4974 
4975 	d->issue_command(d, c);
4976 	if (c->error)
4977 		{ret = 0; goto ex;}
4978 
4979 	len = (c->page->data[0] << 8) | (c->page->data[1]);
4980 	old_alloc_len = *alloc_len;
4981 	*alloc_len = len + 2;
4982 	if (old_alloc_len <= 4)
4983 		{ret = 1; goto ex;}
4984 	if (len + 2 > old_alloc_len)
4985 		len = old_alloc_len - 2;
4986 	if (len < 4)
4987 		{ret = 0; goto ex;}
4988 
4989 	dpt = c->page->data + 4;
4990 	if (len - 2 < min_len)
4991 		{ret = 0; goto ex;}
4992 	*reply = calloc(len - 2, 1);
4993 	if (*reply == NULL)
4994 		{ret = 0; goto ex;}
4995 	*reply_len = len - 2;
4996 	memcpy(*reply, dpt, len - 2);
4997 	ret = 1;
4998 ex:;
4999 	BURN_FREE_MEM(c);
5000 	BURN_FREE_MEM(buf);
5001 	return ret;
5002 }
5003 
5004 
5005 int mmc_read_disc_structure(struct burn_drive *d,
5006 		int media_type, int layer_number, int format, int min_len,
5007 		char **reply, int *reply_len, int flag)
5008 {
5009 	int alloc_len = 4, ret;
5010 	char msg[80];
5011 
5012 	mmc_start_if_needed(d, 1);
5013 	if (mmc_function_spy(d, "mmc_read_disc_structure") <= 0)
5014 		return 0;
5015 
5016 	ret = mmc_read_disc_structure_al(d, &alloc_len,
5017 				media_type, layer_number, format, min_len,
5018 				reply, reply_len, 0);
5019 /*
5020 	fprintf(stderr,"LIBBURN_DEBUG: ADh alloc_len = %d , ret = %d\n",
5021 		 alloc_len, ret);
5022 */
5023 	if (ret <= 0)
5024 		return ret;
5025 	if (alloc_len < 12) {
5026 		sprintf(msg,
5027 		    "READ DISC STRUCTURE announces only %d bytes of reply\n",
5028 		    alloc_len);
5029 		libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
5030 			LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
5031 			msg, 0, 0);
5032 		ret = 0;
5033 
5034 /* ts A91205
5035    LG GH22LS30 revision 1.00 returns for DVD-R format
5036    code 0x0E an allocation length of 4 (= 0 payload).
5037    A MS-Windows tool can inquire media code "RITEKF1",
5038    though.
5039    This macro causes a try to unconditionally read the
5040    desired payload bytes. The drive then returns 35
5041    bytes as requested and the media id is "RITEKF1".
5042    Nevertheless this is not a generally usable gesture
5043    because older GNU/Linux USB dislikes requests to fetch
5044    more bytes than the drive will deliver.
5045 
5046    # define Libburn_enforce_structure_code_0x0E 1
5047 */
5048 
5049 #ifdef Libburn_enforce_structure_code_0x0E
5050 		if (format == 0x0E) {
5051 			alloc_len = min_len + 4;
5052 			ret = mmc_read_disc_structure_al(d, &alloc_len,
5053 				media_type, layer_number, format, min_len,
5054 				reply, reply_len, 0);
5055 			if (*reply_len < min_len || *reply == NULL)
5056 				ret = 0;
5057 			sprintf(msg, "READ DISC STRUCTURE returns %d bytes of required %d\n",
5058 				*reply_len + 4, min_len + 4);
5059 			libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
5060 				LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
5061 				msg, 0, 0);
5062 		}
5063 #endif
5064 
5065 	} else
5066 		ret = mmc_read_disc_structure_al(d, &alloc_len,
5067 				media_type, layer_number, format, min_len,
5068 				reply, reply_len, 0);
5069 	return ret;
5070 }
5071 
5072 /* ts A90903 */
5073 /*
5074     @param flag    bit0= set bit1 in flag for burn_util_make_printable_word
5075                          and do not append media revision
5076                    bit1= truncate media_code1 to 6 characters (else 8)
5077 */
5078 static int mmc_set_product_id(char *reply,
5079 	 int manuf_idx, int type_idx, int rev_idx,
5080 	char **product_id, char **media_code1, char **media_code2, int flag)
5081 {
5082 	int ret;
5083 
5084 	*product_id = calloc(17, 1);
5085 	*media_code1 = calloc(9, 1);
5086 	*media_code2 = calloc(8, 1);
5087 	if (*product_id == NULL ||
5088 	    *media_code1 == NULL || *media_code2 == NULL)
5089 		return -1;
5090 	if (flag & 2)
5091 		sprintf(*media_code1, "%.6s", reply + manuf_idx);
5092 	else
5093 		sprintf(*media_code1, "%.8s", reply + manuf_idx);
5094 	ret = burn_util_make_printable_word(media_code1,
5095 						 1 | ((flag & 1) << 1));
5096 	if (ret <= 0)
5097 		return -1;
5098 	sprintf(*media_code2, "%.3s%s", reply + type_idx,
5099 					 (flag & 1) ? "" : "xxxx");
5100 	ret = burn_util_make_printable_word(media_code2,
5101 						 1 | ((flag & 1) << 1));
5102 	if (ret <= 0)
5103 		return -1;
5104 	if (!(flag & 1)) {
5105 		sprintf(*media_code2 + strlen(*media_code2) - 4, "/%d",
5106 			(int) ((unsigned char *) reply)[rev_idx]);
5107 	}
5108 	sprintf(*product_id, "%s/%s", *media_code1, *media_code2);
5109 	return 1;
5110 }
5111 
5112 
5113 /* ts A90903 */
5114 /* MMC backend of API call burn_disc_get_media_id()
5115    See also doc/mediainfo.txt
5116     @param flag        Bitfield for control purposes
5117                        bit0= do not escape " _/" (not suitable for
5118                              burn_guess_manufacturer())
5119 
5120 */
5121 int mmc_get_media_product_id(struct burn_drive *d,
5122 	char **product_id, char **media_code1, char **media_code2,
5123 	char **book_type, int flag)
5124 {
5125 	int prf, ret, reply_len, i, has_11h = -1, bt, start_lba, end_lba;
5126 	int min, sec, fr, media_type = 0;
5127 	char *reply = NULL, *wpt;
5128 
5129 	static char *books[16] = {
5130 		"DVD-ROM", "DVD-RAM", "DVD-R", "DVD-RW",
5131 		"HD DVD-ROM", "HD DVD-RAM", "HD DVD-R", "unknown",
5132 		"unknown", "DVD+RW", "DVD+R", "unknown",
5133 		"unknown", "DVD+RW DL", "DVD+R DL", "unknown"};
5134 
5135 	*product_id = *media_code1 = *media_code2 = *book_type = NULL;
5136 	prf = d->current_profile;
5137 	if (prf == 0x09 || prf == 0x0A) {
5138 
5139 		*product_id = calloc(20, 1);
5140 		*media_code1 = calloc(10, 1);
5141 		*media_code2 = calloc(10, 1);
5142 		if (*product_id == NULL ||
5143 		    *media_code1 == NULL || *media_code2 == NULL) {
5144 			ret = -1;
5145 			goto ex;
5146 		}
5147 		ret = burn_disc_read_atip(d);
5148 		if (ret <= 0)
5149 			goto ex;
5150 		ret = burn_drive_get_start_end_lba(d, &start_lba, &end_lba, 0);
5151 		if (ret <= 0)
5152 			goto ex;
5153 		burn_lba_to_msf(start_lba, &min, &sec, &fr);
5154 		sprintf(*media_code1, "%2.2dm%2.2ds%2.2df", min, sec, fr);
5155 		burn_lba_to_msf(end_lba, &min, &sec, &fr);
5156 		sprintf(*media_code2, "%2.2dm%2.2ds%2.2df", min, sec, fr);
5157 		sprintf(*product_id, "%s/%s", *media_code1, *media_code2);
5158 		ret = 1;
5159 		goto ex; /* No booktype with CD media */
5160 
5161         } else if (prf == 0x11 || prf == 0x13 || prf == 0x14 || prf == 0x15) {
5162 								 /* DVD-R */
5163 
5164 		ret = mmc_read_disc_structure(d, 0, 0, 0x0E, 31, &reply,
5165 							 &reply_len, 0);
5166 		if (ret <= 0)
5167 			goto ex;
5168 		/* ECMA-279 for DVD-R promises a third sixpack in field 5,
5169 		   but ECMA-338 for DVD-RW defines a different meaning.
5170 		   DVD-R and DVD-RW bear unprintable characters in there.
5171 		 */
5172 		if (reply[16] != 3 || reply[24] != 4) {
5173 			ret = 0;
5174 			goto ex;
5175 		}
5176 		*media_code1 = calloc(19, 1);
5177 		*media_code2 = strdup("");
5178 		if (*media_code1 == NULL || *media_code2 == NULL) {
5179 			ret = -1;
5180 			goto ex;
5181 		}
5182 		memcpy(*media_code1, reply + 17, 6);
5183 		memcpy(*media_code1 + 6, reply + 25, 6);
5184 
5185 		/* Clean out 0 bytes */
5186 		wpt = *media_code1;
5187 		for (i = 0; i < 18; i++)
5188 			if ((*media_code1)[i])
5189 				*(wpt++) = (*media_code1)[i];
5190 		*wpt = 0;
5191 		ret = burn_util_make_printable_word(media_code1,
5192 						 1 | ((flag & 1) << 1));
5193 		if (ret <= 0)
5194 			goto ex;
5195 		*product_id = strdup(*media_code1);
5196 		if (*product_id == NULL) {
5197 			ret = -1;
5198 			goto ex;
5199 		}
5200 
5201         } else if (prf == 0x1a || prf == 0x1b || prf == 0x2b) { /* DVD+R[W] */
5202 
5203 		/* Check whether the drive supports format 11h */
5204 		has_11h = 0;
5205 		ret = mmc_read_disc_structure(d, 0, 0, 0xff, 4, &reply,
5206 							 &reply_len, 0);
5207 		if (ret > 0) {
5208 			for (i = 0; i < reply_len; i += 4) {
5209 				if (reply[i] == 0x11 && (reply[i + 1] & 64))
5210 					has_11h = 1;
5211 			}
5212 		}
5213 		if (reply != NULL)
5214 			free(reply);
5215 		reply = NULL;
5216 		ret = mmc_read_disc_structure(d, 0, 0, 0x11, 29, &reply,
5217 							 &reply_len, 0);
5218 		if (ret <= 0) {
5219 			/* Hope for format 00h */
5220 			has_11h = 0;
5221 		} else {
5222 			/* Dig out manufacturer, media type and revision */
5223 			ret = mmc_set_product_id(reply, 19, 27, 28,
5224 				product_id, media_code1, media_code2,
5225 				flag & 1);
5226 			if (ret <= 0)
5227 				goto ex;
5228 		}
5229         } else if (prf == 0x41 || prf == 0x43 || prf == 0x40 || prf == 0x42) {
5230 								/* BD */
5231 		media_type = 1;
5232 		ret = mmc_read_disc_structure(d, 1, 0, 0x00, 112, &reply,
5233 							 &reply_len, 0);
5234 		if (ret <= 0)
5235 			goto ex;
5236 		if (reply[0] != 'D' || reply[1] != 'I') {
5237 			ret = 0;
5238 			goto ex;
5239 		}
5240 		/* Dig out manufacturer, media type and revision */
5241 		ret = mmc_set_product_id(reply, 100, 106, 111,
5242 			 	product_id, media_code1, media_code2,
5243 				2 | (flag & 1));
5244 		if (ret <= 0)
5245 			goto ex;
5246 
5247 	} else {
5248 
5249 		/* Source of DVD-RAM manufacturer and media id not found yet */
5250 		ret = 0;
5251 		goto ex;
5252 	}
5253 
5254 	if (reply != NULL)
5255 		free(reply);
5256 	reply = NULL;
5257 	ret = mmc_read_disc_structure(d, media_type, 0, 0x00, 1,
5258 							&reply, &reply_len, 0);
5259 	if (ret <= 0)
5260 		goto ex;
5261 	bt = (reply[0] >> 4) & 0xf;
5262 	*book_type = calloc(80 + strlen(books[bt]), 1);
5263 	if (*book_type == NULL) {
5264 		ret = -1;
5265 		goto ex;
5266 	}
5267 	sprintf(*book_type, "%2.2Xh, %s book [revision %d]",
5268 		bt, books[bt], reply[0] & 0xf);
5269 
5270 	if (has_11h == 0 && *product_id == NULL && reply_len > 28) {
5271 		/* DVD+ with no format 11h */
5272 		/* Get manufacturer and media type from bytes 19 and 27 */
5273 		ret = mmc_set_product_id(reply, 19, 27, 28, product_id,
5274 						media_code1, media_code2,
5275 						flag & 1);
5276 		if (*product_id == NULL) {
5277 			ret = 0;
5278 			goto ex;
5279 		}
5280 	}
5281 
5282 	ret = 1;
5283 ex:;
5284 	if (reply != NULL)
5285 		free(reply);
5286 	if (ret <= 0) {
5287 		if (*product_id != NULL)
5288 			free(*product_id);
5289 		if (*media_code1 != NULL)
5290 			free(*media_code1);
5291 		if (*media_code2 != NULL)
5292 			free(*media_code2);
5293 		if (*book_type != NULL)
5294 			free(*book_type);
5295 		*product_id = *media_code1 = *media_code2 = *book_type = NULL;
5296 	}
5297 	return ret;
5298 }
5299 
5300 
5301 /* ts B00924
5302    MMC-5, 6.23.3.3.4 Format Code 0Ah: Spare Area Information
5303 */
5304 int mmc_get_bd_spare_info(struct burn_drive *d,
5305 				int *alloc_blocks, int *free_blocks, int flag)
5306 {
5307 	int ret, reply_len, prf;
5308 	char *reply = NULL;
5309 
5310 	prf = d->current_profile;
5311 	if (!(prf == 0x41 || prf == 0x43 || prf == 0x42))
5312 		return 0; /* Not a BD loaded */
5313 
5314 	ret = mmc_read_disc_structure(d, 1, 0, 0x0a, 12, &reply,
5315 							 &reply_len, 0);
5316 	if (ret <= 0)
5317 		goto ex;
5318 	*alloc_blocks = mmc_four_char_to_int((unsigned char *) reply + 8);
5319 	*free_blocks = mmc_four_char_to_int((unsigned char *) reply + 4);
5320 	ret = 1;
5321 ex:;
5322 	if (reply != NULL)
5323 		free(reply);
5324 	return ret;
5325 }
5326 
5327 
5328 /* ts B10801
5329    MMC-5, 6.23.3.2.1 Format Code 00h: Physical Format Information
5330           6.23.3.2.16 Format Code 10h: Format Information of
5331                                        Control Data Zone in the Lead-in
5332    disk_category
5333 */
5334 int mmc_get_phys_format_info(struct burn_drive *d, int *disk_category,
5335 			char **book_name, int *part_version, int *num_layers,
5336 			int *num_blocks, int flag)
5337 {
5338 	int ret, reply_len, prf;
5339 	char *reply = NULL;
5340 	static char book_names[][16] = {
5341 		"DVD-ROM", "DVD-RAM", "DVD-R", "DVD-RW",
5342 		"HD DVD-ROM", "HD DVD-RAM", "HD DVD-R", "unknown",
5343 		"unknown", "DVD+RW", "DVD+R", "unknown", "unknown",
5344 		"unknown", "DVD+RW DL", "DVD+R DL", "unknown"
5345 	};
5346 
5347 	prf = d->current_profile;
5348 	if (!(prf == 0x11 || prf == 0x13 || prf == 0x14 || prf == 0x15 ||
5349 	      prf == 0x51))
5350 		return 0; /* Not a [HD] DVD-R[W] loaded */
5351 	ret = mmc_read_disc_structure(d, 0, 0, 0x10, 12, &reply,
5352 							 &reply_len, 0);
5353 	if (ret <= 0)
5354 		goto ex;
5355 	if(reply_len < 12) {
5356 		libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
5357 			LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
5358 			"READ DISC STRUCTURE format 10h: Less than 12 bytes",
5359 			0, 0);
5360 		{ret = 0; goto ex;}
5361 	}
5362 	*disk_category = (reply[0] >> 4) & 0xf;
5363 	*book_name = book_names[*disk_category];
5364 	*part_version = reply[0] & 0xf;
5365 	*num_layers = ((reply[2] >> 5) & 0x3) + 1;
5366 	*num_blocks = ((reply[9] << 16) | (reply[10] << 8) | reply[11]) -
5367 	              ((reply[5] << 16) | (reply[6] << 8) | reply[7]) + 1;
5368 	ret = 1;
5369 ex:;
5370 	if (reply != NULL)
5371 		free(reply);
5372 	return ret;
5373 }
5374 
5375 
5376 /* ts A61021 : the mmc specific part of sg.c:enumerate_common()
5377 */
5378 int mmc_setup_drive(struct burn_drive *d)
5379 {
5380 	d->read_atip = mmc_read_atip;
5381 	d->read_toc = mmc_read_toc;
5382 	d->write = mmc_write;
5383 	d->erase = mmc_erase;
5384 	d->read_cd = mmc_read_cd;
5385 	d->perform_opc = mmc_perform_opc;
5386 	d->set_speed = mmc_set_speed;
5387 	d->send_cue_sheet = mmc_send_cue_sheet;
5388 	d->reserve_track = mmc_reserve_track;
5389 	d->sync_cache = mmc_sync_cache;
5390 	d->get_nwa = mmc_get_nwa;
5391 	d->read_multi_session_c1 = mmc_read_multi_session_c1;
5392 	d->close_disc = mmc_close_disc;
5393 	d->close_session = mmc_close_session;
5394 	d->close_track_session = mmc_close;
5395 	d->read_buffer_capacity = mmc_read_buffer_capacity;
5396 	d->format_unit = mmc_format_unit;
5397 	d->read_format_capacities = mmc_read_format_capacities;
5398 	d->read_10 = mmc_read_10;
5399 
5400 
5401 	/* ts A70302 */
5402 	d->phys_if_std = -1;
5403 	d->phys_if_name[0] = 0;
5404 
5405 	/* ts A61020 */
5406 	d->start_lba = -2000000000;
5407 	d->end_lba = -2000000000;
5408 
5409 	d->do_simulate= 0;
5410 
5411 	/* ts A61201 - A90815*/
5412 	d->erasable = 0;
5413 	d->current_profile = -1;
5414 	d->current_profile_text[0] = 0;
5415 	d->current_is_cd_profile = 0;
5416 	d->current_is_supported_profile = 0;
5417 	d->current_is_guessed_profile = 0;
5418 	memset(d->all_profiles, 0, 256);
5419 	d->num_profiles = 0;
5420 	d->current_has_feat21h = 0;
5421 	d->current_feat21h_link_size = -1;
5422 	d->current_feat23h_byte4 = 0;
5423 	d->current_feat23h_byte8 = 0;
5424 	d->current_feat2fh_byte4 = -1;
5425 	d->next_track_damaged = 0;
5426 	d->needs_close_session = 0;
5427 	d->needs_sync_cache = 0;
5428 	d->bg_format_status = -1;
5429 	d->num_opc_tables = -1;
5430 	d->last_lead_in = -2000000000;
5431 	d->last_lead_out = -2000000000;
5432 	d->disc_type = 0xff;
5433 	d->disc_id = 0;
5434 	memset(d->disc_bar_code, 0, 9);
5435 	d->disc_app_code = 0;
5436 	d->disc_info_valid = 0;
5437 	d->num_format_descr = 0;
5438 	d->complete_sessions = 0;
5439 
5440 #ifdef Libburn_disc_with_incomplete_sessioN
5441 	d->incomplete_sessions = 0;
5442 #endif
5443 
5444 	d->state_of_last_session = -1;
5445 	d->last_track_no = 1;
5446 	d->media_capacity_remaining = 0;
5447 	d->media_lba_limit = 0;
5448 	d->media_read_capacity = 0x7fffffff;
5449 	d->mr_capacity_trusted = 0;
5450 	d->pessimistic_buffer_free = 0;
5451 	d->pbf_altered = 0;
5452 	d->wait_for_buffer_free = Libburn_wait_for_buffer_freE;
5453 	d->nominal_write_speed = 0;
5454 	d->pessimistic_writes = 0;
5455 	d->waited_writes = 0;
5456 	d->waited_tries = 0;
5457 	d->waited_usec = 0;
5458 	d->wfb_min_usec = Libburn_wait_for_buffer_min_useC;
5459 	d->wfb_max_usec = Libburn_wait_for_buffer_max_useC;
5460 	d->wfb_timeout_sec = Libburn_wait_for_buffer_tio_seC;
5461 	d->wfb_min_percent = Libburn_wait_for_buffer_min_perC;
5462 	d->wfb_max_percent = Libburn_wait_for_buffer_max_perC;
5463 	d->sent_default_page_05 = 0;
5464 
5465 	return 1;
5466 }
5467 
5468 
5469 /* @param flag bit0= really add to text, else only count
5470 */
5471 static void burn__add_to_text(char *text, int *text_len, char *to_add,
5472 			      int flag)
5473 {
5474 	(*text_len) += strlen(to_add);
5475 	if (flag & 1)
5476 		strcat(text, to_add);
5477 }
5478 
5479 /* @param flag bit0= really add to text, else only count
5480 */
5481 static void burn__add_hex_to_text(char *text, int *text_len,
5482 				  unsigned char *to_add, int add_length,
5483 				  int flag)
5484 {
5485 	int i, l;
5486 
5487 	(*text_len) += 3 * add_length;
5488 	if (!(flag & 1))
5489 		return;
5490 	l = strlen(text);
5491 	for (i = 0; i < add_length; i++)
5492 		sprintf(text + l + 3 * i, " %2.2x", to_add[i]);
5493 }
5494 
5495 int burn_make_feature_text(struct burn_drive *d, unsigned int feature_code,
5496 			   unsigned char flags,
5497 			   unsigned char additional_length,
5498 			   unsigned char *feature_data,
5499 			   char **text, int flag)
5500 {
5501 	char *feature_name, addon[320], *cpt;
5502 	int text_len, ret, i, pass;
5503 	unsigned int phys_is, lmt, num;
5504 
5505 	static unsigned short feature_codes[] = {
5506 		0x00, 0x01, 0x02, 0x03,
5507 		0x04, 0x10, 0x1d, 0x1e,
5508 		0x1f, 0x20, 0x21, 0x22,
5509 		0x23, 0x24, 0x25, 0x26,
5510 		0x27, 0x28, 0x29, 0x2a,
5511 		0x2b, 0x2c, 0x2d, 0x2e,
5512 		0x2f, 0x33, 0x37, 0x38,
5513 		0x3a, 0x3b, 0x40, 0x41,
5514 		0x42, 0x50, 0x51, 0x80,
5515 		0x100, 0x101, 0x102, 0x104,
5516 		0x105, 0x106, 0x107, 0x108,
5517 		0x109, 0x10a, 0x10b, 0x10c,
5518 		0x10d, 0x110,
5519 		0xffff
5520 	};
5521 	static char feature_names[][40] = {
5522 		"Profile List", "Core", "Morphing", "Removable Medium",
5523 		"Write Protect", "Random Readable", "Multi-Read", "CD Read",
5524 		"DVD Read", "Random Writable",
5525 			"Incremental Streaming Writable", "Sector Erasable",
5526 		"Formattable", "Hardware Defect Management", "Write Once",
5527 			"Restricted Overwrite",
5528 		"CD-RW CAV Write", "MRW", "Enhanced Defect Reporting",
5529 			"DVD+RW",
5530 		"DVD+R", "Rigid Restricted Overwrite", "CD Track at Once",
5531 			"CD Mastering",
5532 		"DVD-R/-RW Write", "Layer Jump Recording",
5533 			"CD-RW Media Write Support", "BD-R POW",
5534 		"DVD+RW Dual Layer", "DVD+R Dual Layer", "BD Read Feature",
5535 			"BD Write Feature",
5536 		"TSR", "HD DVD Read", "HD DVD Write", "Hybrid Disc",
5537 		"Power Management", "SMART", "Embedded Changer",
5538 			"Microcode Upgrade",
5539 		"Timeout", "DVD-CSS", "Real Time Streaming",
5540 			"Drive Serial Number",
5541 		"Media Serial Number", "DCBs", "DVD CPRM",
5542 			"Firmware Information",
5543 		"AACS", "VCPS",
5544 		""
5545 	};
5546 	static unsigned short legacy_codes[] = {
5547 		0x30, 0x31, 0x32, 0x103, 0xffff
5548 	};
5549 	static unsigned int phys_is_codes[] = {
5550 		0x00, 0x01, 0x02, 0x03,
5551 		0x04, 0x05, 0x06, 0x07,
5552 		0x08, 0xffff,
5553 		0xffffffff
5554 	};
5555 	static char phys_is_names[][40] = {
5556 		"Unspecified", "SCSI_Family", "ATAPI", "IEEE_1394-1995",
5557 		"IEEE_1394A", "Fibre_Channel", "IEEE_1394B", "Serial_ATAPI",
5558 		"USB", "Vendor_Unique",
5559 		""
5560 	};
5561 	static char load_mech_names[8][40] = {
5562 		"Caddy/Slot", "Tray", "Pop-up", "(Reserved)",
5563 		"Embedded_changer_individually", "Embedded_changer_magazine",
5564 			"(Reserved)",  "(Reserved)"
5565 	};
5566 
5567 	feature_name = "(Reserved)";
5568 	for (i = 0; feature_codes[i] != 0xffff; i++) {
5569 		if (feature_codes[i] == feature_code) {
5570 			feature_name = feature_names[i];
5571 	break;
5572 		}
5573 	}
5574 	if (feature_codes[i] == 0xffff) {
5575 		for (i = 0; legacy_codes[i] != 0xffff; i++) {
5576 			if (legacy_codes[i] == feature_code) {
5577 				feature_name = "(Legacy)";
5578 		break;
5579 			}
5580 		}
5581 	}
5582 	if (feature_code >= 0xff00 && feature_code <= 0xffff)
5583 		feature_name = "(Vendor Specific)";
5584 
5585 	*text = NULL;
5586 	for (pass = 0; pass < 2; pass++) {
5587 		if (pass == 1) {
5588 			BURN_ALLOC_MEM(*text, char, text_len + 1);
5589 		}
5590 		text_len = 0;
5591 
5592 		sprintf(addon, "%4.4x %c : ", feature_code,
5593 					      (flags & 1) ? '+' : '-');
5594 		burn__add_to_text(*text, &text_len, addon, pass);
5595 
5596 		burn__add_to_text(*text, &text_len, feature_name, pass);
5597 
5598 		/* Version, Persistent, Current */
5599 		sprintf(addon, " : %1.1x,%c :",
5600 			(flags >> 2) & 15, (flags & 2) ? 'P' : 'N');
5601 		burn__add_to_text(*text, &text_len, addon, pass);
5602 
5603 		burn__add_hex_to_text(*text, &text_len,
5604 				feature_data, (int) additional_length, pass);
5605 		burn__add_to_text(*text, &text_len, " :", pass);
5606 
5607 		if (feature_code == 0x01 && additional_length >= 4) {
5608 			/* Core : Physical Interface Standard , INQ2, DBE */
5609 			phys_is = mmc_four_char_to_int(feature_data);
5610 			cpt = "(Not_Recognizable)";
5611 			for (i = 0; phys_is_codes[i] != 0xffffffff; i++) {
5612 				if (phys_is_codes[i] == phys_is) {
5613 					cpt = phys_is_names[i];
5614 			break;
5615 				}
5616 
5617 			}
5618 			num = 0;
5619 			if (additional_length >= 9)
5620 				num = feature_data[8];
5621 			sprintf(addon,
5622 				" PhysInterface=%x/%s , INQ2=%d , DBE=%d",
5623 				phys_is, cpt, (num >> 1) & 1, num & 1);
5624 			burn__add_to_text(*text, &text_len, addon, pass);
5625 
5626 		} else if (feature_code == 0x03 && additional_length >= 1) {
5627 			/* Removable Medium : Lock, Pvnt Jmpr, Eject,
5628 						Loading mechanism Type
5629 			*/
5630 			num = feature_data[0];
5631 			lmt = (num >> 5) & 7;
5632 			sprintf(addon,
5633 		      " LoadMechType=%x/%s , Eject=%d , PvntJmpr=%d , Lock=%d",
5634 				lmt, load_mech_names[lmt], (num >> 3) & 1,
5635 				(num >> 2) & 1, num & 1);
5636 			burn__add_to_text(*text, &text_len, addon, pass);
5637 
5638 		} else if (feature_code == 0x10 && additional_length >= 4) {
5639 			/* Random Readable: Logical Block Size, Blocking */
5640 			num = 0;
5641 			if (additional_length >= 6)
5642 				num = (feature_data[4] << 8) | feature_data[5];
5643 			sprintf(addon, " BlockSize=%d , Blocking=%u",
5644 				mmc_four_char_to_int(feature_data), num);
5645 			num = 0;
5646 			if (additional_length >= 7)
5647 				num = feature_data[6];
5648 			sprintf(addon + strlen(addon), " , PP=%d", num & 1);
5649 			burn__add_to_text(*text, &text_len, addon, pass);
5650 
5651 		} else if (feature_code == 0x1e && additional_length >= 1) {
5652 			/* CD Read: DAP, C2 Flags, CD-Text */
5653 			sprintf(addon, " DAP=%d , C2Flags=%d , CDText=%d",
5654 				(feature_data[0] >> 7) & 1,
5655 				(feature_data[0] >> 1) & 1,
5656 				feature_data[0] & 1);
5657 			burn__add_to_text(*text, &text_len, addon, pass);
5658 
5659 		} else if (feature_code == 0x1f && additional_length >= 1) {
5660 			/* DVD Read: MULTI110, Dual-R */
5661 			num = 0;
5662 			if (additional_length >= 3)
5663 				num = feature_data[2];
5664 			sprintf(addon, " MULTI10=%d , DualR=%d",
5665 				feature_data[0] & 1, num & 1);
5666 			burn__add_to_text(*text, &text_len, addon, pass);
5667 
5668 		} else if (feature_code == 0x20 && additional_length >= 4) {
5669 			/* Random Writable: Last LBA, Logical Block Size,
5670 						Blocking, PP */
5671 			num = 0;
5672 			if (additional_length >= 8)
5673 				num = mmc_four_char_to_int(feature_data + 4);
5674 			sprintf(addon, " LastLBA=%d , BlockSize=%u",
5675 				 mmc_four_char_to_int(feature_data), num);
5676 			num = 0;
5677 			if (additional_length >= 10)
5678 				num = (feature_data[8] << 8) | feature_data[9];
5679 			sprintf(addon + strlen(addon), " , Blocking=%u", num);
5680 			num = 0;
5681 			if (additional_length >= 11)
5682 				num = feature_data[10];
5683 			sprintf(addon + strlen(addon), " , PP=%u", num);
5684 			burn__add_to_text(*text, &text_len, addon, pass);
5685 
5686 		} else if (feature_code == 0x21 && additional_length >= 2) {
5687 			/* Incremental Streaming Writable :
5688 			   Data Block Types , TRIO , ARSV , BUF
5689 			   Number of Link Sizes
5690 			*/
5691 			num = 0;
5692 			if (additional_length >= 3)
5693 				num = feature_data[2];
5694 			sprintf(addon,
5695 		     " DataBlockTypes=%2.2x%2.2x , TRIO=%d , ARSV=%d , BUF=%d",
5696 				feature_data[0], feature_data[1],
5697 				(num >> 2) & 1, (num >> 1) & 1, num & 1);
5698 			num = 0;
5699 			if (additional_length >= 4)
5700 				num = feature_data[3];
5701 			sprintf(addon + strlen(addon), " , NumLinkSizes=%d",
5702 				num);
5703 			burn__add_to_text(*text, &text_len, addon, pass);
5704 
5705 		} else if (feature_code == 0x23 && additional_length >= 1) {
5706 			/* Formattable: RENoSA, Expand, QCert, Cert, RRM */
5707 			num = feature_data[0];
5708 			sprintf(addon,
5709 				" RENoSA=%d , Expand=%d , QCert=%d , Cert=%d",
5710 				(num >> 3) & 1, (num >> 2) & 1,
5711 				(num >> 1) & 1, num & 1);
5712 			num = 0;
5713 			if (additional_length >= 5)
5714 				num = feature_data[4];
5715 			sprintf(addon + strlen(addon), " , RRM=%d", num & 1);
5716 			burn__add_to_text(*text, &text_len, addon, pass);
5717 
5718 		} else if (feature_code == 0x24 && additional_length >= 1) {
5719 			/* Defect Management : SSA */
5720 			sprintf(addon, " SSA=%d", (feature_data[0] >> 7) & 1);
5721 			burn__add_to_text(*text, &text_len, addon, pass);
5722 
5723 		} else if (feature_code == 0x28 && additional_length >= 1) {
5724 			/* MRW */
5725 			num = feature_data[0];
5726 			sprintf(addon,
5727 				" DVDPWrite=%d , DVDPRead=%d , CDWrite=%d",
5728 				(num >> 2) & 1, (num >> 1) & 1, num & 1);
5729 			burn__add_to_text(*text, &text_len, addon, pass);
5730 
5731 		} else if (feature_code == 0x2a && additional_length >= 1) {
5732 			/* DVD+RW */
5733 			num = 0;
5734 			if (additional_length >= 2)
5735 				num = feature_data[1];
5736 			sprintf(addon,
5737 				" Write=%d , QuickStart=%d , CloseOnly=%d",
5738 				feature_data[0] & 1, (num >> 1) & 1, num & 1);
5739 			burn__add_to_text(*text, &text_len, addon, pass);
5740 
5741 		} else if (feature_code == 0x2b && additional_length >= 1) {
5742 			/* DVD+R */
5743 			sprintf(addon, " Write=%d", feature_data[0] & 1);
5744 			burn__add_to_text(*text, &text_len, addon, pass);
5745 
5746 		} else if (feature_code == 0x2c && additional_length >= 1) {
5747 			/* Rigid Restricted Overwrite */
5748 			num = feature_data[0];
5749 			sprintf(addon,
5750 			     " DSDG=%d , DSDR=%d , Intermediate=%d , Blank=%d",
5751 				(num >> 3) & 1, (num >> 2) & 1,
5752 				(num >> 1) & 1, num & 1);
5753 			burn__add_to_text(*text, &text_len, addon, pass);
5754 
5755 		} else if (feature_code == 0x2d && additional_length >= 1) {
5756 			/* CD Track at Once */
5757 			num= feature_data[0];
5758 			sprintf(addon,
5759      " BUF=%d , RWRaw=%d , RWPack=%d , TestWrite=%d , CD-RW=%d , RWSubcode=%d",
5760 				(num >> 6) & 1, (num >> 4) & 1,
5761 				(num >> 3) & 1, (num >> 2) & 1,
5762 				(num >> 1) & 1, num & 1);
5763 			num = 0;
5764 			if (additional_length >= 4)
5765 				num = (feature_data[2] << 8) | feature_data[3];
5766 			sprintf(addon + strlen(addon), " , DataTypeSupp=%4.4x",
5767 				num);
5768 			burn__add_to_text(*text, &text_len, addon, pass);
5769 
5770 		} else if (feature_code == 0x2e && additional_length >= 1) {
5771 			/* CD Mastering (SAO) */
5772 			num = feature_data[0];
5773 			sprintf(addon,
5774       " BUF=%d , SAO=%d , RawMS=%d , Raw=%d , TestWrite=%d , CD-RW=%d , RW=%d",
5775 				(num >> 6) & 1, (num >> 5) & 1, (num >> 4) & 1,
5776 				(num >> 3) & 1, (num >> 2) & 1,
5777 				(num >> 1) & 1, num & 1);
5778 			num = 0;
5779 			if (additional_length >= 4)
5780 				num = (feature_data[1] << 16) |
5781 				      (feature_data[2] << 8) | feature_data[3];
5782 			sprintf(addon + strlen(addon),
5783 				" , MaxCueSheetLen=%u", num);
5784 			burn__add_to_text(*text, &text_len, addon, pass);
5785 
5786 		} else if (feature_code == 0x2f && additional_length >= 1) {
5787 			/* DVD-R/RW Write */
5788 			num = feature_data[0];
5789 			sprintf(addon,
5790 				" BUF=%d , RDL=%d , TestWrite=%d , DVDRW=%d",
5791 				(num >> 6) & 1,  (num >> 3) & 1,
5792 				(num >> 2) & 1, (num >> 1) & 1);
5793 			burn__add_to_text(*text, &text_len, addon, pass);
5794 
5795 		} else if (feature_code == 0x33 && additional_length >= 4) {
5796 			/* Layer Jump Recording */
5797 			sprintf(addon, " NumLinkSizes=%d", feature_data[3]);
5798 			burn__add_to_text(*text, &text_len, addon, pass);
5799 
5800 		} else if (feature_code == 0x37 && additional_length >= 2) {
5801 			/* CD-RW Media Write Support */
5802 			addon[0]= 0;
5803 			for (i = 7; i >= 0; i--) {
5804 				sprintf(addon + strlen(addon),
5805 					" Subtype%d=%d%s",
5806 					i, (feature_data[1] >> i) & 1,
5807 					i > 0 ? " ," : "");
5808 			}
5809 			burn__add_to_text(*text, &text_len, addon, pass);
5810 
5811 		} else if (feature_code == 0x3a && additional_length >= 2) {
5812 			/* DVD+RW Dual Layer */
5813 			sprintf(addon,
5814 				" Write=%d , QuickStart=%d , CloseOnly=%d",
5815 				feature_data[0] & 1,
5816 				(feature_data[1] >> 1) & 1,
5817 				feature_data[1] & 1);
5818 			burn__add_to_text(*text, &text_len, addon, pass);
5819 
5820 		} else if (feature_code == 0x3b && additional_length >= 1) {
5821 			/* DVD+R Dual Layer */
5822 			sprintf(addon, " Write=%d", feature_data[0] & 1);
5823 			burn__add_to_text(*text, &text_len, addon, pass);
5824 
5825 		} else if (feature_code == 0x50 && additional_length >= 1) {
5826 			/* HD DVD Read */
5827 			num = 0;
5828 			if (additional_length >= 3)
5829 				num = feature_data[2];
5830 			sprintf(addon, " HDDVDR=%d , HDDVDRAM=%d",
5831 				feature_data[0] & 1, num & 1);
5832 			burn__add_to_text(*text, &text_len, addon, pass);
5833 
5834 		} else if (feature_code == 0x51 && additional_length >= 1) {
5835 			/* HD DVD Write */
5836 			num = 0;
5837 			if (additional_length >= 3)
5838 				num = feature_data[2];
5839 			sprintf(addon, " HDDVDR=%d , HDDVDRAM=%d",
5840 				feature_data[0] & 1, num & 1);
5841 			burn__add_to_text(*text, &text_len, addon, pass);
5842 
5843 		} else if (feature_code == 0x101 && additional_length >= 1) {
5844 			/* SMART */
5845 			sprintf(addon, " PP=%d", feature_data[0] & 1);
5846 			burn__add_to_text(*text, &text_len, addon, pass);
5847 
5848 		} else if (feature_code == 0x102 && additional_length >= 1) {
5849 			/* Embedded Changer */
5850 			num = 0;
5851 			if (additional_length >= 4)
5852 				num = feature_data[3];
5853 			sprintf(addon, " SCC=%d , SDP=%d , HighestSlotNo=%u",
5854 				(feature_data[0] >> 4) & 1,
5855 				(feature_data[0] >> 2) & 1, num & 31);
5856 			burn__add_to_text(*text, &text_len, addon, pass);
5857 
5858 		} else if (feature_code == 0x105 && additional_length >= 1) {
5859 			/* Timeout */
5860 			num = 0;
5861 			if (additional_length >= 4)
5862 				num = (feature_data[2] << 8) | feature_data[3];
5863 			sprintf(addon, " Group3=%d , UnitLength=%u",
5864 				feature_data[0] & 1, num);
5865 			burn__add_to_text(*text, &text_len, addon, pass);
5866 
5867 		} else if (feature_code == 0x106 && additional_length >= 4) {
5868 			/* DVD CSS */
5869 			sprintf(addon, " CSSVersion=%d",
5870 				(int) feature_data[3]);
5871 			burn__add_to_text(*text, &text_len, addon, pass);
5872 
5873 		} else if (feature_code == 0x107 && additional_length >= 1) {
5874 			/* Real Time Streaming */
5875 			num = feature_data[0];
5876 			sprintf(addon,
5877 			       " RBCB=%d , SCS=%d , MP2A=%d , WSPD=%d , SW=%d",
5878 				(num >> 4) & 1, (num >> 3) & 1, (num >> 2) & 1,
5879 				(num >> 1) & 1, num & 1);
5880 			burn__add_to_text(*text, &text_len, addon, pass);
5881 
5882 		} else if (feature_code == 0x108 && additional_length >= 1) {
5883 			/* Drive Serial Number */
5884 			strcpy(addon, " SerialNumber=");
5885 			for (i = 0; i < additional_length; i++) {
5886 				num = feature_data[i];
5887 				if (num >= ' ' && num < 127)
5888 					addon[14 + i] = feature_data[i];
5889 				else
5890 					addon[14 + i] = '?';
5891 			}
5892 			addon[14 + i] = 0;
5893 			burn__add_to_text(*text, &text_len, addon, pass);
5894 
5895 		} else if (feature_code == 0x10a && additional_length >= 4) {
5896 			/* DCBs */
5897 			addon[0] = 0;
5898 			for (i = 0; i < additional_length / 4; i++)
5899 				sprintf(addon + strlen(addon),
5900 					" SuppEntry%d=%2.2x%2.2x%2.2x%2.2x%s",
5901 					i, feature_data[i * 4 + 0],
5902 					feature_data[i * 4 + 1],
5903 					feature_data[i * 4 + 2],
5904 					feature_data[i * 4 + 3],
5905 					i < additional_length / 4 - 1 ?
5906 								" ," : "");
5907 			burn__add_to_text(*text, &text_len, addon, pass);
5908 
5909 		} else if (feature_code == 0x10b && additional_length >= 4) {
5910 			/* DVD CPRM */
5911 			sprintf(addon, " CPRMVersion=%d", feature_data[3]);
5912 			burn__add_to_text(*text, &text_len, addon, pass);
5913 
5914 		} else if (feature_code == 0x10c && additional_length >= 14) {
5915 			/* Firmware Information */
5916 			strcpy(addon, " Date=");
5917 			for (i = 0; i < 14; i += 2)
5918 				sprintf(addon + 6 + i, "%2.2d",
5919 					((feature_data[i] & 0xf) % 10) * 10 +
5920 					((feature_data[i + 1] & 0xf) % 10));
5921 			burn__add_to_text(*text, &text_len, addon, pass);
5922 
5923 		} else if (feature_code == 0x10d && additional_length >= 4) {
5924 			/* AACS */
5925 			sprintf(addon,
5926        " BNG=%d , BlockCountBindingNonce=%d , NumberAGIDs=%d , AACSVersion=%d",
5927 				feature_data[0] & 1, feature_data[1],
5928 				feature_data[2] & 0xf, feature_data[3]);
5929 			burn__add_to_text(*text, &text_len, addon, pass);
5930 
5931 		}
5932 	}
5933 	ret = 1;
5934 ex:;
5935 	return ret;
5936 }
5937