mmcformat.c revision 1.5 1 /* $NetBSD: mmcformat.c,v 1.5 2019/02/04 09:53:41 mrg 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 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