mmcformat.c revision 1.4 1 /* $NetBSD: mmcformat.c,v 1.4 2013/10/19 17:16:37 christos 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 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
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 case 'I' :
769 inquiry = 1;
770 break;
771 case 'X' :
772 /* TODO parse expert mode string */
773 printf("-X not implemented yet\n");
774 expert = 1;
775 exit(1);
776 break;
777 case 'O' :
778 /* oldtimer CD-RW format */
779 oldtimer = 1;
780 format = 1;
781 break;
782 case 'b' :
783 blockingnr = atoi(optarg);
784 break;
785 case 'D' :
786 uscsilib_verbose = 1;
787 break;
788 default :
789 return usage(progname);
790 }
791 }
792 argv += optind;
793 argc -= optind;
794
795 if ((!blank && !format && !grow_session && !grow_spare) &&
796 (!expert && !inquiry)) {
797 fprintf(stderr, "%s : at least one of -B, -F, -G, -S, -X or -I "
798 "needs to be specified\n\n", progname);
799 return usage(progname);
800 }
801
802 if (format + grow_session + grow_spare + expert > 1) {
803 fprintf(stderr, "%s : at most one of -F, -G, -S or -X "
804 "needs to be specified\n\n", progname);
805 return usage(progname);
806 }
807
808 if (argc != 1) return usage(progname);
809
810 /* Open the device */
811 dev.dev_name = strdup(*argv);
812 printf("Opening device %s\n", dev.dev_name);
813 error = uscsi_open(&dev);
814 if (error) {
815 fprintf(stderr, "Device failed to open : %s\n",
816 strerror(error));
817 exit(1);
818 }
819
820 error = uscsi_check_for_scsi(&dev);
821 if (error) {
822 fprintf(stderr, "sorry, not a SCSI/ATAPI device : %s\n",
823 strerror(error));
824 exit(1);
825 }
826
827 error = uscsi_identify(&dev, &saddr);
828 if (error) {
829 fprintf(stderr, "SCSI/ATAPI identify returned : %s\n",
830 strerror(error));
831 exit(1);
832 }
833
834 printf("\nDevice identifies itself as : ");
835
836 if (saddr.type == USCSI_TYPE_SCSI) {
837 printf("SCSI busnum = %d, target = %d, lun = %d\n",
838 saddr.addr.scsi.scbus, saddr.addr.scsi.target,
839 saddr.addr.scsi.lun);
840 } else {
841 printf("ATAPI busnum = %d, drive = %d\n",
842 saddr.addr.atapi.atbus, saddr.addr.atapi.drive);
843 }
844
845 printf("\n");
846
847 /* get MMC profile */
848 error = uscsi_get_mmc_profile(&dev, &mmc_profile);
849 if (error) {
850 fprintf(stderr,
851 "Can't get the disc's MMC profile because of :"
852 " %s\n", strerror(error));
853 fprintf(stderr, "aborting\n");
854 uscsi_close(&dev);
855 return 1;
856 }
857
858 /* blank disc section */
859 if (blank) {
860 printf("\nBlanking disc.... "); fflush(stdout);
861 error = uscsi_blank_disc(&dev);
862
863 if (error) {
864 printf("fail\n"); fflush(stdout);
865 fprintf(stderr,
866 "Blanking failed because of : %s\n",
867 strerror(error));
868 uscsi_close(&dev);
869
870 return 1;
871 } else {
872 printf("success!\n\n");
873 }
874 }
875
876 /* re-get MMC profile */
877 error = uscsi_get_mmc_profile(&dev, &mmc_profile);
878 if (error) {
879 fprintf(stderr,
880 "Can't get the disc's MMC profile because of : %s\n",
881 strerror(error));
882 fprintf(stderr, "aborting\n");
883 uscsi_close(&dev);
884 return 1;
885 }
886
887 error = get_format_capabilities(&dev, caps, &caps_len);
888 if (error)
889 exit(1);
890
891 process_format_caps(caps, caps_len, inquiry, allow, blks, params);
892
893 format_type = 0;
894 /* expert format section */
895 if (expert) {
896 }
897
898 if (!format && !grow_spare && !grow_session) {
899 /* we're done */
900 if (display_usage)
901 usage(progname);
902 uscsi_close(&dev);
903 exit(0);
904 }
905
906 /* normal format section */
907 if (format) {
908 /* get current mmc profile of disc */
909
910 if (oldtimer && mmc_profile != 0x0a) {
911 printf("Oldtimer flag only defined for CD-RW; "
912 "ignored\n");
913 }
914
915 switch (mmc_profile) {
916 case 0x12 : /* DVD-RAM */
917 format_type = 0x00;
918 break;
919 case 0x0a : /* CD-RW */
920 format_type = mrw ? 0x24 : 0x10;
921 packet_wr = 1;
922 break;
923 case 0x13 : /* DVD-RW restricted overwrite */
924 case 0x14 : /* DVD-RW sequential */
925 format_type = 0x10;
926 /*
927 * Some drives suddenly stop supporting this format
928 * type when packet_wr = 1
929 */
930 packet_wr = 0;
931 break;
932 case 0x1a : /* DVD+RW */
933 format_type = mrw ? 0x24 : 0x26;
934 break;
935 case 0x43 : /* BD-RE */
936 format_type = spare ? 0x30 : 0x31;
937 break;
938 default :
939 fprintf(stderr, "Can't format discs of type %s\n",
940 print_mmc_profile(mmc_profile));
941 uscsi_close(&dev);
942 exit(1);
943 }
944 }
945
946 if (grow_spare) {
947 switch (mmc_profile) {
948 case 0x12 : /* DVD-RAM */
949 case 0x43 : /* BD-RE */
950 format_type = 0x01;
951 break;
952 default :
953 fprintf(stderr,
954 "Can't grow spare area for discs of type %s\n",
955 print_mmc_profile(mmc_profile));
956 uscsi_close(&dev);
957 exit(1);
958 }
959 }
960
961 if (grow_session) {
962 switch (mmc_profile) {
963 case 0x0a : /* CD-RW */
964 format_type = 0x11;
965 break;
966 case 0x13 : /* DVD-RW restricted overwrite */
967 case 0x14 : /* DVD-RW sequential ? */
968 format_type = 0x13;
969 break;
970 default :
971 uscsi_close(&dev);
972 fprintf(stderr,
973 "Can't grow session for discs of type %s\n",
974 print_mmc_profile(mmc_profile));
975 exit(1);
976 }
977 }
978
979 /* check if format type is allowed */
980 format_blks = blks[format_type];
981 format_param = params[format_type];
982 if (!allow[format_type]) {
983 if (!inquiry)
984 process_format_caps(caps, caps_len, 1, allow,
985 blks, params);
986
987 printf("\n");
988 fflush(stdout);
989 fprintf(stderr,
990 "Drive indicates it can't format with deduced format "
991 "type 0x%02x\n", format_type);
992 uscsi_close(&dev);
993 exit(1);
994 }
995
996 if (restart_format && !((mmc_profile == 0x1a) || (format_type == 0x24)))
997 {
998 fprintf(stderr,
999 "Format restarting only for MRW formats or DVD+RW "
1000 "formats\n");
1001 uscsi_close(&dev);
1002 exit(1);
1003 }
1004
1005 if (restart_format && !wait_until_finished) {
1006 printf( "Warning : format restarting without waiting for it be "
1007 "finished is prolly not handy\n");
1008 }
1009
1010 /* explicitly select packet write just in case */
1011 if (packet_wr) {
1012 printf("Explicitly setting packet type and blocking number\n");
1013 error = uscsi_set_packet_parameters(&dev, blockingnr);
1014 if (error) {
1015 fprintf(stderr,
1016 "Can't set packet writing and blocking number: "
1017 "%s\n", strerror(error));
1018 uscsi_close(&dev);
1019 exit(1);
1020 }
1021 }
1022
1023 /* determine if formatting is done in the background */
1024 background = 0;
1025 if (format_type == 0x24) background = 1;
1026 if (format_type == 0x26) background = 1;
1027
1028 /* special case format type 0x24 : MRW */
1029 if (format_type == 0x24) {
1030 format_blks = spare ? 0xffff0000 : 0xffffffff;
1031 format_param = restart_format;
1032 }
1033 /* special case format type 0x26 : DVD+RW */
1034 if (format_type == 0x26) {
1035 format_param = restart_format;
1036 }
1037
1038 /* verbose to the user */
1039 DEBUG(
1040 printf("Actual format selected: "
1041 "format_type 0x%02x, blks %d, param %d, "
1042 "certification %d, cmplist %d\n",
1043 format_type, format_blks, format_param,
1044 certification, cmplist);
1045 );
1046 printf("\nFormatting.... "); fflush(stdout);
1047
1048 /* formatting time! */
1049 if (oldtimer) {
1050 error = uscsi_format_cdrw_mode7(&dev, format_blks);
1051 background = 0;
1052 } else {
1053 error = uscsi_format_disc(&dev, !background, format_type,
1054 format_blks, format_param, certification,
1055 cmplist);
1056 }
1057
1058 /* what now? */
1059 if (error) {
1060 printf("fail\n"); fflush(stdout);
1061 fprintf(stderr, "Formatting failed because of : %s\n",
1062 strerror(error));
1063 } else {
1064 if (background) {
1065 printf("background formatting in progress\n");
1066 if (wait_until_finished) {
1067 printf("Waiting for completion ... ");
1068 uscsi_waitop(&dev);
1069 }
1070 /* explicitly do NOT close disc ... (for now) */
1071 return 0;
1072 } else {
1073 printf("success!\n\n");
1074 }
1075 }
1076
1077 /* finish up */
1078 uscsi_close(&dev);
1079
1080 return error;
1081 }
1082
1083