1 #ifndef lint 2 static char sccsid[] = "@(#)relocate.c 1.7 (Berkeley/CCI) 06/24/90"; 3 #endif 4 5 #include "vdfmt.h" 6 #include "cmd.h" 7 8 /* 9 ** 10 */ 11 12 relocate() 13 { 14 extern boolean is_formatted(); 15 16 cur.state = rel; 17 print("Adding flaws to bad sector map on "); 18 printf("controller %d, drive %d, ", cur.controller, cur.drive); 19 printf("type %s.\n", lab->d_typename); 20 21 indent(); 22 if(is_formatted() == true) { 23 if(read_bad_sector_map() == true) 24 if(bad_map->bs_id != D_INFO->id) { 25 print("Drive serial numbers do not match!\n"); 26 exdent(1); 27 _longjmp(abort_environ, 1); 28 } 29 get_new_relocations(); 30 cur.substate = sub_wmap; 31 sync_bad_sector_map(); 32 } 33 else 34 print("Drive must be formatted befor relocations are done.\n"); 35 exdent(1); 36 } 37 38 39 /* 40 ** 41 */ 42 43 rel_help() 44 { 45 indent(); 46 print("Relocation commands are in the following form:\n"); 47 indent(); 48 print("[a-h] (block) - UNIX file system block (%s-byte) number.\n", 49 DEV_BSIZE); 50 print("SEctor (sector) - Absolute sector number on disk.\n"); 51 print("Track (track) - Absolute disk track number.\n"); 52 print("(cylinder) (head) (offset) (length) - CDC flaw map format.\n"); 53 print("STARt - Starts relocation process.\n\n"); 54 exdent(2); 55 } 56 57 58 /* 59 ** 60 */ 61 62 get_new_relocations() 63 { 64 char line[256]; 65 char *ptr; 66 bs_entry entry; 67 dskadr dskaddr; 68 fmt_err dskerr; 69 int max_track; 70 register int block; 71 72 dskaddr.cylinder = lab->d_ncylinders - 1; 73 dskaddr.track = lab->d_ntracks - 1; 74 max_track = to_track(dskaddr); 75 for(;;) { 76 print("Location? "); 77 get_string_cmd(line, rel_help); 78 if(kill_processes == true) 79 _longjmp(quit_environ, 1); 80 if(line[0] == '\0') 81 continue; 82 ptr = line; 83 trim_white(ptr); 84 if(!strncmp(ptr, "he", 2) || !strncmp(ptr, "?", 1) || 85 !strncmp(ptr, "stat", 4) || !strncmp(ptr, "!", 1)) 86 continue; 87 indent(); 88 if((*ptr >= 'a') && (*ptr <= 'h')) { 89 register char par = *(ptr++); 90 91 block = get_next_digit(ptr); 92 dskerr.err_adr = *from_unix((unsigned char)par, 93 (unsigned int)block); 94 if((dskerr.err_adr.cylinder == -1) || (block == -1)) { 95 print("Invalid UNIX block number!\n"); 96 goto next; 97 } 98 print("Confirm block %d on file-system '%c'",block,par); 99 dskerr.err_stat = DATA_ERROR; 100 doreloc: 101 printf(" (cn %d tn %d sn %d)", dskerr.err_adr.cylinder, 102 dskerr.err_adr.track, dskerr.err_adr.sector); 103 if(get_yes_no("") == true) { 104 (*C_INFO->code_pos)(&dskerr, &entry); 105 add_user_relocations(&entry); 106 } 107 } 108 else if(*ptr == 't') { 109 block = get_next_digit(ptr); 110 if((block == -1) || (block >= max_track)) { 111 print("Invalid track number!\n"); 112 goto next; 113 } 114 dskerr.err_adr = *from_track(block); 115 dskerr.err_stat = HEADER_ERROR; 116 print("Confirm track %d", block); 117 goto doreloc; 118 } 119 else if(!strncmp(ptr, "se", 2)) { 120 block = get_next_digit(ptr); 121 122 if((block == -1) || 123 ((lab->d_nsectors*lab->d_ntracks*lab->d_ncylinders)<block)){ 124 print("Invalid sector number!\n"); 125 goto next; 126 } 127 dskerr.err_adr = *from_sector((unsigned int)block); 128 dskerr.err_stat = DATA_ERROR; 129 goto doreloc; 130 } 131 else if(is_digit(*ptr)) { 132 entry.bs_cyl = get_next_digit(ptr); 133 skipdigits(ptr); 134 finddigit(ptr); 135 entry.bs_trk = get_next_digit(ptr); 136 skipdigits(ptr); 137 finddigit(ptr); 138 entry.bs_offset = get_next_digit(ptr); 139 skipdigits(ptr); 140 finddigit(ptr); 141 entry.bs_length = get_next_digit(ptr); 142 if((entry.bs_trk != -1) && (entry.bs_offset != -1) && 143 (entry.bs_length != -1)) { 144 if(entry.bs_cyl >= lab->d_ncylinders) 145 print("Cylinder number to high!\n"); 146 else if(entry.bs_trk >= lab->d_ntracks) 147 print("Head number to high!\n"); 148 else if(entry.bs_offset >= lab->d_traksize) 149 print("Offset too long!\n"); 150 else if(entry.bs_length == 0) 151 print("Can't have a 0 length error!\n"); 152 else { 153 print("Confirm Cyl %d, ",entry.bs_cyl); 154 printf("Head %d, ", entry.bs_trk); 155 printf("offset %d, ", entry.bs_offset); 156 printf("length %d", entry.bs_length); 157 if(get_yes_no("") == true) 158 add_user_relocations(&entry); 159 } 160 } 161 else 162 goto bad; 163 } 164 else if(!strncmp(ptr, "start", 4)) { 165 exdent(1); 166 break; 167 } 168 else 169 bad: print("What?\n"); 170 next: exdent(1); 171 } 172 } 173 174 dskadr check_track_for_relocations(entry, i) 175 bs_entry entry; 176 register int i; 177 { 178 register int j = i; 179 fmt_err temp, cmp; 180 boolean bad_track = false; 181 182 (*C_INFO->decode_pos)(&entry, &cmp); 183 /* Check to see if a alternate track is or will be on this track */ 184 while((bad_map->list[j].bs_cyl == entry.bs_cyl) && 185 (bad_map->list[j].bs_trk == entry.bs_trk)) { 186 (*C_INFO->decode_pos)(&bad_map->list[j], &temp); 187 if(temp.err_stat & HEADER_ERROR) { 188 bad_track = true; 189 /* if track was mapped out (it can't be us) */ 190 if(((bad_map->list[j].bs_alt.cylinder != 0)) || 191 (bad_map->list[j].bs_alt.track != 0) || 192 (bad_map->list[j].bs_alt.sector != 0)) { 193 return cmp.err_adr; 194 } 195 } 196 j++; 197 } 198 /* 199 ** If it was a bad track and it was not the current entry 200 ** that produced it then then map it 201 ** to itself and forget about it for now since it will be taken 202 ** care of later. 203 ** 204 ** If it was the current entry return zero and the track will be 205 ** mapped out correctly. 206 */ 207 if(bad_track == true) { 208 if(cmp.err_stat & HEADER_ERROR) 209 return entry.bs_alt; /* better known as zero */ 210 else 211 return cmp.err_adr; 212 } 213 /* 214 ** if we made it through all the bad track stuff then check for 215 ** multiple errors on the same sector that are already mapped! 216 */ 217 j = i; 218 while((bad_map->list[j].bs_cyl == entry.bs_cyl) && 219 (bad_map->list[j].bs_trk == entry.bs_trk)) { 220 (*C_INFO->decode_pos)(&bad_map->list[j], &temp); 221 if(temp.err_adr.sector == cmp.err_adr.sector) { 222 /* if it is not really the current entry */ 223 if((bad_map->list[j].bs_offset != entry.bs_offset) || 224 (bad_map->list[j].bs_length != entry.bs_length)) { 225 /* if the sector is already mapped out */ 226 if(((bad_map->list[j].bs_alt.cylinder != 0)) || 227 (bad_map->list[j].bs_alt.track != 0) || 228 (bad_map->list[j].bs_alt.sector != 0)) { 229 return temp.err_adr; 230 } 231 } 232 } 233 j++; 234 } 235 return entry.bs_alt; 236 } 237 238 239 /* 240 ** 241 */ 242 243 dskadr is_relocated(entry) 244 bs_entry entry; 245 { 246 register int i; 247 248 for(i=0; i<bad_map->bs_count; i++) 249 if((bad_map->list[i].bs_cyl == entry.bs_cyl) && 250 (bad_map->list[i].bs_trk == entry.bs_trk)) 251 return check_track_for_relocations(entry, i); 252 return entry.bs_alt; 253 } 254 255 256 257 /* 258 ** 259 */ 260 261 sync_bad_sector_map() 262 { 263 register int i; 264 dskadr dskaddr; 265 266 /* 267 ** do all the relocation cylinders first to allocate all flaws in 268 ** relocation area. 269 */ 270 for(i=bad_map->bs_count-1; i>=0; i--) { 271 if((bad_map->list[i].bs_cyl >= lab->d_ncylinders-NUMSYS) && 272 (bad_map->list[i].bs_cyl < lab->d_ncylinders-NUMMAP-NUMMNT)) { 273 if((bad_map->list[i].bs_alt.cylinder == 0) && 274 (bad_map->list[i].bs_alt.track == 0) && 275 (bad_map->list[i].bs_alt.sector == 0)) { 276 bad_map->list[i].bs_alt = 277 *new_location(&bad_map->list[i]); 278 } 279 } 280 } 281 for(i=bad_map->bs_count-1; i>=0; i--) { 282 if((bad_map->list[i].bs_alt.cylinder == 0) && 283 (bad_map->list[i].bs_alt.track == 0) && 284 (bad_map->list[i].bs_alt.sector == 0)) { 285 dskaddr = is_relocated(bad_map->list[i]); 286 if((dskaddr.cylinder == 0) && (dskaddr.track == 0) && 287 (dskaddr.sector == 0)) { 288 bad_map->list[i].bs_alt = 289 *new_location(&bad_map->list[i]); 290 do_relocation(bad_map->list[i]); 291 } 292 else 293 bad_map->list[i].bs_alt = dskaddr; 294 } 295 } 296 write_bad_sector_map(); 297 } 298 299 300 301 /* 302 ** 303 */ 304 305 do_relocation(entry) 306 bs_entry entry; 307 { 308 fmt_err temp; 309 310 if(entry.bs_cyl >= lab->d_ncylinders-NUMSYS) 311 if(entry.bs_cyl != (lab->d_ncylinders - NUMMAP - NUMMNT)) 312 return; 313 (*C_INFO->decode_pos)(&entry, &temp); 314 if((entry.bs_alt.cylinder == 0) && (entry.bs_alt.track == 0) && 315 (entry.bs_alt.sector == 0)) 316 print_unix_block(temp.err_adr); 317 else if(temp.err_stat & HEADER_ERROR) 318 if(C_INFO->type == VDTYPE_VDDC) { 319 print("Can't relocate tracks on VDDC controllers.\n"); 320 print_unix_block(temp.err_adr); 321 } 322 else 323 relocate_track(entry); 324 else 325 relocate_sector(entry); 326 } 327 328 329 /* 330 ** 331 */ 332 333 relocate_sector(entry) 334 bs_entry entry; 335 { 336 dskadr phys, reloc; 337 fmt_err temp; 338 register long status; 339 340 (*C_INFO->decode_pos)(&entry, &temp); 341 phys = temp.err_adr; 342 reloc = entry.bs_alt; 343 format_sectors(&phys, &reloc, RELOC_SECTOR, (long)1); 344 345 format_sectors(&reloc, &phys, ALT_SECTOR, (long)1); 346 status = access_dsk((char *)save, &temp.err_adr, VDOP_WD, 1, 1); 347 if(!((status & DCBS_ATA) && !(status & (DCBS_HARD|DCBS_SOFT)))) { 348 print( 349 "Sector relocation failed (c %d t %d s %d). Status = 0x%x.\n", 350 phys.cylinder, phys.track, phys.sector, status); 351 print_unix_block(phys); 352 } 353 } 354 355 356 357 /* 358 ** 359 */ 360 361 relocate_track(entry) 362 bs_entry entry; 363 { 364 dskadr phys, reloc; 365 fmt_err temp; 366 register long status; 367 368 (*C_INFO->decode_pos)(&entry, &temp); 369 temp.err_adr.sector = 0; 370 phys = temp.err_adr; 371 reloc = entry.bs_alt; 372 reloc.sector = 0xff; 373 format_sectors(&phys, &reloc, RELOC_SECTOR, (long)lab->d_nsectors); 374 375 reloc.sector = 0x00; 376 format_sectors(&reloc, &phys, ALT_SECTOR, (long)lab->d_nsectors); 377 status = access_dsk((char *)save, &temp.err_adr, VDOP_WD, lab->d_nsectors, 1); 378 if(!((status & DCBS_ATA) && !(status & (DCBS_HARD|DCBS_SOFT)))) { 379 print("Track relocation failed. Status = 0x%x.\n", status); 380 print_unix_block(phys); 381 } 382 } 383