1 /* $NetBSD: mmcformat.c,v 1.6 2019/12/26 04:53:12 msaitoh 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 trans_len; 264 size_t buf_len = 512; 265 int error; 266 267 assert(*len >= buf_len); 268 bzero(buf, buf_len); 269 270 trans_len = 12; /* only fixed header first */ 271 bzero(cmd, SCSI_CMD_LEN); 272 cmd[0] = 0x23; /* Read format capabilities */ 273 cmd[7] = trans_len >> 8; /* MSB allocation length */ 274 cmd[8] = trans_len & 0xff; /* LSB allocation length */ 275 cmd[9] = 0; /* control */ 276 error = uscsi_command(SCSI_READCMD, mydev, 277 cmd, 10, buf, trans_len, 30000, NULL); 278 if (error) { 279 fprintf(stderr, "While reading format capabilities : %s\n", 280 strerror(error)); 281 return error; 282 } 283 284 list_length = buf[ 3]; 285 286 if (list_length % 8) { 287 printf( "\t\tWarning: violating SCSI spec," 288 "capacity list length ought to be multiple of 8\n"); 289 printf("\t\tInterpreting as including header of 4 bytes\n"); 290 assert(list_length % 8 == 4); 291 list_length -= 4; 292 } 293 294 /* read in full capacity list */ 295 trans_len = 12 + list_length; /* complete structure */ 296 bzero(cmd, SCSI_CMD_LEN); 297 cmd[0] = 0x23; /* Read format capabilities */ 298 cmd[7] = trans_len >> 8; /* MSB allocation length */ 299 cmd[8] = trans_len & 0xff; /* LSB allocation length */ 300 cmd[9] = 0; /* control */ 301 error = uscsi_command(SCSI_READCMD, mydev, 302 cmd, 10, buf, trans_len, 30000, NULL); 303 if (error) { 304 fprintf(stderr, "While reading format capabilities : %s\n", 305 strerror(error)); 306 return error; 307 } 308 309 *len = list_length; 310 return 0; 311 } 312 313 314 static void 315 print_format(int format_tp, uint32_t num_blks, uint32_t param, 316 int dscr_type, int verbose, int *supported) 317 { 318 char const *format_str, *nblks_str, *param_str, *user_spec; 319 320 format_str = nblks_str = param_str = "reserved"; 321 user_spec = ""; 322 *supported = 1; 323 324 switch (format_tp) { 325 case 0x00 : 326 format_str = "full format capacity"; 327 nblks_str = "sectors"; 328 param_str = "block length in bytes"; 329 user_spec = "'-F [-b blockingnr]'"; 330 break; 331 case 0x01 : 332 format_str = "spare area expansion"; 333 nblks_str = "extension in blocks"; 334 param_str = "block length in bytes"; 335 user_spec = "'-S'"; 336 break; 337 /* 0x02 - 0x03 reserved */ 338 case 0x04 : 339 format_str = "variable length zone'd format"; 340 nblks_str = "zone length"; 341 param_str = "zone number"; 342 *supported = 0; 343 break; 344 case 0x05 : 345 format_str = "fixed length zone'd format"; 346 nblks_str = "zone length"; 347 param_str = "last zone number"; 348 *supported = 0; 349 break; 350 /* 0x06 - 0x0f reserved */ 351 case 0x10 : 352 format_str = "CD-RW/DVD-RW full packet format"; 353 nblks_str = "adressable blocks"; 354 param_str = "fixed packet size/ECC blocksize in sectors"; 355 user_spec = "'-F -p [-b blockingnr]'"; 356 break; 357 case 0x11 : 358 format_str = "CD-RW/DVD-RW grow session"; 359 nblks_str = "adressable blocks"; 360 param_str = "fixed packet size/ECC blocksize in sectors"; 361 user_spec = "'-G'"; 362 break; 363 case 0x12 : 364 format_str = "CD-RW/DVD-RW add session"; 365 nblks_str = "adressable blocks"; 366 param_str = "maximum fixed packet size/ECC blocksize " 367 "in sectors"; 368 *supported = 0; 369 break; 370 case 0x13 : 371 format_str = "DVD-RW max growth of last complete session"; 372 nblks_str = "adressable blocks"; 373 param_str = "ECC blocksize in sectors"; 374 user_spec = "'-G'"; 375 break; 376 case 0x14 : 377 format_str = "DVD-RW quick grow last session"; 378 nblks_str = "adressable blocks"; 379 param_str = "ECC blocksize in sectors"; 380 *supported = 0; 381 break; 382 case 0x15 : 383 format_str = "DVD-RW quick full format"; 384 nblks_str = "adressable blocks"; 385 param_str = "ECC blocksize in sectors"; 386 *supported = 0; 387 break; 388 /* 0x16 - 0x23 reserved */ 389 case 0x24 : 390 format_str = "background MRW format"; 391 nblks_str = "Defect Management Area blocks"; 392 param_str = "not used"; 393 user_spec = "'[-R] [-s] [-w] -F -M [-b blockingnr]'"; 394 break; 395 /* 0x25 reserved */ 396 case 0x26 : 397 format_str = "background DVD+RW full format"; 398 nblks_str = "sectors"; 399 param_str = "not used"; 400 user_spec = "'[-R] [-w] -F'"; 401 break; 402 /* 0x27 - 0x2f reserved */ 403 case 0x30 : 404 format_str = "BD-RE full format with spare area"; 405 nblks_str = "blocks"; 406 param_str = "total spare area size in clusters"; 407 user_spec = "'[-s] -F'"; 408 break; 409 case 0x31 : 410 format_str = "BD-RE full format without spare area"; 411 nblks_str = "blocks"; 412 param_str = "block length in bytes"; 413 user_spec = "'-F'"; 414 break; 415 /* 0x32 - 0x3f reserved */ 416 default : 417 break; 418 } 419 420 if (verbose) { 421 printf("\n\tFormat type 0x%02x : %s\n", format_tp, format_str); 422 423 switch (dscr_type) { 424 case 1 : 425 printf( "\t\tUnformatted media," 426 "maximum formatted capacity\n"); 427 break; 428 case 2 : 429 printf( "\t\tFormatted media," 430 "current formatted capacity\n"); 431 break; 432 case 3 : 433 printf( "\t\tNo media present or incomplete session, " 434 "maximum formatted capacity\n"); 435 break; 436 default : 437 printf("\t\tUnspecified descriptor type\n"); 438 break; 439 } 440 441 printf("\t\tNumber of blocks : %12d\t(%s)\n", 442 num_blks, nblks_str); 443 printf("\t\tParameter : %12d\t(%s)\n", 444 param, param_str); 445 446 if (format_tp == 0x24) { 447 printf( "\t\tExpert select : " 448 "'-X 0x%02x:0xffffff:0' or " 449 "'-X 0x%02x:0xffff0000:0'\n", 450 format_tp, format_tp); 451 } else { 452 printf( "\t\tExpert select : " 453 "'-X 0x%02x:%d:%d'\n", 454 format_tp, num_blks, param); 455 } 456 if (*supported) { 457 printf("\t\tmmc_format arg : %s\n", user_spec); 458 } else { 459 printf("\t\t** not supported **\n"); 460 } 461 } 462 } 463 464 465 static void 466 process_format_caps(uint8_t *buf, int list_length, int verbose, 467 uint8_t *allow, uint32_t *blks, uint32_t *params) 468 { 469 uint32_t num_blks, param; 470 uint8_t *fcd; 471 int dscr_type, format_tp; 472 int supported; 473 474 bzero(allow, 255); 475 bzero(blks, 255*4); 476 bzero(params, 255*4); 477 478 fcd = buf + 4; 479 list_length -= 4; /* strip header */ 480 481 if (verbose) 482 printf("\tCurrent/max capacity followed by additional capacity," 483 "reported length of %d bytes (8/entry)\n", list_length); 484 485 while (list_length > 0) { 486 num_blks = fcd[ 3] | (fcd[ 2] << 8) | 487 (fcd[ 1] << 16) | (fcd[ 0] << 24); 488 dscr_type = fcd[ 4] & 3; 489 format_tp = fcd[ 4] >> 2; 490 param = fcd[ 7] | (fcd[ 6] << 8) | (fcd[ 5] << 16); 491 492 print_format(format_tp, num_blks, param, dscr_type, verbose, 493 &supported); 494 495 allow[format_tp] = 1; /* TODO = supported? */ 496 blks[format_tp] = num_blks; 497 params[format_tp] = param; 498 499 fcd += 8; 500 list_length-=8; 501 } 502 } 503 504 505 506 /* format a CD-RW disc */ 507 /* old style format 7 */ 508 static int 509 uscsi_format_cdrw_mode7(struct uscsi_dev *mydev, uint32_t blocks) 510 { 511 scsicmd cmd; 512 struct uscsi_sense sense; 513 uint8_t buffer[16]; 514 int error; 515 516 if (blocks % 32) { 517 blocks -= blocks % 32; 518 } 519 520 bzero(cmd, SCSI_CMD_LEN); 521 bzero(buffer, sizeof(buffer)); 522 523 cmd[0] = 0x04; /* format unit */ 524 cmd[1] = 0x17; /* parameter list format 7 follows */ 525 cmd[5] = 0; /* control */ 526 527 /* format list header */ 528 buffer[ 0] = 0; /* reserved */ 529 buffer[ 1] = 0x80 | 0x02; /* Valid info, immediate return */ 530 buffer[ 2] = 0; /* MSB format descriptor length */ 531 buffer[ 3] = 8; /* LSB ... */ 532 533 /* 534 * for CD-RW the initialisation pattern bit is reserved, but there IS 535 * one 536 */ 537 538 buffer[ 4] = 0; /* no header */ 539 buffer[ 5] = 0; /* default pattern */ 540 buffer[ 6] = 0; /* pattern length MSB */ 541 buffer[ 7] = 0; /* pattern length LSB */ 542 543 /* 8 bytes of format descriptor */ 544 /* (s)ession bit 1<<7, (g)row bit 1<<6 */ 545 /* SG action */ 546 /* 00 format disc with number of user data blocks */ 547 /* 10 create new session with number of data blocks */ 548 /* x1 grow session to be number of data blocks */ 549 550 buffer[ 8] = 0x00; /* session and grow bits (7 and 6) */ 551 buffer[ 9] = 0; /* reserved */ 552 buffer[10] = 0; /* reserved */ 553 buffer[11] = 0; /* reserved */ 554 buffer[12] = (blocks >> 24) & 0xff; /* blocks MSB */ 555 buffer[13] = (blocks >> 16) & 0xff; 556 buffer[14] = (blocks >> 8) & 0xff; 557 buffer[15] = (blocks ) & 0xff; /* blocks LSB */ 558 559 /* this will take a while .... */ 560 error = uscsi_command(SCSI_WRITECMD, mydev, 561 cmd, 6, buffer, sizeof(buffer), UINT_MAX, &sense); 562 if (error) 563 return error; 564 565 uscsi_waitop(mydev); 566 return 0; 567 } 568 569 570 static int 571 uscsi_format_disc(struct uscsi_dev *mydev, int immed, int format_type, 572 uint32_t blocks, uint32_t param, int certification, int cmplist) 573 { 574 scsicmd cmd; 575 struct uscsi_sense sense; 576 uint8_t buffer[16], fmt_flags; 577 int error; 578 579 fmt_flags = 0x80; /* valid info flag */ 580 if (immed) 581 fmt_flags |= 2; 582 if (certification == 0) 583 fmt_flags |= 32; 584 585 if (cmplist) 586 cmplist = 8; 587 588 #if 0 589 if (mmc_profile != 0x43) { 590 /* certification specifier only valid for BD-RE */ 591 certification = 0; 592 } 593 #endif 594 595 bzero(cmd, SCSI_CMD_LEN); 596 bzero(buffer, sizeof(buffer)); 597 598 cmd[0] = 0x04; /* format unit */ 599 cmd[1] = 0x11 | cmplist; /* parameter list format 1 follows */ 600 cmd[5] = 0; /* control */ 601 602 /* format list header */ 603 buffer[ 0] = 0; /* reserved */ 604 buffer[ 1] = 0x80 | fmt_flags; /* Valid info, flags follow */ 605 buffer[ 2] = 0; /* MSB format descriptor length */ 606 buffer[ 3] = 8; /* LSB ... */ 607 608 /* 8 bytes of format descriptor */ 609 buffer[ 4] = (blocks >> 24) & 0xff; /* blocks MSB */ 610 buffer[ 5] = (blocks >> 16) & 0xff; 611 buffer[ 6] = (blocks >> 8) & 0xff; 612 buffer[ 7] = (blocks ) & 0xff; /* blocks LSB */ 613 buffer[ 8] = (format_type << 2) | certification; 614 buffer[ 9] = (param >> 16) & 0xff; /* parameter MSB */ 615 buffer[10] = (param >> 8) & 0xff; /* packet size */ 616 buffer[11] = (param ) & 0xff; /* parameter LSB */ 617 618 /* this will take a while .... */ 619 error = uscsi_command(SCSI_WRITECMD, mydev, 620 cmd, 6, buffer, 12, UINT_MAX, &sense); 621 if (error) 622 return error; 623 624 if (immed) 625 uscsi_waitop(mydev); 626 627 return 0; 628 } 629 630 631 static int 632 uscsi_blank_disc(struct uscsi_dev *mydev) 633 { 634 scsicmd cmd; 635 int error; 636 637 /* XXX check if the device can blank! */ 638 639 640 /* blank disc */ 641 bzero(cmd, SCSI_CMD_LEN); 642 cmd[ 0] = 0xA1; /* blank */ 643 cmd[ 1] = 16; /* Immediate, blank complete */ 644 cmd[11] = 0; /* control */ 645 646 /* this will take a while .... */ 647 error = uscsi_command(SCSI_WRITECMD, mydev, 648 cmd, 12, NULL, 0, UINT_MAX, NULL); 649 if (error) 650 return error; 651 652 uscsi_waitop(mydev); 653 return 0; 654 } 655 656 657 static int 658 usage(char *program) 659 { 660 fprintf(stderr, "\n"); 661 fprintf(stderr, "Usage: %s [options] devicename\n", program); 662 fprintf(stderr, 663 "-B blank cd-rw disc before formatting\n" 664 "-F format cd-rw disc\n" 665 "-O CD-RW formatting 'old-style' for old CD-RW drives\n" 666 "-M select MRW format\n" 667 "-R restart MRW & DVD+RW format\n" 668 "-G grow last CD-RW/DVD-RW session\n" 669 "-S grow spare space DVD-RAM/BD-RE\n" 670 "-s format DVD+MRW/BD-RE with extra spare space\n" 671 "-w wait until completion of background format\n" 672 "-p explicitly set packet format\n" 673 "-c num media certification for DVD-RAM/BD-RE : " 674 "0 no, 1 full, 2 quick\n" 675 "-r recompile defect list for DVD-RAM (cmplist)\n" 676 "-h -H -I help/inquiry formats\n" 677 "-X format expert format selector form 'fmt:blks:param' with -c\n" 678 "-b blockingnr in sectors (for CD-RW)\n" 679 "-D verbose SCSI command errors\n" 680 ); 681 return 1; 682 } 683 684 685 extern char *optarg; 686 extern int optind; 687 extern int optreset; 688 689 690 int 691 main(int argc, char *argv[]) 692 { 693 struct uscsi_addr saddr; 694 uint32_t blks[256], params[256]; 695 uint32_t format_type, format_blks, format_param, blockingnr; 696 uint8_t allow[256]; 697 uint8_t caps[512]; 698 uint32_t caps_len = sizeof(caps); 699 char *progname; 700 int blank, format, mrw, background; 701 int inquiry, spare, oldtimer; 702 int expert; 703 int restart_format, grow_session, grow_spare, packet_wr; 704 int mmc_profile, flag, error, display_usage; 705 int certification, cmplist; 706 int wait_until_finished; 707 progname = strdup(argv[0]); 708 if (argc == 1) { 709 return usage(progname); 710 } 711 712 blank = 0; 713 format = 0; 714 mrw = 0; 715 restart_format = 0; 716 grow_session = 0; 717 grow_spare = 0; 718 wait_until_finished = 0; 719 packet_wr = 0; 720 certification = 1; 721 cmplist = 0; 722 inquiry = 0; 723 spare = 0; 724 inquiry = 0; 725 oldtimer = 0; 726 expert = 0; 727 display_usage = 0; 728 blockingnr = 32; 729 uscsilib_verbose = 0; 730 while ((flag = getopt(argc, argv, "BFMRGSwpsc:rhHIX:Ob:D")) != -1) { 731 switch (flag) { 732 case 'B' : 733 blank = 1; 734 break; 735 case 'F' : 736 format = 1; 737 break; 738 case 'M' : 739 mrw = 1; 740 break; 741 case 'R' : 742 restart_format = 1; 743 break; 744 case 'G' : 745 grow_session = 1; 746 break; 747 case 'S' : 748 grow_spare = 1; 749 break; 750 case 'w' : 751 wait_until_finished = 1; 752 break; 753 case 'p' : 754 packet_wr = 1; 755 break; 756 case 's' : 757 spare = 1; 758 break; 759 case 'c' : 760 certification = atoi(optarg); 761 break; 762 case 'r' : 763 cmplist = 1; 764 break; 765 case 'h' : 766 case 'H' : 767 display_usage = 1; 768 break; 769 case 'I' : 770 inquiry = 1; 771 break; 772 case 'X' : 773 /* TODO parse expert mode string */ 774 printf("-X not implemented yet\n"); 775 expert = 1; 776 exit(1); 777 break; 778 case 'O' : 779 /* oldtimer CD-RW format */ 780 oldtimer = 1; 781 format = 1; 782 break; 783 case 'b' : 784 blockingnr = atoi(optarg); 785 break; 786 case 'D' : 787 uscsilib_verbose = 1; 788 break; 789 default : 790 return usage(progname); 791 } 792 } 793 argv += optind; 794 argc -= optind; 795 796 if (!blank && !format && !grow_session && !grow_spare && 797 !expert && !inquiry && !display_usage) { 798 fprintf(stderr, "%s : at least one of -B, -F, -G, -h, -H -S, " 799 "-X or -I needs to be specified\n\n", progname); 800 return usage(progname); 801 } 802 803 if (format + grow_session + grow_spare + expert > 1) { 804 fprintf(stderr, "%s : at most one of -F, -G, -S or -X " 805 "needs to be specified\n\n", progname); 806 return usage(progname); 807 } 808 809 if (argc != 1) return usage(progname); 810 811 /* Open the device */ 812 dev.dev_name = strdup(*argv); 813 printf("Opening device %s\n", dev.dev_name); 814 error = uscsi_open(&dev); 815 if (error) { 816 fprintf(stderr, "Device failed to open : %s\n", 817 strerror(error)); 818 exit(1); 819 } 820 821 error = uscsi_check_for_scsi(&dev); 822 if (error) { 823 fprintf(stderr, "sorry, not a SCSI/ATAPI device : %s\n", 824 strerror(error)); 825 exit(1); 826 } 827 828 error = uscsi_identify(&dev, &saddr); 829 if (error) { 830 fprintf(stderr, "SCSI/ATAPI identify returned : %s\n", 831 strerror(error)); 832 exit(1); 833 } 834 835 printf("\nDevice identifies itself as : "); 836 837 if (saddr.type == USCSI_TYPE_SCSI) { 838 printf("SCSI busnum = %d, target = %d, lun = %d\n", 839 saddr.addr.scsi.scbus, saddr.addr.scsi.target, 840 saddr.addr.scsi.lun); 841 } else { 842 printf("ATAPI busnum = %d, drive = %d\n", 843 saddr.addr.atapi.atbus, saddr.addr.atapi.drive); 844 } 845 846 printf("\n"); 847 848 /* get MMC profile */ 849 error = uscsi_get_mmc_profile(&dev, &mmc_profile); 850 if (error) { 851 fprintf(stderr, 852 "Can't get the disc's MMC profile because of :" 853 " %s\n", strerror(error)); 854 fprintf(stderr, "aborting\n"); 855 uscsi_close(&dev); 856 return 1; 857 } 858 859 /* blank disc section */ 860 if (blank) { 861 printf("\nBlanking disc.... "); fflush(stdout); 862 error = uscsi_blank_disc(&dev); 863 864 if (error) { 865 printf("fail\n"); fflush(stdout); 866 fprintf(stderr, 867 "Blanking failed because of : %s\n", 868 strerror(error)); 869 uscsi_close(&dev); 870 871 return 1; 872 } else { 873 printf("success!\n\n"); 874 } 875 } 876 877 /* re-get MMC profile */ 878 error = uscsi_get_mmc_profile(&dev, &mmc_profile); 879 if (error) { 880 fprintf(stderr, 881 "Can't get the disc's MMC profile because of : %s\n", 882 strerror(error)); 883 fprintf(stderr, "aborting\n"); 884 uscsi_close(&dev); 885 return 1; 886 } 887 888 error = get_format_capabilities(&dev, caps, &caps_len); 889 if (error) 890 exit(1); 891 892 process_format_caps(caps, caps_len, inquiry, allow, blks, params); 893 894 format_type = 0; 895 /* expert format section */ 896 if (expert) { 897 } 898 899 if (!format && !grow_spare && !grow_session) { 900 /* we're done */ 901 if (display_usage) 902 usage(progname); 903 uscsi_close(&dev); 904 exit(0); 905 } 906 907 /* normal format section */ 908 if (format) { 909 /* get current mmc profile of disc */ 910 911 if (oldtimer && mmc_profile != 0x0a) { 912 printf("Oldtimer flag only defined for CD-RW; " 913 "ignored\n"); 914 } 915 916 switch (mmc_profile) { 917 case 0x12 : /* DVD-RAM */ 918 format_type = 0x00; 919 break; 920 case 0x0a : /* CD-RW */ 921 format_type = mrw ? 0x24 : 0x10; 922 packet_wr = 1; 923 break; 924 case 0x13 : /* DVD-RW restricted overwrite */ 925 case 0x14 : /* DVD-RW sequential */ 926 format_type = 0x10; 927 /* 928 * Some drives suddenly stop supporting this format 929 * type when packet_wr = 1 930 */ 931 packet_wr = 0; 932 break; 933 case 0x1a : /* DVD+RW */ 934 format_type = mrw ? 0x24 : 0x26; 935 break; 936 case 0x43 : /* BD-RE */ 937 format_type = spare ? 0x30 : 0x31; 938 break; 939 default : 940 fprintf(stderr, "Can't format discs of type %s\n", 941 print_mmc_profile(mmc_profile)); 942 uscsi_close(&dev); 943 exit(1); 944 } 945 } 946 947 if (grow_spare) { 948 switch (mmc_profile) { 949 case 0x12 : /* DVD-RAM */ 950 case 0x43 : /* BD-RE */ 951 format_type = 0x01; 952 break; 953 default : 954 fprintf(stderr, 955 "Can't grow spare area for discs of type %s\n", 956 print_mmc_profile(mmc_profile)); 957 uscsi_close(&dev); 958 exit(1); 959 } 960 } 961 962 if (grow_session) { 963 switch (mmc_profile) { 964 case 0x0a : /* CD-RW */ 965 format_type = 0x11; 966 break; 967 case 0x13 : /* DVD-RW restricted overwrite */ 968 case 0x14 : /* DVD-RW sequential ? */ 969 format_type = 0x13; 970 break; 971 default : 972 uscsi_close(&dev); 973 fprintf(stderr, 974 "Can't grow session for discs of type %s\n", 975 print_mmc_profile(mmc_profile)); 976 exit(1); 977 } 978 } 979 980 /* check if format type is allowed */ 981 format_blks = blks[format_type]; 982 format_param = params[format_type]; 983 if (!allow[format_type]) { 984 if (!inquiry) 985 process_format_caps(caps, caps_len, 1, allow, 986 blks, params); 987 988 printf("\n"); 989 fflush(stdout); 990 fprintf(stderr, 991 "Drive indicates it can't format with deduced format " 992 "type 0x%02x\n", format_type); 993 uscsi_close(&dev); 994 exit(1); 995 } 996 997 if (restart_format && !((mmc_profile == 0x1a) || (format_type == 0x24))) 998 { 999 fprintf(stderr, 1000 "Format restarting only for MRW formats or DVD+RW " 1001 "formats\n"); 1002 uscsi_close(&dev); 1003 exit(1); 1004 } 1005 1006 if (restart_format && !wait_until_finished) { 1007 printf( "Warning : format restarting without waiting for it be " 1008 "finished is prolly not handy\n"); 1009 } 1010 1011 /* explicitly select packet write just in case */ 1012 if (packet_wr) { 1013 printf("Explicitly setting packet type and blocking number\n"); 1014 error = uscsi_set_packet_parameters(&dev, blockingnr); 1015 if (error) { 1016 fprintf(stderr, 1017 "Can't set packet writing and blocking number: " 1018 "%s\n", strerror(error)); 1019 uscsi_close(&dev); 1020 exit(1); 1021 } 1022 } 1023 1024 /* determine if formatting is done in the background */ 1025 background = 0; 1026 if (format_type == 0x24) background = 1; 1027 if (format_type == 0x26) background = 1; 1028 1029 /* special case format type 0x24 : MRW */ 1030 if (format_type == 0x24) { 1031 format_blks = spare ? 0xffff0000 : 0xffffffff; 1032 format_param = restart_format; 1033 } 1034 /* special case format type 0x26 : DVD+RW */ 1035 if (format_type == 0x26) { 1036 format_param = restart_format; 1037 } 1038 1039 /* verbose to the user */ 1040 DEBUG( 1041 printf("Actual format selected: " 1042 "format_type 0x%02x, blks %d, param %d, " 1043 "certification %d, cmplist %d\n", 1044 format_type, format_blks, format_param, 1045 certification, cmplist); 1046 ); 1047 printf("\nFormatting.... "); fflush(stdout); 1048 1049 /* formatting time! */ 1050 if (oldtimer) { 1051 error = uscsi_format_cdrw_mode7(&dev, format_blks); 1052 background = 0; 1053 } else { 1054 error = uscsi_format_disc(&dev, !background, format_type, 1055 format_blks, format_param, certification, 1056 cmplist); 1057 } 1058 1059 /* what now? */ 1060 if (error) { 1061 printf("fail\n"); fflush(stdout); 1062 fprintf(stderr, "Formatting failed because of : %s\n", 1063 strerror(error)); 1064 } else { 1065 if (background) { 1066 printf("background formatting in progress\n"); 1067 if (wait_until_finished) { 1068 printf("Waiting for completion ... "); 1069 uscsi_waitop(&dev); 1070 } 1071 /* explicitly do NOT close disc ... (for now) */ 1072 return 0; 1073 } else { 1074 printf("success!\n\n"); 1075 } 1076 } 1077 1078 /* finish up */ 1079 uscsi_close(&dev); 1080 1081 return error; 1082 } 1083 1084