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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [ftape/] [lowlevel/] [ftape-format.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * Copyright (C) 1997 Claus-Justus Heine.
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
 *
19
 * $Source: /home/marcus/revision_ctrl_test/oc_cvs/cvs/or1k/linux/linux-2.4/drivers/char/ftape/lowlevel/ftape-format.c,v $
20
 * $Revision: 1.1.1.1 $
21
 * $Date: 2004-04-15 02:02:39 $
22
 *
23
 *      This file contains the code to support formatting of floppy
24
 *      tape cartridges with the QIC-40/80/3010/3020 floppy-tape
25
 *      driver "ftape" for Linux.
26
 */
27
 
28
#include <linux/string.h>
29
#include <linux/errno.h>
30
 
31
#include <linux/ftape.h>
32
#include <linux/qic117.h>
33
#include "../lowlevel/ftape-tracing.h"
34
#include "../lowlevel/ftape-io.h"
35
#include "../lowlevel/ftape-ctl.h"
36
#include "../lowlevel/ftape-rw.h"
37
#include "../lowlevel/ftape-ecc.h"
38
#include "../lowlevel/ftape-bsm.h"
39
#include "../lowlevel/ftape-format.h"
40
 
41
#if defined(TESTING)
42
#define FT_FMT_SEGS_PER_BUF 50
43
#else
44
#define FT_FMT_SEGS_PER_BUF (FT_BUFF_SIZE/(4*FT_SECTORS_PER_SEGMENT))
45
#endif
46
 
47
/*
48
 *  first segment of the new buffer
49
 */
50
static int switch_segment;
51
 
52
/*
53
 *  at most 256 segments fit into one 32 kb buffer.  Even TR-1 cartridges have
54
 *  more than this many segments per track, so better be careful.
55
 *
56
 *  buffer_struct *buff: buffer to store the formatting coordinates in
57
 *  int  start: starting segment for this buffer.
58
 *  int    spt: segments per track
59
 *
60
 *  Note: segment ids are relative to the start of the track here.
61
 */
62
static void setup_format_buffer(buffer_struct *buff, int start, int spt,
63
                                __u8 gap3)
64
{
65
        int to_do = spt - start;
66
        TRACE_FUN(ft_t_flow);
67
 
68
        if (to_do > FT_FMT_SEGS_PER_BUF) {
69
                to_do = FT_FMT_SEGS_PER_BUF;
70
        }
71
        buff->ptr          = buff->address;
72
        buff->remaining    = to_do * FT_SECTORS_PER_SEGMENT; /* # sectors */
73
        buff->bytes        = buff->remaining * 4; /* need 4 bytes per sector */
74
        buff->gap3         = gap3;
75
        buff->segment_id   = start;
76
        buff->next_segment = start + to_do;
77
        if (buff->next_segment >= spt) {
78
                buff->next_segment = 0; /* 0 means: stop runner */
79
        }
80
        buff->status       = waiting; /* tells the isr that it can use
81
                                       * this buffer
82
                                       */
83
        TRACE_EXIT;
84
}
85
 
86
 
87
/*
88
 *  start formatting a new track.
89
 */
90
int ftape_format_track(const unsigned int track, const __u8 gap3)
91
{
92
        unsigned long flags;
93
        buffer_struct *tail, *head;
94
        int status;
95
        TRACE_FUN(ft_t_flow);
96
 
97
        TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),);
98
        if (track & 1) {
99
                if (!(status & QIC_STATUS_AT_EOT)) {
100
                        TRACE_CATCH(ftape_seek_to_eot(),);
101
                }
102
        } else {
103
                if (!(status & QIC_STATUS_AT_BOT)) {
104
                        TRACE_CATCH(ftape_seek_to_bot(),);
105
                }
106
        }
107
        ftape_abort_operation(); /* this sets ft_head = ft_tail = 0 */
108
        ftape_set_state(formatting);
109
 
110
        TRACE(ft_t_noise,
111
              "Formatting track %d, logical: from segment %d to %d",
112
              track, track * ft_segments_per_track,
113
              (track + 1) * ft_segments_per_track - 1);
114
 
115
        /*
116
         *  initialize the buffer switching protocol for this track
117
         */
118
        head = ftape_get_buffer(ft_queue_head); /* tape isn't running yet */
119
        tail = ftape_get_buffer(ft_queue_tail); /* tape isn't running yet */
120
        switch_segment = 0;
121
        do {
122
                FT_SIGNAL_EXIT(_DONT_BLOCK);
123
                setup_format_buffer(tail, switch_segment,
124
                                    ft_segments_per_track, gap3);
125
                switch_segment = tail->next_segment;
126
        } while ((switch_segment != 0) &&
127
                 ((tail = ftape_next_buffer(ft_queue_tail)) != head));
128
        /* go */
129
        head->status = formatting;
130
        TRACE_CATCH(ftape_seek_head_to_track(track),);
131
        TRACE_CATCH(ftape_command(QIC_LOGICAL_FORWARD),);
132
        save_flags(flags); cli();
133
        TRACE_CATCH(fdc_setup_formatting(head), restore_flags(flags));
134
        restore_flags(flags);
135
        TRACE_EXIT 0;
136
}
137
 
138
/*   return segment id of segment currently being formatted and do the
139
 *   buffer switching stuff.
140
 */
141
int ftape_format_status(unsigned int *segment_id)
142
{
143
        buffer_struct *tail = ftape_get_buffer(ft_queue_tail);
144
        int result;
145
        TRACE_FUN(ft_t_flow);
146
 
147
        while (switch_segment != 0 &&
148
               ftape_get_buffer(ft_queue_head) != tail) {
149
                FT_SIGNAL_EXIT(_DONT_BLOCK);
150
                /*  need more buffers, first wait for empty buffer
151
                 */
152
                TRACE_CATCH(ftape_wait_segment(formatting),);
153
                /*  don't worry for gap3. If we ever hit this piece of code,
154
                 *  then all buffer already have the correct gap3 set!
155
                 */
156
                setup_format_buffer(tail, switch_segment,
157
                                    ft_segments_per_track, tail->gap3);
158
                switch_segment = tail->next_segment;
159
                if (switch_segment != 0) {
160
                        tail = ftape_next_buffer(ft_queue_tail);
161
                }
162
        }
163
        /*    should runner stop ?
164
         */
165
        if (ft_runner_status == aborting || ft_runner_status == do_abort) {
166
                buffer_struct *head = ftape_get_buffer(ft_queue_head);
167
                TRACE(ft_t_warn, "Error formatting segment %d",
168
                      ftape_get_buffer(ft_queue_head)->segment_id);
169
                (void)ftape_abort_operation();
170
                TRACE_EXIT (head->status != error) ? -EAGAIN : -EIO;
171
        }
172
        /*
173
         *  don't care if the timer expires, this is just kind of a
174
         *  "select" operation that lets the calling process sleep
175
         *  until something has happened
176
         */
177
        if (fdc_interrupt_wait(5 * FT_SECOND) < 0) {
178
                TRACE(ft_t_noise, "End of track %d at segment %d",
179
                      ft_location.track,
180
                      ftape_get_buffer(ft_queue_head)->segment_id);
181
                result = 1;  /* end of track, unlock module */
182
        } else {
183
                result = 0;
184
        }
185
        /*
186
         *  the calling process should use the seg id to determine
187
         *  which parts of the dma buffers can be safely overwritten
188
         *  with new data.
189
         */
190
        *segment_id = ftape_get_buffer(ft_queue_head)->segment_id;
191
        /*
192
         *  Internally we start counting segment ids from the start of
193
         *  each track when formatting, but externally we keep them
194
         *  relative to the start of the tape:
195
         */
196
        *segment_id += ft_location.track * ft_segments_per_track;
197
        TRACE_EXIT result;
198
}
199
 
200
/*
201
 *  The segment id is relative to the start of the tape
202
 */
203
int ftape_verify_segment(const unsigned int segment_id, SectorMap *bsm)
204
{
205
        int result;
206
        int verify_done = 0;
207
        TRACE_FUN(ft_t_flow);
208
 
209
        TRACE(ft_t_noise, "Verifying segment %d", segment_id);
210
 
211
        if (ft_driver_state != verifying) {
212
                TRACE(ft_t_noise, "calling ftape_abort_operation");
213
                if (ftape_abort_operation() < 0) {
214
                        TRACE(ft_t_err, "ftape_abort_operation failed");
215
                        TRACE_EXIT -EIO;
216
                }
217
        }
218
        *bsm = 0x00000000;
219
        ftape_set_state(verifying);
220
        for (;;) {
221
                buffer_struct *tail;
222
                /*
223
                 *  Allow escape from this loop on signal
224
                 */
225
                FT_SIGNAL_EXIT(_DONT_BLOCK);
226
                /*
227
                 *  Search all full buffers for the first matching the
228
                 *  wanted segment.  Clear other buffers on the fly.
229
                 */
230
                tail = ftape_get_buffer(ft_queue_tail);
231
                while (!verify_done && tail->status == done) {
232
                        /*
233
                         *  Allow escape from this loop on signal !
234
                         */
235
                        FT_SIGNAL_EXIT(_DONT_BLOCK);
236
                        if (tail->segment_id == segment_id) {
237
                                /*  If out buffer is already full,
238
                                 *  return its contents.
239
                                 */
240
                                TRACE(ft_t_flow, "found segment in cache: %d",
241
                                      segment_id);
242
                                if ((tail->soft_error_map |
243
                                     tail->hard_error_map) != 0) {
244
                                        TRACE(ft_t_info,"bsm[%d] = 0x%08lx",
245
                                              segment_id,
246
                                              (unsigned long)
247
                                              (tail->soft_error_map |
248
                                              tail->hard_error_map));
249
                                        *bsm = (tail->soft_error_map |
250
                                                tail->hard_error_map);
251
                                }
252
                                verify_done = 1;
253
                        } else {
254
                                TRACE(ft_t_flow,"zapping segment in cache: %d",
255
                                      tail->segment_id);
256
                        }
257
                        tail->status = waiting;
258
                        tail = ftape_next_buffer(ft_queue_tail);
259
                }
260
                if (!verify_done && tail->status == verifying) {
261
                        if (tail->segment_id == segment_id) {
262
                                switch(ftape_wait_segment(verifying)) {
263
                                case 0:
264
                                        break;
265
                                case -EINTR:
266
                                        TRACE_ABORT(-EINTR, ft_t_warn,
267
                                                    "interrupted by "
268
                                                    "non-blockable signal");
269
                                        break;
270
                                default:
271
                                        ftape_abort_operation();
272
                                        ftape_set_state(verifying);
273
                                        /* be picky */
274
                                        TRACE_ABORT(-EIO, ft_t_warn,
275
                                                    "wait_segment failed");
276
                                }
277
                        } else {
278
                                /*  We're reading the wrong segment,
279
                                 *  stop runner.
280
                                 */
281
                                TRACE(ft_t_noise, "verifying wrong segment");
282
                                ftape_abort_operation();
283
                                ftape_set_state(verifying);
284
                        }
285
                }
286
                /*    should runner stop ?
287
                 */
288
                if (ft_runner_status == aborting) {
289
                        buffer_struct *head = ftape_get_buffer(ft_queue_head);
290
                        if (head->status == error ||
291
                            head->status == verifying) {
292
                                /* no data or overrun error */
293
                                head->status = waiting;
294
                        }
295
                        TRACE_CATCH(ftape_dumb_stop(),);
296
                } else {
297
                        /*  If just passed last segment on tape: wait
298
                         *  for BOT or EOT mark. Sets ft_runner_status to
299
                         *  idle if at lEOT and successful
300
                         */
301
                        TRACE_CATCH(ftape_handle_logical_eot(),);
302
                }
303
                if (verify_done) {
304
                        TRACE_EXIT 0;
305
                }
306
                /*    Now at least one buffer is idle!
307
                 *    Restart runner & tape if needed.
308
                 */
309
                /*  We could optimize the following a little bit. We know that
310
                 *  the bad sector map is empty.
311
                 */
312
                tail = ftape_get_buffer(ft_queue_tail);
313
                if (tail->status == waiting) {
314
                        buffer_struct *head = ftape_get_buffer(ft_queue_head);
315
 
316
                        ftape_setup_new_segment(head, segment_id, -1);
317
                        ftape_calc_next_cluster(head);
318
                        if (ft_runner_status == idle) {
319
                                result = ftape_start_tape(segment_id,
320
                                                          head->sector_offset);
321
                                switch(result) {
322
                                case 0:
323
                                        break;
324
                                case -ETIME:
325
                                case -EINTR:
326
                                        TRACE_ABORT(result, ft_t_err, "Error: "
327
                                                    "segment %d unreachable",
328
                                                    segment_id);
329
                                        break;
330
                                default:
331
                                        *bsm = EMPTY_SEGMENT;
332
                                        TRACE_EXIT 0;
333
                                        break;
334
                                }
335
                        }
336
                        head->status = verifying;
337
                        fdc_setup_read_write(head, FDC_VERIFY);
338
                }
339
        }
340
        /* not reached */
341
        TRACE_EXIT -EIO;
342
}

powered by: WebSVN 2.1.0

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