2 * Copyright (C) 1997 Claus-Justus Heine.
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)
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.
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.
19 * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-format.c,v $
20 * $Revision: 1.2.4.1 $
21 * $Date: 1997/11/14 16:05:39 $
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.
28 #include <linux/string.h>
29 #include <linux/errno.h>
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"
42 #define FT_FMT_SEGS_PER_BUF 50
44 #define FT_FMT_SEGS_PER_BUF (FT_BUFF_SIZE/(4*FT_SECTORS_PER_SEGMENT))
47 static spinlock_t ftape_format_lock
;
50 * first segment of the new buffer
52 static int switch_segment
;
55 * at most 256 segments fit into one 32 kb buffer. Even TR-1 cartridges have
56 * more than this many segments per track, so better be careful.
58 * buffer_struct *buff: buffer to store the formatting coordinates in
59 * int start: starting segment for this buffer.
60 * int spt: segments per track
62 * Note: segment ids are relative to the start of the track here.
64 static void setup_format_buffer(buffer_struct
*buff
, int start
, int spt
,
67 int to_do
= spt
- start
;
70 if (to_do
> FT_FMT_SEGS_PER_BUF
) {
71 to_do
= FT_FMT_SEGS_PER_BUF
;
73 buff
->ptr
= buff
->address
;
74 buff
->remaining
= to_do
* FT_SECTORS_PER_SEGMENT
; /* # sectors */
75 buff
->bytes
= buff
->remaining
* 4; /* need 4 bytes per sector */
77 buff
->segment_id
= start
;
78 buff
->next_segment
= start
+ to_do
;
79 if (buff
->next_segment
>= spt
) {
80 buff
->next_segment
= 0; /* 0 means: stop runner */
82 buff
->status
= waiting
; /* tells the isr that it can use
90 * start formatting a new track.
92 int ftape_format_track(const unsigned int track
, const __u8 gap3
)
95 buffer_struct
*tail
, *head
;
99 TRACE_CATCH(ftape_ready_wait(ftape_timeout
.pause
, &status
),);
101 if (!(status
& QIC_STATUS_AT_EOT
)) {
102 TRACE_CATCH(ftape_seek_to_eot(),);
105 if (!(status
& QIC_STATUS_AT_BOT
)) {
106 TRACE_CATCH(ftape_seek_to_bot(),);
109 ftape_abort_operation(); /* this sets ft_head = ft_tail = 0 */
110 ftape_set_state(formatting
);
113 "Formatting track %d, logical: from segment %d to %d",
114 track
, track
* ft_segments_per_track
,
115 (track
+ 1) * ft_segments_per_track
- 1);
118 * initialize the buffer switching protocol for this track
120 head
= ftape_get_buffer(ft_queue_head
); /* tape isn't running yet */
121 tail
= ftape_get_buffer(ft_queue_tail
); /* tape isn't running yet */
124 FT_SIGNAL_EXIT(_DONT_BLOCK
);
125 setup_format_buffer(tail
, switch_segment
,
126 ft_segments_per_track
, gap3
);
127 switch_segment
= tail
->next_segment
;
128 } while ((switch_segment
!= 0) &&
129 ((tail
= ftape_next_buffer(ft_queue_tail
)) != head
));
131 head
->status
= formatting
;
132 TRACE_CATCH(ftape_seek_head_to_track(track
),);
133 TRACE_CATCH(ftape_command(QIC_LOGICAL_FORWARD
),);
134 spin_lock_irqsave(&ftape_format_lock
, flags
);
135 TRACE_CATCH(fdc_setup_formatting(head
), restore_flags(flags
));
136 spin_unlock_irqrestore(&ftape_format_lock
, flags
);
140 /* return segment id of segment currently being formatted and do the
141 * buffer switching stuff.
143 int ftape_format_status(unsigned int *segment_id
)
145 buffer_struct
*tail
= ftape_get_buffer(ft_queue_tail
);
147 TRACE_FUN(ft_t_flow
);
149 while (switch_segment
!= 0 &&
150 ftape_get_buffer(ft_queue_head
) != tail
) {
151 FT_SIGNAL_EXIT(_DONT_BLOCK
);
152 /* need more buffers, first wait for empty buffer
154 TRACE_CATCH(ftape_wait_segment(formatting
),);
155 /* don't worry for gap3. If we ever hit this piece of code,
156 * then all buffer already have the correct gap3 set!
158 setup_format_buffer(tail
, switch_segment
,
159 ft_segments_per_track
, tail
->gap3
);
160 switch_segment
= tail
->next_segment
;
161 if (switch_segment
!= 0) {
162 tail
= ftape_next_buffer(ft_queue_tail
);
165 /* should runner stop ?
167 if (ft_runner_status
== aborting
|| ft_runner_status
== do_abort
) {
168 buffer_struct
*head
= ftape_get_buffer(ft_queue_head
);
169 TRACE(ft_t_warn
, "Error formatting segment %d",
170 ftape_get_buffer(ft_queue_head
)->segment_id
);
171 (void)ftape_abort_operation();
172 TRACE_EXIT (head
->status
!= error
) ? -EAGAIN
: -EIO
;
175 * don't care if the timer expires, this is just kind of a
176 * "select" operation that lets the calling process sleep
177 * until something has happened
179 if (fdc_interrupt_wait(5 * FT_SECOND
) < 0) {
180 TRACE(ft_t_noise
, "End of track %d at segment %d",
182 ftape_get_buffer(ft_queue_head
)->segment_id
);
183 result
= 1; /* end of track, unlock module */
188 * the calling process should use the seg id to determine
189 * which parts of the dma buffers can be safely overwritten
192 *segment_id
= ftape_get_buffer(ft_queue_head
)->segment_id
;
194 * Internally we start counting segment ids from the start of
195 * each track when formatting, but externally we keep them
196 * relative to the start of the tape:
198 *segment_id
+= ft_location
.track
* ft_segments_per_track
;
203 * The segment id is relative to the start of the tape
205 int ftape_verify_segment(const unsigned int segment_id
, SectorMap
*bsm
)
209 TRACE_FUN(ft_t_flow
);
211 TRACE(ft_t_noise
, "Verifying segment %d", segment_id
);
213 if (ft_driver_state
!= verifying
) {
214 TRACE(ft_t_noise
, "calling ftape_abort_operation");
215 if (ftape_abort_operation() < 0) {
216 TRACE(ft_t_err
, "ftape_abort_operation failed");
221 ftape_set_state(verifying
);
225 * Allow escape from this loop on signal
227 FT_SIGNAL_EXIT(_DONT_BLOCK
);
229 * Search all full buffers for the first matching the
230 * wanted segment. Clear other buffers on the fly.
232 tail
= ftape_get_buffer(ft_queue_tail
);
233 while (!verify_done
&& tail
->status
== done
) {
235 * Allow escape from this loop on signal !
237 FT_SIGNAL_EXIT(_DONT_BLOCK
);
238 if (tail
->segment_id
== segment_id
) {
239 /* If out buffer is already full,
240 * return its contents.
242 TRACE(ft_t_flow
, "found segment in cache: %d",
244 if ((tail
->soft_error_map
|
245 tail
->hard_error_map
) != 0) {
246 TRACE(ft_t_info
,"bsm[%d] = 0x%08lx",
249 (tail
->soft_error_map
|
250 tail
->hard_error_map
));
251 *bsm
= (tail
->soft_error_map
|
252 tail
->hard_error_map
);
256 TRACE(ft_t_flow
,"zapping segment in cache: %d",
259 tail
->status
= waiting
;
260 tail
= ftape_next_buffer(ft_queue_tail
);
262 if (!verify_done
&& tail
->status
== verifying
) {
263 if (tail
->segment_id
== segment_id
) {
264 switch(ftape_wait_segment(verifying
)) {
268 TRACE_ABORT(-EINTR
, ft_t_warn
,
270 "non-blockable signal");
273 ftape_abort_operation();
274 ftape_set_state(verifying
);
276 TRACE_ABORT(-EIO
, ft_t_warn
,
277 "wait_segment failed");
280 /* We're reading the wrong segment,
283 TRACE(ft_t_noise
, "verifying wrong segment");
284 ftape_abort_operation();
285 ftape_set_state(verifying
);
288 /* should runner stop ?
290 if (ft_runner_status
== aborting
) {
291 buffer_struct
*head
= ftape_get_buffer(ft_queue_head
);
292 if (head
->status
== error
||
293 head
->status
== verifying
) {
294 /* no data or overrun error */
295 head
->status
= waiting
;
297 TRACE_CATCH(ftape_dumb_stop(),);
299 /* If just passed last segment on tape: wait
300 * for BOT or EOT mark. Sets ft_runner_status to
301 * idle if at lEOT and successful
303 TRACE_CATCH(ftape_handle_logical_eot(),);
308 /* Now at least one buffer is idle!
309 * Restart runner & tape if needed.
311 /* We could optimize the following a little bit. We know that
312 * the bad sector map is empty.
314 tail
= ftape_get_buffer(ft_queue_tail
);
315 if (tail
->status
== waiting
) {
316 buffer_struct
*head
= ftape_get_buffer(ft_queue_head
);
318 ftape_setup_new_segment(head
, segment_id
, -1);
319 ftape_calc_next_cluster(head
);
320 if (ft_runner_status
== idle
) {
321 result
= ftape_start_tape(segment_id
,
322 head
->sector_offset
);
328 TRACE_ABORT(result
, ft_t_err
, "Error: "
329 "segment %d unreachable",
333 *bsm
= EMPTY_SEGMENT
;
338 head
->status
= verifying
;
339 fdc_setup_read_write(head
, FDC_VERIFY
);