+#ifndef lint
+static char sccsid[] = "@(#)relocate.c 1.1 (Berkeley/CCI) %G%";
+#endif
+
+#include "vdfmt.h"
+#include "cmd.h"
+
+/*
+**
+*/
+
+relocate()
+{
+ extern boolean is_formatted();
+
+ cur.state = rel;
+ print("Adding flaws to bad setor map on ");
+ printf("controller %d, drive %d, ", cur.controller, cur.drive);
+ printf("type %s.\n",CURRENT->vc_name);
+
+ indent();
+ if(is_formatted() == true) {
+ if(read_bad_sector_map() == true)
+ if(bad_map->bs_id != D_INFO.id) {
+ print("Drive serial numbers do not match!\n");
+ exdent(1);
+ _longjmp(abort_environ, 1);
+ }
+ get_new_relocations();
+ sync_bad_sector_map();
+ }
+ else
+ print("Drive must be formatted befor relocations are done.\n");
+ exdent(1);
+}
+
+
+/*
+**
+*/
+
+rel_help()
+{
+ indent();
+ print("Relocation commands are in the following form:\n");
+ indent();
+ print("[a-h] (block) - UNIX file system format.\n");
+ print("SEctor (sector) - Absolute sector number on disk.\n");
+ print("Track (track) - Absolute disk track number.\n");
+ print("(cylinder) (head) (offset) (length) - CDC flaw map format.\n");
+ print("STARt - Starts relocation process.\n\n");
+ exdent(2);
+}
+
+
+/*
+**
+*/
+
+get_new_relocations()
+{
+ char line[256];
+ char *ptr;
+ bs_entry entry;
+ dskadr dskaddr;
+ int max_track;
+
+ dskaddr.cylinder = CURRENT->vc_ncyl - 1;
+ dskaddr.cylinder = CURRENT->vc_ntrak - 1;
+ max_track = to_track(dskaddr);
+ for(;;) {
+ print("Location? ");
+ get_string_cmd(line, rel_help);
+ if(kill_processes == true)
+ _longjmp(quit_environ, 1);
+ if(line[0] == '\0')
+ continue;
+ ptr = line;
+ trim_white(ptr);
+ if(!strncmp(ptr, "he", 2) || !strncmp(ptr, "?", 1) ||
+ !strncmp(ptr, "stat", 4) || !strncmp(ptr, "!", 1))
+ continue;
+ indent();
+ if((*ptr >= 'a') && (*ptr <= 'h')) {
+ register char par = *(ptr++);
+ register int block = get_next_digit(ptr);
+
+ dskaddr = *from_unix((unsigned char)par,
+ (unsigned int)block);
+ if((dskaddr.cylinder == -1) || (block == -1)) {
+ print("Invalid UNIX block number!\n");
+ goto next;
+ }
+ print("Confirm block %d on file-system '%c'",block,par);
+ if(get_yes_no("") == true) {
+ entry=(*C_INFO.code_pos)(dskaddr,HEADER_ERROR);
+ add_user_relocations(&entry);
+ }
+ }
+ else if(*ptr == 't') {
+ register int trk = get_next_digit(ptr);
+
+ if((trk == -1) || (trk >= max_track)) {
+ print("Invalid track number!\n");
+ goto next;
+ }
+ print("Confirm track %d", trk);
+ if(get_yes_no("") == true) {
+ dskaddr = *from_track(trk);
+ entry=(*C_INFO.code_pos)(dskaddr,HEADER_ERROR);
+ add_user_relocations(&entry);
+ }
+ }
+ else if(!strncmp(ptr, "se", 2)) {
+ register int sec = get_next_digit(ptr);
+
+ if((sec == -1) ||
+ ((CURRENT->vc_nsec*CURRENT->vc_ntrak*CURRENT->vc_ncyl)<sec)){
+ print("Invalid sector number!\n");
+ goto next;
+ }
+ print("Confirm sector %d", sec);
+ if(get_yes_no("") == true) {
+ dskaddr = *from_sector((unsigned int)sec);
+ entry = (*C_INFO.code_pos)(dskaddr, DATA_ERROR);
+ add_user_relocations(&entry);
+ }
+ }
+ else if(is_digit(*ptr)) {
+ entry.bs_cyl = get_next_digit(ptr);
+ skipdigits(ptr);
+ finddigit(ptr);
+ entry.bs_trk = get_next_digit(ptr);
+ skipdigits(ptr);
+ finddigit(ptr);
+ entry.bs_offset = get_next_digit(ptr);
+ skipdigits(ptr);
+ finddigit(ptr);
+ entry.bs_length = get_next_digit(ptr);
+ if((entry.bs_trk != -1) && (entry.bs_offset != -1) &&
+ (entry.bs_length != -1)) {
+ if(entry.bs_cyl >= CURRENT->vc_ncyl)
+ print("Cylinder number to high!\n");
+ else if(entry.bs_trk >= CURRENT->vc_ntrak)
+ print("Head number to high!\n");
+ else if(entry.bs_offset >= CURRENT->vc_traksize)
+ print("Offset too long!\n");
+ else if(entry.bs_length == 0)
+ print("Can't have a 0 length error!\n");
+ else {
+ print("Confirm Cyl %d, ",entry.bs_cyl);
+ printf("Head %d, ", entry.bs_trk);
+ printf("offset %d, ", entry.bs_offset);
+ printf("length %d", entry.bs_length);
+ if(get_yes_no("") == true)
+ add_user_relocations(&entry);
+ }
+ }
+ else
+ goto bad;
+ }
+ else if(!strncmp(ptr, "star", 4)) {
+ exdent(1);
+ break;
+ }
+ else
+bad: print("What?\n");
+next: exdent(1);
+ }
+}
+
+dskadr check_track_for_relocations(entry, i)
+bs_entry entry;
+register int i;
+{
+ register int j = i;
+ fmt_err temp, cmp;
+ boolean bad_track = false;
+
+ cmp = (*C_INFO.decode_pos)(entry);
+ /* Check to see if a alternate track is or will be on this track */
+ while((bad_map->list[j].bs_cyl == entry.bs_cyl) &&
+ (bad_map->list[j].bs_trk == entry.bs_trk)) {
+ temp = (*C_INFO.decode_pos)(bad_map->list[j]);
+ if(temp.err_stat & HEADER_ERROR) {
+ bad_track = true;
+ /* if track was mapped out (it can't be us) */
+ if(((bad_map->list[j].bs_alt.cylinder != 0)) ||
+ (bad_map->list[j].bs_alt.track != 0) ||
+ (bad_map->list[j].bs_alt.sector != 0)) {
+ return cmp.err_adr;
+ }
+ }
+ j++;
+ }
+ /*
+ ** If it was a bad track and it was not the current entry
+ ** that produced it then then map it
+ ** to itself and forget about it for now since it will be taken
+ ** care of later.
+ **
+ ** If it was the current entry return zero and the track will be
+ ** mapped out correctly.
+ */
+ if(bad_track == true) {
+ if(cmp.err_stat & HEADER_ERROR)
+ return entry.bs_alt; /* better known as zero */
+ else
+ return cmp.err_adr;
+ }
+ /*
+ ** if we made it through all the bad track stuff then check for
+ ** multiple errors on the same sector that are already mapped!
+ */
+ j = i;
+ while((bad_map->list[j].bs_cyl == entry.bs_cyl) &&
+ (bad_map->list[j].bs_trk == entry.bs_trk)) {
+ temp = (*C_INFO.decode_pos)(bad_map->list[j]);
+ if(temp.err_adr.sector == cmp.err_adr.sector) {
+ /* if it is not really the current entry */
+ if((bad_map->list[j].bs_offset != entry.bs_offset) ||
+ (bad_map->list[j].bs_length != entry.bs_length)) {
+ /* if the sector is already mapped out */
+ if(((bad_map->list[j].bs_alt.cylinder != 0)) ||
+ (bad_map->list[j].bs_alt.track != 0) ||
+ (bad_map->list[j].bs_alt.sector != 0)) {
+ return temp.err_adr;
+ }
+ }
+ }
+ j++;
+ }
+ return entry.bs_alt;
+}
+
+
+/*
+**
+*/
+
+dskadr is_relocated(entry)
+bs_entry entry;
+{
+ register int i;
+
+ for(i=0; i<bad_map->bs_count; i++)
+ if((bad_map->list[i].bs_cyl == entry.bs_cyl) &&
+ (bad_map->list[i].bs_trk == entry.bs_trk))
+ return check_track_for_relocations(entry, i);
+ return entry.bs_alt;
+}
+
+
+
+/*
+**
+*/
+
+sync_bad_sector_map()
+{
+ register int i;
+ dskadr dskaddr;
+
+ /*
+ ** do all the relocation cylinders first to allocate all flaws in
+ ** relocation area.
+ */
+ for(i=bad_map->bs_count-1; i>=0; i--) {
+ if((bad_map->list[i].bs_cyl >= CURRENT->vc_ncyl-NUMSYS) &&
+ (bad_map->list[i].bs_cyl < CURRENT->vc_ncyl-NUMMAP-NUMMNT)) {
+ if((bad_map->list[i].bs_alt.cylinder == 0) &&
+ (bad_map->list[i].bs_alt.track == 0) &&
+ (bad_map->list[i].bs_alt.sector == 0)) {
+ bad_map->list[i].bs_alt =
+ *new_location(&bad_map->list[i]);
+ }
+ }
+ }
+ for(i=bad_map->bs_count-1; i>=0; i--) {
+ if((bad_map->list[i].bs_alt.cylinder == 0) &&
+ (bad_map->list[i].bs_alt.track == 0) &&
+ (bad_map->list[i].bs_alt.sector == 0)) {
+ dskaddr = is_relocated(bad_map->list[i]);
+ if((dskaddr.cylinder == 0) && (dskaddr.track == 0) &&
+ (dskaddr.sector == 0)) {
+ bad_map->list[i].bs_alt =
+ *new_location(&bad_map->list[i]);
+ do_relocation(bad_map->list[i]);
+ }
+ else
+ bad_map->list[i].bs_alt = dskaddr;
+ }
+ }
+ write_bad_sector_map();
+}
+
+
+
+/*
+**
+*/
+
+do_relocation(entry)
+bs_entry entry;
+{
+ fmt_err temp;
+
+ if(entry.bs_cyl >= CURRENT->vc_ncyl-NUMSYS)
+ if(entry.bs_cyl != (CURRENT->vc_ncyl - NUMMAP - NUMMNT))
+ return;
+ temp = (*C_INFO.decode_pos)(entry);
+ if((entry.bs_alt.cylinder == 0) && (entry.bs_alt.track == 0) &&
+ (entry.bs_alt.sector == 0))
+ print_unix_block(temp.err_adr);
+ else if(temp.err_stat & HEADER_ERROR)
+ if(C_INFO.type == SMDCTLR) {
+ print("Can't relocate tracks on VDDC controllers.\n");
+ print_unix_block(temp.err_adr);
+ }
+ else
+ relocate_track(entry);
+ else
+ relocate_sector(entry);
+}
+
+
+/*
+**
+*/
+
+relocate_sector(entry)
+bs_entry entry;
+{
+ dskadr phys, reloc;
+ fmt_err temp;
+ register long status;
+
+ temp = (*C_INFO.decode_pos)(entry);
+ phys = temp.err_adr;
+ reloc = entry.bs_alt;
+ format_sectors(&phys, &reloc, RELOC_SECTOR, (long)1);
+
+ format_sectors(&reloc, &phys, ALT_SECTOR, (long)1);
+ status = access_dsk((char *)save, &temp.err_adr, WD, 1, 1);
+ if(!((status & ALTACC) && !(status & (HRDERR |SFTERR)))) {
+ print("Sector relocation failed. Status = 0x%x.\n", status);
+ print_unix_block(phys);
+ }
+}
+
+
+
+/*
+**
+*/
+
+relocate_track(entry)
+bs_entry entry;
+{
+ dskadr phys, reloc;
+ fmt_err temp;
+ register long status;
+
+ temp = (*C_INFO.decode_pos)(entry);
+ temp.err_adr.sector = 0;
+ phys = temp.err_adr;
+ reloc = entry.bs_alt;
+ reloc.sector = 0xff;
+ format_sectors(&phys, &reloc, RELOC_SECTOR, (long)CURRENT->vc_nsec);
+
+ reloc.sector = 0x00;
+ format_sectors(&reloc, &phys, ALT_SECTOR, (long)CURRENT->vc_nsec);
+ status = access_dsk((char *)save, &temp.err_adr, WD, CURRENT->vc_nsec, 1);
+ if(!((status & ALTACC) && !(status & (HRDERR | SFTERR)))) {
+ print("Track relocation failed. Status = 0x%x.\n", status);
+ print_unix_block(phys);
+ }
+}
+
+
+