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/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
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;
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
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
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;
133 first_data_segment = -1;
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
151
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);
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
223
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
236
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
245
246
247
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;
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
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
288
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
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();
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
328
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;
362 }
363 if (vendor_index < 0) {
364
365
366
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, "Kai Harrekilde-Petersen <khp@pip.dknet.dk>");
375 TRACE(-1, "==========================================");
376 drive_type.speed = 500;
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
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 <khp@pip.dknet.dk>");
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;
407 int length;
408
409
410
411
412
413
414
415
416
417
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
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 <khp@pip.dknet.dk>");
460 TRACE(-1, "==========================================");
461 }
462
463
464
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
485
486
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
507
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
529 ftape_new_cartridge();
530 }
531 init_drive_needed = 0;
532 TRACE_EXIT;
533 return result;
534 }
535
536
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;
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
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
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
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
678
679
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
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;
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;
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
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;
810 krnl_arg.mtget.mt_dsreg = 0;
811 krnl_arg.mtget.mt_gstat =
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;
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();
882 ftape_init_bsm();
883 }