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

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