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

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