~ubuntu-branches/ubuntu/intrepid/sg3-utils/intrepid

« back to all changes in this revision

Viewing changes to sg_format.c

  • Committer: Bazaar Package Importer
  • Author(s): Luk Claes
  • Date: 2006-11-05 17:23:29 UTC
  • mfrom: (1.1.4 upstream) (3.1.2 edgy)
  • Revision ID: james.westby@ubuntu.com-20061105172329-l4loha00sk36qz6k
* Non-maintainer upload.
* Fix FTBFS due to old syscall usage (Closes: #395512).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** sg_format : format a SCSI disk
 
3
**             potentially with a different number of blocks and block size
 
4
**
 
5
** formerly called blk512-linux.c (v0.4)
 
6
**
 
7
** Copyright (C) 2003  Grant Grundler    grundler at parisc-linux dot org
 
8
** Copyright (C) 2003  James Bottomley       jejb at parisc-linux dot org
 
9
** Copyright (C) 2005-2006  Douglas Gilbert   dgilbert at interlog dot com
 
10
**
 
11
**   This program is free software; you can redistribute it and/or modify
 
12
**   it under the terms of the GNU General Public License as published by
 
13
**   the Free Software Foundation; either version 2, or (at your option)
 
14
**   any later version.
 
15
**
 
16
** http://www.t10.org/scsi-3.htm
 
17
** http://www.tldp.org/HOWTO/SCSI-Generic-HOWTO
 
18
**
 
19
**
 
20
**  List of some (older) disk manufacturers' block counts.
 
21
**  These are not needed in newer disks which will automatically use
 
22
**  the manufacturers' recommended block count if a count of -1 is given.
 
23
**      Inquiry         Block Count (@512 byte blocks)
 
24
**      ST150150N       8388315
 
25
**      IBM_DCHS04F     8888543
 
26
**      IBM_DGHS09Y     17916240
 
27
**      ST336704FC      71132960
 
28
**      ST318304FC      35145034  (Factory spec is 35885167 sectors)
 
29
**      ST336605FC      ???
 
30
**      ST336753FC      71132960  (Factory spec is 71687372 sectors) 
 
31
*/
 
32
 
 
33
#include <stdio.h>
 
34
#include <stdlib.h>
 
35
#include <string.h>
 
36
#include <getopt.h>
 
37
#include <unistd.h>
 
38
 
 
39
#include "sg_lib.h"
 
40
#include "sg_cmds.h"
 
41
 
 
42
 
 
43
#define RW_ERROR_RECOVERY_PAGE 1  /* every disk should have one */
 
44
#define FORMAT_DEV_PAGE 3         /* Format Device Mode Page [now obsolete] */
 
45
#define CONTROL_MODE_PAGE 0xa     /* alternative page all devices have?? */
 
46
 
 
47
#define SHORT_TIMEOUT           20   /* 20 seconds unless immed=0 ... */
 
48
#define FORMAT_TIMEOUT          (4 * 3600)       /* 4 hours ! */
 
49
 
 
50
#define POLL_DURATION_SECS 30
 
51
 
 
52
 
 
53
#define MAX_BUFF_SZ     252
 
54
static unsigned char dbuff[MAX_BUFF_SZ];
 
55
 
 
56
static char * version_str = "1.09 20060623";
 
57
 
 
58
static struct option long_options[] = {
 
59
        {"count", 1, 0, 'c'},
 
60
        {"early", 0, 0, 'e'},
 
61
        {"format", 0, 0, 'F'},
 
62
        {"help", 0, 0, 'h'},
 
63
        {"long", 0, 0, 'l'},
 
64
        {"pinfo", 0, 0, 'p'},
 
65
        {"resize", 0, 0, 'r'},
 
66
        {"rto_req", 0, 0, 'R'},
 
67
        {"six", 0, 0, '6'},
 
68
        {"size", 1, 0, 's'},
 
69
        {"verbose", 0, 0, 'v'},
 
70
        {"version", 0, 0, 'V'},
 
71
        {"wait", 0, 0, 'w'},
 
72
        {0, 0, 0, 0},
 
73
};
 
74
 
 
75
/* Return 0 on success, else see sg_ll_format_unit() */
 
76
static int
 
77
scsi_format(int fd, int pinfo, int rto_req, int immed, int early, int verbose)
 
78
{
 
79
        int res;
 
80
        const char FORMAT_HEADER_SIZE = 4;
 
81
        unsigned char fmt_hdr[FORMAT_HEADER_SIZE];
 
82
 
 
83
        /* fmt_hdr is a short format header, only used when 'immed' is set */
 
84
        fmt_hdr[0] = 0;         /* reserved */
 
85
        fmt_hdr[1] = 0x2;       /* use device defaults, IMMED return */
 
86
        fmt_hdr[2] = 0;         /* defect list length MSB */
 
87
        fmt_hdr[3] = 0;         /* defect list length LSB */
 
88
 
 
89
        res = sg_ll_format_unit(fd, pinfo, rto_req, 0 /* longlist */,
 
90
                                (!! immed) /* fmtdata */, 0 /* cmplist */,
 
91
                                0 /* dlist_format */,
 
92
                                (immed ? SHORT_TIMEOUT : FORMAT_TIMEOUT),
 
93
                                fmt_hdr, (immed ? sizeof(fmt_hdr) : 0),
 
94
                                1, verbose);
 
95
 
 
96
        switch (res) {
 
97
        case 0:
 
98
                break;
 
99
        case SG_LIB_CAT_NOT_READY:
 
100
                fprintf(stderr, "Format command, device not ready\n");
 
101
                break;
 
102
        case SG_LIB_CAT_INVALID_OP:
 
103
                fprintf(stderr, "Format command not supported\n");
 
104
                break;
 
105
        case SG_LIB_CAT_ILLEGAL_REQ:
 
106
                fprintf(stderr, "Format command, illegal parameter\n");
 
107
                break;
 
108
        case SG_LIB_CAT_UNIT_ATTENTION:
 
109
                fprintf(stderr, "Format command, unit attention\n");
 
110
                break;
 
111
        default:
 
112
                fprintf(stderr, "Format command failed\n");
 
113
                break;
 
114
        }
 
115
        if (res)
 
116
                return res;
 
117
 
 
118
        if (! immed)
 
119
                return 0;
 
120
 
 
121
        printf("\nFormat has started\n");
 
122
        if (early) {
 
123
                if (immed)
 
124
                        printf("Format continuing, request sense or test "
 
125
                               "unit ready can be used to monitor progress\n");
 
126
                return 0;
 
127
        }
 
128
 
 
129
        for(;;) {
 
130
                int progress;
 
131
 
 
132
                sleep(POLL_DURATION_SECS);
 
133
                progress = -1;
 
134
                res = sg_ll_test_unit_ready_progress(fd, 0, &progress, 0,
 
135
                                                      verbose);
 
136
                if (progress >= 0)
 
137
                        printf("Format in progress, %d%% done\n",
 
138
                                (progress * 100) / 65536);
 
139
                else
 
140
                        break;
 
141
        }
 
142
        printf("FORMAT Complete\n");
 
143
        return 0;
 
144
}
 
145
 
 
146
#define RCAP_REPLY_LEN 32
 
147
 
 
148
static int
 
149
print_read_cap(int fd, int do_16, int verbose)
 
150
{
 
151
        int res, k;
 
152
        unsigned char resp_buff[RCAP_REPLY_LEN];
 
153
        unsigned int last_blk_addr, block_size;
 
154
        unsigned long long llast_blk_addr;
 
155
 
 
156
        if (do_16) {
 
157
                res = sg_ll_readcap_16(fd, 0 /* pmi */, 0 /* llba */,
 
158
                                       resp_buff, 32, 0, verbose);
 
159
                if (0 == res) {
 
160
                        for (k = 0, llast_blk_addr = 0; k < 8; ++k) {
 
161
                                llast_blk_addr <<= 8;
 
162
                                llast_blk_addr |= resp_buff[k];
 
163
                        }
 
164
                        block_size = ((resp_buff[8] << 24) |
 
165
                                      (resp_buff[9] << 16) |
 
166
                                      (resp_buff[10] << 8) |
 
167
                                      resp_buff[11]);
 
168
                        printf("Read Capacity (16) results:\n");
 
169
                        printf("   Protection: prot_en=%d, rto_en=%d\n",
 
170
                               !!(resp_buff[12] & 0x1),
 
171
                               !!(resp_buff[12] & 0x2));
 
172
                        printf("   Number of blocks=%llu\n",
 
173
                               llast_blk_addr + 1);
 
174
                        printf("   Block size=%u bytes\n", block_size);
 
175
                        return (int)block_size;
 
176
                }
 
177
        } else {
 
178
                res = sg_ll_readcap_10(fd, 0 /* pmi */, 0 /* lba */,
 
179
                                       resp_buff, 8, 0, verbose);
 
180
                if (0 == res) {
 
181
                        last_blk_addr = ((resp_buff[0] << 24) |
 
182
                                         (resp_buff[1] << 16) |
 
183
                                         (resp_buff[2] << 8) |
 
184
                                         resp_buff[3]);
 
185
                        block_size = ((resp_buff[4] << 24) |
 
186
                                      (resp_buff[5] << 16) |
 
187
                                      (resp_buff[6] << 8) |
 
188
                                      resp_buff[7]);
 
189
                        printf("Read Capacity (10) results:\n");
 
190
                        printf("   Number of blocks=%u\n", 
 
191
                               last_blk_addr + 1);
 
192
                        printf("   Block size=%u bytes\n", block_size);
 
193
                        return (int)block_size;
 
194
                }
 
195
        }
 
196
        if (SG_LIB_CAT_NOT_READY == res) 
 
197
                fprintf(stderr, "READ CAPACITY (%d): device not ready\n",
 
198
                        (do_16 ? 16 : 10));
 
199
        else if (SG_LIB_CAT_INVALID_OP == res) 
 
200
                fprintf(stderr, "READ CAPACITY (%d) not supported\n",
 
201
                        (do_16 ? 16 : 10));
 
202
        else if (SG_LIB_CAT_ILLEGAL_REQ == res)
 
203
                fprintf(stderr, "bad field in READ CAPACITY (%d) "
 
204
                        "cdb\n", (do_16 ? 16 : 10));
 
205
        else if (verbose)
 
206
                fprintf(stderr, "READ CAPACITY (%d) failed "
 
207
                        "[res=%d]\n", (do_16 ? 16 : 10), res);
 
208
        return -1;
 
209
}
 
210
 
 
211
static void usage()
 
212
{
 
213
        printf("usage: sg_format [--count=<block count>] [--early] [--format]"
 
214
                " [--help]\n"
 
215
                "                 [--long] [--pinfo] [--resize] [--rto_req] "
 
216
                "[--six]\n"
 
217
                "                 [--size=<block size>] [--verbose]"
 
218
                " [--version] [--wait]\n"
 
219
                "                 <scsi_disk>\n"
 
220
                "  where:\n"
 
221
                "    --count=<block count> | -c <block count>\n"
 
222
                "                   best left alone during format (defaults "
 
223
                "to max allowable)\n"
 
224
                "    --early | -e   exit once format started (user can "
 
225
                "monitor progress)\n"
 
226
                "    --format | -F  format unit (default report current count"
 
227
                " and size)\n"
 
228
                "    --help | -h    prints out this usage message\n"
 
229
                "    --long | -l    allow for 64 bit lbas (default: assume "
 
230
                "32 bit lbas)\n"
 
231
                "    --pinfo | -p   set the FMTPINFO bit to format with "
 
232
                "protection\n");
 
233
        printf( "                   information (defaults to no protection "
 
234
                "information)\n"
 
235
                "    --resize | -r  resize (rather than format) to '--count' "
 
236
                "value\n"
 
237
                "    --rto_req | -R  set the RTO_REQ bit in format (only valid "
 
238
                "with '--pinfo')\n"
 
239
                "    --six | -6      use 6 byte MODE SENSE/SELECT\n"
 
240
                "    --size=<block size> | -s <block size>\n"
 
241
                "                   only needed to change block size"
 
242
                " (default to\n"
 
243
                "                   current device's block size)\n"
 
244
                "    --verbose | -v verbosity (show commands + parameters "
 
245
                "sent)\n"
 
246
                "                   use multiple time for more verbosity\n"
 
247
                "    --version | -V print version details and exit\n"
 
248
                "    --wait | -w    format command waits till complete (def: "
 
249
                "poll)\n\n"
 
250
                "\tExample: sg_format --format /dev/sdc\n\n"
 
251
                "This utility formats or resizes SCSI disks.\n");
 
252
        printf("WARNING: This utility will destroy all the data on the "
 
253
                "target device when\n\t '--format' is given. Check that you "
 
254
                "have the correct device.\n");
 
255
}
 
256
 
 
257
 
 
258
int main(int argc, char **argv)
 
259
{
 
260
        const int mode_page = RW_ERROR_RECOVERY_PAGE;
 
261
        int fd, res, calc_len, bd_len, dev_specific_param;
 
262
        int offset, j, bd_blk_len, prob, len;
 
263
        unsigned long long ull;
 
264
        long long blk_count = 0;  /* -c value */
 
265
        int blk_size = 0;     /* -s value */
 
266
        int format = 0;         /* -F */
 
267
        int resize = 0;         /* -r */
 
268
        int verbose = 0;        /* -v */
 
269
        int fwait = 0;          /* -w */
 
270
        int mode6 = 0;
 
271
        int pinfo = 0;
 
272
        int rto_req = 0;
 
273
        int do_rcap16 = 0;
 
274
        int long_lba = 0;
 
275
        int early = 0;
 
276
        char device_name[256];
 
277
        char pdt_name[64];
 
278
        struct sg_simple_inquiry_resp inq_out;
 
279
        int ret = 0;
 
280
 
 
281
        device_name[0] = '\0';
 
282
        while (1) {
 
283
                int option_index = 0;
 
284
                int c;
 
285
 
 
286
                c = getopt_long(argc, argv, "c:eFhlprRs:vVw6",
 
287
                                long_options, &option_index);
 
288
                if (c == -1)
 
289
                        break;
 
290
 
 
291
                switch (c) {
 
292
                case 'c':
 
293
                        if (0 == strcmp("-1", optarg))
 
294
                                blk_count = -1;
 
295
                        else {
 
296
                                blk_count = sg_get_llnum(optarg);
 
297
                                if (-1 == blk_count) {
 
298
                                        fprintf(stderr, "bad argument to "
 
299
                                                "'--count'\n");
 
300
                                        return SG_LIB_SYNTAX_ERROR;
 
301
                                }
 
302
                        }
 
303
                        break;
 
304
                case 'e':
 
305
                        early = 1;
 
306
                        break;
 
307
                case 'F':
 
308
                        format = 1;
 
309
                        break;
 
310
                case 'h':
 
311
                        usage();
 
312
                        return 0;
 
313
                case 'l':
 
314
                        long_lba = 1;
 
315
                        do_rcap16 = 1;
 
316
                        break;
 
317
                case 'p':
 
318
                        pinfo = 1;
 
319
                        break;
 
320
                case 'r':
 
321
                        resize = 1;
 
322
                        break;
 
323
                case 'R':
 
324
                        rto_req = 1;
 
325
                        break;
 
326
                case 's':
 
327
                        blk_size = sg_get_num(optarg);
 
328
                        if (blk_size <= 0) {
 
329
                                fprintf(stderr, "bad argument to '--size', "
 
330
                                        "want arg > 0)\n");
 
331
                                return SG_LIB_SYNTAX_ERROR;
 
332
                        }
 
333
                        break;
 
334
                case 'v':
 
335
                        verbose++;
 
336
                        break;
 
337
                case 'V':
 
338
                        fprintf(stderr, "sg_format version: %s\n",
 
339
                                version_str);
 
340
                        return 0;
 
341
                case 'w':
 
342
                        fwait = 1;
 
343
                        break;
 
344
                case '6':
 
345
                        mode6 = 1;
 
346
                        break;
 
347
                default:
 
348
                        usage();
 
349
                        return SG_LIB_SYNTAX_ERROR;
 
350
                }
 
351
        }
 
352
        if (optind < argc) {
 
353
                if ('\0' == device_name[0]) {
 
354
                        strncpy(device_name, argv[optind],
 
355
                                sizeof(device_name) - 1);
 
356
                        device_name[sizeof(device_name) - 1] = '\0';
 
357
                        ++optind;
 
358
                }
 
359
        }
 
360
        if (optind < argc) {
 
361
                for (; optind < argc; ++optind)
 
362
                        fprintf(stderr, "Unexpected extra argument: %s\n",
 
363
                                argv[optind]);
 
364
                usage();
 
365
                return SG_LIB_SYNTAX_ERROR;
 
366
        }
 
367
        if ('\0' == device_name[0]) {
 
368
                fprintf(stderr, "no device name given\n");
 
369
                usage();
 
370
                return SG_LIB_SYNTAX_ERROR;
 
371
        }
 
372
        if (resize) {
 
373
                if (format) {
 
374
                        fprintf(stderr, "both '--format' and '--resize'"
 
375
                                "not permitted\n");
 
376
                        usage();
 
377
                        return SG_LIB_SYNTAX_ERROR;
 
378
                } else if (0 == blk_count) {
 
379
                        fprintf(stderr, "'--resize' needs a '--count' (other"
 
380
                                " than 0)\n");
 
381
                        usage();
 
382
                        return SG_LIB_SYNTAX_ERROR;
 
383
                } else if (0 != blk_size) {
 
384
                        fprintf(stderr, "'--resize' not compatible with "
 
385
                                "'--size')\n");
 
386
                        usage();
 
387
                        return SG_LIB_SYNTAX_ERROR;
 
388
                }
 
389
        }
 
390
 
 
391
        /* FIXME: add more sanity checks:
 
392
        ** o block size/count might already be set...don't repeat
 
393
        ** o verify SCSI device is a disk (get inquiry data first)
 
394
        */
 
395
 
 
396
        if ((fd = sg_cmds_open_device(device_name, 0 /* rw */, verbose)) < 0) {
 
397
                fprintf(stderr, "error opening device file: %s: %s\n",
 
398
                        device_name, safe_strerror(-fd));
 
399
                return SG_LIB_FILE_ERROR;
 
400
        }
 
401
 
 
402
        if (sg_simple_inquiry(fd, &inq_out, 1, verbose)) {
 
403
                fprintf(stderr, "%s doesn't respond to a SCSI INQUIRY\n",
 
404
                        device_name);
 
405
                ret = SG_LIB_CAT_OTHER;
 
406
                goto out;
 
407
        }
 
408
        printf("    %.8s  %.16s  %.4s   peripheral_type: %s [0x%x]\n",
 
409
               inq_out.vendor, inq_out.product, inq_out.revision,
 
410
               sg_get_pdt_str(inq_out.peripheral_type, sizeof(pdt_name),
 
411
                              pdt_name),
 
412
               inq_out.peripheral_type);
 
413
        if (verbose)
 
414
                printf("      PROTECT=%d\n", !!(inq_out.byte_5 & 1));
 
415
        if (inq_out.byte_5 & 1)
 
416
                printf("      << supports 'protection information'>>\n");
 
417
 
 
418
        if ((0 != inq_out.peripheral_type) &&
 
419
            (0xe != inq_out.peripheral_type)) {
 
420
                fprintf(stderr, "This format is only defined for disks "
 
421
                        "(using SBC-2 or RBC)\n");
 
422
                ret = SG_LIB_CAT_MALFORMED;
 
423
                goto out;
 
424
        }
 
425
 
 
426
        memset(dbuff, 0, MAX_BUFF_SZ);
 
427
        if (mode6)
 
428
                res = sg_ll_mode_sense6(fd, 0 /* DBD */, 0 /* current */,
 
429
                                        mode_page, 0 /* subpage */, dbuff,
 
430
                                        MAX_BUFF_SZ, 1, verbose);
 
431
        else
 
432
                res = sg_ll_mode_sense10(fd, long_lba, 0 /* DBD */,
 
433
                                         0 /* current */, mode_page,
 
434
                                         0 /* subpage */, dbuff,
 
435
                                         MAX_BUFF_SZ, 1, verbose);
 
436
        ret = res;
 
437
        if (res) {
 
438
                if (SG_LIB_CAT_NOT_READY == res)
 
439
                        fprintf(stderr, "MODE SENSE (%d) command, device "
 
440
                                "not ready\n", (mode6 ? 6 : 10));
 
441
                else if (SG_LIB_CAT_UNIT_ATTENTION == res)
 
442
                        fprintf(stderr, "MODE SENSE (%d) command, unit "
 
443
                                "attention\n", (mode6 ? 6 : 10));
 
444
                else if (SG_LIB_CAT_INVALID_OP == res) {
 
445
                        fprintf(stderr, "MODE SENSE (%d) command is not "
 
446
                                "supported\n", (mode6 ? 6 : 10));
 
447
                        fprintf(stderr, "    try again %s the '--six' "
 
448
                                "option\n", (mode6 ? "without" : "with"));
 
449
        
 
450
                } else if (SG_LIB_CAT_ILLEGAL_REQ == res) {
 
451
                        if (long_lba && (! mode6)) 
 
452
                                fprintf(stderr, "bad field in MODE SENSE "
 
453
                                        "(%d) [longlba flag not supported?]"
 
454
                                        "\n", (mode6 ? 6 : 10));
 
455
                        else
 
456
                                fprintf(stderr, "bad field in MODE SENSE "
 
457
                                        "(%d) [mode_page %d not supported?]"
 
458
                                        "\n", (mode6 ? 6 : 10), mode_page);
 
459
                } else
 
460
                        fprintf(stderr, "MODE SENSE (%d) command failed\n",
 
461
                                (mode6 ? 6 : 10));
 
462
                        if (0 == verbose)
 
463
                                fprintf(stderr, "    try '-v' for more "
 
464
                                        "information\n");
 
465
                goto out;
 
466
        }
 
467
        if (mode6) {
 
468
                calc_len = dbuff[0] + 1;
 
469
                dev_specific_param = dbuff[2];
 
470
                bd_len = dbuff[3];
 
471
                long_lba = 0;
 
472
                offset = 4;
 
473
                /* prepare for mode select */
 
474
                dbuff[0] = 0;
 
475
                dbuff[1] = 0;
 
476
                dbuff[2] = 0;
 
477
        } else {
 
478
                calc_len = (dbuff[0] << 8) + dbuff[1] + 2;
 
479
                dev_specific_param = dbuff[3];
 
480
                bd_len = (dbuff[6] << 8) + dbuff[7];
 
481
                long_lba = (dbuff[4] & 1);
 
482
                offset = 8;
 
483
                /* prepare for mode select */
 
484
                dbuff[0] = 0;
 
485
                dbuff[1] = 0;
 
486
                dbuff[2] = 0;
 
487
                dbuff[3] = 0;
 
488
        }
 
489
        if ((offset + bd_len) < calc_len)
 
490
                dbuff[offset + bd_len] &= 0x7f;  /* clear PS bit in mpage */
 
491
        prob = 0;
 
492
        bd_blk_len = 0;
 
493
        printf("Mode sense (block descriptor) data, prior to changes:\n");
 
494
        if (dev_specific_param & 0x40)
 
495
                printf("  <<< Write Protect (WP) bit set >>>\n");
 
496
        if (bd_len > 0) {
 
497
                ull = 0;
 
498
                for (j = 0; j < (long_lba ? 8 : 4); ++j) {
 
499
                        if (j > 0)
 
500
                                ull <<= 8;
 
501
                        ull |= dbuff[offset + j];
 
502
                }
 
503
                if (long_lba)
 
504
                        bd_blk_len = (dbuff[offset + 12] << 24) +
 
505
                                     (dbuff[offset + 13] << 16) +
 
506
                                     (dbuff[offset + 14] << 8) +
 
507
                                     dbuff[offset + 15];
 
508
                else
 
509
                        bd_blk_len = (dbuff[offset + 5] << 16) +
 
510
                                     (dbuff[offset + 6] << 8) +
 
511
                                     dbuff[offset + 7];
 
512
                if (long_lba) {
 
513
                        printf("  <<< longlba flag set (64 bit lba) >>>\n");
 
514
                        if (bd_len != 16)
 
515
                                prob = 1;
 
516
                } else if (bd_len != 8)
 
517
                        prob = 1;
 
518
                printf("  Number of blocks=%llu [0x%llx]\n", ull, ull);
 
519
                printf("  Block size=%d [0x%x]\n", bd_blk_len, bd_blk_len);
 
520
        } else {
 
521
                printf("  No block descriptors present\n");
 
522
                prob = 1;
 
523
        }
 
524
        if (resize ||
 
525
            (format && ((blk_count != 0) ||
 
526
                        ((blk_size > 0) && (blk_size != bd_blk_len))))) {
 
527
                /* want to run MODE SELECT */
 
528
 
 
529
/* Working Draft SCSI Primary Commands - 3 (SPC-3)    pg 255
 
530
**
 
531
** If the SCSI device doesn't support changing its capacity by changing
 
532
** the NUMBER OF BLOCKS field using the MODE SELECT command, the value
 
533
** in the NUMBER OF BLOCKS field is ignored. If the device supports changing
 
534
** its capacity by changing the NUMBER OF BLOCKS field, then the
 
535
** NUMBER OF BLOCKS field is interpreted as follows:
 
536
**      a) If the number of blocks is set to zero, the device shall retain
 
537
**         its current capacity if the block size has not changed. If the
 
538
**         number of blocks is set to zero and the block size has changed,
 
539
**         the device shall be set to its maximum capacity when the new
 
540
**         block size takes effect;
 
541
**
 
542
**      b) If the number of blocks is greater than zero and less than or
 
543
**         equal to its maximum capacity, the device shall be set to that
 
544
**         number of blocks. If the block size has not changed, the device
 
545
**         shall not become format corrupted. This capacity setting shall be
 
546
**         retained through power cycles, hard resets, logical unit resets,
 
547
**         and I_T nexus losses;
 
548
**
 
549
**      c) If the number of blocks field is set to a value greater than the
 
550
**         maximum capacity of the device and less than FFFF FFFFh, then the
 
551
**         command is terminated with a CHECK CONDITION status. The sense key
 
552
**         is set to ILLEGAL REQUEST. The device shall retain its previous
 
553
**         block descriptor settings; or
 
554
**
 
555
**      d) If the number of blocks is set to FFFF FFFFh, the device shall be
 
556
**         set to its maximum capacity. If the block size has not changed,
 
557
**         the device shall not become format corrupted. This capacity setting
 
558
**         shall be retained through power cycles, hard resets, logical unit
 
559
**         resets, and I_T nexus losses.
 
560
*/
 
561
 
 
562
                if (prob) {
 
563
                        fprintf(stderr, "Need to perform MODE SELECT (to "
 
564
                                "change number or blocks or block length)\n");
 
565
                        fprintf(stderr, "but (single) block descriptor not "
 
566
                                "found in earlier MODE SENSE\n");
 
567
                        ret = SG_LIB_CAT_MALFORMED;
 
568
                        goto out;
 
569
                }
 
570
                if (blk_count != 0)  {
 
571
                        len = (long_lba ? 8 : 4);
 
572
                        for (j = 0; j < len; ++j)
 
573
                                dbuff[offset + j] =
 
574
                                    (blk_count >> ((len - j - 1) * 8)) & 0xff;
 
575
                } else if ((blk_size > 0) && (blk_size != bd_blk_len)) {
 
576
                        len = (long_lba ? 8 : 4);
 
577
                        for (j = 0; j < len; ++j)
 
578
                                dbuff[offset + j] = 0;
 
579
                }
 
580
                if ((blk_size > 0) && (blk_size != bd_blk_len)) {
 
581
                        if (long_lba) {
 
582
                                dbuff[offset + 12] = (blk_size >> 24) & 0xff;
 
583
                                dbuff[offset + 13] = (blk_size >> 16) & 0xff;
 
584
                                dbuff[offset + 14] = (blk_size >> 8) & 0xff;
 
585
                                dbuff[offset + 15] = blk_size & 0xff;
 
586
                        } else {
 
587
                                dbuff[offset + 5] = (blk_size >> 16) & 0xff;
 
588
                                dbuff[offset + 6] = (blk_size >> 8) & 0xff;
 
589
                                dbuff[offset + 7] = blk_size & 0xff;
 
590
                        }
 
591
                }
 
592
                if (mode6)
 
593
                        res = sg_ll_mode_select6(fd, 1 /* PF */, 1 /* SP */,
 
594
                                                 dbuff, calc_len, 1, verbose);
 
595
                else
 
596
                        res = sg_ll_mode_select10(fd, 1 /* PF */, 1 /* SP */,
 
597
                                                  dbuff, calc_len, 1, verbose);
 
598
                ret = res;
 
599
                if (res) {
 
600
                        if (SG_LIB_CAT_NOT_READY == res)
 
601
                                fprintf(stderr, "MODE SELECT command, "
 
602
                                        "device not ready\n");
 
603
                        else if (SG_LIB_CAT_UNIT_ATTENTION == res)
 
604
                                fprintf(stderr, "MODE SELECT command, "
 
605
                                        "unit attention\n");
 
606
                        else if (SG_LIB_CAT_INVALID_OP == res)
 
607
                                fprintf(stderr, "MODE SELECT (%d) command is "
 
608
                                        "not supported\n", (mode6 ? 6 : 10));
 
609
                        else if (SG_LIB_CAT_ILLEGAL_REQ == res)
 
610
                                fprintf(stderr, "bad field in MODE SELECT "
 
611
                                        "(%d)\n", (mode6 ? 6 : 10));
 
612
                        else
 
613
                                fprintf(stderr, "MODE SELECT (%d) command "
 
614
                                        "failed\n", (mode6 ? 6 : 10));
 
615
                        if (0 == verbose)
 
616
                                fprintf(stderr, "    try '-v' for "
 
617
                                        "more information\n");
 
618
                        goto out;
 
619
                }
 
620
        }
 
621
        if (resize) {
 
622
                printf("Resize operation seems to have been successful\n");
 
623
                goto out;
 
624
        }
 
625
        else if (! format) {
 
626
                res = print_read_cap(fd, do_rcap16, verbose);
 
627
                if (res < 0)
 
628
                        ret = -1;
 
629
                if ((res > 0) && (bd_blk_len > 0) &&
 
630
                    (res != (int)bd_blk_len)) {
 
631
                        printf("  Warning: mode sense and read capacity "
 
632
                               "report different block sizes [%d,%d]\n",
 
633
                               bd_blk_len, res);
 
634
                        printf("           Probably needs format\n");
 
635
                }
 
636
                printf("No changes made. To format use '--format'. To "
 
637
                       "resize use '--resize'\n");
 
638
                goto out;
 
639
        }
 
640
 
 
641
        if(format)
 
642
#if 1
 
643
                printf("\nA FORMAT will commence in 10 seconds\n");
 
644
                printf("    ALL data on %s will be DESTROYED\n", device_name);
 
645
                printf("        Press control-C to abort\n");
 
646
                sleep(5);
 
647
                printf("A FORMAT will commence in 5 seconds\n");
 
648
                printf("    ALL data on %s will be DESTROYED\n", device_name);
 
649
                printf("        Press control-C to abort\n");
 
650
                sleep(5);
 
651
                res = scsi_format(fd, pinfo, rto_req, ! fwait, early,
 
652
                                  verbose);
 
653
                ret = res;
 
654
                if (res) {
 
655
                        fprintf(stderr, "FORMAT failed\n");
 
656
                        if (0 == verbose)
 
657
                                fprintf(stderr, "    try '-v' for more "
 
658
                                        "information\n");
 
659
                }
 
660
#else
 
661
                fprintf(stderr, "FORMAT ignored, testing\n");
 
662
#endif
 
663
 
 
664
out:
 
665
        res = sg_cmds_close_device(fd);
 
666
        if (res < 0) {
 
667
                fprintf(stderr, "close error: %s\n", safe_strerror(-res));
 
668
                if (0 == ret)
 
669
                        return SG_LIB_FILE_ERROR;
 
670
        }
 
671
        return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
 
672
}