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

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