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

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