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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*
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
 *
19
 *      This file contains the non-read/write ftape functions
20
 *      for the QIC-40/80 floppy-tape driver for Linux.
21
 */
22
 
23
#include <linux/errno.h>
24
#include <linux/mm.h>
25
#include <linux/ftape.h>
26
#include <asm/segment.h>
27
 
28
#include "tracing.h"
29
#include "ftape-eof.h"
30
#include "ftape-io.h"
31
#include "ftape-ctl.h"
32
#include "ftape-write.h"
33
#include "ftape-read.h"
34
#include "ftape-rw.h"
35
#include "qic117.h"
36
#include "ftape-bsm.h"
37
 
38
 
39
/*      Global vars.
40
 */
41
int segments_per_track = 102;
42
int segments_per_head = 1020;
43
int segments_per_cylinder = 4;
44
int tracks_per_tape = 20;
45
int ftape_failure = 1;
46
int ftape_seg_pos = 0;
47
int first_data_segment = -1;
48
int ftape_state = idle;         /* use buffer_state_enum */
49
history_record history;
50
int write_protected;
51
int ftape_offline = 0;
52
int no_tape = 1;
53
int formatted = 0;
54
int ftape_data_rate = 0;
55
int going_offline = 0;
56
int read_only = 0;
57
 
58
/*      Local vars.
59
 */
60
static int ftape_last_error = 0;
61
static const vendor_struct vendors[] = QIC117_VENDORS;
62
static const wakeup_method methods[] = WAKEUP_METHODS;
63
static int init_drive_needed = 1;
64
 
65
 
66
static int ftape_not_operational(int status)
67
{
68
        /* return true if status indicates tape can not be used.
69
         */
70
        return ((status ^ QIC_STATUS_CARTRIDGE_PRESENT) &
71
                (QIC_STATUS_ERROR |
72
                 QIC_STATUS_CARTRIDGE_PRESENT |
73
                 QIC_STATUS_NEW_CARTRIDGE));
74
}
75
 
76
int ftape_seek_to_eot(void)
77
{
78
        TRACE_FUN(8, "ftape_seek_to_eot");
79
        int result;
80
        int status;
81
 
82
        result = ftape_ready_wait(timeout.pause, &status);
83
        while ((status & QIC_STATUS_AT_EOT) == 0) {
84
                if (result < 0) {
85
                        TRACE(1, "failed");
86
                        TRACE_EXIT;
87
                        return result;
88
                }
89
                if (ftape_not_operational(status)) {
90
                        TRACE_EXIT;
91
                        return -EIO;
92
                }
93
                result = ftape_command_wait(QIC_PHYSICAL_FORWARD,
94
                                            timeout.rewind, &status);
95
        }
96
        TRACE_EXIT;
97
        return 0;
98
}
99
 
100
int ftape_seek_to_bot(void)
101
{
102
        TRACE_FUN(8, "ftape_seek_to_bot");
103
        int result;
104
        int status;
105
 
106
        result = ftape_ready_wait(timeout.pause, &status);
107
        while ((status & QIC_STATUS_AT_BOT) == 0) {
108
                if (result < 0) {
109
                        TRACE(1, "failed");
110
                        TRACE_EXIT;
111
                        return result;
112
                }
113
                if (ftape_not_operational(status)) {
114
                        TRACE_EXIT;
115
                        return -EIO;
116
                }
117
                result = ftape_command_wait(QIC_PHYSICAL_REVERSE,
118
                                            timeout.rewind, &status);
119
        }
120
        TRACE_EXIT;
121
        return 0;
122
}
123
 
124
void ftape_reset_position(void)
125
{
126
        ftape_seg_pos = first_data_segment;
127
        reset_eof_list();
128
}
129
 
130
int ftape_new_cartridge(void)
131
{
132
        location.track = -1;    /* force seek on first access */
133
        first_data_segment = -1;        /* unknown */
134
        ftape_zap_read_buffers();
135
        ftape_zap_write_buffers();
136
        ftape_reset_position();
137
        return 0;
138
}
139
 
140
int ftape_abort_operation(void)
141
{
142
        TRACE_FUN(5, "ftape_abort_operation");
143
        int result = 0;
144
        int i;
145
        int status;
146
 
147
        if (runner_status == running) {
148
                TRACE(5, "aborting runner, waiting");
149
                runner_status = do_abort;
150
                /* set timeout so that the tape will run to logical EOT
151
                 * if we missed the last sector and there are no queue pulses.
152
                 */
153
                result = ftape_dumb_stop();
154
                if (result == 0) {
155
                        runner_status = idle;
156
                }
157
        }
158
        if (runner_status != idle) {
159
                if (runner_status == do_abort) {
160
                        TRACE(5, "forcing runner abort");
161
                }
162
                TRACE(5, "stopping tape");
163
                result = ftape_command_wait(QIC_STOP_TAPE, timeout.stop, &status);
164
                location.known = 0;
165
                runner_status = idle;
166
        }
167
        for (i = 0; i < NR_BUFFERS; ++i) {
168
                buffer[i].status = waiting;
169
        }
170
        head = tail = 0;
171
        TRACE_EXIT;
172
        return result;
173
}
174
 
175
int lookup_vendor_id(int vendor_id)
176
{
177
        int i = 0;
178
 
179
        while (vendors[i].vendor_id != vendor_id) {
180
                if (++i >= NR_ITEMS(vendors)) {
181
                        return -1;
182
                }
183
        }
184
        return i;
185
}
186
 
187
void ftape_detach_drive(void)
188
{
189
        TRACE_FUN(8, "ftape_detach_drive");
190
 
191
        TRACE(5, "disabling tape drive and fdc");
192
        ftape_put_drive_to_sleep(drive_type);
193
        fdc_catch_stray_interrupts(1);  /* one always comes */
194
        fdc_disable();
195
        fdc_release_irq_and_dma();
196
        TRACE_EXIT;
197
}
198
 
199
static void clear_history(void)
200
{
201
        history.used = 0;
202
        history.id_am_errors =
203
            history.id_crc_errors =
204
            history.data_am_errors =
205
            history.data_crc_errors =
206
            history.overrun_errors =
207
            history.no_data_errors =
208
            history.retries =
209
            history.crc_errors =
210
            history.crc_failures =
211
            history.ecc_failures =
212
            history.corrected =
213
            history.defects =
214
            history.rewinds = 0;
215
}
216
 
217
int ftape_activate_drive(vendor_struct * drive_type)
218
{
219
        TRACE_FUN(5, "ftape_activate_drive");
220
        int result = 0;
221
 
222
        /* If we already know the drive type, wake it up.
223
         * Else try to find out what kind of drive is attached.
224
         */
225
        if (drive_type->wake_up != unknown_wake_up) {
226
                TRACE(5, "enabling tape drive and fdc");
227
                result = ftape_wakeup_drive(drive_type->wake_up);
228
                if (result < 0) {
229
                        TRACE(1, "known wakeup method failed");
230
                }
231
        } else {
232
                int old_tracing = tracing;
233
                wake_up_types method;
234
 
235
                /*  Try to awaken the drive using all known methods.
236
                 *  Lower tracing for a while.
237
                 */
238
                if (tracing <= 4) {
239
                        tracing = 0;
240
                }
241
                for (method = no_wake_up; method < NR_ITEMS(methods); ++method) {
242
                        drive_type->wake_up = method;
243
#if 0
244
                        /*  Test setup for dual drive configuration in dodo.
245
                         *  /dev/rft2 uses mountain wakeup only -> Archive QIC-80
246
                         *  /dev/rft3 uses colorado wakeup only -> Jumbo QIC-40
247
                         *  Other systems will use the normal scheme.
248
                         */
249
                        if ((FTAPE_UNIT < 2) ||
250
                        (FTAPE_UNIT == 2 && method == wake_up_mountain) ||
251
                        (FTAPE_UNIT == 3 && method == wake_up_colorado)) {
252
                                result = ftape_wakeup_drive(drive_type->wake_up);
253
                        } else {
254
                                result = -EIO;
255
                        }
256
#else
257
                        result = ftape_wakeup_drive(drive_type->wake_up);
258
#endif
259
                        if (result >= 0) {
260
                                int tracing = old_tracing;      /* fool TRACE */
261
                                TRACEx1(2, "drive wakeup method: %s",
262
                                      methods[drive_type->wake_up].name);
263
                                break;
264
                        }
265
                }
266
                tracing = old_tracing;
267
                if (method >= NR_ITEMS(methods)) {
268
                        /* no response at all, cannot open this drive */
269
                        drive_type->wake_up = unknown_wake_up;
270
                        TRACE(1, "no tape drive found !");
271
                        tracing = old_tracing;
272
                        result = -ENODEV;
273
                }
274
        }
275
        TRACE_EXIT;
276
        return result;
277
}
278
 
279
int ftape_get_drive_status(int *new_tape, int *no_tape, int *wp_tape)
280
{
281
        TRACE_FUN(5, "ftape_get_drive_status");
282
        int result;
283
        int status;
284
 
285
        *no_tape =
286
            *wp_tape = 0;
287
        /*    Tape drive is activated now.
288
         *    First clear error status if present.
289
         */
290
        do {
291
                result = ftape_ready_wait(timeout.reset, &status);
292
                if (result < 0) {
293
                        if (result == -ETIME) {
294
                                TRACE(1, "ftape_ready_wait timeout");
295
                        } else if (result == -EINTR) {
296
                                TRACE(1, "ftape_ready_wait aborted");
297
                        } else {
298
                                TRACE(1, "ftape_ready_wait failed");
299
                        }
300
                        result = -EIO;
301
                        break;
302
                }
303
                /*  Clear error condition (drive is ready !)
304
                 */
305
                if (status & QIC_STATUS_ERROR) {
306
                        int error;
307
                        int command;
308
 
309
                        TRACE(1, "error status set");
310
                        result = ftape_report_error(&error, &command, 1);
311
                        if (result < 0) {
312
                                TRACEi(1, "report_error_code failed:", result);
313
                                ftape_reset_drive();    /* hope it's working next time */
314
                                init_drive_needed = 1;
315
                                result = -EIO;
316
                                break;
317
                        } else if (error != 0) {
318
                                TRACEi(4, "error code   :", error);
319
                                TRACEi(4, "error command:", command);
320
                        }
321
                }
322
                if (status & QIC_STATUS_NEW_CARTRIDGE) {
323
                        int error;
324
                        int command;
325
                        int old_tracing = tracing;
326
 
327
                        /*  Undocumented feature: Must clear (not present!) error
328
                         *  here or we'll fail later.
329
                         */
330
                        tracing = 0;
331
                        ftape_report_error(&error, &command, 1);
332
                        tracing = old_tracing;
333
                        TRACE(3, "status: new cartridge");
334
                        *new_tape = 1;
335
                }
336
        } while (status & QIC_STATUS_ERROR);
337
 
338
        *no_tape = !(status & QIC_STATUS_CARTRIDGE_PRESENT);
339
        *wp_tape = (status & QIC_STATUS_WRITE_PROTECT);
340
        if (*no_tape) {
341
                TRACE(1, "no cartridge present");
342
        } else {
343
                if (*wp_tape) {
344
                        TRACE(2, "Write protected cartridge");
345
                }
346
        }
347
        TRACE_EXIT;
348
        return result;
349
}
350
 
351
void ftape_log_vendor_id(void)
352
{
353
        TRACE_FUN(5, "ftape_log_vendor_id");
354
        int vendor_index;
355
 
356
        ftape_report_vendor_id(&drive_type.vendor_id);
357
        vendor_index = lookup_vendor_id(drive_type.vendor_id);
358
        if (drive_type.vendor_id == UNKNOWN_VENDOR &&
359
            drive_type.wake_up == wake_up_colorado) {
360
                vendor_index = 0;
361
                drive_type.vendor_id = 0;        /* hack to get rid of all this mail */
362
        }
363
        if (vendor_index < 0) {
364
                /* Unknown vendor id, first time opening device.
365
                 * The drive_type remains set to type found at wakeup time, this
366
                 * will probably keep the driver operating for this new vendor.
367
                 */
368
                TRACE(-1, "============ unknown vendor id ===========");
369
                TRACE(-1, "A new, yet unsupported tape drive is found");
370
                TRACE(-1, "Please report the following values:");
371
                TRACEx1(-1, "   Vendor id     : 0x%04x", drive_type.vendor_id);
372
                TRACEx1(-1, "   Wakeup method : %s", methods[drive_type.wake_up].name);
373
                TRACE(-1, "And a description of your tape drive to:");
374
                TRACE(-1, "Claus Heine <claus@momo.math.rwth-aachen.de>");
375
                TRACE(-1, "==========================================");
376
                drive_type.speed = 500;         /* deci-ips: very safe value */
377
        } else {
378
                drive_type.name = vendors[vendor_index].name;
379
                drive_type.speed = vendors[vendor_index].speed;
380
                TRACEx1(3, "tape drive type: %s", drive_type.name);
381
                /* scan all methods for this vendor_id in table */
382
                while (drive_type.wake_up != vendors[vendor_index].wake_up) {
383
                        if (vendor_index < NR_ITEMS(vendors) - 1 &&
384
                            vendors[vendor_index + 1].vendor_id == drive_type.vendor_id) {
385
                                ++vendor_index;
386
                        } else {
387
                                break;
388
                        }
389
                }
390
                if (drive_type.wake_up != vendors[vendor_index].wake_up) {
391
                        TRACE(-1, "==========================================");
392
                        TRACE(-1, "wakeup type mismatch:");
393
                        TRACEx2(-1, "found: %s, expected: %s",
394
                                methods[drive_type.wake_up].name,
395
                            methods[vendors[vendor_index].wake_up].name);
396
                        TRACE(-1, "please report this to <claus@momo.math.rwth-aachen.de>");
397
                        TRACE(-1, "==========================================");
398
                }
399
        }
400
        TRACE_EXIT;
401
}
402
 
403
void ftape_calc_timeouts(void)
404
{
405
        TRACE_FUN(8, "ftape_calc_timeouts");
406
        int speed;              /* deci-ips ! */
407
        int length;
408
 
409
        /*                           tape transport speed
410
         *  data rate:        QIC-40   QIC-80   QIC-3010 QIC-3020
411
         *
412
         *    250 Kbps        25 ips     n/a      n/a      n/a
413
         *    500 Kbps        50 ips   34 ips   22.6 ips   n/a
414
         *      1 Mbps          n/a    68 ips   45.2 ips 22.6 ips
415
         *      2 Mbps          n/a      n/a      n/a    45.2 ips
416
         *
417
         *  fast tape transport speed is at least 68 ips.
418
         */
419
        switch (qic_std) {
420
        case QIC_TAPE_QIC40:
421
                speed = (ftape_data_rate == 3) ? 250 : 500;
422
                break;
423
        case QIC_TAPE_QIC80:
424
                speed = (ftape_data_rate == 2) ? 340 : 680;
425
                break;
426
        case QIC_TAPE_QIC3010:
427
                speed = (ftape_data_rate == 2) ? 226 : 452;
428
                break;
429
        case QIC_TAPE_QIC3020:
430
                speed = (ftape_data_rate == 1) ? 226 : 452;
431
                break;
432
        default:
433
                TRACE(-1, "Unknown qic_std (bug) ?");
434
                speed = 500;
435
                break;
436
        }
437
        if (tape_len <= 0) {
438
                /*  Handle unknown length tapes as 1100 ft ones (worst case)
439
                 */
440
                TRACE(1, "Unknown tape length, using worst case timing values!");
441
                length = 1100;
442
        } else {
443
                length = tape_len;
444
        }
445
        if (drive_type.speed == 0) {
446
                unsigned long t0;
447
                int dt;
448
 
449
                ftape_seek_to_bot();
450
                t0 = jiffies;
451
                ftape_seek_to_eot();
452
                ftape_seek_to_bot();
453
                dt = (int) ((jiffies - t0) * MSPT);
454
                drive_type.speed = (2 * 12 * length * 1000) / dt;
455
                TRACE(-1, "==========================================");
456
                TRACEx1(-1, "drive : %s", drive_type.name);
457
                TRACEx2(-1, "delta time = %d, length = %d", dt, length);
458
                TRACEx1(-1, "has max tape speed of %d ips", drive_type.speed);
459
                TRACE(-1, "please report this to <claus@momo.math.rwth-aachen.de>");
460
                TRACE(-1, "==========================================");
461
        }
462
        /*  time to go from bot to eot at normal speed (data rate):
463
         *  time = (1+delta) * length (ft) * 12 (inch/ft) / speed (ips)
464
         *  delta = 10 % for seek speed, 20 % for rewind speed.
465
         */
466
        timeout.seek = (length * 132 * SECOND) / speed;
467
        timeout.rewind = (length * 144 * SECOND) / (10 * drive_type.speed);
468
        timeout.reset = 20 * SECOND + timeout.rewind;
469
        TRACEx2(4, "speed = %d, length = %d", speed, length);
470
        TRACEx1(4, "seek timeout: %d sec", (timeout.seek + 500) / 1000);
471
        TRACEx1(4, "rewind timeout: %d sec", (timeout.rewind + 500) / 1000);
472
        TRACE_EXIT;
473
}
474
 
475
int ftape_init_drive(int *formatted)
476
{
477
        TRACE_FUN(5, "ftape_init_drive");
478
        int result = 0;
479
        int status;
480
 
481
        result = ftape_report_raw_drive_status(&status);
482
        if (result >= 0 && (status & QIC_STATUS_CARTRIDGE_PRESENT)) {
483
                if (!(status & QIC_STATUS_AT_BOT)) {
484
                        /*  Antique drives will get here after a soft reset,
485
                         *  modern ones only if the driver is loaded when the
486
                         *  tape wasn't rewound properly.
487
                         */
488
                        ftape_seek_to_bot();
489
                }
490
                if (!(status & QIC_STATUS_REFERENCED)) {
491
                        TRACE(5, "starting seek_load_point");
492
                        result = ftape_command_wait(QIC_SEEK_LOAD_POINT,
493
                                                 timeout.reset, &status);
494
                        if (result < 0) {
495
                                TRACE(1, "seek_load_point failed (command)");
496
                        }
497
                }
498
        }
499
        if (result >= 0) {
500
                int rate;
501
 
502
                *formatted = (status & QIC_STATUS_REFERENCED);
503
                if (!*formatted) {
504
                        TRACE(1, "Warning: tape is not formatted !");
505
                }
506
                /*  Select highest rate supported by both fdc and drive.
507
                 *  Start with highest rate supported by the fdc.
508
                 */
509
                if (fdc.type >= i82078_1)
510
                        rate = 0;
511
                else if (fdc.type >= i82077)
512
                        rate = 1;
513
                else
514
                        rate = 2;
515
                do {
516
                        result = ftape_set_data_rate(rate);
517
                        if (result >= 0) {
518
                                ftape_calc_timeouts();
519
                                break;
520
                        }
521
                        ++rate;
522
                } while (rate < 4);
523
                if (result < 0) {
524
                        result = -EIO;
525
                }
526
        }
527
        if (result >= 0) {
528
                /* Tape should be at bot if new cartridge ! */
529
                ftape_new_cartridge();
530
        }
531
        init_drive_needed = 0;
532
        TRACE_EXIT;
533
        return result;
534
}
535
 
536
/*      OPEN routine called by kernel-interface code
537
 */
538
int _ftape_open(void)
539
{
540
        TRACE_FUN(8, "_ftape_open");
541
        int result;
542
        static int new_tape = 1;
543
 
544
        result = fdc_init();
545
        if (result >= 0) {
546
                result = ftape_activate_drive(&drive_type);
547
                if (result < 0) {
548
                        fdc_disable();
549
                        fdc_release_irq_and_dma();
550
 
551
                } else {
552
                        result = ftape_get_drive_status(&new_tape, &no_tape, &write_protected);
553
                        if (result < 0) {
554
                                ftape_detach_drive();
555
                        } else {
556
                                if (drive_type.vendor_id == UNKNOWN_VENDOR) {
557
                                        ftape_log_vendor_id();
558
                                }
559
                                if (no_tape) {
560
                                        ftape_offline = 1;
561
                                } else if (new_tape) {
562
                                        ftape_offline = 0;
563
                                        init_drive_needed = 1;
564
                                        read_only = 0;   /* enable writes again */
565
                                }
566
                                if (!ftape_offline && init_drive_needed) {
567
                                        result = ftape_init_drive(&formatted);
568
                                        if (result >= 0) {
569
                                                new_tape = 0;
570
                                        } else {
571
                                                ftape_detach_drive();
572
                                        }
573
                                }
574
                                if (result >= 0) {
575
                                        clear_history();
576
                                }
577
                        }
578
                }
579
        }
580
        TRACE_EXIT;
581
        return result;
582
}
583
 
584
/*      RELEASE routine called by kernel-interface code
585
 */
586
int _ftape_close(void)
587
{
588
        TRACE_FUN(8, "_ftape_close");
589
        int result = 0;
590
        int last_segment = 0;
591
 
592
        if (!ftape_offline) {
593
                result = ftape_flush_buffers();
594
                last_segment = ftape_seg_pos - 1;
595
                if (!(ftape_unit & FTAPE_NO_REWIND)) {
596
                        if (result >= 0) {
597
                                result = ftape_update_header_segments(NULL, 1);
598
                                if (result < 0) {
599
                                        TRACE(1, "error: update of header segments failed");
600
                                }
601
                        } else {
602
                                TRACE(1, "error: unable to update header segments");
603
                        }
604
                }
605
                ftape_abort_operation();
606
                if (!(ftape_unit & FTAPE_NO_REWIND)) {
607
                        if (!no_tape) {
608
                                TRACE(5, "rewinding tape");
609
                                result = ftape_seek_to_bot();
610
                        }
611
                        ftape_reset_position();
612
                        ftape_zap_read_buffers();
613
                        ftape_zap_write_buffers();
614
                }
615
        }
616
        ftape_detach_drive();
617
        fdc_uninit();
618
        if (history.used) {
619
                TRACE(3, "== Non-fatal errors this run: ==");
620
                TRACE(3, "fdc isr statistics:");
621
                TRACEi(3, " id_am_errors     :", history.id_am_errors);
622
                TRACEi(3, " id_crc_errors    :", history.id_crc_errors);
623
                TRACEi(3, " data_am_errors   :", history.data_am_errors);
624
                TRACEi(3, " data_crc_errors  :", history.data_crc_errors);
625
                TRACEi(3, " overrun_errors   :", history.overrun_errors);
626
                TRACEi(3, " no_data_errors   :", history.no_data_errors);
627
                TRACEi(3, " retries          :", history.retries);
628
                if (history.used & 1) {
629
                        TRACE(3, "ecc statistics:");
630
                        TRACEi(3, " crc_errors       :", history.crc_errors);
631
                        TRACEi(3, " crc_failures     :", history.crc_failures);
632
                        TRACEi(3, " ecc_failures     :", history.ecc_failures);
633
                        TRACEi(3, " sectors corrected:", history.corrected);
634
                }
635
                TRACEx2(3, "media defects     : %d%s", history.defects,
636
                        history.defects ? " !!!" : "");
637
                TRACEi(3, "repositions       :", history.rewinds);
638
                TRACEi(3, "last segment      :", last_segment);
639
        }
640
        if (going_offline) {
641
                going_offline = 0;
642
                ftape_offline = 1;
643
        }
644
        TRACE_EXIT;
645
        return result;
646
}
647
 
648
/*      IOCTL routine called by kernel-interface code
649
 */
650
int _ftape_ioctl(unsigned int command, void *arg)
651
{
652
        TRACE_FUN(8, "ftape_ioctl");
653
        int result = EINVAL;
654
        union {
655
                struct mtop mtop;
656
                struct mtget mtget;
657
        } krnl_arg;
658
        int arg_size = (command & IOCSIZE_MASK) >> IOCSIZE_SHIFT;
659
 
660
        /* This check will only catch arguments that are too large !
661
         */
662
        if ((command & IOC_INOUT) && arg_size > sizeof(krnl_arg)) {
663
                TRACEi(1, "bad argument size:", arg_size);
664
                TRACE_EXIT;
665
                return -EINVAL;
666
        }
667
        if (command & IOC_IN) {
668
                int error = verify_area(VERIFY_READ, arg, arg_size);
669
                if (error) {
670
                        TRACE_EXIT;
671
                        return error;
672
                }
673
                memcpy_fromfs(&krnl_arg.mtop, arg, arg_size);
674
        }
675
        TRACEx1(5, "called with ioctl command: 0x%08x", command);
676
        switch (command) {
677
                /* cpio compatibility
678
                 * mtrasx and mtreset are mt extension by Hennus Bergman
679
                 * mtseek and mttell are mt extension by eddy olk
680
                 */
681
        case MTIOCTOP:
682
                TRACEx1(5, "calling MTIOCTOP command: 0x%08x", krnl_arg.mtop.mt_op);
683
                switch (krnl_arg.mtop.mt_op) {
684
                case MTNOP:
685
                        /* gnu mt calls MTNOP before MTIOCGET to set status */
686
                        result = 0;
687
                        break;
688
                case MTRESET:
689
                        result = ftape_reset_drive();
690
                        init_drive_needed = 1;
691
                        if (result < 0 || ftape_offline) {
692
                                break;
693
                        }
694
                        result = ftape_seek_to_bot();
695
                        ftape_reset_position();
696
                        break;
697
                case MTREW:
698
                case MTOFFL:
699
                        if (ftape_offline) {
700
                                result = -EIO;
701
                                break;
702
                        }
703
                        ftape_flush_buffers();
704
                        ftape_update_header_segments(NULL, 1);
705
                        result = ftape_seek_to_bot();
706
                        ftape_reset_position();
707
                        if (krnl_arg.mtop.mt_op == MTOFFL) {
708
                                going_offline = 1;
709
                                TRACE(4, "Putting tape drive offline");
710
                        }
711
                        result = 0;
712
                        break;
713
                case MTRETEN:
714
                        if (ftape_offline) {
715
                                result = -EIO;
716
                                break;
717
                        }
718
                        result = ftape_seek_to_eot();
719
                        if (result >= 0) {
720
                                result = ftape_seek_to_bot();
721
                        }
722
                        ftape_reset_position();
723
                        break;
724
                case MTERASE:
725
                        if (ftape_offline) {
726
                                result = -EIO;
727
                                break;
728
                        }
729
                        result = ftape_erase();
730
                        break;
731
                case MTEOM:
732
                        if (ftape_offline) {
733
                                result = -EIO;
734
                                break;
735
                        }
736
                        result = ftape_seek_eom();
737
                        break;
738
                case MTFSFM:
739
                        if (ftape_offline) {
740
                                result = -EIO;
741
                                break;
742
                        }
743
                        eof_mark = 1;   /* position ready to extend */
744
                case MTFSF:
745
                        if (ftape_offline) {
746
                                result = -EIO;
747
                                break;
748
                        }
749
                        result = ftape_seek_eof(krnl_arg.mtop.mt_count);
750
                        break;
751
                case MTBSFM:
752
                        if (ftape_offline) {
753
                                result = -EIO;
754
                                break;
755
                        }
756
                        eof_mark = 1;   /* position ready to extend */
757
                case MTBSF:
758
                        if (ftape_offline) {
759
                                result = -EIO;
760
                                break;
761
                        }
762
                        result = ftape_seek_eof(-krnl_arg.mtop.mt_count);
763
                        break;
764
                case MTFSR:
765
                        if (ftape_offline) {
766
                                result = -EIO;
767
                                break;
768
                        }
769
                        tracing = krnl_arg.mtop.mt_count;
770
                        TRACEx1(2, "tracing set to %d", tracing);
771
                        result = 0;
772
                        break;
773
                case MTBSR:
774
                        if (ftape_offline) {
775
                                result = -EIO;
776
                                break;
777
                        }
778
#if 0
779
                        result = ftape_fix();
780
#else
781
                        result = 0;
782
#endif
783
                        break;
784
                case MTWEOF:
785
                        if (ftape_offline) {
786
                                result = -EIO;
787
                                break;
788
                        }
789
                        result = ftape_weof(krnl_arg.mtop.mt_count, ftape_seg_pos, 1);
790
                        if (result >= 0) {
791
                                ftape_seg_pos += krnl_arg.mtop.mt_count - 1;
792
                        }
793
                        break;
794
                        /* MTRASx and MTRESET are mt extension by Hennus Bergman
795
                         */
796
                case MTRAS1:
797
                case MTRAS2:
798
                case MTRAS3:
799
                case MTSEEK:
800
                case MTTELL:
801
                default:
802
                        TRACEi(1, "MTIOCTOP sub-command not implemented:", krnl_arg.mtop.mt_op);
803
                        result = -EIO;
804
                        break;
805
                }
806
                break;
807
        case MTIOCGET:
808
                krnl_arg.mtget.mt_type = drive_type.vendor_id + 0x800000;
809
                krnl_arg.mtget.mt_resid = 0;     /* not implemented */
810
                krnl_arg.mtget.mt_dsreg = 0;     /* status register */
811
                krnl_arg.mtget.mt_gstat =       /* device independent status */
812
                    ((ftape_offline) ? 0 : GMT_ONLINE(-1L)) |
813
                    ((write_protected) ? GMT_WR_PROT(-1L) : 0) |
814
                    ((no_tape) ? GMT_DR_OPEN(-1L) : 0);
815
                krnl_arg.mtget.mt_erreg = ftape_last_error;     /* error register */
816
                result = ftape_file_no(&krnl_arg.mtget.mt_fileno,
817
                                       &krnl_arg.mtget.mt_blkno);
818
                break;
819
        case MTIOCPOS:
820
                TRACE(5, "Mag tape ioctl command: MTIOCPOS");
821
                TRACE(1, "MTIOCPOS command not implemented");
822
                break;
823
        default:
824
                result = -EINVAL;
825
                break;
826
        }
827
        if (command & IOC_OUT) {
828
                int error = verify_area(VERIFY_WRITE, arg, arg_size);
829
                if (error) {
830
                        TRACE_EXIT;
831
                        return error;
832
                }
833
                memcpy_tofs(arg, &krnl_arg, arg_size);
834
        }
835
        TRACE_EXIT;
836
        return result;
837
}
838
 
839
void ftape_init_driver(void)
840
{
841
        drive_type.vendor_id = UNKNOWN_VENDOR;
842
        drive_type.speed = 0;
843
        drive_type.wake_up = unknown_wake_up;
844
        drive_type.name = "Unknown";
845
 
846
        timeout.seek = 650 * SECOND;
847
        timeout.reset = 670 * SECOND;
848
        timeout.rewind = 650 * SECOND;
849
        timeout.head_seek = 15 * SECOND;
850
        timeout.stop = 5 * SECOND;
851
        timeout.pause = 16 * SECOND;
852
 
853
        qic_std = -1;
854
        tape_len = -1;
855
        current_command = 0;
856
        current_cylinder = -1;
857
 
858
        segments_per_track = 102;
859
        segments_per_head = 1020;
860
        segments_per_cylinder = 4;
861
        tracks_per_tape = 20;
862
        ftape_failure = 1;
863
        ftape_seg_pos = 0;
864
        first_data_segment = -1;
865
        ftape_state = idle;
866
        no_tape = 1;
867
        formatted = 0;
868
        ftape_data_rate = 0;
869
        going_offline = 0;
870
        read_only = 0;
871
 
872
        init_drive_needed = 1;
873
        header_segment_1 = -1;
874
        header_segment_2 = -1;
875
        used_header_segment = -1;
876
        location.track = -1;
877
        location.known = 0;
878
        tape_running = 0;
879
        might_be_off_track = 1;
880
 
881
        ftape_new_cartridge();  /* init some tape related variables */
882
        ftape_init_bsm();
883
}

powered by: WebSVN 2.1.0

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