xref: /illumos-gate/usr/src/cmd/cdrw/misc_scsi.c (revision f3041bfa)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  * Copyright 2012 Milan Jurik. All rights reserved.
25  */
26 
27 #include <sys/types.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdio.h>
31 #include <sys/dkio.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #include <libintl.h>
35 #include <sys/time.h>
36 
37 #include "mmc.h"
38 #include "util.h"
39 #include "misc_scsi.h"
40 #include "transport.h"
41 #include "main.h"
42 #include "toshiba.h"
43 #include "msgs.h"
44 #include "device.h"
45 
46 static int check_track_size(cd_device *dev, int trk_num,
47     struct track_info *tip);
48 static int rtoc_get_trk_sess_num(uchar_t *rtoc, size_t rtoc_len, int trk_num,
49     int *sess_nump);
50 static int rtoc_get_sess_last_trk_num(uchar_t *rtoc, size_t rtoc_len,
51     int sess_num, int *last_trk_nump);
52 static int rtoc_get_sess_leadout_lba(uchar_t *rtoc, size_t rtoc_len,
53     int sess_num, uint32_t *leadout_lba);
54 static rtoc_td_t *get_rtoc_td(rtoc_td_t *begin_tdp, rtoc_td_t *end_tdp,
55     uchar_t adr, uchar_t point);
56 
57 uint32_t
58 read_scsi32(void *addr)
59 {
60 	uchar_t *ad = (uchar_t *)addr;
61 	uint32_t ret;
62 
63 	ret = ((((uint32_t)ad[0]) << 24) | (((uint32_t)ad[1]) << 16) |
64 	    (((uint32_t)ad[2]) << 8) | ad[3]);
65 	return (ret);
66 }
67 
68 uint16_t
69 read_scsi16(void *addr)
70 {
71 	uchar_t *ad = (uchar_t *)addr;
72 	uint16_t ret;
73 
74 	ret = ((((uint16_t)ad[0]) << 8) | ad[1]);
75 	return (ret);
76 }
77 
78 void
79 load_scsi32(void *addr, uint32_t v)
80 {
81 	uchar_t *ad = (uchar_t *)addr;
82 
83 	ad[0] = (uchar_t)(v >> 24);
84 	ad[1] = (uchar_t)(v >> 16);
85 	ad[2] = (uchar_t)(v >> 8);
86 	ad[3] = (uchar_t)v;
87 }
88 
89 void
90 load_scsi16(void *addr, uint16_t v)
91 {
92 	uchar_t *ad = (uchar_t *)addr;
93 	ad[0] = (uchar_t)(v >> 8);
94 	ad[1] = (uchar_t)v;
95 }
96 /*
97  * will get the mode page only i.e. will strip off the header.
98  */
99 int
100 get_mode_page(int fd, int page_no, int pc, int buf_len, uchar_t *buffer)
101 {
102 	int ret;
103 	uchar_t byte2, *buf;
104 	uint_t header_len, page_len, copy_cnt;
105 
106 	byte2 = (uchar_t)(((pc << 6) & 0xC0) | (page_no & 0x3f));
107 	buf = (uchar_t *)my_zalloc(256);
108 
109 	/* Ask 254 bytes only to make our IDE driver happy */
110 	ret = mode_sense(fd, byte2, 1, 254, buf);
111 	if (ret == 0) {
112 		free(buf);
113 		return (0);
114 	}
115 
116 	header_len = 8 + read_scsi16(&buf[6]);
117 	page_len = buf[header_len + 1] + 2;
118 
119 	copy_cnt = (page_len > buf_len) ? buf_len : page_len;
120 	(void) memcpy(buffer, &buf[header_len], copy_cnt);
121 	free(buf);
122 
123 	return (1);
124 }
125 
126 /*
127  * will take care of adding mode header and any extra bytes at the end.
128  */
129 int
130 set_mode_page(int fd, uchar_t *buffer)
131 {
132 	int ret;
133 	uchar_t *buf;
134 	uint_t total, p_len;
135 
136 	p_len = buffer[1] + 2;
137 	total = p_len + 8;
138 	buf = (uchar_t *)my_zalloc(total);
139 
140 	(void) memcpy(&buf[8], buffer, p_len);
141 	if (debug) {
142 		int i;
143 
144 		(void) printf("MODE: [");
145 		for (i = 0; i < p_len; i++) {
146 			(void) printf("0x%02x ", (uchar_t)buffer[i]);
147 		}
148 
149 		(void) printf("]\n");
150 	}
151 	ret = mode_select(fd, total, buf);
152 	free(buf);
153 
154 	return (ret);
155 }
156 
157 /*
158  * Builds track information database for track trackno. If trackno is
159  * -1, builds the database for next blank track.
160  */
161 int
162 build_track_info(cd_device *dev, int trackno, struct track_info *t_info)
163 {
164 	uchar_t *ti;
165 	uchar_t toc[20];		/* 2 entries + 4 byte header */
166 	int ret;
167 
168 	(void) memset(t_info, 0, sizeof (*t_info));
169 	/* 1st try READ TRACK INFORMATION */
170 	ti = (uchar_t *)my_zalloc(TRACK_INFO_SIZE);
171 	t_info->ti_track_no = trackno;
172 
173 	/* Gererate faked information for writing to DVD */
174 	if (device_type != CD_RW) {
175 		uint_t bsize;
176 
177 		t_info->ti_flags = 0x3000;
178 		t_info->ti_track_no = 1;
179 		t_info->ti_session_no = 1;
180 		t_info->ti_track_mode = 0x4;
181 		t_info->ti_data_mode = 1;
182 		t_info->ti_start_address = 0;
183 
184 		/* only 1 track on DVD make it max size */
185 		t_info->ti_track_size = read_format_capacity(target->d_fd,
186 		    &bsize);
187 		if (t_info->ti_track_size < MAX_CD_BLKS) {
188 			t_info->ti_track_size = MAX_DVD_BLKS;
189 		}
190 
191 		t_info->ti_nwa = 0;
192 		t_info->ti_lra = 0;
193 		t_info->ti_packet_size = 0x10;
194 		t_info->ti_free_blocks = 0;
195 	}
196 
197 	if (read_track_info(dev->d_fd, trackno, ti)) {
198 
199 		if (debug)
200 			(void) printf("using read_track_info for TOC \n");
201 
202 		t_info->ti_track_no = ti[2];
203 		t_info->ti_session_no = ti[3];
204 		t_info->ti_flags = (ti[6] >> 4) & 0xf;
205 		t_info->ti_flags |= (uint32_t)(ti[5] & 0xf0);
206 		t_info->ti_flags |= (uint32_t)(ti[7]) << 8;
207 		t_info->ti_flags |= TI_SESSION_NO_VALID | TI_FREE_BLOCKS_VALID;
208 		t_info->ti_track_mode = ti[5] & 0xf;
209 		if ((ti[6] & 0xf) == 0xf)
210 			t_info->ti_data_mode = 0xff;
211 		else
212 			t_info->ti_data_mode = ti[6] & 0xf;
213 		t_info->ti_start_address = read_scsi32(&ti[8]);
214 		t_info->ti_nwa = read_scsi32(&ti[12]);
215 		t_info->ti_free_blocks = read_scsi32(&ti[16]);
216 		t_info->ti_packet_size = read_scsi32(&ti[20]);
217 		t_info->ti_track_size = read_scsi32(&ti[24]);
218 		t_info->ti_lra = read_scsi32(&ti[28]);
219 		free(ti);
220 		return (1);
221 	}
222 	/* READ TRACK INFORMATION not supported, try other options */
223 	free(ti);
224 	/*
225 	 * We can get info for next blank track if READ TRACK INFO is not
226 	 * supported.
227 	 */
228 	if (trackno == -1)
229 		return (0);
230 
231 	if (debug)
232 		(void) printf("using READ_TOC for TOC\n");
233 
234 	/* Try Read TOC */
235 	if (!read_toc(dev->d_fd, 0, trackno, 20, toc)) {
236 		return (0);
237 	}
238 	t_info->ti_start_address = read_scsi32(&toc[8]);
239 	t_info->ti_track_mode = toc[5] & 0xf;
240 	t_info->ti_track_size = read_scsi32(&toc[16]) - read_scsi32(&toc[8]);
241 	t_info->ti_data_mode = get_data_mode(dev->d_fd, read_scsi32(&toc[8]));
242 
243 	/* Numbers for audio tracks are always in 2K chunks */
244 	if ((dev->d_blksize == 512) && ((t_info->ti_track_mode & 4) == 0)) {
245 		t_info->ti_start_address /= 4;
246 		t_info->ti_track_size /= 4;
247 	}
248 
249 	/* Now find out the session thing */
250 	ret = read_toc(dev->d_fd, 1, trackno, 12, toc);
251 
252 	/*
253 	 * Make sure that the call succeeds and returns the requested
254 	 * TOC size correctly.
255 	 */
256 
257 	if ((ret == 0) || (toc[1] != 0x0a)) {
258 
259 		/* For ATAPI drives or old Toshiba drives */
260 		ret = read_toc_as_per_8020(dev->d_fd, 1, trackno, 12, toc);
261 	}
262 	/* If this goes through well TOC length will always be 0x0a */
263 	if (ret && (toc[1] == 0x0a)) {
264 		if (trackno >= toc[6]) {
265 			t_info->ti_session_no = toc[3];
266 			t_info->ti_flags |= TI_SESSION_NO_VALID;
267 		}
268 		/*
269 		 * This might be the last track of this session. If so,
270 		 * exclude the leadout and next lead in.
271 		 */
272 		if (trackno == (toc[6] - 1)) {
273 			/*
274 			 * 1.5 Min leadout + 1 min. leadin + 2 sec. pre-gap.
275 			 * For 2nd+ leadout it will be 0.5 min. But currently
276 			 * there is no direct way. And it will not happen
277 			 * for any normal case.
278 			 *
279 			 * 75 frames/sec, 60 sec/min, so leadin gap is
280 			 * ((1.5 +1)*60 + 2)*75 = 11400 frames (blocks)
281 			 */
282 			t_info->ti_track_size -= 11400;
283 		}
284 	} else {
285 		if (check_track_size(dev, trackno, t_info) != 1)
286 			return (0);
287 	}
288 
289 	return (1);
290 }
291 
292 /*
293  * The size of the last track in one of the first N - 1 sessions of an
294  * N-session (N > 1) disc is reported incorrectly by some drives and calculated
295  * incorrectly for others, because a pre-gap/lead-out/lead-in section that ends
296  * a session is erroneously considered part of that track. This function checks
297  * for this corner case, and adjusts the track size if necessary.
298  */
299 static int
300 check_track_size(cd_device *dev, int trk_num, struct track_info *tip)
301 {
302 	size_t raw_toc_len;
303 	uchar_t *raw_toc;
304 	rtoc_hdr_t hdr;
305 	uint32_t sess_leadout_lba;
306 	int sess_last_trk_num;
307 	int trk_sess_num;
308 	uint32_t trk_size;
309 
310 	/* Request Raw TOC Header for session count. */
311 	if (read_toc(dev->d_fd, FORMAT_RAW_TOC, 1,
312 	    sizeof (rtoc_hdr_t), (uchar_t *)&hdr) != 1)
313 		return (0);
314 
315 	/* Is this a multi-session medium? */
316 	if (hdr.rh_last_sess_num > hdr.rh_first_sess_num) {
317 		/* Yes; request entire Raw TOC. */
318 		raw_toc_len = read_scsi16(&hdr.rh_data_len1) + RTOC_DATA_LEN_SZ;
319 		raw_toc = (uchar_t *)my_zalloc(raw_toc_len);
320 
321 		if (read_toc(dev->d_fd, FORMAT_RAW_TOC, 1, raw_toc_len, raw_toc)
322 		    != 1)
323 			goto fail;
324 
325 		if (rtoc_get_trk_sess_num(raw_toc, raw_toc_len, trk_num,
326 		    &trk_sess_num) != 1)
327 			goto fail;
328 
329 		tip->ti_session_no = trk_sess_num;
330 		tip->ti_flags |= TI_SESSION_NO_VALID;
331 
332 		/* Is the track in one of the first N - 1 sessions? */
333 		if (trk_sess_num < hdr.rh_last_sess_num) {
334 			if (rtoc_get_sess_last_trk_num(raw_toc, raw_toc_len,
335 			    trk_sess_num, &sess_last_trk_num) != 1)
336 				goto fail;
337 
338 			/* Is the track the last track in the session? */
339 			if (trk_num == sess_last_trk_num) {
340 				if (rtoc_get_sess_leadout_lba(raw_toc,
341 				    raw_toc_len, trk_sess_num,
342 				    &sess_leadout_lba) != 1)
343 					goto fail;
344 
345 				trk_size = sess_leadout_lba -
346 				    tip->ti_start_address;
347 
348 				/* Fix track size if it was too big. */
349 				if (tip->ti_track_size > trk_size)
350 					tip->ti_track_size = trk_size;
351 			}
352 		}
353 		free(raw_toc);
354 	}
355 	return (1);
356 
357 fail:
358 	free(raw_toc);
359 	return (0);
360 }
361 
362 /*
363  * Determine what session number a track is in by parsing the Raw TOC format of
364  * the the READ TOC/PMA/ATIP command response data.
365  */
366 static int
367 rtoc_get_trk_sess_num(uchar_t *rtoc, size_t rtoc_len, int trk_num,
368     int *sess_nump)
369 {
370 	rtoc_td_t *tdp = (rtoc_td_t *)(rtoc + sizeof (rtoc_hdr_t));
371 	rtoc_td_t *last_tdp = (rtoc_td_t *)(rtoc + rtoc_len -
372 	    sizeof (rtoc_td_t));
373 
374 	if ((tdp = get_rtoc_td(tdp, last_tdp, Q_MODE_1, (uchar_t)trk_num)) !=
375 	    NULL) {
376 		*sess_nump = tdp->rt_session_num;
377 		return (1);
378 	} else
379 		return (0);
380 }
381 
382 /*
383  * Determine the last track number in a specified session number by parsing the
384  * Raw TOC format of the READ TOC/PMA/ATIP command response data.
385  */
386 static int
387 rtoc_get_sess_last_trk_num(uchar_t *rtoc, size_t rtoc_len, int sess_num,
388     int *last_trk_nump)
389 {
390 	rtoc_td_t *tdp = (rtoc_td_t *)(rtoc + sizeof (rtoc_hdr_t));
391 	rtoc_td_t *last_tdp = (rtoc_td_t *)(rtoc + rtoc_len -
392 	    sizeof (rtoc_td_t));
393 
394 	while ((tdp = get_rtoc_td(tdp, last_tdp, Q_MODE_1,
395 	    POINT_SESS_LAST_TRK)) != NULL) {
396 		if (tdp->rt_session_num == sess_num) {
397 			*last_trk_nump = tdp->rt_pmin;
398 			return (1);
399 		} else {
400 			++tdp;
401 		}
402 	}
403 
404 	return (0);
405 }
406 
407 /*
408  * Determine the starting LBA of the the session leadout by parsing the Raw TOC
409  * format of the READ TOC/PMA/ATIP command response data.
410  */
411 static int
412 rtoc_get_sess_leadout_lba(uchar_t *rtoc, size_t rtoc_len, int sess_num,
413     uint32_t *leadout_lba)
414 {
415 	rtoc_td_t *tdp = (rtoc_td_t *)(rtoc + sizeof (rtoc_hdr_t));
416 	rtoc_td_t *last_tdp = (rtoc_td_t *)(rtoc + rtoc_len -
417 	    sizeof (rtoc_td_t));
418 
419 	while ((tdp = get_rtoc_td(tdp, last_tdp, Q_MODE_1,
420 	    POINT_LEADOUT_ADDR)) != NULL) {
421 		if (tdp->rt_session_num == sess_num) {
422 			*leadout_lba = MSF2LBA(tdp->rt_pmin, tdp->rt_psec,
423 			    tdp->rt_pframe);
424 			return (1);
425 		} else {
426 			++tdp;
427 		}
428 	}
429 
430 	return (0);
431 }
432 
433 /*
434  * Search a set of Raw TOC Track Descriptors using <'adr', 'point'> as the
435  * search key. Return a pointer to the first Track Descriptor that matches.
436  */
437 static rtoc_td_t *
438 get_rtoc_td(rtoc_td_t *begin_tdp, rtoc_td_t *end_tdp, uchar_t adr,
439     uchar_t point)
440 {
441 	rtoc_td_t *cur_tdp = begin_tdp;
442 
443 	while (cur_tdp <= end_tdp) {
444 		if ((cur_tdp->rt_adr == adr) && (cur_tdp->rt_point == point))
445 			return (cur_tdp);
446 		else
447 			cur_tdp++;
448 	}
449 
450 	return (NULL);
451 }
452 
453 uchar_t
454 get_data_mode(int fd, uint32_t lba)
455 {
456 	int ret;
457 	uchar_t *buf;
458 	uchar_t mode;
459 
460 	buf = (uchar_t *)my_zalloc(8);
461 	ret = read_header(fd, lba, buf);
462 	if (ret == 0)
463 		mode = 0xff;
464 	else
465 		mode = buf[0];
466 	free(buf);
467 	return (mode);
468 }
469 
470 /*
471  * Set page code 5 for TAO mode.
472  */
473 int
474 prepare_for_write(cd_device *dev, int track_mode, int test_write,
475     int keep_disc_open)
476 {
477 	uchar_t *buf;
478 	int no_err;
479 	int reset_device;
480 
481 	if ((write_mode == DAO_MODE) && keep_disc_open) {
482 		(void) printf(gettext(
483 		    "Multi-session is not supported on DVD media\n"));
484 		exit(1);
485 	}
486 
487 	if ((write_mode == DAO_MODE) && debug) {
488 		(void) printf("Preparing to write in DAO\n");
489 	}
490 
491 	(void) start_stop(dev->d_fd, 1);
492 	/* Some drives do not support this command but still do it */
493 	(void) rezero_unit(dev->d_fd);
494 
495 	buf = (uchar_t *)my_zalloc(64);
496 
497 	no_err = get_mode_page(dev->d_fd, 5, 0, 64, buf);
498 	if (no_err)
499 		no_err = ((buf[1] + 2) > 64) ? 0 : 1;
500 	/*
501 	 * If the device is already in simulation mode and again a
502 	 * simulation is requested, then set the device in non-simulation
503 	 * 1st and then take it to simulation mode. This will flush any
504 	 * previous fake state in the drive.
505 	 */
506 	if (no_err && test_write && (buf[2] & 0x10)) {
507 		reset_device = 1;
508 	} else {
509 		reset_device = 0;
510 	}
511 	if (no_err != 0) {
512 		buf[0] &= 0x3f;
513 
514 		/* set TAO or DAO writing mode */
515 		buf[2] = (write_mode == TAO_MODE)?1:2;
516 
517 		/* set simulation flag */
518 		if (test_write && (!reset_device)) {
519 			buf[2] |= 0x10;
520 		} else {
521 			buf[2] &= ~0x10;
522 		}
523 
524 		/* Turn on HW buffer underrun protection (BUFE) */
525 		if (!test_write) {
526 			buf[2] |= 0x40;
527 		}
528 
529 		/* set track mode type */
530 		if (device_type == CD_RW) {
531 			buf[3] = track_mode & 0x0f;	/* ctrl nibble */
532 		}
533 
534 		if (keep_disc_open) {
535 			buf[3] |= 0xc0;		/* Allow more sessions */
536 		}
537 
538 		/* Select track type (audio or data) */
539 		if (track_mode == TRACK_MODE_DATA) {
540 			buf[4] = 8;		/* 2048 byte sector */
541 		} else {
542 			buf[4] = 0;		/* 2352 byte sector */
543 		}
544 		buf[7] = buf[8] = 0;
545 
546 		/* Need to clear these fields for setting into DAO */
547 		if (write_mode == DAO_MODE)
548 			buf[5] = buf[15] = 0;
549 
550 		/* print out mode for detailed log */
551 		if (debug && verbose) {
552 			int i;
553 
554 			(void) printf("setting = [ ");
555 			for (i = 0; i < 15; i++)
556 				(void) printf("0x%x ", buf[i]);
557 			(void) printf("]\n");
558 		}
559 
560 		no_err = set_mode_page(dev->d_fd, buf);
561 
562 		if (no_err && reset_device) {
563 			/* Turn the test write bit back on */
564 			buf[2] |= 0x10;
565 			no_err = set_mode_page(dev->d_fd, buf);
566 		}
567 
568 		/*
569 		 * Since BUFE is the only optional flag we are
570 		 * setting we will try to turn it off if the command
571 		 * fails.
572 		 */
573 		if (!no_err) {
574 			/*
575 			 * Some old drives may not support HW
576 			 * buffer underrun protection, try again
577 			 * after turning it off.
578 			 */
579 			if (debug)
580 				(void) printf("Turning off BUFE\n");
581 			buf[2] &= ~0x40;
582 			no_err = set_mode_page(dev->d_fd, buf);
583 		}
584 	}
585 
586 	free(buf);
587 	return (no_err);
588 }
589 
590 /*
591  * Close session. This will write TOC.
592  */
593 int
594 finalize(cd_device *dev)
595 {
596 	uchar_t *di;
597 	int count, ret, err;
598 	int immediate;
599 	int finalize_max;
600 
601 	/*
602 	 * For ATAPI devices we will use the immediate mode and will
603 	 * poll the command for completion so that this command may
604 	 * not hog the channel. But for SCSI, we will use the treditional
605 	 * way of issuing the command with a large enough timeout. This
606 	 * is done because immediate mode was designed for ATAPI and some
607 	 * SCSI RW drives might not be even tested with it.
608 	 */
609 	if ((dev->d_inq[2] & 7) != 0) {
610 		/* SCSI device */
611 		immediate = 0;
612 	} else {
613 		/* non-SCSI (e.g ATAPI) device */
614 		immediate = 1;
615 	}
616 
617 	/* We need to close track before close session */
618 	if (device_type == DVD_PLUS) {
619 		if (!close_track(dev->d_fd, 0, 0, immediate))
620 			return (0);
621 	}
622 
623 	if (!close_track(dev->d_fd, 0, 1, immediate)) {
624 		/*
625 		 * For DAO mode which we use for DVD-RW, the latest MMC
626 		 * specification does not mention close_track. Some
627 		 * newer drives will return an ILLEGAL INSTRUCTION
628 		 * which we will ignore. We have also found a Panasonic
629 		 * drive which will return a MEDIA ERROR. It is safe
630 		 * to ignore both errors as this is not needed for
631 		 * these drives.
632 		 * This is kept for older drives which had needed
633 		 * us to issue close_track to flush the cache fully.
634 		 * once we are certain these drives have cleared the
635 		 * market, this can be removed.
636 		 */
637 		if (device_type == DVD_MINUS) {
638 			return (0);
639 		}
640 	} else {
641 		if (!immediate)
642 			return (1);
643 	}
644 	if (immediate) {
645 		(void) sleep(10);
646 
647 		di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
648 		err = 0;
649 
650 		if (device_type == CD_RW) {
651 			/* Finalization should not take more than 6 minutes */
652 			finalize_max = FINALIZE_TIMEOUT;
653 		} else {
654 			/* some DVD-RW drives take longer than 6 minutes */
655 			finalize_max = FINALIZE_TIMEOUT*2;
656 		}
657 
658 		for (count = 0; count < finalize_max; count++) {
659 			ret = read_disc_info(dev->d_fd, di);
660 			if (ret != 0)
661 				break;
662 			if (uscsi_status != 2)
663 				err = 1;
664 			if (SENSE_KEY(rqbuf) == 2) {
665 				/* not ready but not becoming ready */
666 				if (ASC(rqbuf) != 4)
667 					err = 1;
668 			} else if (SENSE_KEY(rqbuf) == 5) {
669 				/* illegal mode for this track */
670 				if (ASC(rqbuf) != 0x64)
671 					err = 1;
672 			} else {
673 				err = 1;
674 			}
675 			if (err == 1) {
676 				if (debug) {
677 					(void) printf("Finalization failed\n");
678 					(void) printf("%x %x %x %x\n",
679 					    uscsi_status, SENSE_KEY(rqbuf),
680 					    ASC(rqbuf), ASCQ(rqbuf));
681 				}
682 				free(di);
683 				return (0);
684 			}
685 			if (uscsi_status == 2) {
686 				int i;
687 				/* illegal field in command packet */
688 				if (ASC(rqbuf) == 0x24) {
689 					/* print it out! */
690 					(void) printf("\n");
691 					for (i = 0; i < 18; i++)
692 						(void) printf("%x ",
693 						    (unsigned)(rqbuf[i]));
694 					(void) printf("\n");
695 				}
696 			}
697 			(void) sleep(5);
698 		}
699 		free(di);
700 	}
701 	return (ret);
702 }
703 
704 /*
705  * Find out media capacity.
706  */
707 uint32_t
708 get_last_possible_lba(cd_device *dev)
709 {
710 	uchar_t *di;
711 	uint32_t cap;
712 
713 	di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
714 	if (!read_disc_info(dev->d_fd, di)) {
715 		free(di);
716 		return (0);
717 	}
718 
719 	/*
720 	 * If we have a DVD+R this field is an LBA. If the media is
721 	 * a CD-R/W the field is MSF formatted. Otherwise this field
722 	 * is not valid and will be zero.
723 	 */
724 	if (device_type == DVD_PLUS) {
725 		if (read_scsi32(&di[20]) != 0xffffffff) {
726 			cap = read_scsi32(&di[20]);
727 		} else {
728 			cap = 0;
729 		}
730 	} else {
731 		if ((di[21] != 0) && (di[21] != 0xff)) {
732 			cap = MSF2LBA(di[21], di[22], di[23]);
733 		} else {
734 			cap = 0;
735 		}
736 	}
737 
738 	free(di);
739 	return (cap);
740 }
741 
742 int
743 read_audio_through_read_cd(cd_device *dev, uint_t start_lba, uint_t nblks,
744     uchar_t *buf)
745 {
746 	int retry;
747 	int ret;
748 
749 	for (retry = 0; retry < 3; retry++) {
750 		ret = read_cd(dev->d_fd, (uint32_t)start_lba, (uint16_t)nblks,
751 		    1, buf, (uint32_t)(nblks * 2352));
752 		if (ret)
753 			break;
754 	}
755 	return (ret);
756 }
757 
758 int
759 eject_media(cd_device *dev)
760 {
761 	if (vol_running) {
762 		/* If there is a media, try using DKIOCEJECT 1st */
763 		if (check_device(dev, CHECK_NO_MEDIA) == 0) {
764 			/*
765 			 * The check_device() call will issue
766 			 * a TEST UNIT READY (TUR) and retry many
767 			 * times when a DVD-R is present. The DKIOCEJECT
768 			 * ioctl will subsequently fail causing us to
769 			 * issue the LOAD/UNLOAD SCSI command to the device
770 			 * with out ejecting the media. Insted of letting
771 			 * this happen, issue a reset to the device before
772 			 * issuing the DKIOCEJCET ioctl.
773 			 */
774 			if (device_type == DVD_MINUS)
775 				reset_dev(dev->d_fd);
776 
777 			if (ioctl(dev->d_fd, DKIOCEJECT, 0) == 0) {
778 				return (1);
779 			}
780 		}
781 	}
782 	if (load_unload(dev->d_fd, 0) == 0) {
783 		/* if eject fails */
784 		if ((uscsi_status == 2) && (ASC(rqbuf) == 0x53)) {
785 			/*
786 			 * check that eject is not blocked on the device
787 			 */
788 			if (!prevent_allow_mr(dev->d_fd, 1))
789 				return (0);
790 			return (load_unload(dev->d_fd, 0));
791 		}
792 		return (0);
793 	}
794 	return (1);
795 }
796 
797 /*
798  * Get current Read or Write Speed from Mode Page 0x2a.
799  *
800  * Use the size of the Page to determine which Multimedia Command
801  * set (MMC) is present.  Based on the MMC version, get the
802  * specified Read/Write Speed.
803  *
804  * Note that some MMC versions do not necessarily support a
805  * (current) Read or Write Speed.  As a result, this function
806  * _can_ return a value of zero.
807  *
808  * The newer standards (reserve and) mark the field(s) as Obsolete,
809  * yet many vendors populate the Obsolete fields with valid values
810  * (assumedly for backward compatibility).  This is important, as
811  * a command like GET PERFORMANCE cannot return _the_ speed; it can
812  * only return a Logical-Block-Address-dependent (LBA) speed.  Such
813  * values can vary widely between the innermost and outermost Track.
814  * Mode Page 0x2a is the best solution identifying "the current
815  * (nominal) speed".
816  */
817 static uint16_t
818 cd_speed_get(cd_device *dev, int cmd)
819 {
820 	uchar_t		*mp2a;
821 	uint16_t	rate = 0;
822 	int		offset;
823 	uint_t		buflen = 254;
824 
825 	/*
826 	 * Allocate a buffer acceptably larger than any nominal
827 	 * Page for Page Code 0x2A.
828 	 */
829 	mp2a = (uchar_t *)my_zalloc(buflen);
830 	if (get_mode_page(dev->d_fd, 0x2A, 0, buflen, mp2a) == 0)
831 		goto end;
832 
833 	/* Determine MMC version based on 'Page Length' field */
834 	switch (mp2a[1]) {
835 	case 0x14:  /* MMC-1 */
836 		if (debug)
837 			(void) printf("Mode Page 2A: MMC-1\n");
838 
839 		offset = (cmd == GET_READ_SPEED) ? 14 : 20;
840 		rate = read_scsi16(&mp2a[offset]);
841 		break;
842 
843 
844 	case 0x18: /* MMC-2 */
845 		if (debug)
846 			(void) printf("Mode Page 2A: MMC-2;"
847 			    " Read and Write Speeds are "
848 			    "obsolete\n");
849 
850 		/* see if "Obsolete" values are valid: */
851 		offset = (cmd == GET_READ_SPEED) ? 14 : 20;
852 		rate = read_scsi16(&mp2a[offset]);
853 		break;
854 
855 	default: /* MMC-3 or newer */
856 		if (debug)
857 			(void) printf("Mode Page 2A: MMC-3 or"
858 			    " newer; Read Speed is obsolete.\n");
859 
860 		if (cmd == GET_READ_SPEED) {
861 			/* this is Obsolete, but try it */
862 			offset = 14;
863 			rate = read_scsi16(&mp2a[offset]);
864 		} else {
865 			/* Write Speed is not obsolete */
866 			offset = 28;
867 			rate = read_scsi16(&mp2a[offset]);
868 
869 			if (rate == 0) {
870 				/*
871 				 * then try an Obsolete field
872 				 * (but this shouldn't happen!)
873 				 */
874 				offset = 20;
875 				rate = read_scsi16(&mp2a[offset]);
876 			}
877 		}
878 		break;
879 	}
880 end:
881 	free(mp2a);
882 
883 	if (debug)
884 		(void) printf("cd_speed_get: %s Speed is "
885 		    "%uX\n", (cmd == GET_READ_SPEED) ?
886 		    "Read" : "Write", cdrw_bandwidth_to_x(rate));
887 	return (rate);
888 }
889 
890 /*
891  * CD speed related functions (ioctl style) for drives which do not support
892  * real time streaming.
893  *
894  * For the SET operations, the SET CD SPEED command needs
895  * both the Read Speed and the Write Speed.  Eg, if
896  * we're trying to set the Write Speed (SET_WRITE_SPEED),
897  * then we first need to obtain the current Read Speed.
898  * That speed is specified along with the chosen_speed (the
899  * Write Speed in this case) in the SET CD SPEED command.
900  */
901 int
902 cd_speed_ctrl(cd_device *dev, int cmd, int speed)
903 {
904 	uint16_t rate;
905 
906 	switch (cmd) {
907 	case GET_READ_SPEED:
908 		rate = cd_speed_get(dev, GET_READ_SPEED);
909 		return (cdrw_bandwidth_to_x(rate));
910 
911 	case GET_WRITE_SPEED:
912 		rate = cd_speed_get(dev, GET_WRITE_SPEED);
913 		return (cdrw_bandwidth_to_x(rate));
914 
915 	case SET_READ_SPEED:
916 		rate = cd_speed_get(dev, GET_WRITE_SPEED);
917 		return (set_cd_speed(dev->d_fd,
918 		    cdrw_x_to_bandwidth(speed), rate));
919 
920 	case SET_WRITE_SPEED:
921 		rate = cd_speed_get(dev, GET_READ_SPEED);
922 		return (set_cd_speed(dev->d_fd, rate,
923 		    cdrw_x_to_bandwidth(speed)));
924 
925 	default:
926 		return (0);
927 	}
928 }
929 
930 /*
931  * Manage sending of SET STREAMING command using the specified
932  * read_speed and write_speed.
933  *
934  * This function allocates and initializes a Performance
935  * Descriptor, which is sent as part of the SET STREAMING
936  * command.  The descriptor is deallocated before function
937  * exit.
938  */
939 static int
940 do_set_streaming(cd_device *dev, uint_t read_speed,
941 	uint_t write_speed)
942 {
943 	int ret;
944 	uchar_t *str;
945 
946 	/* Allocate and initialize the Performance Descriptor */
947 	str = (uchar_t *)my_zalloc(SET_STREAM_DATA_LEN);
948 
949 	/* Read Time (in milliseconds) */
950 	load_scsi32(&str[16], 1000);
951 	/* Write Time (in milliseconds) */
952 	load_scsi32(&str[24], 1000);
953 
954 	/* Read Speed */
955 	load_scsi32(&str[12], (uint32_t)read_speed);
956 	/* Write Speed */
957 	load_scsi32(&str[20], (uint32_t)write_speed);
958 
959 	/* issue SET STREAMING command */
960 	ret = set_streaming(dev->d_fd, str);
961 	free(str);
962 
963 	return (ret);
964 }
965 
966 /*
967  * cd speed related functions for drives which support
968  * Real-Time Streaming Feature.
969  *
970  * For the SET operations, the SET STREAMING command needs
971  * both the Read Speed and the Write Speed.  Eg, if
972  * we're trying to set the Write Speed (SET_WRITE_SPEED),
973  * then we first need to obtain the current Read Speed.
974  * That speed is specified along with the chosen_speed (the
975  * Write Speed in this case) in the SET STREAMING command.
976  */
977 int
978 rt_streaming_ctrl(cd_device *dev, int cmd, int speed)
979 {
980 	int ret = 0;
981 	uint_t rate;
982 
983 	switch (cmd) {
984 	case GET_WRITE_SPEED:
985 		rate = cd_speed_get(dev, GET_WRITE_SPEED);
986 		ret = (int)cdrw_bandwidth_to_x(rate);
987 		break;
988 
989 	case GET_READ_SPEED:
990 		rate = cd_speed_get(dev, GET_READ_SPEED);
991 		ret = (int)cdrw_bandwidth_to_x(rate);
992 		break;
993 
994 	case SET_READ_SPEED: {
995 		uint_t write_speed = cd_speed_get(dev, GET_WRITE_SPEED);
996 
997 		/* set Read Speed using SET STREAMING */
998 		ret = do_set_streaming(dev,
999 		    cdrw_x_to_bandwidth(speed), write_speed);
1000 
1001 		/* If rt_speed_ctrl fails for any reason use cd_speed_ctrl */
1002 		if (ret == 0) {
1003 			if (debug)
1004 				(void) printf(" real time speed control"
1005 				    " failed, using CD speed control\n");
1006 
1007 			dev->d_speed_ctrl = cd_speed_ctrl;
1008 			ret = dev->d_speed_ctrl(dev, cmd, speed);
1009 		}
1010 		break;
1011 	}
1012 
1013 	case SET_WRITE_SPEED: {
1014 		uint_t read_speed = cd_speed_get(dev, GET_READ_SPEED);
1015 
1016 		/* set Write Speed using SET STREAMING */
1017 		ret = do_set_streaming(dev, read_speed,
1018 		    cdrw_x_to_bandwidth(speed));
1019 
1020 		/* If rt_speed_ctrl fails for any reason use cd_speed_ctrl */
1021 		if (ret == 0) {
1022 			if (debug)
1023 				(void) printf(" real time speed control"
1024 				    " failed, using CD speed control\n");
1025 
1026 			dev->d_speed_ctrl = cd_speed_ctrl;
1027 			ret = dev->d_speed_ctrl(dev, cmd, speed);
1028 		}
1029 		break;
1030 	}
1031 
1032 	default:
1033 		break;
1034 	}
1035 
1036 	return (ret);
1037 }
1038 
1039 /*
1040  * Initialize device for track-at-once mode of writing. All of the data will
1041  * need to be written to the track without interruption.
1042  * This initialized TAO by setting page code 5 and speed.
1043  */
1044 void
1045 write_init(int mode)
1046 {
1047 	(void) printf(gettext("Initializing device"));
1048 	if (simulation)
1049 		(void) printf(gettext("(Simulation mode)"));
1050 	print_n_flush("...");
1051 
1052 	get_media_type(target->d_fd);
1053 
1054 	/* DVD- requires DAO mode */
1055 	if (device_type == DVD_MINUS) {
1056 		write_mode = DAO_MODE;
1057 	}
1058 
1059 	/* DVD+ and DVD- have no support for AUDIO, bail out */
1060 	if ((mode == TRACK_MODE_AUDIO) && (device_type != CD_RW)) {
1061 		err_msg(gettext("Audio mode is only supported for CD media\n"));
1062 		exit(1);
1063 	}
1064 	if (simulation &&
1065 	    check_device(target, CHECK_MEDIA_IS_NOT_BLANK) &&
1066 	    !check_device(target, CHECK_MEDIA_IS_NOT_ERASABLE) &&
1067 	    device_type != DVD_PLUS_W) {
1068 		/*
1069 		 * If we were in simulation mode, and media wasn't blank,
1070 		 * but medium was erasable, then cdrw goes to erase the
1071 		 * contents of the media after the simulation writing in order
1072 		 * to cleanup the ghost TOC (see write_fini() calls blank()).
1073 		 * This is bad because it removes existing data if media was
1074 		 * multi-session. Therefore, we no longer allow simulation
1075 		 * writing if such condition is met. we don't blank the DVD+RW
1076 		 * media, so DVD+RWs are fine.
1077 		 */
1078 		err_msg(gettext(
1079 		    "Cannot perform simulation for non-blank media\n"));
1080 		exit(1);
1081 	}
1082 
1083 	if (!prepare_for_write(target, mode, simulation, keep_disc_open)) {
1084 		/* l10n_NOTE : 'failed' as in Initializing device...failed  */
1085 		(void) printf(gettext("failed.\n"));
1086 		err_msg(gettext("Cannot initialize device for write\n"));
1087 		exit(1);
1088 	}
1089 	/* l10n_NOTE : 'done' as in "Initializing device...done"  */
1090 	(void) printf(gettext("done.\n"));
1091 
1092 	/* if speed change option was used (-p) then try to set the speed */
1093 	if (requested_speed != 0) {
1094 		if (verbose)
1095 			(void) printf(gettext("Trying to set speed to %dX.\n"),
1096 			    requested_speed);
1097 		if (target->d_speed_ctrl(target, SET_WRITE_SPEED,
1098 		    requested_speed) == 0) {
1099 			err_msg(gettext("Unable to set speed.\n"));
1100 			exit(1);
1101 		}
1102 		if (verbose) {
1103 			int speed;
1104 			speed = target->d_speed_ctrl(target,
1105 			    GET_WRITE_SPEED, 0);
1106 			if (speed == requested_speed) {
1107 				(void) printf(gettext("Speed set to %dX.\n"),
1108 				    speed);
1109 			} else if (speed == 0) {
1110 				(void) printf(gettext("Could not obtain "
1111 				    "current Write Speed.\n"));
1112 			} else {
1113 				(void) printf(
1114 				gettext("Speed set to closest approximation "
1115 				    "of %dX allowed by device (%dX).\n"),
1116 				    requested_speed, speed);
1117 			}
1118 		}
1119 	}
1120 }
1121 
1122 void
1123 write_fini(void)
1124 {
1125 	print_n_flush(gettext("Finalizing (Can take several minutes)..."));
1126 	/* Some drives don't like this while in test write mode */
1127 	if (!simulation) {
1128 		if (!finalize(target)) {
1129 			/*
1130 			 * It is possible that the drive is busy writing the
1131 			 * buffered portion. So do not get upset yet.
1132 			 */
1133 			(void) sleep(10);
1134 			if (!finalize(target)) {
1135 				if (debug) {
1136 					(void) printf("status %x, %x/%x/%x\n",
1137 					    uscsi_status, SENSE_KEY(rqbuf),
1138 					    ASC(rqbuf), ASCQ(rqbuf));
1139 				}
1140 
1141 				/*
1142 				 * Different vendor drives return different
1143 				 * sense error info for CLOSE SESSION command.
1144 				 * The Panasonic drive that we are using is
1145 				 * one such drive.
1146 				 */
1147 				if (device_type == DVD_MINUS) {
1148 					if (verbose) {
1149 						(void) printf(
1150 						    "skipping finalizing\n");
1151 					}
1152 				} else {
1153 
1154 			/* l10n_NOTE : 'failed' as in finishing up...failed  */
1155 					(void) printf(gettext("failed.\n"));
1156 
1157 					err_msg(gettext(
1158 					    "Could not finalize the disc.\n"));
1159 					exit(1);
1160 				}
1161 
1162 
1163 			}
1164 		}
1165 		if (vol_running) {
1166 			(void) eject_media(target);
1167 		}
1168 	} else if (check_device(target, CHECK_MEDIA_IS_NOT_BLANK)) {
1169 		/*
1170 		 * Some drives such as the pioneer A04 will retain a
1171 		 * ghost TOC after a simulation write is done. The
1172 		 * media will actually be blank, but the drive will
1173 		 * report a TOC. There is currently no other way to
1174 		 * re-initialize the media other than ejecting or
1175 		 * to ask the drive to clear the leadout. The laser
1176 		 * is currently off so nothing is written to the
1177 		 * media (on a good behaving drive).
1178 		 * NOTE that a device reset does not work to make
1179 		 * the drive re-initialize the media.
1180 		 */
1181 
1182 		blanking_type = "clear_ghost";
1183 		blank();
1184 
1185 	}
1186 	/* l10n_NOTE : 'done' as in "Finishing up...done"  */
1187 	(void) printf(gettext("done.\n"));
1188 }
1189