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

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

DEFINITIONS

This source file includes following definitions.
  1. udelay
  2. udelay_calibrate
  3. ftape_sleep
  4. ftape_command
  5. ftape_parameter
  6. ftape_ready_wait
  7. ftape_command_wait
  8. ftape_parameter_wait
  9. ftape_report_operation
  10. ftape_report_raw_drive_status
  11. ftape_report_drive_status
  12. ftape_report_error
  13. ftape_in_error_state
  14. ftape_report_configuration
  15. ftape_report_rom_version
  16. ftape_report_signature
  17. ftape_report_vendor_id
  18. ftape_set_rate_test
  19. ftape_set_data_rate
  20. ftape_seek_head_to_track
  21. ftape_wakeup_drive
  22. ftape_put_drive_to_sleep
  23. ftape_reset_drive

   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  $Source: /home/bas/distr/ftape-2.03b/RCS/ftape-io.c,v $
  19  $Author: bas $
  20  *
  21  $Revision: 1.58 $
  22  $Date: 1995/05/27 08:54:21 $
  23  $State: Beta $
  24  *
  25  *      This file contains the general control functions
  26  *      for the QIC-40/80 floppy-tape driver for Linux.
  27  */
  28 
  29 #include <linux/module.h>
  30 #include <linux/errno.h>
  31 #include <linux/sched.h>
  32 #include <linux/mm.h>
  33 #include <linux/ftape.h>
  34 #include <asm/segment.h>
  35 #include <asm/system.h>
  36 #include <linux/ioctl.h>
  37 #include <linux/mtio.h>
  38 
  39 #include "tracing.h"
  40 #include "fdc-io.h"
  41 #include "qic117.h"
  42 #include "ftape-io.h"
  43 #include "ftape-ctl.h"
  44 #include "ftape-rw.h"
  45 #include "ftape-write.h"
  46 #include "ftape-read.h"
  47 #include "ftape-eof.h"
  48 #include "kernel-interface.h"
  49 #include "calibr.h"
  50 
  51 /*      Global vars.
  52  */
  53 /* NOTE: sectors start numbering at 1, all others at 0 ! */
  54 timeout_table timeout;
  55 vendor_struct drive_type;
  56 int qic_std;
  57 int tape_len;
  58 volatile int current_command;
  59 const struct qic117_command_table qic117_cmds[] = QIC117_COMMANDS;
  60 int might_be_off_track;
  61 
  62 /*      Local vars.
  63  */
  64 static int command_parameter = 0;
  65 /*      command-restrictions is a table according
  66  *      to the QIC-117 specs specifying the state
  67  *      the drive status should be in at command execution.
  68  */
  69 static const ftape_error ftape_errors[] = QIC117_ERRORS;
  70 static int ftape_udelay_count;
  71 static int ftape_udelay_time;
  72 static const struct {
  73         char *text;
  74         int fdc_code;
  75         byte drive_code;
  76         int precomp;
  77 } rates[4] = {
  78 
  79 #if defined(FDC_82078SL)
  80         {
  81                 "2 M", -1 /* unsupported */ , QIC_CONFIG_RATE_2000, 0
  82         },
  83 #else
  84         {
  85                 "2 M", fdc_data_rate_2000, QIC_CONFIG_RATE_2000, 0
  86         },
  87 #endif
  88         {
  89                 "1 M", fdc_data_rate_1000, QIC_CONFIG_RATE_1000, 42
  90         },
  91         {
  92                 "500 K", fdc_data_rate_500, QIC_CONFIG_RATE_500, 125
  93         },
  94         {
  95                 "250 K", fdc_data_rate_250, QIC_CONFIG_RATE_250, 250
  96         },
  97 };
  98 typedef enum {
  99         prehistoric, pre_qic117c, post_qic117b, post_qic117d
 100 } qic_model;
 101 
 102 
 103 void udelay(int usecs)
     /* [previous][next][first][last][top][bottom][index][help] */
 104 {
 105         volatile int count = (1 + (usecs * ftape_udelay_count - 1) /
 106                               ftape_udelay_time);
 107         volatile int i;
 108 
 109         while (count-- > 0) {
 110                 for (i = 0; i < 20; ++i);
 111         }
 112 }
 113 
 114 int udelay_calibrate(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116         return calibrate("udelay", udelay, &ftape_udelay_count, &ftape_udelay_time);
 117 }
 118 
 119 /*      Delay (msec) routine.
 120  */
 121 void ftape_sleep(unsigned int time)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123         TRACE_FUN(8, "ftape_sleep");
 124         unsigned long flags;
 125         int ticks = 1 + (time + MSPT - 1) / MSPT;
 126 
 127         /*    error in range [0..1] MSPT
 128          */
 129         if (time < MSPT) {
 130                 /*  Time too small for scheduler, do a busy wait ! */
 131                 udelay(1000 * time);
 132         } else {
 133                 TRACEx2(8, "%d msec, %d ticks", time, ticks);
 134                 current->timeout = jiffies + ticks;
 135                 current->state = TASK_INTERRUPTIBLE;
 136                 save_flags(flags);
 137                 sti();
 138                 do {
 139                         while (current->state != TASK_RUNNING) {
 140                                 schedule();
 141                         }
 142                         if (current->signal & ~current->blocked) {
 143                                 TRACE(1, "awoken by non-blocked signal :-(");
 144                                 break;  /* exit on signal */
 145                         }
 146                 } while (current->timeout > 0);
 147                 restore_flags(flags);
 148         }
 149         TRACE_EXIT;
 150 }
 151 
 152 /* forward */ int ftape_report_raw_drive_status(int *status);
 153 
 154 /*      Issue a tape command:
 155  *      Generate command # of step pulses.
 156  */
 157 int ftape_command(int command)
     /* [previous][next][first][last][top][bottom][index][help] */
 158 {
 159         TRACE_FUN(8, "ftape_command");
 160         int result = 0;
 161         int track;
 162         int old_tracing = tracing;
 163         static int level = 0;
 164         int status = -1;
 165 
 166         if (++level > 5) {
 167                 /*  This is a bug we'll want to know about.
 168                  */
 169                 TRACEx1(1, "bug - recursion for command: %d", command);
 170                 result = -EIO;
 171         } else if (command_parameter) {
 172                 /*  Don't check restrictions for parameters.
 173                  */
 174                 TRACEx1(5, "called with parameter = %d", command - 2);
 175         } else if (command <= 0 || command > NR_ITEMS(qic117_cmds)) {
 176                 /*  This is a bug we'll want to know about too.
 177                  */
 178                 TRACEx1(-1, "bug - bad command: %d", command);
 179                 result = -EIO;
 180         } else {
 181                 /*  disable logging and restriction check for some commands,
 182                  *  check all other commands that have a prescribed starting status.
 183                  */
 184                 if (command == QIC_REPORT_DRIVE_STATUS) {
 185                         TRACE(8, "report drive status called");
 186                         tracing = 0;
 187                 } else if (command == QIC_REPORT_NEXT_BIT) {
 188                         tracing = 0;
 189                 } else {
 190                         TRACEx1(5, "%s", qic117_cmds[command].name);
 191                         /*  A new motion command during an uninterruptible (motion)
 192                          *  command requires a ready status before the new command
 193                          *  can be issued. Otherwise a new motion command needs to
 194                          *  be checked against required status.
 195                          */
 196                         if (qic117_cmds[command].cmd_type == motion &&
 197                             qic117_cmds[current_command].non_intr) {
 198                                 ftape_report_raw_drive_status(&status);
 199                                 if ((status & QIC_STATUS_READY) == 0) {
 200                                         TRACEx2(4, "motion cmd (%d) during non-intr cmd (%d)",
 201                                                 command, current_command);
 202                                         TRACE(4, "waiting until drive gets ready");
 203                                         ftape_ready_wait(timeout.seek, &status);
 204                                 }
 205                         }
 206                         if (qic117_cmds[command].mask != 0) {
 207                                 byte difference;
 208 
 209                                 /*  Some commands do require a certain status:
 210                                  */
 211                                 if (status == -1) {     /* not yet set */
 212                                         ftape_report_raw_drive_status(&status);
 213                                 }
 214                                 difference = ((status ^ qic117_cmds[command].state) &
 215                                               qic117_cmds[command].mask);
 216                                 /*  Wait until the drive gets ready. This may last forever
 217                                  *  if the drive never gets ready...
 218                                  */
 219                                 while ((difference & QIC_STATUS_READY) != 0) {
 220                                         TRACEx1(4, "command %d issued while not ready", command);
 221                                         TRACE(4, "waiting until drive gets ready");
 222                                         ftape_ready_wait(timeout.seek, &status);
 223                                         difference = ((status ^ qic117_cmds[command].state) &
 224                                               qic117_cmds[command].mask);
 225                                         /*  Bail out on signal !
 226                                          */
 227                                         if (current->signal & _DONT_BLOCK) {
 228                                                 result = -EINTR;
 229                                                 break;
 230                                         }
 231                                 }
 232                                 while (result == 0 && (difference & QIC_STATUS_ERROR) != 0) {
 233                                         int err;
 234                                         int cmd;
 235 
 236                                         TRACEx1(4, "command %d issued while error pending", command);
 237                                         TRACE(4, "clearing error status");
 238                                         ftape_report_error(&err, &cmd, 1);
 239                                         ftape_report_raw_drive_status(&status);
 240                                         difference = ((status ^ qic117_cmds[command].state) &
 241                                               qic117_cmds[command].mask);
 242                                         /*  Bail out on fatal signal !
 243                                          */
 244                                         if (current->signal & _DONT_BLOCK) {
 245                                                 result = -EINTR;
 246                                                 break;
 247                                         }
 248                                 }
 249                                 if (result == 0 && difference) {
 250                                         /*  Any remaining difference can't be solved here.
 251                                          */
 252                                         if (difference & (QIC_STATUS_CARTRIDGE_PRESENT |
 253                                                QIC_STATUS_NEW_CARTRIDGE |
 254                                                 QIC_STATUS_REFERENCED)) {
 255                                                 TRACE(1, "Fatal: tape removed or reinserted !");
 256                                                 ftape_failure = 1;
 257                                         } else {
 258                                                 TRACEx2(1, "wrong state: 0x%02x should be: 0x%02x",
 259                                                         status & qic117_cmds[command].mask,
 260                                                         qic117_cmds[command].state);
 261                                         }
 262                                         result = -EIO;
 263                                 }
 264                                 if (~status & QIC_STATUS_READY & qic117_cmds[command].mask) {
 265                                         TRACE(1, "Bad: still busy!");
 266                                         result = -EBUSY;
 267                                 }
 268                         }
 269                 }
 270         }
 271         tracing = old_tracing;
 272         /*  Now all conditions are met or result is < 0.
 273          */
 274         if (result >= 0) {
 275                 /*  Always wait for a command_timeout period to separate
 276                  *  individuals commands and/or parameters.
 277                  */
 278                 ftape_sleep(3 * MILLISECOND);
 279                 /*  Keep cylinder nr within range, step towards home if possible.
 280                  */
 281                 if (current_cylinder >= command) {
 282                         track = current_cylinder - command;
 283                 } else {
 284                         track = current_cylinder + command;
 285                 }
 286                 result = fdc_seek(track);
 287                 /*  position is no longer valid after any of these commands
 288                  *  have completed.
 289                  */
 290                 if (qic117_cmds[command].cmd_type == motion &&
 291                     command != QIC_LOGICAL_FORWARD && command != QIC_STOP_TAPE) {
 292                         location.known = 0;
 293                 }
 294                 command_parameter = 0;  /* always turned off for next command */
 295                 current_command = command;
 296         }
 297         --level;
 298         TRACE_EXIT;
 299         return result;
 300 }
 301 
 302 /*      Send a tape command parameter:
 303  *      Generates command # of step pulses.
 304  *      Skips tape-status call !
 305  */
 306 int ftape_parameter(int command)
     /* [previous][next][first][last][top][bottom][index][help] */
 307 {
 308         command_parameter = 1;
 309         return ftape_command(command + 2);
 310 }
 311 
 312 /*      Wait for the drive to get ready.
 313  *      timeout time in milli-seconds
 314  *      Returned status is valid if result != -EIO
 315  */
 316 int ftape_ready_wait(int timeout, int *status)
     /* [previous][next][first][last][top][bottom][index][help] */
 317 {
 318         TRACE_FUN(8, "ftape_ready_wait");
 319         int result;
 320         unsigned long t0;
 321         const int poll_delay = 100 * MILLISECOND;
 322 
 323         for (;;) {
 324                 t0 = jiffies;
 325                 result = ftape_report_raw_drive_status(status);
 326                 if (result < 0) {
 327                         TRACE(1, "ftape_report_raw_drive_status failed");
 328                         result = -EIO;
 329                         break;
 330                 }
 331                 if (*status & QIC_STATUS_READY) {
 332                         result = 0;
 333                         break;
 334                 }
 335                 if (timeout >= 0) {
 336                         /* this will fail when jiffies wraps around about
 337                          * once every year :-)
 338                          */
 339                         timeout -= ((jiffies - t0) * SECOND) / HZ;
 340                         if (timeout <= 0) {
 341                                 TRACE(1, "timeout");
 342                                 result = -ETIME;
 343                                 break;
 344                         }
 345                         ftape_sleep(poll_delay);
 346                         timeout -= poll_delay;
 347                 } else {
 348                         ftape_sleep(poll_delay);
 349                 }
 350                 if (current->signal & _NEVER_BLOCK) {
 351                         TRACE(1, "interrupted by fatal signal");
 352                         result = -EINTR;
 353                         break;  /* exit on signal */
 354                 }
 355         }
 356         TRACE_EXIT;
 357         return result;
 358 }
 359 
 360 /*      Issue command and wait up to timeout seconds for drive ready
 361  */
 362 int ftape_command_wait(int command, int timeout, int *status)
     /* [previous][next][first][last][top][bottom][index][help] */
 363 {
 364         TRACE_FUN(8, "ftape_command_wait");
 365         int result;
 366 
 367         /* Drive should be ready, issue command
 368          */
 369         result = ftape_command(command);
 370         if (result >= 0) {
 371                 result = ftape_ready_wait(timeout, status);
 372         }
 373         TRACE_EXIT;
 374         return result;
 375 }
 376 
 377 int ftape_parameter_wait(int command, int timeout, int *status)
     /* [previous][next][first][last][top][bottom][index][help] */
 378 {
 379         TRACE_FUN(8, "ftape_parameter_wait");
 380         int result;
 381 
 382         /* Drive should be ready, issue command
 383          */
 384         result = ftape_parameter(command);
 385         if (result >= 0) {
 386                 result = ftape_ready_wait(timeout, status);
 387         }
 388         TRACE_EXIT;
 389         return result;
 390 }
 391 
 392 /*--------------------------------------------------------------------------
 393  *      Report operations
 394  */
 395 
 396 /* Query the drive about its status.  The command is sent and
 397    result_length bits of status are returned (2 extra bits are read
 398    for start and stop). */
 399 
 400 static int ftape_report_operation(int *status, int command, int result_length)
     /* [previous][next][first][last][top][bottom][index][help] */
 401 {
 402         TRACE_FUN(8, "ftape_report_operation");
 403         int i, st3;
 404         int result;
 405         unsigned int t0, t1, dt;
 406 
 407         result = ftape_command(command);
 408         if (result < 0) {
 409                 TRACE(1, "ftape_command failed");
 410                 TRACE_EXIT;
 411                 return result;
 412         }
 413         t0 = timestamp();
 414         dt = 0;
 415         i = 0;
 416         do {
 417                 ++i;
 418                 ftape_sleep(3 * MILLISECOND);   /* see remark below */
 419                 result = fdc_sense_drive_status(&st3);
 420                 if (result < 0) {
 421                         TRACE(1, "fdc_sense_drive_status failed");
 422                         TRACE_EXIT;
 423                         return result;
 424                 }
 425                 /*  Calculate time difference every iteration because timer may
 426                  *  wrap around (but only one !) and timediff will account for this.
 427                  *  Note that the sleep above must be < 1/HZ or we'll lose ticks !
 428                  */
 429                 t1 = timestamp();
 430                 dt += timediff(t0, t1);
 431                 t0 = t1;
 432                 /*  Ack should be asserted within Ttimout + Tack = 6 msec.
 433                  *  Looks like some drives fail to do this so extend this
 434                  *  period to 300 msec.
 435                  */
 436         } while (!(st3 & ST3_TRACK_0) && dt < 300000);
 437         if (st3 & ST3_TRACK_0) {
 438                 /*  dt may be larger than expected because of other tasks
 439                  *  scheduled while we were sleeping.
 440                  */
 441                 if (i > 1 && dt > 6000) {
 442                         TRACEx2(1, "Acknowledge after %u msec. (%i iter)", dt / 1000, i);
 443                 }
 444         } else {
 445                 TRACEx2(1, "No acknowledge after %u msec. (%i iter)", dt / 1000, i);
 446                 TRACE(1, "timeout on Acknowledge");
 447                 TRACE_EXIT;
 448                 return -EIO;
 449         }
 450         *status = 0;
 451         for (i = 0; i < result_length + 1; i++) {
 452                 result = ftape_command(QIC_REPORT_NEXT_BIT);
 453                 if (result < 0) {
 454                         TRACE(1, "report next bit failed");
 455                         TRACE_EXIT;
 456                         return result;
 457                 }
 458 #if 1
 459                 /*  fdc_seek does interrupt wait, so why should we ?
 460                  *  (it will only fail causing fdc to be reset...)
 461                  *  It's only purpose may be the delay, we'll have to find out!
 462                  */
 463 #else
 464                 fdc_interrupt_wait(25 * MILLISECOND);   /* fails only if hw fails */
 465 #endif
 466                 result = fdc_sense_drive_status(&st3);
 467                 if (result < 0) {
 468                         TRACE(1, "fdc_sense_drive_status (2) failed");
 469                         TRACE_EXIT;
 470                         return result;
 471                 }
 472                 if (i < result_length) {
 473                         *status |= ((st3 & ST3_TRACK_0) ? 1 : 0) << i;
 474                 } else {
 475                         if ((st3 & ST3_TRACK_0) == 0) {
 476                                 TRACE(1, "missing status stop bit");
 477                                 TRACE_EXIT;
 478                                 return -EIO;
 479                         }
 480                 }
 481         }
 482         /* this command will put track zero and index back into normal state */
 483         result = ftape_command(QIC_REPORT_NEXT_BIT);
 484         TRACE_EXIT;
 485         return 0;
 486 }
 487 
 488 /* Report the current drive status. */
 489 
 490 int ftape_report_raw_drive_status(int *status)
     /* [previous][next][first][last][top][bottom][index][help] */
 491 {
 492         TRACE_FUN(8, "ftape_report_raw_drive_status");
 493         int result;
 494         int count = 0;
 495 
 496         do {
 497                 result = ftape_report_operation(status, QIC_REPORT_DRIVE_STATUS, 8);
 498         } while (result < 0 && ++count <= 3);
 499         if (result < 0) {
 500                 TRACE(1, "report_operation failed");
 501                 result = -EIO;
 502         } else if (*status & QIC_STATUS_READY) {
 503                 current_command = 0;    /* completed */
 504         }
 505         TRACE_EXIT;
 506         return result;
 507 }
 508 
 509 int ftape_report_drive_status(int *status)
     /* [previous][next][first][last][top][bottom][index][help] */
 510 {
 511         TRACE_FUN(8, "ftape_report_drive_status");
 512         int result;
 513 
 514         result = ftape_report_raw_drive_status(status);
 515         if (result < 0) {
 516                 TRACE(1, "ftape_report_raw_drive_status failed");
 517                 TRACE_EXIT;
 518                 return result;
 519         }
 520         if (*status & QIC_STATUS_NEW_CARTRIDGE ||
 521             !(*status & QIC_STATUS_CARTRIDGE_PRESENT)) {
 522                 ftape_failure = 1;      /* will inhibit further operations */
 523                 TRACE_EXIT;
 524                 return -EIO;
 525         }
 526         if (*status & QIC_STATUS_READY && *status & QIC_STATUS_ERROR) {
 527                 /*  Let caller handle all errors */
 528                 TRACE(2, "warning: error status set!");
 529                 result = 1;
 530         }
 531         TRACE_EXIT;
 532         return result;
 533 }
 534 
 535 int ftape_report_error(int *error, int *command, int report)
     /* [previous][next][first][last][top][bottom][index][help] */
 536 {
 537         TRACE_FUN(8, "ftape_report_error");
 538         int code;
 539         int result;
 540 
 541         result = ftape_report_operation(&code, QIC_REPORT_ERROR_CODE, 16);
 542         if (result < 0) {
 543                 result = -EIO;
 544         } else {
 545                 *error = code & 0xff;
 546                 *command = (code >> 8) & 0xff;
 547                 if (report) {
 548                         if (*error != 0) {
 549                                 TRACEi(3, "errorcode:", *error);
 550                         } else {
 551                                 TRACE(3, "No error");
 552                         }
 553                 }
 554                 if (report && *error != 0 && tracing > 3) {
 555                         if (*error >= 0 && *error < NR_ITEMS(ftape_errors)) {
 556                                 TRACEx1(-1, "%sFatal ERROR:",
 557                                         (ftape_errors[*error].fatal ? "" : "Non-"));
 558                                 TRACEx1(-1, "%s ...", ftape_errors[*error].message);
 559                         } else {
 560                                 TRACE(-1, "Unknown ERROR !");
 561                         }
 562                         if (*command >= 0 && *command < NR_ITEMS(qic117_cmds) &&
 563                             qic117_cmds[*command].name != NULL) {
 564                                 TRACEx1(-1, "... caused by command \'%s\'",
 565                                         qic117_cmds[*command].name);
 566                         } else {
 567                                 TRACEi(-1, "... caused by unknown command", *command);
 568                         }
 569                 }
 570         }
 571         TRACE_EXIT;
 572         return result;
 573 }
 574 
 575 int ftape_in_error_state(int status)
     /* [previous][next][first][last][top][bottom][index][help] */
 576 {
 577         TRACE_FUN(8, "ftape_in_error_state");
 578         int result = 0;
 579 
 580         if ((status & QIC_STATUS_READY) && (status & QIC_STATUS_ERROR)) {
 581                 TRACE(2, "warning: error status set!");
 582                 result = 1;
 583         }
 584         TRACE_EXIT;
 585         return result;
 586 }
 587 
 588 static int ftape_report_configuration(qic_model * model, int *rate,
     /* [previous][next][first][last][top][bottom][index][help] */
 589                                       int *qic_std, int *tape_len)
 590 {
 591         int result;
 592         int config;
 593         int status;
 594 
 595         TRACE_FUN(8, "ftape_report_configuration");
 596         result = ftape_report_operation(&config, QIC_REPORT_DRIVE_CONFIGURATION, 8);
 597         if (result < 0) {
 598                 *model = prehistoric;
 599                 *rate = QIC_CONFIG_RATE_500;
 600                 *qic_std = QIC_TAPE_QIC40;
 601                 *tape_len = 205;
 602                 result = 0;
 603         } else {
 604                 *rate = (config & QIC_CONFIG_RATE_MASK) >> QIC_CONFIG_RATE_SHIFT;
 605                 result = ftape_report_operation(&status, QIC_REPORT_TAPE_STATUS, 8);
 606                 if (result < 0) {
 607                         /* pre- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is valid.
 608                          */
 609                         *qic_std = (config & QIC_CONFIG_80) ? QIC_TAPE_QIC80 : QIC_TAPE_QIC40;
 610                         *tape_len = (config & QIC_CONFIG_LONG) ? 307 : 205;
 611                         *model = pre_qic117c;
 612                         result = 0;
 613                 } else {
 614                         *model = post_qic117b;
 615                         TRACEx1(8, "report tape status result = %02x", status);
 616                         /* post- QIC117 rev C spec. drive, QIC_CONFIG_80 bit is invalid.
 617                          */
 618                         switch (status & QIC_TAPE_STD_MASK) {
 619                         case QIC_TAPE_QIC40:
 620                         case QIC_TAPE_QIC80:
 621                         case QIC_TAPE_QIC3020:
 622                         case QIC_TAPE_QIC3010:
 623                                 *qic_std = status & QIC_TAPE_STD_MASK;
 624                                 break;
 625                         default:
 626                                 *qic_std = -1;
 627                                 break;
 628                         }
 629                         switch (status & QIC_TAPE_LEN_MASK) {
 630                         case QIC_TAPE_205FT:
 631                                 /* Unfortunately the new QIC-117 rev G standard shows
 632                                  * no way to discriminate between 205 and 425 ft tapes.
 633                                  * The obvious way seems not to be used: the QIC_CONFIG_LONG
 634                                  * bit isn't used for this (on all drives ?).
 635                                  */
 636                                 if (config & QIC_CONFIG_LONG) {
 637                                         *tape_len = 425;        /* will this ever execute ??? */
 638                                 } else {
 639                                         *tape_len = 0;  /* length unknown: 205 or 425 ft. */
 640                                 }
 641                                 break;
 642                         case QIC_TAPE_307FT:
 643                                 *tape_len = 307;
 644                                 break;
 645                         case QIC_TAPE_400FT:
 646                                 /*
 647                                  * Trouble! Iomega Ditto 800 and Conner TST800R drives reports
 648                                  * 400ft for 750ft tapes. Yuck, yuck, yuck.  Since the value
 649                                  * is only used to compute a timeout value, the largest of the
 650                                  * two is used.
 651                                  */
 652                                 *tape_len = 750;        /* either 400 or 750 ft. */
 653                                 break;
 654                         case QIC_TAPE_1100FT:
 655                                 *tape_len = 1100;
 656                                 break;
 657                         case QIC_TAPE_FLEX:
 658                                 *tape_len = 0;
 659                                 break;
 660                         default:
 661                                 *tape_len = -1;
 662                                 break;
 663                         }
 664                         if (*qic_std == -1 || *tape_len == -1) {
 665                                 TRACE(2, "post qic-117b spec drive with unknown tape");
 666                                 result = -EIO;
 667                         } else {
 668                                 result = 0;
 669                         }
 670                 }
 671         }
 672         TRACE_EXIT;
 673         return (result < 0) ? -EIO : 0;
 674 }
 675 
 676 int ftape_report_rom_version(int *version)
     /* [previous][next][first][last][top][bottom][index][help] */
 677 {
 678         int result;
 679 
 680         result = ftape_report_operation(version, QIC_REPORT_ROM_VERSION, 8);
 681         return (result < 0) ? -EIO : 0;
 682 }
 683 
 684 int ftape_report_signature(int *signature)
     /* [previous][next][first][last][top][bottom][index][help] */
 685 {
 686         int result;
 687 
 688         result = ftape_command(28);
 689         result = ftape_report_operation(signature, 9, 8);
 690         result = ftape_command(30);
 691         return (result < 0) ? -EIO : 0;
 692 }
 693 
 694 void ftape_report_vendor_id(unsigned int *id)
     /* [previous][next][first][last][top][bottom][index][help] */
 695 {
 696         TRACE_FUN(8, "ftape_report_vendor_id");
 697         int result;
 698 
 699         /*
 700          *    We'll try to get a vendor id from the drive.
 701          *    First according to the QIC-117 spec, a 16-bit id is requested.
 702          *    If that fails we'll try an 8-bit version, otherwise we'll try
 703          *    an undocumented query.
 704          */
 705         result = ftape_report_operation((int *) id, QIC_REPORT_VENDOR_ID, 16);
 706         if (result < 0) {
 707                 result = ftape_report_operation((int *) id, QIC_REPORT_VENDOR_ID, 8);
 708                 if (result < 0) {
 709                         /*  The following is an undocumented call found in the CMS code.
 710                          */
 711                         result = ftape_report_operation((int *) id, 24, 8);
 712                         if (result < 0) {
 713                                 *id = UNKNOWN_VENDOR;
 714                         } else {
 715                                 TRACEx1(4, "got old 8 bit id: %04x", *id);
 716                                 *id |= 0x20000;
 717                         }
 718                 } else {
 719                         TRACEx1(4, "got 8 bit id: %04x", *id);
 720                         *id |= 0x10000;
 721                 }
 722         } else {
 723                 TRACEx1(4, "got 16 bit id: %04x", *id);
 724         }
 725         if (*id == 0x0047) {
 726                 int version;
 727                 int sign;
 728 
 729                 result = ftape_report_rom_version(&version);
 730                 if (result < 0) {
 731                         TRACE(-1, "report rom version failed");
 732                         TRACE_EXIT;
 733                         return;
 734                 }
 735                 TRACEx1(4, "CMS rom version: %d", version);
 736                 ftape_command(QIC_ENTER_DIAGNOSTIC_1);
 737                 ftape_command(QIC_ENTER_DIAGNOSTIC_1);
 738                 result = ftape_report_operation(&sign, 9, 8);
 739                 if (result < 0) {
 740                         int error, command;
 741 
 742                         ftape_report_error(&error, &command, 1);
 743                         ftape_command(QIC_ENTER_PRIMARY_MODE);
 744                         TRACE_EXIT;
 745                         return; /* faalt hier ! */
 746                 } else {
 747                         TRACEx1(4, "CMS signature: %02x", sign);
 748                 }
 749                 if (sign == 0xa5) {
 750                         result = ftape_report_operation(&sign, 37, 8);
 751                         if (result < 0) {
 752                                 if (version >= 63) {
 753                                         *id = 0x8880;
 754                                         TRACE(4, "This is an Iomega drive !");
 755                                 } else {
 756                                         *id = 0x0047;
 757                                         TRACE(4, "This is a real CMS drive !");
 758                                 }
 759                         } else {
 760                                 *id = 0x0047;
 761                                 TRACEx1(4, "CMS status: %d", sign);
 762                         }
 763                 } else {
 764                         *id = UNKNOWN_VENDOR;
 765                 }
 766                 ftape_command(QIC_ENTER_PRIMARY_MODE);
 767         }
 768         TRACE_EXIT;
 769 }
 770 
 771 void ftape_set_rate_test(int *supported)
     /* [previous][next][first][last][top][bottom][index][help] */
 772 {
 773         TRACE_FUN(8, "ftape_set_rate_test");
 774         int error;
 775         int command;
 776         int i;
 777         int result;
 778         int status;
 779 
 780         /*  Check if the drive does support the select rate command by testing
 781          *  all different settings.
 782          *  If any one is accepted we assume the command is supported, else not.
 783          */
 784         *supported = 0;
 785         for (i = 0; i < NR_ITEMS(rates); ++i) {
 786                 result = ftape_command(QIC_SELECT_RATE);
 787                 if (result >= 0) {
 788                         result = ftape_parameter_wait(rates[i].drive_code,
 789                                                     1 * SECOND, &status);
 790                         if (result >= 0) {
 791                                 if (status & QIC_STATUS_ERROR) {
 792                                         result = ftape_report_error(&error, &command, 0);
 793                                 } else {
 794                                         *supported = 1;         /* did accept a request */
 795                                 }
 796                         }
 797                 }
 798         }
 799         TRACEx1(4, "Select Rate command is%s supported",
 800                 *supported ? "" : " not");
 801         TRACE_EXIT;
 802 }
 803 
 804 int ftape_set_data_rate(int new_rate)
     /* [previous][next][first][last][top][bottom][index][help] */
 805 {
 806         TRACE_FUN(8, "ftape_set_data_rate");
 807         int status;
 808         int result;
 809         int data_rate;
 810         qic_model model;
 811         int supported;
 812         static int first_time = 1;
 813 
 814         if (first_time) {
 815                 ftape_set_rate_test(&supported);
 816                 first_time = 0;
 817         }
 818         if (rates[new_rate].fdc_code == -1) {
 819                 TRACEx1(4, "%sb/s data rate not supported by the fdc",
 820                         rates[new_rate].text);
 821                 result = -EINVAL;
 822         } else {
 823                 int error = 0;
 824                 int command;
 825 
 826                 result = ftape_command(QIC_SELECT_RATE);
 827                 if (result >= 0) {
 828                         result = ftape_parameter_wait(rates[new_rate].drive_code,
 829                                                     1 * SECOND, &status);
 830                         result = ftape_report_raw_drive_status(&status);
 831                         if (result >= 0 && (status & QIC_STATUS_ERROR)) {
 832                                 result = ftape_report_error(&error, &command, 0);
 833                                 if (result >= 0 && supported &&
 834                                     error == 31 && command == QIC_SELECT_RATE) {
 835                                         result = -EINVAL;
 836                                 }
 837                         }
 838                 }
 839                 if (result >= 0) {
 840                         result = ftape_report_configuration(&model, &data_rate,
 841                                                     &qic_std, &tape_len);
 842                         if (result >= 0 && data_rate != rates[new_rate].drive_code) {
 843                                 result = -EINVAL;
 844                         }
 845                 }
 846                 if (result < 0) {
 847                         TRACEx1(4, "could not set %sb/s data rate", rates[new_rate].text);
 848                 } else {
 849                         TRACEx2(2, "%s drive @ %sb/s",
 850                                 (model == prehistoric) ? "prehistoric" :
 851                                 ((model == pre_qic117c) ? "pre QIC-117C" :
 852                                  ((model == post_qic117b) ? "post QIC-117B" : "post QIC-117D")),
 853                                 rates[new_rate].text);
 854                         if (tape_len == 0) {
 855                                 TRACEx1(2, "unknown length QIC-%s tape",
 856                                      (qic_std == QIC_TAPE_QIC40) ? "40" :
 857                                     ((qic_std == QIC_TAPE_QIC80) ? "80" :
 858                                      ((qic_std == QIC_TAPE_QIC3010) ? "3010" : "3020")));
 859                         } else {
 860                                 TRACEx2(2, "%d ft. QIC-%s tape",
 861                                         tape_len,
 862                                      (qic_std == QIC_TAPE_QIC40) ? "40" :
 863                                     ((qic_std == QIC_TAPE_QIC80) ? "80" :
 864                                      ((qic_std == QIC_TAPE_QIC3010) ? "3010" : "3020")));
 865                         }
 866                         /*
 867                          *  Set data rate and write precompensation as specified:
 868                          *
 869                          *            |  QIC-40/80  | QIC-3010/3020
 870                          *   rate     |   precomp   |    precomp
 871                          *  ----------+-------------+--------------
 872                          *  250 Kbps. |   250 ns.   |     0 ns.
 873                          *  500 Kbps. |   125 ns.   |     0 ns.
 874                          *    1 Mbps. |    42 ns.   |     0 ns.
 875                          *    2 Mbps  |      N/A    |     0 ns.
 876                          */
 877                         if (qic_std == QIC_TAPE_QIC40 || qic_std == QIC_TAPE_QIC80) {
 878                                 fdc_set_write_precomp(rates[new_rate].precomp);
 879                         } else {
 880                                 fdc_set_write_precomp(0);
 881                         }
 882                         fdc_set_data_rate(rates[new_rate].fdc_code);
 883                         ftape_data_rate = new_rate;     /* store rate set */
 884                 }
 885         }
 886         if (result < 0 && result != -EINVAL) {
 887                 result = -EIO;
 888         }
 889         TRACE_EXIT;
 890         return result;
 891 }
 892 
 893 /*      Seek the head to the specified track.
 894  */
 895 int ftape_seek_head_to_track(int track)
     /* [previous][next][first][last][top][bottom][index][help] */
 896 {
 897         TRACE_FUN(8, "ftape_seek_head_to_track");
 898         int status;
 899         int result;
 900 
 901         location.track = -1;    /* remains set in case of error */
 902         if (track < 0 || track >= tracks_per_tape) {
 903                 TRACE(-1, "track out of bounds");
 904                 result = -EINVAL;
 905         } else {
 906                 TRACEx1(5, "seeking track %d", track);
 907                 result = ftape_command(QIC_SEEK_HEAD_TO_TRACK);
 908                 if (result < 0) {
 909                         TRACE(1, "ftape_command failed");
 910                 } else {
 911                         result = ftape_parameter_wait(track, timeout.head_seek, &status);
 912                         if (result < 0) {
 913                                 TRACE(1, "ftape_parameter_wait failed");
 914                         } else {
 915                                 location.track = track;
 916                                 might_be_off_track = 0;
 917                         }
 918                 }
 919         }
 920         TRACE_EXIT;
 921         return result;
 922 }
 923 
 924 int ftape_wakeup_drive(wake_up_types method)
     /* [previous][next][first][last][top][bottom][index][help] */
 925 {
 926         TRACE_FUN(8, "ftape_wakeup_drive");
 927         int result;
 928         int status;
 929         int motor_on = 0;
 930 
 931         switch (method) {
 932         case wake_up_colorado:
 933                 result = ftape_command(QIC_PHANTOM_SELECT);
 934                 if (result == 0) {
 935                         result = ftape_parameter( /* unit */ 0);
 936                 }
 937                 break;
 938         case wake_up_mountain:
 939                 result = ftape_command(QIC_SOFT_SELECT);
 940                 if (result == 0) {
 941                         ftape_sleep(MILLISECOND);       /* NEEDED */
 942                         result = ftape_parameter(18);
 943                 }
 944                 break;
 945         case wake_up_insight:
 946                 ftape_sleep(100 * MILLISECOND);
 947                 motor_on = 1;
 948                 fdc_motor(motor_on);    /* enable is done by motor-on */
 949         case no_wake_up:
 950                 result = 0;
 951                 break;
 952         default:
 953                 result = -ENODEV;       /* unknown wakeup method */
 954         }
 955         /*  If wakeup succeeded we should't get and error here..
 956          */
 957         if (result == 0) {
 958                 result = ftape_report_raw_drive_status(&status);
 959                 if (result < 0 && motor_on) {
 960                         fdc_motor(0);   /* motor off if failed */
 961                 }
 962         }
 963         TRACE_EXIT;
 964         return result;
 965 }
 966 
 967 int ftape_put_drive_to_sleep(vendor_struct drive_type)
     /* [previous][next][first][last][top][bottom][index][help] */
 968 {
 969         TRACE_FUN(8, "ftape_put_drive_to_sleep");
 970         int result;
 971 
 972         switch (drive_type.wake_up) {
 973         case wake_up_colorado:
 974                 result = ftape_command(QIC_PHANTOM_DESELECT);
 975                 break;
 976         case wake_up_mountain:
 977                 result = ftape_command(QIC_SOFT_DESELECT);
 978                 break;
 979         case wake_up_insight:
 980                 fdc_motor(0);   /* enable is done by motor-on */
 981         case no_wake_up:        /* no wakeup / no sleep ! */
 982                 result = 0;
 983                 break;
 984         default:
 985                 result = -ENODEV;       /* unknown wakeup method */
 986         }
 987         TRACE_EXIT;
 988         return result;
 989 }
 990 
 991 int ftape_reset_drive(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 992 {
 993         TRACE_FUN(8, "ftape_reset_drive");
 994         int result = 0;
 995         int status;
 996         int err_code;
 997         int err_command;
 998         int i;
 999 
1000         /*    We want to re-establish contact with our drive.
1001          *    Fire a number of reset commands (single step pulses)
1002          *    and pray for success.
1003          */
1004         for (i = 0; i < 2; ++i) {
1005                 TRACE(5, "Resetting fdc");
1006                 fdc_reset();
1007                 ftape_sleep(10 * MILLISECOND);
1008                 TRACE(5, "Reset command to drive");
1009                 result = ftape_command(QIC_RESET);
1010                 if (result == 0) {
1011                         ftape_sleep(1 * SECOND);        /* drive not accessible during 1 second */
1012                         TRACE(5, "Re-selecting drive");
1013                         /*  Strange, the QIC-117 specs don't mention this but the
1014                          *  drive gets deselected after a soft reset !
1015                          *  So we need to enable it again.
1016                          */
1017                         result = ftape_wakeup_drive(drive_type.wake_up);
1018                         if (result < 0) {
1019                                 TRACE(1, "Wakeup failed !");
1020                         }
1021                         TRACE(5, "Waiting until drive gets ready");
1022                         result = ftape_ready_wait(timeout.reset, &status);
1023                         if (result == 0 && status & QIC_STATUS_ERROR) {
1024                                 result = ftape_report_error(&err_code, &err_command, 1);
1025                                 if (result == 0 && err_code == 27) {
1026                                         /* Okay, drive saw reset command and responded as it should
1027                                          */
1028                                         break;
1029                                 } else {
1030                                         result = -EIO;
1031                                 }
1032                         } else {
1033                                 result = -EIO;
1034                         }
1035                 }
1036                 if (current->signal & _DONT_BLOCK) {
1037                         TRACE(1, "aborted by non-blockable signal");
1038                         result = -EINTR;
1039                         break;  /* exit on signal */
1040                 }
1041         }
1042         if (result != 0) {
1043                 TRACE(1, "General failure to reset tape drive");
1044         } else {
1045                 /*  Restore correct settings
1046                  */
1047                 ftape_set_data_rate(ftape_data_rate);   /* keep original rate */
1048         }
1049         TRACE_EXIT;
1050         return result;
1051 }

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