📄 ftape-read.c
字号:
ftape_setup_new_segment(head, segment_id, -1); if (read_mode == FT_RD_SINGLE) { /* disable read-ahead */ head->next_segment = 0; } ftape_calc_next_cluster(head); if (ft_runner_status == idle) { result = ftape_start_tape(segment_id, head->sector_offset); if (result < 0) { TRACE_ABORT(result, ft_t_err, "Error: " "segment %d unreachable", segment_id); } } head->status = reading; fdc_setup_read_write(head, FDC_READ); } } /* not reached */ TRACE_EXIT -EIO;}int ftape_read_header_segment(__u8 *address){ int result; int header_segment; int first_failed = 0; int status; TRACE_FUN(ft_t_flow); ft_used_header_segment = -1; TRACE_CATCH(ftape_report_drive_status(&status),); TRACE(ft_t_flow, "reading..."); /* We're looking for the first header segment. * A header segment cannot contain bad sectors, therefor at the * tape start, segments with bad sectors are (according to QIC-40/80) * written with deleted data marks and must be skipped. */ memset(address, '\0', (FT_SECTORS_PER_SEGMENT - 3) * FT_SECTOR_SIZE); result = 0;#define HEADER_SEGMENT_BOUNDARY 68 /* why not 42? */ for (header_segment = 0; header_segment < HEADER_SEGMENT_BOUNDARY && result == 0; ++header_segment) { /* Set no read-ahead, the isr will force read-ahead whenever * it encounters deleted data ! */ result = ftape_read_segment(header_segment, address, FT_RD_SINGLE); if (result < 0 && !first_failed) { TRACE(ft_t_err, "header segment damaged, trying backup"); first_failed = 1; result = 0; /* force read of next (backup) segment */ } } if (result < 0 || header_segment >= HEADER_SEGMENT_BOUNDARY) { TRACE_ABORT(-EIO, ft_t_err, "no readable header segment found"); } TRACE_CATCH(ftape_abort_operation(),); ft_used_header_segment = header_segment; result = ftape_decode_header_segment(address); TRACE_EXIT result;}int ftape_decode_header_segment(__u8 *address){ unsigned int max_floppy_side; unsigned int max_floppy_track; unsigned int max_floppy_sector; unsigned int new_tape_len; TRACE_FUN(ft_t_flow); if (GET4(address, FT_SIGNATURE) == FT_D2G_MAGIC) { /* Ditto 2GB header segment. They encrypt the bad sector map. * We decrypt it and store them in normal format. * I hope this is correct. */ int i; TRACE(ft_t_warn, "Found Ditto 2GB tape, " "trying to decrypt bad sector map"); for (i=256; i < 29 * FT_SECTOR_SIZE; i++) { address[i] = ~(address[i] - (i&0xff)); } PUT4(address, 0,FT_HSEG_MAGIC); } else if (GET4(address, FT_SIGNATURE) != FT_HSEG_MAGIC) { TRACE_ABORT(-EIO, ft_t_err, "wrong signature in header segment"); } ft_format_code = (ft_format_type) address[FT_FMT_CODE]; if (ft_format_code != fmt_big) { ft_header_segment_1 = GET2(address, FT_HSEG_1); ft_header_segment_2 = GET2(address, FT_HSEG_2); ft_first_data_segment = GET2(address, FT_FRST_SEG); ft_last_data_segment = GET2(address, FT_LAST_SEG); } else { ft_header_segment_1 = GET4(address, FT_6_HSEG_1); ft_header_segment_2 = GET4(address, FT_6_HSEG_2); ft_first_data_segment = GET4(address, FT_6_FRST_SEG); ft_last_data_segment = GET4(address, FT_6_LAST_SEG); } TRACE(ft_t_noise, "first data segment: %d", ft_first_data_segment); TRACE(ft_t_noise, "last data segment: %d", ft_last_data_segment); TRACE(ft_t_noise, "header segments are %d and %d", ft_header_segment_1, ft_header_segment_2); /* Verify tape parameters... * QIC-40/80 spec: tape_parameters: * * segments-per-track segments_per_track * tracks-per-cartridge tracks_per_tape * max-floppy-side (segments_per_track * * tracks_per_tape - 1) / * ftape_segments_per_head * max-floppy-track ftape_segments_per_head / * ftape_segments_per_cylinder - 1 * max-floppy-sector ftape_segments_per_cylinder * * FT_SECTORS_PER_SEGMENT */ ft_segments_per_track = GET2(address, FT_SPT); ft_tracks_per_tape = address[FT_TPC]; max_floppy_side = address[FT_FHM]; max_floppy_track = address[FT_FTM]; max_floppy_sector = address[FT_FSM]; TRACE(ft_t_noise, "(fmt/spt/tpc/fhm/ftm/fsm) = %d/%d/%d/%d/%d/%d", ft_format_code, ft_segments_per_track, ft_tracks_per_tape, max_floppy_side, max_floppy_track, max_floppy_sector); new_tape_len = ftape_tape_len; switch (ft_format_code) { case fmt_425ft: new_tape_len = 425; break; case fmt_normal: if (ftape_tape_len == 0) { /* otherwise 307 ft */ new_tape_len = 205; } break; case fmt_1100ft: new_tape_len = 1100; break; case fmt_var:{ int segments_per_1000_inch = 1; /* non-zero default for switch */ switch (ft_qic_std) { case QIC_TAPE_QIC40: segments_per_1000_inch = 332; break; case QIC_TAPE_QIC80: segments_per_1000_inch = 488; break; case QIC_TAPE_QIC3010: segments_per_1000_inch = 730; break; case QIC_TAPE_QIC3020: segments_per_1000_inch = 1430; break; } new_tape_len = (1000 * ft_segments_per_track + (segments_per_1000_inch - 1)) / segments_per_1000_inch; break; } case fmt_big:{ int segments_per_1000_inch = 1; /* non-zero default for switch */ switch (ft_qic_std) { case QIC_TAPE_QIC40: segments_per_1000_inch = 332; break; case QIC_TAPE_QIC80: segments_per_1000_inch = 488; break; case QIC_TAPE_QIC3010: segments_per_1000_inch = 730; break; case QIC_TAPE_QIC3020: segments_per_1000_inch = 1430; break; default: TRACE_ABORT(-EIO, ft_t_bug, "%x QIC-standard with fmt-code %d, please report", ft_qic_std, ft_format_code); } new_tape_len = ((1000 * ft_segments_per_track + (segments_per_1000_inch - 1)) / segments_per_1000_inch); break; } default: TRACE_ABORT(-EIO, ft_t_err, "unknown tape format, please report !"); } if (new_tape_len != ftape_tape_len) { ftape_tape_len = new_tape_len; TRACE(ft_t_info, "calculated tape length is %d ft", ftape_tape_len); ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len); } if (ft_segments_per_track == 0 && ft_tracks_per_tape == 0 && max_floppy_side == 0 && max_floppy_track == 0 && max_floppy_sector == 0) { /* QIC-40 Rev E and earlier has no values in the header. */ ft_segments_per_track = 68; ft_tracks_per_tape = 20; max_floppy_side = 1; max_floppy_track = 169; max_floppy_sector = 128; } /* This test will compensate for the wrong parameter on tapes * formatted by Conner software. */ if (ft_segments_per_track == 150 && ft_tracks_per_tape == 28 && max_floppy_side == 7 && max_floppy_track == 149 && max_floppy_sector == 128) {TRACE(ft_t_info, "the famous CONNER bug: max_floppy_side off by one !"); max_floppy_side = 6; } /* These tests will compensate for the wrong parameter on tapes * formatted by ComByte Windows software. * * First, for 205 foot tapes */ if (ft_segments_per_track == 100 && ft_tracks_per_tape == 28 && max_floppy_side == 9 && max_floppy_track == 149 && max_floppy_sector == 128) {TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!"); max_floppy_side = 4; } /* Next, for 307 foot tapes. */ if (ft_segments_per_track == 150 && ft_tracks_per_tape == 28 && max_floppy_side == 9 && max_floppy_track == 149 && max_floppy_sector == 128) {TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!"); max_floppy_side = 6; } /* This test will compensate for the wrong parameter on tapes * formatted by Colorado Windows software. */ if (ft_segments_per_track == 150 && ft_tracks_per_tape == 28 && max_floppy_side == 6 && max_floppy_track == 150 && max_floppy_sector == 128) {TRACE(ft_t_info, "the famous Colorado bug: max_floppy_track off by one !"); max_floppy_track = 149; } ftape_segments_per_head = ((max_floppy_sector/FT_SECTORS_PER_SEGMENT) * (max_floppy_track + 1)); /* This test will compensate for some bug reported by Dima * Brodsky. Seems to be a Colorado bug, either. (freebee * Imation tape shipped together with Colorado T3000 */ if ((ft_format_code == fmt_var || ft_format_code == fmt_big) && ft_tracks_per_tape == 50 && max_floppy_side == 54 && max_floppy_track == 255 && max_floppy_sector == 128) {TRACE(ft_t_info, "the famous ??? bug: max_floppy_track off by one !"); max_floppy_track = 254; } /* * Verify drive_configuration with tape parameters */ if (ftape_segments_per_head == 0 || ftape_segments_per_cylinder == 0 || ((ft_segments_per_track * ft_tracks_per_tape - 1) / ftape_segments_per_head != max_floppy_side) || (ftape_segments_per_head / ftape_segments_per_cylinder - 1 != max_floppy_track) || (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT != max_floppy_sector)#ifdef TESTING || ((ft_format_code == fmt_var || ft_format_code == fmt_big) && (max_floppy_track != 254 || max_floppy_sector != 128))#endif ) { char segperheadz = ftape_segments_per_head ? ' ' : '?'; char segpercylz = ftape_segments_per_cylinder ? ' ' : '?'; TRACE(ft_t_err,"Tape parameters inconsistency, please report"); TRACE(ft_t_err, "reported = %d/%d/%d/%d/%d/%d", ft_format_code, ft_segments_per_track, ft_tracks_per_tape, max_floppy_side, max_floppy_track, max_floppy_sector); TRACE(ft_t_err, "required = %d/%d/%d/%d%c/%d%c/%d", ft_format_code, ft_segments_per_track, ft_tracks_per_tape, ftape_segments_per_head ? ((ft_segments_per_track * ft_tracks_per_tape -1) / ftape_segments_per_head ) : (ft_segments_per_track * ft_tracks_per_tape -1), segperheadz, ftape_segments_per_cylinder ? (ftape_segments_per_head / ftape_segments_per_cylinder - 1 ) : ftape_segments_per_head - 1, segpercylz, (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT)); TRACE_EXIT -EIO; } ftape_extract_bad_sector_map(address); TRACE_EXIT 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -