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 <unistd.h>
 128 #include <asm/io.h>
 129 #include <asm/irq.h>
 130 #include "sd.h"
 131 #include "hosts.h"
 132 #include "qlogic.h"
 133 
 134 /*----------------------------------------------------------------*/
 135 /* driver state info, local to driver */
 136 static int          qbase = 0;  /* Port */
 137 static int          qinitid;    /* initiator ID */
 138 static int          qabort;     /* Flag to cause an abort */
 139 static int          qlirq = -1; /* IRQ being used */
 140 static char         qinfo[80];  /* description */
 141 static Scsi_Cmnd   *qlcmd;      /* current command being processed */
 142 
 143 static int          qlcfg5 = ( XTALFREQ << 5 ); /* 15625/512 */
 144 static int          qlcfg6 = SYNCXFRPD;
 145 static int          qlcfg7 = SYNCOFFST;
 146 static int          qlcfg8 = ( SLOWCABLE << 7 ) | ( QL_ENABLE_PARITY << 4 );
 147 static int          qlcfg9 = ( ( XTALFREQ + 4 ) / 5 );
 148 static int          qlcfgc = ( FASTCLK << 3 ) | ( FASTSCSI << 4 );
 149 
 150 /*----------------------------------------------------------------*/
 151 /* The qlogic card uses two register maps - These macros select which one */
 152 #define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
 153 #define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd ))
 154 
 155 /* following is watchdog timeout in microseconds */
 156 #define WATCHDOG 5000000
 157 
 158 /*----------------------------------------------------------------*/
 159 /* the following will set the monitor border color (useful to find
 160    where something crashed or gets stuck at and as a simple profiler) */
 161 
 162 #if 0
 163 #define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);}
 164 #else
 165 #define rtrc(i) {}
 166 #endif
 167 
 168 /*----------------------------------------------------------------*/
 169 /* local functions */
 170 /*----------------------------------------------------------------*/
 171 static void     ql_zap(void);
 172 /* error recovery - reset everything */
 173 void    ql_zap()
     /* [previous][next][first][last][top][bottom][index][help] */
 174 {
 175 int     x;
 176 unsigned long   flags;
 177         save_flags( flags );
 178         cli();
 179         x = inb(qbase + 0xd);
 180         REG0;
 181         outb(3, qbase + 3);                             /* reset SCSI */
 182         outb(2, qbase + 3);                             /* reset chip */
 183         if (x & 0x80)
 184                 REG1;
 185         restore_flags( flags );
 186 }
 187 
 188 /*----------------------------------------------------------------*/
 189 /* do pseudo-dma */
 190 static int      ql_pdma(int phase, char *request, int reqlen)
     /* [previous][next][first][last][top][bottom][index][help] */
 191 {
 192 int     j;
 193         j = 0;
 194         if (phase & 1) {        /* in */
 195 #if QL_TURBO_PDMA
 196 rtrc(4)
 197                 /* empty fifo in large chunks */
 198                 if( reqlen >= 128 && (inb( qbase + 8 ) & 2) ) { /* full */
 199                         insl( qbase + 4, request, 32 );
 200                         reqlen -= 128;
 201                         request += 128;
 202                 }
 203                 while( reqlen >= 84 && !( j & 0xc0 ) ) /* 2/3 */
 204                         if( (j=inb( qbase + 8 )) & 4 ) {
 205                                 insl( qbase + 4, request, 21 );
 206                                 reqlen -= 84;
 207                                 request += 84;
 208                         }
 209                 if( reqlen >= 44 && (inb( qbase + 8 ) & 8) ) {  /* 1/3 */
 210                         insl( qbase + 4, request, 11 );
 211                         reqlen -= 44;
 212                         request += 44;
 213                 }
 214 #endif
 215                 /* until both empty and int (or until reclen is 0) */
 216 rtrc(7)
 217                 j = 0;
 218                 while( reqlen && !( (j & 0x10) && (j & 0xc0) ) ) {
 219                         /* while bytes to receive and not empty */
 220                         j &= 0xc0;
 221                         while ( reqlen && !( (j=inb(qbase + 8)) & 0x10 ) ) {
 222                                 *request++ = inb(qbase + 4);
 223                                 reqlen--;
 224                         }
 225                         if( j & 0x10 )
 226                                 j = inb(qbase+8);
 227 
 228                 }
 229         }
 230         else {  /* out */
 231 #if QL_TURBO_PDMA
 232 rtrc(4)
 233                 if( reqlen >= 128 && inb( qbase + 8 ) & 0x10 ) { /* empty */
 234                         outsl(qbase + 4, request, 32 );
 235                         reqlen -= 128;
 236                         request += 128;
 237                 }
 238                 while( reqlen >= 84 && !( j & 0xc0 ) ) /* 1/3 */
 239                         if( !((j=inb( qbase + 8 )) & 8) ) {
 240                                 outsl( qbase + 4, request, 21 );
 241                                 reqlen -= 84;
 242                                 request += 84;
 243                         }
 244                 if( reqlen >= 40 && !(inb( qbase + 8 ) & 4 ) ) { /* 2/3 */
 245                         outsl( qbase + 4, request, 10 );
 246                         reqlen -= 40;
 247                         request += 40;
 248                 }
 249 #endif
 250                 /* until full and int (or until reclen is 0) */
 251 rtrc(7)
 252                 j = 0;
 253                 while( reqlen && !( (j & 2) && (j & 0xc0) ) ) {
 254                         /* while bytes to send and not full */
 255                         while ( reqlen && !( (j=inb(qbase + 8)) & 2 ) ) {
 256                                 outb(*request++, qbase + 4);
 257                                 reqlen--;
 258                         }
 259                         if( j & 2 )
 260                                 j = inb(qbase+8);
 261                 }
 262         }
 263 /* maybe return reqlen */
 264         return inb( qbase + 8 ) & 0xc0;
 265 }
 266 
 267 /*----------------------------------------------------------------*/
 268 /* wait for interrupt flag (polled - not real hardware interrupt) */
 269 static int      ql_wai(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 270 {
 271 int     i,k;
 272         k = 0;
 273         i = jiffies + WATCHDOG;
 274         while ( i > jiffies && !qabort && !((k = inb(qbase + 4)) & 0xe0))
 275                 barrier();
 276         if (i <= jiffies)
 277                 return (DID_TIME_OUT);
 278         if (qabort)
 279                 return (qabort == 1 ? DID_ABORT : DID_RESET);
 280         if (k & 0x60)
 281                 ql_zap();
 282         if (k & 0x20)
 283                 return (DID_PARITY);
 284         if (k & 0x40)
 285                 return (DID_ERROR);
 286         return 0;
 287 }
 288 
 289 /*----------------------------------------------------------------*/
 290 /* initiate scsi command - queueing handler */
 291 static void     ql_icmd(Scsi_Cmnd * cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 292 {
 293 unsigned int        i;
 294 unsigned long   flags;
 295 
 296         qabort = 0;
 297 
 298         save_flags( flags );
 299         cli();
 300         REG0;
 301 /* clearing of interrupts and the fifo is needed */
 302         inb(qbase + 5);                         /* clear interrupts */
 303         if (inb(qbase + 5))                     /* if still interrupting */
 304                 outb(2, qbase + 3);             /* reset chip */
 305         else if (inb(qbase + 7) & 0x1f)
 306                 outb(1, qbase + 3);             /* clear fifo */
 307         while (inb(qbase + 5));                 /* clear ints */
 308         REG1;
 309         outb(1, qbase + 8);                     /* set for PIO pseudo DMA */
 310         outb(0, qbase + 0xb);                   /* disable ints */
 311         inb(qbase + 8);                         /* clear int bits */
 312         REG0;
 313         outb(0x40, qbase + 0xb);                /* enable features */
 314 
 315 /* configurables */
 316         outb( qlcfgc , qbase + 0xc);
 317 /* config: no reset interrupt, (initiator) bus id */
 318         outb( 0x40 | qlcfg8 | qinitid, qbase + 8);
 319         outb( qlcfg7 , qbase + 7 );
 320         outb( qlcfg6 , qbase + 6 );
 321 /**/
 322         outb(qlcfg5, qbase + 5);                /* select timer */
 323         outb(qlcfg9 & 7, qbase + 9);                    /* prescaler */
 324 /*      outb(0x99, qbase + 5);  */
 325         outb(cmd->target, qbase + 4);
 326 
 327         for (i = 0; i < cmd->cmd_len; i++)
 328                 outb(cmd->cmnd[i], qbase + 2);
 329         qlcmd = cmd;
 330         outb(0x41, qbase + 3);  /* select and send command */
 331         restore_flags( flags );
 332 }
 333 /*----------------------------------------------------------------*/
 334 /* process scsi command - usually after interrupt */
 335 static unsigned int     ql_pcmd(Scsi_Cmnd * cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 336 {
 337 unsigned int    i, j, k;
 338 unsigned int    result;                 /* ultimate return result */
 339 unsigned int    status;                 /* scsi returned status */
 340 unsigned int    message;                /* scsi returned message */
 341 unsigned int    phase;                  /* recorded scsi phase */
 342 unsigned int    reqlen;                 /* total length of transfer */
 343 struct scatterlist      *sglist;        /* scatter-gather list pointer */
 344 unsigned int    sgcount;                /* sg counter */
 345 
 346 rtrc(1)
 347         j = inb(qbase + 6);
 348         i = inb(qbase + 5);
 349         if (i == 0x20) {
 350                 return (DID_NO_CONNECT << 16);
 351         }
 352         i |= inb(qbase + 5);    /* the 0x10 bit can be set after the 0x08 */
 353         if (i != 0x18) {
 354                 printk("Ql:Bad Interrupt status:%02x\n", i);
 355                 ql_zap();
 356                 return (DID_BAD_INTR << 16);
 357         }
 358         j &= 7; /* j = inb( qbase + 7 ) >> 5; */
 359 /* correct status is supposed to be step 4 */
 360 /* it sometimes returns step 3 but with 0 bytes left to send */
 361 /* We can try stuffing the FIFO with the max each time, but we will get a
 362    sequence of 3 if any bytes are left (but we do flush the FIFO anyway */
 363         if(j != 3 && j != 4) {
 364                 printk("Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", j, i, inb( qbase+7 ) & 0x1f );
 365                 ql_zap();
 366                 return (DID_ERROR << 16);
 367         }
 368         result = DID_OK;
 369         if (inb(qbase + 7) & 0x1f)      /* if some bytes in fifo */
 370                 outb(1, qbase + 3);             /* clear fifo */
 371 /* note that request_bufflen is the total xfer size when sg is used */
 372         reqlen = cmd->request_bufflen;
 373 /* note that it won't work if transfers > 16M are requested */
 374         if (reqlen && !((phase = inb(qbase + 4)) & 6)) {        /* data phase */
 375 rtrc(2)
 376                 outb(reqlen, qbase);                    /* low-mid xfer cnt */
 377                 outb(reqlen >> 8, qbase+1);                     /* low-mid xfer cnt */
 378                 outb(reqlen >> 16, qbase + 0xe);        /* high xfer cnt */
 379                 outb(0x90, qbase + 3);                  /* command do xfer */
 380 /* PIO pseudo DMA to buffer or sglist */
 381                 REG1;
 382                 if (!cmd->use_sg)
 383                         ql_pdma(phase, cmd->request_buffer, cmd->request_bufflen);
 384                 else {
 385                         sgcount = cmd->use_sg;
 386                         sglist = cmd->request_buffer;
 387                         while (sgcount--) {
 388                                 if (qabort) {
 389                                         REG0;
 390                                         return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
 391                                 }
 392                                 if (ql_pdma(phase, sglist->address, sglist->length))
 393                                         break;
 394                                 sglist++;
 395                         }
 396                 }
 397                 REG0;
 398 rtrc(2)
 399 /* wait for irq (split into second state of irq handler if this can take time) */
 400                 if ((k = ql_wai()))
 401                         return (k << 16);
 402                 k = inb(qbase + 5);     /* should be 0x10, bus service */
 403         }
 404 /*** Enter Status (and Message In) Phase ***/
 405         k = jiffies + WATCHDOG;
 406         while ( k > jiffies && !qabort && !(inb(qbase + 4) & 6));       /* wait for status phase */
 407         if ( k <= jiffies ) {
 408                 ql_zap();
 409                 return (DID_TIME_OUT << 16);
 410         }
 411         while (inb(qbase + 5));                                 /* clear pending ints */
 412         if (qabort)
 413                 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
 414         outb(0x11, qbase + 3);                                  /* get status and message */
 415         if ((k = ql_wai()))
 416                 return (k << 16);
 417         i = inb(qbase + 5);                                     /* get chip irq stat */
 418         j = inb(qbase + 7) & 0x1f;                              /* and bytes rec'd */
 419         status = inb(qbase + 2);
 420         message = inb(qbase + 2);
 421 /* should get function complete int if Status and message, else bus serv if only status */
 422         if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) {
 423                 printk("Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j);
 424                 result = DID_ERROR;
 425         }
 426         outb(0x12, qbase + 3);  /* done, disconnect */
 427 rtrc(1)
 428         if ((k = ql_wai()))
 429                 return (k << 16);
 430 /* should get bus service interrupt and disconnect interrupt */
 431         i = inb(qbase + 5);     /* should be bus service */
 432         while (!qabort && ((i & 0x20) != 0x20)) {
 433                 barrier();
 434                 i |= inb(qbase + 5);
 435         }
 436 rtrc(0)
 437         if (qabort)
 438                 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
 439         return (result << 16) | (message << 8) | (status & STATUS_MASK);
 440 }
 441 
 442 #if QL_USE_IRQ
 443 /*----------------------------------------------------------------*/
 444 /* interrupt handler */
 445 static void                 ql_ihandl(int irq, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 446 {
 447 Scsi_Cmnd          *icmd;
 448         REG0;
 449         if (!(inb(qbase + 4) & 0x80))   /* false alarm? */
 450                 return;
 451         if (qlcmd == NULL) {            /* no command to process? */
 452                 int     i;
 453                 i = 16;
 454                 while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */
 455                 return;
 456         }
 457         icmd = qlcmd;
 458         icmd->result = ql_pcmd(icmd);
 459         qlcmd = NULL;
 460 /* if result is CHECK CONDITION done calls qcommand to request sense */
 461         (icmd->scsi_done) (icmd);
 462 }
 463 #endif
 464 
 465 /*----------------------------------------------------------------*/
 466 /* global functions */
 467 /*----------------------------------------------------------------*/
 468 /* non queued command */
 469 #if QL_USE_IRQ
 470 static void     qlidone(Scsi_Cmnd * cmd) {};            /* null function */
     /* [previous][next][first][last][top][bottom][index][help] */
 471 #endif
 472 
 473 /* command process */
 474 int     qlogic_command(Scsi_Cmnd * cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 475 {
 476 int     k;
 477 #if QL_USE_IRQ
 478         if (qlirq >= 0) {
 479                 qlogic_queuecommand(cmd, qlidone);
 480                 while (qlcmd != NULL);
 481                 return cmd->result;
 482         }
 483 #endif
 484 /* non-irq version */
 485         if (cmd->target == qinitid)
 486                 return (DID_BAD_TARGET << 16);
 487         ql_icmd(cmd);
 488         if ((k = ql_wai()))
 489                 return (k << 16);
 490         return ql_pcmd(cmd);
 491 
 492 }
 493 
 494 #if QL_USE_IRQ
 495 /*----------------------------------------------------------------*/
 496 /* queued command */
 497 int     qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 498 {
 499         if(cmd->target == qinitid) {
 500                 cmd->result = DID_BAD_TARGET << 16;
 501                 done(cmd);
 502                 return 0;
 503         }
 504 
 505         cmd->scsi_done = done;
 506 /* wait for the last command's interrupt to finish */
 507         while (qlcmd != NULL)
 508                 barrier();
 509         ql_icmd(cmd);
 510         return 0;
 511 }
 512 #else
 513 int     qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
     /* [previous][next][first][last][top][bottom][index][help] */
 514 {
 515         return 1;
 516 }
 517 #endif
 518 
 519 #ifdef PCMCIA
 520 /*----------------------------------------------------------------*/
 521 /* allow PCMCIA code to preset the port */
 522 /* port should be 0 and irq to -1 respectively for autoprobing */
 523 void    qlogic_preset(int port, int irq)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525         qbase=port;
 526         qlirq=irq;
 527 }
 528 #endif
 529 
 530 /*----------------------------------------------------------------*/
 531 /* look for qlogic card and init if found */
 532 int     qlogic_detect(Scsi_Host_Template * host)
     /* [previous][next][first][last][top][bottom][index][help] */
 533 {
 534 int     i, j;                   /* these are only used by IRQ detect */
 535 int     qltyp;                  /* type of chip */
 536 struct  Scsi_Host       *hreg;  /* registered host structure */
 537 unsigned long   flags;
 538 
 539 /* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the
 540    address - I check 230 first since MIDI cards are typically at 330
 541 
 542    Theoretically, two Qlogic cards can coexist in the same system.  This
 543    should work by simply using this as a loadable module for the second
 544    card, but I haven't tested this.
 545 */
 546 
 547         if( !qbase ) {
 548                 for (qbase = 0x230; qbase < 0x430; qbase += 0x100) {
 549                         if( check_region( qbase , 0x10 ) )
 550                                 continue;
 551                         REG1;
 552                         if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
 553                           && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
 554                                 break;
 555                 }
 556                 if (qbase == 0x430)
 557                         return 0;
 558         }
 559         else
 560                 printk( "Ql: Using preset base address of %03x\n", qbase );
 561 
 562         qltyp = inb(qbase + 0xe) & 0xf8;
 563         qinitid = host->this_id;
 564         if (qinitid < 0)
 565                 qinitid = 7;                    /* if no ID, use 7 */
 566         outb(1, qbase + 8);                     /* set for PIO pseudo DMA */
 567         REG0;
 568         outb(0x40 | qlcfg8 | qinitid, qbase + 8);       /* (ini) bus id, disable scsi rst */
 569         outb(qlcfg5, qbase + 5);                /* select timer */
 570         outb(qlcfg9, qbase + 9);                        /* prescaler */
 571 #if QL_RESET_AT_START
 572         outb( 3 , qbase + 3 );
 573         REG1;
 574         while( inb( qbase + 0xf ) & 4 );
 575         REG0;
 576 #endif
 577 #if QL_USE_IRQ
 578 /* IRQ probe - toggle pin and check request pending */
 579 
 580         if( qlirq == -1 ) {
 581                 save_flags( flags );
 582                 cli();
 583                 i = 0xffff;
 584                 j = 3;
 585                 outb(0x90, qbase + 3);  /* illegal command - cause interrupt */
 586                 REG1;
 587                 outb(10, 0x20); /* access pending interrupt map */
 588                 outb(10, 0xa0);
 589                 while (j--) {
 590                         outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd);  /* int pin off */
 591                         i &= ~(inb(0x20) | (inb(0xa0) << 8));   /* find IRQ off */
 592                         outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd);  /* int pin on */
 593                         i &= inb(0x20) | (inb(0xa0) << 8);      /* find IRQ on */
 594                 }
 595                 REG0;
 596                 while (inb(qbase + 5));                         /* purge int */
 597                 j = -1;
 598                 while (i)                                       /* find on bit */
 599                         i >>= 1, j++;   /* should check for exactly 1 on */
 600                 qlirq = j;
 601                 restore_flags( flags );
 602         }
 603         else
 604                 printk( "Ql: Using preset IRQ %d\n", qlirq );
 605 
 606         if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic"))
 607                 host->can_queue = 1;
 608 #endif
 609         request_region( qbase , 0x10 ,"qlogic");
 610         hreg = scsi_register( host , 0 );       /* no host data */
 611         hreg->io_port = qbase;
 612         hreg->n_io_port = 16;
 613         hreg->dma_channel = -1;
 614         if( qlirq != -1 )
 615                 hreg->irq = qlirq;
 616 
 617         sprintf(qinfo, "Qlogic Driver version 0.43, chip %02X at %03X, IRQ %d, TPdma:%d",
 618             qltyp, qbase, qlirq, QL_TURBO_PDMA );
 619         host->name = qinfo;
 620 
 621         return 1;
 622 }
 623 
 624 /*----------------------------------------------------------------*/
 625 /* return bios parameters */
 626 int     qlogic_biosparam(Disk * disk, int dev, int ip[])
     /* [previous][next][first][last][top][bottom][index][help] */
 627 {
 628 /* This should mimic the DOS Qlogic driver's behavior exactly */
 629         ip[0] = 0x40;
 630         ip[1] = 0x20;
 631         ip[2] = disk->capacity / (ip[0] * ip[1]);
 632         if (ip[2] > 1024) {
 633                 ip[0] = 0xff;
 634                 ip[1] = 0x3f;
 635                 ip[2] = disk->capacity / (ip[0] * ip[1]);
 636                 if (ip[2] > 1023)
 637                         ip[2] = 1023;
 638         }
 639         return 0;
 640 }
 641 
 642 /*----------------------------------------------------------------*/
 643 /* abort command in progress */
 644 int     qlogic_abort(Scsi_Cmnd * cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 645 {
 646         qabort = 1;
 647         ql_zap();
 648         return 0;
 649 }
 650 
 651 /*----------------------------------------------------------------*/
 652 /* reset SCSI bus */
 653 int     qlogic_reset(Scsi_Cmnd * cmd)
     /* [previous][next][first][last][top][bottom][index][help] */
 654 {
 655         qabort = 2;
 656         ql_zap();
 657         return 1;
 658 }
 659 
 660 /*----------------------------------------------------------------*/
 661 /* return info string */
 662 const char      *qlogic_info(struct Scsi_Host * host)
     /* [previous][next][first][last][top][bottom][index][help] */
 663 {
 664         return qinfo;
 665 }
 666 
 667 #ifdef MODULE
 668 /* Eventually this will go into an include file, but this will be later */
 669 Scsi_Host_Template driver_template = QLOGIC;
 670 
 671 #include "scsi_module.c"
 672 #endif

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