Home | History | Annotate | Download | only in cdrw
      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 2005 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 <libintl.h>
     33 #include <unistd.h>
     34 
     35 #include "msgs.h"
     36 #include "mmc.h"
     37 #include "util.h"
     38 #include "transport.h"
     39 #include "main.h"
     40 #include "misc_scsi.h"
     41 
     42 /*
     43  * This is called recursively once, if an ALL blank succeeds but the
     44  * media is not blank we call blank() again to perform a fast blank.
     45  * This is a workaround for some drives such as older Toshiba DVD-RW
     46  * which has this problem with ALL blanking.
     47  */
     48 void
     49 blank(void)
     50 {
     51 	int type, invalid;
     52 	int count, ret;
     53 	uchar_t *di, *buf;
     54 	int immediate, err;
     55 	int silent_pass = 0;
     56 	/*
     57 	 * silent_pass is set to 1 whenever we do not want to print
     58 	 * information messages. This is the case where blank() function
     59 	 * is called within the blank() function or the blank() function
     60 	 * is called from other functions within cdrw to blank the media
     61 	 * as part of other operations (clearing ghost TOC, closing the media
     62 	 * after a write operation, etc). In all those cases we need not print
     63 	 * or duplicate information messages. We should also return from the
     64 	 * blank() function to the calling function in those cases.
     65 	 */
     66 	int ignore_error = 0;
     67 	/*
     68 	 * ignore_error is set to 1 whenever we do not want to report any
     69 	 * error messages to the user and make things transparent to the
     70 	 * user (For eg: Clearing ghost TOC during write simulation).
     71 	 */
     72 
     73 	invalid = 0;
     74 	err = 0;
     75 
     76 	(void) check_device(target, CHECK_TYPE_NOT_CDROM | CHECK_NO_MEDIA |
     77 	    EXIT_IF_CHECK_FAILED);
     78 	(void) check_device(target, CHECK_DEVICE_NOT_READY |
     79 	    CHECK_DEVICE_NOT_WRITABLE | EXIT_IF_CHECK_FAILED);
     80 
     81 	if (blanking_type == NULL) {
     82 		invalid = 1;
     83 	}
     84 
     85 	get_media_type(target->d_fd);
     86 
     87 	if (strcmp(blanking_type, "all") == 0) {
     88 		/* erase the whole disk */
     89 		type = ALL;
     90 	} else if (strcmp(blanking_type, "session") == 0) {
     91 		/* only erase the last session */
     92 		type = SESSION;
     93 	} else if (strcmp(blanking_type, "fast") == 0) {
     94 		/* quick blank the TOC on the media */
     95 		type = FAST;
     96 	} else if (strcmp(blanking_type, "leadout") == 0) {
     97 		/* erase the track tail to unclose the media */
     98 		type = LEADOUT;
     99 		silent_pass = 1;
    100 	} else if (strcmp(blanking_type, "clear") == 0) {
    101 		/*
    102 		 * used for drives where "all" blanking fails,
    103 		 * if it fails we follow up with a quick erase of TOC.
    104 		 * This is only called from within this function to do
    105 		 * a second blanking pass.
    106 		 */
    107 		type = CLEAR;
    108 		silent_pass = 1;
    109 	} else if (strcmp(blanking_type, "clear_ghost") == 0) {
    110 		/*
    111 		 * used for drives in simulation mode to blank ghost
    112 		 * TOC after simulation write is complete.
    113 		 */
    114 		type = CLEAR;
    115 		silent_pass = 1;
    116 		ignore_error = 1;
    117 	} else {
    118 		/* invalid blank type was passed on the command line */
    119 		invalid = 1;
    120 	}
    121 
    122 	if (invalid) {
    123 		err_msg(gettext("Invalid blanking type specified\n"));
    124 		exit(1);
    125 	}
    126 
    127 	/*
    128 	 * many DVD+RW drives do not allow blanking the media, it is also
    129 	 * not included in the spec, we would just reformat the media prior
    130 	 * to writing. This is not the equivelent to blanking as the media
    131 	 * contains a TOC when formatted.
    132 	 */
    133 	if (device_type == DVD_PLUS_W) {
    134 		if (ignore_error)
    135 			return;
    136 		err_msg(gettext("Blanking cannot be done on DVD+RW media\n"));
    137 		exit(1);
    138 	}
    139 
    140 	if ((target->d_inq[2] & 7) != 0) {
    141 		/* SCSI device */
    142 		immediate = 0;
    143 	} else {
    144 		/* non-SCSI (e.g ATAPI) device */
    145 		immediate = 1;
    146 	}
    147 
    148 	/* we are doing a second pass. We don't want to re-print messsages */
    149 	if (!silent_pass)
    150 		print_n_flush(gettext("Initializing device..."));
    151 
    152 	/* Make sure that test write is off */
    153 	buf = (uchar_t *)my_zalloc(64);
    154 
    155 	/* get mode page for test writing if it fails we cannot turn it off */
    156 	if (!get_mode_page(target->d_fd, 5, 0, 64, buf)) {
    157 		if (ignore_error)
    158 			return;
    159 		err_msg(gettext("Device not supported\n"));
    160 		exit(1);
    161 	}
    162 
    163 	buf[2] &= 0xef;
    164 
    165 	/* turn laser on */
    166 	if (!set_mode_page(target->d_fd, buf)) {
    167 		if (ignore_error)
    168 			return;
    169 		err_msg(gettext("Unable to configure device\n"));
    170 		exit(1);
    171 	}
    172 	free(buf);
    173 
    174 	/* we are doing a second pass. We don't want to re-print messsages */
    175 	if (!silent_pass) {
    176 		/* l10n_NOTE : 'done' as in "Initializing device...done"  */
    177 		(void) printf(gettext("done.\n"));
    178 
    179 		print_n_flush(gettext(
    180 		    "Blanking the media (Can take several minutes)..."));
    181 	}
    182 	if (!blank_disc(target->d_fd, type, immediate)) {
    183 		if (ignore_error)
    184 			return;
    185 		err_msg(gettext("Blank command failed\n"));
    186 		if (debug)
    187 			(void) printf("%x %x %x %x\n", uscsi_status,
    188 			    SENSE_KEY(rqbuf), ASC(rqbuf), ASCQ(rqbuf));
    189 		goto blank_failed;
    190 	}
    191 	/* Allow the blanking to start */
    192 	(void) sleep(10);
    193 
    194 	/*
    195 	 * set ATAPI devices to immediately return from the command and poll
    196 	 * so that we don't hog the channel.
    197 	 */
    198 
    199 	if (immediate) {
    200 		di = (uchar_t *)my_zalloc(DISC_INFO_BLOCK_SIZE);
    201 		/* Blanking should not take more than 75 minutes */
    202 		for (count = 0; count < (16*60); count++) {
    203 			ret = read_disc_info(target->d_fd, di);
    204 			if (ret != 0)
    205 				break;
    206 			if (uscsi_status != 2)
    207 				err = 1;
    208 			/* not ready but not becoming ready */
    209 			if (SENSE_KEY(rqbuf) == 2) {
    210 				if (ASC(rqbuf) != 4)
    211 					err = 1;
    212 			/* illegal mode for this track */
    213 			} else if (SENSE_KEY(rqbuf) == 5) {
    214 				if (ASC(rqbuf) != 0x64)
    215 					err = 1;
    216 			} else {
    217 				err = 1;
    218 			}
    219 			if (err == 1) {
    220 				if (ignore_error)
    221 					break;
    222 				err_msg(gettext("Blanking operation failed\n"));
    223 				if (debug) {
    224 					(void) printf("%x %x %x %x\n",
    225 					    uscsi_status, SENSE_KEY(rqbuf),
    226 					    ASC(rqbuf), ASCQ(rqbuf));
    227 				}
    228 				free(di);
    229 				goto blank_failed;
    230 			}
    231 			(void) sleep(5);
    232 		}
    233 		free(di);
    234 		if (count == (16*60)) {
    235 			if (!silent_pass) {
    236 				(void) printf(gettext(
    237 				    "Blank command timed out.\n"));
    238 			}
    239 			goto blank_failed;
    240 		}
    241 	}
    242 	/* we are doing a second pass. We don't want to re-print messsages */
    243 	if (!silent_pass) {
    244 		/* l10n_NOTE : 'done' as in "Erasing track 1...done"  */
    245 		(void) printf(gettext("done.\n"));
    246 	}
    247 
    248 	/*
    249 	 * some cruft left from all blanking, this has been seen on some
    250 	 * newer drives including Toshiba SD-6112 DVD-RW and Sony 510A.
    251 	 * we will do a second pass with a recursive call to blank the
    252 	 * lead-in.
    253 	 */
    254 	if (type == ALL) {
    255 		if (check_device(target,  CHECK_MEDIA_IS_NOT_BLANK)) {
    256 			blanking_type = "clear";
    257 			blank();
    258 			if (silent_pass)
    259 				return;
    260 			exit(0);
    261 		}
    262 	}
    263 
    264 	/*
    265 	 * We erased part of the leadout for the media to unclose
    266 	 * the disk, we still need to generate an appendable leadout
    267 	 * so that the next track can be written. so do not eject or exit.
    268 	 */
    269 	if (silent_pass)
    270 		return;
    271 
    272 	if (vol_running)
    273 		(void) eject_media(target);
    274 	exit(0);
    275 blank_failed:
    276 	if ((type != ALL) && !silent_pass) {
    277 		(void) printf("Try using blanking type 'all'\n");
    278 	}
    279 	if (silent_pass)
    280 		return;
    281 	if (vol_running)
    282 		(void) eject_media(target);
    283 	exit(1);
    284 }
    285