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

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