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