129533Ssam #ifndef lint 2*31318Ssam static char sccsid[] = "@(#)maps.c 1.4 (Berkeley/CCI) 06/01/87"; 329533Ssam #endif 429533Ssam 529533Ssam 629533Ssam #include "vdfmt.h" 729533Ssam 829533Ssam 929533Ssam /* 1029533Ssam ** 1129533Ssam */ 1229533Ssam 1329533Ssam boolean align_buf(buf, sync) 1429533Ssam unsigned long *buf; 1529533Ssam unsigned long sync; 1629533Ssam { 1729533Ssam register int i, shift; 1829533Ssam 1929533Ssam /* find shift amount */ 2029533Ssam for(shift=0; shift<32; shift++) { 2129533Ssam if((*buf >> shift ) == sync) { 2229533Ssam for(i=(512/sizeof(long))-1; i >= 0; i--) { 2329533Ssam *(buf+i+1) |= *(buf+i) << (32 - shift); 2429533Ssam *(buf+i) = *(buf+i) >> shift; 2529533Ssam } 2629533Ssam return true; 2729533Ssam } 2829533Ssam } 2929533Ssam return false; 3029533Ssam } 3129533Ssam 3229533Ssam 3329533Ssam /* 3429533Ssam ** Looks for two maps in a row that are the same. 3529533Ssam */ 3629533Ssam 3729981Skarels boolean 3829981Skarels read_map(flags) 3929533Ssam short flags; 4029533Ssam { 4129533Ssam register int trk, i; 4229533Ssam dskadr dskaddr; 4329533Ssam 4429533Ssam dskaddr.cylinder = (CURRENT->vc_ncyl - 1) | flags; 4529533Ssam for(i=0; i<100; i++) 4629533Ssam scratch[i] = -1; 4729533Ssam for(trk=0; trk<CURRENT->vc_ntrak; trk++) { 4829533Ssam dskaddr.track = trk; 4929533Ssam dskaddr.sector = 0; 50*31318Ssam if(access_dsk((char *)save,&dskaddr, VDOP_RD, 51*31318Ssam CURRENT->vc_nsec,1)& VDERR_HARD) 5229533Ssam continue; 5329533Ssam if(blkcmp((char *)scratch, (char *)save, bytes_trk) == true) { 5429533Ssam blkcopy((char *)save, (char *)bad_map, bytes_trk); 5529533Ssam if(bad_map->bs_count <= MAX_FLAWS) { 5629533Ssam for(i=0; i<bad_map->bs_count; i++) { 5729533Ssam if(bad_map->list[i].bs_cyl >= 5829533Ssam CURRENT->vc_ncyl) 5929533Ssam break; 6029533Ssam if(bad_map->list[i].bs_trk >= 6129533Ssam CURRENT->vc_ntrak) 6229533Ssam break; 6329533Ssam if(bad_map->list[i].bs_offset >= 6429533Ssam CURRENT->vc_traksize) 6529533Ssam break; 6629533Ssam } 6729533Ssam if(i == bad_map->bs_count) { 6829533Ssam load_free_table(); 6929533Ssam return true; 7029533Ssam } 7129981Skarels } 7229533Ssam blkzero(bad_map, bytes_trk); 7329533Ssam bad_map->bs_id = 0; 7429533Ssam bad_map->bs_max = MAX_FLAWS; 7529533Ssam } 7629533Ssam blkcopy((char *)save, (char *)scratch, bytes_trk); 7729533Ssam } 7829533Ssam return false; 7929533Ssam } 8029533Ssam 8129533Ssam 8229533Ssam /* 8329533Ssam ** 8429533Ssam */ 8529533Ssam 8629533Ssam boolean read_bad_sector_map() 8729533Ssam { 8829533Ssam dskadr dskaddr; 8929533Ssam 9029533Ssam dskaddr.cylinder = CURRENT->vc_ncyl - 1; 9129533Ssam dskaddr.track = 0; 9229533Ssam dskaddr.sector = 0; 9329533Ssam /* start with nothing in map */ 9429533Ssam blkzero(bad_map, bytes_trk); 9529533Ssam bad_map->bs_id = 0; 9629533Ssam bad_map->bs_max = MAX_FLAWS; 97*31318Ssam if (C_INFO.type == VDTYPE_SMDE) { 98*31318Ssam access_dsk((char *)save, &dskaddr, VDOP_RDRAW, 1, 1); 9929981Skarels if (align_buf((unsigned long *)save, CDCSYNC) == true) { 10029533Ssam read_flaw_map(); 10129981Skarels return (false); 10229981Skarels } else if (read_map(NRM) == true) { 10329981Skarels return (true); 10429981Skarels } else { 10529533Ssam get_smde_relocations(); 10629533Ssam return false; 10729533Ssam } 10829981Skarels } else { 10929981Skarels if (read_map(WPT) == true) 11029981Skarels return (true); 11129981Skarels else { 11229981Skarels get_relocations_the_hard_way(); 11329981Skarels return (false); 11429981Skarels } 11529533Ssam } 11629533Ssam } 11729533Ssam 11829533Ssam 11929533Ssam /* 12029533Ssam ** 12129533Ssam */ 12229533Ssam 12329533Ssam get_relocations_the_hard_way() 12429533Ssam { 12529533Ssam register int cyl, trk; 12629533Ssam register int status; 12729533Ssam dskadr dskaddr; 12829533Ssam 12929533Ssam dskaddr.sector = 0; 13029533Ssam /* scan each sector to see if it is relocated and take note if it is */ 13129533Ssam for(cyl=0; cyl<CURRENT->vc_ncyl-NUMSYS; cyl++) { 13229533Ssam dskaddr.cylinder = cyl; 13329533Ssam for(trk=0; trk<CURRENT->vc_ntrak; trk++) { 13429533Ssam dskaddr.track = trk; 13529533Ssam status=access_dsk((char *)scratch, &dskaddr, 136*31318Ssam VDOP_RD, CURRENT->vc_nsec, 1); 137*31318Ssam if(status & DCBS_ATA) 13829533Ssam get_track_relocations(dskaddr); 13929533Ssam } 14029533Ssam } 14129533Ssam load_free_table(); 14229533Ssam } 14329533Ssam 14429533Ssam 14529533Ssam /* 14629533Ssam ** 14729533Ssam */ 14829533Ssam 14929533Ssam get_track_relocations(dskaddr) 15029533Ssam dskadr dskaddr; 15129533Ssam { 15229533Ssam register int status; 15329533Ssam bs_entry temp; 15429533Ssam fmt_err error; 15529533Ssam 15629533Ssam for(dskaddr.sector=0; dskaddr.sector<CURRENT->vc_nsec; dskaddr.sector++) { 157*31318Ssam status = access_dsk((char *)scratch, &dskaddr, VDOP_RD, 1, 1); 158*31318Ssam if(status & DCBS_ATA) { 15929533Ssam error.err_adr = dskaddr; 16029533Ssam error.err_stat = DATA_ERROR; 16129533Ssam temp = (*C_INFO.code_pos)(error); 16229533Ssam temp.bs_how = operator; 16329533Ssam add_flaw(&temp); 16429533Ssam } 16529533Ssam } 16629533Ssam } 16729533Ssam 16829533Ssam 16929533Ssam /* 17029533Ssam ** 17129533Ssam */ 17229533Ssam 17329533Ssam remove_user_relocations(entry) 17429533Ssam bs_entry entry; 17529533Ssam { 17629533Ssam register int i, j; 17729533Ssam fmt_err temp; 17829533Ssam fmt_err error; 17929533Ssam bs_entry *ptr; 18029533Ssam 18129533Ssam error = (*C_INFO.decode_pos)(entry); 18229533Ssam if(is_in_map(&error.err_adr) == true) { 18329533Ssam ptr = bad_map->list; 18429533Ssam for(i=0; i<bad_map->bs_count; i++) { 18529533Ssam temp = (*C_INFO.decode_pos)(*ptr); 18629533Ssam if((ptr->bs_how == operator) && 18729533Ssam (temp.err_adr.cylinder == error.err_adr.cylinder) && 18829533Ssam (temp.err_adr.track == error.err_adr.track) && 18929533Ssam (temp.err_adr.sector == error.err_adr.sector)) { 19029533Ssam if(temp.err_stat & HEADER_ERROR) 19129533Ssam remove_track(temp, ptr); 19229533Ssam else 19329533Ssam remove_sector(temp, ptr); 19429533Ssam for(j=i+1; j<bad_map->bs_count; j++) 19529533Ssam bad_map->list[j-1] = bad_map->list[j]; 19629533Ssam bad_map->bs_count--; 19729533Ssam return; 19829533Ssam } 19929533Ssam ptr++; 20029533Ssam } 20129533Ssam } 20229533Ssam else { 20329533Ssam indent(); 20429533Ssam print("Sector %d is not in bad sector map!\n", 20529533Ssam to_sector(error.err_adr)); 20629533Ssam exdent(1); 20729533Ssam } 20829533Ssam } 20929533Ssam 21029533Ssam 21129533Ssam /* 21229533Ssam ** 21329533Ssam */ 21429533Ssam 21529533Ssam remove_sector(error, entry) 21629533Ssam fmt_err error; 21729533Ssam bs_entry *entry; 21829533Ssam { 21929533Ssam format_sectors(&error.err_adr, &error.err_adr, NRM, 1); 22029533Ssam format_sectors(&entry->bs_alt, &entry->bs_alt, NRM, 1); 22129533Ssam } 22229533Ssam 22329533Ssam 22429533Ssam /* 22529533Ssam ** 22629533Ssam */ 22729533Ssam 22829533Ssam remove_track(error, entry) 22929533Ssam fmt_err error; 23029533Ssam bs_entry *entry; 23129533Ssam { 23229533Ssam format_sectors(&error.err_adr,&error.err_adr,NRM,(long)CURRENT->vc_nsec); 23329533Ssam format_sectors(&entry->bs_alt,&entry->bs_alt,NRM,(long)CURRENT->vc_nsec); 23429533Ssam } 23529533Ssam 23629533Ssam 23729533Ssam /* 23829533Ssam ** 23929533Ssam */ 24029533Ssam 24129533Ssam write_bad_sector_map() 24229533Ssam { 24329533Ssam register int trk, sec; 24429533Ssam dskadr dskaddr; 24529533Ssam 24629533Ssam dskaddr.cylinder = (CURRENT->vc_ncyl - NUMMAP); 24729533Ssam for(trk=0; trk<CURRENT->vc_ntrak; trk++) { 24829533Ssam for(sec = 0; sec < CURRENT->vc_nsec; sec++) { 24929981Skarels blkcopy((char *)bs_map_space + (sec * SECSIZ), 25029533Ssam (char *)scratch, SECSIZ); 25129533Ssam dskaddr.track = trk; 25229533Ssam dskaddr.sector = sec; 25329533Ssam format_sectors(&dskaddr, &dskaddr, WPT, 1); 25429533Ssam } 25529533Ssam } 25629533Ssam } 25729533Ssam 25829533Ssam 25929533Ssam /* 26029533Ssam ** 26129533Ssam */ 26229533Ssam 26329533Ssam zero_bad_sector_map() 26429533Ssam { 26529533Ssam bs_map *bm = bad_map; 26629533Ssam register int i; 26729533Ssam dskadr zero; 26829533Ssam 26929533Ssam zero.cylinder = 0; 27029533Ssam zero.track = 0; 27129533Ssam zero.sector = 0; 27229533Ssam for(i=0; i<bm->bs_count; i++) 27329533Ssam bm->list[i].bs_alt = zero; 27429533Ssam load_free_table(); 27529533Ssam } 27629533Ssam 27729533Ssam 27829533Ssam /* 27929533Ssam ** 28029533Ssam */ 28129533Ssam 28229533Ssam read_flaw_map() 28329533Ssam { 28429533Ssam register int cyl, trk; 28529533Ssam dskadr dskaddr; 28629533Ssam flaw buffer; 28729533Ssam 28829533Ssam dskaddr.sector = 0; 28929533Ssam for (cyl=0; cyl<CURRENT->vc_ncyl; cyl++) { 29029533Ssam dskaddr.cylinder = cyl; 29129533Ssam for (trk=0; trk<CURRENT->vc_ntrak; trk++) { 29229533Ssam dskaddr.track = trk; 293*31318Ssam access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1); 29429533Ssam if(align_buf(&buffer, CDCSYNC) == true) { 29529533Ssam add_flaw_entries(&buffer); 29629533Ssam continue; 29729533Ssam } 29829533Ssam } 29929533Ssam } 30029533Ssam load_free_table(); 30129533Ssam } 30229533Ssam 30329533Ssam 30429533Ssam /* 30529533Ssam ** 30629533Ssam */ 30729533Ssam 30829533Ssam get_smde_relocations() 30929533Ssam { 31029533Ssam register int cyl, trk, sec; 31129533Ssam smde_hdr buffer; 31229533Ssam dskadr dskaddr; 31329533Ssam fmt_err bad; 31429533Ssam bs_entry temp; 31529533Ssam boolean bad_track; 31629533Ssam 31729533Ssam /* Read any old drive relocations */ 31829533Ssam for(cyl=0; cyl<NUMREL; cyl++) { 31929533Ssam dskaddr.cylinder = CURRENT->vc_ncyl - NUMSYS + cyl; 32029533Ssam for(trk=0; trk<CURRENT->vc_ntrak; trk++) { 32129533Ssam dskaddr.track = trk; 32229533Ssam bad_track = true; 32329533Ssam for(sec=0; sec<CURRENT->vc_nsec; sec++) { 32429533Ssam dskaddr.sector = sec; 325*31318Ssam access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1); 32629533Ssam if(align_buf(&buffer, SMDE1SYNC) == false) { 32729533Ssam bad_track = false; 32829533Ssam break; 32929533Ssam } 33029533Ssam } 33129533Ssam if(bad_track == true) { 33229533Ssam dskaddr.sector = 0; 33329533Ssam bad.err_adr.cylinder = buffer.alt_cyl; 33429533Ssam bad.err_adr.track = buffer.alt_trk; 33529533Ssam bad.err_adr.sector = 0; 33629533Ssam bad.err_stat = HEADER_ERROR; 33729533Ssam temp = (*C_INFO.code_pos)(bad); 33829533Ssam temp.bs_alt = dskaddr; 33929533Ssam temp.bs_how = scanning; 34029533Ssam add_flaw(&temp); 34129533Ssam continue; 34229533Ssam } 34329533Ssam for(sec=0; sec<CURRENT->vc_nsec; sec++) { 34429533Ssam dskaddr.sector = sec; 345*31318Ssam access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1); 34629533Ssam if(align_buf(&buffer, SMDE1SYNC) == true) { 34729533Ssam bad.err_adr.cylinder = buffer.alt_cyl; 34829533Ssam bad.err_adr.track = buffer.alt_trk; 34929533Ssam bad.err_adr.sector = buffer.alt_sec; 35029533Ssam bad.err_stat = DATA_ERROR; 35129533Ssam temp = (*C_INFO.code_pos)(bad); 35229533Ssam temp.bs_alt = dskaddr; 35329533Ssam temp.bs_how = scanning; 35429533Ssam add_flaw(&temp); 35529533Ssam } 35629533Ssam } 35729533Ssam } 35829533Ssam } 35929533Ssam load_free_table(); 36029533Ssam } 36129533Ssam 36229533Ssam 36329533Ssam /* 36429533Ssam ** 36529533Ssam */ 36629533Ssam 36729533Ssam add_flaw_entries(buffer) 36829533Ssam flaw *buffer; 36929533Ssam { 37029533Ssam register int i; 37129533Ssam bs_entry temp; 37229533Ssam 37329533Ssam temp.bs_cyl = buffer->flaw_cyl & 0x7fff; /* clear off bad track bit */ 37429533Ssam temp.bs_trk = buffer->flaw_trk; 37529533Ssam for(i=0; i<4; i++) { 37629533Ssam if(buffer->flaw_pos[i].flaw_length != 0) { 37729533Ssam temp.bs_offset = buffer->flaw_pos[i].flaw_offset; 37829533Ssam temp.bs_length = buffer->flaw_pos[i].flaw_length; 37929533Ssam temp.bs_alt.cylinder = 0; 38029533Ssam temp.bs_alt.track = 0; 38129533Ssam temp.bs_alt.sector = 0; 38229533Ssam temp.bs_how = flaw_map; 38329533Ssam add_flaw(&temp); 38429533Ssam } 38529533Ssam } 38629533Ssam } 38729533Ssam 38829533Ssam 38929533Ssam cmp_entry(a, b) 39029533Ssam bs_entry *a; 39129533Ssam bs_entry *b; 39229533Ssam { 39329533Ssam if(a->bs_cyl == b->bs_cyl) { 39429533Ssam if(a->bs_trk == b->bs_trk) { 39529533Ssam if(a->bs_offset == b->bs_offset) 39629533Ssam return 0; 39729533Ssam else if(a->bs_offset < b->bs_offset) 39829533Ssam return -1; 39929981Skarels } 40029533Ssam else if(a->bs_trk < b->bs_trk) 40129533Ssam return -1; 40229533Ssam } 40329533Ssam else if(a->bs_cyl < b->bs_cyl) 40429533Ssam return -1; 40529533Ssam return 1; 40629533Ssam } 40729533Ssam 40829533Ssam 40929533Ssam add_flaw(entry) 41029533Ssam bs_entry *entry; 41129533Ssam { 41229533Ssam extern int cmp_entry(); 41329533Ssam bs_map *bm = bad_map; 41429533Ssam register int i; 41529533Ssam 41629533Ssam if(bm->bs_count > MAX_FLAWS) 41729533Ssam return; 41829981Skarels if (entry->bs_cyl >= CURRENT->vc_ncyl || 41929981Skarels entry->bs_trk >= CURRENT->vc_ntrak || 42029981Skarels entry->bs_offset >= CURRENT->vc_traksize) 42129981Skarels return; 42229533Ssam for(i=0; i<bm->bs_count; i++) { 42329533Ssam if(((bm->list[i].bs_cyl == entry->bs_cyl)) && 42429533Ssam (bm->list[i].bs_trk == entry->bs_trk) && 42529533Ssam (bm->list[i].bs_offset == entry->bs_offset)) { 42629533Ssam if((int)bm->list[i].bs_how > (int)entry->bs_how) 42729533Ssam bm->list[i].bs_how = entry->bs_how; 42829533Ssam return; 42929533Ssam } 43029533Ssam } 43129533Ssam bm->list[i] = *entry; 43229533Ssam bm->list[i].bs_alt.cylinder = 0; 43329533Ssam bm->list[i].bs_alt.track = 0; 43429533Ssam bm->list[i].bs_alt.sector = 0; 43529533Ssam bm->bs_count++; 43629533Ssam qsort((char *)&(bm->list[0]), (unsigned)bm->bs_count, 43729533Ssam sizeof(bs_entry), cmp_entry); 43829533Ssam } 43929533Ssam 44029533Ssam 44129533Ssam /* 44229533Ssam ** Is_in_map checks to see if a block is known to be bad already. 44329533Ssam */ 44429533Ssam 44529533Ssam boolean is_in_map(dskaddr) 44629533Ssam dskadr *dskaddr; 44729533Ssam { 44829533Ssam register int i; 44929533Ssam fmt_err temp; 45029533Ssam 45129533Ssam for(i=0; i<bad_map->bs_count; i++) { 45229533Ssam temp = (*C_INFO.decode_pos)(bad_map->list[i]); 45329533Ssam if((temp.err_adr.cylinder == dskaddr->cylinder) && 45429533Ssam (temp.err_adr.track == dskaddr->track) && 45529533Ssam (temp.err_adr.sector == dskaddr->sector)) { 45629533Ssam return true; 45729533Ssam } 45829533Ssam } 45929533Ssam return false; 46029533Ssam } 46129533Ssam 46229533Ssam 46329533Ssam /* 46429533Ssam ** 46529533Ssam */ 46629533Ssam 46729533Ssam print_bad_sector_list() 46829533Ssam { 46929533Ssam register int i; 47029533Ssam fmt_err errloc; 47129533Ssam 47229533Ssam if(bad_map->bs_count == 0) { 47329533Ssam print("There are no bad sectors in bad sector map.\n"); 47429533Ssam return; 47529533Ssam } 47629533Ssam print("The following sector%s known to be bad:\n", 47729533Ssam (bad_map->bs_count == 1) ? " is" : "s are"); 47829533Ssam indent(); 47929533Ssam for(i=0; i<bad_map->bs_count; i++) { 48029533Ssam print("cyl %d, head %d, pos %d, len %d ", 48129533Ssam bad_map->list[i].bs_cyl, 48229533Ssam bad_map->list[i].bs_trk, 48329533Ssam bad_map->list[i].bs_offset, 48429533Ssam bad_map->list[i].bs_length); 48529533Ssam errloc = (*C_INFO.decode_pos)(bad_map->list[i]); 48629533Ssam if(errloc.err_stat & HEADER_ERROR) { 48729533Ssam printf("(Track #%d)", to_track(errloc.err_adr)); 48829533Ssam } 48929533Ssam else { 49029533Ssam printf("(Sector #%d)", to_sector(errloc.err_adr)); 49129533Ssam } 49229533Ssam if((bad_map->list[i].bs_alt.cylinder != 0) || 49329533Ssam (bad_map->list[i].bs_alt.track != 0) || 49429533Ssam (bad_map->list[i].bs_alt.sector != 0)) { 49529533Ssam indent(); 49629533Ssam printf(" -> "); 49729533Ssam if(errloc.err_stat & HEADER_ERROR) { 49829533Ssam printf("Track %d", 49929533Ssam to_track(bad_map->list[i].bs_alt)); 50029533Ssam } 50129533Ssam else { 50229533Ssam printf("Sector %d", 50329533Ssam to_sector(bad_map->list[i].bs_alt)); 50429533Ssam } 50529533Ssam exdent(1); 50629533Ssam } 50729533Ssam printf(".\n"); 50829533Ssam } 50929533Ssam exdent(1); 51029533Ssam } 51129533Ssam 51229533Ssam 51329533Ssam /* 51429533Ssam ** Vdload_free_table checks each block in the bad block relocation area 51529533Ssam ** to see if it is used. If it is, the free relocation block table is updated. 51629533Ssam */ 51729533Ssam 51829533Ssam load_free_table() 51929533Ssam { 52029533Ssam register int i, j; 52129533Ssam fmt_err temp; 52229533Ssam 52329533Ssam /* Clear free table before starting */ 52429533Ssam for(i = 0; i < (CURRENT->vc_ntrak * NUMREL); i++) { 52529533Ssam for(j=0; j < CURRENT->vc_nsec; j++) 52629533Ssam free_tbl[i][j].free_status = NOTALLOCATED; 52729533Ssam } 52829533Ssam for(i=0; i<bad_map->bs_count; i++) 52929533Ssam if((bad_map->list[i].bs_alt.cylinder != 0) || 53029533Ssam (bad_map->list[i].bs_alt.track != 0) || 53129533Ssam (bad_map->list[i].bs_alt.sector != 0)) { 53229533Ssam temp = (*C_INFO.decode_pos)(bad_map->list[i]); 53329533Ssam allocate(&(bad_map->list[i].bs_alt), temp.err_stat); 53429533Ssam } 53529533Ssam } 53629533Ssam 53729533Ssam 53829533Ssam /* 53929533Ssam ** allocate marks a replacement sector as used. 54029533Ssam */ 54129533Ssam 54229533Ssam allocate(dskaddr, status) 54329533Ssam dskadr *dskaddr; 54429533Ssam long status; 54529533Ssam { 54629533Ssam register int trk, sec; 54729533Ssam 54829533Ssam trk = dskaddr->cylinder - (CURRENT->vc_ncyl - NUMSYS); 54929533Ssam if((trk < 0) || (trk >= NUMREL)) 55029533Ssam return; 55129533Ssam trk *= CURRENT->vc_ntrak; 55229533Ssam trk += dskaddr->track; 55329533Ssam if(status & HEADER_ERROR) 55429533Ssam for(sec=0; sec<CURRENT->vc_nsec; sec++) 55529533Ssam free_tbl[trk][sec].free_status = ALLOCATED; 55629533Ssam else 55729533Ssam free_tbl[trk][dskaddr->sector].free_status = ALLOCATED; 55829533Ssam } 55929533Ssam 56029533Ssam 56129533Ssam /* 56229533Ssam ** 56329533Ssam */ 56429533Ssam 56529533Ssam boolean mapping_collision(entry) 56629533Ssam bs_entry *entry; 56729533Ssam { 56829533Ssam register int trk, sec; 56929533Ssam fmt_err temp; 57029533Ssam 57129533Ssam trk = entry->bs_cyl - (CURRENT->vc_ncyl - NUMSYS); 57229533Ssam if((trk < 0) || (trk >= NUMREL)) 57329533Ssam return false; 57429533Ssam trk *= CURRENT->vc_ntrak; 57529533Ssam trk += entry->bs_trk; 57629533Ssam temp = (*C_INFO.decode_pos)(*entry); 57729533Ssam /* if this relocation should take up the whole track */ 57829533Ssam if(temp.err_stat & HEADER_ERROR) { 57929533Ssam for(sec=0; sec<CURRENT->vc_nsec; sec++) 58029533Ssam if(free_tbl[trk][sec].free_status == ALLOCATED) 58129533Ssam return true; 58229533Ssam } 58329533Ssam /* else just check the current sector */ 58429533Ssam else { 58529533Ssam if(free_tbl[trk][temp.err_adr.sector].free_status == ALLOCATED) 58629533Ssam return true; 58729533Ssam } 58829533Ssam return false; 58929533Ssam } 59029533Ssam 59129533Ssam 59229533Ssam /* 59329533Ssam ** 59429533Ssam */ 59529533Ssam 59629533Ssam report_collision() 59729533Ssam { 59829533Ssam indent(); 59929533Ssam print("Sector resides in relocation area"); 60029533Ssam printf("but it has a sector mapped to it already.\n"); 60129533Ssam print("Please reformat disk with 0 patterns to eliminate problem.\n"); 60229533Ssam exdent(1); 60329533Ssam } 60429533Ssam 60529533Ssam 60629533Ssam /* 60729533Ssam ** 60829533Ssam */ 60929533Ssam 61029533Ssam add_user_relocations(entry) 61129533Ssam bs_entry *entry; 61229533Ssam { 61329533Ssam fmt_err error; 61429533Ssam 61529533Ssam error = (*C_INFO.decode_pos)(*entry); 61629533Ssam if(is_in_map(&error.err_adr) == false) { 61729533Ssam if(mapping_collision(entry) == true) 61829533Ssam report_collision(); 61929533Ssam entry->bs_how = operator; 62029533Ssam add_flaw(entry); 62129533Ssam } 62229533Ssam else { 62329533Ssam indent(); 62429533Ssam print("Sector %d is already mapped out!\n", 62529533Ssam to_sector(error.err_adr)); 62629533Ssam exdent(1); 62729533Ssam } 62829533Ssam } 62929533Ssam 63029533Ssam 63129533Ssam /* 63229533Ssam ** New_location allocates a replacement block given a bad block address. 63329533Ssam ** The algorithm is fairly simple; it simply searches for the first 63429533Ssam ** free sector that has the same sector number of the bad sector. If no sector 63529533Ssam ** is found then the drive should be considered bad because of a microcode bug 63629533Ssam ** in the controller that forces us to use the same sector number as the bad 63729533Ssam ** sector for relocation purposes. Using different tracks and cylinders is ok 63829533Ssam ** of course. 63929533Ssam */ 64029533Ssam 64129533Ssam dskadr *new_location(entry) 64229533Ssam bs_entry *entry; 64329533Ssam { 64429533Ssam register int i, sec; 64529533Ssam static fmt_err temp; 64629533Ssam static dskadr newaddr; 64729533Ssam 64829533Ssam newaddr.cylinder = 0; 64929533Ssam newaddr.track = 0; 65029533Ssam newaddr.sector = 0; 65129533Ssam temp = (*C_INFO.decode_pos)(*entry); 65229533Ssam /* If it is ouside of the user's data area */ 65329533Ssam if(entry->bs_cyl >= CURRENT->vc_ncyl-NUMSYS) { 65429533Ssam /* if it is in the relocation area */ 65529533Ssam if(entry->bs_cyl < (CURRENT->vc_ncyl - NUMMAP - NUMMNT)) { 65629533Ssam /* mark space as allocated */ 65729533Ssam allocate(&temp.err_adr, temp.err_stat); 65829533Ssam return &temp.err_adr; 65929533Ssam } 66029533Ssam /* if it is in the map area forget about it */ 66129533Ssam if(entry->bs_cyl != (CURRENT->vc_ncyl - NUMMAP - NUMMNT)) 66229533Ssam return &temp.err_adr; 66329533Ssam /* otherwise treat maintainence cylinder normally */ 66429533Ssam } 66529533Ssam if(temp.err_stat & (HEADER_ERROR)) { 66629533Ssam for(i = 0; i < (CURRENT->vc_ntrak * NUMREL); i++) { 66729533Ssam for(sec=0; sec < CURRENT->vc_nsec; sec++) { 66829533Ssam if(free_tbl[i][sec].free_status == ALLOCATED) 66929533Ssam break; 67029533Ssam } 67129533Ssam if(sec == CURRENT->vc_nsec) { 67229533Ssam for(sec = 0; sec < CURRENT->vc_nsec; sec++) 67329533Ssam free_tbl[i][sec].free_status=ALLOCATED; 67429533Ssam newaddr.cylinder = i / CURRENT->vc_ntrak + 67529533Ssam (CURRENT->vc_ncyl - NUMSYS); 67629533Ssam newaddr.track = i % CURRENT->vc_ntrak; 67729533Ssam break; 67829533Ssam } 67929533Ssam } 68029533Ssam } 681*31318Ssam else if(C_INFO.type == VDTYPE_VDDC) { 68229533Ssam for(i = 0; i < (CURRENT->vc_ntrak * NUMREL); i++) { 68329533Ssam if(free_tbl[i][temp.err_adr.sector].free_status != 68429533Ssam ALLOCATED) { 68529533Ssam free_tbl[i][temp.err_adr.sector].free_status = 68629533Ssam ALLOCATED; 68729533Ssam newaddr.cylinder = i / CURRENT->vc_ntrak + 68829533Ssam (CURRENT->vc_ncyl - NUMSYS); 68929533Ssam newaddr.track = i % CURRENT->vc_ntrak; 69029533Ssam newaddr.sector = temp.err_adr.sector; 69129533Ssam break; 69229533Ssam } 69329533Ssam } 69429533Ssam } 69529533Ssam else { 69629533Ssam for(i = 0; i < (CURRENT->vc_ntrak * NUMREL); i++) { 69729533Ssam for(sec=0; sec < CURRENT->vc_nsec; sec++) 69829533Ssam if(free_tbl[i][sec].free_status != ALLOCATED) 69929533Ssam break; 70029533Ssam if(sec < CURRENT->vc_nsec) { 70129533Ssam free_tbl[i][sec].free_status = ALLOCATED; 70229533Ssam newaddr.cylinder = i / CURRENT->vc_ntrak + 70329533Ssam (CURRENT->vc_ncyl - NUMSYS); 70429533Ssam newaddr.track = i % CURRENT->vc_ntrak; 70529533Ssam newaddr.sector = sec; 70629533Ssam break; 70729533Ssam } 70829533Ssam } 70929533Ssam } 71029533Ssam return &newaddr; 71129533Ssam } 712