1 /* @(#)drv_dvd.c	1.167 13/12/10 Copyright 1998-2013 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)drv_dvd.c	1.167 13/12/10 Copyright 1998-2013 J. Schilling";
6 #endif
7 /*
8  *	DVD-R device implementation for
9  *	SCSI-3/mmc-2 conforming drives
10  *	Currently it only supports the Pioneer DVD-R S101
11  *	as for the near future, there are no other drives.
12  *
13  *		Check recovery		- DUMMY
14  *		Load Media		- OK
15  *		Get Disktype		- Disk Status & Size (read ATIP -> DVD structure)
16  *		Check Session ??	- Nicht vorhanden
17  *		Check Disk size		- Nach Status & size + Next wr. Addr.
18  *		Set Speed/Dummy		- Speed auf DVD -> dummy
19  *		Open Session		- Set Write Parameter & ??? -> DAO
20  *		LOOP
21  *			Open Track	- Set Write Parameter ???
22  *			Get Next wr. Addr.	-> DUMMY "0" ???
23  *			Write Track Data	OK
24  *			Close Track	- Flush Cache -> DUMMY
25  *		END
26  *		Fixate			- Close Track/Session -> Flush Cache
27  *		Unload Media		- OK
28  *
29  *	Verbose levels:
30  *			0		silent
31  *			1		print laser log & track sizes
32  *			2		print disk info & write parameters
33  *			3		print log pages & dvd structure
34  *
35  *	Copyright (c) 1998-2013 J. Schilling
36  */
37 /*
38  * The contents of this file are subject to the terms of the
39  * Common Development and Distribution License, Version 1.0 only
40  * (the "License").  You may not use this file except in compliance
41  * with the License.
42  *
43  * See the file CDDL.Schily.txt in this distribution for details.
44  * A copy of the CDDL is also available via the Internet at
45  * http://www.opensource.org/licenses/cddl1.txt
46  *
47  * When distributing Covered Code, include this CDDL HEADER in each
48  * file and include the License file CDDL.Schily.txt from this distribution.
49  */
50 
51 #ifndef	DEBUG
52 #define	DEBUG
53 #endif
54 #include <schily/mconfig.h>
55 
56 #include <schily/stdio.h>
57 #include <schily/stdlib.h>
58 #include <schily/unistd.h>	/* Include sys/types.h to make off_t available */
59 #include <schily/standard.h>
60 #include <schily/string.h>
61 
62 #include <schily/utypes.h>
63 #include <schily/btorder.h>
64 #include <schily/intcvt.h>
65 #include <schily/schily.h>
66 #include <schily/nlsdefs.h>
67 
68 #include <scg/scgcmd.h>
69 #include <scg/scsidefs.h>
70 #include <scg/scsireg.h>
71 #include <scg/scsitransp.h>
72 
73 #include "scsimmc.h"
74 #include "scsilog.h"
75 #include "mmcvendor.h"
76 #include "cdrecord.h"
77 
78 
79 extern	char	*driveropts;
80 
81 extern	int	lverbose;
82 extern	int	xdebug;
83 
84 #define	strbeg(s1, s2)	(strstr((s2), (s1)) == (s2))
85 
86 LOCAL	cdr_t	*identify_dvd		__PR((SCSI *scgp, cdr_t *, struct scsi_inquiry *));
87 LOCAL	int	attach_dvd		__PR((SCSI *scgp, cdr_t *));
88 LOCAL	void	di_to_dstat		__PR((struct disk_info *dip, dstat_t *dsp));
89 LOCAL	int	init_dvd		__PR((SCSI *scgp, cdr_t *dp));
90 LOCAL	int	getdisktype_dvd		__PR((SCSI *scgp, cdr_t *dp));
91 LOCAL	int	prdiskstatus_dvd	__PR((SCSI *scgp, cdr_t *dp));
92 LOCAL	int	speed_select_dvd	__PR((SCSI *scgp, cdr_t *dp, int *speedp));
93 LOCAL	int 	session_offset_dvd	__PR((SCSI *scgp, long *offp));
94 LOCAL	int	next_wr_addr_dvd	__PR((SCSI *scgp, track_t *trackp, long *ap));
95 LOCAL	int	open_track_dvd		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
96 LOCAL	long	rzone_size		__PR((track_t *trackp));
97 LOCAL	int	close_track_dvd		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
98 LOCAL	int	open_session_dvd	__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
99 LOCAL	int	waitformat		__PR((SCSI *scgp, int secs));
100 LOCAL	int	fixate_dvd		__PR((SCSI *scgp, cdr_t *dp, track_t *trackp));
101 LOCAL	int	blank_dvd		__PR((SCSI *scgp, cdr_t *dp, long addr, int blanktype));
102 LOCAL	int	stats_dvd		__PR((SCSI *scgp, cdr_t *dp));
103 #ifdef	__needed__
104 LOCAL	int	read_rzone_info		__PR((SCSI *scgp, caddr_t bp, int cnt));
105 LOCAL	int	reserve_rzone		__PR((SCSI *scgp, long size));
106 #endif
107 /*LOCAL	int	send_dvd_structure	__PR((SCSI *scgp, caddr_t bp, int cnt));*/
108 #ifdef	__needed__
109 LOCAL	int	set_layerbreak		__PR((SCSI *scgp, long	tsize, Int32_t lbreak));
110 #endif
111 LOCAL	void	print_dvd00		__PR((struct dvd_structure_00 *dp));
112 LOCAL	void	print_dvd01		__PR((struct dvd_structure_01 *dp));
113 LOCAL	void	print_dvd04		__PR((struct dvd_structure_04 *dp));
114 LOCAL	void	print_dvd05		__PR((struct dvd_structure_05 *dp));
115 LOCAL	void	print_dvd0D		__PR((struct dvd_structure_0D *dp));
116 LOCAL	void	print_dvd0E		__PR((struct dvd_structure_0E *dp));
117 LOCAL	void	print_dvd0F		__PR((struct dvd_structure_0F *dp));
118 LOCAL	void	print_dvd20		__PR((struct dvd_structure_20 *dp));
119 LOCAL	void	print_dvd22		__PR((struct dvd_structure_22 *dp));
120 LOCAL	void	print_dvd23		__PR((struct dvd_structure_23 *dp));
121 #ifdef	__needed__
122 LOCAL	void	send_dvd0F		__PR((SCSI *scgp));
123 #endif
124 /*LOCAL	void	print_dvd_info		__PR((SCSI *scgp));*/
125 EXPORT	void	print_dvd_info		__PR((SCSI *scgp));
126 LOCAL	void	print_laserlog		__PR((SCSI *scgp));
127 
128 cdr_t	cdr_dvd = {
129 	0, 0, 0,
130 	CDR_DVD|CDR_SWABAUDIO,
131 	CDR2_NOCD,
132 	CDR_CDRW_ALL,
133 	WM_SAO,
134 	1000, 1000,
135 	"mmc_dvd",
136 	"generic SCSI-3/mmc-2 DVD-R/DVD-RW/DVD-RAM driver",
137 	0,
138 	(dstat_t *)0,
139 	identify_dvd,
140 	attach_dvd,
141 	init_dvd,
142 	getdisktype_dvd,
143 	prdiskstatus_dvd,
144 	scsi_load,
145 	scsi_unload,
146 	read_buff_cap,
147 	cmd_dummy,					/* recovery_needed */
148 	(int(*)__PR((SCSI *, cdr_t *, int)))cmd_dummy,	/* recover	*/
149 	speed_select_dvd,
150 	select_secsize,
151 	next_wr_addr_dvd,
152 	(int(*)__PR((SCSI *, Ulong)))cmd_ill,		/* reserve_track */
153 	scsi_cdr_write,
154 	(int(*)__PR((track_t *, void *, BOOL)))cmd_dummy,	/* gen_cue */
155 	(int(*)__PR((SCSI *scgp, cdr_t *, track_t *)))cmd_dummy, /* send_cue */
156 	(int(*)__PR((SCSI *, cdr_t *, track_t *)))cmd_dummy, /* leadin */
157 	open_track_dvd,
158 	close_track_dvd,
159 	open_session_dvd,
160 	cmd_dummy,
161 	cmd_dummy,					/* abort	*/
162 	session_offset_dvd,
163 	fixate_dvd,
164 	stats_dvd,
165 	blank_dvd,
166 	format_dummy,
167 	(int(*)__PR((SCSI *, caddr_t, int, int)))NULL,	/* no OPC	*/
168 	cmd_dummy,					/* opt1		*/
169 	cmd_dummy,					/* opt2		*/
170 };
171 
172 
173 LOCAL cdr_t *
identify_dvd(scgp,dp,ip)174 identify_dvd(scgp, dp, ip)
175 	SCSI			*scgp;
176 	cdr_t			*dp;
177 	struct scsi_inquiry	*ip;
178 {
179 	BOOL	dvd	 = FALSE;	/* DVD writer	*/
180 	Uchar	mode[0x100];
181 	struct	cd_mode_page_2A *mp;
182 	int	profile;
183 
184 	if (ip->type != INQ_WORM && ip->type != INQ_ROMD)
185 		return ((cdr_t *)0);
186 
187 	allow_atapi(scgp, TRUE); /* Try to switch to 10 byte mode cmds */
188 
189 	scgp->silent++;
190 	mp = mmc_cap(scgp, mode); /* Get MMC capabilities */
191 	scgp->silent--;
192 	if (mp == NULL)
193 		return (NULL);	/* Pre SCSI-2/mmc drive		*/
194 
195 	/*
196 	 * At this point we know that we have a SCSI-3/mmc compliant drive.
197 	 * Unfortunately ATAPI drives violate the SCSI spec in returning
198 	 * a response data format of '1' which from the SCSI spec would
199 	 * tell us not to use the "PF" bit in mode select. As ATAPI drives
200 	 * require the "PF" bit to be set, we 'correct' the inquiry data.
201 	 *
202 	 * XXX xxx_identify() should not have any side_effects ??
203 	 */
204 	if (ip->data_format < 2)
205 		ip->data_format = 2;
206 
207 	dvd = mp->dvd_r_write;		/* Mode page 0x2A DVD-R writer */
208 
209 	/*
210 	 * Be careful, Lite-ON drives are lying in mode page 0x2A.
211 	 * We need to check the MMC-3 profile list too.
212 	 */
213 	profile = get_curprofile(scgp);
214 	if (profile >= 0x11 && profile <= 0x19)
215 		dvd = TRUE;
216 
217 	if (!dvd)
218 		get_wproflist(scgp, NULL, &dvd, NULL, NULL);
219 
220 	if (!dvd)			/* Any DVD- writer		*/
221 		return (NULL);
222 
223 	return (dp);
224 }
225 
226 LOCAL int
attach_dvd(scgp,dp)227 attach_dvd(scgp, dp)
228 	SCSI	*scgp;
229 	cdr_t	*dp;
230 {
231 	Uchar	mode[0x100];
232 	struct	cd_mode_page_2A *mp;
233 	struct	ricoh_mode_page_30 *rp = NULL;
234 	Ulong	xspeed;
235 	Ulong	mp2Aspeed;
236 
237 
238 	allow_atapi(scgp, TRUE); /* Try to switch to 10 byte mode cmds */
239 
240 	scgp->silent++;
241 	mp = mmc_cap(scgp, NULL); /* Get MMC capabilities in allocated mp */
242 	scgp->silent--;
243 	if (mp == NULL)
244 		return (-1);	/* Pre SCSI-3/mmc drive		*/
245 
246 	dp->cdr_cdcap = mp;	/* Store MMC cap pointer	*/
247 
248 	/*
249 	 * XXX hier sollte drive max write speed & drive cur write speed
250 	 * XXX gesetzt werden.
251 	 */
252 	dp->cdr_dstat->ds_dr_max_rspeed = a_to_u_2_byte(mp->max_read_speed)/1385;
253 	if (dp->cdr_dstat->ds_dr_max_rspeed == 0)
254 		dp->cdr_dstat->ds_dr_max_rspeed = 47;
255 	dp->cdr_dstat->ds_dr_cur_rspeed = a_to_u_2_byte(mp->cur_read_speed)/1385;
256 	if (dp->cdr_dstat->ds_dr_cur_rspeed == 0)
257 		dp->cdr_dstat->ds_dr_cur_rspeed = 47;
258 
259 	dp->cdr_dstat->ds_dr_max_wspeed = a_to_u_2_byte(mp->max_write_speed)/1385;
260 	if (mp->p_len >= 28)
261 		dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->v3_cur_write_speed)/1385;
262 	else
263 		dp->cdr_dstat->ds_dr_cur_wspeed = a_to_u_2_byte(mp->cur_write_speed)/1385;
264 
265 	/*
266 	 * NEC drives incorrectly return CD speed values in mode page 2A.
267 	 * Try MMC3 get performance in hope that values closer to DVD speeds
268 	 * are always more correct than what is found in mode page 2A.
269 	 */
270 	xspeed = 0;
271 	scsi_get_perf_maxspeed(scgp, NULL, &xspeed, NULL);
272 
273 	mp2Aspeed = a_to_u_2_byte(mp->max_write_speed);
274 
275 	if (lverbose > 2) {
276 		printf(_("max page 2A speed %lu (%lux), max perf speed %lu (%lux)\n"),
277 			mp2Aspeed, mp2Aspeed/1385,
278 			xspeed, xspeed/1385);
279 	}
280 
281 	if ((is_cdspeed(mp2Aspeed) && !is_cdspeed(xspeed)) ||
282 	    (mp2Aspeed < 10000 && xspeed > 10000)) {
283 		dp->cdr_dstat->ds_dr_max_wspeed = xspeed/1385;
284 		xspeed = 0;
285 		scsi_get_perf_curspeed(scgp, NULL, &xspeed, NULL);
286 		if (xspeed > 0)
287 			dp->cdr_dstat->ds_dr_cur_wspeed = xspeed / 1385;
288 	}
289 
290 	if (dp->cdr_speedmax > dp->cdr_dstat->ds_dr_max_wspeed)
291 		dp->cdr_speedmax = dp->cdr_dstat->ds_dr_max_wspeed;
292 
293 	if (dp->cdr_speeddef > dp->cdr_speedmax)
294 		dp->cdr_speeddef = dp->cdr_speedmax;
295 
296 	rp = get_justlink_ricoh(scgp, mode);
297 
298 	if (mp->p_len >= 28)
299 		dp->cdr_flags |= CDR_MMC3;
300 	if (mp->p_len >= 24)
301 		dp->cdr_flags |= CDR_MMC2;
302 	dp->cdr_flags |= CDR_MMC;
303 
304 	if (mp->loading_type == LT_TRAY)
305 		dp->cdr_flags |= CDR_TRAYLOAD;
306 	else if (mp->loading_type == LT_CADDY)
307 		dp->cdr_flags |= CDR_CADDYLOAD;
308 
309 	if (mp->BUF != 0)
310 		dp->cdr_flags |= CDR_BURNFREE;
311 
312 	check_writemodes_mmc(scgp, dp);
313 	/*
314 	 * To avoid that silly people try to call cdrecord will write modes
315 	 * that are illegal for DVDs, we clear anything that does now work.
316 	 */
317 	dp->cdr_flags &= ~(CDR_RAW|CDR_RAW16|CDR_RAW96P|CDR_RAW96R|CDR_SRAW96P|CDR_SRAW96R);
318 	dp->cdr_flags &= ~(CDR_TAO);
319 
320 	if (scgp->inq != NULL) {
321 		if (strbeg("PIONEER", scgp->inq->inq_vendor_info)) {
322 			if (strbeg("DVD-RW  DVR-103", scgp->inq->inq_prod_ident) ||
323 			    strbeg("DVD-R DVD-R7322", scgp->inq->inq_prod_ident)) {
324 				mp->BUF = 1;
325 			}
326 		}
327 	}
328 	if (mp->BUF != 0) {
329 		dp->cdr_flags |= CDR_BURNFREE;
330 	} else if (rp) {
331 		if ((dp->cdr_cmdflags & F_DUMMY) && rp->TWBFS && rp->BUEFS)
332 			dp->cdr_flags |= CDR_BURNFREE;
333 
334 		if (rp->BUEFS)
335 			dp->cdr_flags |= CDR_BURNFREE;
336 	}
337 
338 	if (rp && rp->AWSCS)
339 		dp->cdr_flags |= CDR_FORCESPEED;
340 
341 
342 	if ((dp->cdr_flags & (CDR_SAO)) != (CDR_SAO)) {
343 		/*
344 		 * XXX Ist dies ueberhaupt noch notwendig seit wir nicht
345 		 * XXX mehr CDR_TAO vorgaukeln muessen?
346 		 *
347 		 * Das Panasonic DVD-R mag check_writemodes_mmc() nicht
348 		 * hilft das vielleicht?
349 		 */
350 		dp->cdr_flags |= CDR_SAO;
351 	}
352 
353 	if (driveropts != NULL) {
354 		char	*p;
355 
356 		if (strcmp(driveropts, "help") == 0) {
357 			mmc_opthelp(scgp, dp, 0);
358 		}
359 
360 		p = hasdrvopt(driveropts, "burnfree");
361 		if (p == NULL)
362 			p = hasdrvopt(driveropts, "burnproof");
363 		if (p != NULL && (dp->cdr_flags & CDR_BURNFREE) != 0) {
364 			if (*p == '1') {
365 				dp->cdr_dstat->ds_cdrflags |= RF_BURNFREE;
366 			} else if (*p == '0') {
367 				dp->cdr_dstat->ds_cdrflags &= ~RF_BURNFREE;
368 			}
369 		}
370 
371 		p = hasdrvopt(driveropts, "forcespeed");
372 		if (p != NULL && *p == '1' && (dp->cdr_flags & CDR_FORCESPEED) != 0) {
373 			dp->cdr_dstat->ds_cdrflags |= RF_FORCESPEED;
374 		}
375 
376 		p = hasdrvoptx(driveropts, "layerbreak", 0);
377 		if (p != NULL && *p != '\0') {
378 			char	*ep;
379 			Llong	ll;
380 			Int32_t	lb;
381 
382 			ep = astoll(p, &ll);
383 			lb = ll;
384 			if ((*ep != '\0' && *ep != ',') ||
385 			    ll <= 0 || ll != lb) {
386 				errmsgno(EX_BAD,
387 					_("Bad layer break value '%s'.\n"), p);
388 				return (-1);
389 			}
390 			dp->cdr_dstat->ds_layer_break = lb;
391 		} else {
392 			p = hasdrvopt(driveropts, "layerbreak");
393 			if (p != NULL && *p == '1')
394 				dp->cdr_dstat->ds_layer_break = 0;
395 		}
396 		if (dp->cdr_dstat->ds_layer_break >= 0 &&
397 		    (dp->cdr_flags & CDR_LAYER_JUMP) == 0) {
398 			errmsgno(EX_BAD,
399 			_("Cannot set layer break on this drive/medium.\n"));
400 			return (-1);
401 		}
402 		if (dp->cdr_dstat->ds_layer_break != -1 &&
403 		    dp->cdr_dstat->ds_layer_break !=
404 		    roundup(dp->cdr_dstat->ds_layer_break, 16)) {
405 			errmsgno(EX_BAD,
406 			_("Layer break at %u is not properly aligned.\n"),
407 				dp->cdr_dstat->ds_layer_break);
408 			return (-1);
409 		}
410 	}
411 
412 	/*
413 	 * Raise the default timeout.
414 	 * The first write takes a long time as it writes the lead in.
415 	 */
416 	if (scgp->deftimeout < 100)
417 		scg_settimeout(scgp, 100);	/* 1:40			*/
418 
419 	return (0);
420 }
421 
422 LOCAL void
di_to_dstat(dip,dsp)423 di_to_dstat(dip, dsp)
424 	struct disk_info	*dip;
425 	dstat_t	*dsp;
426 {
427 	dsp->ds_diskid = a_to_u_4_byte(dip->disk_id);
428 
429 	dsp->ds_flags |= DSF_NOCD|DSF_DVD;	/* This is a DVD */
430 
431 	if (dip->did_v)
432 		dsp->ds_flags |= DSF_DID_V;
433 	dsp->ds_disktype = dip->disk_type;
434 	dsp->ds_diskstat = dip->disk_status;
435 	dsp->ds_sessstat = dip->sess_status;
436 	if (dip->erasable)
437 		dsp->ds_flags |= DSF_ERA;
438 
439 	dsp->ds_trfirst	   = dip->first_track;
440 	dsp->ds_trlast	   = dip->last_track_ls;
441 	dsp->ds_trfirst_ls = dip->first_track_ls;
442 
443 #ifdef	nono
444 	/*
445 	 * On DVD systems, there is no lead out start time
446 	 * in the disk info because there is no time based data.
447 	 */
448 	dsp->ds_maxblocks = msf_to_lba(dip->last_lead_out[1],
449 					dip->last_lead_out[2],
450 					dip->last_lead_out[3], TRUE);
451 #endif
452 }
453 
454 LOCAL int
init_dvd(scgp,dp)455 init_dvd(scgp, dp)
456 	SCSI	*scgp;
457 	cdr_t	*dp;
458 {
459 	return (speed_select_dvd(scgp, dp, NULL));
460 }
461 
462 LOCAL int
getdisktype_dvd(scgp,dp)463 getdisktype_dvd(scgp, dp)
464 	SCSI	*scgp;
465 	cdr_t	*dp;
466 {
467 extern	char	*buf;
468 	dstat_t	*dsp = dp->cdr_dstat;
469 	struct disk_info *dip;
470 	Uchar	mode[0x100];
471 	struct rzone_info rz;
472 	struct rzone_info *rp;
473 	struct dvd_structure_00 *sp;
474 	int	profile;
475 	int	len;
476 	BOOL	did_dummy = FALSE;
477 
478 	if (lverbose > 0)
479 		print_laserlog(scgp);
480 
481 	if (lverbose > 2)
482 		print_logpages(scgp);
483 
484 
485 	if (dsp->ds_type == DST_UNKNOWN) {
486 		profile = get_curprofile(scgp);
487 		if (profile >= 0)
488 			dsp->ds_type = profile;
489 	}
490 
491 	if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0) {
492 		if (((dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == 0) ||
493 				lverbose > 1) {
494 			/*
495 			 * Das DVD Medieninfo ist so lang, da� wir es
496 			 * beim Schreiben mit -v noch nicht ausgeben.
497 			 */
498 			print_dvd_info(scgp);
499 		}
500 	}
501 
502 again:
503 	dip = (struct disk_info *)buf;
504 	if (get_diskinfo(scgp, dip, sizeof (*dip)) < 0)
505 		return (-1);
506 
507 	/*
508 	 * Check for non writable disk first.
509 	 */
510 	if (dip->disk_status == DS_COMPLETE &&
511 			(dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == RF_WRITE) {
512 		if (!did_dummy) {
513 			int	xspeed = 0xFFFF;
514 			int	oflags = dp->cdr_cmdflags;
515 
516 			/*
517 			 * Try to clear the dummy bit to reset the virtual
518 			 * drive status. Not all drives support it even though
519 			 * it is mentioned in the MMC standard.
520 			 */
521 			if (lverbose)
522 				printf(_("Trying to clear drive status.\n"));
523 
524 			dp->cdr_cmdflags &= ~F_DUMMY;
525 			speed_select_dvd(scgp, dp, &xspeed);
526 			dp->cdr_cmdflags = oflags;
527 			did_dummy = TRUE;
528 			goto again;
529 		}
530 		/*
531 		 * Trying to clear drive status did not work...
532 		 */
533 		reload_media(scgp, dp);
534 	}
535 	if (get_diskinfo(scgp, dip, sizeof (*dip)) < 0)
536 		return (-1);
537 	di_to_dstat(dip, dsp);
538 
539 	/*
540 	 * This information is based on a logical recording zone
541 	 * and may not always be correct.
542 	 * XXX Check this if we want to support anything else but
543 	 * XXX one data track on DAO mode. The current firmware
544 	 * XXX of the recorder supports only this method but future
545 	 * XXX releases may support more.
546 	 */
547 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
548 	rp = (struct rzone_info *)mode;
549 	read_rzone_info(scgp, (caddr_t)rp, sizeof (struct rzone_info));
550 
551 	if ((dp->cdr_dstat->ds_cdrflags & RF_PRATIP) != 0) {
552 		if (((dsp->ds_cdrflags & (RF_WRITE|RF_BLANK)) == 0) ||
553 				lverbose > 1) {
554 			przone(rp);
555 			print_format_capacities(scgp);
556 		}
557 	}
558 	movebytes(mode, (caddr_t)&rz, sizeof (struct rzone_info));
559 #ifdef	nonono_old_code
560 	/*
561 	 * Old code used with the S101 seems to be a bad idea....
562 	 * The new code seems to work with all DVD drives.
563 	 */
564 	dsp->ds_maxblocks = a_to_u_4_byte(rp->rzone_size);
565 	if (dsp->ds_maxblocks == 0)
566 #endif
567 	dsp->ds_maxblocks = a_to_u_4_byte(rp->free_blocks);
568 	if (rp->nwa_v)
569 		dsp->ds_maxblocks += a_to_u_4_byte(rp->next_recordable_addr);
570 
571 	/*
572 	 * This information is based on the physical pre recorded information.
573 	 * First try to find the len supported by the actual drive.
574 	 */
575 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
576 	if (read_dvd_structure(scgp, (caddr_t)mode, 2, 0, 0, 0, 0) < 0) {
577 		errmsgno(EX_BAD, _("Cannot read DVD structure.\n"));
578 		return (-1);
579 	}
580 	len = a_to_u_2_byte(mode);
581 	len += 2;			/* Data len is not included */
582 
583 	if (len > sizeof (struct dvd_structure_00)) {
584 		len = sizeof (struct dvd_structure_00);
585 		/*
586 		 * The ACARD TECH AEC-7720 ATAPI<->SCSI adaptor
587 		 * chokes if we try to transfer odd byte counts (rounds up to
588 		 * even byte counts and thus causes a DMA overflow and a
589 		 * bus reset), so make the byte count even.
590 		 */
591 		len += 1;
592 		len &= ~1;
593 	}
594 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
595 	sp = (struct dvd_structure_00 *)mode;
596 	read_dvd_structure(scgp, (caddr_t)sp, len, 0, 0, 0, 0);
597 /*	if (lverbose > 1)*/
598 /*		print_dvd00(sp);*/
599 	if (((struct dvd_structure_00 *)sp)->book_type == 1) {
600 		dsp->ds_type = DST_DVD_RAM;
601 	} else {
602 		dsp->ds_type = DST_UNKNOWN;
603 	}
604 	if (get_curprofile(scgp) == 0x12) {
605 		dsp->ds_type = DST_DVD_RAM;
606 	}
607 	if (dsp->ds_type == DST_DVD_RAM)
608 		dsp->ds_maxblocks = a_to_u_4_byte(rz.rzone_size);
609 	/*
610 	 * Bei Pioneer ist Phys End ist nur bei dem S101 != 0.
611 	 * Bei Panasonic ist Phys End == Phys Start.
612 	 * Do not print this for -msinfo
613 	 */
614 	if ((dp->cdr_cmdflags & F_MSINFO) == 0 &&
615 	    (a_to_u_3_byte(sp->phys_end) != 0) &&
616 			(dsp->ds_maxblocks !=
617 			(long)(a_to_u_3_byte(sp->phys_end) - a_to_u_3_byte(sp->phys_start) + 1))) {
618 		/*
619 		 * NEC 'DVD_RW ND-3500AG' mit 'MCC 03RG20  ' DVD-R (leer):
620 		 * dsp->ds_maxblocks:	2298496
621 		 * sp->phys_start:	196608 (0x30000)
622 		 * sp->phys_end:	2495103
623 		 *			2298496 = 2495103 - 196608 +1
624 		 * Bei diesen Parametern gibt es keine Warnung.
625 		 */
626 
627 		printf(_("WARNING: Phys disk size %ld differs from rzone size %ld! Prerecorded disk?\n"),
628 			(long)(a_to_u_3_byte(sp->phys_end) - a_to_u_3_byte(sp->phys_start) + 1),
629 			(long)dsp->ds_maxblocks);
630 		printf(_("WARNING: Phys start: %ld Phys end %ld\n"),
631 			(long)a_to_u_3_byte(sp->phys_start),
632 			(long)a_to_u_3_byte(sp->phys_end));
633 
634 		/*
635 		 * Workaround for some drive media combinations.
636 		 * At least the drive	'HL-DT-ST' 'DVD-RAM GH22NP20' '1.02'
637 		 * does not report maxblocks correctly with 'MCC 03RG20  ' media.
638 		 * Use the information from ADIP instead.
639 		 */
640 		if (dsp->ds_maxblocks == 0) {
641 			printf(_("WARNING: Drive returns zero media size. Using media size from ADIP.\n"));
642 			dsp->ds_maxblocks = a_to_u_3_byte(sp->phys_end) - a_to_u_3_byte(sp->phys_start) + 1;
643 		}
644 	}
645 
646 	return (drive_getdisktype(scgp, dp));
647 }
648 
649 LOCAL int
prdiskstatus_dvd(scgp,dp)650 prdiskstatus_dvd(scgp, dp)
651 	SCSI	*scgp;
652 	cdr_t	*dp;
653 {
654 	return (prdiskstatus(scgp, dp, FALSE));
655 }
656 
657 LOCAL int
speed_select_dvd(scgp,dp,speedp)658 speed_select_dvd(scgp, dp, speedp)
659 	SCSI	*scgp;
660 	cdr_t	*dp;
661 	int	*speedp;
662 {
663 	Uchar	mode[0x100];
664 	Uchar	moder[0x100];
665 	int	len;
666 	struct	cd_mode_page_05 *mp;
667 	struct	ricoh_mode_page_30 *rp = NULL;
668 	int	val;
669 	Ulong	ul;
670 	BOOL	forcespeed = FALSE;
671 	BOOL	dummy = (dp->cdr_cmdflags & F_DUMMY) != 0;
672 	int	curspeed = 1;
673 
674 
675 	if (speedp)
676 		curspeed = *speedp;
677 
678 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
679 
680 	if (!get_mode_params(scgp, 0x05, _("CD write parameter"),
681 			mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
682 		return (-1);
683 	if (len == 0)
684 		return (-1);
685 
686 	mp = (struct cd_mode_page_05 *)
687 		(mode + sizeof (struct scsi_mode_header) +
688 		((struct scsi_mode_header *)mode)->blockdesc_len);
689 #ifdef	DEBUG
690 	if (lverbose > 1)
691 		scg_prbytes(_("CD write parameter:"), (Uchar *)mode, len);
692 #endif
693 
694 	if (dp->cdr_dstat->ds_type == DST_DVD_RAM && dummy != 0) {
695 		errmsgno(EX_BAD, _("DVD-RAM has no -dummy mode.\n"));
696 		return (-1);
697 	}
698 
699 	mp->test_write = dummy != 0;
700 	/*
701 	 * Set default values:
702 	 * Write type = 02 (disk at once)
703 	 * Track mode = 00 Reserved on Pioneer DVR-S101
704 	 * Data block type = 00 Reserved on Pioneer DVR-S101
705 	 * Session format = 00 Reserved on Pioneer DVR-S101
706 	 * XXX DVR-S101 uses ls_v and link size violating
707 	 * XXX the current MMC2 spec.
708 	 */
709 	mp->write_type = WT_SAO;
710 	if (dp->cdr_dstat->ds_layer_break >= 0)
711 		mp->write_type = WT_LAYER_JUMP;
712 
713 #ifdef	DEBUG
714 	if (lverbose > 1)
715 		scg_prbytes(_("CD write parameter:"), (Uchar *)mode, len);
716 #endif
717 	if (!set_mode_params(scgp, _("CD write parameter"), mode, len, 0, -1))
718 		return (-1);
719 
720 	/*
721 	 * Neither set nor get speed.
722 	 */
723 	if (speedp == 0)
724 		return (0);
725 
726 
727 	rp = get_justlink_ricoh(scgp, moder);
728 	if ((dp->cdr_flags & CDR_FORCESPEED) != 0) {
729 		forcespeed = rp && rp->AWSCD != 0;
730 	}
731 
732 	if (lverbose && (dp->cdr_flags & CDR_FORCESPEED) != 0)
733 		printf(_("Forcespeed is %s.\n"), forcespeed?_("ON"):_("OFF"));
734 
735 	if (!forcespeed && (dp->cdr_dstat->ds_cdrflags & RF_FORCESPEED) != 0) {
736 		printf(_("Turning forcespeed on\n"));
737 		forcespeed = TRUE;
738 	}
739 	if (forcespeed && (dp->cdr_dstat->ds_cdrflags & RF_FORCESPEED) == 0) {
740 		printf(_("Turning forcespeed off\n"));
741 		forcespeed = FALSE;
742 	}
743 	if ((dp->cdr_flags & CDR_FORCESPEED) != 0) {
744 
745 		if (rp) {
746 			rp->AWSCD = forcespeed?1:0;
747 			set_mode_params(scgp, _("Ricoh Vendor Page"), moder, moder[0]+1, 0, -1);
748 			rp = get_justlink_ricoh(scgp, moder);
749 		}
750 	}
751 
752 	/*
753 	 * DVD single speed is 1385 kB/s
754 	 * Rounding down is guaranteed.
755 	 */
756 	val = curspeed*1390;
757 	if (val > 0x7FFFFFFF)
758 		val = 0x7FFFFFFF;
759 	if (dp->cdr_flags & CDR_MMC3) {
760 		if (speed_select_mdvd(scgp, -1, val) < 0)
761 			errmsgno(EX_BAD, _("MMC-3 speed select did not work.\n"));
762 	} else {
763 		if (val > 0xFFFF)
764 			val = 0xFFFF;
765 		scgp->silent++;
766 		if (scsi_set_speed(scgp, -1, val, ROTCTL_CLV) < 0) {
767 			/*
768 			 * Don't complain if it does not work,
769 			 * DVD drives may not have speed setting.
770 			 * The DVR-S101 and the DVR-S201 difinitely
771 			 * don't allow to set the speed.
772 			 */
773 		}
774 		scgp->silent--;
775 	}
776 
777 	scgp->silent++;
778 	val = 0;
779 	if (scsi_get_speed(scgp, 0, &val) >= 0) {
780 		if (val > 0) {
781 			curspeed = val / 1385;
782 			*speedp = curspeed;
783 		}
784 	}
785 	/*
786 	 * NEC drives incorrectly return CD speed values in mode page 2A.
787 	 * Try MMC3 get performance in hope that values closer to DVD speeds
788 	 * are always more correct than what is found in mode page 2A.
789 	 */
790 	ul = 0;
791 	if (scsi_get_perf_curspeed(scgp, NULL, &ul, NULL) >= 0) {
792 		if (is_cdspeed(val) && !is_cdspeed(ul)) {
793 			curspeed = ul / 1385;
794 			*speedp = curspeed;
795 		}
796 	}
797 
798 	scgp->silent--;
799 	return (0);
800 }
801 
802 LOCAL int
session_offset_dvd(scgp,offp)803 session_offset_dvd(scgp, offp)
804 	SCSI	*scgp;
805 	long	*offp;
806 {
807 	return (sessstatus(scgp, FALSE, offp, (long *)NULL));
808 }
809 
810 LOCAL long	dvd_next_addr;
811 
812 LOCAL int
next_wr_addr_dvd(scgp,trackp,ap)813 next_wr_addr_dvd(scgp, trackp, ap)
814 	SCSI	*scgp;
815 	track_t	*trackp;
816 	long	*ap;
817 {
818 	struct disk_info	di;
819 	struct rzone_info	rz;
820 	int			tracks;
821 	long			next_addr = -1;
822 
823 	/*
824 	 * If the track pointer is set to NULL, our caller likes to get
825 	 * the next writable address for the next (unwritten) session.
826 	 */
827 	if (trackp == 0) {
828 		fillbytes((caddr_t)&di, sizeof (di), '\0');
829 		if (get_diskinfo(scgp, &di, sizeof (di)) < 0)
830 			return (-1);
831 
832 		tracks = di.last_track_ls + di.last_track_ls_msb * 256;
833 		fillbytes((caddr_t)&rz, sizeof (rz), '\0');
834 		if (get_trackinfo(scgp, (caddr_t)&rz, TI_TYPE_TRACK, tracks, sizeof (rz)) < 0)
835 			return (-1);
836 		if (!rz.nwa_v)
837 			return (-1);
838 		next_addr = a_to_4_byte(rz.next_recordable_addr);
839 		if (ap)
840 			*ap = next_addr;
841 		return (0);
842 	}
843 	if (trackp->track <= 1) {
844 		/*
845 		 * XXX This is a workaround for the filesize > 2GB problem.
846 		 * XXX Check this if we support more than one track DAO
847 		 * XXX or if we give up this hack in favour of real 64bit
848 		 * XXX filesize support.
849 		 */
850 		fillbytes((caddr_t)&rz, sizeof (rz), '\0');
851 		if (track_base(trackp)->tracktype & TOCF_MULTI)
852 			get_trackinfo(scgp, (caddr_t)&rz, TI_TYPE_TRACK, trackp->trackno, sizeof (rz));
853 		else
854 			read_rzone_info(scgp, (caddr_t)&rz, sizeof (struct rzone_info));
855 		dvd_next_addr = a_to_4_byte(rz.next_recordable_addr);
856 		if (lverbose > 1)
857 			printf(_("next writable addr: %ld valid: %d\n"), dvd_next_addr, rz.nwa_v);
858 	}
859 	if (ap)
860 		*ap = dvd_next_addr;
861 	return (0);
862 }
863 
864 LOCAL int
open_track_dvd(scgp,dp,trackp)865 open_track_dvd(scgp, dp, trackp)
866 	SCSI	*scgp;
867 	cdr_t	*dp;
868 	track_t *trackp;
869 {
870 	Uchar	mode[0x100];
871 	int	len;
872 	long	sectors;
873 	struct	cd_mode_page_05 *mp;
874 
875 	if (trackp->track > 1)	/* XXX Hack to make one 'track' from several */
876 		return (0);	/* XXX files in Disk at once mode only.	    */
877 
878 	if (dp->cdr_dstat->ds_type == DST_DVD_RAM) {
879 		/*
880 		 * Compile vitual track list
881 		 */
882 		sectors = rzone_size(trackp);
883 		if (sectors < 0)
884 			return (-1);
885 		return (0);	/* No further setup needed */
886 	}
887 
888 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
889 
890 	if (!get_mode_params(scgp, 0x05, _("CD write parameter"),
891 			mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
892 		return (-1);
893 	if (len == 0)
894 		return (-1);
895 
896 	mp = (struct cd_mode_page_05 *)
897 		(mode + sizeof (struct scsi_mode_header) +
898 		((struct scsi_mode_header *)mode)->blockdesc_len);
899 
900 	/*
901 	 * XXX as long as the Pioneer DVR-S101 only supports a single
902 	 * XXX data track in DAO mode,
903 	 * XXX do not set:
904 	 * XXX track_mode
905 	 * XXX copy
906 	 * XXX dbtype
907 	 *
908 	 * Track mode = 00 Reserved on Pioneer DVR-S101
909 	 * Data block type = 00 Reserved on Pioneer DVR-S101
910 	 * Session format = 00 Reserved on Pioneer DVR-S101
911 	 * XXX DVR-S101 uses ls_v and link size violating
912 	 * XXX the current MMC2 spec.
913 	 */
914 	/* XXX look into drv_mmc.c for re-integration of above settings */
915 
916 #ifdef	DEBUG
917 	if (lverbose > 1)
918 		scg_prbytes(_("CD write parameter:"), (Uchar *)mode, len);
919 #endif
920 	if (!set_mode_params(scgp, _("CD write parameter"), mode, len, 0, trackp->secsize))
921 		return (-1);
922 
923 	/*
924 	 * Compile vitual track list
925 	 */
926 	sectors = rzone_size(trackp);
927 	if (sectors < 0)
928 		return (-1);
929 	return (reserve_tr_rzone(scgp, sectors));
930 }
931 
932 /*
933  * XXX Hack to make one 'track' from several
934  * XXX files in Disk at once mode only.
935  * XXX Calculate track size and reserve rzone.
936  */
937 LOCAL long
rzone_size(trackp)938 rzone_size(trackp)
939 	track_t *trackp;	/* Called with &track[1] */
940 {
941 	int	i;
942 	BOOL	vtracks = FALSE;
943 	long	sectors = 0L;
944 	Llong	ttrsize = 0L;
945 	Llong	tamount = 0L;
946 	Llong	amount;
947 	long	secsize = trackp->secsize;
948 
949 	for (i = 0; i < MAX_TRACK; i++) {
950 		if (is_last(&trackp[i]))
951 			break;
952 	}
953 	if (i >= 1)
954 		vtracks = TRUE;
955 	if (vtracks && lverbose)
956 		printf(_("Compiling virtual track list ...\n"));
957 
958 	for (i = 0; i < MAX_TRACK; i++) {
959 		if (trackp[i].tracksize < (tsize_t)0) {
960 			errmsgno(EX_BAD, _("VTrack %d has unknown length.\n"), i);
961 			return (-1);
962 		}
963 		amount = roundup(trackp[i].tracksize, secsize);
964 		amount += (Llong)trackp[i].padsecs * secsize;
965 		sectors += amount/secsize;
966 		ttrsize += trackp[i].tracksize;
967 		tamount += amount;
968 		if (vtracks && lverbose)
969 			printf(_("Vtrack:  %d size: %lld bytes %lld rounded (%lld sectors)\n"),
970 				(int)trackp[i].track, (Llong)trackp[i].tracksize,
971 				amount, amount / (Llong)secsize);
972 
973 		if (is_last(&trackp[i]))
974 			break;
975 
976 		/*
977 		 * XXX Is it possible for a DVD that input sector size
978 		 * XXX differes from output sector size?
979 		 * XXX I believe that not.
980 		 */
981 		if (trackp[i].tracksize % secsize) {
982 			comerrno(EX_BAD, _("Virtual track %d is not a multiple of secsize.\n"), (int)trackp[i].track);
983 		}
984 	}
985 
986 	if (vtracks && lverbose)
987 		printf(_("Vtracks: %d size: %lld bytes %lld rounded (%ld sectors) total\n"),
988 			i+1, ttrsize, tamount, sectors);
989 
990 	return (sectors);
991 }
992 
993 LOCAL int
close_track_dvd(scgp,dp,trackp)994 close_track_dvd(scgp, dp, trackp)
995 	SCSI	*scgp;
996 	cdr_t	*dp;
997 	track_t	*trackp;
998 {
999 	long	sectors = 0L;
1000 	Llong	amount;
1001 	long	secsize = trackp->secsize;
1002 
1003 	/*
1004 	 * Compute the start of the next "track" for the hack
1005 	 * that allows to have a track in more than one file.
1006 	 * XXX Check this if the vtrack code is removed.
1007 	 */
1008 	amount = roundup(trackp->tracksize, secsize);
1009 	amount += (Llong)trackp->padsecs * secsize;
1010 	sectors += amount/secsize;
1011 
1012 	dvd_next_addr += sectors;
1013 
1014 	return (0);
1015 }
1016 
1017 LOCAL int
open_session_dvd(scgp,dp,trackp)1018 open_session_dvd(scgp, dp, trackp)
1019 	SCSI	*scgp;
1020 	cdr_t	*dp;
1021 	track_t	*trackp;
1022 {
1023 	Uchar	mode[0x100];
1024 	Uchar	moder[0x100];
1025 	int	len;
1026 	struct	cd_mode_page_05 *mp;
1027 	struct	ricoh_mode_page_30 *rp = NULL;
1028 	BOOL	burnfree = FALSE;
1029 
1030 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
1031 
1032 	if (!get_mode_params(scgp, 0x05, _("CD write parameter"),
1033 			mode, (Uchar *)0, (Uchar *)0, (Uchar *)0, &len))
1034 		return (-1);
1035 	if (len == 0)
1036 		return (-1);
1037 
1038 	mp = (struct cd_mode_page_05 *)
1039 		(mode + sizeof (struct scsi_mode_header) +
1040 		((struct scsi_mode_header *)mode)->blockdesc_len);
1041 
1042 	/*
1043 	 * XXX as long as the Pioneer DVR-S101 only supports a single
1044 	 * XXX data track in DAO mode,
1045 	 * XXX do not set:
1046 	 * XXX multi_session
1047 	 * XXX sessipon_format
1048 	 *
1049 	 * Track mode = 00 Reserved on Pioneer DVR-S101
1050 	 * Data block type = 00 Reserved on Pioneer DVR-S101
1051 	 * Session format = 00 Reserved on Pioneer DVR-S101
1052 	 * XXX DVR-S101 uses ls_v and link size violating
1053 	 * XXX the current MMC2 spec.
1054 	 */
1055 	/* XXX look into drv_mmc.c for re-integration of above settings */
1056 	mp->write_type = WT_SAO;
1057 	if (dp->cdr_dstat->ds_layer_break >= 0)
1058 		mp->write_type = WT_LAYER_JUMP;
1059 
1060 
1061 	rp = get_justlink_ricoh(scgp, moder);
1062 
1063 	if (dp->cdr_cdcap->BUF != 0) {
1064 		burnfree = mp->BUFE != 0;
1065 	} else if ((dp->cdr_flags & CDR_BURNFREE) != 0) {
1066 		burnfree = rp && rp->BUEFE != 0;
1067 	}
1068 
1069 	if (lverbose && (dp->cdr_flags & CDR_BURNFREE) != 0)
1070 		printf(_("BURN-Free is %s.\n"), burnfree?_("ON"):_("OFF"));
1071 
1072 	if (!burnfree && (dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) != 0) {
1073 		printf(_("Turning BURN-Free on\n"));
1074 		burnfree = TRUE;
1075 	}
1076 	if (burnfree && (dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0) {
1077 		printf(_("Turning BURN-Free off\n"));
1078 		burnfree = FALSE;
1079 	}
1080 	if (dp->cdr_cdcap->BUF != 0) {
1081 		mp->BUFE = burnfree?1:0;
1082 	} else if ((dp->cdr_flags & CDR_BURNFREE) != 0) {
1083 
1084 		if (rp)
1085 			rp->BUEFE = burnfree?1:0;
1086 	}
1087 	if (rp) {
1088 		i_to_2_byte(rp->link_counter, 0);
1089 		if (xdebug)
1090 			scg_prbytes(_("Mode Select Data "), moder, moder[0]+1);
1091 
1092 		set_mode_params(scgp, _("Ricoh Vendor Page"), moder, moder[0]+1, 0, -1);
1093 		rp = get_justlink_ricoh(scgp, moder);
1094 	}
1095 
1096 	/*
1097 	 * 05 32 40 c5  08 10 00 00
1098 	 *	 FUFE + PACKET
1099 	 *	    MULTI + NO FP + TM_DATA
1100 	 *		DB_ROM_MODE1
1101 	 *		   LINKSIZE == 16
1102 	 * mp->session_format SES_DA_ROM
1103 	 */
1104 	mp->multi_session = (track_base(trackp)->tracktype & TOCF_MULTI) ?
1105 			MS_MULTI : MS_NONE;
1106 
1107 	/*
1108 	 * If we are writing in multi-border mode, we need to write in packet
1109 	 * mode even if we have been told to write on SAO mode.
1110 	 */
1111 	if (track_base(trackp)->tracktype & TOCF_MULTI) {
1112 		mp->write_type = WT_PACKET;
1113 		mp->track_mode = TM_DATA;
1114 		mp->track_mode |= TM_INCREMENTAL;
1115 		mp->fp = 0;
1116 		i_to_4_byte(mp->packet_size, 0);
1117 		mp->link_size = 16;
1118 	}
1119 
1120 #ifdef	DEBUG
1121 	if (lverbose > 1)
1122 		scg_prbytes(_("CD write parameter:"), (Uchar *)mode, len);
1123 #endif
1124 	if (!set_mode_params(scgp, _("CD write parameter"), mode, len, 0, -1))
1125 		return (-1);
1126 
1127 	return (0);
1128 }
1129 
1130 LOCAL int
waitformat(scgp,secs)1131 waitformat(scgp, secs)
1132 	SCSI	*scgp;
1133 	int	secs;
1134 {
1135 #ifdef	DVD_DEBUG
1136 	Uchar   sensebuf[CCS_SENSE_LEN];
1137 #endif
1138 	int	i;
1139 	int	key;
1140 #define	W_SLEEP	2
1141 
1142 	scgp->silent++;
1143 	for (i = 0; i < secs/W_SLEEP; i++) {
1144 		if (test_unit_ready(scgp) >= 0) {
1145 			scgp->silent--;
1146 			return (0);
1147 		}
1148 		key = scg_sense_key(scgp);
1149 		if (key != SC_UNIT_ATTENTION && key != SC_NOT_READY)
1150 			break;
1151 #ifdef	DVD_DEBUG
1152 		request_sense_b(scgp, (caddr_t)sensebuf, sizeof (sensebuf));
1153 #ifdef	XXX
1154 		scg_prbytes(_("Sense:"), sensebuf, sizeof (sensebuf));
1155 		scgp->scmd->u_scb.cmd_scb[0] = 2;
1156 		movebytes(sensebuf, scgp->scmd->u_sense.cmd_sense, sizeof (sensebuf));
1157 		scgp->scmd->sense_count = sizeof (sensebuf);
1158 		scg_printerr(scgp);
1159 #endif
1160 /*
1161  * status: 0x2 (CHECK CONDITION)
1162  * Sense Bytes: F0 00 00 00 24 1C 10 0C 00 00 00 00 04 04 00 80 03 F6
1163  * Sense Key: 0x0 No Additional Sense, Segment 0
1164  * Sense Code: 0x04 Qual 0x04 (logical unit not ready, format in progress) Fru 0x0
1165  * Sense flags: Blk 2366480 (valid)
1166  * cmd finished after 0.000s timeout 100s
1167  * Das Fehlt:
1168  * operation 1% done
1169  */
1170 
1171 		if (sensebuf[15] & 0x80) {
1172 			error(_("operation %d%% done\n"),
1173 				(100*(sensebuf[16] << 8 |
1174 					sensebuf[17]))/(unsigned)65536);
1175 		}
1176 #endif	/* DVD_DEBUG */
1177 		sleep(W_SLEEP);
1178 	}
1179 	scgp->silent--;
1180 	return (-1);
1181 #undef	W_SLEEP
1182 }
1183 
1184 LOCAL int
fixate_dvd(scgp,dp,trackp)1185 fixate_dvd(scgp, dp, trackp)
1186 	SCSI	*scgp;
1187 	cdr_t	*dp;
1188 	track_t	*trackp;
1189 {
1190 	int	oldtimeout = scgp->deftimeout;
1191 	int	ret = 0;
1192 	int	trackno;
1193 
1194 	/*
1195 	 * This is only valid for DAO recording.
1196 	 * XXX Check this if the DVR-S101 supports more.
1197 	 * XXX flush cache currently makes sure that
1198 	 * XXX at least ~ 800 MBytes written to the track.
1199 	 * XXX flush cache triggers writing the lead out.
1200 	 */
1201 	if (scgp->deftimeout < 1000)
1202 		scg_settimeout(scgp, 1000);
1203 
1204 	if (scsi_flush_cache(scgp, FALSE) < 0) {
1205 		printf(_("Trouble flushing the cache\n"));
1206 		scg_settimeout(scgp, oldtimeout);
1207 		return (-1);
1208 	}
1209 	waitformat(scgp, 100);
1210 	trackno = trackp->trackno;
1211 	if (trackno <= 0)
1212 		trackno = 1;
1213 
1214 	scg_settimeout(scgp, oldtimeout);
1215 
1216 	if (dp->cdr_dstat->ds_type == DST_DVD_RAM) {
1217 		/*
1218 		 * XXX make sure we do not forget DVD-RAM once we did add
1219 		 * XXX support for multi-border recording.
1220 		 */
1221 		return (ret);
1222 	}
1223 	if (track_base(trackp)->tracktype & TOCF_MULTI)
1224 		scsi_close_tr_session(scgp, CL_TYPE_SESSION, trackno, TRUE);
1225 
1226 	return (ret);
1227 }
1228 
1229 LOCAL int
blank_dvd(scgp,dp,addr,blanktype)1230 blank_dvd(scgp, dp, addr, blanktype)
1231 	SCSI	*scgp;
1232 	cdr_t	*dp;
1233 	long	addr;
1234 	int	blanktype;
1235 {
1236 /*XXX*/extern char *blank_types[];
1237 
1238 	BOOL	cdrr	 = FALSE;	/* Read CD-R	*/
1239 	BOOL	cdwr	 = FALSE;	/* Write CD-R	*/
1240 	BOOL	cdrrw	 = FALSE;	/* Read CD-RW	*/
1241 	BOOL	cdwrw	 = FALSE;	/* Write CD-RW	*/
1242 	BOOL	dvdwr	 = FALSE;	/* DVD writer	*/
1243 	int	profile;
1244 
1245 	mmc_check(scgp, &cdrr, &cdwr, &cdrrw, &cdwrw, NULL, &dvdwr);
1246 	/*
1247 	 * If the drive supports MMC-3, check for a DVD-RW medium.
1248 	 */
1249 	profile = get_curprofile(scgp);
1250 	if (profile > 0)
1251 		dvdwr = (profile == 0x13) || (profile == 0x14) ||
1252 			(profile == 0x17);
1253 
1254 	if (profile == 0x12)	/* DVD-RAM */
1255 		return (blank_simul(scgp, dp, addr, blanktype));
1256 
1257 	if (!dvdwr)
1258 		return (blank_dummy(scgp, dp, addr, blanktype));
1259 
1260 	if (lverbose) {
1261 		printf(_("Blanking %s\n"), blank_types[blanktype & 0x07]);
1262 		flush();
1263 	}
1264 
1265 	return (scsi_blank(scgp, addr, blanktype, FALSE));
1266 }
1267 
1268 LOCAL int
stats_dvd(scgp,dp)1269 stats_dvd(scgp, dp)
1270 	SCSI	*scgp;
1271 	cdr_t	*dp;
1272 {
1273 	Uchar mode[256];
1274 	struct	ricoh_mode_page_30 *rp;
1275 	UInt32_t count;
1276 
1277 	if ((dp->cdr_dstat->ds_cdrflags & RF_BURNFREE) == 0)
1278 		return (0);
1279 
1280 	rp = get_justlink_ricoh(scgp, mode);
1281 	if (rp) {
1282 		count = a_to_u_2_byte(rp->link_counter);
1283 		if (lverbose) {
1284 			if (count == 0)
1285 				printf(_("BURN-Free was not used.\n"));
1286 			else
1287 				printf(_("BURN-Free was %d times used.\n"),
1288 					(int)count);
1289 		}
1290 	}
1291 	return (0);
1292 }
1293 
1294 #ifdef	__needed__
1295 LOCAL int
read_rzone_info(scgp,bp,cnt)1296 read_rzone_info(scgp, bp, cnt)
1297 	SCSI	*scgp;
1298 	caddr_t	bp;
1299 	int	cnt;
1300 {
1301 	register struct	scg_cmd	*scmd = scgp->scmd;
1302 
1303 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1304 	scmd->addr = bp;
1305 	scmd->size = cnt;
1306 	scmd->flags = SCG_RECV_DATA|SCG_DISRE_ENA;
1307 	scmd->cdb_len = SC_G1_CDBLEN;
1308 	scmd->sense_len = CCS_SENSE_LEN;
1309 	scmd->cdb.g1_cdb.cmd = 0x52;
1310 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1311 /*	g1_cdbaddr(&scmd->cdb.g1_cdb, addr);*/
1312 	g1_cdblen(&scmd->cdb.g1_cdb, cnt);
1313 
1314 	scgp->cmdname = "read rzone info";
1315 
1316 	if (scg_cmd(scgp) < 0)
1317 		return (-1);
1318 	return (0);
1319 }
1320 
1321 LOCAL int
reserve_rzone(scgp,size)1322 reserve_rzone(scgp, size)
1323 	SCSI	*scgp;
1324 	long	size;		/* number of blocks */
1325 {
1326 	register struct	scg_cmd	*scmd = scgp->scmd;
1327 
1328 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1329 	scmd->addr = (caddr_t)0;
1330 	scmd->size = 0;
1331 	scmd->flags = SCG_DISRE_ENA|SCG_CMD_RETRY;
1332 	scmd->cdb_len = SC_G1_CDBLEN;
1333 	scmd->sense_len = CCS_SENSE_LEN;
1334 	scmd->cdb.g1_cdb.cmd = 0x53;
1335 	scmd->cdb.g1_cdb.lun = scg_lun(scgp);
1336 
1337 	i_to_4_byte(&scmd->cdb.g1_cdb.addr[3], size);
1338 
1339 	scgp->cmdname = "reserve_rzone";
1340 
1341 	if (scg_cmd(scgp) < 0)
1342 		return (-1);
1343 	return (0);
1344 }
1345 #endif
1346 
1347 #ifdef	_is_this_pioneer_vendor_unique_
1348 LOCAL int
send_dvd_structure(scgp,bp,cnt)1349 send_dvd_structure(scgp, bp, cnt)
1350 	SCSI	*scgp;
1351 	caddr_t	bp;
1352 	int	cnt;
1353 {
1354 	register struct	scg_cmd	*scmd = scgp->scmd;
1355 
1356 	fillbytes((caddr_t)scmd, sizeof (*scmd), '\0');
1357 	scmd->addr = bp;
1358 	scmd->size = cnt;
1359 	scmd->flags = SCG_DISRE_ENA;
1360 	scmd->cdb_len = SC_G5_CDBLEN;
1361 	scmd->sense_len = CCS_SENSE_LEN;
1362 	scmd->timeout = 4 * 60;		/* Needs up to 2 minutes ??? */
1363 	scmd->cdb.g5_cdb.cmd = 0xFB;
1364 	scmd->cdb.g5_cdb.lun = scg_lun(scgp);
1365 	g5_cdblen(&scmd->cdb.g5_cdb, cnt);
1366 
1367 	scgp->cmdname = "read dvd structure";
1368 
1369 	if (scg_cmd(scgp) < 0)
1370 		return (-1);
1371 	return (0);
1372 }
1373 #endif
1374 
1375 #ifdef	__needed__
1376 LOCAL int
set_layerbreak(scgp,tsize,lbreak)1377 set_layerbreak(scgp, tsize, lbreak)
1378 	SCSI	*scgp;
1379 	long	tsize;
1380 	Int32_t	lbreak;
1381 {
1382 #ifdef	USE_STRUC_22
1383 	struct dvd_structure_22	jz;
1384 #endif
1385 	struct dvd_structure_23	lb;
1386 	int			ret;
1387 	UInt32_t		dsize;
1388 #ifdef	USE_STRUC_22
1389 	UInt32_t		jump_size;
1390 #endif
1391 	UInt32_t		jump_lba;
1392 
1393 #ifdef	USE_STRUC_22
1394 	/*
1395 	 * Jump interval size 0x22
1396 	 */
1397 	fillbytes((caddr_t)&jz, sizeof (jz), '\0');
1398 	ret = read_dvd_structure(scgp, (caddr_t)&jz, sizeof (jz), 0, 0, 0, 0x22);
1399 	if (ret < 0)
1400 		return (ret);
1401 
1402 	jump_size = a_to_u_4_byte(jz.jump_interval_size);
1403 
1404 	if (jump_size != 0) {
1405 
1406 #ifdef	AAAA
1407 		dsize = roundup(tsize, 16);
1408 		jump_lba = dsize / 2;
1409 		jump_lba = roundup(jump_lba, 16);
1410 /*		jump_lba -= 1;*/
1411 		error("jump lba %d\n", jump_lba);
1412 		i_to_4_byte(lb.jump_lba, jump_lba);
1413 #else
1414 		i_to_4_byte(jz.jump_interval_size, 0);
1415 #endif
1416 		ret = send_dvd_structure(scgp, (caddr_t)&jz, sizeof (jz), 0x22);
1417 		if (ret < 0)
1418 			return (ret);
1419 	}
1420 #endif	/* USE_STRUC_22 */
1421 
1422 	/*
1423 	 * Jump logical block address 0x23
1424 	 */
1425 	fillbytes((caddr_t)&lb, sizeof (lb), '\0');
1426 	ret = read_dvd_structure(scgp, (caddr_t)&lb, sizeof (lb), 0, 0, 0, 0x23);
1427 	if (ret < 0)
1428 		return (ret);
1429 
1430 	jump_lba = a_to_u_4_byte(lb.jump_lba);
1431 	if (lbreak > 0 && lbreak > jump_lba) {
1432 		errmsgno(EX_BAD, _("Manual layer break %d > %u not allowed.\n"),
1433 							lbreak, jump_lba);
1434 		return (-1);
1435 	}
1436 	dsize = roundup(tsize, 16);
1437 	if (lbreak <= 0 && dsize <= (jump_lba+1)) {
1438 		/*
1439 		 * Allow to write DL media with less than single layer size
1440 		 * in case of manual layer break set up.
1441 		 */
1442 		errmsgno(EX_BAD,
1443 			_("Layer 0 size %u is bigger than expected disk size %u.\n"),
1444 			(jump_lba+1), dsize);
1445 		errmsgno(EX_BAD, _("Use single layer medium.\n"));
1446 		return (-1);
1447 	}
1448 	jump_lba = dsize / 2;
1449 	jump_lba = roundup(jump_lba, 16);
1450 	if (lbreak > 0 && lbreak < jump_lba) {
1451 		errmsgno(EX_BAD, _("Manual layer break %d < %u not allowed.\n"),
1452 							lbreak, jump_lba);
1453 		return (-1);
1454 	}
1455 	if (lbreak > 0)
1456 		jump_lba = lbreak;
1457 	jump_lba -= 1;
1458 	i_to_4_byte(lb.jump_lba, jump_lba);
1459 
1460 	ret = send_dvd_structure(scgp, (caddr_t)&lb, sizeof (lb), 0x23);
1461 	return (ret);
1462 }
1463 #endif
1464 
1465 LOCAL	char	ill_booktype[] = "reserved book type";
1466 char	*book_types[] = {
1467 	"DVD-ROM",
1468 	"DVD-RAM",
1469 	"DVD-R",
1470 	"DVD-RW",
1471 	"HD DVD-ROM",
1472 	"HD DVD-RAM",
1473 	"HD DVD-R",
1474 	ill_booktype,
1475 	ill_booktype,
1476 	"DVD+RW",
1477 	"DVD+R",
1478 	ill_booktype,
1479 	ill_booktype,
1480 	"DVD+RW/DL",
1481 	"DVD+R/DL",
1482 	ill_booktype,
1483 };
1484 
1485 LOCAL	char	res_bvers[] = "reserved book version";
1486 LOCAL char	*R_vers[] = {
1487 	"0.9x",
1488 	"1.0x",
1489 	"1.1x",
1490 	res_bvers,
1491 	"1.9x",
1492 	"2.0x",
1493 	"> 2.0x",
1494 	res_bvers,
1495 	res_bvers,
1496 	res_bvers,
1497 	res_bvers,
1498 	res_bvers,
1499 	res_bvers,
1500 	res_bvers,
1501 	res_bvers,
1502 	res_bvers,
1503 };
1504 
1505 LOCAL char	*RW_vers[] = {
1506 	"0.9x",
1507 	"1.0x",
1508 	"1.1x",
1509 	"> 1.1x",
1510 	res_bvers,
1511 	res_bvers,
1512 	res_bvers,
1513 	res_bvers,
1514 	res_bvers,
1515 	res_bvers,
1516 	res_bvers,
1517 	res_bvers,
1518 	res_bvers,
1519 	res_bvers,
1520 	res_bvers,
1521 	res_bvers,
1522 };
1523 
1524 LOCAL	char	ill_dsize[] = "illegal size";
1525 char	*disc_sizes[] = {
1526 	"120mm",
1527 	"80mm",
1528 	ill_dsize,
1529 	ill_dsize,
1530 	ill_dsize,
1531 	ill_dsize,
1532 	ill_dsize,
1533 	ill_dsize,
1534 	ill_dsize,
1535 	ill_dsize,
1536 	ill_dsize,
1537 	ill_dsize,
1538 	ill_dsize,
1539 	ill_dsize,
1540 	ill_dsize,
1541 	ill_dsize,
1542 };
1543 
1544 LOCAL	char	ill_rate[] = "illegal rate";
1545 char	*tr_rates[] = {
1546 	"2.52 MB/s",
1547 	"5.04 MB/s",
1548 	"10.08 MB/s",
1549 	"20.16 MB/s",
1550 	"30.24 MB/s",
1551 	ill_rate,
1552 	ill_rate,
1553 	ill_rate,
1554 	ill_rate,
1555 	ill_rate,
1556 	ill_rate,
1557 	ill_rate,
1558 	ill_rate,
1559 	ill_rate,
1560 	ill_rate,
1561 	"Not specified",
1562 };
1563 
1564 LOCAL	char	ill_layer[] = "illegal layer type";
1565 char	*layer_types[] = {
1566 	"Embossed Data",
1567 	"Recordable Area",
1568 	"Rewritable Area",
1569 	ill_layer,
1570 	ill_layer,
1571 	ill_layer,
1572 	ill_layer,
1573 	ill_layer,
1574 	ill_layer,
1575 	ill_layer,
1576 	ill_layer,
1577 	ill_layer,
1578 	ill_layer,
1579 	ill_layer,
1580 	ill_layer,
1581 	ill_layer,
1582 };
1583 
1584 LOCAL	char	ill_dens[] = "illegal density";
1585 char	*ldensities[] = {
1586 	"0.267 �m/bit",
1587 	"0.293 �m/bit",
1588 	"0.409-0.435 �m/bit",
1589 	"0.280-0.291 �m/bit",
1590 	"0.353 �m/bit",
1591 	ill_dens,
1592 	ill_dens,
1593 	ill_dens,
1594 	ill_dens,
1595 	ill_dens,
1596 	ill_dens,
1597 	ill_dens,
1598 	ill_dens,
1599 	ill_dens,
1600 	ill_dens,
1601 	ill_dens,
1602 };
1603 
1604 char	*tdensities[] = {
1605 	"0.74 �m/track",
1606 	"0.80 �m/track",
1607 	"0.615 �m/track",
1608 	"0.40 �m/track",
1609 	"0.34 �m/track",
1610 	ill_dens,
1611 	ill_dens,
1612 	ill_dens,
1613 	ill_dens,
1614 	ill_dens,
1615 	ill_dens,
1616 	ill_dens,
1617 	ill_dens,
1618 	ill_dens,
1619 	ill_dens,
1620 	ill_dens,
1621 };
1622 
1623 LOCAL void
print_dvd00(dp)1624 print_dvd00(dp)
1625 	struct dvd_structure_00 *dp;
1626 {
1627 	int	len = a_to_2_byte(dp->data_len)+2;
1628 	long	lbr;
1629 	char	*vers = "";
1630 	char	*ext_vers = "";
1631 	char	ev[8];
1632 	int	evers = 0;
1633 
1634 	ev[0] = '\0';
1635 	if (len >= (27+4))
1636 		evers = ((char *)dp)[27+4] & 0xFF;
1637 
1638 	if (dp->book_type == 2) {		/* DVD-R */
1639 		vers = R_vers[dp->book_version];
1640 		if ((dp->book_version == 5 ||
1641 		    dp->book_version == 6) &&
1642 		    evers != 0) {
1643 			snprintf(ev, sizeof (ev),
1644 					" -> %d.%d",
1645 					(evers >> 4) & 0x0F,
1646 					evers & 0x0F);
1647 			ext_vers = ev;
1648 		}
1649 
1650 	} else if (dp->book_type == 3) {	/* DVD-RW */
1651 		vers = RW_vers[dp->book_version];
1652 		if ((dp->book_version == 2 ||
1653 		    dp->book_version == 3) &&
1654 		    evers != 0) {
1655 			snprintf(ev, sizeof (ev),
1656 					" -> %d.%d",
1657 					(evers >> 4) & 0x0F,
1658 					evers & 0x0F);
1659 			ext_vers = ev;
1660 		}
1661 	}
1662 
1663 	printf(_("book type:       %s, Version %s%s%s(%d.%d)\n"),
1664 					book_types[dp->book_type],
1665 					vers, ext_vers, *vers ? " ":"",
1666 					dp->book_type,
1667 					dp->book_version);
1668 	printf(_("disc size:       %s (%d)\n"), disc_sizes[dp->disc_size], dp->disc_size);
1669 	printf(_("maximum rate:    %s (%d)\n"), tr_rates[dp->maximum_rate], dp->maximum_rate);
1670 	printf(_("number of layers:%d\n"), dp->numlayers+1);
1671 	printf(_("track path:      %s Track Path (%d)\n"),
1672 					dp->track_path?_("Opposite"):_("Parallel"),
1673 					dp->track_path);
1674 	printf(_("layer type:      %s (%d)\n"), layer_types[dp->layer_type],
1675 					dp->layer_type);
1676 	printf(_("linear density:  %s (%d)\n"), ldensities[dp->linear_density],
1677 					dp->linear_density);
1678 	printf(_("track density:   %s (%d)\n"), tdensities[dp->track_density],
1679 					dp->track_density);
1680 	printf(_("phys start:      %ld (0x%lX) \n"),
1681 					a_to_u_3_byte(dp->phys_start),
1682 					a_to_u_3_byte(dp->phys_start));
1683 	printf(_("phys end:        %ld\n"), a_to_u_3_byte(dp->phys_end));
1684 	printf(_("end layer 0:     %ld\n"), a_to_u_3_byte(dp->end_layer0));
1685 	printf(_("bca:             %d\n"), dp->bca);
1686 	printf(_("phys size:...    %ld\n"), a_to_u_3_byte(dp->phys_end) - a_to_u_3_byte(dp->phys_start) + 1);
1687 	lbr = a_to_u_3_byte(dp->end_layer0) - a_to_u_3_byte(dp->phys_start) + 1;
1688 	if (lbr > 0)
1689 		printf(_("layer break at:  %ld\n"), lbr);
1690 }
1691 
1692 LOCAL void
print_dvd01(dp)1693 print_dvd01(dp)
1694 	struct dvd_structure_01 *dp;
1695 {
1696 	printf(_("copyr prot type: %d\n"), dp->copyr_prot_type);
1697 	printf(_("region mgt info: %d\n"), dp->region_mgt_info);
1698 }
1699 
1700 LOCAL void
print_dvd04(dp)1701 print_dvd04(dp)
1702 	struct dvd_structure_04 *dp;
1703 {
1704 	if (cmpnullbytes(dp->man_info, sizeof (dp->man_info)) <
1705 						sizeof (dp->man_info)) {
1706 		printf(_("Manufacturing info: '%.2048s'\n"), dp->man_info);
1707 	}
1708 }
1709 
1710 LOCAL void
print_dvd05(dp)1711 print_dvd05(dp)
1712 	struct dvd_structure_05 *dp;
1713 {
1714 	printf(_("cpm:             %d\n"), dp->cpm);
1715 	printf(_("cgms:            %d\n"), dp->cgms);
1716 }
1717 
1718 LOCAL void
print_dvd0D(dp)1719 print_dvd0D(dp)
1720 	struct dvd_structure_0D *dp;
1721 {
1722 	printf(_("last rma sector: %d\n"), a_to_u_2_byte(dp->last_rma_sector));
1723 }
1724 
1725 LOCAL void
print_dvd0E(dp)1726 print_dvd0E(dp)
1727 	struct dvd_structure_0E *dp;
1728 {
1729 	int	i;
1730 	int	len = 44;
1731 	int	c;
1732 	char	*p = (char *)dp;
1733 
1734 	if (dp->field_id != 1)
1735 	printf(_("field id:        %d\n"), dp->field_id);
1736 	printf(_("application code:%d\n"), dp->application_code);
1737 	printf(_("physical code:   %d\n"), dp->phys_data);
1738 	printf(_("last rec address:%ld\n"), a_to_u_3_byte(dp->last_recordable_addr));
1739 	printf(_("part v./ext code:%X/%X\n"), (Uint)(dp->res_a[0] & 0xF0) >> 4,
1740 						dp->res_a[0] & 0xF);
1741 
1742 	if (dp->field_id_2 != 2)
1743 	printf(_("field id2:       %d\n"), dp->field_id_2);
1744 	printf(_("ind wr. power:   %d\n"), dp->ind_wr_power);
1745 	printf(_("wavelength code: %d\n"), dp->ind_wavelength);
1746 	scg_fprbytes(stdout, _("write str. code:"), dp->opt_wr_strategy, 4);
1747 
1748 	if (dp->field_id_3 != 3)
1749 	printf(_("field id3:       %d\n"), dp->field_id_3);
1750 	if (dp->field_id_4 != 4)
1751 	printf(_("field id4:       %d\n"), dp->field_id_4);
1752 
1753 	printf(_("Manufacturer:   '"));
1754 	for (i = 0; i < 6; i++) {
1755 		c = dp->man_id[i];
1756 		if (c >= ' ' && c < 0177)
1757 			printf("%c", c);
1758 		else if (c != 0)
1759 			printf(".");
1760 	}
1761 	for (i = 0; i < 6; i++) {
1762 		c = dp->man_id2[i];
1763 		if (c >= ' ' && c < 0177)
1764 			printf("%c", c);
1765 		else if (c != 0)
1766 			printf(".");
1767 	}
1768 	printf("'\n");
1769 	/*
1770 	 * Next field: opt wr str. II or Manufacturer part III
1771 	 */
1772 /*	scg_prbytes("write str. code:", dp->opt_wr_strategy, 4);*/
1773 
1774 	if (lverbose <= 1)
1775 		return;
1776 	printf(_("Prerecorded info   : "));
1777 	for (i = 0; i < len; i++) {
1778 		c = p[i];
1779 		if (c >= ' ' && c < 0177)
1780 			printf("%c", c);
1781 		else
1782 			printf(".");
1783 	}
1784 	printf("\n");
1785 }
1786 
1787 LOCAL void
print_dvd0F(dp)1788 print_dvd0F(dp)
1789 	struct dvd_structure_0F *dp;
1790 {
1791 	printf(_("random:          %d\n"), a_to_u_2_byte(dp->random));
1792 	printf(_("year:            %.4s\n"), dp->year);
1793 	printf(_("month:           %.2s\n"), dp->month);
1794 	printf(_("day:             %.2s\n"), dp->day);
1795 	printf(_("hour:            %.2s\n"), dp->hour);
1796 	printf(_("minute:          %.2s\n"), dp->minute);
1797 	printf(_("second:          %.2s\n"), dp->second);
1798 }
1799 
1800 
1801 #ifdef	__needed__
1802 LOCAL void
send_dvd0F(scgp)1803 send_dvd0F(scgp)
1804 	SCSI	*scgp;
1805 {
1806 	struct dvd_structure_0F_w d;
1807 
1808 	strncpy((char *)d.year,		"1998", 4);
1809 	strncpy((char *)d.month,	"05", 2);
1810 	strncpy((char *)d.day,		"12", 2);
1811 	strncpy((char *)d.hour,		"22", 2);
1812 	strncpy((char *)d.minute,	"59", 2);
1813 	strncpy((char *)d.second,	"00", 2);
1814 /*	send_dvd_structure(scgp, (caddr_t)&d, sizeof (d));*/
1815 }
1816 #endif
1817 
1818 LOCAL void
print_dvd20(dp)1819 print_dvd20(dp)
1820 	struct dvd_structure_20 *dp;
1821 {
1822 	printf(_("L0 init status:  %d\n"), dp->res47[0] & 0x80 ? 1 : 0);
1823 	printf(_("L0 data areacap: %ld\n"), a_to_u_4_byte(dp->l0_area_cap));
1824 }
1825 
1826 LOCAL void
print_dvd22(dp)1827 print_dvd22(dp)
1828 	struct dvd_structure_22 *dp;
1829 {
1830 	printf(_("Jump intervalsz: %ld\n"), a_to_u_4_byte(dp->jump_interval_size));
1831 }
1832 
1833 LOCAL void
print_dvd23(dp)1834 print_dvd23(dp)
1835 	struct dvd_structure_23 *dp;
1836 {
1837 	printf(_("Jump LBA:        %ld\n"), a_to_u_4_byte(dp->jump_lba));
1838 }
1839 
1840 
1841 #include "adip.h"
1842 /*LOCAL void*/
1843 EXPORT void
print_dvd_info(scgp)1844 print_dvd_info(scgp)
1845 	SCSI	*scgp;
1846 {
1847 	Uchar	mode[4096];
1848 	int	ret;
1849 	int	i;
1850 
1851 	if (lverbose > 2)
1852 		printf(_("Entering DVD info....\n"));
1853 	/*
1854 	 * The ACARD TECH AEC-7720 ATAPI<->SCSI adaptor
1855 	 * chokes if we try to transfer odd byte counts (rounds up to
1856 	 * even byte counts and thus causes a DMA overflow and a
1857 	 * bus reset), so make the byte count even.
1858 	 * It also chokes if we try to transfer more than 0x40 bytes with
1859 	 * mode_sense of all pages. As we don't want to avoid this
1860 	 * command here, we need to wait until the drive recoveres
1861 	 * from the reset?? it receives after the adapter dies.
1862 	 */
1863 /*	mode_sense(scgp, mode, 255, 0x3F, 0);*/
1864 /*	if (lverbose > 2)*/
1865 /*		scg_prbytes("Mode: ", mode, 255 - scg_getresid(scgp));*/
1866 
1867 	if (lverbose > 1)
1868 		mode_sense(scgp, mode, 250, 0x3F, 0);
1869 	if (lverbose > 2)
1870 		scg_prbytes(_("Mode: "), mode, 250 - scg_getresid(scgp));
1871 	wait_unit_ready(scgp, 120);
1872 	if (lverbose > 1) {
1873 		printf(_("Supported DVD (readable) structures:"));
1874 		scgp->silent++;
1875 		for (i = 0; i <= 255; i++) {
1876 			fillbytes((caddr_t)mode, sizeof (mode), '\0');
1877 			ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, i);
1878 			if (ret >= 0 && (sizeof (mode) - scg_getresid(scgp)) > 4)
1879 				printf(" %02X", i);
1880 		}
1881 		scgp->silent--;
1882 		printf("\n");
1883 /*		printf("Page: %d ret: %d len: %d\n", i, ret, sizeof (mode) - scg_getresid(scgp));*/
1884 		if (lverbose > 2)
1885 			scg_prbytes(_("Page FF: "), mode, sizeof (mode) - scg_getresid(scgp));
1886 		if (sizeof (mode) - scg_getresid(scgp) > 4) {
1887 			int	len = a_to_u_2_byte(mode) - 2;
1888 			Uchar	*p = &mode[4];
1889 			int	m;
1890 
1891 			len /= 4;
1892 			for (i = 0; i < len; i++) {
1893 				m = p[1] & 0xC0;
1894 				printf(_("Page %02X %s  (%02X) len %d\n"),
1895 					*p & 0xFF,
1896 					m == 0xC0 ?
1897 					_("read/write") :
1898 					(m == 0x80 ? _("     write") :
1899 					(m == 0x40 ? _("read      ") : _("unknown   "))),
1900 					p[1] & 0xFF,
1901 					a_to_u_2_byte(&p[2]));
1902 				p += 4;
1903 			}
1904 		}
1905 	}
1906 	wait_unit_ready(scgp, 120);
1907 
1908 	/*
1909 	 * Physical Format information 0x00
1910 	 */
1911 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
1912 	scgp->silent++;
1913 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 0);
1914 	scgp->silent--;
1915 	if (ret >= 0) {
1916 		if (lverbose > 2) {
1917 			scg_prbytes(_("DVD structure[0]: "),
1918 				mode, sizeof (mode) - scg_getresid(scgp));
1919 /*			scg_prascii("DVD structure[0]: ", mode, sizeof (mode) - scg_getresid(scgp));*/
1920 		}
1921 		print_dvd00((struct dvd_structure_00 *)mode);
1922 		ret = get_curprofile(scgp);
1923 		if (ret == 0x001A || ret == 0x001B) {
1924 			/*profile >= 0x0018 && profile < 0x0020*/
1925 			printf(_("Manufacturer:    '%.8s'\n"), &mode[23]);
1926 			printf(_("Media type:      '%.3s'\n"), &mode[23+8]);
1927 		}
1928 	}
1929 
1930 	/*
1931 	 * ADIP information 0x11
1932 	 */
1933 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
1934 	scgp->silent++;
1935 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 0x11);
1936 	scgp->silent--;
1937 	if (ret >= 0) {
1938 		adip_t	*adp;
1939 		if (lverbose > 2) {
1940 			scg_prbytes(_("DVD structure[11]: "),
1941 				mode, sizeof (mode) - scg_getresid(scgp));
1942 			scg_prascii(_("DVD structure[11]: "),
1943 				mode, sizeof (mode) - scg_getresid(scgp));
1944 		}
1945 /*		print_dvd0F((struct dvd_structure_0F *)mode);*/
1946 		adp = (adip_t *)&mode[4];
1947 #ifndef	offsetof
1948 #define	offsetof(TYPE, MEMBER)  ((size_t) &((TYPE *)0)->MEMBER)
1949 #endif
1950 /*		printf("size %d %d\n", sizeof (adip_t), offsetof(adip_t, res_controldat));*/
1951 		printf(_("Category/Version	%02X\n"), adp->cat_vers);
1952 		printf(_("Disk size		%02X\n"), adp->disk_size);
1953 		printf(_("Disk structure		%02X\n"), adp->disk_struct);
1954 		printf(_("Recoding density	%02X\n"), adp->density);
1955 
1956 		printf(_("Manufacturer:		'%.8s'\n"), adp->man_id);
1957 		printf(_("Media type:		'%.3s'\n"), adp->media_id);
1958 		printf(_("Product revision	%u\n"), adp->prod_revision);
1959 		printf(_("ADIP numbytes		%u\n"), adp->adip_numbytes);
1960 		printf(_("Reference speed		%u\n"), adp->ref_speed);
1961 		printf(_("Max speed		%u\n"), adp->max_speed);
1962 	}
1963 
1964 	/*
1965 	 * Layer boundary information 0x20
1966 	 */
1967 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
1968 	scgp->silent++;
1969 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 0x20);
1970 	scgp->silent--;
1971 	if (ret >= 0) {
1972 		if (lverbose > 2) {
1973 			scg_prbytes(_("DVD structure[20]: "),
1974 				mode, sizeof (mode) - scg_getresid(scgp));
1975 			scg_prascii(_("DVD structure[20]: "),
1976 				mode, sizeof (mode) - scg_getresid(scgp));
1977 		}
1978 		print_dvd20((struct dvd_structure_20 *)mode);
1979 	}
1980 
1981 	/*
1982 	 * Jump interval size 0x22
1983 	 */
1984 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
1985 	scgp->silent++;
1986 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 0x22);
1987 	scgp->silent--;
1988 	if (ret >= 0) {
1989 		if (lverbose > 2) {
1990 			scg_prbytes(_("DVD structure[22]: "),
1991 				mode, sizeof (mode) - scg_getresid(scgp));
1992 			scg_prascii(_("DVD structure[22]: "),
1993 				mode, sizeof (mode) - scg_getresid(scgp));
1994 		}
1995 		print_dvd22((struct dvd_structure_22 *)mode);
1996 	}
1997 
1998 	/*
1999 	 * Jump logical block address 0x23
2000 	 */
2001 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2002 	scgp->silent++;
2003 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 0x23);
2004 	scgp->silent--;
2005 	if (ret >= 0) {
2006 		if (lverbose > 2) {
2007 			scg_prbytes(_("DVD structure[23]: "),
2008 				mode, sizeof (mode) - scg_getresid(scgp));
2009 			scg_prascii(_("DVD structure[23]: "),
2010 				mode, sizeof (mode) - scg_getresid(scgp));
2011 		}
2012 		print_dvd23((struct dvd_structure_23 *)mode);
2013 	}
2014 
2015 	/*
2016 	 * Copyright information 0x01
2017 	 */
2018 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2019 	scgp->silent++;
2020 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 1);
2021 	scgp->silent--;
2022 	if (ret >= 0) {
2023 		if (lverbose > 2) {
2024 			scg_prbytes(_("DVD structure[1]: "),
2025 				mode, sizeof (mode) - scg_getresid(scgp));
2026 		}
2027 		print_dvd01((struct dvd_structure_01 *)mode);
2028 	}
2029 
2030 	/*
2031 	 * Manufacturer information 0x04
2032 	 */
2033 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2034 	scgp->silent++;
2035 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 4);
2036 	scgp->silent--;
2037 	if (ret >= 0) {
2038 		if (lverbose > 2) {
2039 			scg_prbytes(_("DVD structure[4]: "),
2040 				mode, sizeof (mode) - scg_getresid(scgp));
2041 		}
2042 		print_dvd04((struct dvd_structure_04 *)mode);
2043 	}
2044 
2045 	/*
2046 	 * Copyright management information 0x05
2047 	 */
2048 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2049 	scgp->silent++;
2050 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 5);
2051 	scgp->silent--;
2052 	if (ret >= 0) {
2053 		if (lverbose > 2) {
2054 			scg_prbytes(_("DVD structure[5]: "),
2055 				mode, sizeof (mode) - scg_getresid(scgp));
2056 		}
2057 		print_dvd05((struct dvd_structure_05 *)mode);
2058 	}
2059 
2060 	/*
2061 	 * Recording Management Area Data information 0x0D
2062 	 */
2063 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2064 	scgp->silent++;
2065 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 0xD);
2066 	scgp->silent--;
2067 	if (ret >= 0) {
2068 		if (lverbose > 2) {
2069 			scg_prbytes(_("DVD structure[D]: "),
2070 				mode, sizeof (mode) - scg_getresid(scgp));
2071 		}
2072 		print_dvd0D((struct dvd_structure_0D *)mode);
2073 	}
2074 
2075 	/*
2076 	 * Prerecorded information 0x0E
2077 	 */
2078 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2079 	scgp->silent++;
2080 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 0xE);
2081 	scgp->silent--;
2082 	if (ret >= 0) {
2083 		if (lverbose > 2) {
2084 			scg_prbytes(_("DVD structure[E]: "),
2085 				mode, sizeof (mode) - scg_getresid(scgp));
2086 		}
2087 		print_dvd0E((struct dvd_structure_0E *)mode);
2088 	}
2089 
2090 	if (lverbose <= 1)
2091 		return;
2092 
2093 	/*
2094 	 * Unique Disk identifier 0x0F
2095 	 */
2096 /*	send_dvd0F();*/
2097 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2098 	scgp->silent++;
2099 	ret = read_dvd_structure(scgp, (caddr_t)mode, sizeof (mode), 0, 0, 0, 0xF);
2100 	scgp->silent--;
2101 	if (ret >= 0) {
2102 		if (lverbose > 2) {
2103 			scg_prbytes(_("DVD structure[F]: "),
2104 				mode, sizeof (mode) - scg_getresid(scgp));
2105 		}
2106 		print_dvd0F((struct dvd_structure_0F *)mode);
2107 	}
2108 
2109 	fillbytes((caddr_t)mode, sizeof (mode), '\0');
2110 	read_rzone_info(scgp, (caddr_t)mode, sizeof (mode));
2111 	if (lverbose > 2)
2112 		scg_prbytes(_("Rzone info: "), mode, sizeof (mode) - scg_getresid(scgp));
2113 	przone((struct rzone_info *)mode);
2114 
2115 	scgp->verbose++;
2116 	log_sense(scgp, (caddr_t)mode, 255, 0x3, 1, 0);
2117 	log_sense(scgp, (caddr_t)mode, 255, 0x31, 1, 0);
2118 	scgp->verbose--;
2119 
2120 	if (lverbose > 2)
2121 		printf(_("Leaving DVD info.\n"));
2122 }
2123 
2124 LOCAL void
print_laserlog(scgp)2125 print_laserlog(scgp)
2126 	SCSI	*scgp;
2127 {
2128 	Uchar	log[256];
2129 	Uchar	*p;
2130 	int	len = sizeof (log);
2131 	long	val;
2132 
2133 	if (!has_log_page(scgp, 0x30, LOG_CUMUL))
2134 		return;
2135 
2136 	p = log + sizeof (scsi_log_hdr);
2137 
2138 	/*
2139 	 * This is Pioneer specific so other drives will not have it.
2140 	 * Not all values may be available with newer Pioneer drives.
2141 	 */
2142 	scgp->silent++;
2143 	fillbytes((caddr_t)log, sizeof (log), '\0');
2144 	if (get_log(scgp, (caddr_t)log, &len, 0x30, LOG_CUMUL, 0) < 0) {
2145 		scgp->silent--;
2146 		return;
2147 	}
2148 	scgp->silent--;
2149 
2150 	val = a_to_u_4_byte(((struct pioneer_logpage_30_0 *)p)->total_poh);
2151 	if (((struct scsi_logp_header *)log)->p_len > 0)
2152 		printf(_("Total power on  hours: %ld\n"), val);
2153 
2154 	scgp->silent++;
2155 	fillbytes((caddr_t)log, sizeof (log), '\0');
2156 	if (get_log(scgp, (caddr_t)log, &len, 0x30, LOG_CUMUL, 1) < 0) {
2157 		scgp->silent--;
2158 		return;
2159 	}
2160 	scgp->silent--;
2161 
2162 	val = a_to_u_4_byte(((struct pioneer_logpage_30_1 *)p)->laser_poh);
2163 	if (((struct scsi_logp_header *)log)->p_len > 0)
2164 		printf(_("Total laser on  hours: %ld\n"), val);
2165 
2166 	scgp->silent++;
2167 	fillbytes((caddr_t)log, sizeof (log), '\0');
2168 	if (get_log(scgp, (caddr_t)log, &len, 0x30, LOG_CUMUL, 2) < 0) {
2169 		scgp->silent--;
2170 		return;
2171 	}
2172 	scgp->silent--;
2173 
2174 	val = a_to_u_4_byte(((struct pioneer_logpage_30_2 *)p)->record_poh);
2175 	if (((struct scsi_logp_header *)log)->p_len > 0)
2176 		printf(_("Total recording hours: %ld\n"), val);
2177 }
2178