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 tz@execpc.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.46 1/30/97 - kernel 1.2.0+ 22 23 Functions as standalone, loadable, and PCMCIA driver, the latter from 24 Dave Hinds' PCMCIA package. 25 26 Redistributable under terms of the GNU General Public License 27 28*/ 29/*----------------------------------------------------------------*/ 30/* Configuration */ 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. */ 43#define QL_TURBO_PDMA 1 44 45/* This should be 1 to enable parity detection */ 46#define QL_ENABLE_PARITY 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 0 55 56/* crystal frequency in megahertz (for offset 5 and 9) 57 Please set this for your card. Most Qlogic cards are 40 Mhz. The 58 Control Concepts ISA (not VLB) is 24 Mhz */ 59#define XTALFREQ 40 60 61/**********/ 62/* DANGER! modify these at your own risk */ 63/* SLOWCABLE can usually be reset to zero if you have a clean setup and 64 proper termination. The rest are for synchronous transfers and other 65 advanced features if your device can transfer faster than 5Mb/sec. 66 If you are really curious, email me for a quick howto until I have 67 something official */ 68/**********/ 69 70/*****/ 71/* config register 1 (offset 8) options */ 72/* This needs to be set to 1 if your cabling is long or noisy */ 73#define SLOWCABLE 1 74 75/*****/ 76/* offset 0xc */ 77/* This will set fast (10Mhz) synchronous timing when set to 1 78 For this to have an effect, FASTCLK must also be 1 */ 79#define FASTSCSI 0 80 81/* This when set to 1 will set a faster sync transfer rate */ 82#define FASTCLK 0 83/*(XTALFREQ>25?1:0)*/ 84 85/*****/ 86/* offset 6 */ 87/* This is the sync transfer divisor, XTALFREQ/X will be the maximum 88 achievable data rate (assuming the rest of the system is capable 89 and set properly) */ 90#define SYNCXFRPD 5 91/*(XTALFREQ/5)*/ 92 93/*****/ 94/* offset 7 */ 95/* This is the count of how many synchronous transfers can take place 96 i.e. how many reqs can occur before an ack is given. 97 The maximum value for this is 15, the upper bits can modify 98 REQ/ACK assertion and deassertion during synchronous transfers 99 If this is 0, the bus will only transfer asynchronously */ 100#define SYNCOFFST 0 101/* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles 102 of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will 103 cause the deassertion to be early by 1/2 clock. Bits 5&4 control 104 the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */ 105 106/*----------------------------------------------------------------*/ 107#ifdef PCMCIA 108#undef QL_INT_ACTIVE_HIGH 109#define QL_INT_ACTIVE_HIGH 0 110#endif 111 112#include <linux/module.h> 113 114#ifdef PCMCIA 115#undef MODULE 116#endif 117 118#include <linux/blk.h> /* to get disk capacity */ 119#include <linux/kernel.h> 120#include <linux/string.h> 121#include <linux/init.h> 122#include <linux/ioport.h> 123#include <linux/sched.h> 124#include <linux/proc_fs.h> 125#include <linux/unistd.h> 126#include <linux/spinlock.h> 127#include <asm/io.h> 128#include <asm/irq.h> 129#include "sd.h" 130#include "hosts.h" 131#include "qlogicfas.h" 132#include <linux/stat.h> 133 134/*----------------------------------------------------------------*/ 135/* driver state info, local to driver */ 136static int qbase; /* Port */ 137static int qinitid; /* initiator ID */ 138static int qabort; /* Flag to cause an abort */ 139static int qlirq = -1; /* IRQ being used */ 140static char qinfo[80]; /* description */ 141static Scsi_Cmnd *qlcmd; /* current command being processed */ 142 143static int qlcfg5 = ( XTALFREQ << 5 ); /* 15625/512 */ 144static int qlcfg6 = SYNCXFRPD; 145static int qlcfg7 = SYNCOFFST; 146static int qlcfg8 = ( SLOWCABLE << 7 ) | ( QL_ENABLE_PARITY << 4 ); 147static int qlcfg9 = ( ( XTALFREQ + 4 ) / 5 ); 148static int qlcfgc = ( FASTCLK << 3 ) | ( FASTSCSI << 4 ); 149 150/*----------------------------------------------------------------*/ 151/* The qlogic card uses two register maps - These macros select which one */ 152#define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd )) 153#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd )) 154 155/* following is watchdog timeout in microseconds */ 156#define WATCHDOG 5000000 157 158/*----------------------------------------------------------------*/ 159/* the following will set the monitor border color (useful to find 160 where something crashed or gets stuck at and as a simple profiler) */ 161 162#define rtrc(i) {} 163 164/*----------------------------------------------------------------*/ 165/* local functions */ 166/*----------------------------------------------------------------*/ 167static void ql_zap(void); 168/* error recovery - reset everything */ 169void ql_zap() 170{ 171int x; 172unsigned long flags; 173 save_flags( flags ); 174 cli(); 175 x = inb(qbase + 0xd); 176 REG0; 177 outb(3, qbase + 3); /* reset SCSI */ 178 outb(2, qbase + 3); /* reset chip */ 179 if (x & 0x80) 180 REG1; 181 restore_flags( flags ); 182} 183 184/*----------------------------------------------------------------*/ 185/* do pseudo-dma */ 186static int ql_pdma(int phase, char *request, int reqlen) 187{ 188int j; 189 j = 0; 190 if (phase & 1) { /* in */ 191#if QL_TURBO_PDMA 192rtrc(4) 193 /* empty fifo in large chunks */ 194 if( reqlen >= 128 && (inb( qbase + 8 ) & 2) ) { /* full */ 195 insl( qbase + 4, request, 32 ); 196 reqlen -= 128; 197 request += 128; 198 } 199 while( reqlen >= 84 && !( j & 0xc0 ) ) /* 2/3 */ 200 if( (j=inb( qbase + 8 )) & 4 ) { 201 insl( qbase + 4, request, 21 ); 202 reqlen -= 84; 203 request += 84; 204 } 205 if( reqlen >= 44 && (inb( qbase + 8 ) & 8) ) { /* 1/3 */ 206 insl( qbase + 4, request, 11 ); 207 reqlen -= 44; 208 request += 44; 209 } 210#endif 211 /* until both empty and int (or until reclen is 0) */ 212rtrc(7) 213 j = 0; 214 while( reqlen && !( (j & 0x10) && (j & 0xc0) ) ) { 215 /* while bytes to receive and not empty */ 216 j &= 0xc0; 217 while ( reqlen && !( (j=inb(qbase + 8)) & 0x10 ) ) { 218 *request++ = inb(qbase + 4); 219 reqlen--; 220 } 221 if( j & 0x10 ) 222 j = inb(qbase+8); 223 224 } 225 } 226 else { /* out */ 227#if QL_TURBO_PDMA 228rtrc(4) 229 if( reqlen >= 128 && inb( qbase + 8 ) & 0x10 ) { /* empty */ 230 outsl(qbase + 4, request, 32 ); 231 reqlen -= 128; 232 request += 128; 233 } 234 while( reqlen >= 84 && !( j & 0xc0 ) ) /* 1/3 */ 235 if( !((j=inb( qbase + 8 )) & 8) ) { 236 outsl( qbase + 4, request, 21 ); 237 reqlen -= 84; 238 request += 84; 239 } 240 if( reqlen >= 40 && !(inb( qbase + 8 ) & 4 ) ) { /* 2/3 */ 241 outsl( qbase + 4, request, 10 ); 242 reqlen -= 40; 243 request += 40; 244 } 245#endif 246 /* until full and int (or until reclen is 0) */ 247rtrc(7) 248 j = 0; 249 while( reqlen && !( (j & 2) && (j & 0xc0) ) ) { 250 /* while bytes to send and not full */ 251 while ( reqlen && !( (j=inb(qbase + 8)) & 2 ) ) { 252 outb(*request++, qbase + 4); 253 reqlen--; 254 } 255 if( j & 2 ) 256 j = inb(qbase+8); 257 } 258 } 259/* maybe return reqlen */ 260 return inb( qbase + 8 ) & 0xc0; 261} 262 263/*----------------------------------------------------------------*/ 264/* wait for interrupt flag (polled - not real hardware interrupt) */ 265static int ql_wai(void) 266{ 267int i,k; 268 k = 0; 269 i = jiffies + WATCHDOG; 270 while (time_before(jiffies, i) && !qabort && !((k = inb(qbase + 4)) & 0xe0)) { 271 barrier(); 272 cpu_relax(); 273 } 274 if (time_after_eq(jiffies, i)) 275 return (DID_TIME_OUT); 276 if (qabort) 277 return (qabort == 1 ? DID_ABORT : DID_RESET); 278 if (k & 0x60) 279 ql_zap(); 280 if (k & 0x20) 281 return (DID_PARITY); 282 if (k & 0x40) 283 return (DID_ERROR); 284 return 0; 285} 286 287/*----------------------------------------------------------------*/ 288/* initiate scsi command - queueing handler */ 289static void ql_icmd(Scsi_Cmnd * cmd) 290{ 291unsigned int i; 292unsigned long flags; 293 294 qabort = 0; 295 296 save_flags( flags ); 297 cli(); 298 REG0; 299/* clearing of interrupts and the fifo is needed */ 300 inb(qbase + 5); /* clear interrupts */ 301 if (inb(qbase + 5)) /* if still interrupting */ 302 outb(2, qbase + 3); /* reset chip */ 303 else if (inb(qbase + 7) & 0x1f) 304 outb(1, qbase + 3); /* clear fifo */ 305 while (inb(qbase + 5)); /* clear ints */ 306 REG1; 307 outb(1, qbase + 8); /* set for PIO pseudo DMA */ 308 outb(0, qbase + 0xb); /* disable ints */ 309 inb(qbase + 8); /* clear int bits */ 310 REG0; 311 outb(0x40, qbase + 0xb); /* enable features */ 312 313/* configurables */ 314 outb( qlcfgc , qbase + 0xc); 315/* config: no reset interrupt, (initiator) bus id */ 316 outb( 0x40 | qlcfg8 | qinitid, qbase + 8); 317 outb( qlcfg7 , qbase + 7 ); 318 outb( qlcfg6 , qbase + 6 ); 319/**/ 320 outb(qlcfg5, qbase + 5); /* select timer */ 321 outb(qlcfg9 & 7, qbase + 9); /* prescaler */ 322/* outb(0x99, qbase + 5); */ 323 outb(cmd->target, qbase + 4); 324 325 for (i = 0; i < cmd->cmd_len; i++) 326 outb(cmd->cmnd[i], qbase + 2); 327 qlcmd = cmd; 328 outb(0x41, qbase + 3); /* select and send command */ 329 restore_flags( flags ); 330} 331/*----------------------------------------------------------------*/ 332/* process scsi command - usually after interrupt */ 333static unsigned int ql_pcmd(Scsi_Cmnd * cmd) 334{ 335unsigned int i, j, k; 336unsigned int result; /* ultimate return result */ 337unsigned int status; /* scsi returned status */ 338unsigned int message; /* scsi returned message */ 339unsigned int phase; /* recorded scsi phase */ 340unsigned int reqlen; /* total length of transfer */ 341struct scatterlist *sglist; /* scatter-gather list pointer */ 342unsigned int sgcount; /* sg counter */ 343 344rtrc(1) 345 j = inb(qbase + 6); 346 i = inb(qbase + 5); 347 if (i == 0x20) { 348 return (DID_NO_CONNECT << 16); 349 } 350 i |= inb(qbase + 5); /* the 0x10 bit can be set after the 0x08 */ 351 if (i != 0x18) { 352 printk("Ql:Bad Interrupt status:%02x\n", i); 353 ql_zap(); 354 return (DID_BAD_INTR << 16); 355 } 356 j &= 7; /* j = inb( qbase + 7 ) >> 5; */ 357/* correct status is supposed to be step 4 */ 358/* it sometimes returns step 3 but with 0 bytes left to send */ 359/* We can try stuffing the FIFO with the max each time, but we will get a 360 sequence of 3 if any bytes are left (but we do flush the FIFO anyway */ 361 if(j != 3 && j != 4) { 362 printk("Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", j, i, inb( qbase+7 ) & 0x1f ); 363 ql_zap(); 364 return (DID_ERROR << 16); 365 } 366 result = DID_OK; 367 if (inb(qbase + 7) & 0x1f) /* if some bytes in fifo */ 368 outb(1, qbase + 3); /* clear fifo */ 369/* note that request_bufflen is the total xfer size when sg is used */ 370 reqlen = cmd->request_bufflen; 371/* note that it won't work if transfers > 16M are requested */ 372 if (reqlen && !((phase = inb(qbase + 4)) & 6)) { /* data phase */ 373rtrc(2) 374 outb(reqlen, qbase); /* low-mid xfer cnt */ 375 outb(reqlen >> 8, qbase+1); /* low-mid xfer cnt */ 376 outb(reqlen >> 16, qbase + 0xe); /* high xfer cnt */ 377 outb(0x90, qbase + 3); /* command do xfer */ 378/* PIO pseudo DMA to buffer or sglist */ 379 REG1; 380 if (!cmd->use_sg) 381 ql_pdma(phase, cmd->request_buffer, cmd->request_bufflen); 382 else { 383 sgcount = cmd->use_sg; 384 sglist = cmd->request_buffer; 385 while (sgcount--) { 386 if (qabort) { 387 REG0; 388 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); 389 } 390 if (ql_pdma(phase, sglist->address, sglist->length)) 391 break; 392 sglist++; 393 } 394 } 395 REG0; 396rtrc(2) 397/* wait for irq (split into second state of irq handler if this can take time) */ 398 if ((k = ql_wai())) 399 return (k << 16); 400 k = inb(qbase + 5); /* should be 0x10, bus service */ 401 } 402/*** Enter Status (and Message In) Phase ***/ 403 k = jiffies + WATCHDOG; 404 while ( time_before(jiffies, k) && !qabort && !(inb(qbase + 4) & 6)); /* wait for status phase */ 405 if ( time_after_eq(jiffies, k) ) { 406 ql_zap(); 407 return (DID_TIME_OUT << 16); 408 } 409 while (inb(qbase + 5)); /* clear pending ints */ 410 if (qabort) 411 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); 412 outb(0x11, qbase + 3); /* get status and message */ 413 if ((k = ql_wai())) 414 return (k << 16); 415 i = inb(qbase + 5); /* get chip irq stat */ 416 j = inb(qbase + 7) & 0x1f; /* and bytes rec'd */ 417 status = inb(qbase + 2); 418 message = inb(qbase + 2); 419/* should get function complete int if Status and message, else bus serv if only status */ 420 if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) { 421 printk("Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j); 422 result = DID_ERROR; 423 } 424 outb(0x12, qbase + 3); /* done, disconnect */ 425rtrc(1) 426 if ((k = ql_wai())) 427 return (k << 16); 428/* should get bus service interrupt and disconnect interrupt */ 429 i = inb(qbase + 5); /* should be bus service */ 430 while (!qabort && ((i & 0x20) != 0x20)) { 431 barrier(); 432 cpu_relax(); 433 i |= inb(qbase + 5); 434 } 435rtrc(0) 436 if (qabort) 437 return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16); 438 return (result << 16) | (message << 8) | (status & STATUS_MASK); 439} 440 441#if QL_USE_IRQ 442/*----------------------------------------------------------------*/ 443/* interrupt handler */ 444static void ql_ihandl(int irq, void *dev_id, struct pt_regs * regs) 445{ 446Scsi_Cmnd *icmd; 447 REG0; 448 if (!(inb(qbase + 4) & 0x80)) /* false alarm? */ 449 return; 450 if (qlcmd == NULL) { /* no command to process? */ 451 int i; 452 i = 16; 453 while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */ 454 return; 455 } 456 icmd = qlcmd; 457 icmd->result = ql_pcmd(icmd); 458 qlcmd = NULL; 459/* if result is CHECK CONDITION done calls qcommand to request sense */ 460 (icmd->scsi_done) (icmd); 461} 462 463static void do_ql_ihandl(int irq, void *dev_id, struct pt_regs * regs) 464{ 465 unsigned long flags; 466 467 spin_lock_irqsave(&io_request_lock, flags); 468 ql_ihandl(irq, dev_id, regs); 469 spin_unlock_irqrestore(&io_request_lock, flags); 470} 471#endif 472 473/*----------------------------------------------------------------*/ 474/* global functions */ 475/*----------------------------------------------------------------*/ 476/* non queued command */ 477#if QL_USE_IRQ 478static void qlidone(Scsi_Cmnd * cmd) {}; /* null function */ 479#endif 480 481/* command process */ 482int qlogicfas_command(Scsi_Cmnd * cmd) 483{ 484int k; 485#if QL_USE_IRQ 486 if (qlirq >= 0) { 487 qlogicfas_queuecommand(cmd, qlidone); 488 while (qlcmd != NULL); 489 return cmd->result; 490 } 491#endif 492/* non-irq version */ 493 if (cmd->target == qinitid) 494 return (DID_BAD_TARGET << 16); 495 ql_icmd(cmd); 496 if ((k = ql_wai())) 497 return (k << 16); 498 return ql_pcmd(cmd); 499 500} 501 502#if QL_USE_IRQ 503/*----------------------------------------------------------------*/ 504/* queued command */ 505int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 506{ 507 if(cmd->target == qinitid) { 508 cmd->result = DID_BAD_TARGET << 16; 509 done(cmd); 510 return 0; 511 } 512 513 cmd->scsi_done = done; 514/* wait for the last command's interrupt to finish */ 515 while (qlcmd != NULL) { 516 barrier(); 517 cpu_relax(); 518 } 519 ql_icmd(cmd); 520 return 0; 521} 522#else 523int qlogicfas_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) 524{ 525 return 1; 526} 527#endif 528 529#ifdef PCMCIA 530/*----------------------------------------------------------------*/ 531/* allow PCMCIA code to preset the port */ 532/* port should be 0 and irq to -1 respectively for autoprobing */ 533void qlogicfas_preset(int port, int irq) 534{ 535 qbase=port; 536 qlirq=irq; 537} 538#endif 539 540/*----------------------------------------------------------------*/ 541/* look for qlogic card and init if found */ 542int __QLINIT qlogicfas_detect(Scsi_Host_Template * host) 543{ 544int i, j; /* these are only used by IRQ detect */ 545int qltyp; /* type of chip */ 546struct Scsi_Host *hreg; /* registered host structure */ 547unsigned long flags; 548 549host->proc_name = "qlogicfas"; 550 551/* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the 552 address - I check 230 first since MIDI cards are typically at 330 553 554 Theoretically, two Qlogic cards can coexist in the same system. This 555 should work by simply using this as a loadable module for the second 556 card, but I haven't tested this. 557*/ 558 559 if( !qbase ) { 560 for (qbase = 0x230; qbase < 0x430; qbase += 0x100) { 561 if( !request_region( qbase , 0x10, "qlogicfas" ) ) 562 continue; 563 REG1; 564 if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) 565 && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) ) 566 break; 567 release_region(qbase, 0x10 ); 568 } 569 if (qbase == 0x430) 570 return 0; 571 } 572 else 573 printk( "Ql: Using preset base address of %03x\n", qbase ); 574 575 qltyp = inb(qbase + 0xe) & 0xf8; 576 qinitid = host->this_id; 577 if (qinitid < 0) 578 qinitid = 7; /* if no ID, use 7 */ 579 outb(1, qbase + 8); /* set for PIO pseudo DMA */ 580 REG0; 581 outb(0x40 | qlcfg8 | qinitid, qbase + 8); /* (ini) bus id, disable scsi rst */ 582 outb(qlcfg5, qbase + 5); /* select timer */ 583 outb(qlcfg9, qbase + 9); /* prescaler */ 584#if QL_RESET_AT_START 585 outb( 3 , qbase + 3 ); 586 REG1; 587 while( inb( qbase + 0xf ) & 4 ); 588 REG0; 589#endif 590#if QL_USE_IRQ 591/* IRQ probe - toggle pin and check request pending */ 592 593 if( qlirq == -1 ) { 594 save_flags( flags ); 595 cli(); 596 i = 0xffff; 597 j = 3; 598 outb(0x90, qbase + 3); /* illegal command - cause interrupt */ 599 REG1; 600 outb(10, 0x20); /* access pending interrupt map */ 601 outb(10, 0xa0); 602 while (j--) { 603 outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin off */ 604 i &= ~(inb(0x20) | (inb(0xa0) << 8)); /* find IRQ off */ 605 outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd); /* int pin on */ 606 i &= inb(0x20) | (inb(0xa0) << 8); /* find IRQ on */ 607 } 608 REG0; 609 while (inb(qbase + 5)); /* purge int */ 610 j = -1; 611 while (i) /* find on bit */ 612 i >>= 1, j++; /* should check for exactly 1 on */ 613 qlirq = j; 614 restore_flags( flags ); 615 } 616 else 617 printk( "Ql: Using preset IRQ %d\n", qlirq ); 618 619 if (qlirq >= 0 && !request_irq(qlirq, do_ql_ihandl, 0, "qlogicfas", NULL)) 620 host->can_queue = 1; 621#endif 622 hreg = scsi_register( host , 0 ); /* no host data */ 623 if (!hreg) 624 goto err_release_mem; 625 hreg->io_port = qbase; 626 hreg->n_io_port = 16; 627 hreg->dma_channel = -1; 628 if( qlirq != -1 ) 629 hreg->irq = qlirq; 630 631 sprintf(qinfo, "Qlogicfas Driver version 0.46, chip %02X at %03X, IRQ %d, TPdma:%d", 632 qltyp, qbase, qlirq, QL_TURBO_PDMA ); 633 host->name = qinfo; 634 635 return 1; 636 637 err_release_mem: 638 release_region(qbase, 0x10); 639 if (host->can_queue) 640 free_irq(qlirq, do_ql_ihandl); 641 return 0; 642 643} 644 645/*----------------------------------------------------------------*/ 646/* return bios parameters */ 647int qlogicfas_biosparam(Disk * disk, kdev_t dev, int ip[]) 648{ 649/* This should mimic the DOS Qlogic driver's behavior exactly */ 650 ip[0] = 0x40; 651 ip[1] = 0x20; 652 ip[2] = disk->capacity / (ip[0] * ip[1]); 653 if (ip[2] > 1024) { 654 ip[0] = 0xff; 655 ip[1] = 0x3f; 656 ip[2] = disk->capacity / (ip[0] * ip[1]); 657 } 658 return 0; 659} 660 661/*----------------------------------------------------------------*/ 662/* abort command in progress */ 663int qlogicfas_abort(Scsi_Cmnd * cmd) 664{ 665 qabort = 1; 666 ql_zap(); 667 return 0; 668} 669 670/*----------------------------------------------------------------*/ 671/* reset SCSI bus */ 672int qlogicfas_reset(Scsi_Cmnd * cmd, unsigned int ignored) 673{ 674 qabort = 2; 675 ql_zap(); 676 return 1; 677} 678 679/*----------------------------------------------------------------*/ 680/* return info string */ 681const char *qlogicfas_info(struct Scsi_Host * host) 682{ 683 return qinfo; 684} 685MODULE_LICENSE("GPL"); 686 687/* Eventually this will go into an include file, but this will be later */ 688static Scsi_Host_Template driver_template = QLOGICFAS; 689#include "scsi_module.c" 690 691