root/drivers/scsi/qlogic.c

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

DEFINITIONS

This source file includes following definitions.
  1. ql_zap
  2. ql_pdma
  3. ql_wai
  4. ql_icmd
  5. ql_pcmd
  6. ql_ihandl
  7. qlidone
  8. qlogic_command
  9. qlogic_queuecommand
  10. qlogic_queuecommand
  11. qlogic_preset
  12. qlogic_detect
  13. qlogic_biosparam
  14. qlogic_abort
  15. qlogic_reset
  16. qlogic_info

   1 /*----------------------------------------------------------------*/
   2 /*
   3    Qlogic linux driver - work in progress. No Warranty express or implied.
   4    Use at your own risk.  Support Tort Reform so you won't have to read all
   5    these silly disclaimers.
   6 
   7    Copyright 1994, Tom Zerucha.   
   8    zerucha@shell.portal.com
   9 
  10    Additional Code, and much appreciated help by
  11    Michael A. Griffith
  12    grif@cs.ucr.edu
  13 
  14    Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA
  15    help respectively, and for suffering through my foolishness during the
  16    debugging process.
  17 
  18    Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994
  19    (you can reference it, but it is incomplete and inaccurate in places)
  20 
  21    Version 0.43 4/6/95 - kernel 1.2.0+, pcmcia 2.5.4+
  22 
  23    Functions as standalone, loadable, and PCMCIA driver, the latter from
  24    Dave Hind's PCMCIA package.
  25 
  26    Redistributable under terms of the GNU Public License
  27 
  28 */
  29 /*----------------------------------------------------------------*/
  30 /* Configuration */
  31 
  32 /* Set the following to 2 to use normal interrupt (active high/totempole-
  33    tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open
  34    drain */
  35 #define QL_INT_ACTIVE_HIGH 2
  36 
  37 /* Set the following to 1 to enable the use of interrupts.  Note that 0 tends
  38    to be more stable, but slower (or ties up the system more) */
  39 #define QL_USE_IRQ 1
  40 
  41 /* Set the following to max out the speed of the PIO PseudoDMA transfers,
  42    again, 0 tends to be slower, but more stable.  */
  43 #define QL_TURBO_PDMA 1
  44 
  45 /* This should be 1 to enable parity detection */
  46 #define QL_ENABLE_PARITY 1
  47 
  48 /* This will reset all devices when the driver is initialized (during bootup).
  49    The other linux drivers don't do this, but the DOS drivers do, and after
  50    using DOS or some kind of crash or lockup this will bring things back
  51    without requiring a cold boot.  It does take some time to recover from a
  52    reset, so it is slower, and I have seen timeouts so that devices weren't
  53    recognized when this was set. */
  54 #define QL_RESET_AT_START 0
  55 
  56 /* crystal frequency in megahertz (for offset 5 and 9)
  57    Please set this for your card.  Most Qlogic cards are 40 Mhz.  The
  58    Control Concepts ISA (not VLB) is 24 Mhz */
  59 #define XTALFREQ        40
  60 
  61 /**********/
  62 /* DANGER! modify these at your own risk */
  63 /* SLOWCABLE can usually be reset to zero if you have a clean setup and
  64    proper termination.  The rest are for synchronous transfers and other
  65    advanced features if your device can transfer faster than 5Mb/sec.
  66    If you are really curious, email me for a quick howto until I have
  67    something official */
  68 /**********/
  69 
  70 /*****/
  71 /* config register 1 (offset 8) options */
  72 /* This needs to be set to 1 if your cabling is long or noisy */
  73 #define SLOWCABLE 1
  74 
  75 /*****/
  76 /* offset 0xc */
  77 /* This will set fast (10Mhz) synchronous timing when set to 1
  78    For this to have an effect, FASTCLK must also be 1 */
  79 #define FASTSCSI 0
  80 
  81 /* This when set to 1 will set a faster sync transfer rate */
  82 #define FASTCLK 0
  83 /*(XTALFREQ>25?1:0)*/
  84 
  85 /*****/
  86 /* offset 6 */
  87 /* This is the sync transfer divisor, XTALFREQ/X will be the maximum
  88    achievable data rate (assuming the rest of the system is capable
  89    and set properly) */
  90 #define SYNCXFRPD 5
  91 /*(XTALFREQ/5)*/
  92 
  93 /*****/
  94 /* offset 7 */
  95 /* This is the count of how many synchronous transfers can take place
  96         i.e. how many reqs can occur before an ack is given.
  97         The maximum value for this is 15, the upper bits can modify
  98         REQ/ACK assertion and deassertion during synchronous transfers
  99         If this is 0, the bus will only transfer asynchronously */
 100 #define SYNCOFFST 0
 101 /* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles
 102         of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will
 103         cause the deassertion to be early by 1/2 clock.  Bits 5&4 control
 104         the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */
 105 
 106 /*----------------------------------------------------------------*/
 107 #ifdef PCMCIA
 108 #undef QL_INT_ACTIVE_HIGH
 109 #define QL_INT_ACTIVE_HIGH 0
 110 #define MODULE
 111 #endif 
 112 
 113 #if defined(MODULE)
 114 #include <linux/config.h>
 115 #include <linux/module.h>
 116 #endif
 117 
 118 #ifdef PCMCIA
 119 #undef MODULE
 120 #endif 
 121 
 122 #include "../block/blk.h"       /* to get disk capacity */
 123 #include <linux/kernel.h>
 124 #include <linux/string.h>
 125 #include <linux/ioport.h>
 126 #include <linux/sched.h>
 127 #include <linux/proc_fs.h>
 128 #include <linux/unistd.h>
 129 #include <asm/io.h>
 130 #include <asm/irq.h>
 131 #include "sd.h"
 132 #include "hosts.h"
 133 #include "qlogic.h"
 134 
 135 /*----------------------------------------------------------------*/
 136 /* driver state info, local to driver */
 137 static int          qbase = 0;  /* Port */
 138 static int          qinitid;    /* initiator ID */
 139 static int          qabort;     /* Flag to cause an abort */
 140 static int          qlirq = -1; /* IRQ being used */
 141 static char         qinfo[80];  /* description */
 142 static Scsi_Cmnd   *qlcmd;      /* current command being processed */
 143 
 144 static int          qlcfg5 = ( XTALFREQ << 5 ); /* 15625/512 */
 145 static int          qlcfg6 = SYNCXFRPD;
 146 static int          qlcfg7 = SYNCOFFST;
 147 static int          qlcfg8 = ( SLOWCABLE << 7 ) | ( QL_ENABLE_PARITY << 4 );
 148 static int          qlcfg9 = ( ( XTALFREQ + 4 ) / 5 );
 149 static int          qlcfgc = ( FASTCLK << 3 ) | ( FASTSCSI << 4 );
 150 
 151 /*----------------------------------------------------------------*/
 152 /* The qlogic card uses two register maps - These macros select which one */
 153 #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
 154 #define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd ))
 155 
 156 /* following is watchdog timeout in microseconds */
 157 #define WATCHDOG 5000000
 158 
 159 /*----------------------------------------------------------------*/
 160 /* the following will set the monitor border color (useful to find
 161    where something crashed or gets stuck at and as a simple profiler) */
 162 
 163 #if 0
 164 #define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);}
 165 #else
 166 #define rtrc(i) {}
 167 #endif
 168 
 169 /*----------------------------------------------------------------*/
 170 /* local functions */
 171 /*----------------------------------------------------------------*/
 172 static void     ql_zap(void);
 173 /* error recovery - reset everything */
 174 void    ql_zap()
     /* [previous][next][first][last][top][bottom][index][help] */
 175 {
 176 int     x;
 177 unsigned long   flags;
 178         save_flags( flags );
 179         cli();
 180         x = inb(qbase + 0xd);
 181         REG0;
 182         outb(3, qbase + 3);                             /* reset SCSI */
 183         outb(2, qbase + 3);                             /* reset chip */
 184         if (x & 0x80)
 185                 REG1;
 186         restore_flags( flags );
 187 }
 188 
 189 /*----------------------------------------------------------------*/
 190 /* do pseudo-dma */
 191 static int      ql_pdma(int phase, char *request, int reqlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 192 {
 193 int     j;
 194         j = 0;
 195         if (phase & 1) {        /* in */
 196 #if QL_TURBO_PDMA
 197 rtrc(4)
 198                 /* empty fifo in large chunks */
 199                 if( reqlen >= 128 && (inb( qbase + 8 ) & 2) ) { /* full */
 200                         insl( qbase + 4, request, 32 );
 201                         reqlen -= 128;
 202                         request += 128;
 203                 }
 204                 while( reqlen >= 84 && !( j & 0xc0 ) ) /* 2/3 */
 205                         if( (j=inb( qbase + 8 )) & 4 ) {
 206                                 insl( qbase + 4, request, 21 );
 207                                 reqlen -= 84;
 208                                 request += 84;
 209                         }
 210                 if( reqlen >= 44 && (inb( qbase + 8 ) & 8) ) {  /* 1/3 */
 211                         insl( qbase + 4, request, 11 );
 212                         reqlen -= 44;
 213                         request += 44;
 214                 }
 215 #endif
 216                 /* until both empty and int (or until reclen is 0) */
 217 rtrc(7)
 218                 j = 0;
 219                 while( reqlen && !( (j & 0x10) && (j & 0xc0) ) ) {
 220                         /* while bytes to receive and not empty */
 221                         j &= 0xc0;
 222                         while ( reqlen && !( (j=inb(qbase + 8)) & 0x10 ) ) {
 223                                 *request++ = inb(qbase + 4);
 224                                 reqlen--;
 225                         }
 226                         if( j & 0x10 )
 227                                 j = inb(qbase+8);
 228 
 229                 }
 230         }
 231         else {  /* out */
 232 #if QL_TURBO_PDMA
 233 rtrc(4)
 234                 if( reqlen >= 128 && inb( qbase + 8 ) & 0x10 ) { /* empty */
 235                         outsl(qbase + 4, request, 32 );
 236                         reqlen -= 128;
 237                         request += 128;
 238                 }
 239                 while( reqlen >= 84 && !( j & 0xc0 ) ) /* 1/3 */
 240                         if( !((j=inb( qbase + 8 )) & 8) ) {
 241                                 outsl( qbase + 4, request, 21 );
 242                                 reqlen -= 84;
 243                                 request += 84;
 244                         }
 245                 if( reqlen >= 40 && !(inb( qbase + 8 ) & 4 ) ) { /* 2/3 */
 246                         outsl( qbase + 4, request, 10 );
 247                         reqlen -= 40;
 248                         request += 40;
 249                 }
 250 #endif
 251                 /* until full and int (or until reclen is 0) */
 252 rtrc(7)
 253                 j = 0;
 254                 while( reqlen && !( (j & 2) && (j & 0xc0) ) ) {
 255                         /* while bytes to send and not full */
 256                         while ( reqlen && !( (j=inb(qbase + 8)) & 2 ) ) {
 257                                 outb(*request++, qbase + 4);
 258                                 reqlen--;
 259                         }
 260                         if( j & 2 )
 261                                 j = inb(qbase+8);
 262                 }
 263         }
 264 /* maybe return reqlen */
 265         return inb( qbase + 8 ) & 0xc0;
 266 }
 267 
 268 /*----------------------------------------------------------------*/
 269 /* wait for interrupt flag (polled - not real hardware interrupt) */
 270 static int      ql_wai(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 271 {
 272 int     i,k;
 273         k = 0;
 274         i = jiffies + WATCHDOG;
 275         while ( i > jiffies && !qabort && !((k = inb(qbase + 4)) & 0xe0))
 276                 barrier();
 277         if (i <= jiffies)
 278                 return (DID_TIME_OUT);
 279         if (qabort)
 280                 return (qabort == 1 ? DID_ABORT : DID_RESET);
 281         if (k & 0x60)
 282                 ql_zap();
 283         if (k & 0x20)
 284                 return (DID_PARITY);
 285         if (k & 0x40)
 286                 return (DID_ERROR);
 287         return 0;
 288 }
 289 
 290 /*----------------------------------------------------------------*/
 291 /* initiate scsi command - queueing handler */
 292 static void     ql_icmd(Scsi_Cmnd * cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 293 {
 294 unsigned int        i;
 295 unsigned long   flags;
 296 
 297         qabort = 0;
 298 
 299         save_flags( flags );
 300         cli();
 301         REG0;
 302 /* clearing of interrupts and the fifo is needed */
 303         inb(qbase + 5);                         /* clear interrupts */
 304         if (inb(qbase + 5))                     /* if still interrupting */
 305                 outb(2, qbase + 3);             /* reset chip */
 306         else if (inb(qbase + 7) & 0x1f)
 307                 outb(1, qbase + 3);             /* clear fifo */
 308         while (inb(qbase + 5));                 /* clear ints */
 309         REG1;
 310         outb(1, qbase + 8);                     /* set for PIO pseudo DMA */
 311         outb(0, qbase + 0xb);                   /* disable ints */
 312         inb(qbase + 8);                         /* clear int bits */
 313         REG0;
 314         outb(0x40, qbase + 0xb);                /* enable features */
 315 
 316 /* configurables */
 317         outb( qlcfgc , qbase + 0xc);
 318 /* config: no reset interrupt, (initiator) bus id */
 319         outb( 0x40 | qlcfg8 | qinitid, qbase + 8);
 320         outb( qlcfg7 , qbase + 7 );
 321         outb( qlcfg6 , qbase + 6 );
 322 /**/
 323         outb(qlcfg5, qbase + 5);                /* select timer */
 324         outb(qlcfg9 & 7, qbase + 9);                    /* prescaler */
 325 /*      outb(0x99, qbase + 5);  */
 326         outb(cmd->target, qbase + 4);
 327 
 328         for (i = 0; i < cmd->cmd_len; i++)
 329                 outb(cmd->cmnd[i], qbase + 2);
 330         qlcmd = cmd;
 331         outb(0x41, qbase + 3);  /* select and send command */
 332         restore_flags( flags );
 333 }
 334 /*----------------------------------------------------------------*/
 335 /* process scsi command - usually after interrupt */
 336 static unsigned int     ql_pcmd(Scsi_Cmnd * cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 337 {
 338 unsigned int    i, j, k;
 339 unsigned int    result;                 /* ultimate return result */
 340 unsigned int    status;                 /* scsi returned status */
 341 unsigned int    message;                /* scsi returned message */
 342 unsigned int    phase;                  /* recorded scsi phase */
 343 unsigned int    reqlen;                 /* total length of transfer */
 344 struct scatterlist      *sglist;        /* scatter-gather list pointer */
 345 unsigned int    sgcount;                /* sg counter */
 346 
 347 rtrc(1)
 348         j = inb(qbase + 6);
 349         i = inb(qbase + 5);
 350         if (i == 0x20) {
 351                 return (DID_NO_CONNECT << 16);
 352         }
 353         i |= inb(qbase + 5);    /* the 0x10 bit can be set after the 0x08 */
 354         if (i != 0x18) {
 355                 printk("Ql:Bad Interrupt status:%02x\n", i);
 356                 ql_zap();
 357                 return (DID_BAD_INTR << 16);
 358         }
 359         j &= 7; /* j = inb( qbase + 7 ) >> 5; */
 360 /* correct status is supposed to be step 4 */
 361 /* it sometimes returns step 3 but with 0 bytes left to send */
 362 /* We can try stuffing the FIFO with the max each time, but we will get a
 363    sequence of 3 if any bytes are left (but we do flush the FIFO anyway */
 364         if(j != 3 && j != 4) {
 365                 printk("Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", j, i, inb( qbase+7 ) & 0x1f );
 366                 ql_zap();
 367                 return (DID_ERROR << 16);
 368         }
 369         result = DID_OK;
 370         if (inb(qbase + 7) & 0x1f)      /* if some bytes in fifo */
 371                 outb(1, qbase + 3);             /* clear fifo */
 372 /* note that request_bufflen is the total xfer size when sg is used */
 373         reqlen = cmd->request_bufflen;
 374 /* note that it won't work if transfers > 16M are requested */
 375         if (reqlen && !((phase = inb(qbase + 4)) & 6)) {        /* data phase */
 376 rtrc(2)
 377                 outb(reqlen, qbase);                    /* low-mid xfer cnt */
 378                 outb(reqlen >> 8, qbase+1);                     /* low-mid xfer cnt */
 379                 outb(reqlen >> 16, qbase + 0xe);        /* high xfer cnt */
 380                 outb(0x90, qbase + 3);                  /* command do xfer */
 381 /* PIO pseudo DMA to buffer or sglist */
 382                 REG1;
 383                 if (!cmd->use_sg)
 384                         ql_pdma(phase, cmd->request_buffer, cmd->request_bufflen);
 385                 else {
 386                         sgcount = cmd->use_sg;
 387                         sglist = cmd->request_buffer;
 388                         while (sgcount--) {
 389                                 if (qabort) {
 390                                         REG0;
 391                                         return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
 392                                 }
 393                                 if (ql_pdma(phase, sglist->address, sglist->length))
 394                                         break;
 395                                 sglist++;
 396                         }
 397                 }
 398                 REG0;
 399 rtrc(2)
 400 /* wait for irq (split into second state of irq handler if this can take time) */
 401                 if ((k = ql_wai()))
 402                         return (k << 16);
 403                 k = inb(qbase + 5);     /* should be 0x10, bus service */
 404         }
 405 /*** Enter Status (and Message In) Phase ***/
 406         k = jiffies + WATCHDOG;
 407         while ( k > jiffies && !qabort && !(inb(qbase + 4) & 6));       /* wait for status phase */
 408         if ( k <= jiffies ) {
 409                 ql_zap();
 410                 return (DID_TIME_OUT << 16);
 411         }
 412         while (inb(qbase + 5));                                 /* clear pending ints */
 413         if (qabort)
 414                 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
 415         outb(0x11, qbase + 3);                                  /* get status and message */
 416         if ((k = ql_wai()))
 417                 return (k << 16);
 418         i = inb(qbase + 5);                                     /* get chip irq stat */
 419         j = inb(qbase + 7) & 0x1f;                              /* and bytes rec'd */
 420         status = inb(qbase + 2);
 421         message = inb(qbase + 2);
 422 /* should get function complete int if Status and message, else bus serv if only status */
 423         if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) {
 424                 printk("Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j);
 425                 result = DID_ERROR;
 426         }
 427         outb(0x12, qbase + 3);  /* done, disconnect */
 428 rtrc(1)
 429         if ((k = ql_wai()))
 430                 return (k << 16);
 431 /* should get bus service interrupt and disconnect interrupt */
 432         i = inb(qbase + 5);     /* should be bus service */
 433         while (!qabort && ((i & 0x20) != 0x20)) {
 434                 barrier();
 435                 i |= inb(qbase + 5);
 436         }
 437 rtrc(0)
 438         if (qabort)
 439                 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
 440         return (result << 16) | (message << 8) | (status & STATUS_MASK);
 441 }
 442 
 443 #if QL_USE_IRQ
 444 /*----------------------------------------------------------------*/
 445 /* interrupt handler */
 446 static void                 ql_ihandl(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 447 {
 448 Scsi_Cmnd          *icmd;
 449         REG0;
 450         if (!(inb(qbase + 4) & 0x80))   /* false alarm? */
 451                 return;
 452         if (qlcmd == NULL) {            /* no command to process? */
 453                 int     i;
 454                 i = 16;
 455                 while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */
 456                 return;
 457         }
 458         icmd = qlcmd;
 459         icmd->result = ql_pcmd(icmd);
 460         qlcmd = NULL;
 461 /* if result is CHECK CONDITION done calls qcommand to request sense */
 462         (icmd->scsi_done) (icmd);
 463 }
 464 #endif
 465 
 466 /*----------------------------------------------------------------*/
 467 /* global functions */
 468 /*----------------------------------------------------------------*/
 469 /* non queued command */
 470 #if QL_USE_IRQ
 471 static void     qlidone(Scsi_Cmnd * cmd) {};            /* null function */
     /* [previous][next][first][last][top][bottom][index][help] */
 472 #endif
 473 
 474 /* command process */
 475 int     qlogic_command(Scsi_Cmnd * cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 476 {
 477 int     k;
 478 #if QL_USE_IRQ
 479         if (qlirq >= 0) {
 480                 qlogic_queuecommand(cmd, qlidone);
 481                 while (qlcmd != NULL);
 482                 return cmd->result;
 483         }
 484 #endif
 485 /* non-irq version */
 486         if (cmd->target == qinitid)
 487                 return (DID_BAD_TARGET << 16);
 488         ql_icmd(cmd);
 489         if ((k = ql_wai()))
 490                 return (k << 16);
 491         return ql_pcmd(cmd);
 492 
 493 }
 494 
 495 #if QL_USE_IRQ
 496 /*----------------------------------------------------------------*/
 497 /* queued command */
 498 int     qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 499 {
 500         if(cmd->target == qinitid) {
 501                 cmd->result = DID_BAD_TARGET << 16;
 502                 done(cmd);
 503                 return 0;
 504         }
 505 
 506         cmd->scsi_done = done;
 507 /* wait for the last command's interrupt to finish */
 508         while (qlcmd != NULL)
 509                 barrier();
 510         ql_icmd(cmd);
 511         return 0;
 512 }
 513 #else
 514 int     qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 515 {
 516         return 1;
 517 }
 518 #endif
 519 
 520 #ifdef PCMCIA
 521 /*----------------------------------------------------------------*/
 522 /* allow PCMCIA code to preset the port */
 523 /* port should be 0 and irq to -1 respectively for autoprobing */
 524 void    qlogic_preset(int port, int irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 525 {
 526         qbase=port;
 527         qlirq=irq;
 528 }
 529 #endif
 530 
 531 /*----------------------------------------------------------------*/
 532 /* look for qlogic card and init if found */
 533 int     qlogic_detect(Scsi_Host_Template * host)
     /* [previous][next][first][last][top][bottom][index][help] */
 534 {
 535 int     i, j;                   /* these are only used by IRQ detect */
 536 int     qltyp;                  /* type of chip */
 537 struct  Scsi_Host       *hreg;  /* registered host structure */
 538 unsigned long   flags;
 539 
 540 /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the
 541    address - I check 230 first since MIDI cards are typically at 330
 542 
 543    Theoretically, two Qlogic cards can coexist in the same system.  This
 544    should work by simply using this as a loadable module for the second
 545    card, but I haven't tested this.
 546 */
 547 
 548         if( !qbase ) {
 549                 for (qbase = 0x230; qbase < 0x430; qbase += 0x100) {
 550                         if( check_region( qbase , 0x10 ) )
 551                                 continue;
 552                         REG1;
 553                         if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
 554                           && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
 555                                 break;
 556                 }
 557                 if (qbase == 0x430)
 558                         return 0;
 559         }
 560         else
 561                 printk( "Ql: Using preset base address of %03x\n", qbase );
 562 
 563         qltyp = inb(qbase + 0xe) & 0xf8;
 564         qinitid = host->this_id;
 565         if (qinitid < 0)
 566                 qinitid = 7;                    /* if no ID, use 7 */
 567         outb(1, qbase + 8);                     /* set for PIO pseudo DMA */
 568         REG0;
 569         outb(0x40 | qlcfg8 | qinitid, qbase + 8);       /* (ini) bus id, disable scsi rst */
 570         outb(qlcfg5, qbase + 5);                /* select timer */
 571         outb(qlcfg9, qbase + 9);                        /* prescaler */
 572 #if QL_RESET_AT_START
 573         outb( 3 , qbase + 3 );
 574         REG1;
 575         while( inb( qbase + 0xf ) & 4 );
 576         REG0;
 577 #endif
 578 #if QL_USE_IRQ
 579 /* IRQ probe - toggle pin and check request pending */
 580 
 581         if( qlirq == -1 ) {
 582                 save_flags( flags );
 583                 cli();
 584                 i = 0xffff;
 585                 j = 3;
 586                 outb(0x90, qbase + 3);  /* illegal command - cause interrupt */
 587                 REG1;
 588                 outb(10, 0x20); /* access pending interrupt map */
 589                 outb(10, 0xa0);
 590                 while (j--) {
 591                         outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd);  /* int pin off */
 592                         i &= ~(inb(0x20) | (inb(0xa0) << 8));   /* find IRQ off */
 593                         outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd);  /* int pin on */
 594                         i &= inb(0x20) | (inb(0xa0) << 8);      /* find IRQ on */
 595                 }
 596                 REG0;
 597                 while (inb(qbase + 5));                         /* purge int */
 598                 j = -1;
 599                 while (i)                                       /* find on bit */
 600                         i >>= 1, j++;   /* should check for exactly 1 on */
 601                 qlirq = j;
 602                 restore_flags( flags );
 603         }
 604         else
 605                 printk( "Ql: Using preset IRQ %d\n", qlirq );
 606 
 607         if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic"))
 608                 host->can_queue = 1;
 609 #endif
 610         request_region( qbase , 0x10 ,"qlogic");
 611         hreg = scsi_register( host , 0 );       /* no host data */
 612         hreg->io_port = qbase;
 613         hreg->n_io_port = 16;
 614         hreg->dma_channel = -1;
 615         if( qlirq != -1 )
 616                 hreg->irq = qlirq;
 617 
 618         sprintf(qinfo, "Qlogic Driver version 0.43, chip %02X at %03X, IRQ %d, TPdma:%d",
 619             qltyp, qbase, qlirq, QL_TURBO_PDMA );
 620         host->name = qinfo;
 621 
 622         return 1;
 623 }
 624 
 625 /*----------------------------------------------------------------*/
 626 /* return bios parameters */
 627 int     qlogic_biosparam(Disk * disk, int dev, int ip[])
     /* [previous][next][first][last][top][bottom][index][help] */
 628 {
 629 /* This should mimic the DOS Qlogic driver's behavior exactly */
 630         ip[0] = 0x40;
 631         ip[1] = 0x20;
 632         ip[2] = disk->capacity / (ip[0] * ip[1]);
 633         if (ip[2] > 1024) {
 634                 ip[0] = 0xff;
 635                 ip[1] = 0x3f;
 636                 ip[2] = disk->capacity / (ip[0] * ip[1]);
 637                 if (ip[2] > 1023)
 638                         ip[2] = 1023;
 639         }
 640         return 0;
 641 }
 642 
 643 /*----------------------------------------------------------------*/
 644 /* abort command in progress */
 645 int     qlogic_abort(Scsi_Cmnd * cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 646 {
 647         qabort = 1;
 648         ql_zap();
 649         return 0;
 650 }
 651 
 652 /*----------------------------------------------------------------*/
 653 /* reset SCSI bus */
 654 int     qlogic_reset(Scsi_Cmnd * cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 655 {
 656         qabort = 2;
 657         ql_zap();
 658         return 1;
 659 }
 660 
 661 /*----------------------------------------------------------------*/
 662 /* return info string */
 663 const char      *qlogic_info(struct Scsi_Host * host)
     /* [previous][next][first][last][top][bottom][index][help] */
 664 {
 665         return qinfo;
 666 }
 667 
 668 #ifdef MODULE
 669 /* Eventually this will go into an include file, but this will be later */
 670 Scsi_Host_Template driver_template = QLOGIC;
 671 
 672 #include "scsi_module.c"
 673 #endif

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