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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      Copyright (C) 1993-1996 Bas Laarhoven,
3
 *                (C) 1996      Kai Harrekilde-Petersen,
4
 *                (C) 1997      Claus-Justus Heine.
5
 
6
 This program is free software; you can redistribute it and/or modify
7
 it under the terms of the GNU General Public License as published by
8
 the Free Software Foundation; either version 2, or (at your option)
9
 any later version.
10
 
11
 This program is distributed in the hope that it will be useful,
12
 but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 GNU General Public License for more details.
15
 
16
 You should have received a copy of the GNU General Public License
17
 along with this program; see the file COPYING.  If not, write to
18
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19
 
20
 *
21
 * $Source: /home/marcus/revision_ctrl_test/oc_cvs/cvs/or1k/linux/linux-2.4/drivers/char/ftape/lowlevel/ftape-io.c,v $
22
 * $Revision: 1.1.1.1 $
23
 * $Date: 2004-04-15 02:02:40 $
24
 *
25
 *      This file contains the general control functions for the
26
 *      QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux.
27
 */
28
 
29
#include <linux/errno.h>
30
#include <linux/sched.h>
31
#include <linux/mm.h>
32
#include <asm/segment.h>
33
#include <asm/system.h>
34
#include <linux/ioctl.h>
35
#include <linux/mtio.h>
36
 
37
#include <linux/ftape.h>
38
#include <linux/qic117.h>
39
#include "../lowlevel/ftape-tracing.h"
40
#include "../lowlevel/fdc-io.h"
41
#include "../lowlevel/ftape-io.h"
42
#include "../lowlevel/ftape-ctl.h"
43
#include "../lowlevel/ftape-rw.h"
44
#include "../lowlevel/ftape-write.h"
45
#include "../lowlevel/ftape-read.h"
46
#include "../lowlevel/ftape-init.h"
47
#include "../lowlevel/ftape-calibr.h"
48
 
49
/*      Global vars.
50
 */
51
/* NOTE: sectors start numbering at 1, all others at 0 ! */
52
ft_timeout_table ftape_timeout;
53
unsigned int ftape_tape_len;
54
volatile qic117_cmd_t ftape_current_command;
55
const struct qic117_command_table qic117_cmds[] = QIC117_COMMANDS;
56
int ftape_might_be_off_track;
57
 
58
/*      Local vars.
59
 */
60
static int diagnostic_mode;
61
static unsigned int ftape_udelay_count;
62
static unsigned int ftape_udelay_time;
63
 
64
void ftape_udelay(unsigned int usecs)
65
{
66
        volatile int count = (ftape_udelay_count * usecs +
67
                              ftape_udelay_count - 1) / ftape_udelay_time;
68
        volatile int i;
69
 
70
        while (count-- > 0) {
71
                for (i = 0; i < 20; ++i);
72
        }
73
}
74
 
75
void ftape_udelay_calibrate(void)
76
{
77
        ftape_calibrate("ftape_udelay",
78
                        ftape_udelay, &ftape_udelay_count, &ftape_udelay_time);
79
}
80
 
81
/*      Delay (msec) routine.
82
 */
83
void ftape_sleep(unsigned int time)
84
{
85
        TRACE_FUN(ft_t_any);
86
 
87
        time *= 1000;   /* msecs -> usecs */
88
        if (time < FT_USPT) {
89
                /*  Time too small for scheduler, do a busy wait ! */
90
                ftape_udelay(time);
91
        } else {
92
                long timeout;
93
                unsigned long flags;
94
                unsigned int ticks = (time + FT_USPT - 1) / FT_USPT;
95
 
96
                TRACE(ft_t_any, "%d msec, %d ticks", time/1000, ticks);
97
                timeout = ticks;
98
                save_flags(flags);
99
                sti();
100
                set_current_state(TASK_INTERRUPTIBLE);
101
                do {
102
                        /*  Mmm. Isn't current->blocked == 0xffffffff ?
103
                         */
104
                        if (signal_pending(current)) {
105
                                TRACE(ft_t_err,
106
                                      "awoken by non-blocked signal :-(");
107
                                break;  /* exit on signal */
108
                        }
109
                        while (current->state != TASK_RUNNING) {
110
                                timeout = schedule_timeout(timeout);
111
                        }
112
                } while (timeout);
113
                restore_flags(flags);
114
        }
115
        TRACE_EXIT;
116
}
117
 
118
/*  send a command or parameter to the drive
119
 *  Generates # of step pulses.
120
 */
121
static inline int ft_send_to_drive(int arg)
122
{
123
        /*  Always wait for a command_timeout period to separate
124
         *  individuals commands and/or parameters.
125
         */
126
        ftape_sleep(3 * FT_MILLISECOND);
127
        /*  Keep cylinder nr within range, step towards home if possible.
128
         */
129
        if (ftape_current_cylinder >= arg) {
130
                return fdc_seek(ftape_current_cylinder - arg);
131
        } else {
132
                return fdc_seek(ftape_current_cylinder + arg);
133
        }
134
}
135
 
136
/* forward */ int ftape_report_raw_drive_status(int *status);
137
 
138
static int ft_check_cmd_restrictions(qic117_cmd_t command)
139
{
140
        int status = -1;
141
        TRACE_FUN(ft_t_any);
142
 
143
        TRACE(ft_t_flow, "%s", qic117_cmds[command].name);
144
        /* A new motion command during an uninterruptible (motion)
145
         *  command requires a ready status before the new command can
146
         *  be issued. Otherwise a new motion command needs to be
147
         *  checked against required status.
148
         */
149
        if (qic117_cmds[command].cmd_type == motion &&
150
            qic117_cmds[ftape_current_command].non_intr) {
151
                ftape_report_raw_drive_status(&status);
152
                if ((status & QIC_STATUS_READY) == 0) {
153
                        TRACE(ft_t_noise,
154
                              "motion cmd (%d) during non-intr cmd (%d)",
155
                              command, ftape_current_command);
156
                        TRACE(ft_t_noise, "waiting until drive gets ready");
157
                        ftape_ready_wait(ftape_timeout.seek,
158
                                         &status);
159
                }
160
        }
161
        if (qic117_cmds[command].mask != 0) {
162
                __u8 difference;
163
                /*  Some commands do require a certain status:
164
                 */
165
                if (status == -1) {     /* not yet set */
166
                        ftape_report_raw_drive_status(&status);
167
                }
168
                difference = ((status ^ qic117_cmds[command].state) &
169
                              qic117_cmds[command].mask);
170
                /*  Wait until the drive gets
171
                 *  ready. This may last forever if
172
                 *  the drive never gets ready...
173
                 */
174
                while ((difference & QIC_STATUS_READY) != 0) {
175
                        TRACE(ft_t_noise, "command %d issued while not ready",
176
                              command);
177
                        TRACE(ft_t_noise, "waiting until drive gets ready");
178
                        if (ftape_ready_wait(ftape_timeout.seek,
179
                                             &status) == -EINTR) {
180
                                /*  Bail out on signal !
181
                                 */
182
                                TRACE_ABORT(-EINTR, ft_t_warn,
183
                                      "interrupted by non-blockable signal");
184
                        }
185
                        difference = ((status ^ qic117_cmds[command].state) &
186
                                      qic117_cmds[command].mask);
187
                }
188
                while ((difference & QIC_STATUS_ERROR) != 0) {
189
                        int err;
190
                        qic117_cmd_t cmd;
191
 
192
                        TRACE(ft_t_noise,
193
                              "command %d issued while error pending",
194
                              command);
195
                        TRACE(ft_t_noise, "clearing error status");
196
                        ftape_report_error(&err, &cmd, 1);
197
                        ftape_report_raw_drive_status(&status);
198
                        difference = ((status ^ qic117_cmds[command].state) &
199
                                      qic117_cmds[command].mask);
200
                        if ((difference & QIC_STATUS_ERROR) != 0) {
201
                                /*  Bail out on fatal signal !
202
                                 */
203
                                FT_SIGNAL_EXIT(_NEVER_BLOCK);
204
                        }
205
                }
206
                if (difference) {
207
                        /*  Any remaining difference can't be solved
208
                         *  here.
209
                         */
210
                        if (difference & (QIC_STATUS_CARTRIDGE_PRESENT |
211
                                          QIC_STATUS_NEW_CARTRIDGE |
212
                                          QIC_STATUS_REFERENCED)) {
213
                                TRACE(ft_t_warn,
214
                                      "Fatal: tape removed or reinserted !");
215
                                ft_failure = 1;
216
                        } else {
217
                                TRACE(ft_t_err, "wrong state: 0x%02x should be: 0x%02x",
218
                                      status & qic117_cmds[command].mask,
219
                                      qic117_cmds[command].state);
220
                        }
221
                        TRACE_EXIT -EIO;
222
                }
223
                if (~status & QIC_STATUS_READY & qic117_cmds[command].mask) {
224
                        TRACE_ABORT(-EBUSY, ft_t_err, "Bad: still busy!");
225
                }
226
        }
227
        TRACE_EXIT 0;
228
}
229
 
230
/*      Issue a tape command:
231
 */
232
int ftape_command(qic117_cmd_t command)
233
{
234
        int result = 0;
235
        static int level;
236
        TRACE_FUN(ft_t_any);
237
 
238
        if ((unsigned int)command > NR_ITEMS(qic117_cmds)) {
239
                /*  This is a bug we'll want to know about too.
240
                 */
241
                TRACE_ABORT(-EIO, ft_t_bug, "bug - bad command: %d", command);
242
        }
243
        if (++level > 5) { /*  This is a bug we'll want to know about. */
244
                --level;
245
                TRACE_ABORT(-EIO, ft_t_bug, "bug - recursion for command: %d",
246
                            command);
247
        }
248
        /*  disable logging and restriction check for some commands,
249
         *  check all other commands that have a prescribed starting
250
         *  status.
251
         */
252
        if (diagnostic_mode) {
253
                TRACE(ft_t_flow, "diagnostic command %d", command);
254
        } else if (command == QIC_REPORT_DRIVE_STATUS ||
255
                   command == QIC_REPORT_NEXT_BIT) {
256
                TRACE(ft_t_any, "%s", qic117_cmds[command].name);
257
        } else {
258
                TRACE_CATCH(ft_check_cmd_restrictions(command), --level);
259
        }
260
        /*  Now all conditions are met or result was < 0.
261
         */
262
        result = ft_send_to_drive((unsigned int)command);
263
        if (qic117_cmds[command].cmd_type == motion &&
264
            command != QIC_LOGICAL_FORWARD && command != QIC_STOP_TAPE) {
265
                ft_location.known = 0;
266
        }
267
        ftape_current_command = command;
268
        --level;
269
        TRACE_EXIT result;
270
}
271
 
272
/*      Send a tape command parameter:
273
 *      Generates command # of step pulses.
274
 *      Skips tape-status call !
275
 */
276
int ftape_parameter(unsigned int parameter)
277
{
278
        TRACE_FUN(ft_t_any);
279
 
280
        TRACE(ft_t_flow, "called with parameter = %d", parameter);
281
        TRACE_EXIT ft_send_to_drive(parameter + 2);
282
}
283
 
284
/*      Wait for the drive to get ready.
285
 *      timeout time in milli-seconds
286
 *      Returned status is valid if result != -EIO
287
 *
288
 *      Should we allow to be killed by SIGINT?  (^C)
289
 *      Would be nice at least for large timeouts.
290
 */
291
int ftape_ready_wait(unsigned int timeout, int *status)
292
{
293
        unsigned long t0;
294
        unsigned int poll_delay;
295
        int signal_retries;
296
        TRACE_FUN(ft_t_any);
297
 
298
        /*  the following ** REALLY ** reduces the system load when
299
         *  e.g. one simply rewinds or retensions. The tape is slow
300
         *  anyway. It is really not necessary to detect error
301
         *  conditions with 1/10 seconds granularity
302
         *
303
         *  On my AMD 133MHZ 486: 100 ms: 23% system load
304
         *                        1  sec:  5%
305
         *                        5  sec:  0.6%, yeah
306
         */
307
        if (timeout <= FT_SECOND) {
308
                poll_delay = 100 * FT_MILLISECOND;
309
                signal_retries = 20; /* two seconds */
310
        } else if (timeout < 20 * FT_SECOND) {
311
                TRACE(ft_t_flow, "setting poll delay to 1 second");
312
                poll_delay = FT_SECOND;
313
                signal_retries = 2; /* two seconds */
314
        } else {
315
                TRACE(ft_t_flow, "setting poll delay to 5 seconds");
316
                poll_delay = 5 * FT_SECOND;
317
                signal_retries = 1; /* five seconds */
318
        }
319
        for (;;) {
320
                t0 = jiffies;
321
                TRACE_CATCH(ftape_report_raw_drive_status(status),);
322
                if (*status & QIC_STATUS_READY) {
323
                        TRACE_EXIT 0;
324
                }
325
                if (!signal_retries--) {
326
                        FT_SIGNAL_EXIT(_NEVER_BLOCK);
327
                }
328
                if ((int)timeout >= 0) {
329
                        /* this will fail when jiffies wraps around about
330
                         * once every year :-)
331
                         */
332
                        timeout -= ((jiffies - t0) * FT_SECOND) / HZ;
333
                        if (timeout <= 0) {
334
                                TRACE_ABORT(-ETIME, ft_t_err, "timeout");
335
                        }
336
                        ftape_sleep(poll_delay);
337
                        timeout -= poll_delay;
338
                } else {
339
                        ftape_sleep(poll_delay);
340
                }
341
        }
342
        TRACE_EXIT -ETIME;
343
}
344
 
345
/*      Issue command and wait up to timeout milli seconds for drive ready
346
 */
347
int ftape_command_wait(qic117_cmd_t command, unsigned int timeout, int *status)
348
{
349
        int result;
350
 
351
        /* Drive should be ready, issue command
352
         */
353
        result = ftape_command(command);
354
        if (result >= 0) {
355
                result = ftape_ready_wait(timeout, status);
356
        }
357
        return result;
358
}
359
 
360
int ftape_parameter_wait(unsigned int parm, unsigned int timeout, int *status)
361
{
362
        int result;
363
 
364
        /* Drive should be ready, issue command
365
         */
366
        result = ftape_parameter(parm);
367
        if (result >= 0) {
368
                result = ftape_ready_wait(timeout, status);
369
        }
370
        return result;
371
}
372
 
373
/*--------------------------------------------------------------------------
374
 *      Report operations
375
 */
376
 
377
/* Query the drive about its status.  The command is sent and
378
   result_length bits of status are returned (2 extra bits are read
379
   for start and stop). */
380
 
381
int ftape_report_operation(int *status,
382
                           qic117_cmd_t command,
383
                           int result_length)
384
{
385
        int i, st3;
386
        unsigned int t0;
387
        unsigned int dt;
388
        TRACE_FUN(ft_t_any);
389
 
390
        TRACE_CATCH(ftape_command(command),);
391
        t0 = ftape_timestamp();
392
        i = 0;
393
        do {
394
                ++i;
395
                ftape_sleep(3 * FT_MILLISECOND);        /* see remark below */
396
                TRACE_CATCH(fdc_sense_drive_status(&st3),);
397
                dt = ftape_timediff(t0, ftape_timestamp());
398
                /*  Ack should be asserted within Ttimout + Tack = 6 msec.
399
                 *  Looks like some drives fail to do this so extend this
400
                 *  period to 300 msec.
401
                 */
402
        } while (!(st3 & ST3_TRACK_0) && dt < 300000);
403
        if (!(st3 & ST3_TRACK_0)) {
404
                TRACE(ft_t_err,
405
                      "No acknowledge after %u msec. (%i iter)", dt / 1000, i);
406
                TRACE_ABORT(-EIO, ft_t_err, "timeout on Acknowledge");
407
        }
408
        /*  dt may be larger than expected because of other tasks
409
         *  scheduled while we were sleeping.
410
         */
411
        if (i > 1 && dt > 6000) {
412
                TRACE(ft_t_err, "Acknowledge after %u msec. (%i iter)",
413
                      dt / 1000, i);
414
        }
415
        *status = 0;
416
        for (i = 0; i < result_length + 1; i++) {
417
                TRACE_CATCH(ftape_command(QIC_REPORT_NEXT_BIT),);
418
                TRACE_CATCH(fdc_sense_drive_status(&st3),);
419
                if (i < result_length) {
420
                        *status |= ((st3 & ST3_TRACK_0) ? 1 : 0) << i;
421
                } else if ((st3 & ST3_TRACK_0) == 0) {
422
                        TRACE_ABORT(-EIO, ft_t_err, "missing status stop bit");
423
                }
424
        }
425
        /* this command will put track zero and index back into normal state */
426
        (void)ftape_command(QIC_REPORT_NEXT_BIT);
427
        TRACE_EXIT 0;
428
}
429
 
430
/* Report the current drive status. */
431
 
432
int ftape_report_raw_drive_status(int *status)
433
{
434
        int result;
435
        int count = 0;
436
        TRACE_FUN(ft_t_any);
437
 
438
        do {
439
                result = ftape_report_operation(status,
440
                                                QIC_REPORT_DRIVE_STATUS, 8);
441
        } while (result < 0 && ++count <= 3);
442
        if (result < 0) {
443
                TRACE_ABORT(-EIO, ft_t_err,
444
                            "report_operation failed after %d trials", count);
445
        }
446
        if ((*status & 0xff) == 0xff) {
447
                TRACE_ABORT(-EIO, ft_t_err,
448
                            "impossible drive status 0xff");
449
        }
450
        if (*status & QIC_STATUS_READY) {
451
                ftape_current_command = QIC_NO_COMMAND; /* completed */
452
        }
453
        ft_last_status.status.drive_status = (__u8)(*status & 0xff);
454
        TRACE_EXIT 0;
455
}
456
 
457
int ftape_report_drive_status(int *status)
458
{
459
        TRACE_FUN(ft_t_any);
460
 
461
        TRACE_CATCH(ftape_report_raw_drive_status(status),);
462
        if (*status & QIC_STATUS_NEW_CARTRIDGE ||
463
            !(*status & QIC_STATUS_CARTRIDGE_PRESENT)) {
464
                ft_failure = 1; /* will inhibit further operations */
465
                TRACE_EXIT -EIO;
466
        }
467
        if (*status & QIC_STATUS_READY && *status & QIC_STATUS_ERROR) {
468
                /*  Let caller handle all errors */
469
                TRACE_ABORT(1, ft_t_warn, "warning: error status set!");
470
        }
471
        TRACE_EXIT 0;
472
}
473
 
474
int ftape_report_error(unsigned int *error,
475
                       qic117_cmd_t *command, int report)
476
{
477
        static const ftape_error ftape_errors[] = QIC117_ERRORS;
478
        int code;
479
        TRACE_FUN(ft_t_any);
480
 
481
        TRACE_CATCH(ftape_report_operation(&code, QIC_REPORT_ERROR_CODE, 16),);
482
        *error   = (unsigned int)(code & 0xff);
483
        *command = (qic117_cmd_t)((code>>8)&0xff);
484
        /*  remember hardware status, maybe useful for status ioctls
485
         */
486
        ft_last_error.error.command = (__u8)*command;
487
        ft_last_error.error.error   = (__u8)*error;
488
        if (!report) {
489
                TRACE_EXIT 0;
490
        }
491
        if (*error == 0) {
492
                TRACE_ABORT(0, ft_t_info, "No error");
493
        }
494
        TRACE(ft_t_info, "errorcode: %d", *error);
495
        if (*error < NR_ITEMS(ftape_errors)) {
496
                TRACE(ft_t_noise, "%sFatal ERROR:",
497
                      (ftape_errors[*error].fatal ? "" : "Non-"));
498
                TRACE(ft_t_noise, "%s ...", ftape_errors[*error].message);
499
        } else {
500
                TRACE(ft_t_noise, "Unknown ERROR !");
501
        }
502
        if ((unsigned int)*command < NR_ITEMS(qic117_cmds) &&
503
            qic117_cmds[*command].name != NULL) {
504
                TRACE(ft_t_noise, "... caused by command \'%s\'",
505
                      qic117_cmds[*command].name);
506
        } else {
507
                TRACE(ft_t_noise, "... caused by unknown command %d",
508
                      *command);
509
        }
510
        TRACE_EXIT 0;
511
}
512
 
513
int ftape_in_error_state(int status)
514
{
515
        TRACE_FUN(ft_t_any);
516
 
517
        if ((status & QIC_STATUS_READY) && (status & QIC_STATUS_ERROR)) {
518
                TRACE_ABORT(1, ft_t_warn, "warning: error status set!");
519
        }
520
        TRACE_EXIT 0;
521
}
522
 
523
int ftape_report_configuration(qic_model *model,
524
                               unsigned int *rate,
525
                               int *qic_std,
526
                               int *tape_len)
527
{
528
        int result;
529
        int config;
530
        int status;
531
        static const unsigned int qic_rates[ 4] = { 250, 2000, 500, 1000 };
532
        TRACE_FUN(ft_t_any);
533
 
534
        result = ftape_report_operation(&config,
535
                                        QIC_REPORT_DRIVE_CONFIGURATION, 8);
536
        if (result < 0) {
537
                ft_last_status.status.drive_config = (__u8)0x00;
538
                *model = prehistoric;
539
                *rate = 500;
540
                *qic_std = QIC_TAPE_QIC40;
541
                *tape_len = 205;
542
                TRACE_EXIT 0;
543
        } else {
544
                ft_last_status.status.drive_config = (__u8)(config & 0xff);
545
        }
546
        *rate = qic_rates[(config & QIC_CONFIG_RATE_MASK) >> QIC_CONFIG_RATE_SHIFT];
547
        result = ftape_report_operation(&status, QIC_REPORT_TAPE_STATUS, 8);
548
        if (result < 0) {
549
                ft_last_status.status.tape_status = (__u8)0x00;
550
                /* pre- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is valid.
551
                 */
552
                *qic_std = (config & QIC_CONFIG_80) ?
553
                        QIC_TAPE_QIC80 : QIC_TAPE_QIC40;
554
                /* ?? how's about 425ft tapes? */
555
                *tape_len = (config & QIC_CONFIG_LONG) ? 307 : 0;
556
                *model = pre_qic117c;
557
                result = 0;
558
        } else {
559
                ft_last_status.status.tape_status = (__u8)(status & 0xff);
560
                *model = post_qic117b;
561
                TRACE(ft_t_any, "report tape status result = %02x", status);
562
                /* post- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is
563
                 * invalid.
564
                 */
565
                switch (status & QIC_TAPE_STD_MASK) {
566
                case QIC_TAPE_QIC40:
567
                case QIC_TAPE_QIC80:
568
                case QIC_TAPE_QIC3020:
569
                case QIC_TAPE_QIC3010:
570
                        *qic_std = status & QIC_TAPE_STD_MASK;
571
                        break;
572
                default:
573
                        *qic_std = -1;
574
                        break;
575
                }
576
                switch (status & QIC_TAPE_LEN_MASK) {
577
                case QIC_TAPE_205FT:
578
                        /* 205 or 425+ ft 550 Oe tape */
579
                        *tape_len = 0;
580
                        break;
581
                case QIC_TAPE_307FT:
582
                        /* 307.5 ft 550 Oe Extended Length (XL) tape */
583
                        *tape_len = 307;
584
                        break;
585
                case QIC_TAPE_VARIABLE:
586
                        /* Variable length 550 Oe tape */
587
                        *tape_len = 0;
588
                        break;
589
                case QIC_TAPE_1100FT:
590
                        /* 1100 ft 550 Oe tape */
591
                        *tape_len = 1100;
592
                        break;
593
                case QIC_TAPE_FLEX:
594
                        /* Variable length 900 Oe tape */
595
                        *tape_len = 0;
596
                        break;
597
                default:
598
                        *tape_len = -1;
599
                        break;
600
                }
601
                if (*qic_std == -1 || *tape_len == -1) {
602
                        TRACE(ft_t_any,
603
                              "post qic-117b spec drive with unknown tape");
604
                }
605
                result = *tape_len == -1 ? -EIO : 0;
606
                if (status & QIC_TAPE_WIDE) {
607
                        switch (*qic_std) {
608
                        case QIC_TAPE_QIC80:
609
                                TRACE(ft_t_info, "TR-1 tape detected");
610
                                break;
611
                        case QIC_TAPE_QIC3010:
612
                                TRACE(ft_t_info, "TR-2 tape detected");
613
                                break;
614
                        case QIC_TAPE_QIC3020:
615
                                TRACE(ft_t_info, "TR-3 tape detected");
616
                                break;
617
                        default:
618
                                TRACE(ft_t_warn,
619
                                      "Unknown Travan tape type detected");
620
                                break;
621
                        }
622
                }
623
        }
624
        TRACE_EXIT (result < 0) ? -EIO : 0;
625
}
626
 
627
int ftape_report_rom_version(int *version)
628
{
629
 
630
        if (ftape_report_operation(version, QIC_REPORT_ROM_VERSION, 8) < 0) {
631
                return -EIO;
632
        } else {
633
                return 0;
634
        }
635
}
636
 
637
int ftape_report_signature(int *signature)
638
{
639
        int result;
640
 
641
        result = ftape_command(28);
642
        result = ftape_report_operation(signature, 9, 8);
643
        result = ftape_command(30);
644
        return (result < 0) ? -EIO : 0;
645
}
646
 
647
void ftape_report_vendor_id(unsigned int *id)
648
{
649
        int result;
650
        TRACE_FUN(ft_t_any);
651
 
652
        /* We'll try to get a vendor id from the drive.  First
653
         * according to the QIC-117 spec, a 16-bit id is requested.
654
         * If that fails we'll try an 8-bit version, otherwise we'll
655
         * try an undocumented query.
656
         */
657
        result = ftape_report_operation((int *) id, QIC_REPORT_VENDOR_ID, 16);
658
        if (result < 0) {
659
                result = ftape_report_operation((int *) id,
660
                                                QIC_REPORT_VENDOR_ID, 8);
661
                if (result < 0) {
662
                        /* The following is an undocumented call found
663
                         * in the CMS code.
664
                         */
665
                        result = ftape_report_operation((int *) id, 24, 8);
666
                        if (result < 0) {
667
                                *id = UNKNOWN_VENDOR;
668
                        } else {
669
                                TRACE(ft_t_noise, "got old 8 bit id: %04x",
670
                                      *id);
671
                                *id |= 0x20000;
672
                        }
673
                } else {
674
                        TRACE(ft_t_noise, "got 8 bit id: %04x", *id);
675
                        *id |= 0x10000;
676
                }
677
        } else {
678
                TRACE(ft_t_noise, "got 16 bit id: %04x", *id);
679
        }
680
        if (*id == 0x0047) {
681
                int version;
682
                int sign;
683
 
684
                if (ftape_report_rom_version(&version) < 0) {
685
                        TRACE(ft_t_bug, "report rom version failed");
686
                        TRACE_EXIT;
687
                }
688
                TRACE(ft_t_noise, "CMS rom version: %d", version);
689
                ftape_command(QIC_ENTER_DIAGNOSTIC_1);
690
                ftape_command(QIC_ENTER_DIAGNOSTIC_1);
691
                diagnostic_mode = 1;
692
                if (ftape_report_operation(&sign, 9, 8) < 0) {
693
                        unsigned int error;
694
                        qic117_cmd_t command;
695
 
696
                        ftape_report_error(&error, &command, 1);
697
                        ftape_command(QIC_ENTER_PRIMARY_MODE);
698
                        diagnostic_mode = 0;
699
                        TRACE_EXIT;     /* failure ! */
700
                } else {
701
                        TRACE(ft_t_noise, "CMS signature: %02x", sign);
702
                }
703
                if (sign == 0xa5) {
704
                        result = ftape_report_operation(&sign, 37, 8);
705
                        if (result < 0) {
706
                                if (version >= 63) {
707
                                        *id = 0x8880;
708
                                        TRACE(ft_t_noise,
709
                                              "This is an Iomega drive !");
710
                                } else {
711
                                        *id = 0x0047;
712
                                        TRACE(ft_t_noise,
713
                                              "This is a real CMS drive !");
714
                                }
715
                        } else {
716
                                *id = 0x0047;
717
                                TRACE(ft_t_noise, "CMS status: %d", sign);
718
                        }
719
                } else {
720
                        *id = UNKNOWN_VENDOR;
721
                }
722
                ftape_command(QIC_ENTER_PRIMARY_MODE);
723
                diagnostic_mode = 0;
724
        }
725
        TRACE_EXIT;
726
}
727
 
728
static int qic_rate_code(unsigned int rate)
729
{
730
        switch (rate) {
731
        case 250:
732
                return QIC_CONFIG_RATE_250;
733
        case 500:
734
                return QIC_CONFIG_RATE_500;
735
        case 1000:
736
                return QIC_CONFIG_RATE_1000;
737
        case 2000:
738
                return QIC_CONFIG_RATE_2000;
739
        default:
740
                return QIC_CONFIG_RATE_500;
741
        }
742
}
743
 
744
static int ftape_set_rate_test(unsigned int *max_rate)
745
{
746
        unsigned int error;
747
        qic117_cmd_t command;
748
        int status;
749
        int supported = 0;
750
        TRACE_FUN(ft_t_any);
751
 
752
        /*  Check if the drive does support the select rate command
753
         *  by testing all different settings. If any one is accepted
754
         *  we assume the command is supported, else not.
755
         */
756
        for (*max_rate = 2000; *max_rate >= 250; *max_rate /= 2) {
757
                if (ftape_command(QIC_SELECT_RATE) < 0) {
758
                        continue;
759
                }
760
                if (ftape_parameter_wait(qic_rate_code(*max_rate),
761
                                         1 * FT_SECOND, &status) < 0) {
762
                        continue;
763
                }
764
                if (status & QIC_STATUS_ERROR) {
765
                        ftape_report_error(&error, &command, 0);
766
                        continue;
767
                }
768
                supported = 1; /* did accept a request */
769
                break;
770
        }
771
        TRACE(ft_t_noise, "Select Rate command is%s supported",
772
              supported ? "" : " not");
773
        TRACE_EXIT supported;
774
}
775
 
776
int ftape_set_data_rate(unsigned int new_rate /* Kbps */, unsigned int qic_std)
777
{
778
        int status;
779
        int result = 0;
780
        unsigned int data_rate = new_rate;
781
        static int supported;
782
        int rate_changed = 0;
783
        qic_model dummy_model;
784
        unsigned int dummy_qic_std, dummy_tape_len;
785
        TRACE_FUN(ft_t_any);
786
 
787
        if (ft_drive_max_rate == 0) { /* first time */
788
                supported = ftape_set_rate_test(&ft_drive_max_rate);
789
        }
790
        if (supported) {
791
                ftape_command(QIC_SELECT_RATE);
792
                result = ftape_parameter_wait(qic_rate_code(new_rate),
793
                                              1 * FT_SECOND, &status);
794
                if (result >= 0 && !(status & QIC_STATUS_ERROR)) {
795
                        rate_changed = 1;
796
                }
797
        }
798
        TRACE_CATCH(result = ftape_report_configuration(&dummy_model,
799
                                                        &data_rate,
800
                                                        &dummy_qic_std,
801
                                                        &dummy_tape_len),);
802
        if (data_rate != new_rate) {
803
                if (!supported) {
804
                        TRACE(ft_t_warn, "Rate change not supported!");
805
                } else if (rate_changed) {
806
                        TRACE(ft_t_warn, "Requested: %d, got %d",
807
                              new_rate, data_rate);
808
                } else {
809
                        TRACE(ft_t_warn, "Rate change failed!");
810
                }
811
                result = -EINVAL;
812
        }
813
        /*
814
         *  Set data rate and write precompensation as specified:
815
         *
816
         *            |  QIC-40/80  | QIC-3010/3020
817
         *   rate     |   precomp   |    precomp
818
         *  ----------+-------------+--------------
819
         *  250 Kbps. |   250 ns.   |     0 ns.
820
         *  500 Kbps. |   125 ns.   |     0 ns.
821
         *    1 Mbps. |    42 ns.   |     0 ns.
822
         *    2 Mbps  |      N/A    |     0 ns.
823
         */
824
        if ((qic_std == QIC_TAPE_QIC40 && data_rate > 500) ||
825
            (qic_std == QIC_TAPE_QIC80 && data_rate > 1000)) {
826
                TRACE_ABORT(-EINVAL,
827
                            ft_t_warn, "Datarate too high for QIC-mode");
828
        }
829
        TRACE_CATCH(fdc_set_data_rate(data_rate),_res = -EINVAL);
830
        ft_data_rate = data_rate;
831
        if (qic_std == QIC_TAPE_QIC40 || qic_std == QIC_TAPE_QIC80) {
832
                switch (data_rate) {
833
                case 250:
834
                        fdc_set_write_precomp(250);
835
                        break;
836
                default:
837
                case 500:
838
                        fdc_set_write_precomp(125);
839
                        break;
840
                case 1000:
841
                        fdc_set_write_precomp(42);
842
                        break;
843
                }
844
        } else {
845
                fdc_set_write_precomp(0);
846
        }
847
        TRACE_EXIT result;
848
}
849
 
850
/*  The next two functions are used to cope with excessive overrun errors
851
 */
852
int ftape_increase_threshold(void)
853
{
854
        TRACE_FUN(ft_t_flow);
855
 
856
        if (fdc.type < i82077 || ft_fdc_threshold >= 12) {
857
                TRACE_ABORT(-EIO, ft_t_err, "cannot increase fifo threshold");
858
        }
859
        if (fdc_fifo_threshold(++ft_fdc_threshold, NULL, NULL, NULL) < 0) {
860
                TRACE(ft_t_err, "cannot increase fifo threshold");
861
                ft_fdc_threshold --;
862
                fdc_reset();
863
        }
864
        TRACE(ft_t_info, "New FIFO threshold: %d", ft_fdc_threshold);
865
        TRACE_EXIT 0;
866
}
867
 
868
int ftape_half_data_rate(void)
869
{
870
        if (ft_data_rate < 500) {
871
                return -1;
872
        }
873
        if (ftape_set_data_rate(ft_data_rate / 2, ft_qic_std) < 0) {
874
                return -EIO;
875
        }
876
        ftape_calc_timeouts(ft_qic_std, ft_data_rate, ftape_tape_len);
877
        return 0;
878
}
879
 
880
/*      Seek the head to the specified track.
881
 */
882
int ftape_seek_head_to_track(unsigned int track)
883
{
884
        int status;
885
        TRACE_FUN(ft_t_any);
886
 
887
        ft_location.track = -1; /* remains set in case of error */
888
        if (track >= ft_tracks_per_tape) {
889
                TRACE_ABORT(-EINVAL, ft_t_bug, "track out of bounds");
890
        }
891
        TRACE(ft_t_flow, "seeking track %d", track);
892
        TRACE_CATCH(ftape_command(QIC_SEEK_HEAD_TO_TRACK),);
893
        TRACE_CATCH(ftape_parameter_wait(track, ftape_timeout.head_seek,
894
                                         &status),);
895
        ft_location.track = track;
896
        ftape_might_be_off_track = 0;
897
        TRACE_EXIT 0;
898
}
899
 
900
int ftape_wakeup_drive(wake_up_types method)
901
{
902
        int status;
903
        int motor_on = 0;
904
        TRACE_FUN(ft_t_any);
905
 
906
        switch (method) {
907
        case wake_up_colorado:
908
                TRACE_CATCH(ftape_command(QIC_PHANTOM_SELECT),);
909
                TRACE_CATCH(ftape_parameter(0 /* ft_drive_sel ?? */),);
910
                break;
911
        case wake_up_mountain:
912
                TRACE_CATCH(ftape_command(QIC_SOFT_SELECT),);
913
                ftape_sleep(FT_MILLISECOND);    /* NEEDED */
914
                TRACE_CATCH(ftape_parameter(18),);
915
                break;
916
        case wake_up_insight:
917
                ftape_sleep(100 * FT_MILLISECOND);
918
                motor_on = 1;
919
                fdc_motor(motor_on);    /* enable is done by motor-on */
920
        case no_wake_up:
921
                break;
922
        default:
923
                TRACE_EXIT -ENODEV;     /* unknown wakeup method */
924
                break;
925
        }
926
        /*  If wakeup succeeded we shouldn't get an error here..
927
         */
928
        TRACE_CATCH(ftape_report_raw_drive_status(&status),
929
                    if (motor_on) {
930
                            fdc_motor(0);
931
                    });
932
        TRACE_EXIT 0;
933
}
934
 
935
int ftape_put_drive_to_sleep(wake_up_types method)
936
{
937
        TRACE_FUN(ft_t_any);
938
 
939
        switch (method) {
940
        case wake_up_colorado:
941
                TRACE_CATCH(ftape_command(QIC_PHANTOM_DESELECT),);
942
                break;
943
        case wake_up_mountain:
944
                TRACE_CATCH(ftape_command(QIC_SOFT_DESELECT),);
945
                break;
946
        case wake_up_insight:
947
                fdc_motor(0);    /* enable is done by motor-on */
948
        case no_wake_up:        /* no wakeup / no sleep ! */
949
                break;
950
        default:
951
                TRACE_EXIT -ENODEV;     /* unknown wakeup method */
952
        }
953
        TRACE_EXIT 0;
954
}
955
 
956
int ftape_reset_drive(void)
957
{
958
        int result = 0;
959
        int status;
960
        unsigned int err_code;
961
        qic117_cmd_t err_command;
962
        int i;
963
        TRACE_FUN(ft_t_any);
964
 
965
        /*  We want to re-establish contact with our drive.  Fire a
966
         *  number of reset commands (single step pulses) and pray for
967
         *  success.
968
         */
969
        for (i = 0; i < 2; ++i) {
970
                TRACE(ft_t_flow, "Resetting fdc");
971
                fdc_reset();
972
                ftape_sleep(10 * FT_MILLISECOND);
973
                TRACE(ft_t_flow, "Reset command to drive");
974
                result = ftape_command(QIC_RESET);
975
                if (result == 0) {
976
                        ftape_sleep(1 * FT_SECOND); /*  drive not
977
                                                     *  accessible
978
                                                     *  during 1 second
979
                                                     */
980
                        TRACE(ft_t_flow, "Re-selecting drive");
981
 
982
                        /* Strange, the QIC-117 specs don't mention
983
                         * this but the drive gets deselected after a
984
                         * soft reset !  So we need to enable it
985
                         * again.
986
                         */
987
                        if (ftape_wakeup_drive(ft_drive_type.wake_up) < 0) {
988
                                TRACE(ft_t_err, "Wakeup failed !");
989
                        }
990
                        TRACE(ft_t_flow, "Waiting until drive gets ready");
991
                        result= ftape_ready_wait(ftape_timeout.reset, &status);
992
                        if (result == 0 && (status & QIC_STATUS_ERROR)) {
993
                                result = ftape_report_error(&err_code,
994
                                                            &err_command, 1);
995
                                if (result == 0 && err_code == 27) {
996
                                        /*  Okay, drive saw reset
997
                                         *  command and responded as it
998
                                         *  should
999
                                         */
1000
                                        break;
1001
                                } else {
1002
                                        result = -EIO;
1003
                                }
1004
                        } else {
1005
                                result = -EIO;
1006
                        }
1007
                }
1008
                FT_SIGNAL_EXIT(_DONT_BLOCK);
1009
        }
1010
        if (result != 0) {
1011
                TRACE(ft_t_err, "General failure to reset tape drive");
1012
        } else {
1013
                /*  Restore correct settings: keep original rate
1014
                 */
1015
                ftape_set_data_rate(ft_data_rate, ft_qic_std);
1016
        }
1017
        ftape_init_drive_needed = 1;
1018
        TRACE_EXIT result;
1019
}

powered by: WebSVN 2.1.0

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