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 */ 46struct uscsi_dev dev; 47extern int scsilib_verbose; 48 49/* #define DEBUG(a) {a;} */ 50#define DEBUG(a) ; 51 52 53static uint64_t 54getmtime(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 63static void 64print_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 84static void 85uscsi_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 151static char const * 152print_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 187static int 188uscsi_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 209static int 210uscsi_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 258static int 259get_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 314static void 315print_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 lenght"; 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 465static void 466process_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 */ 508static int 509uscsi_format_cdrw_mode7(struct uscsi_dev *mydev, uint32_t blocks) 510{ 511 scsicmd cmd; 512 struct uscsi_sense sense; 513 uint32_t param; 514 uint8_t buffer[16]; 515 int cnt, error; 516 517 param = cnt = 0; 518 519 if (blocks % 32) { 520 blocks -= blocks % 32; 521 } 522 523 bzero(cmd, SCSI_CMD_LEN); 524 bzero(buffer, sizeof(buffer)); 525 526 cmd[0] = 0x04; /* format unit */ 527 cmd[1] = 0x17; /* parameter list format 7 follows */ 528 cmd[5] = 0; /* control */ 529 530 /* format list header */ 531 buffer[ 0] = 0; /* reserved */ 532 buffer[ 1] = 0x80 | 0x02; /* Valid info, immediate return */ 533 buffer[ 2] = 0; /* MSB format descriptor length */ 534 buffer[ 3] = 8; /* LSB ... */ 535 536 /* 537 * for CD-RW the initialisation pattern bit is reserved, but there IS 538 * one 539 */ 540 541 buffer[ 4] = 0; /* no header */ 542 buffer[ 5] = 0; /* default pattern */ 543 buffer[ 6] = 0; /* pattern length MSB */ 544 buffer[ 7] = 0; /* pattern length LSB */ 545 546 /* 8 bytes of format descriptor */ 547 /* (s)ession bit 1<<7, (g)row bit 1<<6 */ 548 /* SG action */ 549 /* 00 format disc with number of user data blocks */ 550 /* 10 create new session with number of data blocks */ 551 /* x1 grow session to be number of data blocks */ 552 553 buffer[ 8] = 0x00; /* session and grow bits (7 and 6) */ 554 buffer[ 9] = 0; /* reserved */ 555 buffer[10] = 0; /* reserved */ 556 buffer[11] = 0; /* reserved */ 557 buffer[12] = (blocks >> 24) & 0xff; /* blocks MSB */ 558 buffer[13] = (blocks >> 16) & 0xff; 559 buffer[14] = (blocks >> 8) & 0xff; 560 buffer[15] = (blocks ) & 0xff; /* blocks LSB */ 561 562 /* this will take a while .... */ 563 error = uscsi_command(SCSI_WRITECMD, mydev, 564 cmd, 6, buffer, sizeof(buffer), UINT_MAX, &sense); 565 if (error) 566 return error; 567 568 uscsi_waitop(mydev); 569 return 0; 570} 571 572 573static int 574uscsi_format_disc(struct uscsi_dev *mydev, int immed, int format_type, 575 uint32_t blocks, uint32_t param, int certification, int cmplist) 576{ 577 scsicmd cmd; 578 struct uscsi_sense sense; 579 uint8_t buffer[16], fmt_flags; 580 int error; 581 582 fmt_flags = 0x80; /* valid info flag */ 583 if (immed) 584 fmt_flags |= 2; 585 if (certification == 0) 586 fmt_flags |= 32; 587 588 if (cmplist) 589 cmplist = 8; 590 591#if 0 592 if (mmc_profile != 0x43) { 593 /* certification specifier only valid for BD-RE */ 594 certification = 0; 595 } 596#endif 597 598 bzero(cmd, SCSI_CMD_LEN); 599 bzero(buffer, sizeof(buffer)); 600 601 cmd[0] = 0x04; /* format unit */ 602 cmd[1] = 0x11 | cmplist; /* parameter list format 1 follows */ 603 cmd[5] = 0; /* control */ 604 605 /* format list header */ 606 buffer[ 0] = 0; /* reserved */ 607 buffer[ 1] = 0x80 | fmt_flags; /* Valid info, flags follow */ 608 buffer[ 2] = 0; /* MSB format descriptor length */ 609 buffer[ 3] = 8; /* LSB ... */ 610 611 /* 8 bytes of format descriptor */ 612 buffer[ 4] = (blocks >> 24) & 0xff; /* blocks MSB */ 613 buffer[ 5] = (blocks >> 16) & 0xff; 614 buffer[ 6] = (blocks >> 8) & 0xff; 615 buffer[ 7] = (blocks ) & 0xff; /* blocks LSB */ 616 buffer[ 8] = (format_type << 2) | certification; 617 buffer[ 9] = (param >> 16) & 0xff; /* parameter MSB */ 618 buffer[10] = (param >> 8) & 0xff; /* packet size */ 619 buffer[11] = (param ) & 0xff; /* parameter LSB */ 620 621 /* this will take a while .... */ 622 error = uscsi_command(SCSI_WRITECMD, mydev, 623 cmd, 6, buffer, 12, UINT_MAX, &sense); 624 if (error) 625 return error; 626 627 if (immed) 628 uscsi_waitop(mydev); 629 630 return 0; 631} 632 633 634static int 635uscsi_blank_disc(struct uscsi_dev *mydev) 636{ 637 scsicmd cmd; 638 int error; 639 640 /* XXX check if the device can blank! */ 641 642 643 /* blank disc */ 644 bzero(cmd, SCSI_CMD_LEN); 645 cmd[ 0] = 0xA1; /* blank */ 646 cmd[ 1] = 16; /* Immediate, blank complete */ 647 cmd[11] = 0; /* control */ 648 649 /* this will take a while .... */ 650 error = uscsi_command(SCSI_WRITECMD, mydev, 651 cmd, 12, NULL, 0, UINT_MAX, NULL); 652 if (error) 653 return error; 654 655 uscsi_waitop(mydev); 656 return 0; 657} 658 659 660static int 661usage(char *program) 662{ 663 fprintf(stderr, "\n"); 664 fprintf(stderr, "Usage: %s [options] devicename\n", program); 665 fprintf(stderr, 666 "-B blank cd-rw disc before formatting\n" 667 "-F format cd-rw disc\n" 668 "-O CD-RW formatting 'old-style' for old CD-RW drives\n" 669 "-M select MRW format\n" 670 "-R restart MRW & DVD+RW format\n" 671 "-G grow last CD-RW/DVD-RW session\n" 672 "-S grow spare space DVD-RAM/BD-RE\n" 673 "-s format DVD+MRW/BD-RE with extra spare space\n" 674 "-w wait until completion of background format\n" 675 "-p explicitly set packet format\n" 676 "-c num media certification for DVD-RAM/BD-RE : " 677 "0 no, 1 full, 2 quick\n" 678 "-r recompile defect list for DVD-RAM (cmplist)\n" 679 "-h -H -I help/inquiry formats\n" 680 "-X format expert format selector form 'fmt:blks:param' with -c\n" 681 "-b blockingnr in sectors (for CD-RW)\n" 682 "-D verbose SCSI command errors\n" 683 ); 684 return 1; 685} 686 687 688extern char *optarg; 689extern int optind; 690extern int optreset; 691 692 693int 694main(int argc, char *argv[]) 695{ 696 struct uscsi_addr saddr; 697 uint32_t blks[256], params[256]; 698 uint32_t format_type, format_blks, format_param, blockingnr; 699 uint8_t allow[256]; 700 uint8_t caps[512]; 701 uint32_t caps_len = sizeof(caps); 702 char *progname; 703 int blank, format, mrw, background; 704 int inquiry, spare, oldtimer; 705 int expert; 706 int restart_format, grow_session, grow_spare, packet_wr; 707 int mmc_profile, flag, error, display_usage; 708 int certification, cmplist; 709 int wait_until_finished; 710 progname = strdup(argv[0]); 711 if (argc == 1) { 712 return usage(progname); 713 } 714 715 blank = 0; 716 format = 0; 717 mrw = 0; 718 restart_format = 0; 719 grow_session = 0; 720 grow_spare = 0; 721 wait_until_finished = 0; 722 packet_wr = 0; 723 certification = 1; 724 cmplist = 0; 725 inquiry = 0; 726 spare = 0; 727 inquiry = 0; 728 oldtimer = 0; 729 expert = 0; 730 display_usage = 0; 731 blockingnr = 32; 732 uscsilib_verbose = 0; 733 while ((flag = getopt(argc, argv, "BFMRGSwpsc:rhHIX:Ob:D")) != -1) { 734 switch (flag) { 735 case 'B' : 736 blank = 1; 737 break; 738 case 'F' : 739 format = 1; 740 break; 741 case 'M' : 742 mrw = 1; 743 break; 744 case 'R' : 745 restart_format = 1; 746 break; 747 case 'G' : 748 grow_session = 1; 749 break; 750 case 'S' : 751 grow_spare = 1; 752 break; 753 case 'w' : 754 wait_until_finished = 1; 755 break; 756 case 'p' : 757 packet_wr = 1; 758 break; 759 case 's' : 760 spare = 1; 761 break; 762 case 'c' : 763 certification = atoi(optarg); 764 break; 765 case 'r' : 766 cmplist = 1; 767 break; 768 case 'h' : 769 case 'H' : 770 display_usage = 1; 771 case 'I' : 772 inquiry = 1; 773 break; 774 case 'X' : 775 /* TODO parse expert mode string */ 776 printf("-X not implemented yet\n"); 777 expert = 1; 778 exit(1); 779 break; 780 case 'O' : 781 /* oldtimer CD-RW format */ 782 oldtimer = 1; 783 format = 1; 784 break; 785 case 'b' : 786 blockingnr = atoi(optarg); 787 break; 788 case 'D' : 789 uscsilib_verbose = 1; 790 break; 791 default : 792 return usage(progname); 793 } 794 } 795 argv += optind; 796 argc -= optind; 797 798 if ((!blank && !format && !grow_session && !grow_spare) && 799 (!expert && !inquiry)) { 800 fprintf(stderr, "%s : at least one of -B, -F, -G, -S, -X or -I " 801 "needs to be specified\n\n", progname); 802 return usage(progname); 803 } 804 805 if (format + grow_session + grow_spare + expert > 1) { 806 fprintf(stderr, "%s : at most one of -F, -G, -S or -X " 807 "needs to be specified\n\n", progname); 808 return usage(progname); 809 } 810 811 if (argc != 1) return usage(progname); 812 813 /* Open the device */ 814 dev.dev_name = strdup(*argv); 815 printf("Opening device %s\n", dev.dev_name); 816 error = uscsi_open(&dev); 817 if (error) { 818 fprintf(stderr, "Device failed to open : %s\n", 819 strerror(error)); 820 exit(1); 821 } 822 823 error = uscsi_check_for_scsi(&dev); 824 if (error) { 825 fprintf(stderr, "sorry, not a SCSI/ATAPI device : %s\n", 826 strerror(error)); 827 exit(1); 828 } 829 830 error = uscsi_identify(&dev, &saddr); 831 if (error) { 832 fprintf(stderr, "SCSI/ATAPI identify returned : %s\n", 833 strerror(error)); 834 exit(1); 835 } 836 837 printf("\nDevice identifies itself as : "); 838 839 if (saddr.type == USCSI_TYPE_SCSI) { 840 printf("SCSI busnum = %d, target = %d, lun = %d\n", 841 saddr.addr.scsi.scbus, saddr.addr.scsi.target, 842 saddr.addr.scsi.lun); 843 } else { 844 printf("ATAPI busnum = %d, drive = %d\n", 845 saddr.addr.atapi.atbus, saddr.addr.atapi.drive); 846 } 847 848 printf("\n"); 849 850 /* get MMC profile */ 851 error = uscsi_get_mmc_profile(&dev, &mmc_profile); 852 if (error) { 853 fprintf(stderr, 854 "Can't get the disc's MMC profile because of :" 855 " %s\n", strerror(error)); 856 fprintf(stderr, "aborting\n"); 857 uscsi_close(&dev); 858 return 1; 859 } 860 861 /* blank disc section */ 862 if (blank) { 863 printf("\nBlanking disc.... "); fflush(stdout); 864 error = uscsi_blank_disc(&dev); 865 866 if (error) { 867 printf("fail\n"); fflush(stdout); 868 fprintf(stderr, 869 "Blanking failed because of : %s\n", 870 strerror(error)); 871 uscsi_close(&dev); 872 873 return 1; 874 } else { 875 printf("success!\n\n"); 876 } 877 } 878 879 /* re-get MMC profile */ 880 error = uscsi_get_mmc_profile(&dev, &mmc_profile); 881 if (error) { 882 fprintf(stderr, 883 "Can't get the disc's MMC profile because of : %s\n", 884 strerror(error)); 885 fprintf(stderr, "aborting\n"); 886 uscsi_close(&dev); 887 return 1; 888 } 889 890 error = get_format_capabilities(&dev, caps, &caps_len); 891 if (error) 892 exit(1); 893 894 process_format_caps(caps, caps_len, inquiry, allow, blks, params); 895 896 format_type = 0; 897 /* expert format section */ 898 if (expert) { 899 } 900 901 if (!format && !grow_spare && !grow_session) { 902 /* we're done */ 903 if (display_usage) 904 usage(progname); 905 uscsi_close(&dev); 906 exit(0); 907 } 908 909 /* normal format section */ 910 if (format) { 911 /* get current mmc profile of disc */ 912 913 if (oldtimer && mmc_profile != 0x0a) { 914 printf("Oldtimer flag only defined for CD-RW; " 915 "ignored\n"); 916 } 917 918 switch (mmc_profile) { 919 case 0x12 : /* DVD-RAM */ 920 format_type = 0x00; 921 break; 922 case 0x0a : /* CD-RW */ 923 format_type = mrw ? 0x24 : 0x10; 924 packet_wr = 1; 925 break; 926 case 0x13 : /* DVD-RW restricted overwrite */ 927 case 0x14 : /* DVD-RW sequential */ 928 format_type = 0x10; 929 /* 930 * Some drives suddenly stop supporting this format 931 * type when packet_wr = 1 932 */ 933 packet_wr = 0; 934 break; 935 case 0x1a : /* DVD+RW */ 936 format_type = mrw ? 0x24 : 0x26; 937 break; 938 case 0x43 : /* BD-RE */ 939 format_type = spare ? 0x30 : 0x31; 940 break; 941 default : 942 fprintf(stderr, "Can't format discs of type %s\n", 943 print_mmc_profile(mmc_profile)); 944 uscsi_close(&dev); 945 exit(1); 946 } 947 } 948 949 if (grow_spare) { 950 switch (mmc_profile) { 951 case 0x12 : /* DVD-RAM */ 952 case 0x43 : /* BD-RE */ 953 format_type = 0x01; 954 break; 955 default : 956 fprintf(stderr, 957 "Can't grow spare area for discs of type %s\n", 958 print_mmc_profile(mmc_profile)); 959 uscsi_close(&dev); 960 exit(1); 961 } 962 } 963 964 if (grow_session) { 965 switch (mmc_profile) { 966 case 0x0a : /* CD-RW */ 967 format_type = 0x11; 968 break; 969 case 0x13 : /* DVD-RW restricted overwrite */ 970 case 0x14 : /* DVD-RW sequential ? */ 971 format_type = 0x13; 972 break; 973 default : 974 uscsi_close(&dev); 975 fprintf(stderr, 976 "Can't grow session for discs of type %s\n", 977 print_mmc_profile(mmc_profile)); 978 exit(1); 979 } 980 } 981 982 /* check if format type is allowed */ 983 format_blks = blks[format_type]; 984 format_param = params[format_type]; 985 if (!allow[format_type]) { 986 if (!inquiry) 987 process_format_caps(caps, caps_len, 1, allow, 988 blks, params); 989 990 printf("\n"); 991 fflush(stdout); 992 fprintf(stderr, 993 "Drive indicates it can't format with deduced format " 994 "type 0x%02x\n", format_type); 995 uscsi_close(&dev); 996 exit(1); 997 } 998 999 if (restart_format && !((mmc_profile == 0x1a) || (format_type == 0x24))) 1000 { 1001 fprintf(stderr, 1002 "Format restarting only for MRW formats or DVD+RW " 1003 "formats\n"); 1004 uscsi_close(&dev); 1005 exit(1); 1006 } 1007 1008 if (restart_format && !wait_until_finished) { 1009 printf( "Warning : format restarting without waiting for it be " 1010 "finished is prolly not handy\n"); 1011 } 1012 1013 /* explicitly select packet write just in case */ 1014 if (packet_wr) { 1015 printf("Explicitly setting packet type and blocking number\n"); 1016 error = uscsi_set_packet_parameters(&dev, blockingnr); 1017 if (error) { 1018 fprintf(stderr, 1019 "Can't set packet writing and blocking number: " 1020 "%s\n", strerror(error)); 1021 uscsi_close(&dev); 1022 exit(1); 1023 } 1024 } 1025 1026 /* determine if formatting is done in the background */ 1027 background = 0; 1028 if (format_type == 0x24) background = 1; 1029 if (format_type == 0x26) background = 1; 1030 1031 /* special case format type 0x24 : MRW */ 1032 if (format_type == 0x24) { 1033 format_blks = spare ? 0xffff0000 : 0xffffffff; 1034 format_param = restart_format; 1035 } 1036 /* special case format type 0x26 : DVD+RW */ 1037 if (format_type == 0x26) { 1038 format_param = restart_format; 1039 } 1040 1041 /* verbose to the user */ 1042 DEBUG( 1043 printf("Actual format selected: " 1044 "format_type 0x%02x, blks %d, param %d, " 1045 "certification %d, cmplist %d\n", 1046 format_type, format_blks, format_param, 1047 certification, cmplist); 1048 ); 1049 printf("\nFormatting.... "); fflush(stdout); 1050 1051 /* formatting time! */ 1052 if (oldtimer) { 1053 error = uscsi_format_cdrw_mode7(&dev, format_blks); 1054 background = 0; 1055 } else { 1056 error = uscsi_format_disc(&dev, !background, format_type, 1057 format_blks, format_param, certification, 1058 cmplist); 1059 } 1060 1061 /* what now? */ 1062 if (error) { 1063 printf("fail\n"); fflush(stdout); 1064 fprintf(stderr, "Formatting failed because of : %s\n", 1065 strerror(error)); 1066 } else { 1067 if (background) { 1068 printf("background formatting in progress\n"); 1069 if (wait_until_finished) { 1070 printf("Waiting for completion ... "); 1071 uscsi_waitop(&dev); 1072 } 1073 /* explicitly do NOT close disc ... (for now) */ 1074 return 0; 1075 } else { 1076 printf("success!\n\n"); 1077 } 1078 } 1079 1080 /* finish up */ 1081 uscsi_close(&dev); 1082 1083 return error; 1084} 1085 1086