#include "structs.h" #include "defs.h" #include #include #include #include /* Global variables */ extern struct type_htable hd_table; extern struct type_task_file task_file; extern struct type_esfile ; extern union type_scan scan_code; extern struct type_error err_table[300]; extern struct type_error defect_table[300]; extern char far *wr_buffer[2]; extern char far *fmt_buffer[16]; extern int command,err_count, defect_count, errcnt,bad_count,redirection,quit; extern int bad_sector_map[100]; extern unsigned char alt_value; /*************************************/ /* */ /* init_disk() */ /* */ /* initialize hard disk */ /* */ /*************************************/ init_disk() { /* start of init_disk */ int temp_sdh,i,ii; char temp; if(hd_table.max_head > 7) temp = 0x0a; else temp = 0x02; outp(temp & 4,0x0e); /* reset hard drive */ i= 0; // delay 5.0 usec min ii = 1; while(ii<30) { i++; ii=i; ii*=3; } i=27; outp(temp,0x0a); // turn off reset while(at_ckbsy()); /* check busy bit in controler */ temp_sdh = (hd_table.max_head & 0xf) + /* bits 0-3 */ ((hd_table.drv_number <<4) & 0x10) + /* bit 4 */ ((hd_table.sec_size << 5) & 0x60) + /* bits 5,6 */ ((hd_table.ecc << 7) & 0x80); /* bit 7 */ at_setp(temp_sdh,hd_table.max_sec); /* set parameters */ while(at_ckbsy()); /* check busy bit in controler */ while(at_ckbsy()); /* wait untill drive is ready */ load_task_file(); /* load task file */ at_rest(0); /* recal drive */ while(at_ckbsy()); /* check busy bit in controler */ while(at_ckbsy()); /* check busy bit in controler */ load_task_file(); /* load task file */ at_rest(0); /* restore drive */ while(at_ckbsy()); /* check busy bit in controler */ while(at_ckbsy()); /* check busy bit in controler */ if (at_rstat() & 0x05) /* check if error for recal */ show_error(); /* show any errors */ } /* end of init_disk */ /*************************************/ /* */ /* should_do_errors() */ /* */ /* find out from user if bad tracks */ /* should be marked bad then mark */ /* bad if was "Y" typed. */ /* */ /*************************************/ should_do_errors() { /* start of error junk */ int done; unsigned char resp; char temp_str[8]; do_errors(); /* show errors found in err_table */ if(err_count <= 0) return; printf("\n\nDo you wish to mark these blocks bad? (y/n)"); done = FALSE; while(!done) { resp = get_input(redirection); /* get user responce */ resp = toupper(resp); switch(resp) { /* start of switch */ case 'Y' : done = TRUE; era_eol(); printf("\nPlease wait..."); mark_bad_sectors(); /* mark bad sectors*/ err_count = 0; break; case 'N' : err_count = 0; done = TRUE; break; default : BELL; } /* end of switch */ } /* end while */ err_count = 0; } /* end of sould_do_errors */ /*************************************/ /* */ /* mark bad sectors */ /* */ /*************************************/ mark_bad_sectors() { /* start of fmt_bad_track */ int error_val, errcnt, tempc, swap; unsigned char temps, temph, tempb; int count = 0; temps = hd_table.sec_number; temph = hd_table.head_number; tempc = hd_table.cyl_number; tempb = hd_table.blk_size; hd_table.blk_size = 1; for (errcnt = 0; errcnt < err_count; errcnt++) { /* fmt bad each sector in table */ hd_table.cyl_number = err_table[errcnt].cyl; hd_table.head_number = err_table[errcnt].head; if((hd_table.cyl_number != 0) || (hd_table.head_number != 0)) /* do not mark c:0 h:0 */ { if(err_table[errcnt].sector == 0xff) /* test if no offset */ fmt_bad_track(); /* no offset */ else fmt_bad_sector(err_table[errcnt].sector); /* format bad sectorson track */ } } hd_table.sec_number = temps; hd_table.head_number = temph; hd_table.cyl_number = tempc; hd_table.blk_size = tempb; } /* end of fmt_bad_sector */ /************************************************ ** ** fmt_bad_sector(sector) ** ** inputs : ** sector : sector to mark bad ** ** output : error code ** ** this routine will find all sectors marked bad then format ** those sectors bad along with sector as bad ** *************************************************/ fmt_bad_sector(sector) unsigned char sector; { /* start of fmt_bad_sector() */ unsigned char temp_count,temp_sector; int error_val; temp_count = hd_table.blk_size; temp_sector = hd_table.sec_number; hd_table.blk_size = 1; for(hd_table.sec_number = 1;hd_table.sec_number < hd_table.max_sec;hd_table.sec_number++) bad_sector_map[hd_table.sec_number] = test_bad_sector(); if(hd_table.alt_sector) { hd_table.sec_number = (int)alt_value; if(test_bad_sector()) { /* if alt sector bad then mark track */ fmt_bad_track(); return; } } else { hd_table.sec_number = hd_table.max_sec; bad_sector_map[hd_table.max_sec] = test_bad_sector();/* check if maked bad */ } bad_sector_map[sector] = TRUE; do_ilt(0,hd_table.head_number); /* make interleave table */ set_bad_sectors(); hd_table.blk_size = hd_table.max_sec; /* set block size */ hd_table.sec_number = 1; load_task_file(); at_fmt(); /* send format command */ while(! (0x08 & at_rstat())); /* wait for data request */ at_wrbfr(0,fmt_buffer[hd_table.head_number]); while(at_ckbsy()); /* check busy bit in controler */ while(at_ckbsy()); /* check busy bit in controler */ if ((at_rstat() & 0x05)) fmt_bad_track(); /* format all track bad */ hd_table.blk_size = temp_count; hd_table.sec_number = temp_sector; return; } /* end of fmt_bad_sector() */ /*********************************************** ** ** fmt_bad_track() ** ** inputs : none ** ** output : error value ** ** this routine will mark all of the track bad *************************************************/ fmt_bad_track() { unsigned char temp_count,temp_sector; int i; temp_count = hd_table.blk_size; temp_sector = hd_table.sec_number; do_ilt(0x80,0); hd_table.blk_size = hd_table.max_sec; /* set block size */ hd_table.sec_number = 1; load_task_file(); at_fmt(); /* send format command */ while(! (0x08 & at_rstat())); /* wait for data request */ at_wrbfr(0,fmt_buffer[0]); while(at_ckbsy()); /* check busy bit in controler */ while(at_ckbsy()); /* check busy bit in controler */ hd_table.blk_size = temp_count; hd_table.sec_number = temp_sector; } /************************************************ ** ** set_bad_sectors() ** ** inputs : none ** ** output : none ** ** this routine will update interleave table for bad sectors ** *************************************************/ set_bad_sectors() { /* start of set_bad_sectors() */ int offset, temp_offset; unsigned char last_offset, last_sector, sector; if(hd_table.alt_sector) last_sector = hd_table.max_sec -1; else last_sector = hd_table.max_sec; last_offset = last_sector * 2; for(sector = 1; sector <= last_sector; sector++) { /* start of check each sector */ if(bad_sector_map[sector]) { /* if sector to be marked bad */ for(offset = 0; offset < last_offset; offset += 2) if(*(fmt_buffer[hd_table.head_number] + offset + 1) == sector) { /* mark this sector bad */ *(fmt_buffer[hd_table.head_number] + offset) = 0x80; break; } } } /* end of check each sector */ if(hd_table.alt_sector) { /* swap alt_value with bad value */ for(temp_offset = last_offset-2; temp_offset >= offset; temp_offset -= 2) /* shift sector number */ *(fmt_buffer[hd_table.head_number]+temp_offset+3) = *(fmt_buffer[hd_table.head_number]+temp_offset+1); *(fmt_buffer[hd_table.head_number] + offset + 1) = alt_value; /*put alt_value on bad sector */ } /* end of if alt sector */ } /* end of set_bad_sector() */ /************************************** ** ** test_bad_sector() ** inputs : none ** output : ** TRUE : sector is bad ** FALSE: sector is ok ** ** this routine will test a single sector ***************************************/ test_bad_sector() { load_task_file(); at_rdver(1); /* do that verify with out retry */ while(at_ckbsy()); /* check busy bit in controler */ while(at_ckbsy()); /* check busy bit in controler */ if(at_rstat() & 0x05) return (TRUE); /* if error */ return(FALSE); } /*************************************/ #define BOTTOM 20 #define TOP 10 #define COL_C 20 #define COL_H 40 #define COL_O 60 #define WINDOW 1,TOP,BOTTOM,1,79,7 /*************************************/ /* */ /* enter_bad_map() */ /* */ /* user can enter bad track map from */ /* keyboard. */ /* */ /*************************************/ enter_bad_map() { /* start of enter_bad_map() */ int done,in_valid; int temp, i, j, max_i, row, col, in_key; unsigned char in_char; cls(); curs(1,1); printf("\n\nYou may now enter additional areas to be marked bad."); printf("\nEnter cylinder number head number and offset "); printf("\n Use \x18 \x19 -> <- PgUP PgDn to move curser "); printf("\n Use ESC to exit without marking, M to mark bad spots on drive"); curs(8,10);printf("Enter "); for(i=0; i<=hd_table.max_head; i++) do_ilt(0,i); /* set up interleave for good blocks */ for(i = 0; i < 300; i++) { /*clear table */ err_table[i].cyl = 0; err_table[i].head = 0; err_table[i].sector = 0xff; err_table[i].offset = 0; } i = 0; max_i = 0; row = TOP;col = COL_C; curs(row,col); done = FALSE; while(!done) { /* start of while */ in_char = kbgetkey(&in_key); switch(in_key) { /* start of switch */ case KB_S_N_DOWN: /* down arrow */ if(i > max_i) break; /* if last entry */ i++; if(row == BOTTOM) { /* print new line */ upscroll(WINDOW); if(i < max_i) { curs(row,COL_C);printf("%4d",err_table[i].cyl ); curs(row,COL_H);printf("%4d",err_table[i].head ); curs(row,COL_O);printf("%6d",err_table[i].offset); } } else row++; curs(row,col+3); break; case KB_S_N_UP : /* up arrow */ if(i == 0) break; i--; if(row == TOP) { downscroll(WINDOW); curs(row,COL_C);printf("%4d",err_table[i].cyl ); curs(row,COL_H);printf("%4d",err_table[i].head ); curs(row,COL_O);printf("%6d",err_table[i].offset); } else row--; curs(row,col+3); break; case KB_S_N_PGDN: /* page down */ j = BOTTOM - row; /* is there a page full page after this */ if((i+j) > max_i) { /* if last page */ row += max_i - i; i = max_i; curs(row,col); break; } i += BOTTOM - row; row = BOTTOM; for(j = 0; (j < (BOTTOM - TOP+1)) && (i < (max_i-1)); j++) { ++i; upscroll(WINDOW); curs(row,COL_C);printf("%4d",err_table[i].cyl ); curs(row,COL_H);printf("%4d",err_table[i].head ); curs(row,COL_O);printf("%6d",err_table[i].offset); } curs(row,col+3); break; case KB_S_N_PGUP: /* page up */ if(i == 0) break; i -= row - TOP; row = TOP; for(j = 0; (j < (BOTTOM - TOP)) && (i > 0); j++) { --i; downscroll(WINDOW); curs(row,COL_C);printf("%4d",err_table[i].cyl ); curs(row,COL_H);printf("%4d",err_table[i].head ); curs(row,COL_O);printf("%6d",err_table[i].offset); } curs(row,col+3); break; case KB_S_N_RIGHT : /* right arrow */ switch(col) { /* switch on col */ case COL_C: col = COL_H; /* if at cyl */ break; case COL_H: col = COL_O; /* if at head */ break; case COL_O: col = COL_C; /* if at offset */ break; } curs(row,col+3); break; case KB_S_N_LEFT: /* left arrow */ switch(col) { /* switch on col */ case COL_C: col = COL_O; /* if at cyl */ break; case COL_H: col = COL_C; /* if at head */ break; case COL_O: col = COL_H; /* if at offset */ break; } curs(row,col+3); break; case KB_S_N_ESC: case KB_S_N_Q: /* duit or escape */ done = TRUE; break; case KB_S_N_M: /* case mark bad sectors */ curs(24,30);printf("Please wait"); err_count = max_i; mark_bad_sectors(); /* mark sectors as bad */ curs(24,30);printf(" "); done = TRUE; break; default: /* probly a number */ kbplace(1,in_char,in_key); /* put char back into buffer */ switch(col) { /* switch on col */ case COL_C: /* if at cyl */ in_valid = TRUE; while(in_valid) /* get cyl number */ { temp = get_dec(row,COL_C-1,4,err_table[i].cyl); /* get cyl number */ if((0 <= temp) AND (temp <= hd_table.max_cyl)) in_valid = FALSE; if(in_valid) BELL; } err_table[i].cyl = temp; col = COL_H; curs(row,col+3); break; case COL_H: /* if at head */ in_valid = TRUE; while(in_valid) { /* start of if valid */ temp = get_dec(row,COL_H+1,2,err_table[i].head); /* get head number */ if((0 <= temp) AND (temp <= hd_table.max_head)) in_valid = FALSE; if(in_valid) BELL; } /* end while valid */ err_table[i].head = (unsigned char)(temp & 0xff); col = COL_O; curs(row,col+4); break; case COL_O: /* if at offset */ in_valid = TRUE; while(in_valid) { /* start of if valid */ temp = get_dec(row,COL_O-1,6,err_table[i].offset); /* byte offset */ if(0 <= temp) in_valid = FALSE; if(in_valid) BELL; } /* end while valid */ err_table[i].offset = temp; err_table[i].sector = *(fmt_buffer[err_table[i].head]+((temp/577)*2)+1); /* get sector number */ if(temp == 0) err_table[i].sector = 0xff; /* if no offset */ col = COL_C; /* adjust screen */ i++; /* next entry */ if(row == BOTTOM) { upscroll(WINDOW); if(i < max_i) { curs(row,COL_C);printf("%4d",err_table[i].cyl ); curs(row,COL_H);printf("%4d",err_table[i].head ); curs(row,COL_O);printf("%6d",err_table[i].offset); } } else row++; if(max_i < i) max_i = i; if(i>=298) { curs(23,5);printf("You must Mark errors as bad before going on."); } if(max_i < i) max_i = i; curs(row,col+3); break; } /* end switch on col */ break; } /* end switch on in_char */ } /* end while */ } /* end enter bad_map() */ /*************************************/ /* */ /* display errors found in error table*/ /* */ /*************************************/ do_errors() { cls(); curs(1,1); if(err_count <= 0) return; printf("Errors will be marked at the following cylinder/head/sector locations:"); printf("\n"); for (errcnt = 0; errcnt < err_count; errcnt++) { if ((errcnt % 5) == 0) printf ("\n"); printf(" %4d/%2d/%2d", err_table[errcnt].cyl, err_table[errcnt].head,err_table[errcnt].sector); } } /* *************************************** ** ** show_defect_list ** ** inputs : none ** ** output : none ** ** display previously marked bad sectors ******************************************/ show_defect_list() { cls(); if(defect_count <= 0) return; curs(1,1); printf("Sectors that were found marked bad cylinder/head/sector:"); printf("\n\n"); for (errcnt = 0; errcnt < defect_count; errcnt++) { if ((errcnt % 5) == 0) printf ("\n"); printf(" %4d/%2d/%2d", defect_table[errcnt].cyl, defect_table[errcnt].head,defect_table[errcnt].sector); } printf("\n\nPress any key to continue"); getch(); } /*************************************/ /* */ /* make block mark and sector # */ /* for one track */ /* */ /*************************************/ do_ilt(block_mark,head) char block_mark; int head; { int count, ileave, maxcnt; unsigned char temp; char far *p; long offset; p = fmt_buffer[head]; for( count=0; count < 512; count++ ) *p++ = 0xff; /* fill buffer with 0xFF */ ileave = hd_table.ileave; /* set up vars for loop */ count = 0; if(hd_table.alt_sector) maxcnt = hd_table.max_sec-1; else maxcnt = hd_table.max_sec; offset = (long)((hd_table.skew*head)%maxcnt); /* clear offset */ while ( count < maxcnt ) { for( ;(unsigned char)*(fmt_buffer[head]+(offset*2)) != 0xFF; offset++); /* inc offset if overlap*/ p = fmt_buffer[head] + ( offset * 2 ); *p++ = block_mark; /* block mark */ *p = 1+(count % maxcnt); /* sector number */ offset +=(long)ileave; /* inc offset by interleave */ offset = offset%(long)maxcnt; /* loop offset */ count++; } /* end of while */ if(hd_table.alt_sector) /* if need alt sector */ { p = fmt_buffer[head] + (maxcnt * 2); *p++ = block_mark; /* block mark */ *p = 0; /* sector number*/ } } /*************************************/ /* */ /* set up task file and load it */ /* */ /*************************************/ load_task_file() { task_file.error = hd_table.precomp; task_file.secnt = hd_table.blk_size; task_file.sector = hd_table.sec_number; task_file.cyllo = (hd_table.cyl_number % 256); task_file.cylhi = (hd_table.cyl_number / 256); task_file.SDH = (hd_table.head_number & 0xf) + /* bits 0-3 */ ((hd_table.drv_number <<4) & 0x10) + /* bit 4 */ ((hd_table.sec_size << 5) & 0x60) + /* bits 5,6 */ (hd_table.ecc << 7); /* bit 7 */ at_wtskf(&task_file); } /*************************************/ /* */ /* display errors from reisters */ /* */ /*************************************/ show_error() { curs(22,1); printf(" Error!!... Cyl. %4d Head %2d Status %2x Error %2x", hd_table.cyl_number, hd_table.head_number, at_rstat(), at_rderr()); } /*************************************/ /* */ /* dimp 5 lines of buffer to screen */ /* */ /*************************************/ dump_5lines(buffer) char *buffer; { int num_bytes, count; for (count = 0; count < 80; count++) { if ((count % 16) == 0) printf("\n%04x ", count); printf("%02x ", buffer[count]); }; printf("\n"); }