1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 1991-2002 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate /* 30*0Sstevel@tonic-gate * This file contains functions to implement the defect menu commands. 31*0Sstevel@tonic-gate */ 32*0Sstevel@tonic-gate #include "global.h" 33*0Sstevel@tonic-gate #include <unistd.h> 34*0Sstevel@tonic-gate #include <string.h> 35*0Sstevel@tonic-gate #include "misc.h" 36*0Sstevel@tonic-gate #include "menu_defect.h" 37*0Sstevel@tonic-gate #include "param.h" 38*0Sstevel@tonic-gate #include "ctlr_scsi.h" 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate /* 41*0Sstevel@tonic-gate * This is the working defect list. All the commands here operate on 42*0Sstevel@tonic-gate * the working list, except for 'commit'. This way the user can 43*0Sstevel@tonic-gate * change his mind at any time without having mangled the current defect 44*0Sstevel@tonic-gate * list. 45*0Sstevel@tonic-gate */ 46*0Sstevel@tonic-gate struct defect_list work_list; 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate #ifdef __STDC__ 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate /* Function prototypes for ANSI C Compilers */ 51*0Sstevel@tonic-gate static int commit_list(void); 52*0Sstevel@tonic-gate 53*0Sstevel@tonic-gate #else /* __STDC__ */ 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gate /* Function prototypes for non-ANSI C Compilers */ 56*0Sstevel@tonic-gate static int commit_list(); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate #endif /* __STDC__ */ 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate /* 61*0Sstevel@tonic-gate * This routine implements the 'restore' command. It sets the working 62*0Sstevel@tonic-gate * list equal to the current list. 63*0Sstevel@tonic-gate */ 64*0Sstevel@tonic-gate int 65*0Sstevel@tonic-gate d_restore() 66*0Sstevel@tonic-gate { 67*0Sstevel@tonic-gate int i; 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate assert(!EMBEDDED_SCSI); 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate /* 72*0Sstevel@tonic-gate * If the working list has not been modified, there's nothing to do. 73*0Sstevel@tonic-gate */ 74*0Sstevel@tonic-gate if (!(work_list.flags & LIST_DIRTY)) { 75*0Sstevel@tonic-gate err_print("working list was not modified.\n"); 76*0Sstevel@tonic-gate return (0); 77*0Sstevel@tonic-gate } 78*0Sstevel@tonic-gate /* 79*0Sstevel@tonic-gate * Make sure the user is serious. 80*0Sstevel@tonic-gate */ 81*0Sstevel@tonic-gate if (check("Ready to update working list, continue")) 82*0Sstevel@tonic-gate return (-1); 83*0Sstevel@tonic-gate /* 84*0Sstevel@tonic-gate * Lock out interrupts so the lists can't get mangled. 85*0Sstevel@tonic-gate */ 86*0Sstevel@tonic-gate enter_critical(); 87*0Sstevel@tonic-gate /* 88*0Sstevel@tonic-gate * Kill off the old working list. 89*0Sstevel@tonic-gate */ 90*0Sstevel@tonic-gate kill_deflist(&work_list); 91*0Sstevel@tonic-gate /* 92*0Sstevel@tonic-gate * If the current isn't null, set the working list to be a 93*0Sstevel@tonic-gate * copy of it. 94*0Sstevel@tonic-gate */ 95*0Sstevel@tonic-gate if (cur_list.list != NULL) { 96*0Sstevel@tonic-gate work_list.header = cur_list.header; 97*0Sstevel@tonic-gate work_list.list = (struct defect_entry *)zalloc( 98*0Sstevel@tonic-gate LISTSIZE(work_list.header.count) * SECSIZE); 99*0Sstevel@tonic-gate for (i = 0; i < work_list.header.count; i++) 100*0Sstevel@tonic-gate *(work_list.list + i) = *(cur_list.list + i); 101*0Sstevel@tonic-gate } 102*0Sstevel@tonic-gate /* 103*0Sstevel@tonic-gate * Initialize the flags since they are now in sync. 104*0Sstevel@tonic-gate */ 105*0Sstevel@tonic-gate work_list.flags = 0; 106*0Sstevel@tonic-gate if (work_list.list == NULL) 107*0Sstevel@tonic-gate fmt_print("working list set to null.\n\n"); 108*0Sstevel@tonic-gate else 109*0Sstevel@tonic-gate fmt_print("working list updated, total of %d defects.\n\n", 110*0Sstevel@tonic-gate work_list.header.count); 111*0Sstevel@tonic-gate exit_critical(); 112*0Sstevel@tonic-gate return (0); 113*0Sstevel@tonic-gate } 114*0Sstevel@tonic-gate 115*0Sstevel@tonic-gate /* 116*0Sstevel@tonic-gate * This routine implements the 'original' command. It extracts the 117*0Sstevel@tonic-gate * manufacturer's defect list from the current disk. 118*0Sstevel@tonic-gate */ 119*0Sstevel@tonic-gate int 120*0Sstevel@tonic-gate d_original() 121*0Sstevel@tonic-gate { 122*0Sstevel@tonic-gate int status; 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate /* 126*0Sstevel@tonic-gate * If the controller does not support the extraction, we're out 127*0Sstevel@tonic-gate * of luck. 128*0Sstevel@tonic-gate */ 129*0Sstevel@tonic-gate if (cur_ops->op_ex_man == NULL) { 130*0Sstevel@tonic-gate err_print("Controller does not support extracting "); 131*0Sstevel@tonic-gate err_print("manufacturer's defect list.\n"); 132*0Sstevel@tonic-gate return (-1); 133*0Sstevel@tonic-gate } 134*0Sstevel@tonic-gate /* 135*0Sstevel@tonic-gate * Make sure the user is serious. Note, for SCSI disks 136*0Sstevel@tonic-gate * since this is instantaneous, we will just do it and 137*0Sstevel@tonic-gate * not ask for confirmation. 138*0Sstevel@tonic-gate */ 139*0Sstevel@tonic-gate if (!(cur_ctype->ctype_flags & CF_CONFIRM) && 140*0Sstevel@tonic-gate check( 141*0Sstevel@tonic-gate "Ready to update working list. This cannot be interrupted\n\ 142*0Sstevel@tonic-gate and may take a long while. Continue")) 143*0Sstevel@tonic-gate return (-1); 144*0Sstevel@tonic-gate /* 145*0Sstevel@tonic-gate * Lock out interrupts so we don't get half the list. 146*0Sstevel@tonic-gate */ 147*0Sstevel@tonic-gate enter_critical(); 148*0Sstevel@tonic-gate /* 149*0Sstevel@tonic-gate * Kill off the working list. 150*0Sstevel@tonic-gate */ 151*0Sstevel@tonic-gate kill_deflist(&work_list); 152*0Sstevel@tonic-gate fmt_print("Extracting manufacturer's defect list..."); 153*0Sstevel@tonic-gate /* 154*0Sstevel@tonic-gate * Do the extraction. 155*0Sstevel@tonic-gate */ 156*0Sstevel@tonic-gate status = (*cur_ops->op_ex_man)(&work_list); 157*0Sstevel@tonic-gate if (status) 158*0Sstevel@tonic-gate fmt_print("Extraction failed.\n\n"); 159*0Sstevel@tonic-gate else { 160*0Sstevel@tonic-gate fmt_print("Extraction complete.\n"); 161*0Sstevel@tonic-gate fmt_print("Working list updated, total of %d defects.\n\n", 162*0Sstevel@tonic-gate work_list.header.count); 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate /* 165*0Sstevel@tonic-gate * Mark the working list dirty since we modified it. 166*0Sstevel@tonic-gate */ 167*0Sstevel@tonic-gate work_list.flags |= LIST_DIRTY; 168*0Sstevel@tonic-gate exit_critical(); 169*0Sstevel@tonic-gate /* 170*0Sstevel@tonic-gate * Return status. 171*0Sstevel@tonic-gate */ 172*0Sstevel@tonic-gate return (status); 173*0Sstevel@tonic-gate } 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate /* 176*0Sstevel@tonic-gate * This routine implements the 'extract' command. It extracts the 177*0Sstevel@tonic-gate * entire defect list from the current disk. 178*0Sstevel@tonic-gate */ 179*0Sstevel@tonic-gate int 180*0Sstevel@tonic-gate d_extract() 181*0Sstevel@tonic-gate { 182*0Sstevel@tonic-gate int status; 183*0Sstevel@tonic-gate 184*0Sstevel@tonic-gate /* 185*0Sstevel@tonic-gate * If the controller does not support the extraction, we are out 186*0Sstevel@tonic-gate * of luck. 187*0Sstevel@tonic-gate */ 188*0Sstevel@tonic-gate if (cur_ops->op_ex_cur == NULL) { 189*0Sstevel@tonic-gate err_print("Controller does not support extracting "); 190*0Sstevel@tonic-gate err_print("current defect list.\n"); 191*0Sstevel@tonic-gate return (-1); 192*0Sstevel@tonic-gate } 193*0Sstevel@tonic-gate 194*0Sstevel@tonic-gate /* 195*0Sstevel@tonic-gate * If disk is unformatted, you really shouldn't do this. 196*0Sstevel@tonic-gate * However, ask user to be sure. 197*0Sstevel@tonic-gate */ 198*0Sstevel@tonic-gate if (! (cur_flags & DISK_FORMATTED) && 199*0Sstevel@tonic-gate (check( 200*0Sstevel@tonic-gate "Cannot extract defect list from an unformatted disk. Continue"))) 201*0Sstevel@tonic-gate return (-1); 202*0Sstevel@tonic-gate 203*0Sstevel@tonic-gate /* 204*0Sstevel@tonic-gate * If this takes a long time, let's ask the user if he 205*0Sstevel@tonic-gate * doesn't mind waiting. Note, for SCSI disks 206*0Sstevel@tonic-gate * this operation is instantaneous so we won't ask for 207*0Sstevel@tonic-gate * for confirmation. 208*0Sstevel@tonic-gate */ 209*0Sstevel@tonic-gate if (! (cur_ctype->ctype_flags & CF_CONFIRM) && 210*0Sstevel@tonic-gate check( 211*0Sstevel@tonic-gate "Ready to extract working list. This cannot be interrupted\n\ 212*0Sstevel@tonic-gate and may take a long while. Continue")) 213*0Sstevel@tonic-gate return (-1); 214*0Sstevel@tonic-gate /* 215*0Sstevel@tonic-gate * Lock out interrupts so we don't get half the list and 216*0Sstevel@tonic-gate * Kill off the working list. 217*0Sstevel@tonic-gate */ 218*0Sstevel@tonic-gate enter_critical(); 219*0Sstevel@tonic-gate kill_deflist(&work_list); 220*0Sstevel@tonic-gate fmt_print("Extracting defect list..."); 221*0Sstevel@tonic-gate 222*0Sstevel@tonic-gate /* 223*0Sstevel@tonic-gate * Do the extraction. 224*0Sstevel@tonic-gate */ 225*0Sstevel@tonic-gate status = (*cur_ops->op_ex_cur)(&work_list); 226*0Sstevel@tonic-gate if (status) { 227*0Sstevel@tonic-gate if (!EMBEDDED_SCSI) { 228*0Sstevel@tonic-gate if (cur_flags & DISK_FORMATTED) 229*0Sstevel@tonic-gate read_list(&work_list); 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gate if (work_list.list != NULL) { 232*0Sstevel@tonic-gate status = 0; 233*0Sstevel@tonic-gate fmt_print("Extraction complete.\n"); 234*0Sstevel@tonic-gate fmt_print( 235*0Sstevel@tonic-gate "Working list updated, total of %d defects.\n\n", 236*0Sstevel@tonic-gate work_list.header.count); 237*0Sstevel@tonic-gate } else { 238*0Sstevel@tonic-gate fmt_print("Extraction failed.\n\n"); 239*0Sstevel@tonic-gate } 240*0Sstevel@tonic-gate } else { 241*0Sstevel@tonic-gate fmt_print("Extraction failed.\n\n"); 242*0Sstevel@tonic-gate } 243*0Sstevel@tonic-gate } else { 244*0Sstevel@tonic-gate fmt_print("Extraction complete.\n"); 245*0Sstevel@tonic-gate fmt_print("Working list updated, total of %d defects.\n\n", 246*0Sstevel@tonic-gate work_list.header.count); 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate /* 249*0Sstevel@tonic-gate * Mark the working list dirty since we modified it. 250*0Sstevel@tonic-gate */ 251*0Sstevel@tonic-gate work_list.flags |= LIST_DIRTY; 252*0Sstevel@tonic-gate exit_critical(); 253*0Sstevel@tonic-gate /* 254*0Sstevel@tonic-gate * Return status. 255*0Sstevel@tonic-gate */ 256*0Sstevel@tonic-gate return (status); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate /* 260*0Sstevel@tonic-gate * This routine implements the 'add' command. It allows the user to 261*0Sstevel@tonic-gate * enter the working defect list manually. It loops infinitely until 262*0Sstevel@tonic-gate * the user breaks out with a ctrl-C. 263*0Sstevel@tonic-gate */ 264*0Sstevel@tonic-gate int 265*0Sstevel@tonic-gate d_add() 266*0Sstevel@tonic-gate { 267*0Sstevel@tonic-gate int type, bn, deflt, index; 268*0Sstevel@tonic-gate u_ioparam_t ioparam; 269*0Sstevel@tonic-gate struct defect_entry def; 270*0Sstevel@tonic-gate 271*0Sstevel@tonic-gate assert(!EMBEDDED_SCSI); 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate /* 274*0Sstevel@tonic-gate * Ask the user which mode of input he'd like to use. 275*0Sstevel@tonic-gate */ 276*0Sstevel@tonic-gate fmt_print(" 0. bytes-from-index\n"); 277*0Sstevel@tonic-gate fmt_print(" 1. logical block\n"); 278*0Sstevel@tonic-gate deflt = 0; 279*0Sstevel@tonic-gate ioparam.io_bounds.lower = 0; 280*0Sstevel@tonic-gate ioparam.io_bounds.upper = 1; 281*0Sstevel@tonic-gate type = input(FIO_INT, "Select input format (enter its number)", ':', 282*0Sstevel@tonic-gate &ioparam, &deflt, DATA_INPUT); 283*0Sstevel@tonic-gate fmt_print("\nEnter Control-C to terminate.\n"); 284*0Sstevel@tonic-gate loop: 285*0Sstevel@tonic-gate if (type) { 286*0Sstevel@tonic-gate /* 287*0Sstevel@tonic-gate * Mode selected is logical block. Input the defective block 288*0Sstevel@tonic-gate * and fill in the defect entry with the info. 289*0Sstevel@tonic-gate */ 290*0Sstevel@tonic-gate def.bfi = def.nbits = UNKNOWN; 291*0Sstevel@tonic-gate ioparam.io_bounds.lower = 0; 292*0Sstevel@tonic-gate if (cur_disk->label_type == L_TYPE_SOLARIS) { 293*0Sstevel@tonic-gate ioparam.io_bounds.upper = physsects() - 1; 294*0Sstevel@tonic-gate } else { 295*0Sstevel@tonic-gate ioparam.io_bounds.upper = cur_parts->etoc->efi_last_lba; 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate bn = input(FIO_BN, "Enter defective block number", ':', 298*0Sstevel@tonic-gate &ioparam, (int *)NULL, DATA_INPUT); 299*0Sstevel@tonic-gate def.cyl = bn2c(bn); 300*0Sstevel@tonic-gate def.head = bn2h(bn); 301*0Sstevel@tonic-gate def.sect = bn2s(bn); 302*0Sstevel@tonic-gate } else { 303*0Sstevel@tonic-gate /* 304*0Sstevel@tonic-gate * Mode selected is bytes-from-index. Input the information 305*0Sstevel@tonic-gate * about the defect and fill in the defect entry. 306*0Sstevel@tonic-gate */ 307*0Sstevel@tonic-gate def.sect = UNKNOWN; 308*0Sstevel@tonic-gate ioparam.io_bounds.lower = 0; 309*0Sstevel@tonic-gate ioparam.io_bounds.upper = pcyl - 1; 310*0Sstevel@tonic-gate def.cyl = input(FIO_INT, 311*0Sstevel@tonic-gate "Enter defect's cylinder number", ':', 312*0Sstevel@tonic-gate &ioparam, (int *)NULL, DATA_INPUT); 313*0Sstevel@tonic-gate ioparam.io_bounds.upper = nhead - 1; 314*0Sstevel@tonic-gate def.head = input(FIO_INT, "Enter defect's head number", 315*0Sstevel@tonic-gate ':', &ioparam, (int *)NULL, DATA_INPUT); 316*0Sstevel@tonic-gate ioparam.io_bounds.upper = cur_dtype->dtype_bpt - 1; 317*0Sstevel@tonic-gate def.bfi = input(FIO_INT, "Enter defect's bytes-from-index", 318*0Sstevel@tonic-gate ':', &ioparam, (int *)NULL, DATA_INPUT); 319*0Sstevel@tonic-gate ioparam.io_bounds.lower = -1; 320*0Sstevel@tonic-gate ioparam.io_bounds.upper = (cur_dtype->dtype_bpt - def.bfi) * 8; 321*0Sstevel@tonic-gate if (ioparam.io_bounds.upper >= 32 * 1024) 322*0Sstevel@tonic-gate ioparam.io_bounds.upper = 32 * 1024 - 1; 323*0Sstevel@tonic-gate /* 324*0Sstevel@tonic-gate * Note: a length of -1 means the length is not known. We 325*0Sstevel@tonic-gate * make this the default value. 326*0Sstevel@tonic-gate */ 327*0Sstevel@tonic-gate deflt = -1; 328*0Sstevel@tonic-gate def.nbits = input(FIO_INT, "Enter defect's length (in bits)", 329*0Sstevel@tonic-gate ':', &ioparam, &deflt, DATA_INPUT); 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate /* 332*0Sstevel@tonic-gate * Calculate where in the defect list this defect belongs 333*0Sstevel@tonic-gate * and print it out. 334*0Sstevel@tonic-gate */ 335*0Sstevel@tonic-gate index = sort_defect(&def, &work_list); 336*0Sstevel@tonic-gate fmt_print(DEF_PRINTHEADER); 337*0Sstevel@tonic-gate pr_defect(&def, index); 338*0Sstevel@tonic-gate 339*0Sstevel@tonic-gate /* 340*0Sstevel@tonic-gate * Lock out interrupts so lists don't get mangled. 341*0Sstevel@tonic-gate * Also, mark the working list dirty since we are modifying it. 342*0Sstevel@tonic-gate */ 343*0Sstevel@tonic-gate enter_critical(); 344*0Sstevel@tonic-gate work_list.flags |= LIST_DIRTY; 345*0Sstevel@tonic-gate /* 346*0Sstevel@tonic-gate * If the list is null, create it with zero length. This is 347*0Sstevel@tonic-gate * necessary because the routines to add a defect to the list 348*0Sstevel@tonic-gate * assume the list is initialized. 349*0Sstevel@tonic-gate */ 350*0Sstevel@tonic-gate if (work_list.list == NULL) { 351*0Sstevel@tonic-gate work_list.header.magicno = (uint_t)DEFECT_MAGIC; 352*0Sstevel@tonic-gate work_list.header.count = 0; 353*0Sstevel@tonic-gate work_list.list = (struct defect_entry *)zalloc( 354*0Sstevel@tonic-gate LISTSIZE(0) * SECSIZE); 355*0Sstevel@tonic-gate } 356*0Sstevel@tonic-gate /* 357*0Sstevel@tonic-gate * Add the defect to the working list. 358*0Sstevel@tonic-gate */ 359*0Sstevel@tonic-gate add_def(&def, &work_list, index); 360*0Sstevel@tonic-gate fmt_print("defect number %d added.\n\n", index + 1); 361*0Sstevel@tonic-gate exit_critical(); 362*0Sstevel@tonic-gate /* 363*0Sstevel@tonic-gate * Loop back for the next defect. 364*0Sstevel@tonic-gate */ 365*0Sstevel@tonic-gate goto loop; 366*0Sstevel@tonic-gate /*NOTREACHED*/ 367*0Sstevel@tonic-gate #ifdef lint 368*0Sstevel@tonic-gate return (0); 369*0Sstevel@tonic-gate #endif 370*0Sstevel@tonic-gate } 371*0Sstevel@tonic-gate 372*0Sstevel@tonic-gate /* 373*0Sstevel@tonic-gate * This routine implements the 'delete' command. It allows the user 374*0Sstevel@tonic-gate * to manually delete a defect from the working list. 375*0Sstevel@tonic-gate */ 376*0Sstevel@tonic-gate int 377*0Sstevel@tonic-gate d_delete() 378*0Sstevel@tonic-gate { 379*0Sstevel@tonic-gate int i, count, num; 380*0Sstevel@tonic-gate u_ioparam_t ioparam; 381*0Sstevel@tonic-gate 382*0Sstevel@tonic-gate assert(!EMBEDDED_SCSI); 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate /* 385*0Sstevel@tonic-gate * If the working list is null or zero length, there's nothing 386*0Sstevel@tonic-gate * to delete. 387*0Sstevel@tonic-gate */ 388*0Sstevel@tonic-gate count = work_list.header.count; 389*0Sstevel@tonic-gate if (work_list.list == NULL || count == 0) { 390*0Sstevel@tonic-gate err_print("No defects to delete.\n"); 391*0Sstevel@tonic-gate return (-1); 392*0Sstevel@tonic-gate } 393*0Sstevel@tonic-gate /* 394*0Sstevel@tonic-gate * Ask the user which defect should be deleted. Bounds are off by 395*0Sstevel@tonic-gate * one because user sees a one-relative list. 396*0Sstevel@tonic-gate */ 397*0Sstevel@tonic-gate ioparam.io_bounds.lower = 1; 398*0Sstevel@tonic-gate ioparam.io_bounds.upper = count; 399*0Sstevel@tonic-gate num = input(FIO_INT, "Specify defect to be deleted (enter its number)", 400*0Sstevel@tonic-gate ':', &ioparam, (int *)NULL, DATA_INPUT); 401*0Sstevel@tonic-gate /* 402*0Sstevel@tonic-gate * 403*0Sstevel@tonic-gate * The user thinks it's one relative but it's not really. 404*0Sstevel@tonic-gate */ 405*0Sstevel@tonic-gate --num; 406*0Sstevel@tonic-gate /* 407*0Sstevel@tonic-gate * Print the defect selected and ask the user for confirmation. 408*0Sstevel@tonic-gate */ 409*0Sstevel@tonic-gate fmt_print(DEF_PRINTHEADER); 410*0Sstevel@tonic-gate pr_defect(work_list.list + num, num); 411*0Sstevel@tonic-gate /* 412*0Sstevel@tonic-gate * Lock out interrupts so the lists don't get mangled. 413*0Sstevel@tonic-gate */ 414*0Sstevel@tonic-gate enter_critical(); 415*0Sstevel@tonic-gate /* 416*0Sstevel@tonic-gate * Move down all the defects beyond the one deleted so the defect 417*0Sstevel@tonic-gate * list is still fully populated. 418*0Sstevel@tonic-gate */ 419*0Sstevel@tonic-gate for (i = num; i < count - 1; i++) 420*0Sstevel@tonic-gate *(work_list.list + i) = *(work_list.list + i + 1); 421*0Sstevel@tonic-gate /* 422*0Sstevel@tonic-gate * If the size of the list in sectors has changed, reallocate 423*0Sstevel@tonic-gate * the list to shrink it appropriately. 424*0Sstevel@tonic-gate */ 425*0Sstevel@tonic-gate if (LISTSIZE(count - 1) < LISTSIZE(count)) 426*0Sstevel@tonic-gate work_list.list = (struct defect_entry *)rezalloc( 427*0Sstevel@tonic-gate (void *)work_list.list, LISTSIZE(count - 1) * SECSIZE); 428*0Sstevel@tonic-gate /* 429*0Sstevel@tonic-gate * Decrement the defect count. 430*0Sstevel@tonic-gate */ 431*0Sstevel@tonic-gate work_list.header.count--; 432*0Sstevel@tonic-gate /* 433*0Sstevel@tonic-gate * Recalculate the list's checksum. 434*0Sstevel@tonic-gate */ 435*0Sstevel@tonic-gate (void) checkdefsum(&work_list, CK_MAKESUM); 436*0Sstevel@tonic-gate /* 437*0Sstevel@tonic-gate * Mark the working list dirty since we modified it. 438*0Sstevel@tonic-gate */ 439*0Sstevel@tonic-gate work_list.flags |= LIST_DIRTY; 440*0Sstevel@tonic-gate fmt_print("defect number %d deleted.\n\n", ++num); 441*0Sstevel@tonic-gate exit_critical(); 442*0Sstevel@tonic-gate return (0); 443*0Sstevel@tonic-gate } 444*0Sstevel@tonic-gate 445*0Sstevel@tonic-gate /* 446*0Sstevel@tonic-gate * This routine implements the 'print' command. It prints the working 447*0Sstevel@tonic-gate * defect list out in human-readable format. 448*0Sstevel@tonic-gate */ 449*0Sstevel@tonic-gate int 450*0Sstevel@tonic-gate d_print() 451*0Sstevel@tonic-gate { 452*0Sstevel@tonic-gate int i, nomore = 0; 453*0Sstevel@tonic-gate int c, one_line = 0; 454*0Sstevel@tonic-gate int tty_lines = get_tty_lines(); 455*0Sstevel@tonic-gate 456*0Sstevel@tonic-gate /* 457*0Sstevel@tonic-gate * If the working list is null, there's nothing to print. 458*0Sstevel@tonic-gate */ 459*0Sstevel@tonic-gate if (work_list.list == NULL) { 460*0Sstevel@tonic-gate if (EMBEDDED_SCSI) 461*0Sstevel@tonic-gate err_print( 462*0Sstevel@tonic-gate "No list defined,extract primary or grown or both defects list first.\n"); 463*0Sstevel@tonic-gate else 464*0Sstevel@tonic-gate err_print("No working list defined.\n"); 465*0Sstevel@tonic-gate return (-1); 466*0Sstevel@tonic-gate } 467*0Sstevel@tonic-gate /* 468*0Sstevel@tonic-gate * If we're running from a file, don't use the paging scheme. 469*0Sstevel@tonic-gate * If we are running interactive, turn off echoing. 470*0Sstevel@tonic-gate */ 471*0Sstevel@tonic-gate if (option_f || (!isatty(0)) || (!isatty(1))) 472*0Sstevel@tonic-gate nomore++; 473*0Sstevel@tonic-gate else { 474*0Sstevel@tonic-gate enter_critical(); 475*0Sstevel@tonic-gate echo_off(); 476*0Sstevel@tonic-gate charmode_on(); 477*0Sstevel@tonic-gate exit_critical(); 478*0Sstevel@tonic-gate } 479*0Sstevel@tonic-gate /* Print out the banner. */ 480*0Sstevel@tonic-gate if (work_list.header.count != 0) 481*0Sstevel@tonic-gate fmt_print(DEF_PRINTHEADER); 482*0Sstevel@tonic-gate 483*0Sstevel@tonic-gate /* 484*0Sstevel@tonic-gate * Loop through the each defect in the working list. 485*0Sstevel@tonic-gate */ 486*0Sstevel@tonic-gate for (i = 0; i < work_list.header.count; i++) { 487*0Sstevel@tonic-gate /* 488*0Sstevel@tonic-gate * If we are paging and hit the end of a page, wait for 489*0Sstevel@tonic-gate * the user to hit either space-bar, "q", or return 490*0Sstevel@tonic-gate * before going on. 491*0Sstevel@tonic-gate */ 492*0Sstevel@tonic-gate if (one_line || 493*0Sstevel@tonic-gate (!nomore && ((i + 1) % (tty_lines - 1) == 0))) { 494*0Sstevel@tonic-gate /* 495*0Sstevel@tonic-gate * Get the next character. 496*0Sstevel@tonic-gate */ 497*0Sstevel@tonic-gate fmt_print("- hit space for more - "); 498*0Sstevel@tonic-gate c = getchar(); 499*0Sstevel@tonic-gate fmt_print("\015"); 500*0Sstevel@tonic-gate one_line = 0; 501*0Sstevel@tonic-gate /* Handle display one line command (return key) */ 502*0Sstevel@tonic-gate if (c == '\012') { 503*0Sstevel@tonic-gate one_line++; 504*0Sstevel@tonic-gate } 505*0Sstevel@tonic-gate /* Handle Quit command */ 506*0Sstevel@tonic-gate if (c == 'q') { 507*0Sstevel@tonic-gate fmt_print(" \015"); 508*0Sstevel@tonic-gate goto PRINT_EXIT; 509*0Sstevel@tonic-gate } 510*0Sstevel@tonic-gate /* Handle ^D */ 511*0Sstevel@tonic-gate if (c == '\004') 512*0Sstevel@tonic-gate fullabort(); 513*0Sstevel@tonic-gate } 514*0Sstevel@tonic-gate /* 515*0Sstevel@tonic-gate * Print the defect. 516*0Sstevel@tonic-gate */ 517*0Sstevel@tonic-gate pr_defect(work_list.list + i, i); 518*0Sstevel@tonic-gate } 519*0Sstevel@tonic-gate fmt_print("total of %d defects.\n\n", i); 520*0Sstevel@tonic-gate /* 521*0Sstevel@tonic-gate * If we were doing paging, turn echoing back on. 522*0Sstevel@tonic-gate */ 523*0Sstevel@tonic-gate PRINT_EXIT: 524*0Sstevel@tonic-gate if (!nomore) { 525*0Sstevel@tonic-gate enter_critical(); 526*0Sstevel@tonic-gate charmode_off(); 527*0Sstevel@tonic-gate echo_on(); 528*0Sstevel@tonic-gate exit_critical(); 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate return (0); 531*0Sstevel@tonic-gate } 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate /* 534*0Sstevel@tonic-gate * This routine implements the 'dump' command. It writes the working 535*0Sstevel@tonic-gate * defect list to a file. 536*0Sstevel@tonic-gate */ 537*0Sstevel@tonic-gate int 538*0Sstevel@tonic-gate d_dump() 539*0Sstevel@tonic-gate { 540*0Sstevel@tonic-gate int i, status = 0; 541*0Sstevel@tonic-gate char *str; 542*0Sstevel@tonic-gate FILE *fptr; 543*0Sstevel@tonic-gate struct defect_entry *dptr; 544*0Sstevel@tonic-gate 545*0Sstevel@tonic-gate /* 546*0Sstevel@tonic-gate * If the working list is null, there's nothing to do. 547*0Sstevel@tonic-gate */ 548*0Sstevel@tonic-gate if (work_list.list == NULL) { 549*0Sstevel@tonic-gate if (EMBEDDED_SCSI) 550*0Sstevel@tonic-gate err_print( 551*0Sstevel@tonic-gate "No list defined,extract primary or grown or both defects list first.\n"); 552*0Sstevel@tonic-gate else 553*0Sstevel@tonic-gate err_print("No working list defined.\n"); 554*0Sstevel@tonic-gate return (-1); 555*0Sstevel@tonic-gate } 556*0Sstevel@tonic-gate /* 557*0Sstevel@tonic-gate * Ask the user for the name of the defect file. Note that the 558*0Sstevel@tonic-gate * input will be in malloc'd space since we are inputting 559*0Sstevel@tonic-gate * type OSTR. 560*0Sstevel@tonic-gate */ 561*0Sstevel@tonic-gate str = (char *)input(FIO_OSTR, "Enter name of defect file", ':', 562*0Sstevel@tonic-gate (u_ioparam_t *)NULL, (int *)NULL, DATA_INPUT); 563*0Sstevel@tonic-gate /* 564*0Sstevel@tonic-gate * Lock out interrupts so the file doesn't get half written. 565*0Sstevel@tonic-gate */ 566*0Sstevel@tonic-gate enter_critical(); 567*0Sstevel@tonic-gate /* 568*0Sstevel@tonic-gate * Open the file for writing. 569*0Sstevel@tonic-gate */ 570*0Sstevel@tonic-gate if ((fptr = fopen(str, "w+")) == NULL) { 571*0Sstevel@tonic-gate err_print("unable to open defect file.\n"); 572*0Sstevel@tonic-gate status = -1; 573*0Sstevel@tonic-gate goto out; 574*0Sstevel@tonic-gate } 575*0Sstevel@tonic-gate /* 576*0Sstevel@tonic-gate * Print a header containing the magic number, count, and checksum. 577*0Sstevel@tonic-gate */ 578*0Sstevel@tonic-gate (void) fprintf(fptr, "0x%08x%8d 0x%08x\n", 579*0Sstevel@tonic-gate work_list.header.magicno, 580*0Sstevel@tonic-gate work_list.header.count, work_list.header.cksum); 581*0Sstevel@tonic-gate /* 582*0Sstevel@tonic-gate * Loop through each defect in the working list. Write the 583*0Sstevel@tonic-gate * defect info to the defect file. 584*0Sstevel@tonic-gate */ 585*0Sstevel@tonic-gate for (i = 0; i < work_list.header.count; i++) { 586*0Sstevel@tonic-gate dptr = work_list.list + i; 587*0Sstevel@tonic-gate (void) fprintf(fptr, "%4d%8d%7d%8d%8d%8d\n", 588*0Sstevel@tonic-gate i+1, dptr->cyl, dptr->head, 589*0Sstevel@tonic-gate dptr->bfi, dptr->nbits, dptr->sect); 590*0Sstevel@tonic-gate } 591*0Sstevel@tonic-gate fmt_print("defect file updated, total of %d defects.\n", i); 592*0Sstevel@tonic-gate /* 593*0Sstevel@tonic-gate * Close the defect file. 594*0Sstevel@tonic-gate */ 595*0Sstevel@tonic-gate (void) fclose(fptr); 596*0Sstevel@tonic-gate out: 597*0Sstevel@tonic-gate /* 598*0Sstevel@tonic-gate * Destroy the string used for the file name. 599*0Sstevel@tonic-gate */ 600*0Sstevel@tonic-gate destroy_data(str); 601*0Sstevel@tonic-gate exit_critical(); 602*0Sstevel@tonic-gate fmt_print("\n"); 603*0Sstevel@tonic-gate return (status); 604*0Sstevel@tonic-gate } 605*0Sstevel@tonic-gate 606*0Sstevel@tonic-gate /* 607*0Sstevel@tonic-gate * This routine implements the 'load' command. It reads the working 608*0Sstevel@tonic-gate * list in from a file. 609*0Sstevel@tonic-gate */ 610*0Sstevel@tonic-gate int 611*0Sstevel@tonic-gate d_load() 612*0Sstevel@tonic-gate { 613*0Sstevel@tonic-gate int i, items, status = 0, count, cksum; 614*0Sstevel@tonic-gate uint_t magicno; 615*0Sstevel@tonic-gate char *str; 616*0Sstevel@tonic-gate TOKEN filename; 617*0Sstevel@tonic-gate FILE *fptr; 618*0Sstevel@tonic-gate struct defect_entry *dptr; 619*0Sstevel@tonic-gate 620*0Sstevel@tonic-gate assert(!EMBEDDED_SCSI); 621*0Sstevel@tonic-gate 622*0Sstevel@tonic-gate /* 623*0Sstevel@tonic-gate * Ask the user for the name of the defect file. Note that the 624*0Sstevel@tonic-gate * input will be malloc'd space since we inputted type OSTR. 625*0Sstevel@tonic-gate */ 626*0Sstevel@tonic-gate str = (char *)input(FIO_OSTR, "Enter name of defect file", ':', 627*0Sstevel@tonic-gate (u_ioparam_t *)NULL, (int *)NULL, DATA_INPUT); 628*0Sstevel@tonic-gate /* 629*0Sstevel@tonic-gate * Copy the file name into local space then destroy the string 630*0Sstevel@tonic-gate * it came in. This is simply a precaution against later having 631*0Sstevel@tonic-gate * to remember to destroy this space. 632*0Sstevel@tonic-gate */ 633*0Sstevel@tonic-gate enter_critical(); 634*0Sstevel@tonic-gate (void) strcpy(filename, str); 635*0Sstevel@tonic-gate destroy_data(str); 636*0Sstevel@tonic-gate exit_critical(); 637*0Sstevel@tonic-gate /* 638*0Sstevel@tonic-gate * See if the defect file is accessable. If not, we can't load 639*0Sstevel@tonic-gate * from it. We do this here just so we can get out before asking 640*0Sstevel@tonic-gate * the user for confirmation. 641*0Sstevel@tonic-gate */ 642*0Sstevel@tonic-gate status = access(filename, 4); 643*0Sstevel@tonic-gate if (status) { 644*0Sstevel@tonic-gate err_print("defect file not accessable.\n"); 645*0Sstevel@tonic-gate return (-1); 646*0Sstevel@tonic-gate } 647*0Sstevel@tonic-gate /* 648*0Sstevel@tonic-gate * Make sure the user is serious. 649*0Sstevel@tonic-gate */ 650*0Sstevel@tonic-gate if (check("ready to update working list, continue")) 651*0Sstevel@tonic-gate return (-1); 652*0Sstevel@tonic-gate /* 653*0Sstevel@tonic-gate * Lock out interrupts so the list doesn't get half loaded. 654*0Sstevel@tonic-gate */ 655*0Sstevel@tonic-gate enter_critical(); 656*0Sstevel@tonic-gate /* 657*0Sstevel@tonic-gate * Open the defect file. 658*0Sstevel@tonic-gate */ 659*0Sstevel@tonic-gate if ((fptr = fopen(filename, "r")) == NULL) { 660*0Sstevel@tonic-gate err_print("unable to open defect file.\n"); 661*0Sstevel@tonic-gate exit_critical(); 662*0Sstevel@tonic-gate return (-1); 663*0Sstevel@tonic-gate } 664*0Sstevel@tonic-gate /* 665*0Sstevel@tonic-gate * Scan in the header. 666*0Sstevel@tonic-gate */ 667*0Sstevel@tonic-gate items = fscanf(fptr, "0x%x%d 0x%x\n", &magicno, 668*0Sstevel@tonic-gate &count, (uint_t *)&cksum); 669*0Sstevel@tonic-gate /* 670*0Sstevel@tonic-gate * If the header is wrong, this isn't a good defect file. 671*0Sstevel@tonic-gate */ 672*0Sstevel@tonic-gate if (items != 3 || count < 0 || 673*0Sstevel@tonic-gate (magicno != (uint_t)DEFECT_MAGIC && 674*0Sstevel@tonic-gate magicno != (uint_t)NO_CHECKSUM)) { 675*0Sstevel@tonic-gate err_print("Defect file is corrupted.\n"); 676*0Sstevel@tonic-gate status = -1; 677*0Sstevel@tonic-gate goto out; 678*0Sstevel@tonic-gate } 679*0Sstevel@tonic-gate /* 680*0Sstevel@tonic-gate * Kill off any old defects in the working list. 681*0Sstevel@tonic-gate */ 682*0Sstevel@tonic-gate kill_deflist(&work_list); 683*0Sstevel@tonic-gate /* 684*0Sstevel@tonic-gate * Load the working list header with the header info. 685*0Sstevel@tonic-gate */ 686*0Sstevel@tonic-gate if (magicno == NO_CHECKSUM) 687*0Sstevel@tonic-gate work_list.header.magicno = (uint_t)DEFECT_MAGIC; 688*0Sstevel@tonic-gate else 689*0Sstevel@tonic-gate work_list.header.magicno = magicno; 690*0Sstevel@tonic-gate work_list.header.count = count; 691*0Sstevel@tonic-gate work_list.header.cksum = cksum; 692*0Sstevel@tonic-gate /* 693*0Sstevel@tonic-gate * Allocate space for the new list. 694*0Sstevel@tonic-gate */ 695*0Sstevel@tonic-gate work_list.list = (struct defect_entry *)zalloc(LISTSIZE(count) * 696*0Sstevel@tonic-gate SECSIZE); 697*0Sstevel@tonic-gate /* 698*0Sstevel@tonic-gate * Mark the working list dirty since we are modifying it. 699*0Sstevel@tonic-gate */ 700*0Sstevel@tonic-gate work_list.flags |= LIST_DIRTY; 701*0Sstevel@tonic-gate /* 702*0Sstevel@tonic-gate * Loop through each defect in the defect file. 703*0Sstevel@tonic-gate */ 704*0Sstevel@tonic-gate for (i = 0; i < count; i++) { 705*0Sstevel@tonic-gate dptr = work_list.list + i; 706*0Sstevel@tonic-gate /* 707*0Sstevel@tonic-gate * Scan the info into the defect entry. 708*0Sstevel@tonic-gate */ 709*0Sstevel@tonic-gate items = fscanf(fptr, "%*d%hd%hd%d%hd%hd\n", &dptr->cyl, 710*0Sstevel@tonic-gate &dptr->head, &dptr->bfi, &dptr->nbits, &dptr->sect); 711*0Sstevel@tonic-gate /* 712*0Sstevel@tonic-gate * If it didn't scan right, give up. 713*0Sstevel@tonic-gate */ 714*0Sstevel@tonic-gate if (items != 5) 715*0Sstevel@tonic-gate goto bad; 716*0Sstevel@tonic-gate } 717*0Sstevel@tonic-gate /* 718*0Sstevel@tonic-gate * Check to be sure the checksum from the defect file was correct 719*0Sstevel@tonic-gate * unless there wasn't supposed to be a checksum. 720*0Sstevel@tonic-gate * If there was supposed to be a valid checksum and there isn't 721*0Sstevel@tonic-gate * then give up. 722*0Sstevel@tonic-gate */ 723*0Sstevel@tonic-gate if (magicno != NO_CHECKSUM && checkdefsum(&work_list, CK_CHECKSUM)) 724*0Sstevel@tonic-gate goto bad; 725*0Sstevel@tonic-gate fmt_print("working list updated, total of %d defects.\n", i); 726*0Sstevel@tonic-gate goto out; 727*0Sstevel@tonic-gate 728*0Sstevel@tonic-gate bad: 729*0Sstevel@tonic-gate /* 730*0Sstevel@tonic-gate * Some kind of error occurred. Kill off the working list and 731*0Sstevel@tonic-gate * mark the status bad. 732*0Sstevel@tonic-gate */ 733*0Sstevel@tonic-gate err_print("Defect file is corrupted, working list set to NULL.\n"); 734*0Sstevel@tonic-gate kill_deflist(&work_list); 735*0Sstevel@tonic-gate status = -1; 736*0Sstevel@tonic-gate out: 737*0Sstevel@tonic-gate /* 738*0Sstevel@tonic-gate * Close the defect file. 739*0Sstevel@tonic-gate */ 740*0Sstevel@tonic-gate (void) fclose(fptr); 741*0Sstevel@tonic-gate exit_critical(); 742*0Sstevel@tonic-gate fmt_print("\n"); 743*0Sstevel@tonic-gate return (status); 744*0Sstevel@tonic-gate } 745*0Sstevel@tonic-gate 746*0Sstevel@tonic-gate /* 747*0Sstevel@tonic-gate * This routine implements the 'commit' command. It causes the current 748*0Sstevel@tonic-gate * defect list to be set equal to the working defect list. It is the only 749*0Sstevel@tonic-gate * way that changes made to the working list can actually take effect in 750*0Sstevel@tonic-gate * the next format. 751*0Sstevel@tonic-gate */ 752*0Sstevel@tonic-gate int 753*0Sstevel@tonic-gate d_commit() 754*0Sstevel@tonic-gate { 755*0Sstevel@tonic-gate /* 756*0Sstevel@tonic-gate * If the working list wasn't modified, no commit is necessary. 757*0Sstevel@tonic-gate */ 758*0Sstevel@tonic-gate if (work_list.list != NULL && !(work_list.flags & LIST_DIRTY)) { 759*0Sstevel@tonic-gate err_print("working list was not modified.\n"); 760*0Sstevel@tonic-gate return (0); 761*0Sstevel@tonic-gate } 762*0Sstevel@tonic-gate 763*0Sstevel@tonic-gate /* 764*0Sstevel@tonic-gate * Make sure the user is serious. 765*0Sstevel@tonic-gate */ 766*0Sstevel@tonic-gate if (check("Ready to update Current Defect List, continue")) 767*0Sstevel@tonic-gate return (-1); 768*0Sstevel@tonic-gate return (do_commit()); 769*0Sstevel@tonic-gate } 770*0Sstevel@tonic-gate 771*0Sstevel@tonic-gate int 772*0Sstevel@tonic-gate do_commit() 773*0Sstevel@tonic-gate { 774*0Sstevel@tonic-gate int status; 775*0Sstevel@tonic-gate 776*0Sstevel@tonic-gate if ((status = commit_list()) == 0) { 777*0Sstevel@tonic-gate /* 778*0Sstevel@tonic-gate * Remind the user to format the drive, since changing 779*0Sstevel@tonic-gate * the list does nothing unless a format is performed. 780*0Sstevel@tonic-gate */ 781*0Sstevel@tonic-gate fmt_print(\ 782*0Sstevel@tonic-gate "Disk must be reformatted for changes to take effect.\n\n"); 783*0Sstevel@tonic-gate } 784*0Sstevel@tonic-gate return (status); 785*0Sstevel@tonic-gate } 786*0Sstevel@tonic-gate 787*0Sstevel@tonic-gate 788*0Sstevel@tonic-gate static int 789*0Sstevel@tonic-gate commit_list() 790*0Sstevel@tonic-gate { 791*0Sstevel@tonic-gate int i; 792*0Sstevel@tonic-gate 793*0Sstevel@tonic-gate /* 794*0Sstevel@tonic-gate * Lock out interrupts so the list doesn't get half copied. 795*0Sstevel@tonic-gate */ 796*0Sstevel@tonic-gate enter_critical(); 797*0Sstevel@tonic-gate /* 798*0Sstevel@tonic-gate * Kill off any current defect list. 799*0Sstevel@tonic-gate */ 800*0Sstevel@tonic-gate kill_deflist(&cur_list); 801*0Sstevel@tonic-gate /* 802*0Sstevel@tonic-gate * If the working list is null, initialize it to zero length. 803*0Sstevel@tonic-gate * This is so the user can do a commit on a null list and get 804*0Sstevel@tonic-gate * a zero length list. Otherwise there would be no way to get 805*0Sstevel@tonic-gate * a zero length list conveniently. 806*0Sstevel@tonic-gate */ 807*0Sstevel@tonic-gate if (work_list.list == NULL) { 808*0Sstevel@tonic-gate work_list.header.magicno = (uint_t)DEFECT_MAGIC; 809*0Sstevel@tonic-gate work_list.header.count = 0; 810*0Sstevel@tonic-gate work_list.list = (struct defect_entry *)zalloc( 811*0Sstevel@tonic-gate LISTSIZE(0) * SECSIZE); 812*0Sstevel@tonic-gate } 813*0Sstevel@tonic-gate /* 814*0Sstevel@tonic-gate * Copy the working list into the current list. 815*0Sstevel@tonic-gate */ 816*0Sstevel@tonic-gate cur_list.header = work_list.header; 817*0Sstevel@tonic-gate cur_list.list = (struct defect_entry *)zalloc( 818*0Sstevel@tonic-gate LISTSIZE(cur_list.header.count) * SECSIZE); 819*0Sstevel@tonic-gate for (i = 0; i < cur_list.header.count; i++) 820*0Sstevel@tonic-gate *(cur_list.list + i) = *(work_list.list + i); 821*0Sstevel@tonic-gate /* 822*0Sstevel@tonic-gate * Mark the working list clean, since it is now the same as the 823*0Sstevel@tonic-gate * current list. Note we do not mark the current list dirty, 824*0Sstevel@tonic-gate * even though it has been changed. This is because it does 825*0Sstevel@tonic-gate * not reflect the state of disk, so we don't want it written 826*0Sstevel@tonic-gate * out until a format has been done. The format will mark it 827*0Sstevel@tonic-gate * dirty and write it out. 828*0Sstevel@tonic-gate */ 829*0Sstevel@tonic-gate work_list.flags &= ~(LIST_DIRTY|LIST_RELOAD); 830*0Sstevel@tonic-gate cur_list.flags = work_list.flags; 831*0Sstevel@tonic-gate if (EMBEDDED_SCSI) 832*0Sstevel@tonic-gate fmt_print("Defect List has a total of %d defects.\n", 833*0Sstevel@tonic-gate cur_list.header.count); 834*0Sstevel@tonic-gate else 835*0Sstevel@tonic-gate fmt_print("Current Defect List updated, total of %d defects.\n", 836*0Sstevel@tonic-gate cur_list.header.count); 837*0Sstevel@tonic-gate exit_critical(); 838*0Sstevel@tonic-gate return (0); 839*0Sstevel@tonic-gate } 840*0Sstevel@tonic-gate 841*0Sstevel@tonic-gate 842*0Sstevel@tonic-gate /* 843*0Sstevel@tonic-gate * This routine implements the 'create' command. It creates the 844*0Sstevel@tonic-gate * manufacturer's defect on the current disk from the defect list 845*0Sstevel@tonic-gate */ 846*0Sstevel@tonic-gate int 847*0Sstevel@tonic-gate d_create() 848*0Sstevel@tonic-gate { 849*0Sstevel@tonic-gate int status; 850*0Sstevel@tonic-gate 851*0Sstevel@tonic-gate assert(!EMBEDDED_SCSI); 852*0Sstevel@tonic-gate 853*0Sstevel@tonic-gate /* 854*0Sstevel@tonic-gate * If the controller does not support the extraction, we're out 855*0Sstevel@tonic-gate * of luck. 856*0Sstevel@tonic-gate */ 857*0Sstevel@tonic-gate if (cur_ops->op_create == NULL) { 858*0Sstevel@tonic-gate err_print("Controller does not support creating "); 859*0Sstevel@tonic-gate err_print("manufacturer's defect list.\n"); 860*0Sstevel@tonic-gate return (-1); 861*0Sstevel@tonic-gate } 862*0Sstevel@tonic-gate /* 863*0Sstevel@tonic-gate * Make sure the user is serious. Note, for SCSI disks 864*0Sstevel@tonic-gate * since this is instantaneous, we will just do it and 865*0Sstevel@tonic-gate * not ask for confirmation. 866*0Sstevel@tonic-gate */ 867*0Sstevel@tonic-gate if (! (cur_ctype->ctype_flags & CF_SCSI) && 868*0Sstevel@tonic-gate check( 869*0Sstevel@tonic-gate "Ready to create the manufacturers defect information on the disk.\n\ 870*0Sstevel@tonic-gate This cannot be interrupted and may take a long while.\n\ 871*0Sstevel@tonic-gate IT WILL DESTROY ALL OF THE DATA ON THE DISK! Continue")) 872*0Sstevel@tonic-gate return (-1); 873*0Sstevel@tonic-gate /* 874*0Sstevel@tonic-gate * Lock out interrupts so we don't get half the list. 875*0Sstevel@tonic-gate */ 876*0Sstevel@tonic-gate enter_critical(); 877*0Sstevel@tonic-gate fmt_print("Creating manufacturer's defect list..."); 878*0Sstevel@tonic-gate /* 879*0Sstevel@tonic-gate * Do the Creation 880*0Sstevel@tonic-gate */ 881*0Sstevel@tonic-gate status = (*cur_ops->op_create)(&work_list); 882*0Sstevel@tonic-gate if (status) { 883*0Sstevel@tonic-gate fmt_print("Creation failed.\n\n"); 884*0Sstevel@tonic-gate } else { 885*0Sstevel@tonic-gate fmt_print("Creation complete.\n"); 886*0Sstevel@tonic-gate } 887*0Sstevel@tonic-gate exit_critical(); 888*0Sstevel@tonic-gate /* 889*0Sstevel@tonic-gate * Return status. 890*0Sstevel@tonic-gate */ 891*0Sstevel@tonic-gate return (status); 892*0Sstevel@tonic-gate } 893*0Sstevel@tonic-gate 894*0Sstevel@tonic-gate 895*0Sstevel@tonic-gate /* 896*0Sstevel@tonic-gate * Extract primary defect list - SCSI only 897*0Sstevel@tonic-gate */ 898*0Sstevel@tonic-gate int 899*0Sstevel@tonic-gate d_primary() 900*0Sstevel@tonic-gate { 901*0Sstevel@tonic-gate int status; 902*0Sstevel@tonic-gate 903*0Sstevel@tonic-gate assert(EMBEDDED_SCSI); 904*0Sstevel@tonic-gate 905*0Sstevel@tonic-gate /* 906*0Sstevel@tonic-gate * Lock out interrupts so we don't get half the list and 907*0Sstevel@tonic-gate * Kill off the working list. 908*0Sstevel@tonic-gate */ 909*0Sstevel@tonic-gate enter_critical(); 910*0Sstevel@tonic-gate kill_deflist(&work_list); 911*0Sstevel@tonic-gate fmt_print("Extracting primary defect list..."); 912*0Sstevel@tonic-gate 913*0Sstevel@tonic-gate /* 914*0Sstevel@tonic-gate * Do the extraction. 915*0Sstevel@tonic-gate */ 916*0Sstevel@tonic-gate status = scsi_ex_man(&work_list); 917*0Sstevel@tonic-gate if (status) { 918*0Sstevel@tonic-gate fmt_print("Extraction failed.\n\n"); 919*0Sstevel@tonic-gate } else { 920*0Sstevel@tonic-gate fmt_print("Extraction complete.\n"); 921*0Sstevel@tonic-gate /* 922*0Sstevel@tonic-gate * Mark the working list dirty since we modified it. 923*0Sstevel@tonic-gate * Automatically commit it, for SCSI only. 924*0Sstevel@tonic-gate */ 925*0Sstevel@tonic-gate work_list.flags |= LIST_DIRTY; 926*0Sstevel@tonic-gate status = commit_list(); 927*0Sstevel@tonic-gate fmt_print("\n"); 928*0Sstevel@tonic-gate } 929*0Sstevel@tonic-gate exit_critical(); 930*0Sstevel@tonic-gate 931*0Sstevel@tonic-gate /* 932*0Sstevel@tonic-gate * Return status. 933*0Sstevel@tonic-gate */ 934*0Sstevel@tonic-gate return (status); 935*0Sstevel@tonic-gate } 936*0Sstevel@tonic-gate 937*0Sstevel@tonic-gate 938*0Sstevel@tonic-gate /* 939*0Sstevel@tonic-gate * Extract grown defects list - SCSI only 940*0Sstevel@tonic-gate */ 941*0Sstevel@tonic-gate int 942*0Sstevel@tonic-gate d_grown() 943*0Sstevel@tonic-gate { 944*0Sstevel@tonic-gate int status; 945*0Sstevel@tonic-gate 946*0Sstevel@tonic-gate assert(EMBEDDED_SCSI); 947*0Sstevel@tonic-gate 948*0Sstevel@tonic-gate /* 949*0Sstevel@tonic-gate * Lock out interrupts so we don't get half the list and 950*0Sstevel@tonic-gate * Kill off the working list. 951*0Sstevel@tonic-gate */ 952*0Sstevel@tonic-gate enter_critical(); 953*0Sstevel@tonic-gate kill_deflist(&work_list); 954*0Sstevel@tonic-gate fmt_print("Extracting grown defects list..."); 955*0Sstevel@tonic-gate 956*0Sstevel@tonic-gate /* 957*0Sstevel@tonic-gate * Do the extraction. 958*0Sstevel@tonic-gate */ 959*0Sstevel@tonic-gate status = scsi_ex_grown(&work_list); 960*0Sstevel@tonic-gate if (status) { 961*0Sstevel@tonic-gate fmt_print("Extraction failed.\n\n"); 962*0Sstevel@tonic-gate } else { 963*0Sstevel@tonic-gate fmt_print("Extraction complete.\n"); 964*0Sstevel@tonic-gate /* 965*0Sstevel@tonic-gate * Mark the working list dirty since we modified it. 966*0Sstevel@tonic-gate * Automatically commit it, for SCSI only. 967*0Sstevel@tonic-gate */ 968*0Sstevel@tonic-gate work_list.flags |= LIST_DIRTY; 969*0Sstevel@tonic-gate status = commit_list(); 970*0Sstevel@tonic-gate fmt_print("\n"); 971*0Sstevel@tonic-gate } 972*0Sstevel@tonic-gate exit_critical(); 973*0Sstevel@tonic-gate 974*0Sstevel@tonic-gate /* 975*0Sstevel@tonic-gate * Return status. 976*0Sstevel@tonic-gate */ 977*0Sstevel@tonic-gate return (status); 978*0Sstevel@tonic-gate } 979*0Sstevel@tonic-gate 980*0Sstevel@tonic-gate 981*0Sstevel@tonic-gate /* 982*0Sstevel@tonic-gate * Extract both primary and grown defects list - SCSI only 983*0Sstevel@tonic-gate */ 984*0Sstevel@tonic-gate int 985*0Sstevel@tonic-gate d_both() 986*0Sstevel@tonic-gate { 987*0Sstevel@tonic-gate int status; 988*0Sstevel@tonic-gate 989*0Sstevel@tonic-gate assert(EMBEDDED_SCSI); 990*0Sstevel@tonic-gate 991*0Sstevel@tonic-gate /* 992*0Sstevel@tonic-gate * Lock out interrupts so we don't get half the list and 993*0Sstevel@tonic-gate * Kill off the working list. 994*0Sstevel@tonic-gate */ 995*0Sstevel@tonic-gate enter_critical(); 996*0Sstevel@tonic-gate kill_deflist(&work_list); 997*0Sstevel@tonic-gate fmt_print("Extracting both primary and grown defects lists..."); 998*0Sstevel@tonic-gate 999*0Sstevel@tonic-gate /* 1000*0Sstevel@tonic-gate * Do the extraction. 1001*0Sstevel@tonic-gate */ 1002*0Sstevel@tonic-gate status = scsi_ex_cur(&work_list); 1003*0Sstevel@tonic-gate if (status) { 1004*0Sstevel@tonic-gate fmt_print("Extraction failed.\n\n"); 1005*0Sstevel@tonic-gate } else { 1006*0Sstevel@tonic-gate fmt_print("Extraction complete.\n"); 1007*0Sstevel@tonic-gate /* 1008*0Sstevel@tonic-gate * Mark the working list dirty since we modified it. 1009*0Sstevel@tonic-gate * Automatically commit it, for SCSI only. 1010*0Sstevel@tonic-gate */ 1011*0Sstevel@tonic-gate work_list.flags |= LIST_DIRTY; 1012*0Sstevel@tonic-gate status = commit_list(); 1013*0Sstevel@tonic-gate fmt_print("\n"); 1014*0Sstevel@tonic-gate } 1015*0Sstevel@tonic-gate exit_critical(); 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate /* 1018*0Sstevel@tonic-gate * Return status. 1019*0Sstevel@tonic-gate */ 1020*0Sstevel@tonic-gate return (status); 1021*0Sstevel@tonic-gate } 1022