patch-2.2.4 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: 2082
- Date:
Mon Mar 22 13:05:53 1999
- Orig file:
v2.2.3/linux/drivers/scsi/pci2220i.c
- Orig date:
Wed Sep 9 14:51:08 1998
diff -u --recursive --new-file v2.2.3/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c
@@ -1,7 +1,7 @@
/*+M*************************************************************************
- * Perceptive Solutions, Inc. PCI-2000 device driver proc support for Linux.
+ * Perceptive Solutions, Inc. PCI-22220I 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
@@ -25,56 +25,51 @@
*-M*************************************************************************/
#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>
#include <linux/sched.h>
#include <linux/proc_fs.h>
+#include <linux/stat.h>
+#include <linux/kdev_t.h>
+#include <linux/blk.h>
+#include <linux/timer.h>
#include <asm/dma.h>
#include <asm/system.h>
-#include <asm/spinlock.h>
#include <asm/io.h>
-#include <linux/blk.h>
#include "scsi.h"
#include "hosts.h"
-
#include "pci2220i.h"
-#include "psi_dale.h"
-#include<linux/stat.h>
+#define PCI2220I_VERSION "1.10"
+//#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
+#define READ_CMD IDE_CMD_READ_MULTIPLE
+#define WRITE_CMD IDE_CMD_WRITE_MULTIPLE
+#define MAX_BUS_MASTER_BLOCKS SECTORSXFER // This is the maximum we can bus master
+
struct proc_dir_entry Proc_Scsi_Pci2220i =
- { PROC_SCSI_PCI2220I, 7, "pci2220i", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
+ { PROC_SCSI_PCI2220I, 8, "pci2220i", S_IFDIR | S_IRUGO | S_IXUGO, 2 };
//#define DEBUG 1
#ifdef DEBUG
#define DEB(x) x
-#define STOP_HERE {int st;for(st=0;st<100;st++){st=1;}}
+#define STOP_HERE() {int st;for(st=0;st<100;st++){st=1;}}
#else
#define DEB(x)
-#define STOP_HERE
+#define STOP_HERE()
#endif
-#define MAXADAPTER 4 /* Increase this and the sizes of the arrays below, if you need more. */
-
-#define MAX_BUS_MASTER_BLOCKS 1 // This is the maximum we can bus master for (1024 bytes)
+#define MAXADAPTER 4 // Increase this and the sizes of the arrays below, if you need more.
-#define PORT_DATA 0
-#define PORT_ERROR 1
-#define PORT_SECTOR_COUNT 2
-#define PORT_LBA_0 3
-#define PORT_LBA_8 4
-#define PORT_LBA_16 5
-#define PORT_LBA_24 6
-#define PORT_STAT_CMD 7
-#define PORT_STAT_SEL 8
-#define PORT_FAIL 9
-#define PORT_ALT_STAT 10
typedef struct
{
@@ -87,44 +82,245 @@
USHORT cylinders; // number of cylinders for this device
USHORT spareword; // placeholder
ULONG blocks; // number of blocks on device
- } OUR_DEVICE, *POUR_DEVICE;
+ DISK_MIRROR DiskMirror[2]; // RAID status and control
+ ULONG lastsectorlba[2]; // last addressable sector on the drive
+ USHORT raid; // RAID active flag
+ USHORT mirrorRecon;
+ UCHAR hotRecon;
+ USHORT reconCount;
+ } OUR_DEVICE, *POUR_DEVICE;
typedef struct
{
- USHORT ports[12];
- USHORT regDmaDesc; // address of the DMA discriptor register for direction of transfer
- USHORT regDmaCmdStat; // Byte #1 of DMA command status register
- USHORT regDmaAddrPci; // 32 bit register for PCI address of DMA
- USHORT regDmaAddrLoc; // 32 bit register for local bus address of DMA
- USHORT regDmaCount; // 32 bit register for DMA transfer count
- USHORT regDmaMode; // 32 bit register for DMA mode control
- USHORT regRemap; // 32 bit local space remap
- USHORT regDesc; // 32 bit local region descriptor
- USHORT regRange; // 32 bit local range
- USHORT regIrqControl; // 16 bit Interrupt enable/disable and status
- USHORT regScratchPad; // scratch pad I/O base address
- USHORT regBase; // Base I/O register for data space
- USHORT basePort; // PLX base I/O port
- USHORT timingMode; // timing mode currently set for adapter
- ULONG timingAddress; // address to use on adapter for current timing mode
- OUR_DEVICE device[4];
- IDE_STRUCT ide;
+ USHORT regDmaDesc; // address of the DMA discriptor register for direction of transfer
+ USHORT regDmaCmdStat; // Byte #1 of DMA command status register
+ USHORT regDmaAddrPci; // 32 bit register for PCI address of DMA
+ USHORT regDmaAddrLoc; // 32 bit register for local bus address of DMA
+ USHORT regDmaCount; // 32 bit register for DMA transfer count
+ USHORT regDmaMode; // 32 bit register for DMA mode control
+ USHORT regRemap; // 32 bit local space remap
+ USHORT regDesc; // 32 bit local region descriptor
+ USHORT regRange; // 32 bit local range
+ USHORT regIrqControl; // 16 bit Interrupt enable/disable and status
+ USHORT regScratchPad; // scratch pad I/O base address
+ USHORT regBase; // Base I/O register for data space
+ USHORT regData; // data register I/O address
+ USHORT regError; // error register I/O address
+ USHORT regSectCount; // sector count register I/O address
+ USHORT regLba0; // least significant byte of LBA
+ USHORT regLba8; // next least significant byte of LBA
+ USHORT regLba16; // next most significan byte of LBA
+ USHORT regLba24; // head and most 4 significant bits of LBA
+ USHORT regStatCmd; // status on read and command on write register
+ USHORT regStatSel; // board status on read and spigot select on write register
+ USHORT regFail; // fail bits control register
+ USHORT regAltStat; // alternate status and drive control register
+ USHORT basePort; // PLX base I/O port
+ 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
+ OUR_DEVICE device[DALE_MAXDRIVES];
+ DISK_MIRROR *raidData[8];
ULONG startSector;
USHORT sectorCount;
+ UCHAR cmd;
Scsi_Cmnd *SCpnt;
VOID *buffer;
+ POUR_DEVICE pdev; // current device opearating on
USHORT expectingIRQ;
- USHORT readPhase;
+ USHORT reconIsStarting; // indicate hot reconstruct is starting
+ USHORT reconOn; // Hot reconstruct is to be done.
+ USHORT reconPhase; // Hot reconstruct operation is in progress.
+ ULONG reconSize;
+ USHORT demoFail; // flag for RAID failure demonstration
+ USHORT survivor;
+ USHORT failinprog;
+ USHORT timeoutReconRetry;
+ struct timer_list reconTimer;
+ struct timer_list timer;
} ADAPTER2220I, *PADAPTER2220I;
#define HOSTDATA(host) ((PADAPTER2220I)&host->hostdata)
+#define RECON_PHASE_READY 0x01
+#define RECON_PHASE_COPY 0x02
+#define RECON_PHASE_UPDATE 0x03
+#define RECON_PHASE_LAST 0x04
+#define RECON_PHASE_END 0x07
+#define RECON_PHASE_MARKING 0x80
+#define RECON_PHASE_FAILOVER 0xFF
static struct Scsi_Host *PsiHost[MAXADAPTER] = {NULL,}; // One for each adapter
static int NumAdapters = 0;
-static IDENTIFY_DATA identifyData;
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);
+
+/****************************************************************
+ * Name: MuteAlarm :LOCAL
+ *
+ * Description: Mute the audible alarm.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static void MuteAlarm (PADAPTER2220I padapter)
+ {
+ UCHAR old;
+
+ old = (inb_p (padapter->regStatSel) >> 3) | (inb_p (padapter->regStatSel) & 0x83);
+ outb_p (old | 0x40, padapter->regFail);
+ }
+/****************************************************************
+ * Name: WaitReady :LOCAL
+ *
+ * Description: Wait for device ready.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int WaitReady (PADAPTER2220I padapter)
+ {
+ ULONG z;
+ UCHAR status;
+
+ for ( z = 0; z < (TIMEOUT_READY * 4); z++ )
+ {
+ status = inb_p (padapter->regStatCmd);
+ if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
+ return 0;
+ udelay (250);
+ }
+ return status;
+ }
+/****************************************************************
+ * Name: WaitReadyReset :LOCAL
+ *
+ * Description: Wait for device ready.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int WaitReadyReset (PADAPTER2220I padapter)
+ {
+ ULONG z;
+ UCHAR status;
+
+ for ( z = 0; z < (250 * 4); z++ ) // wait up to 1/4 second
+ {
+ status = inb_p (padapter->regStatCmd);
+ if ( (status & (IDE_STATUS_DRDY | IDE_STATUS_BUSY)) == IDE_STATUS_DRDY )
+ {
+ DEB (printk ("\nPCI2220I: Reset took %ld mSec to be ready", z / 4));
+ return 0;
+ }
+ udelay (250);
+ }
+ DEB (printk ("\nPCI2220I: Reset took more than 1 Second to come ready, Disk Failure"));
+ return status;
+ }
+/****************************************************************
+ * Name: WaitDrq :LOCAL
+ *
+ * Description: Wait for device ready for data transfer.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int WaitDrq (PADAPTER2220I padapter)
+ {
+ ULONG z;
+ UCHAR status;
+ for ( z = 0; z < (TIMEOUT_DRQ * 4); z++ )
+ {
+ status = inb_p (padapter->regStatCmd);
+ if ( status & IDE_STATUS_DRQ )
+ return 0;
+ udelay (250);
+ }
+ return status;
+ }
+/****************************************************************
+ * Name: HardReset :LOCAL
+ *
+ * Description: Wait for device ready for data transfer.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ * pdev - Pointer to device.
+ * spigot - Spigot number.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int HardReset (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot)
+ {
+ SelectSpigot (padapter, spigot | 0x80);
+
+ outb_p (0x0E, padapter->regAltStat); // reset the suvivor
+ udelay (100); // wait a little
+ outb_p (0x08, padapter->regAltStat); // clear the reset
+ udelay (100);
+ outb_p (0xA0, padapter->regLba24); //Specify drive
+
+ outb_p (pdev->byte6, padapter->regLba24); // select the drive
+ if ( WaitReadyReset (padapter) )
+ return TRUE;
+ outb_p (SECTORSXFER, padapter->regSectCount);
+ WriteCommand (padapter, IDE_CMD_SET_MULTIPLE);
+ if ( WaitReady (padapter) )
+ return TRUE;
+ return FALSE;
+ }
+/****************************************************************
+ * Name: BusMaster :LOCAL
+ *
+ * Description: Do a bus master I/O.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ * datain - TRUE if data read.
+ * irq - TRUE if bus master interrupt expected.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static void BusMaster (PADAPTER2220I padapter, UCHAR datain, UCHAR irq)
+ {
+ ULONG zl;
+
+ outl (padapter->timingAddress, padapter->regDmaAddrLoc);
+ outl (virt_to_bus (padapter->buffer), padapter->regDmaAddrPci);
+ zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
+ padapter->sectorCount -= zl;
+ zl *= (ULONG)BYTES_PER_SECTOR;
+ padapter->buffer += zl;
+ outl (zl, padapter->regDmaCount);
+ if ( datain )
+ {
+ outb_p (8, padapter->regDmaDesc); // read operation
+ if ( irq && !padapter->sectorCount )
+ outb_p (5, padapter->regDmaMode); // interrupt on
+ else
+ outb_p (1, padapter->regDmaMode); // no interrupt
+ }
+ else
+ {
+ outb_p (0, padapter->regDmaDesc); // write operation
+ outb_p (1, padapter->regDmaMode); // no interrupt
+ }
+ outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
+ }
/****************************************************************
* Name: WriteData :LOCAL
*
@@ -137,114 +333,224 @@
****************************************************************/
static int WriteData (PADAPTER2220I padapter)
{
- ULONG timer;
- USHORT *pports = padapter->ports;
+ ULONG zl;
+
+ if ( !WaitDrq (padapter) )
+ {
+ if ( padapter->timingPIO )
+ {
+ zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
+ outsw (padapter->regData, padapter->buffer, zl * (BYTES_PER_SECTOR / 2));
+ padapter->sectorCount -= zl;
+ padapter->buffer += zl * BYTES_PER_SECTOR;
+ }
+ else
+ BusMaster (padapter, 0, 0);
+ return 0;
+ }
+ padapter->cmd = 0; // null out the command byte
+ return 1;
+ }
+/****************************************************************
+ * Name: WriteDataBoth :LOCAL
+ *
+ * Description: Write data to device.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ *
+ * Returns: TRUE if drive does not assert DRQ in time.
+ *
+ ****************************************************************/
+static int WriteDataBoth (PADAPTER2220I padapter)
+ {
+ ULONG zl;
+ UCHAR status0, status1;
- timer = jiffies + TIMEOUT_DRQ; // calculate the timeout value
- do {
- if ( inb_p (pports[PORT_STAT_CMD]) & IDE_STATUS_DRQ )
- {
- outb_p (0, padapter->regDmaDesc); // write operation
- outl (padapter->timingAddress, padapter->regDmaAddrLoc);
- outl (virt_to_bus (padapter->buffer), padapter->regDmaAddrPci);
- outl ((ULONG)padapter->ide.ide.ide[2] * (ULONG)512, padapter->regDmaCount);
- outb_p (1, padapter->regDmaMode); // interrupts off
- outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
+ SelectSpigot (padapter, 1);
+ status0 = WaitDrq (padapter);
+ if ( !status0 )
+ {
+ SelectSpigot (padapter, 2);
+ status1 = WaitDrq (padapter);
+ if ( !status1 )
+ {
+ SelectSpigot (padapter, 3);
+ if ( padapter->timingPIO )
+ {
+ zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
+ outsw (padapter->regData, padapter->buffer, zl * (BYTES_PER_SECTOR / 2));
+ padapter->sectorCount -= zl;
+ padapter->buffer += zl * BYTES_PER_SECTOR;
+ }
+ else
+ BusMaster (padapter, 0, 0);
return 0;
}
- } while ( timer > jiffies ); // test for timeout
-
- padapter->ide.ide.ides.cmd = 0; // null out the command byte
- return 1;
+ }
+ padapter->cmd = 0; // null out the command byte
+ if ( status0 )
+ return 1;
+ return 2;
}
/****************************************************************
* Name: IdeCmd :LOCAL
*
- * Description: Process a queued command from the SCSI manager.
+ * Description: Process an IDE command.
*
* Parameters: padapter - Pointer adapter data structure.
+ * pdev - Pointer to device.
*
* Returns: Zero if no error or status register contents on error.
*
****************************************************************/
-static UCHAR IdeCmd (PADAPTER2220I padapter)
+static UCHAR IdeCmd (PADAPTER2220I padapter, POUR_DEVICE pdev)
{
- ULONG timer;
- USHORT *pports = padapter->ports;
UCHAR status;
- outb_p (padapter->ide.ide.ides.spigot, pports[PORT_STAT_SEL]); // select the spigot
- outb_p (padapter->ide.ide.ide[6], pports[PORT_LBA_24]); // select the drive
- timer = jiffies + TIMEOUT_READY; // calculate the timeout value
- DEB(printk ("\npci2220i Issueing new command: 0x%X",padapter->ide.ide.ides.cmd));
- do {
- status = inb_p (padapter->ports[PORT_STAT_CMD]);
- if ( status & IDE_STATUS_DRDY )
- {
- outb_p (padapter->ide.ide.ide[2], pports[PORT_SECTOR_COUNT]);
- outb_p (padapter->ide.ide.ide[3], pports[PORT_LBA_0]);
- outb_p (padapter->ide.ide.ide[4], pports[PORT_LBA_8]);
- outb_p (padapter->ide.ide.ide[5], pports[PORT_LBA_16]);
- padapter->expectingIRQ = 1;
- outb_p (padapter->ide.ide.ide[7], pports[PORT_STAT_CMD]);
-
- if ( padapter->ide.ide.ides.cmd == IDE_CMD_WRITE_MULTIPLE )
- return (WriteData (padapter));
- return 0;
- }
- } while ( timer > jiffies ); // test for timeout
+ SelectSpigot (padapter, pdev->spigot); // select the spigot
+ outb_p (pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24); // select the drive
+ status = WaitReady (padapter);
+ if ( !status )
+ {
+ outb_p (padapter->sectorCount, padapter->regSectCount);
+ outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
+ outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
+ outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
+ padapter->expectingIRQ = TRUE;
+ WriteCommand (padapter, padapter->cmd);
+ return 0;
+ }
- padapter->ide.ide.ides.cmd = 0; // null out the command byte
+ padapter->cmd = 0; // null out the command byte
return status;
}
/****************************************************************
- * Name: SetupTransfer :LOCAL
+ * Name: IdeCmdBoth :LOCAL
*
- * Description: Setup a data transfer command.
+ * Description: Process an IDE command to both drivers.
*
* Parameters: padapter - Pointer adapter data structure.
- * drive - Drive/head register upper nibble only.
*
- * Returns: TRUE if no data to transfer.
+ * Returns: Zero if no error or spigot of error.
*
****************************************************************/
-static int SetupTransfer (PADAPTER2220I padapter, UCHAR drive)
+static UCHAR IdeCmdBoth (PADAPTER2220I padapter)
{
- if ( padapter->sectorCount )
+ UCHAR status0;
+ UCHAR status1;
+
+ SelectSpigot (padapter, 3); // select the spigots
+ outb_p (padapter->pdev->byte6 | ((UCHAR *)(&padapter->startSector))[3], padapter->regLba24);// select the drive
+ SelectSpigot (padapter, 1);
+ status0 = WaitReady (padapter);
+ if ( !status0 )
{
- *(ULONG *)padapter->ide.ide.ides.lba = padapter->startSector;
- padapter->ide.ide.ide[6] |= drive;
-// padapter->ide.ide.ides.sectors = ( padapter->sectorCount > SECTORSXFER ) ? SECTORSXFER : padapter->sectorCount;
- padapter->ide.ide.ides.sectors = ( padapter->sectorCount > MAX_BUS_MASTER_BLOCKS ) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
- padapter->sectorCount -= padapter->ide.ide.ides.sectors; // bump the start and count for next xfer
- padapter->startSector += padapter->ide.ide.ides.sectors;
- return 0;
+ SelectSpigot (padapter, 2);
+ status1 = WaitReady (padapter);
+ if ( !status1 )
+ {
+ SelectSpigot (padapter, 3);
+ outb_p (padapter->sectorCount, padapter->regSectCount);
+ outb_p (((UCHAR *)(&padapter->startSector))[0], padapter->regLba0);
+ outb_p (((UCHAR *)(&padapter->startSector))[1], padapter->regLba8);
+ outb_p (((UCHAR *)(&padapter->startSector))[2], padapter->regLba16);
+ padapter->expectingIRQ = TRUE;
+ WriteCommand (padapter, padapter->cmd);
+ return 0;
+ }
+ }
+ padapter->cmd = 0; // null out the command byte
+ if ( status0 )
+ return 1;
+ return 2;
+ }
+/****************************************************************
+ * Name: OpDone :LOCAL
+ *
+ * Description: Complete an operatoin done sequence.
+ *
+ * Parameters: padapter - Pointer to host data block.
+ * spigot - Spigot select code.
+ * device - Device byte code.
+ *
+ * Returns: Nothing.
+ *
+ ****************************************************************/
+static void OpDone (PADAPTER2220I padapter, ULONG result)
+ {
+ Scsi_Cmnd *SCpnt = padapter->SCpnt;
+
+ if ( padapter->reconPhase )
+ {
+ padapter->reconPhase = 0;
+ if ( padapter->SCpnt )
+ {
+ Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
+ }
+ else
+ {
+ if ( padapter->reconOn )
+ {
+ ReconTimerExpiry ((unsigned long)padapter);
+ }
+ }
}
else
{
- padapter->ide.ide.ides.cmd = 0; // null out the command byte
- padapter->SCpnt = NULL;
- return 1;
+ padapter->cmd = 0;
+ padapter->SCpnt = NULL;
+ SCpnt->result = result;
+ SCpnt->scsi_done (SCpnt);
+ if ( padapter->reconOn && !padapter->reconTimer.data )
+ {
+ padapter->reconTimer.expires = jiffies + (HZ / 4); // start in 1/4 second
+ padapter->reconTimer.data = (unsigned long)padapter;
+ add_timer (&padapter->reconTimer);
+ }
}
}
/****************************************************************
+ * Name: InlineIdentify :LOCAL
+ *
+ * Description: Do an intline inquiry on a drive.
+ *
+ * Parameters: padapter - Pointer to host data block.
+ * spigot - Spigot select code.
+ * device - Device byte code.
+ *
+ * Returns: Last addressable sector or zero if none.
+ *
+ ****************************************************************/
+static ULONG InlineIdentify (PADAPTER2220I padapter, UCHAR spigot, UCHAR device)
+ {
+ PIDENTIFY_DATA pid = (PIDENTIFY_DATA)Buffer;
+
+ SelectSpigot (padapter, spigot | 0x80); // select the spigot
+ outb_p (device << 4, padapter->regLba24); // select the drive
+ if ( WaitReady (padapter) )
+ return 0;
+ WriteCommand (padapter, IDE_COMMAND_IDENTIFY);
+ if ( WaitDrq (padapter) )
+ return 0;
+ insw (padapter->regData, Buffer, sizeof (IDENTIFY_DATA) >> 1);
+ return (pid->LBATotalSectors - 1);
+ }
+/****************************************************************
* Name: DecodeError :LOCAL
*
* Description: Decode and process device errors.
*
- * Parameters: pshost - Pointer to host data block.
+ * Parameters: padapter - Pointer to adapter data.
* status - Status register code.
*
* Returns: The driver status code.
*
****************************************************************/
-static ULONG DecodeError (struct Scsi_Host *pshost, UCHAR status)
+static ULONG DecodeError (PADAPTER2220I padapter, UCHAR status)
{
- PADAPTER2220I padapter = HOSTDATA(pshost);
UCHAR error;
padapter->expectingIRQ = 0;
- padapter->SCpnt = NULL;
if ( status & IDE_STATUS_WRITE_FAULT )
{
return DID_PARITY << 16;
@@ -252,7 +558,7 @@
if ( status & IDE_STATUS_BUSY )
return DID_BUS_BUSY << 16;
- error = inb_p (padapter->ports[PORT_ERROR]);
+ error = inb_p (padapter->regError);
DEB(printk ("\npci2220i error register: %x", error));
switch ( error )
{
@@ -268,6 +574,483 @@
return DID_ERROR << 16;
}
/****************************************************************
+ * Name: StartTimer :LOCAL
+ *
+ * Description: Start the timer.
+ *
+ * Parameters: ipadapter - Pointer adapter data structure.
+ *
+ * Returns: Nothing.
+ *
+ ****************************************************************/
+static void StartTimer (PADAPTER2220I padapter)
+ {
+ padapter->timer.expires = jiffies + TIMEOUT_DATA;
+ add_timer (&padapter->timer);
+ }
+/****************************************************************
+ * Name: WriteSignature :LOCAL
+ *
+ * Description: Start the timer.
+ *
+ * Parameters: padapter - Pointer adapter data structure.
+ * pdev - Pointer to our device.
+ * spigot - Selected spigot.
+ * index - index of mirror signature on device.
+ *
+ * Returns: TRUE on any error.
+ *
+ ****************************************************************/
+static int WriteSignature (PADAPTER2220I padapter, POUR_DEVICE pdev, UCHAR spigot, int index)
+ {
+ ULONG zl;
+
+ SelectSpigot (padapter, spigot);
+ zl = pdev->lastsectorlba[index];
+ outb_p (pdev->byte6 | ((UCHAR *)&zl)[3], padapter->regLba24);
+ 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_WRITE);
+ if ( WaitDrq (padapter) )
+ return TRUE;
+ 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));
+ return FALSE;
+ }
+/*******************************************************************************************************
+ * Name: InitFailover
+ *
+ * Description: This is the beginning of the failover routine
+ *
+ * Parameters: SCpnt - Pointer to SCSI command structure.
+ * padapter - Pointer adapter data structure.
+ * pdev - Pointer to our device.
+ *
+ * Returns: TRUE on error.
+ *
+ ******************************************************************************************************/
+static int InitFailover (PADAPTER2220I padapter, POUR_DEVICE pdev)
+ {
+ UCHAR spigot;
+
+ DEB (printk ("\npci2000i: Initialize failover process - survivor = %d", padapter->survivor));
+ pdev->raid = FALSE; //initializes system for non raid mode
+ pdev->hotRecon = 0;
+ padapter->reconOn = FALSE;
+ spigot = (padapter->survivor) ? 2 : 1;
+
+ if ( pdev->DiskMirror[padapter->survivor].status & UCBF_REBUILD )
+ return (TRUE);
+
+ if ( HardReset (padapter, pdev, spigot) )
+ return TRUE;
+
+ outb_p (0x3C | spigot, padapter->regFail); // sound alarm and set fail light
+ pdev->DiskMirror[padapter->survivor].status = UCBF_MIRRORED | UCBF_SURVIVOR; //clear present status
+
+ if ( WriteSignature (padapter, pdev, spigot, padapter->survivor) )
+ return TRUE;
+ padapter->failinprog = TRUE;
+ return FALSE;
+ }
+/****************************************************************
+ * Name: TimerExpiry :LOCAL
+ *
+ * Description: Timer expiry routine.
+ *
+ * Parameters: data - Pointer adapter data structure.
+ *
+ * Returns: Nothing.
+ *
+ ****************************************************************/
+static void TimerExpiry (unsigned long data)
+ {
+ PADAPTER2220I padapter = (PADAPTER2220I)data;
+ POUR_DEVICE pdev = padapter->pdev;
+ ULONG flags;
+ UCHAR status = IDE_STATUS_BUSY;
+ UCHAR temp, temp1;
+
+ 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;
+ }
+
+ 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;
+
+ case RECON_PHASE_READY:
+ OpDone (padapter, DID_ERROR << 16);
+ return;
+
+ case RECON_PHASE_COPY:
+ padapter->survivor = (pdev->spigot) >> 1;
+ restore_flags (flags);
+ DEB (printk ("\npci2220i: FAILURE 2"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DID_ERROR << 16);
+ return;
+
+ case RECON_PHASE_UPDATE:
+ padapter->survivor = (pdev->spigot) >> 1;
+ restore_flags (flags);
+ DEB (printk ("\npci2220i: FAILURE 3"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DID_ERROR << 16);
+ return;
+
+ 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;
+
+ default:
+ return;
+ }
+ }
+
+ while ( padapter->cmd )
+ {
+ outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
+ if ( pdev->raid )
+ {
+ if ( padapter->cmd == WRITE_CMD )
+ {
+ DEB (printk ("in RAID write operation"));
+ if ( inb_p (padapter->regStatSel) & 1 )
+ {
+ SelectSpigot (padapter, 0x81 ); // Masking the interrupt during spigot select
+ temp = inb_p (padapter->regStatCmd);
+ }
+ else
+ temp = IDE_STATUS_BUSY;
+
+ if ( inb (padapter->regStatSel) & 2 )
+ {
+ SelectSpigot (padapter, 0x82 ); // Masking the interrupt during spigot select
+ temp1 = inb_p (padapter->regStatCmd);
+ }
+ else
+ temp1 = IDE_STATUS_BUSY;
+
+ if ( (temp & IDE_STATUS_BUSY) || (temp1 & IDE_STATUS_BUSY) )
+ {
+ if ( (temp & IDE_STATUS_BUSY) && (temp1 & IDE_STATUS_BUSY) )
+ {
+ status = temp;
+ break;
+ }
+ else
+ {
+ if (temp & IDE_STATUS_BUSY)
+ padapter->survivor = 1;
+ else
+ padapter->survivor = 0;
+ restore_flags (flags);
+ DEB (printk ("\npci2220i: FAILURE 5"));
+ if ( InitFailover (padapter, pdev) )
+ {
+ status = inb_p (padapter->regStatCmd);
+ break;
+ }
+ return;
+ }
+ }
+ }
+ else
+ {
+ 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;
+ }
+ }
+ else
+ {
+ DEB (printk ("in I/O operation"));
+ status = inb_p (padapter->regStatCmd);
+ }
+ break;
+ }
+
+ restore_flags (flags);
+ OpDone (padapter, DecodeError (padapter, status));
+ }
+/****************************************************************
+ * Name: SetReconstruct :LOCAL
+ *
+ * Description: Set the reconstruct up.
+ *
+ * Parameters: pdev - Pointer to device structure.
+ * index - Mirror index number.
+ *
+ * Returns: Number of sectors on new disk required.
+ *
+ ****************************************************************/
+static LONG SetReconstruct (POUR_DEVICE pdev, int index)
+ {
+ pdev->DiskMirror[index].status = UCBF_MIRRORED; // setup the flags
+ pdev->DiskMirror[index ^ 1].status = UCBF_MIRRORED | UCBF_REBUILD;
+ pdev->DiskMirror[index ^ 1].reconstructPoint = 0; // start the reconstruct
+ pdev->reconCount = 1990; // mark target drive early
+ pdev->hotRecon = 1 >> index;
+ return pdev->DiskMirror[index].reconstructPoint;
+ }
+/****************************************************************
+ * Name: ReconTimerExpiry :LOCAL
+ *
+ * Description: Reconstruct timer expiry routine.
+ *
+ * Parameters: data - Pointer adapter data structure.
+ *
+ * Returns: Nothing.
+ *
+ ****************************************************************/
+static void ReconTimerExpiry (unsigned long data)
+ {
+ PADAPTER2220I padapter;
+ POUR_DEVICE pdev;
+ ULONG testsize = 0;
+ PIDENTIFY_DATA pid;
+ USHORT minmode;
+ ULONG zl;
+ UCHAR zc;
+
+ padapter = (PADAPTER2220I)data;
+ if ( padapter->SCpnt )
+ return;
+
+ pdev = padapter->device;
+ pid = (PIDENTIFY_DATA)Buffer;
+ padapter->reconTimer.data = 0;
+ padapter->timeoutReconRetry = 2;
+ padapter->pdev = pdev;
+ if ( padapter->reconIsStarting )
+ {
+ padapter->reconIsStarting = FALSE;
+ padapter->reconOn = FALSE;
+ pdev->hotRecon = FALSE;
+
+ if ( (pdev->DiskMirror[0].signature == SIGNATURE) && (pdev->DiskMirror[1].signature == SIGNATURE) &&
+ (pdev->DiskMirror[0].pairIdentifier == (pdev->DiskMirror[1].pairIdentifier ^ 1)) )
+ {
+ if ( (pdev->DiskMirror[0].status & UCBF_MATCHED) && (pdev->DiskMirror[1].status & UCBF_MATCHED) )
+ {
+ return;
+ }
+
+ if ( pdev->DiskMirror[0].status & UCBF_SURVIVOR ) // is first drive survivor?
+ testsize = SetReconstruct (pdev, 0);
+ else
+ if ( pdev->DiskMirror[1].status & UCBF_SURVIVOR ) // is second drive survivor?
+ testsize = SetReconstruct (pdev, 1);
+
+ if ( (pdev->DiskMirror[0].status & UCBF_REBUILD) || (pdev->DiskMirror[1].status & UCBF_REBUILD) )
+ {
+ if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
+ {
+ pdev->hotRecon = 1;
+ pdev->mirrorRecon = 0;
+ }
+ else
+ {
+ pdev->hotRecon = 2;
+ pdev->mirrorRecon = 1;
+ }
+ }
+ }
+
+ if ( !pdev->hotRecon )
+ return;
+
+ zc = ((inb_p (padapter->regStatSel) >> 3) | inb_p (padapter->regStatSel)) & 0x83; // mute the alarm
+ outb_p (zc | pdev->hotRecon | 0x40, padapter->regFail);
+
+ while ( 1 )
+ {
+ if ( HardReset (padapter, pdev, pdev->hotRecon) )
+ {
+ DEB (printk ("\npci2220i: sub 1"));
+ break;
+ }
+
+ pdev->lastsectorlba[pdev->mirrorRecon] = InlineIdentify (padapter, pdev->hotRecon, 0);
+
+ if ( pdev->lastsectorlba[pdev->mirrorRecon] < testsize )
+ {
+ DEB (printk ("\npci2220i: sub 2 %ld %ld", pdev->lastsectorlba[pdev->mirrorRecon], testsize));
+ break;
+ }
+
+ // test LBA and multiper sector transfer compatability
+ if (!pid->SupportLBA || (pid->NumSectorsPerInt < SECTORSXFER) || !pid->Valid_64_70 )
+ {
+ DEB (printk ("\npci2220i: sub 3"));
+ break;
+ }
+
+ // test PIO/bus matering mode compatability
+ if ( (pid->MinPIOCycleWithoutFlow > 240) && !pid->SupportIORDYDisable && !padapter->timingPIO )
+ {
+ DEB (printk ("\npci2220i: sub 4"));
+ break;
+ }
+
+ if ( pid->MinPIOCycleWithoutFlow <= 120 ) // setup timing mode of drive
+ minmode = 5;
+ else
+ {
+ if ( pid->MinPIOCylceWithFlow <= 150 )
+ minmode = 4;
+ else
+ {
+ if ( pid->MinPIOCylceWithFlow <= 180 )
+ minmode = 3;
+ else
+ {
+ if ( pid->MinPIOCylceWithFlow <= 240 )
+ minmode = 2;
+ else
+ {
+ DEB (printk ("\npci2220i: sub 5"));
+ break;
+ }
+ }
+ }
+ }
+
+ if ( padapter->timingMode > minmode ) // set minimum timing mode
+ padapter->timingMode = minmode;
+ if ( padapter->timingMode >= 2 )
+ padapter->timingAddress = ModeArray[padapter->timingMode - 2];
+ else
+ padapter->timingPIO = TRUE;
+
+ padapter->reconOn = TRUE;
+ break;
+ }
+
+ if ( !padapter->reconOn )
+ {
+ pdev->hotRecon = FALSE;
+ padapter->survivor = pdev->mirrorRecon ^ 1;
+ padapter->reconPhase = RECON_PHASE_FAILOVER;
+ DEB (printk ("\npci2220i: FAILURE 7"));
+ InitFailover (padapter, pdev);
+ return;
+ }
+
+ pdev->raid = TRUE;
+
+ if ( WriteSignature (padapter, pdev, pdev->spigot, pdev->mirrorRecon ^ 1) )
+ return;
+ padapter->reconPhase = RECON_PHASE_MARKING;
+ return;
+ }
+
+ //**********************************
+ // reconstruct copy starts here
+ //**********************************
+ if ( pdev->reconCount++ > 2000 )
+ {
+ pdev->reconCount = 0;
+ if ( WriteSignature (padapter, pdev, pdev->hotRecon, pdev->mirrorRecon) )
+ {
+ padapter->survivor = pdev->mirrorRecon ^ 1;
+ padapter->reconPhase = RECON_PHASE_FAILOVER;
+ DEB (printk ("\npci2220i: FAILURE 8"));
+ InitFailover (padapter, pdev);
+ return;
+ }
+ padapter->reconPhase = RECON_PHASE_UPDATE;
+ return;
+ }
+
+ zl = pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint;
+ padapter->reconSize = pdev->DiskMirror[pdev->mirrorRecon ^ 1].reconstructPoint - zl;
+ if ( padapter->reconSize > MAX_BUS_MASTER_BLOCKS )
+ padapter->reconSize = MAX_BUS_MASTER_BLOCKS;
+
+ if ( padapter->reconSize )
+ {
+ SelectSpigot (padapter, 3); // select the spigots
+ outb_p (pdev->byte6 | ((UCHAR *)(&zl))[3], padapter->regLba24);// select the drive
+ SelectSpigot (padapter, pdev->spigot);
+ if ( WaitReady (padapter) )
+ return;
+
+ SelectSpigot (padapter, pdev->hotRecon);
+ if ( WaitReady (padapter) )
+ {
+ padapter->survivor = pdev->mirrorRecon ^ 1;
+ padapter->reconPhase = RECON_PHASE_FAILOVER;
+ DEB (printk ("\npci2220i: FAILURE 9"));
+ InitFailover (padapter, pdev);
+ return;
+ }
+
+ SelectSpigot (padapter, 3);
+ outb_p (padapter->reconSize & 0xFF, padapter->regSectCount);
+ outb_p (((UCHAR *)(&zl))[0], padapter->regLba0);
+ outb_p (((UCHAR *)(&zl))[1], padapter->regLba8);
+ outb_p (((UCHAR *)(&zl))[2], padapter->regLba16);
+ padapter->expectingIRQ = TRUE;
+ padapter->reconPhase = RECON_PHASE_READY;
+ SelectSpigot (padapter, pdev->hotRecon);
+ WriteCommand (padapter, WRITE_CMD);
+ StartTimer (padapter);
+ SelectSpigot (padapter, pdev->spigot);
+ WriteCommand (padapter, READ_CMD);
+ return;
+ }
+
+ 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;
+ padapter->reconPhase = RECON_PHASE_LAST;
+ return;
+ }
+/****************************************************************
* Name: Irq_Handler :LOCAL
*
* Description: Interrupt handler.
@@ -283,12 +1066,14 @@
{
struct Scsi_Host *shost = NULL; // Pointer to host data block
PADAPTER2220I padapter; // Pointer to adapter control structure
- USHORT *pports; // I/O port array
+ POUR_DEVICE pdev;
Scsi_Cmnd *SCpnt;
UCHAR status;
+ UCHAR status1;
int z;
+ ULONG zl;
-// DEB(printk ("\npci2220i recieved interrupt\n"));
+// DEB (printk ("\npci2220i recieved interrupt\n"));
for ( z = 0; z < NumAdapters; z++ ) // scan for interrupt to process
{
@@ -309,82 +1094,264 @@
}
padapter = HOSTDATA(shost);
- pports = padapter->ports;
+ pdev = padapter->pdev;
SCpnt = padapter->SCpnt;
- if ( !padapter->expectingIRQ )
+ if ( !padapter->expectingIRQ || !(SCpnt || padapter->reconPhase) )
{
DEB(printk ("\npci2220i Unsolicited interrupt\n"));
+ STOP_HERE ();
return;
}
padapter->expectingIRQ = 0;
+ outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
+
+ if ( padapter->failinprog )
+ {
+ DEB (printk ("\npci2220i interrupt failover complete"));
+ padapter->failinprog = FALSE;
+ status = inb_p (padapter->regStatCmd); // read the device status
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ DEB (printk ("\npci2220i: interrupt failover error from drive %X", status));
+ padapter->cmd = 0;
+ }
+ else
+ {
+ DEB (printk ("\npci2220i: restarting failed opertation."));
+ pdev->spigot = (padapter->survivor) ? 2 : 1;
+ del_timer (&padapter->timer);
+ if ( padapter->reconPhase )
+ OpDone (padapter, DID_OK << 16);
+ else
+ Pci2220i_QueueCommand (SCpnt, SCpnt->scsi_done);
+ return;
+ }
+ }
+
+ if ( padapter->reconPhase )
+ {
+ switch ( padapter->reconPhase )
+ {
+ case RECON_PHASE_MARKING:
+ case RECON_PHASE_LAST:
+ status = inb_p (padapter->regStatCmd); // read the device status
+ del_timer (&padapter->timer);
+ if ( padapter->reconPhase == RECON_PHASE_LAST )
+ {
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ padapter->survivor = (pdev->spigot ^ 3) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 10"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DecodeError (padapter, status));
+ return;
+ }
+ if ( WriteSignature (padapter, pdev, pdev->hotRecon, pdev->mirrorRecon) )
+ {
+ padapter->survivor = (pdev->spigot) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 11"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DecodeError (padapter, status));
+ return;
+ }
+ padapter->reconPhase = RECON_PHASE_END;
+ return;
+ }
+ OpDone (padapter, DID_OK << 16);
+ return;
- status = inb_p (padapter->ports[PORT_STAT_CMD]); // read the device status
- if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
- goto irqerror;
-
- switch ( padapter->ide.ide.ides.cmd ) // decide how to handle the interrupt
- {
- case IDE_CMD_READ_MULTIPLE:
- if ( padapter->readPhase == 1 ) // is this a bus master channel complete?
- {
- DEB(printk ("\npci2220i processing read interrupt cleanup"));
- outb_p (0x08, padapter->regDmaCmdStat); // cancel interrupt from DMA engine
- padapter->buffer += padapter->ide.ide.ides.sectors * 512;
- if ( SetupTransfer (padapter, padapter->ide.ide.ide[6] & 0xF0) )
- {
- SCpnt->result = DID_OK << 16;
- padapter->SCpnt = NULL;
- SCpnt->scsi_done (SCpnt);
+ case RECON_PHASE_READY:
+ status = inb_p (padapter->regStatCmd); // read the device status
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ del_timer (&padapter->timer);
+ OpDone (padapter, DecodeError (padapter, status));
return;
}
- padapter->readPhase = 0;
- if ( !(status = IdeCmd (padapter)) )
+ SelectSpigot (padapter, pdev->hotRecon);
+ if ( WaitDrq (padapter) )
{
- DEB (printk ("\npci2220i interrupt complete, waiting for another"));
+ del_timer (&padapter->timer);
+ padapter->survivor = (pdev->spigot) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 12"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DecodeError (padapter, status));
return;
}
- }
- if ( status & IDE_STATUS_DRQ )
+ 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));
+ }
+ else
+ {
+ outl (padapter->timingAddress, padapter->regDmaAddrLoc);
+ outl (virt_to_bus (Buffer), 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;
+
+ case RECON_PHASE_COPY:
+ pdev->DiskMirror[pdev->mirrorRecon].reconstructPoint += padapter->reconSize;
+
+ case RECON_PHASE_UPDATE:
+ SelectSpigot (padapter, pdev->hotRecon | 0x80);
+ status = inb_p (padapter->regStatCmd); // read the device status
+ del_timer (&padapter->timer);
+ 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)));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DecodeError (padapter, status));
+ return;
+ }
+ OpDone (padapter, DID_OK << 16);
+ return;
+
+ case RECON_PHASE_END:
+ status = inb_p (padapter->regStatCmd); // read the device status
+ del_timer (&padapter->timer);
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ padapter->survivor = (pdev->spigot) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 14"));
+ if ( InitFailover (padapter, pdev) )
+ OpDone (padapter, DecodeError (padapter, status));
+ return;
+ }
+ padapter->reconOn = FALSE;
+ pdev->hotRecon = 0;
+ OpDone (padapter, DID_OK << 16);
+ return;
+
+ default:
+ return;
+ }
+ }
+
+ switch ( padapter->cmd ) // decide how to handle the interrupt
+ {
+ case READ_CMD:
+ if ( padapter->sectorCount )
{
- DEB(printk ("\npci2220i processing read interrupt start bus master cycle"));
- outb_p (8, padapter->regDmaDesc); // read operation
- padapter->readPhase = 1;
- padapter->expectingIRQ = 1;
- outl (padapter->timingAddress, padapter->regDmaAddrLoc);
- outl (virt_to_bus (padapter->buffer), padapter->regDmaAddrPci);
- outl ((ULONG)padapter->ide.ide.ides.sectors * (ULONG)512, padapter->regDmaCount);
- outb_p (5, padapter->regDmaMode); // interrupt enable/disable
- outb_p (0x03, padapter->regDmaCmdStat); // kick the DMA engine in gear
+ status = inb_p (padapter->regStatCmd); // read the device status
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ if ( pdev->raid )
+ {
+ padapter->survivor = (pdev->spigot ^ 3) >> 1;
+ del_timer (&padapter->timer);
+ DEB (printk ("\npci2220i: FAILURE 15"));
+ if ( !InitFailover (padapter, pdev) )
+ return;
+ }
+ break;
+ }
+ if ( padapter->timingPIO )
+ {
+ zl = (padapter->sectorCount > MAX_BUS_MASTER_BLOCKS) ? MAX_BUS_MASTER_BLOCKS : padapter->sectorCount;
+ insw (padapter->regData, padapter->buffer, zl * (BYTES_PER_SECTOR / 2));
+ padapter->sectorCount -= zl;
+ padapter->buffer += zl * BYTES_PER_SECTOR;
+ if ( !padapter->sectorCount )
+ {
+ status = 0;
+ break;
+ }
+ }
+ else
+ BusMaster (padapter, 1, 1);
+ padapter->expectingIRQ = TRUE;
return;
}
+ status = 0;
break;
- case IDE_CMD_WRITE_MULTIPLE:
- DEB(printk ("\npci2220i processing write interrupt cleanup"));
- padapter->buffer += padapter->ide.ide.ides.sectors * 512;
- if ( SetupTransfer (padapter, padapter->ide.ide.ide[6] & 0xF0) )
+ case WRITE_CMD:
+ SelectSpigot (padapter, pdev->spigot | 0x80);
+ status = inb_p (padapter->regStatCmd); // read the device status
+ if ( pdev->raid )
{
- SCpnt->result = DID_OK << 16;
- padapter->SCpnt = NULL;
- SCpnt->scsi_done (SCpnt);
- return;
+ SelectSpigot (padapter, (pdev->spigot ^ 3) | 0x80);
+ status1 = inb_p (padapter->regStatCmd); // read the device status
}
- if ( !(status = IdeCmd (padapter)) )
+ else
+ status1 = 0;
+
+ if ( status & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ if ( pdev->raid && !(status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT)) )
+ {
+ padapter->survivor = (pdev->spigot ^ 3) >> 1;
+ del_timer (&padapter->timer);
+ SelectSpigot (padapter, pdev->spigot | 0x80);
+ DEB (printk ("\npci2220i: FAILURE 16 status = %X error = %X", status, inb_p (padapter->regError)));
+ if ( !InitFailover (padapter, pdev) )
+ return;
+ }
+ break;
+ }
+ if ( pdev->raid )
{
- DEB (printk ("\npci2220i interrupt complete, waiting for another"));
+ if ( status1 & (IDE_STATUS_ERROR | IDE_STATUS_WRITE_FAULT) )
+ {
+ padapter->survivor = pdev->spigot >> 1;
+ del_timer (&padapter->timer);
+ DEB (printk ("\npci2220i: FAILURE 17 status = %X error = %X", status1, inb_p (padapter->regError)));
+ if ( !InitFailover (padapter, pdev) )
+ return;
+ status = status1;
+ break;
+ }
+ if ( padapter->sectorCount )
+ {
+ status = WriteDataBoth (padapter);
+ if ( status )
+ {
+ padapter->survivor = (status ^ 3) >> 1;
+ del_timer (&padapter->timer);
+ DEB (printk ("\npci2220i: FAILURE 18"));
+ if ( !InitFailover (padapter, pdev) )
+ return;
+ SelectSpigot (padapter, status | 0x80);
+ status = inb_p (padapter->regStatCmd); // read the device status
+ break;
+ }
+ padapter->expectingIRQ = TRUE;
+ return;
+ }
+ status = 0;
+ break;
+ }
+ if ( padapter->sectorCount )
+ {
+ SelectSpigot (padapter, pdev->spigot);
+ status = WriteData (padapter);
+ if ( status )
+ break;
+ padapter->expectingIRQ = TRUE;
return;
}
+ status = 0;
break;
case IDE_COMMAND_IDENTIFY:
{
PINQUIRYDATA pinquiryData = SCpnt->request_buffer;
+ PIDENTIFY_DATA pid = (PIDENTIFY_DATA)Buffer;
- DEB(printk ("\npci2220i processing verify interrupt cleanup"));
+ status = inb_p (padapter->regStatCmd);
if ( status & IDE_STATUS_DRQ )
{
- insw (pports[PORT_DATA], &identifyData, sizeof (identifyData) >> 1);
+ insw (padapter->regData, pid, sizeof (IDENTIFY_DATA) >> 1);
memset (pinquiryData, 0, SCpnt->request_bufflen); // Zero INQUIRY data structure.
pinquiryData->DeviceType = 0;
@@ -394,8 +1361,8 @@
// Fill in vendor identification fields.
for ( z = 0; z < 20; z += 2 )
{
- pinquiryData->VendorId[z] = ((UCHAR *)identifyData.ModelNumber)[z + 1];
- pinquiryData->VendorId[z + 1] = ((UCHAR *)identifyData.ModelNumber)[z];
+ pinquiryData->VendorId[z] = ((UCHAR *)pid->ModelNumber)[z + 1];
+ pinquiryData->VendorId[z + 1] = ((UCHAR *)pid->ModelNumber)[z];
}
// Initialize unused portion of product id.
@@ -406,38 +1373,32 @@
// product revision in INQUIRY data.
for ( z = 0; z < 4; z += 2 )
{
- pinquiryData->ProductRevisionLevel[z] = ((UCHAR *)identifyData.FirmwareRevision)[z + 1];
- pinquiryData->ProductRevisionLevel[z + 1] = ((UCHAR *)identifyData.FirmwareRevision)[z];
+ pinquiryData->ProductRevisionLevel[z] = ((UCHAR *)pid->FirmwareRevision)[z + 1];
+ pinquiryData->ProductRevisionLevel[z + 1] = ((UCHAR *)pid->FirmwareRevision)[z];
}
-
- SCpnt->result = DID_OK << 16;
- padapter->SCpnt = NULL;
- SCpnt->scsi_done (SCpnt);
- return;
+ if ( pdev == padapter->device )
+ *((USHORT *)(&pinquiryData->VendorSpecific)) = DEVICE_DALE_1;
+
+ status = 0;
}
break;
}
default:
- DEB(printk ("\npci2220i no real process here!"));
- SCpnt->result = DID_OK << 16;
- padapter->SCpnt = NULL;
- SCpnt->scsi_done (SCpnt);
- return;
+ status = 0;
+ break;
+ }
+
+ del_timer (&padapter->timer);
+ if ( status )
+ {
+ DEB (printk ("\npci2220i Interupt hanlder return error"));
+ zl = DecodeError (padapter, status);
}
+ else
+ zl = DID_OK << 16;
-irqerror:;
- DEB(printk ("\npci2220i error Device Status: %X\n", status));
- SCpnt->result = DecodeError (shost, status);
- SCpnt->scsi_done (SCpnt);
- }
-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);
+ OpDone (padapter, zl);
}
/****************************************************************
* Name: Pci2220i_QueueCommand
@@ -456,121 +1417,182 @@
PADAPTER2220I padapter = HOSTDATA(SCpnt->host); // Pointer to adapter control structure
POUR_DEVICE pdev = &padapter->device[SCpnt->target];// Pointer to device information
UCHAR rc; // command return code
+ int z;
+ PDEVICE_RAID1 pdr;
SCpnt->scsi_done = done;
- padapter->ide.ide.ides.spigot = pdev->spigot;
padapter->buffer = SCpnt->request_buffer;
- if (done)
+ padapter->SCpnt = SCpnt; // Save this command data
+ if ( !done )
{
- if ( !pdev->device )
- {
- SCpnt->result = DID_BAD_TARGET << 16;
- done (SCpnt);
- return 0;
- }
+ printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb);
+ return 0;
}
- else
+
+ if ( padapter->reconPhase )
+ return 0;
+ if ( padapter->reconTimer.data )
{
- printk("pci2220i_queuecommand: %02X: done can't be NULL\n", *cdb);
+ del_timer (&padapter->reconTimer);
+ padapter->reconTimer.data = 0;
+ }
+
+ if ( !pdev->device || SCpnt->lun )
+ {
+ OpDone (padapter, DID_BAD_TARGET << 16);
return 0;
}
- DEB (if(*cdb) printk ("\nCDB: %X- %X %X %X %X %X %X %X %X %X %X ", SCpnt->cmd_len, cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5], cdb[6], cdb[7], cdb[8], cdb[9]));
+
switch ( *cdb )
{
case SCSIOP_INQUIRY: // inquiry CDB
{
- padapter->ide.ide.ide[6] = pdev->byte6;
- padapter->ide.ide.ides.cmd = IDE_COMMAND_IDENTIFY;
+ if ( cdb[2] == SC_MY_RAID )
+ {
+ switch ( cdb[3] )
+ {
+ case MY_SCSI_REBUILD:
+ padapter->reconOn = padapter->reconIsStarting = TRUE;
+ OpDone (padapter, DID_OK << 16);
+ break;
+ case MY_SCSI_ALARMMUTE:
+ MuteAlarm (padapter);
+ OpDone (padapter, DID_OK << 16);
+ break;
+ case MY_SCSI_DEMOFAIL:
+ padapter->demoFail = TRUE;
+ OpDone (padapter, DID_OK << 16);
+ break;
+ default:
+ z = cdb[5]; // get index
+ pdr = (PDEVICE_RAID1)SCpnt->request_buffer;
+ if ( padapter->raidData[z] )
+ {
+ memcpy (&pdr->DiskRaid1, padapter->raidData[z], sizeof (DISK_MIRROR));
+ pdr->TotalSectors = padapter->device[0].blocks;
+ }
+ else
+ memset (pdr, 0, sizeof (DEVICE_RAID1));
+ OpDone (padapter, DID_OK << 16);
+ break;
+ }
+ return 0;
+ }
+ padapter->cmd = IDE_COMMAND_IDENTIFY;
break;
}
case SCSIOP_TEST_UNIT_READY: // test unit ready CDB
- SCpnt->result = DID_OK << 16;
- done (SCpnt);
+ OpDone (padapter, DID_OK << 16);
return 0;
-
case SCSIOP_READ_CAPACITY: // read capctiy CDB
{
PREAD_CAPACITY_DATA pdata = (PREAD_CAPACITY_DATA)SCpnt->request_buffer;
pdata->blksiz = 0x20000;
XANY2SCSI ((UCHAR *)&pdata->blks, pdev->blocks);
- SCpnt->result = DID_OK << 16;
- done (SCpnt);
+ OpDone (padapter, DID_OK << 16);
return 0;
}
-
case SCSIOP_VERIFY: // verify CDB
- *(ULONG *)padapter->ide.ide.ides.lba = XSCSI2LONG (&cdb[2]);
- padapter->ide.ide.ide[6] |= pdev->byte6;
- padapter->ide.ide.ide[2] = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8));
- padapter->ide.ide.ides.cmd = IDE_COMMAND_VERIFY;
+ padapter->startSector = XSCSI2LONG (&cdb[2]);
+ padapter->sectorCount = (UCHAR)((USHORT)cdb[8] | ((USHORT)cdb[7] << 8));
+ padapter->cmd = IDE_COMMAND_VERIFY;
break;
-
case SCSIOP_READ: // read10 CDB
padapter->startSector = XSCSI2LONG (&cdb[2]);
padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
- SetupTransfer (padapter, pdev->byte6);
- padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE;
- padapter->readPhase = 0;
+ padapter->cmd = READ_CMD;
break;
-
case SCSIOP_READ6: // read6 CDB
padapter->startSector = SCSI2LONG (&cdb[1]);
padapter->sectorCount = cdb[4];
- SetupTransfer (padapter, pdev->byte6);
- padapter->ide.ide.ides.cmd = IDE_CMD_READ_MULTIPLE;
- padapter->readPhase = 0;
+ padapter->cmd = READ_CMD;
break;
-
case SCSIOP_WRITE: // write10 CDB
padapter->startSector = XSCSI2LONG (&cdb[2]);
padapter->sectorCount = (USHORT)cdb[8] | ((USHORT)cdb[7] << 8);
- SetupTransfer (padapter, pdev->byte6);
- padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE;
+ padapter->cmd = WRITE_CMD;
break;
case SCSIOP_WRITE6: // write6 CDB
padapter->startSector = SCSI2LONG (&cdb[1]);
padapter->sectorCount = cdb[4];
- SetupTransfer (padapter, pdev->byte6);
- padapter->ide.ide.ides.cmd = IDE_CMD_WRITE_MULTIPLE;
+ padapter->cmd = WRITE_CMD;
break;
-
default:
DEB (printk ("pci2220i_queuecommand: Unsupported command %02X\n", *cdb));
- SCpnt->result = DID_ERROR << 16;
- done (SCpnt);
+ OpDone (padapter, DID_ERROR << 16);
return 0;
}
- padapter->SCpnt = SCpnt; // Save this command data
+ if ( padapter->reconPhase )
+ return 0;
+
+ padapter->pdev = pdev;
- rc = IdeCmd (padapter);
- if ( rc )
+ while ( padapter->demoFail )
{
- padapter->expectingIRQ = 0;
- DEB (printk ("pci2220i_queuecommand: %02X, %02X: Device failed to respond for command\n", *cdb, padapter->ide.ide.ides.cmd));
- SCpnt->result = DID_ERROR << 16;
- done (SCpnt);
+ padapter->demoFail = FALSE;
+ if ( !pdev->raid ||
+ (pdev->DiskMirror[0].status & UCBF_SURVIVOR) ||
+ (pdev->DiskMirror[1].status & UCBF_SURVIVOR) )
+ {
+ break;
+ }
+ if ( pdev->DiskMirror[0].status & UCBF_REBUILD )
+ padapter->survivor = 1;
+ else
+ padapter->survivor = 0;
+ DEB (printk ("\npci2220i: FAILURE 19"));
+ if ( InitFailover (padapter, pdev ) )
+ break;
return 0;
}
- if ( padapter->ide.ide.ides.cmd == IDE_CMD_WRITE_MULTIPLE )
+
+ StartTimer (padapter);
+ if ( pdev->raid && (padapter->cmd == WRITE_CMD) )
+ {
+ rc = IdeCmdBoth (padapter);
+ if ( !rc )
+ rc = WriteDataBoth (padapter);
+ if ( rc )
+ {
+ del_timer (&padapter->timer);
+ padapter->expectingIRQ = 0;
+ padapter->survivor = (rc ^ 3) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 20"));
+ if ( InitFailover (padapter, pdev) )
+ {
+ OpDone (padapter, DID_ERROR << 16);
+ return 0;
+ }
+ }
+ }
+ else
{
- if ( WriteData (padapter) )
+ rc = IdeCmd (padapter, pdev);
+ if ( (padapter->cmd == WRITE_CMD) && !rc )
+ rc = WriteData (padapter);
+ if ( rc )
{
+ del_timer (&padapter->timer);
padapter->expectingIRQ = 0;
- DEB (printk ("pci2220i_queuecommand: %02X, %02X: Device failed to accept data\n", *cdb, padapter->ide.ide.ides.cmd));
- SCpnt->result = DID_ERROR << 16;
- done (SCpnt);
+ if ( pdev->raid )
+ {
+ padapter->survivor = (pdev->spigot ^ 3) >> 1;
+ DEB (printk ("\npci2220i: FAILURE 21"));
+ if ( !InitFailover (padapter, pdev) )
+ return 0;
+ }
+ OpDone (padapter, DID_ERROR << 16);
return 0;
}
}
- DEB (printk(" now waiting for initial interrupt "));
return 0;
}
-static void internal_done(Scsi_Cmnd * SCpnt)
+static void internal_done(Scsi_Cmnd *SCpnt)
{
SCpnt->SCp.Status++;
}
@@ -586,10 +1608,7 @@
****************************************************************/
int Pci2220i_Command (Scsi_Cmnd *SCpnt)
{
- DEB(printk("pci2220i_command: ..calling pci2220i_queuecommand\n"));
-
Pci2220i_QueueCommand (SCpnt, internal_done);
-
SCpnt->SCp.Status = 0;
while (!SCpnt->SCp.Status)
barrier ();
@@ -600,7 +1619,7 @@
*
* Description: Read information from controller Flash memory.
*
- * Parameters: hostdata - Pointer to host interface data structure.
+ * Parameters: padapter - Pointer to host interface data structure.
* pdata - Pointer to data structures.
* base - base address in Flash.
* length - lenght of data space in bytes.
@@ -608,25 +1627,24 @@
* Returns: Nothing.
*
****************************************************************/
-VOID ReadFlash (PADAPTER2220I hostdata, VOID *pdata, ULONG base, ULONG length)
+VOID ReadFlash (PADAPTER2220I padapter, VOID *pdata, ULONG base, ULONG length)
{
ULONG oldremap;
UCHAR olddesc;
ULONG z;
UCHAR *pd = (UCHAR *)pdata;
- oldremap = inl (hostdata->regRemap); // save values to restore later
- olddesc = inb_p (hostdata->regDesc);
+ oldremap = inl (padapter->regRemap); // save values to restore later
+ olddesc = inb_p (padapter->regDesc);
- outl (base | 1, hostdata->regRemap); // remap to Flash space as specified
- outb_p (0x40, hostdata->regDesc); // describe remap region as 8 bit
+ outl (base | 1, padapter->regRemap); // remap to Flash space as specified
+ outb_p (0x40, padapter->regDesc); // describe remap region as 8 bit
for ( z = 0; z < length; z++) // get "length" data count
- *pd++ = inb_p (hostdata->regBase + z); // read in the data
+ *pd++ = inb_p (padapter->regBase + z); // read in the data
- outl (oldremap, hostdata->regRemap); // restore remap register values
- outb_p (olddesc, hostdata->regDesc);
+ outl (oldremap, padapter->regRemap); // restore remap register values
+ outb_p (olddesc, padapter->regDesc);
}
-
/****************************************************************
* Name: Pci2220i_Detect
*
@@ -639,109 +1657,183 @@
****************************************************************/
int Pci2220i_Detect (Scsi_Host_Template *tpnt)
{
- struct pci_dev *pdev = NULL;
+ int pci_index = 0;
struct Scsi_Host *pshost;
- PADAPTER2220I hostdata;
- ULONG modearray[] = {DALE_DATA_MODE2, DALE_DATA_MODE3, DALE_DATA_MODE4, DALE_DATA_MODE4P};
+ PADAPTER2220I padapter;
int unit;
int z;
+ USHORT zs;
+ USHORT raidon = FALSE;
int setirq;
+ UCHAR spigot1 = FALSE;
+ UCHAR spigot2 = FALSE;
- if ( pci_present () )
- while ((pdev = pci_find_device(VENDOR_PSI, DEVICE_DALE_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_DALE_1, pci_index, &pci_bus, &pci_device_fn) != 0 )
+ break;
+
pshost = scsi_register (tpnt, sizeof(ADAPTER2220I));
- hostdata = HOSTDATA(pshost);
+ padapter = HOSTDATA(pshost);
+ memset (padapter, 0, sizeof (ADAPTER2220I));
- hostdata->basePort = pdev->base_address[1] & PCI_BASE_ADDRESS_IO_MASK;
- DEB (printk ("\nBase Regs = %#04X", hostdata->basePort));
- hostdata->regRemap = hostdata->basePort + RTR_LOCAL_REMAP; // 32 bit local space remap
- DEB (printk (" %#04X", hostdata->regRemap));
- hostdata->regDesc = hostdata->basePort + RTR_REGIONS; // 32 bit local region descriptor
- DEB (printk (" %#04X", hostdata->regDesc));
- hostdata->regRange = hostdata->basePort + RTR_LOCAL_RANGE; // 32 bit local range
- DEB (printk (" %#04X", hostdata->regRange));
- hostdata->regIrqControl = hostdata->basePort + RTR_INT_CONTROL_STATUS; // 16 bit interupt control and status
- DEB (printk (" %#04X", hostdata->regIrqControl));
- hostdata->regScratchPad = hostdata->basePort + RTR_MAILBOX; // 16 byte scratchpad I/O base address
- DEB (printk (" %#04X", hostdata->regScratchPad));
-
- hostdata->regBase = pdev->base_address[2] & PCI_BASE_ADDRESS_IO_MASK;
- for ( z = 0; z < 9; z++ ) // build regester address array
- hostdata->ports[z] = hostdata->regBase + 0x80 + (z * 4);
- hostdata->ports[PORT_FAIL] = hostdata->regBase + REG_FAIL;
- hostdata->ports[PORT_ALT_STAT] = hostdata->regBase + REG_ALT_STAT;
- DEB (printk ("\nPorts ="));
- DEB (for (z=0;z<11;z++) printk(" %#04X", hostdata->ports[z]););
-
- hostdata->regDmaDesc = hostdata->regBase + RTL_DMA1_DESC_PTR; // address of the DMA discriptor register for direction of transfer
- DEB (printk ("\nDMA Regs = %#04X", hostdata->regDmaDesc));
- hostdata->regDmaCmdStat = hostdata->regBase + RTL_DMA_COMMAND_STATUS + 1; // Byte #1 of DMA command status register
- DEB (printk (" %#04X", hostdata->regDmaCmdStat));
- hostdata->regDmaAddrPci = hostdata->regBase + RTL_DMA1_PCI_ADDR; // 32 bit register for PCI address of DMA
- DEB (printk (" %#04X", hostdata->regDmaAddrPci));
- hostdata->regDmaAddrLoc = hostdata->regBase + RTL_DMA1_LOCAL_ADDR; // 32 bit register for local bus address of DMA
- DEB (printk (" %#04X", hostdata->regDmaAddrLoc));
- hostdata->regDmaCount = hostdata->regBase + RTL_DMA1_COUNT; // 32 bit register for DMA transfer count
- DEB (printk (" %#04X", hostdata->regDmaCount));
- hostdata->regDmaMode = hostdata->regBase + RTL_DMA1_MODE + 1; // 32 bit register for DMA mode control
- DEB (printk (" %#04X", hostdata->regDmaMode));
+ 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 (hostdata->regScratchPad + DALE_NUM_DRIVES) ) // if no devices on this board
+ if ( !inb_p (padapter->regScratchPad + DALE_NUM_DRIVES) ) // if no devices on this board
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 < NumAdapters; 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, "pci2220i", NULL) )
+ if ( request_irq (pshost->irq, Irq_Handler, 0, "pci2220i", NULL) )
{
printk ("Unable to allocate IRQ for PSI-2220I controller.\n");
goto unregister;
}
}
- PsiHost[NumAdapters] = pshost; // save SCSI_HOST pointer
+ PsiHost[pci_index] = pshost; // save SCSI_HOST pointer
- pshost->unique_id = hostdata->regBase;
+ pshost->unique_id = padapter->regBase;
pshost->max_id = 4;
- outb_p (0x01, hostdata->regRange); // fix our range register because other drivers want to tromp on it
+ outb_p (0x01, padapter->regRange); // fix our range register because other drivers want to tromp on it
- hostdata->timingMode = inb_p (hostdata->regScratchPad + DALE_TIMING_MODE);
- hostdata->timingAddress = modearray[hostdata->timingMode - 2];
- ReadFlash (hostdata, &DaleSetup, DALE_FLASH_SETUP, sizeof (SETUP));
-
- for ( z = 0; z < inb_p (hostdata->regScratchPad + DALE_NUM_DRIVES); ++z )
- {
- unit = inb_p (hostdata->regScratchPad + DALE_CHANNEL_DEVICE_0 + z) & 0x0F;
- hostdata->device[unit].device = inb_p (hostdata->regScratchPad + DALE_SCRATH_DEVICE_0 + unit);
- hostdata->device[unit].byte6 = (UCHAR)(((unit & 1) << 4) | 0xE0);
- hostdata->device[unit].spigot = (UCHAR)(1 << (unit >> 1));
- hostdata->device[unit].sectors = DaleSetup.setupDevice[unit].sectors;
- hostdata->device[unit].heads = DaleSetup.setupDevice[unit].heads;
- hostdata->device[unit].cylinders = DaleSetup.setupDevice[unit].cylinders;
- hostdata->device[unit].blocks = DaleSetup.setupDevice[unit].blocks;
- DEB (printk ("\nHOSTDATA->device = %X", hostdata->device[unit].device));
- DEB (printk ("\n byte6 = %X", hostdata->device[unit].byte6));
- DEB (printk ("\n spigot = %X", hostdata->device[unit].spigot));
- DEB (printk ("\n sectors = %X", hostdata->device[unit].sectors));
- DEB (printk ("\n heads = %X", hostdata->device[unit].heads));
- DEB (printk ("\n cylinders = %X", hostdata->device[unit].cylinders));
- DEB (printk ("\n blocks = %lX", hostdata->device[unit].blocks));
- }
+ 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;
- printk("\nPSI-2220I EIDE CONTROLLER: at I/O = %X/%X IRQ = %d\n", hostdata->basePort, hostdata->regBase, pshost->irq);
- printk("(C) 1997 Perceptive Solutions, Inc. All rights reserved\n\n");
+ 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 ( !(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 && 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 )
+ {
+ 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;
+ }
+
+ 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++;
continue;
-unregister:
+unregister:;
scsi_unregister (pshost);
- NumAdapters++;
}
+ }
+
return NumAdapters;
}
/****************************************************************
@@ -756,7 +1848,6 @@
****************************************************************/
int Pci2220i_Abort (Scsi_Cmnd *SCpnt)
{
- DEB (printk ("pci2220i_abort\n"));
return SCSI_ABORT_SNOOZE;
}
/****************************************************************
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)