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