|
|
BSD 4.3reno
#ifndef lint
static char sccsid[] = "@(#)maps.c 1.8 (Berkeley/CCI) 6/24/90";
#endif
#include "vdfmt.h"
/*
**
*/
boolean align_buf(buf, sync)
unsigned long *buf;
unsigned long sync;
{
register int i, shift;
/* find shift amount */
for(shift=0; shift < 32; shift++) {
if((*buf >> shift ) == sync) {
for(i=(512/sizeof(long))-1; i >= 0; i--) {
*(buf+i+1) |= *(buf+i) << (32 - shift);
*(buf+i) = *(buf+i) >> shift;
}
return true;
}
}
return false;
}
/*
** Looks for two maps in a row that are the same.
*/
boolean
read_map(flags)
short flags;
{
register int trk, i;
register bs_map *map;
dskadr dskaddr;
dskaddr.cylinder = (lab->d_ncylinders - 1) | flags;
for(trk=0; trk < lab->d_ntracks; trk++) {
dskaddr.track = trk;
dskaddr.sector = 0;
if(access_dsk((char *)map_space, &dskaddr, VDOP_RD,
lab->d_nsectors, 1) & VDERR_HARD)
continue;
map = &norm_bad_map;
/*
* If this doesn't look like a new-style map,
* but (as an old-style map) bs_count and bs_max are sensible,
* munge pointer to prepend fields missing in old map.
*/
if (map->bs_magic != BSMAGIC &&
map->bs_cksum <= MAX_FLAWMAP(bytes_trk) /* bs_count */
&& map->bs_id <= MAX_FLAWMAP(bytes_trk)) /* bs_max */
map = &offset_bad_map;
if (trk > 0 &&
bcmp((char *)map_space, (char *)save, bytes_trk) == 0 &&
map->bs_count <= MAX_FLAWMAP(bytes_trk)) {
for (i=0; i < map->bs_count; i++) {
if (map->list[i].bs_cyl >=
lab->d_ncylinders)
break;
if (map->list[i].bs_trk >=
lab->d_ntracks)
break;
if (map->list[i].bs_offset >=
lab->d_traksize)
break;
}
if (i == map->bs_count) {
bad_map = map;
load_free_table();
return true;
}
}
bcopy((char *)map_space, (char *)save, bytes_trk);
}
map = &norm_bad_map;
bad_map = map;
bzero((char *)map, bytes_trk);
map->bs_magic = BSMAGIC;
map->bs_id = 0;
map->bs_max = MAX_FLAWS;
return false;
}
/*
**
*/
boolean read_bad_sector_map()
{
dskadr dskaddr;
dskaddr.cylinder = lab->d_ncylinders - 1;
dskaddr.track = 0;
dskaddr.sector = 0;
offset_bad_map.bs_magic = BSMAGIC;
offset_bad_map.bs_cksum = 0;
bad_map = &norm_bad_map;
/* start with nothing in map */
bzero(map_space, bytes_trk);
bad_map->bs_magic = BSMAGIC;
bad_map->bs_id = 0;
bad_map->bs_max = MAX_FLAWS;
if (C_INFO->type == VDTYPE_SMDE) {
access_dsk((char *)save, &dskaddr, VDOP_RDRAW, 1, 1);
if (align_buf((unsigned long *)save, CDCSYNC) == true) {
read_flaw_map();
return (false);
} else if (read_map(NRM) == true) {
return (true);
} else {
get_smde_relocations();
return false;
}
} else {
if (read_map(WPT) == true)
return (true);
else {
get_relocations_the_hard_way();
return (false);
}
}
}
/*
**
*/
get_relocations_the_hard_way()
{
register int cyl, trk;
register int status;
dskadr dskaddr;
dskaddr.sector = 0;
/* scan each sector to see if it is relocated and take note if it is */
for(cyl=0; cyl < lab->d_ncylinders - NUMSYS; cyl++) {
dskaddr.cylinder = cyl;
for(trk=0; trk < lab->d_ntracks; trk++) {
dskaddr.track = trk;
status=access_dsk((char *)scratch, &dskaddr,
VDOP_RD, lab->d_nsectors, 1);
if(status & DCBS_ATA)
get_track_relocations(dskaddr);
}
}
load_free_table();
}
/*
**
*/
get_track_relocations(dskaddr)
dskadr dskaddr;
{
register int status;
bs_entry temp;
fmt_err error;
for(dskaddr.sector=0; dskaddr.sector < lab->d_nsectors; dskaddr.sector++) {
status = access_dsk((char *)scratch, &dskaddr, VDOP_RD, 1, 1);
if(status & DCBS_ATA) {
error.err_adr = dskaddr;
error.err_stat = DATA_ERROR;
(*C_INFO->code_pos)(&error, &temp);
temp.bs_how = operator;
add_flaw(&temp);
}
}
}
/*
**
*/
remove_user_relocations(entry)
bs_entry *entry;
{
register int i, j;
fmt_err temp;
fmt_err error;
register bs_entry *ptr;
(*C_INFO->decode_pos)(entry, &error);
ptr = bad_map->list;
for(i=0; i < bad_map->bs_count; i++) {
if (ptr->bs_cyl != entry->bs_cyl ||
ptr->bs_trk != entry->bs_trk)
continue;
(*C_INFO->decode_pos)(ptr, &temp);
if((ptr->bs_how != flaw_map) &&
(temp.err_adr.cylinder == error.err_adr.cylinder) &&
(temp.err_adr.track == error.err_adr.track) &&
(temp.err_adr.sector == error.err_adr.sector)) {
if(temp.err_stat & HEADER_ERROR)
remove_track(&temp, ptr);
else
remove_sector(&temp, ptr);
for(j=i+1; j < bad_map->bs_count; j++)
bad_map->list[j-1] = bad_map->list[j];
bad_map->bs_count--;
return;
}
ptr++;
}
indent();
print("Sector %d is not in bad sector map!\n",
to_sector(error.err_adr));
exdent(1);
}
clear_relocations(reformat)
boolean reformat;
{
fmt_err temp;
register bs_entry *ptr1, *ptr2, *end;
int oldsub = cur.substate;
cur.substate = sub_rel;
ptr1 = bad_map->list;
ptr2 = bad_map->list;
end = &bad_map->list[bad_map->bs_count];
for (; ptr1 < end; ptr1++) {
if (ptr1->bs_how != flaw_map) {
if (reformat == true) {
(*C_INFO->decode_pos)(ptr1, &temp);
if(temp.err_stat & HEADER_ERROR)
remove_track(&temp, ptr1);
else
remove_sector(&temp, ptr1);
}
bad_map->bs_count--;
} else {
if (ptr1 != ptr2)
*ptr2 = *ptr1;
ptr2++;
}
}
cur.substate = oldsub;
}
/*
**
*/
remove_sector(error, entry)
fmt_err *error;
bs_entry *entry;
{
format_sectors(&error->err_adr, &error->err_adr, NRM, 1);
format_sectors(&entry->bs_alt, &entry->bs_alt, NRM, 1);
}
/*
**
*/
remove_track(error, entry)
fmt_err *error;
bs_entry *entry;
{
format_sectors(&error->err_adr,&error->err_adr,NRM,(long)lab->d_nsectors);
format_sectors(&entry->bs_alt,&entry->bs_alt,NRM,(long)lab->d_nsectors);
}
/*
**
*/
write_bad_sector_map()
{
register int trk, sec;
dskadr dskaddr;
bad_map->bs_magic = BSMAGIC;
bad_map->bs_id = 0;
dskaddr.cylinder = (lab->d_ncylinders - NUMMAP);
for(trk=0; trk < lab->d_ntracks; trk++) {
for(sec = 0; sec < lab->d_nsectors; sec++) {
bcopy((char *)bad_map + (sec * lab->d_secsize),
(char *)scratch, lab->d_secsize);
dskaddr.track = trk;
dskaddr.sector = sec;
format_sectors(&dskaddr, &dskaddr, WPT, 1);
}
}
}
/*
**
*/
zero_bad_sector_map()
{
bs_map *bm = bad_map;
register int i;
dskadr zero;
zero.cylinder = 0;
zero.track = 0;
zero.sector = 0;
for(i=0; i < bm->bs_count; i++)
bm->list[i].bs_alt = zero;
load_free_table();
}
/*
**
*/
read_flaw_map()
{
register int cyl, trk;
dskadr dskaddr;
flaw buffer;
dskaddr.sector = 0;
for (cyl=0; cyl < lab->d_ncylinders; cyl++) {
dskaddr.cylinder = cyl;
for (trk=0; trk < lab->d_ntracks; trk++) {
dskaddr.track = trk;
access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
if(align_buf(&buffer, CDCSYNC) == true) {
add_flaw_entries(&buffer);
continue;
}
}
}
load_free_table();
}
/*
**
*/
get_smde_relocations()
{
register int cyl, trk, sec;
smde_hdr buffer;
dskadr dskaddr;
fmt_err bad;
bs_entry temp;
boolean bad_track;
/* Read any old drive relocations */
for(cyl=0; cyl < NUMREL; cyl++) {
dskaddr.cylinder = lab->d_ncylinders - NUMSYS + cyl;
for(trk=0; trk < lab->d_ntracks; trk++) {
dskaddr.track = trk;
bad_track = true;
for(sec=0; sec < lab->d_nsectors; sec++) {
dskaddr.sector = sec;
access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
if(align_buf(&buffer, SMDE1SYNC) == false) {
bad_track = false;
break;
}
}
if(bad_track == true) {
dskaddr.sector = 0;
bad.err_adr.cylinder = buffer.alt_cyl;
bad.err_adr.track = buffer.alt_trk;
bad.err_adr.sector = 0;
bad.err_stat = HEADER_ERROR;
(*C_INFO->code_pos)(&bad, &temp);
temp.bs_alt = dskaddr;
temp.bs_how = scanning;
add_flaw(&temp);
continue;
}
for(sec=0; sec < lab->d_nsectors; sec++) {
dskaddr.sector = sec;
access_dsk(&buffer, &dskaddr, VDOP_RDRAW, 1, 1);
if(align_buf(&buffer, SMDE1SYNC) == true) {
bad.err_adr.cylinder = buffer.alt_cyl;
bad.err_adr.track = buffer.alt_trk;
bad.err_adr.sector = buffer.alt_sec;
bad.err_stat = DATA_ERROR;
(*C_INFO->code_pos)(&bad, &temp);
temp.bs_alt = dskaddr;
temp.bs_how = scanning;
add_flaw(&temp);
}
}
}
}
load_free_table();
}
/*
**
*/
add_flaw_entries(buffer)
flaw *buffer;
{
register int i;
bs_entry temp;
temp.bs_cyl = buffer->flaw_cyl & 0x7fff; /* clear off bad track bit */
temp.bs_trk = buffer->flaw_trk;
for(i=0; i < 4; i++) {
if(buffer->flaw_pos[i].flaw_length != 0) {
temp.bs_offset = buffer->flaw_pos[i].flaw_offset;
temp.bs_length = buffer->flaw_pos[i].flaw_length;
temp.bs_alt.cylinder = 0;
temp.bs_alt.track = 0;
temp.bs_alt.sector = 0;
temp.bs_how = flaw_map;
add_flaw(&temp);
}
}
}
cmp_entry(a, b)
bs_entry *a;
bs_entry *b;
{
if(a->bs_cyl == b->bs_cyl) {
if(a->bs_trk == b->bs_trk) {
if(a->bs_offset == b->bs_offset)
return 0;
else if(a->bs_offset < b->bs_offset)
return -1;
}
else if(a->bs_trk < b->bs_trk)
return -1;
}
else if(a->bs_cyl < b->bs_cyl)
return -1;
return 1;
}
/*
* Add flaw to map.
* Return value:
* 1 OK
* 0 sector was in map
* -1 failure
*/
add_flaw(entry)
bs_entry *entry;
{
extern int cmp_entry();
bs_map *bm = bad_map;
register int i;
if(bm->bs_count > MAX_FLAWS)
return (-1);
if (entry->bs_cyl >= lab->d_ncylinders ||
entry->bs_trk >= lab->d_ntracks ||
entry->bs_offset >= lab->d_traksize)
return (-1);
for(i=0; i < bm->bs_count; i++) {
if(((bm->list[i].bs_cyl == entry->bs_cyl)) &&
(bm->list[i].bs_trk == entry->bs_trk) &&
(bm->list[i].bs_offset == entry->bs_offset)) {
if((int)bm->list[i].bs_how > (int)entry->bs_how)
bm->list[i].bs_how = entry->bs_how;
return (0);
}
}
bm->list[i] = *entry;
bm->list[i].bs_alt.cylinder = 0;
bm->list[i].bs_alt.track = 0;
bm->list[i].bs_alt.sector = 0;
bm->bs_count++;
qsort((char *)&(bm->list[0]), (unsigned)bm->bs_count,
sizeof(bs_entry), cmp_entry);
return (1);
}
/*
** Is_in_map checks to see if a block is known to be bad already.
*/
boolean is_in_map(dskaddr)
dskadr *dskaddr;
{
register int i;
fmt_err temp;
for(i=0; i < bad_map->bs_count; i++) {
(*C_INFO->decode_pos)(&bad_map->list[i], &temp);
if((temp.err_adr.cylinder == dskaddr->cylinder) &&
(temp.err_adr.track == dskaddr->track) &&
(temp.err_adr.sector == dskaddr->sector)) {
return true;
}
}
return false;
}
/*
**
*/
print_bad_sector_list()
{
register int i;
fmt_err errloc;
register bs_entry *bad;
if(bad_map->bs_magic != BSMAGIC)
print("Bad-sector map magic number wrong! (%x != %x)\n",
bad_map->bs_magic, BSMAGIC);
if(bad_map->bs_count == 0) {
print("There are no bad sectors in bad sector map.\n");
return;
}
print("The following %d sector%s known to be bad:\n",
bad_map->bs_count, (bad_map->bs_count == 1) ? " is" : "s are");
exdent(0);
for(i=0, bad = bad_map->list; i < bad_map->bs_count; i++, bad++) {
(*C_INFO->decode_pos)(bad, &errloc);
print("%c %d cn %d tn %d sn %d pos %d len %d ",
errloc.err_stat & HEADER_ERROR ? 'T' : 'S',
to_sector(errloc.err_adr),
bad->bs_cyl,
bad->bs_trk,
errloc.err_adr.sector,
bad->bs_offset,
bad->bs_length);
if (bad->bs_how == flaw_map)
printf("(flawmap) ");
else if (bad->bs_how == scanning)
printf("(verify) ");
else
printf("(operator) ");
if((bad->bs_alt.cylinder != 0) || (bad->bs_alt.track != 0) ||
(bad->bs_alt.sector != 0)) {
printf("-> ");
printf("cn %d tn %d sn %d", bad->bs_alt.cylinder,
bad->bs_alt.track, bad->bs_alt.sector);
}
printf("\n");
}
}
/*
** load_free_table checks each block in the bad block relocation area
** to see if it is used. If it is, the free relocation block table is updated.
*/
load_free_table()
{
register int i, j;
fmt_err temp;
/* Clear free table before starting */
for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
for(j=0; j < lab->d_nsectors; j++)
free_tbl[i][j].free_status = NOTALLOCATED;
}
for(i=0; i < bad_map->bs_count; 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)) {
(*C_INFO->decode_pos)(&bad_map->list[i], &temp);
allocate(&(bad_map->list[i].bs_alt), temp.err_stat);
}
}
/*
** allocate marks a replacement sector as used.
*/
allocate(dskaddr, status)
dskadr *dskaddr;
long status;
{
register int trk, sec;
trk = dskaddr->cylinder - (lab->d_ncylinders - NUMSYS);
if((trk < 0) || (trk >= NUMREL))
return;
trk *= lab->d_ntracks;
trk += dskaddr->track;
if(status & HEADER_ERROR)
for(sec=0; sec < lab->d_nsectors; sec++)
free_tbl[trk][sec].free_status = ALLOCATED;
else
free_tbl[trk][dskaddr->sector].free_status = ALLOCATED;
}
/*
**
*/
boolean mapping_collision(entry)
bs_entry *entry;
{
register int trk, sec;
fmt_err temp;
trk = entry->bs_cyl - (lab->d_ncylinders - NUMSYS);
if((trk < 0) || (trk >= NUMREL))
return false;
trk *= lab->d_ntracks;
trk += entry->bs_trk;
(*C_INFO->decode_pos)(entry, &temp);
/* if this relocation should take up the whole track */
if(temp.err_stat & HEADER_ERROR) {
for(sec=0; sec < lab->d_nsectors; sec++)
if(free_tbl[trk][sec].free_status == ALLOCATED)
return true;
}
/* else just check the current sector */
else {
if(free_tbl[trk][temp.err_adr.sector].free_status == ALLOCATED)
return true;
}
return false;
}
/*
**
*/
report_collision()
{
indent();
print("Sector resides in relocation area");
printf("but it has a sector mapped to it already.\n");
print("Please reformat disk with 0 patterns to eliminate problem.\n");
exdent(1);
}
/*
**
*/
add_user_relocations(entry)
bs_entry *entry;
{
fmt_err error;
(*C_INFO->decode_pos)(entry, &error);
if(is_in_map(&error.err_adr) == false) {
if(mapping_collision(entry) == true)
report_collision();
entry->bs_how = operator;
add_flaw(entry);
}
else {
indent();
print("Sector %d is already mapped out!\n",
to_sector(error.err_adr));
exdent(1);
}
}
/*
** New_location allocates a replacement block given a bad block address.
** The algorithm is fairly simple; it simply searches for the first
** free sector that has the same sector number of the bad sector. If no sector
** is found then the drive should be considered bad because of a microcode bug
** in the controller that forces us to use the same sector number as the bad
** sector for relocation purposes. Using different tracks and cylinders is ok
** of course.
*/
dskadr *new_location(entry)
bs_entry *entry;
{
register int i, sec;
static fmt_err temp;
static dskadr newaddr;
newaddr.cylinder = 0;
newaddr.track = 0;
newaddr.sector = 0;
(*C_INFO->decode_pos)(entry, &temp);
/* If it is ouside of the user's data area */
if(entry->bs_cyl >= lab->d_ncylinders-NUMSYS) {
/* if it is in the relocation area */
if(entry->bs_cyl < (lab->d_ncylinders - NUMMAP - NUMMNT)) {
/* mark space as allocated */
allocate(&temp.err_adr, temp.err_stat);
return &temp.err_adr;
}
/* if it is in the map area forget about it */
if(entry->bs_cyl != (lab->d_ncylinders - NUMMAP - NUMMNT))
return &temp.err_adr;
/* otherwise treat maintainence cylinder normally */
}
if(temp.err_stat & (HEADER_ERROR)) {
for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
for(sec=0; sec < lab->d_nsectors; sec++) {
if(free_tbl[i][sec].free_status == ALLOCATED)
break;
}
if(sec == lab->d_nsectors) {
for(sec = 0; sec < lab->d_nsectors; sec++)
free_tbl[i][sec].free_status=ALLOCATED;
newaddr.cylinder = i / lab->d_ntracks +
(lab->d_ncylinders - NUMSYS);
newaddr.track = i % lab->d_ntracks;
break;
}
}
}
else if(C_INFO->type == VDTYPE_VDDC) {
for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
if(free_tbl[i][temp.err_adr.sector].free_status !=
ALLOCATED) {
free_tbl[i][temp.err_adr.sector].free_status =
ALLOCATED;
newaddr.cylinder = i / lab->d_ntracks +
(lab->d_ncylinders - NUMSYS);
newaddr.track = i % lab->d_ntracks;
newaddr.sector = temp.err_adr.sector;
break;
}
}
}
else {
for(i = 0; i < (lab->d_ntracks * NUMREL); i++) {
for(sec=0; sec < lab->d_nsectors; sec++)
if(free_tbl[i][sec].free_status != ALLOCATED)
break;
if(sec < lab->d_nsectors) {
free_tbl[i][sec].free_status = ALLOCATED;
newaddr.cylinder = i / lab->d_ntracks +
(lab->d_ncylinders - NUMSYS);
newaddr.track = i % lab->d_ntracks;
newaddr.sector = sec;
break;
}
}
}
return &newaddr;
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.