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

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