#include #include "hd.h" char rbuf[ HD_SECTOR ]; char wbuf[ HD_SECTOR ]; FILE *input; FILE *logfile; main ( argc , argv ) int argc; char **argv; { char *commands; int done_write; int status; if ( argc != 3 && argc != 4 ) usage (); if ( argc > 3 ) { input = fopen ( argv[3] , "r" ); if ( input == NULL ) { fprintf ( stderr , "Failed to open '%s'\n" ); usage (); } } else input = NULL; logfile = fopen ( argv[1] , "w" ); if ( logfile == NULL ) { printf ( "Failed to create logfile %s\n" , argv[1] ); usage (); } init_wbuf (); status = wd_open (); if ( status != 0 ) { fprintf ( stderr , "wd_open() failed - returned %d\n" , status ); fprintf ( stderr , "continue(y/n)? " ); if ( getchar () != 'y' ) { wd_close (); exit ( 1 ); } } commands = argv[2]; if ( *commands == 'f' || *commands == 'F' ) { if ( input == NULL ) { fprintf ( stderr , "Inputfile must be specified when formatting a disk\n" ); usage (); } printf ( "Formatting disk\n" ); fprintf ( logfile , "Formatting disk\n" ); init_first_sector (); format_disk (); commands++; } else { if ( input != NULL ) fprintf ( stderr , "warning: inputfile only used when disk is reformatted\n" ); read_first_sector (); if ( first.magic != HD_MAGIC ) { fprintf ( stderr , "incorrect magic number in sector\n" ); wd_close (); exit ( 1 ); } } done_write = 0; while ( *commands != '\0' ) { switch ( *commands++ ) { case 'r' : case 'R' : printf ( "Reading disk\n" ); fprintf ( logfile , "Reading disk\n" ); read_disk ( done_write ); break; case 'w' : case 'W' : printf ( "Writing disk\n" ); fprintf ( logfile , "Pass 3: Writing disk\n" ); write_disk (); done_write = 1; break; default : usage (); } } printf ( "Done - writing bad sector table to disk\n" ); dump_first_sector (); printf ( "\n%d sectors used for map information\n" , HD_MAP_SECTORS ); printf ( "%ld sectors used so far for relinking bad sectors\n" , (long)first.bad_sectors ); printf ( "%ld tracks would be required to hold these sectors\n\n" , (long)( HD_MAP_SECTORS + first.bad_sectors - 1 ) / first.sectors + 1 ); printf ( "A total of %d sectors could be used for relinking bad sectors\n" , HD_MAP_SECTORS + HD_MAP_SIZE ); printf ( "This would require %ld reserved tracks\n" , (long) ( HD_MAP_SECTORS + HD_MAP_SIZE - 1 ) / first.sectors + 1 ); fclose ( logfile ); wd_close (); } usage () { fprintf ( stderr , "Usage: initiate logfile commands [inputfile]\n" ); fprintf ( stderr , "The commands consist of a series of command characters\n" ); fprintf ( stderr , "If the first character is a 'f' then the hard disk is formatted\n" ); fprintf ( stderr , "and the map table is rebuilt from the input file\n" ); fprintf ( stderr , "If the following characters are 'r' or 'w' the entire hard disk\n" ); fprintf ( stderr , "is read or written to and any errors added to the map table\n" ); wd_close (); exit ( 1 ); } init_first_sector () { int i; UBYTE *p; long interleave_factor; struct posn posn; char buf[ 128 ]; if ( fgets ( buf , sizeof(buf) , input ) != NULL && sscanf ( buf , "%ld" , &first.cylinders ) != 1 ) { fprintf ( stderr , "Failed to read number of cylinders\n" ); usage (); } if ( fgets ( buf , sizeof(buf) , input ) != NULL && sscanf ( buf , "%ld" , &first.park_cylinder ) != 1 ) { fprintf ( stderr , "Failed to read parking cylinder\n" ); usage (); } if ( fgets ( buf , sizeof(buf) , input ) != NULL && sscanf ( buf , "%ld" , &first.heads ) != 1 ) { fprintf ( stderr , "Failed to read number of heads (surfaces)\n" ); usage (); } if ( fgets ( buf , sizeof(buf) , input ) != NULL && sscanf ( buf , "%ld" , &first.sectors ) != 1 ) { fprintf ( stderr , "Failed to read number of sectors\n" ); usage (); } if ( fgets ( buf , sizeof(buf) , input ) != NULL && sscanf ( buf , "%ld" , &interleave_factor ) != 1 ) { fprintf ( stderr , "Failed to read interleave factor\n" ); usage (); } first.magic = HD_MAGIC; first.map_sectors = HD_MAP_SECTORS; first.bad_sectors = 0; fprintf ( logfile , "%3ld cylinders\n" , first.cylinders ); fprintf ( logfile , "%3ld park cylinder\n" , first.park_cylinder ); fprintf ( logfile , "%3ld heads\n" , first.heads ); fprintf ( logfile , "%3ld sectors\n" , first.sectors ); fprintf ( logfile , "%3ld interleave factor\n" , interleave_factor ); p = &first.pad[0]; for ( i = 0; i < sizeof ( first.pad ); i++ ) *p++ = 0x55; new_interleave ( interleave_factor ); for ( i = 0; i < HD_MAP_SIZE; i++ ) first.map[i] = MAP_MARK_FREE; while ( fgets ( buf , sizeof(buf) , input ) != NULL ) { switch ( sscanf ( buf , "%ld %ld %ld\n" , &posn.cylinder , &posn.surface , &posn.sector ) ) { case 2 : for ( posn.sector = 0; posn.sector < first.sectors; posn.sector++ ) { posn.block = posn.sector + ( posn.surface * first.sectors ) + ( posn.cylinder * first.sectors * first.heads ); bad_sector ( &posn , 0 , "input" ); } break; case 3 : posn.block = posn.sector + ( posn.surface * first.sectors ) + ( posn.cylinder * first.sectors * first.heads ); bad_sector ( &posn , 0 , "input" ); break; default : fprintf ( stderr , "Error in bad sector file\n" ); wd_close (); exit ( 1 ); } } } read_first_sector () { int i; char *p; struct posn posn; posn.cylinder = 0; posn.surface = 0; posn.sector = 0; posn.block = 0; p = (char*) &first; for ( i = 0; i < HD_MAP_SECTORS; i++ ) { if ( read_sector ( &posn , p ) != 0 ) { fprintf ( stderr , "Read error when reading map sector %d\n" , i ); wd_close (); exit ( 1 ); } posn.sector++; posn.block++; p += HD_SECTOR; } if ( first.magic != HD_MAGIC ) { fprintf ( stderr , "Incorrect magic number in bad sector map\n" ); fprintf ( stderr , "Want %08lx, Found %08lx\n" , (long)HD_MAGIC , (long)first.magic ); wd_close (); exit ( 1 ); } if ( first.map_sectors != HD_MAP_SECTORS ) { fprintf ( stderr , "error: differing number of map sectors\n" ); fprintf ( stderr , "(program is hard coded for %d sectors, disk wants %d sectors\n" , HD_MAP_SECTORS , (int)first.map_sectors ); wd_close (); exit ( 1 ); } fprintf ( logfile , "%3ld cylinders\n" , first.cylinders ); fprintf ( logfile , "%3ld park cylinder\n" , first.park_cylinder ); fprintf ( logfile , "%3ld heads\n" , first.heads ); fprintf ( logfile , "%3ld sectors\n" , first.sectors ); } init_wbuf () { int i; for ( i = 0; i < HD_SECTOR; i++ ) wbuf[i] = i; } format_disk () { struct posn posn; int status; int i; for ( posn.cylinder = 0; posn.cylinder < first.cylinders; posn.cylinder++ ) { printf ( "%03ld " , posn.cylinder ); for ( posn.surface = 0; posn.surface < first.heads; posn.surface++ ) { posn.sector = 0; posn.block = posn.sector + ( posn.surface * first.sectors ) + ( posn.cylinder * first.sectors * first.heads ); printf ( "%ld " , posn.surface ); fflush ( stdout ); wd_format_track ( &posn ); } printf ( "\n" ); } } read_disk ( check ) int check; { struct posn posn; int status; int i; for ( posn.cylinder = 0; posn.cylinder < first.cylinders; posn.cylinder++ ) { printf ( "%03ld " , posn.cylinder ); fflush ( stdout ); for ( posn.surface = 0; posn.surface < first.heads; posn.surface++ ) { /* printf ( "%03ld %ld " , posn.cylinder , posn.surface ); fflush ( stdout ); */ for ( posn.sector = 0; posn.sector < first.sectors; posn.sector++ ) { posn.block = posn.sector + ( posn.surface * first.sectors ) + ( posn.cylinder * first.sectors * first.heads ); if ( is_bad ( &posn ) ) { /* putchar ( 's' ); fflush ( stdout ); */ continue; } /* putchar ( '.' ); fflush ( stdout ); */ status = read_sector ( &posn , rbuf ); if ( status != 0 ) bad_sector ( &posn , status , "read" ); if ( check ) { if ( ! cmp_equal ( rbuf , wbuf ) ) bad_sector ( &posn , 0 , "compare" ); } } /* printf ( "\n" ); */ } } } write_disk () { struct posn posn; int status; int i; for ( posn.cylinder = 0; posn.cylinder < first.cylinders; posn.cylinder++ ) { for ( posn.surface = 0; posn.surface < first.heads; posn.surface++ ) { printf ( "%03ld %ld " , posn.cylinder , posn.surface ); fflush ( stdout ); for ( posn.sector = 0; posn.sector < first.sectors; posn.sector++ ) { posn.block = posn.sector + ( posn.surface * first.sectors ) + ( posn.cylinder * first.sectors * first.heads ); if ( is_bad ( &posn ) ) { putchar ( 's' ); fflush ( stdout ); continue; } putchar ( '.' ); fflush ( stdout ); status = write_sector ( &posn , wbuf ); if ( status != 0 ) bad_sector ( &posn , status , "write" ); } printf ( "\n" ); } } } bad_sector ( posn , status , msg ) struct posn *posn; int status; char *msg; { fprintf ( logfile , "%s: Cylinder %ld, Head %ld, Sector %ld: Status %d\n" , msg , posn->cylinder , posn->surface , posn->sector , status ); printf ( "\n%s: Cylinder %ld, Head %ld, Sector %ld: Status %d\n" , msg , posn->cylinder , posn->surface , posn->sector , status ); /* ok, now add it to the table of bad sectors */ while ( first.bad_sectors < HD_MAP_SIZE && first.map[ first.bad_sectors ] == MAP_MARK_BAD ) first.bad_sectors++; if ( first.bad_sectors < HD_MAP_SIZE ) { first.map[ first.bad_sectors++ ] = posn->block; } else { fprintf ( logfile , " Overflow: Too many bad sectors!\n" ); printf ( " Overflow: Too many bad sectors!\n" ); } /* if a bad sector, mark the bad map table so dont try and replace */ /* a bad sector with a bad sector */ if ( posn->block < HD_MAP_SECTORS ) { printf ( "FATAL ERROR! bad sector in map table\n" ); fprintf ( logfile , "FATAL ERROR! bad sector in map table\n" ); } else if ( posn->block < HD_MAP_SECTORS + HD_MAP_SIZE ) first.map[ posn->block - HD_MAP_SECTORS ] = MAP_MARK_BAD; } cmp_equal ( buf1 , buf2 ) register char *buf1 , *buf2; { register int i; for ( i = 0; i < HD_SECTOR; i++ ) if ( buf1[i] != buf2[i] ) return ( 0 ); return ( 1 ); } dump_first_sector () { struct posn posn; int i , j; LONG *pl; char *p; int count; fprintf ( logfile , "\nInitial Sector\n" ); pl = (LONG*) &first; for ( i = 0; i < sizeof(first)/sizeof(long); i++ ) { fprintf ( logfile , "%08lx " , *pl++ ); if ( ( i + 1 ) % 8 == 0 ) fprintf ( logfile , "\n" ); } fprintf ( logfile , "\n" ); posn.surface = 0; posn.cylinder = 0; posn.sector = 0; posn.block = 0; p = (char*) &first; count = HD_MAP_SECTORS; while ( count-- > 0 ) { if ( write_sector ( &posn , p ) != 0 ) fprintf ( stderr , "Failed to write map sector %d\n" , posn.sector ); posn.sector++; posn.block++; p += HD_SECTOR; } } is_bad ( posn ) struct posn *posn; { int i; for ( i = 0; i < first.bad_sectors; i++ ) { if ( posn->block == first.map[ i ] ) return ( 1 ); } return ( 0 ); } new_interleave ( interleave ) long interleave; { int i; int j; for ( i = 0; i < first.sectors; i++ ) first.interleave[i*2+1] = first.sectors; /* mark as free */ j = 0; for ( i = 0; i < first.sectors; i++ ) { while ( first.interleave[j*2+1] != first.sectors ) { j++; while ( j >= first.sectors ) j -= first.sectors; } first.interleave[j*2+1] = i; j += interleave; while ( j >= first.sectors ) j -= first.sectors; } for ( i = 0; i < first.sectors; i++ ) printf ( "%d " , first.interleave[i*2+1] ); printf ( "\n" ); }