patch-pre2.0.6 linux/drivers/scsi/qlogic.c

Next file: linux/drivers/scsi/qlogic.h
Previous file: linux/drivers/scsi/hosts.h
Back to the patch index
Back to the overall index

diff -u --recursive --new-file pre2.0.5/linux/drivers/scsi/qlogic.c linux/drivers/scsi/qlogic.c
@@ -1,678 +0,0 @@
-/*----------------------------------------------------------------*/
-/*
-   Qlogic linux driver - work in progress. No Warranty express or implied.
-   Use at your own risk.  Support Tort Reform so you won't have to read all
-   these silly disclaimers.
-
-   Copyright 1994, Tom Zerucha.   
-   zerucha@shell.portal.com
-
-   Additional Code, and much appreciated help by
-   Michael A. Griffith
-   grif@cs.ucr.edu
-
-   Thanks to Eric Youngdale and Dave Hinds for loadable module and PCMCIA
-   help respectively, and for suffering through my foolishness during the
-   debugging process.
-
-   Reference Qlogic FAS408 Technical Manual, 53408-510-00A, May 10, 1994
-   (you can reference it, but it is incomplete and inaccurate in places)
-
-   Version 0.43 4/6/95 - kernel 1.2.0+, pcmcia 2.5.4+
-
-   Functions as standalone, loadable, and PCMCIA driver, the latter from
-   Dave Hind's PCMCIA package.
-
-   Redistributable under terms of the GNU Public License
-
-*/
-/*----------------------------------------------------------------*/
-/* Configuration */
-
-/* Set the following to 2 to use normal interrupt (active high/totempole-
-   tristate), otherwise use 0 (REQUIRED FOR PCMCIA) for active low, open
-   drain */
-#define QL_INT_ACTIVE_HIGH 2
-
-/* Set the following to 1 to enable the use of interrupts.  Note that 0 tends
-   to be more stable, but slower (or ties up the system more) */
-#define QL_USE_IRQ 1
-
-/* Set the following to max out the speed of the PIO PseudoDMA transfers,
-   again, 0 tends to be slower, but more stable.  */
-#define QL_TURBO_PDMA 1
-
-/* This should be 1 to enable parity detection */
-#define QL_ENABLE_PARITY 1
-
-/* This will reset all devices when the driver is initialized (during bootup).
-   The other linux drivers don't do this, but the DOS drivers do, and after
-   using DOS or some kind of crash or lockup this will bring things back
-   without requiring a cold boot.  It does take some time to recover from a
-   reset, so it is slower, and I have seen timeouts so that devices weren't
-   recognized when this was set. */
-#define QL_RESET_AT_START 0
-
-/* crystal frequency in megahertz (for offset 5 and 9)
-   Please set this for your card.  Most Qlogic cards are 40 Mhz.  The
-   Control Concepts ISA (not VLB) is 24 Mhz */
-#define XTALFREQ	40
-
-/**********/
-/* DANGER! modify these at your own risk */
-/* SLOWCABLE can usually be reset to zero if you have a clean setup and
-   proper termination.  The rest are for synchronous transfers and other
-   advanced features if your device can transfer faster than 5Mb/sec.
-   If you are really curious, email me for a quick howto until I have
-   something official */
-/**********/
-
-/*****/
-/* config register 1 (offset 8) options */
-/* This needs to be set to 1 if your cabling is long or noisy */
-#define SLOWCABLE 1
-
-/*****/
-/* offset 0xc */
-/* This will set fast (10Mhz) synchronous timing when set to 1
-   For this to have an effect, FASTCLK must also be 1 */
-#define FASTSCSI 0
-
-/* This when set to 1 will set a faster sync transfer rate */
-#define FASTCLK 0
-/*(XTALFREQ>25?1:0)*/
-
-/*****/
-/* offset 6 */
-/* This is the sync transfer divisor, XTALFREQ/X will be the maximum
-   achievable data rate (assuming the rest of the system is capable
-   and set properly) */
-#define SYNCXFRPD 5
-/*(XTALFREQ/5)*/
-
-/*****/
-/* offset 7 */
-/* This is the count of how many synchronous transfers can take place
-	i.e. how many reqs can occur before an ack is given.
-	The maximum value for this is 15, the upper bits can modify
-	REQ/ACK assertion and deassertion during synchronous transfers
-	If this is 0, the bus will only transfer asynchronously */
-#define SYNCOFFST 0
-/* for the curious, bits 7&6 control the deassertion delay in 1/2 cycles
-	of the 40Mhz clock. If FASTCLK is 1, specifying 01 (1/2) will
-	cause the deassertion to be early by 1/2 clock.  Bits 5&4 control
-	the assertion delay, also in 1/2 clocks (FASTCLK is ignored here). */
-
-/*----------------------------------------------------------------*/
-#ifdef PCMCIA
-#undef QL_INT_ACTIVE_HIGH
-#define QL_INT_ACTIVE_HIGH 0
-#define MODULE
-#endif 
-
-#include <linux/module.h>
-
-#ifdef PCMCIA
-#undef MODULE
-#endif 
-
-#include <linux/blk.h>	/* to get disk capacity */
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
-#include <linux/unistd.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include "sd.h"
-#include "hosts.h"
-#include "qlogic.h"
-#include<linux/stat.h>
-
-struct proc_dir_entry proc_scsi_qlogic = {
-    PROC_SCSI_QLOGIC, 6, "qlogic",
-    S_IFDIR | S_IRUGO | S_IXUGO, 2
-};
-
-/*----------------------------------------------------------------*/
-/* driver state info, local to driver */
-static int	    qbase = 0;	/* Port */
-static int	    qinitid;	/* initiator ID */
-static int	    qabort;	/* Flag to cause an abort */
-static int	    qlirq = -1;	/* IRQ being used */
-static char	    qinfo[80];	/* description */
-static Scsi_Cmnd   *qlcmd;	/* current command being processed */
-
-static int	    qlcfg5 = ( XTALFREQ << 5 );	/* 15625/512 */
-static int	    qlcfg6 = SYNCXFRPD;
-static int	    qlcfg7 = SYNCOFFST;
-static int	    qlcfg8 = ( SLOWCABLE << 7 ) | ( QL_ENABLE_PARITY << 4 );
-static int	    qlcfg9 = ( ( XTALFREQ + 4 ) / 5 );
-static int	    qlcfgc = ( FASTCLK << 3 ) | ( FASTSCSI << 4 );
-
-/*----------------------------------------------------------------*/
-/* The qlogic card uses two register maps - These macros select which one */
-#define REG0 ( outb( inb( qbase + 0xd ) & 0x7f , qbase + 0xd ), outb( 4 , qbase + 0xd ))
-#define REG1 ( outb( inb( qbase + 0xd ) | 0x80 , qbase + 0xd ), outb( 0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd ))
-
-/* following is watchdog timeout in microseconds */
-#define WATCHDOG 5000000
-
-/*----------------------------------------------------------------*/
-/* the following will set the monitor border color (useful to find
-   where something crashed or gets stuck at and as a simple profiler) */
-
-#if 0
-#define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);}
-#else
-#define rtrc(i) {}
-#endif
-
-/*----------------------------------------------------------------*/
-/* local functions */
-/*----------------------------------------------------------------*/
-static void	ql_zap(void);
-/* error recovery - reset everything */
-void	ql_zap()
-{
-int	x;
-unsigned long	flags;
-	save_flags( flags );
-	cli();
-	x = inb(qbase + 0xd);
-	REG0;
-	outb(3, qbase + 3);				/* reset SCSI */
-	outb(2, qbase + 3);				/* reset chip */
-	if (x & 0x80)
-		REG1;
-	restore_flags( flags );
-}
-
-/*----------------------------------------------------------------*/
-/* do pseudo-dma */
-static int	ql_pdma(int phase, char *request, int reqlen)
-{
-int	j;
-	j = 0;
-	if (phase & 1) {	/* in */
-#if QL_TURBO_PDMA
-rtrc(4)
-		/* empty fifo in large chunks */
-		if( reqlen >= 128 && (inb( qbase + 8 ) & 2) ) { /* full */
-			insl( qbase + 4, request, 32 );
-			reqlen -= 128;
-			request += 128;
-		}
-		while( reqlen >= 84 && !( j & 0xc0 ) ) /* 2/3 */
-			if( (j=inb( qbase + 8 )) & 4 ) {
-				insl( qbase + 4, request, 21 );
-				reqlen -= 84;
-				request += 84;
-			}
-		if( reqlen >= 44 && (inb( qbase + 8 ) & 8) ) {	/* 1/3 */
-			insl( qbase + 4, request, 11 );
-			reqlen -= 44;
-			request += 44;
-		}
-#endif
-		/* until both empty and int (or until reclen is 0) */
-rtrc(7)
-		j = 0;
-		while( reqlen && !( (j & 0x10) && (j & 0xc0) ) ) {
-			/* while bytes to receive and not empty */
-			j &= 0xc0;
-			while ( reqlen && !( (j=inb(qbase + 8)) & 0x10 ) ) {
-				*request++ = inb(qbase + 4);
-				reqlen--;
-			}
-			if( j & 0x10 )
-				j = inb(qbase+8);
-
-		}
-	}
-	else {	/* out */
-#if QL_TURBO_PDMA
-rtrc(4)
-		if( reqlen >= 128 && inb( qbase + 8 ) & 0x10 ) { /* empty */
-			outsl(qbase + 4, request, 32 );
-			reqlen -= 128;
-			request += 128;
-		}
-		while( reqlen >= 84 && !( j & 0xc0 ) ) /* 1/3 */
-			if( !((j=inb( qbase + 8 )) & 8) ) {
-				outsl( qbase + 4, request, 21 );
-				reqlen -= 84;
-				request += 84;
-			}
-		if( reqlen >= 40 && !(inb( qbase + 8 ) & 4 ) ) { /* 2/3 */
-			outsl( qbase + 4, request, 10 );
-			reqlen -= 40;
-			request += 40;
-		}
-#endif
-		/* until full and int (or until reclen is 0) */
-rtrc(7)
-		j = 0;
-		while( reqlen && !( (j & 2) && (j & 0xc0) ) ) {
-			/* while bytes to send and not full */
-			while ( reqlen && !( (j=inb(qbase + 8)) & 2 ) ) {
-				outb(*request++, qbase + 4);
-				reqlen--;
-			}
-			if( j & 2 )
-				j = inb(qbase+8);
-		}
-	}
-/* maybe return reqlen */
-	return inb( qbase + 8 ) & 0xc0;
-}
-
-/*----------------------------------------------------------------*/
-/* wait for interrupt flag (polled - not real hardware interrupt) */
-static int	ql_wai(void)
-{
-int	i,k;
-	k = 0;
-	i = jiffies + WATCHDOG;
-	while ( i > jiffies && !qabort && !((k = inb(qbase + 4)) & 0xe0))
-		barrier();
-	if (i <= jiffies)
-		return (DID_TIME_OUT);
-	if (qabort)
-		return (qabort == 1 ? DID_ABORT : DID_RESET);
-	if (k & 0x60)
-		ql_zap();
-	if (k & 0x20)
-		return (DID_PARITY);
-	if (k & 0x40)
-		return (DID_ERROR);
-	return 0;
-}
-
-/*----------------------------------------------------------------*/
-/* initiate scsi command - queueing handler */
-static void	ql_icmd(Scsi_Cmnd * cmd)
-{
-unsigned int	    i;
-unsigned long	flags;
-
-	qabort = 0;
-
-	save_flags( flags );
-	cli();
-	REG0;
-/* clearing of interrupts and the fifo is needed */
-	inb(qbase + 5); 			/* clear interrupts */
-	if (inb(qbase + 5))			/* if still interrupting */
-		outb(2, qbase + 3);		/* reset chip */
-	else if (inb(qbase + 7) & 0x1f)
-		outb(1, qbase + 3);		/* clear fifo */
-	while (inb(qbase + 5)); 		/* clear ints */
-	REG1;
-	outb(1, qbase + 8);			/* set for PIO pseudo DMA */
-	outb(0, qbase + 0xb);			/* disable ints */
-	inb(qbase + 8); 			/* clear int bits */
-	REG0;
-	outb(0x40, qbase + 0xb);		/* enable features */
-
-/* configurables */
-	outb( qlcfgc , qbase + 0xc);
-/* config: no reset interrupt, (initiator) bus id */
-	outb( 0x40 | qlcfg8 | qinitid, qbase + 8);
-	outb( qlcfg7 , qbase + 7 );
-	outb( qlcfg6 , qbase + 6 );
-/**/
-	outb(qlcfg5, qbase + 5);		/* select timer */
-	outb(qlcfg9 & 7, qbase + 9);			/* prescaler */
-/*	outb(0x99, qbase + 5);	*/
-	outb(cmd->target, qbase + 4);
-
-	for (i = 0; i < cmd->cmd_len; i++)
-		outb(cmd->cmnd[i], qbase + 2);
-	qlcmd = cmd;
-	outb(0x41, qbase + 3);	/* select and send command */
-	restore_flags( flags );
-}
-/*----------------------------------------------------------------*/
-/* process scsi command - usually after interrupt */
-static unsigned int	ql_pcmd(Scsi_Cmnd * cmd)
-{
-unsigned int	i, j, k;
-unsigned int	result; 		/* ultimate return result */
-unsigned int	status; 		/* scsi returned status */
-unsigned int	message;		/* scsi returned message */
-unsigned int	phase;			/* recorded scsi phase */
-unsigned int	reqlen; 		/* total length of transfer */
-struct scatterlist	*sglist;	/* scatter-gather list pointer */
-unsigned int	sgcount;		/* sg counter */
-
-rtrc(1)
-	j = inb(qbase + 6);
-	i = inb(qbase + 5);
-	if (i == 0x20) {
-		return (DID_NO_CONNECT << 16);
-	}
-	i |= inb(qbase + 5);	/* the 0x10 bit can be set after the 0x08 */
-	if (i != 0x18) {
-		printk("Ql:Bad Interrupt status:%02x\n", i);
-		ql_zap();
-		return (DID_BAD_INTR << 16);
-	}
-	j &= 7; /* j = inb( qbase + 7 ) >> 5; */
-/* correct status is supposed to be step 4 */
-/* it sometimes returns step 3 but with 0 bytes left to send */
-/* We can try stuffing the FIFO with the max each time, but we will get a
-   sequence of 3 if any bytes are left (but we do flush the FIFO anyway */
-	if(j != 3 && j != 4) {
-		printk("Ql:Bad sequence for command %d, int %02X, cmdleft = %d\n", j, i, inb( qbase+7 ) & 0x1f );
-		ql_zap();
-		return (DID_ERROR << 16);
-	}
-	result = DID_OK;
-	if (inb(qbase + 7) & 0x1f)	/* if some bytes in fifo */
-		outb(1, qbase + 3);		/* clear fifo */
-/* note that request_bufflen is the total xfer size when sg is used */
-	reqlen = cmd->request_bufflen;
-/* note that it won't work if transfers > 16M are requested */
-	if (reqlen && !((phase = inb(qbase + 4)) & 6)) {	/* data phase */
-rtrc(2)
-		outb(reqlen, qbase);			/* low-mid xfer cnt */
-		outb(reqlen >> 8, qbase+1);			/* low-mid xfer cnt */
-		outb(reqlen >> 16, qbase + 0xe);	/* high xfer cnt */
-		outb(0x90, qbase + 3);			/* command do xfer */
-/* PIO pseudo DMA to buffer or sglist */
-		REG1;
-		if (!cmd->use_sg)
-			ql_pdma(phase, cmd->request_buffer, cmd->request_bufflen);
-		else {
-			sgcount = cmd->use_sg;
-			sglist = cmd->request_buffer;
-			while (sgcount--) {
-				if (qabort) {
-					REG0;
-					return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
-				}
-				if (ql_pdma(phase, sglist->address, sglist->length))
-					break;
-				sglist++;
-			}
-		}
-		REG0;
-rtrc(2)
-/* wait for irq (split into second state of irq handler if this can take time) */
-		if ((k = ql_wai()))
-			return (k << 16);
-		k = inb(qbase + 5);	/* should be 0x10, bus service */
-	}
-/*** Enter Status (and Message In) Phase ***/
-	k = jiffies + WATCHDOG;
-	while ( k > jiffies && !qabort && !(inb(qbase + 4) & 6));	/* wait for status phase */
-	if ( k <= jiffies ) {
-		ql_zap();
-		return (DID_TIME_OUT << 16);
-	}
-	while (inb(qbase + 5)); 				/* clear pending ints */
-	if (qabort)
-		return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
-	outb(0x11, qbase + 3);					/* get status and message */
-	if ((k = ql_wai()))
-		return (k << 16);
-	i = inb(qbase + 5);					/* get chip irq stat */
-	j = inb(qbase + 7) & 0x1f;				/* and bytes rec'd */
-	status = inb(qbase + 2);
-	message = inb(qbase + 2);
-/* should get function complete int if Status and message, else bus serv if only status */
-	if (!((i == 8 && j == 2) || (i == 0x10 && j == 1))) {
-		printk("Ql:Error during status phase, int=%02X, %d bytes recd\n", i, j);
-		result = DID_ERROR;
-	}
-	outb(0x12, qbase + 3);	/* done, disconnect */
-rtrc(1)
-	if ((k = ql_wai()))
-		return (k << 16);
-/* should get bus service interrupt and disconnect interrupt */
-	i = inb(qbase + 5);	/* should be bus service */
-	while (!qabort && ((i & 0x20) != 0x20)) {
-		barrier();
-		i |= inb(qbase + 5);
-	}
-rtrc(0)
-	if (qabort)
-		return ((qabort == 1 ? DID_ABORT : DID_RESET) << 16);
-	return (result << 16) | (message << 8) | (status & STATUS_MASK);
-}
-
-#if QL_USE_IRQ
-/*----------------------------------------------------------------*/
-/* interrupt handler */
-static void	       ql_ihandl(int irq, void *dev_id, struct pt_regs * regs)
-{
-Scsi_Cmnd	   *icmd;
-	REG0;
-	if (!(inb(qbase + 4) & 0x80))	/* false alarm? */
-		return;
-	if (qlcmd == NULL) {		/* no command to process? */
-		int	i;
-		i = 16;
-		while (i-- && inb(qbase + 5)); /* maybe also ql_zap() */
-		return;
-	}
-	icmd = qlcmd;
-	icmd->result = ql_pcmd(icmd);
-	qlcmd = NULL;
-/* if result is CHECK CONDITION done calls qcommand to request sense */
-	(icmd->scsi_done) (icmd);
-}
-#endif
-
-/*----------------------------------------------------------------*/
-/* global functions */
-/*----------------------------------------------------------------*/
-/* non queued command */
-#if QL_USE_IRQ
-static void	qlidone(Scsi_Cmnd * cmd) {};		/* null function */
-#endif
-
-/* command process */
-int	qlogic_command(Scsi_Cmnd * cmd)
-{
-int	k;
-#if QL_USE_IRQ
-	if (qlirq >= 0) {
-		qlogic_queuecommand(cmd, qlidone);
-		while (qlcmd != NULL);
-		return cmd->result;
-	}
-#endif
-/* non-irq version */
-	if (cmd->target == qinitid)
-		return (DID_BAD_TARGET << 16);
-	ql_icmd(cmd);
-	if ((k = ql_wai()))
-		return (k << 16);
-	return ql_pcmd(cmd);
-
-}
-
-#if QL_USE_IRQ
-/*----------------------------------------------------------------*/
-/* queued command */
-int	qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
-{
-	if(cmd->target == qinitid) {
-		cmd->result = DID_BAD_TARGET << 16;
-		done(cmd);
-		return 0;
-	}
-
-	cmd->scsi_done = done;
-/* wait for the last command's interrupt to finish */
-	while (qlcmd != NULL)
-		barrier();
-	ql_icmd(cmd);
-	return 0;
-}
-#else
-int	qlogic_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *))
-{
-	return 1;
-}
-#endif
-
-#ifdef PCMCIA
-/*----------------------------------------------------------------*/
-/* allow PCMCIA code to preset the port */
-/* port should be 0 and irq to -1 respectively for autoprobing */
-void	qlogic_preset(int port, int irq)
-{
-	qbase=port;
-	qlirq=irq;
-}
-#endif
-
-/*----------------------------------------------------------------*/
-/* look for qlogic card and init if found */
-int	qlogic_detect(Scsi_Host_Template * host)
-{
-int	i, j;			/* these are only used by IRQ detect */
-int	qltyp;			/* type of chip */
-struct	Scsi_Host	*hreg;	/* registered host structure */
-unsigned long	flags;
-
-host->proc_dir =  &proc_scsi_qlogic;
-
-/* Qlogic Cards only exist at 0x230 or 0x330 (the chip itself decodes the
-   address - I check 230 first since MIDI cards are typically at 330
-
-   Theoretically, two Qlogic cards can coexist in the same system.  This
-   should work by simply using this as a loadable module for the second
-   card, but I haven't tested this.
-*/
-
-	if( !qbase ) {
-		for (qbase = 0x230; qbase < 0x430; qbase += 0x100) {
-			if( check_region( qbase , 0x10 ) )
-				continue;
-			REG1;
-			if ( ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 )
-			  && ( (inb(qbase + 0xe) ^ inb(qbase + 0xe)) == 7 ) )
-				break;
-		}
-		if (qbase == 0x430)
-			return 0;
-	}
-	else
-		printk( "Ql: Using preset base address of %03x\n", qbase );
-
-	qltyp = inb(qbase + 0xe) & 0xf8;
-	qinitid = host->this_id;
-	if (qinitid < 0)
-		qinitid = 7;			/* if no ID, use 7 */
-	outb(1, qbase + 8);			/* set for PIO pseudo DMA */
-	REG0;
-	outb(0x40 | qlcfg8 | qinitid, qbase + 8);	/* (ini) bus id, disable scsi rst */
-	outb(qlcfg5, qbase + 5);		/* select timer */
-	outb(qlcfg9, qbase + 9);			/* prescaler */
-#if QL_RESET_AT_START
-	outb( 3 , qbase + 3 );
-	REG1;
-	while( inb( qbase + 0xf ) & 4 );
-	REG0;
-#endif
-#if QL_USE_IRQ
-/* IRQ probe - toggle pin and check request pending */
-
-	if( qlirq == -1 ) {
-		save_flags( flags );
-		cli();
-		i = 0xffff;
-		j = 3;
-		outb(0x90, qbase + 3);	/* illegal command - cause interrupt */
-		REG1;
-		outb(10, 0x20); /* access pending interrupt map */
-		outb(10, 0xa0);
-		while (j--) {
-			outb(0xb0 | QL_INT_ACTIVE_HIGH , qbase + 0xd);	/* int pin off */
-			i &= ~(inb(0x20) | (inb(0xa0) << 8));	/* find IRQ off */
-			outb(0xb4 | QL_INT_ACTIVE_HIGH , qbase + 0xd);	/* int pin on */
-			i &= inb(0x20) | (inb(0xa0) << 8);	/* find IRQ on */
-		}
-		REG0;
-		while (inb(qbase + 5)); 			/* purge int */
-		j = -1;
-		while (i)					/* find on bit */
-			i >>= 1, j++;	/* should check for exactly 1 on */
-		qlirq = j;
-		restore_flags( flags );
-	}
-	else
-		printk( "Ql: Using preset IRQ %d\n", qlirq );
-
-	if (qlirq >= 0 && !request_irq(qlirq, ql_ihandl, 0, "qlogic", NULL))
-		host->can_queue = 1;
-#endif
-	request_region( qbase , 0x10 ,"qlogic");
-	hreg = scsi_register( host , 0 );	/* no host data */
-	hreg->io_port = qbase;
-	hreg->n_io_port = 16;
-	hreg->dma_channel = -1;
-	if( qlirq != -1 )
-		hreg->irq = qlirq;
-
-	sprintf(qinfo, "Qlogic Driver version 0.43, chip %02X at %03X, IRQ %d, TPdma:%d",
-	    qltyp, qbase, qlirq, QL_TURBO_PDMA );
-	host->name = qinfo;
-
-	return 1;
-}
-
-/*----------------------------------------------------------------*/
-/* return bios parameters */
-int	qlogic_biosparam(Disk * disk, kdev_t dev, int ip[])
-{
-/* This should mimic the DOS Qlogic driver's behavior exactly */
-	ip[0] = 0x40;
-	ip[1] = 0x20;
-	ip[2] = disk->capacity / (ip[0] * ip[1]);
-	if (ip[2] > 1024) {
-		ip[0] = 0xff;
-		ip[1] = 0x3f;
-		ip[2] = disk->capacity / (ip[0] * ip[1]);
-		if (ip[2] > 1023)
-			ip[2] = 1023;
-	}
-	return 0;
-}
-
-/*----------------------------------------------------------------*/
-/* abort command in progress */
-int	qlogic_abort(Scsi_Cmnd * cmd)
-{
-	qabort = 1;
-	ql_zap();
-	return 0;
-}
-
-/*----------------------------------------------------------------*/
-/* reset SCSI bus */
-int	qlogic_reset(Scsi_Cmnd * cmd)
-{
-	qabort = 2;
-	ql_zap();
-	return 1;
-}
-
-/*----------------------------------------------------------------*/
-/* return info string */
-const char	*qlogic_info(struct Scsi_Host * host)
-{
-	return qinfo;
-}
-
-#ifdef MODULE
-/* Eventually this will go into an include file, but this will be later */
-Scsi_Host_Template driver_template = QLOGIC;
-
-#include "scsi_module.c"
-#endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov with Sam's (original) version
of this