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