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