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