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