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