ftape-read.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:18k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *      Copyright (C) 1993-1996 Bas Laarhoven,
  3.  *                (C) 1996-1997 Claus-Justus Heine.
  4.  This program is free software; you can redistribute it and/or modify
  5.  it under the terms of the GNU General Public License as published by
  6.  the Free Software Foundation; either version 2, or (at your option)
  7.  any later version.
  8.  This program is distributed in the hope that it will be useful,
  9.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  GNU General Public License for more details.
  12.  You should have received a copy of the GNU General Public License
  13.  along with this program; see the file COPYING.  If not, write to
  14.  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  15.  *
  16.  * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-read.c,v $
  17.  * $Revision: 1.6 $
  18.  * $Date: 1997/10/21 14:39:22 $
  19.  *
  20.  *      This file contains the reading code
  21.  *      for the QIC-117 floppy-tape driver for Linux.
  22.  *
  23.  */
  24. #include <linux/string.h>
  25. #include <linux/errno.h>
  26. #include <linux/mm.h>
  27. #include <asm/segment.h>
  28. #include <linux/ftape.h>
  29. #include <linux/qic117.h>
  30. #include "../lowlevel/ftape-tracing.h"
  31. #include "../lowlevel/ftape-read.h"
  32. #include "../lowlevel/ftape-io.h"
  33. #include "../lowlevel/ftape-ctl.h"
  34. #include "../lowlevel/ftape-rw.h"
  35. #include "../lowlevel/ftape-write.h"
  36. #include "../lowlevel/ftape-ecc.h"
  37. #include "../lowlevel/ftape-bsm.h"
  38. /*      Global vars.
  39.  */
  40. /*      Local vars.
  41.  */
  42. void ftape_zap_read_buffers(void)
  43. {
  44. int i;
  45. for (i = 0; i < ft_nr_buffers; ++i) {
  46. /*  changed to "fit" with dynamic allocation of tape_buffer. --khp  */
  47. ft_buffer[i]->status = waiting;
  48. ft_buffer[i]->bytes = 0;
  49. ft_buffer[i]->skip = 0;
  50. ft_buffer[i]->retry = 0;
  51. }
  52. /* ftape_reset_buffer(); */
  53. }
  54. static SectorMap convert_sector_map(buffer_struct * buff)
  55. {
  56. int i = 0;
  57. SectorMap bad_map = ftape_get_bad_sector_entry(buff->segment_id);
  58. SectorMap src_map = buff->soft_error_map | buff->hard_error_map;
  59. SectorMap dst_map = 0;
  60. TRACE_FUN(ft_t_any);
  61. if (bad_map || src_map) {
  62. TRACE(ft_t_flow, "bad_map = 0x%08lx", (long) bad_map);
  63. TRACE(ft_t_flow, "src_map = 0x%08lx", (long) src_map);
  64. }
  65. while (bad_map) {
  66. while ((bad_map & 1) == 0) {
  67. if (src_map & 1) {
  68. dst_map |= (1 << i);
  69. }
  70. src_map >>= 1;
  71. bad_map >>= 1;
  72. ++i;
  73. }
  74. /* (bad_map & 1) == 1 */
  75. src_map >>= 1;
  76. bad_map >>= 1;
  77. }
  78. if (src_map) {
  79. dst_map |= (src_map << i);
  80. }
  81. if (dst_map) {
  82. TRACE(ft_t_flow, "dst_map = 0x%08lx", (long) dst_map);
  83. }
  84. TRACE_EXIT dst_map;
  85. }
  86. static int correct_and_copy_fraction(buffer_struct *buff, __u8 * destination,
  87.      int start, int size)
  88. {
  89. struct memory_segment mseg;
  90. int result;
  91. SectorMap read_bad;
  92. TRACE_FUN(ft_t_any);
  93. mseg.read_bad = convert_sector_map(buff);
  94. mseg.marked_bad = 0; /* not used... */
  95. mseg.blocks = buff->bytes / FT_SECTOR_SIZE;
  96. mseg.data = buff->address;
  97. /*    If there are no data sectors we can skip this segment.
  98.  */
  99. if (mseg.blocks <= 3) {
  100. TRACE_ABORT(0, ft_t_noise, "empty segment");
  101. }
  102. read_bad = mseg.read_bad;
  103. ft_history.crc_errors += count_ones(read_bad);
  104. result = ftape_ecc_correct_data(&mseg);
  105. if (read_bad != 0 || mseg.corrected != 0) {
  106. TRACE(ft_t_noise, "crc error map: 0x%08lx", (unsigned long)read_bad);
  107. TRACE(ft_t_noise, "corrected map: 0x%08lx", (unsigned long)mseg.corrected);
  108. ft_history.corrected += count_ones(mseg.corrected);
  109. }
  110. if (result == ECC_CORRECTED || result == ECC_OK) {
  111. if (result == ECC_CORRECTED) {
  112. TRACE(ft_t_info, "ecc corrected segment: %d", buff->segment_id);
  113. }
  114. if(start < 0) {
  115. start= 0;
  116. }
  117. if((start+size) > ((mseg.blocks - 3) * FT_SECTOR_SIZE)) {
  118. size = (mseg.blocks - 3) * FT_SECTOR_SIZE  - start;
  119. if (size < 0) {
  120. size= 0;
  121. }
  122. if(size > 0) {
  123. memcpy(destination + start, mseg.data + start, size);
  124. }
  125. if ((read_bad ^ mseg.corrected) & mseg.corrected) {
  126. /* sectors corrected without crc errors set */
  127. ft_history.crc_failures++;
  128. }
  129. TRACE_EXIT size; /* (mseg.blocks - 3) * FT_SECTOR_SIZE; */
  130. } else {
  131. ft_history.ecc_failures++;
  132. TRACE_ABORT(-EAGAIN,
  133.     ft_t_err, "ecc failure on segment %d",
  134.     buff->segment_id);
  135. }
  136. TRACE_EXIT 0;
  137. }
  138. /*      Read given segment into buffer at address.
  139.  */
  140. int ftape_read_segment_fraction(const int segment_id,
  141. void  *address, 
  142. const ft_read_mode_t read_mode,
  143. const int start,
  144. const int size)
  145. {
  146. int result = 0;
  147. int retry  = 0;
  148. int bytes_read = 0;
  149. int read_done  = 0;
  150. TRACE_FUN(ft_t_flow);
  151. ft_history.used |= 1;
  152. TRACE(ft_t_data_flow, "segment_id = %d", segment_id);
  153. if (ft_driver_state != reading) {
  154. TRACE(ft_t_noise, "calling ftape_abort_operation");
  155. TRACE_CATCH(ftape_abort_operation(),);
  156. ftape_set_state(reading);
  157. }
  158. for(;;) {
  159. buffer_struct *tail;
  160. /*  Allow escape from this loop on signal !
  161.  */
  162. FT_SIGNAL_EXIT(_DONT_BLOCK);
  163. /*  Search all full buffers for the first matching the
  164.  *  wanted segment.  Clear other buffers on the fly.
  165.  */
  166. tail = ftape_get_buffer(ft_queue_tail);
  167. while (!read_done && tail->status == done) {
  168. /*  Allow escape from this loop on signal !
  169.  */
  170. FT_SIGNAL_EXIT(_DONT_BLOCK);
  171. if (tail->segment_id == segment_id) {
  172. /*  If out buffer is already full,
  173.  *  return its contents.  
  174.  */
  175. TRACE(ft_t_flow, "found segment in cache: %d",
  176.       segment_id);
  177. if (tail->deleted) {
  178. /*  Return a value that
  179.  *  read_header_segment
  180.  *  understands.  As this
  181.  *  should only occur when
  182.  *  searching for the header
  183.  *  segments it shouldn't be
  184.  *  misinterpreted elsewhere.
  185.  */
  186. TRACE_EXIT 0;
  187. }
  188. result = correct_and_copy_fraction(
  189. tail,
  190. address,
  191. start,
  192. size);
  193. TRACE(ft_t_flow, "segment contains (bytes): %d",
  194.       result);
  195. if (result < 0) {
  196. if (result != -EAGAIN) {
  197. TRACE_EXIT result;
  198. }
  199. /* keep read_done == 0, will
  200.  * trigger
  201.  * ftape_abort_operation
  202.  * because reading wrong
  203.  * segment.
  204.  */
  205. TRACE(ft_t_err, "ecc failed, retry");
  206. ++retry;
  207. } else {
  208. read_done = 1;
  209. bytes_read = result;
  210. }
  211. } else {
  212. TRACE(ft_t_flow,"zapping segment in cache: %d",
  213.       tail->segment_id);
  214. }
  215. tail->status = waiting;
  216. tail = ftape_next_buffer(ft_queue_tail);
  217. }
  218. if (!read_done && tail->status == reading) {
  219. if (tail->segment_id == segment_id) {
  220. switch(ftape_wait_segment(reading)) {
  221. case 0:
  222. break;
  223. case -EINTR:
  224. TRACE_ABORT(-EINTR, ft_t_warn,
  225.     "interrupted by "
  226.     "non-blockable signal");
  227. break;
  228. default:
  229. TRACE(ft_t_noise,
  230.       "wait_segment failed");
  231. ftape_abort_operation();
  232. ftape_set_state(reading);
  233. break;
  234. }
  235. } else {
  236. /*  We're reading the wrong segment,
  237.  *  stop runner.
  238.  */
  239. TRACE(ft_t_noise, "reading wrong segment");
  240. ftape_abort_operation();
  241. ftape_set_state(reading);
  242. }
  243. }
  244. /*    should runner stop ?
  245.  */
  246. if (ft_runner_status == aborting) {
  247. buffer_struct *head = ftape_get_buffer(ft_queue_head);
  248. switch(head->status) {
  249. case error:
  250. ft_history.defects += 
  251. count_ones(head->hard_error_map);
  252. case reading:
  253. head->status = waiting;
  254. break;
  255. default:
  256. break;
  257. }
  258. TRACE_CATCH(ftape_dumb_stop(),);
  259. } else {
  260. /*  If just passed last segment on tape: wait
  261.  *  for BOT or EOT mark. Sets ft_runner_status to
  262.  *  idle if at lEOT and successful 
  263.  */
  264. TRACE_CATCH(ftape_handle_logical_eot(),);
  265. }
  266. /*    If we got a segment: quit, or else retry up to limit.
  267.  *
  268.  *    If segment to read is empty, do not start runner for it,
  269.  *    but wait for next read call.
  270.  */
  271. if (read_done ||
  272.     ftape_get_bad_sector_entry(segment_id) == EMPTY_SEGMENT ) {
  273. /* bytes_read = 0;  should still be zero */
  274. TRACE_EXIT bytes_read;
  275. }
  276. if (retry > FT_RETRIES_ON_ECC_ERROR) {
  277. ft_history.defects++;
  278. TRACE_ABORT(-ENODATA, ft_t_err,
  279.     "too many retries on ecc failure");
  280. }
  281. /*    Now at least one buffer is empty !
  282.  *    Restart runner & tape if needed.
  283.  */
  284. TRACE(ft_t_any, "head: %d, tail: %d, ft_runner_status: %d",
  285.       ftape_buffer_id(ft_queue_head),
  286.       ftape_buffer_id(ft_queue_tail),
  287.       ft_runner_status);
  288. TRACE(ft_t_any, "buffer[].status, [head]: %d, [tail]: %d",
  289.       ftape_get_buffer(ft_queue_head)->status,
  290.       ftape_get_buffer(ft_queue_tail)->status);
  291. tail = ftape_get_buffer(ft_queue_tail);
  292. if (tail->status == waiting) {
  293. buffer_struct *head = ftape_get_buffer(ft_queue_head);
  294. ftape_setup_new_segment(head, segment_id, -1);
  295. if (read_mode == FT_RD_SINGLE) {
  296. /* disable read-ahead */
  297. head->next_segment = 0;
  298. }
  299. ftape_calc_next_cluster(head);
  300. if (ft_runner_status == idle) {
  301. result = ftape_start_tape(segment_id,
  302.   head->sector_offset);
  303. if (result < 0) {
  304. TRACE_ABORT(result, ft_t_err, "Error: "
  305.     "segment %d unreachable",
  306.     segment_id);
  307. }
  308. }
  309. head->status = reading;
  310. fdc_setup_read_write(head, FDC_READ);
  311. }
  312. }
  313. /* not reached */
  314. TRACE_EXIT -EIO;
  315. }
  316. int ftape_read_header_segment(__u8 *address)
  317. {
  318. int result;
  319. int header_segment;
  320. int first_failed = 0;
  321. int status;
  322. TRACE_FUN(ft_t_flow);
  323. ft_used_header_segment = -1;
  324. TRACE_CATCH(ftape_report_drive_status(&status),);
  325. TRACE(ft_t_flow, "reading...");
  326. /*  We're looking for the first header segment.
  327.  *  A header segment cannot contain bad sectors, therefor at the
  328.  *  tape start, segments with bad sectors are (according to QIC-40/80)
  329.  *  written with deleted data marks and must be skipped.
  330.  */
  331. memset(address, '', (FT_SECTORS_PER_SEGMENT - 3) * FT_SECTOR_SIZE); 
  332. result = 0;
  333. #define HEADER_SEGMENT_BOUNDARY 68  /* why not 42? */
  334. for (header_segment = 0;
  335.      header_segment < HEADER_SEGMENT_BOUNDARY && result == 0;
  336.      ++header_segment) {
  337. /*  Set no read-ahead, the isr will force read-ahead whenever
  338.  *  it encounters deleted data !
  339.  */
  340. result = ftape_read_segment(header_segment,
  341.     address,
  342.     FT_RD_SINGLE);
  343. if (result < 0 && !first_failed) {
  344. TRACE(ft_t_err, "header segment damaged, trying backup");
  345. first_failed = 1;
  346. result = 0; /* force read of next (backup) segment */
  347. }
  348. }
  349. if (result < 0 || header_segment >= HEADER_SEGMENT_BOUNDARY) {
  350. TRACE_ABORT(-EIO, ft_t_err,
  351.     "no readable header segment found");
  352. }
  353. TRACE_CATCH(ftape_abort_operation(),);
  354. ft_used_header_segment = header_segment;
  355. result = ftape_decode_header_segment(address);
  356.   TRACE_EXIT result;
  357. }
  358. int ftape_decode_header_segment(__u8 *address)
  359. {
  360. unsigned int max_floppy_side;
  361. unsigned int max_floppy_track;
  362. unsigned int max_floppy_sector;
  363. unsigned int new_tape_len;
  364. TRACE_FUN(ft_t_flow);
  365. if (GET4(address, FT_SIGNATURE) == FT_D2G_MAGIC) {
  366. /* Ditto 2GB header segment. They encrypt the bad sector map.
  367.  * We decrypt it and store them in normal format.
  368.  * I hope this is correct.
  369.  */
  370. int i;
  371. TRACE(ft_t_warn,
  372.       "Found Ditto 2GB tape, "
  373.       "trying to decrypt bad sector map");
  374. for (i=256; i < 29 * FT_SECTOR_SIZE; i++) {
  375. address[i] = ~(address[i] - (i&0xff));
  376. }
  377. PUT4(address, 0,FT_HSEG_MAGIC);
  378. } else if (GET4(address, FT_SIGNATURE) != FT_HSEG_MAGIC) {
  379. TRACE_ABORT(-EIO, ft_t_err,
  380.     "wrong signature in header segment");
  381. }
  382. ft_format_code = (ft_format_type) address[FT_FMT_CODE];
  383. if (ft_format_code != fmt_big) {
  384. ft_header_segment_1   = GET2(address, FT_HSEG_1);
  385. ft_header_segment_2   = GET2(address, FT_HSEG_2);
  386. ft_first_data_segment = GET2(address, FT_FRST_SEG);
  387. ft_last_data_segment  = GET2(address, FT_LAST_SEG);
  388. } else {
  389. ft_header_segment_1   = GET4(address, FT_6_HSEG_1);
  390. ft_header_segment_2   = GET4(address, FT_6_HSEG_2);
  391. ft_first_data_segment = GET4(address, FT_6_FRST_SEG);
  392. ft_last_data_segment  = GET4(address, FT_6_LAST_SEG);
  393. }
  394. TRACE(ft_t_noise, "first data segment: %d", ft_first_data_segment);
  395. TRACE(ft_t_noise, "last  data segment: %d", ft_last_data_segment);
  396. TRACE(ft_t_noise, "header segments are %d and %d",
  397.       ft_header_segment_1, ft_header_segment_2);
  398. /*    Verify tape parameters...
  399.  *    QIC-40/80 spec:                 tape_parameters:
  400.  *
  401.  *    segments-per-track              segments_per_track
  402.  *    tracks-per-cartridge            tracks_per_tape
  403.  *    max-floppy-side                 (segments_per_track *
  404.  *                                    tracks_per_tape - 1) /
  405.  *                                    ftape_segments_per_head
  406.  *    max-floppy-track                ftape_segments_per_head /
  407.  *                                    ftape_segments_per_cylinder - 1
  408.  *    max-floppy-sector               ftape_segments_per_cylinder *
  409.  *                                    FT_SECTORS_PER_SEGMENT
  410.  */
  411. ft_segments_per_track = GET2(address, FT_SPT);
  412. ft_tracks_per_tape    = address[FT_TPC];
  413. max_floppy_side       = address[FT_FHM];
  414. max_floppy_track      = address[FT_FTM];
  415. max_floppy_sector     = address[FT_FSM];
  416. TRACE(ft_t_noise, "(fmt/spt/tpc/fhm/ftm/fsm) = %d/%d/%d/%d/%d/%d",
  417.       ft_format_code, ft_segments_per_track, ft_tracks_per_tape,
  418.       max_floppy_side, max_floppy_track, max_floppy_sector);
  419. new_tape_len = ftape_tape_len;
  420. switch (ft_format_code) {
  421. case fmt_425ft:
  422. new_tape_len = 425;
  423. break;
  424. case fmt_normal:
  425. if (ftape_tape_len == 0) { /* otherwise 307 ft */
  426. new_tape_len = 205;
  427. }
  428. break;
  429. case fmt_1100ft:
  430. new_tape_len = 1100;
  431. break;
  432. case fmt_var:{
  433. int segments_per_1000_inch = 1; /* non-zero default for switch */
  434. switch (ft_qic_std) {
  435. case QIC_TAPE_QIC40:
  436. segments_per_1000_inch = 332;
  437. break;
  438. case QIC_TAPE_QIC80:
  439. segments_per_1000_inch = 488;
  440. break;
  441. case QIC_TAPE_QIC3010:
  442. segments_per_1000_inch = 730;
  443. break;
  444. case QIC_TAPE_QIC3020:
  445. segments_per_1000_inch = 1430;
  446. break;
  447. }
  448. new_tape_len = (1000 * ft_segments_per_track +
  449. (segments_per_1000_inch - 1)) / segments_per_1000_inch;
  450. break;
  451. }
  452. case fmt_big:{
  453. int segments_per_1000_inch = 1; /* non-zero default for switch */
  454. switch (ft_qic_std) {
  455. case QIC_TAPE_QIC40:
  456. segments_per_1000_inch = 332;
  457. break;
  458. case QIC_TAPE_QIC80:
  459. segments_per_1000_inch = 488;
  460. break;
  461. case QIC_TAPE_QIC3010:
  462. segments_per_1000_inch = 730;
  463. break;
  464. case QIC_TAPE_QIC3020:
  465. segments_per_1000_inch = 1430;
  466. break;
  467. default:
  468. TRACE_ABORT(-EIO, ft_t_bug,
  469. "%x QIC-standard with fmt-code %d, please report",
  470.     ft_qic_std, ft_format_code);
  471. }
  472. new_tape_len = ((1000 * ft_segments_per_track +
  473.  (segments_per_1000_inch - 1)) / 
  474. segments_per_1000_inch);
  475. break;
  476. }
  477. default:
  478. TRACE_ABORT(-EIO, ft_t_err,
  479.     "unknown tape format, please report !");
  480. }
  481. if (new_tape_len != ftape_tape_len) {
  482. ftape_tape_len = new_tape_len;
  483. TRACE(ft_t_info, "calculated tape length is %d ft",
  484.       ftape_tape_len);
  485. ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);
  486. }
  487. if (ft_segments_per_track == 0 && ft_tracks_per_tape == 0 &&
  488.     max_floppy_side == 0 && max_floppy_track == 0 &&
  489.     max_floppy_sector == 0) {
  490. /*  QIC-40 Rev E and earlier has no values in the header.
  491.  */
  492. ft_segments_per_track = 68;
  493. ft_tracks_per_tape = 20;
  494. max_floppy_side = 1;
  495. max_floppy_track = 169;
  496. max_floppy_sector = 128;
  497. }
  498. /*  This test will compensate for the wrong parameter on tapes
  499.  *  formatted by Conner software.
  500.  */
  501. if (ft_segments_per_track == 150 &&
  502.     ft_tracks_per_tape == 28 &&
  503.     max_floppy_side == 7 &&
  504.     max_floppy_track == 149 &&
  505.     max_floppy_sector == 128) {
  506. TRACE(ft_t_info, "the famous CONNER bug: max_floppy_side off by one !");
  507. max_floppy_side = 6;
  508. }
  509. /*  These tests will compensate for the wrong parameter on tapes
  510.  *  formatted by ComByte Windows software.
  511.  *
  512.  *  First, for 205 foot tapes
  513.  */
  514. if (ft_segments_per_track == 100 &&
  515.     ft_tracks_per_tape == 28 &&
  516.     max_floppy_side == 9 &&
  517.     max_floppy_track == 149 &&
  518.     max_floppy_sector == 128) {
  519. TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!");
  520. max_floppy_side = 4;
  521. }
  522. /* Next, for 307 foot tapes. */
  523. if (ft_segments_per_track == 150 &&
  524.     ft_tracks_per_tape == 28 &&
  525.     max_floppy_side == 9 &&
  526.     max_floppy_track == 149 &&
  527.     max_floppy_sector == 128) {
  528. TRACE(ft_t_info, "the ComByte bug: max_floppy_side incorrect!");
  529. max_floppy_side = 6;
  530. }
  531. /*  This test will compensate for the wrong parameter on tapes
  532.  *  formatted by Colorado Windows software.
  533.  */
  534. if (ft_segments_per_track == 150 &&
  535.     ft_tracks_per_tape == 28 &&
  536.     max_floppy_side == 6 &&
  537.     max_floppy_track == 150 &&
  538.     max_floppy_sector == 128) {
  539. TRACE(ft_t_info, "the famous Colorado bug: max_floppy_track off by one !");
  540. max_floppy_track = 149;
  541. }
  542. ftape_segments_per_head = ((max_floppy_sector/FT_SECTORS_PER_SEGMENT) *
  543.    (max_floppy_track + 1));
  544. /*  This test will compensate for some bug reported by Dima
  545.  *  Brodsky.  Seems to be a Colorado bug, either. (freebee
  546.  *  Imation tape shipped together with Colorado T3000
  547.  */
  548. if ((ft_format_code == fmt_var || ft_format_code == fmt_big) &&
  549.     ft_tracks_per_tape == 50 &&
  550.     max_floppy_side == 54 &&
  551.     max_floppy_track == 255 &&
  552.     max_floppy_sector == 128) {
  553. TRACE(ft_t_info, "the famous ??? bug: max_floppy_track off by one !");
  554. max_floppy_track = 254;
  555. }
  556. /*
  557.  *    Verify drive_configuration with tape parameters
  558.  */
  559. if (ftape_segments_per_head == 0 || ftape_segments_per_cylinder == 0 ||
  560.   ((ft_segments_per_track * ft_tracks_per_tape - 1) / ftape_segments_per_head
  561.    != max_floppy_side) ||
  562.     (ftape_segments_per_head / ftape_segments_per_cylinder - 1 != max_floppy_track) ||
  563. (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT != max_floppy_sector)
  564. #ifdef TESTING
  565.     || ((ft_format_code == fmt_var || ft_format_code == fmt_big) && 
  566. (max_floppy_track != 254 || max_floppy_sector != 128))
  567. #endif
  568.    ) {
  569. TRACE(ft_t_err,"Tape parameters inconsistency, please report");
  570. TRACE(ft_t_err, "reported = %d/%d/%d/%d/%d/%d",
  571.       ft_format_code,
  572.       ft_segments_per_track,
  573.       ft_tracks_per_tape,
  574.       max_floppy_side,
  575.       max_floppy_track,
  576.       max_floppy_sector);
  577. TRACE(ft_t_err, "required = %d/%d/%d/%d/%d/%d",
  578.       ft_format_code,
  579.       ft_segments_per_track,
  580.       ft_tracks_per_tape,
  581.       ((ft_segments_per_track * ft_tracks_per_tape -1) / 
  582.        ftape_segments_per_head ),
  583.       (ftape_segments_per_head / 
  584.        ftape_segments_per_cylinder - 1 ),
  585.       (ftape_segments_per_cylinder * FT_SECTORS_PER_SEGMENT));
  586. TRACE_EXIT -EIO;
  587. }
  588. ftape_extract_bad_sector_map(address);
  589.   TRACE_EXIT 0;
  590. }