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
mmc_load(SCSI * usalp,cdr_t * dp)175 mmc_load(SCSI *usalp, cdr_t *dp)
176 {
177 return (scsi_load_unload(usalp, 1));
178 }
179
180 static int
mmc_unload(SCSI * usalp,cdr_t * dp)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
mmc_opthelp(cdr_t * dp,int excode)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 *
hasdrvopt(char * optstr,char * optname)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 *
identify_mmc(SCSI * usalp,cdr_t * dp,struct scsi_inquiry * ip)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 }
4363