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

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