Imported Upstream version 1.1.11
[platform/upstream/cdrkit.git] / wodim / drv_mmc.c
1 /*
2  * This file has been modified for the cdrkit suite.
3  *
4  * The behaviour and appearence of the program code below can differ to a major
5  * extent from the version distributed by the original author(s).
6  *
7  * For details, see Changelog file distributed with the cdrkit package. If you
8  * received this file from another source then ask the distributing person for
9  * a log of modifications.
10  *
11  */
12
13 /* @(#)drv_mmc.c        1.163 06/01/12 Copyright 1997-2006 J. Schilling */
14 /*
15  *      CDR device implementation for
16  *      SCSI-3/mmc conforming drives
17  *      e.g. Yamaha CDR-400, Ricoh MP6200
18  *
19  *      Copyright (c) 1997-2006 J. Schilling
20  */
21 /*
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License version 2
24  * as published by the Free Software Foundation.
25  *
26  * This program is distributed in the hope that it will be useful,
27  * but WITHOUT ANY WARRANTY; without even the implied warranty of
28  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
29  * GNU General Public License for more details.
30  *
31  * You should have received a copy of the GNU General Public License along with
32  * this program; see the file COPYING.  If not, write to the Free Software
33  * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34  */
35
36 /*#define       DEBUG*/
37 #define PRINT_ATIP
38 #include <mconfig.h>
39
40 #include <stdio.h>
41 #include <standard.h>
42 #include <fctldefs.h>
43 #include <errno.h>
44 #include <strdefs.h>
45 #include <stdxlib.h>
46 #include <unixstd.h>
47 #include <timedefs.h>
48
49 #include <utypes.h>
50 #include <btorder.h>
51 #include <intcvt.h>
52 #include <schily.h>
53
54 #include <usal/usalcmd.h>
55 #include <usal/scsidefs.h>
56 #include <usal/scsireg.h>
57 #include <usal/scsitransp.h>
58
59 #include "scsimmc.h"
60 #include "mmcvendor.h"
61 #include "wodim.h"
62 #include "scsi_scan.h"
63
64 extern  char    *driveropts;
65
66 extern  int     debug;
67 extern  int     lverbose;
68 extern  int     xdebug;
69
70 static  int     curspeed = 1;
71
72 static  char    clv_to_speed[16] = {
73 /*              0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 */
74                 0, 2, 4, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
75 };
76
77 static  char    hs_clv_to_speed[16] = {
78 /*              0  1  2  3  4  5  6  7   8  9 10 11 12 13 14 15 */
79                 0, 2, 4, 6, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
80 };
81
82 static  char    us_clv_to_speed[16] = {
83 /*              0  1  2  3  4  5   6  7  8   9   10  11 12 13 14 15 */
84                 0, 2, 4, 8, 0, 0, 16, 0, 24, 32, 40, 48, 0, 0, 0, 0
85 };
86
87 #ifdef  __needed__
88 static  int     mmc_load(SCSI *usalp, cdr_t *dp);
89 static  int     mmc_unload(SCSI *usalp, cdr_t *dp);
90 #endif
91 void                            mmc_opthelp(cdr_t *dp, int excode);
92 char                            *hasdrvopt(char *optstr, char *optname);
93 static  cdr_t   *identify_mmc(SCSI *usalp, cdr_t *, struct scsi_inquiry *);
94 static  int     attach_mmc(SCSI *usalp, cdr_t *);
95 static   int   attach_mdvd(SCSI *usalp, cdr_t *);
96 int                             check_writemodes_mmc(SCSI *usalp, cdr_t *dp);
97 int                             check_writemodes_mdvd(SCSI *usalp, cdr_t *dp);
98 static  int     deflt_writemodes_mmc(SCSI *usalp, BOOL reset_dummy);
99 static   int   deflt_writemodes_mdvd(SCSI *usalp, BOOL reset_dummy);
100 static  int     get_diskinfo(SCSI *usalp, struct disk_info *dip);
101 static  void    di_to_dstat(struct disk_info *dip, dstat_t *dsp);
102 static  int     get_atip(SCSI *usalp, struct atipinfo *atp);
103 #ifdef  PRINT_ATIP
104 static  int     get_pma(SCSI *usalp);
105 #endif
106 static  int     init_mmc(SCSI *usalp, cdr_t *dp);
107 static  int     getdisktype_mmc(SCSI *usalp, cdr_t *dp);
108 static  int   getdisktype_mdvd(SCSI *usalp, cdr_t *dp);
109 static  int     speed_select_mmc(SCSI *usalp, cdr_t *dp, int *speedp);
110 static  int   speed_select_mdvd(SCSI *usalp, cdr_t *dp, int *speedp);
111 static  int     mmc_set_speed(SCSI *usalp, int readspeed, int writespeed, 
112                                                                           int rotctl);
113 static  int     next_wr_addr_mmc(SCSI *usalp, track_t *trackp, long *ap);
114 static  int   next_wr_addr_mdvd(SCSI *usalp, track_t *trackp, long *ap);
115 static  int     write_leadin_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
116 static  int     open_track_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
117 static  int   open_track_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp);
118 static  int     close_track_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
119 static  int   close_track_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp); 
120 static  int     open_session_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
121 static  int   open_session_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp);
122 static  int     waitfix_mmc(SCSI *usalp, int secs);
123 static  int     fixate_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
124 static  int   fixate_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp);
125 static  int     blank_mmc(SCSI *usalp, cdr_t *dp, long addr, int blanktype);
126 static  int     format_mdvd(SCSI *usalp, cdr_t *dp, int formattype);
127 static  int     send_opc_mmc(SCSI *usalp, caddr_t, int cnt, int doopc);
128 static  int     opt1_mmc(SCSI *usalp, cdr_t *dp);
129 static  int     opt1_mdvd(SCSI *usalp, cdr_t *dp);
130 static  int     opt2_mmc(SCSI *usalp, cdr_t *dp);
131 static  int     scsi_sony_write(SCSI *usalp, caddr_t bp, long sectaddr, long size, 
132                                                                                  int blocks, BOOL islast);
133 static  int     gen_cue_mmc(track_t *trackp, void *vcuep, BOOL needgap);
134 static  void    fillcue(struct mmc_cue *cp, int ca, int tno, int idx, int dataform,
135                                                          int scms, msf_t *mp);
136 static  int     send_cue_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp);
137 static  int     stats_mmc(SCSI *usalp, cdr_t *dp);
138 static  BOOL    mmc_isplextor(SCSI *usalp);
139 static  BOOL    mmc_isyamaha(SCSI *usalp);
140 static  void    do_varirec_plextor(SCSI *usalp);
141 static  int     do_gigarec_plextor(SCSI *usalp);
142 static  int     drivemode_plextor(SCSI *usalp, caddr_t bp, int cnt, int modecode, 
143                                                                                         void *modeval);
144 static  int     drivemode2_plextor(SCSI *usalp, caddr_t bp, int cnt, int modecode, 
145                                                                                          void *modeval);
146 static  int     check_varirec_plextor(SCSI *usalp);
147 static  int     check_gigarec_plextor(SCSI *usalp);
148 static  int     varirec_plextor(SCSI *usalp, BOOL on, int val);
149 static  int     gigarec_plextor(SCSI *usalp, int val);
150 static  Int32_t gigarec_mult(int code, Int32_t  val);
151 static  int     check_ss_hide_plextor(SCSI *usalp);
152 static  int     check_speed_rd_plextor(SCSI *usalp);
153 static  int     check_powerrec_plextor(SCSI *usalp);
154 static  int     ss_hide_plextor(SCSI *usalp, BOOL do_ss, BOOL do_hide);
155 static  int     speed_rd_plextor(SCSI *usalp, BOOL do_speedrd);
156 static  int     powerrec_plextor(SCSI *usalp, BOOL do_powerrec);
157 static  int     get_speeds_plextor(SCSI *usalp, int *selp, int *maxp, int *lastp);
158 static  int     bpc_plextor(SCSI *usalp, int mode, int *bpp);
159 static  int     set_audiomaster_yamaha(SCSI *usalp, cdr_t *dp, BOOL keep_mode);
160
161 struct  ricoh_mode_page_30 * get_justlink_ricoh(SCSI *usalp, Uchar *mode);
162 static  int     force_speed_yamaha(SCSI *usalp, int readspeed, int writespeed);
163 static  BOOL    get_tattoo_yamaha(SCSI *usalp, BOOL print, Int32_t *irp, 
164                                                                                 Int32_t *orp);
165 static  int     do_tattoo_yamaha(SCSI *usalp, FILE *f);
166 static  int     yamaha_write_buffer(SCSI *usalp, int mode, int bufferid, long offset,
167                                                                                   long parlen, void *buffer, long buflen);
168 static  int     dvd_dual_layer_split(SCSI *usalp, cdr_t *dp, long tsize);
169
170 extern int      reserve_track(SCSI *usalp, Ulong size); /* FIXME */
171 extern int      scsi_format(SCSI *usalp, caddr_t addr, int size, BOOL background); /* FIXME */
172
173 #ifdef  __needed__
174 static int 
175 mmc_load(SCSI *usalp, cdr_t *dp)
176 {
177         return (scsi_load_unload(usalp, 1));
178 }
179
180 static int 
181 mmc_unload(SCSI *usalp, cdr_t *dp)
182 {
183         return (scsi_load_unload(usalp, 0));
184 }
185 #endif
186
187 /*
188  * MMC CD-writer
189  */
190 cdr_t   cdr_mmc = {
191         0, 0,
192         CDR_SWABAUDIO,
193         CDR_CDRW_ALL,
194         372, 372,
195         "mmc_cdr",
196         "generic SCSI-3/mmc   CD-R/CD-RW driver",
197         0,
198         (dstat_t *)0,
199         identify_mmc,
200         attach_mmc,
201         init_mmc,
202         getdisktype_mmc,
203         scsi_load,
204         scsi_unload,
205         read_buff_cap,
206         cmd_dummy,                                      /* check_recovery */
207         (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
208         speed_select_mmc,
209         select_secsize,
210         next_wr_addr_mmc,
211         (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
212         scsi_cdr_write,
213         gen_cue_mmc,
214         send_cue_mmc,
215         write_leadin_mmc,
216         open_track_mmc,
217         close_track_mmc,
218         open_session_mmc,
219         cmd_dummy,
220         cmd_dummy,                                      /* abort        */
221         read_session_offset,
222         fixate_mmc,
223         stats_mmc,
224         blank_mmc,
225         format_dummy,
226         send_opc_mmc,
227         opt1_mmc,
228         opt2_mmc,
229 };
230
231 cdr_t   cdr_mdvd = {
232         0, 0,
233         CDR_SWABAUDIO,
234         CDR_CDRW_ALL,
235         370,370,
236         "mmc_mdvd",
237         "generic SCSI-3/mmc DVD-R(W) driver",
238         0,
239         (dstat_t *)0,
240         identify_mmc,
241         attach_mdvd,
242         init_mmc,
243         getdisktype_mdvd,
244         scsi_load,
245         scsi_unload,
246         read_buff_cap,
247         cmd_dummy,                                       /* check_recovery */
248         (int(*)__PR((SCSI *, cdr_t *, int)))cmd_dummy,   /* recover     */
249         speed_select_mdvd,
250         select_secsize,
251         next_wr_addr_mdvd,
252         (int(*)(SCSI *, Ulong))cmd_ill,   /* reserve_track        */
253         scsi_cdr_write,
254         (int(*)__PR((track_t *, void *, BOOL)))cmd_dummy, /* gen_cue */
255         (int(*)__PR((SCSI *usalp, cdr_t *, track_t *)))cmd_dummy, /* send_cue */
256         write_leadin_mmc,
257         open_track_mdvd,
258         close_track_mdvd,
259         open_session_mdvd,
260         cmd_dummy,
261         cmd_dummy,                                      /* abort        */
262         read_session_offset,
263         fixate_mdvd,
264         stats_mmc,
265         blank_mmc,
266         format_mdvd,
267         send_opc_mmc,
268         opt1_mdvd,
269         opt2_mmc,
270         dvd_dual_layer_split,
271 };
272
273 /*
274  * Sony MMC CD-writer
275  */
276 cdr_t   cdr_mmc_sony = {
277         0, 0,
278         CDR_SWABAUDIO,
279         CDR_CDRW_ALL,
280         372, 372,
281         "mmc_cdr_sony",
282         "generic SCSI-3/mmc   CD-R/CD-RW driver (Sony 928 variant)",
283         0,
284         (dstat_t *)0,
285         identify_mmc,
286         attach_mmc,
287         init_mmc,
288         getdisktype_mmc,
289         scsi_load,
290         scsi_unload,
291         read_buff_cap,
292         cmd_dummy,                                      /* check_recovery */
293         (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
294         speed_select_mmc,
295         select_secsize,
296         next_wr_addr_mmc,
297         (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
298         scsi_sony_write,
299         gen_cue_mmc,
300         send_cue_mmc,
301         write_leadin_mmc,
302         open_track_mmc,
303         close_track_mmc,
304         open_session_mmc,
305         cmd_dummy,
306         cmd_dummy,                                      /* abort        */
307         read_session_offset,
308         fixate_mmc,
309         cmd_dummy,                              /* stats                */
310         blank_mmc,
311         format_dummy,
312         send_opc_mmc,
313         opt1_mmc,
314         opt2_mmc,
315 };
316
317 /*
318  * SCSI-3/mmc conformant CD-ROM drive
319  */
320 cdr_t   cdr_cd = {
321         0, 0,
322         CDR_ISREADER|CDR_SWABAUDIO,
323         CDR_CDRW_NONE,
324         372, 372,
325         "mmc_cd",
326         "generic SCSI-3/mmc   CD-ROM driver",
327         0,
328         (dstat_t *)0,
329         identify_mmc,
330         attach_mmc,
331         cmd_dummy,
332         drive_getdisktype,
333         scsi_load,
334         scsi_unload,
335         read_buff_cap,
336         cmd_dummy,                                      /* check_recovery */
337         (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
338         speed_select_mmc,
339         select_secsize,
340         (int(*)(SCSI *usalp, track_t *, long *))cmd_ill,        /* next_wr_addr         */
341         (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
342         scsi_cdr_write,
343         (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
344         no_sendcue,
345         (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
346         open_track_mmc,
347         close_track_mmc,
348         (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,
349         cmd_dummy,
350         cmd_dummy,                                      /* abort        */
351         read_session_offset,
352         (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,     /* fixation */
353         cmd_dummy,                                      /* stats        */
354         blank_dummy,
355         format_dummy,
356         (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
357         cmd_dummy,                                      /* opt1         */
358         cmd_dummy,                                      /* opt2         */
359 };
360
361 /*
362  * Old pre SCSI-3/mmc CD drive
363  */
364 cdr_t   cdr_oldcd = {
365         0, 0,
366         CDR_ISREADER,
367         CDR_CDRW_NONE,
368         372, 372,
369         "scsi2_cd",
370         "generic SCSI-2       CD-ROM driver",
371         0,
372         (dstat_t *)0,
373         identify_mmc,
374         drive_attach,
375         cmd_dummy,
376         drive_getdisktype,
377         scsi_load,
378         scsi_unload,
379         buf_dummy,
380         cmd_dummy,                                      /* check_recovery */
381         (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
382         speed_select_mmc,
383         select_secsize,
384         (int(*)(SCSI *usal, track_t *, long *))cmd_ill, /* next_wr_addr         */
385         (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
386         scsi_cdr_write,
387         (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
388         no_sendcue,
389         (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
390         open_track_mmc,
391         close_track_mmc,
392         (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,
393         cmd_dummy,
394         cmd_dummy,                                      /* abort        */
395         read_session_offset_philips,
396         (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,     /* fixation */
397         cmd_dummy,                                      /* stats        */
398         blank_dummy,
399         format_dummy,
400         (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
401         cmd_dummy,                                      /* opt1         */
402         cmd_dummy,                                      /* opt2         */
403 };
404
405 /*
406  * SCSI-3/mmc conformant CD or DVD writer
407  * Checks the current medium and then returns either cdr_mmc or cdr_dvd
408  */
409 cdr_t   cdr_cd_dvd = {
410         0, 0,
411         CDR_SWABAUDIO,
412         CDR_CDRW_ALL,
413         372, 372,
414         "mmc_cd_dvd",
415         "generic SCSI-3/mmc   CD/DVD driver (checks media)",
416         0,
417         (dstat_t *)0,
418         identify_mmc,
419         attach_mmc,
420         cmd_dummy,
421         drive_getdisktype,
422         scsi_load,
423         scsi_unload,
424         read_buff_cap,
425         cmd_dummy,                                      /* check_recovery */
426         (int(*)(SCSI *, cdr_t *, int))cmd_dummy,        /* recover      */
427         speed_select_mmc,
428         select_secsize,
429         (int(*)(SCSI *usalp, track_t *, long *))cmd_ill,        /* next_wr_addr         */
430         (int(*)(SCSI *, Ulong))cmd_ill, /* reserve_track        */
431         scsi_cdr_write,
432         (int(*)(track_t *, void *, BOOL))cmd_dummy,     /* gen_cue */
433         no_sendcue,
434         (int(*)(SCSI *, cdr_t *, track_t *))cmd_dummy, /* leadin */
435         open_track_mmc,
436         close_track_mmc,
437         (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,
438         cmd_dummy,
439         cmd_dummy,                                      /* abort        */
440         read_session_offset,
441         (int(*)(SCSI *usalp, cdr_t *, track_t *))cmd_dummy,     /* fixation */
442         cmd_dummy,                                      /* stats        */
443         blank_dummy,
444         format_dummy,
445         (int(*)(SCSI *, caddr_t, int, int))NULL,        /* no OPC       */
446         cmd_dummy,                                      /* opt1         */
447         cmd_dummy,                                      /* opt2         */
448 };
449
450 void 
451 mmc_opthelp(cdr_t *dp, int excode)
452 {
453         BOOL    haveopts = FALSE;
454
455         fprintf(stderr, "Driver options:\n");
456         if (dp->cdr_flags & CDR_BURNFREE) {
457                 fprintf(stderr, "burnfree       Prepare writer to use BURN-Free technology\n");
458                 fprintf(stderr, "noburnfree     Disable using BURN-Free technology\n");
459                 haveopts = TRUE;
460         }
461         if (dp->cdr_flags & CDR_VARIREC) {
462                 fprintf(stderr, "varirec=val    Set VariRec Laserpower to -2, -1, 0, 1, 2\n");
463                 fprintf(stderr, "               Only works for audio and if speed is set to 4\n");
464                 haveopts = TRUE;
465         }
466         if (dp->cdr_flags & CDR_GIGAREC) {
467                 fprintf(stderr, "gigarec=val    Set GigaRec capacity ratio to 0.6, 0.7, 0.8, 1.0, 1.2, 1.3, 1.4\n");
468                 haveopts = TRUE;
469         }
470         if (dp->cdr_flags & CDR_AUDIOMASTER) {
471                 fprintf(stderr, "audiomaster    Turn Audio Master feature on (SAO CD-R Audio/Data only)\n");
472                 haveopts = TRUE;
473         }
474         if (dp->cdr_flags & CDR_FORCESPEED) {
475                 fprintf(stderr, "forcespeed     Tell the drive to force speed even for low quality media\n");
476                 haveopts = TRUE;
477         }
478         if (dp->cdr_flags & CDR_SPEEDREAD) {
479                 fprintf(stderr, "speedread      Tell the drive to read as fast as possible\n");
480                 fprintf(stderr, "nospeedread    Disable to read as fast as possible\n");
481                 haveopts = TRUE;
482         }
483         if (dp->cdr_flags & CDR_DISKTATTOO) {
484                 fprintf(stderr, "tattooinfo     Print image size info for DiskT@2 feature\n");
485                 fprintf(stderr, "tattoofile=name        Use 'name' as DiskT@2 image file\n");
486                 haveopts = TRUE;
487         }
488         if (dp->cdr_flags & CDR_SINGLESESS) {
489                 fprintf(stderr, "singlesession  Tell the drive to behave as single session only drive\n");
490                 fprintf(stderr, "nosinglesession        Disable single session only mode\n");
491                 haveopts = TRUE;
492         }
493         if (dp->cdr_flags & CDR_HIDE_CDR) {
494                 fprintf(stderr, "hidecdr                Tell the drive to hide CD-R media\n");
495                 fprintf(stderr, "nohidecdr      Disable hiding CD-R media\n");
496                 haveopts = TRUE;
497         }
498         if (!haveopts) {
499                 fprintf(stderr, "None supported for this drive.\n");
500         }
501         exit(excode);
502 }
503
504 char *
505 hasdrvopt(char *optstr, char *optname)
506 {
507         char    *ep;
508         char    *np;
509         char    *ret = NULL;
510         int     optnamelen;
511         int     optlen;
512         BOOL    not = FALSE;
513
514         if (optstr == NULL)
515                 return (ret);
516
517         optnamelen = strlen(optname);
518
519         while (*optstr) {
520                 not = FALSE;                    /* Reset before every token */
521                 if ((ep = strchr(optstr, ',')) != NULL) {
522                         optlen = ep - optstr;
523                         np = &ep[1];
524                 } else {
525                         optlen = strlen(optstr);
526                         np = &optstr[optlen];
527                 }
528                 if ((ep = strchr(optstr, '=')) != NULL) {
529                         if (ep < np)
530                                 optlen = ep - optstr;
531                 }
532                 if (optstr[0] == '!') {
533                         optstr++;
534                         optlen--;
535                         not = TRUE;
536                 }
537                 if (strncmp(optstr, "no", 2) == 0) {
538                         optstr += 2;
539                         optlen -= 2;
540                         not = TRUE;
541                 }
542                 if (strncmp(optstr, optname, optlen) == 0) {
543                         ret = &optstr[optlen];
544                         break;
545                 }
546                 optstr = np;
547         }
548         if (ret != NULL) {
549                 if (*ret == ',' || *ret == '\0') {
550                         if (not)
551                                 return ("0");
552                         return ("1");
553                 }
554                 if (*ret == '=') {
555                         if (not)
556                                 return (NULL);
557                         return (++ret);
558                 }
559         }
560         return (ret);
561 }
562
563 static cdr_t *
564 identify_mmc(SCSI *usalp, cdr_t *dp, struct scsi_inquiry *ip)
565 {
566         BOOL    cdrr     = FALSE;       /* Read CD-R    */
567         BOOL    cdwr     = FALSE;       /* Write CD-R   */
568         BOOL    cdrrw    = FALSE;       /* Read CD-RW   */
569         BOOL    cdwrw    = FALSE;       /* Write CD-RW  */
570         BOOL    dvdwr    = FALSE;       /* DVD writer   */
571         BOOL    is_dvd   = FALSE;       /* use DVD driver*/
572         Uchar   mode[0x100];
573         struct  cd_mode_page_2A *mp;
574         int     profile;
575
576         if (ip->type != INQ_WORM && ip->type != INQ_ROMD)
577                 return ((cdr_t *)0);
578
579         allow_atapi(usalp, TRUE); /* Try to switch to 10 byte mode cmds */
580
581         usalp->silent++;
582         mp = mmc_cap(usalp, mode);      /* Get MMC capabilities */
583         usalp->silent--;
584         if (mp == NULL)
585                 return (&cdr_oldcd);    /* Pre SCSI-3/mmc drive         */
586
587         /*
588          * At this point we know that we have a SCSI-3/mmc compliant drive.
589          * Unfortunately ATAPI drives violate the SCSI spec in returning
590          * a response data format of '1' which from the SCSI spec would
591          * tell us not to use the "PF" bit in mode select. As ATAPI drives
592          * require the "PF" bit to be set, we 'correct' the inquiry data.
593          *
594          * XXX xxx_identify() should not have any side_effects ??
595          */
596         if (ip->data_format < 2)
597                 ip->data_format = 2;
598
599         /*
600          * First handle exceptions....
601          */
602         if (strncmp(ip->vendor_info, "SONY", 4) == 0 &&
603             strncmp(ip->prod_ident, "CD-R   CDU928E", 14) == 0) {
604                 return (&cdr_mmc_sony);
605         }
606
607         /*
608          * Now try to do it the MMC-3 way....
609          */
610         profile = get_curprofile(usalp);
611         if (xdebug)
612                 printf("Current profile: 0x%04X\n", profile);
613         if (profile == 0) {
614                 if (xdebug)
615                         print_profiles(usalp);
616                 /*
617                  * If the current profile is 0x0000, then the
618                  * drive does not know about the media. First
619                  * close the tray and then try to issue the
620                  * get_curprofile() command again.
621                  */
622                 usalp->silent++;
623                 load_media(usalp, dp, FALSE);
624                 usalp->silent--;
625                 profile = get_curprofile(usalp);
626                 scsi_prevent_removal(usalp, 0);
627                 if (xdebug)
628                         printf("Current profile: 0x%04X\n", profile);
629         }
630         if (profile >= 0) {
631                 if (lverbose)
632                         print_profiles(usalp);
633                 if (profile == 0 || (profile >= 0x10 && profile <= 0x15) || profile > 0x19) {
634                     /*
635                      * 10h DVD-ROM
636                      * 11h DVD-R
637                      * 12h DVD-RAM
638                      * 13h DVD-RW (Restricted overwrite)
639                      * 14h DVD-RW (Sequential recording)
640                      * 1Ah DVD+RW
641                      * 1Bh DVD+R
642                      * 2Bh DVD+R DL
643                      * 
644                      */
645                     if (profile == 0x11 || profile == 0x13 || profile == 0x14 || profile == 0x1A || profile == 0x1B || profile == 0x2B) {
646                         is_dvd = TRUE;
647                         dp = &cdr_mdvd;
648                     } else {
649                         is_dvd = FALSE;
650                         dp = &cdr_cd;
651
652                         if (profile == 0) {             /* No Medium */
653                                 BOOL    is_cdr = FALSE;
654
655                                 /*
656                                  * Check for CD-writer
657                                  */
658                                 get_wproflist(usalp, &is_cdr, NULL,
659                                                         NULL, NULL);
660                                 if (is_cdr)
661                                         return (&cdr_mmc);
662                                 /*
663                                  * Other MMC-3 drive without media
664                                  */
665                                 return (dp);
666                         } if (profile == 0x12) {        /* DVD-RAM */
667                                 errmsgno(EX_BAD,
668                                 "Found unsupported DVD-RAM media.\n");
669                                 return (dp);
670                         }
671                     }
672                 }
673         } else {
674                 if (xdebug)
675                         printf("Drive is pre MMC-3\n");
676         }
677
678         mmc_getval(mp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL, &dvdwr);
679
680         if (!cdwr && !cdwrw) {  /* SCSI-3/mmc CD drive          */
681                 /*
682                  * If the drive does not support to write CD's, we select the
683                  * CD-ROM driver here. If we have DVD-R/DVD-RW support compiled
684                  * in, we may later decide to switch to the DVD driver.
685                  */
686                 dp = &cdr_cd;
687         } else {
688                 /*
689                  * We need to set the driver to cdr_mmc because we may come
690                  * here with driver set to cdr_cd_dvd which is not a driver
691                  * that may be used for actual CD/DVD writing.
692                  */
693                 dp = &cdr_mmc;
694         }
695
696 /*#define       DVD_DEBUG*/
697 #ifdef  DVD_DEBUG
698         if (1) {        /* Always check for DVD media in debug mode */
699 #else
700         if ((cdwr || cdwrw) && dvdwr) {
701 #endif
702                 char    xb[32];
703
704 #ifndef DVD_DEBUG
705                 usalp->silent++;
706 #else
707                 fprintf(stderr, "identify_dvd: checking for DVD media\n");
708 #endif
709                 if (read_dvd_structure(usalp, (caddr_t)xb, 32, 0, 0, 0) >= 0) {
710                         /*
711                          * If read DVD structure is supported and works, then
712                          * we must have a DVD media in the drive. Signal to
713                          * use the DVD driver.
714                          */
715                         is_dvd = TRUE;
716                 } else {
717                         if (usal_sense_key(usalp) == SC_NOT_READY) {
718                                 /*
719                                  * If the SCSI sense key is NOT READY, then the
720                                  * drive does not know about the media. First
721                                  * close the tray and then try to issue the
722                                  * read_dvd_structure() command again.
723                                  */
724                                 load_media(usalp, dp, FALSE);
725                                 if (read_dvd_structure(usalp, (caddr_t)xb, 32, 0, 0, 0) >= 0) {
726                                         is_dvd = TRUE;
727                                 }
728                                 scsi_prevent_removal(usalp, 0);
729                         }
730                 }
731 #ifndef DVD_DEBUG
732                 usalp->silent--;
733 #else
734                 fprintf(stderr, "identify_dvd: is_dvd: %d\n", is_dvd);
735 #endif
736         }
737         if (is_dvd) {
738      if(lverbose>2) 
739         fprintf(stderr, "Found DVD media: using cdr_mdvd.\n");  
740      dp = &cdr_mdvd; 
741         }
742         dp->profile = profile;
743         dp->is_dvd = is_dvd;
744         return (dp);
745 }
746
747 static int 
748 attach_mmc(SCSI *usalp, cdr_t *dp)
749 {
750         int     ret;
751         Uchar   mode[0x100];
752         struct  cd_mode_page_2A *mp;
753         struct  ricoh_mode_page_30 *rp = NULL;
754
755         allow_atapi(usalp, TRUE); /* Try to switch to 10 byte mode cmds */
756
757         usalp->silent++;
758         mp = mmc_cap(usalp, NULL); /* Get MMC capabilities in allocated mp */
759         usalp->silent--;
760         if (mp == NULL)
761                 return (-1);    /* Pre SCSI-3/mmc drive         */
762
763         dp->cdr_cdcap = mp;     /* Store MMC cap pointer        */
764
765         dp->cdr_dstat->ds_dr_max_rspeed = a_to_u_2_byte(mp->max_read_speed)/176;
766         if (dp->cdr_dstat->ds_dr_max_rspeed == 0)
767                 dp->cdr_dstat->ds_dr_max_rspeed = 372;
768         dp->cdr_dstat->ds_dr_cur_rspeed = a_to_u_2_byte(mp->cur_read_speed)/176;
769         if (dp->cdr_dstat->ds_dr_cur_rspeed == 0)
770                 dp->cdr_dstat->ds_dr_cur_rspeed = 372;
771
772         dp->cdr_dstat->ds_dr_max_wspeed = a_to_u_2_byte(mp->max_write_speed)/176;
773         if (mp->p_len >= 28)
774                 dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->v3_cur_write_speed)/176;
775         else
776                 dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->cur_write_speed)/176;
777
778         if (dp->cdr_speedmax > dp->cdr_dstat->ds_dr_max_wspeed)
779                 dp->cdr_speedmax = dp->cdr_dstat->ds_dr_max_wspeed;
780
781         if (dp->cdr_speeddef > dp->cdr_speedmax)
782                 dp->cdr_speeddef = dp->cdr_speedmax;
783
784         rp = get_justlink_ricoh(usalp, mode);
785
786         if (mp->p_len >= 28)
787                 dp->cdr_flags |= CDR_MMC3;
788         if (mp->p_len >= 24)
789                 dp->cdr_flags |= CDR_MMC2;
790         dp->cdr_flags |= CDR_MMC;
791
792         if (mp->loading_type == LT_TRAY)
793                 dp->cdr_flags |= CDR_TRAYLOAD;
794         else if (mp->loading_type == LT_CADDY)
795                 dp->cdr_flags |= CDR_CADDYLOAD;
796
797         if (mp->BUF != 0) {
798                 dp->cdr_flags |= CDR_BURNFREE;
799         } else if (rp) {
800                 if ((dp->cdr_cmdflags & F_DUMMY) && rp->TWBFS && rp->BUEFS)
801                         dp->cdr_flags |= CDR_BURNFREE;
802
803                 if (rp->BUEFS)
804                         dp->cdr_flags |= CDR_BURNFREE;
805         }
806
807         if (mmc_isplextor(usalp)) {
808                 if (check_varirec_plextor(usalp) >= 0)
809                         dp->cdr_flags |= CDR_VARIREC;
810
811                 if (check_gigarec_plextor(usalp) >= 0)
812                         dp->cdr_flags |= CDR_GIGAREC;
813
814                 if (check_ss_hide_plextor(usalp) >= 0)
815                         dp->cdr_flags |= CDR_SINGLESESS|CDR_HIDE_CDR;
816
817                 if (check_powerrec_plextor(usalp) >= 0)
818                         dp->cdr_flags |= CDR_FORCESPEED;
819
820                 if (check_speed_rd_plextor(usalp) >= 0)
821                         dp->cdr_flags |= CDR_SPEEDREAD;
822         }
823         if (mmc_isyamaha(usalp)) {
824                 if (set_audiomaster_yamaha(usalp, dp, FALSE) >= 0)
825                         dp->cdr_flags |= CDR_AUDIOMASTER;
826
827                 /*
828                  * Starting with CRW 2200 / CRW 3200
829                  */
830                 if ((mp->p_len+2) >= (unsigned)28)
831                         dp->cdr_flags |= CDR_FORCESPEED;
832
833                 if (get_tattoo_yamaha(usalp, FALSE, 0, 0))
834                         dp->cdr_flags |= CDR_DISKTATTOO;
835         }
836
837         if (rp && rp->AWSCS)
838                 dp->cdr_flags |= CDR_FORCESPEED;
839
840 #ifdef  FUTURE_ROTCTL
841         if (mp->p_len >= 28) {
842                 int     val;
843
844                 val = dp->cdr_dstat->ds_dr_cur_wspeed;
845                 if (val == 0)
846                         val = 372;
847
848                 usalp->verbose++;
849                 if (scsi_set_speed(usalp, -1, val, ROTCTL_CAV) < 0) {
850                         fprintf(stderr, "XXX\n");
851                 }
852                 usalp->verbose--;
853         }
854 #endif
855
856         check_writemodes_mmc(usalp, dp);
857
858         /* Enable Burnfree by default, it can be disabled later */
859         if ((dp->cdr_flags & CDR_BURNFREE) != 0)
860                 dp->cdr_dstat->ds_cdrflags |= RF_BURNFREE;
861
862         if (driveropts != NULL) {
863                 char    *p;
864
865                 if (strcmp(driveropts, "help") == 0) {
866                         mmc_opthelp(dp, 0);
867                 }
868
869                 p = hasdrvopt(driveropts, "varirec");
870                 if (p != NULL && (dp->cdr_flags & CDR_VARIREC) != 0) {
871                         dp->cdr_dstat->ds_cdrflags |= RF_VARIREC;
872                 }
873
874                 p = hasdrvopt(driveropts, "gigarec");
875                 if (p != NULL && (dp->cdr_flags & CDR_GIGAREC) != 0) {
876                         dp->cdr_dstat->ds_cdrflags |= RF_GIGAREC;
877                 }
878
879                 p = hasdrvopt(driveropts, "audiomaster");
880                 if (p != NULL && *p == '1' && (dp->cdr_flags & CDR_AUDIOMASTER) != 0) {
881                         dp->cdr_dstat->ds_cdrflags |= RF_AUDIOMASTER;
882                         dp->cdr_dstat->ds_cdrflags &= ~RF_BURNFREE;
883                 }
884                 p = hasdrvopt(driveropts, "forcespeed");
885                 if (p != NULL && *p == '1' && (dp->cdr_flags & CDR_FORCESPEED) != 0) {
886                         dp->cdr_dstat->ds_cdrflags |= RF_FORCESPEED;
887                 }
888                 p = hasdrvopt(driveropts, "tattooinfo");
889                 if (p != NULL && *p == '1' && (dp->cdr_flags & CDR_DISKTATTOO) != 0) {
890                         get_tattoo_yamaha(usalp, TRUE, 0, 0);
891                 }
892                 p = hasdrvopt(driveropts, "tattoofile");
893                 if (p != NULL && (dp->cdr_flags & CDR_DISKTATTOO) != 0) {
894                         FILE    *f;
895
896                         if ((f = fileopen(p, "rb")) == NULL)
897                                 comerr("Cannot open '%s'.\n", p);
898
899                         if (do_tattoo_yamaha(usalp, f) < 0)
900                                 errmsgno(EX_BAD, "Cannot do DiskT@2.\n");
901                         fclose(f);
902                 }
903                 p = hasdrvopt(driveropts, "singlesession");
904                 if (p != NULL && (dp->cdr_flags & CDR_SINGLESESS) != 0) {
905                         if (*p == '1') {
906                                 dp->cdr_dstat->ds_cdrflags |= RF_SINGLESESS;
907                         } else if (*p == '0') {
908                                 dp->cdr_dstat->ds_cdrflags &= ~RF_SINGLESESS;
909                         }
910                 }
911                 p = hasdrvopt(driveropts, "hidecdr");
912                 if (p != NULL && (dp->cdr_flags & CDR_HIDE_CDR) != 0) {
913                         if (*p == '1') {
914                                 dp->cdr_dstat->ds_cdrflags |= RF_HIDE_CDR;
915                         } else if (*p == '0') {
916                                 dp->cdr_dstat->ds_cdrflags &= ~RF_HIDE_CDR;
917                         }
918                 }
919                 p = hasdrvopt(driveropts, "speedread");
920                 if (p != NULL && (dp->cdr_flags & CDR_SPEEDREAD) != 0) {
921                         if (*p == '1') {
922                                 dp->cdr_dstat->ds_cdrflags |= RF_SPEEDREAD;
923                         } else if (*p == '0') {
924                                 dp->cdr_dstat->ds_cdrflags &= ~RF_SPEEDREAD;
925                         }
926                 }
927         }
928
929         if ((ret = get_supported_cdrw_media_types(usalp)) < 0) {
930                 dp->cdr_cdrw_support = CDR_CDRW_ALL;
931                 return (0);
932         }
933         dp->cdr_cdrw_support = ret;
934         if (lverbose > 1)
935                 printf("Supported CD-RW media types: %02X\n", dp->cdr_cdrw_support);
936
937         return (0);
938 }
939
940 static int 
941 attach_mdvd(SCSI *usalp, cdr_t *dp)
942 {
943         struct  cd_mode_page_2A *mp;
944
945
946         allow_atapi(usalp, TRUE);/* Try to switch to 10 byte mode cmds */
947
948         usalp->silent++;
949         mp = mmc_cap(usalp, NULL);/* Get MMC capabilities in allocated mp */
950         usalp->silent--;
951         if (mp == NULL)
952                 return (-1);    /* Pre SCSI-3/mmc drive         */
953
954         dp->cdr_cdcap = mp;     /* Store MMC cap pointer        */
955
956         dp->cdr_dstat->ds_dr_max_rspeed = a_to_u_2_byte(mp->max_read_speed)/1385;
957         if (dp->cdr_dstat->ds_dr_max_rspeed == 0)
958                 dp->cdr_dstat->ds_dr_max_rspeed = 1385;
959         dp->cdr_dstat->ds_dr_cur_rspeed = a_to_u_2_byte(mp->cur_read_speed)/1385;
960         if (dp->cdr_dstat->ds_dr_cur_rspeed == 0)
961                 dp->cdr_dstat->ds_dr_cur_rspeed = 1385;
962
963         dp->cdr_dstat->ds_dr_max_wspeed = a_to_u_2_byte(mp->max_write_speed)/1385;
964         if (mp->p_len >= 28)
965                 dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->v3_cur_write_speed)/1385;
966         else
967                 dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->cur_write_speed)/1385;
968
969         if (dp->cdr_speedmax > dp->cdr_dstat->ds_dr_max_wspeed)
970                 dp->cdr_speedmax = dp->cdr_dstat->ds_dr_max_wspeed;
971
972         if (dp->cdr_speeddef > dp->cdr_speedmax)
973                 dp->cdr_speeddef = dp->cdr_speedmax;
974
975
976         if (mp->loading_type == LT_TRAY)
977                 dp->cdr_flags |= CDR_TRAYLOAD;
978         else if (mp->loading_type == LT_CADDY)
979                 dp->cdr_flags |= CDR_CADDYLOAD;
980
981         if (mp->BUF != 0)
982                 dp->cdr_flags |= CDR_BURNFREE;
983
984         check_writemodes_mdvd(usalp, dp);
985
986         if (driveropts != NULL) {
987                 if (strcmp(driveropts, "help") == 0) {
988                         mmc_opthelp(dp, 0);
989                 }
990         }
991
992         return (0);
993 }
994
995 int 
996 check_writemodes_mmc(SCSI *usalp, cdr_t *dp)
997 {
998         Uchar   mode[0x100];
999         int     len;
1000         struct  cd_mode_page_05 *mp;
1001
1002         if (xdebug)
1003                 printf("Checking possible write modes: ");
1004
1005         /*
1006          * Reset mp->test_write (-dummy) here.
1007          */
1008         deflt_writemodes_mmc(usalp, TRUE);
1009
1010         fillbytes((caddr_t)mode, sizeof (mode), '\0');
1011
1012         usalp->silent++;
1013         if (!get_mode_params(usalp, 0x05, "CD write parameter",
1014                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
1015                 usalp->silent--;
1016                 return (-1);
1017         }
1018         if (len == 0) {
1019                 usalp->silent--;
1020                 return (-1);
1021         }
1022
1023         mp = (struct cd_mode_page_05 *)
1024                 (mode + sizeof (struct scsi_mode_header) +
1025                 ((struct scsi_mode_header *)mode)->blockdesc_len);
1026 #ifdef  DEBUG
1027         usal_prbytes("CD write parameter:", (Uchar *)mode, len);
1028 #endif
1029
1030         /*
1031          * mp->test_write has already been reset in deflt_writemodes_mmc()
1032          * Do not reset mp->test_write (-dummy) here. It should be set
1033          * only at one place and only one time.
1034          */
1035
1036         mp->write_type = WT_TAO;
1037         mp->track_mode = TM_DATA;
1038         mp->dbtype = DB_ROM_MODE1;
1039
1040         if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1041                 dp->cdr_flags |= CDR_TAO;
1042                 if (xdebug)
1043                         printf("TAO ");
1044         } else
1045                 dp->cdr_flags &= ~CDR_TAO;
1046
1047         mp->write_type = WT_PACKET;
1048         mp->track_mode |= TM_INCREMENTAL;
1049 /*      mp->fp = (trackp->pktsize > 0) ? 1 : 0;*/
1050 /*      i_to_4_byte(mp->packet_size, trackp->pktsize);*/
1051         mp->fp = 0;
1052         i_to_4_byte(mp->packet_size, 0);
1053
1054         if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1055                 dp->cdr_flags |= CDR_PACKET;
1056                 if (xdebug)
1057                         printf("PACKET ");
1058         } else
1059                 dp->cdr_flags &= ~CDR_PACKET;
1060         mp->fp = 0;
1061         i_to_4_byte(mp->packet_size, 0);
1062         mp->track_mode = TM_DATA;
1063         mp->write_type = WT_SAO;
1064
1065         if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1066                 dp->cdr_flags |= CDR_SAO;
1067                 if (xdebug)
1068                         printf("SAO ");
1069         } else
1070                 dp->cdr_flags &= ~CDR_SAO;
1071
1072         if (dp->cdr_flags & CDR_SAO) {
1073                 mp->dbtype = DB_RAW_PQ;
1074
1075 #ifdef  __needed__
1076                 if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1077                         dp->cdr_flags |= CDR_SRAW16;
1078                         if (xdebug)
1079                                 printf("SAO/R16 ");
1080                 }
1081 #endif
1082
1083                 mp->dbtype = DB_RAW_PW;
1084
1085                 if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1086                         dp->cdr_flags |= CDR_SRAW96P;
1087                         if (xdebug)
1088                                 printf("SAO/R96P ");
1089                 }
1090
1091                 mp->dbtype = DB_RAW_PW_R;
1092
1093                 if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1094                         dp->cdr_flags |= CDR_SRAW96R;
1095                         if (xdebug)
1096                                 printf("SAO/R96R ");
1097                 }
1098         }
1099
1100         mp->write_type = WT_RAW;
1101         mp->dbtype = DB_RAW_PQ;
1102
1103         if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1104                 dp->cdr_flags |= CDR_RAW;
1105                 dp->cdr_flags |= CDR_RAW16;
1106                 if (xdebug)
1107                         printf("RAW/R16 ");
1108         }
1109
1110         mp->dbtype = DB_RAW_PW;
1111
1112         if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1113                 dp->cdr_flags |= CDR_RAW;
1114                 dp->cdr_flags |= CDR_RAW96P;
1115                 if (xdebug)
1116                         printf("RAW/R96P ");
1117         }
1118
1119         mp->dbtype = DB_RAW_PW_R;
1120
1121         if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1122                 dp->cdr_flags |= CDR_RAW;
1123                 dp->cdr_flags |= CDR_RAW96R;
1124                 if (xdebug)
1125                         printf("RAW/R96R ");
1126         }
1127
1128         if (xdebug)
1129                 printf("\n");
1130
1131         /*
1132          * Reset mp->test_write (-dummy) here.
1133          */
1134         deflt_writemodes_mmc(usalp, TRUE);
1135         usalp->silent--;
1136
1137         return (0);
1138 }
1139
1140 int 
1141 check_writemodes_mdvd(SCSI *usalp, cdr_t *dp)
1142 {
1143         Uchar   mode[0x100];
1144         int     len;
1145         struct  cd_mode_page_05 *mp;
1146
1147         if (xdebug)
1148                 printf("Checking possible write modes: ");
1149
1150         deflt_writemodes_mdvd(usalp, FALSE);
1151
1152         fillbytes((caddr_t)mode, sizeof(mode), '\0');
1153
1154         usalp->silent++;
1155         if (!get_mode_params(usalp, 0x05, "DVD write parameter",
1156                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
1157                 usalp->silent--;
1158                 return (-1);
1159         }
1160         if (len == 0) {
1161                 usalp->silent--;
1162                 return (-1);
1163         }
1164
1165         mp = (struct cd_mode_page_05 *)
1166                 (mode + sizeof(struct scsi_mode_header) +
1167                 ((struct scsi_mode_header *)mode)->blockdesc_len);
1168
1169         mp->test_write = 0;
1170
1171         /*We only check for PACKET and SAO since these are the only supported modes for DVD */
1172         /*XXX these checks are irrelevant because they are not medium sensitive. ie the device returns 
1173           error only when it does not support a given mode for ALL mediums. It should check using 
1174           GET CONFIGURATION command.*/
1175
1176         mp->write_type = WT_PACKET;
1177         mp->fp = 0;
1178         i_to_4_byte(mp->packet_size, 0);
1179
1180         if (set_mode_params(usalp, "DVD write parameter", mode, len, 0, -1)) {
1181                 dp->cdr_flags |= CDR_PACKET;
1182                 if (xdebug)
1183                   printf("PACKET ");
1184         } else
1185           dp->cdr_flags &= ~CDR_PACKET;
1186         mp->fp = 0;
1187         i_to_4_byte(mp->packet_size, 0);
1188         mp->track_mode = TM_DATA; 
1189
1190
1191         mp->write_type = WT_SAO;
1192
1193         if (set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1194                 dp->cdr_flags |= CDR_SAO;
1195                 if (xdebug)
1196                         printf("SAO ");
1197         } else
1198                 dp->cdr_flags &= ~CDR_SAO;
1199
1200
1201         if (xdebug)
1202                 printf("\n");
1203
1204         deflt_writemodes_mdvd(usalp, TRUE);
1205         usalp->silent--;
1206         return (0);
1207 }
1208
1209 static int 
1210 deflt_writemodes_mmc(SCSI *usalp, BOOL reset_dummy)
1211 {
1212         Uchar   mode[0x100];
1213         int     len;
1214         struct  cd_mode_page_05 *mp;
1215
1216         fillbytes((caddr_t)mode, sizeof (mode), '\0');
1217
1218         usalp->silent++;
1219         if (!get_mode_params(usalp, 0x05, "CD write parameter",
1220                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
1221                 usalp->silent--;
1222                 return (-1);
1223         }
1224         if (len == 0) {
1225                 usalp->silent--;
1226                 return (-1);
1227         }
1228
1229         mp = (struct cd_mode_page_05 *)
1230                 (mode + sizeof (struct scsi_mode_header) +
1231                 ((struct scsi_mode_header *)mode)->blockdesc_len);
1232 #ifdef  DEBUG
1233         usal_prbytes("CD write parameter:", (Uchar *)mode, len);
1234         fprintf(stderr, "Audio pause len: %d\n", a_to_2_byte(mp->audio_pause_len));
1235 #endif
1236
1237         /*
1238          * This is the only place where we reset mp->test_write (-dummy)
1239          */
1240         if (reset_dummy)
1241                 mp->test_write = 0;
1242
1243         /*
1244          * Set default values:
1245          * Write type = 01 (track at once)
1246          * Track mode = 04 (CD-ROM)
1247          * Data block type = 08 (CD-ROM)
1248          * Session format = 00 (CD-ROM)
1249          *
1250          * XXX Note:    the same code appears in check_writemodes_mmc() and
1251          * XXX          in speed_select_mmc().
1252          */
1253         mp->write_type = WT_TAO;
1254         mp->track_mode = TM_DATA;
1255         mp->dbtype = DB_ROM_MODE1;
1256         mp->session_format = SES_DA_ROM; /* Matsushita has illegal def. value */
1257
1258         i_to_2_byte(mp->audio_pause_len, 150);  /* LG has illegal def. value */
1259
1260 #ifdef  DEBUG
1261         usal_prbytes("CD write parameter:", (Uchar *)mode, len);
1262 #endif
1263         if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1264
1265                 mp->write_type  = WT_SAO;
1266                 mp->LS_V        = 0;
1267                 mp->copy        = 0;
1268                 mp->fp          = 0;
1269                 mp->multi_session  = MS_NONE;
1270                 mp->host_appl_code = 0;
1271
1272                 if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1)) {
1273                         usalp->silent--;
1274                         return (-1);
1275                 }
1276         }
1277         usalp->silent--;
1278         return (0);
1279 }
1280
1281 static int 
1282 deflt_writemodes_mdvd(SCSI *usalp, BOOL reset_dummy)
1283 {
1284         Uchar   mode[0x100];
1285         int     len;
1286         struct  cd_mode_page_05 *mp;
1287
1288         fillbytes((caddr_t)mode, sizeof(mode), '\0');
1289
1290         usalp->silent++;
1291         if (!get_mode_params(usalp, 0x05, "DVD write parameter",
1292                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
1293                 usalp->silent--;
1294                 return (-1);
1295         }
1296         if (len == 0) {
1297                 usalp->silent--;
1298                 return (-1);
1299         }
1300
1301         mp = (struct cd_mode_page_05 *)
1302                 (mode + sizeof(struct scsi_mode_header) +
1303                 ((struct scsi_mode_header *)mode)->blockdesc_len);
1304
1305         mp->test_write = 0;
1306         /*
1307          * This is the only place where we reset mp->test_write (-dummy) for DVD
1308          */
1309         if (reset_dummy)
1310                 mp->test_write = 0;
1311
1312         /*
1313          * Set default values:
1314          * Write type = 02 (session at once)
1315          *
1316          * XXX Note:    the same code appears in check_writemodes_mmc() and
1317          * XXX          in speed_select_mmc().
1318          */
1319         mp->write_type = WT_SAO;
1320         mp->track_mode = TM_DATA; 
1321         mp->dbtype = DB_ROM_MODE1;
1322         mp->session_format = SES_DA_ROM;
1323
1324
1325         if (set_mode_params(usalp, "DVD write parameter", mode, len, 0, -1) < 0) {
1326                 usalp->silent--;
1327                 return (-1);
1328         }
1329         usalp->silent--;
1330         return (0);
1331 }
1332
1333 #ifdef  PRINT_ATIP
1334 static  void    print_di(struct disk_info *dip);
1335 static  void    atip_printspeed(char *fmt, int speedindex, char speedtab[]);
1336 static  void    print_atip(SCSI *usalp, struct atipinfo *atp);
1337 #endif  /* PRINT_ATIP */
1338
1339 static int 
1340 get_diskinfo(SCSI *usalp, struct disk_info *dip)
1341 {
1342         int     len;
1343         int     ret;
1344
1345         fillbytes((caddr_t)dip, sizeof (*dip), '\0');
1346
1347         /*
1348          * Used to be 2 instead of 4 (now). But some Y2k ATAPI drives as used
1349          * by IOMEGA create a DMA overrun if we try to transfer only 2 bytes.
1350          */
1351 /*      if (read_disk_info(usalp, (caddr_t)dip, 2) < 0)*/
1352         if (read_disk_info(usalp, (caddr_t)dip, 4) < 0)
1353                 return (-1);
1354         len = a_to_u_2_byte(dip->data_len);
1355         len += 2;
1356         ret = read_disk_info(usalp, (caddr_t)dip, len);
1357
1358 #ifdef  DEBUG
1359         usal_prbytes("Disk info:", (Uchar *)dip,
1360                                 len-usal_getresid(usalp));
1361 #endif
1362         return (ret);
1363 }
1364
1365 static void 
1366 di_to_dstat(struct disk_info *dip, dstat_t *dsp)
1367 {
1368         dsp->ds_diskid = a_to_u_4_byte(dip->disk_id);
1369         if (dip->did_v)
1370                 dsp->ds_flags |= DSF_DID_V;
1371         dsp->ds_disktype = dip->disk_type;
1372         dsp->ds_diskstat = dip->disk_status;
1373         dsp->ds_sessstat = dip->sess_status;
1374         if (dip->erasable)
1375                 dsp->ds_flags |= DSF_ERA;
1376
1377         dsp->ds_trfirst    = dip->first_track;
1378         dsp->ds_trlast     = dip->last_track_ls;
1379         dsp->ds_trfirst_ls = dip->first_track_ls;
1380
1381         dsp->ds_maxblocks = msf_to_lba(dip->last_lead_out[1],
1382                                         dip->last_lead_out[2],
1383                                         dip->last_lead_out[3], TRUE);
1384         /*
1385          * Check for 0xFF:0xFF/0xFF which is an indicator for a complete disk
1386          */
1387         if (dsp->ds_maxblocks == 1166730)
1388                 dsp->ds_maxblocks = -1L;
1389
1390         dsp->ds_first_leadin = msf_to_lba(dip->last_lead_in[1],
1391                                         dip->last_lead_in[2],
1392                                         dip->last_lead_in[3], FALSE);
1393         if (dsp->ds_first_leadin > 0)
1394                 dsp->ds_first_leadin = 0;
1395
1396         if (dsp->ds_last_leadout == 0 && dsp->ds_maxblocks >= 0)
1397                 dsp->ds_last_leadout = dsp->ds_maxblocks;
1398         dsp->ds_trfirst=dip->first_track; 
1399         dsp->ds_trlast=dip->last_track_ls;
1400         dsp->ds_trfirst_ls=dip->first_track_ls;
1401 }
1402
1403 static int 
1404 get_atip(SCSI *usalp, struct atipinfo *atp)
1405 {
1406         int     len;
1407         int     ret;
1408
1409         fillbytes((caddr_t)atp, sizeof (*atp), '\0');
1410
1411         /*
1412          * Used to be 2 instead of sizeof (struct tocheader), but all
1413          * other places in the code use sizeof (struct tocheader) too and
1414          * some Y2k ATAPI drives as used by IOMEGA create a DMA overrun if we
1415          * try to transfer only 2 bytes.
1416          */
1417         if (read_toc(usalp, (caddr_t)atp, 0, sizeof (struct tocheader), 0, FMT_ATIP) < 0)
1418                 return (-1);
1419         len = a_to_u_2_byte(atp->hd.len);
1420         len += 2;
1421         ret = read_toc(usalp, (caddr_t)atp, 0, len, 0, FMT_ATIP);
1422
1423 #ifdef  DEBUG
1424         usal_prbytes("ATIP info:", (Uchar *)atp,
1425                                 len-usal_getresid(usalp));
1426 #endif
1427         /*
1428          * Yamaha sometimes returns zeroed ATIP info for disks without ATIP
1429          */
1430         if (atp->desc.lead_in[1] == 0 &&
1431                         atp->desc.lead_in[2] == 0 &&
1432                         atp->desc.lead_in[3] == 0 &&
1433                         atp->desc.lead_out[1] == 0 &&
1434                         atp->desc.lead_out[2] == 0 &&
1435                         atp->desc.lead_out[3] == 0)
1436                 return (-1);
1437
1438         if (atp->desc.lead_in[1] >= 0x90 && debug) {
1439                 /*
1440                  * Only makes sense with buggy Ricoh firmware.
1441                  */
1442                 errmsgno(EX_BAD, "Converting ATIP from BCD\n");
1443                 atp->desc.lead_in[1] = from_bcd(atp->desc.lead_in[1]);
1444                 atp->desc.lead_in[2] = from_bcd(atp->desc.lead_in[2]);
1445                 atp->desc.lead_in[3] = from_bcd(atp->desc.lead_in[3]);
1446
1447                 atp->desc.lead_out[1] = from_bcd(atp->desc.lead_out[1]);
1448                 atp->desc.lead_out[2] = from_bcd(atp->desc.lead_out[2]);
1449                 atp->desc.lead_out[3] = from_bcd(atp->desc.lead_out[3]);
1450         }
1451
1452         return (ret);
1453 }
1454
1455 #ifdef  PRINT_ATIP
1456
1457 static int 
1458 get_pma(SCSI *usalp)
1459 {
1460         int     len;
1461         int     ret;
1462         char    atp[1024];
1463
1464         fillbytes((caddr_t)atp, sizeof (*atp), '\0');
1465
1466         /*
1467          * Used to be 2 instead of sizeof (struct tocheader), but all
1468          * other places in the code use sizeof (struct tocheader) too and
1469          * some Y2k ATAPI drives as used by IOMEGA create a DMA overrun if we
1470          * try to transfer only 2 bytes.
1471          */
1472 /*      if (read_toc(usalp, (caddr_t)atp, 0, 2, 1, FMT_PMA) < 0)*/
1473 /*      if (read_toc(usalp, (caddr_t)atp, 0, 2, 0, FMT_PMA) < 0)*/
1474         if (read_toc(usalp, (caddr_t)atp, 0, sizeof (struct tocheader), 0, FMT_PMA) < 0)
1475                 return (-1);
1476 /*      len = a_to_u_2_byte(atp->hd.len);*/
1477         len = a_to_u_2_byte(atp);
1478         len += 2;
1479 /*      ret = read_toc(usalp, (caddr_t)atp, 0, len, 1, FMT_PMA);*/
1480         ret = read_toc(usalp, (caddr_t)atp, 0, len, 0, FMT_PMA);
1481
1482 #ifdef  DEBUG
1483         usal_prbytes("PMA:", (Uchar *)atp,
1484                                 len-usal_getresid(usalp));
1485 #endif
1486         ret = read_toc(usalp, (caddr_t)atp, 0, len, 1, FMT_PMA);
1487
1488 #ifdef  DEBUG
1489         usal_prbytes("PMA:", (Uchar *)atp,
1490                                 len-usal_getresid(usalp));
1491 #endif
1492         return (ret);
1493 }
1494
1495 #endif  /* PRINT_ATIP */
1496
1497 static int 
1498 init_mmc(SCSI *usalp, cdr_t *dp)
1499 {
1500         return (speed_select_mmc(usalp, dp, NULL));
1501 }
1502
1503 static int 
1504 getdisktype_mdvd(SCSI *usalp, cdr_t *dp)
1505 {
1506         int ret = 0;
1507         dstat_t *dsp = dp->cdr_dstat;
1508
1509         struct track_info track_info;
1510     if(lverbose)
1511         printf("HINT: use dvd+rw-mediainfo from dvd+rw-tools for information extraction.\n");
1512         /* if(getdisktype_mmc(usalp, dp)<0)
1513                 return -1;
1514                 */
1515
1516         /* read rzone info to get the space left on disk */
1517         /*ds_trlast is the last rzone on disk, can be invisible */
1518         if(read_rzone_info(usalp, (caddr_t)&track_info, sizeof(track_info))>=0)
1519                 dsp->ds_maxblocks=a_to_u_4_byte(track_info.free_blocks)+a_to_4_byte(track_info.next_writable_addr);
1520
1521         dsp->ds_disktype&= ~DT_CD;
1522         dsp->ds_disktype|= DT_DVD;
1523
1524         return (ret);
1525
1526 }
1527
1528 static int 
1529 getdisktype_mmc(SCSI *usalp, cdr_t *dp)
1530 {
1531 extern  char    *buf;
1532         dstat_t *dsp = dp->cdr_dstat;
1533         struct disk_info *dip;
1534         Uchar   mode[0x100];
1535         msf_t   msf;
1536         BOOL    did_atip = FALSE;
1537         BOOL    did_dummy = FALSE;
1538         int     rplus;
1539
1540         msf.msf_min = msf.msf_sec = msf.msf_frame = 0;
1541
1542         /*
1543          * It seems that there are drives that do not support to
1544          * read ATIP (e.g. HP 7100)
1545          * Also if a NON CD-R media is inserted, this will never work.
1546          * For this reason, make a failure non-fatal.
1547          */
1548         usalp->silent++;
1549         if (get_atip(usalp, (struct atipinfo *)mode) >= 0) {
1550                 struct atipinfo *atp = (struct atipinfo *)mode;
1551
1552                 msf.msf_min =           mode[8];
1553                 msf.msf_sec =           mode[9];
1554                 msf.msf_frame =         mode[10];
1555                 if (atp->desc.erasable) {
1556                         dsp->ds_flags |= DSF_ERA;
1557                         if (atp->desc.sub_type == 1)
1558                                 dsp->ds_flags |= DSF_HIGHSP_ERA;
1559                         else if (atp->desc.sub_type == 2)
1560                                 dsp->ds_flags |= DSF_ULTRASP_ERA;
1561                         else if (atp->desc.sub_type == 3)
1562                                 dsp->ds_flags |= DSF_ULTRASP_ERA | DSF_ULTRASPP_ERA;
1563                 }
1564                 if (atp->desc.a1_v) {
1565                         if (atp->desc.clv_low != 0)
1566                                 dsp->ds_at_min_speed = clv_to_speed[atp->desc.clv_low];
1567                         if (atp->desc.clv_high != 0)
1568                                 dsp->ds_at_max_speed = clv_to_speed[atp->desc.clv_high];
1569
1570                         if (atp->desc.erasable && atp->desc.sub_type == 1) {
1571                                 if (atp->desc.clv_high != 0)
1572                                         dsp->ds_at_max_speed = hs_clv_to_speed[atp->desc.clv_high];
1573                         }
1574                 }
1575                 if (atp->desc.a2_v && atp->desc.erasable && (atp->desc.sub_type == 2 || atp->desc.sub_type == 3)) {
1576                         Uint    vlow;
1577                         Uint    vhigh;
1578
1579                         vlow = (atp->desc.a2[0] >> 4) & 0x07;
1580                         vhigh = atp->desc.a2[0] & 0x0F;
1581                         if (vlow != 0)
1582                                 dsp->ds_at_min_speed = us_clv_to_speed[vlow];
1583                         if (vhigh != 0)
1584                                 dsp->ds_at_max_speed = us_clv_to_speed[vhigh];
1585                 }
1586                 did_atip = TRUE;
1587         }
1588         usalp->silent--;
1589
1590 #ifdef  PRINT_ATIP
1591         if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0 && did_atip) {
1592                 print_atip(usalp, (struct atipinfo *)mode);
1593                 pr_manufacturer(&msf,
1594                         ((struct atipinfo *)mode)->desc.erasable,
1595                         ((struct atipinfo *)mode)->desc.uru);
1596         }
1597 #endif
1598 again:
1599         dip = (struct disk_info *)buf;
1600         if (get_diskinfo(usalp, dip) < 0)
1601                 return (-1);
1602
1603         /*
1604          * Check for non writable disk first.
1605          */
1606         
1607         /* DVD+RW does not need to be blanked */
1608         rplus = dsp->ds_cdrflags;
1609         if (dp->profile == 0x1A) rplus = RF_BLANK;
1610         
1611         if (dip->disk_status == DS_COMPLETE &&
1612                         (rplus & dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == RF_WRITE) {
1613                 if (!did_dummy) {
1614                         int     xspeed = 0xFFFF;
1615                         int     oflags = dp->cdr_cmdflags;
1616
1617                         /*
1618                          * Try to clear the dummy bit to reset the virtual
1619                          * drive status. Not all drives support it even though
1620                          * it is mentioned in the MMC standard.
1621                          */
1622                         if (lverbose)
1623                                 printf("Trying to clear drive status.\n");
1624
1625                         dp->cdr_cmdflags &= ~F_DUMMY;
1626                         speed_select_mmc(usalp, dp, &xspeed);
1627                         dp->cdr_cmdflags = oflags;
1628                         did_dummy = TRUE;
1629                         goto again;
1630                 }
1631                 /*
1632                  * Trying to clear drive status did not work...
1633                  */
1634                 reload_media(usalp, dp);
1635         }
1636         if (get_diskinfo(usalp, dip) < 0)
1637                 return (-1);
1638         di_to_dstat(dip, dsp);
1639         if (!did_atip && dsp->ds_first_leadin < 0)
1640                 lba_to_msf(dsp->ds_first_leadin, &msf);
1641
1642         if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0 && !did_atip) {
1643                 print_min_atip(dsp->ds_first_leadin, dsp->ds_last_leadout);
1644                 if (dsp->ds_first_leadin < 0)
1645                                 pr_manufacturer(&msf,
1646                                 dip->erasable,
1647                                 dip->uru);
1648         }
1649         dsp->ds_maxrblocks = disk_rcap(&msf, dsp->ds_maxblocks,
1650                                 dip->erasable,
1651                                 dip->uru);
1652
1653
1654 #ifdef  PRINT_ATIP
1655 #ifdef  DEBUG
1656         if (get_atip(usalp, (struct atipinfo *)mode) < 0)
1657                 return (-1);
1658         /*
1659          * Get pma gibt Ã„rger mit CW-7502
1660          * Wenn Die Disk leer ist, dann stuerzt alles ab.
1661          * Firmware 4.02 kann nicht get_pma
1662          */
1663         if (dip->disk_status != DS_EMPTY) {
1664 /*              get_pma();*/
1665         }
1666         printf("ATIP lead in:  %ld (%02d:%02d/%02d)\n",
1667                 msf_to_lba(mode[8], mode[9], mode[10], FALSE),
1668                 mode[8], mode[9], mode[10]);
1669         printf("ATIP lead out: %ld (%02d:%02d/%02d)\n",
1670                 msf_to_lba(mode[12], mode[13], mode[14], TRUE),
1671                 mode[12], mode[13], mode[14]);
1672         print_di(dip);
1673         print_atip(usalp, (struct atipinfo *)mode);
1674 #endif
1675 #endif  /* PRINT_ATIP */
1676         return (drive_getdisktype(usalp, dp));
1677 }
1678
1679 #ifdef  PRINT_ATIP
1680
1681 #define DOES(what, flag)        printf("  Does %s%s\n", flag?"":"not ", what);
1682 #define IS(what, flag)          printf("  Is %s%s\n", flag?"":"not ", what);
1683 #define VAL(what, val)          printf("  %s: %d\n", what, val[0]*256 + val[1]);
1684 #define SVAL(what, val)         printf("  %s: %s\n", what, val);
1685
1686 static void 
1687 print_di(struct disk_info *dip)
1688 {
1689         static  char *ds_name[] = { "empty", "incomplete/appendable", "complete", "illegal" };
1690         static  char *ss_name[] = { "empty", "incomplete/appendable", "illegal", "complete", };
1691
1692         IS("erasable", dip->erasable);
1693         printf("disk status: %s\n", ds_name[dip->disk_status]);
1694         printf("session status: %s\n", ss_name[dip->sess_status]);
1695         printf("first track: %d number of sessions: %d first track in last sess: %d last track in last sess: %d\n",
1696                 dip->first_track,
1697                 dip->numsess,
1698                 dip->first_track_ls,
1699                 dip->last_track_ls);
1700         IS("unrestricted", dip->uru);
1701         printf("Disk type: ");
1702         switch (dip->disk_type) {
1703
1704         case SES_DA_ROM:        printf("CD-DA or CD-ROM");      break;
1705         case SES_CDI:           printf("CDI");                  break;
1706         case SES_XA:            printf("CD-ROM XA");            break;
1707         case SES_UNDEF:         printf("undefined");            break;
1708         default:                printf("reserved");             break;
1709         }
1710         printf("\n");
1711         if (dip->did_v)
1712                 printf("Disk id: 0x%lX\n", a_to_u_4_byte(dip->disk_id));
1713
1714         printf("last start of lead in: %ld\n",
1715                 msf_to_lba(dip->last_lead_in[1],
1716                 dip->last_lead_in[2],
1717                 dip->last_lead_in[3], FALSE));
1718         printf("last start of lead out: %ld\n",
1719                 msf_to_lba(dip->last_lead_out[1],
1720                 dip->last_lead_out[2],
1721                 dip->last_lead_out[3], TRUE));
1722
1723         if (dip->dbc_v)
1724                 printf("Disk bar code: 0x%lX%lX\n",
1725                         a_to_u_4_byte(dip->disk_barcode),
1726                         a_to_u_4_byte(&dip->disk_barcode[4]));
1727
1728         if (dip->num_opc_entries > 0) {
1729                 printf("OPC table:\n");
1730         }
1731 }
1732
1733 char    *cdr_subtypes[] = {
1734         "Normal Rewritable (CLV) media",
1735         "High speed Rewritable (CAV) media",
1736         "Medium Type A, low Beta category (A-)",
1737         "Medium Type A, high Beta category (A+)",
1738         "Medium Type B, low Beta category (B-)",
1739         "Medium Type B, high Beta category (B+)",
1740         "Medium Type C, low Beta category (C-)",
1741         "Medium Type C, high Beta category (C+)",
1742 };
1743
1744 char    *cdrw_subtypes[] = {
1745         "Normal Rewritable (CLV) media",
1746         "High speed Rewritable (CAV) media",
1747         "Ultra High speed Rewritable media",
1748         "Ultra High speed+ Rewritable media",
1749         "Medium Type B, low Beta category (B-)",
1750         "Medium Type B, high Beta category (B+)",
1751         "Medium Type C, low Beta category (C-)",
1752         "Medium Type C, high Beta category (C+)",
1753 };
1754
1755 static void 
1756 atip_printspeed(char *fmt, int speedindex, char speedtab[])
1757 {
1758         printf("%s:", fmt);
1759         if (speedtab[speedindex] == 0) {
1760                 printf(" %2d (reserved val %2d)",
1761                         speedtab[speedindex], speedindex);
1762         } else {
1763                 printf(" %2d", speedtab[speedindex]);
1764         }
1765 }
1766
1767 static void 
1768 print_atip(SCSI *usalp, struct atipinfo *atp)
1769 {
1770         char    *sub_type;
1771         char    *speedvtab = clv_to_speed;
1772
1773         if (usalp->verbose)
1774                 usal_prbytes("ATIP info: ", (Uchar *)atp, sizeof (*atp));
1775
1776         printf("ATIP info from disk:\n");
1777         printf("  Indicated writing power: %d\n", atp->desc.ind_wr_power);
1778         if (atp->desc.erasable || atp->desc.ref_speed)
1779                 printf("  Reference speed: %d\n", clv_to_speed[atp->desc.ref_speed]);
1780         IS("unrestricted", atp->desc.uru);
1781 /*      printf("  Disk application code: %d\n", atp->desc.res5_05);*/
1782         IS("erasable", atp->desc.erasable);
1783         if (atp->desc.erasable)
1784                 sub_type = cdrw_subtypes[atp->desc.sub_type];
1785         else
1786                 sub_type = cdr_subtypes[atp->desc.sub_type];
1787         if (atp->desc.sub_type)
1788                 printf("  Disk sub type: %s (%d)\n", sub_type, atp->desc.sub_type);
1789         printf("  ATIP start of lead in:  %ld (%02d:%02d/%02d)\n",
1790                 msf_to_lba(atp->desc.lead_in[1],
1791                 atp->desc.lead_in[2],
1792                 atp->desc.lead_in[3], FALSE),
1793                 atp->desc.lead_in[1],
1794                 atp->desc.lead_in[2],
1795                 atp->desc.lead_in[3]);
1796         printf("  ATIP start of lead out: %ld (%02d:%02d/%02d)\n",
1797                 msf_to_lba(atp->desc.lead_out[1],
1798                 atp->desc.lead_out[2],
1799                 atp->desc.lead_out[3], TRUE),
1800                 atp->desc.lead_out[1],
1801                 atp->desc.lead_out[2],
1802                 atp->desc.lead_out[3]);
1803         if (atp->desc.a1_v) {
1804                 if (atp->desc.erasable && atp->desc.sub_type == 1) {
1805                         speedvtab = hs_clv_to_speed;
1806                 }
1807                 if (atp->desc.a2_v && (atp->desc.sub_type == 2 || atp->desc.sub_type == 3)) {
1808                         speedvtab = us_clv_to_speed;
1809                 }
1810                 if (atp->desc.clv_low != 0 || atp->desc.clv_high != 0) {
1811                         atip_printspeed("  1T speed low",
1812                                 atp->desc.clv_low, speedvtab);
1813                         atip_printspeed(" 1T speed high",
1814                                 atp->desc.clv_high, speedvtab);
1815                         printf("\n");
1816                 }
1817         }
1818         if (atp->desc.a2_v) {
1819                 Uint    vlow;
1820                 Uint    vhigh;
1821
1822                 vlow = (atp->desc.a2[0] >> 4) & 0x07;
1823                 vhigh = atp->desc.a2[0] & 0x0F;
1824
1825                 if (vlow != 0 || vhigh != 0) {
1826                         atip_printspeed("  2T speed low",
1827                                         vlow, speedvtab);
1828                         atip_printspeed(" 2T speed high",
1829                                         vhigh, speedvtab);
1830                         printf("\n");
1831                 }
1832         }
1833         if (atp->desc.a1_v) {
1834                 printf("  power mult factor: %d %d\n", atp->desc.power_mult, atp->desc.tgt_y_pow);
1835                 if (atp->desc.erasable)
1836                         printf("  recommended erase/write power: %d\n", atp->desc.rerase_pwr_ratio);
1837         }
1838         if (atp->desc.a1_v) {
1839                 printf("  A1 values: %02X %02X %02X\n",
1840                                 (&atp->desc.res15)[1],
1841                                 (&atp->desc.res15)[2],
1842                                 (&atp->desc.res15)[3]);
1843         }
1844         if (atp->desc.a2_v) {
1845                 printf("  A2 values: %02X %02X %02X\n",
1846                                 atp->desc.a2[0],
1847                                 atp->desc.a2[1],
1848                                 atp->desc.a2[2]);
1849         }
1850         if (atp->desc.a3_v) {
1851                 printf("  A3 values: %02X %02X %02X\n",
1852                                 atp->desc.a3[0],
1853                                 atp->desc.a3[1],
1854                                 atp->desc.a3[2]);
1855         }
1856 }
1857 #endif  /* PRINT_ATIP */
1858
1859 static int 
1860 speed_select_mmc(SCSI *usalp, cdr_t *dp, int *speedp)
1861 {
1862         Uchar   mode[0x100];
1863         Uchar   moder[0x100];
1864         int     len;
1865         struct  cd_mode_page_05 *mp;
1866         struct  ricoh_mode_page_30 *rp = NULL;
1867         int     val;
1868         BOOL    forcespeed = FALSE;
1869         BOOL    dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
1870
1871         if (speedp)
1872                 curspeed = *speedp;
1873
1874         /*
1875          * Do not reset mp->test_write (-dummy) here.
1876          */
1877         deflt_writemodes_mmc(usalp, FALSE);
1878
1879         fillbytes((caddr_t)mode, sizeof (mode), '\0');
1880
1881         if (!get_mode_params(usalp, 0x05, "CD write parameter",
1882                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
1883                 return (-1);
1884         if (len == 0)
1885                 return (-1);
1886
1887         mp = (struct cd_mode_page_05 *)
1888                 (mode + sizeof (struct scsi_mode_header) +
1889                 ((struct scsi_mode_header *)mode)->blockdesc_len);
1890 #ifdef  DEBUG
1891         usal_prbytes("CD write parameter:", (Uchar *)mode, len);
1892 #endif
1893
1894     if(dummy) {
1895         mp->test_write = 1;
1896         /* but it does not work on DVD+RW and -RAM, also bail out on other
1897          * types that have not been tested yet */
1898         int profile=get_curprofile(usalp);
1899         switch(profile) {
1900             case(0x12):
1901             case(0x1a):
1902             case(0x2a):
1903             case(0x43):
1904             case(0x52):
1905                 {
1906                     fprintf(stderr, 
1907                             "Dummy mode not possible with %s.\n",
1908                             mmc_obtain_profile_name(profile) );
1909                     exit(EXIT_FAILURE);
1910                 }
1911         }
1912     }
1913     else
1914         mp->test_write = 0;
1915
1916 #ifdef  DEBUG
1917         usal_prbytes("CD write parameter:", (Uchar *)mode, len);
1918 #endif
1919         if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1))
1920                 return (-1);
1921
1922         /*
1923          * Neither set nor get speed.
1924          */
1925         if (speedp == 0)
1926                 return (0);
1927
1928
1929         rp = get_justlink_ricoh(usalp, moder);
1930         if (mmc_isyamaha(usalp)) {
1931                 forcespeed = FALSE;
1932         } else if (mmc_isplextor(usalp) && (dp->cdr_flags & CDR_FORCESPEED) != 0) {
1933                 int     pwr;
1934
1935                 pwr = check_powerrec_plextor(usalp);
1936                 if (pwr >= 0)
1937                         forcespeed = (pwr == 0);
1938         } else if ((dp->cdr_flags & CDR_FORCESPEED) != 0) {
1939                 forcespeed = rp && rp->AWSCD != 0;
1940         }
1941
1942         if (lverbose && (dp->cdr_flags & CDR_FORCESPEED) != 0)
1943                 printf("Forcespeed is %s.\n", forcespeed?"ON":"OFF");
1944
1945         if (!forcespeed && (dp->cdr_dstat->ds_cdrflags & RF_FORCESPEED) != 0) {
1946                 printf("Turning forcespeed on\n");
1947                 forcespeed = TRUE;
1948         }
1949         if (forcespeed && (dp->cdr_dstat->ds_cdrflags & RF_FORCESPEED) == 0) {
1950                 printf("Turning forcespeed off\n");
1951                 forcespeed = FALSE;
1952         }
1953         if (mmc_isplextor(usalp) && (dp->cdr_flags & CDR_FORCESPEED) != 0) {
1954                 powerrec_plextor(usalp, !forcespeed);
1955         }
1956         if (!mmc_isyamaha(usalp) && (dp->cdr_flags & CDR_FORCESPEED) != 0) {
1957
1958                 if (rp) {
1959                         rp->AWSCD = forcespeed?1:0;
1960                         set_mode_params(usalp, "Ricoh Vendor Page", moder, moder[0]+1, 0, -1);
1961                         rp = get_justlink_ricoh(usalp, moder);
1962                 }
1963         }
1964
1965         /*
1966          * 44100 * 2 * 2 =  176400 bytes/s
1967          *
1968          * The right formula would be:
1969          * tmp = (((long)curspeed) * 1764) / 10;
1970          *
1971          * But the standard is rounding the wrong way.
1972          * Furtunately rounding down is guaranteed.
1973          */
1974         val = curspeed*177;
1975         if (val > 0xFFFF)
1976                 val = 0xFFFF;
1977         if (mmc_isyamaha(usalp) && forcespeed) {
1978                 if (force_speed_yamaha(usalp, -1, val) < 0)
1979                         return (-1);
1980         } else if (mmc_set_speed(usalp, -1, val, ROTCTL_CLV) < 0) {
1981                 return (-1);
1982         }
1983
1984         if (scsi_get_speed(usalp, 0, &val) >= 0) {
1985                 if (val > 0) {
1986                         fprintf(stderr, "Speed set to %d KB/s\n", val); 
1987                         curspeed = val / 176;
1988                         *speedp = curspeed;
1989                 }
1990         }
1991         return (0);
1992 }
1993
1994 /*
1995  * Some drives do not round up when writespeed is e.g. 1 and
1996  * the minimum write speed of the drive is higher. Try to increment
1997  * the write speed unti it gets accepted by the drive.
1998  */
1999 static int 
2000 mmc_set_speed(SCSI *usalp, int readspeed, int writespeed, int rotctl)
2001 {
2002         int     rs;
2003         int     ws;
2004         int     ret = -1;
2005         int     c;
2006         int     k;
2007
2008         if (scsi_get_speed(usalp, &rs, &ws) >= 0) {
2009                 if (readspeed < 0)
2010                         readspeed = rs;
2011                 if (writespeed < 0)
2012                         writespeed = ws;
2013         }
2014         if (writespeed < 0 || writespeed > 0xFFFF)
2015                 return (ret);
2016
2017         usalp->silent++;
2018         while (writespeed <= 0xFFFF) {
2019                 ret = scsi_set_speed(usalp, readspeed, writespeed, rotctl);
2020                 if (ret >= 0)
2021                         break;
2022                 c = usal_sense_code(usalp);
2023                 k = usal_sense_key(usalp);
2024                 /*
2025                  * Abort quickly if it does not make sense to repeat.
2026                  * 0x24 == Invalid field in cdb
2027                  * 0x24 means illegal speed.
2028                  */
2029                 if ((k != SC_ILLEGAL_REQUEST) || (c != 0x24)) {
2030                         if (usalp->silent <= 1)
2031                                 usal_printerr(usalp);
2032                         usalp->silent--;
2033                         return (-1);
2034                 }
2035                 writespeed += 177;
2036         }
2037         if (ret < 0 && usalp->silent <= 1)
2038                 usal_printerr(usalp);
2039         usalp->silent--;
2040
2041         return (ret);
2042 }
2043
2044 static int 
2045 speed_select_mdvd(SCSI *usalp, cdr_t *dp, int *speedp)
2046 {
2047   int retcode;
2048   char perf_desc[28];
2049   int write_speed = *speedp * 1385;
2050    
2051   /* For the moment we just divide the CD speed by 7*/
2052
2053   if(speedp!=NULL)
2054      (*speedp)=(*speedp)*8;
2055   
2056   memset(perf_desc, 0, sizeof(perf_desc));
2057
2058   /* Write Rotation Control = ROTCTL_CLV 
2059    * | Restore Logical Unit Defaults = 0 
2060    * | Exact = 0 
2061    * | Random Access = 0) 
2062    */
2063   perf_desc[0]= ROTCTL_CLV << 3 | 0 << 2 | 0 << 1 | 0; 
2064   /* Start LBA to 0 */
2065   perf_desc[4] = 0;
2066   perf_desc[5] = 0;
2067   perf_desc[6] = 0;
2068   perf_desc[7] = 0;
2069   /* End LBA set to 0 (setting to 0xffffffff failed on my LG burner
2070    */
2071   perf_desc[8] = 0;
2072   perf_desc[9] = 0;
2073   perf_desc[10] = 0;
2074   perf_desc[11] = 0;
2075   /* Read Speed = 0xFFFF */
2076   perf_desc[12] = 0;
2077   perf_desc[13] = 0;
2078   perf_desc[14] = 0xFF;
2079   perf_desc[15] = 0xFF;
2080   /* Read Time = 1s */
2081   perf_desc[18] = 1000 >> 8;
2082   perf_desc[19] = 1000 & 0xFF;   
2083   /* Write Speed */
2084   perf_desc[20] = write_speed >> 24;
2085   perf_desc[21] = write_speed >> 16 & 0xFF;
2086   perf_desc[22] = write_speed >> 8 & 0xFF;
2087   perf_desc[23] = write_speed & 0xFF;
2088   /* Write Time = 1s */
2089   perf_desc[26] = 1000 >> 8;
2090   perf_desc[27] = 1000 & 0xFF;  
2091   
2092   /* retcode = scsi_set_streaming(usalp, NULL, 0); */
2093   retcode = scsi_set_streaming(usalp, perf_desc, sizeof(perf_desc));
2094   if (retcode == -1) return retcode;
2095   retcode = speed_select_mmc(usalp, dp, speedp);
2096   if(speedp!=NULL)
2097      (*speedp)=(*speedp)/7;
2098    return retcode;
2099 }
2100
2101 static int 
2102 next_wr_addr_mmc(SCSI *usalp, track_t *trackp, long *ap)
2103 {
2104         struct  track_info      track_info;
2105         long    next_addr;
2106         int     result = -1;
2107
2108
2109         /*
2110          * Reading info for current track may require doing the read_track_info
2111          * with either the track number (if the track is currently being written)
2112          * or with 0xFF (if the track hasn't been started yet and is invisible
2113          */
2114
2115         if (trackp != 0 && trackp->track > 0 && is_packet(trackp)) {
2116                 usalp->silent++;
2117                 result = read_track_info(usalp, (caddr_t)&track_info, TI_TYPE_TRACK,
2118                                                         trackp->trackno,
2119                                                         sizeof (track_info));
2120                 usalp->silent--;
2121         }
2122
2123         if (result < 0) {
2124                 if (read_track_info(usalp, (caddr_t)&track_info, TI_TYPE_TRACK, 0xFF,
2125                                                 sizeof (track_info)) < 0) {
2126                         errmsgno(EX_BAD, "Cannot get next writable address for 'invisible' track.\n");
2127                         errmsgno(EX_BAD, "This means that we are checking recorded media.\n");
2128                         errmsgno(EX_BAD, "This media cannot be written in streaming mode anymore.\n");
2129                         errmsgno(EX_BAD, "If you like to write to 'preformatted' RW media, try to blank the media first.\n");
2130                         return (-1);
2131                 }
2132         }
2133         if (usalp->verbose)
2134                 usal_prbytes("track info:", (Uchar *)&track_info,
2135                                 sizeof (track_info)-usal_getresid(usalp));
2136         next_addr = a_to_4_byte(track_info.next_writable_addr);
2137         if (ap)
2138                 *ap = next_addr;
2139         return (0);
2140 }
2141
2142 static int 
2143 write_leadin_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
2144 {
2145         Uint    i;
2146         long    startsec = 0L;
2147
2148 /*      if (flags & F_SAO) {*/
2149         if (wm_base(dp->cdr_dstat->ds_wrmode) == WM_SAO) {
2150                 if (debug || lverbose) {
2151                         printf("Sending CUE sheet...\n");
2152                         flush();
2153                 }
2154                 if ((*dp->cdr_send_cue)(usalp, dp, trackp) < 0) {
2155                         errmsgno(EX_BAD, "Cannot send CUE sheet.\n");
2156                         return (-1);
2157                 }
2158
2159                 (*dp->cdr_next_wr_address)(usalp, &trackp[0], &startsec);
2160                 if (trackp[0].flags & TI_TEXT) {
2161                         startsec = dp->cdr_dstat->ds_first_leadin;
2162                         printf("SAO startsec: %ld\n", startsec);
2163                 } else if (startsec <= 0 && startsec != -150) {
2164                         if(lverbose>2)
2165                                 fprintf(stderr, "WARNING: Drive returns wrong startsec (%ld) using -150\n",
2166                                         startsec);
2167                         startsec = -150;
2168                 }
2169                 if (debug)
2170                         printf("SAO startsec: %ld\n", startsec);
2171
2172                 if (trackp[0].flags & TI_TEXT) {
2173                         if (startsec > 0) {
2174                                 errmsgno(EX_BAD, "CD-Text must be in first session.\n");
2175                                 return (-1);
2176                         }
2177                         if (debug || lverbose)
2178                                 printf("Writing lead-in...\n");
2179                         if (write_cdtext(usalp, dp, startsec) < 0)
2180                                 return (-1);
2181
2182                         dp->cdr_dstat->ds_cdrflags |= RF_LEADIN;
2183                 } else for (i = 1; i <= trackp->tracks; i++) {
2184                         trackp[i].trackstart += startsec +150;
2185                 }
2186 #ifdef  XXX
2187                 if (debug || lverbose)
2188                         printf("Writing lead-in...\n");
2189
2190                 pad_track(usalp, dp, &trackp[1], -150, (Llong)0,
2191                                         FALSE, 0);
2192 #endif
2193         }
2194 /*      if (flags & F_RAW) {*/
2195     if (wm_base(dp->cdr_dstat->ds_wrmode) == WM_RAW) {
2196         /*
2197                  * In RAW write mode, we now write the lead in (TOC).
2198                  */
2199                 (*dp->cdr_next_wr_address)(usalp, &trackp[0], &startsec);
2200                 if (startsec > -4500) {
2201                         /*
2202                          * There must be at least 1 minute lead-in.
2203                          */
2204                         errmsgno(EX_BAD, "WARNING: Drive returns wrong startsec (%ld) using %ld from ATIP\n",
2205                                         startsec, (long)dp->cdr_dstat->ds_first_leadin);
2206                         startsec = dp->cdr_dstat->ds_first_leadin;
2207                 }
2208                 if (startsec > -4500) {
2209                         errmsgno(EX_BAD, "Illegal startsec (%ld)\n", startsec);
2210                         return (-1);
2211                 }
2212                 if (debug || lverbose)
2213                         printf("Writing lead-in at sector %ld\n", startsec);
2214                 if (write_leadin(usalp, dp, trackp, startsec) < 0)
2215                         return (-1);
2216                 dp->cdr_dstat->ds_cdrflags |= RF_LEADIN;
2217         }
2218         return (0);
2219 }
2220
2221 int     st2mode[] = {
2222         0,              /* 0                    */
2223         TM_DATA,        /* 1 ST_ROM_MODE1       */
2224         TM_DATA,        /* 2 ST_ROM_MODE2       */
2225         0,              /* 3                    */
2226         0,              /* 4 ST_AUDIO_NOPRE     */
2227         TM_PREEM,       /* 5 ST_AUDIO_PRE       */
2228         0,              /* 6                    */
2229         0,              /* 7                    */
2230 };
2231
2232 static int 
2233 next_wr_addr_mdvd(SCSI *usalp, track_t *trackp, long *ap)
2234 {
2235         int     track=0;
2236         struct  track_info      track_info;
2237         long    next_addr;
2238         int     result = -1;
2239         struct  disk_info disk_info;
2240         if (trackp){
2241             track = trackp->trackno;
2242         }
2243
2244         if (trackp != 0 && track > 0 && is_packet(trackp)) {
2245                 usalp->silent++;
2246                 result = read_track_info(usalp, (caddr_t)&track_info, TI_TYPE_SESS, track, sizeof(track_info));
2247                 usalp->silent--;
2248                 if (scsi_in_progress(usalp)){
2249                   return -1;
2250                 }
2251                 
2252         }
2253
2254         if (result < 0) {
2255           /* Get the last rzone*/
2256                 if(read_disk_info(usalp,(caddr_t)&disk_info,8)<0)
2257                   return (-1);
2258              
2259                 /* if (read_track_info(usalp, (caddr_t)&track_info, TI_TYPE_SESS, 0xFF, sizeof(track_info)) < 0) */
2260                     if (read_rzone_info(usalp, (caddr_t)&track_info, sizeof(track_info)) < 0)
2261                         return (-1);
2262         }
2263         if (usalp->verbose)
2264                 usal_prbytes("track info:", (Uchar *)&track_info,
2265                                 sizeof(track_info)-usal_getresid(usalp));
2266         next_addr = a_to_4_byte(track_info.next_writable_addr);
2267         if (ap)
2268                 *ap = next_addr;
2269         return (0);
2270 }
2271
2272 static int 
2273 open_track_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
2274 {
2275         Uchar   mode[0x100];
2276         int     len;
2277         struct  cd_mode_page_05 *mp;
2278
2279         if (!is_tao(trackp) && !is_packet(trackp)) {
2280                 if (trackp->pregapsize > 0 && (trackp->flags & TI_PREGAP) == 0) {
2281                         if (lverbose) {
2282                                 printf("Writing pregap for track %d at %ld\n",
2283                                         (int)trackp->trackno,
2284                                         trackp->trackstart-trackp->pregapsize);
2285                         }
2286                         /*
2287                          * XXX Do we need to check isecsize too?
2288                          */
2289                         pad_track(usalp, dp, trackp,
2290                                 trackp->trackstart-trackp->pregapsize,
2291                                 (Llong)trackp->pregapsize*trackp->secsize,
2292                                         FALSE, 0);
2293                 }
2294                 return (0);
2295         }
2296
2297         fillbytes((caddr_t)mode, sizeof (mode), '\0');
2298
2299         if (!get_mode_params(usalp, 0x05, "CD write parameter",
2300                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
2301                 return (-1);
2302         if (len == 0)
2303                 return (-1);
2304
2305         mp = (struct cd_mode_page_05 *)
2306                 (mode + sizeof (struct scsi_mode_header) +
2307                 ((struct scsi_mode_header *)mode)->blockdesc_len);
2308
2309
2310 /*      mp->track_mode = ???;*/
2311         mp->track_mode = st2mode[trackp->sectype & ST_MASK];
2312 /*      mp->copy = ???;*/
2313         mp->dbtype = trackp->dbtype;
2314
2315 /*i_to_short(mp->audio_pause_len, 300);*/
2316 /*i_to_short(mp->audio_pause_len, 150);*/
2317 /*i_to_short(mp->audio_pause_len, 0);*/
2318
2319         if (is_packet(trackp)) {
2320                 mp->write_type = WT_PACKET;
2321                 mp->track_mode |= TM_INCREMENTAL;
2322                 mp->fp = (trackp->pktsize > 0) ? 1 : 0;
2323                 i_to_4_byte(mp->packet_size, trackp->pktsize);
2324         } else if (is_tao(trackp)) {
2325                 mp->write_type = WT_TAO;
2326                 mp->fp = 0;
2327                 i_to_4_byte(mp->packet_size, 0);
2328         } else {
2329                 errmsgno(EX_BAD, "Unknown write mode.\n");
2330                 return (-1);
2331         }
2332         if (trackp->isrc) {
2333                 mp->ISRC[0] = 0x80;     /* Set ISRC valid */
2334                 strncpy((char *)&mp->ISRC[1], trackp->isrc, 12);
2335
2336         } else {
2337                 fillbytes(&mp->ISRC[0], sizeof (mp->ISRC), '\0');
2338         }
2339
2340 #ifdef  DEBUG
2341         usal_prbytes("CD write parameter:", (Uchar *)mode, len);
2342 #endif
2343         if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, trackp->secsize))
2344                 return (-1);
2345
2346         return (0);
2347 }
2348
2349 static int 
2350 open_track_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp)
2351 {
2352         Uchar   mode[0x100];
2353         int     len;
2354         struct  cd_mode_page_05 *mp;
2355
2356         if (is_packet(trackp)) {
2357                fillbytes((caddr_t)mode, sizeof(mode), '\0');
2358           
2359                if (!get_mode_params(usalp, 0x05, "DVD write parameter",
2360                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
2361                       return (-1);
2362                if (len == 0)
2363                       return (-1);
2364
2365                 mp = (struct cd_mode_page_05 *)
2366                       (mode + sizeof(struct scsi_mode_header) +
2367                       ((struct scsi_mode_header *)mode)->blockdesc_len);
2368
2369                 mp->write_type = WT_PACKET;
2370                 mp->LS_V = 1;
2371                 /*For now we set the link size to 0x10(32k) because Pioneer-A03 only support this */
2372                 mp->link_size=0x10;
2373                 mp->fp = 1;
2374                 i_to_4_byte(mp->packet_size, trackp->pktsize);
2375         } else {
2376              return 0;
2377         }
2378  
2379         if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, trackp->secsize))
2380                 return (-1);
2381
2382         return (0);
2383 }
2384
2385 static int 
2386 close_track_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
2387 {
2388         int     ret;
2389
2390         if (!is_tao(trackp) && !is_packet(trackp))
2391                 return (0);
2392
2393         if (scsi_flush_cache(usalp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) {
2394                 printf("Trouble flushing the cache\n");
2395                 return (-1);
2396         }
2397         wait_unit_ready(usalp, 300);            /* XXX Wait for ATAPI */
2398         if (is_packet(trackp) && !is_noclose(trackp)) {
2399                         /* close the incomplete track */
2400                 ret = scsi_close_tr_session(usalp, CL_TYPE_TRACK, 0xFF,
2401                                 (dp->cdr_cmdflags&F_IMMED) != 0);
2402                 wait_unit_ready(usalp, 300);    /* XXX Wait for ATAPI */
2403                 return (ret);
2404         }
2405         return (0);
2406 }
2407
2408 static int 
2409 close_track_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp)
2410 {
2411         int     ret;
2412         if (!is_packet(trackp))
2413              return (0);
2414
2415         if (scsi_flush_cache(usalp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) {
2416                 printf("Trouble flushing the cache\n");
2417                 return -1;
2418         }
2419         wait_unit_ready(usalp, 300);            /* XXX Wait for ATAPI */
2420         if (is_packet(trackp) && !is_noclose(trackp)) {
2421                         /* close the incomplete track */
2422                 ret = scsi_close_tr_session(usalp, 1, 0xFF, (dp->cdr_cmdflags&F_IMMED) != 0);
2423                 wait_unit_ready(usalp, 300);    /* XXX Wait for ATAPI */
2424                 return (ret);
2425         }
2426         return (0);
2427 }
2428
2429 int     toc2sess[] = {
2430         SES_DA_ROM,     /* CD-DA                 */
2431         SES_DA_ROM,     /* CD-ROM                */
2432         SES_XA,         /* CD-ROM XA mode 1      */
2433         SES_XA,         /* CD-ROM XA MODE 2      */
2434         SES_CDI,        /* CDI                   */
2435         SES_DA_ROM,     /* Invalid - use default */
2436         SES_DA_ROM,     /* Invalid - use default */
2437 };
2438
2439 static int 
2440 open_session_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
2441 {
2442         Uchar   mode[0x100];
2443         int     len;
2444         struct  cd_mode_page_05 *mp;
2445
2446         fillbytes((caddr_t)mode, sizeof (mode), '\0');
2447
2448         if (!get_mode_params(usalp, 0x05, "CD write parameter",
2449                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
2450                 return (-1);
2451         if (len == 0)
2452                 return (-1);
2453
2454         mp = (struct cd_mode_page_05 *)
2455                 (mode + sizeof (struct scsi_mode_header) +
2456                 ((struct scsi_mode_header *)mode)->blockdesc_len);
2457
2458         mp->write_type = WT_TAO; /* fix to allow DAO later */
2459         /*
2460          * We need to set the right dbtype here because Sony drives
2461          * don't like multi session in to be set with DB_ROM_MODE1
2462          * which is set by us at the beginning as default as some drives
2463          * have illegal default values.
2464          */
2465         mp->track_mode = st2mode[trackp[0].sectype & ST_MASK];
2466         mp->dbtype = trackp[0].dbtype;
2467
2468         if (!is_tao(trackp) && !is_packet(trackp)) {
2469                 mp->write_type = WT_SAO;
2470                 if (dp->cdr_dstat->ds_cdrflags & RF_AUDIOMASTER)
2471                         mp->write_type = 8;
2472                 mp->track_mode = 0;
2473                 mp->dbtype = DB_RAW;
2474         }
2475         if (is_raw(trackp)) {
2476                 mp->write_type = WT_RAW;
2477                 mp->track_mode = 0;
2478
2479                 if (is_raw16(trackp)) {
2480                         mp->dbtype = DB_RAW_PQ;
2481                 } else if (is_raw96r(trackp)) {
2482                         mp->dbtype = DB_RAW_PW_R;
2483                 } else {
2484                         mp->dbtype = DB_RAW_PW;
2485                 }
2486         }
2487
2488         mp->multi_session = (track_base(trackp)->tracktype & TOCF_MULTI) ?
2489                                 MS_MULTI : MS_NONE;
2490         mp->session_format = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
2491
2492         if (trackp->isrc) {
2493                 mp->media_cat_number[0] = 0x80; /* Set MCN valid */
2494                 strncpy((char *)&mp->media_cat_number[1], trackp->isrc, 13);
2495
2496         } else {
2497                 fillbytes(&mp->media_cat_number[0], sizeof (mp->media_cat_number), '\0');
2498         }
2499 #ifdef  DEBUG
2500         usal_prbytes("CD write parameter:", (Uchar *)mode, len);
2501 #endif
2502         if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1))
2503                 return (-1);
2504
2505         return (0);
2506 }
2507
2508 static int 
2509 open_session_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp)
2510 {
2511         Uchar   mode[0x100];
2512         int     tracks = trackp->tracks;
2513
2514         int     len;
2515         struct  cd_mode_page_05 *mp;
2516         Ulong totalsize;
2517         int i;
2518         int profile;
2519
2520         fillbytes((caddr_t)mode, sizeof(mode), '\0');
2521
2522         if (!get_mode_params(usalp, 0x05, "DVD write parameter",
2523                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
2524                 return (-1);
2525         if (len == 0)
2526                 return (-1);
2527
2528         mp = (struct cd_mode_page_05 *)
2529                 (mode + sizeof(struct scsi_mode_header) +
2530                 ((struct scsi_mode_header *)mode)->blockdesc_len);
2531         if(is_packet(trackp)){
2532           mp->write_type=WT_PACKET;
2533           mp->fp=0;
2534           mp->BUFE=1;
2535           mp->track_mode=1;
2536         }else{
2537           mp->write_type = WT_SAO; 
2538         }
2539
2540         mp->multi_session = (track_base(trackp)->tracktype & TOCF_MULTI) ?
2541                                 MS_MULTI : MS_NONE;
2542         mp->session_format = toc2sess[track_base(trackp)->tracktype & TOC_MASK];
2543
2544         /* Enable Burnfree by default, allow to disable. XXX Sucks, duplicated functionality. */
2545         if (dp->cdr_cdcap->BUF != 0) {
2546                 if (lverbose > 2)
2547                         fprintf(stderr, 
2548                                         "BURN-Free is %s.\n"
2549                                         "Turning BURN-Free on\n",
2550                                         mp->BUFE?"ON":"OFF");
2551                 mp->BUFE = 1;
2552         }
2553         if (driveropts != NULL) {
2554                 if ((strcmp(driveropts, "noburnproof") == 0 ||
2555                                         strcmp(driveropts, "noburnfree") == 0)) {
2556                         if(lverbose>1)
2557                                 fprintf(stderr, "Turning BURN-Free off\n");
2558                         mp->BUFE = 0;
2559                 }
2560                 else if ((strcmp(driveropts, "burnproof") == 0 ||
2561                                         strcmp(driveropts, "burnfree") == 0)) {
2562                         /* a NOP, we enable burnfree by default */
2563                         if(lverbose>2)
2564                                 fprintf(stderr, "Found burnproof/burnfree in driveropts, those options are enabled by default now.");
2565                 }
2566                 else if (strcmp(driveropts, "help") == 0) {
2567                         mmc_opthelp(dp, 0);
2568                 } 
2569                 else {
2570                         errmsgno(EX_BAD, "Bad driver opts '%s'.\n", driveropts);
2571                         mmc_opthelp(dp, EX_BAD);
2572                 }
2573         }
2574
2575
2576         if (!set_mode_params(usalp, "DVD write parameter", mode, len, 0, -1))
2577                 return (-1);
2578
2579                 
2580         totalsize=0;
2581         for(i=1;i<=tracks;i++) {
2582           totalsize+=trackp[i].tracksecs;
2583         }
2584        
2585         profile = get_curprofile(usalp);
2586         if(!is_packet(trackp) && profile != 0x1A){
2587           /* in DAO mode we need to reserve space for the track*/
2588           if(reserve_track(usalp, totalsize)<0)
2589             return (-1);
2590           }
2591         return (0);
2592 }
2593
2594 static int 
2595 waitfix_mmc(SCSI *usalp, int secs)
2596 {
2597         char    dibuf[16];
2598         int     i;
2599         int     key;
2600 #define W_SLEEP 2
2601
2602         usalp->silent++;
2603         for (i = 0; i < secs/W_SLEEP; i++) {
2604                 if (read_disk_info(usalp, dibuf, sizeof (dibuf)) >= 0) {
2605                         usalp->silent--;
2606                         return (0);
2607                 }
2608                 key = usal_sense_key(usalp);
2609                 if (key != SC_UNIT_ATTENTION && key != SC_NOT_READY)
2610                         break;
2611                 sleep(W_SLEEP);
2612         }
2613         usalp->silent--;
2614         return (-1);
2615 #undef  W_SLEEP
2616 }
2617
2618 static int 
2619 fixate_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
2620 {
2621         int     ret = 0;
2622         int     key = 0;
2623         int     code = 0;
2624         struct timeval starttime;
2625         struct timeval stoptime;
2626         int     dummy = (track_base(trackp)->tracktype & TOCF_DUMMY) != 0;
2627
2628         if(debug)
2629                  printf("fixate_mmc\n");
2630         starttime.tv_sec = 0;
2631         starttime.tv_usec = 0;
2632         stoptime = starttime;
2633         gettimeofday(&starttime, (struct timezone *)0);
2634
2635         if (dummy && lverbose)
2636                 printf("WARNING: Some drives don't like fixation in dummy mode.\n");
2637
2638         usalp->silent++;
2639         if(debug)
2640                  printf("is_tao: %d,is_packet: %d\n", is_tao(trackp), is_packet(trackp));
2641         if (is_tao(trackp) || is_packet(trackp)) {
2642                 ret = scsi_close_tr_session(usalp, CL_TYPE_SESSION, 0,
2643                                 (dp->cdr_cmdflags&F_IMMED) != 0);
2644         } else {
2645                 if (scsi_flush_cache(usalp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) {
2646                         if (!scsi_in_progress(usalp))
2647                                 printf("Trouble flushing the cache\n");
2648                 }
2649         }
2650         usalp->silent--;
2651         key = usal_sense_key(usalp);
2652         code = usal_sense_code(usalp);
2653
2654         usalp->silent++;
2655         if (debug && !unit_ready(usalp)) {
2656                 fprintf(stderr, "Early return from fixating. Ret: %d Key: %d, Code: %d\n", ret, key, code);
2657         }
2658         usalp->silent--;
2659
2660         if (ret >= 0) {
2661                 wait_unit_ready(usalp, 420/curspeed);   /* XXX Wait for ATAPI */
2662                 waitfix_mmc(usalp, 420/curspeed);       /* XXX Wait for ATAPI */
2663                 return (ret);
2664         }
2665
2666         if ((dummy != 0 && (key != SC_ILLEGAL_REQUEST)) ||
2667                 /*
2668                  * Try to suppress messages from drives that don't like fixation
2669                  * in -dummy mode.
2670                  */
2671                 ((dummy == 0) &&
2672                 (((key != SC_UNIT_ATTENTION) && (key != SC_NOT_READY)) ||
2673                                 ((code != 0x2E) && (code != 0x04))))) {
2674                 /*
2675                  * UNIT ATTENTION/2E seems to be a magic for old Mitsumi ATAPI drives
2676                  * NOT READY/ code 4 qual 7 (logical unit not ready, operation in progress)
2677                  * seems to be a magic for newer Mitsumi ATAPI drives
2678                  * NOT READY/ code 4 qual 8 (logical unit not ready, long write in progress)
2679                  * seems to be a magic for SONY drives
2680                  * when returning early from fixating.
2681                  * Try to supress the error message in this case to make
2682                  * simple minded users less confused.
2683                  */
2684                 usal_printerr(usalp);
2685                 usal_printresult(usalp);        /* XXX restore key/code in future */
2686         }
2687
2688         if (debug && !unit_ready(usalp)) {
2689                 fprintf(stderr, "Early return from fixating. Ret: %d Key: %d, Code: %d\n", ret, key, code);
2690         }
2691
2692         wait_unit_ready(usalp, 420);     /* XXX Wait for ATAPI */
2693         waitfix_mmc(usalp, 420/curspeed); /* XXX Wait for ATAPI */
2694
2695         if (!dummy &&
2696                 (ret >= 0 || (key == SC_UNIT_ATTENTION && code == 0x2E))) {
2697                 /*
2698                  * Some ATAPI drives (e.g. Mitsumi) imply the
2699                  * IMMED bit in the SCSI cdb. As there seems to be no
2700                  * way to properly check for the real end of the
2701                  * fixating process we wait for the expected time.
2702                  */
2703                 gettimeofday(&stoptime, (struct timezone *)0);
2704                 timevaldiff(&starttime, &stoptime);
2705                 if (stoptime.tv_sec < (220 / curspeed)) {
2706                         unsigned secs;
2707
2708                         if (lverbose) {
2709                                 printf("Actual fixating time: %ld seconds\n",
2710                                                         (long)stoptime.tv_sec);
2711                         }
2712                         secs = (280 / curspeed) - stoptime.tv_sec;
2713                         if (lverbose) {
2714                                 printf("ATAPI early return: sleeping %d seconds.\n",
2715                                                                 secs);
2716                         }
2717                         sleep(secs);
2718                 }
2719         }
2720         return (ret);
2721 }
2722
2723 static int 
2724 fixate_mdvd(SCSI *usalp, cdr_t *dp, track_t *trackp)
2725 {
2726         int ret;
2727         if (scsi_flush_cache(usalp, (dp->cdr_cmdflags&F_IMMED) != 0) < 0) {
2728                 printf("Trouble flushing the cache\n");
2729                 return -1;
2730         }
2731         wait_unit_ready(usalp, 300);            /* XXX Wait for ATAPI */
2732       /*set a really BIG timeout and call fixate_mmc
2733          The BIG timeout is needed in case there was a very short rzone to write at the 
2734          beginning of the disk, because lead-out needs to be at some distance.
2735       */
2736         if(debug)
2737                 printf("fixate_mdvd\n");
2738       usal_settimeout(usalp, 1000);
2739       if(is_packet(trackp) || dp->profile == 0x1B){
2740           scsi_close_tr_session(usalp, CL_TYPE_SESSION, 0, FALSE);
2741       }
2742       ret = fixate_mmc(usalp, dp, trackp);
2743       if (dp->profile == 0x2B) {
2744           scsi_close_tr_session(usalp, CL_TYPE_OPEN_SESSION, 0, FALSE);
2745           scsi_close_tr_session(usalp, CL_TYPE_FINALISE_MINRAD, 0, FALSE);
2746       }
2747       usal_settimeout(usalp, 200);
2748
2749       return ret;
2750 }
2751
2752 char    *blank_types[] = {
2753         "entire disk",
2754         "PMA, TOC, pregap",
2755         "incomplete track",
2756         "reserved track",
2757         "tail of track",
2758         "closing of last session",
2759         "last session",
2760         "reserved blanking type",
2761 };
2762
2763 char    *format_types[] = {
2764         "full format",
2765         "background format",
2766         "forced format",
2767 };
2768
2769 static int 
2770 blank_mmc(SCSI *usalp, cdr_t *dp, long addr, int blanktype)
2771 {
2772         BOOL    cdrr     = FALSE;       /* Read CD-R    */
2773         BOOL    cdwr     = FALSE;       /* Write CD-R   */
2774         BOOL    cdrrw    = FALSE;       /* Read CD-RW   */
2775         BOOL    cdwrw    = FALSE;       /* Write CD-RW  */
2776         int     ret;
2777
2778         mmc_check(usalp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL, NULL);
2779         if (!cdwrw)
2780                 return (blank_dummy(usalp, dp, addr, blanktype));
2781
2782         if (dp->profile == 0x1A) {
2783                 printf("Error: this media does not support blanking, ignoring.\n");
2784                 return (blank_dummy(usalp, dp, addr, blanktype));
2785         }
2786         if (lverbose) {
2787                 printf("Blanking %s\n", blank_types[blanktype & 0x07]);
2788                 flush();
2789         }
2790
2791         ret = scsi_blank(usalp, addr, blanktype, (dp->cdr_cmdflags&F_IMMED) != 0);
2792         if (ret < 0)
2793                 return (ret);
2794
2795         wait_unit_ready(usalp, 90*60/curspeed); /* XXX Wait for ATAPI */
2796         waitfix_mmc(usalp, 90*60/curspeed);     /* XXX Wait for ATAPI */
2797         return (ret);
2798 }
2799
2800 static int format_mdvd(SCSI *usalp, cdr_t *dp, int formattype)
2801 {
2802 extern  char    *buf;
2803         BOOL    dvdwr    = FALSE;       /* Write DVD    */
2804         int     ret;
2805         int     profile;
2806         char    addr[12];
2807         struct disk_info *dip;
2808
2809         if (debug || lverbose > 2)
2810                 printf("format_mdvd\n");
2811         mmc_check(usalp, NULL, NULL, NULL, NULL, NULL, &dvdwr);
2812         if (!dvdwr)
2813                 return (format_dummy(usalp, dp, formattype));
2814
2815         if (debug || lverbose > 2)
2816                 printf("format_mdvd: drive is a dvd burner.\n");
2817         profile = get_curprofile(usalp);
2818         if (profile != 0x1A) {
2819                 printf("Error: only support DVD+RW formating, ignoring.\n");
2820                 return (format_dummy(usalp, dp, formattype));
2821         }
2822         dip = (struct disk_info *)buf;
2823         if (get_diskinfo(usalp, dip) < 0)
2824                 return -1;
2825         
2826         if (dip->disk_status & 3 && formattype != FORCE_FORMAT) {
2827                 printf("Error: disk already formated, ignoring.\n");
2828                 return -1;
2829         }
2830         addr[0] = 0;           /* "Reserved" */
2831         addr[1] = 2;           /* "IMMED" flag */
2832         addr[2] = 0;           /* "Descriptor Length" (MSB) */
2833         addr[3] = 8;           /* "Descriptor Length" (LSB) */
2834         addr[4+0] = 0xff;
2835         addr[4+1] = 0xff;
2836         addr[4+2] = 0xff;
2837         addr[4+3] = 0xff;
2838         addr[4+4] = 0x26<<2;
2839         addr[4+5] = 0;
2840         addr[4+6] = 0;
2841         addr[4+7] = 0;
2842         if (formattype == FORCE_FORMAT) {
2843             printf("format_mdvd: forcing reformat.\n"); 
2844             formattype = FULL_FORMAT;
2845             addr[4+0] = 0;
2846             addr[4+1] = 0;
2847             addr[4+2] = 0;
2848             addr[4+3] = 0;
2849             addr[4+7] = 1;
2850         } else {
2851             printf("format_mdvd: media is unformated.\n"); 
2852         }
2853
2854         if (lverbose) {
2855                 printf("Formating %s\n", format_types[formattype & 0x07]);
2856                 flush();
2857         }
2858         if (formattype == FULL_FORMAT) {
2859                 ret = scsi_format(usalp, (caddr_t)&addr, sizeof(addr), FALSE);
2860         } else {
2861                 ret = scsi_format(usalp, (caddr_t)&addr, sizeof(addr), TRUE);
2862         }
2863         if (ret < 0)
2864                 return (ret);
2865
2866         wait_unit_ready(usalp, 90*60/curspeed); /* XXX Wait for ATAPI */
2867         waitfix_mmc(usalp, 90*60/curspeed);     /* XXX Wait for ATAPI */
2868         return (ret);
2869 }
2870
2871 static int 
2872 send_opc_mmc(SCSI *usalp, caddr_t bp, int cnt, int doopc)
2873 {
2874         int     ret;
2875
2876         usalp->silent++;
2877         ret = send_opc(usalp, bp, cnt, doopc);
2878         usalp->silent--;
2879
2880         if (ret >= 0)
2881                 return (ret);
2882
2883         /* BEGIN CSTYLED */
2884         /*
2885          * Hack for a mysterioys drive ....
2886          * Device type    : Removable CD-ROM
2887          * Version        : 0
2888          * Response Format: 1
2889          * Vendor_info    : 'RWD     '
2890          * Identifikation : 'RW2224          '
2891          * Revision       : '2.53'
2892          * Device seems to be: Generic mmc CD-RW.
2893          *
2894          * Performing OPC...
2895          * CDB:  54 01 00 00 00 00 00 00 00 00
2896          * Sense Bytes: 70 00 06 00 00 00 00 0A 00 00 00 00 5A 03 00 00
2897          * Sense Key: 0x6 Unit Attention, Segment 0
2898          * Sense Code: 0x5A Qual 0x03 (operator selected write permit) Fru 0x0
2899          * Sense flags: Blk 0 (not valid)
2900          */
2901         /* END CSTYLED */
2902         if (usal_sense_key(usalp) == SC_UNIT_ATTENTION &&
2903             usal_sense_code(usalp) == 0x5A &&
2904             usal_sense_qual(usalp) == 0x03)
2905                 return (0);
2906
2907         /*
2908          * Do not make the condition:
2909          * "Power calibration area almost full" a fatal error.
2910          * It just flags that we have a single and last chance to write now.
2911          */
2912         if ((usal_sense_key(usalp) == SC_RECOVERABLE_ERROR ||
2913             usal_sense_key(usalp) == SC_MEDIUM_ERROR) &&
2914             usal_sense_code(usalp) == 0x73 &&
2915             usal_sense_qual(usalp) == 0x01)
2916                 return (0);
2917
2918         /*
2919          * Send OPC is optional.
2920          */
2921         if (usal_sense_key(usalp) != SC_ILLEGAL_REQUEST) {
2922                 if (usalp->silent <= 0)
2923                         usal_printerr(usalp);
2924                 return (ret);
2925         }
2926         return (0);
2927 }
2928
2929 static int 
2930 opt1_mmc(SCSI *usalp, cdr_t *dp)
2931 {
2932         int     oflags = dp->cdr_dstat->ds_cdrflags;
2933
2934         if ((dp->cdr_dstat->ds_cdrflags & RF_AUDIOMASTER) != 0) {
2935                 printf("Turning Audio Master Q. R. on\n");
2936                 if (set_audiomaster_yamaha(usalp, dp, TRUE) < 0)
2937                         return (-1);
2938                 if (!debug && lverbose <= 1)
2939                         dp->cdr_dstat->ds_cdrflags &= ~RF_PRATIP;
2940                 if (getdisktype_mmc(usalp, dp) < 0) {
2941                         dp->cdr_dstat->ds_cdrflags = oflags;
2942                         return (-1);
2943                 }
2944                 dp->cdr_dstat->ds_cdrflags = oflags;
2945                 if (oflags & RF_PRATIP) {
2946                         msf_t   msf;
2947                         lba_to_msf(dp->cdr_dstat->ds_first_leadin, &msf);
2948                         printf("New start of lead in: %ld (%02d:%02d/%02d)\n",
2949                                 (long)dp->cdr_dstat->ds_first_leadin,
2950                                 msf.msf_min,
2951                                 msf.msf_sec,
2952                                 msf.msf_frame);
2953                         lba_to_msf(dp->cdr_dstat->ds_maxblocks, &msf);
2954                         printf("New start of lead out: %ld (%02d:%02d/%02d)\n",
2955                                 (long)dp->cdr_dstat->ds_maxblocks,
2956                                 msf.msf_min,
2957                                 msf.msf_sec,
2958                                 msf.msf_frame);
2959                 }
2960         }
2961         if (mmc_isplextor(usalp)) {
2962                 int     gcode;
2963
2964                 if ((dp->cdr_flags & (CDR_SINGLESESS|CDR_HIDE_CDR)) != 0) {
2965                         if (ss_hide_plextor(usalp,
2966                             (dp->cdr_dstat->ds_cdrflags & RF_SINGLESESS) != 0,
2967                             (dp->cdr_dstat->ds_cdrflags & RF_HIDE_CDR) != 0) < 0)
2968                                 return (-1);
2969                 }
2970
2971                 if ((dp->cdr_flags & CDR_SPEEDREAD) != 0) {
2972                         if (speed_rd_plextor(usalp,
2973                             (dp->cdr_dstat->ds_cdrflags & RF_SPEEDREAD) != 0) < 0)
2974                                 return (-1);
2975                 }
2976
2977                 if ((dp->cdr_cmdflags & F_SETDROPTS) ||
2978                     (wm_base(dp->cdr_dstat->ds_wrmode) == WM_SAO) ||
2979                     (wm_base(dp->cdr_dstat->ds_wrmode) == WM_RAW))
2980                         gcode = do_gigarec_plextor(usalp);
2981                 else
2982                         gcode = gigarec_plextor(usalp, 0);
2983                 if (gcode != 0) {
2984                         msf_t   msf;
2985
2986                         dp->cdr_dstat->ds_first_leadin =
2987                                         gigarec_mult(gcode, dp->cdr_dstat->ds_first_leadin);
2988                         dp->cdr_dstat->ds_maxblocks =
2989                                         gigarec_mult(gcode, dp->cdr_dstat->ds_maxblocks);
2990
2991                         if (oflags & RF_PRATIP) {
2992                                 lba_to_msf(dp->cdr_dstat->ds_first_leadin, &msf);
2993                                 printf("New start of lead in: %ld (%02d:%02d/%02d)\n",
2994                                         (long)dp->cdr_dstat->ds_first_leadin,
2995                                         msf.msf_min,
2996                                         msf.msf_sec,
2997                                         msf.msf_frame);
2998                                 lba_to_msf(dp->cdr_dstat->ds_maxblocks, &msf);
2999                                 printf("New start of lead out: %ld (%02d:%02d/%02d)\n",
3000                                         (long)dp->cdr_dstat->ds_maxblocks,
3001                                         msf.msf_min,
3002                                         msf.msf_sec,
3003                                         msf.msf_frame);
3004                         }
3005                 }
3006         }
3007         return (0);
3008 }
3009
3010 static int 
3011 opt2_mmc(SCSI *usalp, cdr_t *dp)
3012 {
3013         Uchar   mode[0x100];
3014         Uchar   moder[0x100];
3015         int     len;
3016         struct  cd_mode_page_05 *mp;
3017         struct  ricoh_mode_page_30 *rp = NULL;
3018         BOOL    burnfree = FALSE;
3019
3020         fillbytes((caddr_t)mode, sizeof (mode), '\0');
3021
3022         if (!get_mode_params(usalp, 0x05, "CD write parameter",
3023                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
3024                 return (-1);
3025         if (len == 0)
3026                 return (-1);
3027
3028         mp = (struct cd_mode_page_05 *)
3029                 (mode + sizeof (struct scsi_mode_header) +
3030                 ((struct scsi_mode_header *)mode)->blockdesc_len);
3031
3032
3033         rp = get_justlink_ricoh(usalp, moder);
3034
3035         if (dp->cdr_cdcap->BUF != 0) {
3036                 burnfree = (mp->BUFE != 0);
3037         } else if ((dp->cdr_flags & CDR_BURNFREE) != 0) {
3038                 burnfree = (rp && (rp->BUEFE != 0));
3039         }
3040
3041         if (lverbose>2 && (dp->cdr_flags & CDR_BURNFREE) != 0)
3042                 printf("BURN-Free is %s.\n", burnfree?"ON":"OFF");
3043
3044         if (!burnfree && (dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) != 0) {
3045                 if(lverbose>2)
3046                         printf("Turning BURN-Free on\n");
3047                 burnfree = TRUE;
3048         }
3049         if (burnfree && (dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0) {
3050                 if(lverbose>2)
3051                         printf("Turning BURN-Free off\n");
3052                 burnfree = FALSE;
3053         }
3054         if (dp->cdr_cdcap->BUF != 0) {
3055                 mp->BUFE = burnfree?1:0;
3056         } 
3057     else if ((dp->cdr_flags & CDR_BURNFREE) != 0) {
3058
3059                 if (rp)
3060                         rp->BUEFE = burnfree?1:0;
3061         }
3062         if (rp) {
3063                 /*
3064                  * Clear Just-Link counter
3065                  */
3066                 i_to_2_byte(rp->link_counter, 0);
3067                 if (xdebug)
3068                         usal_prbytes("Mode Select Data ", moder, moder[0]+1);
3069
3070                 if (!set_mode_params(usalp, "Ricoh Vendor Page", moder, moder[0]+1, 0, -1))
3071                         return (-1);
3072                 rp = get_justlink_ricoh(usalp, moder);
3073         }
3074
3075 #ifdef  DEBUG
3076         usal_prbytes("CD write parameter:", (Uchar *)mode, len);
3077 #endif
3078         if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1))
3079                 return (-1);
3080
3081         if (mmc_isplextor(usalp)) {
3082                 /*
3083                  * Clear Burn-Proof counter
3084                  */
3085                 usalp->silent++;
3086                 bpc_plextor(usalp, 1, NULL);
3087                 usalp->silent--;
3088
3089                 do_varirec_plextor(usalp);
3090         }
3091
3092         return (0);
3093 }
3094
3095 static int 
3096 opt1_mdvd(SCSI *usalp, cdr_t *dp)
3097 {
3098         int     oflags = dp->cdr_dstat->ds_cdrflags;
3099
3100         if ((dp->cdr_dstat->ds_cdrflags & RF_AUDIOMASTER) != 0) {
3101                 printf("Turning Audio Master Q. R. on\n");
3102                 if (set_audiomaster_yamaha(usalp, dp, TRUE) < 0)
3103                         return (-1);
3104                 if (!debug && lverbose <= 1)
3105                         dp->cdr_dstat->ds_cdrflags &= ~RF_PRATIP;
3106                 if (getdisktype_mdvd(usalp, dp) < 0) {
3107                         dp->cdr_dstat->ds_cdrflags = oflags;
3108                         return (-1);
3109                 }
3110                 dp->cdr_dstat->ds_cdrflags = oflags;
3111                 if (oflags & RF_PRATIP) {
3112                         msf_t   msf;
3113                         lba_to_msf(dp->cdr_dstat->ds_first_leadin, &msf);
3114                         printf("New start of lead in: %ld (%02d:%02d/%02d)\n",
3115                                 (long)dp->cdr_dstat->ds_first_leadin,
3116                                 msf.msf_min,
3117                                 msf.msf_sec,
3118                                 msf.msf_frame);
3119                         lba_to_msf(dp->cdr_dstat->ds_maxblocks, &msf);
3120                         printf("New start of lead out: %ld (%02d:%02d/%02d)\n",
3121                                 (long)dp->cdr_dstat->ds_maxblocks,
3122                                 msf.msf_min,
3123                                 msf.msf_sec,
3124                                 msf.msf_frame);
3125                 }
3126         }
3127         return (0);
3128 }
3129
3130 static int
3131 scsi_sony_write(SCSI *usalp, 
3132                 caddr_t bp      /* address of buffer */, 
3133                 long sectaddr   /* disk address (sector) to put */, 
3134                 long size       /* number of bytes to transfer */, 
3135                 int blocks      /* sector count */, 
3136                 BOOL islast     /* last write for track */)
3137 {
3138         return (write_xg5(usalp, bp, sectaddr, size, blocks));
3139 }
3140
3141 Uchar   db2df[] = {
3142         0x00,                   /*  0 2352 bytes of raw data                    */
3143         0xFF,                   /*  1 2368 bytes (raw data + P/Q Subchannel)    */
3144         0xFF,                   /*  2 2448 bytes (raw data + P-W Subchannel)    */
3145         0xFF,                   /*  3 2448 bytes (raw data + P-W raw Subchannel)*/
3146         0xFF,                   /*  4 -    Reserved                             */
3147         0xFF,                   /*  5 -    Reserved                             */
3148         0xFF,                   /*  6 -    Reserved                             */
3149         0xFF,                   /*  7 -    Vendor specific                      */
3150         0x10,                   /*  8 2048 bytes Mode 1 (ISO/IEC 10149)         */
3151         0x30,                   /*  9 2336 bytes Mode 2 (ISO/IEC 10149)         */
3152         0xFF,                   /* 10 2048 bytes Mode 2! (CD-ROM XA form 1)     */
3153         0xFF,                   /* 11 2056 bytes Mode 2 (CD-ROM XA form 1)      */
3154         0xFF,                   /* 12 2324 bytes Mode 2 (CD-ROM XA form 2)      */
3155         0xFF,                   /* 13 2332 bytes Mode 2 (CD-ROM XA 1/2+subhdr)  */
3156         0xFF,                   /* 14 -    Reserved                             */
3157         0xFF,                   /* 15 -    Vendor specific                      */
3158 };
3159
3160 static int 
3161 gen_cue_mmc(track_t *trackp, void *vcuep, BOOL needgap)
3162 {
3163         int     tracks = trackp->tracks;
3164         int     i;
3165         struct mmc_cue  **cuep = vcuep;
3166         struct mmc_cue  *cue;
3167         struct mmc_cue  *cp;
3168         int     ncue = 0;
3169         int     icue = 0;
3170         int     pgsize;
3171         msf_t   m;
3172         int     ctl;
3173         int     df;
3174         int     scms;
3175
3176         cue = malloc(1);
3177
3178         for (i = 0; i <= tracks; i++) {
3179                 ctl = (st2mode[trackp[i].sectype & ST_MASK]) << 4;
3180                 if (is_copy(&trackp[i]))
3181                         ctl |= TM_ALLOW_COPY << 4;
3182                 if (is_quadro(&trackp[i]))
3183                         ctl |= TM_QUADRO << 4;
3184                 df = db2df[trackp[i].dbtype & 0x0F];
3185                 if (trackp[i].tracktype == TOC_XA2 &&
3186                     trackp[i].sectype   == (SECT_MODE_2_MIX|ST_MODE_RAW)) {
3187                         /*
3188                          * Hack for CUE with MODE2/CDI and
3189                          * trackp[i].dbtype == DB_RAW
3190                          */
3191                         df = 0x21;
3192                 }
3193
3194                 if (trackp[i].isrc) {   /* MCN or ISRC */
3195                         ncue += 2;
3196                         cue = realloc(cue, ncue * sizeof (*cue));
3197                         cp = &cue[icue++];
3198                         if (i == 0) {
3199                                 cp->cs_ctladr = 0x02;
3200                                 movebytes(&trackp[i].isrc[0], &cp->cs_tno, 7);
3201                                 cp = &cue[icue++];
3202                                 cp->cs_ctladr = 0x02;
3203                                 movebytes(&trackp[i].isrc[7], &cp->cs_tno, 7);
3204                         } else {
3205                                 cp->cs_ctladr = 0x03;
3206                                 cp->cs_tno = i;
3207                                 movebytes(&trackp[i].isrc[0], &cp->cs_index, 6);
3208                                 cp = &cue[icue++];
3209                                 cp->cs_ctladr = 0x03;
3210                                 cp->cs_tno = i;
3211                                 movebytes(&trackp[i].isrc[6], &cp->cs_index, 6);
3212                         }
3213                 }
3214                 if (i == 0) {   /* Lead in */
3215                         df &= ~7;       /* Mask off data size & nonRAW subch */
3216                         if (df < 0x10)
3217                                 df |= 1;
3218                         else
3219                                 df |= 4;
3220                         if (trackp[0].flags & TI_TEXT)  /* CD-Text in Lead-in*/
3221                                 df |= 0x40;
3222                         lba_to_msf(-150, &m);
3223                         cue = realloc(cue, ++ncue * sizeof (*cue));
3224                         cp = &cue[icue++];
3225                         fillcue(cp, ctl|0x01, i, 0, df, 0, &m);
3226                 } else {
3227                         scms = 0;
3228
3229                         if (is_scms(&trackp[i]))
3230                                 scms = 0x80;
3231                         pgsize = trackp[i].pregapsize;
3232                         if (pgsize == 0 && needgap)
3233                                 pgsize++;
3234                         lba_to_msf(trackp[i].trackstart-pgsize, &m);
3235                         cue = realloc(cue, ++ncue * sizeof (*cue));
3236                         cp = &cue[icue++];
3237                         fillcue(cp, ctl|0x01, i, 0, df, scms, &m);
3238
3239                         if (trackp[i].nindex == 1) {
3240                                 lba_to_msf(trackp[i].trackstart, &m);
3241                                 cue = realloc(cue, ++ncue * sizeof (*cue));
3242                                 cp = &cue[icue++];
3243                                 fillcue(cp, ctl|0x01, i, 1, df, scms, &m);
3244                         } else {
3245                                 int     idx;
3246                                 long    *idxlist;
3247
3248                                 ncue += trackp[i].nindex;
3249                                 idxlist = trackp[i].tindex;
3250                                 cue = realloc(cue, ncue * sizeof (*cue));
3251
3252                                 for (idx = 1; idx <= trackp[i].nindex; idx++) {
3253                                         lba_to_msf(trackp[i].trackstart + idxlist[idx], &m);
3254                                         cp = &cue[icue++];
3255                                         fillcue(cp, ctl|0x01, i, idx, df, scms, &m);
3256                                 }
3257                         }
3258                 }
3259         }
3260         /* Lead out */
3261         ctl = (st2mode[trackp[tracks+1].sectype & ST_MASK]) << 4;
3262         if (is_copy(&trackp[i]))
3263                 ctl |= TM_ALLOW_COPY << 4;
3264         if (is_quadro(&trackp[i]))
3265                 ctl |= TM_QUADRO << 4;
3266         df = db2df[trackp[tracks+1].dbtype & 0x0F];
3267         if (trackp[i].tracktype == TOC_XA2 &&
3268             trackp[i].sectype   == (SECT_MODE_2_MIX|ST_MODE_RAW)) {
3269                 /*
3270                  * Hack for CUE with MODE2/CDI and
3271                  * trackp[i].dbtype == DB_RAW
3272                  */
3273                 df = 0x21;
3274         }
3275         df &= ~7;       /* Mask off data size & nonRAW subch */
3276         if (df < 0x10)
3277                 df |= 1;
3278         else
3279                 df |= 4;
3280         lba_to_msf(trackp[tracks+1].trackstart, &m);
3281         cue = realloc(cue, ++ncue * sizeof (*cue));
3282         cp = &cue[icue++];
3283         fillcue(cp, ctl|0x01, 0xAA, 1, df, 0, &m);
3284
3285         if (lverbose > 1) {
3286                 for (i = 0; i < ncue; i++) {
3287                         usal_prbytes("", (Uchar *)&cue[i], 8);
3288                 }
3289         }
3290         if (cuep)
3291                 *cuep = cue;
3292         else
3293                 free(cue);
3294         return (ncue);
3295 }
3296
3297 static void 
3298 fillcue(struct mmc_cue *cp  /* The target cue entry */, 
3299         int ca              /* Control/adr for this entry */, 
3300         int tno             /* Track number for this entry */, 
3301         int idx             /* Index for this entry */, 
3302         int dataform        /* Data format for this entry */, 
3303         int scms            /* Serial copy management */, 
3304         msf_t *mp           /* MSF value for this entry */)
3305 {
3306         cp->cs_ctladr = ca;             /* XXX wie lead in */
3307         cp->cs_tno = tno;
3308         cp->cs_index = idx;
3309         cp->cs_dataform = dataform;     /* XXX wie lead in */
3310         cp->cs_scms = scms;
3311         cp->cs_min = mp->msf_min;
3312         cp->cs_sec = mp->msf_sec;
3313         cp->cs_frame = mp->msf_frame;
3314 }
3315
3316 static int 
3317 send_cue_mmc(SCSI *usalp, cdr_t *dp, track_t *trackp)
3318 {
3319         struct mmc_cue  *cp;
3320         int             ncue;
3321         int             ret;
3322         Uint            i;
3323
3324         for (i = 1; i <= trackp->tracks; i++) {
3325                 if (trackp[i].tracksize < (tsize_t)0) {
3326                         errmsgno(EX_BAD, "Track %d has unknown length.\n", i);
3327                         return (-1);
3328                 }
3329         }
3330         ncue = (*dp->cdr_gen_cue)(trackp, &cp, FALSE);
3331
3332         usalp->silent++;
3333         ret = send_cue_sheet(usalp, (caddr_t)cp, ncue*8);
3334         usalp->silent--;
3335         free(cp);
3336         if (ret < 0) {
3337                 errmsgno(EX_BAD, "CUE sheet not accepted. Retrying with minimum pregapsize = 1.\n");
3338                 ncue = (*dp->cdr_gen_cue)(trackp, &cp, TRUE);
3339                 ret = send_cue_sheet(usalp, (caddr_t)cp, ncue*8);
3340                 if (ret < 0) {
3341                         errmsgno(EX_BAD,
3342                         "CUE sheet still not accepted. Please try to write in RAW (-raw96r) mode.\n");
3343                 }
3344                 free(cp);
3345         }
3346         return (ret);
3347 }
3348
3349 static int 
3350 stats_mmc(SCSI *usalp, cdr_t *dp)
3351 {
3352         Uchar mode[256];
3353         struct  ricoh_mode_page_30 *rp;
3354         UInt32_t count;
3355
3356         if (mmc_isplextor(usalp) && lverbose) {
3357                 int     sels;
3358                 int     maxs;
3359                 int     lasts;
3360
3361                 /*
3362                  * Run it in silent mode as old drives do not support it.
3363                  * As this function looks to be a part of the PowerRec
3364                  * features, we may want to check
3365                  * dp->cdr_flags & CDR_FORCESPEED
3366                  */
3367                 usalp->silent++;
3368                 if (get_speeds_plextor(usalp, &sels, &maxs, &lasts) >= 0) {
3369                         printf("Last selected write speed: %dx\n",
3370                                                 sels / 176);
3371                         printf("Max media write speed:     %dx\n",
3372                                                 maxs / 176);
3373                         printf("Last actual write speed:   %dx\n",
3374                                                 lasts / 176);
3375                 }
3376                 usalp->silent--;
3377         }
3378
3379         if ((dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0)
3380                 return (0);
3381
3382         if (mmc_isplextor(usalp)) {
3383                 int     i = 0;
3384                 int     ret;
3385
3386                 /*
3387                  * Read Burn-Proof counter
3388                  */
3389                 usalp->silent++;
3390                 ret = bpc_plextor(usalp, 2, &i);
3391                 usalp->silent--;
3392                 if (ret < 0)
3393                         return (-1);
3394                 count = i;
3395                 /*
3396                  * Clear Burn-Proof counter
3397                  */
3398                 bpc_plextor(usalp, 1, NULL);
3399         } else {
3400                 rp = get_justlink_ricoh(usalp, mode);
3401                 if (rp)
3402                         count = a_to_u_2_byte(rp->link_counter);
3403                 else
3404                         return (-1);
3405         }
3406         if (lverbose) {
3407                 if (count == 0)
3408                         printf("BURN-Free was never needed.\n");
3409                 else
3410                         printf("BURN-Free was %d times used.\n",
3411                                 (int)count);
3412         }
3413         return (0);
3414 }
3415 /*--------------------------------------------------------------------------*/
3416 static BOOL 
3417 mmc_isplextor(SCSI *usalp)
3418 {
3419         if (usalp->inq != NULL &&
3420                         strncmp(usalp->inq->vendor_info, "PLEXTOR", 7) == 0) {
3421                 return (TRUE);
3422         }
3423         return (FALSE);
3424 }
3425
3426 static BOOL 
3427 mmc_isyamaha(SCSI *usalp)
3428 {
3429         if (usalp->inq != NULL &&
3430                         strncmp(usalp->inq->vendor_info, "YAMAHA", 6) == 0) {
3431                 return (TRUE);
3432         }
3433         return (FALSE);
3434 }
3435
3436 static void 
3437 do_varirec_plextor(SCSI *usalp)
3438 {
3439         char    *p;
3440         int     voff;
3441
3442         p = hasdrvopt(driveropts, "varirec=");
3443         if (p == NULL || curspeed != 4) {
3444                 if (check_varirec_plextor(usalp) >= 0)
3445                         varirec_plextor(usalp, FALSE, 0);
3446         } else {
3447                 if (*astoi(p, &voff) != '\0')
3448                         comerrno(EX_BAD,
3449                                 "Bad varirec value '%s'.\n", p);
3450                 if (check_varirec_plextor(usalp) < 0)
3451                         comerrno(EX_BAD, "Drive does not support VariRec.\n");
3452                 varirec_plextor(usalp, TRUE, voff);
3453         }
3454 }
3455
3456 /*
3457  * GigaRec value table
3458  */
3459 struct gr {
3460         Uchar   val;
3461         char    vadd;
3462         char    *name;
3463 } gr[] = {
3464         { 0x00, 0,  "off", },
3465         { 0x00, 0,  "1.0", },
3466         { 0x01, 2,  "1.2", },
3467         { 0x02, 3,  "1.3", },
3468         { 0x03, 4,  "1.4", },
3469         { 0x81, -2, "0.8", },
3470         { 0x82, -3, "0.7", },
3471         { 0x83, -4, "0.6", },
3472         { 0x00, 0,  NULL, },
3473 };
3474
3475 static int 
3476 do_gigarec_plextor(SCSI *usalp)
3477 {
3478         char    *p;
3479         int     val = 0;        /* Make silly GCC happy */
3480
3481         p = hasdrvopt(driveropts, "gigarec=");
3482         if (p == NULL) {
3483                 if (check_gigarec_plextor(usalp) >= 0)
3484                         gigarec_plextor(usalp, 0);
3485         } else {
3486                 struct gr *gp = gr;
3487
3488                 for (; gp->name != NULL; gp++) {
3489                         if (streql(p, gp->name)) {
3490                                 val = gp->val;
3491                                 break;
3492                         }
3493                 }
3494                 if (gp->name == NULL)
3495                         comerrno(EX_BAD,
3496                                 "Bad gigarec value '%s'.\n", p);
3497                 if (check_gigarec_plextor(usalp) < 0)
3498                         comerrno(EX_BAD, "Drive does not support GigaRec.\n");
3499                 return (gigarec_plextor(usalp, val));
3500         }
3501         return (0);
3502 }
3503
3504 static int 
3505 drivemode_plextor(SCSI *usalp, caddr_t bp, int cnt, int modecode, void *modeval)
3506 {
3507         register struct usal_cmd        *scmd = usalp->scmd;
3508
3509         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
3510         scmd->flags = SCG_DISRE_ENA;
3511         if (modeval == NULL) {
3512                 scmd->flags |= SCG_RECV_DATA;
3513                 scmd->addr = bp;
3514                 scmd->size = cnt;
3515         } else {
3516                 scmd->cdb.g5_cdb.res = 0x08;
3517         }
3518         scmd->cdb_len = SC_G5_CDBLEN;
3519         scmd->sense_len = CCS_SENSE_LEN;
3520         scmd->cdb.g5_cdb.cmd = 0xE9;
3521         scmd->cdb.g5_cdb.lun = usal_lun(usalp);
3522         scmd->cdb.g1_cdb.addr[0] = modecode;
3523         if (modeval)
3524                 movebytes(modeval, &scmd->cdb.g1_cdb.addr[1], 6);
3525         else
3526                 i_to_2_byte(&scmd->cdb.g1_cdb.count[2], cnt);
3527
3528         usalp->cmdname = "plextor drive mode";
3529
3530         if (usal_cmd(usalp) < 0)
3531                 return (-1);
3532         return (0);
3533 }
3534
3535 /*
3536  * #defines for drivemode_plextor()...
3537  */
3538 #define MODE_CODE_SH    0x01    /* Mode code for Single Session & Hide-CDR */
3539 #define MB1_SS          0x01    /* Single Session Mode                     */
3540 #define MB1_HIDE_CDR    0x02    /* Hide CDR Media                          */
3541
3542 #define MODE_CODE_VREC  0x02    /* Mode code for Vari Rec                  */
3543
3544 #define MODE_CODE_GREC  0x04    /* Mode code for Giga Rec                  */
3545
3546 #define MODE_CODE_SPEED 0xbb    /* Mode code for Speed Read                */
3547 #define MBbb_SPEAD_READ 0x01    /* Spead Read                              */
3548                                 /* Danach Speed auf 0xFFFF 0xFFFF setzen   */
3549
3550 static int 
3551 drivemode2_plextor(SCSI *usalp, caddr_t bp, int cnt, int modecode, void *modeval)
3552 {
3553         register struct usal_cmd        *scmd = usalp->scmd;
3554
3555         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
3556         scmd->flags = SCG_DISRE_ENA;
3557         if (modeval == NULL) {
3558                 scmd->flags |= SCG_RECV_DATA;
3559                 scmd->addr = bp;
3560                 scmd->size = cnt;
3561         } else {
3562                 scmd->cdb.g5_cdb.res = 0x08;
3563         }
3564         scmd->cdb_len = SC_G5_CDBLEN;
3565         scmd->sense_len = CCS_SENSE_LEN;
3566         scmd->cdb.g5_cdb.cmd = 0xED;
3567         scmd->cdb.g5_cdb.lun = usal_lun(usalp);
3568         scmd->cdb.g1_cdb.addr[0] = modecode;
3569         if (modeval)
3570                 scmd->cdb.g5_cdb.reladr = *(char *)modeval != 0 ? 1 : 0;
3571         else
3572                 i_to_2_byte(&scmd->cdb.g1_cdb.count[1], cnt);
3573
3574         usalp->cmdname = "plextor drive mode2";
3575
3576         if (usal_cmd(usalp) < 0)
3577                 return (-1);
3578
3579         return (0);
3580 }
3581
3582 static int 
3583 check_varirec_plextor(SCSI *usalp)
3584 {
3585         int     modecode = 2;
3586         Uchar   getmode[8];
3587
3588         fillbytes(getmode, sizeof (getmode), '\0');
3589         usalp->silent++;
3590         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
3591                 usalp->silent--;
3592                 return (-1);
3593         }
3594         usalp->silent--;
3595
3596         return (0);
3597 }
3598
3599 static int 
3600 check_gigarec_plextor(SCSI *usalp)
3601 {
3602         int     modecode = 4;
3603         Uchar   getmode[8];
3604
3605         fillbytes(getmode, sizeof (getmode), '\0');
3606         usalp->silent++;
3607         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
3608                 usalp->silent--;
3609                 return (-1);
3610         }
3611         usalp->silent--;
3612
3613         return (0);
3614 }
3615
3616 static int 
3617 varirec_plextor(SCSI *usalp, BOOL on, int val)
3618 {
3619         int     modecode = 2;
3620         Uchar   setmode[8];
3621         Uchar   getmode[8];
3622
3623         fillbytes(getmode, sizeof (getmode), '\0');
3624         usalp->silent++;
3625         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
3626                 usalp->silent--;
3627                 return (-1);
3628         }
3629         usalp->silent--;
3630
3631         if (lverbose > 1)
3632                 usal_prbytes("Modes", getmode, sizeof (getmode));
3633
3634
3635         fillbytes(setmode, sizeof (setmode), '\0');
3636         setmode[0] = on?1:0;
3637         if (on) {
3638                 if (val < -2 || val > 2)
3639                         comerrno(EX_BAD, "Bad VariRec offset %d\n", val);
3640                 printf("Turning Varirec on.\n");
3641                 printf("Varirec offset is %d.\n", val);
3642
3643                 if (val > 0) {
3644                         setmode[1] = val & 0x7F;
3645                 } else {
3646                         setmode[1] = (-val) & 0x7F;
3647                         setmode[1] |= 0x80;
3648                 }
3649         }
3650
3651         if (drivemode_plextor(usalp, NULL, 0, modecode, setmode) < 0)
3652                 return (-1);
3653
3654         fillbytes(getmode, sizeof (getmode), '\0');
3655         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0)
3656                 return (-1);
3657
3658         if (lverbose > 1)
3659                 usal_prbytes("Modes", getmode, sizeof (getmode));
3660
3661         return (0);
3662 }
3663
3664 static int 
3665 gigarec_plextor(SCSI *usalp, int val)
3666 {
3667         int     modecode = 4;
3668         Uchar   setmode[8];
3669         Uchar   getmode[8];
3670
3671         fillbytes(getmode, sizeof (getmode), '\0');
3672         usalp->silent++;
3673         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
3674                 usalp->silent--;
3675                 return (-1);
3676         }
3677         usalp->silent--;
3678
3679         if (lverbose > 1)
3680                 usal_prbytes("Modes", getmode, sizeof (getmode));
3681
3682
3683         fillbytes(setmode, sizeof (setmode), '\0');
3684         setmode[1] = val;
3685
3686         if (drivemode_plextor(usalp, NULL, 0, modecode, setmode) < 0)
3687                 return (-1);
3688
3689         fillbytes(getmode, sizeof (getmode), '\0');
3690         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0)
3691                 return (-1);
3692
3693         if (lverbose > 1)
3694                 usal_prbytes("Modes", getmode, sizeof (getmode));
3695
3696         {
3697                 struct gr *gp = gr;
3698
3699                 for (; gp->name != NULL; gp++) {
3700                         if (getmode[3] == gp->val)
3701                                 break;
3702                 }
3703                 if (gp->name == NULL)
3704                         printf("Unknown GigaRec value 0x%X.\n", getmode[3]);
3705                 else
3706                         printf("GigaRec %sis %s.\n", gp->val?"value ":"", gp->name);
3707         }
3708         return (getmode[3]);
3709 }
3710
3711 static Int32_t 
3712 gigarec_mult(int code, Int32_t val)
3713 {
3714         Int32_t add;
3715         struct gr *gp = gr;
3716
3717         for (; gp->name != NULL; gp++) {
3718                 if (code == gp->val)
3719                         break;
3720         }
3721         if (gp->vadd == 0)
3722                 return (val);
3723
3724         add = val * gp->vadd / 10;
3725         return (val + add);
3726 }
3727
3728 static int 
3729 check_ss_hide_plextor(SCSI *usalp)
3730 {
3731         int     modecode = 1;
3732         Uchar   getmode[8];
3733
3734         fillbytes(getmode, sizeof (getmode), '\0');
3735         usalp->silent++;
3736         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
3737                 usalp->silent--;
3738                 return (-1);
3739         }
3740         usalp->silent--;
3741
3742         return (getmode[2] & 0x03);
3743 }
3744
3745 static int 
3746 check_speed_rd_plextor(SCSI *usalp)
3747 {
3748         int     modecode = 0xBB;
3749         Uchar   getmode[8];
3750
3751         fillbytes(getmode, sizeof (getmode), '\0');
3752         usalp->silent++;
3753         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
3754                 usalp->silent--;
3755                 return (-1);
3756         }
3757         usalp->silent--;
3758
3759         return (getmode[2] & 0x01);
3760 }
3761
3762 static int 
3763 check_powerrec_plextor(SCSI *usalp)
3764 {
3765         int     modecode = 0;
3766         Uchar   getmode[8];
3767
3768         fillbytes(getmode, sizeof (getmode), '\0');
3769         usalp->silent++;
3770         if (drivemode2_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
3771                 usalp->silent--;
3772                 return (-1);
3773         }
3774         usalp->silent--;
3775
3776         if (getmode[2] & 1)
3777                 return (1);
3778
3779         return (0);
3780 }
3781
3782 static int 
3783 ss_hide_plextor(SCSI *usalp, BOOL do_ss, BOOL do_hide)
3784 {
3785         int     modecode = 1;
3786         Uchar   setmode[8];
3787         Uchar   getmode[8];
3788         BOOL    is_ss;
3789         BOOL    is_hide;
3790
3791         fillbytes(getmode, sizeof (getmode), '\0');
3792         usalp->silent++;
3793         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
3794                 usalp->silent--;
3795                 return (-1);
3796         }
3797         usalp->silent--;
3798
3799         if (lverbose > 1)
3800                 usal_prbytes("Modes", getmode, sizeof (getmode));
3801
3802
3803         is_ss = (getmode[2] & MB1_SS) != 0;
3804         is_hide = (getmode[2] & MB1_HIDE_CDR) != 0;
3805
3806         if (lverbose > 0) {
3807                 printf("Single session is %s.\n", is_ss ? "ON":"OFF");
3808                 printf("Hide CDR is %s.\n", is_hide ? "ON":"OFF");
3809         }
3810
3811         fillbytes(setmode, sizeof (setmode), '\0');
3812         setmode[0] = getmode[2];                /* Copy over old values */
3813         if (do_ss >= 0) {
3814                 if (do_ss)
3815                         setmode[0] |= MB1_SS;
3816                 else
3817                         setmode[0] &= ~MB1_SS;
3818         }
3819         if (do_hide >= 0) {
3820                 if (do_hide)
3821                         setmode[0] |= MB1_HIDE_CDR;
3822                 else
3823                         setmode[0] &= ~MB1_HIDE_CDR;
3824         }
3825
3826         if (do_ss >= 0 && do_ss != is_ss)
3827                 printf("Turning single session %s.\n", do_ss?"on":"off");
3828         if (do_hide >= 0 && do_hide != is_hide)
3829                 printf("Turning hide CDR %s.\n", do_hide?"on":"off");
3830
3831         if (drivemode_plextor(usalp, NULL, 0, modecode, setmode) < 0)
3832                 return (-1);
3833
3834         fillbytes(getmode, sizeof (getmode), '\0');
3835         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0)
3836                 return (-1);
3837
3838         if (lverbose > 1)
3839                 usal_prbytes("Modes", getmode, sizeof (getmode));
3840
3841         return (0);
3842 }
3843
3844 static int 
3845 speed_rd_plextor(SCSI *usalp, BOOL do_speedrd)
3846 {
3847         int     modecode = 0xBB;
3848         Uchar   setmode[8];
3849         Uchar   getmode[8];
3850         BOOL    is_speedrd;
3851
3852         fillbytes(getmode, sizeof (getmode), '\0');
3853         usalp->silent++;
3854         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
3855                 usalp->silent--;
3856                 return (-1);
3857         }
3858         usalp->silent--;
3859
3860         if (lverbose > 1)
3861                 usal_prbytes("Modes", getmode, sizeof (getmode));
3862
3863
3864         is_speedrd = (getmode[2] & MBbb_SPEAD_READ) != 0;
3865
3866         if (lverbose > 0)
3867                 printf("Speed-Read is %s.\n", is_speedrd ? "ON":"OFF");
3868
3869         fillbytes(setmode, sizeof (setmode), '\0');
3870         setmode[0] = getmode[2];                /* Copy over old values */
3871         if (do_speedrd >= 0) {
3872                 if (do_speedrd)
3873                         setmode[0] |= MBbb_SPEAD_READ;
3874                 else
3875                         setmode[0] &= ~MBbb_SPEAD_READ;
3876         }
3877
3878         if (do_speedrd >= 0 && do_speedrd != is_speedrd)
3879                 printf("Turning Speed-Read %s.\n", do_speedrd?"on":"off");
3880
3881         if (drivemode_plextor(usalp, NULL, 0, modecode, setmode) < 0)
3882                 return (-1);
3883
3884         fillbytes(getmode, sizeof (getmode), '\0');
3885         if (drivemode_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0)
3886                 return (-1);
3887
3888         if (lverbose > 1)
3889                 usal_prbytes("Modes", getmode, sizeof (getmode));
3890
3891         /*
3892          * Set current read speed to new max value.
3893          */
3894         if (do_speedrd >= 0 && do_speedrd != is_speedrd)
3895                 scsi_set_speed(usalp, 0xFFFF, -1, ROTCTL_CAV);
3896
3897         return (0);
3898 }
3899
3900 static int 
3901 powerrec_plextor(SCSI *usalp, BOOL do_powerrec)
3902 {
3903         int     modecode = 0;
3904         Uchar   setmode[8];
3905         Uchar   getmode[8];
3906         BOOL    is_powerrec;
3907         int     speed;
3908
3909         fillbytes(getmode, sizeof (getmode), '\0');
3910         usalp->silent++;
3911         if (drivemode2_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0) {
3912                 usalp->silent--;
3913                 return (-1);
3914         }
3915         usalp->silent--;
3916
3917         if (lverbose > 1)
3918                 usal_prbytes("Modes", getmode, sizeof (getmode));
3919
3920
3921         is_powerrec = (getmode[2] & 1) != 0;
3922
3923         speed = a_to_u_2_byte(&getmode[4]);
3924
3925         if (lverbose > 0) {
3926                 printf("Power-Rec is %s.\n", is_powerrec ? "ON":"OFF");
3927                 printf("Power-Rec write speed:     %dx (recommended)\n", speed / 176);
3928         }
3929
3930         fillbytes(setmode, sizeof (setmode), '\0');
3931         setmode[0] = getmode[2];                /* Copy over old values */
3932         if (do_powerrec >= 0) {
3933                 if (do_powerrec)
3934                         setmode[0] |= 1;
3935                 else
3936                         setmode[0] &= ~1;
3937         }
3938
3939         if (do_powerrec >= 0 && do_powerrec != is_powerrec)
3940                 printf("Turning Power-Rec %s.\n", do_powerrec?"on":"off");
3941
3942         if (drivemode2_plextor(usalp, NULL, 0, modecode, setmode) < 0)
3943                 return (-1);
3944
3945         fillbytes(getmode, sizeof (getmode), '\0');
3946         if (drivemode2_plextor(usalp, (caddr_t)getmode, sizeof (getmode), modecode, NULL) < 0)
3947                 return (-1);
3948
3949         if (lverbose > 1)
3950                 usal_prbytes("Modes", getmode, sizeof (getmode));
3951
3952         return (0);
3953 }
3954
3955 static int 
3956 get_speeds_plextor(SCSI *usalp, int *selp, int *maxp, int *lastp)
3957 {
3958         register struct usal_cmd        *scmd = usalp->scmd;
3959         char    buf[10];
3960         int     i;
3961
3962         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
3963         fillbytes((caddr_t)buf, sizeof (buf), '\0');
3964         scmd->flags = SCG_DISRE_ENA;
3965         scmd->flags |= SCG_RECV_DATA;
3966         scmd->addr = buf;
3967         scmd->size = sizeof (buf);
3968         scmd->cdb_len = SC_G5_CDBLEN;
3969         scmd->sense_len = CCS_SENSE_LEN;
3970         scmd->cdb.g5_cdb.cmd = 0xEB;
3971         scmd->cdb.g5_cdb.lun = usal_lun(usalp);
3972
3973         i_to_2_byte(&scmd->cdb.g1_cdb.count[1], sizeof (buf));
3974
3975         usalp->cmdname = "plextor get speedlist";
3976
3977         if (usal_cmd(usalp) < 0)
3978                 return (-1);
3979
3980         i = a_to_u_2_byte(&buf[4]);
3981         if (selp)
3982                 *selp = i;
3983
3984         i = a_to_u_2_byte(&buf[6]);
3985         if (maxp)
3986                 *maxp = i;
3987
3988         i = a_to_u_2_byte(&buf[8]);
3989         if (lastp)
3990                 *lastp = i;
3991
3992         return (0);
3993 }
3994
3995 static int 
3996 bpc_plextor(SCSI *usalp, int mode, int *bpp)
3997 {
3998         register struct usal_cmd        *scmd = usalp->scmd;
3999         char    buf[4];
4000         int     i;
4001
4002         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
4003         fillbytes((caddr_t)buf, sizeof (buf), '\0');
4004         scmd->flags = SCG_DISRE_ENA;
4005         scmd->flags |= SCG_RECV_DATA;
4006         scmd->addr = buf;
4007         scmd->size = sizeof (buf);
4008         scmd->cdb_len = SC_G5_CDBLEN;
4009         scmd->sense_len = CCS_SENSE_LEN;
4010         scmd->cdb.g5_cdb.cmd = 0xF5;
4011         scmd->cdb.g5_cdb.lun = usal_lun(usalp);
4012
4013         scmd->cdb.g5_cdb.addr[1] = 0x08;
4014         scmd->cdb.g5_cdb.addr[2] = mode;
4015
4016         i_to_2_byte(&scmd->cdb.g1_cdb.count[1], sizeof (buf));
4017
4018         usalp->cmdname = "plextor read bpc";
4019
4020         if (usal_cmd(usalp) < 0)
4021                 return (-1);
4022
4023         if (usal_getresid(usalp) > 2)
4024                 return (0);
4025
4026         i = a_to_u_2_byte(buf);
4027         if (bpp)
4028                 *bpp = i;
4029
4030         return (0);
4031 }
4032
4033 static int 
4034 set_audiomaster_yamaha(SCSI *usalp, cdr_t *dp, BOOL keep_mode)
4035 {
4036         Uchar   mode[0x100];
4037         int     len;
4038         int     ret = 0;
4039         struct  cd_mode_page_05 *mp;
4040
4041         if (xdebug && !keep_mode)
4042                 printf("Checking for Yamaha Audio Master feature: ");
4043
4044         /*
4045          * Do not reset mp->test_write (-dummy) here.
4046          */
4047         deflt_writemodes_mmc(usalp, FALSE);
4048
4049         fillbytes((caddr_t)mode, sizeof (mode), '\0');
4050
4051         usalp->silent++;
4052         if (!get_mode_params(usalp, 0x05, "CD write parameter",
4053                         mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len)) {
4054                 usalp->silent--;
4055                 return (-1);
4056         }
4057         if (len == 0) {
4058                 usalp->silent--;
4059                 return (-1);
4060         }
4061
4062         mp = (struct cd_mode_page_05 *)
4063                 (mode + sizeof (struct scsi_mode_header) +
4064                 ((struct scsi_mode_header *)mode)->blockdesc_len);
4065 #ifdef  DEBUG
4066         usal_prbytes("CD write parameter:", (Uchar *)mode, len);
4067 #endif
4068
4069         /*
4070          * Do not set mp->test_write (-dummy) here. It should be set
4071          * only at one place and only one time.
4072          */
4073         mp->BUFE = 0;
4074
4075         mp->write_type = 8;
4076         mp->track_mode = 0;
4077         mp->dbtype = DB_RAW;
4078
4079         if (!set_mode_params(usalp, "CD write parameter", mode, len, 0, -1))
4080                 ret = -1;
4081
4082         /*
4083          * Do not reset mp->test_write (-dummy) here.
4084          */
4085         if (!keep_mode || ret < 0)
4086                 deflt_writemodes_mmc(usalp, FALSE);
4087         usalp->silent--;
4088
4089         return (ret);
4090 }
4091
4092 struct 
4093 ricoh_mode_page_30 *get_justlink_ricoh(SCSI *usalp, Uchar *mode)
4094 {
4095         Uchar   modec[0x100];
4096         int     len;
4097         struct  ricoh_mode_page_30 *mp;
4098
4099         usalp->silent++;
4100         if (!get_mode_params(usalp, 0x30, "Ricoh Vendor Page", mode, modec, NULL, NULL, &len)) {
4101                 usalp->silent--;
4102                 return ((struct ricoh_mode_page_30 *)0);
4103         }
4104         usalp->silent--;
4105
4106         /*
4107          * SCSI mode header + 6 bytes mode page 30.
4108          * This is including the Burn-Free counter.
4109          */
4110         if (len < 10)
4111                 return ((struct ricoh_mode_page_30 *)0);
4112
4113         if (xdebug) {
4114                 fprintf(stderr, "Mode len: %d\n", len);
4115                 usal_prbytes("Mode Sense Data ", mode, len);
4116                 usal_prbytes("Mode Sence CData", modec, len);
4117         }
4118
4119         mp = (struct ricoh_mode_page_30 *)
4120                 (mode + sizeof (struct scsi_mode_header) +
4121                 ((struct scsi_mode_header *)mode)->blockdesc_len);
4122
4123         /*
4124          * 6 bytes mode page 30.
4125          * This is including the Burn-Free counter.
4126          */
4127         if ((len - ((Uchar *)mp - mode) -1) < 5)
4128                 return ((struct ricoh_mode_page_30 *)0);
4129
4130         if (xdebug) {
4131                 fprintf(stderr, "Burnfree counter: %d\n", a_to_u_2_byte(mp->link_counter));
4132         }
4133         return (mp);
4134 }
4135
4136 static int 
4137 force_speed_yamaha(SCSI *usalp, int readspeed, int writespeed)
4138 {
4139         register struct usal_cmd        *scmd = usalp->scmd;
4140
4141         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
4142         scmd->flags = SCG_DISRE_ENA;
4143         scmd->cdb_len = SC_G5_CDBLEN;
4144         scmd->sense_len = CCS_SENSE_LEN;
4145         scmd->cdb.g5_cdb.cmd = 0xBB;
4146         scmd->cdb.g5_cdb.lun = usal_lun(usalp);
4147
4148         if (readspeed < 0)
4149                 i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], 0xFFFF);
4150         else
4151                 i_to_2_byte(&scmd->cdb.g5_cdb.addr[0], readspeed);
4152         if (writespeed < 0)
4153                 i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], 0xFFFF);
4154         else
4155                 i_to_2_byte(&scmd->cdb.g5_cdb.addr[2], writespeed);
4156
4157         scmd->cdb.cmd_cdb[11] = 0x80;
4158
4159         usalp->cmdname = "yamaha force cd speed";
4160
4161         if (usal_cmd(usalp) < 0)
4162                 return (-1);
4163         return (0);
4164 }
4165
4166 static BOOL
4167 get_tattoo_yamaha(SCSI *usalp, BOOL print, Int32_t *irp, Int32_t *orp)
4168 {
4169         Uchar   mode[0x100];
4170         int     len;
4171         UInt32_t ival;
4172         UInt32_t oval;
4173         Uchar   *mp;
4174
4175         usalp->silent++;
4176         if (!get_mode_params(usalp, 0x31, "Yamaha Tattoo Page", mode, NULL, NULL, NULL, &len)) {
4177                 usalp->silent--;
4178                 return (FALSE);
4179         }
4180         usalp->silent--;
4181
4182         /*
4183          * SCSI mode header + 16 bytes mode page 31.
4184          * This is including the Burn-Free counter.
4185          */
4186         if (len < 20)
4187                 return (FALSE);
4188
4189         mp = (Uchar *)
4190                 (mode + sizeof (struct scsi_mode_header) +
4191                 ((struct scsi_mode_header *)mode)->blockdesc_len);
4192
4193         /*
4194          * 10 bytes mode page 31.
4195          * This is including the Burn-Free counter.
4196          */
4197         if ((len - ((Uchar *)mp - mode) -1) < 10)
4198                 return (FALSE);
4199
4200         ival = a_to_u_3_byte(&mp[4]);
4201         oval = a_to_u_3_byte(&mp[7]);
4202
4203         if (irp)
4204                 *irp = ival;
4205         if (orp)
4206                 *orp = oval;
4207
4208         if (print && ival > 0 && oval > 0) {
4209                 printf("DiskT@2 inner r: %d\n", (int)ival);
4210                 printf("DiskT@2 outer r: %d\n", (int)oval);
4211                 printf("DiskT@2 image size: 3744 x %d pixel.\n",
4212                                                 (int)(oval-ival)+1);
4213         }
4214
4215         return (TRUE);
4216 }
4217
4218 static int 
4219 do_tattoo_yamaha(SCSI *usalp, FILE *f)
4220 {
4221         Int32_t ival = 0;
4222         Int32_t oval = 0;
4223         Int32_t lines;
4224         off_t   fsize;
4225         char    *buf = usalp->bufptr;
4226         long    bufsize = usalp->maxbuf;
4227         long    nsecs;
4228         long    amt;
4229
4230         nsecs = bufsize / 2048;
4231         bufsize = nsecs * 2048;
4232
4233         if (!get_tattoo_yamaha(usalp, FALSE, &ival, &oval)) {
4234                 errmsgno(EX_BAD, "Cannot get DiskT@2 info.\n");
4235                 return (-1);
4236         }
4237
4238         if (ival == 0 || oval == 0) {
4239                 errmsgno(EX_BAD, "DiskT@2 info not valid.\n");
4240                 return (-1);
4241         }
4242
4243         lines = oval - ival + 1;
4244         fsize = filesize(f);
4245         if ((fsize % 3744) != 0 || fsize < (lines*3744)) {
4246                 errmsgno(EX_BAD, "Illegal DiskT@2 file size.\n");
4247                 return (-1);
4248         }
4249         if (fsize > (lines*3744))
4250                 fsize = lines*3744;
4251
4252         if (lverbose)
4253                 printf("Starting to write DiskT@2 data.\n");
4254         fillbytes(buf, bufsize, '\0');
4255         if ((amt = fileread(f, buf, bufsize)) <= 0) {
4256                 errmsg("DiskT@2 file read error.\n");
4257                 return (-1);
4258         }
4259
4260         if (yamaha_write_buffer(usalp, 1, 0, ival, amt/2048, buf, amt) < 0) {
4261                 errmsgno(EX_BAD, "DiskT@2 1st write error.\n");
4262                 return (-1);
4263         }
4264         amt = (amt+2047) / 2048 * 2048;
4265         fsize -= amt;
4266
4267         while (fsize > 0) {
4268                 fillbytes(buf, bufsize, '\0');
4269                 if ((amt = fileread(f, buf, bufsize)) <= 0) {
4270                         errmsg("DiskT@2 file read error.\n");
4271                         return (-1);
4272                 }
4273                 amt = (amt+2047) / 2048 * 2048;
4274                 fsize -= amt;
4275                 if (yamaha_write_buffer(usalp, 1, 0, 0, amt/2048, buf, amt) < 0) {
4276                         errmsgno(EX_BAD, "DiskT@2 write error.\n");
4277                         return (-1);
4278                 }
4279         }
4280
4281         if (yamaha_write_buffer(usalp, 1, 0, oval, 0, buf, 0) < 0) {
4282                 errmsgno(EX_BAD, "DiskT@2 final error.\n");
4283                 return (-1);
4284         }
4285
4286         wait_unit_ready(usalp, 1000);   /* Wait for DiskT@2 */
4287         waitfix_mmc(usalp, 1000);       /* Wait for DiskT@2 */
4288
4289         return (0);
4290 }
4291
4292 /*
4293  * Yamaha specific version of 'write buffer' that offers an additional
4294  * Parameter Length 'parlen' parameter.
4295  */
4296 static int 
4297 yamaha_write_buffer(SCSI *usalp, int mode, int bufferid, long offset,
4298                     long parlen, void *buffer, long buflen)
4299 {
4300         register struct usal_cmd        *scmd = usalp->scmd;
4301                 Uchar   *CDB;
4302
4303         fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
4304         scmd->addr = buffer;
4305         scmd->size = buflen;
4306         scmd->flags = SCG_DISRE_ENA;
4307         scmd->cdb_len = SC_G1_CDBLEN;
4308         scmd->sense_len = CCS_SENSE_LEN;
4309         scmd->cdb.g1_cdb.cmd = 0x3B;
4310
4311         CDB    = (Uchar *)scmd->cdb.cmd_cdb;
4312         CDB[1] = mode & 7;
4313         CDB[2] = bufferid;
4314         i_to_3_byte(&CDB[3], offset);
4315         i_to_3_byte(&CDB[6], parlen);
4316
4317         usalp->cmdname = "write_buffer";
4318
4319         if (usal_cmd(usalp) >= 0)
4320                 return (1);
4321         return (0);
4322 }
4323
4324 static int 
4325 dvd_dual_layer_split(SCSI *usalp, cdr_t *dp, long tsize)
4326 {
4327     unsigned char       xb[12];
4328     long        l0_size;
4329     
4330     /* Get the Layer 0 defined data zone*/
4331     if (read_dvd_structure(usalp, (caddr_t)xb, 12, 0, 0, 0x20) >= 0) {
4332         if ((xb[1] | xb[0] << 8) < 13) {
4333             fprintf(stderr, "dvd_dual_layer_split: read_dvd_structure returns invalid data\n");
4334             return 1;
4335         }
4336         if (xb[4] & 0x80) {
4337             printf("L0 zone size already set\n");
4338             return 1;
4339         }
4340         l0_size = xb[11] | xb[10] << 8 | xb[9] << 16 | xb[8] << 24;
4341         if (tsize < l0_size) {
4342             fprintf(stderr, "track size smaller than one layer, use --force to force burning.");
4343             return 0;
4344         }
4345         printf("L0 size: %ld (track size %ld)\n", l0_size, tsize);
4346         l0_size = tsize / 2;
4347         l0_size = l0_size - 1 + 16 - (l0_size - 1) % 16;
4348         printf("New L0 size: %ld\n", l0_size);
4349
4350         memset (xb, 0, sizeof(xb));
4351         xb[1]  = sizeof(xb) - 2;
4352         xb[8]  = l0_size >> 24;
4353         xb[9]  = l0_size >> 16;
4354         xb[10] = l0_size >> 8;
4355         xb[11] = l0_size;
4356         if (send_dvd_structure(usalp, (caddr_t)xb, 12, 0, 0x20)) {
4357             fprintf(stderr, "dvd_dual_layer_split: send_dvd_structure failed, could not set middle zone location.\n");
4358             return 0;
4359         }
4360     }
4361    return 1;
4362 }