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