root/kernel/blk_drv/scsi/seagate.c

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

DEFINITIONS

This source file includes following definitions.
  1. seagate_st0x_detect
  2. seagate_st0x_info
  3. seagate_reconnect_intr
  4. seagate_st0x_queue_command
  5. seagate_st0x_command
  6. internal_command
  7. seagate_st0x_abort
  8. seagate_st0x_reset

   1 /*
   2  *      seagate.c Copyright (C) 1992 Drew Eckhardt 
   3  *      low level scsi driver for ST01/ST02 by
   4  *              Drew Eckhardt 
   5  *
   6  *      <drew@colorado.edu>
   7  */
   8 
   9 #include <linux/config.h>
  10 
  11 #if defined(CONFIG_SCSI_SEAGATE) || defined(CONFIG_SCSI_FD_88x) 
  12 #include <asm/io.h>
  13 #include <asm/system.h>
  14 #include <linux/signal.h>
  15 #include <linux/sched.h>
  16 #include "seagate.h"
  17 #include "scsi.h"
  18 #include "hosts.h"
  19 
  20 
  21 static int internal_command(unsigned char target, const void *cmnd,
  22                          void *buff, int bufflen, int reselect);
  23 
  24 static int incommand;                   /*
  25                                                 set if arbitration has finished and we are 
  26                                                 in some command phase.
  27                                         */
  28 
  29 static void *base_address = NULL;       /*
  30                                                 Where the card ROM starts,
  31                                                 used to calculate memory mapped
  32                                                 register location.
  33                                         */
  34 static volatile int abort_confirm = 0;
  35 
  36 static volatile void *st0x_cr_sr;       /*
  37                                                 control register write,
  38                                                 status register read.
  39                                                 256 bytes in length.
  40 
  41                                                 Read is status of SCSI BUS,
  42                                                 as per STAT masks.
  43 
  44                                         */
  45 
  46 
  47 static volatile void *st0x_dr;         /*
  48                                                 data register, read write
  49                                                 256 bytes in length.
  50                                         */
  51 
  52 
  53 static volatile int st0x_aborted=0;     /* 
  54                                                 set when we are aborted, ie by a time out, etc.
  55                                         */
  56 
  57                                         /*
  58                                                 In theory, we have a nice auto
  59                                                 detect routine - but this 
  60                                                 overides it. 
  61                                         */
  62 
  63                         
  64 #define retcode(result) (((result) << 16) | (message << 8) | status)                    
  65 #define STATUS (*(unsigned char *) st0x_cr_sr)
  66 #define CONTROL STATUS 
  67 #define DATA (*(unsigned char *) st0x_dr)
  68 
  69 #ifndef OVERRIDE                
  70 static const char *  seagate_bases[] = {(char *) 0xc8000, (char *) 0xca000, (char *) 0xcc000, (char *) 0xce000, (char *) 0xce000,
  71                                         (char *) 0xdc000, (char *) 0xde000};
  72 typedef struct 
  73         {
  74         char *signature ;
  75         unsigned offset;
  76         unsigned length;
  77         } Signature;
  78         
  79 static const Signature signatures[] = {
  80 #ifdef CONFIG_SCSI_SEAGATE
  81 {"SCSI BIOS 2.00  (C) Copyright 1987 Seagate", 15, 40},
  82 
  83 /*
  84         The following two lines are NOT mistakes.  One detects 
  85         ROM revision 3.0.0, the other 3.2.  Since seagate
  86         has only one type of SCSI adapter, and this is not 
  87         going to change, the "SEAGATE" and "SCSI" together
  88         are probably "good enough"
  89 */
  90 
  91 {"SEAGATE SCSI BIOS ",16, 17},
  92 {"SEAGATE SCSI BIOS ",17, 17},
  93 #endif
  94 
  95 /*
  96         This is for the Future Domain 88x series.  I've been told that
  97         the Seagate controllers are just repackages of these, and seeing
  98         early seagate BIOS bearing the Future Domain copyright,
  99         I believe it.
 100 */
 101 
 102 #ifdef CONFIG_SCSI_FD_88x
 103 {"FUTURE DOMAIN CORP. (C) 1986-1989 V6.0A7/28/90", 5, 46},
 104 #endif
 105 }
 106 ;
 107 /*
 108         Note that the last signature handles BIOS revisions 3.0.0 and 
 109         3.2 - the real ID's are 
 110 
 111 SEAGATE SCSI BIOS REVISION 3.0.0
 112 SEAGATE SCSI BIOS REVISION 3.2
 113 
 114 */
 115 
 116 #define NUM_SIGNATURES (sizeof(signatures) / sizeof(Signature))
 117 #endif
 118 
 119 /*
 120  * hostno stores the hostnumber, as told to us by the init routine.
 121  */
 122 
 123 static int hostno = -1;
 124 static void seagate_reconnect_intr(int);
 125 
 126 int seagate_st0x_detect (int hostnum)
     /* [previous][next][first][last][top][bottom][index][help] */
 127         {
 128 #ifndef OVERRIDE
 129         int i,j;
 130 #endif
 131 static struct sigaction seagate_sigaction = {
 132         &seagate_reconnect_intr,
 133         0,
 134         SA_INTERRUPT,
 135         NULL
 136 };
 137 
 138 /*
 139  *      First, we try for the manual override.
 140  */
 141 #ifdef DEBUG 
 142         printk("Autodetecting seagate ST0x\n");
 143 #endif
 144         
 145         if (hostno != -1)
 146                 {
 147                 printk ("ERROR : seagate_st0x_detect() called twice.\n");
 148                 return 0;
 149                 }
 150         
 151         base_address = NULL;
 152 #ifdef OVERRIDE
 153         base_address = (void *) OVERRIDE;       
 154 #ifdef DEBUG
 155         printk("Base address overridden to %x\n", base_address);
 156 #endif
 157 #else   
 158 /*
 159  *      To detect this card, we simply look for the signature
 160  *      from the BIOS version notice in all the possible locations
 161  *      of the ROM's.  This has a nice sideeffect of not trashing
 162  *      any register locations that might be used by something else.
 163  */
 164 
 165         for (i = 0; i < (sizeof (seagate_bases) / sizeof (char  * )); ++i)
 166                 for (j = 0; !base_address && j < NUM_SIGNATURES; ++j)
 167                 if (!memcmp ((void *) (seagate_bases[i] +
 168                     signatures[j].offset), (void *) signatures[j].signature,
 169                     signatures[j].length))
 170                         base_address = (void *) seagate_bases[i];
 171  #endif
 172  
 173         if (base_address)
 174                 {
 175                 st0x_cr_sr =(void *) (((unsigned char *) base_address) + 0x1a00); 
 176                 st0x_dr = (void *) (((unsigned char *) base_address )+ 0x1c00);
 177 #ifdef DEBUG
 178                 printk("ST0x detected. Base address = %x, cr = %x, dr = %x\n", base_address, st0x_cr_sr, st0x_dr);
 179 #endif
 180 /*
 181  *      At all times, we will use IRQ 5.  
 182  */
 183                 hostno = hostnum;
 184                 if (irqaction(5, &seagate_sigaction)) {
 185                         printk("Unable to allocate IRQ5 for ST0x driver\n");
 186                         return 0;
 187                 }
 188                 return -1;
 189                 }
 190         else
 191                 {
 192 #ifdef DEBUG
 193                 printk("ST0x not detected.\n");
 194 #endif
 195                 return 0;
 196                 }
 197         }
 198          
 199 char *seagate_st0x_info(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 200 {
 201         static char buffer[] = "Seagate ST-0X SCSI driver by Drew Eckhardt \n"
 202 "$Header: /usr/src/linux/kernel/blk_drv/scsi/RCS/seagate.c,v 1.1 1992/07/24 06:27:38 root Exp root $\n";
 203         return buffer;
 204 }
 205 
 206 /*
 207  * These are our saved pointers for the outstanding command that is 
 208  * waiting for a reconnect
 209  */
 210 
 211 static unsigned char current_target;
 212 static unsigned char *current_cmnd, *current_data;
 213 static int current_bufflen;
 214 static void (*done_fn)(int, int) = NULL;
 215 
 216 /*
 217  * These control whether or not disconnect / reconnect will be attempted,
 218  * or are being attempted.
 219  */
 220 
 221 #define NO_RECONNECT    0
 222 #define RECONNECT_NOW   1
 223 #define CAN_RECONNECT   2
 224 
 225 /*
 226  * This determines if we are expecting to reconnect or not.
 227  */
 228 
 229 static int should_reconnect = 0;
 230 
 231 /*
 232  * The seagate_reconnect_intr routine is called when a target reselects the 
 233  * host adapter.  This occurs on the interrupt triggered by the target 
 234  * asserting SEL.
 235  */
 236 
 237 static void seagate_reconnect_intr (int unused)
     /* [previous][next][first][last][top][bottom][index][help] */
 238         {
 239         int temp;
 240 
 241 /* enable all other interrupts. */      
 242         sti();
 243 #if (DEBUG & PHASE_RESELECT)
 244         printk("scsi%d : seagate_reconnect_intr() called\n", hostno);
 245 #endif
 246 
 247         if (!should_reconnect)
 248             printk("scsi%d: unexpected interrupt.\n", hostno);
 249         else
 250                 {
 251                 should_reconnect = 0;
 252 
 253 #if (DEBUG & PHASE_RESELECT)
 254                 printk("scsi%d : internal_command("
 255                        "%d, %08x, %08x, %d, RECONNECT_NOW\n", hostno, 
 256                         current_target, current_data, current_bufflen);
 257 #endif
 258         
 259                 temp =  internal_command (current_target, 
 260                         current_cmnd, current_data, current_bufflen,
 261                         RECONNECT_NOW);
 262 
 263                 if (msg_byte(temp) != DISCONNECT)
 264                         {
 265                         if (done_fn)
 266                                 {
 267 #if (DEBUG & PHASE_RESELECT)
 268                                 printk("scsi%d : done_fn(%d,%08x)", hostno, 
 269                                 hostno, temp);
 270 #endif
 271                                 done_fn (hostno, temp);
 272                                 }
 273                         else
 274                                 printk("done_fn() not defined.\n");
 275                         }
 276                 }
 277         } 
 278 
 279 /* 
 280  * The seagate_st0x_queue_command() function provides a queued interface
 281  * to the seagate SCSI driver.  Basically, it just passes control onto the
 282  * seagate_command() function, after fixing it so that the done_fn()
 283  * is set to the one passed to the function.
 284  */
 285 
 286 int seagate_st0x_queue_command (unsigned char target, const void *cmnd,
     /* [previous][next][first][last][top][bottom][index][help] */
 287                                 void *buff, int bufflen, void (*fn)(int, 
 288                                  int))
 289         {
 290         int result;
 291 
 292         done_fn = fn;
 293         current_target = target;
 294         (const void *) current_cmnd = cmnd;
 295         current_data = buff;
 296         current_bufflen = bufflen;
 297 
 298         result = internal_command (target, cmnd, buff, bufflen, 
 299                                    CAN_RECONNECT);
 300         if (msg_byte(result) == DISCONNECT)
 301                 return 0;
 302         else 
 303                 {
 304                 done_fn (hostno, result); 
 305                 return 1; 
 306                 }
 307         }
 308 
 309 int seagate_st0x_command (unsigned char target, const void *cmnd, 
     /* [previous][next][first][last][top][bottom][index][help] */
 310                         void *buff, int bufflen)
 311         {
 312         return internal_command (target, cmnd, buff, bufflen, 
 313                                  (int) NO_RECONNECT);
 314         }
 315         
 316 static int internal_command(unsigned char target, const void *cmnd,
     /* [previous][next][first][last][top][bottom][index][help] */
 317                          void *buff, int bufflen, int reselect)
 318         {
 319         int len;                        
 320         unsigned char *data;    
 321         int clock;                      
 322         int temp;
 323 
 324 
 325 #if ((DEBUG & PHASE_ETC) || (DEBUG & PRINT_COMMAND) || (DEBUG & PHASE_EXIT))    
 326         int i;
 327 #endif
 328 
 329 #if (DEBUG & PHASE_ETC)
 330         int phase=0, newphase;
 331 #endif
 332 
 333         int done = 0;
 334         unsigned char status = 0;       
 335         unsigned char message = 0;
 336         register unsigned char status_read;
 337 
 338         len=bufflen;
 339         data=(unsigned char *) buff;
 340 
 341         incommand = 0;
 342         st0x_aborted = 0;
 343 
 344 #if (DEBUG & PRINT_COMMAND)
 345         printk ("scsi%d : target = %d, command = ", hostno, target);
 346         for (i = 0; i < COMMAND_SIZE(((unsigned char *)cmnd)[0]); ++i)
 347                 printk("%02x ",  ((unsigned char *) cmnd)[i]);
 348         printk("\n");
 349 #endif
 350 
 351 #if (DEBUG & PHASE_RESELECT)
 352         switch (reselect)
 353         {
 354         case RECONNECT_NOW :
 355                 printk("scsi%d : reconnecting\n", hostno);
 356                 break;
 357         case CAN_RECONNECT :
 358                 printk("scsi%d : allowed to reconnect\n", hostno);
 359                 break;
 360         default :
 361                 printk("scsi%d : not allowed to reconnect\n", hostno);
 362         }
 363 #endif
 364         
 365 
 366         if (target > 6)
 367                 return DID_BAD_TARGET;
 368 
 369 /*
 370  *      We work it differently depending on if this is is "the first time,"
 371  *      or a reconnect.  If this is a reselct phase, then SEL will 
 372  *      be asserted, and we must skip selection / arbitration phases.
 373  */
 374 
 375         if (reselect == RECONNECT_NOW) 
 376                 {
 377 #if (DEBUG & PHASE_RESELECT)
 378                 printk("scsi%d : phase RESELECT \n", hostno);
 379 #endif
 380 
 381 /*
 382  *      At this point, we should find the logical or of our ID and the original
 383  *      target's ID on the BUS, with BSY, SEL, and I/O signals asserted.
 384  *
 385  *      After ARBITRATION phase is completed, only SEL, BSY, and the 
 386  *      target ID are asserted.  A valid initator ID is not on the bus
 387  *      until IO is asserted, so we must wait for that.
 388  */
 389                 
 390                 for (clock = jiffies + 10, temp = 0; (jiffies < clock) &&
 391                      !(STATUS & STAT_IO););
 392                 
 393                 if (jiffies >= clock)
 394                         {
 395 #if (DEBUG & PHASE_RESELECT)
 396                         printk("scsi%d : RESELECT timed out while waiting for IO .\n",
 397                                 hostno);
 398 #endif
 399                         return (DID_BAD_INTR << 16);
 400                         }
 401 
 402 /* 
 403  *      After I/O is asserted by the target, we can read our ID and its
 404  *      ID off of the BUS.
 405  */
 406  
 407                 if (!((temp = DATA) & 0x80))
 408                         {
 409 #if (DEBUG & PHASE_RESELECT)
 410                         printk("scsi%d : detected reconnect request to different target.\n" 
 411                                "\tData bus = %d\n", hostno, temp);
 412 #endif
 413                         return (DID_BAD_INTR << 16);
 414                         }
 415 
 416                 if (!(temp & (1 << current_target)))
 417                         {
 418                         printk("scsi%d : Unexpected reselect interrupt.  Data bus = %d\n",
 419                                 hostno, temp);
 420                         return (DID_BAD_INTR << 16);
 421                         }
 422                 data=current_data;      /* WDE add */
 423                 cmnd=current_cmnd;      /* WDE add */
 424                 len=current_bufflen;    /* WDE add */
 425 
 426 /*
 427  *      We have determined that we have been selected.  At this point, 
 428  *      we must respond to the reselection by asserting BSY ourselves
 429  */
 430 
 431                 CONTROL = (BASE_CMD | CMD_DRVR_ENABLE | CMD_BSY);
 432 
 433 /*
 434  *      The target will drop SEL, and raise BSY, at which time we must drop
 435  *      BSY.
 436  */
 437 
 438                 for (clock = jiffies + 10; (jiffies < clock) &&  (STATUS & STAT_SEL););
 439 
 440                 if (jiffies >= clock)
 441                         { 
 442                         CONTROL = (BASE_CMD | CMD_INTR);
 443 #if (DEBUG & PHASE_RESELECT)
 444                         printk("scsi%d : RESELECT timed out while waiting for SEL.\n",
 445                                 hostno);
 446 #endif
 447                         return (DID_BAD_INTR << 16);                             
 448                         }
 449 
 450                 CONTROL = BASE_CMD;
 451 
 452 /*
 453  *      At this point, we have connected with the target and can get 
 454  *      on with our lives.
 455  */      
 456                 }       
 457         else
 458                 {       
 459 #if (DEBUG & PHASE_BUS_FREE)
 460                 printk ("scsi%d : phase = BUS FREE \n", hostno);
 461 #endif
 462 
 463 /*
 464  *      BUS FREE PHASE
 465  *
 466  *      On entry, we make sure that the BUS is in a BUS FREE
 467  *      phase, by insuring that both BSY and SEL are low for
 468  *      at least one bus settle delay.  Several reads help
 469  *      eliminate wire glitch.
 470  */
 471 
 472                 clock = jiffies + ST0X_BUS_FREE_DELAY;  
 473 
 474                 while (((STATUS |  STATUS | STATUS) & 
 475                          (STAT_BSY | STAT_SEL)) && 
 476                          (!st0x_aborted) && (jiffies < clock));
 477 
 478                 if (jiffies > clock)
 479                         return retcode(DID_BUS_BUSY);
 480                 else if (st0x_aborted)
 481                         return retcode(st0x_aborted);
 482 
 483 /*
 484  *      Bus free has been detected, within BUS settle.  I used to 
 485  *      support an arbitration phase - however, on the Seagate, this 
 486  *      degraded performance by a factor > 10 - so it is no more.
 487  */
 488 
 489 /*
 490  *      SELECTION PHASE
 491  *
 492  *      Now, we select the disk, giving it the SCSI ID at data
 493  *      and a command of PARITY if necessary, and we raise SEL.
 494  */
 495 
 496 #if (DEBUG & PHASE_SELECTION)
 497                 printk("scsi%d : phase = SELECTION\n", hostno);
 498 #endif
 499 
 500                 clock = jiffies + ST0X_SELECTION_DELAY;
 501 
 502 /*
 503  *      If we wish to disconnect, we should request a MESSAGE OUT
 504  *      at this point.  Technically, ATTN should be raised before 
 505  *      SEL = true and BSY = false (from arbitration), but I think this 
 506  *      should do.
 507  */
 508                 if (reselect)
 509                         CONTROL = BASE_CMD | CMD_DRVR_ENABLE |
 510                                 CMD_ATTN;
 511                 
 512 /*
 513  *      We must assert both our ID and our target's ID on the bus.
 514  */
 515                 DATA = (unsigned char) ((1 << target) | 0x80);
 516 
 517 /*
 518  *      If we are allowing ourselves to reconnect, then I will keep 
 519  *      ATTN raised so we get MSG OUT. 
 520  */ 
 521                 CONTROL =  BASE_CMD | CMD_DRVR_ENABLE | CMD_SEL | 
 522                         (reselect ? CMD_ATTN : 0);
 523 
 524 /*
 525  *      When the SCSI device decides that we're gawking at it, it will 
 526  *      respond by asserting BUSY on the bus.
 527  */
 528                 while (!((status_read = STATUS) & STAT_BSY) && 
 529                         (jiffies < clock) && !st0x_aborted)
 530 
 531 #if (DEBUG & PHASE_SELECTION)
 532                 {
 533                 temp = clock - jiffies;
 534 
 535                 if (!(jiffies % 5))
 536                         printk("seagate_st0x_timeout : %d            \r",temp);
 537         
 538                 }
 539                 printk("Done.                                             \n\r");
 540                 printk("scsi%d : status = %02x, seagate_st0x_timeout = %d, aborted = %02x \n", 
 541                         hostno, status_read, temp, st0x_aborted);
 542 #else
 543                 ;
 544 #endif
 545         
 546 
 547                 if ((jiffies > clock)  || (!st0x_aborted && 
 548                         !(status_read & STAT_BSY)))
 549                         {
 550 #if (DEBUG & PHASE_SELECT)
 551                         printk ("scsi%d : NO CONNECT with target %d, status = %x \n", 
 552                                 hostno, target, STATUS);
 553 #endif
 554                         return retcode(DID_NO_CONNECT);
 555                         }
 556 
 557 /*
 558  *      If we have been aborted, and we have a command in progress, IE the 
 559  *      target still has BSY asserted, then we will reset the bus, and 
 560  *      notify the midlevel driver to expect sense.
 561  */
 562 
 563                 if (st0x_aborted)
 564                         {
 565                         CONTROL = BASE_CMD;
 566                         if (STATUS & STAT_BSY)
 567                                 {
 568                                 seagate_st0x_reset();
 569                                 return retcode(DID_RESET);
 570                                 }
 571                         return retcode(st0x_aborted);
 572                         }       
 573                 }
 574 
 575         CONTROL = BASE_CMD | CMD_DRVR_ENABLE | 
 576                 ((reselect == CAN_RECONNECT) ? CMD_ATTN : 0) ;
 577         
 578 /*
 579  *      INFORMATION TRANSFER PHASE
 580  *
 581  *      The nasty looking read / write inline assembler loops we use for 
 582  *      DATAIN and DATAOUT phases are approximately 4-5 times as fast as 
 583  *      the 'C' versions - since we're moving 1024 bytes of data, this
 584  *      really adds up.
 585  */
 586 
 587 #if (DEBUG & PHASE_ETC)
 588         printk("scsi%d : phase = INFORMATION TRANSFER\n", hostno);
 589 #endif  
 590 
 591         incommand = 1;
 592 
 593 
 594 /*
 595  *      Now, we poll the device for status information,
 596  *      and handle any requests it makes.  Note that since we are unsure of 
 597  *      how much data will be flowing across the system, etc and cannot 
 598  *      make reasonable timeouts, that we will instead have the midlevel
 599  *      driver handle any timeouts that occur in this phase.
 600  */
 601 
 602         while (((status_read = STATUS) & STAT_BSY) && !st0x_aborted && !done) 
 603                 {
 604 #ifdef PARITY
 605                 if (status_read & STAT_PARITY)
 606                         {
 607                         done = 1;
 608                         st0x_aborted = DID_PARITY;
 609                         }       
 610 #endif
 611 
 612                 if (status_read & STAT_REQ)
 613                         {
 614 #if (DEBUG & PHASE_ETC)
 615                         if ((newphase = (status_read & REQ_MASK)) != phase)
 616                                 {
 617                                 phase = newphase;
 618                                 switch (phase)
 619                                 {
 620                                 case REQ_DATAOUT: 
 621                                         printk("scsi%d : phase = DATA OUT\n",
 622                                                 hostno); 
 623                                         break;
 624                                 case REQ_DATAIN : 
 625                                         printk("scsi%d : phase = DATA IN\n",
 626                                                 hostno); 
 627                                         break;
 628                                 case REQ_CMDOUT : 
 629                                         printk("scsi%d : phase = COMMAND OUT\n",
 630                                                 hostno); 
 631                                         break;
 632                                 case REQ_STATIN :
 633                                          printk("scsi%d : phase = STATUS IN\n",
 634                                                 hostno); 
 635                                         break;
 636                                 case REQ_MSGOUT :
 637                                         printk("scsi%d : phase = MESSAGE OUT\n",
 638                                                 hostno); 
 639                                         break;
 640                                 case REQ_MSGIN :
 641                                         printk("scsi%d : phase = MESSAGE IN\n",
 642                                                 hostno);
 643                                         break;
 644                                 default : 
 645                                         printk("scsi%d : phase = UNKNOWN\n",
 646                                                 hostno); 
 647                                         st0x_aborted = 1; 
 648                                         done = 1;
 649                                 }       
 650                                 }
 651 #endif
 652 
 653                 switch (status_read & REQ_MASK)
 654                 {                       
 655                 case REQ_DATAOUT : 
 656 
 657 /*
 658  *      We loop as long as we are in a data out phase, there is data to send, 
 659  *      and BSY is still active.
 660  */
 661                 __asm__ ("
 662 
 663 /*
 664         Local variables : 
 665         len = ecx
 666         data = esi
 667         st0x_cr_sr = ebx
 668         st0x_dr =  edi
 669 
 670         Test for any data here at all.
 671 */
 672         movl %0, %%esi          /* local value of data */
 673         movl %1, %%ecx          /* local value of len */        
 674         orl %%ecx, %%ecx
 675         jz 2f
 676 
 677         cld
 678 
 679         movl _st0x_cr_sr, %%ebx
 680         movl _st0x_dr, %%edi
 681         
 682 1:      movb (%%ebx), %%al
 683 /*
 684         Test for BSY
 685 */
 686 
 687         test $1, %%al 
 688         jz 2f
 689 
 690 /*
 691         Test for data out phase - STATUS & REQ_MASK should be REQ_DATAOUT, which is 0.
 692 */
 693         test $0xe, %%al
 694         jnz 2f  
 695 /*
 696         Test for REQ
 697 */      
 698         test $0x10, %%al
 699         jz 1b
 700         lodsb
 701         movb %%al, (%%edi) 
 702         loop 1b
 703 
 704 2: 
 705         movl %%esi, %2
 706         movl %%ecx, %3
 707                                                                         ":
 708 /* output */
 709 "=r" (data), "=r" (len) :
 710 /* input */
 711 "0" (data), "1" (len) :
 712 /* clobbered */
 713 "ebx", "ecx", "edi", "esi"); 
 714 
 715                         break;
 716 
 717                 case REQ_DATAIN : 
 718 /*
 719  *      We loop as long as we are in a data in phase, there is room to read, 
 720  *      and BSY is still active
 721  */
 722  
 723                         __asm__ ("
 724 /*
 725         Local variables : 
 726         ecx = len
 727         edi = data
 728         esi = st0x_cr_sr
 729         ebx = st0x_dr
 730 
 731         Test for room to read
 732 */
 733 
 734         movl %0, %%edi          /* data */
 735         movl %1, %%ecx          /* len */
 736         orl %%ecx, %%ecx
 737         jz 2f
 738 
 739         cld
 740         movl _st0x_cr_sr, %%esi
 741         movl _st0x_dr, %%ebx
 742 
 743 1:      movb (%%esi), %%al
 744 /*
 745         Test for BSY
 746 */
 747 
 748         test $1, %%al 
 749         jz 2f
 750 
 751 /*
 752         Test for data in phase - STATUS & REQ_MASK should be REQ_DATAIN, = STAT_IO, which is 4.
 753 */
 754         movb $0xe, %%ah 
 755         andb %%al, %%ah
 756         cmpb $0x04, %%ah
 757         jne 2f
 758                 
 759 /*
 760         Test for REQ
 761 */      
 762         test $0x10, %%al
 763         jz 1b
 764 
 765         movb (%%ebx), %%al      
 766         stosb   
 767         loop 1b
 768 
 769 2:      movl %%edi, %2          /* data */
 770         movl %%ecx, %3          /* len */
 771                                                                         ":
 772 /* output */
 773 "=r" (data), "=r" (len) :
 774 /* input */
 775 "0" (data), "1" (len) :
 776 /* clobbered */
 777 "ebx", "ecx", "edi", "esi"); 
 778                         break;
 779 
 780                 case REQ_CMDOUT : 
 781                         while (((status_read = STATUS) & STAT_BSY) && 
 782                                ((status_read & REQ_MASK) == REQ_CMDOUT))
 783                                 if (status_read & STAT_REQ)
 784                                         DATA = *(unsigned char *) cmnd ++;
 785                         break;
 786         
 787                 case REQ_STATIN : 
 788                         status = DATA;
 789                         break;
 790                                 
 791                 case REQ_MSGOUT : 
 792 /*
 793  *      We can only have sent a MSG OUT if we requested to do this 
 794  *      by raising ATTN.  So, we must drop ATTN.
 795  */
 796 
 797                         CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
 798 /*
 799  *      If we are reconecting, then we must send an IDENTIFY message in 
 800  *       response  to MSGOUT.
 801  */
 802                         if (reselect)
 803                                 {
 804                                 DATA = IDENTIFY(1,0);
 805 #if (DEBUG & (PHASE_RESELECT | PHASE_MSGOUT)) 
 806                                 printk("scsi%d : sent IDENTIFY message.\n", hostno);
 807 #endif
 808                                 }
 809                         else  
 810                                 {
 811                                 DATA = MESSAGE_REJECT;
 812                                 
 813 #if (DEBUG & PHASE_MSGOUT)
 814                                 printk("scsi%d : sent MESSAGE REJECT message.\n", hostno);
 815 #endif
 816                                 }
 817                         break;
 818                                         
 819                 case REQ_MSGIN : 
 820                         switch (message = DATA)
 821                         {
 822                         case DISCONNECT :
 823                                 should_reconnect = 1;
 824                                 current_data = data;    /* WDE add */
 825                                 current_bufflen = len;  /* WDE add */
 826 #if (DEBUG & (PHASE_RESELECT | PHASE_MSGIN))
 827                                 printk("scsi%d : disconnected.\n", hostno);
 828                                 done=1;
 829                                 break;
 830 #endif
 831                         case COMMAND_COMPLETE :
 832 #if (DEBUG & PHASE_MSGIN)       
 833                                 printk("scsi%d : command complete.\n", hostno);
 834                                 done=1;
 835                                 break;
 836 #endif
 837                         case ABORT :
 838 #if (DEBUG & PHASE_MSGIN)
 839                                 printk("scsi%d : abort message.\n", hostno);
 840 #endif
 841                                 done=1;
 842                                 break;
 843                         case SAVE_POINTERS :
 844                                 current_data = data;    /* WDE mod */
 845                                 current_bufflen = len;  /* WDE add */
 846 #if (DEBUG & PHASE_MSGIN)
 847                                 printk("scsi%d : pointers saved.\n", hostno);
 848 #endif 
 849                                 break;
 850                         case RESTORE_POINTERS:
 851                                 data=current_data;      /* WDE mod */
 852                                 cmnd=current_cmnd;
 853 #if (DEBUG & PHASE_MSGIN)
 854                                 printk("scsi%d : pointers restored.\n", hostno);
 855 #endif
 856                                 break;
 857                         default:
 858 
 859 /*
 860  *      IDENTIFY distinguishes itself from the other messages by setting the
 861  *      high byte.
 862  */
 863 
 864                                 if (message & 0x80)
 865                                         {
 866 #if (DEBUG & PHASE_MSGIN)
 867                                         printk("scsi%d : IDENTIFY message received from id %d, lun %d.\n",
 868                                                 hostno, target, message & 7);
 869 #endif
 870                                         }       
 871                                 else
 872                                         {
 873                         
 874 #if (DEBUG & PHASE_MSGIN)
 875                                         printk("scsi%d : unknown message %d from target %d.\n",
 876                                                 hostno,  message,   target);
 877 #endif  
 878                                         }
 879                         }
 880                         break;
 881 
 882                 default : 
 883                         printk("scsi%d : unknown phase.\n", hostno); 
 884                         st0x_aborted = DID_ERROR; 
 885                 }       
 886                 } /* while ends */
 887                 } /* if ends */
 888 
 889 #if (DEBUG & (PHASE_DATAIN | PHASE_DATAOUT | PHASE_EXIT))
 890         printk("Transfered %d bytes, allowed %d additional bytes\n", (bufflen - len), len);
 891 #endif
 892 
 893 #if (DEBUG & PHASE_EXIT)
 894         printk("Buffer : \n");
 895         for (i = 0; i < 20; ++i) 
 896                 printk ("%02x  ", ((unsigned char *) data)[i]); /* WDE mod */
 897         printk("\n");
 898         printk("Status = %02x, message = %02x\n", status, message);
 899 #endif
 900 
 901         
 902         if (st0x_aborted)
 903                 {
 904                 if (STATUS & STAT_BSY)
 905                         {
 906                         seagate_st0x_reset();
 907                         st0x_aborted = DID_RESET;
 908                         }
 909                 abort_confirm = 1;
 910                 }               
 911 
 912         if (should_reconnect)
 913                 {
 914 #if (DEBUG & PHASE_RESELECT)
 915                 printk("scsi%d : exiting seagate_st0x_queue_command() with reconnect enabled.\n",
 916                         hostno);
 917 #endif
 918                 CONTROL = BASE_CMD | CMD_INTR ;
 919                 }
 920         else
 921                 CONTROL = BASE_CMD;
 922 
 923         return retcode (st0x_aborted);
 924         }
 925 
 926 int seagate_st0x_abort (int code)
     /* [previous][next][first][last][top][bottom][index][help] */
 927         {
 928         if (code)
 929                 st0x_aborted = code;
 930         else
 931                 st0x_aborted = DID_ABORT;
 932 
 933                 return 0;
 934         }
 935 
 936 /*
 937         the seagate_st0x_reset function resets the SCSI bus
 938 */
 939         
 940 int seagate_st0x_reset (void)
     /* [previous][next][first][last][top][bottom][index][help] */
 941         {
 942         unsigned clock;
 943         /*
 944                 No timeouts - this command is going to fail because 
 945                 it was reset.
 946         */
 947 
 948 #ifdef DEBUG
 949         printk("In seagate_st0x_reset()\n");
 950 #endif
 951 
 952 
 953         /* assert  RESET signal on SCSI bus.  */
 954                 
 955         CONTROL = BASE_CMD  | CMD_RST;
 956         clock=jiffies+2;
 957 
 958         
 959         /* Wait.  */
 960         
 961         while (jiffies < clock);
 962 
 963         CONTROL = BASE_CMD;
 964         
 965         st0x_aborted = DID_RESET;
 966 
 967 #ifdef DEBUG
 968         printk("SCSI bus reset.\n");
 969 #endif
 970         return 0;
 971         }
 972 
 973 #endif  
 974 

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