OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [char/] [ftape/] [ftape-write.c] - Blame information for rev 1777

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
 
2
 
3
 
4
/*
5
 *      Copyright (C) 1993-1995 Bas Laarhoven.
6
 
7
 This program is free software; you can redistribute it and/or modify
8
 it under the terms of the GNU General Public License as published by
9
 the Free Software Foundation; either version 2, or (at your option)
10
 any later version.
11
 
12
 This program is distributed in the hope that it will be useful,
13
 but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 GNU General Public License for more details.
16
 
17
 You should have received a copy of the GNU General Public License
18
 along with this program; see the file COPYING.  If not, write to
19
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
20
 
21
 $Source: /home/marcus/revision_ctrl_test/oc_cvs/cvs/or1k/rc203soc/sw/uClinux/drivers/char/ftape/ftape-write.c,v $
22
 $Author: jcastillo $
23
 *
24
 $Revision: 1.1 $
25
 $Date: 2005-12-20 10:16:52 $
26
 $State: Exp $
27
 *
28
 *      This file contains the writing code
29
 *      for the QIC-117 floppy-tape driver for Linux.
30
 */
31
 
32
#include <linux/string.h>
33
#include <linux/errno.h>
34
#include <linux/mm.h>
35
#include <linux/ftape.h>
36
#include <asm/segment.h>
37
 
38
#include "tracing.h"
39
#include "ftape-write.h"
40
#include "ftape-read.h"
41
#include "qic117.h"
42
#include "ftape-io.h"
43
#include "ftape-ctl.h"
44
#include "ftape-rw.h"
45
#include "ftape-eof.h"
46
#include "ecc.h"
47
#include "ftape-bsm.h"
48
 
49
 
50
/*      Global vars.
51
 */
52
 
53
/*      Local vars.
54
 */
55
static int buf_pos_wr = 0;
56
static int last_write_failed = 0;
57
static int need_flush = 0;
58
 
59
#define WRITE_MULTI  0
60
#define WRITE_SINGLE 1
61
 
62
void ftape_zap_write_buffers(void)
63
{
64
        int i;
65
 
66
        for (i = 0; i < NR_BUFFERS; ++i) {
67
                buffer[i].status = done;
68
        }
69
        need_flush = 0;
70
}
71
 
72
int copy_and_gen_ecc(char *destination, byte * source,
73
                     unsigned int bad_sector_map)
74
{
75
        TRACE_FUN(8, "copy_and_gen_ecc");
76
        int result;
77
        struct memory_segment mseg;
78
        int bads = count_ones(bad_sector_map);
79
 
80
        if (bads > 0) {
81
                TRACEi(4, "bad sectors in map:", bads);
82
        }
83
        if (bads + 3 >= SECTORS_PER_SEGMENT) {
84
                TRACE(4, "empty segment");
85
                mseg.blocks = 0; /* skip entire segment */
86
                result = 0;      /* nothing written */
87
        } else {
88
                mseg.blocks = SECTORS_PER_SEGMENT - bads;
89
                mseg.data = destination;
90
                memcpy(mseg.data, source, (mseg.blocks - 3) * SECTOR_SIZE);
91
                result = ecc_set_segment_parity(&mseg);
92
                if (result < 0) {
93
                        TRACE(1, "ecc_set_segment_parity failed");
94
                } else {
95
                        result = (mseg.blocks - 3) * SECTOR_SIZE;
96
                }
97
        }
98
        TRACE_EXIT;
99
        return result;
100
}
101
 
102
void prevent_flush(void)
103
{
104
        need_flush = 0;
105
        ftape_state = idle;
106
}
107
 
108
int start_writing(int mode)
109
{
110
        TRACE_FUN(5, "start_writing");
111
        int result = 0;
112
        buffer_struct *buff = &buffer[head];
113
        int segment_id = buff->segment_id;
114
 
115
        if (ftape_state == writing && buff->status == waiting) {
116
                setup_new_segment(buff, segment_id, 1);
117
                if (mode == WRITE_SINGLE) {
118
                        buffer[head].next_segment = 0;   /* stop tape instead of pause */
119
                }
120
                calc_next_cluster(buff);        /* prepare */
121
                buff->status = writing;
122
                if (runner_status == idle) {
123
                        TRACEi(5, "starting runner for segment", segment_id);
124
                        result = ftape_start_tape(segment_id, buff->sector_offset);
125
                        if (result >= 0) {
126
                                runner_status = running;
127
                        }
128
                }
129
                if (result >= 0) {
130
                        result = setup_fdc_and_dma(buff, FDC_WRITE);    /* go */
131
                }
132
                ftape_state = writing;
133
        }
134
        TRACE_EXIT;
135
        return result;
136
}
137
 
138
int loop_until_writes_done(void)
139
{
140
        TRACE_FUN(5, "loop_until_writes_done");
141
        int i;
142
        int result = 0;
143
 
144
        /*
145
         *  Wait until all data is actually written to tape.
146
         */
147
        while (ftape_state == writing && buffer[head].status != done) {
148
                TRACEx2(7, "tail: %d, head: %d", tail, head);
149
                for (i = 0; i < NR_BUFFERS; ++i) {
150
                        TRACEx3(8, "buffer[ %d] segment_id: %d, status: %d",
151
                              i, buffer[i].segment_id, buffer[i].status);
152
                }
153
                result = fdc_interrupt_wait(5 * SECOND);
154
                if (result < 0) {
155
                        TRACE(1, "fdc_interrupt_wait failed");
156
                        last_write_failed = 1;
157
                        break;
158
                }
159
                if (buffer[head].status == error) {
160
                        /* Allow escape from loop when signaled !
161
                         */
162
                        if (current->signal & _DONT_BLOCK) {
163
                                TRACE(2, "interrupted by signal");
164
                                TRACE_EXIT;
165
                                result = -EINTR;        /* is this the right return value ? */
166
                                break;
167
                        }
168
                        if (buffer[head].hard_error_map != 0) {
169
                                /*  Implement hard write error recovery here
170
                                 */
171
                        }
172
                        buffer[head].status = waiting;  /* retry this one */
173
                        if (runner_status == aborting) {
174
                                ftape_dumb_stop();
175
                                runner_status = idle;
176
                        }
177
                        if (runner_status != idle) {
178
                                TRACE(1, "unexpected state: runner_status != idle");
179
                                result = -EIO;
180
                                break;
181
                        }
182
                        start_writing(WRITE_MULTI);
183
                }
184
                TRACE(5, "looping until writes done");
185
                result = 0;      /* normal exit status */
186
        }
187
        TRACE_EXIT;
188
        return result;
189
}
190
 
191
/*      Write given segment from buffer at address onto tape.
192
 */
193
int write_segment(unsigned segment_id, byte * address, int flushing)
194
{
195
        TRACE_FUN(5, "write_segment");
196
        int result = 0;
197
        int bytes_written = 0;
198
 
199
        TRACEi(5, "segment_id =", segment_id);
200
        if (ftape_state != writing) {
201
                if (ftape_state == reading) {
202
                        TRACE(5, "calling ftape_abort_operation");
203
                        result = ftape_abort_operation();
204
                        if (result < 0) {
205
                                TRACE(1, "ftape_abort_operation failed");
206
                        }
207
                }
208
                ftape_zap_read_buffers();
209
                ftape_zap_write_buffers();
210
                ftape_state = writing;
211
        }
212
        /*    if all buffers full we'll have to wait...
213
         */
214
        wait_segment(writing);
215
        if (buffer[tail].status == error) {
216
                /*  setup for a retry
217
                 */
218
                buffer[tail].status = waiting;
219
                bytes_written = -EAGAIN;        /* force retry */
220
                if (buffer[tail].hard_error_map != 0) {
221
                        TRACEx1(1, "warning: %d hard error(s) in written segment",
222
                                count_ones(buffer[tail].hard_error_map));
223
                        TRACEx1(4, "hard_error_map = 0x%08lx", buffer[tail].hard_error_map);
224
                        /*  Implement hard write error recovery here
225
                         */
226
                }
227
        } else if (buffer[tail].status == done) {
228
                history.defects += count_ones(buffer[tail].hard_error_map);
229
        } else {
230
                TRACE(1, "wait for empty segment failed");
231
                result = -EIO;
232
        }
233
        /*    If just passed last segment on tape: wait for BOT or EOT mark.
234
         */
235
        if (result >= 0 && runner_status == logical_eot) {
236
                int status;
237
 
238
                result = ftape_ready_wait(timeout.seek, &status);
239
                if (result < 0 || (status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) == 0) {
240
                        TRACE(1, "eot/bot not reached");
241
                } else {
242
                        runner_status = end_of_tape;
243
                }
244
        }
245
        /*    should runner stop ?
246
         */
247
        if (result >= 0 &&
248
        (runner_status == aborting || runner_status == buffer_underrun ||
249
         runner_status == end_of_tape)) {
250
                if (runner_status != end_of_tape) {
251
                        result = ftape_dumb_stop();
252
                }
253
                if (result >= 0) {
254
                        if (runner_status == aborting) {
255
                                if (buffer[head].status == writing) {
256
                                        buffer[head].status = done;     /* ????? */
257
                                }
258
                        }
259
                        runner_status = idle;   /* aborted ? */
260
                }
261
        }
262
        /*  Don't start tape if runner idle and segment empty.
263
         */
264
        if (result >= 0 && !(runner_status == idle &&
265
                    get_bad_sector_entry(segment_id) == EMPTY_SEGMENT)) {
266
                if (buffer[tail].status == done) {
267
                        /*    now at least one buffer is empty, fill it with our data.
268
                         *    skip bad sectors and generate ecc.
269
                         *    copy_and_gen_ecc return nr of bytes written,
270
                         *    range 0..29 Kb inclusive !
271
                         */
272
                        result = copy_and_gen_ecc(buffer[tail].address, address,
273
                                       get_bad_sector_entry(segment_id));
274
                        if (result >= 0) {
275
                                bytes_written = result;
276
                                buffer[tail].segment_id = segment_id;
277
                                buffer[tail].status = waiting;
278
                                next_buffer(&tail);
279
                        }
280
                }
281
                /*    Start tape only if all buffers full or flush mode.
282
                 *    This will give higher probability of streaming.
283
                 */
284
                if (result >= 0 && runner_status != running &&
285
                    ((head == tail && buffer[tail].status == waiting) || flushing)) {
286
                        result = start_writing(WRITE_MULTI);
287
                }
288
        }
289
        TRACE_EXIT;
290
        return (result < 0) ? result : bytes_written;
291
}
292
 
293
/*  Write as much as fits from buffer to the given segment on tape
294
 *  and handle retries.
295
 *  Return the number of bytes written (>= 0), or:
296
 *      -EIO          write failed
297
 *      -EINTR        interrupted by signal
298
 *      -ENOSPC       device full
299
 */
300
int _write_segment(unsigned int segment_id, byte * buffer, int flush)
301
{
302
        TRACE_FUN(5, "_write_segment");
303
        int retry = 0;
304
        int result;
305
 
306
        history.used |= 2;
307
        for (;;) {
308
                if (segment_id > ftape_last_segment.id && !flush) {
309
                        result = -ENOSPC;       /* tape full */
310
                        break;
311
                }
312
                result = write_segment(segment_id, buffer, flush);
313
                if (result < 0) {
314
                        if (result == -EAGAIN) {
315
                                if (++retry > 100) {
316
                                        TRACE(1, "write failed, >100 retries in segment");
317
                                        result = -EIO;  /* give up */
318
                                        break;
319
                                } else {
320
                                        TRACEx1(2, "write error, retry %d", retry);
321
                                }
322
                        } else {
323
                                TRACEi(1, "write_segment failed, error:", -result);
324
                                break;
325
                        }
326
                } else {        /* success */
327
                        if (result == 0) {       /* empty segment */
328
                                TRACE(4, "empty segment, nothing written");
329
                        }
330
                        break;
331
                }
332
                /* Allow escape from loop when signaled !
333
                 */
334
                if (current->signal & _DONT_BLOCK) {
335
                        TRACE(2, "interrupted by signal");
336
                        TRACE_EXIT;
337
                        result = -EINTR;        /* is this the right return value ? */
338
                        break;
339
                }
340
        }
341
        TRACE_EXIT;
342
        return result;
343
}
344
 
345
int update_header_segment(unsigned segment, byte * buffer)
346
{
347
        TRACE_FUN(5, "update_header_segment");
348
        int result = 0;
349
        int status;
350
 
351
        if (buffer == NULL) {
352
                TRACE(5, "no input buffer specified");
353
                buffer = deblock_buffer;
354
                result = read_segment(used_header_segment, buffer, &status, 0);
355
                if (bad_sector_map_changed) {
356
                        store_bad_sector_map(buffer);
357
                }
358
                if (failed_sector_log_changed) {
359
                        update_failed_sector_log(buffer);
360
                }
361
        }
362
        if (result >= 0 && GET4(buffer, 0) != 0xaa55aa55) {
363
                TRACE(1, "wrong header signature found, aborting");
364
                result = -EIO;
365
        }
366
        if (result >= 0) {
367
                result = _write_segment(segment, buffer, 0);
368
                if (result >= 0 && runner_status == idle) {
369
                        /*  Force flush for single segment instead of relying on
370
                         *  flush in read_segment for multiple segments.
371
                         */
372
                        result = start_writing(WRITE_SINGLE);
373
                        if (result >= 0 && ftape_state == writing) {
374
                                result = loop_until_writes_done();
375
                                prevent_flush();
376
                        }
377
                }
378
#ifdef VERIFY_HEADERS
379
                if (result >= 0) {       /* read back and verify */
380
                        result = read_segment(segment, scratch_buffer, &status, 0);
381
                        /*  Should retry if soft error during read !
382
                         *  TO BE IMPLEMENTED
383
                         */
384
                        if (result >= 0) {
385
                                if (memcmp(buffer, scratch_buffer, sizeof(buffer)) == 0) {
386
                                        result = 0;      /* verified */
387
                                        TRACE(5, "verified");
388
                                } else {
389
                                        result = -EIO;  /* verify failed */
390
                                        TRACE(5, "verify failed");
391
                                }
392
                        }
393
                }
394
#endif
395
        }
396
        TRACE_EXIT;
397
        return result;
398
}
399
 
400
int ftape_write_header_segments(byte * buffer)
401
{
402
        TRACE_FUN(5, "ftape_write_header_segments");
403
        int result = 0;
404
        int retry = 0;
405
        int header_1_ok = 0;
406
        int header_2_ok = 0;
407
 
408
        do {
409
                if (!header_1_ok) {
410
                        result = update_header_segment(header_segment_1, buffer);
411
                        if (result < 0) {
412
                                continue;
413
                        }
414
                        header_1_ok = 1;
415
                }
416
                if (!header_2_ok) {
417
                        result = update_header_segment(header_segment_2, buffer);
418
                        if (result < 0) {
419
                                continue;
420
                        }
421
                        header_2_ok = 1;
422
                }
423
        } while (result < 0 && retry++ < 3);
424
        if (result < 0) {
425
                if (!header_1_ok) {
426
                        TRACE(1, "update of first header segment failed");
427
                }
428
                if (!header_2_ok) {
429
                        TRACE(1, "update of second header segment failed");
430
                }
431
                result = -EIO;
432
        }
433
        TRACE_EXIT;
434
        return result;
435
}
436
 
437
int ftape_update_header_segments(byte * buffer, int update)
438
{
439
        TRACE_FUN(5, "ftape_update_header_segments");
440
        int result = 0;
441
        int dummy;
442
        int header_changed = 1;
443
 
444
        if (ftape_state == writing) {
445
                result = loop_until_writes_done();
446
        }
447
        if (read_only) {
448
                result = 0;      /* exit and fake success */
449
                TRACE(4, "Tape set read-only: no update");
450
        } else if (result >= 0) {
451
                result = ftape_abort_operation();
452
                if (result >= 0) {
453
                        if (buffer == NULL) {
454
                                if (bad_sector_map_changed || failed_sector_log_changed) {
455
                                        ftape_seek_to_bot();    /* prevents extra rewind */
456
                                        buffer = deblock_buffer;
457
                                        result = read_segment(used_header_segment, buffer, &dummy, 0);
458
                                        if (result < 0) {
459
                                                TRACE_EXIT;
460
                                                return result;
461
                                        }
462
                                }
463
                                header_changed = 0;
464
                        }
465
                        if (update) {
466
                                if (bad_sector_map_changed) {
467
                                        store_bad_sector_map(buffer);
468
                                        header_changed = 1;
469
                                }
470
                                if (failed_sector_log_changed) {
471
                                        update_failed_sector_log(buffer);
472
                                        header_changed = 1;
473
                                }
474
                        }
475
                        if (header_changed) {
476
                                ftape_seek_to_bot();    /* prevents extra rewind */
477
                                result = ftape_write_header_segments(buffer);
478
                        }
479
                }
480
        }
481
        TRACE_EXIT;
482
        return result;
483
}
484
 
485
int ftape_flush_buffers(void)
486
{
487
        TRACE_FUN(5, "ftape_flush_buffers");
488
        int result;
489
        int pad_count;
490
        int data_remaining;
491
        static int active = 0;
492
 
493
        if (active) {
494
                TRACE(5, "nested call, abort");
495
                TRACE_EXIT;
496
                return 0;
497
        }
498
        active = 1;
499
        TRACEi(5, "entered, ftape_state =", ftape_state);
500
        if (ftape_state != writing && !need_flush) {
501
                active = 0;
502
                TRACE(5, "no need for flush");
503
                TRACE_EXIT;
504
                return 0;
505
        }
506
        data_remaining = buf_pos_wr;
507
        buf_pos_wr = 0;          /* prevent further writes if this fails */
508
        TRACE(5, "flushing write buffers");
509
        if (last_write_failed) {
510
                ftape_zap_write_buffers();
511
                active = 0;
512
                TRACE_EXIT;
513
                return write_protected ? -EROFS : -EIO;
514
        }
515
        /*
516
         *    If there is any data not written to tape yet, append zero's
517
         *    up to the end of the sector. Then write the segment(s) to tape.
518
         */
519
        if (data_remaining > 0) {
520
                int written;
521
 
522
                do {
523
                        TRACEi(4, "remaining in buffer:", data_remaining);
524
                        pad_count = sizeof(deblock_buffer) - data_remaining;
525
                        TRACEi(7, "flush, padding count:", pad_count);
526
                        memset(deblock_buffer + data_remaining, 0, pad_count);   /* pad buffer */
527
                        result = _write_segment(ftape_seg_pos, deblock_buffer, 1);
528
                        if (result < 0) {
529
                                if (result != -ENOSPC) {
530
                                        last_write_failed = 1;
531
                                }
532
                                active = 0;
533
                                TRACE_EXIT;
534
                                return result;
535
                        }
536
                        written = result;
537
                        clear_eof_mark_if_set(ftape_seg_pos, written);
538
                        TRACEi(7, "flush, moved out buffer:", written);
539
                        if (written > 0) {
540
                                data_remaining -= written;
541
                                if (data_remaining > 0) {
542
                                        /*  Need another segment for remaining data, move the remainder
543
                                         *  to the beginning of the buffer
544
                                         */
545
                                        memmove(deblock_buffer, deblock_buffer + written, data_remaining);
546
                                }
547
                        }
548
                        ++ftape_seg_pos;
549
                } while (data_remaining > 0);
550
                /*  Data written to last segment == data_remaining + written
551
                 *  value is in range [1..29K].
552
                 */
553
                TRACEx2(4, "last write: %d, netto pad-count: %d",
554
                        data_remaining + written, -data_remaining);
555
                if (-1024 < data_remaining && data_remaining <= 0) {
556
                        /*  Last sector of segment was used for data, so put eof mark
557
                         *  in next segment and position at second file mark.
558
                         */
559
                        if (ftape_weof(2, ftape_seg_pos, 1) >= 0) {
560
                                ++ftape_seg_pos;        /* position between file marks */
561
                        }
562
                } else {
563
                        /*  Put eof mark in previous segment after data and position
564
                         *  at second file mark.
565
                         */
566
                        ftape_weof(2, ftape_seg_pos - 1, 1 +
567
                                   ((SECTOR_SIZE - 1 + result + data_remaining) / SECTOR_SIZE));
568
                }
569
        } else {
570
                TRACE(7, "deblock_buffer empty");
571
                if (ftape_weof(2, ftape_seg_pos, 1) >= 0) {
572
                        ++ftape_seg_pos;        /* position between file marks */
573
                }
574
                start_writing(WRITE_MULTI);
575
        }
576
        TRACE(7, "waiting");
577
        result = loop_until_writes_done();
578
        if (result < 0) {
579
                TRACE(1, "flush buffers failed");
580
        }
581
        ftape_state = idle;
582
        last_write_failed = 0;
583
        need_flush = 0;
584
        active = 0;
585
        TRACE_EXIT;
586
        return result;
587
}
588
 
589
int _ftape_write(const char *buff, int req_len)
590
{
591
        TRACE_FUN(5, "_ftape_write");
592
        int result = 0;
593
        int cnt;
594
        int written = 0;
595
 
596
        if (write_protected) {
597
                TRACE(1, "error: cartridge write protected");
598
                last_write_failed = 1;
599
                result = -EROFS;
600
        } else if (ftape_offline || !formatted || no_tape) {
601
                result = -EIO;
602
        } else if (first_data_segment == -1) {
603
                /*
604
                 *    If we haven't read the header segment yet, do it now.
605
                 *    This will verify the configuration, get the eof markers
606
                 *    and the bad sector table.
607
                 *    We'll use the deblock buffer for scratch.
608
                 */
609
                result = read_header_segment(deblock_buffer);
610
                if (result >= 0 && ftape_seg_pos > ftape_last_segment.id) {
611
                        result = -ENOSPC;       /* full is full */
612
                }
613
        }
614
        if (result < 0) {
615
                TRACE_EXIT;
616
                return result;
617
        }
618
        /*
619
         *    This part writes data blocks to tape until the
620
         *    requested amount is written.
621
         *    The data will go in a buffer until it's enough
622
         *    for a segment without bad sectors. Then we'll write
623
         *    that segment to tape.
624
         *    The bytes written will be removed from the buffer
625
         *    and the process is repeated until there is less
626
         *    than one segment to write left in the buffer.
627
         */
628
        while (req_len > 0) {
629
                int space_left = sizeof(deblock_buffer) - buf_pos_wr;
630
 
631
                TRACEi(7, "remaining req_len:", req_len);
632
                TRACEi(7, "          buf_pos:", buf_pos_wr);
633
                cnt = (req_len < space_left) ? req_len : space_left;
634
                if (cnt > 0) {
635
                        result = verify_area(VERIFY_READ, buff, cnt);
636
                        if (result) {
637
                                TRACE(1, "verify_area failed");
638
                                last_write_failed = 1;
639
                                TRACE_EXIT;
640
                                return result;
641
                        }
642
                        memcpy_fromfs(deblock_buffer + buf_pos_wr, buff, cnt);
643
                        buff += cnt;
644
                        req_len -= cnt;
645
                        buf_pos_wr += cnt;
646
                }
647
                TRACEi(7, "moved into blocking buffer:", cnt);
648
                while (buf_pos_wr >= sizeof(deblock_buffer)) {
649
                        /*  If this is the last buffer to be written, let flush handle it.
650
                         */
651
                        if (ftape_seg_pos >= ftape_last_segment.id) {
652
                                TRACEi(7, "remaining in blocking buffer:", buf_pos_wr);
653
                                TRACEi(7, "just written bytes:", written + cnt);
654
                                TRACE_EXIT;
655
                                return written + cnt;
656
                        }
657
                        /* Got one full buffer, write it to disk
658
                         */
659
                        result = _write_segment(ftape_seg_pos, deblock_buffer, 0);
660
                        TRACEi(5, "_write_segment result =", result);
661
                        if (result < 0) {
662
                                if (result == -EAGAIN) {
663
                                        TRACE(5, "retry...");
664
                                        continue;       /* failed, retry same segment */
665
                                }
666
                                last_write_failed = 1;
667
                                TRACE_EXIT;
668
                                return result;
669
                        } else {
670
                                clear_eof_mark_if_set(ftape_seg_pos, result);
671
                        }
672
                        if (result > 0 && result < buf_pos_wr) {
673
                                /* Partial write: move remainder in lower part of buffer
674
                                 */
675
                                memmove(deblock_buffer, deblock_buffer + result, buf_pos_wr - result);
676
                        }
677
                        TRACEi(7, "moved out of blocking buffer:", result);
678
                        buf_pos_wr -= result;   /* remainder */
679
                        ++ftape_seg_pos;
680
                        /* Allow us to escape from this loop with a signal !
681
                         */
682
                        if (current->signal & _DONT_BLOCK) {
683
                                TRACE(2, "interrupted by signal");
684
                                last_write_failed = 1;
685
                                TRACE_EXIT;
686
                                return -EINTR;  /* is this the right return value ? */
687
                        }
688
                }
689
                written += cnt;
690
        }
691
        TRACEi(7, "remaining in blocking buffer:", buf_pos_wr);
692
        TRACEi(7, "just written bytes:", written);
693
        last_write_failed = 0;
694
        if (!need_flush && written > 0) {
695
                need_flush = 1;
696
        }
697
        TRACE_EXIT;
698
        return written;         /* bytes written */
699
}
700
 
701
int ftape_fix(void)
702
{
703
        TRACE_FUN(5, "ftape_fix");
704
        int result = 0;
705
        int dummy;
706
        int status;
707
 
708
        if (write_protected) {
709
                result = -EROFS;
710
        } else {
711
                /*  This will copy header segment 2 to header segment 1
712
                 *  Spares us a tape format operation if header 2 is still good.
713
                 */
714
                header_segment_1 = 0;
715
                header_segment_2 = 1;
716
                first_data_segment = 2;
717
                result = read_segment(header_segment_2, scratch_buffer, &dummy, 0);
718
                result = ftape_ready_wait(timeout.pause, &status);
719
                result = ftape_write_header_segments(scratch_buffer);
720
        }
721
        TRACE_EXIT;
722
        return result;
723
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.