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