Sync usage with man page.
[netbsd-mini2440.git] / usr.sbin / mmcformat / mmcformat.c
blob49a040a7fe0ba929bdbf80674841566a72d7ed02
1 /* $NetBSD: mmcformat.c,v 1.2 2008/05/18 13:08:58 tron Exp $ */
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.
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.
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>
42 #include "uscsilib.h"
45 /* globals */
46 struct uscsi_dev dev;
47 extern int scsilib_verbose;
49 /* #define DEBUG(a) {a;} */
50 #define DEBUG(a) ;
53 static uint64_t
54 getmtime(void)
56 struct timeval tp;
58 gettimeofday(&tp, NULL);
59 return (uint64_t) 1000000 * tp.tv_sec + tp.tv_usec;
63 static void
64 print_eta(uint32_t progress, uint64_t now, uint64_t start_time)
66 int hours, minutes, seconds;
67 uint64_t tbusy, ttot_est, eta;
69 if (progress == 0) {
70 printf(" ETA --:--:--");
71 return;
73 tbusy = now - start_time;
74 ttot_est = (tbusy * 0x10000) / progress;
75 eta = (ttot_est - tbusy) / 1000000;
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);
84 static void
85 uscsi_waitop(struct uscsi_dev *mydev)
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;
95 bzero(cmd, SCSI_CMD_LEN);
96 bzero(buffer, sizeof(buffer));
99 * not be to unpatient... give the drive some time to start or it
100 * might break off
103 start_time = getmtime();
104 sleep(10);
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);
115 * asc may be `not-ready' or `no-sense'. ascq for format in
116 * progress is 4 too
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;
129 /* check if drive is ready again, ifso break out loop */
130 if ((asc == 0) && (ascq == 0)) {
131 progress = 0x10000;
134 printf("%3d %% ", (100 * progress / 0x10000));
135 printf("%c", "|/-\\" [cnt++ %4]); /* twirl */
137 /* print ETA */
138 print_eta(progress, getmtime(), start_time);
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);
145 printf("\n");
147 return;
151 static char const *
152 print_mmc_profile(int profile)
154 static char scrap[100];
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";
182 sprintf(scrap, "Reserved profile 0x%02x", profile);
183 return scrap;
187 static int
188 uscsi_get_mmc_profile(struct uscsi_dev *mydev, int *mmc_profile)
190 scsicmd cmd;
191 uint8_t buf[32];
192 int error;
194 *mmc_profile = 0;
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);
205 return error;
209 static int
210 uscsi_set_packet_parameters(struct uscsi_dev *mydev, int blockingnr)
212 scsicmd cmd;
213 int val_len;
214 uint8_t res[10000], *pos;
215 int error;
217 /* Set up CD/DVD recording parameters */
218 DEBUG(printf("Setting device's recording parameters\n"));
220 val_len = 0x32+2+8;
221 bzero(res, val_len);
223 pos = res + 8;
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 */
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 */
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 */
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;
253 /* flag OK */
254 return 0;
258 static int
259 get_format_capabilities(struct uscsi_dev *mydev, uint8_t *buf, uint32_t *len)
261 scsicmd cmd;
262 int list_length;
263 int trans_len;
264 size_t buf_len = 512;
265 int error;
267 assert(*len >= buf_len);
268 bzero(buf, buf_len);
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;
284 list_length = buf[ 3];
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;
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;
309 *len = list_length;
310 return 0;
314 static void
315 print_format(int format_tp, uint32_t num_blks, uint32_t param,
316 int dscr_type, int verbose, int *supported)
318 char const *format_str, *nblks_str, *param_str, *user_spec;
320 format_str = nblks_str = param_str = "reserved";
321 user_spec = "";
322 *supported = 1;
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;
420 if (verbose) {
421 printf("\n\tFormat type 0x%02x : %s\n", format_tp, format_str);
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;
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);
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);
456 if (*supported) {
457 printf("\t\tmmc_format arg : %s\n", user_spec);
458 } else {
459 printf("\t\t** not supported **\n");
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)
469 uint32_t num_blks, param;
470 uint8_t *fcd;
471 int dscr_type, format_tp;
472 int supported;
474 bzero(allow, 255);
475 bzero(blks, 255*4);
476 bzero(params, 255*4);
478 fcd = buf + 4;
479 list_length -= 4; /* strip header */
481 if (verbose)
482 printf("\tCurrent/max capacity followed by additional capacity,"
483 "reported length of %d bytes (8/entry)\n", list_length);
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);
492 print_format(format_tp, num_blks, param, dscr_type, verbose,
493 &supported);
495 allow[format_tp] = 1; /* TODO = supported? */
496 blks[format_tp] = num_blks;
497 params[format_tp] = param;
499 fcd += 8;
500 list_length-=8;
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)
511 scsicmd cmd;
512 struct uscsi_sense sense;
513 uint32_t param;
514 uint8_t buffer[16];
515 int cnt, error;
517 param = cnt = 0;
519 if (blocks % 32) {
520 blocks -= blocks % 32;
523 bzero(cmd, SCSI_CMD_LEN);
524 bzero(buffer, sizeof(buffer));
526 cmd[0] = 0x04; /* format unit */
527 cmd[1] = 0x17; /* parameter list format 7 follows */
528 cmd[5] = 0; /* control */
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 ... */
537 * for CD-RW the initialisation pattern bit is reserved, but there IS
538 * one
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 */
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 */
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 */
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;
568 uscsi_waitop(mydev);
569 return 0;
573 static int
574 uscsi_format_disc(struct uscsi_dev *mydev, int immed, int format_type,
575 uint32_t blocks, uint32_t param, int certification, int cmplist)
577 scsicmd cmd;
578 struct uscsi_sense sense;
579 uint8_t buffer[16], fmt_flags;
580 int error;
582 fmt_flags = 0x80; /* valid info flag */
583 if (immed)
584 fmt_flags |= 2;
585 if (certification == 0)
586 fmt_flags |= 32;
588 if (cmplist)
589 cmplist = 8;
591 #if 0
592 if (mmc_profile != 0x43) {
593 /* certification specifier only valid for BD-RE */
594 certification = 0;
596 #endif
598 bzero(cmd, SCSI_CMD_LEN);
599 bzero(buffer, sizeof(buffer));
601 cmd[0] = 0x04; /* format unit */
602 cmd[1] = 0x11 | cmplist; /* parameter list format 1 follows */
603 cmd[5] = 0; /* control */
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 ... */
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 */
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;
627 if (immed)
628 uscsi_waitop(mydev);
630 return 0;
634 static int
635 uscsi_blank_disc(struct uscsi_dev *mydev)
637 scsicmd cmd;
638 int error;
640 /* XXX check if the device can blank! */
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 */
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;
655 uscsi_waitop(mydev);
656 return 0;
660 static int
661 usage(char *program)
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"
684 return 1;
688 extern char *optarg;
689 extern int optind;
690 extern int optreset;
694 main(int argc, char *argv[])
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);
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);
795 argv += optind;
796 argc -= optind;
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);
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);
811 if (argc != 1) return usage(progname);
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);
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);
830 error = uscsi_identify(&dev, &saddr);
831 if (error) {
832 fprintf(stderr, "SCSI/ATAPI identify returned : %s\n",
833 strerror(error));
834 exit(1);
837 printf("\nDevice identifies itself as : ");
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);
848 printf("\n");
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;
861 /* blank disc section */
862 if (blank) {
863 printf("\nBlanking disc.... "); fflush(stdout);
864 error = uscsi_blank_disc(&dev);
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);
873 return 1;
874 } else {
875 printf("success!\n\n");
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;
890 error = get_format_capabilities(&dev, caps, &caps_len);
891 if (error)
892 exit(1);
894 process_format_caps(caps, caps_len, inquiry, allow, blks, params);
896 format_type = 0;
897 /* expert format section */
898 if (expert) {
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);
909 /* normal format section */
910 if (format) {
911 /* get current mmc profile of disc */
913 if (oldtimer && mmc_profile != 0x0a) {
914 printf("Oldtimer flag only defined for CD-RW; "
915 "ignored\n");
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;
930 * Some drives suddenly stop supporting this format
931 * type when packet_wr = 1
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);
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);
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);
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);
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);
999 if (restart_format && !((mmc_profile == 0x1a) || (format_type == 0x24)))
1001 fprintf(stderr,
1002 "Format restarting only for MRW formats or DVD+RW "
1003 "formats\n");
1004 uscsi_close(&dev);
1005 exit(1);
1008 if (restart_format && !wait_until_finished) {
1009 printf( "Warning : format restarting without waiting for it be "
1010 "finished is prolly not handy\n");
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);
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;
1031 /* special case format type 0x24 : MRW */
1032 if (format_type == 0x24) {
1033 format_blks = spare ? 0xffff0000 : 0xffffffff;
1034 format_param = restart_format;
1036 /* special case format type 0x26 : DVD+RW */
1037 if (format_type == 0x26) {
1038 format_param = restart_format;
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);
1049 printf("\nFormatting.... "); fflush(stdout);
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);
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);
1073 /* explicitly do NOT close disc ... (for now) */
1074 return 0;
1075 } else {
1076 printf("success!\n\n");
1080 /* finish up */
1081 uscsi_close(&dev);
1083 return error;