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

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