1*2dbb216cSchristos /* $NetBSD: mmcformat.c,v 1.4 2013/10/19 17:16:37 christos Exp $ */ 2e979c658Sreinoud 3e979c658Sreinoud /* 4e979c658Sreinoud * Copyright (c) 2006, 2008 Reinoud Zandijk 5e979c658Sreinoud * All rights reserved. 6e979c658Sreinoud * 7e979c658Sreinoud * Redistribution and use in source and binary forms, with or without 8e979c658Sreinoud * modification, are permitted provided that the following conditions 9e979c658Sreinoud * are met: 10e979c658Sreinoud * 1. Redistributions of source code must retain the above copyright 11e979c658Sreinoud * notice, this list of conditions and the following disclaimer. 12e979c658Sreinoud * 2. Redistributions in binary form must reproduce the above copyright 13e979c658Sreinoud * notice, this list of conditions and the following disclaimer in the 14e979c658Sreinoud * documentation and/or other materials provided with the distribution. 15e979c658Sreinoud * 16e979c658Sreinoud * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17e979c658Sreinoud * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18e979c658Sreinoud * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19e979c658Sreinoud * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20e979c658Sreinoud * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21e979c658Sreinoud * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22e979c658Sreinoud * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23e979c658Sreinoud * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24e979c658Sreinoud * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25e979c658Sreinoud * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26e979c658Sreinoud * 27e979c658Sreinoud */ 28e979c658Sreinoud 29e979c658Sreinoud #include <stdio.h> 30e979c658Sreinoud #include <fcntl.h> 31e979c658Sreinoud #include <unistd.h> 32e979c658Sreinoud #include <stdlib.h> 33e979c658Sreinoud #include <errno.h> 34e979c658Sreinoud #include <string.h> 35e979c658Sreinoud #include <strings.h> 36e979c658Sreinoud #include <assert.h> 37e979c658Sreinoud #include <limits.h> 38e979c658Sreinoud #include <sys/types.h> 39e979c658Sreinoud #include <sys/time.h> 40e979c658Sreinoud #include <inttypes.h> 41e979c658Sreinoud 42e979c658Sreinoud #include "uscsilib.h" 43e979c658Sreinoud 44e979c658Sreinoud 45e979c658Sreinoud /* globals */ 46e979c658Sreinoud struct uscsi_dev dev; 47e979c658Sreinoud extern int scsilib_verbose; 48e979c658Sreinoud 49e979c658Sreinoud /* #define DEBUG(a) {a;} */ 50e979c658Sreinoud #define DEBUG(a) ; 51e979c658Sreinoud 52e979c658Sreinoud 53e979c658Sreinoud static uint64_t 54e979c658Sreinoud getmtime(void) 55e979c658Sreinoud { 56e979c658Sreinoud struct timeval tp; 57e979c658Sreinoud 58e979c658Sreinoud gettimeofday(&tp, NULL); 59e979c658Sreinoud return (uint64_t) 1000000 * tp.tv_sec + tp.tv_usec; 60e979c658Sreinoud } 61e979c658Sreinoud 62e979c658Sreinoud 63e979c658Sreinoud static void 64e979c658Sreinoud print_eta(uint32_t progress, uint64_t now, uint64_t start_time) 65e979c658Sreinoud { 66e979c658Sreinoud int hours, minutes, seconds; 67e979c658Sreinoud uint64_t tbusy, ttot_est, eta; 68e979c658Sreinoud 69e979c658Sreinoud if (progress == 0) { 70e979c658Sreinoud printf(" ETA --:--:--"); 71e979c658Sreinoud return; 72e979c658Sreinoud } 73e979c658Sreinoud tbusy = now - start_time; 74e979c658Sreinoud ttot_est = (tbusy * 0x10000) / progress; 75e979c658Sreinoud eta = (ttot_est - tbusy) / 1000000; 76e979c658Sreinoud 77e979c658Sreinoud hours = (int) (eta/3600); 78e979c658Sreinoud minutes = (int) (eta/60) % 60; 79e979c658Sreinoud seconds = (int) eta % 60; 80e979c658Sreinoud printf(" ETA %02d:%02d:%02d", hours, minutes, seconds); 81e979c658Sreinoud } 82e979c658Sreinoud 83e979c658Sreinoud 84e979c658Sreinoud static void 85e979c658Sreinoud uscsi_waitop(struct uscsi_dev *mydev) 86e979c658Sreinoud { 87e979c658Sreinoud scsicmd cmd; 88e979c658Sreinoud struct uscsi_sense sense; 89e979c658Sreinoud uint64_t start_time; 90e979c658Sreinoud uint32_t progress; 91e979c658Sreinoud uint8_t buffer[256]; 92e979c658Sreinoud int asc, ascq; 93e979c658Sreinoud int cnt = 0; 94e979c658Sreinoud 95e979c658Sreinoud bzero(cmd, SCSI_CMD_LEN); 96e979c658Sreinoud bzero(buffer, sizeof(buffer)); 97e979c658Sreinoud 98e979c658Sreinoud /* 99e979c658Sreinoud * not be to unpatient... give the drive some time to start or it 100e979c658Sreinoud * might break off 101e979c658Sreinoud */ 102e979c658Sreinoud 103e979c658Sreinoud start_time = getmtime(); 104e979c658Sreinoud sleep(10); 105e979c658Sreinoud 106e979c658Sreinoud progress = 0; 107e979c658Sreinoud while (progress < 0x10000) { 108e979c658Sreinoud /* we need a command that is NOT going to stop the formatting */ 109e979c658Sreinoud bzero(cmd, SCSI_CMD_LEN); 110e979c658Sreinoud cmd[0] = 0; /* test unit ready */ 111e979c658Sreinoud uscsi_command(SCSI_READCMD, mydev, 112e979c658Sreinoud cmd, 6, buffer, 0, 10000, &sense); 113e979c658Sreinoud 114e979c658Sreinoud /* 115e979c658Sreinoud * asc may be `not-ready' or `no-sense'. ascq for format in 116e979c658Sreinoud * progress is 4 too 117e979c658Sreinoud */ 118e979c658Sreinoud asc = sense.asc; 119e979c658Sreinoud ascq = sense.ascq; 120e979c658Sreinoud if (((asc == 0) && (ascq == 4)) || (asc == 4)) { 121e979c658Sreinoud /* drive not ready : operation/format in progress */ 122e979c658Sreinoud if (sense.skey_valid) { 123e979c658Sreinoud progress = sense.sense_key; 124e979c658Sreinoud } else { 125e979c658Sreinoud /* finished */ 126e979c658Sreinoud progress = 0x10000; 127e979c658Sreinoud } 128e979c658Sreinoud } 129e979c658Sreinoud /* check if drive is ready again, ifso break out loop */ 130e979c658Sreinoud if ((asc == 0) && (ascq == 0)) { 131e979c658Sreinoud progress = 0x10000; 132e979c658Sreinoud } 133e979c658Sreinoud 134e979c658Sreinoud printf("%3d %% ", (100 * progress / 0x10000)); 135e979c658Sreinoud printf("%c", "|/-\\" [cnt++ %4]); /* twirl */ 136e979c658Sreinoud 137e979c658Sreinoud /* print ETA */ 138e979c658Sreinoud print_eta(progress, getmtime(), start_time); 139e979c658Sreinoud 140e979c658Sreinoud fflush(stdout); 141e979c658Sreinoud sleep(1); 142e979c658Sreinoud printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); 143e979c658Sreinoud fflush(stdout); 144e979c658Sreinoud } 145e979c658Sreinoud printf("\n"); 146e979c658Sreinoud 147e979c658Sreinoud return; 148e979c658Sreinoud } 149e979c658Sreinoud 150e979c658Sreinoud 151e979c658Sreinoud static char const * 152e979c658Sreinoud print_mmc_profile(int profile) 153e979c658Sreinoud { 154e979c658Sreinoud static char scrap[100]; 155e979c658Sreinoud 156e979c658Sreinoud switch (profile) { 157e979c658Sreinoud case 0x00 : return "Unknown[0] profile"; 158e979c658Sreinoud case 0x01 : return "Non removeable disc"; 159e979c658Sreinoud case 0x02 : return "Removable disc"; 160e979c658Sreinoud case 0x03 : return "Magneto Optical with sector erase"; 161e979c658Sreinoud case 0x04 : return "Magneto Optical write once"; 162e979c658Sreinoud case 0x05 : return "Advance Storage Magneto Optical"; 163e979c658Sreinoud case 0x08 : return "CD-ROM"; 164e979c658Sreinoud case 0x09 : return "CD-R recordable"; 165e979c658Sreinoud case 0x0a : return "CD-RW rewritable"; 166e979c658Sreinoud case 0x10 : return "DVD-ROM"; 167e979c658Sreinoud case 0x11 : return "DVD-R sequential"; 168e979c658Sreinoud case 0x12 : return "DVD-RAM rewritable"; 169e979c658Sreinoud case 0x13 : return "DVD-RW restricted overwrite"; 170e979c658Sreinoud case 0x14 : return "DVD-RW sequential"; 171e979c658Sreinoud case 0x1a : return "DVD+RW rewritable"; 172e979c658Sreinoud case 0x1b : return "DVD+R recordable"; 173e979c658Sreinoud case 0x20 : return "DDCD readonly"; 174e979c658Sreinoud case 0x21 : return "DDCD-R recordable"; 175e979c658Sreinoud case 0x22 : return "DDCD-RW rewritable"; 176e979c658Sreinoud case 0x2b : return "DVD+R double layer"; 177e979c658Sreinoud case 0x40 : return "BD-ROM"; 178e979c658Sreinoud case 0x41 : return "BD-R Sequential Recording (SRM)"; 179e979c658Sreinoud case 0x42 : return "BD-R Random Recording (RRM)"; 180e979c658Sreinoud case 0x43 : return "BD-RE rewritable"; 181e979c658Sreinoud } 182e979c658Sreinoud sprintf(scrap, "Reserved profile 0x%02x", profile); 183e979c658Sreinoud return scrap; 184e979c658Sreinoud } 185e979c658Sreinoud 186e979c658Sreinoud 187e979c658Sreinoud static int 188e979c658Sreinoud uscsi_get_mmc_profile(struct uscsi_dev *mydev, int *mmc_profile) 189e979c658Sreinoud { 190e979c658Sreinoud scsicmd cmd; 191e979c658Sreinoud uint8_t buf[32]; 192e979c658Sreinoud int error; 193e979c658Sreinoud 194e979c658Sreinoud *mmc_profile = 0; 195e979c658Sreinoud 196e979c658Sreinoud bzero(cmd, SCSI_CMD_LEN); 197e979c658Sreinoud cmd[ 0] = 0x46; /* Get configuration */ 198e979c658Sreinoud cmd[ 8] = 32; /* just a small buffer size */ 199e979c658Sreinoud cmd[ 9] = 0; /* control */ 200e979c658Sreinoud error = uscsi_command(SCSI_READCMD, mydev, cmd, 10, buf, 32, 30000, NULL); 201e979c658Sreinoud if (!error) { 202e979c658Sreinoud *mmc_profile = buf[7] | (buf[6] << 8); 203e979c658Sreinoud } 204e979c658Sreinoud 205e979c658Sreinoud return error; 206e979c658Sreinoud } 207e979c658Sreinoud 208e979c658Sreinoud 209e979c658Sreinoud static int 210e979c658Sreinoud uscsi_set_packet_parameters(struct uscsi_dev *mydev, int blockingnr) 211e979c658Sreinoud { 212e979c658Sreinoud scsicmd cmd; 213d5f41fe1Stron int val_len; 214d5f41fe1Stron uint8_t res[10000], *pos; 215e979c658Sreinoud int error; 216e979c658Sreinoud 217e979c658Sreinoud /* Set up CD/DVD recording parameters */ 218e979c658Sreinoud DEBUG(printf("Setting device's recording parameters\n")); 219e979c658Sreinoud 220e979c658Sreinoud val_len = 0x32+2+8; 221e979c658Sreinoud bzero(res, val_len); 222e979c658Sreinoud 223e979c658Sreinoud pos = res + 8; 224e979c658Sreinoud 225e979c658Sreinoud bzero(cmd, SCSI_CMD_LEN); 226e979c658Sreinoud pos[ 0] = 0x05; /* page code 5 : cd writing */ 227e979c658Sreinoud pos[ 1] = 0x32; /* length in bytes */ 228e979c658Sreinoud pos[ 2] = 0; /* write type 0 : packet/incremental */ 229e979c658Sreinoud 230e979c658Sreinoud /* next session OK, data packet, rec. incr. fixed packets */ 231e979c658Sreinoud pos[ 3] = (3<<6) | 32 | 5; 232e979c658Sreinoud pos[ 4] = 10; /* ISO mode 2; XA form 1 */ 233e979c658Sreinoud pos[ 8] = 0x20; /* CD-ROM XA disc or DDCD disc */ 234e979c658Sreinoud pos[10] = (blockingnr >> 24) & 0xff; /* MSB packet size */ 235e979c658Sreinoud pos[11] = (blockingnr >> 16) & 0xff; 236e979c658Sreinoud pos[12] = (blockingnr >> 8) & 0xff; 237e979c658Sreinoud pos[13] = (blockingnr ) & 0xff; /* LSB packet size */ 238e979c658Sreinoud 239e979c658Sreinoud bzero(cmd, SCSI_CMD_LEN); 240e979c658Sreinoud cmd[0] = 0x55; /* MODE SELECT (10) */ 241e979c658Sreinoud cmd[1] = 16; /* PF format */ 242e979c658Sreinoud cmd[7] = val_len >> 8; /* length of blob */ 243e979c658Sreinoud cmd[8] = val_len & 0xff; 244e979c658Sreinoud cmd[9] = 0; /* control */ 245e979c658Sreinoud 246e979c658Sreinoud error = uscsi_command(SCSI_WRITECMD, mydev, 247e979c658Sreinoud cmd, 10, res, val_len, 30000, NULL); 248e979c658Sreinoud if (error) { 249e979c658Sreinoud perror("While WRTITING parameter page 5"); 250e979c658Sreinoud return error; 251e979c658Sreinoud } 252e979c658Sreinoud 253e979c658Sreinoud /* flag OK */ 254e979c658Sreinoud return 0; 255e979c658Sreinoud } 256e979c658Sreinoud 257e979c658Sreinoud 258e979c658Sreinoud static int 259e979c658Sreinoud get_format_capabilities(struct uscsi_dev *mydev, uint8_t *buf, uint32_t *len) 260e979c658Sreinoud { 261e979c658Sreinoud scsicmd cmd; 262e979c658Sreinoud int list_length; 263f5a433a7Slukem int trans_len; 264f5a433a7Slukem size_t buf_len = 512; 265e979c658Sreinoud int error; 266e979c658Sreinoud 267e979c658Sreinoud assert(*len >= buf_len); 268e979c658Sreinoud bzero(buf, buf_len); 269e979c658Sreinoud 270e979c658Sreinoud trans_len = 12; /* only fixed header first */ 271e979c658Sreinoud bzero(cmd, SCSI_CMD_LEN); 272e979c658Sreinoud cmd[0] = 0x23; /* Read format capabilities */ 273e979c658Sreinoud cmd[7] = trans_len >> 8; /* MSB allocation length */ 274e979c658Sreinoud cmd[8] = trans_len & 0xff; /* LSB allocation length */ 275e979c658Sreinoud cmd[9] = 0; /* control */ 276e979c658Sreinoud error = uscsi_command(SCSI_READCMD, mydev, 277e979c658Sreinoud cmd, 10, buf, trans_len, 30000, NULL); 278e979c658Sreinoud if (error) { 279e979c658Sreinoud fprintf(stderr, "While reading format capabilities : %s\n", 280e979c658Sreinoud strerror(error)); 281e979c658Sreinoud return error; 282e979c658Sreinoud } 283e979c658Sreinoud 284e979c658Sreinoud list_length = buf[ 3]; 285e979c658Sreinoud 286e979c658Sreinoud if (list_length % 8) { 287e979c658Sreinoud printf( "\t\tWarning: violating SCSI spec," 288e979c658Sreinoud "capacity list length ought to be multiple of 8\n"); 289e979c658Sreinoud printf("\t\tInterpreting as including header of 4 bytes\n"); 290e979c658Sreinoud assert(list_length % 8 == 4); 291e979c658Sreinoud list_length -= 4; 292e979c658Sreinoud } 293e979c658Sreinoud 294e979c658Sreinoud /* read in full capacity list */ 295e979c658Sreinoud trans_len = 12 + list_length; /* complete structure */ 296e979c658Sreinoud bzero(cmd, SCSI_CMD_LEN); 297e979c658Sreinoud cmd[0] = 0x23; /* Read format capabilities */ 298e979c658Sreinoud cmd[7] = trans_len >> 8; /* MSB allocation length */ 299e979c658Sreinoud cmd[8] = trans_len & 0xff; /* LSB allocation length */ 300e979c658Sreinoud cmd[9] = 0; /* control */ 301e979c658Sreinoud error = uscsi_command(SCSI_READCMD, mydev, 302e979c658Sreinoud cmd, 10, buf, trans_len, 30000, NULL); 303e979c658Sreinoud if (error) { 304e979c658Sreinoud fprintf(stderr, "While reading format capabilities : %s\n", 305e979c658Sreinoud strerror(error)); 306e979c658Sreinoud return error; 307e979c658Sreinoud } 308e979c658Sreinoud 309e979c658Sreinoud *len = list_length; 310e979c658Sreinoud return 0; 311e979c658Sreinoud } 312e979c658Sreinoud 313e979c658Sreinoud 314e979c658Sreinoud static void 315e979c658Sreinoud print_format(int format_tp, uint32_t num_blks, uint32_t param, 316e979c658Sreinoud int dscr_type, int verbose, int *supported) 317e979c658Sreinoud { 318e979c658Sreinoud char const *format_str, *nblks_str, *param_str, *user_spec; 319e979c658Sreinoud 320e979c658Sreinoud format_str = nblks_str = param_str = "reserved"; 321e979c658Sreinoud user_spec = ""; 322e979c658Sreinoud *supported = 1; 323e979c658Sreinoud 324e979c658Sreinoud switch (format_tp) { 325e979c658Sreinoud case 0x00 : 326e979c658Sreinoud format_str = "full format capacity"; 327e979c658Sreinoud nblks_str = "sectors"; 328e979c658Sreinoud param_str = "block length in bytes"; 329e979c658Sreinoud user_spec = "'-F [-b blockingnr]'"; 330e979c658Sreinoud break; 331e979c658Sreinoud case 0x01 : 332e979c658Sreinoud format_str = "spare area expansion"; 333e979c658Sreinoud nblks_str = "extension in blocks"; 334e979c658Sreinoud param_str = "block length in bytes"; 335e979c658Sreinoud user_spec = "'-S'"; 336e979c658Sreinoud break; 337e979c658Sreinoud /* 0x02 - 0x03 reserved */ 338e979c658Sreinoud case 0x04 : 339e979c658Sreinoud format_str = "variable length zone'd format"; 340e979c658Sreinoud nblks_str = "zone length"; 341e979c658Sreinoud param_str = "zone number"; 342e979c658Sreinoud *supported = 0; 343e979c658Sreinoud break; 344e979c658Sreinoud case 0x05 : 345e979c658Sreinoud format_str = "fixed length zone'd format"; 346e979c658Sreinoud nblks_str = "zone lenght"; 347e979c658Sreinoud param_str = "last zone number"; 348e979c658Sreinoud *supported = 0; 349e979c658Sreinoud break; 350e979c658Sreinoud /* 0x06 - 0x0f reserved */ 351e979c658Sreinoud case 0x10 : 352e979c658Sreinoud format_str = "CD-RW/DVD-RW full packet format"; 353e979c658Sreinoud nblks_str = "adressable blocks"; 354e979c658Sreinoud param_str = "fixed packet size/ECC blocksize in sectors"; 355e979c658Sreinoud user_spec = "'-F -p [-b blockingnr]'"; 356e979c658Sreinoud break; 357e979c658Sreinoud case 0x11 : 358e979c658Sreinoud format_str = "CD-RW/DVD-RW grow session"; 359e979c658Sreinoud nblks_str = "adressable blocks"; 360e979c658Sreinoud param_str = "fixed packet size/ECC blocksize in sectors"; 361e979c658Sreinoud user_spec = "'-G'"; 362e979c658Sreinoud break; 363e979c658Sreinoud case 0x12 : 364e979c658Sreinoud format_str = "CD-RW/DVD-RW add session"; 365e979c658Sreinoud nblks_str = "adressable blocks"; 366e979c658Sreinoud param_str = "maximum fixed packet size/ECC blocksize " 367e979c658Sreinoud "in sectors"; 368e979c658Sreinoud *supported = 0; 369e979c658Sreinoud break; 370e979c658Sreinoud case 0x13 : 371e979c658Sreinoud format_str = "DVD-RW max growth of last complete session"; 372e979c658Sreinoud nblks_str = "adressable blocks"; 373e979c658Sreinoud param_str = "ECC blocksize in sectors"; 374e979c658Sreinoud user_spec = "'-G'"; 375e979c658Sreinoud break; 376e979c658Sreinoud case 0x14 : 377e979c658Sreinoud format_str = "DVD-RW quick grow last session"; 378e979c658Sreinoud nblks_str = "adressable blocks"; 379e979c658Sreinoud param_str = "ECC blocksize in sectors"; 380e979c658Sreinoud *supported = 0; 381e979c658Sreinoud break; 382e979c658Sreinoud case 0x15 : 383e979c658Sreinoud format_str = "DVD-RW quick full format"; 384e979c658Sreinoud nblks_str = "adressable blocks"; 385e979c658Sreinoud param_str = "ECC blocksize in sectors"; 386e979c658Sreinoud *supported = 0; 387e979c658Sreinoud break; 388e979c658Sreinoud /* 0x16 - 0x23 reserved */ 389e979c658Sreinoud case 0x24 : 390e979c658Sreinoud format_str = "background MRW format"; 391e979c658Sreinoud nblks_str = "Defect Management Area blocks"; 392e979c658Sreinoud param_str = "not used"; 393e979c658Sreinoud user_spec = "'[-R] [-s] [-w] -F -M [-b blockingnr]'"; 394e979c658Sreinoud break; 395e979c658Sreinoud /* 0x25 reserved */ 396e979c658Sreinoud case 0x26 : 397e979c658Sreinoud format_str = "background DVD+RW full format"; 398e979c658Sreinoud nblks_str = "sectors"; 399e979c658Sreinoud param_str = "not used"; 400e979c658Sreinoud user_spec = "'[-R] [-w] -F'"; 401e979c658Sreinoud break; 402e979c658Sreinoud /* 0x27 - 0x2f reserved */ 403e979c658Sreinoud case 0x30 : 404e979c658Sreinoud format_str = "BD-RE full format with spare area"; 405e979c658Sreinoud nblks_str = "blocks"; 406e979c658Sreinoud param_str = "total spare area size in clusters"; 407e979c658Sreinoud user_spec = "'[-s] -F'"; 408e979c658Sreinoud break; 409e979c658Sreinoud case 0x31 : 410e979c658Sreinoud format_str = "BD-RE full format without spare area"; 411e979c658Sreinoud nblks_str = "blocks"; 412e979c658Sreinoud param_str = "block length in bytes"; 413e979c658Sreinoud user_spec = "'-F'"; 414e979c658Sreinoud break; 415e979c658Sreinoud /* 0x32 - 0x3f reserved */ 416e979c658Sreinoud default : 417e979c658Sreinoud break; 418e979c658Sreinoud } 419e979c658Sreinoud 420e979c658Sreinoud if (verbose) { 421e979c658Sreinoud printf("\n\tFormat type 0x%02x : %s\n", format_tp, format_str); 422e979c658Sreinoud 423e979c658Sreinoud switch (dscr_type) { 424e979c658Sreinoud case 1 : 425e979c658Sreinoud printf( "\t\tUnformatted media," 426e979c658Sreinoud "maximum formatted capacity\n"); 427e979c658Sreinoud break; 428e979c658Sreinoud case 2 : 429e979c658Sreinoud printf( "\t\tFormatted media," 430e979c658Sreinoud "current formatted capacity\n"); 431e979c658Sreinoud break; 432e979c658Sreinoud case 3 : 433e979c658Sreinoud printf( "\t\tNo media present or incomplete session, " 434e979c658Sreinoud "maximum formatted capacity\n"); 435e979c658Sreinoud break; 436e979c658Sreinoud default : 437e979c658Sreinoud printf("\t\tUnspecified descriptor type\n"); 438e979c658Sreinoud break; 439e979c658Sreinoud } 440e979c658Sreinoud 441e979c658Sreinoud printf("\t\tNumber of blocks : %12d\t(%s)\n", 442e979c658Sreinoud num_blks, nblks_str); 443e979c658Sreinoud printf("\t\tParameter : %12d\t(%s)\n", 444e979c658Sreinoud param, param_str); 445e979c658Sreinoud 446e979c658Sreinoud if (format_tp == 0x24) { 447e979c658Sreinoud printf( "\t\tExpert select : " 448e979c658Sreinoud "'-X 0x%02x:0xffffff:0' or " 449e979c658Sreinoud "'-X 0x%02x:0xffff0000:0'\n", 450e979c658Sreinoud format_tp, format_tp); 451e979c658Sreinoud } else { 452e979c658Sreinoud printf( "\t\tExpert select : " 453e979c658Sreinoud "'-X 0x%02x:%d:%d'\n", 454e979c658Sreinoud format_tp, num_blks, param); 455e979c658Sreinoud } 456e979c658Sreinoud if (*supported) { 457e979c658Sreinoud printf("\t\tmmc_format arg : %s\n", user_spec); 458e979c658Sreinoud } else { 459e979c658Sreinoud printf("\t\t** not supported **\n"); 460e979c658Sreinoud } 461e979c658Sreinoud } 462e979c658Sreinoud } 463e979c658Sreinoud 464e979c658Sreinoud 465e979c658Sreinoud static void 466e979c658Sreinoud process_format_caps(uint8_t *buf, int list_length, int verbose, 467e979c658Sreinoud uint8_t *allow, uint32_t *blks, uint32_t *params) 468e979c658Sreinoud { 469e979c658Sreinoud uint32_t num_blks, param; 470e979c658Sreinoud uint8_t *fcd; 471e979c658Sreinoud int dscr_type, format_tp; 472e979c658Sreinoud int supported; 473e979c658Sreinoud 474e979c658Sreinoud bzero(allow, 255); 475e979c658Sreinoud bzero(blks, 255*4); 476e979c658Sreinoud bzero(params, 255*4); 477e979c658Sreinoud 478e979c658Sreinoud fcd = buf + 4; 479e979c658Sreinoud list_length -= 4; /* strip header */ 480e979c658Sreinoud 481e979c658Sreinoud if (verbose) 482e979c658Sreinoud printf("\tCurrent/max capacity followed by additional capacity," 483e979c658Sreinoud "reported length of %d bytes (8/entry)\n", list_length); 484e979c658Sreinoud 485e979c658Sreinoud while (list_length > 0) { 486e979c658Sreinoud num_blks = fcd[ 3] | (fcd[ 2] << 8) | 487e979c658Sreinoud (fcd[ 1] << 16) | (fcd[ 0] << 24); 488e979c658Sreinoud dscr_type = fcd[ 4] & 3; 489e979c658Sreinoud format_tp = fcd[ 4] >> 2; 490e979c658Sreinoud param = fcd[ 7] | (fcd[ 6] << 8) | (fcd[ 5] << 16); 491e979c658Sreinoud 492e979c658Sreinoud print_format(format_tp, num_blks, param, dscr_type, verbose, 493e979c658Sreinoud &supported); 494e979c658Sreinoud 495e979c658Sreinoud allow[format_tp] = 1; /* TODO = supported? */ 496e979c658Sreinoud blks[format_tp] = num_blks; 497e979c658Sreinoud params[format_tp] = param; 498e979c658Sreinoud 499e979c658Sreinoud fcd += 8; 500e979c658Sreinoud list_length-=8; 501e979c658Sreinoud } 502e979c658Sreinoud } 503e979c658Sreinoud 504e979c658Sreinoud 505e979c658Sreinoud 506e979c658Sreinoud /* format a CD-RW disc */ 507e979c658Sreinoud /* old style format 7 */ 508e979c658Sreinoud static int 509e979c658Sreinoud uscsi_format_cdrw_mode7(struct uscsi_dev *mydev, uint32_t blocks) 510e979c658Sreinoud { 511e979c658Sreinoud scsicmd cmd; 512e979c658Sreinoud struct uscsi_sense sense; 513e979c658Sreinoud uint8_t buffer[16]; 514*2dbb216cSchristos int error; 515e979c658Sreinoud 516e979c658Sreinoud if (blocks % 32) { 517e979c658Sreinoud blocks -= blocks % 32; 518e979c658Sreinoud } 519e979c658Sreinoud 520e979c658Sreinoud bzero(cmd, SCSI_CMD_LEN); 521e979c658Sreinoud bzero(buffer, sizeof(buffer)); 522e979c658Sreinoud 523e979c658Sreinoud cmd[0] = 0x04; /* format unit */ 524e979c658Sreinoud cmd[1] = 0x17; /* parameter list format 7 follows */ 525e979c658Sreinoud cmd[5] = 0; /* control */ 526e979c658Sreinoud 527e979c658Sreinoud /* format list header */ 528e979c658Sreinoud buffer[ 0] = 0; /* reserved */ 529e979c658Sreinoud buffer[ 1] = 0x80 | 0x02; /* Valid info, immediate return */ 530e979c658Sreinoud buffer[ 2] = 0; /* MSB format descriptor length */ 531e979c658Sreinoud buffer[ 3] = 8; /* LSB ... */ 532e979c658Sreinoud 533e979c658Sreinoud /* 534e979c658Sreinoud * for CD-RW the initialisation pattern bit is reserved, but there IS 535e979c658Sreinoud * one 536e979c658Sreinoud */ 537e979c658Sreinoud 538e979c658Sreinoud buffer[ 4] = 0; /* no header */ 539e979c658Sreinoud buffer[ 5] = 0; /* default pattern */ 540e979c658Sreinoud buffer[ 6] = 0; /* pattern length MSB */ 541e979c658Sreinoud buffer[ 7] = 0; /* pattern length LSB */ 542e979c658Sreinoud 543e979c658Sreinoud /* 8 bytes of format descriptor */ 544e979c658Sreinoud /* (s)ession bit 1<<7, (g)row bit 1<<6 */ 545e979c658Sreinoud /* SG action */ 546e979c658Sreinoud /* 00 format disc with number of user data blocks */ 547e979c658Sreinoud /* 10 create new session with number of data blocks */ 548e979c658Sreinoud /* x1 grow session to be number of data blocks */ 549e979c658Sreinoud 550e979c658Sreinoud buffer[ 8] = 0x00; /* session and grow bits (7 and 6) */ 551e979c658Sreinoud buffer[ 9] = 0; /* reserved */ 552e979c658Sreinoud buffer[10] = 0; /* reserved */ 553e979c658Sreinoud buffer[11] = 0; /* reserved */ 554e979c658Sreinoud buffer[12] = (blocks >> 24) & 0xff; /* blocks MSB */ 555e979c658Sreinoud buffer[13] = (blocks >> 16) & 0xff; 556e979c658Sreinoud buffer[14] = (blocks >> 8) & 0xff; 557e979c658Sreinoud buffer[15] = (blocks ) & 0xff; /* blocks LSB */ 558e979c658Sreinoud 559e979c658Sreinoud /* this will take a while .... */ 560e979c658Sreinoud error = uscsi_command(SCSI_WRITECMD, mydev, 561e979c658Sreinoud cmd, 6, buffer, sizeof(buffer), UINT_MAX, &sense); 562e979c658Sreinoud if (error) 563e979c658Sreinoud return error; 564e979c658Sreinoud 565e979c658Sreinoud uscsi_waitop(mydev); 566e979c658Sreinoud return 0; 567e979c658Sreinoud } 568e979c658Sreinoud 569e979c658Sreinoud 570e979c658Sreinoud static int 571e979c658Sreinoud uscsi_format_disc(struct uscsi_dev *mydev, int immed, int format_type, 572e979c658Sreinoud uint32_t blocks, uint32_t param, int certification, int cmplist) 573e979c658Sreinoud { 574e979c658Sreinoud scsicmd cmd; 575e979c658Sreinoud struct uscsi_sense sense; 576e979c658Sreinoud uint8_t buffer[16], fmt_flags; 577e979c658Sreinoud int error; 578e979c658Sreinoud 579e979c658Sreinoud fmt_flags = 0x80; /* valid info flag */ 580e979c658Sreinoud if (immed) 581e979c658Sreinoud fmt_flags |= 2; 582e979c658Sreinoud if (certification == 0) 583e979c658Sreinoud fmt_flags |= 32; 584e979c658Sreinoud 585e979c658Sreinoud if (cmplist) 586e979c658Sreinoud cmplist = 8; 587e979c658Sreinoud 588e979c658Sreinoud #if 0 589e979c658Sreinoud if (mmc_profile != 0x43) { 590e979c658Sreinoud /* certification specifier only valid for BD-RE */ 591e979c658Sreinoud certification = 0; 592e979c658Sreinoud } 593e979c658Sreinoud #endif 594e979c658Sreinoud 595e979c658Sreinoud bzero(cmd, SCSI_CMD_LEN); 596e979c658Sreinoud bzero(buffer, sizeof(buffer)); 597e979c658Sreinoud 598e979c658Sreinoud cmd[0] = 0x04; /* format unit */ 599e979c658Sreinoud cmd[1] = 0x11 | cmplist; /* parameter list format 1 follows */ 600e979c658Sreinoud cmd[5] = 0; /* control */ 601e979c658Sreinoud 602e979c658Sreinoud /* format list header */ 603e979c658Sreinoud buffer[ 0] = 0; /* reserved */ 604e979c658Sreinoud buffer[ 1] = 0x80 | fmt_flags; /* Valid info, flags follow */ 605e979c658Sreinoud buffer[ 2] = 0; /* MSB format descriptor length */ 606e979c658Sreinoud buffer[ 3] = 8; /* LSB ... */ 607e979c658Sreinoud 608e979c658Sreinoud /* 8 bytes of format descriptor */ 609e979c658Sreinoud buffer[ 4] = (blocks >> 24) & 0xff; /* blocks MSB */ 610e979c658Sreinoud buffer[ 5] = (blocks >> 16) & 0xff; 611e979c658Sreinoud buffer[ 6] = (blocks >> 8) & 0xff; 612e979c658Sreinoud buffer[ 7] = (blocks ) & 0xff; /* blocks LSB */ 613e979c658Sreinoud buffer[ 8] = (format_type << 2) | certification; 614e979c658Sreinoud buffer[ 9] = (param >> 16) & 0xff; /* parameter MSB */ 615e979c658Sreinoud buffer[10] = (param >> 8) & 0xff; /* packet size */ 616e979c658Sreinoud buffer[11] = (param ) & 0xff; /* parameter LSB */ 617e979c658Sreinoud 618e979c658Sreinoud /* this will take a while .... */ 619e979c658Sreinoud error = uscsi_command(SCSI_WRITECMD, mydev, 620e979c658Sreinoud cmd, 6, buffer, 12, UINT_MAX, &sense); 621e979c658Sreinoud if (error) 622e979c658Sreinoud return error; 623e979c658Sreinoud 624e979c658Sreinoud if (immed) 625e979c658Sreinoud uscsi_waitop(mydev); 626e979c658Sreinoud 627e979c658Sreinoud return 0; 628e979c658Sreinoud } 629e979c658Sreinoud 630e979c658Sreinoud 631e979c658Sreinoud static int 632e979c658Sreinoud uscsi_blank_disc(struct uscsi_dev *mydev) 633e979c658Sreinoud { 634e979c658Sreinoud scsicmd cmd; 635e979c658Sreinoud int error; 636e979c658Sreinoud 637e979c658Sreinoud /* XXX check if the device can blank! */ 638e979c658Sreinoud 639e979c658Sreinoud 640e979c658Sreinoud /* blank disc */ 641e979c658Sreinoud bzero(cmd, SCSI_CMD_LEN); 642e979c658Sreinoud cmd[ 0] = 0xA1; /* blank */ 643e979c658Sreinoud cmd[ 1] = 16; /* Immediate, blank complete */ 644e979c658Sreinoud cmd[11] = 0; /* control */ 645e979c658Sreinoud 646e979c658Sreinoud /* this will take a while .... */ 647e979c658Sreinoud error = uscsi_command(SCSI_WRITECMD, mydev, 648e979c658Sreinoud cmd, 12, NULL, 0, UINT_MAX, NULL); 649e979c658Sreinoud if (error) 650e979c658Sreinoud return error; 651e979c658Sreinoud 652e979c658Sreinoud uscsi_waitop(mydev); 653e979c658Sreinoud return 0; 654e979c658Sreinoud } 655e979c658Sreinoud 656e979c658Sreinoud 657e979c658Sreinoud static int 658e979c658Sreinoud usage(char *program) 659e979c658Sreinoud { 660e979c658Sreinoud fprintf(stderr, "\n"); 661e979c658Sreinoud fprintf(stderr, "Usage: %s [options] devicename\n", program); 662e979c658Sreinoud fprintf(stderr, 663e979c658Sreinoud "-B blank cd-rw disc before formatting\n" 664e979c658Sreinoud "-F format cd-rw disc\n" 665e979c658Sreinoud "-O CD-RW formatting 'old-style' for old CD-RW drives\n" 666e979c658Sreinoud "-M select MRW format\n" 667e979c658Sreinoud "-R restart MRW & DVD+RW format\n" 668e979c658Sreinoud "-G grow last CD-RW/DVD-RW session\n" 669e979c658Sreinoud "-S grow spare space DVD-RAM/BD-RE\n" 670e979c658Sreinoud "-s format DVD+MRW/BD-RE with extra spare space\n" 671e979c658Sreinoud "-w wait until completion of background format\n" 672e979c658Sreinoud "-p explicitly set packet format\n" 673e979c658Sreinoud "-c num media certification for DVD-RAM/BD-RE : " 674e979c658Sreinoud "0 no, 1 full, 2 quick\n" 675e979c658Sreinoud "-r recompile defect list for DVD-RAM (cmplist)\n" 676e979c658Sreinoud "-h -H -I help/inquiry formats\n" 677e979c658Sreinoud "-X format expert format selector form 'fmt:blks:param' with -c\n" 678e979c658Sreinoud "-b blockingnr in sectors (for CD-RW)\n" 679e979c658Sreinoud "-D verbose SCSI command errors\n" 680e979c658Sreinoud ); 681e979c658Sreinoud return 1; 682e979c658Sreinoud } 683e979c658Sreinoud 684e979c658Sreinoud 685e979c658Sreinoud extern char *optarg; 686e979c658Sreinoud extern int optind; 687e979c658Sreinoud extern int optreset; 688e979c658Sreinoud 689e979c658Sreinoud 690e979c658Sreinoud int 691e979c658Sreinoud main(int argc, char *argv[]) 692e979c658Sreinoud { 693e979c658Sreinoud struct uscsi_addr saddr; 694e979c658Sreinoud uint32_t blks[256], params[256]; 695e979c658Sreinoud uint32_t format_type, format_blks, format_param, blockingnr; 696e979c658Sreinoud uint8_t allow[256]; 697d5f41fe1Stron uint8_t caps[512]; 698d5f41fe1Stron uint32_t caps_len = sizeof(caps); 699e979c658Sreinoud char *progname; 700e979c658Sreinoud int blank, format, mrw, background; 701e979c658Sreinoud int inquiry, spare, oldtimer; 702e979c658Sreinoud int expert; 703e979c658Sreinoud int restart_format, grow_session, grow_spare, packet_wr; 704e979c658Sreinoud int mmc_profile, flag, error, display_usage; 705e979c658Sreinoud int certification, cmplist; 706e979c658Sreinoud int wait_until_finished; 707e979c658Sreinoud progname = strdup(argv[0]); 708e979c658Sreinoud if (argc == 1) { 709e979c658Sreinoud return usage(progname); 710e979c658Sreinoud } 711e979c658Sreinoud 712e979c658Sreinoud blank = 0; 713e979c658Sreinoud format = 0; 714e979c658Sreinoud mrw = 0; 715e979c658Sreinoud restart_format = 0; 716e979c658Sreinoud grow_session = 0; 717e979c658Sreinoud grow_spare = 0; 718e979c658Sreinoud wait_until_finished = 0; 719e979c658Sreinoud packet_wr = 0; 720e979c658Sreinoud certification = 1; 721e979c658Sreinoud cmplist = 0; 722e979c658Sreinoud inquiry = 0; 723e979c658Sreinoud spare = 0; 724e979c658Sreinoud inquiry = 0; 725e979c658Sreinoud oldtimer = 0; 726e979c658Sreinoud expert = 0; 727e979c658Sreinoud display_usage = 0; 728e979c658Sreinoud blockingnr = 32; 729e979c658Sreinoud uscsilib_verbose = 0; 730e979c658Sreinoud while ((flag = getopt(argc, argv, "BFMRGSwpsc:rhHIX:Ob:D")) != -1) { 731e979c658Sreinoud switch (flag) { 732e979c658Sreinoud case 'B' : 733e979c658Sreinoud blank = 1; 734e979c658Sreinoud break; 735e979c658Sreinoud case 'F' : 736e979c658Sreinoud format = 1; 737e979c658Sreinoud break; 738e979c658Sreinoud case 'M' : 739e979c658Sreinoud mrw = 1; 740e979c658Sreinoud break; 741e979c658Sreinoud case 'R' : 742e979c658Sreinoud restart_format = 1; 743e979c658Sreinoud break; 744e979c658Sreinoud case 'G' : 745e979c658Sreinoud grow_session = 1; 746e979c658Sreinoud break; 747e979c658Sreinoud case 'S' : 748e979c658Sreinoud grow_spare = 1; 749e979c658Sreinoud break; 750e979c658Sreinoud case 'w' : 751e979c658Sreinoud wait_until_finished = 1; 752e979c658Sreinoud break; 753e979c658Sreinoud case 'p' : 754e979c658Sreinoud packet_wr = 1; 755e979c658Sreinoud break; 756e979c658Sreinoud case 's' : 757e979c658Sreinoud spare = 1; 758e979c658Sreinoud break; 759e979c658Sreinoud case 'c' : 760e979c658Sreinoud certification = atoi(optarg); 761e979c658Sreinoud break; 762e979c658Sreinoud case 'r' : 763e979c658Sreinoud cmplist = 1; 764e979c658Sreinoud break; 765e979c658Sreinoud case 'h' : 766e979c658Sreinoud case 'H' : 767e979c658Sreinoud display_usage = 1; 768e979c658Sreinoud case 'I' : 769e979c658Sreinoud inquiry = 1; 770e979c658Sreinoud break; 771e979c658Sreinoud case 'X' : 772e979c658Sreinoud /* TODO parse expert mode string */ 773e979c658Sreinoud printf("-X not implemented yet\n"); 774e979c658Sreinoud expert = 1; 775e979c658Sreinoud exit(1); 776e979c658Sreinoud break; 777e979c658Sreinoud case 'O' : 778e979c658Sreinoud /* oldtimer CD-RW format */ 779e979c658Sreinoud oldtimer = 1; 780e979c658Sreinoud format = 1; 781e979c658Sreinoud break; 782e979c658Sreinoud case 'b' : 783e979c658Sreinoud blockingnr = atoi(optarg); 784e979c658Sreinoud break; 785e979c658Sreinoud case 'D' : 786e979c658Sreinoud uscsilib_verbose = 1; 787e979c658Sreinoud break; 788e979c658Sreinoud default : 789e979c658Sreinoud return usage(progname); 790e979c658Sreinoud } 791e979c658Sreinoud } 792e979c658Sreinoud argv += optind; 793e979c658Sreinoud argc -= optind; 794e979c658Sreinoud 795e979c658Sreinoud if ((!blank && !format && !grow_session && !grow_spare) && 796e979c658Sreinoud (!expert && !inquiry)) { 797e979c658Sreinoud fprintf(stderr, "%s : at least one of -B, -F, -G, -S, -X or -I " 798e979c658Sreinoud "needs to be specified\n\n", progname); 799e979c658Sreinoud return usage(progname); 800e979c658Sreinoud } 801e979c658Sreinoud 802e979c658Sreinoud if (format + grow_session + grow_spare + expert > 1) { 803e979c658Sreinoud fprintf(stderr, "%s : at most one of -F, -G, -S or -X " 804e979c658Sreinoud "needs to be specified\n\n", progname); 805e979c658Sreinoud return usage(progname); 806e979c658Sreinoud } 807e979c658Sreinoud 808e979c658Sreinoud if (argc != 1) return usage(progname); 809e979c658Sreinoud 810e979c658Sreinoud /* Open the device */ 811e979c658Sreinoud dev.dev_name = strdup(*argv); 812e979c658Sreinoud printf("Opening device %s\n", dev.dev_name); 813e979c658Sreinoud error = uscsi_open(&dev); 814e979c658Sreinoud if (error) { 815e979c658Sreinoud fprintf(stderr, "Device failed to open : %s\n", 816e979c658Sreinoud strerror(error)); 817e979c658Sreinoud exit(1); 818e979c658Sreinoud } 819e979c658Sreinoud 820e979c658Sreinoud error = uscsi_check_for_scsi(&dev); 821e979c658Sreinoud if (error) { 822e979c658Sreinoud fprintf(stderr, "sorry, not a SCSI/ATAPI device : %s\n", 823e979c658Sreinoud strerror(error)); 824e979c658Sreinoud exit(1); 825e979c658Sreinoud } 826e979c658Sreinoud 827e979c658Sreinoud error = uscsi_identify(&dev, &saddr); 828e979c658Sreinoud if (error) { 829e979c658Sreinoud fprintf(stderr, "SCSI/ATAPI identify returned : %s\n", 830e979c658Sreinoud strerror(error)); 831e979c658Sreinoud exit(1); 832e979c658Sreinoud } 833e979c658Sreinoud 834e979c658Sreinoud printf("\nDevice identifies itself as : "); 835e979c658Sreinoud 836e979c658Sreinoud if (saddr.type == USCSI_TYPE_SCSI) { 837e979c658Sreinoud printf("SCSI busnum = %d, target = %d, lun = %d\n", 838e979c658Sreinoud saddr.addr.scsi.scbus, saddr.addr.scsi.target, 839e979c658Sreinoud saddr.addr.scsi.lun); 840e979c658Sreinoud } else { 841e979c658Sreinoud printf("ATAPI busnum = %d, drive = %d\n", 842e979c658Sreinoud saddr.addr.atapi.atbus, saddr.addr.atapi.drive); 843e979c658Sreinoud } 844e979c658Sreinoud 845e979c658Sreinoud printf("\n"); 846e979c658Sreinoud 847e979c658Sreinoud /* get MMC profile */ 848e979c658Sreinoud error = uscsi_get_mmc_profile(&dev, &mmc_profile); 849e979c658Sreinoud if (error) { 850e979c658Sreinoud fprintf(stderr, 851e979c658Sreinoud "Can't get the disc's MMC profile because of :" 852e979c658Sreinoud " %s\n", strerror(error)); 853e979c658Sreinoud fprintf(stderr, "aborting\n"); 854e979c658Sreinoud uscsi_close(&dev); 855e979c658Sreinoud return 1; 856e979c658Sreinoud } 857e979c658Sreinoud 858e979c658Sreinoud /* blank disc section */ 859e979c658Sreinoud if (blank) { 860e979c658Sreinoud printf("\nBlanking disc.... "); fflush(stdout); 861e979c658Sreinoud error = uscsi_blank_disc(&dev); 862e979c658Sreinoud 863e979c658Sreinoud if (error) { 864e979c658Sreinoud printf("fail\n"); fflush(stdout); 865e979c658Sreinoud fprintf(stderr, 866e979c658Sreinoud "Blanking failed because of : %s\n", 867e979c658Sreinoud strerror(error)); 868e979c658Sreinoud uscsi_close(&dev); 869e979c658Sreinoud 870e979c658Sreinoud return 1; 871e979c658Sreinoud } else { 872e979c658Sreinoud printf("success!\n\n"); 873e979c658Sreinoud } 874e979c658Sreinoud } 875e979c658Sreinoud 876e979c658Sreinoud /* re-get MMC profile */ 877e979c658Sreinoud error = uscsi_get_mmc_profile(&dev, &mmc_profile); 878e979c658Sreinoud if (error) { 879e979c658Sreinoud fprintf(stderr, 880e979c658Sreinoud "Can't get the disc's MMC profile because of : %s\n", 881e979c658Sreinoud strerror(error)); 882e979c658Sreinoud fprintf(stderr, "aborting\n"); 883e979c658Sreinoud uscsi_close(&dev); 884e979c658Sreinoud return 1; 885e979c658Sreinoud } 886e979c658Sreinoud 887e979c658Sreinoud error = get_format_capabilities(&dev, caps, &caps_len); 888e979c658Sreinoud if (error) 889e979c658Sreinoud exit(1); 890e979c658Sreinoud 891e979c658Sreinoud process_format_caps(caps, caps_len, inquiry, allow, blks, params); 892e979c658Sreinoud 893e979c658Sreinoud format_type = 0; 894e979c658Sreinoud /* expert format section */ 895e979c658Sreinoud if (expert) { 896e979c658Sreinoud } 897e979c658Sreinoud 898e979c658Sreinoud if (!format && !grow_spare && !grow_session) { 899e979c658Sreinoud /* we're done */ 900e979c658Sreinoud if (display_usage) 901e979c658Sreinoud usage(progname); 902e979c658Sreinoud uscsi_close(&dev); 903e979c658Sreinoud exit(0); 904e979c658Sreinoud } 905e979c658Sreinoud 906e979c658Sreinoud /* normal format section */ 907e979c658Sreinoud if (format) { 908e979c658Sreinoud /* get current mmc profile of disc */ 909e979c658Sreinoud 910e979c658Sreinoud if (oldtimer && mmc_profile != 0x0a) { 911e979c658Sreinoud printf("Oldtimer flag only defined for CD-RW; " 912e979c658Sreinoud "ignored\n"); 913e979c658Sreinoud } 914e979c658Sreinoud 915e979c658Sreinoud switch (mmc_profile) { 916e979c658Sreinoud case 0x12 : /* DVD-RAM */ 917e979c658Sreinoud format_type = 0x00; 918e979c658Sreinoud break; 919e979c658Sreinoud case 0x0a : /* CD-RW */ 920e979c658Sreinoud format_type = mrw ? 0x24 : 0x10; 921e979c658Sreinoud packet_wr = 1; 922e979c658Sreinoud break; 923e979c658Sreinoud case 0x13 : /* DVD-RW restricted overwrite */ 924e979c658Sreinoud case 0x14 : /* DVD-RW sequential */ 925e979c658Sreinoud format_type = 0x10; 926e979c658Sreinoud /* 927e979c658Sreinoud * Some drives suddenly stop supporting this format 928e979c658Sreinoud * type when packet_wr = 1 929e979c658Sreinoud */ 930e979c658Sreinoud packet_wr = 0; 931e979c658Sreinoud break; 932e979c658Sreinoud case 0x1a : /* DVD+RW */ 933e979c658Sreinoud format_type = mrw ? 0x24 : 0x26; 934e979c658Sreinoud break; 935e979c658Sreinoud case 0x43 : /* BD-RE */ 936e979c658Sreinoud format_type = spare ? 0x30 : 0x31; 937e979c658Sreinoud break; 938e979c658Sreinoud default : 939e979c658Sreinoud fprintf(stderr, "Can't format discs of type %s\n", 940e979c658Sreinoud print_mmc_profile(mmc_profile)); 941e979c658Sreinoud uscsi_close(&dev); 942e979c658Sreinoud exit(1); 943e979c658Sreinoud } 944e979c658Sreinoud } 945e979c658Sreinoud 946e979c658Sreinoud if (grow_spare) { 947e979c658Sreinoud switch (mmc_profile) { 948e979c658Sreinoud case 0x12 : /* DVD-RAM */ 949e979c658Sreinoud case 0x43 : /* BD-RE */ 950e979c658Sreinoud format_type = 0x01; 951e979c658Sreinoud break; 952e979c658Sreinoud default : 953e979c658Sreinoud fprintf(stderr, 954e979c658Sreinoud "Can't grow spare area for discs of type %s\n", 955e979c658Sreinoud print_mmc_profile(mmc_profile)); 956e979c658Sreinoud uscsi_close(&dev); 957e979c658Sreinoud exit(1); 958e979c658Sreinoud } 959e979c658Sreinoud } 960e979c658Sreinoud 961e979c658Sreinoud if (grow_session) { 962e979c658Sreinoud switch (mmc_profile) { 963e979c658Sreinoud case 0x0a : /* CD-RW */ 964e979c658Sreinoud format_type = 0x11; 965e979c658Sreinoud break; 966e979c658Sreinoud case 0x13 : /* DVD-RW restricted overwrite */ 967e979c658Sreinoud case 0x14 : /* DVD-RW sequential ? */ 968e979c658Sreinoud format_type = 0x13; 969e979c658Sreinoud break; 970e979c658Sreinoud default : 971e979c658Sreinoud uscsi_close(&dev); 972e979c658Sreinoud fprintf(stderr, 973e979c658Sreinoud "Can't grow session for discs of type %s\n", 974e979c658Sreinoud print_mmc_profile(mmc_profile)); 975e979c658Sreinoud exit(1); 976e979c658Sreinoud } 977e979c658Sreinoud } 978e979c658Sreinoud 979e979c658Sreinoud /* check if format type is allowed */ 980e979c658Sreinoud format_blks = blks[format_type]; 981e979c658Sreinoud format_param = params[format_type]; 982e979c658Sreinoud if (!allow[format_type]) { 983e979c658Sreinoud if (!inquiry) 984e979c658Sreinoud process_format_caps(caps, caps_len, 1, allow, 985e979c658Sreinoud blks, params); 986e979c658Sreinoud 987e979c658Sreinoud printf("\n"); 988e979c658Sreinoud fflush(stdout); 989e979c658Sreinoud fprintf(stderr, 990e979c658Sreinoud "Drive indicates it can't format with deduced format " 991e979c658Sreinoud "type 0x%02x\n", format_type); 992e979c658Sreinoud uscsi_close(&dev); 993e979c658Sreinoud exit(1); 994e979c658Sreinoud } 995e979c658Sreinoud 996e979c658Sreinoud if (restart_format && !((mmc_profile == 0x1a) || (format_type == 0x24))) 997e979c658Sreinoud { 998e979c658Sreinoud fprintf(stderr, 999e979c658Sreinoud "Format restarting only for MRW formats or DVD+RW " 1000e979c658Sreinoud "formats\n"); 1001e979c658Sreinoud uscsi_close(&dev); 1002e979c658Sreinoud exit(1); 1003e979c658Sreinoud } 1004e979c658Sreinoud 1005e979c658Sreinoud if (restart_format && !wait_until_finished) { 1006e979c658Sreinoud printf( "Warning : format restarting without waiting for it be " 1007e979c658Sreinoud "finished is prolly not handy\n"); 1008e979c658Sreinoud } 1009e979c658Sreinoud 1010e979c658Sreinoud /* explicitly select packet write just in case */ 1011e979c658Sreinoud if (packet_wr) { 1012e979c658Sreinoud printf("Explicitly setting packet type and blocking number\n"); 1013e979c658Sreinoud error = uscsi_set_packet_parameters(&dev, blockingnr); 1014e979c658Sreinoud if (error) { 1015e979c658Sreinoud fprintf(stderr, 1016e979c658Sreinoud "Can't set packet writing and blocking number: " 1017e979c658Sreinoud "%s\n", strerror(error)); 1018e979c658Sreinoud uscsi_close(&dev); 1019e979c658Sreinoud exit(1); 1020e979c658Sreinoud } 1021e979c658Sreinoud } 1022e979c658Sreinoud 1023e979c658Sreinoud /* determine if formatting is done in the background */ 1024e979c658Sreinoud background = 0; 1025e979c658Sreinoud if (format_type == 0x24) background = 1; 1026e979c658Sreinoud if (format_type == 0x26) background = 1; 1027e979c658Sreinoud 1028e979c658Sreinoud /* special case format type 0x24 : MRW */ 1029e979c658Sreinoud if (format_type == 0x24) { 1030e979c658Sreinoud format_blks = spare ? 0xffff0000 : 0xffffffff; 1031e979c658Sreinoud format_param = restart_format; 1032e979c658Sreinoud } 1033e979c658Sreinoud /* special case format type 0x26 : DVD+RW */ 1034e979c658Sreinoud if (format_type == 0x26) { 1035e979c658Sreinoud format_param = restart_format; 1036e979c658Sreinoud } 1037e979c658Sreinoud 1038e979c658Sreinoud /* verbose to the user */ 1039e979c658Sreinoud DEBUG( 1040e979c658Sreinoud printf("Actual format selected: " 1041e979c658Sreinoud "format_type 0x%02x, blks %d, param %d, " 1042e979c658Sreinoud "certification %d, cmplist %d\n", 1043e979c658Sreinoud format_type, format_blks, format_param, 1044e979c658Sreinoud certification, cmplist); 1045e979c658Sreinoud ); 1046e979c658Sreinoud printf("\nFormatting.... "); fflush(stdout); 1047e979c658Sreinoud 1048e979c658Sreinoud /* formatting time! */ 1049e979c658Sreinoud if (oldtimer) { 1050e979c658Sreinoud error = uscsi_format_cdrw_mode7(&dev, format_blks); 1051e979c658Sreinoud background = 0; 1052e979c658Sreinoud } else { 1053e979c658Sreinoud error = uscsi_format_disc(&dev, !background, format_type, 1054e979c658Sreinoud format_blks, format_param, certification, 1055e979c658Sreinoud cmplist); 1056e979c658Sreinoud } 1057e979c658Sreinoud 1058e979c658Sreinoud /* what now? */ 1059e979c658Sreinoud if (error) { 1060e979c658Sreinoud printf("fail\n"); fflush(stdout); 1061e979c658Sreinoud fprintf(stderr, "Formatting failed because of : %s\n", 1062e979c658Sreinoud strerror(error)); 1063e979c658Sreinoud } else { 1064e979c658Sreinoud if (background) { 1065e979c658Sreinoud printf("background formatting in progress\n"); 1066e979c658Sreinoud if (wait_until_finished) { 1067e979c658Sreinoud printf("Waiting for completion ... "); 1068e979c658Sreinoud uscsi_waitop(&dev); 1069e979c658Sreinoud } 1070e979c658Sreinoud /* explicitly do NOT close disc ... (for now) */ 1071e979c658Sreinoud return 0; 1072e979c658Sreinoud } else { 1073e979c658Sreinoud printf("success!\n\n"); 1074e979c658Sreinoud } 1075e979c658Sreinoud } 1076e979c658Sreinoud 1077e979c658Sreinoud /* finish up */ 1078e979c658Sreinoud uscsi_close(&dev); 1079e979c658Sreinoud 1080e979c658Sreinoud return error; 1081e979c658Sreinoud } 1082e979c658Sreinoud 1083