patch-2.2.6 linux/drivers/scsi/pci2220i.c
Next file: linux/drivers/scsi/pci2220i.h
Previous file: linux/drivers/scsi/pci2000.h
Back to the patch index
Back to the overall index
- Lines: 1155
- Date:
Tue Apr 13 07:54:02 1999
- Orig file:
v2.2.5/linux/drivers/scsi/pci2220i.c
- Orig date:
Tue Mar 23 14:35:48 1999
diff -u --recursive --new-file v2.2.5/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c
@@ -1,35 +1,36 @@
-/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-22220I device driver proc support for Linux.
+/****************************************************************************
+ * Perceptive Solutions, Inc. PCI-2220I device driver for Linux.
*
- * Copyright (c) 1999 Perceptive Solutions, Inc.
+ * pci2220i.c - Linux Host Driver for PCI-2220I EIDE RAID Adapters
*
- * 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
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
+ * Copyright (c) 1997-1999 Perceptive Solutions, Inc.
+ * All Rights Reserved.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that redistributions of source
+ * code retain the above copyright notice and this comment without
+ * modification.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * Technical updates and product information at:
+ * http://www.psidisk.com
*
+ * Please send questions, comments, bug reports to:
+ * tech@psidisk.com Technical Support
*
- * File Name: pci2220i.c
*
- * Description: SCSI driver for the PCI2220I EIDE interface card.
+ * Revisions 1.10 Mar-26-1999
+ * - Updated driver for RAID and hot reconstruct support.
*
- *-M*************************************************************************/
+ * Revisions 1.11 Mar-26-1999
+ * - Fixed spinlock and PCI configuration.
+ *
+ ****************************************************************************/
#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/malloc.h>
#include <linux/pci.h>
#include <linux/ioport.h>
#include <linux/delay.h>
@@ -46,7 +47,14 @@
#include "hosts.h"
#include "pci2220i.h"
-#define PCI2220I_VERSION "1.10"
+#if LINUX_VERSION_CODE >= LINUXVERSION(2,1,95)
+#include <asm/spinlock.h>
+#endif
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,93)
+#include <linux/bios32.h>
+#endif
+
+#define PCI2220I_VERSION "1.11"
//#define READ_CMD IDE_COMMAND_READ
//#define WRITE_CMD IDE_COMMAND_WRITE
//#define MAX_BUS_MASTER_BLOCKS 1 // This is the maximum we can bus master
@@ -119,6 +127,7 @@
USHORT timingMode; // timing mode currently set for adapter
USHORT timingPIO; // TRUE if PIO timing is active
ULONG timingAddress; // address to use on adapter for current timing mode
+ ULONG irqOwned; // owned IRQ or zero if shared
OUR_DEVICE device[DALE_MAXDRIVES];
DISK_MIRROR *raidData[8];
ULONG startSector;
@@ -135,9 +144,9 @@
USHORT demoFail; // flag for RAID failure demonstration
USHORT survivor;
USHORT failinprog;
- USHORT timeoutReconRetry;
struct timer_list reconTimer;
struct timer_list timer;
+ UCHAR *kBuffer;
} ADAPTER2220I, *PADAPTER2220I;
#define HOSTDATA(host) ((PADAPTER2220I)&host->hostdata)
@@ -155,7 +164,6 @@
static SETUP DaleSetup;
static DISK_MIRROR DiskMirror[2];
static ULONG ModeArray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE4P};
-static UCHAR Buffer[SECTORSXFER * BYTES_PER_SECTOR];
static void ReconTimerExpiry (unsigned long data);
@@ -523,7 +531,7 @@
****************************************************************/
static ULONG InlineIdentify (PADAPTER2220I padapter, UCHAR spigot, UCHAR device)
{
- PIDENTIFY_DATA pid = (PIDENTIFY_DATA)Buffer;
+ PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
SelectSpigot (padapter, spigot | 0x80); // select the spigot
outb_p (device << 4, padapter->regLba24); // select the drive
@@ -532,10 +540,51 @@
WriteCommand (padapter, IDE_COMMAND_IDENTIFY);
if ( WaitDrq (padapter) )
return 0;
- insw (padapter->regData, Buffer, sizeof (IDENTIFY_DATA) >> 1);
+ insw (padapter->regData, padapter->kBuffer, sizeof (IDENTIFY_DATA) >> 1);
return (pid->LBATotalSectors - 1);
}
/****************************************************************
+ * Name: InlineReadSignature :LOCAL
+ *
+ * Description: Do an inline read RAID sigature.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ * pdev - Pointer to device.
+ * index - index of data to read.
+ *
+ * Returns: Zero if no error or status register contents on error.
+ *
+ ****************************************************************/
+static UCHAR InlineReadSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, int index)
+ {
+ UCHAR status;
+ UCHAR spigot = 1 << index;
+ ULONG zl = pdev->lastsectorlba[index];
+
+ SelectSpigot (padapter, spigot | 0x80); // select the spigot without interrupts
+ outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
+ status = WaitReady (padapter);
+ if ( !status )
+ {
+ outb_p (((UCHAR *)&zl)[2], padapter->regLba16);
+ outb_p (((UCHAR *)&zl)[1], padapter->regLba8);
+ outb_p (((UCHAR *)&zl)[0], padapter->regLba0);
+ outb_p (1, padapter->regSectCount);
+ WriteCommand (padapter, IDE_COMMAND_READ);
+ status = WaitDrq (padapter);
+ if ( !status )
+ {
+ insw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
+ ((ULONG *)(&pdev->DiskMirror[index]))[0] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0];
+ ((ULONG *)(&pdev->DiskMirror[index]))[1] = ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1];
+ // some drives assert DRQ before IRQ so let's make sure we clear the IRQ
+ WaitReady (padapter);
+ return 0;
+ }
+ }
+ return status;
+ }
+/****************************************************************
* Name: DecodeError :LOCAL
*
* Description: Decode and process device errors.
@@ -619,9 +668,9 @@
StartTimer (padapter);
padapter->expectingIRQ = TRUE;
- outsw (padapter->regData, Buffer, DISK_MIRROR_POSITION / 2);
- outsw (padapter->regData, &pdev->DiskMirror[index], sizeof (DISK_MIRROR) / 2);
- outsw (padapter->regData, Buffer, ((512 - (DISK_MIRROR_POSITION + sizeof (DISK_MIRROR))) / 2));
+ ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[0] = ((ULONG *)(&pdev->DiskMirror[index]))[0];
+ ((ULONG *)(&padapter->kBuffer[DISK_MIRROR_POSITION]))[1] = ((ULONG *)(&pdev->DiskMirror[index]))[1];
+ outsw (padapter->regData, padapter->kBuffer, BYTES_PER_SECTOR / 2);
return FALSE;
}
/*******************************************************************************************************
@@ -640,7 +689,7 @@
{
UCHAR spigot;
- DEB (printk ("\npci2000i: Initialize failover process - survivor = %d", padapter->survivor));
+ DEB (printk ("\npci2220i: Initialize failover process - survivor = %d", padapter->survivor));
pdev->raid = FALSE; //initializes system for non raid mode
pdev->hotRecon = 0;
padapter->reconOn = FALSE;
@@ -674,71 +723,75 @@
{
PADAPTER2220I padapter = (PADAPTER2220I)data;
POUR_DEVICE pdev = padapter->pdev;
- ULONG flags;
UCHAR status = IDE_STATUS_BUSY;
UCHAR temp, temp1;
-
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
DEB (printk ("\nPCI2220I: Timeout expired "));
- save_flags (flags);
- cli ();
if ( padapter->failinprog )
{
DEB (printk ("in failover process"));
- restore_flags (flags);
OpDone (padapter, DecodeError (padapter, inb_p (padapter->regStatCmd)));
- return;
+ goto timerExpiryDone;
}
while ( padapter->reconPhase )
{
DEB (printk ("in recon phase %X", padapter->reconPhase));
- if ( --padapter->timeoutReconRetry )
- {
- StartTimer (padapter);
- return;
- }
switch ( padapter->reconPhase )
{
case RECON_PHASE_MARKING:
case RECON_PHASE_LAST:
padapter->survivor = (pdev->spigot ^ 3) >> 1;
- restore_flags (flags);
DEB (printk ("\npci2220i: FAILURE 1"));
if ( InitFailover (padapter, pdev) )
OpDone (padapter, DID_ERROR << 16);
- return;
+ goto timerExpiryDone;
case RECON_PHASE_READY:
OpDone (padapter, DID_ERROR << 16);
- return;
+ goto timerExpiryDone;
case RECON_PHASE_COPY:
padapter->survivor = (pdev->spigot) >> 1;
- restore_flags (flags);
DEB (printk ("\npci2220i: FAILURE 2"));
+ DEB (printk ("\n spig/stat = %X", inb_p (padapter->regStatSel));
if ( InitFailover (padapter, pdev) )
OpDone (padapter, DID_ERROR << 16);
- return;
+ goto timerExpiryDone;
case RECON_PHASE_UPDATE:
padapter->survivor = (pdev->spigot) >> 1;
- restore_flags (flags);
- DEB (printk ("\npci2220i: FAILURE 3"));
+ DEB (printk ("\npci2220i: FAILURE 3")));
if ( InitFailover (padapter, pdev) )
OpDone (padapter, DID_ERROR << 16);
- return;
+ goto timerExpiryDone;
case RECON_PHASE_END:
padapter->survivor = (pdev->spigot) >> 1;
- restore_flags (flags);
DEB (printk ("\npci2220i: FAILURE 4"));
if ( InitFailover (padapter, pdev) )
OpDone (padapter, DID_ERROR << 16);
- return;
+ goto timerExpiryDone;
default:
- return;
+ goto timerExpiryDone;
}
}
@@ -779,14 +832,13 @@
padapter->survivor = 1;
else
padapter->survivor = 0;
- restore_flags (flags);
- DEB (printk ("\npci2220i: FAILURE 5"));
+ DEB (printk ("\npci2220i: FAILURE 5"));
if ( InitFailover (padapter, pdev) )
{
status = inb_p (padapter->regStatCmd);
break;
}
- return;
+ goto timerExpiryDone;
}
}
}
@@ -794,14 +846,13 @@
{
DEB (printk ("in RAID read operation"));
padapter->survivor = (pdev->spigot ^ 3) >> 1;
- restore_flags (flags);
DEB (printk ("\npci2220i: FAILURE 6"));
if ( InitFailover (padapter, pdev) )
{
status = inb_p (padapter->regStatCmd);
break;
}
- return;
+ goto timerExpiryDone;
}
}
else
@@ -812,8 +863,23 @@
break;
}
- restore_flags (flags);
OpDone (padapter, DecodeError (padapter, status));
+
+timerExpiryDone:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
}
/****************************************************************
* Name: SetReconstruct :LOCAL
@@ -854,15 +920,31 @@
USHORT minmode;
ULONG zl;
UCHAR zc;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
padapter = (PADAPTER2220I)data;
if ( padapter->SCpnt )
- return;
+ goto reconTimerExpiry;
pdev = padapter->device;
- pid = (PIDENTIFY_DATA)Buffer;
+ pid = (PIDENTIFY_DATA)padapter->kBuffer;
padapter->reconTimer.data = 0;
- padapter->timeoutReconRetry = 2;
padapter->pdev = pdev;
if ( padapter->reconIsStarting )
{
@@ -875,7 +957,7 @@
{
if ( (pdev->DiskMirror[0].status & UCBF_MATCHED) && (pdev->DiskMirror[1].status & UCBF_MATCHED) )
{
- return;
+ goto reconTimerExpiry;
}
if ( pdev->DiskMirror[0].status & UCBF_SURVIVOR ) // is first drive survivor?
@@ -900,7 +982,7 @@
}
if ( !pdev->hotRecon )
- return;
+ goto reconTimerExpiry;
zc = ((inb_p (padapter->regStatSel) >> 3) | inb_p (padapter->regStatSel)) & 0x83; // mute the alarm
outb_p (zc | pdev->hotRecon | 0x40, padapter->regFail);
@@ -976,15 +1058,15 @@
padapter->reconPhase = RECON_PHASE_FAILOVER;
DEB (printk ("\npci2220i: FAILURE 7"));
InitFailover (padapter, pdev);
- return;
+ goto reconTimerExpiry;
}
pdev->raid = TRUE;
if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
- return;
+ goto reconTimerExpiry;
padapter->reconPhase = RECON_PHASE_MARKING;
- return;
+ goto reconTimerExpiry;
}
//**********************************
@@ -999,10 +1081,10 @@
padapter->reconPhase = RECON_PHASE_FAILOVER;
DEB (printk ("\npci2220i: FAILURE 8"));
InitFailover (padapter, pdev);
- return;
+ goto reconTimerExpiry;
}
padapter->reconPhase = RECON_PHASE_UPDATE;
- return;
+ goto reconTimerExpiry;
}
zl = pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint;
@@ -1016,7 +1098,7 @@
outb_p (pdev->byte6 | ((UCHAR *)(&zl))[3], padapter->regLba24);// select the drive
SelectSpigot (padapter, pdev->spigot);
if ( WaitReady (padapter) )
- return;
+ goto reconTimerExpiry;
SelectSpigot (padapter, pdev->hotRecon);
if ( WaitReady (padapter) )
@@ -1025,7 +1107,7 @@
padapter->reconPhase = RECON_PHASE_FAILOVER;
DEB (printk ("\npci2220i: FAILURE 9"));
InitFailover (padapter, pdev);
- return;
+ goto reconTimerExpiry;
}
SelectSpigot (padapter, 3);
@@ -1040,15 +1122,30 @@
StartTimer (padapter);
SelectSpigot (padapter, pdev->spigot);
WriteCommand (padapter, READ_CMD);
- return;
+ goto reconTimerExpiry;
}
pdev->DiskMirror[pdev->mirrorRecon].status = UCBF_MIRRORED | UCBF_MATCHED;
pdev->DiskMirror[pdev->mirrorRecon ^ 1].status = UCBF_MIRRORED | UCBF_MATCHED;
if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
- return;
+ goto reconTimerExpiry;
padapter->reconPhase = RECON_PHASE_LAST;
- return;
+
+reconTimerExpiry:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
}
/****************************************************************
* Name: Irq_Handler :LOCAL
@@ -1072,6 +1169,23 @@
UCHAR status1;
int z;
ULONG zl;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ int flags;
+#else /* version >= v2.1.95 */
+ unsigned long flags;
+#endif /* version >= v2.1.95 */
+
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /* Disable interrupts, if they aren't already disabled. */
+ save_flags (flags);
+ cli ();
+#else /* version >= v2.1.95 */
+ /*
+ * Disable interrupts, if they aren't already disabled and acquire
+ * the I/O spinlock.
+ */
+ spin_lock_irqsave (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
// DEB (printk ("\npci2220i recieved interrupt\n"));
@@ -1090,7 +1204,7 @@
if ( !shost )
{
DEB (printk ("\npci2220i: not my interrupt"));
- return;
+ goto irq_return;
}
padapter = HOSTDATA(shost);
@@ -1101,7 +1215,7 @@
{
DEB(printk ("\npci2220i Unsolicited interrupt\n"));
STOP_HERE ();
- return;
+ goto irq_return;
}
padapter->expectingIRQ = 0;
outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
@@ -1125,7 +1239,7 @@
OpDone (padapter, DID_OK << 16);
else
Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
- return;
+ goto irq_return;
}
}
@@ -1142,24 +1256,24 @@
if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
{
padapter->survivor = (pdev->spigot ^ 3) >> 1;
- DEB (printk ("\npci2220i: FAILURE 10"));
+ DEB (printk ("\npci2220i: FAILURE 10"));
if ( InitFailover (padapter, pdev) )
OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
}
if ( WriteSignature (padapter, pdev, pdev->hotRecon, pdev->mirrorRecon) )
{
padapter->survivor = (pdev->spigot) >> 1;
- DEB (printk ("\npci2220i: FAILURE 11"));
+ DEB (printk ("\npci2220i: FAILURE 11"));
if ( InitFailover (padapter, pdev) )
OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
}
padapter->reconPhase = RECON_PHASE_END;
- return;
+ goto irq_return;
}
OpDone (padapter, DID_OK << 16);
- return;
+ goto irq_return;
case RECON_PHASE_READY:
status = inb_p (padapter->regStatCmd); // read the device status
@@ -1167,7 +1281,7 @@
{
del_timer (&padapter->timer);
OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
}
SelectSpigot (padapter, pdev->hotRecon);
if ( WaitDrq (padapter) )
@@ -1177,25 +1291,25 @@
DEB (printk ("\npci2220i: FAILURE 12"));
if ( InitFailover (padapter, pdev) )
OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
}
SelectSpigot (padapter, pdev->spigot | 0x40);
padapter->reconPhase = RECON_PHASE_COPY;
padapter->expectingIRQ = TRUE;
if ( padapter->timingPIO )
{
- insw (padapter->regData, Buffer, padapter->reconSize * (BYTES_PER_SECTOR / 2));
+ insw (padapter->regData, padapter->kBuffer, padapter->reconSize * (BYTES_PER_SECTOR / 2));
}
else
{
outl (padapter->timingAddress, padapter->regDmaAddrLoc);
- outl (virt_to_bus (Buffer), padapter->regDmaAddrPci);
+ outl (virt_to_bus (padapter->kBuffer), padapter->regDmaAddrPci);
outl (padapter->reconSize * BYTES_PER_SECTOR, padapter->regDmaCount);
outb_p (8, padapter->regDmaDesc); // read operation
outb_p (1, padapter->regDmaMode); // no interrupt
outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
}
- return;
+ goto irq_return;
case RECON_PHASE_COPY:
pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint += padapter->reconSize;
@@ -1207,14 +1321,13 @@
if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
{
padapter->survivor = (pdev->spigot) >> 1;
- DEB (printk ("\npci2220i: FAILURE 13"));
- DEB (printk (" status = %X error = %X", status, inb_p (padapter->regError)));
+ DEB (printk ("\npci2220i: FAILURE 13"));
if ( InitFailover (padapter, pdev) )
OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
}
OpDone (padapter, DID_OK << 16);
- return;
+ goto irq_return;
case RECON_PHASE_END:
status = inb_p (padapter->regStatCmd); // read the device status
@@ -1225,15 +1338,15 @@
DEB (printk ("\npci2220i: FAILURE 14"));
if ( InitFailover (padapter, pdev) )
OpDone (padapter, DecodeError (padapter, status));
- return;
+ goto irq_return;
}
padapter->reconOn = FALSE;
pdev->hotRecon = 0;
OpDone (padapter, DID_OK << 16);
- return;
+ goto irq_return;
default:
- return;
+ goto irq_return;
}
}
@@ -1251,7 +1364,7 @@
del_timer (&padapter->timer);
DEB (printk ("\npci2220i: FAILURE 15"));
if ( !InitFailover (padapter, pdev) )
- return;
+ goto irq_return;
}
break;
}
@@ -1270,7 +1383,7 @@
else
BusMaster (padapter, 1, 1);
padapter->expectingIRQ = TRUE;
- return;
+ goto irq_return;
}
status = 0;
break;
@@ -1295,7 +1408,7 @@
SelectSpigot (padapter, pdev->spigot | 0x80);
DEB (printk ("\npci2220i: FAILURE 16 status = %X error = %X", status, inb_p (padapter->regError)));
if ( !InitFailover (padapter, pdev) )
- return;
+ goto irq_return;
}
break;
}
@@ -1307,7 +1420,7 @@
del_timer (&padapter->timer);
DEB (printk ("\npci2220i: FAILURE 17 status = %X error = %X", status1, inb_p (padapter->regError)));
if ( !InitFailover (padapter, pdev) )
- return;
+ goto irq_return;
status = status1;
break;
}
@@ -1320,13 +1433,13 @@
del_timer (&padapter->timer);
DEB (printk ("\npci2220i: FAILURE 18"));
if ( !InitFailover (padapter, pdev) )
- return;
+ goto irq_return;
SelectSpigot (padapter, status | 0x80);
status = inb_p (padapter->regStatCmd); // read the device status
break;
}
padapter->expectingIRQ = TRUE;
- return;
+ goto irq_return;
}
status = 0;
break;
@@ -1338,7 +1451,7 @@
if ( status )
break;
padapter->expectingIRQ = TRUE;
- return;
+ goto irq_return;
}
status = 0;
break;
@@ -1346,7 +1459,7 @@
case IDE_COMMAND_IDENTIFY:
{
PINQUIRYDATA pinquiryData = SCpnt->request_buffer;
- PIDENTIFY_DATA pid = (PIDENTIFY_DATA)Buffer;
+ PIDENTIFY_DATA pid = (PIDENTIFY_DATA)padapter->kBuffer;
status = inb_p (padapter->regStatCmd);
if ( status & IDE_STATUS_DRQ )
@@ -1399,6 +1512,21 @@
zl = DID_OK << 16;
OpDone (padapter, zl);
+irq_return:;
+#if LINUX_VERSION_CODE < LINUXVERSION(2,1,95)
+ /*
+ * Restore the original flags which will enable interrupts
+ * if and only if they were enabled on entry.
+ */
+ restore_flags (flags);
+#else /* version >= v2.1.95 */
+ /*
+ * Release the I/O spinlock and restore the original flags
+ * which will enable interrupts if and only if they were
+ * enabled on entry.
+ */
+ spin_unlock_irqrestore (&io_request_lock, flags);
+#endif /* version >= v2.1.95 */
}
/****************************************************************
* Name: Pci2220i_QueueCommand
@@ -1652,12 +1780,13 @@
*
* Parameters: tpnt - Pointer to SCSI host template structure.
*
- * Returns: Number of adapters found.
+ * Returns: Number of adapters installed.
*
****************************************************************/
int Pci2220i_Detect (Scsi_Host_Template *tpnt)
{
- int pci_index = 0;
+ int found = 0;
+ int installed = 0;
struct Scsi_Host *pshost;
PADAPTER2220I padapter;
int unit;
@@ -1667,174 +1796,223 @@
int setirq;
UCHAR spigot1 = FALSE;
UCHAR spigot2 = FALSE;
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ struct pci_dev *pdev = NULL;
+#else
+ UCHAR pci_bus, pci_device_fn;
+#endif
- if ( pcibios_present () )
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ if ( !pci_present () )
+#else
+ if ( !pcibios_present () )
+#endif
{
- for ( pci_index = 0; pci_index <= MAXADAPTER; ++pci_index )
- {
- UCHAR pci_bus, pci_device_fn;
+ printk ("pci2220i: PCI BIOS not present\n");
+ return 0;
+ }
- if ( pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, pci_index, &pci_bus, &pci_device_fn) != 0 )
- break;
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ while ( (pdev = pci_find_device (VENDOR_PSI, DEVICE_DALE_1, pdev)) != NULL )
+#else
+ while ( !pcibios_find_device (VENDOR_PSI, DEVICE_DALE_1, found, &pci_bus, &pci_device_fn) )
+#endif
+ {
+ pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
+ padapter = HOSTDATA(pshost);
+ memset (padapter, 0, sizeof (ADAPTER2220I));
- pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
- padapter = HOSTDATA(pshost);
- memset (padapter, 0, sizeof (ADAPTER2220I));
-
- pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &zs);
- zs &= 0xFFFE;
- padapter->basePort = zs;
- padapter->regRemap = zs + RTR_LOCAL_REMAP; // 32 bit local space remap
- padapter->regDesc = zs + RTR_REGIONS; // 32 bit local region descriptor
- padapter->regRange = zs + RTR_LOCAL_RANGE; // 32 bit local range
- padapter->regIrqControl = zs + RTR_INT_CONTROL_STATUS; // 16 bit interupt control and status
- padapter->regScratchPad = zs + RTR_MAILBOX; // 16 byte scratchpad I/O base address
-
- pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &zs);
- zs &= 0xFFFE;
- padapter->regBase = zs;
- padapter->regData = zs + REG_DATA; // data register I/O address
- padapter->regError = zs + REG_ERROR; // error register I/O address
- padapter->regSectCount = zs + REG_SECTOR_COUNT; // sector count register I/O address
- padapter->regLba0 = zs + REG_LBA_0; // least significant byte of LBA
- padapter->regLba8 = zs + REG_LBA_8; // next least significant byte of LBA
- padapter->regLba16 = zs + REG_LBA_16; // next most significan byte of LBA
- padapter->regLba24 = zs + REG_LBA_24; // head and most 4 significant bits of LBA
- padapter->regStatCmd = zs + REG_STAT_CMD; // status on read and command on write register
- padapter->regStatSel = zs + REG_STAT_SEL; // board status on read and spigot select on write register
- padapter->regFail = zs + REG_FAIL;
- padapter->regAltStat = zs + REG_ALT_STAT;
-
- padapter->regDmaDesc = zs + RTL_DMA1_DESC_PTR; // address of the DMA discriptor register for direction of transfer
- padapter->regDmaCmdStat = zs + RTL_DMA_COMMAND_STATUS + 1; // Byte #1 of DMA command status register
- padapter->regDmaAddrPci = zs + RTL_DMA1_PCI_ADDR; // 32 bit register for PCI address of DMA
- padapter->regDmaAddrLoc = zs + RTL_DMA1_LOCAL_ADDR; // 32 bit register for local bus address of DMA
- padapter->regDmaCount = zs + RTL_DMA1_COUNT; // 32 bit register for DMA transfer count
- padapter->regDmaMode = zs + RTL_DMA1_MODE + 1; // 32 bit register for DMA mode control
-
- if ( !inb_p (padapter->regScratchPad + DALE_NUM_DRIVES) ) // if no devices on this board
- goto unregister;
-
- 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
- {
- if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
- setirq = 0;
- }
- if ( setirq ) // if not shared, posses
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ zs = pdev->base_address[1] & 0xFFFE;
+#else
+ pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_1, &zs);
+ zs &= 0xFFFE;
+#endif
+ padapter->basePort = zs;
+ padapter->regRemap = zs + RTR_LOCAL_REMAP; // 32 bit local space remap
+ padapter->regDesc = zs + RTR_REGIONS; // 32 bit local region descriptor
+ padapter->regRange = zs + RTR_LOCAL_RANGE; // 32 bit local range
+ padapter->regIrqControl = zs + RTR_INT_CONTROL_STATUS; // 16 bit interupt control and status
+ padapter->regScratchPad = zs + RTR_MAILBOX; // 16 byte scratchpad I/O base address
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ zs = pdev->base_address[2] & 0xFFFE;
+#else
+ pcibios_read_config_word (pci_bus, pci_device_fn, PCI_BASE_ADDRESS_2, &zs);
+ zs &= 0xFFFE;
+#endif
+ padapter->regBase = zs;
+ padapter->regData = zs + REG_DATA; // data register I/O address
+ padapter->regError = zs + REG_ERROR; // error register I/O address
+ padapter->regSectCount = zs + REG_SECTOR_COUNT; // sector count register I/O address
+ padapter->regLba0 = zs + REG_LBA_0; // least significant byte of LBA
+ padapter->regLba8 = zs + REG_LBA_8; // next least significant byte of LBA
+ padapter->regLba16 = zs + REG_LBA_16; // next most significan byte of LBA
+ padapter->regLba24 = zs + REG_LBA_24; // head and most 4 significant bits of LBA
+ padapter->regStatCmd = zs + REG_STAT_CMD; // status on read and command on write register
+ padapter->regStatSel = zs + REG_STAT_SEL; // board status on read and spigot select on write register
+ padapter->regFail = zs + REG_FAIL;
+ padapter->regAltStat = zs + REG_ALT_STAT;
+
+ padapter->regDmaDesc = zs + RTL_DMA1_DESC_PTR; // address of the DMA discriptor register for direction of transfer
+ padapter->regDmaCmdStat = zs + RTL_DMA_COMMAND_STATUS + 1; // Byte #1 of DMA command status register
+ padapter->regDmaAddrPci = zs + RTL_DMA1_PCI_ADDR; // 32 bit register for PCI address of DMA
+ padapter->regDmaAddrLoc = zs + RTL_DMA1_LOCAL_ADDR; // 32 bit register for local bus address of DMA
+ padapter->regDmaCount = zs + RTL_DMA1_COUNT; // 32 bit register for DMA transfer count
+ padapter->regDmaMode = zs + RTL_DMA1_MODE + 1; // 32 bit register for DMA mode control
+
+ if ( !inb_p (padapter->regScratchPad + DALE_NUM_DRIVES) ) // if no devices on this board
+ goto unregister;
+
+#if LINUX_VERSION_CODE > LINUXVERSION(2,1,92)
+ pshost->irq = pdev->irq;
+#else
+ pcibios_read_config_byte (pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &pshost->irq);
+#endif
+ setirq = 1;
+ for ( z = 0; z < installed; z++ ) // scan for shared interrupts
+ {
+ if ( PsiHost[z]->irq == pshost->irq ) // if shared then, don't posses
+ setirq = 0;
+ }
+ if ( setirq ) // if not shared, posses
+ {
+ if ( request_irq (pshost->irq, Irq_Handler, SA_SHIRQ, "pci2220i", padapter) < 0 )
{
- if ( request_irq (pshost->irq, Irq_Handler, 0, "pci2220i", NULL) )
+ if ( request_irq (pshost->irq, Irq_Handler, SA_INTERRUPT | SA_SHIRQ, "pci2220i", padapter) < 0 )
{
- printk ("Unable to allocate IRQ for PSI-2220I controller.\n");
+ printk ("Unable to allocate IRQ for PCI-2220I controller.\n");
goto unregister;
}
}
- PsiHost[pci_index] = pshost; // save SCSI_HOST pointer
-
- pshost->unique_id = padapter->regBase;
- pshost->max_id = 4;
-
- outb_p (0x01, padapter->regRange); // fix our range register because other drivers want to tromp on it
-
- padapter->timingMode = inb_p (padapter->regScratchPad + DALE_TIMING_MODE);
- if ( padapter->timingMode >= 2 )
- padapter->timingAddress = ModeArray[padapter->timingMode - 2];
- else
- padapter->timingPIO = TRUE;
+ padapter->irqOwned = pshost->irq; // set IRQ as owned
+ }
+ padapter->kBuffer = kmalloc (SECTORSXFER * BYTES_PER_SECTOR, GFP_DMA | GFP_ATOMIC);
+ if ( !padapter->kBuffer )
+ {
+ printk ("Unable to allocate DMA buffer for PCI-2220I controller.\n");
+#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
+ free_irq (pshost->irq);
+#else /* version >= v1.3.70 */
+ free_irq (pshost->irq, padapter);
+#endif /* version >= v1.3.70 */
+ goto unregister;
+ }
+ PsiHost[installed] = pshost; // save SCSI_HOST pointer
+
+ pshost->io_port = padapter->basePort;
+ pshost->n_io_port = 0xFF;
+ pshost->unique_id = padapter->regBase;
+ pshost->max_id = 4;
+
+ outb_p (0x01, padapter->regRange); // fix our range register because other drivers want to tromp on it
+
+ padapter->timingMode = inb_p (padapter->regScratchPad + DALE_TIMING_MODE);
+ if ( padapter->timingMode >= 2 )
+ padapter->timingAddress = ModeArray[padapter->timingMode - 2];
+ else
+ padapter->timingPIO = TRUE;
- ReadFlash (padapter, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
- for ( z = 0; z < inb_p (padapter->regScratchPad + DALE_NUM_DRIVES); ++z )
- {
- unit = inb_p (padapter->regScratchPad + DALE_CHANNEL_DEVICE_0 + z) & 0x0F;
- padapter->device[z].device = inb_p (padapter->regScratchPad + DALE_SCRATH_DEVICE_0 + unit);
- padapter->device[z].byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
- padapter->device[z].spigot = (UCHAR)(1 << (unit >> 1));
- padapter->device[z].sectors = DaleSetup.setupDevice[unit].sectors;
- padapter->device[z].heads = DaleSetup.setupDevice[unit].heads;
- padapter->device[z].cylinders = DaleSetup.setupDevice[unit].cylinders;
- padapter->device[z].blocks = DaleSetup.setupDevice[unit].blocks;
-
- if ( !z )
- {
- ReadFlash (padapter, &DiskMirror, DALE_FLASH_RAID, sizeof (DiskMirror));
- DiskMirror[0].status = inb_p (padapter->regScratchPad + DALE_RAID_0_STATUS);
- DiskMirror[1].status = inb_p (padapter->regScratchPad + DALE_RAID_1_STATUS);
- if ( (DiskMirror[0].signature == SIGNATURE) && (DiskMirror[1].signature == SIGNATURE) &&
- (DiskMirror[0].pairIdentifier == (DiskMirror[1].pairIdentifier ^ 1)) )
- {
- raidon = TRUE;
- }
-
- memcpy (padapter->device[z].DiskMirror, DiskMirror, sizeof (DiskMirror));
- padapter->raidData[0] = &padapter->device[z].DiskMirror[0];
- padapter->raidData[2] = &padapter->device[z].DiskMirror[1];
+ ReadFlash (padapter, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
+ for ( z = 0; z < inb_p (padapter->regScratchPad + DALE_NUM_DRIVES); ++z )
+ {
+ unit = inb_p (padapter->regScratchPad + DALE_CHANNEL_DEVICE_0 + z) & 0x0F;
+ padapter->device[z].device = inb_p (padapter->regScratchPad + DALE_SCRATH_DEVICE_0 + unit);
+ padapter->device[z].byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
+ padapter->device[z].spigot = (UCHAR)(1 << (unit >> 1));
+ padapter->device[z].sectors = DaleSetup.setupDevice[unit].sectors;
+ padapter->device[z].heads = DaleSetup.setupDevice[unit].heads;
+ padapter->device[z].cylinders = DaleSetup.setupDevice[unit].cylinders;
+ padapter->device[z].blocks = DaleSetup.setupDevice[unit].blocks;
+
+ if ( !z )
+ {
+ ReadFlash (padapter, &DiskMirror, DALE_FLASH_RAID, sizeof (DiskMirror));
+ DiskMirror[0].status = inb_p (padapter->regScratchPad + DALE_RAID_0_STATUS);
+ DiskMirror[1].status = inb_p (padapter->regScratchPad + DALE_RAID_1_STATUS);
+ if ( (DiskMirror[0].signature == SIGNATURE) && (DiskMirror[1].signature == SIGNATURE) &&
+ (DiskMirror[0].pairIdentifier == (DiskMirror[1].pairIdentifier ^ 1)) )
+ {
+ raidon = TRUE;
+ }
+
+ memcpy (padapter->device[z].DiskMirror, DiskMirror, sizeof (DiskMirror));
+ padapter->raidData[0] = &padapter->device[z].DiskMirror[0];
+ padapter->raidData[2] = &padapter->device[z].DiskMirror[1];
- if ( raidon )
- {
- padapter->device[z].lastsectorlba[0] = InlineIdentify (padapter, 1, 0);
- padapter->device[z].lastsectorlba[1] = InlineIdentify (padapter, 2, 0);
+ if ( raidon )
+ {
+ padapter->device[z].lastsectorlba[0] = InlineIdentify (padapter, 1, 0);
+ padapter->device[z].lastsectorlba[1] = InlineIdentify (padapter, 2, 0);
- if ( !(DiskMirror[1].status & UCBF_SURVIVOR) && padapter->device[z].lastsectorlba[0] )
- spigot1 = TRUE;
- if ( !(DiskMirror[0].status & UCBF_SURVIVOR) && padapter->device[z].lastsectorlba[1] )
- spigot2 = TRUE;
- if ( DiskMirror[0].status & UCBF_SURVIVOR & DiskMirror[1].status & UCBF_SURVIVOR )
- spigot1 = TRUE;
+ if ( !(DiskMirror[1].status & UCBF_SURVIVOR) && padapter->device[z].lastsectorlba[0] )
+ spigot1 = TRUE;
+ if ( !(DiskMirror[0].status & UCBF_SURVIVOR) && padapter->device[z].lastsectorlba[1] )
+ spigot2 = TRUE;
+ if ( DiskMirror[0].status & UCBF_SURVIVOR & DiskMirror[1].status & UCBF_SURVIVOR )
+ spigot1 = TRUE;
+
+ if ( spigot1 && (DiskMirror[0].status & UCBF_REBUILD) )
+ InlineReadSignature (padapter, &padapter->device[z], 0);
+ if ( spigot2 && (DiskMirror[1].status & UCBF_REBUILD) )
+ InlineReadSignature (padapter, &padapter->device[z], 1);
- if ( spigot1 && spigot2 )
+ if ( spigot1 && spigot2 )
+ {
+ padapter->device[z].raid = 1;
+ if ( DiskMirror[0].status & UCBF_REBUILD )
+ padapter->device[z].spigot = 2;
+ else
+ padapter->device[z].spigot = 1;
+ if ( (DiskMirror[0].status & UCBF_REBUILD) || (DiskMirror[1].status & UCBF_REBUILD) )
+ {
+ padapter->reconOn = padapter->reconIsStarting = TRUE;
+ }
+ }
+ else
+ {
+ if ( spigot1 )
{
- padapter->device[z].raid = 1;
if ( DiskMirror[0].status & UCBF_REBUILD )
- padapter->device[z].spigot = 2;
- else
- padapter->device[z].spigot = 1;
- if ( (DiskMirror[0].status & UCBF_REBUILD) || (DiskMirror[1].status & UCBF_REBUILD) )
- {
- padapter->reconOn = padapter->reconIsStarting = TRUE;
- }
+ goto unregister;
+ DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
+ padapter->device[z].spigot = 1;
}
else
{
- if ( spigot1 )
- {
- if ( DiskMirror[0].status & UCBF_REBUILD )
- goto unregister;
- DiskMirror[0].status = UCBF_MIRRORED | UCBF_SURVIVOR;
- padapter->device[z].spigot = 1;
- }
- else
- {
- if ( DiskMirror[1].status & UCBF_REBUILD )
- goto unregister;
- DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
- padapter->device[z].spigot = 2;
- }
- if ( DaleSetup.rebootRebuil )
- padapter->reconOn = padapter->reconIsStarting = TRUE;
+ if ( DiskMirror[1].status & UCBF_REBUILD )
+ goto unregister;
+ DiskMirror[1].status = UCBF_MIRRORED | UCBF_SURVIVOR;
+ padapter->device[z].spigot = 2;
}
-
- break;
+ if ( DaleSetup.rebootRebuil )
+ padapter->reconOn = padapter->reconIsStarting = TRUE;
}
+
+ break;
}
}
+ }
- init_timer (&padapter->timer);
- padapter->timer.function = TimerExpiry;
- padapter->timer.data = (unsigned long)padapter;
- init_timer (&padapter->reconTimer);
- padapter->reconTimer.function = ReconTimerExpiry;
- padapter->reconTimer.data = (unsigned long)padapter;
- printk("\nPCI-2220I EIDE CONTROLLER: at I/O = %X/%X IRQ = %d\n", padapter->basePort, padapter->regBase, pshost->irq);
- printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION, __DATE__, __TIME__);
- NumAdapters++;
+ init_timer (&padapter->timer);
+ padapter->timer.function = TimerExpiry;
+ padapter->timer.data = (unsigned long)padapter;
+ init_timer (&padapter->reconTimer);
+ padapter->reconTimer.function = ReconTimerExpiry;
+ padapter->reconTimer.data = (unsigned long)padapter;
+ printk("\nPCI-2220I EIDE CONTROLLER: at I/O = %X/%X IRQ = %d\n", padapter->basePort, padapter->regBase, pshost->irq);
+ printk("Version %s, Compiled %s %s\n\n", PCI2220I_VERSION, __DATE__, __TIME__);
+ found++;
+ if ( ++installed < MAXADAPTER )
continue;
+ break;;
unregister:;
- scsi_unregister (pshost);
- }
+ scsi_unregister (pshost);
+ found++;
}
- return NumAdapters;
+ NumAdapters = installed;
+ return installed;
}
/****************************************************************
* Name: Pci2220i_Abort
@@ -1868,6 +2046,47 @@
int Pci2220i_Reset (Scsi_Cmnd *SCpnt, unsigned int reset_flags)
{
return SCSI_RESET_PUNT;
+ }
+/****************************************************************
+ * Name: Pci2220i_Release
+ *
+ * Description: Release resources allocated for a single each adapter.
+ *
+ * Parameters: pshost - Pointer to SCSI command structure.
+ *
+ * Returns: zero.
+ *
+ ****************************************************************/
+int Pci2220i_Release (struct Scsi_Host *pshost)
+ {
+ PADAPTER2220I padapter = HOSTDATA (pshost);
+
+ if ( padapter->reconOn )
+ {
+ padapter->reconOn = FALSE; // shut down the hot reconstruct
+ if ( padapter->reconPhase )
+ udelay (300000);
+ if ( padapter->reconTimer.data ) // is the timer running?
+ {
+ del_timer (&padapter->reconTimer);
+ padapter->reconTimer.data = 0;
+ }
+ }
+
+ // save RAID status on the board
+ outb_p (DiskMirror[0].status, padapter->regScratchPad + DALE_RAID_0_STATUS);
+ outb_p (DiskMirror[1].status, padapter->regScratchPad + DALE_RAID_1_STATUS);
+
+ if ( padapter->irqOwned )
+#if LINUX_VERSION_CODE < LINUXVERSION(1,3,70)
+ free_irq (pshost->irq);
+#else /* version >= v1.3.70 */
+ free_irq (pshost->irq, padapter);
+#endif /* version >= v1.3.70 */
+ release_region (pshost->io_port, pshost->n_io_port);
+ kfree (padapter->kBuffer);
+ scsi_unregister(pshost);
+ return 0;
}
#include "sd.h"
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)