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