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