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 to implement the defect menu commands.
280Sstevel@tonic-gate */
290Sstevel@tonic-gate #include "global.h"
300Sstevel@tonic-gate #include <unistd.h>
310Sstevel@tonic-gate #include <string.h>
320Sstevel@tonic-gate #include "misc.h"
330Sstevel@tonic-gate #include "menu_defect.h"
340Sstevel@tonic-gate #include "param.h"
350Sstevel@tonic-gate #include "ctlr_scsi.h"
360Sstevel@tonic-gate
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate * This is the working defect list. All the commands here operate on
390Sstevel@tonic-gate * the working list, except for 'commit'. This way the user can
400Sstevel@tonic-gate * change his mind at any time without having mangled the current defect
410Sstevel@tonic-gate * list.
420Sstevel@tonic-gate */
430Sstevel@tonic-gate struct defect_list work_list;
440Sstevel@tonic-gate
450Sstevel@tonic-gate #ifdef __STDC__
460Sstevel@tonic-gate
470Sstevel@tonic-gate /* Function prototypes for ANSI C Compilers */
480Sstevel@tonic-gate static int commit_list(void);
490Sstevel@tonic-gate
500Sstevel@tonic-gate #else /* __STDC__ */
510Sstevel@tonic-gate
520Sstevel@tonic-gate /* Function prototypes for non-ANSI C Compilers */
530Sstevel@tonic-gate static int commit_list();
540Sstevel@tonic-gate
550Sstevel@tonic-gate #endif /* __STDC__ */
560Sstevel@tonic-gate
570Sstevel@tonic-gate /*
580Sstevel@tonic-gate * This routine implements the 'restore' command. It sets the working
590Sstevel@tonic-gate * list equal to the current list.
600Sstevel@tonic-gate */
610Sstevel@tonic-gate int
d_restore()620Sstevel@tonic-gate d_restore()
630Sstevel@tonic-gate {
640Sstevel@tonic-gate int i;
650Sstevel@tonic-gate
660Sstevel@tonic-gate assert(!EMBEDDED_SCSI);
670Sstevel@tonic-gate
680Sstevel@tonic-gate /*
690Sstevel@tonic-gate * If the working list has not been modified, there's nothing to do.
700Sstevel@tonic-gate */
710Sstevel@tonic-gate if (!(work_list.flags & LIST_DIRTY)) {
720Sstevel@tonic-gate err_print("working list was not modified.\n");
730Sstevel@tonic-gate return (0);
740Sstevel@tonic-gate }
750Sstevel@tonic-gate /*
760Sstevel@tonic-gate * Make sure the user is serious.
770Sstevel@tonic-gate */
780Sstevel@tonic-gate if (check("Ready to update working list, continue"))
790Sstevel@tonic-gate return (-1);
800Sstevel@tonic-gate /*
810Sstevel@tonic-gate * Lock out interrupts so the lists can't get mangled.
820Sstevel@tonic-gate */
830Sstevel@tonic-gate enter_critical();
840Sstevel@tonic-gate /*
850Sstevel@tonic-gate * Kill off the old working list.
860Sstevel@tonic-gate */
870Sstevel@tonic-gate kill_deflist(&work_list);
880Sstevel@tonic-gate /*
890Sstevel@tonic-gate * If the current isn't null, set the working list to be a
900Sstevel@tonic-gate * copy of it.
910Sstevel@tonic-gate */
920Sstevel@tonic-gate if (cur_list.list != NULL) {
930Sstevel@tonic-gate work_list.header = cur_list.header;
940Sstevel@tonic-gate work_list.list = (struct defect_entry *)zalloc(
95*9889SLarry.Liu@Sun.COM deflist_size(cur_blksz, work_list.header.count) *
96*9889SLarry.Liu@Sun.COM cur_blksz);
970Sstevel@tonic-gate for (i = 0; i < work_list.header.count; i++)
980Sstevel@tonic-gate *(work_list.list + i) = *(cur_list.list + i);
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate /*
1010Sstevel@tonic-gate * Initialize the flags since they are now in sync.
1020Sstevel@tonic-gate */
1030Sstevel@tonic-gate work_list.flags = 0;
1040Sstevel@tonic-gate if (work_list.list == NULL)
1050Sstevel@tonic-gate fmt_print("working list set to null.\n\n");
1060Sstevel@tonic-gate else
1070Sstevel@tonic-gate fmt_print("working list updated, total of %d defects.\n\n",
1080Sstevel@tonic-gate work_list.header.count);
1090Sstevel@tonic-gate exit_critical();
1100Sstevel@tonic-gate return (0);
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate /*
1140Sstevel@tonic-gate * This routine implements the 'original' command. It extracts the
1150Sstevel@tonic-gate * manufacturer's defect list from the current disk.
1160Sstevel@tonic-gate */
1170Sstevel@tonic-gate int
d_original()1180Sstevel@tonic-gate d_original()
1190Sstevel@tonic-gate {
1200Sstevel@tonic-gate int status;
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate
1230Sstevel@tonic-gate /*
1240Sstevel@tonic-gate * If the controller does not support the extraction, we're out
1250Sstevel@tonic-gate * of luck.
1260Sstevel@tonic-gate */
1270Sstevel@tonic-gate if (cur_ops->op_ex_man == NULL) {
1280Sstevel@tonic-gate err_print("Controller does not support extracting ");
1290Sstevel@tonic-gate err_print("manufacturer's defect list.\n");
1300Sstevel@tonic-gate return (-1);
1310Sstevel@tonic-gate }
1320Sstevel@tonic-gate /*
1330Sstevel@tonic-gate * Make sure the user is serious. Note, for SCSI disks
1340Sstevel@tonic-gate * since this is instantaneous, we will just do it and
1350Sstevel@tonic-gate * not ask for confirmation.
1360Sstevel@tonic-gate */
1370Sstevel@tonic-gate if (!(cur_ctype->ctype_flags & CF_CONFIRM) &&
1380Sstevel@tonic-gate check(
1390Sstevel@tonic-gate "Ready to update working list. This cannot be interrupted\n\
1400Sstevel@tonic-gate and may take a long while. Continue"))
1410Sstevel@tonic-gate return (-1);
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate * Lock out interrupts so we don't get half the list.
1440Sstevel@tonic-gate */
1450Sstevel@tonic-gate enter_critical();
1460Sstevel@tonic-gate /*
1470Sstevel@tonic-gate * Kill off the working list.
1480Sstevel@tonic-gate */
1490Sstevel@tonic-gate kill_deflist(&work_list);
1500Sstevel@tonic-gate fmt_print("Extracting manufacturer's defect list...");
1510Sstevel@tonic-gate /*
1520Sstevel@tonic-gate * Do the extraction.
1530Sstevel@tonic-gate */
1540Sstevel@tonic-gate status = (*cur_ops->op_ex_man)(&work_list);
1550Sstevel@tonic-gate if (status)
1560Sstevel@tonic-gate fmt_print("Extraction failed.\n\n");
1570Sstevel@tonic-gate else {
1580Sstevel@tonic-gate fmt_print("Extraction complete.\n");
1590Sstevel@tonic-gate fmt_print("Working list updated, total of %d defects.\n\n",
1600Sstevel@tonic-gate work_list.header.count);
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate /*
1630Sstevel@tonic-gate * Mark the working list dirty since we modified it.
1640Sstevel@tonic-gate */
1650Sstevel@tonic-gate work_list.flags |= LIST_DIRTY;
1660Sstevel@tonic-gate exit_critical();
1670Sstevel@tonic-gate /*
1680Sstevel@tonic-gate * Return status.
1690Sstevel@tonic-gate */
1700Sstevel@tonic-gate return (status);
1710Sstevel@tonic-gate }
1720Sstevel@tonic-gate
1730Sstevel@tonic-gate /*
1740Sstevel@tonic-gate * This routine implements the 'extract' command. It extracts the
1750Sstevel@tonic-gate * entire defect list from the current disk.
1760Sstevel@tonic-gate */
1770Sstevel@tonic-gate int
d_extract()1780Sstevel@tonic-gate d_extract()
1790Sstevel@tonic-gate {
1800Sstevel@tonic-gate int status;
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate /*
1830Sstevel@tonic-gate * If the controller does not support the extraction, we are out
1840Sstevel@tonic-gate * of luck.
1850Sstevel@tonic-gate */
1860Sstevel@tonic-gate if (cur_ops->op_ex_cur == NULL) {
1870Sstevel@tonic-gate err_print("Controller does not support extracting ");
1880Sstevel@tonic-gate err_print("current defect list.\n");
1890Sstevel@tonic-gate return (-1);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate /*
1930Sstevel@tonic-gate * If disk is unformatted, you really shouldn't do this.
1940Sstevel@tonic-gate * However, ask user to be sure.
1950Sstevel@tonic-gate */
1960Sstevel@tonic-gate if (! (cur_flags & DISK_FORMATTED) &&
1970Sstevel@tonic-gate (check(
1980Sstevel@tonic-gate "Cannot extract defect list from an unformatted disk. Continue")))
1990Sstevel@tonic-gate return (-1);
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate /*
2020Sstevel@tonic-gate * If this takes a long time, let's ask the user if he
2030Sstevel@tonic-gate * doesn't mind waiting. Note, for SCSI disks
2040Sstevel@tonic-gate * this operation is instantaneous so we won't ask for
2050Sstevel@tonic-gate * for confirmation.
2060Sstevel@tonic-gate */
2070Sstevel@tonic-gate if (! (cur_ctype->ctype_flags & CF_CONFIRM) &&
2080Sstevel@tonic-gate check(
2090Sstevel@tonic-gate "Ready to extract working list. This cannot be interrupted\n\
2100Sstevel@tonic-gate and may take a long while. Continue"))
2110Sstevel@tonic-gate return (-1);
2120Sstevel@tonic-gate /*
2130Sstevel@tonic-gate * Lock out interrupts so we don't get half the list and
2140Sstevel@tonic-gate * Kill off the working list.
2150Sstevel@tonic-gate */
2160Sstevel@tonic-gate enter_critical();
2170Sstevel@tonic-gate kill_deflist(&work_list);
2180Sstevel@tonic-gate fmt_print("Extracting defect list...");
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate * Do the extraction.
2220Sstevel@tonic-gate */
2230Sstevel@tonic-gate status = (*cur_ops->op_ex_cur)(&work_list);
2240Sstevel@tonic-gate if (status) {
2250Sstevel@tonic-gate if (!EMBEDDED_SCSI) {
2260Sstevel@tonic-gate if (cur_flags & DISK_FORMATTED)
2270Sstevel@tonic-gate read_list(&work_list);
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate if (work_list.list != NULL) {
2300Sstevel@tonic-gate status = 0;
2310Sstevel@tonic-gate fmt_print("Extraction complete.\n");
2320Sstevel@tonic-gate fmt_print(
2330Sstevel@tonic-gate "Working list updated, total of %d defects.\n\n",
234*9889SLarry.Liu@Sun.COM work_list.header.count);
2350Sstevel@tonic-gate } else {
2360Sstevel@tonic-gate fmt_print("Extraction failed.\n\n");
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate } else {
2390Sstevel@tonic-gate fmt_print("Extraction failed.\n\n");
2400Sstevel@tonic-gate }
2410Sstevel@tonic-gate } else {
2420Sstevel@tonic-gate fmt_print("Extraction complete.\n");
2430Sstevel@tonic-gate fmt_print("Working list updated, total of %d defects.\n\n",
2440Sstevel@tonic-gate work_list.header.count);
2450Sstevel@tonic-gate }
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate * Mark the working list dirty since we modified it.
2480Sstevel@tonic-gate */
2490Sstevel@tonic-gate work_list.flags |= LIST_DIRTY;
2500Sstevel@tonic-gate exit_critical();
2510Sstevel@tonic-gate /*
2520Sstevel@tonic-gate * Return status.
2530Sstevel@tonic-gate */
2540Sstevel@tonic-gate return (status);
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate /*
2580Sstevel@tonic-gate * This routine implements the 'add' command. It allows the user to
2590Sstevel@tonic-gate * enter the working defect list manually. It loops infinitely until
2600Sstevel@tonic-gate * the user breaks out with a ctrl-C.
2610Sstevel@tonic-gate */
2620Sstevel@tonic-gate int
d_add()2630Sstevel@tonic-gate d_add()
2640Sstevel@tonic-gate {
2657563SPrasad.Singamsetty@Sun.COM int type, deflt, index;
2667563SPrasad.Singamsetty@Sun.COM diskaddr_t bn;
2670Sstevel@tonic-gate u_ioparam_t ioparam;
2680Sstevel@tonic-gate struct defect_entry def;
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate assert(!EMBEDDED_SCSI);
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate /*
2730Sstevel@tonic-gate * Ask the user which mode of input he'd like to use.
2740Sstevel@tonic-gate */
2750Sstevel@tonic-gate fmt_print(" 0. bytes-from-index\n");
2760Sstevel@tonic-gate fmt_print(" 1. logical block\n");
2770Sstevel@tonic-gate deflt = 0;
2780Sstevel@tonic-gate ioparam.io_bounds.lower = 0;
2790Sstevel@tonic-gate ioparam.io_bounds.upper = 1;
2800Sstevel@tonic-gate type = input(FIO_INT, "Select input format (enter its number)", ':',
281*9889SLarry.Liu@Sun.COM &ioparam, &deflt, DATA_INPUT);
2820Sstevel@tonic-gate fmt_print("\nEnter Control-C to terminate.\n");
2830Sstevel@tonic-gate loop:
2840Sstevel@tonic-gate if (type) {
2850Sstevel@tonic-gate /*
2860Sstevel@tonic-gate * Mode selected is logical block. Input the defective block
2870Sstevel@tonic-gate * and fill in the defect entry with the info.
2880Sstevel@tonic-gate */
2890Sstevel@tonic-gate def.bfi = def.nbits = UNKNOWN;
2900Sstevel@tonic-gate ioparam.io_bounds.lower = 0;
2910Sstevel@tonic-gate if (cur_disk->label_type == L_TYPE_SOLARIS) {
292*9889SLarry.Liu@Sun.COM ioparam.io_bounds.upper = physsects() - 1;
2930Sstevel@tonic-gate } else {
294*9889SLarry.Liu@Sun.COM ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba;
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate bn = input(FIO_BN, "Enter defective block number", ':',
2970Sstevel@tonic-gate &ioparam, (int *)NULL, DATA_INPUT);
2980Sstevel@tonic-gate def.cyl = bn2c(bn);
2990Sstevel@tonic-gate def.head = bn2h(bn);
3000Sstevel@tonic-gate def.sect = bn2s(bn);
3010Sstevel@tonic-gate } else {
3020Sstevel@tonic-gate /*
3030Sstevel@tonic-gate * Mode selected is bytes-from-index. Input the information
3040Sstevel@tonic-gate * about the defect and fill in the defect entry.
3050Sstevel@tonic-gate */
3060Sstevel@tonic-gate def.sect = UNKNOWN;
3070Sstevel@tonic-gate ioparam.io_bounds.lower = 0;
3080Sstevel@tonic-gate ioparam.io_bounds.upper = pcyl - 1;
3090Sstevel@tonic-gate def.cyl = input(FIO_INT,
3100Sstevel@tonic-gate "Enter defect's cylinder number", ':',
3110Sstevel@tonic-gate &ioparam, (int *)NULL, DATA_INPUT);
3120Sstevel@tonic-gate ioparam.io_bounds.upper = nhead - 1;
3130Sstevel@tonic-gate def.head = input(FIO_INT, "Enter defect's head number",
3140Sstevel@tonic-gate ':', &ioparam, (int *)NULL, DATA_INPUT);
3150Sstevel@tonic-gate ioparam.io_bounds.upper = cur_dtype->dtype_bpt - 1;
3160Sstevel@tonic-gate def.bfi = input(FIO_INT, "Enter defect's bytes-from-index",
3170Sstevel@tonic-gate ':', &ioparam, (int *)NULL, DATA_INPUT);
3180Sstevel@tonic-gate ioparam.io_bounds.lower = -1;
3190Sstevel@tonic-gate ioparam.io_bounds.upper = (cur_dtype->dtype_bpt - def.bfi) * 8;
3200Sstevel@tonic-gate if (ioparam.io_bounds.upper >= 32 * 1024)
3210Sstevel@tonic-gate ioparam.io_bounds.upper = 32 * 1024 - 1;
3220Sstevel@tonic-gate /*
3230Sstevel@tonic-gate * Note: a length of -1 means the length is not known. We
3240Sstevel@tonic-gate * make this the default value.
3250Sstevel@tonic-gate */
3260Sstevel@tonic-gate deflt = -1;
3270Sstevel@tonic-gate def.nbits = input(FIO_INT, "Enter defect's length (in bits)",
3280Sstevel@tonic-gate ':', &ioparam, &deflt, DATA_INPUT);
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate /*
3310Sstevel@tonic-gate * Calculate where in the defect list this defect belongs
3320Sstevel@tonic-gate * and print it out.
3330Sstevel@tonic-gate */
3340Sstevel@tonic-gate index = sort_defect(&def, &work_list);
3350Sstevel@tonic-gate fmt_print(DEF_PRINTHEADER);
3360Sstevel@tonic-gate pr_defect(&def, index);
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate /*
3390Sstevel@tonic-gate * Lock out interrupts so lists don't get mangled.
3400Sstevel@tonic-gate * Also, mark the working list dirty since we are modifying it.
3410Sstevel@tonic-gate */
3420Sstevel@tonic-gate enter_critical();
3430Sstevel@tonic-gate work_list.flags |= LIST_DIRTY;
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate * If the list is null, create it with zero length. This is
3460Sstevel@tonic-gate * necessary because the routines to add a defect to the list
3470Sstevel@tonic-gate * assume the list is initialized.
3480Sstevel@tonic-gate */
3490Sstevel@tonic-gate if (work_list.list == NULL) {
3500Sstevel@tonic-gate work_list.header.magicno = (uint_t)DEFECT_MAGIC;
3510Sstevel@tonic-gate work_list.header.count = 0;
3520Sstevel@tonic-gate work_list.list = (struct defect_entry *)zalloc(
353*9889SLarry.Liu@Sun.COM deflist_size(cur_blksz, 0) * cur_blksz);
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate /*
3560Sstevel@tonic-gate * Add the defect to the working list.
3570Sstevel@tonic-gate */
3580Sstevel@tonic-gate add_def(&def, &work_list, index);
3590Sstevel@tonic-gate fmt_print("defect number %d added.\n\n", index + 1);
3600Sstevel@tonic-gate exit_critical();
3610Sstevel@tonic-gate /*
3620Sstevel@tonic-gate * Loop back for the next defect.
3630Sstevel@tonic-gate */
3640Sstevel@tonic-gate goto loop;
3650Sstevel@tonic-gate /*NOTREACHED*/
3660Sstevel@tonic-gate #ifdef lint
3670Sstevel@tonic-gate return (0);
3680Sstevel@tonic-gate #endif
3690Sstevel@tonic-gate }
3700Sstevel@tonic-gate
3710Sstevel@tonic-gate /*
3720Sstevel@tonic-gate * This routine implements the 'delete' command. It allows the user
3730Sstevel@tonic-gate * to manually delete a defect from the working list.
3740Sstevel@tonic-gate */
3750Sstevel@tonic-gate int
d_delete()3760Sstevel@tonic-gate d_delete()
3770Sstevel@tonic-gate {
3780Sstevel@tonic-gate int i, count, num;
3790Sstevel@tonic-gate u_ioparam_t ioparam;
3800Sstevel@tonic-gate
3810Sstevel@tonic-gate assert(!EMBEDDED_SCSI);
3820Sstevel@tonic-gate
3830Sstevel@tonic-gate /*
3840Sstevel@tonic-gate * If the working list is null or zero length, there's nothing
3850Sstevel@tonic-gate * to delete.
3860Sstevel@tonic-gate */
3870Sstevel@tonic-gate count = work_list.header.count;
3880Sstevel@tonic-gate if (work_list.list == NULL || count == 0) {
3890Sstevel@tonic-gate err_print("No defects to delete.\n");
3900Sstevel@tonic-gate return (-1);
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate /*
3930Sstevel@tonic-gate * Ask the user which defect should be deleted. Bounds are off by
3940Sstevel@tonic-gate * one because user sees a one-relative list.
3950Sstevel@tonic-gate */
3960Sstevel@tonic-gate ioparam.io_bounds.lower = 1;
3970Sstevel@tonic-gate ioparam.io_bounds.upper = count;
3980Sstevel@tonic-gate num = input(FIO_INT, "Specify defect to be deleted (enter its number)",
3990Sstevel@tonic-gate ':', &ioparam, (int *)NULL, DATA_INPUT);
4000Sstevel@tonic-gate /*
4010Sstevel@tonic-gate *
4020Sstevel@tonic-gate * The user thinks it's one relative but it's not really.
4030Sstevel@tonic-gate */
4040Sstevel@tonic-gate --num;
4050Sstevel@tonic-gate /*
4060Sstevel@tonic-gate * Print the defect selected and ask the user for confirmation.
4070Sstevel@tonic-gate */
4080Sstevel@tonic-gate fmt_print(DEF_PRINTHEADER);
4090Sstevel@tonic-gate pr_defect(work_list.list + num, num);
4100Sstevel@tonic-gate /*
4110Sstevel@tonic-gate * Lock out interrupts so the lists don't get mangled.
4120Sstevel@tonic-gate */
4130Sstevel@tonic-gate enter_critical();
4140Sstevel@tonic-gate /*
4150Sstevel@tonic-gate * Move down all the defects beyond the one deleted so the defect
4160Sstevel@tonic-gate * list is still fully populated.
4170Sstevel@tonic-gate */
4180Sstevel@tonic-gate for (i = num; i < count - 1; i++)
4190Sstevel@tonic-gate *(work_list.list + i) = *(work_list.list + i + 1);
4200Sstevel@tonic-gate /*
4210Sstevel@tonic-gate * If the size of the list in sectors has changed, reallocate
4220Sstevel@tonic-gate * the list to shrink it appropriately.
4230Sstevel@tonic-gate */
424*9889SLarry.Liu@Sun.COM if (deflist_size(cur_blksz, count - 1) <
425*9889SLarry.Liu@Sun.COM deflist_size(cur_blksz, count))
4260Sstevel@tonic-gate work_list.list = (struct defect_entry *)rezalloc(
427*9889SLarry.Liu@Sun.COM (void *)work_list.list,
428*9889SLarry.Liu@Sun.COM deflist_size(cur_blksz, count - 1) * cur_blksz);
4290Sstevel@tonic-gate /*
4300Sstevel@tonic-gate * Decrement the defect count.
4310Sstevel@tonic-gate */
4320Sstevel@tonic-gate work_list.header.count--;
4330Sstevel@tonic-gate /*
4340Sstevel@tonic-gate * Recalculate the list's checksum.
4350Sstevel@tonic-gate */
4360Sstevel@tonic-gate (void) checkdefsum(&work_list, CK_MAKESUM);
4370Sstevel@tonic-gate /*
4380Sstevel@tonic-gate * Mark the working list dirty since we modified it.
4390Sstevel@tonic-gate */
4400Sstevel@tonic-gate work_list.flags |= LIST_DIRTY;
4410Sstevel@tonic-gate fmt_print("defect number %d deleted.\n\n", ++num);
4420Sstevel@tonic-gate exit_critical();
4430Sstevel@tonic-gate return (0);
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate /*
4470Sstevel@tonic-gate * This routine implements the 'print' command. It prints the working
4480Sstevel@tonic-gate * defect list out in human-readable format.
4490Sstevel@tonic-gate */
4500Sstevel@tonic-gate int
d_print()4510Sstevel@tonic-gate d_print()
4520Sstevel@tonic-gate {
4530Sstevel@tonic-gate int i, nomore = 0;
4540Sstevel@tonic-gate int c, one_line = 0;
4550Sstevel@tonic-gate int tty_lines = get_tty_lines();
4560Sstevel@tonic-gate
4570Sstevel@tonic-gate /*
4580Sstevel@tonic-gate * If the working list is null, there's nothing to print.
4590Sstevel@tonic-gate */
4600Sstevel@tonic-gate if (work_list.list == NULL) {
4610Sstevel@tonic-gate if (EMBEDDED_SCSI)
4620Sstevel@tonic-gate err_print(
4630Sstevel@tonic-gate "No list defined,extract primary or grown or both defects list first.\n");
4640Sstevel@tonic-gate else
4650Sstevel@tonic-gate err_print("No working list defined.\n");
4660Sstevel@tonic-gate return (-1);
4670Sstevel@tonic-gate }
4680Sstevel@tonic-gate /*
4690Sstevel@tonic-gate * If we're running from a file, don't use the paging scheme.
4700Sstevel@tonic-gate * If we are running interactive, turn off echoing.
4710Sstevel@tonic-gate */
4720Sstevel@tonic-gate if (option_f || (!isatty(0)) || (!isatty(1)))
4730Sstevel@tonic-gate nomore++;
4740Sstevel@tonic-gate else {
4750Sstevel@tonic-gate enter_critical();
4760Sstevel@tonic-gate echo_off();
4770Sstevel@tonic-gate charmode_on();
4780Sstevel@tonic-gate exit_critical();
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate /* Print out the banner. */
4810Sstevel@tonic-gate if (work_list.header.count != 0)
4820Sstevel@tonic-gate fmt_print(DEF_PRINTHEADER);
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate /*
4850Sstevel@tonic-gate * Loop through the each defect in the working list.
4860Sstevel@tonic-gate */
4870Sstevel@tonic-gate for (i = 0; i < work_list.header.count; i++) {
4880Sstevel@tonic-gate /*
4890Sstevel@tonic-gate * If we are paging and hit the end of a page, wait for
4900Sstevel@tonic-gate * the user to hit either space-bar, "q", or return
4910Sstevel@tonic-gate * before going on.
4920Sstevel@tonic-gate */
4930Sstevel@tonic-gate if (one_line ||
494*9889SLarry.Liu@Sun.COM (!nomore && ((i + 1) % (tty_lines - 1) == 0))) {
4950Sstevel@tonic-gate /*
4960Sstevel@tonic-gate * Get the next character.
4970Sstevel@tonic-gate */
4980Sstevel@tonic-gate fmt_print("- hit space for more - ");
4990Sstevel@tonic-gate c = getchar();
5000Sstevel@tonic-gate fmt_print("\015");
5010Sstevel@tonic-gate one_line = 0;
5020Sstevel@tonic-gate /* Handle display one line command (return key) */
5030Sstevel@tonic-gate if (c == '\012') {
5040Sstevel@tonic-gate one_line++;
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate /* Handle Quit command */
5070Sstevel@tonic-gate if (c == 'q') {
5080Sstevel@tonic-gate fmt_print(" \015");
5090Sstevel@tonic-gate goto PRINT_EXIT;
5100Sstevel@tonic-gate }
5110Sstevel@tonic-gate /* Handle ^D */
5120Sstevel@tonic-gate if (c == '\004')
5130Sstevel@tonic-gate fullabort();
5140Sstevel@tonic-gate }
5150Sstevel@tonic-gate /*
5160Sstevel@tonic-gate * Print the defect.
5170Sstevel@tonic-gate */
5180Sstevel@tonic-gate pr_defect(work_list.list + i, i);
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate fmt_print("total of %d defects.\n\n", i);
5210Sstevel@tonic-gate /*
5220Sstevel@tonic-gate * If we were doing paging, turn echoing back on.
5230Sstevel@tonic-gate */
5240Sstevel@tonic-gate PRINT_EXIT:
5250Sstevel@tonic-gate if (!nomore) {
5260Sstevel@tonic-gate enter_critical();
5270Sstevel@tonic-gate charmode_off();
5280Sstevel@tonic-gate echo_on();
5290Sstevel@tonic-gate exit_critical();
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate return (0);
5320Sstevel@tonic-gate }
5330Sstevel@tonic-gate
5340Sstevel@tonic-gate /*
5350Sstevel@tonic-gate * This routine implements the 'dump' command. It writes the working
5360Sstevel@tonic-gate * defect list to a file.
5370Sstevel@tonic-gate */
5380Sstevel@tonic-gate int
d_dump()5390Sstevel@tonic-gate d_dump()
5400Sstevel@tonic-gate {
5410Sstevel@tonic-gate int i, status = 0;
5420Sstevel@tonic-gate char *str;
5430Sstevel@tonic-gate FILE *fptr;
5440Sstevel@tonic-gate struct defect_entry *dptr;
5450Sstevel@tonic-gate
5460Sstevel@tonic-gate /*
5470Sstevel@tonic-gate * If the working list is null, there's nothing to do.
5480Sstevel@tonic-gate */
5490Sstevel@tonic-gate if (work_list.list == NULL) {
5500Sstevel@tonic-gate if (EMBEDDED_SCSI)
5510Sstevel@tonic-gate err_print(
5520Sstevel@tonic-gate "No list defined,extract primary or grown or both defects list first.\n");
5530Sstevel@tonic-gate else
5540Sstevel@tonic-gate err_print("No working list defined.\n");
5550Sstevel@tonic-gate return (-1);
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate /*
5580Sstevel@tonic-gate * Ask the user for the name of the defect file. Note that the
5590Sstevel@tonic-gate * input will be in malloc'd space since we are inputting
5600Sstevel@tonic-gate * type OSTR.
5610Sstevel@tonic-gate */
562362Sbg159949 str = (char *)(uintptr_t)input(FIO_OSTR, "Enter name of defect file",
563362Sbg159949 ':', (u_ioparam_t *)NULL, (int *)NULL, DATA_INPUT);
5640Sstevel@tonic-gate /*
5650Sstevel@tonic-gate * Lock out interrupts so the file doesn't get half written.
5660Sstevel@tonic-gate */
5670Sstevel@tonic-gate enter_critical();
5680Sstevel@tonic-gate /*
5690Sstevel@tonic-gate * Open the file for writing.
5700Sstevel@tonic-gate */
5710Sstevel@tonic-gate if ((fptr = fopen(str, "w+")) == NULL) {
5720Sstevel@tonic-gate err_print("unable to open defect file.\n");
5730Sstevel@tonic-gate status = -1;
5740Sstevel@tonic-gate goto out;
5750Sstevel@tonic-gate }
5760Sstevel@tonic-gate /*
5770Sstevel@tonic-gate * Print a header containing the magic number, count, and checksum.
5780Sstevel@tonic-gate */
5790Sstevel@tonic-gate (void) fprintf(fptr, "0x%08x%8d 0x%08x\n",
580*9889SLarry.Liu@Sun.COM work_list.header.magicno,
581*9889SLarry.Liu@Sun.COM work_list.header.count, work_list.header.cksum);
5820Sstevel@tonic-gate /*
5830Sstevel@tonic-gate * Loop through each defect in the working list. Write the
5840Sstevel@tonic-gate * defect info to the defect file.
5850Sstevel@tonic-gate */
5860Sstevel@tonic-gate for (i = 0; i < work_list.header.count; i++) {
5870Sstevel@tonic-gate dptr = work_list.list + i;
5880Sstevel@tonic-gate (void) fprintf(fptr, "%4d%8d%7d%8d%8d%8d\n",
589*9889SLarry.Liu@Sun.COM i+1, dptr->cyl, dptr->head,
590*9889SLarry.Liu@Sun.COM dptr->bfi, dptr->nbits, dptr->sect);
5910Sstevel@tonic-gate }
5920Sstevel@tonic-gate fmt_print("defect file updated, total of %d defects.\n", i);
5930Sstevel@tonic-gate /*
5940Sstevel@tonic-gate * Close the defect file.
5950Sstevel@tonic-gate */
5960Sstevel@tonic-gate (void) fclose(fptr);
5970Sstevel@tonic-gate out:
5980Sstevel@tonic-gate /*
5990Sstevel@tonic-gate * Destroy the string used for the file name.
6000Sstevel@tonic-gate */
6010Sstevel@tonic-gate destroy_data(str);
6020Sstevel@tonic-gate exit_critical();
6030Sstevel@tonic-gate fmt_print("\n");
6040Sstevel@tonic-gate return (status);
6050Sstevel@tonic-gate }
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate /*
6080Sstevel@tonic-gate * This routine implements the 'load' command. It reads the working
6090Sstevel@tonic-gate * list in from a file.
6100Sstevel@tonic-gate */
6110Sstevel@tonic-gate int
d_load()6120Sstevel@tonic-gate d_load()
6130Sstevel@tonic-gate {
6140Sstevel@tonic-gate int i, items, status = 0, count, cksum;
6150Sstevel@tonic-gate uint_t magicno;
6160Sstevel@tonic-gate char *str;
6170Sstevel@tonic-gate TOKEN filename;
6180Sstevel@tonic-gate FILE *fptr;
6190Sstevel@tonic-gate struct defect_entry *dptr;
6200Sstevel@tonic-gate
6210Sstevel@tonic-gate assert(!EMBEDDED_SCSI);
6220Sstevel@tonic-gate
6230Sstevel@tonic-gate /*
6240Sstevel@tonic-gate * Ask the user for the name of the defect file. Note that the
6250Sstevel@tonic-gate * input will be malloc'd space since we inputted type OSTR.
6260Sstevel@tonic-gate */
627362Sbg159949 str = (char *)(uintptr_t)input(FIO_OSTR, "Enter name of defect file",
628362Sbg159949 ':', (u_ioparam_t *)NULL, (int *)NULL, DATA_INPUT);
6290Sstevel@tonic-gate /*
6300Sstevel@tonic-gate * Copy the file name into local space then destroy the string
6310Sstevel@tonic-gate * it came in. This is simply a precaution against later having
6320Sstevel@tonic-gate * to remember to destroy this space.
6330Sstevel@tonic-gate */
6340Sstevel@tonic-gate enter_critical();
6350Sstevel@tonic-gate (void) strcpy(filename, str);
6360Sstevel@tonic-gate destroy_data(str);
6370Sstevel@tonic-gate exit_critical();
6380Sstevel@tonic-gate /*
6390Sstevel@tonic-gate * See if the defect file is accessable. If not, we can't load
6400Sstevel@tonic-gate * from it. We do this here just so we can get out before asking
6410Sstevel@tonic-gate * the user for confirmation.
6420Sstevel@tonic-gate */
6430Sstevel@tonic-gate status = access(filename, 4);
6440Sstevel@tonic-gate if (status) {
6450Sstevel@tonic-gate err_print("defect file not accessable.\n");
6460Sstevel@tonic-gate return (-1);
6470Sstevel@tonic-gate }
6480Sstevel@tonic-gate /*
6490Sstevel@tonic-gate * Make sure the user is serious.
6500Sstevel@tonic-gate */
6510Sstevel@tonic-gate if (check("ready to update working list, continue"))
6520Sstevel@tonic-gate return (-1);
6530Sstevel@tonic-gate /*
6540Sstevel@tonic-gate * Lock out interrupts so the list doesn't get half loaded.
6550Sstevel@tonic-gate */
6560Sstevel@tonic-gate enter_critical();
6570Sstevel@tonic-gate /*
6580Sstevel@tonic-gate * Open the defect file.
6590Sstevel@tonic-gate */
6600Sstevel@tonic-gate if ((fptr = fopen(filename, "r")) == NULL) {
6610Sstevel@tonic-gate err_print("unable to open defect file.\n");
6620Sstevel@tonic-gate exit_critical();
6630Sstevel@tonic-gate return (-1);
6640Sstevel@tonic-gate }
6650Sstevel@tonic-gate /*
6660Sstevel@tonic-gate * Scan in the header.
6670Sstevel@tonic-gate */
6680Sstevel@tonic-gate items = fscanf(fptr, "0x%x%d 0x%x\n", &magicno,
669*9889SLarry.Liu@Sun.COM &count, (uint_t *)&cksum);
6700Sstevel@tonic-gate /*
6710Sstevel@tonic-gate * If the header is wrong, this isn't a good defect file.
6720Sstevel@tonic-gate */
6730Sstevel@tonic-gate if (items != 3 || count < 0 ||
6740Sstevel@tonic-gate (magicno != (uint_t)DEFECT_MAGIC &&
675*9889SLarry.Liu@Sun.COM magicno != (uint_t)NO_CHECKSUM)) {
6760Sstevel@tonic-gate err_print("Defect file is corrupted.\n");
6770Sstevel@tonic-gate status = -1;
6780Sstevel@tonic-gate goto out;
6790Sstevel@tonic-gate }
6800Sstevel@tonic-gate /*
6810Sstevel@tonic-gate * Kill off any old defects in the working list.
6820Sstevel@tonic-gate */
6830Sstevel@tonic-gate kill_deflist(&work_list);
6840Sstevel@tonic-gate /*
6850Sstevel@tonic-gate * Load the working list header with the header info.
6860Sstevel@tonic-gate */
6870Sstevel@tonic-gate if (magicno == NO_CHECKSUM)
6880Sstevel@tonic-gate work_list.header.magicno = (uint_t)DEFECT_MAGIC;
6890Sstevel@tonic-gate else
6900Sstevel@tonic-gate work_list.header.magicno = magicno;
6910Sstevel@tonic-gate work_list.header.count = count;
6920Sstevel@tonic-gate work_list.header.cksum = cksum;
6930Sstevel@tonic-gate /*
6940Sstevel@tonic-gate * Allocate space for the new list.
6950Sstevel@tonic-gate */
696*9889SLarry.Liu@Sun.COM work_list.list = (struct defect_entry *)zalloc(
697*9889SLarry.Liu@Sun.COM deflist_size(cur_blksz, count) * cur_blksz);
6980Sstevel@tonic-gate /*
6990Sstevel@tonic-gate * Mark the working list dirty since we are modifying it.
7000Sstevel@tonic-gate */
7010Sstevel@tonic-gate work_list.flags |= LIST_DIRTY;
7020Sstevel@tonic-gate /*
7030Sstevel@tonic-gate * Loop through each defect in the defect file.
7040Sstevel@tonic-gate */
7050Sstevel@tonic-gate for (i = 0; i < count; i++) {
7060Sstevel@tonic-gate dptr = work_list.list + i;
7070Sstevel@tonic-gate /*
7080Sstevel@tonic-gate * Scan the info into the defect entry.
7090Sstevel@tonic-gate */
7100Sstevel@tonic-gate items = fscanf(fptr, "%*d%hd%hd%d%hd%hd\n", &dptr->cyl,
7110Sstevel@tonic-gate &dptr->head, &dptr->bfi, &dptr->nbits, &dptr->sect);
7120Sstevel@tonic-gate /*
7130Sstevel@tonic-gate * If it didn't scan right, give up.
7140Sstevel@tonic-gate */
7150Sstevel@tonic-gate if (items != 5)
7160Sstevel@tonic-gate goto bad;
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate /*
7190Sstevel@tonic-gate * Check to be sure the checksum from the defect file was correct
7200Sstevel@tonic-gate * unless there wasn't supposed to be a checksum.
7210Sstevel@tonic-gate * If there was supposed to be a valid checksum and there isn't
7220Sstevel@tonic-gate * then give up.
7230Sstevel@tonic-gate */
7240Sstevel@tonic-gate if (magicno != NO_CHECKSUM && checkdefsum(&work_list, CK_CHECKSUM))
7250Sstevel@tonic-gate goto bad;
7260Sstevel@tonic-gate fmt_print("working list updated, total of %d defects.\n", i);
7270Sstevel@tonic-gate goto out;
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate bad:
7300Sstevel@tonic-gate /*
7310Sstevel@tonic-gate * Some kind of error occurred. Kill off the working list and
7320Sstevel@tonic-gate * mark the status bad.
7330Sstevel@tonic-gate */
7340Sstevel@tonic-gate err_print("Defect file is corrupted, working list set to NULL.\n");
7350Sstevel@tonic-gate kill_deflist(&work_list);
7360Sstevel@tonic-gate status = -1;
7370Sstevel@tonic-gate out:
7380Sstevel@tonic-gate /*
7390Sstevel@tonic-gate * Close the defect file.
7400Sstevel@tonic-gate */
7410Sstevel@tonic-gate (void) fclose(fptr);
7420Sstevel@tonic-gate exit_critical();
7430Sstevel@tonic-gate fmt_print("\n");
7440Sstevel@tonic-gate return (status);
7450Sstevel@tonic-gate }
7460Sstevel@tonic-gate
7470Sstevel@tonic-gate /*
7480Sstevel@tonic-gate * This routine implements the 'commit' command. It causes the current
7490Sstevel@tonic-gate * defect list to be set equal to the working defect list. It is the only
7500Sstevel@tonic-gate * way that changes made to the working list can actually take effect in
7510Sstevel@tonic-gate * the next format.
7520Sstevel@tonic-gate */
7530Sstevel@tonic-gate int
d_commit()7540Sstevel@tonic-gate d_commit()
7550Sstevel@tonic-gate {
7560Sstevel@tonic-gate /*
7570Sstevel@tonic-gate * If the working list wasn't modified, no commit is necessary.
7580Sstevel@tonic-gate */
7590Sstevel@tonic-gate if (work_list.list != NULL && !(work_list.flags & LIST_DIRTY)) {
7600Sstevel@tonic-gate err_print("working list was not modified.\n");
7610Sstevel@tonic-gate return (0);
7620Sstevel@tonic-gate }
7630Sstevel@tonic-gate
7640Sstevel@tonic-gate /*
7650Sstevel@tonic-gate * Make sure the user is serious.
7660Sstevel@tonic-gate */
7670Sstevel@tonic-gate if (check("Ready to update Current Defect List, continue"))
7680Sstevel@tonic-gate return (-1);
7690Sstevel@tonic-gate return (do_commit());
7700Sstevel@tonic-gate }
7710Sstevel@tonic-gate
7720Sstevel@tonic-gate int
do_commit()7730Sstevel@tonic-gate do_commit()
7740Sstevel@tonic-gate {
7750Sstevel@tonic-gate int status;
7760Sstevel@tonic-gate
7770Sstevel@tonic-gate if ((status = commit_list()) == 0) {
7780Sstevel@tonic-gate /*
7790Sstevel@tonic-gate * Remind the user to format the drive, since changing
7800Sstevel@tonic-gate * the list does nothing unless a format is performed.
7810Sstevel@tonic-gate */
7820Sstevel@tonic-gate fmt_print(\
7830Sstevel@tonic-gate "Disk must be reformatted for changes to take effect.\n\n");
7840Sstevel@tonic-gate }
7850Sstevel@tonic-gate return (status);
7860Sstevel@tonic-gate }
7870Sstevel@tonic-gate
7880Sstevel@tonic-gate
7890Sstevel@tonic-gate static int
commit_list()7900Sstevel@tonic-gate commit_list()
7910Sstevel@tonic-gate {
7920Sstevel@tonic-gate int i;
7930Sstevel@tonic-gate
7940Sstevel@tonic-gate /*
7950Sstevel@tonic-gate * Lock out interrupts so the list doesn't get half copied.
7960Sstevel@tonic-gate */
7970Sstevel@tonic-gate enter_critical();
7980Sstevel@tonic-gate /*
7990Sstevel@tonic-gate * Kill off any current defect list.
8000Sstevel@tonic-gate */
8010Sstevel@tonic-gate kill_deflist(&cur_list);
8020Sstevel@tonic-gate /*
8030Sstevel@tonic-gate * If the working list is null, initialize it to zero length.
8040Sstevel@tonic-gate * This is so the user can do a commit on a null list and get
8050Sstevel@tonic-gate * a zero length list. Otherwise there would be no way to get
8060Sstevel@tonic-gate * a zero length list conveniently.
8070Sstevel@tonic-gate */
8080Sstevel@tonic-gate if (work_list.list == NULL) {
8090Sstevel@tonic-gate work_list.header.magicno = (uint_t)DEFECT_MAGIC;
8100Sstevel@tonic-gate work_list.header.count = 0;
8110Sstevel@tonic-gate work_list.list = (struct defect_entry *)zalloc(
812*9889SLarry.Liu@Sun.COM deflist_size(cur_blksz, 0) * cur_blksz);
8130Sstevel@tonic-gate }
8140Sstevel@tonic-gate /*
8150Sstevel@tonic-gate * Copy the working list into the current list.
8160Sstevel@tonic-gate */
8170Sstevel@tonic-gate cur_list.header = work_list.header;
8180Sstevel@tonic-gate cur_list.list = (struct defect_entry *)zalloc(
819*9889SLarry.Liu@Sun.COM deflist_size(cur_blksz, cur_list.header.count) * cur_blksz);
8200Sstevel@tonic-gate for (i = 0; i < cur_list.header.count; i++)
8210Sstevel@tonic-gate *(cur_list.list + i) = *(work_list.list + i);
8220Sstevel@tonic-gate /*
8230Sstevel@tonic-gate * Mark the working list clean, since it is now the same as the
8240Sstevel@tonic-gate * current list. Note we do not mark the current list dirty,
8250Sstevel@tonic-gate * even though it has been changed. This is because it does
8260Sstevel@tonic-gate * not reflect the state of disk, so we don't want it written
8270Sstevel@tonic-gate * out until a format has been done. The format will mark it
8280Sstevel@tonic-gate * dirty and write it out.
8290Sstevel@tonic-gate */
8300Sstevel@tonic-gate work_list.flags &= ~(LIST_DIRTY|LIST_RELOAD);
8310Sstevel@tonic-gate cur_list.flags = work_list.flags;
8320Sstevel@tonic-gate if (EMBEDDED_SCSI)
8330Sstevel@tonic-gate fmt_print("Defect List has a total of %d defects.\n",
8340Sstevel@tonic-gate cur_list.header.count);
8350Sstevel@tonic-gate else
8360Sstevel@tonic-gate fmt_print("Current Defect List updated, total of %d defects.\n",
8370Sstevel@tonic-gate cur_list.header.count);
8380Sstevel@tonic-gate exit_critical();
8390Sstevel@tonic-gate return (0);
8400Sstevel@tonic-gate }
8410Sstevel@tonic-gate
8420Sstevel@tonic-gate
8430Sstevel@tonic-gate /*
8440Sstevel@tonic-gate * This routine implements the 'create' command. It creates the
8450Sstevel@tonic-gate * manufacturer's defect on the current disk from the defect list
8460Sstevel@tonic-gate */
8470Sstevel@tonic-gate int
d_create()8480Sstevel@tonic-gate d_create()
8490Sstevel@tonic-gate {
8500Sstevel@tonic-gate int status;
8510Sstevel@tonic-gate
8520Sstevel@tonic-gate assert(!EMBEDDED_SCSI);
8530Sstevel@tonic-gate
8540Sstevel@tonic-gate /*
8550Sstevel@tonic-gate * If the controller does not support the extraction, we're out
8560Sstevel@tonic-gate * of luck.
8570Sstevel@tonic-gate */
8580Sstevel@tonic-gate if (cur_ops->op_create == NULL) {
8590Sstevel@tonic-gate err_print("Controller does not support creating ");
8600Sstevel@tonic-gate err_print("manufacturer's defect list.\n");
8610Sstevel@tonic-gate return (-1);
8620Sstevel@tonic-gate }
8630Sstevel@tonic-gate /*
8640Sstevel@tonic-gate * Make sure the user is serious. Note, for SCSI disks
8650Sstevel@tonic-gate * since this is instantaneous, we will just do it and
8660Sstevel@tonic-gate * not ask for confirmation.
8670Sstevel@tonic-gate */
8680Sstevel@tonic-gate if (! (cur_ctype->ctype_flags & CF_SCSI) &&
8690Sstevel@tonic-gate check(
8700Sstevel@tonic-gate "Ready to create the manufacturers defect information on the disk.\n\
8710Sstevel@tonic-gate This cannot be interrupted and may take a long while.\n\
8720Sstevel@tonic-gate IT WILL DESTROY ALL OF THE DATA ON THE DISK! Continue"))
8730Sstevel@tonic-gate return (-1);
8740Sstevel@tonic-gate /*
8750Sstevel@tonic-gate * Lock out interrupts so we don't get half the list.
8760Sstevel@tonic-gate */
8770Sstevel@tonic-gate enter_critical();
8780Sstevel@tonic-gate fmt_print("Creating manufacturer's defect list...");
8790Sstevel@tonic-gate /*
8800Sstevel@tonic-gate * Do the Creation
8810Sstevel@tonic-gate */
8820Sstevel@tonic-gate status = (*cur_ops->op_create)(&work_list);
8830Sstevel@tonic-gate if (status) {
8840Sstevel@tonic-gate fmt_print("Creation failed.\n\n");
8850Sstevel@tonic-gate } else {
8860Sstevel@tonic-gate fmt_print("Creation complete.\n");
8870Sstevel@tonic-gate }
8880Sstevel@tonic-gate exit_critical();
8890Sstevel@tonic-gate /*
8900Sstevel@tonic-gate * Return status.
8910Sstevel@tonic-gate */
8920Sstevel@tonic-gate return (status);
8930Sstevel@tonic-gate }
8940Sstevel@tonic-gate
8950Sstevel@tonic-gate
8960Sstevel@tonic-gate /*
8970Sstevel@tonic-gate * Extract primary defect list - SCSI only
8980Sstevel@tonic-gate */
8990Sstevel@tonic-gate int
d_primary()9000Sstevel@tonic-gate d_primary()
9010Sstevel@tonic-gate {
9020Sstevel@tonic-gate int status;
9030Sstevel@tonic-gate
9040Sstevel@tonic-gate assert(EMBEDDED_SCSI);
9050Sstevel@tonic-gate
9060Sstevel@tonic-gate /*
9070Sstevel@tonic-gate * Lock out interrupts so we don't get half the list and
9080Sstevel@tonic-gate * Kill off the working list.
9090Sstevel@tonic-gate */
9100Sstevel@tonic-gate enter_critical();
9110Sstevel@tonic-gate kill_deflist(&work_list);
9120Sstevel@tonic-gate fmt_print("Extracting primary defect list...");
9130Sstevel@tonic-gate
9140Sstevel@tonic-gate /*
9150Sstevel@tonic-gate * Do the extraction.
9160Sstevel@tonic-gate */
9170Sstevel@tonic-gate status = scsi_ex_man(&work_list);
9180Sstevel@tonic-gate if (status) {
9190Sstevel@tonic-gate fmt_print("Extraction failed.\n\n");
9200Sstevel@tonic-gate } else {
9210Sstevel@tonic-gate fmt_print("Extraction complete.\n");
9220Sstevel@tonic-gate /*
9230Sstevel@tonic-gate * Mark the working list dirty since we modified it.
9240Sstevel@tonic-gate * Automatically commit it, for SCSI only.
9250Sstevel@tonic-gate */
9260Sstevel@tonic-gate work_list.flags |= LIST_DIRTY;
9270Sstevel@tonic-gate status = commit_list();
9280Sstevel@tonic-gate fmt_print("\n");
9290Sstevel@tonic-gate }
9300Sstevel@tonic-gate exit_critical();
9310Sstevel@tonic-gate
9320Sstevel@tonic-gate /*
9330Sstevel@tonic-gate * Return status.
9340Sstevel@tonic-gate */
9350Sstevel@tonic-gate return (status);
9360Sstevel@tonic-gate }
9370Sstevel@tonic-gate
9380Sstevel@tonic-gate
9390Sstevel@tonic-gate /*
9400Sstevel@tonic-gate * Extract grown defects list - SCSI only
9410Sstevel@tonic-gate */
9420Sstevel@tonic-gate int
d_grown()9430Sstevel@tonic-gate d_grown()
9440Sstevel@tonic-gate {
9450Sstevel@tonic-gate int status;
9460Sstevel@tonic-gate
9470Sstevel@tonic-gate assert(EMBEDDED_SCSI);
9480Sstevel@tonic-gate
9490Sstevel@tonic-gate /*
9500Sstevel@tonic-gate * Lock out interrupts so we don't get half the list and
9510Sstevel@tonic-gate * Kill off the working list.
9520Sstevel@tonic-gate */
9530Sstevel@tonic-gate enter_critical();
9540Sstevel@tonic-gate kill_deflist(&work_list);
9550Sstevel@tonic-gate fmt_print("Extracting grown defects list...");
9560Sstevel@tonic-gate
9570Sstevel@tonic-gate /*
9580Sstevel@tonic-gate * Do the extraction.
9590Sstevel@tonic-gate */
9600Sstevel@tonic-gate status = scsi_ex_grown(&work_list);
9610Sstevel@tonic-gate if (status) {
9620Sstevel@tonic-gate fmt_print("Extraction failed.\n\n");
9630Sstevel@tonic-gate } else {
9640Sstevel@tonic-gate fmt_print("Extraction complete.\n");
9650Sstevel@tonic-gate /*
9660Sstevel@tonic-gate * Mark the working list dirty since we modified it.
9670Sstevel@tonic-gate * Automatically commit it, for SCSI only.
9680Sstevel@tonic-gate */
9690Sstevel@tonic-gate work_list.flags |= LIST_DIRTY;
9700Sstevel@tonic-gate status = commit_list();
9710Sstevel@tonic-gate fmt_print("\n");
9720Sstevel@tonic-gate }
9730Sstevel@tonic-gate exit_critical();
9740Sstevel@tonic-gate
9750Sstevel@tonic-gate /*
9760Sstevel@tonic-gate * Return status.
9770Sstevel@tonic-gate */
9780Sstevel@tonic-gate return (status);
9790Sstevel@tonic-gate }
9800Sstevel@tonic-gate
9810Sstevel@tonic-gate
9820Sstevel@tonic-gate /*
9830Sstevel@tonic-gate * Extract both primary and grown defects list - SCSI only
9840Sstevel@tonic-gate */
9850Sstevel@tonic-gate int
d_both()9860Sstevel@tonic-gate d_both()
9870Sstevel@tonic-gate {
9880Sstevel@tonic-gate int status;
9890Sstevel@tonic-gate
9900Sstevel@tonic-gate assert(EMBEDDED_SCSI);
9910Sstevel@tonic-gate
9920Sstevel@tonic-gate /*
9930Sstevel@tonic-gate * Lock out interrupts so we don't get half the list and
9940Sstevel@tonic-gate * Kill off the working list.
9950Sstevel@tonic-gate */
9960Sstevel@tonic-gate enter_critical();
9970Sstevel@tonic-gate kill_deflist(&work_list);
9980Sstevel@tonic-gate fmt_print("Extracting both primary and grown defects lists...");
9990Sstevel@tonic-gate
10000Sstevel@tonic-gate /*
10010Sstevel@tonic-gate * Do the extraction.
10020Sstevel@tonic-gate */
10030Sstevel@tonic-gate status = scsi_ex_cur(&work_list);
10040Sstevel@tonic-gate if (status) {
10050Sstevel@tonic-gate fmt_print("Extraction failed.\n\n");
10060Sstevel@tonic-gate } else {
10070Sstevel@tonic-gate fmt_print("Extraction complete.\n");
10080Sstevel@tonic-gate /*
10090Sstevel@tonic-gate * Mark the working list dirty since we modified it.
10100Sstevel@tonic-gate * Automatically commit it, for SCSI only.
10110Sstevel@tonic-gate */
10120Sstevel@tonic-gate work_list.flags |= LIST_DIRTY;
10130Sstevel@tonic-gate status = commit_list();
10140Sstevel@tonic-gate fmt_print("\n");
10150Sstevel@tonic-gate }
10160Sstevel@tonic-gate exit_critical();
10170Sstevel@tonic-gate
10180Sstevel@tonic-gate /*
10190Sstevel@tonic-gate * Return status.
10200Sstevel@tonic-gate */
10210Sstevel@tonic-gate return (status);
10220Sstevel@tonic-gate }
1023