Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]

Diff markup

Differences between /linux/drivers/char/ftape/zftape/zftape-write.c (Version 2.6.11.8) and /linux/drivers/char/ftape/zftape/zftape-write.c (Version 2.6.25)


  1 /*                                                  1 
  2  *      Copyright (C) 1996, 1997 Claus Heine      
  3                                                   
  4  This program is free software; you can redist    
  5  it under the terms of the GNU General Public     
  6  the Free Software Foundation; either version     
  7  any later version.                               
  8                                                   
  9  This program is distributed in the hope that     
 10  but WITHOUT ANY WARRANTY; without even the im    
 11  MERCHANTABILITY or FITNESS FOR A PARTICULAR P    
 12  GNU General Public License for more details.     
 13                                                   
 14  You should have received a copy of the GNU Ge    
 15  along with this program; see the file COPYING    
 16  the Free Software Foundation, 675 Mass Ave, C    
 17                                                   
 18  *                                                
 19  * $Source: /homes/cvs/ftape-stacked/ftape/zft    
 20  * $Revision: 1.3 $                               
 21  * $Date: 1997/11/06 00:50:29 $                   
 22  *                                                
 23  *      This file contains the writing code       
 24  *      for the QIC-117 floppy-tape driver for    
 25  */                                               
 26                                                   
 27 #include <linux/errno.h>                          
 28 #include <linux/mm.h>                             
 29                                                   
 30 #include <linux/zftape.h>                         
 31                                                   
 32 #include <asm/uaccess.h>                          
 33                                                   
 34 #include "../zftape/zftape-init.h"                
 35 #include "../zftape/zftape-eof.h"                 
 36 #include "../zftape/zftape-ctl.h"                 
 37 #include "../zftape/zftape-write.h"               
 38 #include "../zftape/zftape-read.h"                
 39 #include "../zftape/zftape-rw.h"                  
 40 #include "../zftape/zftape-vtbl.h"                
 41                                                   
 42 /*      Global vars.                              
 43  */                                               
 44                                                   
 45 /*      Local vars.                               
 46  */                                               
 47 static int last_write_failed;                     
 48 static int need_flush;                            
 49                                                   
 50 void zft_prevent_flush(void)                      
 51 {                                                 
 52         need_flush = 0;                           
 53 }                                                 
 54                                                   
 55 static int zft_write_header_segments(__u8* buf    
 56 {                                                 
 57         int header_1_ok = 0;                      
 58         int header_2_ok = 0;                      
 59         unsigned int time_stamp;                  
 60         TRACE_FUN(ft_t_noise);                    
 61                                                   
 62         TRACE_CATCH(ftape_abort_operation(),);    
 63         ftape_seek_to_bot();    /* prevents ex    
 64         if (GET4(buffer, 0) != FT_HSEG_MAGIC)     
 65                 TRACE_ABORT(-EIO, ft_t_err,       
 66                             "wrong header sign    
 67         }                                         
 68         /*   Be optimistic: */                    
 69         PUT4(buffer, FT_SEG_CNT,                  
 70              zft_written_segments + GET4(buffe    
 71         if ((time_stamp = zft_get_time()) != 0    
 72                 PUT4(buffer, FT_WR_DATE, time_    
 73                 if (zft_label_changed) {          
 74                         PUT4(buffer, FT_LABEL_    
 75                 }                                 
 76         }                                         
 77         TRACE(ft_t_noise,                         
 78               "writing first header segment %d    
 79         header_1_ok = zft_verify_write_segment    
 80                                                   
 81                                                   
 82         TRACE(ft_t_noise,                         
 83               "writing second header segment %    
 84         header_2_ok = zft_verify_write_segment    
 85                                                   
 86                                                   
 87         if (!header_1_ok) {                       
 88                 TRACE(ft_t_warn, "Warning: "      
 89                       "update of first header     
 90         }                                         
 91         if (!header_2_ok) {                       
 92                 TRACE(ft_t_warn, "Warning: "      
 93                       "update of second header    
 94         }                                         
 95         if (!header_1_ok && !header_2_ok) {       
 96                 TRACE_ABORT(-EIO, ft_t_err, "E    
 97                       "update of both header s    
 98         }                                         
 99         TRACE_EXIT 0;                             
100 }                                                 
101                                                   
102 int zft_update_header_segments(void)              
103 {                                                 
104         TRACE_FUN(ft_t_noise);                    
105                                                   
106         /*  must NOT use zft_write_protected,     
107          *  file access mode. But we also want    
108          *  write protection is enabled (O_RDO    
109          */                                       
110         if (ft_write_protected || zft_old_ftap    
111                 TRACE_ABORT(0, ft_t_noise, "Ta    
112         }                                         
113         if (!zft_header_read) {                   
114                 TRACE_ABORT(0, ft_t_noise, "No    
115         }                                         
116         if (!zft_header_changed) {                
117                 zft_header_changed = zft_writt    
118         }                                         
119         if (!zft_header_changed && !zft_volume    
120                 TRACE_ABORT(0, ft_t_noise, "No    
121         }                                         
122         TRACE(ft_t_noise, "Updating header seg    
123         if (ftape_get_status()->fti_state == w    
124                 TRACE_CATCH(ftape_loop_until_w    
125         }                                         
126         TRACE_CATCH(ftape_abort_operation(),);    
127                                                   
128         zft_deblock_segment = -1; /* invalidat    
129         if (zft_header_changed) {                 
130                 TRACE_CATCH(zft_write_header_s    
131         }                                         
132         if (zft_volume_table_changed) {           
133                 TRACE_CATCH(zft_update_volume_    
134         }                                         
135         zft_header_changed =                      
136                 zft_volume_table_changed =        
137                 zft_label_changed        =        
138                 zft_written_segments     = 0;     
139         TRACE_CATCH(ftape_abort_operation(),);    
140         ftape_seek_to_bot();                      
141         TRACE_EXIT 0;                             
142 }                                                 
143                                                   
144 static int read_merge_buffer(int seg_pos, __u8    
145 {                                                 
146         int result = 0;                           
147         const ft_trace_t old_tracing = TRACE_L    
148         TRACE_FUN(ft_t_flow);                     
149                                                   
150         if (zft_qic_mode) {                       
151                 /*  writing in the middle of a    
152                  *                                
153                  */                               
154                 TRACE(ft_t_noise, "No need to     
155                 memset(buffer + offset, 0, seg    
156                 TRACE_EXIT 0;                     
157         }                                         
158         TRACE(ft_t_any, "waiting");               
159         ftape_start_writing(FT_WR_MULTI);         
160         TRACE_CATCH(ftape_loop_until_writes_do    
161                                                   
162         TRACE(ft_t_noise, "trying to read segm    
163               seg_pos, offset);                   
164         SET_TRACE_LEVEL(ft_t_bug);                
165         result = zft_fetch_segment_fraction(se    
166                                             FT    
167                                             of    
168         SET_TRACE_LEVEL(old_tracing);             
169         if (result != (seg_sz - offset)) {        
170                 TRACE(ft_t_noise, "Ignore erro    
171                       result);                    
172                 memset(buffer + offset, 0, seg    
173         }                                         
174         TRACE_EXIT 0;                             
175 }                                                 
176                                                   
177 /* flush the write buffer to tape and write an    
178  * current position if not in raw mode.  This     
179  * positions the tape before the eof-marker.      
180  * then advance to the next segment.              
181  *                                                
182  * the parameter "finish_volume" describes whe    
183  * or after the possibly created file-mark. We    
184  * the file-mark when called from ftape_close(    
185  * (that is ftape_write() was the last tape op    
186  * ftape_flush) But we always position before     
187  * function get's called from outside ftape_cl    
188  */                                               
189 int zft_flush_buffers(void)                       
190 {                                                 
191         int result;                               
192         int data_remaining;                       
193         int this_segs_size;                       
194         TRACE_FUN(ft_t_flow);                     
195                                                   
196         TRACE(ft_t_data_flow,                     
197               "entered, ftape_state = %d", fta    
198         if (ftape_get_status()->fti_state != w    
199                 TRACE_ABORT(0, ft_t_noise, "no    
200         }                                         
201         zft_io_state = zft_idle; /*  triggers     
202                                   *  read and     
203                                   */              
204         if (last_write_failed) {                  
205                 ftape_abort_operation();          
206                 TRACE_EXIT -EIO;                  
207         }                                         
208         TRACE(ft_t_noise, "flushing write buff    
209         this_segs_size = zft_get_seg_sz(zft_po    
210         if (this_segs_size == zft_pos.seg_byte    
211                 zft_pos.seg_pos ++;               
212                 data_remaining = zft_pos.seg_b    
213         } else {                                  
214                 data_remaining = zft_pos.seg_b    
215         }                                         
216         /* If there is any data not written to    
217          * up to the end of the sector (if usi    
218          * it with the data existing on the ta    
219          * segment(s) to tape.                    
220          */                                       
221         TRACE(ft_t_noise, "Position:\n"           
222               KERN_INFO "seg_pos  : %d\n"         
223               KERN_INFO "byte pos : %d\n"         
224               KERN_INFO "remaining: %d",          
225               zft_pos.seg_pos, zft_pos.seg_byt    
226         if (data_remaining > 0) {                 
227                 do {                              
228                         this_segs_size = zft_g    
229                         if (this_segs_size > d    
230                                 TRACE_CATCH(re    
231                                                   
232                                                   
233                                                   
234                                             la    
235                         }                         
236                         result = ftape_write_s    
237                                                   
238                                                   
239                         if (result != this_seg    
240                                 TRACE(ft_t_err    
241                                 zft_pos.tape_p    
242                                 zft_pos.seg_by    
243                                                   
244                                 last_write_fai    
245                                 TRACE_EXIT res    
246                         }                         
247                         zft_written_segments +    
248                         TRACE(ft_t_data_flow,     
249                               "flush, moved ou    
250                         /* need next segment f    
251                          */                       
252                         if (result < data_rema    
253                                 if (result > 0    
254                                         /* mov    
255                                          */       
256                                         memmov    
257                                                   
258                                                   
259                                 }                 
260                         }                         
261                         data_remaining -= resu    
262                         zft_pos.seg_pos ++;       
263                 } while (data_remaining > 0);     
264                 TRACE(ft_t_any, "result: %d",     
265                 zft_deblock_segment = --zft_po    
266                 if (data_remaining == 0) {  /*    
267                         zft_pos.seg_byte_pos =    
268                 } else { /* after data previou    
269                         zft_pos.seg_byte_pos =    
270                 }                                 
271         } else {                                  
272                 TRACE(ft_t_noise, "zft_deblock    
273                 zft_pos.seg_pos --;               
274                 zft_pos.seg_byte_pos = zft_get    
275                 ftape_start_writing(FT_WR_MULT    
276         }                                         
277         TRACE(ft_t_any, "waiting");               
278         if ((result = ftape_loop_until_writes_    
279                 /* that's really bad. What to     
280                  */                               
281                 TRACE(ft_t_err, "flush buffers    
282         }                                         
283         TRACE(ft_t_any, "zft_seg_pos: %d, zft_    
284               zft_pos.seg_pos, zft_pos.seg_byt    
285         last_write_failed  =                      
286                 need_flush = 0;                   
287         TRACE_EXIT result;                        
288 }                                                 
289                                                   
290 /* return-value: the number of bytes removed f    
291  *                                                
292  * out:                                           
293  *      int *write_cnt: how much actually has     
294  *                      zft_deblock_buf           
295  *      int req_len  : MUST NOT BE CHANGED, ex    
296  *                      which case it may be a    
297  * in :                                           
298  *      char *buff        : the user buffer       
299  *      int buf_pos_write : copy of buf_len_wr    
300  *      this_segs_size    : the size in bytes     
301  *                          char                  
302  *      *zft_deblock_buf   : zft_deblock_buf      
303  */                                               
304 static int zft_simple_write(int *cnt,             
305                             __u8 *dst_buf, con    
306                             const __u8 __user     
307                             const zft_position    
308 {                                                 
309         int space_left;                           
310         TRACE_FUN(ft_t_flow);                     
311                                                   
312         /* volume->size holds the tape capacit    
313         if (pos->tape_pos + volume->blk_sz > v    
314                 TRACE_EXIT -ENOSPC;               
315         }                                         
316         /*  remaining space in this segment, N    
317          */                                       
318         space_left = seg_sz - pos->seg_byte_po    
319         *cnt = req_len < space_left ? req_len     
320         if (copy_from_user(dst_buf + pos->seg_    
321                 TRACE_EXIT -EFAULT;               
322         }                                         
323         TRACE_EXIT *cnt;                          
324 }                                                 
325                                                   
326 static int check_write_access(int req_len,        
327                               const zft_volinf    
328                               zft_position *po    
329                               const unsigned i    
330 {                                                 
331         int result;                               
332         TRACE_FUN(ft_t_flow);                     
333                                                   
334         if ((req_len % zft_blk_sz) != 0) {        
335                 TRACE_ABORT(-EINVAL, ft_t_info    
336                             "write-count %d mu    
337                             req_len, blk_sz);     
338         }                                         
339         if (zft_io_state == zft_writing) {        
340                 /*  all other error conditions    
341                  */                               
342                 TRACE_EXIT 0;                     
343         }                                         
344         zft_io_state = zft_idle;                  
345         TRACE_CATCH(zft_check_write_access(pos    
346         /*  If we haven't read the header segm    
347          *  This will verify the configuration    
348          *  table and read the volume table se    
349          */                                       
350         if (!zft_header_read) {                   
351                 TRACE_CATCH(zft_read_header_se    
352         }                                         
353         /*  fine. Now the tape is either at BO    
354          *  Write start of volume now             
355          */                                       
356         TRACE_CATCH(zft_open_volume(pos, blk_s    
357         *volume = zft_find_volume(pos->seg_pos    
358         DUMP_VOLINFO(ft_t_noise, "", *volume);    
359         zft_just_before_eof = 0;                  
360         /* now merge with old data if necessar    
361         if (!zft_qic_mode && pos->seg_byte_pos    
362                 result = zft_fetch_segment(pos    
363                                            zft    
364                                            FT_    
365                 if (result < 0) {                 
366                         if (result == -EINTR |    
367                                 TRACE_EXIT res    
368                         }                         
369                         TRACE(ft_t_noise,         
370                               "ftape_read_segm    
371                               "This might be n    
372                               "a newly\nformat    
373                         memset(zft_deblock_buf    
374                 }                                 
375         }                                         
376         zft_io_state = zft_writing;               
377         TRACE_EXIT 0;                             
378 }                                                 
379                                                   
380 static int fill_deblock_buf(__u8 *dst_buf, con    
381                             zft_position *pos,    
382                             const char __user     
383 {                                                 
384         int cnt = 0;                              
385         int result = 0;                           
386         TRACE_FUN(ft_t_flow);                     
387                                                   
388         if (seg_sz == 0) {                        
389                 TRACE_ABORT(0, ft_t_data_flow,    
390         }                                         
391         TRACE(ft_t_data_flow, "\n"                
392               KERN_INFO "remaining req_len: %d    
393               KERN_INFO "          buf_pos: %d    
394               req_len, pos->seg_byte_pos);        
395         /* zft_deblock_buf will not contain a     
396         zft_deblock_segment = -1;                 
397         if (zft_use_compression) {                
398                 TRACE_CATCH(zft_cmpr_lock(1 /*    
399                 TRACE_CATCH(result= (*zft_cmpr    
400                                                   
401                                                   
402                                                   
403         } else {                                  
404                 TRACE_CATCH(result= zft_simple    
405                                                   
406                                                   
407                                                   
408         }                                         
409         pos->volume_pos   += result;              
410         pos->seg_byte_pos += cnt;                 
411         pos->tape_pos     += cnt;                 
412         TRACE(ft_t_data_flow, "\n"                
413               KERN_INFO "removed from user-buf    
414               KERN_INFO "copied to zft_deblock    
415               KERN_INFO "zft_tape_pos             
416               result, cnt, LL(pos->tape_pos));    
417         TRACE_EXIT result;                        
418 }                                                 
419                                                   
420                                                   
421 /*  called by the kernel-interface routine "zf    
422  */                                               
423 int _zft_write(const char __user *buff, int re    
424 {                                                 
425         int result = 0;                           
426         int written = 0;                          
427         int write_cnt;                            
428         int seg_sz;                               
429         static const zft_volinfo *volume = NUL    
430         TRACE_FUN(ft_t_flow);                     
431                                                   
432         zft_resid         = req_len;              
433         last_write_failed = 1; /* reset to 0 w    
434         /* check if write is allowed              
435          */                                       
436         TRACE_CATCH(check_write_access(req_len    
437         while (req_len > 0) {                     
438                 /* Allow us to escape from thi    
439                  */                               
440                 FT_SIGNAL_EXIT(_DONT_BLOCK);      
441                 seg_sz = zft_get_seg_sz(zft_po    
442                 if ((write_cnt = fill_deblock_    
443                                                   
444                                                   
445                                                   
446                                                   
447                                                   
448                         zft_resid -= written;     
449                         if (write_cnt == -ENOS    
450                                 /* leave the r    
451                                  */               
452                                 TRACE(ft_t_inf    
453                                 last_write_fai    
454                                 if (!need_flus    
455                                         need_f    
456                                 }                 
457                                 TRACE_EXIT wri    
458                         } else {                  
459                                 TRACE_EXIT res    
460                         }                         
461                 }                                 
462                 if (zft_pos.seg_byte_pos == se    
463                         TRACE_CATCH(ftape_writ    
464                                                   
465                                                   
466                                     zft_resid     
467                         zft_written_segments +    
468                         zft_pos.seg_byte_pos =    
469                         zft_deblock_segment  =    
470                         ++zft_pos.seg_pos;        
471                 }                                 
472                 written += write_cnt;             
473                 buff    += write_cnt;             
474                 req_len -= write_cnt;             
475         } /* while (req_len > 0) */               
476         TRACE(ft_t_data_flow, "remaining in bl    
477                zft_pos.seg_byte_pos);             
478         TRACE(ft_t_data_flow, "just written by    
479         last_write_failed = 0;                    
480         zft_resid -= written;                     
481         need_flush = need_flush || written > 0    
482         TRACE_EXIT written;               /* b    
483 }                                                 
484                                                   
  This page was automatically generated by the LXR engine.