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/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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
  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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 125 {
 126         ftape_seg_pos = first_data_segment;
 127         reset_eof_list();
 128 }
 129 
 130 int ftape_new_cartridge(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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, "Kai Harrekilde-Petersen <khp@pip.dknet.dk>");
 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 <khp@pip.dknet.dk>");
 397                         TRACE(-1, "==========================================");
 398                 }
 399         }
 400         TRACE_EXIT;
 401 }
 402 
 403 void ftape_calc_timeouts(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 <khp@pip.dknet.dk>");
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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)
     /* [previous][next][first][last][top][bottom][index][help] */
 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 }

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