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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [uclinux/] [uClinux-2.0.x/] [drivers/] [char/] [ftape/] [ftape-read.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *      Copyright (C) 1993-1995 Bas Laarhoven.
3
 
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
 
9
 This program is distributed in the hope that it will be useful,
10
 but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 GNU General Public License for more details.
13
 
14
 You should have received a copy of the GNU General Public License
15
 along with this program; see the file COPYING.  If not, write to
16
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
17
 
18
 $Source: /home/marcus/revision_ctrl_test/oc_cvs/cvs/or1k/uclinux/uClinux-2.0.x/drivers/char/ftape/ftape-read.c,v $
19
 $Author: simons $
20
 *
21
 $Revision: 1.1.1.1 $
22
 $Date: 2001-09-10 07:44:17 $
23
 $State: Exp $
24
 *
25
 *      This file contains the reading code
26
 *      for the QIC-117 floppy-tape driver for Linux.
27
 */
28
 
29
#include <linux/string.h>
30
#include <linux/errno.h>
31
#include <linux/mm.h>
32
#include <linux/ftape.h>
33
#include <asm/segment.h>
34
 
35
#include "tracing.h"
36
#include "ftape-read.h"
37
#include "qic117.h"
38
#include "ftape-io.h"
39
#include "ftape-ctl.h"
40
#include "ftape-rw.h"
41
#include "ftape-write.h"
42
#include "ftape-eof.h"
43
#include "ecc.h"
44
#include "ftape-bsm.h"
45
 
46
/*      Global vars.
47
 */
48
 
49
/*      Local vars.
50
 */
51
int buf_pos_rd = 0;
52
int buf_len_rd = 0;
53
 
54
void ftape_zap_read_buffers(void)
55
{
56
        int i;
57
 
58
        for (i = 0; i < NR_BUFFERS; ++i) {
59
                /*
60
                 * changed to "fit" with dynamic allocation of tape_buffer. --khp
61
                 */
62
                buffer[i].address = tape_buffer[i];
63
                buffer[i].status = waiting;
64
                buffer[i].bytes = 0;
65
                buffer[i].skip = 0;
66
                buffer[i].retry = 0;
67
        }
68
        buf_len_rd = 0;
69
        buf_pos_rd = 0;
70
        eof_mark = 0;
71
        ftape_state = idle;
72
}
73
 
74
static unsigned long convert_sector_map(buffer_struct * buff)
75
{
76
        TRACE_FUN(8, "convert_sector_map");
77
        int i = 0;
78
        unsigned long bad_map = get_bad_sector_entry(buff->segment_id);
79
        unsigned long src_map = buff->soft_error_map | buff->hard_error_map;
80
        unsigned long dst_map = 0;
81
 
82
        if (bad_map || src_map) {
83
                TRACEx1(5, "bad_map = 0x%08lx", bad_map);
84
                TRACEx1(5, "src_map = 0x%08lx", src_map);
85
        }
86
        while (bad_map) {
87
                while ((bad_map & 1) == 0) {
88
                        if (src_map & 1) {
89
                                dst_map |= (1 << i);
90
                        }
91
                        src_map >>= 1;
92
                        bad_map >>= 1;
93
                        ++i;
94
                }
95
                /* (bad_map & 1) == 1 */
96
                src_map >>= 1;
97
                bad_map >>= 1;
98
        }
99
        if (src_map) {
100
                dst_map |= (src_map << i);
101
        }
102
        if (dst_map) {
103
                TRACEx1(5, "dst_map = 0x%08lx", dst_map);
104
        }
105
        TRACE_EXIT;
106
        return dst_map;
107
}
108
 
109
int correct_and_copy(unsigned int tail, byte * destination)
110
{
111
        TRACE_FUN(8, "correct_and_copy");
112
        struct memory_segment mseg;
113
        int result;
114
        BAD_SECTOR read_bad;
115
 
116
        mseg.read_bad = convert_sector_map(&buffer[tail]);
117
        mseg.marked_bad = 0;     /* not used... */
118
        mseg.blocks = buffer[tail].bytes / SECTOR_SIZE;
119
        mseg.data = buffer[tail].address;
120
        /*    If there are no data sectors we can skip this segment.
121
         */
122
        if (mseg.blocks <= 3) {
123
                TRACE(4, "empty segment");
124
                TRACE_EXIT;
125
                return 0;
126
        }
127
        read_bad = mseg.read_bad;
128
        history.crc_errors += count_ones(read_bad);
129
        result = ecc_correct_data(&mseg);
130
        if (read_bad != 0 || mseg.corrected != 0) {
131
                TRACElx(4, "crc error map:", read_bad);
132
                TRACElx(4, "corrected map:", mseg.corrected);
133
                history.corrected += count_ones(mseg.corrected);
134
        }
135
        if (result == ECC_CORRECTED || result == ECC_OK) {
136
                if (result == ECC_CORRECTED) {
137
                        TRACEi(3, "ecc corrected segment:", buffer[tail].segment_id);
138
                }
139
                memcpy(destination, mseg.data, (mseg.blocks - 3) * SECTOR_SIZE);
140
                if ((read_bad ^ mseg.corrected) & mseg.corrected) {
141
                        /* sectors corrected without crc errors set */
142
                        history.crc_failures++;
143
                }
144
                TRACE_EXIT;
145
                return (mseg.blocks - 3) * SECTOR_SIZE;
146
        } else {
147
                TRACEi(1, "ecc failure on segment", buffer[tail].segment_id);
148
                history.ecc_failures++;
149
                TRACE_EXIT;
150
                return -EAGAIN; /* should retry */
151
        }
152
        TRACE_EXIT;
153
        return 0;
154
}
155
 
156
/*      Read given segment into buffer at address.
157
 */
158
int read_segment(unsigned segment_id, byte * address, int *eof_mark,
159
                 int read_ahead)
160
{
161
        TRACE_FUN(5, "read_segment");
162
        int read_done = 0;
163
        int result = 0;
164
        int bytes_read = 0;
165
        int retry = 0;
166
 
167
        TRACEi(5, "segment_id =", segment_id);
168
        if (ftape_state != reading) {
169
                if (ftape_state == writing) {
170
                        ftape_flush_buffers();  /* flush write buffer */
171
                        TRACE(5, "calling ftape_abort_operation");
172
                        result = ftape_abort_operation();
173
                        if (result < 0) {
174
                                TRACE(1, "ftape_abort_operation failed");
175
                                TRACE_EXIT;
176
                                return -EIO;
177
                        }
178
                } else {
179
                        /* clear remaining read buffers */
180
                        ftape_zap_read_buffers();
181
                }
182
                ftape_state = reading;
183
        }
184
        if (segment_id >= segments_per_track * tracks_per_tape) {
185
                TRACE(5, "reading past end of tape");
186
                TRACE_EXIT;
187
                return -ENOSPC;
188
        }
189
        for (;;) {
190
                /*    Search all full buffers for the first matching the wanted segment.
191
                 *    Clear other buffers on the fly.
192
                 */
193
                while (!read_done && buffer[tail].status == done) {
194
                        if (buffer[tail].segment_id == segment_id) {
195
                                unsigned eof_sector;
196
                                unsigned sector_count = 0;
197
                                unsigned long bsm = get_bad_sector_entry(segment_id);
198
                                int i;
199
 
200
                                /*        If out buffer is already full, return its contents.
201
                                 */
202
                                if (buffer[tail].deleted) {
203
                                        TRACEi(5, "found segment in cache :", segment_id);
204
                                        TRACE_EXIT;
205
                                        /*  Return a value that read_header_segment understands.
206
                                         *  As this should only occur when searching for the header
207
                                         *  segments it shouldn't be misinterpreted elsewhere.
208
                                         */
209
                                        return 0;
210
                                }
211
                                TRACEi(5, "found segment in cache :", segment_id);
212
                                eof_sector = check_for_eof(segment_id);
213
                                if (eof_sector > 0) {
214
                                        TRACEi(5, "end of file mark in sector:", eof_sector);
215
                                        for (i = 1; i < eof_sector; ++i) {
216
                                                if ((bsm & 1) == 0) {
217
                                                        ++sector_count;
218
                                                }
219
                                                bsm >>= 1;
220
                                        }
221
                                        *eof_mark = 1;
222
                                }
223
                                if (eof_sector != 1) {  /* not found or gt 1 */
224
                                        result = correct_and_copy(tail, address);
225
                                        TRACEi(5, "segment contains (bytes) :", result);
226
                                        if (result < 0) {
227
                                                if (result != -EAGAIN) {
228
                                                        TRACE_EXIT;
229
                                                        return result;
230
                                                }
231
                                                /* keep read_done == 0, will trigger ftape_abort_operation
232
                                                 * because reading wrong segment.
233
                                                 */
234
                                                TRACE(1, "ecc failed, retry");
235
                                                ++retry;
236
                                        } else {
237
                                                read_done = 1;
238
                                        }
239
                                } else {
240
                                        read_done = 1;
241
                                }
242
                                if (eof_sector > 0) {
243
                                        bytes_read = sector_count * SECTOR_SIZE;
244
                                        TRACEi(5, "partial read count:", bytes_read);
245
                                } else {
246
                                        bytes_read = result;
247
                                }
248
                        } else {
249
                                TRACEi(5, "zapping segment in cache :", buffer[tail].segment_id);
250
                        }
251
                        buffer[tail].status = waiting;
252
                        next_buffer(&tail);
253
                }
254
                if (!read_done && buffer[tail].status == reading) {
255
                        if (buffer[tail].segment_id == segment_id) {
256
                                int result = wait_segment(reading);
257
                                if (result < 0) {
258
                                        if (result == -EINTR) {
259
                                                TRACE_EXIT;
260
                                                return result;
261
                                        }
262
                                        TRACE(1, "wait_segment failed while reading");
263
                                        ftape_abort_operation();
264
                                }
265
                        } else {
266
                                /*        We're reading the wrong segment, stop runner.
267
                                 */
268
                                ftape_abort_operation();
269
                        }
270
                }
271
                /*    if just passed the last segment on a track, wait for BOT or EOT mark.
272
                 */
273
                if (runner_status == logical_eot) {
274
                        int status;
275
                        result = ftape_ready_wait(timeout.seek, &status);
276
                        if (result < 0) {
277
                                TRACE(1, "ftape_ready_wait waiting for eot/bot failed");
278
                        }
279
                        if ((status & (QIC_STATUS_AT_BOT | QIC_STATUS_AT_EOT)) == 0) {
280
                                TRACE(1, "eot/bot not reached");
281
                        }
282
                        runner_status = end_of_tape;
283
                }
284
                /*    should runner stop ?
285
                 */
286
                if (runner_status == aborting || runner_status == buffer_overrun ||
287
                    runner_status == end_of_tape) {
288
                        if (runner_status != end_of_tape &&
289
                         !(runner_status == aborting && !tape_running)) {
290
                                ftape_dumb_stop();
291
                        }
292
                        if (runner_status == aborting) {
293
                                if (buffer[head].status == reading || buffer[head].status == error) {
294
                                        if (buffer[head].status == error) {
295
                                                history.defects += count_ones(buffer[head].hard_error_map);
296
                                        }
297
                                        buffer[head].status = waiting;
298
                                }
299
                        }
300
                        runner_status = idle;   /* aborted ? */
301
                }
302
                /*    If segment to read is empty, do not start runner for it,
303
                 *    but wait for next read call.
304
                 */
305
                if (get_bad_sector_entry(segment_id) == EMPTY_SEGMENT) {
306
                        bytes_read = 0;          /* flag empty segment */
307
                        read_done = 1;
308
                }
309
                /*  Allow escape from this loop on signal !
310
                 */
311
                if (current->signal & _DONT_BLOCK) {
312
                        TRACE(2, "interrupted by non-blockable signal");
313
                        TRACE_EXIT;
314
                        return -EINTR;
315
                }
316
                /*    If we got a segment: quit, or else retry up to limit.
317
                 */
318
                if (read_done) {
319
                        break;
320
                }
321
                if (retry > RETRIES_ON_ECC_ERROR) {
322
                        history.defects++;
323
                        TRACE(1, "too many retries on ecc failure");
324
                        TRACE_EXIT;
325
                        return -ENODATA;
326
                }
327
                /*    Now at least one buffer is empty !
328
                 *    Restart runner & tape if needed.
329
                 */
330
                TRACEx3(8, "head: %d, tail: %d, runner_status: %d",
331
                        head, tail, runner_status);
332
                TRACEx2(8, "buffer[].status, [head]: %d, [tail]: %d",
333
                        buffer[head].status, buffer[tail].status);
334
                if (buffer[tail].status == waiting) {
335
                        setup_new_segment(&buffer[head], segment_id, -1);
336
                        if (!read_ahead) {
337
                                buffer[head].next_segment = 0;   /* disable read-ahead */
338
                        }
339
                        calc_next_cluster(&buffer[head]);
340
                        if (runner_status == idle) {
341
                                result = ftape_start_tape(segment_id,
342
                                             buffer[head].sector_offset);
343
                                if (result < 0) {
344
                                        TRACEx1(1, "Error: segment %d unreachable", segment_id);
345
                                        TRACE_EXIT;
346
                                        return result;
347
                                }
348
                                runner_status = running;
349
                        }
350
                        buffer[head].status = reading;
351
                        setup_fdc_and_dma(&buffer[head], FDC_READ);
352
                }
353
        }
354
        if (read_done) {
355
                TRACE_EXIT;
356
                return bytes_read;
357
        } else {
358
                TRACE(1, "too many retries");
359
                TRACE_EXIT;
360
                return -EIO;
361
        }
362
}
363
 
364
int read_header_segment(byte * address)
365
{
366
        TRACE_FUN(5, "read_header_segment");
367
        int i;
368
        int result;
369
        int header_segment = -1;
370
        unsigned int max_floppy_side;
371
        unsigned int max_floppy_track;
372
        unsigned int max_floppy_sector;
373
        int first_failed = 0;
374
        int status;
375
        int new_tape_len;
376
 
377
        result = ftape_report_drive_status(&status);
378
        if (result < 0) {
379
                TRACE(1, "error: error_status or report failure");
380
                TRACE_EXIT;
381
                return -EIO;
382
        }
383
        TRACE(5, "reading...");
384
        ftape_last_segment.id = 68;     /* will allow us to read the header ! */
385
        /*  We're looking for the first header segment.
386
         *  A header segment cannot contain bad sectors, therefor at the
387
         *  tape start, segments with bad sectors are (according to QIC-40/80)
388
         *  written with deleted data marks and must be skipped.
389
         */
390
        used_header_segment = -1;
391
        result = 0;
392
        for (header_segment = 0;
393
             header_segment < ftape_last_segment.id && result == 0;
394
             ++header_segment) {
395
                /*  Set no read-ahead, the isr will force read-ahead whenever
396
                 *  it encounters deleted data !
397
                 */
398
                result = read_segment(header_segment, address, &status, 0);
399
                if (result < 0 && !first_failed) {
400
                        TRACE(1, "header segment damaged, trying backup");
401
                        first_failed = 1;
402
                        result = 0;      /* force read of next (backup) segment */
403
                }
404
        }
405
        if (result < 0 || header_segment >= ftape_last_segment.id) {
406
                TRACE(1, "no readable header segment found");
407
                TRACE_EXIT;
408
                return -EIO;
409
        }
410
        result = ftape_abort_operation();
411
        if (result < 0) {
412
                TRACE(1, "ftape_abort_operation failed");
413
                TRACE_EXIT;
414
                return -EIO;
415
        }
416
        if (GET4(address, 0) != 0xaa55aa55) {
417
                TRACE(1, "wrong signature in header segment");
418
                TRACE_EXIT;
419
                return -EIO;
420
        }
421
        header_segment_1 = GET2(address, 6);
422
        header_segment_2 = GET2(address, 8);
423
        TRACEx2(2, "header segments are %d and %d",
424
                header_segment_1, header_segment_2);
425
        used_header_segment = (first_failed) ? header_segment_2 : header_segment_1;
426
 
427
        /*    Verify tape parameters...
428
         *    QIC-40/80 spec:                 tape_parameters:
429
         *
430
         *    segments-per-track              segments_per_track
431
         *    tracks-per-cartridge            tracks_per_tape
432
         *    max-floppy-side                 (segments_per_track *
433
         *                                    tracks_per_tape - 1) /
434
         *                                    segments_per_head
435
         *    max-floppy-track                segments_per_head /
436
         *                                    segments_per_cylinder - 1
437
         *    max-floppy-sector               segments_per_cylinder *
438
         *                                    SECTORS_PER_SEGMENT
439
         */
440
        format_code = (format_type) * (address + 4);
441
        segments_per_track = GET2(address, 24);
442
        tracks_per_tape = *(address + 26);
443
        max_floppy_side = *(address + 27);
444
        max_floppy_track = *(address + 28);
445
        max_floppy_sector = *(address + 29);
446
        TRACEx6(4, "(fmt/spt/tpc/fhm/ftm/fsm) = %d/%d/%d/%d/%d/%d",
447
                format_code, segments_per_track, tracks_per_tape,
448
                max_floppy_side, max_floppy_track, max_floppy_sector);
449
        new_tape_len = tape_len;
450
        switch (format_code) {
451
        case fmt_425ft:
452
                new_tape_len = 425;
453
                break;
454
        case fmt_normal:
455
                if (tape_len == 0) {     /* otherwise 307 ft */
456
                        new_tape_len = 205;
457
                }
458
                break;
459
        case fmt_1100ft:
460
                new_tape_len = 1100;
461
                break;
462
        case fmt_wide:{
463
                        int segments_per_1000_inch = 1;         /* non-zero default for switch */
464
                        switch (qic_std) {
465
                        case QIC_TAPE_QIC40:
466
                                segments_per_1000_inch = 332;
467
                                break;
468
                        case QIC_TAPE_QIC80:
469
                                segments_per_1000_inch = 488;
470
                                break;
471
                        case QIC_TAPE_QIC3010:
472
                                segments_per_1000_inch = 730;
473
                                break;
474
                        case QIC_TAPE_QIC3020:
475
                                segments_per_1000_inch = 1430;
476
                                break;
477
                        }
478
                        new_tape_len = (1000 * segments_per_track +
479
                                        (segments_per_1000_inch - 1)) / segments_per_1000_inch;
480
                        break;
481
                }
482
        default:
483
                TRACE(1, "unknown tape format, please report !");
484
                TRACE_EXIT;
485
                return -EIO;
486
        }
487
        if (new_tape_len != tape_len) {
488
                tape_len = new_tape_len;
489
                TRACEx1(1, "calculated tape length is %d ft", tape_len);
490
                ftape_calc_timeouts();
491
        }
492
        if (segments_per_track == 0 && tracks_per_tape == 0 &&
493
            max_floppy_side == 0 && max_floppy_track == 0 &&
494
            max_floppy_sector == 0) {
495
                /*  QIC-40 Rev E and earlier has no values in the header.
496
                 */
497
                segments_per_track = 68;
498
                tracks_per_tape = 20;
499
                max_floppy_side = 1;
500
                max_floppy_track = 169;
501
                max_floppy_sector = 128;
502
        }
503
        /*  This test will compensate for the wrong parameter on tapes
504
         *  formatted by Conner software.
505
         */
506
        if (segments_per_track == 150 &&
507
            tracks_per_tape == 28 &&
508
            max_floppy_side == 7 &&
509
            max_floppy_track == 149 &&
510
            max_floppy_sector == 128) {
511
                TRACE(-1, "the famous CONNER bug: max_floppy_side off by one !");
512
                max_floppy_side = 6;
513
        }
514
        /*  This test will compensate for the wrong parameter on tapes
515
         *  formatted by Colorado Windows software.
516
         */
517
        if (segments_per_track == 150 &&
518
            tracks_per_tape == 28 &&
519
            max_floppy_side == 6 &&
520
            max_floppy_track == 150 &&
521
            max_floppy_sector == 128) {
522
                TRACE(-1, "the famous Colorado bug: max_floppy_track off by one !");
523
                max_floppy_track = 149;
524
        }
525
        segments_per_head = ((max_floppy_sector / SECTORS_PER_SEGMENT) *
526
                             (max_floppy_track + 1));
527
        /*
528
         *    Verify drive_configuration with tape parameters
529
         */
530
        if (segments_per_head == 0 || segments_per_cylinder == 0 ||
531
          ((segments_per_track * tracks_per_tape - 1) / segments_per_head
532
           != max_floppy_side) ||
533
            (segments_per_head / segments_per_cylinder - 1 != max_floppy_track) ||
534
        (segments_per_cylinder * SECTORS_PER_SEGMENT != max_floppy_sector)
535
#ifdef TESTING
536
            || (format_code == 4 && (max_floppy_track != 254 || max_floppy_sector != 128))
537
#endif
538
            ) {
539
                TRACE(1, "Tape parameters inconsistency, please report");
540
                TRACE_EXIT;
541
                return -EIO;
542
        }
543
        first_data_segment = GET2(address, 10);         /* first data segment */
544
        TRACEi(4, "first data segment:", first_data_segment);
545
        extract_bad_sector_map(address);
546
        /*  Find the highest segment id that allows still one full
547
         *  deblock_buffer to be written to tape.
548
         */
549
        ftape_last_segment.size = 0;
550
        for (i = segments_per_track * tracks_per_tape - 1; i >= 0; --i) {
551
                int space = SECTORS_PER_SEGMENT - 3 - count_ones(get_bad_sector_entry(i));
552
                if (space > 0) {
553
                        ftape_last_segment.size += space;       /* sectors free */
554
                        ftape_last_segment.free = (ftape_last_segment.size -
555
                                   sizeof(deblock_buffer) / SECTOR_SIZE);
556
                        if (ftape_last_segment.free >= 0) {
557
                                ftape_last_segment.id = i;
558
                                TRACEx2(4, "`last' segment is %d, %d Kb",
559
                                        ftape_last_segment.id, ftape_last_segment.size);
560
                                break;
561
                        }
562
                }
563
        }
564
        /* Copy the failed sector log into our local buffer.
565
         */
566
        if (!ftape_validate_label(&deblock_buffer[30])) {
567
                TRACE(-1, "This tape has no `Linux raw format' label,\n"
568
                      "***** Use `mt' to erase this tape if you want to use file marks !");
569
        } else {
570
                extract_file_marks(address);
571
        }
572
        ftape_reset_position();
573
        TRACE_EXIT;
574
        return 0;
575
}
576
 
577
int _ftape_read(char *buff, int req_len)
578
{
579
        TRACE_FUN(5, "_ftape_read");
580
        int result = 0;
581
        int cnt;
582
        int to_do = req_len;
583
        static int remaining;
584
        int bytes_read = 0;
585
 
586
        if (ftape_offline || !formatted || no_tape) {
587
                TRACEx3(-1, "offline = %d, formatted = %d, no_tape = %d",
588
                        ftape_offline, formatted, no_tape);
589
                result = -EIO;
590
        } else {
591
                history.used |= 1;
592
                if (first_data_segment == -1) {
593
                        result = read_header_segment(deblock_buffer);
594
                }
595
        }
596
        if (result < 0) {
597
                TRACE_EXIT;
598
                return result;
599
        }
600
        /*  As GNU tar doesn't accept partial read counts when the multiple
601
         *  volume flag is set, we make sure to return the requested amount
602
         *  of data. Except, of course, at the end of the tape or file mark.
603
         */
604
        while (to_do > 0) {      /* don't return with a partial count ! */
605
                /*  If we're reading the `last' segment(s) on tape, make sure we don't
606
                 *  get more than 29 Kb from it (As it only contains this much).
607
                 *  This works only for sequential access, so random access should
608
                 *  stay away from this `last' segment.
609
                 *  Note: ftape_seg_pos points to the next segment that will be
610
                 *        read, so it's one too high here!
611
                 */
612
                if (!eof_mark && ftape_seg_pos - 1 >= ftape_last_segment.id) {
613
                        TRACEi(5, "remaining of last segment:", remaining);
614
                        if (to_do > remaining) {
615
                                to_do = remaining;      /* fake a smaller request */
616
                                TRACE(5, "clipped request to remaining");
617
                        }
618
                }
619
                while (!eof_mark && buf_len_rd == 0) {
620
                        /*  When starting to read the `last' segment, set remaining
621
                         */
622
                        if (ftape_seg_pos == ftape_last_segment.id) {
623
                                remaining = sizeof(deblock_buffer);
624
                                TRACEi(5, "remaining set to:", remaining);
625
                        }
626
                        result = read_segment(ftape_seg_pos, deblock_buffer, &eof_mark, 1);
627
                        if (result < 0) {
628
                                if (result == -ENODATA) {
629
                                        /*  Unable to recover tape data, return error and skip bad spot.
630
                                         */
631
                                        ++ftape_seg_pos;
632
                                }
633
                                TRACEx1(4, "read_segment result: %d", result);
634
                                TRACE_EXIT;
635
                                return result;
636
                        }
637
                        /*  Allow escape from this loop on signal !
638
                         */
639
                        if (current->signal & _DONT_BLOCK) {
640
                                TRACE(2, "interrupted by non-blockable signal");
641
                                TRACE_EXIT;
642
                                return -EINTR;
643
                        }
644
                        buf_pos_rd = 0;
645
                        buf_len_rd = result;
646
                        ++ftape_seg_pos;
647
                }
648
                /*  Take as much as we can use
649
                 */
650
                cnt = (buf_len_rd < to_do) ? buf_len_rd : to_do;
651
                TRACEi(7, "nr bytes just read:", cnt);
652
                if (cnt > 0) {
653
                        result = verify_area(VERIFY_WRITE, buff, cnt);
654
                        if (result) {
655
                                TRACEx1(1, "verify_area failed, exitcode = %d", result);
656
                                TRACE_EXIT;
657
                                return -EIO;
658
                        }
659
                        memcpy_tofs(buff, deblock_buffer + buf_pos_rd, cnt);
660
                        buff += cnt;
661
                        to_do -= cnt;   /* what's left from req_len */
662
                        remaining -= cnt;       /* what remains on this tape */
663
                        bytes_read += cnt;      /* what we got so far */
664
                        buf_pos_rd += cnt;      /* index in buffer */
665
                        buf_len_rd -= cnt;      /* remaining bytes in buffer */
666
                }
667
                if (eof_mark && buf_len_rd == 0) {       /* nothing left */
668
                        TRACE(5, "partial count because of eof mark");
669
                        if (bytes_read == 0) {
670
                                eof_mark = 0;    /* no need for mark next read */
671
                        }
672
                        break;
673
                }
674
        }
675
        TRACE_EXIT;
676
        return bytes_read;
677
}

powered by: WebSVN 2.1.0

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