1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1998-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate /* 30*7c478bd9Sstevel@tonic-gate * This file contains routines that manipulate the defect list. 31*7c478bd9Sstevel@tonic-gate */ 32*7c478bd9Sstevel@tonic-gate #include "global.h" 33*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #if defined(sparc) 37*7c478bd9Sstevel@tonic-gate #include <sys/hdio.h> 38*7c478bd9Sstevel@tonic-gate #endif /* defined(sparc) */ 39*7c478bd9Sstevel@tonic-gate 40*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/ioctl.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/fcntl.h> 44*7c478bd9Sstevel@tonic-gate #include <string.h> 45*7c478bd9Sstevel@tonic-gate #include <unistd.h> 46*7c478bd9Sstevel@tonic-gate #include <memory.h> 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #if defined(sparc) 49*7c478bd9Sstevel@tonic-gate #include <sys/dkbad.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/scsi/targets/sddef.h> 51*7c478bd9Sstevel@tonic-gate #endif /* defined(sparc) */ 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate #include "misc.h" 54*7c478bd9Sstevel@tonic-gate #include "param.h" 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate 57*7c478bd9Sstevel@tonic-gate #if defined(sparc) 58*7c478bd9Sstevel@tonic-gate /* 59*7c478bd9Sstevel@tonic-gate * This structure is the bad block table for the current disk if 60*7c478bd9Sstevel@tonic-gate * the disk uses bad-144 defect mapping. 61*7c478bd9Sstevel@tonic-gate */ 62*7c478bd9Sstevel@tonic-gate struct dkbad badmap; 63*7c478bd9Sstevel@tonic-gate #endif /* defined(sparc) */ 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate /* 66*7c478bd9Sstevel@tonic-gate * This routine reads the defect list off the disk. It also reads in the 67*7c478bd9Sstevel@tonic-gate * bad block table if the disk is a BAD144 type. The defect list is 68*7c478bd9Sstevel@tonic-gate * located on the first 2 tracks of the 2nd alternate cylinder of all 69*7c478bd9Sstevel@tonic-gate * disks. The bad block map is located on the first 5 even sectors of 70*7c478bd9Sstevel@tonic-gate * the last track of the last cylinder. 71*7c478bd9Sstevel@tonic-gate */ 72*7c478bd9Sstevel@tonic-gate void 73*7c478bd9Sstevel@tonic-gate read_list(struct defect_list *list) 74*7c478bd9Sstevel@tonic-gate { 75*7c478bd9Sstevel@tonic-gate int size, head; 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate #if defined(sparc) 78*7c478bd9Sstevel@tonic-gate int sec, status; 79*7c478bd9Sstevel@tonic-gate struct bt_bad *bt; 80*7c478bd9Sstevel@tonic-gate #endif /* defined(sparc) */ 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate assert(!EMBEDDED_SCSI); 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate /* 85*7c478bd9Sstevel@tonic-gate * This flags has been introduced only for Sparc ATA IDE. 86*7c478bd9Sstevel@tonic-gate * This indicates that no list manipulation is done in this controller 87*7c478bd9Sstevel@tonic-gate * and hence return without any other checking. 88*7c478bd9Sstevel@tonic-gate */ 89*7c478bd9Sstevel@tonic-gate if (cur_ctype->ctype_flags & CF_NOWLIST) { 90*7c478bd9Sstevel@tonic-gate return; 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate /* 94*7c478bd9Sstevel@tonic-gate * Panther's working list is maintained by the controller 95*7c478bd9Sstevel@tonic-gate */ 96*7c478bd9Sstevel@tonic-gate if (cur_ctype->ctype_flags & CF_WLIST) { 97*7c478bd9Sstevel@tonic-gate if (*cur_ops->op_ex_cur != NULL && 98*7c478bd9Sstevel@tonic-gate ((*cur_ops->op_ex_cur)(list)) == 0) { 99*7c478bd9Sstevel@tonic-gate if (list->header.magicno != DEFECT_MAGIC) { 100*7c478bd9Sstevel@tonic-gate fmt_print("Defect list BAD\n"); 101*7c478bd9Sstevel@tonic-gate } else { 102*7c478bd9Sstevel@tonic-gate fmt_print("Controller working list found\n"); 103*7c478bd9Sstevel@tonic-gate } 104*7c478bd9Sstevel@tonic-gate return; 105*7c478bd9Sstevel@tonic-gate } 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate if (*cur_ops->op_ex_man != NULL && 108*7c478bd9Sstevel@tonic-gate ((*cur_ops->op_ex_man)(list)) == 0) { 109*7c478bd9Sstevel@tonic-gate if (list->header.magicno != DEFECT_MAGIC) { 110*7c478bd9Sstevel@tonic-gate fmt_print("Defect list BAD\n"); 111*7c478bd9Sstevel@tonic-gate } else { 112*7c478bd9Sstevel@tonic-gate fmt_print("MANUFACTURER's list found\n"); 113*7c478bd9Sstevel@tonic-gate } 114*7c478bd9Sstevel@tonic-gate return; 115*7c478bd9Sstevel@tonic-gate } 116*7c478bd9Sstevel@tonic-gate fmt_print("No defect list found\n"); 117*7c478bd9Sstevel@tonic-gate return; 118*7c478bd9Sstevel@tonic-gate } 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate /* 121*7c478bd9Sstevel@tonic-gate * Loop for each copy of the defect list until we get a good one. 122*7c478bd9Sstevel@tonic-gate */ 123*7c478bd9Sstevel@tonic-gate for (head = 0; head < LISTCOUNT; head++) { 124*7c478bd9Sstevel@tonic-gate /* 125*7c478bd9Sstevel@tonic-gate * Try to read the list header. 126*7c478bd9Sstevel@tonic-gate */ 127*7c478bd9Sstevel@tonic-gate if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, 128*7c478bd9Sstevel@tonic-gate (diskaddr_t)chs2bn(ncyl + 1, head, 0), 1, 129*7c478bd9Sstevel@tonic-gate (char *)&list->header, NULL), F_NORMAL) 130*7c478bd9Sstevel@tonic-gate continue; 131*7c478bd9Sstevel@tonic-gate /* 132*7c478bd9Sstevel@tonic-gate * If the magic number is wrong, this copy is corrupt. 133*7c478bd9Sstevel@tonic-gate */ 134*7c478bd9Sstevel@tonic-gate if (list->header.magicno != DEFECT_MAGIC) 135*7c478bd9Sstevel@tonic-gate continue; 136*7c478bd9Sstevel@tonic-gate /* 137*7c478bd9Sstevel@tonic-gate * Allocate space for the rest of the list. 138*7c478bd9Sstevel@tonic-gate */ 139*7c478bd9Sstevel@tonic-gate size = LISTSIZE(list->header.count); 140*7c478bd9Sstevel@tonic-gate list->list = (struct defect_entry *)zalloc(size * SECSIZE); 141*7c478bd9Sstevel@tonic-gate /* 142*7c478bd9Sstevel@tonic-gate * Try to read in the rest of the list. If there is an 143*7c478bd9Sstevel@tonic-gate * error, or the checksum is wrong, this copy is corrupt. 144*7c478bd9Sstevel@tonic-gate */ 145*7c478bd9Sstevel@tonic-gate if ((*cur_ops->op_rdwr)(DIR_READ, cur_file, 146*7c478bd9Sstevel@tonic-gate (diskaddr_t)chs2bn(ncyl + 1, head, 1), size, 147*7c478bd9Sstevel@tonic-gate (char *)list->list, F_NORMAL, NULL) || 148*7c478bd9Sstevel@tonic-gate checkdefsum(list, CK_CHECKSUM)) { 149*7c478bd9Sstevel@tonic-gate /* 150*7c478bd9Sstevel@tonic-gate * Destroy the list and go on. 151*7c478bd9Sstevel@tonic-gate */ 152*7c478bd9Sstevel@tonic-gate kill_deflist(list); 153*7c478bd9Sstevel@tonic-gate continue; 154*7c478bd9Sstevel@tonic-gate } 155*7c478bd9Sstevel@tonic-gate /* 156*7c478bd9Sstevel@tonic-gate * Got a good copy, stop searching. 157*7c478bd9Sstevel@tonic-gate */ 158*7c478bd9Sstevel@tonic-gate break; 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate #if defined(sparc) 161*7c478bd9Sstevel@tonic-gate if (!(cur_ctlr->ctlr_flags & DKI_BAD144)) 162*7c478bd9Sstevel@tonic-gate return; 163*7c478bd9Sstevel@tonic-gate /* 164*7c478bd9Sstevel@tonic-gate * The disk uses BAD144, read in the bad-block table. 165*7c478bd9Sstevel@tonic-gate */ 166*7c478bd9Sstevel@tonic-gate for (sec = 0; ((sec < BAD_LISTCNT * 2) && (sec < nsect)); sec += 2) { 167*7c478bd9Sstevel@tonic-gate status = (*cur_ops->op_rdwr)(DIR_READ, cur_file, 168*7c478bd9Sstevel@tonic-gate (diskaddr_t)chs2bn(ncyl + acyl - 1, nhead - 1, sec), 1, 169*7c478bd9Sstevel@tonic-gate &badmap, F_NORMAL, NULL); 170*7c478bd9Sstevel@tonic-gate if (status) 171*7c478bd9Sstevel@tonic-gate continue; 172*7c478bd9Sstevel@tonic-gate /* 173*7c478bd9Sstevel@tonic-gate * Do a sanity check on the list read in. If it passes, 174*7c478bd9Sstevel@tonic-gate * stop searching. 175*7c478bd9Sstevel@tonic-gate */ 176*7c478bd9Sstevel@tonic-gate if (badmap.bt_mbz != 0) 177*7c478bd9Sstevel@tonic-gate continue; 178*7c478bd9Sstevel@tonic-gate for (bt = badmap.bt_bad; bt - badmap.bt_bad < NDKBAD; bt++) { 179*7c478bd9Sstevel@tonic-gate if (bt->bt_cyl < 0) 180*7c478bd9Sstevel@tonic-gate break; 181*7c478bd9Sstevel@tonic-gate if (bt->bt_trksec < 0) 182*7c478bd9Sstevel@tonic-gate continue; 183*7c478bd9Sstevel@tonic-gate head = bt->bt_trksec >> 8; 184*7c478bd9Sstevel@tonic-gate if ((bt->bt_cyl >= pcyl) || (head >= nhead) || 185*7c478bd9Sstevel@tonic-gate ((bt->bt_trksec & 0xff) >= sectors(head))) { 186*7c478bd9Sstevel@tonic-gate status = -1; 187*7c478bd9Sstevel@tonic-gate break; 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate if (status) 191*7c478bd9Sstevel@tonic-gate continue; 192*7c478bd9Sstevel@tonic-gate return; 193*7c478bd9Sstevel@tonic-gate } 194*7c478bd9Sstevel@tonic-gate /* 195*7c478bd9Sstevel@tonic-gate * If we couldn't find the bad block table, initialize it to 196*7c478bd9Sstevel@tonic-gate * zero entries. 197*7c478bd9Sstevel@tonic-gate */ 198*7c478bd9Sstevel@tonic-gate for (bt = badmap.bt_bad; bt - badmap.bt_bad < NDKBAD; bt++) 199*7c478bd9Sstevel@tonic-gate bt->bt_cyl = bt->bt_trksec = -1; 200*7c478bd9Sstevel@tonic-gate badmap.bt_mbz = badmap.bt_csn = badmap.bt_flag = 0; 201*7c478bd9Sstevel@tonic-gate #endif /* defined(sparc) */ 202*7c478bd9Sstevel@tonic-gate } 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate /* 205*7c478bd9Sstevel@tonic-gate * This routine either checks or calculates the checksum for a defect 206*7c478bd9Sstevel@tonic-gate * list, depending on the mode parameter. In check mode, it returns 207*7c478bd9Sstevel@tonic-gate * whether or not the checksum is correct. 208*7c478bd9Sstevel@tonic-gate */ 209*7c478bd9Sstevel@tonic-gate int 210*7c478bd9Sstevel@tonic-gate checkdefsum(struct defect_list *list, int mode) 211*7c478bd9Sstevel@tonic-gate { 212*7c478bd9Sstevel@tonic-gate register int *lp, i, sum = 0; 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate /* 215*7c478bd9Sstevel@tonic-gate * Perform the rolling xor to get what the checksum should be. 216*7c478bd9Sstevel@tonic-gate */ 217*7c478bd9Sstevel@tonic-gate lp = (int *)list->list; 218*7c478bd9Sstevel@tonic-gate for (i = 0; i < (list->header.count * 219*7c478bd9Sstevel@tonic-gate sizeof (struct defect_entry) / sizeof (int)); i++) 220*7c478bd9Sstevel@tonic-gate sum ^= *(lp + i); 221*7c478bd9Sstevel@tonic-gate /* 222*7c478bd9Sstevel@tonic-gate * If in check mode, return whether header checksum was correct. 223*7c478bd9Sstevel@tonic-gate */ 224*7c478bd9Sstevel@tonic-gate if (mode == CK_CHECKSUM) 225*7c478bd9Sstevel@tonic-gate return (sum != list->header.cksum); 226*7c478bd9Sstevel@tonic-gate /* 227*7c478bd9Sstevel@tonic-gate * If in create mode, set the header checksum. 228*7c478bd9Sstevel@tonic-gate */ 229*7c478bd9Sstevel@tonic-gate else { 230*7c478bd9Sstevel@tonic-gate list->header.cksum = sum; 231*7c478bd9Sstevel@tonic-gate return (0); 232*7c478bd9Sstevel@tonic-gate } 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate /* 236*7c478bd9Sstevel@tonic-gate * This routine prints a single defect to stdout in a readable format. 237*7c478bd9Sstevel@tonic-gate */ 238*7c478bd9Sstevel@tonic-gate void 239*7c478bd9Sstevel@tonic-gate pr_defect(struct defect_entry *def, int num) 240*7c478bd9Sstevel@tonic-gate { 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate /* 243*7c478bd9Sstevel@tonic-gate * Make defect numbering look 1 relative. 244*7c478bd9Sstevel@tonic-gate */ 245*7c478bd9Sstevel@tonic-gate ++num; 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * Print out common values. 248*7c478bd9Sstevel@tonic-gate */ 249*7c478bd9Sstevel@tonic-gate fmt_print("%4d%8d%7d", num, def->cyl, def->head); 250*7c478bd9Sstevel@tonic-gate /* 251*7c478bd9Sstevel@tonic-gate * The rest of the values may be unknown. If they are, just 252*7c478bd9Sstevel@tonic-gate * print blanks instead. Also, only print length only if bfi is 253*7c478bd9Sstevel@tonic-gate * known, and assume that a known bfi implies an unknown sect. 254*7c478bd9Sstevel@tonic-gate */ 255*7c478bd9Sstevel@tonic-gate if (def->bfi != UNKNOWN) { 256*7c478bd9Sstevel@tonic-gate fmt_print("%8d", def->bfi); 257*7c478bd9Sstevel@tonic-gate if (def->nbits != UNKNOWN) 258*7c478bd9Sstevel@tonic-gate fmt_print("%8d", def->nbits); 259*7c478bd9Sstevel@tonic-gate } else { 260*7c478bd9Sstevel@tonic-gate fmt_print(" "); 261*7c478bd9Sstevel@tonic-gate fmt_print("%8d", def->sect); 262*7c478bd9Sstevel@tonic-gate fmt_print("%8lu", chs2bn(def->cyl, def->head, def->sect)); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate fmt_print("\n"); 265*7c478bd9Sstevel@tonic-gate } 266*7c478bd9Sstevel@tonic-gate 267*7c478bd9Sstevel@tonic-gate /* 268*7c478bd9Sstevel@tonic-gate * This routine calculates where in a defect list a given defect should 269*7c478bd9Sstevel@tonic-gate * be sorted. It returns the index that the defect should become. The 270*7c478bd9Sstevel@tonic-gate * algorithm used sorts all bfi based defects by cylinder/head/bfi, and 271*7c478bd9Sstevel@tonic-gate * adds all logical sector defects to the end of the list. This is 272*7c478bd9Sstevel@tonic-gate * necessary because the ordering of logical sector defects is significant 273*7c478bd9Sstevel@tonic-gate * when sector slipping is employed. 274*7c478bd9Sstevel@tonic-gate */ 275*7c478bd9Sstevel@tonic-gate int 276*7c478bd9Sstevel@tonic-gate sort_defect(struct defect_entry *def, struct defect_list *list) 277*7c478bd9Sstevel@tonic-gate { 278*7c478bd9Sstevel@tonic-gate struct defect_entry *ptr; 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate /* 281*7c478bd9Sstevel@tonic-gate * If it's a logical sector defect, return the entry at the end 282*7c478bd9Sstevel@tonic-gate * of the list. 283*7c478bd9Sstevel@tonic-gate */ 284*7c478bd9Sstevel@tonic-gate if (def->bfi == UNKNOWN) 285*7c478bd9Sstevel@tonic-gate return (list->header.count); 286*7c478bd9Sstevel@tonic-gate /* 287*7c478bd9Sstevel@tonic-gate * It's a bfi defect. Loop through the defect list. 288*7c478bd9Sstevel@tonic-gate */ 289*7c478bd9Sstevel@tonic-gate for (ptr = list->list; ptr - list->list < list->header.count; ptr++) { 290*7c478bd9Sstevel@tonic-gate /* 291*7c478bd9Sstevel@tonic-gate * If we get to a logical sector defect, put this defect 292*7c478bd9Sstevel@tonic-gate * right before it. 293*7c478bd9Sstevel@tonic-gate */ 294*7c478bd9Sstevel@tonic-gate if (ptr->bfi == UNKNOWN) 295*7c478bd9Sstevel@tonic-gate goto found; 296*7c478bd9Sstevel@tonic-gate /* 297*7c478bd9Sstevel@tonic-gate * If we get to a defect that is past this one in 298*7c478bd9Sstevel@tonic-gate * cylinder/head/bfi, put this defect right before it. 299*7c478bd9Sstevel@tonic-gate */ 300*7c478bd9Sstevel@tonic-gate if (def->cyl < ptr->cyl) 301*7c478bd9Sstevel@tonic-gate goto found; 302*7c478bd9Sstevel@tonic-gate if (def->cyl != ptr->cyl) 303*7c478bd9Sstevel@tonic-gate continue; 304*7c478bd9Sstevel@tonic-gate if (def->head < ptr->head) 305*7c478bd9Sstevel@tonic-gate goto found; 306*7c478bd9Sstevel@tonic-gate if (def->head != ptr->head) 307*7c478bd9Sstevel@tonic-gate continue; 308*7c478bd9Sstevel@tonic-gate if (def->bfi < ptr->bfi) 309*7c478bd9Sstevel@tonic-gate goto found; 310*7c478bd9Sstevel@tonic-gate } 311*7c478bd9Sstevel@tonic-gate found: 312*7c478bd9Sstevel@tonic-gate /* 313*7c478bd9Sstevel@tonic-gate * Return the index to put the defect at. 314*7c478bd9Sstevel@tonic-gate */ 315*7c478bd9Sstevel@tonic-gate return (ptr - list->list); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate /* 319*7c478bd9Sstevel@tonic-gate * This routine writes the defect list on the back on the disk. It also 320*7c478bd9Sstevel@tonic-gate * writes the bad block table to disk if bad-144 mapping applies to the 321*7c478bd9Sstevel@tonic-gate * current disk. 322*7c478bd9Sstevel@tonic-gate */ 323*7c478bd9Sstevel@tonic-gate void 324*7c478bd9Sstevel@tonic-gate write_deflist(struct defect_list *list) 325*7c478bd9Sstevel@tonic-gate { 326*7c478bd9Sstevel@tonic-gate int size, head, status; 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate #if defined(sparc) 329*7c478bd9Sstevel@tonic-gate int sec; 330*7c478bd9Sstevel@tonic-gate caddr_t bad_ptr = (caddr_t)&badmap; 331*7c478bd9Sstevel@tonic-gate #endif /* defined(sparc) */ 332*7c478bd9Sstevel@tonic-gate 333*7c478bd9Sstevel@tonic-gate assert(!EMBEDDED_SCSI); 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate /* 336*7c478bd9Sstevel@tonic-gate * Sparc ATA IDE. 337*7c478bd9Sstevel@tonic-gate * This indicates that no list manipulation is done in this controller 338*7c478bd9Sstevel@tonic-gate * and hence return without any other checking. 339*7c478bd9Sstevel@tonic-gate */ 340*7c478bd9Sstevel@tonic-gate if (cur_ctype->ctype_flags & CF_NOWLIST) { 341*7c478bd9Sstevel@tonic-gate return; 342*7c478bd9Sstevel@tonic-gate } 343*7c478bd9Sstevel@tonic-gate 344*7c478bd9Sstevel@tonic-gate /* 345*7c478bd9Sstevel@tonic-gate * Panther's working list is maintained by the controller 346*7c478bd9Sstevel@tonic-gate */ 347*7c478bd9Sstevel@tonic-gate if (cur_ctype->ctype_flags & CF_WLIST) { 348*7c478bd9Sstevel@tonic-gate (*cur_ops->op_wr_cur)(list); 349*7c478bd9Sstevel@tonic-gate return; 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * If the list is null, there is nothing to write. 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate if (list->list != NULL) { 356*7c478bd9Sstevel@tonic-gate /* 357*7c478bd9Sstevel@tonic-gate * calculate how many sectors the defect list will occupy. 358*7c478bd9Sstevel@tonic-gate */ 359*7c478bd9Sstevel@tonic-gate size = LISTSIZE(list->header.count); 360*7c478bd9Sstevel@tonic-gate /* 361*7c478bd9Sstevel@tonic-gate * Loop for each copy of the list to be written. Write 362*7c478bd9Sstevel@tonic-gate * out the header of the list followed by the data. 363*7c478bd9Sstevel@tonic-gate */ 364*7c478bd9Sstevel@tonic-gate for (head = 0; head < LISTCOUNT; head++) { 365*7c478bd9Sstevel@tonic-gate status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, 366*7c478bd9Sstevel@tonic-gate (diskaddr_t)chs2bn(ncyl + 1, head, 0), 1, 367*7c478bd9Sstevel@tonic-gate (char *)&list->header, F_NORMAL, NULL); 368*7c478bd9Sstevel@tonic-gate if (status) { 369*7c478bd9Sstevel@tonic-gate err_print( 370*7c478bd9Sstevel@tonic-gate "Warning: error saving defect list.\n"); 371*7c478bd9Sstevel@tonic-gate continue; 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, 374*7c478bd9Sstevel@tonic-gate (diskaddr_t)chs2bn(ncyl + 1, head, 1), size, 375*7c478bd9Sstevel@tonic-gate (char *)list->list, F_NORMAL, NULL); 376*7c478bd9Sstevel@tonic-gate if (status) 377*7c478bd9Sstevel@tonic-gate err_print( 378*7c478bd9Sstevel@tonic-gate "Warning: error saving defect list.\n"); 379*7c478bd9Sstevel@tonic-gate } 380*7c478bd9Sstevel@tonic-gate } 381*7c478bd9Sstevel@tonic-gate if (!(cur_ctlr->ctlr_flags & DKI_BAD144)) 382*7c478bd9Sstevel@tonic-gate return; 383*7c478bd9Sstevel@tonic-gate #if defined(sparc) 384*7c478bd9Sstevel@tonic-gate /* 385*7c478bd9Sstevel@tonic-gate * Current disk uses bad-144 mapping. Loop for each copy of the 386*7c478bd9Sstevel@tonic-gate * bad block table to be written and write it out. 387*7c478bd9Sstevel@tonic-gate */ 388*7c478bd9Sstevel@tonic-gate for (sec = 0; ((sec < BAD_LISTCNT * 2) && (sec < nsect)); sec += 2) { 389*7c478bd9Sstevel@tonic-gate status = (*cur_ops->op_rdwr)(DIR_WRITE, cur_file, 390*7c478bd9Sstevel@tonic-gate (diskaddr_t)chs2bn(ncyl + acyl - 1, nhead - 1, sec), 1, 391*7c478bd9Sstevel@tonic-gate &badmap, F_NORMAL, NULL); 392*7c478bd9Sstevel@tonic-gate if (status) { 393*7c478bd9Sstevel@tonic-gate err_print( 394*7c478bd9Sstevel@tonic-gate "Warning: error saving bad block map table.\n"); 395*7c478bd9Sstevel@tonic-gate continue; 396*7c478bd9Sstevel@tonic-gate } 397*7c478bd9Sstevel@tonic-gate } 398*7c478bd9Sstevel@tonic-gate /* 399*7c478bd9Sstevel@tonic-gate * Execute an ioctl to tell unix about the new bad block table. 400*7c478bd9Sstevel@tonic-gate */ 401*7c478bd9Sstevel@tonic-gate if (ioctl(cur_file, HDKIOCSBAD, &bad_ptr)) 402*7c478bd9Sstevel@tonic-gate err_print( 403*7c478bd9Sstevel@tonic-gate "Warning: error telling SunOS bad block map table.\n"); 404*7c478bd9Sstevel@tonic-gate #endif /* defined(sparc) */ 405*7c478bd9Sstevel@tonic-gate } 406*7c478bd9Sstevel@tonic-gate 407*7c478bd9Sstevel@tonic-gate /* 408*7c478bd9Sstevel@tonic-gate * This routine adds a logical sector to the given defect list. 409*7c478bd9Sstevel@tonic-gate */ 410*7c478bd9Sstevel@tonic-gate void 411*7c478bd9Sstevel@tonic-gate add_ldef(diskaddr_t blkno, struct defect_list *list) 412*7c478bd9Sstevel@tonic-gate { 413*7c478bd9Sstevel@tonic-gate struct defect_entry def; 414*7c478bd9Sstevel@tonic-gate int index; 415*7c478bd9Sstevel@tonic-gate 416*7c478bd9Sstevel@tonic-gate 417*7c478bd9Sstevel@tonic-gate /* 418*7c478bd9Sstevel@tonic-gate * Calculate the fields for the defect struct. 419*7c478bd9Sstevel@tonic-gate */ 420*7c478bd9Sstevel@tonic-gate def.cyl = bn2c(blkno); 421*7c478bd9Sstevel@tonic-gate def.head = bn2h(blkno); 422*7c478bd9Sstevel@tonic-gate def.sect = bn2s(blkno); 423*7c478bd9Sstevel@tonic-gate /* 424*7c478bd9Sstevel@tonic-gate * Initialize the unknown fields. 425*7c478bd9Sstevel@tonic-gate */ 426*7c478bd9Sstevel@tonic-gate def.bfi = def.nbits = UNKNOWN; 427*7c478bd9Sstevel@tonic-gate /* 428*7c478bd9Sstevel@tonic-gate * Calculate the index into the list that the defect belongs at. 429*7c478bd9Sstevel@tonic-gate */ 430*7c478bd9Sstevel@tonic-gate index = sort_defect(&def, list); 431*7c478bd9Sstevel@tonic-gate /* 432*7c478bd9Sstevel@tonic-gate * Add the defect to the list. 433*7c478bd9Sstevel@tonic-gate */ 434*7c478bd9Sstevel@tonic-gate add_def(&def, list, index); 435*7c478bd9Sstevel@tonic-gate } 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate /* 438*7c478bd9Sstevel@tonic-gate * This routine adds the given defect struct to the defect list at 439*7c478bd9Sstevel@tonic-gate * a precalculated index. 440*7c478bd9Sstevel@tonic-gate */ 441*7c478bd9Sstevel@tonic-gate void 442*7c478bd9Sstevel@tonic-gate add_def(struct defect_entry *def, struct defect_list *list, int index) 443*7c478bd9Sstevel@tonic-gate { 444*7c478bd9Sstevel@tonic-gate int count, i; 445*7c478bd9Sstevel@tonic-gate 446*7c478bd9Sstevel@tonic-gate /* 447*7c478bd9Sstevel@tonic-gate * If adding this defect makes the list overflow into another 448*7c478bd9Sstevel@tonic-gate * sector, allocate the necessary space. 449*7c478bd9Sstevel@tonic-gate */ 450*7c478bd9Sstevel@tonic-gate count = list->header.count; 451*7c478bd9Sstevel@tonic-gate if (LISTSIZE(count + 1) > LISTSIZE(count)) 452*7c478bd9Sstevel@tonic-gate list->list = (struct defect_entry *)rezalloc((void *)list->list, 453*7c478bd9Sstevel@tonic-gate LISTSIZE(count + 1) * SECSIZE); 454*7c478bd9Sstevel@tonic-gate /* 455*7c478bd9Sstevel@tonic-gate * Slip all the defects after this one down one slot in the list. 456*7c478bd9Sstevel@tonic-gate */ 457*7c478bd9Sstevel@tonic-gate for (i = count; i > index; i--) 458*7c478bd9Sstevel@tonic-gate *(list->list + i) = *(list->list + i - 1); 459*7c478bd9Sstevel@tonic-gate /* 460*7c478bd9Sstevel@tonic-gate * Fill in the created hole with this defect. 461*7c478bd9Sstevel@tonic-gate */ 462*7c478bd9Sstevel@tonic-gate *(list->list + i) = *def; 463*7c478bd9Sstevel@tonic-gate /* 464*7c478bd9Sstevel@tonic-gate * Increment the count and calculate a new checksum. 465*7c478bd9Sstevel@tonic-gate */ 466*7c478bd9Sstevel@tonic-gate list->header.count++; 467*7c478bd9Sstevel@tonic-gate (void) checkdefsum(list, CK_MAKESUM); 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate 470*7c478bd9Sstevel@tonic-gate /* 471*7c478bd9Sstevel@tonic-gate * This routine sets the given defect list back to null. 472*7c478bd9Sstevel@tonic-gate */ 473*7c478bd9Sstevel@tonic-gate void 474*7c478bd9Sstevel@tonic-gate kill_deflist(struct defect_list *list) 475*7c478bd9Sstevel@tonic-gate { 476*7c478bd9Sstevel@tonic-gate 477*7c478bd9Sstevel@tonic-gate /* 478*7c478bd9Sstevel@tonic-gate * If it's already null, we're done. 479*7c478bd9Sstevel@tonic-gate */ 480*7c478bd9Sstevel@tonic-gate if (list->list == NULL) 481*7c478bd9Sstevel@tonic-gate return; 482*7c478bd9Sstevel@tonic-gate /* 483*7c478bd9Sstevel@tonic-gate * Free the malloc'd space it's using. 484*7c478bd9Sstevel@tonic-gate */ 485*7c478bd9Sstevel@tonic-gate destroy_data((char *)list->list); 486*7c478bd9Sstevel@tonic-gate /* 487*7c478bd9Sstevel@tonic-gate * Mark it as null, and clear any flags. 488*7c478bd9Sstevel@tonic-gate */ 489*7c478bd9Sstevel@tonic-gate list->list = NULL; 490*7c478bd9Sstevel@tonic-gate list->flags = 0; 491*7c478bd9Sstevel@tonic-gate } 492