"Fossies" - the Fresh Open Source Software Archive

Member "xorriso-1.5.4/libburn/mmc.c" (30 Jan 2021, 171464 Bytes) of package /linux/misc/xorriso-1.5.4.pl02.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "mmc.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.5.2_vs_1.5.4.

    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 
  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 
  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 */
  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 */
  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 */
  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 
  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 */
  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 */
  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 */
  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) */
  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) */
  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 */
  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 
  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 */
  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 
  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 
  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 
  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() */
 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 */
 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 */
 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 */
 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;