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

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