1 #ifndef lint 2 static char sccsid[] = "@(#)maps.c 1.7 (Berkeley/CCI) 06/07/88"; 3 #endif 4 5 6 #include "vdfmt.h" 7 8 9 /* 10 ** 11 */ 12 13 boolean align_buf(buf, sync) 14 unsigned long *buf; 15 unsigned long sync; 16 { 17 register int i, shift; 18 19 /* find shift amount */ 20 for(shift=0; shift < 32; shift++) { 21 if((*buf >> shift ) == sync) { 22 for(i=(512/sizeof(long))-1; i >= 0; i--) { 23 *(buf+i+1) |= *(buf+i) << (32 - shift); 24 *(buf+i) = *(buf+i) >> shift; 25 } 26 return true; 27 } 28 } 29 return false; 30 } 31 32 33 /* 34 ** Looks for two maps in a row that are the same. 35 */ 36 37 boolean 38 read_map(flags) 39 short flags; 40 { 41 register int trk, i; 42 dskadr dskaddr; 43 44 dskaddr.cylinder = (lab->d_ncylinders - 1) | flags; 45 for(i=0; i < 100; i++) 46 scratch[i] = -1; 47 for(trk=0; trk < lab->d_ntracks; trk++) { 48 dskaddr.track = trk; 49 dskaddr.sector = 0; 50 if(access_dsk((char *)save,&dskaddr, VDOP_RD, 51 lab->d_nsectors,1)& VDERR_HARD) 52 continue; 53 if(bcmp((char *)scratch, (char *)save, bytes_trk) == true) { 54 bcopy((char *)save, (char *)bad_map, bytes_trk); 55 if(bad_map->bs_count <= MAX_FLAWS) { 56 for(i=0; i < bad_map->bs_count; i++) { 57 if(bad_map->list[i].bs_cyl >= 58 lab->d_ncylinders) 59 break; 60 if(bad_map->list[i].bs_trk >= 61 lab->d_ntracks) 62 break; 63 if(bad_map->list[i].bs_offset >= 64 lab->d_traksize) 65 break; 66 } 67 if(i == bad_map->bs_count) { 68 load_free_table(); 69 return true; 70 } 71 } 72 bzero(bad_map, bytes_trk); 73 bad_map->bs_id = 0; 74 bad_map->bs_max = MAX_FLAWS; 75 } 76 bcopy((char *)save, (char *)scratch, bytes_trk); 77 } 78 return false; 79 } 80 81 82 /* 83 ** 84 */ 85 86 boolean read_bad_sector_map() 87 { 88 dskadr dskaddr; 89 90 dskaddr.cylinder = lab->d_ncylinders - 1; 91 dskaddr.track = 0; 92 dskaddr.sector = 0; 93 /* start with nothing in map */ 94 bzero(bad_map, bytes_trk); 95 bad_map->bs_id = 0; 96 bad_map->bs_max = MAX_FLAWS; 97 if (C_INFO->type == VDTYPE_SMDE) { 98 access_dsk((char *)save, &dskaddr, VDOP_RDRAW, 1, 1); 99 if (align_buf((unsigned long *)save, CDCSYNC) == true) { 100 read_flaw_map(); 101 return (false); 102 } else if (read_map(NRM) == true) { 103 return (true); 104 } else { 105 get_smde_relocations(); 106 return false; 107 } 108 } else { 109 if (read_map(WPT) == true) 110 return (true); 111 else { 112 get_relocations_the_hard_way(); 113 return (false); 114 } 115 } 116 } 117 118 119 /* 120 ** 121 */ 122 123 get_relocations_the_hard_way() 124 { 125 register int cyl, trk; 126 register int status; 127 dskadr dskaddr; 128 129 dskaddr.sector = 0; 130 /* scan each sector to see if it is relocated and take note if it is */ 131 for(cyl=0; cyl < lab->d_ncylinders - NUMSYS; cyl++) { 132 dskaddr.cylinder = cyl; 133 for(trk=0; trk < lab->d_ntracks; trk++) { 134 dskaddr.track = trk; 135 status=access_dsk((char *)scratch, &dskaddr, 136 VDOP_RD, lab->d_nsectors, 1); 137 if(status & DCBS_ATA) 138 get_track_relocations(dskaddr); 139 } 140 } 141 load_free_table(); 142 } 143 144 145 /* 146 ** 147 */ 148 149 get_track_relocations(dskaddr) 150 dskadr dskaddr; 151 { 152 register int status; 153 bs_entry temp; 154 fmt_err error; 155 156 for(dskaddr.sector=0; dskaddr.sector < lab->d_nsectors; dskaddr.sector++) { 157 status = access_dsk((char *)scratch, &dskaddr, VDOP_RD, 1, 1); 158 if(status & DCBS_ATA) { 159 error.err_adr = dskaddr; 160 error.err_stat = DATA_ERROR; 161 (*C_INFO->code_pos)(&error, &temp); 162 temp.bs_how = operator; 163 add_flaw(&temp); 164 } 165 } 166 } 167 168 169 /* 170 ** 171 */ 172 173 remove_user_relocations(entry) 174 bs_entry *entry; 175 { 176 register int i, j; 177 fmt_err temp; 178 fmt_err error; 179 register bs_entry *ptr; 180 181 (*C_INFO->decode_pos)(entry, &error); 182 ptr = bad_map->list; 183 for(i=0; i < bad_map->bs_count; i++) { 184 if (ptr->bs_cyl != entry->bs_cyl || 185 ptr->bs_trk != entry->bs_trk) 186 continue; 187 (*C_INFO->decode_pos)(ptr, &temp); 188 if((ptr->bs_how != flaw_map) && 189 (temp.err_adr.cylinder == error.err_adr.cylinder) && 190 (temp.err_adr.track == error.err_adr.track) && 191 (temp.err_adr.sector == error.err_adr.sector)) { 192 if(temp.err_stat & HEADER_ERROR) 193 remove_track(&temp, ptr); 194 else 195 remove_sector(&temp, ptr); 196 for(j=i+1; j < bad_map->bs_count; j++) 197 bad_map->list[j-1] = bad_map->list[j]; 198 bad_map->bs_count--; 199 return; 200 } 201 ptr++; 202 } 203 indent(); 204 print("Sector %d is not in bad sector map!\n", 205 to_sector(error.err_adr)); 206 exdent(1); 207 } 208 209 clear_relocations(reformat) 210 boolean reformat; 211 { 212 fmt_err temp; 213 register bs_entry *ptr1, *ptr2, *end; 214 int oldsub = cur.substate; 215 216 cur.substate = sub_rel; 217 ptr1 = bad_map->list; 218 ptr2 = bad_map->list; 219 end = &bad_map->list[bad_map->bs_count]; 220 for (; ptr1 < end; ptr1++) { 221 if (ptr1->bs_how != flaw_map) { 222 if (reformat == true) { 223 (*C_INFO->decode_pos)(ptr1, &temp); 224 if(temp.err_stat & HEADER_ERROR) 225 remove_track(&temp, ptr1); 226 else 227 remove_sector(&temp, ptr1); 228 } 229 bad_map->bs_count--; 230 } else { 231 if (ptr1 != ptr2) 232 *ptr2 = *ptr1; 233 ptr2++; 234 } 235 } 236 cur.substate = oldsub; 237 } 238 239 240 /* 241 ** 242 */ 243 244 remove_sector(error, entry) 245 fmt_err *error; 246 bs_entry *entry; 247 { 248 format_sectors(&error->err_adr, &error->err_adr, NRM, 1); 249 format_sectors(&entry->bs_alt, &entry->bs_alt, NRM, 1); 250 } 251 252 253 /* 254 ** 255 */ 256 257 remove_track(error, entry) 258 fmt_err *error; 259 bs_entry *entry; 260 { 261 format_sectors(&error->err_adr,&error->err_adr,NRM,(long)lab->d_nsectors); 262 format_sectors(&entry->bs_alt,&entry->bs_alt,NRM,(long)lab->d_nsectors); 263 } 264 265 266 /* 267 ** 268 */ 269 270 write_bad_sector_map() 271 { 272 register int trk, sec; 273 dskadr dskaddr; 274 275 dskaddr.cylinder = (lab->d_ncylinders - NUMMAP); 276 for(trk=0; trk < lab->d_ntracks; trk++) { 277 for(sec = 0; sec < lab->d_nsectors; sec++) { 278 bcopy((char *)bs_map_space + (sec * lab->d_secsize), 279 (char *)scratch, lab->d_secsize); 280 dskaddr.track = trk; 281 dskaddr.sector = sec; 282 format_sectors(&dskaddr, &dskaddr, WPT, 1); 283 } 284 } 285 } 286 287 288 /* 289 ** 290 */ 291 292 zero_bad_sector_map() 293 { 294 bs_map *bm = bad_map; 295 register int i; 296 dskadr zero; 297 298 zero.cylinder = 0; 299 zero.track = 0; 300 zero.sector = 0; 301 for(i=0; i < bm->bs_count; i++) 302 bm->list[i].bs_alt = zero; 303 load_free_table(); 304 } 305 306 307 /* 308 ** 309 */ 310 311 read_flaw_map() 312 { 313 register int cyl, trk; 314 dskadr dskaddr; 315 flaw buffer; 316 317 dskaddr.sector = 0; 318 for (cyl=0; cyl < lab->d_ncylinders; cyl++) { 319 dskaddr.cylinder = cyl; 320 for (trk=0; trk < lab->d_ntracks; trk++) { 321 dskaddr.track = trk; 322 access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1); 323 if(align_buf(&buffer, CDCSYNC) == true) { 324 add_flaw_entries(&buffer); 325 continue; 326 } 327 } 328 } 329 load_free_table(); 330 } 331 332 333 /* 334 ** 335 */ 336 337 get_smde_relocations() 338 { 339 register int cyl, trk, sec; 340 smde_hdr buffer; 341 dskadr dskaddr; 342 fmt_err bad; 343 bs_entry temp; 344 boolean bad_track; 345 346 /* Read any old drive relocations */ 347 for(cyl=0; cyl < NUMREL; cyl++) { 348 dskaddr.cylinder = lab->d_ncylinders - NUMSYS + cyl; 349 for(trk=0; trk < lab->d_ntracks; trk++) { 350 dskaddr.track = trk; 351 bad_track = true; 352 for(sec=0; sec < lab->d_nsectors; sec++) { 353 dskaddr.sector = sec; 354 access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1); 355 if(align_buf(&buffer, SMDE1SYNC) == false) { 356 bad_track = false; 357 break; 358 } 359 } 360 if(bad_track == true) { 361 dskaddr.sector = 0; 362 bad.err_adr.cylinder = buffer.alt_cyl; 363 bad.err_adr.track = buffer.alt_trk; 364 bad.err_adr.sector = 0; 365 bad.err_stat = HEADER_ERROR; 366 (*C_INFO->code_pos)(&bad, &temp); 367 temp.bs_alt = dskaddr; 368 temp.bs_how = scanning; 369 add_flaw(&temp); 370 continue; 371 } 372 for(sec=0; sec < lab->d_nsectors; sec++) { 373 dskaddr.sector = sec; 374 access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1); 375 if(align_buf(&buffer, SMDE1SYNC) == true) { 376 bad.err_adr.cylinder = buffer.alt_cyl; 377 bad.err_adr.track = buffer.alt_trk; 378 bad.err_adr.sector = buffer.alt_sec; 379 bad.err_stat = DATA_ERROR; 380 (*C_INFO->code_pos)(&bad, &temp); 381 temp.bs_alt = dskaddr; 382 temp.bs_how = scanning; 383 add_flaw(&temp); 384 } 385 } 386 } 387 } 388 load_free_table(); 389 } 390 391 392 /* 393 ** 394 */ 395 396 add_flaw_entries(buffer) 397 flaw *buffer; 398 { 399 register int i; 400 bs_entry temp; 401 402 temp.bs_cyl = buffer->flaw_cyl & 0x7fff; /* clear off bad track bit */ 403 temp.bs_trk = buffer->flaw_trk; 404 for(i=0; i < 4; i++) { 405 if(buffer->flaw_pos[i].flaw_length != 0) { 406 temp.bs_offset = buffer->flaw_pos[i].flaw_offset; 407 temp.bs_length = buffer->flaw_pos[i].flaw_length; 408 temp.bs_alt.cylinder = 0; 409 temp.bs_alt.track = 0; 410 temp.bs_alt.sector = 0; 411 temp.bs_how = flaw_map; 412 add_flaw(&temp); 413 } 414 } 415 } 416 417 418 cmp_entry(a, b) 419 bs_entry *a; 420 bs_entry *b; 421 { 422 if(a->bs_cyl == b->bs_cyl) { 423 if(a->bs_trk == b->bs_trk) { 424 if(a->bs_offset == b->bs_offset) 425 return 0; 426 else if(a->bs_offset < b->bs_offset) 427 return -1; 428 } 429 else if(a->bs_trk < b->bs_trk) 430 return -1; 431 } 432 else if(a->bs_cyl < b->bs_cyl) 433 return -1; 434 return 1; 435 } 436 437 438 /* 439 * Add flaw to map. 440 * Return value: 441 * 1 OK 442 * 0 sector was in map 443 * -1 failure 444 */ 445 add_flaw(entry) 446 bs_entry *entry; 447 { 448 extern int cmp_entry(); 449 bs_map *bm = bad_map; 450 register int i; 451 452 if(bm->bs_count > MAX_FLAWS) 453 return (-1); 454 if (entry->bs_cyl >= lab->d_ncylinders || 455 entry->bs_trk >= lab->d_ntracks || 456 entry->bs_offset >= lab->d_traksize) 457 return (-1); 458 for(i=0; i < bm->bs_count; i++) { 459 if(((bm->list[i].bs_cyl == entry->bs_cyl)) && 460 (bm->list[i].bs_trk == entry->bs_trk) && 461 (bm->list[i].bs_offset == entry->bs_offset)) { 462 if((int)bm->list[i].bs_how > (int)entry->bs_how) 463 bm->list[i].bs_how = entry->bs_how; 464 return (0); 465 } 466 } 467 bm->list[i] = *entry; 468 bm->list[i].bs_alt.cylinder = 0; 469 bm->list[i].bs_alt.track = 0; 470 bm->list[i].bs_alt.sector = 0; 471 bm->bs_count++; 472 qsort((char *)&(bm->list[0]), (unsigned)bm->bs_count, 473 sizeof(bs_entry), cmp_entry); 474 return (1); 475 } 476 477 478 /* 479 ** Is_in_map checks to see if a block is known to be bad already. 480 */ 481 482 boolean is_in_map(dskaddr) 483 dskadr *dskaddr; 484 { 485 register int i; 486 fmt_err temp; 487 488 for(i=0; i < bad_map->bs_count; i++) { 489 (*C_INFO->decode_pos)(&bad_map->list[i], &temp); 490 if((temp.err_adr.cylinder == dskaddr->cylinder) && 491 (temp.err_adr.track == dskaddr->track) && 492 (temp.err_adr.sector == dskaddr->sector)) { 493 return true; 494 } 495 } 496 return false; 497 } 498 499 500 /* 501 ** 502 */ 503 504 print_bad_sector_list() 505 { 506 register int i; 507 fmt_err errloc; 508 register bs_entry *bad; 509 510 if(bad_map->bs_count == 0) { 511 print("There are no bad sectors in bad sector map.\n"); 512 return; 513 } 514 print("The following sector%s known to be bad:\n", 515 (bad_map->bs_count == 1) ? " is" : "s are"); 516 indent(); 517 for(i=0, bad = bad_map->list; i < bad_map->bs_count; i++, bad++) { 518 (*C_INFO->decode_pos)(bad, &errloc); 519 print("%s %d cn %d tn %d sn %d pos %d len %d ", 520 errloc.err_stat & HEADER_ERROR ? "Track@" : "Sector", 521 to_sector(errloc.err_adr), 522 bad->bs_cyl, 523 bad->bs_trk, 524 errloc.err_adr.sector, 525 bad->bs_offset, 526 bad->bs_length); 527 if (bad->bs_how == flaw_map) 528 printf("(flawmap) "); 529 else if (bad->bs_how == scanning) 530 printf("(verify) "); 531 else 532 printf("(operator) "); 533 if((bad->bs_alt.cylinder != 0) || (bad->bs_alt.track != 0) || 534 (bad->bs_alt.sector != 0)) { 535 printf("-> "); 536 printf("cn %d tn %d sn %d", bad->bs_alt.cylinder, 537 bad->bs_alt.track, bad->bs_alt.sector); 538 } 539 printf("\n"); 540 } 541 exdent(1); 542 } 543 544 545 /* 546 ** load_free_table checks each block in the bad block relocation area 547 ** to see if it is used. If it is, the free relocation block table is updated. 548 */ 549 550 load_free_table() 551 { 552 register int i, j; 553 fmt_err temp; 554 555 /* Clear free table before starting */ 556 for(i = 0; i < (lab->d_ntracks * NUMREL); i++) { 557 for(j=0; j < lab->d_nsectors; j++) 558 free_tbl[i][j].free_status = NOTALLOCATED; 559 } 560 for(i=0; i < bad_map->bs_count; i++) 561 if((bad_map->list[i].bs_alt.cylinder != 0) || 562 (bad_map->list[i].bs_alt.track != 0) || 563 (bad_map->list[i].bs_alt.sector != 0)) { 564 (*C_INFO->decode_pos)(&bad_map->list[i], &temp); 565 allocate(&(bad_map->list[i].bs_alt), temp.err_stat); 566 } 567 } 568 569 570 /* 571 ** allocate marks a replacement sector as used. 572 */ 573 574 allocate(dskaddr, status) 575 dskadr *dskaddr; 576 long status; 577 { 578 register int trk, sec; 579 580 trk = dskaddr->cylinder - (lab->d_ncylinders - NUMSYS); 581 if((trk < 0) || (trk >= NUMREL)) 582 return; 583 trk *= lab->d_ntracks; 584 trk += dskaddr->track; 585 if(status & HEADER_ERROR) 586 for(sec=0; sec < lab->d_nsectors; sec++) 587 free_tbl[trk][sec].free_status = ALLOCATED; 588 else 589 free_tbl[trk][dskaddr->sector].free_status = ALLOCATED; 590 } 591 592 593 /* 594 ** 595 */ 596 597 boolean mapping_collision(entry) 598 bs_entry *entry; 599 { 600 register int trk, sec; 601 fmt_err temp; 602 603 trk = entry->bs_cyl - (lab->d_ncylinders - NUMSYS); 604 if((trk < 0) || (trk >= NUMREL)) 605 return false; 606 trk *= lab->d_ntracks; 607 trk += entry->bs_trk; 608 (*C_INFO->decode_pos)(entry, &temp); 609 /* if this relocation should take up the whole track */ 610 if(temp.err_stat & HEADER_ERROR) { 611 for(sec=0; sec < lab->d_nsectors; sec++) 612 if(free_tbl[trk][sec].free_status == ALLOCATED) 613 return true; 614 } 615 /* else just check the current sector */ 616 else { 617 if(free_tbl[trk][temp.err_adr.sector].free_status == ALLOCATED) 618 return true; 619 } 620 return false; 621 } 622 623 624 /* 625 ** 626 */ 627 628 report_collision() 629 { 630 indent(); 631 print("Sector resides in relocation area"); 632 printf("but it has a sector mapped to it already.\n"); 633 print("Please reformat disk with 0 patterns to eliminate problem.\n"); 634 exdent(1); 635 } 636 637 638 /* 639 ** 640 */ 641 642 add_user_relocations(entry) 643 bs_entry *entry; 644 { 645 fmt_err error; 646 647 (*C_INFO->decode_pos)(entry, &error); 648 if(is_in_map(&error.err_adr) == false) { 649 if(mapping_collision(entry) == true) 650 report_collision(); 651 entry->bs_how = operator; 652 add_flaw(entry); 653 } 654 else { 655 indent(); 656 print("Sector %d is already mapped out!\n", 657 to_sector(error.err_adr)); 658 exdent(1); 659 } 660 } 661 662 663 /* 664 ** New_location allocates a replacement block given a bad block address. 665 ** The algorithm is fairly simple; it simply searches for the first 666 ** free sector that has the same sector number of the bad sector. If no sector 667 ** is found then the drive should be considered bad because of a microcode bug 668 ** in the controller that forces us to use the same sector number as the bad 669 ** sector for relocation purposes. Using different tracks and cylinders is ok 670 ** of course. 671 */ 672 673 dskadr *new_location(entry) 674 bs_entry *entry; 675 { 676 register int i, sec; 677 static fmt_err temp; 678 static dskadr newaddr; 679 680 newaddr.cylinder = 0; 681 newaddr.track = 0; 682 newaddr.sector = 0; 683 (*C_INFO->decode_pos)(entry, &temp); 684 /* If it is ouside of the user's data area */ 685 if(entry->bs_cyl >= lab->d_ncylinders-NUMSYS) { 686 /* if it is in the relocation area */ 687 if(entry->bs_cyl < (lab->d_ncylinders - NUMMAP - NUMMNT)) { 688 /* mark space as allocated */ 689 allocate(&temp.err_adr, temp.err_stat); 690 return &temp.err_adr; 691 } 692 /* if it is in the map area forget about it */ 693 if(entry->bs_cyl != (lab->d_ncylinders - NUMMAP - NUMMNT)) 694 return &temp.err_adr; 695 /* otherwise treat maintainence cylinder normally */ 696 } 697 if(temp.err_stat & (HEADER_ERROR)) { 698 for(i = 0; i < (lab->d_ntracks * NUMREL); i++) { 699 for(sec=0; sec < lab->d_nsectors; sec++) { 700 if(free_tbl[i][sec].free_status == ALLOCATED) 701 break; 702 } 703 if(sec == lab->d_nsectors) { 704 for(sec = 0; sec < lab->d_nsectors; sec++) 705 free_tbl[i][sec].free_status=ALLOCATED; 706 newaddr.cylinder = i / lab->d_ntracks + 707 (lab->d_ncylinders - NUMSYS); 708 newaddr.track = i % lab->d_ntracks; 709 break; 710 } 711 } 712 } 713 else if(C_INFO->type == VDTYPE_VDDC) { 714 for(i = 0; i < (lab->d_ntracks * NUMREL); i++) { 715 if(free_tbl[i][temp.err_adr.sector].free_status != 716 ALLOCATED) { 717 free_tbl[i][temp.err_adr.sector].free_status = 718 ALLOCATED; 719 newaddr.cylinder = i / lab->d_ntracks + 720 (lab->d_ncylinders - NUMSYS); 721 newaddr.track = i % lab->d_ntracks; 722 newaddr.sector = temp.err_adr.sector; 723 break; 724 } 725 } 726 } 727 else { 728 for(i = 0; i < (lab->d_ntracks * NUMREL); i++) { 729 for(sec=0; sec < lab->d_nsectors; sec++) 730 if(free_tbl[i][sec].free_status != ALLOCATED) 731 break; 732 if(sec < lab->d_nsectors) { 733 free_tbl[i][sec].free_status = ALLOCATED; 734 newaddr.cylinder = i / lab->d_ntracks + 735 (lab->d_ncylinders - NUMSYS); 736 newaddr.track = i % lab->d_ntracks; 737 newaddr.sector = sec; 738 break; 739 } 740 } 741 } 742 return &newaddr; 743 } 744