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