patch-2.2.4 linux/drivers/scsi/pci2000.c

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

diff -u --recursive --new-file v2.2.3/linux/drivers/scsi/pci2000.c linux/drivers/scsi/pci2000.c
@@ -1,7 +1,7 @@
 /*+M*************************************************************************
  * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
  *
- * Copyright (c) 1997 Perceptive Solutions, Inc.
+ * Copyright (c) 1999 Perceptive Solutions, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -20,13 +20,24 @@
  *
  *	File Name:		pci2000i.c
  *
+ *	Revisions	1.10	Jan-21-1999
+ *		- Fixed sign on message to reflect proper controller name.
+ *		- Added support for RAID status monitoring and control.
+ *
+ *  Revisions	1.11	Mar-22-1999
+ *		- Fixed control timeout to not lock up the entire system if
+ *		  controller goes offline completely.
+ *
  *-M*************************************************************************/
+#define PCI2000_VERSION		"1.11"
 
 #include <linux/module.h>
 
 #include <linux/kernel.h>
+#include <linux/head.h>
 #include <linux/types.h>
 #include <linux/string.h>
+#include <linux/bios32.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
@@ -34,7 +45,6 @@
 #include <linux/proc_fs.h>
 #include <asm/dma.h>
 #include <asm/system.h>
-#include <asm/spinlock.h>
 #include <asm/io.h>
 #include <linux/blk.h>
 #include "scsi.h"
@@ -89,7 +99,6 @@
 
 static struct	Scsi_Host 	   *PsiHost[MAXADAPTER] = {NULL,};  // One for each adapter
 static			int				NumAdapters = 0;
-
 /****************************************************************
  *	Name:			WaitReady	:LOCAL
  *
@@ -102,13 +111,14 @@
  ****************************************************************/
 static int WaitReady (PADAPTER2000 padapter)
 	{
-	ULONG	timer;
+	ULONG	z;
 
-	timer = jiffies + TIMEOUT_COMMAND;								// calculate the timeout value
-	do	{
+	for ( z = 0;  z < (TIMEOUT_COMMAND * 4);  z++ )
+		{
 		if ( !inb_p (padapter->cmd) )
 			return FALSE;
-		}	while ( timer > jiffies );									// test for timeout
+		udelay (250);
+		};								
 	return TRUE;
 	}
 /****************************************************************
@@ -180,6 +190,26 @@
 	outl (SCpnt->request_bufflen, padapter->mb3);
 	return TRUE;
 	}
+/*********************************************************************
+ *	Name:	PsiRaidCmd
+ *
+ *	Description:	Execute a simple command.
+ *
+ *	Parameters:		padapter - Pointer to adapter control structure.
+ *					cmd		 - Roy command byte.
+ *
+ *	Returns:		Return error status.
+ *
+ ********************************************************************/
+static int PsiRaidCmd (PADAPTER2000 padapter, char cmd)
+	{
+	if ( WaitReady (padapter) )						// test for command register ready
+		return DID_TIME_OUT;
+	outb_p (cmd, padapter->cmd);					// issue command
+	if ( WaitReady (padapter) )						// wait for adapter ready
+		return DID_TIME_OUT;
+	return DID_OK;
+	}
 /****************************************************************
  *	Name:	Irq_Handler	:LOCAL
  *
@@ -366,7 +396,35 @@
 	switch ( *cdb )
 		{
 		case SCSIOP_INQUIRY:   					// inquiry CDB
-			{
+			if ( cdb[2] == SC_MY_RAID )
+				{
+				switch ( cdb[3] ) 
+					{
+					case MY_SCSI_REBUILD:
+						OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_REBUILD) << 16);
+						return 0;
+					case MY_SCSI_ALARMMUTE:
+						OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_MUTE) << 16);
+						return 0;
+					case MY_SCSI_DEMOFAIL:
+						OpDone (SCpnt, PsiRaidCmd (padapter, CMD_RAID_FAIL) << 16);
+						return 0;
+					default:
+						if ( SCpnt->use_sg )
+							{
+							rc = DID_ERROR;
+							goto finished;
+							}
+						else
+							outl (virt_to_bus (SCpnt->request_buffer), padapter->mb2);
+						outl (cdb[5], padapter->mb0);
+						outl (cdb[3], padapter->mb3);
+						cmd = CMD_DASD_RAID_RQ;
+						break;
+					}
+				break;
+				}
+			
 			if ( SCpnt->use_sg )
 				{
 				outl (virt_to_bus (((struct scatterlist *)(SCpnt->request_buffer))->address), padapter->mb2);
@@ -378,7 +436,6 @@
 			outl (SCpnt->request_bufflen, padapter->mb3);
 			cmd = CMD_DASD_SCSI_INQ;
 			break;
-			}
 
 		case SCSIOP_TEST_UNIT_READY:			// test unit ready CDB
 			outl (virt_to_bus (SCpnt->sense_buffer), padapter->mb2);
@@ -466,14 +523,6 @@
 		OpDone (SCpnt, rc << 16);
 	return 0;
 	}
-static void do_Irq_Handler (int irq, void *dev_id, struct pt_regs *regs)
-	{
-	unsigned long flags;
-
-	spin_lock_irqsave(&io_request_lock, flags);
-	Irq_Handler(irq, dev_id, regs);
-	spin_unlock_irqrestore(&io_request_lock, flags);
-	}
 /****************************************************************
  *	Name:	internal_done :LOCAL
  *
@@ -524,17 +573,23 @@
 	int					pci_index = 0;
 	struct Scsi_Host   *pshost;
 	PADAPTER2000	    padapter;
-	int					z;
+	int					z, zz;
 	int					setirq;
-	struct pci_dev	   *pdev = NULL;
 
-	if ( pci_present () )
-		while ((pdev = pci_find_device(VENDOR_PSI, DEVICE_ROY_1, pdev)))
+	if ( pcibios_present () )
+		{
+		for ( pci_index = 0;  pci_index <= MAXADAPTER;  ++pci_index )
 			{
+			UCHAR	pci_bus, pci_device_fn;
+
+			if ( pcibios_find_device (VENDOR_PSI, DEVICE_ROY_1, pci_index, &pci_bus, &pci_device_fn) != 0 )
+				break;
+
 			pshost = scsi_register (tpnt, sizeof(ADAPTER2000));
 			padapter = HOSTDATA(pshost);
 
-			padapter->basePort = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
+			pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &padapter->basePort);
+			padapter->basePort &= 0xFFFE;
 			DEB (printk ("\nBase Regs = %#04X", padapter->basePort));			// get the base I/O port address
 			padapter->mb0	= padapter->basePort + RTR_MAILBOX;		   			// get the 32 bit mail boxes
 			padapter->mb1	= padapter->basePort + RTR_MAILBOX + 4;
@@ -551,35 +606,40 @@
 			if ( WaitReady (padapter) )
 				goto unregister;
 
-			pshost->irq = pdev->irq;
+			pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
 			setirq = 1;
-			for ( z = 0;  z < pci_index;  z++ )											// scan for shared interrupts
+			for ( z = 0;  z < pci_index;  z++ )									// scan for shared interrupts
 				{
-				if ( PsiHost[z]->irq == pshost->irq )						// if shared then, don't posses
+				if ( PsiHost[z]->irq == pshost->irq )							// if shared then, don't posses
 					setirq = 0;
 				}
-			if ( setirq )																// if not shared, posses
+			if ( setirq )														// if not shared, posses
 				{
-				if ( request_irq (pshost->irq, do_Irq_Handler, 0, "pci2000", NULL) )
+				if ( request_irq (pshost->irq, Irq_Handler, 0, "pci2000", NULL) )
 					{
 					printk ("Unable to allocate IRQ for PSI-2000 controller.\n");
 					goto unregister;
 					}
 				}
-			PsiHost[pci_index]	= pshost;												// save SCSI_HOST pointer
+			PsiHost[pci_index]	= pshost;										// save SCSI_HOST pointer
 
 			pshost->unique_id	= padapter->basePort;
 			pshost->max_id		= 16;
 			pshost->max_channel	= 1;
 
-			printk("\nPSI-2000 EIDE CONTROLLER: at I/O = %X  IRQ = %d\n", padapter->basePort, pshost->irq);
-			printk("(C) 1997 Perceptive Solutions, Inc. All rights reserved\n\n");
-			NumAdapters++;
+			for ( zz = 0;  zz < MAX_BUS;  zz++ )
+				for ( z = 0; z < MAX_UNITS;  z++ )
+					padapter->dev[zz][z].tag = 0;
+			
+			printk("\nPSI-2000 Intelligent Storage SCSI CONTROLLER: at I/O = %X  IRQ = %d\n", padapter->basePort, pshost->irq);
+			printk("Version %s, Compiled %s %s\n\n", PCI2000_VERSION,  __DATE__, __TIME__);
 			continue;
 unregister:;
 			scsi_unregister (pshost);
 			}
-	return NumAdapters;
+		}
+	NumAdapters = pci_index;
+	return pci_index;
 	}
 /****************************************************************
  *	Name:	Pci2220i_Abort
@@ -653,7 +713,7 @@
 
 #ifdef MODULE
 /* Eventually this will go into an include file, but this will be later */
-Scsi_Host_Template driver_template = PCI2000;
+Scsi_Host_Template driver_template = PCI2220I;
 
 #include "scsi_module.c"
 #endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)