xref: /onnv-gate/usr/src/cmd/format/menu_analyze.c (revision 9889:68d0fe4c716e)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57563SPrasad.Singamsetty@Sun.COM  * Common Development and Distribution License (the "License").
67563SPrasad.Singamsetty@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*9889SLarry.Liu@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * This file contains functions implementing the analyze menu commands.
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate #include <string.h>
300Sstevel@tonic-gate #include "global.h"
310Sstevel@tonic-gate #include "analyze.h"
320Sstevel@tonic-gate #include "misc.h"
330Sstevel@tonic-gate #include "menu_analyze.h"
340Sstevel@tonic-gate #include "param.h"
350Sstevel@tonic-gate 
360Sstevel@tonic-gate 
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate  * This routine implements the 'read' command.  It performs surface
400Sstevel@tonic-gate  * analysis by reading the disk.  It is ok to run this command on
410Sstevel@tonic-gate  * mounted file systems.
420Sstevel@tonic-gate  */
430Sstevel@tonic-gate int
a_read()440Sstevel@tonic-gate a_read()
450Sstevel@tonic-gate {
460Sstevel@tonic-gate 	/*
470Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
480Sstevel@tonic-gate 	 */
490Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
500Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
510Sstevel@tonic-gate 		return (-1);
520Sstevel@tonic-gate 	}
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	if (check(
550Sstevel@tonic-gate "Ready to analyze (won't harm SunOS). This takes a long time, \n"
567964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue"))
570Sstevel@tonic-gate 		return (-1);
580Sstevel@tonic-gate 	return (do_scan(SCAN_VALID, F_NORMAL));
590Sstevel@tonic-gate }
600Sstevel@tonic-gate 
610Sstevel@tonic-gate /*
620Sstevel@tonic-gate  * This routine implements the 'refresh' command.  It performs surface
630Sstevel@tonic-gate  * analysis by reading the disk then writing the same data back to the
640Sstevel@tonic-gate  * disk.  It is ok to run this command on file systems, but not while
650Sstevel@tonic-gate  * they are mounted.
660Sstevel@tonic-gate  */
670Sstevel@tonic-gate int
a_refresh()680Sstevel@tonic-gate a_refresh()
690Sstevel@tonic-gate {
700Sstevel@tonic-gate 	/*
710Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
720Sstevel@tonic-gate 	 */
730Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
740Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
750Sstevel@tonic-gate 		return (-1);
760Sstevel@tonic-gate 	}
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 	if (check(
790Sstevel@tonic-gate "Ready to analyze (won't harm data). This takes a long time, \n"
807964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue"))
810Sstevel@tonic-gate 		return (-1);
820Sstevel@tonic-gate 	return (do_scan(SCAN_VALID | SCAN_WRITE, F_NORMAL));
830Sstevel@tonic-gate }
840Sstevel@tonic-gate 
850Sstevel@tonic-gate /*
860Sstevel@tonic-gate  * This routine implements the 'test' command.  It performs surface
870Sstevel@tonic-gate  * analysis by reading the disk, writing then reading a pattern on the disk,
880Sstevel@tonic-gate  * then writing the original data back to the disk.
890Sstevel@tonic-gate  * It is ok to run this command on file systems, but not while they are
900Sstevel@tonic-gate  * mounted.
910Sstevel@tonic-gate  */
920Sstevel@tonic-gate int
a_test()930Sstevel@tonic-gate a_test()
940Sstevel@tonic-gate {
950Sstevel@tonic-gate 	/*
960Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
970Sstevel@tonic-gate 	 */
980Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
990Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
1000Sstevel@tonic-gate 		return (-1);
1010Sstevel@tonic-gate 	}
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate 	if (check(
1040Sstevel@tonic-gate "Ready to analyze (won't harm data). This takes a long time, \n"
1057964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue"))
1060Sstevel@tonic-gate 		return (-1);
1070Sstevel@tonic-gate 	return (do_scan(SCAN_VALID | SCAN_PATTERN | SCAN_WRITE, F_NORMAL));
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate  * This routine implements the 'write' command.  It performs surface
1120Sstevel@tonic-gate  * analysis by writing a pattern to the disk then reading it back.
1130Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
1140Sstevel@tonic-gate  */
1150Sstevel@tonic-gate int
a_write()1160Sstevel@tonic-gate a_write()
1170Sstevel@tonic-gate {
1180Sstevel@tonic-gate 	/*
1190Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
1200Sstevel@tonic-gate 	 */
1210Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
1220Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
1230Sstevel@tonic-gate 		return (-1);
1240Sstevel@tonic-gate 	}
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	if (check(
1270Sstevel@tonic-gate "Ready to analyze (will corrupt data). This takes a long time, \n"
1287964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue"))
1290Sstevel@tonic-gate 		return (-1);
1300Sstevel@tonic-gate 	return (do_scan(SCAN_PATTERN, F_NORMAL));
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate 
1330Sstevel@tonic-gate /*
1340Sstevel@tonic-gate  * This routine implements the 'compare' command.  It performs surface
1350Sstevel@tonic-gate  * analysis by writing a pattern to the disk, reading it back, then
1360Sstevel@tonic-gate  * checking the data to be sure it's the same.
1370Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
1380Sstevel@tonic-gate  */
1390Sstevel@tonic-gate int
a_compare()1400Sstevel@tonic-gate a_compare()
1410Sstevel@tonic-gate {
1420Sstevel@tonic-gate 	/*
1430Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
1440Sstevel@tonic-gate 	 */
1450Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
1460Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
1470Sstevel@tonic-gate 		return (-1);
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	if (check(
1510Sstevel@tonic-gate "Ready to analyze (will corrupt data). This takes a long time, \n"
1527964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue"))
1530Sstevel@tonic-gate 		return (-1);
1540Sstevel@tonic-gate 	return (do_scan(SCAN_PATTERN | SCAN_COMPARE, F_NORMAL));
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate /*
1580Sstevel@tonic-gate  * This routine implements the 'print' command.  It displays the data
1590Sstevel@tonic-gate  * buffer in hexadecimal.  It is only useful for checking the disk for
1600Sstevel@tonic-gate  * a specific set of data (by reading it then printing it).
1610Sstevel@tonic-gate  */
1620Sstevel@tonic-gate int
a_print()1630Sstevel@tonic-gate a_print()
1640Sstevel@tonic-gate {
1650Sstevel@tonic-gate 	int	i, j, lines, nomore = 0;
1660Sstevel@tonic-gate 	int	c, one_line = 0;
1670Sstevel@tonic-gate 	int	tty_lines = get_tty_lines();
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	/*
1700Sstevel@tonic-gate 	 * If we are running out of command file, don't page the output.
1710Sstevel@tonic-gate 	 * Otherwise we are running with a user.  Turn off echoing of
1720Sstevel@tonic-gate 	 * input characters so we can page the output.
1730Sstevel@tonic-gate 	 */
1740Sstevel@tonic-gate 	if (option_f || (!isatty(0)) || (!isatty(1)))
1750Sstevel@tonic-gate 		nomore++;
1760Sstevel@tonic-gate 	else {
1770Sstevel@tonic-gate 		enter_critical();
1780Sstevel@tonic-gate 		echo_off();
1790Sstevel@tonic-gate 		charmode_on();
1800Sstevel@tonic-gate 		exit_critical();
1810Sstevel@tonic-gate 	}
1820Sstevel@tonic-gate 	/*
1830Sstevel@tonic-gate 	 * Loop through the data buffer.
1840Sstevel@tonic-gate 	 */
1850Sstevel@tonic-gate 	lines = 0;
186*9889SLarry.Liu@Sun.COM 	for (i = 0; i < scan_size * cur_blksz / sizeof (int); i += 6) {
1870Sstevel@tonic-gate 		/*
1880Sstevel@tonic-gate 		 * Print the data.
1890Sstevel@tonic-gate 		 */
1900Sstevel@tonic-gate 		for (j = 0; j < 6; j++)
191*9889SLarry.Liu@Sun.COM 			if (i + j < scan_size * cur_blksz / sizeof (int))
1920Sstevel@tonic-gate 				fmt_print("0x%08x  ",
1937563SPrasad.Singamsetty@Sun.COM 				    *((int *)((int *)cur_buf + i + j)));
1940Sstevel@tonic-gate 		fmt_print("\n");
1950Sstevel@tonic-gate 		lines++;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 		/*
1980Sstevel@tonic-gate 		 * If we are paging and hit the end of a page, wait for
1990Sstevel@tonic-gate 		 * the user to hit either space-bar, "q", return,
2000Sstevel@tonic-gate 		 * or ctrl-C before going on.
2010Sstevel@tonic-gate 		 */
2020Sstevel@tonic-gate 		if (one_line ||
2030Sstevel@tonic-gate 		    (!nomore && (lines % (tty_lines - 1) == 0))) {
2040Sstevel@tonic-gate 			/*
2050Sstevel@tonic-gate 			 * Print until first screenfull
2060Sstevel@tonic-gate 			 */
2070Sstevel@tonic-gate 			if (lines < (tty_lines -1))
2080Sstevel@tonic-gate 				continue;
2090Sstevel@tonic-gate 			/*
2100Sstevel@tonic-gate 			 * Get the next character.
2110Sstevel@tonic-gate 			 */
2120Sstevel@tonic-gate 			(void) printf("- hit space for more - ");
2130Sstevel@tonic-gate 			c = getchar();
2140Sstevel@tonic-gate 			(void) printf("\015");
2150Sstevel@tonic-gate 			one_line = 0;
2160Sstevel@tonic-gate 			/*
2170Sstevel@tonic-gate 			 * Handle display one line command (return key)
2180Sstevel@tonic-gate 			 */
2190Sstevel@tonic-gate 			if (c == '\012') {
2200Sstevel@tonic-gate 				one_line++;
2210Sstevel@tonic-gate 			}
2220Sstevel@tonic-gate 			/* Handle Quit command */
2230Sstevel@tonic-gate 			if (c == 'q') {
2240Sstevel@tonic-gate 				(void) printf(
2250Sstevel@tonic-gate 				"                       \015");
2260Sstevel@tonic-gate 				goto PRINT_EXIT;
2270Sstevel@tonic-gate 			}
2280Sstevel@tonic-gate 			/* handle ^D */
2290Sstevel@tonic-gate 			if (c == '\004')
2300Sstevel@tonic-gate 				fullabort();
2310Sstevel@tonic-gate 		}
2320Sstevel@tonic-gate 	}
2330Sstevel@tonic-gate 	/*
2340Sstevel@tonic-gate 	 * If we were doing paging, turn echoing back on.
2350Sstevel@tonic-gate 	 */
2360Sstevel@tonic-gate PRINT_EXIT:
2370Sstevel@tonic-gate 	if (!nomore) {
2380Sstevel@tonic-gate 		enter_critical();
2390Sstevel@tonic-gate 		charmode_off();
2400Sstevel@tonic-gate 		echo_on();
2410Sstevel@tonic-gate 		exit_critical();
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 	return (0);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate  * This routine implements the 'setup' command.  It allows the user
2480Sstevel@tonic-gate  * to program the variables that drive surface analysis.  The approach
2490Sstevel@tonic-gate  * is to prompt the user for the value of each variable, with the current
2500Sstevel@tonic-gate  * value as the default.
2510Sstevel@tonic-gate  */
2520Sstevel@tonic-gate int
a_setup()2530Sstevel@tonic-gate a_setup()
2540Sstevel@tonic-gate {
2550Sstevel@tonic-gate 	int			deflt;
2560Sstevel@tonic-gate 	uint64_t		size;
2570Sstevel@tonic-gate 	u_ioparam_t		ioparam;
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 	/*
2600Sstevel@tonic-gate 	 * Because of the polarity of the yes/no structure (yes is 0),
2610Sstevel@tonic-gate 	 * we have to invert the values for all yes/no questions.
2620Sstevel@tonic-gate 	 */
2630Sstevel@tonic-gate 	deflt = !scan_entire;
2640Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
2650Sstevel@tonic-gate 	scan_entire = !input(FIO_MSTR, "Analyze entire disk", '?',
2660Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
2670Sstevel@tonic-gate 	/*
2680Sstevel@tonic-gate 	 * If we are not scanning the whole disk, input the bounds of the scan.
2690Sstevel@tonic-gate 	 */
2700Sstevel@tonic-gate 	if (!scan_entire) {
2710Sstevel@tonic-gate 		ioparam.io_bounds.lower = 0;
2720Sstevel@tonic-gate 		if ((cur_ctype->ctype_flags & CF_SCSI) &&
2730Sstevel@tonic-gate 		    (cur_disk->label_type == L_TYPE_SOLARIS)) {
2747563SPrasad.Singamsetty@Sun.COM 			ioparam.io_bounds.upper = datasects() - 1;
2750Sstevel@tonic-gate 		} else if (cur_disk->label_type == L_TYPE_SOLARIS) {
2767563SPrasad.Singamsetty@Sun.COM 			ioparam.io_bounds.upper = physsects() - 1;
2770Sstevel@tonic-gate 		} else if (cur_disk->label_type == L_TYPE_EFI) {
2787563SPrasad.Singamsetty@Sun.COM 			ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba;
2790Sstevel@tonic-gate 		}
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 		scan_lower = (diskaddr_t)input(FIO_BN,
2820Sstevel@tonic-gate 		    "Enter starting block number", ':',
2830Sstevel@tonic-gate 		    &ioparam, (int *)&scan_lower, DATA_INPUT);
2840Sstevel@tonic-gate 		ioparam.io_bounds.lower = scan_lower;
2850Sstevel@tonic-gate 		if (scan_upper < scan_lower)
2860Sstevel@tonic-gate 			scan_upper = scan_lower;
2870Sstevel@tonic-gate 		scan_upper = (diskaddr_t)input(FIO_BN,
2880Sstevel@tonic-gate 		    "Enter ending block number", ':',
2890Sstevel@tonic-gate 		    &ioparam, (int *)&scan_upper, DATA_INPUT);
2900Sstevel@tonic-gate 	}
2910Sstevel@tonic-gate 	deflt = !scan_loop;
2920Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
2930Sstevel@tonic-gate 	scan_loop = !input(FIO_MSTR, "Loop continuously", '?',
2940Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
2950Sstevel@tonic-gate 	/*
2960Sstevel@tonic-gate 	 * If we are not looping continuously, input the number of passes.
2970Sstevel@tonic-gate 	 */
2980Sstevel@tonic-gate 	if (!scan_loop) {
2990Sstevel@tonic-gate 		ioparam.io_bounds.lower = 1;
3000Sstevel@tonic-gate 		ioparam.io_bounds.upper = 100;
3010Sstevel@tonic-gate 		scan_passes = input(FIO_INT, "Enter number of passes", ':',
3020Sstevel@tonic-gate 		    &ioparam, &scan_passes, DATA_INPUT);
3030Sstevel@tonic-gate 	}
3040Sstevel@tonic-gate 	deflt = !scan_correct;
3050Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3060Sstevel@tonic-gate 	scan_correct = !input(FIO_MSTR, "Repair defective blocks", '?',
3070Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3080Sstevel@tonic-gate 	deflt = !scan_stop;
3090Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3100Sstevel@tonic-gate 	scan_stop = !input(FIO_MSTR, "Stop after first error", '?',
3110Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3120Sstevel@tonic-gate 	deflt = !scan_random;
3130Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3140Sstevel@tonic-gate 	scan_random = !input(FIO_MSTR, "Use random bit patterns", '?',
3150Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3160Sstevel@tonic-gate 	ioparam.io_bounds.lower = 1;
3170Sstevel@tonic-gate 	/*
3180Sstevel@tonic-gate 	 * The number of blocks per transfer is limited by the buffer
3190Sstevel@tonic-gate 	 * size, or the scan boundaries, whichever is smaller.
3200Sstevel@tonic-gate 	 */
3210Sstevel@tonic-gate 	if ((scan_entire) && (cur_disk->label_type == L_TYPE_SOLARIS)) {
3220Sstevel@tonic-gate 		size = physsects() - 1;
3230Sstevel@tonic-gate 	} else if ((scan_entire) && (cur_disk->label_type == L_TYPE_EFI)) {
3240Sstevel@tonic-gate 		size = cur_parts->etoc->efi_last_lba;
3250Sstevel@tonic-gate 	} else {
3260Sstevel@tonic-gate 		size = scan_upper - scan_lower + 1;
3270Sstevel@tonic-gate 	}
3280Sstevel@tonic-gate 	ioparam.io_bounds.upper = min(size, BUF_SECTS);
3290Sstevel@tonic-gate 	if (scan_size > ioparam.io_bounds.upper)
3300Sstevel@tonic-gate 		scan_size = ioparam.io_bounds.upper;
3317563SPrasad.Singamsetty@Sun.COM 	scan_size = input(FIO_INT, "Enter number of blocks per transfer", ':',
3327563SPrasad.Singamsetty@Sun.COM 	    &ioparam, (int *)&scan_size, DATA_INPUT);
3330Sstevel@tonic-gate 	deflt = !scan_auto;
3340Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3350Sstevel@tonic-gate 	scan_auto = !input(FIO_MSTR, "Verify media after formatting", '?',
3360Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3370Sstevel@tonic-gate 
3380Sstevel@tonic-gate 	deflt = !option_msg;
3390Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3400Sstevel@tonic-gate 	option_msg = !input(FIO_MSTR, "Enable extended messages", '?',
3410Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3420Sstevel@tonic-gate 	deflt = !scan_restore_defects;
3430Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3440Sstevel@tonic-gate 	scan_restore_defects = !input(FIO_MSTR, "Restore defect list", '?',
3450Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3460Sstevel@tonic-gate 	deflt = !scan_restore_label;
3470Sstevel@tonic-gate 	ioparam.io_charlist = confirm_list;
3480Sstevel@tonic-gate 	scan_restore_label = !input(FIO_MSTR, "Restore disk label", '?',
3490Sstevel@tonic-gate 	    &ioparam, &deflt, DATA_INPUT);
3500Sstevel@tonic-gate 	fmt_print("\n");
3510Sstevel@tonic-gate 	return (0);
3520Sstevel@tonic-gate }
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate /*
3550Sstevel@tonic-gate  * This routine implements the 'config' command.  It simply prints out
3560Sstevel@tonic-gate  * the values of all the variables controlling surface analysis.  It
3570Sstevel@tonic-gate  * is meant to complement the 'setup' command by allowing the user to
3580Sstevel@tonic-gate  * check the current setup.
3590Sstevel@tonic-gate  */
3600Sstevel@tonic-gate int
a_config()3610Sstevel@tonic-gate a_config()
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate 	fmt_print("        Analyze entire disk? ");
3650Sstevel@tonic-gate 	fmt_print(scan_entire ? "yes\n" : "no\n");
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	if (!scan_entire) {
3680Sstevel@tonic-gate 		fmt_print("        Starting block number: %llu (", scan_lower);
3690Sstevel@tonic-gate 		pr_dblock(fmt_print, scan_lower);
3700Sstevel@tonic-gate 		fmt_print(")\n        Ending block number: %llu (", scan_upper);
3710Sstevel@tonic-gate 		pr_dblock(fmt_print, scan_upper);
3720Sstevel@tonic-gate 		fmt_print(")\n");
3730Sstevel@tonic-gate 	}
3740Sstevel@tonic-gate 	fmt_print("        Loop continuously? ");
3750Sstevel@tonic-gate 	fmt_print(scan_loop ? "yes\n" : "no\n");
3760Sstevel@tonic-gate 
3770Sstevel@tonic-gate 	if (!scan_loop) {
3780Sstevel@tonic-gate 		fmt_print("        Number of passes: %d\n", scan_passes);
3790Sstevel@tonic-gate 	}
3800Sstevel@tonic-gate 
3810Sstevel@tonic-gate 	fmt_print("        Repair defective blocks? ");
3820Sstevel@tonic-gate 	fmt_print(scan_correct ? "yes\n" : "no\n");
3830Sstevel@tonic-gate 
3840Sstevel@tonic-gate 	fmt_print("        Stop after first error? ");
3850Sstevel@tonic-gate 	fmt_print(scan_stop ? "yes\n" : "no\n");
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	fmt_print("        Use random bit patterns? ");
3880Sstevel@tonic-gate 	fmt_print(scan_random ? "yes\n" : "no\n");
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	fmt_print("        Number of blocks per transfer: %d (", scan_size);
3917563SPrasad.Singamsetty@Sun.COM 	pr_dblock(fmt_print, (diskaddr_t)scan_size);
3920Sstevel@tonic-gate 	fmt_print(")\n");
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 	fmt_print("        Verify media after formatting? ");
3950Sstevel@tonic-gate 	fmt_print(scan_auto ? "yes\n" : "no\n");
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	fmt_print("        Enable extended messages? ");
3980Sstevel@tonic-gate 	fmt_print(option_msg ? "yes\n" : "no\n");
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	fmt_print("        Restore defect list? ");
4010Sstevel@tonic-gate 	fmt_print(scan_restore_defects ? "yes\n" : "no\n");
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 	fmt_print("        Restore disk label? ");
4040Sstevel@tonic-gate 	fmt_print(scan_restore_label ? "yes\n" : "no\n");
4050Sstevel@tonic-gate 
4060Sstevel@tonic-gate 	fmt_print("\n");
4070Sstevel@tonic-gate 	return (0);
4080Sstevel@tonic-gate }
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate /*
4110Sstevel@tonic-gate  * This routine implements the 'purge' command.  It purges the disk
4120Sstevel@tonic-gate  * by writing three patterns to the disk then reading the last one back.
4130Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
4140Sstevel@tonic-gate  */
4150Sstevel@tonic-gate int
a_purge()4160Sstevel@tonic-gate a_purge()
4170Sstevel@tonic-gate {
4180Sstevel@tonic-gate 	int status = 0;
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	/*
4210Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
4220Sstevel@tonic-gate 	 */
4230Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
4240Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
4250Sstevel@tonic-gate 		return (-1);
4260Sstevel@tonic-gate 	}
4270Sstevel@tonic-gate 	if (scan_random) {
4280Sstevel@tonic-gate 		fmt_print("The purge command does not write random data\n");
4290Sstevel@tonic-gate 		scan_random = 0;
4300Sstevel@tonic-gate 	}
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	if (!scan_loop && (scan_passes <= NPPATTERNS)) {
4330Sstevel@tonic-gate 		if (scan_passes < NPPATTERNS) {
4340Sstevel@tonic-gate 			fmt_print("The purge command runs for a minimum of ");
4350Sstevel@tonic-gate 			fmt_print("%d passes plus a last pass if the\n",
4367563SPrasad.Singamsetty@Sun.COM 			    NPPATTERNS);
4370Sstevel@tonic-gate 			fmt_print("first %d passes were successful.\n",
4387563SPrasad.Singamsetty@Sun.COM 			    NPPATTERNS);
4390Sstevel@tonic-gate 		}
4400Sstevel@tonic-gate 		scan_passes = NPPATTERNS + 1;
4410Sstevel@tonic-gate 	}
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 	if (check(
4440Sstevel@tonic-gate "Ready to purge (will corrupt data). This takes a long time, \n"
4457964SBo.Zhou@Sun.COM "but is interruptible with CTRL-C. Continue"))
4460Sstevel@tonic-gate 		return (-1);
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	status = do_scan(SCAN_PATTERN | SCAN_PURGE, F_NORMAL);
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	return (status);
4510Sstevel@tonic-gate }
4520Sstevel@tonic-gate 
4530Sstevel@tonic-gate /*
4540Sstevel@tonic-gate  * This routine implements the 'verify' command.  It writes the disk
4550Sstevel@tonic-gate  * by writing unique data for each block; after the write pass, it
4560Sstevel@tonic-gate  * reads the data and verifies for correctness. Note that the entire
4570Sstevel@tonic-gate  * disk (or the range of disk) is fully written first and then read.
4580Sstevel@tonic-gate  * This should eliminate any caching effect on the drives.
4590Sstevel@tonic-gate  * It is not ok to run this command on any data you want to keep.
4600Sstevel@tonic-gate  */
4610Sstevel@tonic-gate int
a_verify()4620Sstevel@tonic-gate a_verify()
4630Sstevel@tonic-gate {
4640Sstevel@tonic-gate 	/*
4650Sstevel@tonic-gate 	 * The current disk must be formatted before disk analysis.
4660Sstevel@tonic-gate 	 */
4670Sstevel@tonic-gate 	if (!(cur_flags & DISK_FORMATTED)) {
4680Sstevel@tonic-gate 		err_print("Current Disk is unformatted.\n");
4690Sstevel@tonic-gate 		return (-1);
4700Sstevel@tonic-gate 	}
4710Sstevel@tonic-gate 	if (scan_random) {
4720Sstevel@tonic-gate 		fmt_print("The verify command does not write random data\n");
4730Sstevel@tonic-gate 		scan_random = 0;
4740Sstevel@tonic-gate 	}
4750Sstevel@tonic-gate 	if (scan_passes < 2 && !scan_loop) {
4760Sstevel@tonic-gate 		scan_passes = 2;
4770Sstevel@tonic-gate 		fmt_print("The verify command runs minimum of 2 passes, one"
4780Sstevel@tonic-gate 		    " for writing and \nanother for reading and verfying."
4790Sstevel@tonic-gate 		    " Resetting the number of passes to 2.\n");
4800Sstevel@tonic-gate 	}
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	if (check("Ready to verify (will corrupt data). This takes a long time,"
4837964SBo.Zhou@Sun.COM 	    "\nbut is interruptible with CTRL-C. Continue")) {
4840Sstevel@tonic-gate 		return (-1);
4850Sstevel@tonic-gate 	}
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	return (do_scan(SCAN_WRITE | SCAN_VERIFY, F_NORMAL));
4880Sstevel@tonic-gate }
489