root/drivers/char/ftape/ftape-ctl.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ftape_not_operational
  2. ftape_seek_to_eot
  3. ftape_seek_to_bot
  4. ftape_reset_position
  5. ftape_new_cartridge
  6. ftape_abort_operation
  7. lookup_vendor_id
  8. ftape_detach_drive
  9. clear_history
  10. ftape_activate_drive
  11. ftape_get_drive_status
  12. ftape_log_vendor_id
  13. ftape_calc_timeouts
  14. ftape_init_drive
  15. _ftape_open
  16. _ftape_close
  17. _ftape_ioctl
  18. ftape_init_driver

   1 /*
   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/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 /*      Global vars.
  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;         /* use buffer_state_enum */
  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 /*      Local vars.
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  68 {
  69         /* return true if status indicates tape can not be used.
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 126 {
 127         ftape_seg_pos = first_data_segment;
 128         reset_eof_list();
 129 }
 130 
 131 int ftape_new_cartridge(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 132 {
 133         location.track = -1;    /* force seek on first access */
 134         first_data_segment = -1;        /* unknown */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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                 /* set timeout so that the tape will run to logical EOT
 152                  * if we missed the last sector and there are no queue pulses.
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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);  /* one always comes */
 195         fdc_disable();
 196         fdc_release_irq_and_dma();
 197         TRACE_EXIT;
 198 }
 199 
 200 static void clear_history(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 219 {
 220         TRACE_FUN(5, "ftape_activate_drive");
 221         int result = 0;
 222 
 223         /* If we already know the drive type, wake it up.
 224          * Else try to find out what kind of drive is attached.
 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                 /*  Try to awaken the drive using all known methods.
 237                  *  Lower tracing for a while.
 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                         /*  Test setup for dual drive configuration in dodo.
 246                          *  /dev/rft2 uses mountain wakeup only -> Archive QIC-80
 247                          *  /dev/rft3 uses colorado wakeup only -> Jumbo QIC-40
 248                          *  Other systems will use the normal scheme.
 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;      /* fool TRACE */
 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                         /* no response at all, cannot open this drive */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 281 {
 282         TRACE_FUN(5, "ftape_get_drive_status");
 283         int result;
 284         int status;
 285 
 286         *no_tape =
 287             *wp_tape = 0;
 288         /*    Tape drive is activated now.
 289          *    First clear error status if present.
 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                 /*  Clear error condition (drive is ready !)
 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();    /* hope it's working next time */
 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                         /*  Undocumented feature: Must clear (not present!) error 
 329                          *  here or we'll fail later.
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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;       /* hack to get rid of all this mail */
 363         }
 364         if (vendor_index < 0) {
 365                 /* Unknown vendor id, first time opening device.
 366                  * The drive_type remains set to type found at wakeup time, this
 367                  * will probably keep the driver operating for this new vendor.
 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;         /* deci-ips: very safe value */
 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                 /* scan all methods for this vendor_id in table */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 405 {
 406         TRACE_FUN(8, "ftape_calc_timeouts");
 407         int speed;              /* deci-ips ! */
 408         int length;
 409 
 410         /*                           tape transport speed
 411          *  data rate:        QIC-40   QIC-80   QIC-3010 QIC-3020
 412          *
 413          *    250 Kbps        25 ips     n/a      n/a      n/a
 414          *    500 Kbps        50 ips   34 ips   22.6 ips   n/a
 415          *      1 Mbps          n/a    68 ips   45.2 ips 22.6 ips
 416          *      2 Mbps          n/a      n/a      n/a    45.2 ips
 417          *
 418          *  fast tape transport speed is at least 68 ips.
 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                 /*  Handle unknown length tapes as 1100 ft ones (worst case)
 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         /*  time to go from bot to eot at normal speed (data rate):
 464          *  time = (1+delta) * length (ft) * 12 (inch/ft) / speed (ips)
 465          *  delta = 10 % for seek speed, 20 % for rewind speed.
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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                         /*  Antique drives will get here after a soft reset,
 486                          *  modern ones only if the driver is loaded when the
 487                          *  tape wasn't rewound properly.
 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                 /*  Select highest rate supported by both fdc and drive.
 508                  *  Start with highest rate supported by the fdc.
 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                 /* Tape should be at bot if new cartridge ! */
 530                 ftape_new_cartridge();
 531         }
 532         init_drive_needed = 0;
 533         TRACE_EXIT;
 534         return result;
 535 }
 536 
 537 /*      OPEN routine called by kernel-interface code
 538  */
 539 int _ftape_open(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 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;  /* enable writes again */
 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 /*      RELEASE routine called by kernel-interface code
 586  */
 587 int _ftape_close(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 /*      IOCTL routine called by kernel-interface code
 650  */
 651 int _ftape_ioctl(unsigned int command, void *arg)
     /* [previous][next][first][last][top][bottom][index][help] */
 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         /* This check will only catch arguments that are too large !
 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                 /* cpio compatibility
 679                  * mtrasx and mtreset are mt extension by Hennus Bergman
 680                  * mtseek and mttell are mt extension by eddy olk
 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                         /* gnu mt calls MTNOP before MTIOCGET to set status */
 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;   /* position ready to extend */
 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;   /* position ready to extend */
 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                         /* MTRASx and MTRESET are mt extension by Hennus Bergman
 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;    /* not implemented */
 811                 krnl_arg.mtget.mt_dsreg = 0;    /* status register */
 812                 krnl_arg.mtget.mt_gstat =       /* device independent status */
 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;     /* error register */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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();  /* init some tape related variables */
 883         ftape_init_bsm();
 884 }

/* [previous][next][first][last][top][bottom][index][help] */