1 1.10 andvar /* $NetBSD: mmcformat.c,v 1.10 2025/07/11 20:45:27 andvar Exp $ */ 2 1.1 reinoud 3 1.1 reinoud /* 4 1.1 reinoud * Copyright (c) 2006, 2008 Reinoud Zandijk 5 1.1 reinoud * All rights reserved. 6 1.9 rillig * 7 1.1 reinoud * Redistribution and use in source and binary forms, with or without 8 1.1 reinoud * modification, are permitted provided that the following conditions 9 1.1 reinoud * are met: 10 1.1 reinoud * 1. Redistributions of source code must retain the above copyright 11 1.1 reinoud * notice, this list of conditions and the following disclaimer. 12 1.1 reinoud * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 reinoud * notice, this list of conditions and the following disclaimer in the 14 1.1 reinoud * documentation and/or other materials provided with the distribution. 15 1.9 rillig * 16 1.1 reinoud * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 1.1 reinoud * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 1.1 reinoud * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 1.1 reinoud * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 1.1 reinoud * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 1.1 reinoud * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 1.1 reinoud * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 1.1 reinoud * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 1.1 reinoud * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 1.1 reinoud * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 1.9 rillig * 27 1.1 reinoud */ 28 1.1 reinoud 29 1.9 rillig #include <sys/cdefs.h> 30 1.10 andvar __RCSID("$NetBSD: mmcformat.c,v 1.10 2025/07/11 20:45:27 andvar Exp $"); 31 1.9 rillig 32 1.9 rillig #include <sys/types.h> 33 1.9 rillig #include <sys/time.h> 34 1.9 rillig #include <assert.h> 35 1.9 rillig #include <errno.h> 36 1.9 rillig #include <fcntl.h> 37 1.9 rillig #include <inttypes.h> 38 1.9 rillig #include <limits.h> 39 1.1 reinoud #include <stdio.h> 40 1.1 reinoud #include <stdlib.h> 41 1.1 reinoud #include <string.h> 42 1.1 reinoud #include <strings.h> 43 1.9 rillig #include <unistd.h> 44 1.1 reinoud 45 1.1 reinoud #include "uscsilib.h" 46 1.1 reinoud 47 1.1 reinoud 48 1.1 reinoud /* globals */ 49 1.9 rillig static struct uscsi_dev dev; 50 1.1 reinoud extern int scsilib_verbose; 51 1.1 reinoud 52 1.1 reinoud /* #define DEBUG(a) {a;} */ 53 1.1 reinoud #define DEBUG(a) ; 54 1.1 reinoud 55 1.1 reinoud 56 1.1 reinoud static uint64_t 57 1.1 reinoud getmtime(void) 58 1.1 reinoud { 59 1.1 reinoud struct timeval tp; 60 1.1 reinoud 61 1.1 reinoud gettimeofday(&tp, NULL); 62 1.1 reinoud return (uint64_t) 1000000 * tp.tv_sec + tp.tv_usec; 63 1.1 reinoud } 64 1.1 reinoud 65 1.1 reinoud 66 1.1 reinoud static void 67 1.1 reinoud print_eta(uint32_t progress, uint64_t now, uint64_t start_time) 68 1.1 reinoud { 69 1.1 reinoud int hours, minutes, seconds; 70 1.1 reinoud uint64_t tbusy, ttot_est, eta; 71 1.1 reinoud 72 1.1 reinoud if (progress == 0) { 73 1.1 reinoud printf(" ETA --:--:--"); 74 1.1 reinoud return; 75 1.1 reinoud } 76 1.1 reinoud tbusy = now - start_time; 77 1.1 reinoud ttot_est = (tbusy * 0x10000) / progress; 78 1.1 reinoud eta = (ttot_est - tbusy) / 1000000; 79 1.1 reinoud 80 1.1 reinoud hours = (int) (eta/3600); 81 1.1 reinoud minutes = (int) (eta/60) % 60; 82 1.1 reinoud seconds = (int) eta % 60; 83 1.1 reinoud printf(" ETA %02d:%02d:%02d", hours, minutes, seconds); 84 1.1 reinoud } 85 1.1 reinoud 86 1.1 reinoud 87 1.1 reinoud static void 88 1.1 reinoud uscsi_waitop(struct uscsi_dev *mydev) 89 1.1 reinoud { 90 1.1 reinoud scsicmd cmd; 91 1.1 reinoud struct uscsi_sense sense; 92 1.1 reinoud uint64_t start_time; 93 1.1 reinoud uint32_t progress; 94 1.1 reinoud uint8_t buffer[256]; 95 1.1 reinoud int asc, ascq; 96 1.1 reinoud int cnt = 0; 97 1.1 reinoud 98 1.1 reinoud bzero(cmd, SCSI_CMD_LEN); 99 1.1 reinoud bzero(buffer, sizeof(buffer)); 100 1.1 reinoud 101 1.1 reinoud /* 102 1.7 andvar * not be to impatient... give the drive some time to start or it 103 1.1 reinoud * might break off 104 1.1 reinoud */ 105 1.1 reinoud 106 1.1 reinoud start_time = getmtime(); 107 1.1 reinoud sleep(10); 108 1.1 reinoud 109 1.1 reinoud progress = 0; 110 1.1 reinoud while (progress < 0x10000) { 111 1.1 reinoud /* we need a command that is NOT going to stop the formatting */ 112 1.1 reinoud bzero(cmd, SCSI_CMD_LEN); 113 1.1 reinoud cmd[0] = 0; /* test unit ready */ 114 1.1 reinoud uscsi_command(SCSI_READCMD, mydev, 115 1.1 reinoud cmd, 6, buffer, 0, 10000, &sense); 116 1.1 reinoud 117 1.1 reinoud /* 118 1.1 reinoud * asc may be `not-ready' or `no-sense'. ascq for format in 119 1.1 reinoud * progress is 4 too 120 1.1 reinoud */ 121 1.1 reinoud asc = sense.asc; 122 1.1 reinoud ascq = sense.ascq; 123 1.1 reinoud if (((asc == 0) && (ascq == 4)) || (asc == 4)) { 124 1.1 reinoud /* drive not ready : operation/format in progress */ 125 1.1 reinoud if (sense.skey_valid) { 126 1.1 reinoud progress = sense.sense_key; 127 1.1 reinoud } else { 128 1.1 reinoud /* finished */ 129 1.1 reinoud progress = 0x10000; 130 1.1 reinoud } 131 1.1 reinoud } 132 1.1 reinoud /* check if drive is ready again, ifso break out loop */ 133 1.1 reinoud if ((asc == 0) && (ascq == 0)) { 134 1.1 reinoud progress = 0x10000; 135 1.1 reinoud } 136 1.1 reinoud 137 1.1 reinoud printf("%3d %% ", (100 * progress / 0x10000)); 138 1.1 reinoud printf("%c", "|/-\\" [cnt++ %4]); /* twirl */ 139 1.1 reinoud 140 1.1 reinoud /* print ETA */ 141 1.1 reinoud print_eta(progress, getmtime(), start_time); 142 1.1 reinoud 143 1.1 reinoud fflush(stdout); 144 1.1 reinoud sleep(1); 145 1.1 reinoud printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 146 1.1 reinoud fflush(stdout); 147 1.1 reinoud } 148 1.1 reinoud printf("\n"); 149 1.1 reinoud 150 1.1 reinoud return; 151 1.1 reinoud } 152 1.1 reinoud 153 1.1 reinoud 154 1.1 reinoud static char const * 155 1.1 reinoud print_mmc_profile(int profile) 156 1.1 reinoud { 157 1.1 reinoud static char scrap[100]; 158 1.1 reinoud 159 1.1 reinoud switch (profile) { 160 1.1 reinoud case 0x00 : return "Unknown[0] profile"; 161 1.7 andvar case 0x01 : return "Non removable disc"; 162 1.1 reinoud case 0x02 : return "Removable disc"; 163 1.1 reinoud case 0x03 : return "Magneto Optical with sector erase"; 164 1.1 reinoud case 0x04 : return "Magneto Optical write once"; 165 1.1 reinoud case 0x05 : return "Advance Storage Magneto Optical"; 166 1.1 reinoud case 0x08 : return "CD-ROM"; 167 1.1 reinoud case 0x09 : return "CD-R recordable"; 168 1.1 reinoud case 0x0a : return "CD-RW rewritable"; 169 1.1 reinoud case 0x10 : return "DVD-ROM"; 170 1.1 reinoud case 0x11 : return "DVD-R sequential"; 171 1.1 reinoud case 0x12 : return "DVD-RAM rewritable"; 172 1.1 reinoud case 0x13 : return "DVD-RW restricted overwrite"; 173 1.1 reinoud case 0x14 : return "DVD-RW sequential"; 174 1.1 reinoud case 0x1a : return "DVD+RW rewritable"; 175 1.1 reinoud case 0x1b : return "DVD+R recordable"; 176 1.1 reinoud case 0x20 : return "DDCD readonly"; 177 1.1 reinoud case 0x21 : return "DDCD-R recordable"; 178 1.1 reinoud case 0x22 : return "DDCD-RW rewritable"; 179 1.1 reinoud case 0x2b : return "DVD+R double layer"; 180 1.1 reinoud case 0x40 : return "BD-ROM"; 181 1.1 reinoud case 0x41 : return "BD-R Sequential Recording (SRM)"; 182 1.1 reinoud case 0x42 : return "BD-R Random Recording (RRM)"; 183 1.1 reinoud case 0x43 : return "BD-RE rewritable"; 184 1.1 reinoud } 185 1.1 reinoud sprintf(scrap, "Reserved profile 0x%02x", profile); 186 1.1 reinoud return scrap; 187 1.1 reinoud } 188 1.1 reinoud 189 1.1 reinoud 190 1.1 reinoud static int 191 1.1 reinoud uscsi_get_mmc_profile(struct uscsi_dev *mydev, int *mmc_profile) 192 1.1 reinoud { 193 1.1 reinoud scsicmd cmd; 194 1.1 reinoud uint8_t buf[32]; 195 1.1 reinoud int error; 196 1.1 reinoud 197 1.1 reinoud *mmc_profile = 0; 198 1.1 reinoud 199 1.1 reinoud bzero(cmd, SCSI_CMD_LEN); 200 1.1 reinoud cmd[ 0] = 0x46; /* Get configuration */ 201 1.1 reinoud cmd[ 8] = 32; /* just a small buffer size */ 202 1.1 reinoud cmd[ 9] = 0; /* control */ 203 1.1 reinoud error = uscsi_command(SCSI_READCMD, mydev, cmd, 10, buf, 32, 30000, NULL); 204 1.1 reinoud if (!error) { 205 1.1 reinoud *mmc_profile = buf[7] | (buf[6] << 8); 206 1.1 reinoud } 207 1.1 reinoud 208 1.1 reinoud return error; 209 1.1 reinoud } 210 1.1 reinoud 211 1.1 reinoud 212 1.1 reinoud static int 213 1.1 reinoud uscsi_set_packet_parameters(struct uscsi_dev *mydev, int blockingnr) 214 1.1 reinoud { 215 1.1 reinoud scsicmd cmd; 216 1.2 tron int val_len; 217 1.2 tron uint8_t res[10000], *pos; 218 1.1 reinoud int error; 219 1.1 reinoud 220 1.1 reinoud /* Set up CD/DVD recording parameters */ 221 1.1 reinoud DEBUG(printf("Setting device's recording parameters\n")); 222 1.1 reinoud 223 1.1 reinoud val_len = 0x32+2+8; 224 1.1 reinoud bzero(res, val_len); 225 1.1 reinoud 226 1.1 reinoud pos = res + 8; 227 1.1 reinoud 228 1.1 reinoud bzero(cmd, SCSI_CMD_LEN); 229 1.1 reinoud pos[ 0] = 0x05; /* page code 5 : cd writing */ 230 1.1 reinoud pos[ 1] = 0x32; /* length in bytes */ 231 1.1 reinoud pos[ 2] = 0; /* write type 0 : packet/incremental */ 232 1.1 reinoud 233 1.1 reinoud /* next session OK, data packet, rec. incr. fixed packets */ 234 1.1 reinoud pos[ 3] = (3<<6) | 32 | 5; 235 1.1 reinoud pos[ 4] = 10; /* ISO mode 2; XA form 1 */ 236 1.1 reinoud pos[ 8] = 0x20; /* CD-ROM XA disc or DDCD disc */ 237 1.1 reinoud pos[10] = (blockingnr >> 24) & 0xff; /* MSB packet size */ 238 1.1 reinoud pos[11] = (blockingnr >> 16) & 0xff; 239 1.1 reinoud pos[12] = (blockingnr >> 8) & 0xff; 240 1.1 reinoud pos[13] = (blockingnr ) & 0xff; /* LSB packet size */ 241 1.1 reinoud 242 1.1 reinoud bzero(cmd, SCSI_CMD_LEN); 243 1.1 reinoud cmd[0] = 0x55; /* MODE SELECT (10) */ 244 1.1 reinoud cmd[1] = 16; /* PF format */ 245 1.1 reinoud cmd[7] = val_len >> 8; /* length of blob */ 246 1.1 reinoud cmd[8] = val_len & 0xff; 247 1.1 reinoud cmd[9] = 0; /* control */ 248 1.1 reinoud 249 1.1 reinoud error = uscsi_command(SCSI_WRITECMD, mydev, 250 1.1 reinoud cmd, 10, res, val_len, 30000, NULL); 251 1.1 reinoud if (error) { 252 1.10 andvar perror("While WRITING parameter page 5"); 253 1.1 reinoud return error; 254 1.1 reinoud } 255 1.1 reinoud 256 1.1 reinoud /* flag OK */ 257 1.1 reinoud return 0; 258 1.1 reinoud } 259 1.1 reinoud 260 1.1 reinoud 261 1.1 reinoud static int 262 1.1 reinoud get_format_capabilities(struct uscsi_dev *mydev, uint8_t *buf, uint32_t *len) 263 1.1 reinoud { 264 1.1 reinoud scsicmd cmd; 265 1.1 reinoud int list_length; 266 1.3 lukem int trans_len; 267 1.3 lukem size_t buf_len = 512; 268 1.1 reinoud int error; 269 1.1 reinoud 270 1.1 reinoud assert(*len >= buf_len); 271 1.1 reinoud bzero(buf, buf_len); 272 1.1 reinoud 273 1.1 reinoud trans_len = 12; /* only fixed header first */ 274 1.1 reinoud bzero(cmd, SCSI_CMD_LEN); 275 1.1 reinoud cmd[0] = 0x23; /* Read format capabilities */ 276 1.1 reinoud cmd[7] = trans_len >> 8; /* MSB allocation length */ 277 1.1 reinoud cmd[8] = trans_len & 0xff; /* LSB allocation length */ 278 1.1 reinoud cmd[9] = 0; /* control */ 279 1.1 reinoud error = uscsi_command(SCSI_READCMD, mydev, 280 1.1 reinoud cmd, 10, buf, trans_len, 30000, NULL); 281 1.1 reinoud if (error) { 282 1.1 reinoud fprintf(stderr, "While reading format capabilities : %s\n", 283 1.1 reinoud strerror(error)); 284 1.1 reinoud return error; 285 1.1 reinoud } 286 1.1 reinoud 287 1.1 reinoud list_length = buf[ 3]; 288 1.1 reinoud 289 1.1 reinoud if (list_length % 8) { 290 1.1 reinoud printf( "\t\tWarning: violating SCSI spec," 291 1.1 reinoud "capacity list length ought to be multiple of 8\n"); 292 1.1 reinoud printf("\t\tInterpreting as including header of 4 bytes\n"); 293 1.1 reinoud assert(list_length % 8 == 4); 294 1.1 reinoud list_length -= 4; 295 1.1 reinoud } 296 1.1 reinoud 297 1.1 reinoud /* read in full capacity list */ 298 1.1 reinoud trans_len = 12 + list_length; /* complete structure */ 299 1.1 reinoud bzero(cmd, SCSI_CMD_LEN); 300 1.1 reinoud cmd[0] = 0x23; /* Read format capabilities */ 301 1.1 reinoud cmd[7] = trans_len >> 8; /* MSB allocation length */ 302 1.1 reinoud cmd[8] = trans_len & 0xff; /* LSB allocation length */ 303 1.1 reinoud cmd[9] = 0; /* control */ 304 1.1 reinoud error = uscsi_command(SCSI_READCMD, mydev, 305 1.1 reinoud cmd, 10, buf, trans_len, 30000, NULL); 306 1.1 reinoud if (error) { 307 1.1 reinoud fprintf(stderr, "While reading format capabilities : %s\n", 308 1.1 reinoud strerror(error)); 309 1.1 reinoud return error; 310 1.1 reinoud } 311 1.1 reinoud 312 1.1 reinoud *len = list_length; 313 1.1 reinoud return 0; 314 1.1 reinoud } 315 1.1 reinoud 316 1.1 reinoud 317 1.1 reinoud static void 318 1.1 reinoud print_format(int format_tp, uint32_t num_blks, uint32_t param, 319 1.9 rillig int dscr_type, int verbose, int *supported) 320 1.1 reinoud { 321 1.1 reinoud char const *format_str, *nblks_str, *param_str, *user_spec; 322 1.1 reinoud 323 1.1 reinoud format_str = nblks_str = param_str = "reserved"; 324 1.1 reinoud user_spec = ""; 325 1.1 reinoud *supported = 1; 326 1.1 reinoud 327 1.1 reinoud switch (format_tp) { 328 1.1 reinoud case 0x00 : 329 1.1 reinoud format_str = "full format capacity"; 330 1.1 reinoud nblks_str = "sectors"; 331 1.1 reinoud param_str = "block length in bytes"; 332 1.1 reinoud user_spec = "'-F [-b blockingnr]'"; 333 1.1 reinoud break; 334 1.1 reinoud case 0x01 : 335 1.1 reinoud format_str = "spare area expansion"; 336 1.1 reinoud nblks_str = "extension in blocks"; 337 1.1 reinoud param_str = "block length in bytes"; 338 1.1 reinoud user_spec = "'-S'"; 339 1.1 reinoud break; 340 1.1 reinoud /* 0x02 - 0x03 reserved */ 341 1.1 reinoud case 0x04 : 342 1.1 reinoud format_str = "variable length zone'd format"; 343 1.1 reinoud nblks_str = "zone length"; 344 1.1 reinoud param_str = "zone number"; 345 1.1 reinoud *supported = 0; 346 1.1 reinoud break; 347 1.1 reinoud case 0x05 : 348 1.1 reinoud format_str = "fixed length zone'd format"; 349 1.6 msaitoh nblks_str = "zone length"; 350 1.1 reinoud param_str = "last zone number"; 351 1.1 reinoud *supported = 0; 352 1.1 reinoud break; 353 1.1 reinoud /* 0x06 - 0x0f reserved */ 354 1.1 reinoud case 0x10 : 355 1.1 reinoud format_str = "CD-RW/DVD-RW full packet format"; 356 1.7 andvar nblks_str = "addressable blocks"; 357 1.1 reinoud param_str = "fixed packet size/ECC blocksize in sectors"; 358 1.1 reinoud user_spec = "'-F -p [-b blockingnr]'"; 359 1.1 reinoud break; 360 1.1 reinoud case 0x11 : 361 1.1 reinoud format_str = "CD-RW/DVD-RW grow session"; 362 1.7 andvar nblks_str = "addressable blocks"; 363 1.1 reinoud param_str = "fixed packet size/ECC blocksize in sectors"; 364 1.1 reinoud user_spec = "'-G'"; 365 1.1 reinoud break; 366 1.1 reinoud case 0x12 : 367 1.1 reinoud format_str = "CD-RW/DVD-RW add session"; 368 1.7 andvar nblks_str = "addressable blocks"; 369 1.1 reinoud param_str = "maximum fixed packet size/ECC blocksize " 370 1.1 reinoud "in sectors"; 371 1.1 reinoud *supported = 0; 372 1.1 reinoud break; 373 1.1 reinoud case 0x13 : 374 1.1 reinoud format_str = "DVD-RW max growth of last complete session"; 375 1.7 andvar nblks_str = "addressable blocks"; 376 1.1 reinoud param_str = "ECC blocksize in sectors"; 377 1.1 reinoud user_spec = "'-G'"; 378 1.1 reinoud break; 379 1.1 reinoud case 0x14 : 380 1.1 reinoud format_str = "DVD-RW quick grow last session"; 381 1.7 andvar nblks_str = "addressable blocks"; 382 1.1 reinoud param_str = "ECC blocksize in sectors"; 383 1.1 reinoud *supported = 0; 384 1.1 reinoud break; 385 1.1 reinoud case 0x15 : 386 1.1 reinoud format_str = "DVD-RW quick full format"; 387 1.7 andvar nblks_str = "addressable blocks"; 388 1.1 reinoud param_str = "ECC blocksize in sectors"; 389 1.1 reinoud *supported = 0; 390 1.1 reinoud break; 391 1.1 reinoud /* 0x16 - 0x23 reserved */ 392 1.1 reinoud case 0x24 : 393 1.1 reinoud format_str = "background MRW format"; 394 1.1 reinoud nblks_str = "Defect Management Area blocks"; 395 1.1 reinoud param_str = "not used"; 396 1.1 reinoud user_spec = "'[-R] [-s] [-w] -F -M [-b blockingnr]'"; 397 1.1 reinoud break; 398 1.1 reinoud /* 0x25 reserved */ 399 1.1 reinoud case 0x26 : 400 1.1 reinoud format_str = "background DVD+RW full format"; 401 1.1 reinoud nblks_str = "sectors"; 402 1.1 reinoud param_str = "not used"; 403 1.1 reinoud user_spec = "'[-R] [-w] -F'"; 404 1.1 reinoud break; 405 1.1 reinoud /* 0x27 - 0x2f reserved */ 406 1.1 reinoud case 0x30 : 407 1.1 reinoud format_str = "BD-RE full format with spare area"; 408 1.1 reinoud nblks_str = "blocks"; 409 1.1 reinoud param_str = "total spare area size in clusters"; 410 1.1 reinoud user_spec = "'[-s] -F'"; 411 1.1 reinoud break; 412 1.1 reinoud case 0x31 : 413 1.1 reinoud format_str = "BD-RE full format without spare area"; 414 1.1 reinoud nblks_str = "blocks"; 415 1.1 reinoud param_str = "block length in bytes"; 416 1.1 reinoud user_spec = "'-F'"; 417 1.1 reinoud break; 418 1.1 reinoud /* 0x32 - 0x3f reserved */ 419 1.1 reinoud default : 420 1.1 reinoud break; 421 1.1 reinoud } 422 1.1 reinoud 423 1.1 reinoud if (verbose) { 424 1.1 reinoud printf("\n\tFormat type 0x%02x : %s\n", format_tp, format_str); 425 1.1 reinoud 426 1.1 reinoud switch (dscr_type) { 427 1.1 reinoud case 1 : 428 1.1 reinoud printf( "\t\tUnformatted media," 429 1.1 reinoud "maximum formatted capacity\n"); 430 1.1 reinoud break; 431 1.1 reinoud case 2 : 432 1.1 reinoud printf( "\t\tFormatted media," 433 1.1 reinoud "current formatted capacity\n"); 434 1.1 reinoud break; 435 1.1 reinoud case 3 : 436 1.1 reinoud printf( "\t\tNo media present or incomplete session, " 437 1.1 reinoud "maximum formatted capacity\n"); 438 1.1 reinoud break; 439 1.1 reinoud default : 440 1.1 reinoud printf("\t\tUnspecified descriptor type\n"); 441 1.1 reinoud break; 442 1.1 reinoud } 443 1.1 reinoud 444 1.1 reinoud printf("\t\tNumber of blocks : %12d\t(%s)\n", 445 1.1 reinoud num_blks, nblks_str); 446 1.1 reinoud printf("\t\tParameter : %12d\t(%s)\n", 447 1.1 reinoud param, param_str); 448 1.1 reinoud 449 1.1 reinoud if (format_tp == 0x24) { 450 1.1 reinoud printf( "\t\tExpert select : " 451 1.1 reinoud "'-X 0x%02x:0xffffff:0' or " 452 1.1 reinoud "'-X 0x%02x:0xffff0000:0'\n", 453 1.1 reinoud format_tp, format_tp); 454 1.1 reinoud } else { 455 1.1 reinoud printf( "\t\tExpert select : " 456 1.1 reinoud "'-X 0x%02x:%d:%d'\n", 457 1.1 reinoud format_tp, num_blks, param); 458 1.1 reinoud } 459 1.1 reinoud if (*supported) { 460 1.1 reinoud printf("\t\tmmc_format arg : %s\n", user_spec); 461 1.1 reinoud } else { 462 1.1 reinoud printf("\t\t** not supported **\n"); 463 1.1 reinoud } 464 1.1 reinoud } 465 1.1 reinoud } 466 1.1 reinoud 467 1.1 reinoud 468 1.1 reinoud static void 469 1.1 reinoud process_format_caps(uint8_t *buf, int list_length, int verbose, 470 1.1 reinoud uint8_t *allow, uint32_t *blks, uint32_t *params) 471 1.1 reinoud { 472 1.1 reinoud uint32_t num_blks, param; 473 1.1 reinoud uint8_t *fcd; 474 1.1 reinoud int dscr_type, format_tp; 475 1.1 reinoud int supported; 476 1.1 reinoud 477 1.1 reinoud bzero(allow, 255); 478 1.1 reinoud bzero(blks, 255*4); 479 1.1 reinoud bzero(params, 255*4); 480 1.9 rillig 481 1.1 reinoud fcd = buf + 4; 482 1.1 reinoud list_length -= 4; /* strip header */ 483 1.1 reinoud 484 1.1 reinoud if (verbose) 485 1.1 reinoud printf("\tCurrent/max capacity followed by additional capacity," 486 1.1 reinoud "reported length of %d bytes (8/entry)\n", list_length); 487 1.1 reinoud 488 1.1 reinoud while (list_length > 0) { 489 1.1 reinoud num_blks = fcd[ 3] | (fcd[ 2] << 8) | 490 1.1 reinoud (fcd[ 1] << 16) | (fcd[ 0] << 24); 491 1.1 reinoud dscr_type = fcd[ 4] & 3; 492 1.1 reinoud format_tp = fcd[ 4] >> 2; 493 1.1 reinoud param = fcd[ 7] | (fcd[ 6] << 8) | (fcd[ 5] << 16); 494 1.1 reinoud 495 1.1 reinoud print_format(format_tp, num_blks, param, dscr_type, verbose, 496 1.1 reinoud &supported); 497 1.1 reinoud 498 1.1 reinoud allow[format_tp] = 1; /* TODO = supported? */ 499 1.1 reinoud blks[format_tp] = num_blks; 500 1.1 reinoud params[format_tp] = param; 501 1.1 reinoud 502 1.1 reinoud fcd += 8; 503 1.1 reinoud list_length-=8; 504 1.1 reinoud } 505 1.1 reinoud } 506 1.1 reinoud 507 1.1 reinoud 508 1.1 reinoud 509 1.1 reinoud /* format a CD-RW disc */ 510 1.1 reinoud /* old style format 7 */ 511 1.1 reinoud static int 512 1.1 reinoud uscsi_format_cdrw_mode7(struct uscsi_dev *mydev, uint32_t blocks) 513 1.1 reinoud { 514 1.1 reinoud scsicmd cmd; 515 1.1 reinoud struct uscsi_sense sense; 516 1.1 reinoud uint8_t buffer[16]; 517 1.4 christos int error; 518 1.1 reinoud 519 1.1 reinoud if (blocks % 32) { 520 1.1 reinoud blocks -= blocks % 32; 521 1.1 reinoud } 522 1.1 reinoud 523 1.1 reinoud bzero(cmd, SCSI_CMD_LEN); 524 1.1 reinoud bzero(buffer, sizeof(buffer)); 525 1.1 reinoud 526 1.1 reinoud cmd[0] = 0x04; /* format unit */ 527 1.1 reinoud cmd[1] = 0x17; /* parameter list format 7 follows */ 528 1.1 reinoud cmd[5] = 0; /* control */ 529 1.1 reinoud 530 1.1 reinoud /* format list header */ 531 1.1 reinoud buffer[ 0] = 0; /* reserved */ 532 1.1 reinoud buffer[ 1] = 0x80 | 0x02; /* Valid info, immediate return */ 533 1.1 reinoud buffer[ 2] = 0; /* MSB format descriptor length */ 534 1.1 reinoud buffer[ 3] = 8; /* LSB ... */ 535 1.1 reinoud 536 1.1 reinoud /* 537 1.1 reinoud * for CD-RW the initialisation pattern bit is reserved, but there IS 538 1.1 reinoud * one 539 1.1 reinoud */ 540 1.1 reinoud 541 1.1 reinoud buffer[ 4] = 0; /* no header */ 542 1.1 reinoud buffer[ 5] = 0; /* default pattern */ 543 1.1 reinoud buffer[ 6] = 0; /* pattern length MSB */ 544 1.1 reinoud buffer[ 7] = 0; /* pattern length LSB */ 545 1.1 reinoud 546 1.1 reinoud /* 8 bytes of format descriptor */ 547 1.1 reinoud /* (s)ession bit 1<<7, (g)row bit 1<<6 */ 548 1.1 reinoud /* SG action */ 549 1.1 reinoud /* 00 format disc with number of user data blocks */ 550 1.1 reinoud /* 10 create new session with number of data blocks */ 551 1.1 reinoud /* x1 grow session to be number of data blocks */ 552 1.1 reinoud 553 1.1 reinoud buffer[ 8] = 0x00; /* session and grow bits (7 and 6) */ 554 1.1 reinoud buffer[ 9] = 0; /* reserved */ 555 1.1 reinoud buffer[10] = 0; /* reserved */ 556 1.1 reinoud buffer[11] = 0; /* reserved */ 557 1.1 reinoud buffer[12] = (blocks >> 24) & 0xff; /* blocks MSB */ 558 1.1 reinoud buffer[13] = (blocks >> 16) & 0xff; 559 1.1 reinoud buffer[14] = (blocks >> 8) & 0xff; 560 1.1 reinoud buffer[15] = (blocks ) & 0xff; /* blocks LSB */ 561 1.1 reinoud 562 1.1 reinoud /* this will take a while .... */ 563 1.1 reinoud error = uscsi_command(SCSI_WRITECMD, mydev, 564 1.1 reinoud cmd, 6, buffer, sizeof(buffer), UINT_MAX, &sense); 565 1.1 reinoud if (error) 566 1.1 reinoud return error; 567 1.1 reinoud 568 1.1 reinoud uscsi_waitop(mydev); 569 1.1 reinoud return 0; 570 1.1 reinoud } 571 1.1 reinoud 572 1.1 reinoud 573 1.1 reinoud static int 574 1.1 reinoud uscsi_format_disc(struct uscsi_dev *mydev, int immed, int format_type, 575 1.9 rillig uint32_t blocks, uint32_t param, int certification, int cmplist) 576 1.1 reinoud { 577 1.1 reinoud scsicmd cmd; 578 1.1 reinoud struct uscsi_sense sense; 579 1.1 reinoud uint8_t buffer[16], fmt_flags; 580 1.1 reinoud int error; 581 1.1 reinoud 582 1.1 reinoud fmt_flags = 0x80; /* valid info flag */ 583 1.1 reinoud if (immed) 584 1.1 reinoud fmt_flags |= 2; 585 1.1 reinoud if (certification == 0) 586 1.1 reinoud fmt_flags |= 32; 587 1.1 reinoud 588 1.1 reinoud if (cmplist) 589 1.1 reinoud cmplist = 8; 590 1.1 reinoud 591 1.1 reinoud #if 0 592 1.1 reinoud if (mmc_profile != 0x43) { 593 1.1 reinoud /* certification specifier only valid for BD-RE */ 594 1.1 reinoud certification = 0; 595 1.1 reinoud } 596 1.1 reinoud #endif 597 1.1 reinoud 598 1.1 reinoud bzero(cmd, SCSI_CMD_LEN); 599 1.1 reinoud bzero(buffer, sizeof(buffer)); 600 1.1 reinoud 601 1.1 reinoud cmd[0] = 0x04; /* format unit */ 602 1.1 reinoud cmd[1] = 0x11 | cmplist; /* parameter list format 1 follows */ 603 1.1 reinoud cmd[5] = 0; /* control */ 604 1.1 reinoud 605 1.1 reinoud /* format list header */ 606 1.1 reinoud buffer[ 0] = 0; /* reserved */ 607 1.1 reinoud buffer[ 1] = 0x80 | fmt_flags; /* Valid info, flags follow */ 608 1.1 reinoud buffer[ 2] = 0; /* MSB format descriptor length */ 609 1.1 reinoud buffer[ 3] = 8; /* LSB ... */ 610 1.1 reinoud 611 1.1 reinoud /* 8 bytes of format descriptor */ 612 1.1 reinoud buffer[ 4] = (blocks >> 24) & 0xff; /* blocks MSB */ 613 1.1 reinoud buffer[ 5] = (blocks >> 16) & 0xff; 614 1.1 reinoud buffer[ 6] = (blocks >> 8) & 0xff; 615 1.1 reinoud buffer[ 7] = (blocks ) & 0xff; /* blocks LSB */ 616 1.1 reinoud buffer[ 8] = (format_type << 2) | certification; 617 1.1 reinoud buffer[ 9] = (param >> 16) & 0xff; /* parameter MSB */ 618 1.1 reinoud buffer[10] = (param >> 8) & 0xff; /* packet size */ 619 1.1 reinoud buffer[11] = (param ) & 0xff; /* parameter LSB */ 620 1.1 reinoud 621 1.1 reinoud /* this will take a while .... */ 622 1.1 reinoud error = uscsi_command(SCSI_WRITECMD, mydev, 623 1.1 reinoud cmd, 6, buffer, 12, UINT_MAX, &sense); 624 1.1 reinoud if (error) 625 1.1 reinoud return error; 626 1.1 reinoud 627 1.1 reinoud if (immed) 628 1.1 reinoud uscsi_waitop(mydev); 629 1.1 reinoud 630 1.1 reinoud return 0; 631 1.1 reinoud } 632 1.1 reinoud 633 1.1 reinoud 634 1.1 reinoud static int 635 1.1 reinoud uscsi_blank_disc(struct uscsi_dev *mydev) 636 1.1 reinoud { 637 1.1 reinoud scsicmd cmd; 638 1.1 reinoud int error; 639 1.1 reinoud 640 1.1 reinoud /* XXX check if the device can blank! */ 641 1.1 reinoud 642 1.1 reinoud 643 1.1 reinoud /* blank disc */ 644 1.1 reinoud bzero(cmd, SCSI_CMD_LEN); 645 1.1 reinoud cmd[ 0] = 0xA1; /* blank */ 646 1.1 reinoud cmd[ 1] = 16; /* Immediate, blank complete */ 647 1.1 reinoud cmd[11] = 0; /* control */ 648 1.1 reinoud 649 1.1 reinoud /* this will take a while .... */ 650 1.1 reinoud error = uscsi_command(SCSI_WRITECMD, mydev, 651 1.1 reinoud cmd, 12, NULL, 0, UINT_MAX, NULL); 652 1.1 reinoud if (error) 653 1.1 reinoud return error; 654 1.1 reinoud 655 1.1 reinoud uscsi_waitop(mydev); 656 1.1 reinoud return 0; 657 1.1 reinoud } 658 1.1 reinoud 659 1.1 reinoud 660 1.1 reinoud static int 661 1.1 reinoud usage(char *program) 662 1.1 reinoud { 663 1.1 reinoud fprintf(stderr, "\n"); 664 1.1 reinoud fprintf(stderr, "Usage: %s [options] devicename\n", program); 665 1.1 reinoud fprintf(stderr, 666 1.1 reinoud "-B blank cd-rw disc before formatting\n" 667 1.1 reinoud "-F format cd-rw disc\n" 668 1.1 reinoud "-O CD-RW formatting 'old-style' for old CD-RW drives\n" 669 1.1 reinoud "-M select MRW format\n" 670 1.1 reinoud "-R restart MRW & DVD+RW format\n" 671 1.1 reinoud "-G grow last CD-RW/DVD-RW session\n" 672 1.1 reinoud "-S grow spare space DVD-RAM/BD-RE\n" 673 1.1 reinoud "-s format DVD+MRW/BD-RE with extra spare space\n" 674 1.1 reinoud "-w wait until completion of background format\n" 675 1.1 reinoud "-p explicitly set packet format\n" 676 1.1 reinoud "-c num media certification for DVD-RAM/BD-RE : " 677 1.1 reinoud "0 no, 1 full, 2 quick\n" 678 1.1 reinoud "-r recompile defect list for DVD-RAM (cmplist)\n" 679 1.1 reinoud "-h -H -I help/inquiry formats\n" 680 1.1 reinoud "-X format expert format selector form 'fmt:blks:param' with -c\n" 681 1.1 reinoud "-b blockingnr in sectors (for CD-RW)\n" 682 1.1 reinoud "-D verbose SCSI command errors\n" 683 1.1 reinoud ); 684 1.1 reinoud return 1; 685 1.1 reinoud } 686 1.1 reinoud 687 1.1 reinoud 688 1.1 reinoud int 689 1.1 reinoud main(int argc, char *argv[]) 690 1.1 reinoud { 691 1.1 reinoud struct uscsi_addr saddr; 692 1.1 reinoud uint32_t blks[256], params[256]; 693 1.1 reinoud uint32_t format_type, format_blks, format_param, blockingnr; 694 1.1 reinoud uint8_t allow[256]; 695 1.2 tron uint8_t caps[512]; 696 1.2 tron uint32_t caps_len = sizeof(caps); 697 1.1 reinoud char *progname; 698 1.1 reinoud int blank, format, mrw, background; 699 1.1 reinoud int inquiry, spare, oldtimer; 700 1.1 reinoud int expert; 701 1.1 reinoud int restart_format, grow_session, grow_spare, packet_wr; 702 1.1 reinoud int mmc_profile, flag, error, display_usage; 703 1.1 reinoud int certification, cmplist; 704 1.1 reinoud int wait_until_finished; 705 1.1 reinoud progname = strdup(argv[0]); 706 1.1 reinoud if (argc == 1) { 707 1.1 reinoud return usage(progname); 708 1.1 reinoud } 709 1.1 reinoud 710 1.1 reinoud blank = 0; 711 1.1 reinoud format = 0; 712 1.1 reinoud mrw = 0; 713 1.1 reinoud restart_format = 0; 714 1.1 reinoud grow_session = 0; 715 1.1 reinoud grow_spare = 0; 716 1.1 reinoud wait_until_finished = 0; 717 1.1 reinoud packet_wr = 0; 718 1.1 reinoud certification = 1; 719 1.1 reinoud cmplist = 0; 720 1.1 reinoud inquiry = 0; 721 1.1 reinoud spare = 0; 722 1.1 reinoud inquiry = 0; 723 1.1 reinoud oldtimer = 0; 724 1.1 reinoud expert = 0; 725 1.1 reinoud display_usage = 0; 726 1.1 reinoud blockingnr = 32; 727 1.1 reinoud uscsilib_verbose = 0; 728 1.1 reinoud while ((flag = getopt(argc, argv, "BFMRGSwpsc:rhHIX:Ob:D")) != -1) { 729 1.1 reinoud switch (flag) { 730 1.1 reinoud case 'B' : 731 1.1 reinoud blank = 1; 732 1.1 reinoud break; 733 1.1 reinoud case 'F' : 734 1.1 reinoud format = 1; 735 1.1 reinoud break; 736 1.1 reinoud case 'M' : 737 1.1 reinoud mrw = 1; 738 1.1 reinoud break; 739 1.1 reinoud case 'R' : 740 1.1 reinoud restart_format = 1; 741 1.1 reinoud break; 742 1.1 reinoud case 'G' : 743 1.1 reinoud grow_session = 1; 744 1.1 reinoud break; 745 1.1 reinoud case 'S' : 746 1.1 reinoud grow_spare = 1; 747 1.1 reinoud break; 748 1.1 reinoud case 'w' : 749 1.1 reinoud wait_until_finished = 1; 750 1.1 reinoud break; 751 1.1 reinoud case 'p' : 752 1.1 reinoud packet_wr = 1; 753 1.1 reinoud break; 754 1.1 reinoud case 's' : 755 1.1 reinoud spare = 1; 756 1.1 reinoud break; 757 1.1 reinoud case 'c' : 758 1.1 reinoud certification = atoi(optarg); 759 1.1 reinoud break; 760 1.1 reinoud case 'r' : 761 1.1 reinoud cmplist = 1; 762 1.1 reinoud break; 763 1.1 reinoud case 'h' : 764 1.1 reinoud case 'H' : 765 1.1 reinoud display_usage = 1; 766 1.5 mrg break; 767 1.1 reinoud case 'I' : 768 1.1 reinoud inquiry = 1; 769 1.1 reinoud break; 770 1.1 reinoud case 'X' : 771 1.1 reinoud /* TODO parse expert mode string */ 772 1.1 reinoud printf("-X not implemented yet\n"); 773 1.1 reinoud expert = 1; 774 1.1 reinoud exit(1); 775 1.1 reinoud break; 776 1.1 reinoud case 'O' : 777 1.1 reinoud /* oldtimer CD-RW format */ 778 1.1 reinoud oldtimer = 1; 779 1.1 reinoud format = 1; 780 1.1 reinoud break; 781 1.1 reinoud case 'b' : 782 1.1 reinoud blockingnr = atoi(optarg); 783 1.1 reinoud break; 784 1.1 reinoud case 'D' : 785 1.1 reinoud uscsilib_verbose = 1; 786 1.1 reinoud break; 787 1.1 reinoud default : 788 1.1 reinoud return usage(progname); 789 1.1 reinoud } 790 1.1 reinoud } 791 1.1 reinoud argv += optind; 792 1.1 reinoud argc -= optind; 793 1.1 reinoud 794 1.5 mrg if (!blank && !format && !grow_session && !grow_spare && 795 1.5 mrg !expert && !inquiry && !display_usage) { 796 1.5 mrg fprintf(stderr, "%s : at least one of -B, -F, -G, -h, -H -S, " 797 1.5 mrg "-X or -I needs to be specified\n\n", progname); 798 1.1 reinoud return usage(progname); 799 1.1 reinoud } 800 1.1 reinoud 801 1.1 reinoud if (format + grow_session + grow_spare + expert > 1) { 802 1.1 reinoud fprintf(stderr, "%s : at most one of -F, -G, -S or -X " 803 1.1 reinoud "needs to be specified\n\n", progname); 804 1.1 reinoud return usage(progname); 805 1.1 reinoud } 806 1.1 reinoud 807 1.1 reinoud if (argc != 1) return usage(progname); 808 1.1 reinoud 809 1.1 reinoud /* Open the device */ 810 1.1 reinoud dev.dev_name = strdup(*argv); 811 1.1 reinoud printf("Opening device %s\n", dev.dev_name); 812 1.1 reinoud error = uscsi_open(&dev); 813 1.1 reinoud if (error) { 814 1.1 reinoud fprintf(stderr, "Device failed to open : %s\n", 815 1.1 reinoud strerror(error)); 816 1.1 reinoud exit(1); 817 1.1 reinoud } 818 1.1 reinoud 819 1.1 reinoud error = uscsi_check_for_scsi(&dev); 820 1.1 reinoud if (error) { 821 1.1 reinoud fprintf(stderr, "sorry, not a SCSI/ATAPI device : %s\n", 822 1.1 reinoud strerror(error)); 823 1.1 reinoud exit(1); 824 1.1 reinoud } 825 1.1 reinoud 826 1.1 reinoud error = uscsi_identify(&dev, &saddr); 827 1.1 reinoud if (error) { 828 1.1 reinoud fprintf(stderr, "SCSI/ATAPI identify returned : %s\n", 829 1.1 reinoud strerror(error)); 830 1.1 reinoud exit(1); 831 1.1 reinoud } 832 1.1 reinoud 833 1.1 reinoud printf("\nDevice identifies itself as : "); 834 1.1 reinoud 835 1.1 reinoud if (saddr.type == USCSI_TYPE_SCSI) { 836 1.1 reinoud printf("SCSI busnum = %d, target = %d, lun = %d\n", 837 1.1 reinoud saddr.addr.scsi.scbus, saddr.addr.scsi.target, 838 1.1 reinoud saddr.addr.scsi.lun); 839 1.1 reinoud } else { 840 1.1 reinoud printf("ATAPI busnum = %d, drive = %d\n", 841 1.1 reinoud saddr.addr.atapi.atbus, saddr.addr.atapi.drive); 842 1.1 reinoud } 843 1.1 reinoud 844 1.1 reinoud printf("\n"); 845 1.1 reinoud 846 1.1 reinoud /* get MMC profile */ 847 1.1 reinoud error = uscsi_get_mmc_profile(&dev, &mmc_profile); 848 1.1 reinoud if (error) { 849 1.1 reinoud fprintf(stderr, 850 1.1 reinoud "Can't get the disc's MMC profile because of :" 851 1.1 reinoud " %s\n", strerror(error)); 852 1.1 reinoud fprintf(stderr, "aborting\n"); 853 1.1 reinoud uscsi_close(&dev); 854 1.1 reinoud return 1; 855 1.1 reinoud } 856 1.1 reinoud 857 1.1 reinoud /* blank disc section */ 858 1.1 reinoud if (blank) { 859 1.1 reinoud printf("\nBlanking disc.... "); fflush(stdout); 860 1.1 reinoud error = uscsi_blank_disc(&dev); 861 1.1 reinoud 862 1.1 reinoud if (error) { 863 1.1 reinoud printf("fail\n"); fflush(stdout); 864 1.1 reinoud fprintf(stderr, 865 1.1 reinoud "Blanking failed because of : %s\n", 866 1.1 reinoud strerror(error)); 867 1.1 reinoud uscsi_close(&dev); 868 1.1 reinoud 869 1.1 reinoud return 1; 870 1.1 reinoud } else { 871 1.1 reinoud printf("success!\n\n"); 872 1.1 reinoud } 873 1.1 reinoud } 874 1.1 reinoud 875 1.1 reinoud /* re-get MMC profile */ 876 1.1 reinoud error = uscsi_get_mmc_profile(&dev, &mmc_profile); 877 1.1 reinoud if (error) { 878 1.1 reinoud fprintf(stderr, 879 1.1 reinoud "Can't get the disc's MMC profile because of : %s\n", 880 1.1 reinoud strerror(error)); 881 1.1 reinoud fprintf(stderr, "aborting\n"); 882 1.1 reinoud uscsi_close(&dev); 883 1.1 reinoud return 1; 884 1.1 reinoud } 885 1.1 reinoud 886 1.1 reinoud error = get_format_capabilities(&dev, caps, &caps_len); 887 1.1 reinoud if (error) 888 1.1 reinoud exit(1); 889 1.1 reinoud 890 1.1 reinoud process_format_caps(caps, caps_len, inquiry, allow, blks, params); 891 1.1 reinoud 892 1.1 reinoud format_type = 0; 893 1.1 reinoud /* expert format section */ 894 1.1 reinoud if (expert) { 895 1.1 reinoud } 896 1.1 reinoud 897 1.1 reinoud if (!format && !grow_spare && !grow_session) { 898 1.1 reinoud /* we're done */ 899 1.1 reinoud if (display_usage) 900 1.1 reinoud usage(progname); 901 1.1 reinoud uscsi_close(&dev); 902 1.1 reinoud exit(0); 903 1.1 reinoud } 904 1.1 reinoud 905 1.1 reinoud /* normal format section */ 906 1.1 reinoud if (format) { 907 1.1 reinoud /* get current mmc profile of disc */ 908 1.1 reinoud 909 1.1 reinoud if (oldtimer && mmc_profile != 0x0a) { 910 1.1 reinoud printf("Oldtimer flag only defined for CD-RW; " 911 1.1 reinoud "ignored\n"); 912 1.1 reinoud } 913 1.1 reinoud 914 1.1 reinoud switch (mmc_profile) { 915 1.1 reinoud case 0x12 : /* DVD-RAM */ 916 1.1 reinoud format_type = 0x00; 917 1.1 reinoud break; 918 1.1 reinoud case 0x0a : /* CD-RW */ 919 1.1 reinoud format_type = mrw ? 0x24 : 0x10; 920 1.1 reinoud packet_wr = 1; 921 1.1 reinoud break; 922 1.1 reinoud case 0x13 : /* DVD-RW restricted overwrite */ 923 1.1 reinoud case 0x14 : /* DVD-RW sequential */ 924 1.1 reinoud format_type = 0x10; 925 1.1 reinoud /* 926 1.1 reinoud * Some drives suddenly stop supporting this format 927 1.1 reinoud * type when packet_wr = 1 928 1.1 reinoud */ 929 1.1 reinoud packet_wr = 0; 930 1.1 reinoud break; 931 1.1 reinoud case 0x1a : /* DVD+RW */ 932 1.1 reinoud format_type = mrw ? 0x24 : 0x26; 933 1.1 reinoud break; 934 1.1 reinoud case 0x43 : /* BD-RE */ 935 1.1 reinoud format_type = spare ? 0x30 : 0x31; 936 1.1 reinoud break; 937 1.1 reinoud default : 938 1.1 reinoud fprintf(stderr, "Can't format discs of type %s\n", 939 1.1 reinoud print_mmc_profile(mmc_profile)); 940 1.1 reinoud uscsi_close(&dev); 941 1.1 reinoud exit(1); 942 1.1 reinoud } 943 1.1 reinoud } 944 1.1 reinoud 945 1.1 reinoud if (grow_spare) { 946 1.1 reinoud switch (mmc_profile) { 947 1.1 reinoud case 0x12 : /* DVD-RAM */ 948 1.1 reinoud case 0x43 : /* BD-RE */ 949 1.1 reinoud format_type = 0x01; 950 1.1 reinoud break; 951 1.1 reinoud default : 952 1.1 reinoud fprintf(stderr, 953 1.1 reinoud "Can't grow spare area for discs of type %s\n", 954 1.1 reinoud print_mmc_profile(mmc_profile)); 955 1.1 reinoud uscsi_close(&dev); 956 1.1 reinoud exit(1); 957 1.1 reinoud } 958 1.1 reinoud } 959 1.1 reinoud 960 1.1 reinoud if (grow_session) { 961 1.1 reinoud switch (mmc_profile) { 962 1.1 reinoud case 0x0a : /* CD-RW */ 963 1.1 reinoud format_type = 0x11; 964 1.1 reinoud break; 965 1.1 reinoud case 0x13 : /* DVD-RW restricted overwrite */ 966 1.1 reinoud case 0x14 : /* DVD-RW sequential ? */ 967 1.1 reinoud format_type = 0x13; 968 1.1 reinoud break; 969 1.1 reinoud default : 970 1.1 reinoud uscsi_close(&dev); 971 1.1 reinoud fprintf(stderr, 972 1.1 reinoud "Can't grow session for discs of type %s\n", 973 1.1 reinoud print_mmc_profile(mmc_profile)); 974 1.1 reinoud exit(1); 975 1.1 reinoud } 976 1.1 reinoud } 977 1.1 reinoud 978 1.1 reinoud /* check if format type is allowed */ 979 1.1 reinoud format_blks = blks[format_type]; 980 1.1 reinoud format_param = params[format_type]; 981 1.1 reinoud if (!allow[format_type]) { 982 1.1 reinoud if (!inquiry) 983 1.1 reinoud process_format_caps(caps, caps_len, 1, allow, 984 1.1 reinoud blks, params); 985 1.1 reinoud 986 1.1 reinoud printf("\n"); 987 1.1 reinoud fflush(stdout); 988 1.1 reinoud fprintf(stderr, 989 1.1 reinoud "Drive indicates it can't format with deduced format " 990 1.1 reinoud "type 0x%02x\n", format_type); 991 1.1 reinoud uscsi_close(&dev); 992 1.1 reinoud exit(1); 993 1.1 reinoud } 994 1.1 reinoud 995 1.1 reinoud if (restart_format && !((mmc_profile == 0x1a) || (format_type == 0x24))) 996 1.1 reinoud { 997 1.1 reinoud fprintf(stderr, 998 1.1 reinoud "Format restarting only for MRW formats or DVD+RW " 999 1.1 reinoud "formats\n"); 1000 1.1 reinoud uscsi_close(&dev); 1001 1.1 reinoud exit(1); 1002 1.1 reinoud } 1003 1.1 reinoud 1004 1.1 reinoud if (restart_format && !wait_until_finished) { 1005 1.1 reinoud printf( "Warning : format restarting without waiting for it be " 1006 1.1 reinoud "finished is prolly not handy\n"); 1007 1.1 reinoud } 1008 1.1 reinoud 1009 1.1 reinoud /* explicitly select packet write just in case */ 1010 1.1 reinoud if (packet_wr) { 1011 1.1 reinoud printf("Explicitly setting packet type and blocking number\n"); 1012 1.1 reinoud error = uscsi_set_packet_parameters(&dev, blockingnr); 1013 1.1 reinoud if (error) { 1014 1.1 reinoud fprintf(stderr, 1015 1.1 reinoud "Can't set packet writing and blocking number: " 1016 1.1 reinoud "%s\n", strerror(error)); 1017 1.1 reinoud uscsi_close(&dev); 1018 1.1 reinoud exit(1); 1019 1.1 reinoud } 1020 1.1 reinoud } 1021 1.1 reinoud 1022 1.1 reinoud /* determine if formatting is done in the background */ 1023 1.1 reinoud background = 0; 1024 1.1 reinoud if (format_type == 0x24) background = 1; 1025 1.1 reinoud if (format_type == 0x26) background = 1; 1026 1.1 reinoud 1027 1.1 reinoud /* special case format type 0x24 : MRW */ 1028 1.1 reinoud if (format_type == 0x24) { 1029 1.1 reinoud format_blks = spare ? 0xffff0000 : 0xffffffff; 1030 1.1 reinoud format_param = restart_format; 1031 1.1 reinoud } 1032 1.1 reinoud /* special case format type 0x26 : DVD+RW */ 1033 1.1 reinoud if (format_type == 0x26) { 1034 1.1 reinoud format_param = restart_format; 1035 1.1 reinoud } 1036 1.1 reinoud 1037 1.1 reinoud /* verbose to the user */ 1038 1.1 reinoud DEBUG( 1039 1.1 reinoud printf("Actual format selected: " 1040 1.1 reinoud "format_type 0x%02x, blks %d, param %d, " 1041 1.1 reinoud "certification %d, cmplist %d\n", 1042 1.1 reinoud format_type, format_blks, format_param, 1043 1.1 reinoud certification, cmplist); 1044 1.1 reinoud ); 1045 1.1 reinoud printf("\nFormatting.... "); fflush(stdout); 1046 1.1 reinoud 1047 1.1 reinoud /* formatting time! */ 1048 1.1 reinoud if (oldtimer) { 1049 1.1 reinoud error = uscsi_format_cdrw_mode7(&dev, format_blks); 1050 1.1 reinoud background = 0; 1051 1.1 reinoud } else { 1052 1.1 reinoud error = uscsi_format_disc(&dev, !background, format_type, 1053 1.1 reinoud format_blks, format_param, certification, 1054 1.1 reinoud cmplist); 1055 1.1 reinoud } 1056 1.1 reinoud 1057 1.1 reinoud /* what now? */ 1058 1.1 reinoud if (error) { 1059 1.1 reinoud printf("fail\n"); fflush(stdout); 1060 1.1 reinoud fprintf(stderr, "Formatting failed because of : %s\n", 1061 1.1 reinoud strerror(error)); 1062 1.1 reinoud } else { 1063 1.1 reinoud if (background) { 1064 1.1 reinoud printf("background formatting in progress\n"); 1065 1.1 reinoud if (wait_until_finished) { 1066 1.1 reinoud printf("Waiting for completion ... "); 1067 1.1 reinoud uscsi_waitop(&dev); 1068 1.1 reinoud } 1069 1.1 reinoud /* explicitly do NOT close disc ... (for now) */ 1070 1.1 reinoud return 0; 1071 1.1 reinoud } else { 1072 1.1 reinoud printf("success!\n\n"); 1073 1.1 reinoud } 1074 1.1 reinoud } 1075 1.1 reinoud 1076 1.1 reinoud /* finish up */ 1077 1.1 reinoud uscsi_close(&dev); 1078 1.1 reinoud 1079 1.1 reinoud return error; 1080 1.1 reinoud } 1081