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

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