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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *      Copyright (C) 1996, 1997 Claus-Justus Heine
  3.  This program is free software; you can redistribute it and/or modify
  4.  it under the terms of the GNU General Public License as published by
  5.  the Free Software Foundation; either version 2, or (at your option)
  6.  any later version.
  7.  This program is distributed in the hope that it will be useful,
  8.  but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.  GNU General Public License for more details.
  11.  You should have received a copy of the GNU General Public License
  12.  along with this program; see the file COPYING.  If not, write to
  13.  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  14.  *
  15.  * $Source: /homes/cvs/ftape-stacked/ftape/zftape/zftape-rw.c,v $
  16.  * $Revision: 1.2 $
  17.  * $Date: 1997/10/05 19:19:08 $
  18.  *
  19.  *      This file contains some common code for the r/w code for
  20.  *      zftape.
  21.  */
  22. #include <linux/config.h> /* for CONFIG_ZFT_DFLT_BLK_SZ */
  23. #include <linux/errno.h>
  24. #include <linux/mm.h>
  25. #include <asm/segment.h>
  26. #include <linux/zftape.h>
  27. #include "../zftape/zftape-init.h"
  28. #include "../zftape/zftape-eof.h"
  29. #include "../zftape/zftape-ctl.h"
  30. #include "../zftape/zftape-write.h"
  31. #include "../zftape/zftape-read.h"
  32. #include "../zftape/zftape-rw.h"
  33. #include "../zftape/zftape-vtbl.h"
  34. /*      Global vars.
  35.  */
  36. __u8 *zft_deblock_buf;
  37. __u8 *zft_hseg_buf;
  38. int zft_deblock_segment = -1;
  39. zft_status_enum zft_io_state = zft_idle;
  40. int zft_header_changed;
  41. int zft_bad_sector_map_changed;
  42. int zft_qic113; /* conform to old specs. and old zftape */
  43. int zft_use_compression;
  44. zft_position zft_pos = {
  45. -1, /* seg_pos */
  46. 0,  /* seg_byte_pos */
  47. 0,  /* tape_pos */
  48. 0   /* volume_pos */
  49. };
  50. unsigned int zft_blk_sz = CONFIG_ZFT_DFLT_BLK_SZ;
  51. __s64 zft_capacity;
  52. unsigned int zft_written_segments;
  53. int zft_label_changed;
  54. /*      Local vars.
  55.  */
  56. unsigned int zft_get_seg_sz(unsigned int segment)
  57. {
  58. int size;
  59. TRACE_FUN(ft_t_any);
  60. size = FT_SEGMENT_SIZE - 
  61. count_ones(ftape_get_bad_sector_entry(segment))*FT_SECTOR_SIZE;
  62. if (size > 0) {
  63. TRACE_EXIT (unsigned)size; 
  64. } else {
  65. TRACE_EXIT 0;
  66. }
  67. }
  68. /* ftape_set_flags(). Claus-Justus Heine, 1994/1995
  69.  */
  70. void zft_set_flags(unsigned minor_unit)
  71. {     
  72. TRACE_FUN(ft_t_flow);
  73. zft_use_compression = zft_qic_mode = 0;
  74. switch (minor_unit & ZFT_MINOR_OP_MASK) {
  75. case (ZFT_Q80_MODE | ZFT_ZIP_MODE):
  76. case ZFT_ZIP_MODE:
  77. zft_use_compression = 1;
  78. case 0:
  79. case ZFT_Q80_MODE:
  80. zft_qic_mode = 1;
  81. if (zft_mt_compression) { /* override the default */
  82. zft_use_compression = 1;
  83. }
  84. break;
  85. case ZFT_RAW_MODE:
  86. TRACE(ft_t_noise, "switching to raw mode");
  87. break;
  88. default:
  89. TRACE(ft_t_warn, "Warning:n"
  90.       KERN_INFO "Wrong combination of minor device bits.n"
  91.       KERN_INFO "Switching to raw read-only mode.");
  92. zft_write_protected = 1;
  93. break;
  94. }
  95. TRACE_EXIT;
  96. }
  97. /* computes the segment and byte offset inside the segment
  98.  * corresponding to tape_pos.
  99.  *
  100.  * tape_pos gives the offset in bytes from the beginning of the
  101.  * ft_first_data_segment *seg_byte_pos is the offset in the current
  102.  * segment in bytes
  103.  *
  104.  * Of, if this routine was called often one should cache the last data
  105.  * pos it was called with, but actually this is only needed in
  106.  * ftape_seek_block(), that is, almost never.
  107.  */
  108. int zft_calc_seg_byte_coord(int *seg_byte_pos, __s64 tape_pos)
  109. {
  110. int segment;
  111. int seg_sz;
  112. TRACE_FUN(ft_t_flow);
  113. if (tape_pos == 0) {
  114. *seg_byte_pos = 0;
  115. segment = ft_first_data_segment;
  116. } else {
  117. seg_sz = 0;
  118. for (segment = ft_first_data_segment; 
  119.      ((tape_pos > 0) && (segment <= ft_last_data_segment));
  120.      segment++) {
  121. seg_sz = zft_get_seg_sz(segment); 
  122. tape_pos -= seg_sz;
  123. }
  124. if(tape_pos >= 0) {
  125. /* the case tape_pos > != 0 means that the
  126.  * argument tape_pos lies beyond the EOT.
  127.  */
  128. *seg_byte_pos= 0;
  129. } else { /* tape_pos < 0 */
  130. segment--;
  131. *seg_byte_pos= tape_pos + seg_sz;
  132. }
  133. }
  134. TRACE_EXIT(segment);
  135. }
  136. /* ftape_calc_tape_pos().
  137.  *
  138.  * computes the offset in bytes from the beginning of the
  139.  * ft_first_data_segment inverse to ftape_calc_seg_byte_coord
  140.  *
  141.  * We should do some caching. But how:
  142.  *
  143.  * Each time the header segments are read in, this routine is called
  144.  * with ft_tracks_per_tape*segments_per_track argumnet. So this should be
  145.  * the time to reset the cache.
  146.  *
  147.  * Also, it might be in the future that the bad sector map gets
  148.  * changed.  -> reset the cache
  149.  */
  150. static int seg_pos;
  151. static __s64 tape_pos;
  152. __s64 zft_get_capacity(void)
  153. {
  154. seg_pos  = ft_first_data_segment;
  155. tape_pos = 0;
  156. while (seg_pos <= ft_last_data_segment) {
  157. tape_pos += zft_get_seg_sz(seg_pos ++);
  158. }
  159. return tape_pos;
  160. }
  161. __s64 zft_calc_tape_pos(int segment)
  162. {
  163. int d1, d2, d3;
  164. TRACE_FUN(ft_t_any);
  165. if (segment > ft_last_data_segment) {
  166.         TRACE_EXIT zft_capacity;
  167. }
  168. if (segment < ft_first_data_segment) {
  169. TRACE_EXIT 0;
  170. }
  171. d2 = segment - seg_pos;
  172. if (-d2 > 10) {
  173. d1 = segment - ft_first_data_segment;
  174. if (-d2 > d1) {
  175. tape_pos = 0;
  176. seg_pos = ft_first_data_segment;
  177. d2 = d1;
  178. }
  179. }
  180. if (d2 > 10) {
  181. d3 = ft_last_data_segment - segment;
  182. if (d2 > d3) {
  183. tape_pos = zft_capacity;
  184. seg_pos  = ft_last_data_segment + 1;
  185. d2 = -d3;
  186. }
  187. }
  188. if (d2 > 0) {
  189. while (seg_pos < segment) {
  190. tape_pos +=  zft_get_seg_sz(seg_pos++);
  191. }
  192. } else {
  193. while (seg_pos > segment) {
  194. tape_pos -=  zft_get_seg_sz(--seg_pos);
  195. }
  196. }
  197. TRACE(ft_t_noise, "new cached pos: %d", seg_pos);
  198. TRACE_EXIT tape_pos;
  199. }
  200. /* copy Z-label string to buffer, keeps track of the correct offset in
  201.  * `buffer' 
  202.  */
  203. void zft_update_label(__u8 *buffer)
  204. TRACE_FUN(ft_t_flow);
  205. if (strncmp(&buffer[FT_LABEL], ZFTAPE_LABEL, 
  206.     sizeof(ZFTAPE_LABEL)-1) != 0) {
  207. TRACE(ft_t_info, "updating label from "%s" to "%s"",
  208.       &buffer[FT_LABEL], ZFTAPE_LABEL);
  209. strcpy(&buffer[FT_LABEL], ZFTAPE_LABEL);
  210. memset(&buffer[FT_LABEL] + sizeof(ZFTAPE_LABEL) - 1, ' ', 
  211.        FT_LABEL_SZ - sizeof(ZFTAPE_LABEL + 1));
  212. PUT4(buffer, FT_LABEL_DATE, 0);
  213. zft_label_changed = zft_header_changed = 1; /* changed */
  214. }
  215. TRACE_EXIT;
  216. }
  217. int zft_verify_write_segments(unsigned int segment, 
  218.       __u8 *data, size_t size,
  219.       __u8 *buffer)
  220. {
  221. int result;
  222. __u8 *write_buf;
  223. __u8 *src_buf;
  224. int single;
  225. int seg_pos;
  226. int seg_sz;
  227. int remaining;
  228. ft_write_mode_t write_mode;
  229. TRACE_FUN(ft_t_flow);
  230. seg_pos   = segment;
  231. seg_sz    = zft_get_seg_sz(seg_pos);
  232. src_buf   = data;
  233. single    = size <= seg_sz;
  234. remaining = size;
  235. do {
  236. TRACE(ft_t_noise, "n"
  237.       KERN_INFO "remaining: %dn"
  238.       KERN_INFO "seg_sz   : %dn"
  239.       KERN_INFO "segment  : %d",
  240.       remaining, seg_sz, seg_pos);
  241. if (remaining == seg_sz) {
  242. write_buf = src_buf;
  243. write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
  244. remaining = 0;
  245. } else if (remaining > seg_sz) {
  246. write_buf = src_buf;
  247. write_mode = FT_WR_ASYNC; /* don't start tape */
  248. remaining -= seg_sz;
  249. } else { /* remaining < seg_sz */
  250. write_buf = buffer;
  251. memcpy(write_buf, src_buf, remaining);
  252. memset(&write_buf[remaining],'',seg_sz-remaining);
  253. write_mode = single ? FT_WR_SINGLE : FT_WR_MULTI;
  254. remaining = 0;
  255. }
  256. if ((result = ftape_write_segment(seg_pos, 
  257.   write_buf, 
  258.   write_mode)) != seg_sz) {
  259. TRACE(ft_t_err, "Error: "
  260.       "Couldn't write segment %d", seg_pos);
  261. TRACE_EXIT result < 0 ? result : -EIO; /* bail out */
  262. }
  263. zft_written_segments ++;
  264. seg_sz = zft_get_seg_sz(++seg_pos);
  265. src_buf += result;
  266. } while (remaining > 0);
  267. if (ftape_get_status()->fti_state == writing) {
  268. TRACE_CATCH(ftape_loop_until_writes_done(),);
  269. TRACE_CATCH(ftape_abort_operation(),);
  270. zft_prevent_flush();
  271. }
  272. seg_pos = segment;
  273. src_buf = data;
  274. remaining = size;
  275. do {
  276. TRACE_CATCH(result = ftape_read_segment(seg_pos, buffer, 
  277. single ? FT_RD_SINGLE
  278. : FT_RD_AHEAD),);
  279. if (memcmp(src_buf, buffer, 
  280.    remaining > result ? result : remaining) != 0) {
  281. TRACE_ABORT(-EIO, ft_t_err,
  282.     "Failed to verify written segment %d",
  283.     seg_pos);
  284. }
  285. remaining -= result;
  286. TRACE(ft_t_noise, "verify successful:n"
  287.       KERN_INFO "segment  : %dn"
  288.       KERN_INFO "segsize  : %dn"
  289.       KERN_INFO "remaining: %d",
  290.       seg_pos, result, remaining);
  291. src_buf   += seg_sz;
  292. seg_pos++;
  293. } while (remaining > 0);
  294. TRACE_EXIT size;
  295. }
  296. /* zft_erase().  implemented compression-handling
  297.  *
  298.  * calculate the first data-segment when using/not using compression.
  299.  *
  300.  * update header-segment and compression-map-segment.
  301.  */
  302. int zft_erase(void)
  303. {
  304. int result = 0;
  305. TRACE_FUN(ft_t_flow);
  306. if (!zft_header_read) {
  307. TRACE_CATCH(zft_vmalloc_once((void **)&zft_hseg_buf,
  308.      FT_SEGMENT_SIZE),);
  309. /* no need to read the vtbl and compression map */
  310. TRACE_CATCH(ftape_read_header_segment(zft_hseg_buf),);
  311. if ((zft_old_ftape = 
  312.      zft_ftape_validate_label(&zft_hseg_buf[FT_LABEL]))) {
  313. zft_ftape_extract_file_marks(zft_hseg_buf);
  314. }
  315. TRACE(ft_t_noise,
  316.       "ft_first_data_segment: %d, ft_last_data_segment: %d", 
  317.       ft_first_data_segment, ft_last_data_segment);
  318. zft_qic113 = (ft_format_code != fmt_normal &&
  319.       ft_format_code != fmt_1100ft &&
  320.       ft_format_code != fmt_425ft);
  321. }
  322. if (zft_old_ftape) {
  323. zft_clear_ftape_file_marks();
  324. zft_old_ftape = 0; /* no longer old ftape */
  325. }
  326. PUT2(zft_hseg_buf, FT_CMAP_START, 0);
  327. zft_volume_table_changed = 1;
  328. zft_capacity = zft_get_capacity();
  329. zft_init_vtbl();
  330. /* the rest must be done in ftape_update_header_segments 
  331.  */
  332. zft_header_read = 1;
  333. zft_header_changed = 1; /* force update of timestamp */
  334. result = zft_update_header_segments();
  335. ftape_abort_operation();
  336. zft_reset_position(&zft_pos);
  337. zft_set_flags (zft_unit);
  338. TRACE_EXIT result;
  339. }
  340. unsigned int zft_get_time(void) 
  341. {
  342. unsigned int date = FT_TIME_STAMP(2097, 11, 30, 23, 59, 59); /* fun */
  343. return date;
  344. }