📄 ftape-ctl.c
字号:
/* * Copyright (C) 1993-1996 Bas Laarhoven, * 1996-1997 Claus-Justus Heine. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * * $Source: /homes/cvs/ftape-stacked/ftape/lowlevel/ftape-ctl.c,v $ * $Revision: 1.4 $ * $Date: 1997/11/11 14:37:44 $ * * This file contains the non-read/write ftape functions for the * QIC-40/80/3010/3020 floppy-tape driver "ftape" for Linux. */#include <linux/config.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/ftape.h>#include <linux/qic117.h>#include <asm/uaccess.h>#include <asm/io.h>/* ease porting between pre-2.4.x and later kernels */#define vma_get_pgoff(v) ((v)->vm_pgoff)#include "../lowlevel/ftape-tracing.h"#include "../lowlevel/ftape-io.h"#include "../lowlevel/ftape-ctl.h"#include "../lowlevel/ftape-write.h"#include "../lowlevel/ftape-read.h"#include "../lowlevel/ftape-rw.h"#include "../lowlevel/ftape-bsm.h"/* Global vars. */ftape_info ftape_status = {/* vendor information */ { 0, }, /* drive type *//* data rates */ 500, /* used data rate */ 500, /* drive max rate */ 500, /* fdc max rate *//* drive selection, either FTAPE_SEL_A/B/C/D */ -1, /* drive selection *//* flags set after decode the drive and tape status */ 0, /* formatted */ 1, /* no tape */ 1, /* write protected */ 1, /* new tape *//* values of last queried drive/tape status and error */ {{0,}}, /* last error code */ {{0,}}, /* drive status, configuration, tape status *//* cartridge geometry */ 20, /* tracks_per_tape */ 102, /* segments_per_track *//* location of header segments, etc. */ -1, /* used_header_segment */ -1, /* header_segment_1 */ -1, /* header_segment_2 */ -1, /* first_data_segment */ -1, /* last_data_segment *//* the format code as stored in the header segment */ fmt_normal, /* format code *//* the default for the qic std: unknown */ -1,/* is tape running? */ idle, /* runner_state *//* is tape reading/writing/verifying/formatting/deleting */ idle, /* driver state *//* flags fatal hardware error */ 1, /* failure *//* history record */ { 0, } /* history record */}; int ftape_segments_per_head = 1020;int ftape_segments_per_cylinder = 4;int ftape_init_drive_needed = 1; /* need to be global for ftape_reset_drive() * in ftape-io.c *//* Local vars. */static const vendor_struct vendors[] = QIC117_VENDORS;static const wakeup_method methods[] = WAKEUP_METHODS;const ftape_info *ftape_get_status(void){#if defined(STATUS_PARANOYA) static ftape_info get_status; get_status = ftape_status; return &get_status;#else return &ftape_status; /* maybe return only a copy of it to assure * read only access */#endif}static int ftape_not_operational(int status){ /* return true if status indicates tape can not be used. */ return ((status ^ QIC_STATUS_CARTRIDGE_PRESENT) & (QIC_STATUS_ERROR | QIC_STATUS_CARTRIDGE_PRESENT | QIC_STATUS_NEW_CARTRIDGE));}int ftape_seek_to_eot(void){ int status; TRACE_FUN(ft_t_any); TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),); while ((status & QIC_STATUS_AT_EOT) == 0) { if (ftape_not_operational(status)) { TRACE_EXIT -EIO; } TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_FORWARD, ftape_timeout.rewind,&status),); } TRACE_EXIT 0;}int ftape_seek_to_bot(void){ int status; TRACE_FUN(ft_t_any); TRACE_CATCH(ftape_ready_wait(ftape_timeout.pause, &status),); while ((status & QIC_STATUS_AT_BOT) == 0) { if (ftape_not_operational(status)) { TRACE_EXIT -EIO; } TRACE_CATCH(ftape_command_wait(QIC_PHYSICAL_REVERSE, ftape_timeout.rewind,&status),); } TRACE_EXIT 0;}static int ftape_new_cartridge(void){ ft_location.track = -1; /* force seek on first access */ ftape_zap_read_buffers(); ftape_zap_write_buffers(); return 0;}int ftape_abort_operation(void){ int result = 0; int status; TRACE_FUN(ft_t_flow); if (ft_runner_status == running) { TRACE(ft_t_noise, "aborting runner, waiting"); ft_runner_status = do_abort; /* set timeout so that the tape will run to logical EOT * if we missed the last sector and there are no queue pulses. */ result = ftape_dumb_stop(); } if (ft_runner_status != idle) { if (ft_runner_status == do_abort) { TRACE(ft_t_noise, "forcing runner abort"); } TRACE(ft_t_noise, "stopping tape"); result = ftape_stop_tape(&status); ft_location.known = 0; ft_runner_status = idle; } ftape_reset_buffer(); ftape_zap_read_buffers(); ftape_set_state(idle); TRACE_EXIT result;}static int lookup_vendor_id(unsigned int vendor_id){ int i = 0; while (vendors[i].vendor_id != vendor_id) { if (++i >= NR_ITEMS(vendors)) { return -1; } } return i;}static void ftape_detach_drive(void){ TRACE_FUN(ft_t_any); TRACE(ft_t_flow, "disabling tape drive and fdc"); ftape_put_drive_to_sleep(ft_drive_type.wake_up); fdc_catch_stray_interrupts(1); /* one always comes */ fdc_disable(); fdc_release_irq_and_dma(); fdc_release_regions(); TRACE_EXIT;}static void clear_history(void){ ft_history.used = 0; ft_history.id_am_errors = ft_history.id_crc_errors = ft_history.data_am_errors = ft_history.data_crc_errors = ft_history.overrun_errors = ft_history.no_data_errors = ft_history.retries = ft_history.crc_errors = ft_history.crc_failures = ft_history.ecc_failures = ft_history.corrected = ft_history.defects = ft_history.rewinds = 0;}static int ftape_activate_drive(vendor_struct * drive_type){ int result = 0; TRACE_FUN(ft_t_flow); /* If we already know the drive type, wake it up. * Else try to find out what kind of drive is attached. */ if (drive_type->wake_up != unknown_wake_up) { TRACE(ft_t_flow, "enabling tape drive and fdc"); result = ftape_wakeup_drive(drive_type->wake_up); if (result < 0) { TRACE(ft_t_err, "known wakeup method failed"); } } else { wake_up_types method; const ft_trace_t old_tracing = TRACE_LEVEL; if (TRACE_LEVEL < ft_t_flow) { SET_TRACE_LEVEL(ft_t_bug); } /* Try to awaken the drive using all known methods. * Lower tracing for a while. */ for (method=no_wake_up; method < NR_ITEMS(methods); ++method) { drive_type->wake_up = method;#ifdef CONFIG_FT_TWO_DRIVES /* Test setup for dual drive configuration. * /dev/rft2 uses mountain wakeup * /dev/rft3 uses colorado wakeup * Other systems will use the normal scheme. */ if ((ft_drive_sel < 2) || (ft_drive_sel == 2 && method == FT_WAKE_UP_1) || (ft_drive_sel == 3 && method == FT_WAKE_UP_2)) { result=ftape_wakeup_drive(drive_type->wake_up); } else { result = -EIO; }#else result = ftape_wakeup_drive(drive_type->wake_up);#endif if (result >= 0) { TRACE(ft_t_warn, "drive wakeup method: %s", methods[drive_type->wake_up].name); break; } } SET_TRACE_LEVEL(old_tracing); if (method >= NR_ITEMS(methods)) { /* no response at all, cannot open this drive */ drive_type->wake_up = unknown_wake_up; TRACE(ft_t_err, "no tape drive found !"); result = -ENODEV; } } TRACE_EXIT result;}static int ftape_get_drive_status(void){ int result; int status; TRACE_FUN(ft_t_flow); ft_no_tape = ft_write_protected = 0; /* Tape drive is activated now. * First clear error status if present. */ do { result = ftape_ready_wait(ftape_timeout.reset, &status); if (result < 0) { if (result == -ETIME) { TRACE(ft_t_err, "ftape_ready_wait timeout"); } else if (result == -EINTR) { TRACE(ft_t_err, "ftape_ready_wait aborted"); } else { TRACE(ft_t_err, "ftape_ready_wait failed"); } TRACE_EXIT -EIO; } /* Clear error condition (drive is ready !) */ if (status & QIC_STATUS_ERROR) { unsigned int error; qic117_cmd_t command; TRACE(ft_t_err, "error status set"); result = ftape_report_error(&error, &command, 1); if (result < 0) { TRACE(ft_t_err, "report_error_code failed: %d", result); /* hope it's working next time */ ftape_reset_drive(); TRACE_EXIT -EIO; } else if (error != 0) { TRACE(ft_t_noise, "error code : %d", error); TRACE(ft_t_noise, "error command: %d", command); } } if (status & QIC_STATUS_NEW_CARTRIDGE) { unsigned int error; qic117_cmd_t command; const ft_trace_t old_tracing = TRACE_LEVEL; SET_TRACE_LEVEL(ft_t_bug); /* Undocumented feature: Must clear (not present!) * error here or we'll fail later. */ ftape_report_error(&error, &command, 1); SET_TRACE_LEVEL(old_tracing); TRACE(ft_t_info, "status: new cartridge"); ft_new_tape = 1; } else { ft_new_tape = 0; } FT_SIGNAL_EXIT(_DONT_BLOCK); } while (status & QIC_STATUS_ERROR); ft_no_tape = !(status & QIC_STATUS_CARTRIDGE_PRESENT); ft_write_protected = (status & QIC_STATUS_WRITE_PROTECT) != 0; if (ft_no_tape) { TRACE(ft_t_warn, "no cartridge present"); } else { if (ft_write_protected) { TRACE(ft_t_noise, "Write protected cartridge"); } } TRACE_EXIT 0;}static void ftape_log_vendor_id(void){ int vendor_index; TRACE_FUN(ft_t_flow); ftape_report_vendor_id(&ft_drive_type.vendor_id); vendor_index = lookup_vendor_id(ft_drive_type.vendor_id); if (ft_drive_type.vendor_id == UNKNOWN_VENDOR && ft_drive_type.wake_up == wake_up_colorado) { vendor_index = 0; /* hack to get rid of all this mail */ ft_drive_type.vendor_id = 0; } if (vendor_index < 0) { /* Unknown vendor id, first time opening device. The * drive_type remains set to type found at wakeup * time, this will probably keep the driver operating * for this new vendor. */ TRACE(ft_t_warn, "\n" KERN_INFO "============ unknown vendor id ===========\n" KERN_INFO "A new, yet unsupported tape drive is found\n" KERN_INFO "Please report the following values:\n" KERN_INFO " Vendor id : 0x%04x\n" KERN_INFO " Wakeup method : %s\n" KERN_INFO "And a description of your tape drive\n" KERN_INFO "to "THE_FTAPE_MAINTAINER"\n" KERN_INFO "==========================================", ft_drive_type.vendor_id, methods[ft_drive_type.wake_up].name); ft_drive_type.speed = 0; /* unknown */ } else { ft_drive_type.name = vendors[vendor_index].name; ft_drive_type.speed = vendors[vendor_index].speed; TRACE(ft_t_info, "tape drive type: %s", ft_drive_type.name); /* scan all methods for this vendor_id in table */ while(ft_drive_type.wake_up != vendors[vendor_index].wake_up) { if (vendor_index < NR_ITEMS(vendors) - 1 && vendors[vendor_index + 1].vendor_id == ft_drive_type.vendor_id) { ++vendor_index; } else { break; } } if (ft_drive_type.wake_up != vendors[vendor_index].wake_up) { TRACE(ft_t_warn, "\n" KERN_INFO "==========================================\n" KERN_INFO "wakeup type mismatch:\n" KERN_INFO "found: %s, expected: %s\n" KERN_INFO "please report this to "THE_FTAPE_MAINTAINER"\n" KERN_INFO "==========================================", methods[ft_drive_type.wake_up].name, methods[vendors[vendor_index].wake_up].name); } } TRACE_EXIT;}void ftape_calc_timeouts(unsigned int qic_std, unsigned int data_rate, unsigned int tape_len){ int speed; /* deci-ips ! */ int ff_speed; int length; TRACE_FUN(ft_t_any); /* tape transport speed * data rate: QIC-40 QIC-80 QIC-3010 QIC-3020 * * 250 Kbps 25 ips n/a n/a n/a * 500 Kbps 50 ips 34 ips 22.6 ips n/a * 1 Mbps n/a 68 ips 45.2 ips 22.6 ips * 2 Mbps n/a n/a n/a 45.2 ips * * fast tape transport speed is at least 68 ips.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -