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