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