2005-04-16 15:20:36 -07:00
/*
Linux Driver for Mylex DAC960 / AcceleRAID / eXtremeRAID PCI RAID Controllers
Copyright 1998 - 2001 by Leonard N . Zubkoff < lnz @ dandelion . com >
2005-05-05 16:15:58 -07:00
Portions Copyright 2002 by Mylex ( An IBM Business Unit )
2005-04-16 15:20:36 -07:00
This program is free software ; you may redistribute and / or modify it under
the terms of the GNU General Public License Version 2 as published by the
Free Software Foundation .
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 complete details .
*/
# define DAC960_DriverVersion "2.5.47"
# define DAC960_DriverDate "14 November 2002"
# include <linux/module.h>
# include <linux/types.h>
# include <linux/miscdevice.h>
# include <linux/blkdev.h>
# include <linux/bio.h>
# include <linux/completion.h>
# include <linux/delay.h>
# include <linux/genhd.h>
# include <linux/hdreg.h>
# include <linux/blkpg.h>
# include <linux/interrupt.h>
# include <linux/ioport.h>
# include <linux/mm.h>
# include <linux/slab.h>
# include <linux/proc_fs.h>
# include <linux/reboot.h>
# include <linux/spinlock.h>
# include <linux/timer.h>
# include <linux/pci.h>
# include <linux/init.h>
# include <asm/io.h>
# include <asm/uaccess.h>
# include "DAC960.h"
# define DAC960_GAM_MINOR 252
static DAC960_Controller_T * DAC960_Controllers [ DAC960_MaxControllers ] ;
static int DAC960_ControllerCount ;
static struct proc_dir_entry * DAC960_ProcDirectoryEntry ;
static long disk_size ( DAC960_Controller_T * p , int drive_nr )
{
if ( p - > FirmwareType = = DAC960_V1_Controller ) {
if ( drive_nr > = p - > LogicalDriveCount )
return 0 ;
return p - > V1 . LogicalDriveInformation [ drive_nr ] .
LogicalDriveSize ;
} else {
DAC960_V2_LogicalDeviceInfo_T * i =
p - > V2 . LogicalDeviceInformation [ drive_nr ] ;
if ( i = = NULL )
return 0 ;
return i - > ConfigurableDeviceSize ;
}
}
static int DAC960_open ( struct inode * inode , struct file * file )
{
struct gendisk * disk = inode - > i_bdev - > bd_disk ;
DAC960_Controller_T * p = disk - > queue - > queuedata ;
int drive_nr = ( long ) disk - > private_data ;
if ( p - > FirmwareType = = DAC960_V1_Controller ) {
if ( p - > V1 . LogicalDriveInformation [ drive_nr ] .
LogicalDriveState = = DAC960_V1_LogicalDrive_Offline )
return - ENXIO ;
} else {
DAC960_V2_LogicalDeviceInfo_T * i =
p - > V2 . LogicalDeviceInformation [ drive_nr ] ;
if ( ! i | | i - > LogicalDeviceState = = DAC960_V2_LogicalDevice_Offline )
return - ENXIO ;
}
check_disk_change ( inode - > i_bdev ) ;
if ( ! get_capacity ( p - > disks [ drive_nr ] ) )
return - ENXIO ;
return 0 ;
}
static int DAC960_ioctl ( struct inode * inode , struct file * file ,
unsigned int cmd , unsigned long arg )
{
struct gendisk * disk = inode - > i_bdev - > bd_disk ;
DAC960_Controller_T * p = disk - > queue - > queuedata ;
int drive_nr = ( long ) disk - > private_data ;
struct hd_geometry g ;
struct hd_geometry __user * loc = ( struct hd_geometry __user * ) arg ;
if ( cmd ! = HDIO_GETGEO | | ! loc )
return - EINVAL ;
if ( p - > FirmwareType = = DAC960_V1_Controller ) {
g . heads = p - > V1 . GeometryTranslationHeads ;
g . sectors = p - > V1 . GeometryTranslationSectors ;
g . cylinders = p - > V1 . LogicalDriveInformation [ drive_nr ] .
LogicalDriveSize / ( g . heads * g . sectors ) ;
} else {
DAC960_V2_LogicalDeviceInfo_T * i =
p - > V2 . LogicalDeviceInformation [ drive_nr ] ;
switch ( i - > DriveGeometry ) {
case DAC960_V2_Geometry_128_32 :
g . heads = 128 ;
g . sectors = 32 ;
break ;
case DAC960_V2_Geometry_255_63 :
g . heads = 255 ;
g . sectors = 63 ;
break ;
default :
DAC960_Error ( " Illegal Logical Device Geometry %d \n " ,
p , i - > DriveGeometry ) ;
return - EINVAL ;
}
g . cylinders = i - > ConfigurableDeviceSize / ( g . heads * g . sectors ) ;
}
g . start = get_start_sect ( inode - > i_bdev ) ;
return copy_to_user ( loc , & g , sizeof g ) ? - EFAULT : 0 ;
}
static int DAC960_media_changed ( struct gendisk * disk )
{
DAC960_Controller_T * p = disk - > queue - > queuedata ;
int drive_nr = ( long ) disk - > private_data ;
if ( ! p - > LogicalDriveInitiallyAccessible [ drive_nr ] )
return 1 ;
return 0 ;
}
static int DAC960_revalidate_disk ( struct gendisk * disk )
{
DAC960_Controller_T * p = disk - > queue - > queuedata ;
int unit = ( long ) disk - > private_data ;
set_capacity ( disk , disk_size ( p , unit ) ) ;
return 0 ;
}
static struct block_device_operations DAC960_BlockDeviceOperations = {
. owner = THIS_MODULE ,
. open = DAC960_open ,
. ioctl = DAC960_ioctl ,
. media_changed = DAC960_media_changed ,
. revalidate_disk = DAC960_revalidate_disk ,
} ;
/*
DAC960_AnnounceDriver announces the Driver Version and Date , Author ' s Name ,
Copyright Notice , and Electronic Mail Address .
*/
static void DAC960_AnnounceDriver ( DAC960_Controller_T * Controller )
{
DAC960_Announce ( " ***** DAC960 RAID Driver Version "
DAC960_DriverVersion " of "
DAC960_DriverDate " ***** \n " , Controller ) ;
DAC960_Announce ( " Copyright 1998-2001 by Leonard N. Zubkoff "
" <lnz@dandelion.com> \n " , Controller ) ;
}
/*
DAC960_Failure prints a standardized error message , and then returns false .
*/
static boolean DAC960_Failure ( DAC960_Controller_T * Controller ,
unsigned char * ErrorMessage )
{
DAC960_Error ( " While configuring DAC960 PCI RAID Controller at \n " ,
Controller ) ;
if ( Controller - > IO_Address = = 0 )
DAC960_Error ( " PCI Bus %d Device %d Function %d I/O Address N/A "
" PCI Address 0x%X \n " , Controller ,
Controller - > Bus , Controller - > Device ,
Controller - > Function , Controller - > PCI_Address ) ;
else DAC960_Error ( " PCI Bus %d Device %d Function %d I/O Address "
" 0x%X PCI Address 0x%X \n " , Controller ,
Controller - > Bus , Controller - > Device ,
Controller - > Function , Controller - > IO_Address ,
Controller - > PCI_Address ) ;
DAC960_Error ( " %s FAILED - DETACHING \n " , Controller , ErrorMessage ) ;
return false ;
}
/*
init_dma_loaf ( ) and slice_dma_loaf ( ) are helper functions for
aggregating the dma - mapped memory for a well - known collection of
data structures that are of different lengths .
These routines don ' t guarantee any alignment . The caller must
include any space needed for alignment in the sizes of the structures
that are passed in .
*/
static boolean init_dma_loaf ( struct pci_dev * dev , struct dma_loaf * loaf ,
size_t len )
{
void * cpu_addr ;
dma_addr_t dma_handle ;
cpu_addr = pci_alloc_consistent ( dev , len , & dma_handle ) ;
if ( cpu_addr = = NULL )
return false ;
loaf - > cpu_free = loaf - > cpu_base = cpu_addr ;
loaf - > dma_free = loaf - > dma_base = dma_handle ;
loaf - > length = len ;
memset ( cpu_addr , 0 , len ) ;
return true ;
}
static void * slice_dma_loaf ( struct dma_loaf * loaf , size_t len ,
dma_addr_t * dma_handle )
{
void * cpu_end = loaf - > cpu_free + len ;
void * cpu_addr = loaf - > cpu_free ;
if ( cpu_end > loaf - > cpu_base + loaf - > length )
BUG ( ) ;
* dma_handle = loaf - > dma_free ;
loaf - > cpu_free = cpu_end ;
loaf - > dma_free + = len ;
return cpu_addr ;
}
static void free_dma_loaf ( struct pci_dev * dev , struct dma_loaf * loaf_handle )
{
if ( loaf_handle - > cpu_base ! = NULL )
pci_free_consistent ( dev , loaf_handle - > length ,
loaf_handle - > cpu_base , loaf_handle - > dma_base ) ;
}
/*
DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary
data structures for Controller . It returns true on success and false on
failure .
*/
static boolean DAC960_CreateAuxiliaryStructures ( DAC960_Controller_T * Controller )
{
int CommandAllocationLength , CommandAllocationGroupSize ;
int CommandsRemaining = 0 , CommandIdentifier , CommandGroupByteCount ;
void * AllocationPointer = NULL ;
void * ScatterGatherCPU = NULL ;
dma_addr_t ScatterGatherDMA ;
struct pci_pool * ScatterGatherPool ;
void * RequestSenseCPU = NULL ;
dma_addr_t RequestSenseDMA ;
struct pci_pool * RequestSensePool = NULL ;
if ( Controller - > FirmwareType = = DAC960_V1_Controller )
{
CommandAllocationLength = offsetof ( DAC960_Command_T , V1 . EndMarker ) ;
CommandAllocationGroupSize = DAC960_V1_CommandAllocationGroupSize ;
ScatterGatherPool = pci_pool_create ( " DAC960_V1_ScatterGather " ,
Controller - > PCIDevice ,
DAC960_V1_ScatterGatherLimit * sizeof ( DAC960_V1_ScatterGatherSegment_T ) ,
sizeof ( DAC960_V1_ScatterGatherSegment_T ) , 0 ) ;
if ( ScatterGatherPool = = NULL )
return DAC960_Failure ( Controller ,
" AUXILIARY STRUCTURE CREATION (SG) " ) ;
Controller - > ScatterGatherPool = ScatterGatherPool ;
}
else
{
CommandAllocationLength = offsetof ( DAC960_Command_T , V2 . EndMarker ) ;
CommandAllocationGroupSize = DAC960_V2_CommandAllocationGroupSize ;
ScatterGatherPool = pci_pool_create ( " DAC960_V2_ScatterGather " ,
Controller - > PCIDevice ,
DAC960_V2_ScatterGatherLimit * sizeof ( DAC960_V2_ScatterGatherSegment_T ) ,
sizeof ( DAC960_V2_ScatterGatherSegment_T ) , 0 ) ;
if ( ScatterGatherPool = = NULL )
return DAC960_Failure ( Controller ,
" AUXILIARY STRUCTURE CREATION (SG) " ) ;
RequestSensePool = pci_pool_create ( " DAC960_V2_RequestSense " ,
Controller - > PCIDevice , sizeof ( DAC960_SCSI_RequestSense_T ) ,
sizeof ( int ) , 0 ) ;
if ( RequestSensePool = = NULL ) {
pci_pool_destroy ( ScatterGatherPool ) ;
return DAC960_Failure ( Controller ,
" AUXILIARY STRUCTURE CREATION (SG) " ) ;
}
Controller - > ScatterGatherPool = ScatterGatherPool ;
Controller - > V2 . RequestSensePool = RequestSensePool ;
}
Controller - > CommandAllocationGroupSize = CommandAllocationGroupSize ;
Controller - > FreeCommands = NULL ;
for ( CommandIdentifier = 1 ;
CommandIdentifier < = Controller - > DriverQueueDepth ;
CommandIdentifier + + )
{
DAC960_Command_T * Command ;
if ( - - CommandsRemaining < = 0 )
{
CommandsRemaining =
Controller - > DriverQueueDepth - CommandIdentifier + 1 ;
if ( CommandsRemaining > CommandAllocationGroupSize )
CommandsRemaining = CommandAllocationGroupSize ;
CommandGroupByteCount =
CommandsRemaining * CommandAllocationLength ;
AllocationPointer = kmalloc ( CommandGroupByteCount , GFP_ATOMIC ) ;
if ( AllocationPointer = = NULL )
return DAC960_Failure ( Controller ,
" AUXILIARY STRUCTURE CREATION " ) ;
memset ( AllocationPointer , 0 , CommandGroupByteCount ) ;
}
Command = ( DAC960_Command_T * ) AllocationPointer ;
AllocationPointer + = CommandAllocationLength ;
Command - > CommandIdentifier = CommandIdentifier ;
Command - > Controller = Controller ;
Command - > Next = Controller - > FreeCommands ;
Controller - > FreeCommands = Command ;
Controller - > Commands [ CommandIdentifier - 1 ] = Command ;
ScatterGatherCPU = pci_pool_alloc ( ScatterGatherPool , SLAB_ATOMIC ,
& ScatterGatherDMA ) ;
if ( ScatterGatherCPU = = NULL )
return DAC960_Failure ( Controller , " AUXILIARY STRUCTURE CREATION " ) ;
if ( RequestSensePool ! = NULL ) {
RequestSenseCPU = pci_pool_alloc ( RequestSensePool , SLAB_ATOMIC ,
& RequestSenseDMA ) ;
if ( RequestSenseCPU = = NULL ) {
pci_pool_free ( ScatterGatherPool , ScatterGatherCPU ,
ScatterGatherDMA ) ;
return DAC960_Failure ( Controller ,
" AUXILIARY STRUCTURE CREATION " ) ;
}
}
if ( Controller - > FirmwareType = = DAC960_V1_Controller ) {
Command - > cmd_sglist = Command - > V1 . ScatterList ;
Command - > V1 . ScatterGatherList =
( DAC960_V1_ScatterGatherSegment_T * ) ScatterGatherCPU ;
Command - > V1 . ScatterGatherListDMA = ScatterGatherDMA ;
} else {
Command - > cmd_sglist = Command - > V2 . ScatterList ;
Command - > V2 . ScatterGatherList =
( DAC960_V2_ScatterGatherSegment_T * ) ScatterGatherCPU ;
Command - > V2 . ScatterGatherListDMA = ScatterGatherDMA ;
Command - > V2 . RequestSense =
( DAC960_SCSI_RequestSense_T * ) RequestSenseCPU ;
Command - > V2 . RequestSenseDMA = RequestSenseDMA ;
}
}
return true ;
}
/*
DAC960_DestroyAuxiliaryStructures deallocates the auxiliary data
structures for Controller .
*/
static void DAC960_DestroyAuxiliaryStructures ( DAC960_Controller_T * Controller )
{
int i ;
struct pci_pool * ScatterGatherPool = Controller - > ScatterGatherPool ;
struct pci_pool * RequestSensePool = NULL ;
void * ScatterGatherCPU ;
dma_addr_t ScatterGatherDMA ;
void * RequestSenseCPU ;
dma_addr_t RequestSenseDMA ;
DAC960_Command_T * CommandGroup = NULL ;
if ( Controller - > FirmwareType = = DAC960_V2_Controller )
RequestSensePool = Controller - > V2 . RequestSensePool ;
Controller - > FreeCommands = NULL ;
for ( i = 0 ; i < Controller - > DriverQueueDepth ; i + + )
{
DAC960_Command_T * Command = Controller - > Commands [ i ] ;
if ( Command = = NULL )
continue ;
if ( Controller - > FirmwareType = = DAC960_V1_Controller ) {
ScatterGatherCPU = ( void * ) Command - > V1 . ScatterGatherList ;
ScatterGatherDMA = Command - > V1 . ScatterGatherListDMA ;
RequestSenseCPU = NULL ;
RequestSenseDMA = ( dma_addr_t ) 0 ;
} else {
ScatterGatherCPU = ( void * ) Command - > V2 . ScatterGatherList ;
ScatterGatherDMA = Command - > V2 . ScatterGatherListDMA ;
RequestSenseCPU = ( void * ) Command - > V2 . RequestSense ;
RequestSenseDMA = Command - > V2 . RequestSenseDMA ;
}
if ( ScatterGatherCPU ! = NULL )
pci_pool_free ( ScatterGatherPool , ScatterGatherCPU , ScatterGatherDMA ) ;
if ( RequestSenseCPU ! = NULL )
pci_pool_free ( RequestSensePool , RequestSenseCPU , RequestSenseDMA ) ;
if ( ( Command - > CommandIdentifier
% Controller - > CommandAllocationGroupSize ) = = 1 ) {
/*
* We can ' t free the group of commands until all of the
* request sense and scatter gather dma structures are free .
* Remember the beginning of the group , but don ' t free it
* until we ' ve reached the beginning of the next group .
*/
if ( CommandGroup ! = NULL )
kfree ( CommandGroup ) ;
CommandGroup = Command ;
}
Controller - > Commands [ i ] = NULL ;
}
if ( CommandGroup ! = NULL )
kfree ( CommandGroup ) ;
if ( Controller - > CombinedStatusBuffer ! = NULL )
{
kfree ( Controller - > CombinedStatusBuffer ) ;
Controller - > CombinedStatusBuffer = NULL ;
Controller - > CurrentStatusBuffer = NULL ;
}
if ( ScatterGatherPool ! = NULL )
pci_pool_destroy ( ScatterGatherPool ) ;
if ( Controller - > FirmwareType = = DAC960_V1_Controller ) return ;
if ( RequestSensePool ! = NULL )
pci_pool_destroy ( RequestSensePool ) ;
for ( i = 0 ; i < DAC960_MaxLogicalDrives ; i + + )
if ( Controller - > V2 . LogicalDeviceInformation [ i ] ! = NULL )
{
kfree ( Controller - > V2 . LogicalDeviceInformation [ i ] ) ;
Controller - > V2 . LogicalDeviceInformation [ i ] = NULL ;
}
for ( i = 0 ; i < DAC960_V2_MaxPhysicalDevices ; i + + )
{
if ( Controller - > V2 . PhysicalDeviceInformation [ i ] ! = NULL )
{
kfree ( Controller - > V2 . PhysicalDeviceInformation [ i ] ) ;
Controller - > V2 . PhysicalDeviceInformation [ i ] = NULL ;
}
if ( Controller - > V2 . InquiryUnitSerialNumber [ i ] ! = NULL )
{
kfree ( Controller - > V2 . InquiryUnitSerialNumber [ i ] ) ;
Controller - > V2 . InquiryUnitSerialNumber [ i ] = NULL ;
}
}
}
/*
DAC960_V1_ClearCommand clears critical fields of Command for DAC960 V1
Firmware Controllers .
*/
static inline void DAC960_V1_ClearCommand ( DAC960_Command_T * Command )
{
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
memset ( CommandMailbox , 0 , sizeof ( DAC960_V1_CommandMailbox_T ) ) ;
Command - > V1 . CommandStatus = 0 ;
}
/*
DAC960_V2_ClearCommand clears critical fields of Command for DAC960 V2
Firmware Controllers .
*/
static inline void DAC960_V2_ClearCommand ( DAC960_Command_T * Command )
{
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
memset ( CommandMailbox , 0 , sizeof ( DAC960_V2_CommandMailbox_T ) ) ;
Command - > V2 . CommandStatus = 0 ;
}
/*
DAC960_AllocateCommand allocates a Command structure from Controller ' s
free list . During driver initialization , a special initialization command
has been placed on the free list to guarantee that command allocation can
never fail .
*/
static inline DAC960_Command_T * DAC960_AllocateCommand ( DAC960_Controller_T
* Controller )
{
DAC960_Command_T * Command = Controller - > FreeCommands ;
if ( Command = = NULL ) return NULL ;
Controller - > FreeCommands = Command - > Next ;
Command - > Next = NULL ;
return Command ;
}
/*
DAC960_DeallocateCommand deallocates Command , returning it to Controller ' s
free list .
*/
static inline void DAC960_DeallocateCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
Command - > Request = NULL ;
Command - > Next = Controller - > FreeCommands ;
Controller - > FreeCommands = Command ;
}
/*
DAC960_WaitForCommand waits for a wake_up on Controller ' s Command Wait Queue .
*/
static void DAC960_WaitForCommand ( DAC960_Controller_T * Controller )
{
spin_unlock_irq ( & Controller - > queue_lock ) ;
__wait_event ( Controller - > CommandWaitQueue , Controller - > FreeCommands ) ;
spin_lock_irq ( & Controller - > queue_lock ) ;
}
2005-05-05 16:15:58 -07:00
/*
DAC960_GEM_QueueCommand queues Command for DAC960 GEM Series Controllers .
*/
static void DAC960_GEM_QueueCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_CommandMailbox_T * NextCommandMailbox =
Controller - > V2 . NextCommandMailbox ;
CommandMailbox - > Common . CommandIdentifier = Command - > CommandIdentifier ;
DAC960_GEM_WriteCommandMailbox ( NextCommandMailbox , CommandMailbox ) ;
if ( Controller - > V2 . PreviousCommandMailbox1 - > Words [ 0 ] = = 0 | |
Controller - > V2 . PreviousCommandMailbox2 - > Words [ 0 ] = = 0 )
DAC960_GEM_MemoryMailboxNewCommand ( ControllerBaseAddress ) ;
Controller - > V2 . PreviousCommandMailbox2 =
Controller - > V2 . PreviousCommandMailbox1 ;
Controller - > V2 . PreviousCommandMailbox1 = NextCommandMailbox ;
if ( + + NextCommandMailbox > Controller - > V2 . LastCommandMailbox )
NextCommandMailbox = Controller - > V2 . FirstCommandMailbox ;
Controller - > V2 . NextCommandMailbox = NextCommandMailbox ;
}
2005-04-16 15:20:36 -07:00
/*
DAC960_BA_QueueCommand queues Command for DAC960 BA Series Controllers .
*/
static void DAC960_BA_QueueCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_CommandMailbox_T * NextCommandMailbox =
Controller - > V2 . NextCommandMailbox ;
CommandMailbox - > Common . CommandIdentifier = Command - > CommandIdentifier ;
DAC960_BA_WriteCommandMailbox ( NextCommandMailbox , CommandMailbox ) ;
if ( Controller - > V2 . PreviousCommandMailbox1 - > Words [ 0 ] = = 0 | |
Controller - > V2 . PreviousCommandMailbox2 - > Words [ 0 ] = = 0 )
DAC960_BA_MemoryMailboxNewCommand ( ControllerBaseAddress ) ;
Controller - > V2 . PreviousCommandMailbox2 =
Controller - > V2 . PreviousCommandMailbox1 ;
Controller - > V2 . PreviousCommandMailbox1 = NextCommandMailbox ;
if ( + + NextCommandMailbox > Controller - > V2 . LastCommandMailbox )
NextCommandMailbox = Controller - > V2 . FirstCommandMailbox ;
Controller - > V2 . NextCommandMailbox = NextCommandMailbox ;
}
/*
DAC960_LP_QueueCommand queues Command for DAC960 LP Series Controllers .
*/
static void DAC960_LP_QueueCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_CommandMailbox_T * NextCommandMailbox =
Controller - > V2 . NextCommandMailbox ;
CommandMailbox - > Common . CommandIdentifier = Command - > CommandIdentifier ;
DAC960_LP_WriteCommandMailbox ( NextCommandMailbox , CommandMailbox ) ;
if ( Controller - > V2 . PreviousCommandMailbox1 - > Words [ 0 ] = = 0 | |
Controller - > V2 . PreviousCommandMailbox2 - > Words [ 0 ] = = 0 )
DAC960_LP_MemoryMailboxNewCommand ( ControllerBaseAddress ) ;
Controller - > V2 . PreviousCommandMailbox2 =
Controller - > V2 . PreviousCommandMailbox1 ;
Controller - > V2 . PreviousCommandMailbox1 = NextCommandMailbox ;
if ( + + NextCommandMailbox > Controller - > V2 . LastCommandMailbox )
NextCommandMailbox = Controller - > V2 . FirstCommandMailbox ;
Controller - > V2 . NextCommandMailbox = NextCommandMailbox ;
}
/*
DAC960_LA_QueueCommandDualMode queues Command for DAC960 LA Series
Controllers with Dual Mode Firmware .
*/
static void DAC960_LA_QueueCommandDualMode ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
DAC960_V1_CommandMailbox_T * NextCommandMailbox =
Controller - > V1 . NextCommandMailbox ;
CommandMailbox - > Common . CommandIdentifier = Command - > CommandIdentifier ;
DAC960_LA_WriteCommandMailbox ( NextCommandMailbox , CommandMailbox ) ;
if ( Controller - > V1 . PreviousCommandMailbox1 - > Words [ 0 ] = = 0 | |
Controller - > V1 . PreviousCommandMailbox2 - > Words [ 0 ] = = 0 )
DAC960_LA_MemoryMailboxNewCommand ( ControllerBaseAddress ) ;
Controller - > V1 . PreviousCommandMailbox2 =
Controller - > V1 . PreviousCommandMailbox1 ;
Controller - > V1 . PreviousCommandMailbox1 = NextCommandMailbox ;
if ( + + NextCommandMailbox > Controller - > V1 . LastCommandMailbox )
NextCommandMailbox = Controller - > V1 . FirstCommandMailbox ;
Controller - > V1 . NextCommandMailbox = NextCommandMailbox ;
}
/*
DAC960_LA_QueueCommandSingleMode queues Command for DAC960 LA Series
Controllers with Single Mode Firmware .
*/
static void DAC960_LA_QueueCommandSingleMode ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
DAC960_V1_CommandMailbox_T * NextCommandMailbox =
Controller - > V1 . NextCommandMailbox ;
CommandMailbox - > Common . CommandIdentifier = Command - > CommandIdentifier ;
DAC960_LA_WriteCommandMailbox ( NextCommandMailbox , CommandMailbox ) ;
if ( Controller - > V1 . PreviousCommandMailbox1 - > Words [ 0 ] = = 0 | |
Controller - > V1 . PreviousCommandMailbox2 - > Words [ 0 ] = = 0 )
DAC960_LA_HardwareMailboxNewCommand ( ControllerBaseAddress ) ;
Controller - > V1 . PreviousCommandMailbox2 =
Controller - > V1 . PreviousCommandMailbox1 ;
Controller - > V1 . PreviousCommandMailbox1 = NextCommandMailbox ;
if ( + + NextCommandMailbox > Controller - > V1 . LastCommandMailbox )
NextCommandMailbox = Controller - > V1 . FirstCommandMailbox ;
Controller - > V1 . NextCommandMailbox = NextCommandMailbox ;
}
/*
DAC960_PG_QueueCommandDualMode queues Command for DAC960 PG Series
Controllers with Dual Mode Firmware .
*/
static void DAC960_PG_QueueCommandDualMode ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
DAC960_V1_CommandMailbox_T * NextCommandMailbox =
Controller - > V1 . NextCommandMailbox ;
CommandMailbox - > Common . CommandIdentifier = Command - > CommandIdentifier ;
DAC960_PG_WriteCommandMailbox ( NextCommandMailbox , CommandMailbox ) ;
if ( Controller - > V1 . PreviousCommandMailbox1 - > Words [ 0 ] = = 0 | |
Controller - > V1 . PreviousCommandMailbox2 - > Words [ 0 ] = = 0 )
DAC960_PG_MemoryMailboxNewCommand ( ControllerBaseAddress ) ;
Controller - > V1 . PreviousCommandMailbox2 =
Controller - > V1 . PreviousCommandMailbox1 ;
Controller - > V1 . PreviousCommandMailbox1 = NextCommandMailbox ;
if ( + + NextCommandMailbox > Controller - > V1 . LastCommandMailbox )
NextCommandMailbox = Controller - > V1 . FirstCommandMailbox ;
Controller - > V1 . NextCommandMailbox = NextCommandMailbox ;
}
/*
DAC960_PG_QueueCommandSingleMode queues Command for DAC960 PG Series
Controllers with Single Mode Firmware .
*/
static void DAC960_PG_QueueCommandSingleMode ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
DAC960_V1_CommandMailbox_T * NextCommandMailbox =
Controller - > V1 . NextCommandMailbox ;
CommandMailbox - > Common . CommandIdentifier = Command - > CommandIdentifier ;
DAC960_PG_WriteCommandMailbox ( NextCommandMailbox , CommandMailbox ) ;
if ( Controller - > V1 . PreviousCommandMailbox1 - > Words [ 0 ] = = 0 | |
Controller - > V1 . PreviousCommandMailbox2 - > Words [ 0 ] = = 0 )
DAC960_PG_HardwareMailboxNewCommand ( ControllerBaseAddress ) ;
Controller - > V1 . PreviousCommandMailbox2 =
Controller - > V1 . PreviousCommandMailbox1 ;
Controller - > V1 . PreviousCommandMailbox1 = NextCommandMailbox ;
if ( + + NextCommandMailbox > Controller - > V1 . LastCommandMailbox )
NextCommandMailbox = Controller - > V1 . FirstCommandMailbox ;
Controller - > V1 . NextCommandMailbox = NextCommandMailbox ;
}
/*
DAC960_PD_QueueCommand queues Command for DAC960 PD Series Controllers .
*/
static void DAC960_PD_QueueCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
CommandMailbox - > Common . CommandIdentifier = Command - > CommandIdentifier ;
while ( DAC960_PD_MailboxFullP ( ControllerBaseAddress ) )
udelay ( 1 ) ;
DAC960_PD_WriteCommandMailbox ( ControllerBaseAddress , CommandMailbox ) ;
DAC960_PD_NewCommand ( ControllerBaseAddress ) ;
}
/*
DAC960_P_QueueCommand queues Command for DAC960 P Series Controllers .
*/
static void DAC960_P_QueueCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
CommandMailbox - > Common . CommandIdentifier = Command - > CommandIdentifier ;
switch ( CommandMailbox - > Common . CommandOpcode )
{
case DAC960_V1_Enquiry :
CommandMailbox - > Common . CommandOpcode = DAC960_V1_Enquiry_Old ;
break ;
case DAC960_V1_GetDeviceState :
CommandMailbox - > Common . CommandOpcode = DAC960_V1_GetDeviceState_Old ;
break ;
case DAC960_V1_Read :
CommandMailbox - > Common . CommandOpcode = DAC960_V1_Read_Old ;
DAC960_PD_To_P_TranslateReadWriteCommand ( CommandMailbox ) ;
break ;
case DAC960_V1_Write :
CommandMailbox - > Common . CommandOpcode = DAC960_V1_Write_Old ;
DAC960_PD_To_P_TranslateReadWriteCommand ( CommandMailbox ) ;
break ;
case DAC960_V1_ReadWithScatterGather :
CommandMailbox - > Common . CommandOpcode =
DAC960_V1_ReadWithScatterGather_Old ;
DAC960_PD_To_P_TranslateReadWriteCommand ( CommandMailbox ) ;
break ;
case DAC960_V1_WriteWithScatterGather :
CommandMailbox - > Common . CommandOpcode =
DAC960_V1_WriteWithScatterGather_Old ;
DAC960_PD_To_P_TranslateReadWriteCommand ( CommandMailbox ) ;
break ;
default :
break ;
}
while ( DAC960_PD_MailboxFullP ( ControllerBaseAddress ) )
udelay ( 1 ) ;
DAC960_PD_WriteCommandMailbox ( ControllerBaseAddress , CommandMailbox ) ;
DAC960_PD_NewCommand ( ControllerBaseAddress ) ;
}
/*
DAC960_ExecuteCommand executes Command and waits for completion .
*/
static void DAC960_ExecuteCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
DECLARE_COMPLETION ( Completion ) ;
unsigned long flags ;
Command - > Completion = & Completion ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_QueueCommand ( Command ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
if ( in_interrupt ( ) )
return ;
wait_for_completion ( & Completion ) ;
}
/*
DAC960_V1_ExecuteType3 executes a DAC960 V1 Firmware Controller Type 3
Command and waits for completion . It returns true on success and false
on failure .
*/
static boolean DAC960_V1_ExecuteType3 ( DAC960_Controller_T * Controller ,
DAC960_V1_CommandOpcode_T CommandOpcode ,
dma_addr_t DataDMA )
{
DAC960_Command_T * Command = DAC960_AllocateCommand ( Controller ) ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
DAC960_V1_CommandStatus_T CommandStatus ;
DAC960_V1_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox - > Type3 . CommandOpcode = CommandOpcode ;
CommandMailbox - > Type3 . BusAddress = DataDMA ;
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V1 . CommandStatus ;
DAC960_DeallocateCommand ( Command ) ;
return ( CommandStatus = = DAC960_V1_NormalCompletion ) ;
}
/*
DAC960_V1_ExecuteTypeB executes a DAC960 V1 Firmware Controller Type 3 B
Command and waits for completion . It returns true on success and false
on failure .
*/
static boolean DAC960_V1_ExecuteType3B ( DAC960_Controller_T * Controller ,
DAC960_V1_CommandOpcode_T CommandOpcode ,
unsigned char CommandOpcode2 ,
dma_addr_t DataDMA )
{
DAC960_Command_T * Command = DAC960_AllocateCommand ( Controller ) ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
DAC960_V1_CommandStatus_T CommandStatus ;
DAC960_V1_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox - > Type3B . CommandOpcode = CommandOpcode ;
CommandMailbox - > Type3B . CommandOpcode2 = CommandOpcode2 ;
CommandMailbox - > Type3B . BusAddress = DataDMA ;
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V1 . CommandStatus ;
DAC960_DeallocateCommand ( Command ) ;
return ( CommandStatus = = DAC960_V1_NormalCompletion ) ;
}
/*
DAC960_V1_ExecuteType3D executes a DAC960 V1 Firmware Controller Type 3 D
Command and waits for completion . It returns true on success and false
on failure .
*/
static boolean DAC960_V1_ExecuteType3D ( DAC960_Controller_T * Controller ,
DAC960_V1_CommandOpcode_T CommandOpcode ,
unsigned char Channel ,
unsigned char TargetID ,
dma_addr_t DataDMA )
{
DAC960_Command_T * Command = DAC960_AllocateCommand ( Controller ) ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
DAC960_V1_CommandStatus_T CommandStatus ;
DAC960_V1_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox - > Type3D . CommandOpcode = CommandOpcode ;
CommandMailbox - > Type3D . Channel = Channel ;
CommandMailbox - > Type3D . TargetID = TargetID ;
CommandMailbox - > Type3D . BusAddress = DataDMA ;
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V1 . CommandStatus ;
DAC960_DeallocateCommand ( Command ) ;
return ( CommandStatus = = DAC960_V1_NormalCompletion ) ;
}
/*
DAC960_V2_GeneralInfo executes a DAC960 V2 Firmware General Information
Reading IOCTL Command and waits for completion . It returns true on success
and false on failure .
Return data in The controller ' s HealthStatusBuffer , which is dma - able memory
*/
static boolean DAC960_V2_GeneralInfo ( DAC960_Controller_T * Controller )
{
DAC960_Command_T * Command = DAC960_AllocateCommand ( Controller ) ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_CommandStatus_T CommandStatus ;
DAC960_V2_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox - > Common . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > Common . CommandControlBits
. DataTransferControllerToHost = true ;
CommandMailbox - > Common . CommandControlBits
. NoAutoRequestSense = true ;
CommandMailbox - > Common . DataTransferSize = sizeof ( DAC960_V2_HealthStatusBuffer_T ) ;
CommandMailbox - > Common . IOCTL_Opcode = DAC960_V2_GetHealthStatus ;
CommandMailbox - > Common . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . HealthStatusBufferDMA ;
CommandMailbox - > Common . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > Common . DataTransferSize ;
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V2 . CommandStatus ;
DAC960_DeallocateCommand ( Command ) ;
return ( CommandStatus = = DAC960_V2_NormalCompletion ) ;
}
/*
DAC960_V2_ControllerInfo executes a DAC960 V2 Firmware Controller
Information Reading IOCTL Command and waits for completion . It returns
true on success and false on failure .
Data is returned in the controller ' s V2 . NewControllerInformation dma - able
memory buffer .
*/
static boolean DAC960_V2_NewControllerInfo ( DAC960_Controller_T * Controller )
{
DAC960_Command_T * Command = DAC960_AllocateCommand ( Controller ) ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_CommandStatus_T CommandStatus ;
DAC960_V2_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox - > ControllerInfo . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > ControllerInfo . CommandControlBits
. DataTransferControllerToHost = true ;
CommandMailbox - > ControllerInfo . CommandControlBits
. NoAutoRequestSense = true ;
CommandMailbox - > ControllerInfo . DataTransferSize = sizeof ( DAC960_V2_ControllerInfo_T ) ;
CommandMailbox - > ControllerInfo . ControllerNumber = 0 ;
CommandMailbox - > ControllerInfo . IOCTL_Opcode = DAC960_V2_GetControllerInfo ;
CommandMailbox - > ControllerInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . NewControllerInformationDMA ;
CommandMailbox - > ControllerInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > ControllerInfo . DataTransferSize ;
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V2 . CommandStatus ;
DAC960_DeallocateCommand ( Command ) ;
return ( CommandStatus = = DAC960_V2_NormalCompletion ) ;
}
/*
DAC960_V2_LogicalDeviceInfo executes a DAC960 V2 Firmware Controller Logical
Device Information Reading IOCTL Command and waits for completion . It
returns true on success and false on failure .
Data is returned in the controller ' s V2 . NewLogicalDeviceInformation
*/
static boolean DAC960_V2_NewLogicalDeviceInfo ( DAC960_Controller_T * Controller ,
unsigned short LogicalDeviceNumber )
{
DAC960_Command_T * Command = DAC960_AllocateCommand ( Controller ) ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_CommandStatus_T CommandStatus ;
DAC960_V2_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox - > LogicalDeviceInfo . CommandOpcode =
DAC960_V2_IOCTL ;
CommandMailbox - > LogicalDeviceInfo . CommandControlBits
. DataTransferControllerToHost = true ;
CommandMailbox - > LogicalDeviceInfo . CommandControlBits
. NoAutoRequestSense = true ;
CommandMailbox - > LogicalDeviceInfo . DataTransferSize =
sizeof ( DAC960_V2_LogicalDeviceInfo_T ) ;
CommandMailbox - > LogicalDeviceInfo . LogicalDevice . LogicalDeviceNumber =
LogicalDeviceNumber ;
CommandMailbox - > LogicalDeviceInfo . IOCTL_Opcode = DAC960_V2_GetLogicalDeviceInfoValid ;
CommandMailbox - > LogicalDeviceInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . NewLogicalDeviceInformationDMA ;
CommandMailbox - > LogicalDeviceInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > LogicalDeviceInfo . DataTransferSize ;
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V2 . CommandStatus ;
DAC960_DeallocateCommand ( Command ) ;
return ( CommandStatus = = DAC960_V2_NormalCompletion ) ;
}
/*
DAC960_V2_PhysicalDeviceInfo executes a DAC960 V2 Firmware Controller " Read
Physical Device Information " IOCTL Command and waits for completion. It
returns true on success and false on failure .
The Channel , TargetID , LogicalUnit arguments should be 0 the first time
this function is called for a given controller . This will return data
for the " first " device on that controller . The returned data includes a
Channel , TargetID , LogicalUnit that can be passed in to this routine to
get data for the NEXT device on that controller .
Data is stored in the controller ' s V2 . NewPhysicalDeviceInfo dma - able
memory buffer .
*/
static boolean DAC960_V2_NewPhysicalDeviceInfo ( DAC960_Controller_T * Controller ,
unsigned char Channel ,
unsigned char TargetID ,
unsigned char LogicalUnit )
{
DAC960_Command_T * Command = DAC960_AllocateCommand ( Controller ) ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_CommandStatus_T CommandStatus ;
DAC960_V2_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox - > PhysicalDeviceInfo . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > PhysicalDeviceInfo . CommandControlBits
. DataTransferControllerToHost = true ;
CommandMailbox - > PhysicalDeviceInfo . CommandControlBits
. NoAutoRequestSense = true ;
CommandMailbox - > PhysicalDeviceInfo . DataTransferSize =
sizeof ( DAC960_V2_PhysicalDeviceInfo_T ) ;
CommandMailbox - > PhysicalDeviceInfo . PhysicalDevice . LogicalUnit = LogicalUnit ;
CommandMailbox - > PhysicalDeviceInfo . PhysicalDevice . TargetID = TargetID ;
CommandMailbox - > PhysicalDeviceInfo . PhysicalDevice . Channel = Channel ;
CommandMailbox - > PhysicalDeviceInfo . IOCTL_Opcode =
DAC960_V2_GetPhysicalDeviceInfoValid ;
CommandMailbox - > PhysicalDeviceInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . NewPhysicalDeviceInformationDMA ;
CommandMailbox - > PhysicalDeviceInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > PhysicalDeviceInfo . DataTransferSize ;
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V2 . CommandStatus ;
DAC960_DeallocateCommand ( Command ) ;
return ( CommandStatus = = DAC960_V2_NormalCompletion ) ;
}
static void DAC960_V2_ConstructNewUnitSerialNumber (
DAC960_Controller_T * Controller ,
DAC960_V2_CommandMailbox_T * CommandMailbox , int Channel , int TargetID ,
int LogicalUnit )
{
CommandMailbox - > SCSI_10 . CommandOpcode = DAC960_V2_SCSI_10_Passthru ;
CommandMailbox - > SCSI_10 . CommandControlBits
. DataTransferControllerToHost = true ;
CommandMailbox - > SCSI_10 . CommandControlBits
. NoAutoRequestSense = true ;
CommandMailbox - > SCSI_10 . DataTransferSize =
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ;
CommandMailbox - > SCSI_10 . PhysicalDevice . LogicalUnit = LogicalUnit ;
CommandMailbox - > SCSI_10 . PhysicalDevice . TargetID = TargetID ;
CommandMailbox - > SCSI_10 . PhysicalDevice . Channel = Channel ;
CommandMailbox - > SCSI_10 . CDBLength = 6 ;
CommandMailbox - > SCSI_10 . SCSI_CDB [ 0 ] = 0x12 ; /* INQUIRY */
CommandMailbox - > SCSI_10 . SCSI_CDB [ 1 ] = 1 ; /* EVPD = 1 */
CommandMailbox - > SCSI_10 . SCSI_CDB [ 2 ] = 0x80 ; /* Page Code */
CommandMailbox - > SCSI_10 . SCSI_CDB [ 3 ] = 0 ; /* Reserved */
CommandMailbox - > SCSI_10 . SCSI_CDB [ 4 ] =
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ;
CommandMailbox - > SCSI_10 . SCSI_CDB [ 5 ] = 0 ; /* Control */
CommandMailbox - > SCSI_10 . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . NewInquiryUnitSerialNumberDMA ;
CommandMailbox - > SCSI_10 . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > SCSI_10 . DataTransferSize ;
}
/*
DAC960_V2_NewUnitSerialNumber executes an SCSI pass - through
Inquiry command to a SCSI device identified by Channel number ,
Target id , Logical Unit Number . This function Waits for completion
of the command .
The return data includes Unit Serial Number information for the
specified device .
Data is stored in the controller ' s V2 . NewPhysicalDeviceInfo dma - able
memory buffer .
*/
static boolean DAC960_V2_NewInquiryUnitSerialNumber ( DAC960_Controller_T * Controller ,
int Channel , int TargetID , int LogicalUnit )
{
DAC960_Command_T * Command ;
DAC960_V2_CommandMailbox_T * CommandMailbox ;
DAC960_V2_CommandStatus_T CommandStatus ;
Command = DAC960_AllocateCommand ( Controller ) ;
CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
DAC960_V2_ConstructNewUnitSerialNumber ( Controller , CommandMailbox ,
Channel , TargetID , LogicalUnit ) ;
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V2 . CommandStatus ;
DAC960_DeallocateCommand ( Command ) ;
return ( CommandStatus = = DAC960_V2_NormalCompletion ) ;
}
/*
DAC960_V2_DeviceOperation executes a DAC960 V2 Firmware Controller Device
Operation IOCTL Command and waits for completion . It returns true on
success and false on failure .
*/
static boolean DAC960_V2_DeviceOperation ( DAC960_Controller_T * Controller ,
DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode ,
DAC960_V2_OperationDevice_T
OperationDevice )
{
DAC960_Command_T * Command = DAC960_AllocateCommand ( Controller ) ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_CommandStatus_T CommandStatus ;
DAC960_V2_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox - > DeviceOperation . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > DeviceOperation . CommandControlBits
. DataTransferControllerToHost = true ;
CommandMailbox - > DeviceOperation . CommandControlBits
. NoAutoRequestSense = true ;
CommandMailbox - > DeviceOperation . IOCTL_Opcode = IOCTL_Opcode ;
CommandMailbox - > DeviceOperation . OperationDevice = OperationDevice ;
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V2 . CommandStatus ;
DAC960_DeallocateCommand ( Command ) ;
return ( CommandStatus = = DAC960_V2_NormalCompletion ) ;
}
/*
DAC960_V1_EnableMemoryMailboxInterface enables the Memory Mailbox Interface
for DAC960 V1 Firmware Controllers .
PD and P controller types have no memory mailbox , but still need the
other dma mapped memory .
*/
static boolean DAC960_V1_EnableMemoryMailboxInterface ( DAC960_Controller_T
* Controller )
{
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_HardwareType_T hw_type = Controller - > HardwareType ;
struct pci_dev * PCI_Device = Controller - > PCIDevice ;
struct dma_loaf * DmaPages = & Controller - > DmaPages ;
size_t DmaPagesSize ;
size_t CommandMailboxesSize ;
size_t StatusMailboxesSize ;
DAC960_V1_CommandMailbox_T * CommandMailboxesMemory ;
dma_addr_t CommandMailboxesMemoryDMA ;
DAC960_V1_StatusMailbox_T * StatusMailboxesMemory ;
dma_addr_t StatusMailboxesMemoryDMA ;
DAC960_V1_CommandMailbox_T CommandMailbox ;
DAC960_V1_CommandStatus_T CommandStatus ;
int TimeoutCounter ;
int i ;
if ( pci_set_dma_mask ( Controller - > PCIDevice , DAC690_V1_PciDmaMask ) )
return DAC960_Failure ( Controller , " DMA mask out of range " ) ;
Controller - > BounceBufferLimit = DAC690_V1_PciDmaMask ;
if ( ( hw_type = = DAC960_PD_Controller ) | | ( hw_type = = DAC960_P_Controller ) ) {
CommandMailboxesSize = 0 ;
StatusMailboxesSize = 0 ;
} else {
CommandMailboxesSize = DAC960_V1_CommandMailboxCount * sizeof ( DAC960_V1_CommandMailbox_T ) ;
StatusMailboxesSize = DAC960_V1_StatusMailboxCount * sizeof ( DAC960_V1_StatusMailbox_T ) ;
}
DmaPagesSize = CommandMailboxesSize + StatusMailboxesSize +
sizeof ( DAC960_V1_DCDB_T ) + sizeof ( DAC960_V1_Enquiry_T ) +
sizeof ( DAC960_V1_ErrorTable_T ) + sizeof ( DAC960_V1_EventLogEntry_T ) +
sizeof ( DAC960_V1_RebuildProgress_T ) +
sizeof ( DAC960_V1_LogicalDriveInformationArray_T ) +
sizeof ( DAC960_V1_BackgroundInitializationStatus_T ) +
sizeof ( DAC960_V1_DeviceState_T ) + sizeof ( DAC960_SCSI_Inquiry_T ) +
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ;
if ( ! init_dma_loaf ( PCI_Device , DmaPages , DmaPagesSize ) )
return false ;
if ( ( hw_type = = DAC960_PD_Controller ) | | ( hw_type = = DAC960_P_Controller ) )
goto skip_mailboxes ;
CommandMailboxesMemory = slice_dma_loaf ( DmaPages ,
CommandMailboxesSize , & CommandMailboxesMemoryDMA ) ;
/* These are the base addresses for the command memory mailbox array */
Controller - > V1 . FirstCommandMailbox = CommandMailboxesMemory ;
Controller - > V1 . FirstCommandMailboxDMA = CommandMailboxesMemoryDMA ;
CommandMailboxesMemory + = DAC960_V1_CommandMailboxCount - 1 ;
Controller - > V1 . LastCommandMailbox = CommandMailboxesMemory ;
Controller - > V1 . NextCommandMailbox = Controller - > V1 . FirstCommandMailbox ;
Controller - > V1 . PreviousCommandMailbox1 = Controller - > V1 . LastCommandMailbox ;
Controller - > V1 . PreviousCommandMailbox2 =
Controller - > V1 . LastCommandMailbox - 1 ;
/* These are the base addresses for the status memory mailbox array */
StatusMailboxesMemory = slice_dma_loaf ( DmaPages ,
StatusMailboxesSize , & StatusMailboxesMemoryDMA ) ;
Controller - > V1 . FirstStatusMailbox = StatusMailboxesMemory ;
Controller - > V1 . FirstStatusMailboxDMA = StatusMailboxesMemoryDMA ;
StatusMailboxesMemory + = DAC960_V1_StatusMailboxCount - 1 ;
Controller - > V1 . LastStatusMailbox = StatusMailboxesMemory ;
Controller - > V1 . NextStatusMailbox = Controller - > V1 . FirstStatusMailbox ;
skip_mailboxes :
Controller - > V1 . MonitoringDCDB = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V1_DCDB_T ) ,
& Controller - > V1 . MonitoringDCDB_DMA ) ;
Controller - > V1 . NewEnquiry = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V1_Enquiry_T ) ,
& Controller - > V1 . NewEnquiryDMA ) ;
Controller - > V1 . NewErrorTable = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V1_ErrorTable_T ) ,
& Controller - > V1 . NewErrorTableDMA ) ;
Controller - > V1 . EventLogEntry = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V1_EventLogEntry_T ) ,
& Controller - > V1 . EventLogEntryDMA ) ;
Controller - > V1 . RebuildProgress = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V1_RebuildProgress_T ) ,
& Controller - > V1 . RebuildProgressDMA ) ;
Controller - > V1 . NewLogicalDriveInformation = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V1_LogicalDriveInformationArray_T ) ,
& Controller - > V1 . NewLogicalDriveInformationDMA ) ;
Controller - > V1 . BackgroundInitializationStatus = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V1_BackgroundInitializationStatus_T ) ,
& Controller - > V1 . BackgroundInitializationStatusDMA ) ;
Controller - > V1 . NewDeviceState = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V1_DeviceState_T ) ,
& Controller - > V1 . NewDeviceStateDMA ) ;
Controller - > V1 . NewInquiryStandardData = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_SCSI_Inquiry_T ) ,
& Controller - > V1 . NewInquiryStandardDataDMA ) ;
Controller - > V1 . NewInquiryUnitSerialNumber = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ,
& Controller - > V1 . NewInquiryUnitSerialNumberDMA ) ;
if ( ( hw_type = = DAC960_PD_Controller ) | | ( hw_type = = DAC960_P_Controller ) )
return true ;
/* Enable the Memory Mailbox Interface. */
Controller - > V1 . DualModeMemoryMailboxInterface = true ;
CommandMailbox . TypeX . CommandOpcode = 0x2B ;
CommandMailbox . TypeX . CommandIdentifier = 0 ;
CommandMailbox . TypeX . CommandOpcode2 = 0x14 ;
CommandMailbox . TypeX . CommandMailboxesBusAddress =
Controller - > V1 . FirstCommandMailboxDMA ;
CommandMailbox . TypeX . StatusMailboxesBusAddress =
Controller - > V1 . FirstStatusMailboxDMA ;
# define TIMEOUT_COUNT 1000000
for ( i = 0 ; i < 2 ; i + + )
switch ( Controller - > HardwareType )
{
case DAC960_LA_Controller :
TimeoutCounter = TIMEOUT_COUNT ;
while ( - - TimeoutCounter > = 0 )
{
if ( ! DAC960_LA_HardwareMailboxFullP ( ControllerBaseAddress ) )
break ;
udelay ( 10 ) ;
}
if ( TimeoutCounter < 0 ) return false ;
DAC960_LA_WriteHardwareMailbox ( ControllerBaseAddress , & CommandMailbox ) ;
DAC960_LA_HardwareMailboxNewCommand ( ControllerBaseAddress ) ;
TimeoutCounter = TIMEOUT_COUNT ;
while ( - - TimeoutCounter > = 0 )
{
if ( DAC960_LA_HardwareMailboxStatusAvailableP (
ControllerBaseAddress ) )
break ;
udelay ( 10 ) ;
}
if ( TimeoutCounter < 0 ) return false ;
CommandStatus = DAC960_LA_ReadStatusRegister ( ControllerBaseAddress ) ;
DAC960_LA_AcknowledgeHardwareMailboxInterrupt ( ControllerBaseAddress ) ;
DAC960_LA_AcknowledgeHardwareMailboxStatus ( ControllerBaseAddress ) ;
if ( CommandStatus = = DAC960_V1_NormalCompletion ) return true ;
Controller - > V1 . DualModeMemoryMailboxInterface = false ;
CommandMailbox . TypeX . CommandOpcode2 = 0x10 ;
break ;
case DAC960_PG_Controller :
TimeoutCounter = TIMEOUT_COUNT ;
while ( - - TimeoutCounter > = 0 )
{
if ( ! DAC960_PG_HardwareMailboxFullP ( ControllerBaseAddress ) )
break ;
udelay ( 10 ) ;
}
if ( TimeoutCounter < 0 ) return false ;
DAC960_PG_WriteHardwareMailbox ( ControllerBaseAddress , & CommandMailbox ) ;
DAC960_PG_HardwareMailboxNewCommand ( ControllerBaseAddress ) ;
TimeoutCounter = TIMEOUT_COUNT ;
while ( - - TimeoutCounter > = 0 )
{
if ( DAC960_PG_HardwareMailboxStatusAvailableP (
ControllerBaseAddress ) )
break ;
udelay ( 10 ) ;
}
if ( TimeoutCounter < 0 ) return false ;
CommandStatus = DAC960_PG_ReadStatusRegister ( ControllerBaseAddress ) ;
DAC960_PG_AcknowledgeHardwareMailboxInterrupt ( ControllerBaseAddress ) ;
DAC960_PG_AcknowledgeHardwareMailboxStatus ( ControllerBaseAddress ) ;
if ( CommandStatus = = DAC960_V1_NormalCompletion ) return true ;
Controller - > V1 . DualModeMemoryMailboxInterface = false ;
CommandMailbox . TypeX . CommandOpcode2 = 0x10 ;
break ;
default :
DAC960_Failure ( Controller , " Unknown Controller Type \n " ) ;
break ;
}
return false ;
}
/*
DAC960_V2_EnableMemoryMailboxInterface enables the Memory Mailbox Interface
for DAC960 V2 Firmware Controllers .
Aggregate the space needed for the controller ' s memory mailbox and
the other data structures that will be targets of dma transfers with
the controller . Allocate a dma - mapped region of memory to hold these
structures . Then , save CPU pointers and dma_addr_t values to reference
the structures that are contained in that region .
*/
static boolean DAC960_V2_EnableMemoryMailboxInterface ( DAC960_Controller_T
* Controller )
{
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
struct pci_dev * PCI_Device = Controller - > PCIDevice ;
struct dma_loaf * DmaPages = & Controller - > DmaPages ;
size_t DmaPagesSize ;
size_t CommandMailboxesSize ;
size_t StatusMailboxesSize ;
DAC960_V2_CommandMailbox_T * CommandMailboxesMemory ;
dma_addr_t CommandMailboxesMemoryDMA ;
DAC960_V2_StatusMailbox_T * StatusMailboxesMemory ;
dma_addr_t StatusMailboxesMemoryDMA ;
DAC960_V2_CommandMailbox_T * CommandMailbox ;
dma_addr_t CommandMailboxDMA ;
DAC960_V2_CommandStatus_T CommandStatus ;
if ( pci_set_dma_mask ( Controller - > PCIDevice , DAC690_V2_PciDmaMask ) )
return DAC960_Failure ( Controller , " DMA mask out of range " ) ;
Controller - > BounceBufferLimit = DAC690_V2_PciDmaMask ;
/* This is a temporary dma mapping, used only in the scope of this function */
CommandMailbox =
( DAC960_V2_CommandMailbox_T * ) pci_alloc_consistent ( PCI_Device ,
sizeof ( DAC960_V2_CommandMailbox_T ) , & CommandMailboxDMA ) ;
if ( CommandMailbox = = NULL )
return false ;
CommandMailboxesSize = DAC960_V2_CommandMailboxCount * sizeof ( DAC960_V2_CommandMailbox_T ) ;
StatusMailboxesSize = DAC960_V2_StatusMailboxCount * sizeof ( DAC960_V2_StatusMailbox_T ) ;
DmaPagesSize =
CommandMailboxesSize + StatusMailboxesSize +
sizeof ( DAC960_V2_HealthStatusBuffer_T ) +
sizeof ( DAC960_V2_ControllerInfo_T ) +
sizeof ( DAC960_V2_LogicalDeviceInfo_T ) +
sizeof ( DAC960_V2_PhysicalDeviceInfo_T ) +
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) +
sizeof ( DAC960_V2_Event_T ) +
sizeof ( DAC960_V2_PhysicalToLogicalDevice_T ) ;
if ( ! init_dma_loaf ( PCI_Device , DmaPages , DmaPagesSize ) ) {
pci_free_consistent ( PCI_Device , sizeof ( DAC960_V2_CommandMailbox_T ) ,
CommandMailbox , CommandMailboxDMA ) ;
return false ;
}
CommandMailboxesMemory = slice_dma_loaf ( DmaPages ,
CommandMailboxesSize , & CommandMailboxesMemoryDMA ) ;
/* These are the base addresses for the command memory mailbox array */
Controller - > V2 . FirstCommandMailbox = CommandMailboxesMemory ;
Controller - > V2 . FirstCommandMailboxDMA = CommandMailboxesMemoryDMA ;
CommandMailboxesMemory + = DAC960_V2_CommandMailboxCount - 1 ;
Controller - > V2 . LastCommandMailbox = CommandMailboxesMemory ;
Controller - > V2 . NextCommandMailbox = Controller - > V2 . FirstCommandMailbox ;
Controller - > V2 . PreviousCommandMailbox1 = Controller - > V2 . LastCommandMailbox ;
Controller - > V2 . PreviousCommandMailbox2 =
Controller - > V2 . LastCommandMailbox - 1 ;
/* These are the base addresses for the status memory mailbox array */
StatusMailboxesMemory = slice_dma_loaf ( DmaPages ,
StatusMailboxesSize , & StatusMailboxesMemoryDMA ) ;
Controller - > V2 . FirstStatusMailbox = StatusMailboxesMemory ;
Controller - > V2 . FirstStatusMailboxDMA = StatusMailboxesMemoryDMA ;
StatusMailboxesMemory + = DAC960_V2_StatusMailboxCount - 1 ;
Controller - > V2 . LastStatusMailbox = StatusMailboxesMemory ;
Controller - > V2 . NextStatusMailbox = Controller - > V2 . FirstStatusMailbox ;
Controller - > V2 . HealthStatusBuffer = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V2_HealthStatusBuffer_T ) ,
& Controller - > V2 . HealthStatusBufferDMA ) ;
Controller - > V2 . NewControllerInformation = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V2_ControllerInfo_T ) ,
& Controller - > V2 . NewControllerInformationDMA ) ;
Controller - > V2 . NewLogicalDeviceInformation = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V2_LogicalDeviceInfo_T ) ,
& Controller - > V2 . NewLogicalDeviceInformationDMA ) ;
Controller - > V2 . NewPhysicalDeviceInformation = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V2_PhysicalDeviceInfo_T ) ,
& Controller - > V2 . NewPhysicalDeviceInformationDMA ) ;
Controller - > V2 . NewInquiryUnitSerialNumber = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ,
& Controller - > V2 . NewInquiryUnitSerialNumberDMA ) ;
Controller - > V2 . Event = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V2_Event_T ) ,
& Controller - > V2 . EventDMA ) ;
Controller - > V2 . PhysicalToLogicalDevice = slice_dma_loaf ( DmaPages ,
sizeof ( DAC960_V2_PhysicalToLogicalDevice_T ) ,
& Controller - > V2 . PhysicalToLogicalDeviceDMA ) ;
/*
Enable the Memory Mailbox Interface .
I don ' t know why we can ' t just use one of the memory mailboxes
we just allocated to do this , instead of using this temporary one .
Try this change later .
*/
memset ( CommandMailbox , 0 , sizeof ( DAC960_V2_CommandMailbox_T ) ) ;
CommandMailbox - > SetMemoryMailbox . CommandIdentifier = 1 ;
CommandMailbox - > SetMemoryMailbox . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > SetMemoryMailbox . CommandControlBits . NoAutoRequestSense = true ;
CommandMailbox - > SetMemoryMailbox . FirstCommandMailboxSizeKB =
( DAC960_V2_CommandMailboxCount * sizeof ( DAC960_V2_CommandMailbox_T ) ) > > 10 ;
CommandMailbox - > SetMemoryMailbox . FirstStatusMailboxSizeKB =
( DAC960_V2_StatusMailboxCount * sizeof ( DAC960_V2_StatusMailbox_T ) ) > > 10 ;
CommandMailbox - > SetMemoryMailbox . SecondCommandMailboxSizeKB = 0 ;
CommandMailbox - > SetMemoryMailbox . SecondStatusMailboxSizeKB = 0 ;
CommandMailbox - > SetMemoryMailbox . RequestSenseSize = 0 ;
CommandMailbox - > SetMemoryMailbox . IOCTL_Opcode = DAC960_V2_SetMemoryMailbox ;
CommandMailbox - > SetMemoryMailbox . HealthStatusBufferSizeKB = 1 ;
CommandMailbox - > SetMemoryMailbox . HealthStatusBufferBusAddress =
Controller - > V2 . HealthStatusBufferDMA ;
CommandMailbox - > SetMemoryMailbox . FirstCommandMailboxBusAddress =
Controller - > V2 . FirstCommandMailboxDMA ;
CommandMailbox - > SetMemoryMailbox . FirstStatusMailboxBusAddress =
Controller - > V2 . FirstStatusMailboxDMA ;
switch ( Controller - > HardwareType )
{
2005-05-05 16:15:58 -07:00
case DAC960_GEM_Controller :
while ( DAC960_GEM_HardwareMailboxFullP ( ControllerBaseAddress ) )
udelay ( 1 ) ;
DAC960_GEM_WriteHardwareMailbox ( ControllerBaseAddress , CommandMailboxDMA ) ;
DAC960_GEM_HardwareMailboxNewCommand ( ControllerBaseAddress ) ;
while ( ! DAC960_GEM_HardwareMailboxStatusAvailableP ( ControllerBaseAddress ) )
udelay ( 1 ) ;
CommandStatus = DAC960_GEM_ReadCommandStatus ( ControllerBaseAddress ) ;
DAC960_GEM_AcknowledgeHardwareMailboxInterrupt ( ControllerBaseAddress ) ;
DAC960_GEM_AcknowledgeHardwareMailboxStatus ( ControllerBaseAddress ) ;
break ;
2005-04-16 15:20:36 -07:00
case DAC960_BA_Controller :
while ( DAC960_BA_HardwareMailboxFullP ( ControllerBaseAddress ) )
udelay ( 1 ) ;
DAC960_BA_WriteHardwareMailbox ( ControllerBaseAddress , CommandMailboxDMA ) ;
DAC960_BA_HardwareMailboxNewCommand ( ControllerBaseAddress ) ;
while ( ! DAC960_BA_HardwareMailboxStatusAvailableP ( ControllerBaseAddress ) )
udelay ( 1 ) ;
CommandStatus = DAC960_BA_ReadCommandStatus ( ControllerBaseAddress ) ;
DAC960_BA_AcknowledgeHardwareMailboxInterrupt ( ControllerBaseAddress ) ;
DAC960_BA_AcknowledgeHardwareMailboxStatus ( ControllerBaseAddress ) ;
break ;
case DAC960_LP_Controller :
while ( DAC960_LP_HardwareMailboxFullP ( ControllerBaseAddress ) )
udelay ( 1 ) ;
DAC960_LP_WriteHardwareMailbox ( ControllerBaseAddress , CommandMailboxDMA ) ;
DAC960_LP_HardwareMailboxNewCommand ( ControllerBaseAddress ) ;
while ( ! DAC960_LP_HardwareMailboxStatusAvailableP ( ControllerBaseAddress ) )
udelay ( 1 ) ;
CommandStatus = DAC960_LP_ReadCommandStatus ( ControllerBaseAddress ) ;
DAC960_LP_AcknowledgeHardwareMailboxInterrupt ( ControllerBaseAddress ) ;
DAC960_LP_AcknowledgeHardwareMailboxStatus ( ControllerBaseAddress ) ;
break ;
default :
DAC960_Failure ( Controller , " Unknown Controller Type \n " ) ;
CommandStatus = DAC960_V2_AbormalCompletion ;
break ;
}
pci_free_consistent ( PCI_Device , sizeof ( DAC960_V2_CommandMailbox_T ) ,
CommandMailbox , CommandMailboxDMA ) ;
return ( CommandStatus = = DAC960_V2_NormalCompletion ) ;
}
/*
DAC960_V1_ReadControllerConfiguration reads the Configuration Information
from DAC960 V1 Firmware Controllers and initializes the Controller structure .
*/
static boolean DAC960_V1_ReadControllerConfiguration ( DAC960_Controller_T
* Controller )
{
DAC960_V1_Enquiry2_T * Enquiry2 ;
dma_addr_t Enquiry2DMA ;
DAC960_V1_Config2_T * Config2 ;
dma_addr_t Config2DMA ;
int LogicalDriveNumber , Channel , TargetID ;
struct dma_loaf local_dma ;
if ( ! init_dma_loaf ( Controller - > PCIDevice , & local_dma ,
sizeof ( DAC960_V1_Enquiry2_T ) + sizeof ( DAC960_V1_Config2_T ) ) )
return DAC960_Failure ( Controller , " LOGICAL DEVICE ALLOCATION " ) ;
Enquiry2 = slice_dma_loaf ( & local_dma , sizeof ( DAC960_V1_Enquiry2_T ) , & Enquiry2DMA ) ;
Config2 = slice_dma_loaf ( & local_dma , sizeof ( DAC960_V1_Config2_T ) , & Config2DMA ) ;
if ( ! DAC960_V1_ExecuteType3 ( Controller , DAC960_V1_Enquiry ,
Controller - > V1 . NewEnquiryDMA ) ) {
free_dma_loaf ( Controller - > PCIDevice , & local_dma ) ;
return DAC960_Failure ( Controller , " ENQUIRY " ) ;
}
memcpy ( & Controller - > V1 . Enquiry , Controller - > V1 . NewEnquiry ,
sizeof ( DAC960_V1_Enquiry_T ) ) ;
if ( ! DAC960_V1_ExecuteType3 ( Controller , DAC960_V1_Enquiry2 , Enquiry2DMA ) ) {
free_dma_loaf ( Controller - > PCIDevice , & local_dma ) ;
return DAC960_Failure ( Controller , " ENQUIRY2 " ) ;
}
if ( ! DAC960_V1_ExecuteType3 ( Controller , DAC960_V1_ReadConfig2 , Config2DMA ) ) {
free_dma_loaf ( Controller - > PCIDevice , & local_dma ) ;
return DAC960_Failure ( Controller , " READ CONFIG2 " ) ;
}
if ( ! DAC960_V1_ExecuteType3 ( Controller , DAC960_V1_GetLogicalDriveInformation ,
Controller - > V1 . NewLogicalDriveInformationDMA ) ) {
free_dma_loaf ( Controller - > PCIDevice , & local_dma ) ;
return DAC960_Failure ( Controller , " GET LOGICAL DRIVE INFORMATION " ) ;
}
memcpy ( & Controller - > V1 . LogicalDriveInformation ,
Controller - > V1 . NewLogicalDriveInformation ,
sizeof ( DAC960_V1_LogicalDriveInformationArray_T ) ) ;
for ( Channel = 0 ; Channel < Enquiry2 - > ActualChannels ; Channel + + )
for ( TargetID = 0 ; TargetID < Enquiry2 - > MaxTargets ; TargetID + + ) {
if ( ! DAC960_V1_ExecuteType3D ( Controller , DAC960_V1_GetDeviceState ,
Channel , TargetID ,
Controller - > V1 . NewDeviceStateDMA ) ) {
free_dma_loaf ( Controller - > PCIDevice , & local_dma ) ;
return DAC960_Failure ( Controller , " GET DEVICE STATE " ) ;
}
memcpy ( & Controller - > V1 . DeviceState [ Channel ] [ TargetID ] ,
Controller - > V1 . NewDeviceState , sizeof ( DAC960_V1_DeviceState_T ) ) ;
}
/*
Initialize the Controller Model Name and Full Model Name fields .
*/
switch ( Enquiry2 - > HardwareID . SubModel )
{
case DAC960_V1_P_PD_PU :
if ( Enquiry2 - > SCSICapability . BusSpeed = = DAC960_V1_Ultra )
strcpy ( Controller - > ModelName , " DAC960PU " ) ;
else strcpy ( Controller - > ModelName , " DAC960PD " ) ;
break ;
case DAC960_V1_PL :
strcpy ( Controller - > ModelName , " DAC960PL " ) ;
break ;
case DAC960_V1_PG :
strcpy ( Controller - > ModelName , " DAC960PG " ) ;
break ;
case DAC960_V1_PJ :
strcpy ( Controller - > ModelName , " DAC960PJ " ) ;
break ;
case DAC960_V1_PR :
strcpy ( Controller - > ModelName , " DAC960PR " ) ;
break ;
case DAC960_V1_PT :
strcpy ( Controller - > ModelName , " DAC960PT " ) ;
break ;
case DAC960_V1_PTL0 :
strcpy ( Controller - > ModelName , " DAC960PTL0 " ) ;
break ;
case DAC960_V1_PRL :
strcpy ( Controller - > ModelName , " DAC960PRL " ) ;
break ;
case DAC960_V1_PTL1 :
strcpy ( Controller - > ModelName , " DAC960PTL1 " ) ;
break ;
case DAC960_V1_1164P :
strcpy ( Controller - > ModelName , " DAC1164P " ) ;
break ;
default :
free_dma_loaf ( Controller - > PCIDevice , & local_dma ) ;
return DAC960_Failure ( Controller , " MODEL VERIFICATION " ) ;
}
strcpy ( Controller - > FullModelName , " Mylex " ) ;
strcat ( Controller - > FullModelName , Controller - > ModelName ) ;
/*
Initialize the Controller Firmware Version field and verify that it
is a supported firmware version . The supported firmware versions are :
DAC1164P 5.06 and above
DAC960PTL / PRL / PJ / PG 4.06 and above
DAC960PU / PD / PL 3.51 and above
DAC960PU / PD / PL / P 2.73 and above
*/
# if defined(CONFIG_ALPHA)
/*
DEC Alpha machines were often equipped with DAC960 cards that were
OEMed from Mylex , and had their own custom firmware . Version 2.70 ,
the last custom FW revision to be released by DEC for these older
controllers , appears to work quite well with this driver .
Cards tested successfully were several versions each of the PD and
PU , called by DEC the KZPSC and KZPAC , respectively , and having
the Manufacturer Numbers ( from Mylex ) , usually on a sticker on the
back of the board , of :
KZPSC : D040347 ( 1 - channel ) or D040348 ( 2 - channel ) or D040349 ( 3 - channel )
KZPAC : D040395 ( 1 - channel ) or D040396 ( 2 - channel ) or D040397 ( 3 - channel )
*/
# define FIRMWARE_27X "2.70"
# else
# define FIRMWARE_27X "2.73"
# endif
if ( Enquiry2 - > FirmwareID . MajorVersion = = 0 )
{
Enquiry2 - > FirmwareID . MajorVersion =
Controller - > V1 . Enquiry . MajorFirmwareVersion ;
Enquiry2 - > FirmwareID . MinorVersion =
Controller - > V1 . Enquiry . MinorFirmwareVersion ;
Enquiry2 - > FirmwareID . FirmwareType = ' 0 ' ;
Enquiry2 - > FirmwareID . TurnID = 0 ;
}
sprintf ( Controller - > FirmwareVersion , " %d.%02d-%c-%02d " ,
Enquiry2 - > FirmwareID . MajorVersion , Enquiry2 - > FirmwareID . MinorVersion ,
Enquiry2 - > FirmwareID . FirmwareType , Enquiry2 - > FirmwareID . TurnID ) ;
if ( ! ( ( Controller - > FirmwareVersion [ 0 ] = = ' 5 ' & &
strcmp ( Controller - > FirmwareVersion , " 5.06 " ) > = 0 ) | |
( Controller - > FirmwareVersion [ 0 ] = = ' 4 ' & &
strcmp ( Controller - > FirmwareVersion , " 4.06 " ) > = 0 ) | |
( Controller - > FirmwareVersion [ 0 ] = = ' 3 ' & &
strcmp ( Controller - > FirmwareVersion , " 3.51 " ) > = 0 ) | |
( Controller - > FirmwareVersion [ 0 ] = = ' 2 ' & &
strcmp ( Controller - > FirmwareVersion , FIRMWARE_27X ) > = 0 ) ) )
{
DAC960_Failure ( Controller , " FIRMWARE VERSION VERIFICATION " ) ;
DAC960_Error ( " Firmware Version = '%s' \n " , Controller ,
Controller - > FirmwareVersion ) ;
free_dma_loaf ( Controller - > PCIDevice , & local_dma ) ;
return false ;
}
/*
Initialize the Controller Channels , Targets , Memory Size , and SAF - TE
Enclosure Management Enabled fields .
*/
Controller - > Channels = Enquiry2 - > ActualChannels ;
Controller - > Targets = Enquiry2 - > MaxTargets ;
Controller - > MemorySize = Enquiry2 - > MemorySize > > 20 ;
Controller - > V1 . SAFTE_EnclosureManagementEnabled =
( Enquiry2 - > FaultManagementType = = DAC960_V1_SAFTE ) ;
/*
Initialize the Controller Queue Depth , Driver Queue Depth , Logical Drive
Count , Maximum Blocks per Command , Controller Scatter / Gather Limit , and
Driver Scatter / Gather Limit . The Driver Queue Depth must be at most one
less than the Controller Queue Depth to allow for an automatic drive
rebuild operation .
*/
Controller - > ControllerQueueDepth = Controller - > V1 . Enquiry . MaxCommands ;
Controller - > DriverQueueDepth = Controller - > ControllerQueueDepth - 1 ;
if ( Controller - > DriverQueueDepth > DAC960_MaxDriverQueueDepth )
Controller - > DriverQueueDepth = DAC960_MaxDriverQueueDepth ;
Controller - > LogicalDriveCount =
Controller - > V1 . Enquiry . NumberOfLogicalDrives ;
Controller - > MaxBlocksPerCommand = Enquiry2 - > MaxBlocksPerCommand ;
Controller - > ControllerScatterGatherLimit = Enquiry2 - > MaxScatterGatherEntries ;
Controller - > DriverScatterGatherLimit =
Controller - > ControllerScatterGatherLimit ;
if ( Controller - > DriverScatterGatherLimit > DAC960_V1_ScatterGatherLimit )
Controller - > DriverScatterGatherLimit = DAC960_V1_ScatterGatherLimit ;
/*
Initialize the Stripe Size , Segment Size , and Geometry Translation .
*/
Controller - > V1 . StripeSize = Config2 - > BlocksPerStripe * Config2 - > BlockFactor
> > ( 10 - DAC960_BlockSizeBits ) ;
Controller - > V1 . SegmentSize = Config2 - > BlocksPerCacheLine * Config2 - > BlockFactor
> > ( 10 - DAC960_BlockSizeBits ) ;
switch ( Config2 - > DriveGeometry )
{
case DAC960_V1_Geometry_128_32 :
Controller - > V1 . GeometryTranslationHeads = 128 ;
Controller - > V1 . GeometryTranslationSectors = 32 ;
break ;
case DAC960_V1_Geometry_255_63 :
Controller - > V1 . GeometryTranslationHeads = 255 ;
Controller - > V1 . GeometryTranslationSectors = 63 ;
break ;
default :
free_dma_loaf ( Controller - > PCIDevice , & local_dma ) ;
return DAC960_Failure ( Controller , " CONFIG2 DRIVE GEOMETRY " ) ;
}
/*
Initialize the Background Initialization Status .
*/
if ( ( Controller - > FirmwareVersion [ 0 ] = = ' 4 ' & &
strcmp ( Controller - > FirmwareVersion , " 4.08 " ) > = 0 ) | |
( Controller - > FirmwareVersion [ 0 ] = = ' 5 ' & &
strcmp ( Controller - > FirmwareVersion , " 5.08 " ) > = 0 ) )
{
Controller - > V1 . BackgroundInitializationStatusSupported = true ;
DAC960_V1_ExecuteType3B ( Controller ,
DAC960_V1_BackgroundInitializationControl , 0x20 ,
Controller - >
V1 . BackgroundInitializationStatusDMA ) ;
memcpy ( & Controller - > V1 . LastBackgroundInitializationStatus ,
Controller - > V1 . BackgroundInitializationStatus ,
sizeof ( DAC960_V1_BackgroundInitializationStatus_T ) ) ;
}
/*
Initialize the Logical Drive Initially Accessible flag .
*/
for ( LogicalDriveNumber = 0 ;
LogicalDriveNumber < Controller - > LogicalDriveCount ;
LogicalDriveNumber + + )
if ( Controller - > V1 . LogicalDriveInformation
[ LogicalDriveNumber ] . LogicalDriveState ! =
DAC960_V1_LogicalDrive_Offline )
Controller - > LogicalDriveInitiallyAccessible [ LogicalDriveNumber ] = true ;
Controller - > V1 . LastRebuildStatus = DAC960_V1_NoRebuildOrCheckInProgress ;
free_dma_loaf ( Controller - > PCIDevice , & local_dma ) ;
return true ;
}
/*
DAC960_V2_ReadControllerConfiguration reads the Configuration Information
from DAC960 V2 Firmware Controllers and initializes the Controller structure .
*/
static boolean DAC960_V2_ReadControllerConfiguration ( DAC960_Controller_T
* Controller )
{
DAC960_V2_ControllerInfo_T * ControllerInfo =
& Controller - > V2 . ControllerInformation ;
unsigned short LogicalDeviceNumber = 0 ;
int ModelNameLength ;
/* Get data into dma-able area, then copy into permanant location */
if ( ! DAC960_V2_NewControllerInfo ( Controller ) )
return DAC960_Failure ( Controller , " GET CONTROLLER INFO " ) ;
memcpy ( ControllerInfo , Controller - > V2 . NewControllerInformation ,
sizeof ( DAC960_V2_ControllerInfo_T ) ) ;
if ( ! DAC960_V2_GeneralInfo ( Controller ) )
return DAC960_Failure ( Controller , " GET HEALTH STATUS " ) ;
/*
Initialize the Controller Model Name and Full Model Name fields .
*/
ModelNameLength = sizeof ( ControllerInfo - > ControllerName ) ;
if ( ModelNameLength > sizeof ( Controller - > ModelName ) - 1 )
ModelNameLength = sizeof ( Controller - > ModelName ) - 1 ;
memcpy ( Controller - > ModelName , ControllerInfo - > ControllerName ,
ModelNameLength ) ;
ModelNameLength - - ;
while ( Controller - > ModelName [ ModelNameLength ] = = ' ' | |
Controller - > ModelName [ ModelNameLength ] = = ' \0 ' )
ModelNameLength - - ;
Controller - > ModelName [ + + ModelNameLength ] = ' \0 ' ;
strcpy ( Controller - > FullModelName , " Mylex " ) ;
strcat ( Controller - > FullModelName , Controller - > ModelName ) ;
/*
Initialize the Controller Firmware Version field .
*/
sprintf ( Controller - > FirmwareVersion , " %d.%02d-%02d " ,
ControllerInfo - > FirmwareMajorVersion ,
ControllerInfo - > FirmwareMinorVersion ,
ControllerInfo - > FirmwareTurnNumber ) ;
if ( ControllerInfo - > FirmwareMajorVersion = = 6 & &
ControllerInfo - > FirmwareMinorVersion = = 0 & &
ControllerInfo - > FirmwareTurnNumber < 1 )
{
DAC960_Info ( " FIRMWARE VERSION %s DOES NOT PROVIDE THE CONTROLLER \n " ,
Controller , Controller - > FirmwareVersion ) ;
DAC960_Info ( " STATUS MONITORING FUNCTIONALITY NEEDED BY THIS DRIVER. \n " ,
Controller ) ;
DAC960_Info ( " PLEASE UPGRADE TO VERSION 6.00-01 OR ABOVE. \n " ,
Controller ) ;
}
/*
Initialize the Controller Channels , Targets , and Memory Size .
*/
Controller - > Channels = ControllerInfo - > NumberOfPhysicalChannelsPresent ;
Controller - > Targets =
ControllerInfo - > MaximumTargetsPerChannel
[ ControllerInfo - > NumberOfPhysicalChannelsPresent - 1 ] ;
Controller - > MemorySize = ControllerInfo - > MemorySizeMB ;
/*
Initialize the Controller Queue Depth , Driver Queue Depth , Logical Drive
Count , Maximum Blocks per Command , Controller Scatter / Gather Limit , and
Driver Scatter / Gather Limit . The Driver Queue Depth must be at most one
less than the Controller Queue Depth to allow for an automatic drive
rebuild operation .
*/
Controller - > ControllerQueueDepth = ControllerInfo - > MaximumParallelCommands ;
Controller - > DriverQueueDepth = Controller - > ControllerQueueDepth - 1 ;
if ( Controller - > DriverQueueDepth > DAC960_MaxDriverQueueDepth )
Controller - > DriverQueueDepth = DAC960_MaxDriverQueueDepth ;
Controller - > LogicalDriveCount = ControllerInfo - > LogicalDevicesPresent ;
Controller - > MaxBlocksPerCommand =
ControllerInfo - > MaximumDataTransferSizeInBlocks ;
Controller - > ControllerScatterGatherLimit =
ControllerInfo - > MaximumScatterGatherEntries ;
Controller - > DriverScatterGatherLimit =
Controller - > ControllerScatterGatherLimit ;
if ( Controller - > DriverScatterGatherLimit > DAC960_V2_ScatterGatherLimit )
Controller - > DriverScatterGatherLimit = DAC960_V2_ScatterGatherLimit ;
/*
Initialize the Logical Device Information .
*/
while ( true )
{
DAC960_V2_LogicalDeviceInfo_T * NewLogicalDeviceInfo =
Controller - > V2 . NewLogicalDeviceInformation ;
DAC960_V2_LogicalDeviceInfo_T * LogicalDeviceInfo ;
DAC960_V2_PhysicalDevice_T PhysicalDevice ;
if ( ! DAC960_V2_NewLogicalDeviceInfo ( Controller , LogicalDeviceNumber ) )
break ;
LogicalDeviceNumber = NewLogicalDeviceInfo - > LogicalDeviceNumber ;
if ( LogicalDeviceNumber > = DAC960_MaxLogicalDrives ) {
DAC960_Error ( " DAC960: Logical Drive Number %d not supported \n " ,
Controller , LogicalDeviceNumber ) ;
break ;
}
if ( NewLogicalDeviceInfo - > DeviceBlockSizeInBytes ! = DAC960_BlockSize ) {
DAC960_Error ( " DAC960: Logical Drive Block Size %d not supported \n " ,
Controller , NewLogicalDeviceInfo - > DeviceBlockSizeInBytes ) ;
LogicalDeviceNumber + + ;
continue ;
}
PhysicalDevice . Controller = 0 ;
PhysicalDevice . Channel = NewLogicalDeviceInfo - > Channel ;
PhysicalDevice . TargetID = NewLogicalDeviceInfo - > TargetID ;
PhysicalDevice . LogicalUnit = NewLogicalDeviceInfo - > LogicalUnit ;
Controller - > V2 . LogicalDriveToVirtualDevice [ LogicalDeviceNumber ] =
PhysicalDevice ;
if ( NewLogicalDeviceInfo - > LogicalDeviceState ! =
DAC960_V2_LogicalDevice_Offline )
Controller - > LogicalDriveInitiallyAccessible [ LogicalDeviceNumber ] = true ;
LogicalDeviceInfo = ( DAC960_V2_LogicalDeviceInfo_T * )
kmalloc ( sizeof ( DAC960_V2_LogicalDeviceInfo_T ) , GFP_ATOMIC ) ;
if ( LogicalDeviceInfo = = NULL )
return DAC960_Failure ( Controller , " LOGICAL DEVICE ALLOCATION " ) ;
Controller - > V2 . LogicalDeviceInformation [ LogicalDeviceNumber ] =
LogicalDeviceInfo ;
memcpy ( LogicalDeviceInfo , NewLogicalDeviceInfo ,
sizeof ( DAC960_V2_LogicalDeviceInfo_T ) ) ;
LogicalDeviceNumber + + ;
}
return true ;
}
/*
DAC960_ReportControllerConfiguration reports the Configuration Information
for Controller .
*/
static boolean DAC960_ReportControllerConfiguration ( DAC960_Controller_T
* Controller )
{
DAC960_Info ( " Configuring Mylex %s PCI RAID Controller \n " ,
Controller , Controller - > ModelName ) ;
DAC960_Info ( " Firmware Version: %s, Channels: %d, Memory Size: %dMB \n " ,
Controller , Controller - > FirmwareVersion ,
Controller - > Channels , Controller - > MemorySize ) ;
DAC960_Info ( " PCI Bus: %d, Device: %d, Function: %d, I/O Address: " ,
Controller , Controller - > Bus ,
Controller - > Device , Controller - > Function ) ;
if ( Controller - > IO_Address = = 0 )
DAC960_Info ( " Unassigned \n " , Controller ) ;
else DAC960_Info ( " 0x%X \n " , Controller , Controller - > IO_Address ) ;
DAC960_Info ( " PCI Address: 0x%X mapped at 0x%lX, IRQ Channel: %d \n " ,
Controller , Controller - > PCI_Address ,
( unsigned long ) Controller - > BaseAddress ,
Controller - > IRQ_Channel ) ;
DAC960_Info ( " Controller Queue Depth: %d, "
" Maximum Blocks per Command: %d \n " ,
Controller , Controller - > ControllerQueueDepth ,
Controller - > MaxBlocksPerCommand ) ;
DAC960_Info ( " Driver Queue Depth: %d, "
" Scatter/Gather Limit: %d of %d Segments \n " ,
Controller , Controller - > DriverQueueDepth ,
Controller - > DriverScatterGatherLimit ,
Controller - > ControllerScatterGatherLimit ) ;
if ( Controller - > FirmwareType = = DAC960_V1_Controller )
{
DAC960_Info ( " Stripe Size: %dKB, Segment Size: %dKB, "
" BIOS Geometry: %d/%d \n " , Controller ,
Controller - > V1 . StripeSize ,
Controller - > V1 . SegmentSize ,
Controller - > V1 . GeometryTranslationHeads ,
Controller - > V1 . GeometryTranslationSectors ) ;
if ( Controller - > V1 . SAFTE_EnclosureManagementEnabled )
DAC960_Info ( " SAF-TE Enclosure Management Enabled \n " , Controller ) ;
}
return true ;
}
/*
DAC960_V1_ReadDeviceConfiguration reads the Device Configuration Information
for DAC960 V1 Firmware Controllers by requesting the SCSI Inquiry and SCSI
Inquiry Unit Serial Number information for each device connected to
Controller .
*/
static boolean DAC960_V1_ReadDeviceConfiguration ( DAC960_Controller_T
* Controller )
{
struct dma_loaf local_dma ;
dma_addr_t DCDBs_dma [ DAC960_V1_MaxChannels ] ;
DAC960_V1_DCDB_T * DCDBs_cpu [ DAC960_V1_MaxChannels ] ;
dma_addr_t SCSI_Inquiry_dma [ DAC960_V1_MaxChannels ] ;
DAC960_SCSI_Inquiry_T * SCSI_Inquiry_cpu [ DAC960_V1_MaxChannels ] ;
dma_addr_t SCSI_NewInquiryUnitSerialNumberDMA [ DAC960_V1_MaxChannels ] ;
DAC960_SCSI_Inquiry_UnitSerialNumber_T * SCSI_NewInquiryUnitSerialNumberCPU [ DAC960_V1_MaxChannels ] ;
struct completion Completions [ DAC960_V1_MaxChannels ] ;
unsigned long flags ;
int Channel , TargetID ;
if ( ! init_dma_loaf ( Controller - > PCIDevice , & local_dma ,
DAC960_V1_MaxChannels * ( sizeof ( DAC960_V1_DCDB_T ) +
sizeof ( DAC960_SCSI_Inquiry_T ) +
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ) ) )
return DAC960_Failure ( Controller ,
" DMA ALLOCATION FAILED IN ReadDeviceConfiguration " ) ;
for ( Channel = 0 ; Channel < Controller - > Channels ; Channel + + ) {
DCDBs_cpu [ Channel ] = slice_dma_loaf ( & local_dma ,
sizeof ( DAC960_V1_DCDB_T ) , DCDBs_dma + Channel ) ;
SCSI_Inquiry_cpu [ Channel ] = slice_dma_loaf ( & local_dma ,
sizeof ( DAC960_SCSI_Inquiry_T ) ,
SCSI_Inquiry_dma + Channel ) ;
SCSI_NewInquiryUnitSerialNumberCPU [ Channel ] = slice_dma_loaf ( & local_dma ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ,
SCSI_NewInquiryUnitSerialNumberDMA + Channel ) ;
}
for ( TargetID = 0 ; TargetID < Controller - > Targets ; TargetID + + )
{
/*
* For each channel , submit a probe for a device on that channel .
* The timeout interval for a device that is present is 10 seconds .
* With this approach , the timeout periods can elapse in parallel
* on each channel .
*/
for ( Channel = 0 ; Channel < Controller - > Channels ; Channel + + )
{
dma_addr_t NewInquiryStandardDataDMA = SCSI_Inquiry_dma [ Channel ] ;
DAC960_V1_DCDB_T * DCDB = DCDBs_cpu [ Channel ] ;
dma_addr_t DCDB_dma = DCDBs_dma [ Channel ] ;
DAC960_Command_T * Command = Controller - > Commands [ Channel ] ;
struct completion * Completion = & Completions [ Channel ] ;
init_completion ( Completion ) ;
DAC960_V1_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
Command - > Completion = Completion ;
Command - > V1 . CommandMailbox . Type3 . CommandOpcode = DAC960_V1_DCDB ;
Command - > V1 . CommandMailbox . Type3 . BusAddress = DCDB_dma ;
DCDB - > Channel = Channel ;
DCDB - > TargetID = TargetID ;
DCDB - > Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem ;
DCDB - > EarlyStatus = false ;
DCDB - > Timeout = DAC960_V1_DCDB_Timeout_10_seconds ;
DCDB - > NoAutomaticRequestSense = false ;
DCDB - > DisconnectPermitted = true ;
DCDB - > TransferLength = sizeof ( DAC960_SCSI_Inquiry_T ) ;
DCDB - > BusAddress = NewInquiryStandardDataDMA ;
DCDB - > CDBLength = 6 ;
DCDB - > TransferLengthHigh4 = 0 ;
DCDB - > SenseLength = sizeof ( DCDB - > SenseData ) ;
DCDB - > CDB [ 0 ] = 0x12 ; /* INQUIRY */
DCDB - > CDB [ 1 ] = 0 ; /* EVPD = 0 */
DCDB - > CDB [ 2 ] = 0 ; /* Page Code */
DCDB - > CDB [ 3 ] = 0 ; /* Reserved */
DCDB - > CDB [ 4 ] = sizeof ( DAC960_SCSI_Inquiry_T ) ;
DCDB - > CDB [ 5 ] = 0 ; /* Control */
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_QueueCommand ( Command ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
}
/*
* Wait for the problems submitted in the previous loop
* to complete . On the probes that are successful ,
* get the serial number of the device that was found .
*/
for ( Channel = 0 ; Channel < Controller - > Channels ; Channel + + )
{
DAC960_SCSI_Inquiry_T * InquiryStandardData =
& Controller - > V1 . InquiryStandardData [ Channel ] [ TargetID ] ;
DAC960_SCSI_Inquiry_T * NewInquiryStandardData = SCSI_Inquiry_cpu [ Channel ] ;
dma_addr_t NewInquiryUnitSerialNumberDMA =
SCSI_NewInquiryUnitSerialNumberDMA [ Channel ] ;
DAC960_SCSI_Inquiry_UnitSerialNumber_T * NewInquiryUnitSerialNumber =
SCSI_NewInquiryUnitSerialNumberCPU [ Channel ] ;
DAC960_SCSI_Inquiry_UnitSerialNumber_T * InquiryUnitSerialNumber =
& Controller - > V1 . InquiryUnitSerialNumber [ Channel ] [ TargetID ] ;
DAC960_Command_T * Command = Controller - > Commands [ Channel ] ;
DAC960_V1_DCDB_T * DCDB = DCDBs_cpu [ Channel ] ;
struct completion * Completion = & Completions [ Channel ] ;
wait_for_completion ( Completion ) ;
if ( Command - > V1 . CommandStatus ! = DAC960_V1_NormalCompletion ) {
memset ( InquiryStandardData , 0 , sizeof ( DAC960_SCSI_Inquiry_T ) ) ;
InquiryStandardData - > PeripheralDeviceType = 0x1F ;
continue ;
} else
memcpy ( InquiryStandardData , NewInquiryStandardData , sizeof ( DAC960_SCSI_Inquiry_T ) ) ;
/* Preserve Channel and TargetID values from the previous loop */
Command - > Completion = Completion ;
DCDB - > TransferLength = sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ;
DCDB - > BusAddress = NewInquiryUnitSerialNumberDMA ;
DCDB - > SenseLength = sizeof ( DCDB - > SenseData ) ;
DCDB - > CDB [ 0 ] = 0x12 ; /* INQUIRY */
DCDB - > CDB [ 1 ] = 1 ; /* EVPD = 1 */
DCDB - > CDB [ 2 ] = 0x80 ; /* Page Code */
DCDB - > CDB [ 3 ] = 0 ; /* Reserved */
DCDB - > CDB [ 4 ] = sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ;
DCDB - > CDB [ 5 ] = 0 ; /* Control */
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_QueueCommand ( Command ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
wait_for_completion ( Completion ) ;
if ( Command - > V1 . CommandStatus ! = DAC960_V1_NormalCompletion ) {
memset ( InquiryUnitSerialNumber , 0 ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ) ;
InquiryUnitSerialNumber - > PeripheralDeviceType = 0x1F ;
} else
memcpy ( InquiryUnitSerialNumber , NewInquiryUnitSerialNumber ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ) ;
}
}
free_dma_loaf ( Controller - > PCIDevice , & local_dma ) ;
return true ;
}
/*
DAC960_V2_ReadDeviceConfiguration reads the Device Configuration Information
for DAC960 V2 Firmware Controllers by requesting the Physical Device
Information and SCSI Inquiry Unit Serial Number information for each
device connected to Controller .
*/
static boolean DAC960_V2_ReadDeviceConfiguration ( DAC960_Controller_T
* Controller )
{
unsigned char Channel = 0 , TargetID = 0 , LogicalUnit = 0 ;
unsigned short PhysicalDeviceIndex = 0 ;
while ( true )
{
DAC960_V2_PhysicalDeviceInfo_T * NewPhysicalDeviceInfo =
Controller - > V2 . NewPhysicalDeviceInformation ;
DAC960_V2_PhysicalDeviceInfo_T * PhysicalDeviceInfo ;
DAC960_SCSI_Inquiry_UnitSerialNumber_T * NewInquiryUnitSerialNumber =
Controller - > V2 . NewInquiryUnitSerialNumber ;
DAC960_SCSI_Inquiry_UnitSerialNumber_T * InquiryUnitSerialNumber ;
if ( ! DAC960_V2_NewPhysicalDeviceInfo ( Controller , Channel , TargetID , LogicalUnit ) )
break ;
PhysicalDeviceInfo = ( DAC960_V2_PhysicalDeviceInfo_T * )
kmalloc ( sizeof ( DAC960_V2_PhysicalDeviceInfo_T ) , GFP_ATOMIC ) ;
if ( PhysicalDeviceInfo = = NULL )
return DAC960_Failure ( Controller , " PHYSICAL DEVICE ALLOCATION " ) ;
Controller - > V2 . PhysicalDeviceInformation [ PhysicalDeviceIndex ] =
PhysicalDeviceInfo ;
memcpy ( PhysicalDeviceInfo , NewPhysicalDeviceInfo ,
sizeof ( DAC960_V2_PhysicalDeviceInfo_T ) ) ;
InquiryUnitSerialNumber = ( DAC960_SCSI_Inquiry_UnitSerialNumber_T * )
kmalloc ( sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) , GFP_ATOMIC ) ;
if ( InquiryUnitSerialNumber = = NULL ) {
kfree ( PhysicalDeviceInfo ) ;
return DAC960_Failure ( Controller , " SERIAL NUMBER ALLOCATION " ) ;
}
Controller - > V2 . InquiryUnitSerialNumber [ PhysicalDeviceIndex ] =
InquiryUnitSerialNumber ;
Channel = NewPhysicalDeviceInfo - > Channel ;
TargetID = NewPhysicalDeviceInfo - > TargetID ;
LogicalUnit = NewPhysicalDeviceInfo - > LogicalUnit ;
/*
Some devices do NOT have Unit Serial Numbers .
This command fails for them . But , we still want to
remember those devices are there . Construct a
UnitSerialNumber structure for the failure case .
*/
if ( ! DAC960_V2_NewInquiryUnitSerialNumber ( Controller , Channel , TargetID , LogicalUnit ) ) {
memset ( InquiryUnitSerialNumber , 0 ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ) ;
InquiryUnitSerialNumber - > PeripheralDeviceType = 0x1F ;
} else
memcpy ( InquiryUnitSerialNumber , NewInquiryUnitSerialNumber ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ) ;
PhysicalDeviceIndex + + ;
LogicalUnit + + ;
}
return true ;
}
/*
DAC960_SanitizeInquiryData sanitizes the Vendor , Model , Revision , and
Product Serial Number fields of the Inquiry Standard Data and Inquiry
Unit Serial Number structures .
*/
static void DAC960_SanitizeInquiryData ( DAC960_SCSI_Inquiry_T
* InquiryStandardData ,
DAC960_SCSI_Inquiry_UnitSerialNumber_T
* InquiryUnitSerialNumber ,
unsigned char * Vendor ,
unsigned char * Model ,
unsigned char * Revision ,
unsigned char * SerialNumber )
{
int SerialNumberLength , i ;
if ( InquiryStandardData - > PeripheralDeviceType = = 0x1F ) return ;
for ( i = 0 ; i < sizeof ( InquiryStandardData - > VendorIdentification ) ; i + + )
{
unsigned char VendorCharacter =
InquiryStandardData - > VendorIdentification [ i ] ;
Vendor [ i ] = ( VendorCharacter > = ' ' & & VendorCharacter < = ' ~ '
? VendorCharacter : ' ' ) ;
}
Vendor [ sizeof ( InquiryStandardData - > VendorIdentification ) ] = ' \0 ' ;
for ( i = 0 ; i < sizeof ( InquiryStandardData - > ProductIdentification ) ; i + + )
{
unsigned char ModelCharacter =
InquiryStandardData - > ProductIdentification [ i ] ;
Model [ i ] = ( ModelCharacter > = ' ' & & ModelCharacter < = ' ~ '
? ModelCharacter : ' ' ) ;
}
Model [ sizeof ( InquiryStandardData - > ProductIdentification ) ] = ' \0 ' ;
for ( i = 0 ; i < sizeof ( InquiryStandardData - > ProductRevisionLevel ) ; i + + )
{
unsigned char RevisionCharacter =
InquiryStandardData - > ProductRevisionLevel [ i ] ;
Revision [ i ] = ( RevisionCharacter > = ' ' & & RevisionCharacter < = ' ~ '
? RevisionCharacter : ' ' ) ;
}
Revision [ sizeof ( InquiryStandardData - > ProductRevisionLevel ) ] = ' \0 ' ;
if ( InquiryUnitSerialNumber - > PeripheralDeviceType = = 0x1F ) return ;
SerialNumberLength = InquiryUnitSerialNumber - > PageLength ;
if ( SerialNumberLength >
sizeof ( InquiryUnitSerialNumber - > ProductSerialNumber ) )
SerialNumberLength = sizeof ( InquiryUnitSerialNumber - > ProductSerialNumber ) ;
for ( i = 0 ; i < SerialNumberLength ; i + + )
{
unsigned char SerialNumberCharacter =
InquiryUnitSerialNumber - > ProductSerialNumber [ i ] ;
SerialNumber [ i ] =
( SerialNumberCharacter > = ' ' & & SerialNumberCharacter < = ' ~ '
? SerialNumberCharacter : ' ' ) ;
}
SerialNumber [ SerialNumberLength ] = ' \0 ' ;
}
/*
DAC960_V1_ReportDeviceConfiguration reports the Device Configuration
Information for DAC960 V1 Firmware Controllers .
*/
static boolean DAC960_V1_ReportDeviceConfiguration ( DAC960_Controller_T
* Controller )
{
int LogicalDriveNumber , Channel , TargetID ;
DAC960_Info ( " Physical Devices: \n " , Controller ) ;
for ( Channel = 0 ; Channel < Controller - > Channels ; Channel + + )
for ( TargetID = 0 ; TargetID < Controller - > Targets ; TargetID + + )
{
DAC960_SCSI_Inquiry_T * InquiryStandardData =
& Controller - > V1 . InquiryStandardData [ Channel ] [ TargetID ] ;
DAC960_SCSI_Inquiry_UnitSerialNumber_T * InquiryUnitSerialNumber =
& Controller - > V1 . InquiryUnitSerialNumber [ Channel ] [ TargetID ] ;
DAC960_V1_DeviceState_T * DeviceState =
& Controller - > V1 . DeviceState [ Channel ] [ TargetID ] ;
DAC960_V1_ErrorTableEntry_T * ErrorEntry =
& Controller - > V1 . ErrorTable . ErrorTableEntries [ Channel ] [ TargetID ] ;
char Vendor [ 1 + sizeof ( InquiryStandardData - > VendorIdentification ) ] ;
char Model [ 1 + sizeof ( InquiryStandardData - > ProductIdentification ) ] ;
char Revision [ 1 + sizeof ( InquiryStandardData - > ProductRevisionLevel ) ] ;
char SerialNumber [ 1 + sizeof ( InquiryUnitSerialNumber
- > ProductSerialNumber ) ] ;
if ( InquiryStandardData - > PeripheralDeviceType = = 0x1F ) continue ;
DAC960_SanitizeInquiryData ( InquiryStandardData , InquiryUnitSerialNumber ,
Vendor , Model , Revision , SerialNumber ) ;
DAC960_Info ( " %d:%d%s Vendor: %s Model: %s Revision: %s \n " ,
Controller , Channel , TargetID , ( TargetID < 10 ? " " : " " ) ,
Vendor , Model , Revision ) ;
if ( InquiryUnitSerialNumber - > PeripheralDeviceType ! = 0x1F )
DAC960_Info ( " Serial Number: %s \n " , Controller , SerialNumber ) ;
if ( DeviceState - > Present & &
DeviceState - > DeviceType = = DAC960_V1_DiskType )
{
if ( Controller - > V1 . DeviceResetCount [ Channel ] [ TargetID ] > 0 )
DAC960_Info ( " Disk Status: %s, %u blocks, %d resets \n " ,
Controller ,
( DeviceState - > DeviceState = = DAC960_V1_Device_Dead
? " Dead "
: DeviceState - > DeviceState
= = DAC960_V1_Device_WriteOnly
? " Write-Only "
: DeviceState - > DeviceState
= = DAC960_V1_Device_Online
? " Online " : " Standby " ) ,
DeviceState - > DiskSize ,
Controller - > V1 . DeviceResetCount [ Channel ] [ TargetID ] ) ;
else
DAC960_Info ( " Disk Status: %s, %u blocks \n " , Controller ,
( DeviceState - > DeviceState = = DAC960_V1_Device_Dead
? " Dead "
: DeviceState - > DeviceState
= = DAC960_V1_Device_WriteOnly
? " Write-Only "
: DeviceState - > DeviceState
= = DAC960_V1_Device_Online
? " Online " : " Standby " ) ,
DeviceState - > DiskSize ) ;
}
if ( ErrorEntry - > ParityErrorCount > 0 | |
ErrorEntry - > SoftErrorCount > 0 | |
ErrorEntry - > HardErrorCount > 0 | |
ErrorEntry - > MiscErrorCount > 0 )
DAC960_Info ( " Errors - Parity: %d, Soft: %d, "
" Hard: %d, Misc: %d \n " , Controller ,
ErrorEntry - > ParityErrorCount ,
ErrorEntry - > SoftErrorCount ,
ErrorEntry - > HardErrorCount ,
ErrorEntry - > MiscErrorCount ) ;
}
DAC960_Info ( " Logical Drives: \n " , Controller ) ;
for ( LogicalDriveNumber = 0 ;
LogicalDriveNumber < Controller - > LogicalDriveCount ;
LogicalDriveNumber + + )
{
DAC960_V1_LogicalDriveInformation_T * LogicalDriveInformation =
& Controller - > V1 . LogicalDriveInformation [ LogicalDriveNumber ] ;
DAC960_Info ( " /dev/rd/c%dd%d: RAID-%d, %s, %u blocks, %s \n " ,
Controller , Controller - > ControllerNumber , LogicalDriveNumber ,
LogicalDriveInformation - > RAIDLevel ,
( LogicalDriveInformation - > LogicalDriveState
= = DAC960_V1_LogicalDrive_Online
? " Online "
: LogicalDriveInformation - > LogicalDriveState
= = DAC960_V1_LogicalDrive_Critical
? " Critical " : " Offline " ) ,
LogicalDriveInformation - > LogicalDriveSize ,
( LogicalDriveInformation - > WriteBack
? " Write Back " : " Write Thru " ) ) ;
}
return true ;
}
/*
DAC960_V2_ReportDeviceConfiguration reports the Device Configuration
Information for DAC960 V2 Firmware Controllers .
*/
static boolean DAC960_V2_ReportDeviceConfiguration ( DAC960_Controller_T
* Controller )
{
int PhysicalDeviceIndex , LogicalDriveNumber ;
DAC960_Info ( " Physical Devices: \n " , Controller ) ;
for ( PhysicalDeviceIndex = 0 ;
PhysicalDeviceIndex < DAC960_V2_MaxPhysicalDevices ;
PhysicalDeviceIndex + + )
{
DAC960_V2_PhysicalDeviceInfo_T * PhysicalDeviceInfo =
Controller - > V2 . PhysicalDeviceInformation [ PhysicalDeviceIndex ] ;
DAC960_SCSI_Inquiry_T * InquiryStandardData =
( DAC960_SCSI_Inquiry_T * ) & PhysicalDeviceInfo - > SCSI_InquiryData ;
DAC960_SCSI_Inquiry_UnitSerialNumber_T * InquiryUnitSerialNumber =
Controller - > V2 . InquiryUnitSerialNumber [ PhysicalDeviceIndex ] ;
char Vendor [ 1 + sizeof ( InquiryStandardData - > VendorIdentification ) ] ;
char Model [ 1 + sizeof ( InquiryStandardData - > ProductIdentification ) ] ;
char Revision [ 1 + sizeof ( InquiryStandardData - > ProductRevisionLevel ) ] ;
char SerialNumber [ 1 + sizeof ( InquiryUnitSerialNumber - > ProductSerialNumber ) ] ;
if ( PhysicalDeviceInfo = = NULL ) break ;
DAC960_SanitizeInquiryData ( InquiryStandardData , InquiryUnitSerialNumber ,
Vendor , Model , Revision , SerialNumber ) ;
DAC960_Info ( " %d:%d%s Vendor: %s Model: %s Revision: %s \n " ,
Controller ,
PhysicalDeviceInfo - > Channel ,
PhysicalDeviceInfo - > TargetID ,
( PhysicalDeviceInfo - > TargetID < 10 ? " " : " " ) ,
Vendor , Model , Revision ) ;
if ( PhysicalDeviceInfo - > NegotiatedSynchronousMegaTransfers = = 0 )
DAC960_Info ( " %sAsynchronous \n " , Controller ,
( PhysicalDeviceInfo - > NegotiatedDataWidthBits = = 16
? " Wide " : " " ) ) ;
else
DAC960_Info ( " %sSynchronous at %d MB/sec \n " , Controller ,
( PhysicalDeviceInfo - > NegotiatedDataWidthBits = = 16
? " Wide " : " " ) ,
( PhysicalDeviceInfo - > NegotiatedSynchronousMegaTransfers
* PhysicalDeviceInfo - > NegotiatedDataWidthBits / 8 ) ) ;
if ( InquiryUnitSerialNumber - > PeripheralDeviceType ! = 0x1F )
DAC960_Info ( " Serial Number: %s \n " , Controller , SerialNumber ) ;
if ( PhysicalDeviceInfo - > PhysicalDeviceState = =
DAC960_V2_Device_Unconfigured )
continue ;
DAC960_Info ( " Disk Status: %s, %u blocks \n " , Controller ,
( PhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Online
? " Online "
: PhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Rebuild
? " Rebuild "
: PhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Missing
? " Missing "
: PhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Critical
? " Critical "
: PhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Dead
? " Dead "
: PhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_SuspectedDead
? " Suspected-Dead "
: PhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_CommandedOffline
? " Commanded-Offline "
: PhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Standby
? " Standby " : " Unknown " ) ,
PhysicalDeviceInfo - > ConfigurableDeviceSize ) ;
if ( PhysicalDeviceInfo - > ParityErrors = = 0 & &
PhysicalDeviceInfo - > SoftErrors = = 0 & &
PhysicalDeviceInfo - > HardErrors = = 0 & &
PhysicalDeviceInfo - > MiscellaneousErrors = = 0 & &
PhysicalDeviceInfo - > CommandTimeouts = = 0 & &
PhysicalDeviceInfo - > Retries = = 0 & &
PhysicalDeviceInfo - > Aborts = = 0 & &
PhysicalDeviceInfo - > PredictedFailuresDetected = = 0 )
continue ;
DAC960_Info ( " Errors - Parity: %d, Soft: %d, "
" Hard: %d, Misc: %d \n " , Controller ,
PhysicalDeviceInfo - > ParityErrors ,
PhysicalDeviceInfo - > SoftErrors ,
PhysicalDeviceInfo - > HardErrors ,
PhysicalDeviceInfo - > MiscellaneousErrors ) ;
DAC960_Info ( " Timeouts: %d, Retries: %d, "
" Aborts: %d, Predicted: %d \n " , Controller ,
PhysicalDeviceInfo - > CommandTimeouts ,
PhysicalDeviceInfo - > Retries ,
PhysicalDeviceInfo - > Aborts ,
PhysicalDeviceInfo - > PredictedFailuresDetected ) ;
}
DAC960_Info ( " Logical Drives: \n " , Controller ) ;
for ( LogicalDriveNumber = 0 ;
LogicalDriveNumber < DAC960_MaxLogicalDrives ;
LogicalDriveNumber + + )
{
DAC960_V2_LogicalDeviceInfo_T * LogicalDeviceInfo =
Controller - > V2 . LogicalDeviceInformation [ LogicalDriveNumber ] ;
unsigned char * ReadCacheStatus [ ] = { " Read Cache Disabled " ,
" Read Cache Enabled " ,
" Read Ahead Enabled " ,
" Intelligent Read Ahead Enabled " ,
" - " , " - " , " - " , " - " } ;
unsigned char * WriteCacheStatus [ ] = { " Write Cache Disabled " ,
" Logical Device Read Only " ,
" Write Cache Enabled " ,
" Intelligent Write Cache Enabled " ,
" - " , " - " , " - " , " - " } ;
unsigned char * GeometryTranslation ;
if ( LogicalDeviceInfo = = NULL ) continue ;
switch ( LogicalDeviceInfo - > DriveGeometry )
{
case DAC960_V2_Geometry_128_32 :
GeometryTranslation = " 128/32 " ;
break ;
case DAC960_V2_Geometry_255_63 :
GeometryTranslation = " 255/63 " ;
break ;
default :
GeometryTranslation = " Invalid " ;
DAC960_Error ( " Illegal Logical Device Geometry %d \n " ,
Controller , LogicalDeviceInfo - > DriveGeometry ) ;
break ;
}
DAC960_Info ( " /dev/rd/c%dd%d: RAID-%d, %s, %u blocks \n " ,
Controller , Controller - > ControllerNumber , LogicalDriveNumber ,
LogicalDeviceInfo - > RAIDLevel ,
( LogicalDeviceInfo - > LogicalDeviceState
= = DAC960_V2_LogicalDevice_Online
? " Online "
: LogicalDeviceInfo - > LogicalDeviceState
= = DAC960_V2_LogicalDevice_Critical
? " Critical " : " Offline " ) ,
LogicalDeviceInfo - > ConfigurableDeviceSize ) ;
DAC960_Info ( " Logical Device %s, BIOS Geometry: %s \n " ,
Controller ,
( LogicalDeviceInfo - > LogicalDeviceControl
. LogicalDeviceInitialized
? " Initialized " : " Uninitialized " ) ,
GeometryTranslation ) ;
if ( LogicalDeviceInfo - > StripeSize = = 0 )
{
if ( LogicalDeviceInfo - > CacheLineSize = = 0 )
DAC960_Info ( " Stripe Size: N/A, "
" Segment Size: N/A \n " , Controller ) ;
else
DAC960_Info ( " Stripe Size: N/A, "
" Segment Size: %dKB \n " , Controller ,
1 < < ( LogicalDeviceInfo - > CacheLineSize - 2 ) ) ;
}
else
{
if ( LogicalDeviceInfo - > CacheLineSize = = 0 )
DAC960_Info ( " Stripe Size: %dKB, "
" Segment Size: N/A \n " , Controller ,
1 < < ( LogicalDeviceInfo - > StripeSize - 2 ) ) ;
else
DAC960_Info ( " Stripe Size: %dKB, "
" Segment Size: %dKB \n " , Controller ,
1 < < ( LogicalDeviceInfo - > StripeSize - 2 ) ,
1 < < ( LogicalDeviceInfo - > CacheLineSize - 2 ) ) ;
}
DAC960_Info ( " %s, %s \n " , Controller ,
ReadCacheStatus [
LogicalDeviceInfo - > LogicalDeviceControl . ReadCache ] ,
WriteCacheStatus [
LogicalDeviceInfo - > LogicalDeviceControl . WriteCache ] ) ;
if ( LogicalDeviceInfo - > SoftErrors > 0 | |
LogicalDeviceInfo - > CommandsFailed > 0 | |
LogicalDeviceInfo - > DeferredWriteErrors )
DAC960_Info ( " Errors - Soft: %d, Failed: %d, "
" Deferred Write: %d \n " , Controller ,
LogicalDeviceInfo - > SoftErrors ,
LogicalDeviceInfo - > CommandsFailed ,
LogicalDeviceInfo - > DeferredWriteErrors ) ;
}
return true ;
}
/*
DAC960_RegisterBlockDevice registers the Block Device structures
associated with Controller .
*/
static boolean DAC960_RegisterBlockDevice ( DAC960_Controller_T * Controller )
{
int MajorNumber = DAC960_MAJOR + Controller - > ControllerNumber ;
int n ;
/*
Register the Block Device Major Number for this DAC960 Controller .
*/
if ( register_blkdev ( MajorNumber , " dac960 " ) < 0 )
return false ;
for ( n = 0 ; n < DAC960_MaxLogicalDrives ; n + + ) {
struct gendisk * disk = Controller - > disks [ n ] ;
struct request_queue * RequestQueue ;
/* for now, let all request queues share controller's lock */
RequestQueue = blk_init_queue ( DAC960_RequestFunction , & Controller - > queue_lock ) ;
if ( ! RequestQueue ) {
printk ( " DAC960: failure to allocate request queue \n " ) ;
continue ;
}
Controller - > RequestQueue [ n ] = RequestQueue ;
blk_queue_bounce_limit ( RequestQueue , Controller - > BounceBufferLimit ) ;
RequestQueue - > queuedata = Controller ;
blk_queue_max_hw_segments ( RequestQueue , Controller - > DriverScatterGatherLimit ) ;
blk_queue_max_phys_segments ( RequestQueue , Controller - > DriverScatterGatherLimit ) ;
blk_queue_max_sectors ( RequestQueue , Controller - > MaxBlocksPerCommand ) ;
disk - > queue = RequestQueue ;
sprintf ( disk - > disk_name , " rd/c%dd%d " , Controller - > ControllerNumber , n ) ;
sprintf ( disk - > devfs_name , " rd/host%d/target%d " , Controller - > ControllerNumber , n ) ;
disk - > major = MajorNumber ;
disk - > first_minor = n < < DAC960_MaxPartitionsBits ;
disk - > fops = & DAC960_BlockDeviceOperations ;
}
/*
Indicate the Block Device Registration completed successfully ,
*/
return true ;
}
/*
DAC960_UnregisterBlockDevice unregisters the Block Device structures
associated with Controller .
*/
static void DAC960_UnregisterBlockDevice ( DAC960_Controller_T * Controller )
{
int MajorNumber = DAC960_MAJOR + Controller - > ControllerNumber ;
int disk ;
/* does order matter when deleting gendisk and cleanup in request queue? */
for ( disk = 0 ; disk < DAC960_MaxLogicalDrives ; disk + + ) {
del_gendisk ( Controller - > disks [ disk ] ) ;
blk_cleanup_queue ( Controller - > RequestQueue [ disk ] ) ;
Controller - > RequestQueue [ disk ] = NULL ;
}
/*
Unregister the Block Device Major Number for this DAC960 Controller .
*/
unregister_blkdev ( MajorNumber , " dac960 " ) ;
}
/*
DAC960_ComputeGenericDiskInfo computes the values for the Generic Disk
Information Partition Sector Counts and Block Sizes .
*/
static void DAC960_ComputeGenericDiskInfo ( DAC960_Controller_T * Controller )
{
int disk ;
for ( disk = 0 ; disk < DAC960_MaxLogicalDrives ; disk + + )
set_capacity ( Controller - > disks [ disk ] , disk_size ( Controller , disk ) ) ;
}
/*
DAC960_ReportErrorStatus reports Controller BIOS Messages passed through
the Error Status Register when the driver performs the BIOS handshaking .
It returns true for fatal errors and false otherwise .
*/
static boolean DAC960_ReportErrorStatus ( DAC960_Controller_T * Controller ,
unsigned char ErrorStatus ,
unsigned char Parameter0 ,
unsigned char Parameter1 )
{
switch ( ErrorStatus )
{
case 0x00 :
DAC960_Notice ( " Physical Device %d:%d Not Responding \n " ,
Controller , Parameter1 , Parameter0 ) ;
break ;
case 0x08 :
if ( Controller - > DriveSpinUpMessageDisplayed ) break ;
DAC960_Notice ( " Spinning Up Drives \n " , Controller ) ;
Controller - > DriveSpinUpMessageDisplayed = true ;
break ;
case 0x30 :
DAC960_Notice ( " Configuration Checksum Error \n " , Controller ) ;
break ;
case 0x60 :
DAC960_Notice ( " Mirror Race Recovery Failed \n " , Controller ) ;
break ;
case 0x70 :
DAC960_Notice ( " Mirror Race Recovery In Progress \n " , Controller ) ;
break ;
case 0x90 :
DAC960_Notice ( " Physical Device %d:%d COD Mismatch \n " ,
Controller , Parameter1 , Parameter0 ) ;
break ;
case 0xA0 :
DAC960_Notice ( " Logical Drive Installation Aborted \n " , Controller ) ;
break ;
case 0xB0 :
DAC960_Notice ( " Mirror Race On A Critical Logical Drive \n " , Controller ) ;
break ;
case 0xD0 :
DAC960_Notice ( " New Controller Configuration Found \n " , Controller ) ;
break ;
case 0xF0 :
DAC960_Error ( " Fatal Memory Parity Error for Controller at \n " , Controller ) ;
return true ;
default :
DAC960_Error ( " Unknown Initialization Error %02X for Controller at \n " ,
Controller , ErrorStatus ) ;
return true ;
}
return false ;
}
/*
* DAC960_DetectCleanup releases the resources that were allocated
* during DAC960_DetectController ( ) . DAC960_DetectController can
* has several internal failure points , so not ALL resources may
* have been allocated . It ' s important to free only
* resources that HAVE been allocated . The code below always
* tests that the resource has been allocated before attempting to
* free it .
*/
static void DAC960_DetectCleanup ( DAC960_Controller_T * Controller )
{
int i ;
/* Free the memory mailbox, status, and related structures */
free_dma_loaf ( Controller - > PCIDevice , & Controller - > DmaPages ) ;
if ( Controller - > MemoryMappedAddress ) {
switch ( Controller - > HardwareType )
{
2005-05-05 16:15:58 -07:00
case DAC960_GEM_Controller :
DAC960_GEM_DisableInterrupts ( Controller - > BaseAddress ) ;
break ;
2005-04-16 15:20:36 -07:00
case DAC960_BA_Controller :
DAC960_BA_DisableInterrupts ( Controller - > BaseAddress ) ;
break ;
case DAC960_LP_Controller :
DAC960_LP_DisableInterrupts ( Controller - > BaseAddress ) ;
break ;
case DAC960_LA_Controller :
DAC960_LA_DisableInterrupts ( Controller - > BaseAddress ) ;
break ;
case DAC960_PG_Controller :
DAC960_PG_DisableInterrupts ( Controller - > BaseAddress ) ;
break ;
case DAC960_PD_Controller :
DAC960_PD_DisableInterrupts ( Controller - > BaseAddress ) ;
break ;
case DAC960_P_Controller :
DAC960_PD_DisableInterrupts ( Controller - > BaseAddress ) ;
break ;
}
iounmap ( Controller - > MemoryMappedAddress ) ;
}
if ( Controller - > IRQ_Channel )
free_irq ( Controller - > IRQ_Channel , Controller ) ;
if ( Controller - > IO_Address )
release_region ( Controller - > IO_Address , 0x80 ) ;
pci_disable_device ( Controller - > PCIDevice ) ;
for ( i = 0 ; ( i < DAC960_MaxLogicalDrives ) & & Controller - > disks [ i ] ; i + + )
put_disk ( Controller - > disks [ i ] ) ;
DAC960_Controllers [ Controller - > ControllerNumber ] = NULL ;
kfree ( Controller ) ;
}
/*
DAC960_DetectController detects Mylex DAC960 / AcceleRAID / eXtremeRAID
PCI RAID Controllers by interrogating the PCI Configuration Space for
Controller Type .
*/
static DAC960_Controller_T *
DAC960_DetectController ( struct pci_dev * PCI_Device ,
const struct pci_device_id * entry )
{
struct DAC960_privdata * privdata =
( struct DAC960_privdata * ) entry - > driver_data ;
irqreturn_t ( * InterruptHandler ) ( int , void * , struct pt_regs * ) =
privdata - > InterruptHandler ;
unsigned int MemoryWindowSize = privdata - > MemoryWindowSize ;
DAC960_Controller_T * Controller = NULL ;
unsigned char DeviceFunction = PCI_Device - > devfn ;
unsigned char ErrorStatus , Parameter0 , Parameter1 ;
unsigned int IRQ_Channel ;
void __iomem * BaseAddress ;
int i ;
Controller = ( DAC960_Controller_T * )
kmalloc ( sizeof ( DAC960_Controller_T ) , GFP_ATOMIC ) ;
if ( Controller = = NULL ) {
DAC960_Error ( " Unable to allocate Controller structure for "
" Controller at \n " , NULL ) ;
return NULL ;
}
memset ( Controller , 0 , sizeof ( DAC960_Controller_T ) ) ;
Controller - > ControllerNumber = DAC960_ControllerCount ;
DAC960_Controllers [ DAC960_ControllerCount + + ] = Controller ;
Controller - > Bus = PCI_Device - > bus - > number ;
Controller - > FirmwareType = privdata - > FirmwareType ;
Controller - > HardwareType = privdata - > HardwareType ;
Controller - > Device = DeviceFunction > > 3 ;
Controller - > Function = DeviceFunction & 0x7 ;
Controller - > PCIDevice = PCI_Device ;
strcpy ( Controller - > FullModelName , " DAC960 " ) ;
if ( pci_enable_device ( PCI_Device ) )
goto Failure ;
switch ( Controller - > HardwareType )
{
2005-05-05 16:15:58 -07:00
case DAC960_GEM_Controller :
Controller - > PCI_Address = pci_resource_start ( PCI_Device , 0 ) ;
break ;
2005-04-16 15:20:36 -07:00
case DAC960_BA_Controller :
Controller - > PCI_Address = pci_resource_start ( PCI_Device , 0 ) ;
break ;
case DAC960_LP_Controller :
Controller - > PCI_Address = pci_resource_start ( PCI_Device , 0 ) ;
break ;
case DAC960_LA_Controller :
Controller - > PCI_Address = pci_resource_start ( PCI_Device , 0 ) ;
break ;
case DAC960_PG_Controller :
Controller - > PCI_Address = pci_resource_start ( PCI_Device , 0 ) ;
break ;
case DAC960_PD_Controller :
Controller - > IO_Address = pci_resource_start ( PCI_Device , 0 ) ;
Controller - > PCI_Address = pci_resource_start ( PCI_Device , 1 ) ;
break ;
case DAC960_P_Controller :
Controller - > IO_Address = pci_resource_start ( PCI_Device , 0 ) ;
Controller - > PCI_Address = pci_resource_start ( PCI_Device , 1 ) ;
break ;
}
pci_set_drvdata ( PCI_Device , ( void * ) ( ( long ) Controller - > ControllerNumber ) ) ;
for ( i = 0 ; i < DAC960_MaxLogicalDrives ; i + + ) {
Controller - > disks [ i ] = alloc_disk ( 1 < < DAC960_MaxPartitionsBits ) ;
if ( ! Controller - > disks [ i ] )
goto Failure ;
Controller - > disks [ i ] - > private_data = ( void * ) ( ( long ) i ) ;
}
init_waitqueue_head ( & Controller - > CommandWaitQueue ) ;
init_waitqueue_head ( & Controller - > HealthStatusWaitQueue ) ;
spin_lock_init ( & Controller - > queue_lock ) ;
DAC960_AnnounceDriver ( Controller ) ;
/*
Map the Controller Register Window .
*/
if ( MemoryWindowSize < PAGE_SIZE )
MemoryWindowSize = PAGE_SIZE ;
Controller - > MemoryMappedAddress =
ioremap_nocache ( Controller - > PCI_Address & PAGE_MASK , MemoryWindowSize ) ;
Controller - > BaseAddress =
Controller - > MemoryMappedAddress + ( Controller - > PCI_Address & ~ PAGE_MASK ) ;
if ( Controller - > MemoryMappedAddress = = NULL )
{
DAC960_Error ( " Unable to map Controller Register Window for "
" Controller at \n " , Controller ) ;
goto Failure ;
}
BaseAddress = Controller - > BaseAddress ;
switch ( Controller - > HardwareType )
{
2005-05-05 16:15:58 -07:00
case DAC960_GEM_Controller :
DAC960_GEM_DisableInterrupts ( BaseAddress ) ;
DAC960_GEM_AcknowledgeHardwareMailboxStatus ( BaseAddress ) ;
udelay ( 1000 ) ;
while ( DAC960_GEM_InitializationInProgressP ( BaseAddress ) )
{
if ( DAC960_GEM_ReadErrorStatus ( BaseAddress , & ErrorStatus ,
& Parameter0 , & Parameter1 ) & &
DAC960_ReportErrorStatus ( Controller , ErrorStatus ,
Parameter0 , Parameter1 ) )
goto Failure ;
udelay ( 10 ) ;
}
if ( ! DAC960_V2_EnableMemoryMailboxInterface ( Controller ) )
{
DAC960_Error ( " Unable to Enable Memory Mailbox Interface "
" for Controller at \n " , Controller ) ;
goto Failure ;
}
DAC960_GEM_EnableInterrupts ( BaseAddress ) ;
Controller - > QueueCommand = DAC960_GEM_QueueCommand ;
Controller - > ReadControllerConfiguration =
DAC960_V2_ReadControllerConfiguration ;
Controller - > ReadDeviceConfiguration =
DAC960_V2_ReadDeviceConfiguration ;
Controller - > ReportDeviceConfiguration =
DAC960_V2_ReportDeviceConfiguration ;
Controller - > QueueReadWriteCommand =
DAC960_V2_QueueReadWriteCommand ;
break ;
2005-04-16 15:20:36 -07:00
case DAC960_BA_Controller :
DAC960_BA_DisableInterrupts ( BaseAddress ) ;
DAC960_BA_AcknowledgeHardwareMailboxStatus ( BaseAddress ) ;
udelay ( 1000 ) ;
while ( DAC960_BA_InitializationInProgressP ( BaseAddress ) )
{
if ( DAC960_BA_ReadErrorStatus ( BaseAddress , & ErrorStatus ,
& Parameter0 , & Parameter1 ) & &
DAC960_ReportErrorStatus ( Controller , ErrorStatus ,
Parameter0 , Parameter1 ) )
goto Failure ;
udelay ( 10 ) ;
}
if ( ! DAC960_V2_EnableMemoryMailboxInterface ( Controller ) )
{
DAC960_Error ( " Unable to Enable Memory Mailbox Interface "
" for Controller at \n " , Controller ) ;
goto Failure ;
}
DAC960_BA_EnableInterrupts ( BaseAddress ) ;
Controller - > QueueCommand = DAC960_BA_QueueCommand ;
Controller - > ReadControllerConfiguration =
DAC960_V2_ReadControllerConfiguration ;
Controller - > ReadDeviceConfiguration =
DAC960_V2_ReadDeviceConfiguration ;
Controller - > ReportDeviceConfiguration =
DAC960_V2_ReportDeviceConfiguration ;
Controller - > QueueReadWriteCommand =
DAC960_V2_QueueReadWriteCommand ;
break ;
case DAC960_LP_Controller :
DAC960_LP_DisableInterrupts ( BaseAddress ) ;
DAC960_LP_AcknowledgeHardwareMailboxStatus ( BaseAddress ) ;
udelay ( 1000 ) ;
while ( DAC960_LP_InitializationInProgressP ( BaseAddress ) )
{
if ( DAC960_LP_ReadErrorStatus ( BaseAddress , & ErrorStatus ,
& Parameter0 , & Parameter1 ) & &
DAC960_ReportErrorStatus ( Controller , ErrorStatus ,
Parameter0 , Parameter1 ) )
goto Failure ;
udelay ( 10 ) ;
}
if ( ! DAC960_V2_EnableMemoryMailboxInterface ( Controller ) )
{
DAC960_Error ( " Unable to Enable Memory Mailbox Interface "
" for Controller at \n " , Controller ) ;
goto Failure ;
}
DAC960_LP_EnableInterrupts ( BaseAddress ) ;
Controller - > QueueCommand = DAC960_LP_QueueCommand ;
Controller - > ReadControllerConfiguration =
DAC960_V2_ReadControllerConfiguration ;
Controller - > ReadDeviceConfiguration =
DAC960_V2_ReadDeviceConfiguration ;
Controller - > ReportDeviceConfiguration =
DAC960_V2_ReportDeviceConfiguration ;
Controller - > QueueReadWriteCommand =
DAC960_V2_QueueReadWriteCommand ;
break ;
case DAC960_LA_Controller :
DAC960_LA_DisableInterrupts ( BaseAddress ) ;
DAC960_LA_AcknowledgeHardwareMailboxStatus ( BaseAddress ) ;
udelay ( 1000 ) ;
while ( DAC960_LA_InitializationInProgressP ( BaseAddress ) )
{
if ( DAC960_LA_ReadErrorStatus ( BaseAddress , & ErrorStatus ,
& Parameter0 , & Parameter1 ) & &
DAC960_ReportErrorStatus ( Controller , ErrorStatus ,
Parameter0 , Parameter1 ) )
goto Failure ;
udelay ( 10 ) ;
}
if ( ! DAC960_V1_EnableMemoryMailboxInterface ( Controller ) )
{
DAC960_Error ( " Unable to Enable Memory Mailbox Interface "
" for Controller at \n " , Controller ) ;
goto Failure ;
}
DAC960_LA_EnableInterrupts ( BaseAddress ) ;
if ( Controller - > V1 . DualModeMemoryMailboxInterface )
Controller - > QueueCommand = DAC960_LA_QueueCommandDualMode ;
else Controller - > QueueCommand = DAC960_LA_QueueCommandSingleMode ;
Controller - > ReadControllerConfiguration =
DAC960_V1_ReadControllerConfiguration ;
Controller - > ReadDeviceConfiguration =
DAC960_V1_ReadDeviceConfiguration ;
Controller - > ReportDeviceConfiguration =
DAC960_V1_ReportDeviceConfiguration ;
Controller - > QueueReadWriteCommand =
DAC960_V1_QueueReadWriteCommand ;
break ;
case DAC960_PG_Controller :
DAC960_PG_DisableInterrupts ( BaseAddress ) ;
DAC960_PG_AcknowledgeHardwareMailboxStatus ( BaseAddress ) ;
udelay ( 1000 ) ;
while ( DAC960_PG_InitializationInProgressP ( BaseAddress ) )
{
if ( DAC960_PG_ReadErrorStatus ( BaseAddress , & ErrorStatus ,
& Parameter0 , & Parameter1 ) & &
DAC960_ReportErrorStatus ( Controller , ErrorStatus ,
Parameter0 , Parameter1 ) )
goto Failure ;
udelay ( 10 ) ;
}
if ( ! DAC960_V1_EnableMemoryMailboxInterface ( Controller ) )
{
DAC960_Error ( " Unable to Enable Memory Mailbox Interface "
" for Controller at \n " , Controller ) ;
goto Failure ;
}
DAC960_PG_EnableInterrupts ( BaseAddress ) ;
if ( Controller - > V1 . DualModeMemoryMailboxInterface )
Controller - > QueueCommand = DAC960_PG_QueueCommandDualMode ;
else Controller - > QueueCommand = DAC960_PG_QueueCommandSingleMode ;
Controller - > ReadControllerConfiguration =
DAC960_V1_ReadControllerConfiguration ;
Controller - > ReadDeviceConfiguration =
DAC960_V1_ReadDeviceConfiguration ;
Controller - > ReportDeviceConfiguration =
DAC960_V1_ReportDeviceConfiguration ;
Controller - > QueueReadWriteCommand =
DAC960_V1_QueueReadWriteCommand ;
break ;
case DAC960_PD_Controller :
if ( ! request_region ( Controller - > IO_Address , 0x80 ,
Controller - > FullModelName ) ) {
DAC960_Error ( " IO port 0x%d busy for Controller at \n " ,
Controller , Controller - > IO_Address ) ;
goto Failure ;
}
DAC960_PD_DisableInterrupts ( BaseAddress ) ;
DAC960_PD_AcknowledgeStatus ( BaseAddress ) ;
udelay ( 1000 ) ;
while ( DAC960_PD_InitializationInProgressP ( BaseAddress ) )
{
if ( DAC960_PD_ReadErrorStatus ( BaseAddress , & ErrorStatus ,
& Parameter0 , & Parameter1 ) & &
DAC960_ReportErrorStatus ( Controller , ErrorStatus ,
Parameter0 , Parameter1 ) )
goto Failure ;
udelay ( 10 ) ;
}
if ( ! DAC960_V1_EnableMemoryMailboxInterface ( Controller ) )
{
DAC960_Error ( " Unable to allocate DMA mapped memory "
" for Controller at \n " , Controller ) ;
goto Failure ;
}
DAC960_PD_EnableInterrupts ( BaseAddress ) ;
Controller - > QueueCommand = DAC960_PD_QueueCommand ;
Controller - > ReadControllerConfiguration =
DAC960_V1_ReadControllerConfiguration ;
Controller - > ReadDeviceConfiguration =
DAC960_V1_ReadDeviceConfiguration ;
Controller - > ReportDeviceConfiguration =
DAC960_V1_ReportDeviceConfiguration ;
Controller - > QueueReadWriteCommand =
DAC960_V1_QueueReadWriteCommand ;
break ;
case DAC960_P_Controller :
if ( ! request_region ( Controller - > IO_Address , 0x80 ,
Controller - > FullModelName ) ) {
DAC960_Error ( " IO port 0x%d busy for Controller at \n " ,
Controller , Controller - > IO_Address ) ;
goto Failure ;
}
DAC960_PD_DisableInterrupts ( BaseAddress ) ;
DAC960_PD_AcknowledgeStatus ( BaseAddress ) ;
udelay ( 1000 ) ;
while ( DAC960_PD_InitializationInProgressP ( BaseAddress ) )
{
if ( DAC960_PD_ReadErrorStatus ( BaseAddress , & ErrorStatus ,
& Parameter0 , & Parameter1 ) & &
DAC960_ReportErrorStatus ( Controller , ErrorStatus ,
Parameter0 , Parameter1 ) )
goto Failure ;
udelay ( 10 ) ;
}
if ( ! DAC960_V1_EnableMemoryMailboxInterface ( Controller ) )
{
DAC960_Error ( " Unable to allocate DMA mapped memory "
" for Controller at \n " , Controller ) ;
goto Failure ;
}
DAC960_PD_EnableInterrupts ( BaseAddress ) ;
Controller - > QueueCommand = DAC960_P_QueueCommand ;
Controller - > ReadControllerConfiguration =
DAC960_V1_ReadControllerConfiguration ;
Controller - > ReadDeviceConfiguration =
DAC960_V1_ReadDeviceConfiguration ;
Controller - > ReportDeviceConfiguration =
DAC960_V1_ReportDeviceConfiguration ;
Controller - > QueueReadWriteCommand =
DAC960_V1_QueueReadWriteCommand ;
break ;
}
/*
Acquire shared access to the IRQ Channel .
*/
IRQ_Channel = PCI_Device - > irq ;
if ( request_irq ( IRQ_Channel , InterruptHandler , SA_SHIRQ ,
Controller - > FullModelName , Controller ) < 0 )
{
DAC960_Error ( " Unable to acquire IRQ Channel %d for Controller at \n " ,
Controller , Controller - > IRQ_Channel ) ;
goto Failure ;
}
Controller - > IRQ_Channel = IRQ_Channel ;
Controller - > InitialCommand . CommandIdentifier = 1 ;
Controller - > InitialCommand . Controller = Controller ;
Controller - > Commands [ 0 ] = & Controller - > InitialCommand ;
Controller - > FreeCommands = & Controller - > InitialCommand ;
return Controller ;
Failure :
if ( Controller - > IO_Address = = 0 )
DAC960_Error ( " PCI Bus %d Device %d Function %d I/O Address N/A "
" PCI Address 0x%X \n " , Controller ,
Controller - > Bus , Controller - > Device ,
Controller - > Function , Controller - > PCI_Address ) ;
else
DAC960_Error ( " PCI Bus %d Device %d Function %d I/O Address "
" 0x%X PCI Address 0x%X \n " , Controller ,
Controller - > Bus , Controller - > Device ,
Controller - > Function , Controller - > IO_Address ,
Controller - > PCI_Address ) ;
DAC960_DetectCleanup ( Controller ) ;
DAC960_ControllerCount - - ;
return NULL ;
}
/*
DAC960_InitializeController initializes Controller .
*/
static boolean
DAC960_InitializeController ( DAC960_Controller_T * Controller )
{
if ( DAC960_ReadControllerConfiguration ( Controller ) & &
DAC960_ReportControllerConfiguration ( Controller ) & &
DAC960_CreateAuxiliaryStructures ( Controller ) & &
DAC960_ReadDeviceConfiguration ( Controller ) & &
DAC960_ReportDeviceConfiguration ( Controller ) & &
DAC960_RegisterBlockDevice ( Controller ) )
{
/*
Initialize the Monitoring Timer .
*/
init_timer ( & Controller - > MonitoringTimer ) ;
Controller - > MonitoringTimer . expires =
jiffies + DAC960_MonitoringTimerInterval ;
Controller - > MonitoringTimer . data = ( unsigned long ) Controller ;
Controller - > MonitoringTimer . function = DAC960_MonitoringTimerFunction ;
add_timer ( & Controller - > MonitoringTimer ) ;
Controller - > ControllerInitialized = true ;
return true ;
}
return false ;
}
/*
DAC960_FinalizeController finalizes Controller .
*/
static void DAC960_FinalizeController ( DAC960_Controller_T * Controller )
{
if ( Controller - > ControllerInitialized )
{
unsigned long flags ;
/*
* Acquiring and releasing lock here eliminates
* a very low probability race .
*
* The code below allocates controller command structures
* from the free list without holding the controller lock .
* This is safe assuming there is no other activity on
* the controller at the time .
*
* But , there might be a monitoring command still
* in progress . Setting the Shutdown flag while holding
* the lock ensures that there is no monitoring command
* in the interrupt handler currently , and any monitoring
* commands that complete from this time on will NOT return
* their command structure to the free list .
*/
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
Controller - > ShutdownMonitoringTimer = 1 ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
del_timer_sync ( & Controller - > MonitoringTimer ) ;
if ( Controller - > FirmwareType = = DAC960_V1_Controller )
{
DAC960_Notice ( " Flushing Cache... " , Controller ) ;
DAC960_V1_ExecuteType3 ( Controller , DAC960_V1_Flush , 0 ) ;
DAC960_Notice ( " done \n " , Controller ) ;
if ( Controller - > HardwareType = = DAC960_PD_Controller )
release_region ( Controller - > IO_Address , 0x80 ) ;
}
else
{
DAC960_Notice ( " Flushing Cache... " , Controller ) ;
DAC960_V2_DeviceOperation ( Controller , DAC960_V2_PauseDevice ,
DAC960_V2_RAID_Controller ) ;
DAC960_Notice ( " done \n " , Controller ) ;
}
}
DAC960_UnregisterBlockDevice ( Controller ) ;
DAC960_DestroyAuxiliaryStructures ( Controller ) ;
DAC960_DestroyProcEntries ( Controller ) ;
DAC960_DetectCleanup ( Controller ) ;
}
/*
DAC960_Probe verifies controller ' s existence and
initializes the DAC960 Driver for that controller .
*/
static int
DAC960_Probe ( struct pci_dev * dev , const struct pci_device_id * entry )
{
int disk ;
DAC960_Controller_T * Controller ;
if ( DAC960_ControllerCount = = DAC960_MaxControllers )
{
DAC960_Error ( " More than %d DAC960 Controllers detected - "
" ignoring from Controller at \n " ,
NULL , DAC960_MaxControllers ) ;
return - ENODEV ;
}
Controller = DAC960_DetectController ( dev , entry ) ;
if ( ! Controller )
return - ENODEV ;
if ( ! DAC960_InitializeController ( Controller ) ) {
DAC960_FinalizeController ( Controller ) ;
return - ENODEV ;
}
for ( disk = 0 ; disk < DAC960_MaxLogicalDrives ; disk + + ) {
set_capacity ( Controller - > disks [ disk ] , disk_size ( Controller , disk ) ) ;
add_disk ( Controller - > disks [ disk ] ) ;
}
DAC960_CreateProcEntries ( Controller ) ;
return 0 ;
}
/*
DAC960_Finalize finalizes the DAC960 Driver .
*/
static void DAC960_Remove ( struct pci_dev * PCI_Device )
{
int Controller_Number = ( long ) pci_get_drvdata ( PCI_Device ) ;
DAC960_Controller_T * Controller = DAC960_Controllers [ Controller_Number ] ;
if ( Controller ! = NULL )
DAC960_FinalizeController ( Controller ) ;
}
/*
DAC960_V1_QueueReadWriteCommand prepares and queues a Read / Write Command for
DAC960 V1 Firmware Controllers .
*/
static void DAC960_V1_QueueReadWriteCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
DAC960_V1_ScatterGatherSegment_T * ScatterGatherList =
Command - > V1 . ScatterGatherList ;
struct scatterlist * ScatterList = Command - > V1 . ScatterList ;
DAC960_V1_ClearCommand ( Command ) ;
if ( Command - > SegmentCount = = 1 )
{
if ( Command - > DmaDirection = = PCI_DMA_FROMDEVICE )
CommandMailbox - > Type5 . CommandOpcode = DAC960_V1_Read ;
else
CommandMailbox - > Type5 . CommandOpcode = DAC960_V1_Write ;
CommandMailbox - > Type5 . LD . TransferLength = Command - > BlockCount ;
CommandMailbox - > Type5 . LD . LogicalDriveNumber = Command - > LogicalDriveNumber ;
CommandMailbox - > Type5 . LogicalBlockAddress = Command - > BlockNumber ;
CommandMailbox - > Type5 . BusAddress =
( DAC960_BusAddress32_T ) sg_dma_address ( ScatterList ) ;
}
else
{
int i ;
if ( Command - > DmaDirection = = PCI_DMA_FROMDEVICE )
CommandMailbox - > Type5 . CommandOpcode = DAC960_V1_ReadWithScatterGather ;
else
CommandMailbox - > Type5 . CommandOpcode = DAC960_V1_WriteWithScatterGather ;
CommandMailbox - > Type5 . LD . TransferLength = Command - > BlockCount ;
CommandMailbox - > Type5 . LD . LogicalDriveNumber = Command - > LogicalDriveNumber ;
CommandMailbox - > Type5 . LogicalBlockAddress = Command - > BlockNumber ;
CommandMailbox - > Type5 . BusAddress = Command - > V1 . ScatterGatherListDMA ;
CommandMailbox - > Type5 . ScatterGatherCount = Command - > SegmentCount ;
for ( i = 0 ; i < Command - > SegmentCount ; i + + , ScatterList + + , ScatterGatherList + + ) {
ScatterGatherList - > SegmentDataPointer =
( DAC960_BusAddress32_T ) sg_dma_address ( ScatterList ) ;
ScatterGatherList - > SegmentByteCount =
( DAC960_ByteCount32_T ) sg_dma_len ( ScatterList ) ;
}
}
DAC960_QueueCommand ( Command ) ;
}
/*
DAC960_V2_QueueReadWriteCommand prepares and queues a Read / Write Command for
DAC960 V2 Firmware Controllers .
*/
static void DAC960_V2_QueueReadWriteCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
struct scatterlist * ScatterList = Command - > V2 . ScatterList ;
DAC960_V2_ClearCommand ( Command ) ;
CommandMailbox - > SCSI_10 . CommandOpcode = DAC960_V2_SCSI_10 ;
CommandMailbox - > SCSI_10 . CommandControlBits . DataTransferControllerToHost =
( Command - > DmaDirection = = PCI_DMA_FROMDEVICE ) ;
CommandMailbox - > SCSI_10 . DataTransferSize =
Command - > BlockCount < < DAC960_BlockSizeBits ;
CommandMailbox - > SCSI_10 . RequestSenseBusAddress = Command - > V2 . RequestSenseDMA ;
CommandMailbox - > SCSI_10 . PhysicalDevice =
Controller - > V2 . LogicalDriveToVirtualDevice [ Command - > LogicalDriveNumber ] ;
CommandMailbox - > SCSI_10 . RequestSenseSize = sizeof ( DAC960_SCSI_RequestSense_T ) ;
CommandMailbox - > SCSI_10 . CDBLength = 10 ;
CommandMailbox - > SCSI_10 . SCSI_CDB [ 0 ] =
( Command - > DmaDirection = = PCI_DMA_FROMDEVICE ? 0x28 : 0x2A ) ;
CommandMailbox - > SCSI_10 . SCSI_CDB [ 2 ] = Command - > BlockNumber > > 24 ;
CommandMailbox - > SCSI_10 . SCSI_CDB [ 3 ] = Command - > BlockNumber > > 16 ;
CommandMailbox - > SCSI_10 . SCSI_CDB [ 4 ] = Command - > BlockNumber > > 8 ;
CommandMailbox - > SCSI_10 . SCSI_CDB [ 5 ] = Command - > BlockNumber ;
CommandMailbox - > SCSI_10 . SCSI_CDB [ 7 ] = Command - > BlockCount > > 8 ;
CommandMailbox - > SCSI_10 . SCSI_CDB [ 8 ] = Command - > BlockCount ;
if ( Command - > SegmentCount = = 1 )
{
CommandMailbox - > SCSI_10 . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
( DAC960_BusAddress64_T ) sg_dma_address ( ScatterList ) ;
CommandMailbox - > SCSI_10 . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > SCSI_10 . DataTransferSize ;
}
else
{
DAC960_V2_ScatterGatherSegment_T * ScatterGatherList ;
int i ;
if ( Command - > SegmentCount > 2 )
{
ScatterGatherList = Command - > V2 . ScatterGatherList ;
CommandMailbox - > SCSI_10 . CommandControlBits
. AdditionalScatterGatherListMemory = true ;
CommandMailbox - > SCSI_10 . DataTransferMemoryAddress
. ExtendedScatterGather . ScatterGatherList0Length = Command - > SegmentCount ;
CommandMailbox - > SCSI_10 . DataTransferMemoryAddress
. ExtendedScatterGather . ScatterGatherList0Address =
Command - > V2 . ScatterGatherListDMA ;
}
else
ScatterGatherList = CommandMailbox - > SCSI_10 . DataTransferMemoryAddress
. ScatterGatherSegments ;
for ( i = 0 ; i < Command - > SegmentCount ; i + + , ScatterList + + , ScatterGatherList + + ) {
ScatterGatherList - > SegmentDataPointer =
( DAC960_BusAddress64_T ) sg_dma_address ( ScatterList ) ;
ScatterGatherList - > SegmentByteCount =
( DAC960_ByteCount64_T ) sg_dma_len ( ScatterList ) ;
}
}
DAC960_QueueCommand ( Command ) ;
}
static int DAC960_process_queue ( DAC960_Controller_T * Controller , struct request_queue * req_q )
{
struct request * Request ;
DAC960_Command_T * Command ;
while ( 1 ) {
Request = elv_next_request ( req_q ) ;
if ( ! Request )
return 1 ;
Command = DAC960_AllocateCommand ( Controller ) ;
if ( Command = = NULL )
return 0 ;
if ( rq_data_dir ( Request ) = = READ ) {
Command - > DmaDirection = PCI_DMA_FROMDEVICE ;
Command - > CommandType = DAC960_ReadCommand ;
} else {
Command - > DmaDirection = PCI_DMA_TODEVICE ;
Command - > CommandType = DAC960_WriteCommand ;
}
Command - > Completion = Request - > waiting ;
Command - > LogicalDriveNumber = ( long ) Request - > rq_disk - > private_data ;
Command - > BlockNumber = Request - > sector ;
Command - > BlockCount = Request - > nr_sectors ;
Command - > Request = Request ;
blkdev_dequeue_request ( Request ) ;
Command - > SegmentCount = blk_rq_map_sg ( req_q ,
Command - > Request , Command - > cmd_sglist ) ;
/* pci_map_sg MAY change the value of SegCount */
Command - > SegmentCount = pci_map_sg ( Controller - > PCIDevice , Command - > cmd_sglist ,
Command - > SegmentCount , Command - > DmaDirection ) ;
DAC960_QueueReadWriteCommand ( Command ) ;
}
}
/*
DAC960_ProcessRequest attempts to remove one I / O Request from Controller ' s
I / O Request Queue and queues it to the Controller . WaitForCommand is true if
this function should wait for a Command to become available if necessary .
This function returns true if an I / O Request was queued and false otherwise .
*/
static void DAC960_ProcessRequest ( DAC960_Controller_T * controller )
{
int i ;
if ( ! controller - > ControllerInitialized )
return ;
/* Do this better later! */
for ( i = controller - > req_q_index ; i < DAC960_MaxLogicalDrives ; i + + ) {
struct request_queue * req_q = controller - > RequestQueue [ i ] ;
if ( req_q = = NULL )
continue ;
if ( ! DAC960_process_queue ( controller , req_q ) ) {
controller - > req_q_index = i ;
return ;
}
}
if ( controller - > req_q_index = = 0 )
return ;
for ( i = 0 ; i < controller - > req_q_index ; i + + ) {
struct request_queue * req_q = controller - > RequestQueue [ i ] ;
if ( req_q = = NULL )
continue ;
if ( ! DAC960_process_queue ( controller , req_q ) ) {
controller - > req_q_index = i ;
return ;
}
}
}
/*
DAC960_queue_partial_rw extracts one bio from the request already
associated with argument command , and construct a new command block to retry I / O
only on that bio . Queue that command to the controller .
This function re - uses a previously - allocated Command ,
there is no failure mode from trying to allocate a command .
*/
static void DAC960_queue_partial_rw ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
struct request * Request = Command - > Request ;
struct request_queue * req_q = Controller - > RequestQueue [ Command - > LogicalDriveNumber ] ;
if ( Command - > DmaDirection = = PCI_DMA_FROMDEVICE )
Command - > CommandType = DAC960_ReadRetryCommand ;
else
Command - > CommandType = DAC960_WriteRetryCommand ;
/*
* We could be more efficient with these mapping requests
* and map only the portions that we need . But since this
* code should almost never be called , just go with a
* simple coding .
*/
( void ) blk_rq_map_sg ( req_q , Command - > Request , Command - > cmd_sglist ) ;
( void ) pci_map_sg ( Controller - > PCIDevice , Command - > cmd_sglist , 1 , Command - > DmaDirection ) ;
/*
* Resubmitting the request sector at a time is really tedious .
* But , this should almost never happen . So , we ' re willing to pay
* this price so that in the end , as much of the transfer is completed
* successfully as possible .
*/
Command - > SegmentCount = 1 ;
Command - > BlockNumber = Request - > sector ;
Command - > BlockCount = 1 ;
DAC960_QueueReadWriteCommand ( Command ) ;
return ;
}
/*
DAC960_RequestFunction is the I / O Request Function for DAC960 Controllers .
*/
static void DAC960_RequestFunction ( struct request_queue * RequestQueue )
{
DAC960_ProcessRequest ( RequestQueue - > queuedata ) ;
}
/*
DAC960_ProcessCompletedBuffer performs completion processing for an
individual Buffer .
*/
static inline boolean DAC960_ProcessCompletedRequest ( DAC960_Command_T * Command ,
boolean SuccessfulIO )
{
struct request * Request = Command - > Request ;
int UpToDate ;
UpToDate = 0 ;
if ( SuccessfulIO )
UpToDate = 1 ;
pci_unmap_sg ( Command - > Controller - > PCIDevice , Command - > cmd_sglist ,
Command - > SegmentCount , Command - > DmaDirection ) ;
if ( ! end_that_request_first ( Request , UpToDate , Command - > BlockCount ) ) {
end_that_request_last ( Request ) ;
if ( Command - > Completion ) {
complete ( Command - > Completion ) ;
Command - > Completion = NULL ;
}
return true ;
}
return false ;
}
/*
DAC960_V1_ReadWriteError prints an appropriate error message for Command
when an error occurs on a Read or Write operation .
*/
static void DAC960_V1_ReadWriteError ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
unsigned char * CommandName = " UNKNOWN " ;
switch ( Command - > CommandType )
{
case DAC960_ReadCommand :
case DAC960_ReadRetryCommand :
CommandName = " READ " ;
break ;
case DAC960_WriteCommand :
case DAC960_WriteRetryCommand :
CommandName = " WRITE " ;
break ;
case DAC960_MonitoringCommand :
case DAC960_ImmediateCommand :
case DAC960_QueuedCommand :
break ;
}
switch ( Command - > V1 . CommandStatus )
{
case DAC960_V1_IrrecoverableDataError :
DAC960_Error ( " Irrecoverable Data Error on %s: \n " ,
Controller , CommandName ) ;
break ;
case DAC960_V1_LogicalDriveNonexistentOrOffline :
DAC960_Error ( " Logical Drive Nonexistent or Offline on %s: \n " ,
Controller , CommandName ) ;
break ;
case DAC960_V1_AccessBeyondEndOfLogicalDrive :
DAC960_Error ( " Attempt to Access Beyond End of Logical Drive "
" on %s: \n " , Controller , CommandName ) ;
break ;
case DAC960_V1_BadDataEncountered :
DAC960_Error ( " Bad Data Encountered on %s: \n " , Controller , CommandName ) ;
break ;
default :
DAC960_Error ( " Unexpected Error Status %04X on %s: \n " ,
Controller , Command - > V1 . CommandStatus , CommandName ) ;
break ;
}
DAC960_Error ( " /dev/rd/c%dd%d: absolute blocks %u..%u \n " ,
Controller , Controller - > ControllerNumber ,
Command - > LogicalDriveNumber , Command - > BlockNumber ,
Command - > BlockNumber + Command - > BlockCount - 1 ) ;
}
/*
DAC960_V1_ProcessCompletedCommand performs completion processing for Command
for DAC960 V1 Firmware Controllers .
*/
static void DAC960_V1_ProcessCompletedCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
DAC960_CommandType_T CommandType = Command - > CommandType ;
DAC960_V1_CommandOpcode_T CommandOpcode =
Command - > V1 . CommandMailbox . Common . CommandOpcode ;
DAC960_V1_CommandStatus_T CommandStatus = Command - > V1 . CommandStatus ;
if ( CommandType = = DAC960_ReadCommand | |
CommandType = = DAC960_WriteCommand )
{
# ifdef FORCE_RETRY_DEBUG
CommandStatus = DAC960_V1_IrrecoverableDataError ;
# endif
if ( CommandStatus = = DAC960_V1_NormalCompletion ) {
if ( ! DAC960_ProcessCompletedRequest ( Command , true ) )
BUG ( ) ;
} else if ( CommandStatus = = DAC960_V1_IrrecoverableDataError | |
CommandStatus = = DAC960_V1_BadDataEncountered )
{
/*
* break the command down into pieces and resubmit each
* piece , hoping that some of them will succeed .
*/
DAC960_queue_partial_rw ( Command ) ;
return ;
}
else
{
if ( CommandStatus ! = DAC960_V1_LogicalDriveNonexistentOrOffline )
DAC960_V1_ReadWriteError ( Command ) ;
if ( ! DAC960_ProcessCompletedRequest ( Command , false ) )
BUG ( ) ;
}
}
else if ( CommandType = = DAC960_ReadRetryCommand | |
CommandType = = DAC960_WriteRetryCommand )
{
boolean normal_completion ;
# ifdef FORCE_RETRY_FAILURE_DEBUG
static int retry_count = 1 ;
# endif
/*
Perform completion processing for the portion that was
retried , and submit the next portion , if any .
*/
normal_completion = true ;
if ( CommandStatus ! = DAC960_V1_NormalCompletion ) {
normal_completion = false ;
if ( CommandStatus ! = DAC960_V1_LogicalDriveNonexistentOrOffline )
DAC960_V1_ReadWriteError ( Command ) ;
}
# ifdef FORCE_RETRY_FAILURE_DEBUG
if ( ! ( + + retry_count % 10000 ) ) {
printk ( " V1 error retry failure test \n " ) ;
normal_completion = false ;
DAC960_V1_ReadWriteError ( Command ) ;
}
# endif
if ( ! DAC960_ProcessCompletedRequest ( Command , normal_completion ) ) {
DAC960_queue_partial_rw ( Command ) ;
return ;
}
}
else if ( CommandType = = DAC960_MonitoringCommand )
{
if ( Controller - > ShutdownMonitoringTimer )
return ;
if ( CommandOpcode = = DAC960_V1_Enquiry )
{
DAC960_V1_Enquiry_T * OldEnquiry = & Controller - > V1 . Enquiry ;
DAC960_V1_Enquiry_T * NewEnquiry = Controller - > V1 . NewEnquiry ;
unsigned int OldCriticalLogicalDriveCount =
OldEnquiry - > CriticalLogicalDriveCount ;
unsigned int NewCriticalLogicalDriveCount =
NewEnquiry - > CriticalLogicalDriveCount ;
if ( NewEnquiry - > NumberOfLogicalDrives > Controller - > LogicalDriveCount )
{
int LogicalDriveNumber = Controller - > LogicalDriveCount - 1 ;
while ( + + LogicalDriveNumber < NewEnquiry - > NumberOfLogicalDrives )
DAC960_Critical ( " Logical Drive %d (/dev/rd/c%dd%d) "
" Now Exists \n " , Controller ,
LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ) ;
Controller - > LogicalDriveCount = NewEnquiry - > NumberOfLogicalDrives ;
DAC960_ComputeGenericDiskInfo ( Controller ) ;
}
if ( NewEnquiry - > NumberOfLogicalDrives < Controller - > LogicalDriveCount )
{
int LogicalDriveNumber = NewEnquiry - > NumberOfLogicalDrives - 1 ;
while ( + + LogicalDriveNumber < Controller - > LogicalDriveCount )
DAC960_Critical ( " Logical Drive %d (/dev/rd/c%dd%d) "
" No Longer Exists \n " , Controller ,
LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ) ;
Controller - > LogicalDriveCount = NewEnquiry - > NumberOfLogicalDrives ;
DAC960_ComputeGenericDiskInfo ( Controller ) ;
}
if ( NewEnquiry - > StatusFlags . DeferredWriteError ! =
OldEnquiry - > StatusFlags . DeferredWriteError )
DAC960_Critical ( " Deferred Write Error Flag is now %s \n " , Controller ,
( NewEnquiry - > StatusFlags . DeferredWriteError
? " TRUE " : " FALSE " ) ) ;
if ( ( NewCriticalLogicalDriveCount > 0 | |
NewCriticalLogicalDriveCount ! = OldCriticalLogicalDriveCount ) | |
( NewEnquiry - > OfflineLogicalDriveCount > 0 | |
NewEnquiry - > OfflineLogicalDriveCount ! =
OldEnquiry - > OfflineLogicalDriveCount ) | |
( NewEnquiry - > DeadDriveCount > 0 | |
NewEnquiry - > DeadDriveCount ! =
OldEnquiry - > DeadDriveCount ) | |
( NewEnquiry - > EventLogSequenceNumber ! =
OldEnquiry - > EventLogSequenceNumber ) | |
Controller - > MonitoringTimerCount = = 0 | |
( jiffies - Controller - > SecondaryMonitoringTime
> = DAC960_SecondaryMonitoringInterval ) )
{
Controller - > V1 . NeedLogicalDriveInformation = true ;
Controller - > V1 . NewEventLogSequenceNumber =
NewEnquiry - > EventLogSequenceNumber ;
Controller - > V1 . NeedErrorTableInformation = true ;
Controller - > V1 . NeedDeviceStateInformation = true ;
Controller - > V1 . StartDeviceStateScan = true ;
Controller - > V1 . NeedBackgroundInitializationStatus =
Controller - > V1 . BackgroundInitializationStatusSupported ;
Controller - > SecondaryMonitoringTime = jiffies ;
}
if ( NewEnquiry - > RebuildFlag = = DAC960_V1_StandbyRebuildInProgress | |
NewEnquiry - > RebuildFlag
= = DAC960_V1_BackgroundRebuildInProgress | |
OldEnquiry - > RebuildFlag = = DAC960_V1_StandbyRebuildInProgress | |
OldEnquiry - > RebuildFlag = = DAC960_V1_BackgroundRebuildInProgress )
{
Controller - > V1 . NeedRebuildProgress = true ;
Controller - > V1 . RebuildProgressFirst =
( NewEnquiry - > CriticalLogicalDriveCount <
OldEnquiry - > CriticalLogicalDriveCount ) ;
}
if ( OldEnquiry - > RebuildFlag = = DAC960_V1_BackgroundCheckInProgress )
switch ( NewEnquiry - > RebuildFlag )
{
case DAC960_V1_NoStandbyRebuildOrCheckInProgress :
DAC960_Progress ( " Consistency Check Completed Successfully \n " ,
Controller ) ;
break ;
case DAC960_V1_StandbyRebuildInProgress :
case DAC960_V1_BackgroundRebuildInProgress :
break ;
case DAC960_V1_BackgroundCheckInProgress :
Controller - > V1 . NeedConsistencyCheckProgress = true ;
break ;
case DAC960_V1_StandbyRebuildCompletedWithError :
DAC960_Progress ( " Consistency Check Completed with Error \n " ,
Controller ) ;
break ;
case DAC960_V1_BackgroundRebuildOrCheckFailed_DriveFailed :
DAC960_Progress ( " Consistency Check Failed - "
" Physical Device Failed \n " , Controller ) ;
break ;
case DAC960_V1_BackgroundRebuildOrCheckFailed_LogicalDriveFailed :
DAC960_Progress ( " Consistency Check Failed - "
" Logical Drive Failed \n " , Controller ) ;
break ;
case DAC960_V1_BackgroundRebuildOrCheckFailed_OtherCauses :
DAC960_Progress ( " Consistency Check Failed - Other Causes \n " ,
Controller ) ;
break ;
case DAC960_V1_BackgroundRebuildOrCheckSuccessfullyTerminated :
DAC960_Progress ( " Consistency Check Successfully Terminated \n " ,
Controller ) ;
break ;
}
else if ( NewEnquiry - > RebuildFlag
= = DAC960_V1_BackgroundCheckInProgress )
Controller - > V1 . NeedConsistencyCheckProgress = true ;
Controller - > MonitoringAlertMode =
( NewEnquiry - > CriticalLogicalDriveCount > 0 | |
NewEnquiry - > OfflineLogicalDriveCount > 0 | |
NewEnquiry - > DeadDriveCount > 0 ) ;
if ( NewEnquiry - > RebuildFlag > DAC960_V1_BackgroundCheckInProgress )
{
Controller - > V1 . PendingRebuildFlag = NewEnquiry - > RebuildFlag ;
Controller - > V1 . RebuildFlagPending = true ;
}
memcpy ( & Controller - > V1 . Enquiry , & Controller - > V1 . NewEnquiry ,
sizeof ( DAC960_V1_Enquiry_T ) ) ;
}
else if ( CommandOpcode = = DAC960_V1_PerformEventLogOperation )
{
static char
* DAC960_EventMessages [ ] =
{ " killed because write recovery failed " ,
" killed because of SCSI bus reset failure " ,
" killed because of double check condition " ,
" killed because it was removed " ,
" killed because of gross error on SCSI chip " ,
" killed because of bad tag returned from drive " ,
" killed because of timeout on SCSI command " ,
" killed because of reset SCSI command issued from system " ,
" killed because busy or parity error count exceeded limit " ,
" killed because of 'kill drive' command from system " ,
" killed because of selection timeout " ,
" killed due to SCSI phase sequence error " ,
" killed due to unknown status " } ;
DAC960_V1_EventLogEntry_T * EventLogEntry =
Controller - > V1 . EventLogEntry ;
if ( EventLogEntry - > SequenceNumber = =
Controller - > V1 . OldEventLogSequenceNumber )
{
unsigned char SenseKey = EventLogEntry - > SenseKey ;
unsigned char AdditionalSenseCode =
EventLogEntry - > AdditionalSenseCode ;
unsigned char AdditionalSenseCodeQualifier =
EventLogEntry - > AdditionalSenseCodeQualifier ;
if ( SenseKey = = DAC960_SenseKey_VendorSpecific & &
AdditionalSenseCode = = 0x80 & &
AdditionalSenseCodeQualifier <
sizeof ( DAC960_EventMessages ) / sizeof ( char * ) )
DAC960_Critical ( " Physical Device %d:%d %s \n " , Controller ,
EventLogEntry - > Channel ,
EventLogEntry - > TargetID ,
DAC960_EventMessages [
AdditionalSenseCodeQualifier ] ) ;
else if ( SenseKey = = DAC960_SenseKey_UnitAttention & &
AdditionalSenseCode = = 0x29 )
{
if ( Controller - > MonitoringTimerCount > 0 )
Controller - > V1 . DeviceResetCount [ EventLogEntry - > Channel ]
[ EventLogEntry - > TargetID ] + + ;
}
else if ( ! ( SenseKey = = DAC960_SenseKey_NoSense | |
( SenseKey = = DAC960_SenseKey_NotReady & &
AdditionalSenseCode = = 0x04 & &
( AdditionalSenseCodeQualifier = = 0x01 | |
AdditionalSenseCodeQualifier = = 0x02 ) ) ) )
{
DAC960_Critical ( " Physical Device %d:%d Error Log: "
" Sense Key = %X, ASC = %02X, ASCQ = %02X \n " ,
Controller ,
EventLogEntry - > Channel ,
EventLogEntry - > TargetID ,
SenseKey ,
AdditionalSenseCode ,
AdditionalSenseCodeQualifier ) ;
DAC960_Critical ( " Physical Device %d:%d Error Log: "
" Information = %02X%02X%02X%02X "
" %02X%02X%02X%02X \n " ,
Controller ,
EventLogEntry - > Channel ,
EventLogEntry - > TargetID ,
EventLogEntry - > Information [ 0 ] ,
EventLogEntry - > Information [ 1 ] ,
EventLogEntry - > Information [ 2 ] ,
EventLogEntry - > Information [ 3 ] ,
EventLogEntry - > CommandSpecificInformation [ 0 ] ,
EventLogEntry - > CommandSpecificInformation [ 1 ] ,
EventLogEntry - > CommandSpecificInformation [ 2 ] ,
EventLogEntry - > CommandSpecificInformation [ 3 ] ) ;
}
}
Controller - > V1 . OldEventLogSequenceNumber + + ;
}
else if ( CommandOpcode = = DAC960_V1_GetErrorTable )
{
DAC960_V1_ErrorTable_T * OldErrorTable = & Controller - > V1 . ErrorTable ;
DAC960_V1_ErrorTable_T * NewErrorTable = Controller - > V1 . NewErrorTable ;
int Channel , TargetID ;
for ( Channel = 0 ; Channel < Controller - > Channels ; Channel + + )
for ( TargetID = 0 ; TargetID < Controller - > Targets ; TargetID + + )
{
DAC960_V1_ErrorTableEntry_T * NewErrorEntry =
& NewErrorTable - > ErrorTableEntries [ Channel ] [ TargetID ] ;
DAC960_V1_ErrorTableEntry_T * OldErrorEntry =
& OldErrorTable - > ErrorTableEntries [ Channel ] [ TargetID ] ;
if ( ( NewErrorEntry - > ParityErrorCount ! =
OldErrorEntry - > ParityErrorCount ) | |
( NewErrorEntry - > SoftErrorCount ! =
OldErrorEntry - > SoftErrorCount ) | |
( NewErrorEntry - > HardErrorCount ! =
OldErrorEntry - > HardErrorCount ) | |
( NewErrorEntry - > MiscErrorCount ! =
OldErrorEntry - > MiscErrorCount ) )
DAC960_Critical ( " Physical Device %d:%d Errors: "
" Parity = %d, Soft = %d, "
" Hard = %d, Misc = %d \n " ,
Controller , Channel , TargetID ,
NewErrorEntry - > ParityErrorCount ,
NewErrorEntry - > SoftErrorCount ,
NewErrorEntry - > HardErrorCount ,
NewErrorEntry - > MiscErrorCount ) ;
}
memcpy ( & Controller - > V1 . ErrorTable , Controller - > V1 . NewErrorTable ,
sizeof ( DAC960_V1_ErrorTable_T ) ) ;
}
else if ( CommandOpcode = = DAC960_V1_GetDeviceState )
{
DAC960_V1_DeviceState_T * OldDeviceState =
& Controller - > V1 . DeviceState [ Controller - > V1 . DeviceStateChannel ]
[ Controller - > V1 . DeviceStateTargetID ] ;
DAC960_V1_DeviceState_T * NewDeviceState =
Controller - > V1 . NewDeviceState ;
if ( NewDeviceState - > DeviceState ! = OldDeviceState - > DeviceState )
DAC960_Critical ( " Physical Device %d:%d is now %s \n " , Controller ,
Controller - > V1 . DeviceStateChannel ,
Controller - > V1 . DeviceStateTargetID ,
( NewDeviceState - > DeviceState
= = DAC960_V1_Device_Dead
? " DEAD "
: NewDeviceState - > DeviceState
= = DAC960_V1_Device_WriteOnly
? " WRITE-ONLY "
: NewDeviceState - > DeviceState
= = DAC960_V1_Device_Online
? " ONLINE " : " STANDBY " ) ) ;
if ( OldDeviceState - > DeviceState = = DAC960_V1_Device_Dead & &
NewDeviceState - > DeviceState ! = DAC960_V1_Device_Dead )
{
Controller - > V1 . NeedDeviceInquiryInformation = true ;
Controller - > V1 . NeedDeviceSerialNumberInformation = true ;
Controller - > V1 . DeviceResetCount
[ Controller - > V1 . DeviceStateChannel ]
[ Controller - > V1 . DeviceStateTargetID ] = 0 ;
}
memcpy ( OldDeviceState , NewDeviceState ,
sizeof ( DAC960_V1_DeviceState_T ) ) ;
}
else if ( CommandOpcode = = DAC960_V1_GetLogicalDriveInformation )
{
int LogicalDriveNumber ;
for ( LogicalDriveNumber = 0 ;
LogicalDriveNumber < Controller - > LogicalDriveCount ;
LogicalDriveNumber + + )
{
DAC960_V1_LogicalDriveInformation_T * OldLogicalDriveInformation =
& Controller - > V1 . LogicalDriveInformation [ LogicalDriveNumber ] ;
DAC960_V1_LogicalDriveInformation_T * NewLogicalDriveInformation =
& ( * Controller - > V1 . NewLogicalDriveInformation ) [ LogicalDriveNumber ] ;
if ( NewLogicalDriveInformation - > LogicalDriveState ! =
OldLogicalDriveInformation - > LogicalDriveState )
DAC960_Critical ( " Logical Drive %d (/dev/rd/c%dd%d) "
" is now %s \n " , Controller ,
LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ,
( NewLogicalDriveInformation - > LogicalDriveState
= = DAC960_V1_LogicalDrive_Online
? " ONLINE "
: NewLogicalDriveInformation - > LogicalDriveState
= = DAC960_V1_LogicalDrive_Critical
? " CRITICAL " : " OFFLINE " ) ) ;
if ( NewLogicalDriveInformation - > WriteBack ! =
OldLogicalDriveInformation - > WriteBack )
DAC960_Critical ( " Logical Drive %d (/dev/rd/c%dd%d) "
" is now %s \n " , Controller ,
LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ,
( NewLogicalDriveInformation - > WriteBack
? " WRITE BACK " : " WRITE THRU " ) ) ;
}
memcpy ( & Controller - > V1 . LogicalDriveInformation ,
Controller - > V1 . NewLogicalDriveInformation ,
sizeof ( DAC960_V1_LogicalDriveInformationArray_T ) ) ;
}
else if ( CommandOpcode = = DAC960_V1_GetRebuildProgress )
{
unsigned int LogicalDriveNumber =
Controller - > V1 . RebuildProgress - > LogicalDriveNumber ;
unsigned int LogicalDriveSize =
Controller - > V1 . RebuildProgress - > LogicalDriveSize ;
unsigned int BlocksCompleted =
LogicalDriveSize - Controller - > V1 . RebuildProgress - > RemainingBlocks ;
if ( CommandStatus = = DAC960_V1_NoRebuildOrCheckInProgress & &
Controller - > V1 . LastRebuildStatus = = DAC960_V1_NormalCompletion )
CommandStatus = DAC960_V1_RebuildSuccessful ;
switch ( CommandStatus )
{
case DAC960_V1_NormalCompletion :
Controller - > EphemeralProgressMessage = true ;
DAC960_Progress ( " Rebuild in Progress: "
" Logical Drive %d (/dev/rd/c%dd%d) "
" %d%% completed \n " ,
Controller , LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ,
( 100 * ( BlocksCompleted > > 7 ) )
/ ( LogicalDriveSize > > 7 ) ) ;
Controller - > EphemeralProgressMessage = false ;
break ;
case DAC960_V1_RebuildFailed_LogicalDriveFailure :
DAC960_Progress ( " Rebuild Failed due to "
" Logical Drive Failure \n " , Controller ) ;
break ;
case DAC960_V1_RebuildFailed_BadBlocksOnOther :
DAC960_Progress ( " Rebuild Failed due to "
" Bad Blocks on Other Drives \n " , Controller ) ;
break ;
case DAC960_V1_RebuildFailed_NewDriveFailed :
DAC960_Progress ( " Rebuild Failed due to "
" Failure of Drive Being Rebuilt \n " , Controller ) ;
break ;
case DAC960_V1_NoRebuildOrCheckInProgress :
break ;
case DAC960_V1_RebuildSuccessful :
DAC960_Progress ( " Rebuild Completed Successfully \n " , Controller ) ;
break ;
case DAC960_V1_RebuildSuccessfullyTerminated :
DAC960_Progress ( " Rebuild Successfully Terminated \n " , Controller ) ;
break ;
}
Controller - > V1 . LastRebuildStatus = CommandStatus ;
if ( CommandType ! = DAC960_MonitoringCommand & &
Controller - > V1 . RebuildStatusPending )
{
Command - > V1 . CommandStatus = Controller - > V1 . PendingRebuildStatus ;
Controller - > V1 . RebuildStatusPending = false ;
}
else if ( CommandType = = DAC960_MonitoringCommand & &
CommandStatus ! = DAC960_V1_NormalCompletion & &
CommandStatus ! = DAC960_V1_NoRebuildOrCheckInProgress )
{
Controller - > V1 . PendingRebuildStatus = CommandStatus ;
Controller - > V1 . RebuildStatusPending = true ;
}
}
else if ( CommandOpcode = = DAC960_V1_RebuildStat )
{
unsigned int LogicalDriveNumber =
Controller - > V1 . RebuildProgress - > LogicalDriveNumber ;
unsigned int LogicalDriveSize =
Controller - > V1 . RebuildProgress - > LogicalDriveSize ;
unsigned int BlocksCompleted =
LogicalDriveSize - Controller - > V1 . RebuildProgress - > RemainingBlocks ;
if ( CommandStatus = = DAC960_V1_NormalCompletion )
{
Controller - > EphemeralProgressMessage = true ;
DAC960_Progress ( " Consistency Check in Progress: "
" Logical Drive %d (/dev/rd/c%dd%d) "
" %d%% completed \n " ,
Controller , LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ,
( 100 * ( BlocksCompleted > > 7 ) )
/ ( LogicalDriveSize > > 7 ) ) ;
Controller - > EphemeralProgressMessage = false ;
}
}
else if ( CommandOpcode = = DAC960_V1_BackgroundInitializationControl )
{
unsigned int LogicalDriveNumber =
Controller - > V1 . BackgroundInitializationStatus - > LogicalDriveNumber ;
unsigned int LogicalDriveSize =
Controller - > V1 . BackgroundInitializationStatus - > LogicalDriveSize ;
unsigned int BlocksCompleted =
Controller - > V1 . BackgroundInitializationStatus - > BlocksCompleted ;
switch ( CommandStatus )
{
case DAC960_V1_NormalCompletion :
switch ( Controller - > V1 . BackgroundInitializationStatus - > Status )
{
case DAC960_V1_BackgroundInitializationInvalid :
break ;
case DAC960_V1_BackgroundInitializationStarted :
DAC960_Progress ( " Background Initialization Started \n " ,
Controller ) ;
break ;
case DAC960_V1_BackgroundInitializationInProgress :
if ( BlocksCompleted = =
Controller - > V1 . LastBackgroundInitializationStatus .
BlocksCompleted & &
LogicalDriveNumber = =
Controller - > V1 . LastBackgroundInitializationStatus .
LogicalDriveNumber )
break ;
Controller - > EphemeralProgressMessage = true ;
DAC960_Progress ( " Background Initialization in Progress: "
" Logical Drive %d (/dev/rd/c%dd%d) "
" %d%% completed \n " ,
Controller , LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ,
( 100 * ( BlocksCompleted > > 7 ) )
/ ( LogicalDriveSize > > 7 ) ) ;
Controller - > EphemeralProgressMessage = false ;
break ;
case DAC960_V1_BackgroundInitializationSuspended :
DAC960_Progress ( " Background Initialization Suspended \n " ,
Controller ) ;
break ;
case DAC960_V1_BackgroundInitializationCancelled :
DAC960_Progress ( " Background Initialization Cancelled \n " ,
Controller ) ;
break ;
}
memcpy ( & Controller - > V1 . LastBackgroundInitializationStatus ,
Controller - > V1 . BackgroundInitializationStatus ,
sizeof ( DAC960_V1_BackgroundInitializationStatus_T ) ) ;
break ;
case DAC960_V1_BackgroundInitSuccessful :
if ( Controller - > V1 . BackgroundInitializationStatus - > Status = =
DAC960_V1_BackgroundInitializationInProgress )
DAC960_Progress ( " Background Initialization "
" Completed Successfully \n " , Controller ) ;
Controller - > V1 . BackgroundInitializationStatus - > Status =
DAC960_V1_BackgroundInitializationInvalid ;
break ;
case DAC960_V1_BackgroundInitAborted :
if ( Controller - > V1 . BackgroundInitializationStatus - > Status = =
DAC960_V1_BackgroundInitializationInProgress )
DAC960_Progress ( " Background Initialization Aborted \n " ,
Controller ) ;
Controller - > V1 . BackgroundInitializationStatus - > Status =
DAC960_V1_BackgroundInitializationInvalid ;
break ;
case DAC960_V1_NoBackgroundInitInProgress :
break ;
}
}
else if ( CommandOpcode = = DAC960_V1_DCDB )
{
/*
This is a bit ugly .
The InquiryStandardData and
the InquiryUntitSerialNumber information
retrieval operations BOTH use the DAC960_V1_DCDB
commands . the test above can ' t distinguish between
these two cases .
Instead , we rely on the order of code later in this
function to ensure that DeviceInquiryInformation commands
are submitted before DeviceSerialNumber commands .
*/
if ( Controller - > V1 . NeedDeviceInquiryInformation )
{
DAC960_SCSI_Inquiry_T * InquiryStandardData =
& Controller - > V1 . InquiryStandardData
[ Controller - > V1 . DeviceStateChannel ]
[ Controller - > V1 . DeviceStateTargetID ] ;
if ( CommandStatus ! = DAC960_V1_NormalCompletion )
{
memset ( InquiryStandardData , 0 ,
sizeof ( DAC960_SCSI_Inquiry_T ) ) ;
InquiryStandardData - > PeripheralDeviceType = 0x1F ;
}
else
memcpy ( InquiryStandardData ,
Controller - > V1 . NewInquiryStandardData ,
sizeof ( DAC960_SCSI_Inquiry_T ) ) ;
Controller - > V1 . NeedDeviceInquiryInformation = false ;
}
else if ( Controller - > V1 . NeedDeviceSerialNumberInformation )
{
DAC960_SCSI_Inquiry_UnitSerialNumber_T * InquiryUnitSerialNumber =
& Controller - > V1 . InquiryUnitSerialNumber
[ Controller - > V1 . DeviceStateChannel ]
[ Controller - > V1 . DeviceStateTargetID ] ;
if ( CommandStatus ! = DAC960_V1_NormalCompletion )
{
memset ( InquiryUnitSerialNumber , 0 ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ) ;
InquiryUnitSerialNumber - > PeripheralDeviceType = 0x1F ;
}
else
memcpy ( InquiryUnitSerialNumber ,
Controller - > V1 . NewInquiryUnitSerialNumber ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ) ;
Controller - > V1 . NeedDeviceSerialNumberInformation = false ;
}
}
/*
Begin submitting new monitoring commands .
*/
if ( Controller - > V1 . NewEventLogSequenceNumber
- Controller - > V1 . OldEventLogSequenceNumber > 0 )
{
Command - > V1 . CommandMailbox . Type3E . CommandOpcode =
DAC960_V1_PerformEventLogOperation ;
Command - > V1 . CommandMailbox . Type3E . OperationType =
DAC960_V1_GetEventLogEntry ;
Command - > V1 . CommandMailbox . Type3E . OperationQualifier = 1 ;
Command - > V1 . CommandMailbox . Type3E . SequenceNumber =
Controller - > V1 . OldEventLogSequenceNumber ;
Command - > V1 . CommandMailbox . Type3E . BusAddress =
Controller - > V1 . EventLogEntryDMA ;
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V1 . NeedErrorTableInformation )
{
Controller - > V1 . NeedErrorTableInformation = false ;
Command - > V1 . CommandMailbox . Type3 . CommandOpcode =
DAC960_V1_GetErrorTable ;
Command - > V1 . CommandMailbox . Type3 . BusAddress =
Controller - > V1 . NewErrorTableDMA ;
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V1 . NeedRebuildProgress & &
Controller - > V1 . RebuildProgressFirst )
{
Controller - > V1 . NeedRebuildProgress = false ;
Command - > V1 . CommandMailbox . Type3 . CommandOpcode =
DAC960_V1_GetRebuildProgress ;
Command - > V1 . CommandMailbox . Type3 . BusAddress =
Controller - > V1 . RebuildProgressDMA ;
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V1 . NeedDeviceStateInformation )
{
if ( Controller - > V1 . NeedDeviceInquiryInformation )
{
DAC960_V1_DCDB_T * DCDB = Controller - > V1 . MonitoringDCDB ;
dma_addr_t DCDB_DMA = Controller - > V1 . MonitoringDCDB_DMA ;
dma_addr_t NewInquiryStandardDataDMA =
Controller - > V1 . NewInquiryStandardDataDMA ;
Command - > V1 . CommandMailbox . Type3 . CommandOpcode = DAC960_V1_DCDB ;
Command - > V1 . CommandMailbox . Type3 . BusAddress = DCDB_DMA ;
DCDB - > Channel = Controller - > V1 . DeviceStateChannel ;
DCDB - > TargetID = Controller - > V1 . DeviceStateTargetID ;
DCDB - > Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem ;
DCDB - > EarlyStatus = false ;
DCDB - > Timeout = DAC960_V1_DCDB_Timeout_10_seconds ;
DCDB - > NoAutomaticRequestSense = false ;
DCDB - > DisconnectPermitted = true ;
DCDB - > TransferLength = sizeof ( DAC960_SCSI_Inquiry_T ) ;
DCDB - > BusAddress = NewInquiryStandardDataDMA ;
DCDB - > CDBLength = 6 ;
DCDB - > TransferLengthHigh4 = 0 ;
DCDB - > SenseLength = sizeof ( DCDB - > SenseData ) ;
DCDB - > CDB [ 0 ] = 0x12 ; /* INQUIRY */
DCDB - > CDB [ 1 ] = 0 ; /* EVPD = 0 */
DCDB - > CDB [ 2 ] = 0 ; /* Page Code */
DCDB - > CDB [ 3 ] = 0 ; /* Reserved */
DCDB - > CDB [ 4 ] = sizeof ( DAC960_SCSI_Inquiry_T ) ;
DCDB - > CDB [ 5 ] = 0 ; /* Control */
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V1 . NeedDeviceSerialNumberInformation )
{
DAC960_V1_DCDB_T * DCDB = Controller - > V1 . MonitoringDCDB ;
dma_addr_t DCDB_DMA = Controller - > V1 . MonitoringDCDB_DMA ;
dma_addr_t NewInquiryUnitSerialNumberDMA =
Controller - > V1 . NewInquiryUnitSerialNumberDMA ;
Command - > V1 . CommandMailbox . Type3 . CommandOpcode = DAC960_V1_DCDB ;
Command - > V1 . CommandMailbox . Type3 . BusAddress = DCDB_DMA ;
DCDB - > Channel = Controller - > V1 . DeviceStateChannel ;
DCDB - > TargetID = Controller - > V1 . DeviceStateTargetID ;
DCDB - > Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem ;
DCDB - > EarlyStatus = false ;
DCDB - > Timeout = DAC960_V1_DCDB_Timeout_10_seconds ;
DCDB - > NoAutomaticRequestSense = false ;
DCDB - > DisconnectPermitted = true ;
DCDB - > TransferLength =
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ;
DCDB - > BusAddress = NewInquiryUnitSerialNumberDMA ;
DCDB - > CDBLength = 6 ;
DCDB - > TransferLengthHigh4 = 0 ;
DCDB - > SenseLength = sizeof ( DCDB - > SenseData ) ;
DCDB - > CDB [ 0 ] = 0x12 ; /* INQUIRY */
DCDB - > CDB [ 1 ] = 1 ; /* EVPD = 1 */
DCDB - > CDB [ 2 ] = 0x80 ; /* Page Code */
DCDB - > CDB [ 3 ] = 0 ; /* Reserved */
DCDB - > CDB [ 4 ] = sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ;
DCDB - > CDB [ 5 ] = 0 ; /* Control */
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V1 . StartDeviceStateScan )
{
Controller - > V1 . DeviceStateChannel = 0 ;
Controller - > V1 . DeviceStateTargetID = 0 ;
Controller - > V1 . StartDeviceStateScan = false ;
}
else if ( + + Controller - > V1 . DeviceStateTargetID = = Controller - > Targets )
{
Controller - > V1 . DeviceStateChannel + + ;
Controller - > V1 . DeviceStateTargetID = 0 ;
}
if ( Controller - > V1 . DeviceStateChannel < Controller - > Channels )
{
Controller - > V1 . NewDeviceState - > DeviceState =
DAC960_V1_Device_Dead ;
Command - > V1 . CommandMailbox . Type3D . CommandOpcode =
DAC960_V1_GetDeviceState ;
Command - > V1 . CommandMailbox . Type3D . Channel =
Controller - > V1 . DeviceStateChannel ;
Command - > V1 . CommandMailbox . Type3D . TargetID =
Controller - > V1 . DeviceStateTargetID ;
Command - > V1 . CommandMailbox . Type3D . BusAddress =
Controller - > V1 . NewDeviceStateDMA ;
DAC960_QueueCommand ( Command ) ;
return ;
}
Controller - > V1 . NeedDeviceStateInformation = false ;
}
if ( Controller - > V1 . NeedLogicalDriveInformation )
{
Controller - > V1 . NeedLogicalDriveInformation = false ;
Command - > V1 . CommandMailbox . Type3 . CommandOpcode =
DAC960_V1_GetLogicalDriveInformation ;
Command - > V1 . CommandMailbox . Type3 . BusAddress =
Controller - > V1 . NewLogicalDriveInformationDMA ;
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V1 . NeedRebuildProgress )
{
Controller - > V1 . NeedRebuildProgress = false ;
Command - > V1 . CommandMailbox . Type3 . CommandOpcode =
DAC960_V1_GetRebuildProgress ;
Command - > V1 . CommandMailbox . Type3 . BusAddress =
Controller - > V1 . RebuildProgressDMA ;
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V1 . NeedConsistencyCheckProgress )
{
Controller - > V1 . NeedConsistencyCheckProgress = false ;
Command - > V1 . CommandMailbox . Type3 . CommandOpcode =
DAC960_V1_RebuildStat ;
Command - > V1 . CommandMailbox . Type3 . BusAddress =
Controller - > V1 . RebuildProgressDMA ;
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V1 . NeedBackgroundInitializationStatus )
{
Controller - > V1 . NeedBackgroundInitializationStatus = false ;
Command - > V1 . CommandMailbox . Type3B . CommandOpcode =
DAC960_V1_BackgroundInitializationControl ;
Command - > V1 . CommandMailbox . Type3B . CommandOpcode2 = 0x20 ;
Command - > V1 . CommandMailbox . Type3B . BusAddress =
Controller - > V1 . BackgroundInitializationStatusDMA ;
DAC960_QueueCommand ( Command ) ;
return ;
}
Controller - > MonitoringTimerCount + + ;
Controller - > MonitoringTimer . expires =
jiffies + DAC960_MonitoringTimerInterval ;
add_timer ( & Controller - > MonitoringTimer ) ;
}
if ( CommandType = = DAC960_ImmediateCommand )
{
complete ( Command - > Completion ) ;
Command - > Completion = NULL ;
return ;
}
if ( CommandType = = DAC960_QueuedCommand )
{
DAC960_V1_KernelCommand_T * KernelCommand = Command - > V1 . KernelCommand ;
KernelCommand - > CommandStatus = Command - > V1 . CommandStatus ;
Command - > V1 . KernelCommand = NULL ;
if ( CommandOpcode = = DAC960_V1_DCDB )
Controller - > V1 . DirectCommandActive [ KernelCommand - > DCDB - > Channel ]
[ KernelCommand - > DCDB - > TargetID ] =
false ;
DAC960_DeallocateCommand ( Command ) ;
KernelCommand - > CompletionFunction ( KernelCommand ) ;
return ;
}
/*
Queue a Status Monitoring Command to the Controller using the just
completed Command if one was deferred previously due to lack of a
free Command when the Monitoring Timer Function was called .
*/
if ( Controller - > MonitoringCommandDeferred )
{
Controller - > MonitoringCommandDeferred = false ;
DAC960_V1_QueueMonitoringCommand ( Command ) ;
return ;
}
/*
Deallocate the Command .
*/
DAC960_DeallocateCommand ( Command ) ;
/*
Wake up any processes waiting on a free Command .
*/
wake_up ( & Controller - > CommandWaitQueue ) ;
}
/*
DAC960_V2_ReadWriteError prints an appropriate error message for Command
when an error occurs on a Read or Write operation .
*/
static void DAC960_V2_ReadWriteError ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
unsigned char * SenseErrors [ ] = { " NO SENSE " , " RECOVERED ERROR " ,
" NOT READY " , " MEDIUM ERROR " ,
" HARDWARE ERROR " , " ILLEGAL REQUEST " ,
" UNIT ATTENTION " , " DATA PROTECT " ,
" BLANK CHECK " , " VENDOR-SPECIFIC " ,
" COPY ABORTED " , " ABORTED COMMAND " ,
" EQUAL " , " VOLUME OVERFLOW " ,
" MISCOMPARE " , " RESERVED " } ;
unsigned char * CommandName = " UNKNOWN " ;
switch ( Command - > CommandType )
{
case DAC960_ReadCommand :
case DAC960_ReadRetryCommand :
CommandName = " READ " ;
break ;
case DAC960_WriteCommand :
case DAC960_WriteRetryCommand :
CommandName = " WRITE " ;
break ;
case DAC960_MonitoringCommand :
case DAC960_ImmediateCommand :
case DAC960_QueuedCommand :
break ;
}
DAC960_Error ( " Error Condition %s on %s: \n " , Controller ,
SenseErrors [ Command - > V2 . RequestSense - > SenseKey ] , CommandName ) ;
DAC960_Error ( " /dev/rd/c%dd%d: absolute blocks %u..%u \n " ,
Controller , Controller - > ControllerNumber ,
Command - > LogicalDriveNumber , Command - > BlockNumber ,
Command - > BlockNumber + Command - > BlockCount - 1 ) ;
}
/*
DAC960_V2_ReportEvent prints an appropriate message when a Controller Event
occurs .
*/
static void DAC960_V2_ReportEvent ( DAC960_Controller_T * Controller ,
DAC960_V2_Event_T * Event )
{
DAC960_SCSI_RequestSense_T * RequestSense =
( DAC960_SCSI_RequestSense_T * ) & Event - > RequestSenseData ;
unsigned char MessageBuffer [ DAC960_LineBufferSize ] ;
static struct { int EventCode ; unsigned char * EventMessage ; } EventList [ ] =
{ /* Physical Device Events (0x0000 - 0x007F) */
{ 0x0001 , " P Online " } ,
{ 0x0002 , " P Standby " } ,
{ 0x0005 , " P Automatic Rebuild Started " } ,
{ 0x0006 , " P Manual Rebuild Started " } ,
{ 0x0007 , " P Rebuild Completed " } ,
{ 0x0008 , " P Rebuild Cancelled " } ,
{ 0x0009 , " P Rebuild Failed for Unknown Reasons " } ,
{ 0x000A , " P Rebuild Failed due to New Physical Device " } ,
{ 0x000B , " P Rebuild Failed due to Logical Drive Failure " } ,
{ 0x000C , " S Offline " } ,
{ 0x000D , " P Found " } ,
{ 0x000E , " P Removed " } ,
{ 0x000F , " P Unconfigured " } ,
{ 0x0010 , " P Expand Capacity Started " } ,
{ 0x0011 , " P Expand Capacity Completed " } ,
{ 0x0012 , " P Expand Capacity Failed " } ,
{ 0x0013 , " P Command Timed Out " } ,
{ 0x0014 , " P Command Aborted " } ,
{ 0x0015 , " P Command Retried " } ,
{ 0x0016 , " P Parity Error " } ,
{ 0x0017 , " P Soft Error " } ,
{ 0x0018 , " P Miscellaneous Error " } ,
{ 0x0019 , " P Reset " } ,
{ 0x001A , " P Active Spare Found " } ,
{ 0x001B , " P Warm Spare Found " } ,
{ 0x001C , " S Sense Data Received " } ,
{ 0x001D , " P Initialization Started " } ,
{ 0x001E , " P Initialization Completed " } ,
{ 0x001F , " P Initialization Failed " } ,
{ 0x0020 , " P Initialization Cancelled " } ,
{ 0x0021 , " P Failed because Write Recovery Failed " } ,
{ 0x0022 , " P Failed because SCSI Bus Reset Failed " } ,
{ 0x0023 , " P Failed because of Double Check Condition " } ,
{ 0x0024 , " P Failed because Device Cannot Be Accessed " } ,
{ 0x0025 , " P Failed because of Gross Error on SCSI Processor " } ,
{ 0x0026 , " P Failed because of Bad Tag from Device " } ,
{ 0x0027 , " P Failed because of Command Timeout " } ,
{ 0x0028 , " P Failed because of System Reset " } ,
{ 0x0029 , " P Failed because of Busy Status or Parity Error " } ,
{ 0x002A , " P Failed because Host Set Device to Failed State " } ,
{ 0x002B , " P Failed because of Selection Timeout " } ,
{ 0x002C , " P Failed because of SCSI Bus Phase Error " } ,
{ 0x002D , " P Failed because Device Returned Unknown Status " } ,
{ 0x002E , " P Failed because Device Not Ready " } ,
{ 0x002F , " P Failed because Device Not Found at Startup " } ,
{ 0x0030 , " P Failed because COD Write Operation Failed " } ,
{ 0x0031 , " P Failed because BDT Write Operation Failed " } ,
{ 0x0039 , " P Missing at Startup " } ,
{ 0x003A , " P Start Rebuild Failed due to Physical Drive Too Small " } ,
{ 0x003C , " P Temporarily Offline Device Automatically Made Online " } ,
{ 0x003D , " P Standby Rebuild Started " } ,
/* Logical Device Events (0x0080 - 0x00FF) */
{ 0x0080 , " M Consistency Check Started " } ,
{ 0x0081 , " M Consistency Check Completed " } ,
{ 0x0082 , " M Consistency Check Cancelled " } ,
{ 0x0083 , " M Consistency Check Completed With Errors " } ,
{ 0x0084 , " M Consistency Check Failed due to Logical Drive Failure " } ,
{ 0x0085 , " M Consistency Check Failed due to Physical Device Failure " } ,
{ 0x0086 , " L Offline " } ,
{ 0x0087 , " L Critical " } ,
{ 0x0088 , " L Online " } ,
{ 0x0089 , " M Automatic Rebuild Started " } ,
{ 0x008A , " M Manual Rebuild Started " } ,
{ 0x008B , " M Rebuild Completed " } ,
{ 0x008C , " M Rebuild Cancelled " } ,
{ 0x008D , " M Rebuild Failed for Unknown Reasons " } ,
{ 0x008E , " M Rebuild Failed due to New Physical Device " } ,
{ 0x008F , " M Rebuild Failed due to Logical Drive Failure " } ,
{ 0x0090 , " M Initialization Started " } ,
{ 0x0091 , " M Initialization Completed " } ,
{ 0x0092 , " M Initialization Cancelled " } ,
{ 0x0093 , " M Initialization Failed " } ,
{ 0x0094 , " L Found " } ,
{ 0x0095 , " L Deleted " } ,
{ 0x0096 , " M Expand Capacity Started " } ,
{ 0x0097 , " M Expand Capacity Completed " } ,
{ 0x0098 , " M Expand Capacity Failed " } ,
{ 0x0099 , " L Bad Block Found " } ,
{ 0x009A , " L Size Changed " } ,
{ 0x009B , " L Type Changed " } ,
{ 0x009C , " L Bad Data Block Found " } ,
{ 0x009E , " L Read of Data Block in BDT " } ,
{ 0x009F , " L Write Back Data for Disk Block Lost " } ,
{ 0x00A0 , " L Temporarily Offline RAID-5/3 Drive Made Online " } ,
{ 0x00A1 , " L Temporarily Offline RAID-6/1/0/7 Drive Made Online " } ,
{ 0x00A2 , " L Standby Rebuild Started " } ,
/* Fault Management Events (0x0100 - 0x017F) */
{ 0x0140 , " E Fan %d Failed " } ,
{ 0x0141 , " E Fan %d OK " } ,
{ 0x0142 , " E Fan %d Not Present " } ,
{ 0x0143 , " E Power Supply %d Failed " } ,
{ 0x0144 , " E Power Supply %d OK " } ,
{ 0x0145 , " E Power Supply %d Not Present " } ,
{ 0x0146 , " E Temperature Sensor %d Temperature Exceeds Safe Limit " } ,
{ 0x0147 , " E Temperature Sensor %d Temperature Exceeds Working Limit " } ,
{ 0x0148 , " E Temperature Sensor %d Temperature Normal " } ,
{ 0x0149 , " E Temperature Sensor %d Not Present " } ,
{ 0x014A , " E Enclosure Management Unit %d Access Critical " } ,
{ 0x014B , " E Enclosure Management Unit %d Access OK " } ,
{ 0x014C , " E Enclosure Management Unit %d Access Offline " } ,
/* Controller Events (0x0180 - 0x01FF) */
{ 0x0181 , " C Cache Write Back Error " } ,
{ 0x0188 , " C Battery Backup Unit Found " } ,
{ 0x0189 , " C Battery Backup Unit Charge Level Low " } ,
{ 0x018A , " C Battery Backup Unit Charge Level OK " } ,
{ 0x0193 , " C Installation Aborted " } ,
{ 0x0195 , " C Battery Backup Unit Physically Removed " } ,
{ 0x0196 , " C Memory Error During Warm Boot " } ,
{ 0x019E , " C Memory Soft ECC Error Corrected " } ,
{ 0x019F , " C Memory Hard ECC Error Corrected " } ,
{ 0x01A2 , " C Battery Backup Unit Failed " } ,
{ 0x01AB , " C Mirror Race Recovery Failed " } ,
{ 0x01AC , " C Mirror Race on Critical Drive " } ,
/* Controller Internal Processor Events */
{ 0x0380 , " C Internal Controller Hung " } ,
{ 0x0381 , " C Internal Controller Firmware Breakpoint " } ,
{ 0x0390 , " C Internal Controller i960 Processor Specific Error " } ,
{ 0x03A0 , " C Internal Controller StrongARM Processor Specific Error " } ,
{ 0 , " " } } ;
int EventListIndex = 0 , EventCode ;
unsigned char EventType , * EventMessage ;
if ( Event - > EventCode = = 0x1C & &
RequestSense - > SenseKey = = DAC960_SenseKey_VendorSpecific & &
( RequestSense - > AdditionalSenseCode = = 0x80 | |
RequestSense - > AdditionalSenseCode = = 0x81 ) )
Event - > EventCode = ( ( RequestSense - > AdditionalSenseCode - 0x80 ) < < 8 ) |
RequestSense - > AdditionalSenseCodeQualifier ;
while ( true )
{
EventCode = EventList [ EventListIndex ] . EventCode ;
if ( EventCode = = Event - > EventCode | | EventCode = = 0 ) break ;
EventListIndex + + ;
}
EventType = EventList [ EventListIndex ] . EventMessage [ 0 ] ;
EventMessage = & EventList [ EventListIndex ] . EventMessage [ 2 ] ;
if ( EventCode = = 0 )
{
DAC960_Critical ( " Unknown Controller Event Code %04X \n " ,
Controller , Event - > EventCode ) ;
return ;
}
switch ( EventType )
{
case ' P ' :
DAC960_Critical ( " Physical Device %d:%d %s \n " , Controller ,
Event - > Channel , Event - > TargetID , EventMessage ) ;
break ;
case ' L ' :
DAC960_Critical ( " Logical Drive %d (/dev/rd/c%dd%d) %s \n " , Controller ,
Event - > LogicalUnit , Controller - > ControllerNumber ,
Event - > LogicalUnit , EventMessage ) ;
break ;
case ' M ' :
DAC960_Progress ( " Logical Drive %d (/dev/rd/c%dd%d) %s \n " , Controller ,
Event - > LogicalUnit , Controller - > ControllerNumber ,
Event - > LogicalUnit , EventMessage ) ;
break ;
case ' S ' :
if ( RequestSense - > SenseKey = = DAC960_SenseKey_NoSense | |
( RequestSense - > SenseKey = = DAC960_SenseKey_NotReady & &
RequestSense - > AdditionalSenseCode = = 0x04 & &
( RequestSense - > AdditionalSenseCodeQualifier = = 0x01 | |
RequestSense - > AdditionalSenseCodeQualifier = = 0x02 ) ) )
break ;
DAC960_Critical ( " Physical Device %d:%d %s \n " , Controller ,
Event - > Channel , Event - > TargetID , EventMessage ) ;
DAC960_Critical ( " Physical Device %d:%d Request Sense: "
" Sense Key = %X, ASC = %02X, ASCQ = %02X \n " ,
Controller ,
Event - > Channel ,
Event - > TargetID ,
RequestSense - > SenseKey ,
RequestSense - > AdditionalSenseCode ,
RequestSense - > AdditionalSenseCodeQualifier ) ;
DAC960_Critical ( " Physical Device %d:%d Request Sense: "
" Information = %02X%02X%02X%02X "
" %02X%02X%02X%02X \n " ,
Controller ,
Event - > Channel ,
Event - > TargetID ,
RequestSense - > Information [ 0 ] ,
RequestSense - > Information [ 1 ] ,
RequestSense - > Information [ 2 ] ,
RequestSense - > Information [ 3 ] ,
RequestSense - > CommandSpecificInformation [ 0 ] ,
RequestSense - > CommandSpecificInformation [ 1 ] ,
RequestSense - > CommandSpecificInformation [ 2 ] ,
RequestSense - > CommandSpecificInformation [ 3 ] ) ;
break ;
case ' E ' :
if ( Controller - > SuppressEnclosureMessages ) break ;
sprintf ( MessageBuffer , EventMessage , Event - > LogicalUnit ) ;
DAC960_Critical ( " Enclosure %d %s \n " , Controller ,
Event - > TargetID , MessageBuffer ) ;
break ;
case ' C ' :
DAC960_Critical ( " Controller %s \n " , Controller , EventMessage ) ;
break ;
default :
DAC960_Critical ( " Unknown Controller Event Code %04X \n " ,
Controller , Event - > EventCode ) ;
break ;
}
}
/*
DAC960_V2_ReportProgress prints an appropriate progress message for
Logical Device Long Operations .
*/
static void DAC960_V2_ReportProgress ( DAC960_Controller_T * Controller ,
unsigned char * MessageString ,
unsigned int LogicalDeviceNumber ,
unsigned long BlocksCompleted ,
unsigned long LogicalDeviceSize )
{
Controller - > EphemeralProgressMessage = true ;
DAC960_Progress ( " %s in Progress: Logical Drive %d (/dev/rd/c%dd%d) "
" %d%% completed \n " , Controller ,
MessageString ,
LogicalDeviceNumber ,
Controller - > ControllerNumber ,
LogicalDeviceNumber ,
( 100 * ( BlocksCompleted > > 7 ) ) / ( LogicalDeviceSize > > 7 ) ) ;
Controller - > EphemeralProgressMessage = false ;
}
/*
DAC960_V2_ProcessCompletedCommand performs completion processing for Command
for DAC960 V2 Firmware Controllers .
*/
static void DAC960_V2_ProcessCompletedCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
DAC960_CommandType_T CommandType = Command - > CommandType ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_IOCTL_Opcode_T CommandOpcode = CommandMailbox - > Common . IOCTL_Opcode ;
DAC960_V2_CommandStatus_T CommandStatus = Command - > V2 . CommandStatus ;
if ( CommandType = = DAC960_ReadCommand | |
CommandType = = DAC960_WriteCommand )
{
# ifdef FORCE_RETRY_DEBUG
CommandStatus = DAC960_V2_AbormalCompletion ;
# endif
Command - > V2 . RequestSense - > SenseKey = DAC960_SenseKey_MediumError ;
if ( CommandStatus = = DAC960_V2_NormalCompletion ) {
if ( ! DAC960_ProcessCompletedRequest ( Command , true ) )
BUG ( ) ;
} else if ( Command - > V2 . RequestSense - > SenseKey = = DAC960_SenseKey_MediumError )
{
/*
* break the command down into pieces and resubmit each
* piece , hoping that some of them will succeed .
*/
DAC960_queue_partial_rw ( Command ) ;
return ;
}
else
{
if ( Command - > V2 . RequestSense - > SenseKey ! = DAC960_SenseKey_NotReady )
DAC960_V2_ReadWriteError ( Command ) ;
/*
Perform completion processing for all buffers in this I / O Request .
*/
( void ) DAC960_ProcessCompletedRequest ( Command , false ) ;
}
}
else if ( CommandType = = DAC960_ReadRetryCommand | |
CommandType = = DAC960_WriteRetryCommand )
{
boolean normal_completion ;
# ifdef FORCE_RETRY_FAILURE_DEBUG
static int retry_count = 1 ;
# endif
/*
Perform completion processing for the portion that was
retried , and submit the next portion , if any .
*/
normal_completion = true ;
if ( CommandStatus ! = DAC960_V2_NormalCompletion ) {
normal_completion = false ;
if ( Command - > V2 . RequestSense - > SenseKey ! = DAC960_SenseKey_NotReady )
DAC960_V2_ReadWriteError ( Command ) ;
}
# ifdef FORCE_RETRY_FAILURE_DEBUG
if ( ! ( + + retry_count % 10000 ) ) {
printk ( " V2 error retry failure test \n " ) ;
normal_completion = false ;
DAC960_V2_ReadWriteError ( Command ) ;
}
# endif
if ( ! DAC960_ProcessCompletedRequest ( Command , normal_completion ) ) {
DAC960_queue_partial_rw ( Command ) ;
return ;
}
}
else if ( CommandType = = DAC960_MonitoringCommand )
{
if ( Controller - > ShutdownMonitoringTimer )
return ;
if ( CommandOpcode = = DAC960_V2_GetControllerInfo )
{
DAC960_V2_ControllerInfo_T * NewControllerInfo =
Controller - > V2 . NewControllerInformation ;
DAC960_V2_ControllerInfo_T * ControllerInfo =
& Controller - > V2 . ControllerInformation ;
Controller - > LogicalDriveCount =
NewControllerInfo - > LogicalDevicesPresent ;
Controller - > V2 . NeedLogicalDeviceInformation = true ;
Controller - > V2 . NeedPhysicalDeviceInformation = true ;
Controller - > V2 . StartLogicalDeviceInformationScan = true ;
Controller - > V2 . StartPhysicalDeviceInformationScan = true ;
Controller - > MonitoringAlertMode =
( NewControllerInfo - > LogicalDevicesCritical > 0 | |
NewControllerInfo - > LogicalDevicesOffline > 0 | |
NewControllerInfo - > PhysicalDisksCritical > 0 | |
NewControllerInfo - > PhysicalDisksOffline > 0 ) ;
memcpy ( ControllerInfo , NewControllerInfo ,
sizeof ( DAC960_V2_ControllerInfo_T ) ) ;
}
else if ( CommandOpcode = = DAC960_V2_GetEvent )
{
if ( CommandStatus = = DAC960_V2_NormalCompletion ) {
DAC960_V2_ReportEvent ( Controller , Controller - > V2 . Event ) ;
}
Controller - > V2 . NextEventSequenceNumber + + ;
}
else if ( CommandOpcode = = DAC960_V2_GetPhysicalDeviceInfoValid & &
CommandStatus = = DAC960_V2_NormalCompletion )
{
DAC960_V2_PhysicalDeviceInfo_T * NewPhysicalDeviceInfo =
Controller - > V2 . NewPhysicalDeviceInformation ;
unsigned int PhysicalDeviceIndex = Controller - > V2 . PhysicalDeviceIndex ;
DAC960_V2_PhysicalDeviceInfo_T * PhysicalDeviceInfo =
Controller - > V2 . PhysicalDeviceInformation [ PhysicalDeviceIndex ] ;
DAC960_SCSI_Inquiry_UnitSerialNumber_T * InquiryUnitSerialNumber =
Controller - > V2 . InquiryUnitSerialNumber [ PhysicalDeviceIndex ] ;
unsigned int DeviceIndex ;
while ( PhysicalDeviceInfo ! = NULL & &
( NewPhysicalDeviceInfo - > Channel >
PhysicalDeviceInfo - > Channel | |
( NewPhysicalDeviceInfo - > Channel = =
PhysicalDeviceInfo - > Channel & &
( NewPhysicalDeviceInfo - > TargetID >
PhysicalDeviceInfo - > TargetID | |
( NewPhysicalDeviceInfo - > TargetID = =
PhysicalDeviceInfo - > TargetID & &
NewPhysicalDeviceInfo - > LogicalUnit >
PhysicalDeviceInfo - > LogicalUnit ) ) ) ) )
{
DAC960_Critical ( " Physical Device %d:%d No Longer Exists \n " ,
Controller ,
PhysicalDeviceInfo - > Channel ,
PhysicalDeviceInfo - > TargetID ) ;
Controller - > V2 . PhysicalDeviceInformation
[ PhysicalDeviceIndex ] = NULL ;
Controller - > V2 . InquiryUnitSerialNumber
[ PhysicalDeviceIndex ] = NULL ;
kfree ( PhysicalDeviceInfo ) ;
kfree ( InquiryUnitSerialNumber ) ;
for ( DeviceIndex = PhysicalDeviceIndex ;
DeviceIndex < DAC960_V2_MaxPhysicalDevices - 1 ;
DeviceIndex + + )
{
Controller - > V2 . PhysicalDeviceInformation [ DeviceIndex ] =
Controller - > V2 . PhysicalDeviceInformation [ DeviceIndex + 1 ] ;
Controller - > V2 . InquiryUnitSerialNumber [ DeviceIndex ] =
Controller - > V2 . InquiryUnitSerialNumber [ DeviceIndex + 1 ] ;
}
Controller - > V2 . PhysicalDeviceInformation
[ DAC960_V2_MaxPhysicalDevices - 1 ] = NULL ;
Controller - > V2 . InquiryUnitSerialNumber
[ DAC960_V2_MaxPhysicalDevices - 1 ] = NULL ;
PhysicalDeviceInfo =
Controller - > V2 . PhysicalDeviceInformation [ PhysicalDeviceIndex ] ;
InquiryUnitSerialNumber =
Controller - > V2 . InquiryUnitSerialNumber [ PhysicalDeviceIndex ] ;
}
if ( PhysicalDeviceInfo = = NULL | |
( NewPhysicalDeviceInfo - > Channel ! =
PhysicalDeviceInfo - > Channel ) | |
( NewPhysicalDeviceInfo - > TargetID ! =
PhysicalDeviceInfo - > TargetID ) | |
( NewPhysicalDeviceInfo - > LogicalUnit ! =
PhysicalDeviceInfo - > LogicalUnit ) )
{
PhysicalDeviceInfo = ( DAC960_V2_PhysicalDeviceInfo_T * )
kmalloc ( sizeof ( DAC960_V2_PhysicalDeviceInfo_T ) , GFP_ATOMIC ) ;
InquiryUnitSerialNumber =
( DAC960_SCSI_Inquiry_UnitSerialNumber_T * )
kmalloc ( sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ,
GFP_ATOMIC ) ;
if ( InquiryUnitSerialNumber = = NULL & &
PhysicalDeviceInfo ! = NULL )
{
kfree ( PhysicalDeviceInfo ) ;
PhysicalDeviceInfo = NULL ;
}
DAC960_Critical ( " Physical Device %d:%d Now Exists%s \n " ,
Controller ,
NewPhysicalDeviceInfo - > Channel ,
NewPhysicalDeviceInfo - > TargetID ,
( PhysicalDeviceInfo ! = NULL
? " " : " - Allocation Failed " ) ) ;
if ( PhysicalDeviceInfo ! = NULL )
{
memset ( PhysicalDeviceInfo , 0 ,
sizeof ( DAC960_V2_PhysicalDeviceInfo_T ) ) ;
PhysicalDeviceInfo - > PhysicalDeviceState =
DAC960_V2_Device_InvalidState ;
memset ( InquiryUnitSerialNumber , 0 ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ) ;
InquiryUnitSerialNumber - > PeripheralDeviceType = 0x1F ;
for ( DeviceIndex = DAC960_V2_MaxPhysicalDevices - 1 ;
DeviceIndex > PhysicalDeviceIndex ;
DeviceIndex - - )
{
Controller - > V2 . PhysicalDeviceInformation [ DeviceIndex ] =
Controller - > V2 . PhysicalDeviceInformation [ DeviceIndex - 1 ] ;
Controller - > V2 . InquiryUnitSerialNumber [ DeviceIndex ] =
Controller - > V2 . InquiryUnitSerialNumber [ DeviceIndex - 1 ] ;
}
Controller - > V2 . PhysicalDeviceInformation
[ PhysicalDeviceIndex ] =
PhysicalDeviceInfo ;
Controller - > V2 . InquiryUnitSerialNumber
[ PhysicalDeviceIndex ] =
InquiryUnitSerialNumber ;
Controller - > V2 . NeedDeviceSerialNumberInformation = true ;
}
}
if ( PhysicalDeviceInfo ! = NULL )
{
if ( NewPhysicalDeviceInfo - > PhysicalDeviceState ! =
PhysicalDeviceInfo - > PhysicalDeviceState )
DAC960_Critical (
" Physical Device %d:%d is now %s \n " , Controller ,
NewPhysicalDeviceInfo - > Channel ,
NewPhysicalDeviceInfo - > TargetID ,
( NewPhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Online
? " ONLINE "
: NewPhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Rebuild
? " REBUILD "
: NewPhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Missing
? " MISSING "
: NewPhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Critical
? " CRITICAL "
: NewPhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Dead
? " DEAD "
: NewPhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_SuspectedDead
? " SUSPECTED-DEAD "
: NewPhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_CommandedOffline
? " COMMANDED-OFFLINE "
: NewPhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Standby
? " STANDBY " : " UNKNOWN " ) ) ;
if ( ( NewPhysicalDeviceInfo - > ParityErrors ! =
PhysicalDeviceInfo - > ParityErrors ) | |
( NewPhysicalDeviceInfo - > SoftErrors ! =
PhysicalDeviceInfo - > SoftErrors ) | |
( NewPhysicalDeviceInfo - > HardErrors ! =
PhysicalDeviceInfo - > HardErrors ) | |
( NewPhysicalDeviceInfo - > MiscellaneousErrors ! =
PhysicalDeviceInfo - > MiscellaneousErrors ) | |
( NewPhysicalDeviceInfo - > CommandTimeouts ! =
PhysicalDeviceInfo - > CommandTimeouts ) | |
( NewPhysicalDeviceInfo - > Retries ! =
PhysicalDeviceInfo - > Retries ) | |
( NewPhysicalDeviceInfo - > Aborts ! =
PhysicalDeviceInfo - > Aborts ) | |
( NewPhysicalDeviceInfo - > PredictedFailuresDetected ! =
PhysicalDeviceInfo - > PredictedFailuresDetected ) )
{
DAC960_Critical ( " Physical Device %d:%d Errors: "
" Parity = %d, Soft = %d, "
" Hard = %d, Misc = %d \n " ,
Controller ,
NewPhysicalDeviceInfo - > Channel ,
NewPhysicalDeviceInfo - > TargetID ,
NewPhysicalDeviceInfo - > ParityErrors ,
NewPhysicalDeviceInfo - > SoftErrors ,
NewPhysicalDeviceInfo - > HardErrors ,
NewPhysicalDeviceInfo - > MiscellaneousErrors ) ;
DAC960_Critical ( " Physical Device %d:%d Errors: "
" Timeouts = %d, Retries = %d, "
" Aborts = %d, Predicted = %d \n " ,
Controller ,
NewPhysicalDeviceInfo - > Channel ,
NewPhysicalDeviceInfo - > TargetID ,
NewPhysicalDeviceInfo - > CommandTimeouts ,
NewPhysicalDeviceInfo - > Retries ,
NewPhysicalDeviceInfo - > Aborts ,
NewPhysicalDeviceInfo
- > PredictedFailuresDetected ) ;
}
if ( ( PhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_Dead | |
PhysicalDeviceInfo - > PhysicalDeviceState
= = DAC960_V2_Device_InvalidState ) & &
NewPhysicalDeviceInfo - > PhysicalDeviceState
! = DAC960_V2_Device_Dead )
Controller - > V2 . NeedDeviceSerialNumberInformation = true ;
memcpy ( PhysicalDeviceInfo , NewPhysicalDeviceInfo ,
sizeof ( DAC960_V2_PhysicalDeviceInfo_T ) ) ;
}
NewPhysicalDeviceInfo - > LogicalUnit + + ;
Controller - > V2 . PhysicalDeviceIndex + + ;
}
else if ( CommandOpcode = = DAC960_V2_GetPhysicalDeviceInfoValid )
{
unsigned int DeviceIndex ;
for ( DeviceIndex = Controller - > V2 . PhysicalDeviceIndex ;
DeviceIndex < DAC960_V2_MaxPhysicalDevices ;
DeviceIndex + + )
{
DAC960_V2_PhysicalDeviceInfo_T * PhysicalDeviceInfo =
Controller - > V2 . PhysicalDeviceInformation [ DeviceIndex ] ;
DAC960_SCSI_Inquiry_UnitSerialNumber_T * InquiryUnitSerialNumber =
Controller - > V2 . InquiryUnitSerialNumber [ DeviceIndex ] ;
if ( PhysicalDeviceInfo = = NULL ) break ;
DAC960_Critical ( " Physical Device %d:%d No Longer Exists \n " ,
Controller ,
PhysicalDeviceInfo - > Channel ,
PhysicalDeviceInfo - > TargetID ) ;
Controller - > V2 . PhysicalDeviceInformation [ DeviceIndex ] = NULL ;
Controller - > V2 . InquiryUnitSerialNumber [ DeviceIndex ] = NULL ;
kfree ( PhysicalDeviceInfo ) ;
kfree ( InquiryUnitSerialNumber ) ;
}
Controller - > V2 . NeedPhysicalDeviceInformation = false ;
}
else if ( CommandOpcode = = DAC960_V2_GetLogicalDeviceInfoValid & &
CommandStatus = = DAC960_V2_NormalCompletion )
{
DAC960_V2_LogicalDeviceInfo_T * NewLogicalDeviceInfo =
Controller - > V2 . NewLogicalDeviceInformation ;
unsigned short LogicalDeviceNumber =
NewLogicalDeviceInfo - > LogicalDeviceNumber ;
DAC960_V2_LogicalDeviceInfo_T * LogicalDeviceInfo =
Controller - > V2 . LogicalDeviceInformation [ LogicalDeviceNumber ] ;
if ( LogicalDeviceInfo = = NULL )
{
DAC960_V2_PhysicalDevice_T PhysicalDevice ;
PhysicalDevice . Controller = 0 ;
PhysicalDevice . Channel = NewLogicalDeviceInfo - > Channel ;
PhysicalDevice . TargetID = NewLogicalDeviceInfo - > TargetID ;
PhysicalDevice . LogicalUnit = NewLogicalDeviceInfo - > LogicalUnit ;
Controller - > V2 . LogicalDriveToVirtualDevice [ LogicalDeviceNumber ] =
PhysicalDevice ;
LogicalDeviceInfo = ( DAC960_V2_LogicalDeviceInfo_T * )
kmalloc ( sizeof ( DAC960_V2_LogicalDeviceInfo_T ) , GFP_ATOMIC ) ;
Controller - > V2 . LogicalDeviceInformation [ LogicalDeviceNumber ] =
LogicalDeviceInfo ;
DAC960_Critical ( " Logical Drive %d (/dev/rd/c%dd%d) "
" Now Exists%s \n " , Controller ,
LogicalDeviceNumber ,
Controller - > ControllerNumber ,
LogicalDeviceNumber ,
( LogicalDeviceInfo ! = NULL
? " " : " - Allocation Failed " ) ) ;
if ( LogicalDeviceInfo ! = NULL )
{
memset ( LogicalDeviceInfo , 0 ,
sizeof ( DAC960_V2_LogicalDeviceInfo_T ) ) ;
DAC960_ComputeGenericDiskInfo ( Controller ) ;
}
}
if ( LogicalDeviceInfo ! = NULL )
{
unsigned long LogicalDeviceSize =
NewLogicalDeviceInfo - > ConfigurableDeviceSize ;
if ( NewLogicalDeviceInfo - > LogicalDeviceState ! =
LogicalDeviceInfo - > LogicalDeviceState )
DAC960_Critical ( " Logical Drive %d (/dev/rd/c%dd%d) "
" is now %s \n " , Controller ,
LogicalDeviceNumber ,
Controller - > ControllerNumber ,
LogicalDeviceNumber ,
( NewLogicalDeviceInfo - > LogicalDeviceState
= = DAC960_V2_LogicalDevice_Online
? " ONLINE "
: NewLogicalDeviceInfo - > LogicalDeviceState
= = DAC960_V2_LogicalDevice_Critical
? " CRITICAL " : " OFFLINE " ) ) ;
if ( ( NewLogicalDeviceInfo - > SoftErrors ! =
LogicalDeviceInfo - > SoftErrors ) | |
( NewLogicalDeviceInfo - > CommandsFailed ! =
LogicalDeviceInfo - > CommandsFailed ) | |
( NewLogicalDeviceInfo - > DeferredWriteErrors ! =
LogicalDeviceInfo - > DeferredWriteErrors ) )
DAC960_Critical ( " Logical Drive %d (/dev/rd/c%dd%d) Errors: "
" Soft = %d, Failed = %d, Deferred Write = %d \n " ,
Controller , LogicalDeviceNumber ,
Controller - > ControllerNumber ,
LogicalDeviceNumber ,
NewLogicalDeviceInfo - > SoftErrors ,
NewLogicalDeviceInfo - > CommandsFailed ,
NewLogicalDeviceInfo - > DeferredWriteErrors ) ;
if ( NewLogicalDeviceInfo - > ConsistencyCheckInProgress )
DAC960_V2_ReportProgress ( Controller ,
" Consistency Check " ,
LogicalDeviceNumber ,
NewLogicalDeviceInfo
- > ConsistencyCheckBlockNumber ,
LogicalDeviceSize ) ;
else if ( NewLogicalDeviceInfo - > RebuildInProgress )
DAC960_V2_ReportProgress ( Controller ,
" Rebuild " ,
LogicalDeviceNumber ,
NewLogicalDeviceInfo
- > RebuildBlockNumber ,
LogicalDeviceSize ) ;
else if ( NewLogicalDeviceInfo - > BackgroundInitializationInProgress )
DAC960_V2_ReportProgress ( Controller ,
" Background Initialization " ,
LogicalDeviceNumber ,
NewLogicalDeviceInfo
- > BackgroundInitializationBlockNumber ,
LogicalDeviceSize ) ;
else if ( NewLogicalDeviceInfo - > ForegroundInitializationInProgress )
DAC960_V2_ReportProgress ( Controller ,
" Foreground Initialization " ,
LogicalDeviceNumber ,
NewLogicalDeviceInfo
- > ForegroundInitializationBlockNumber ,
LogicalDeviceSize ) ;
else if ( NewLogicalDeviceInfo - > DataMigrationInProgress )
DAC960_V2_ReportProgress ( Controller ,
" Data Migration " ,
LogicalDeviceNumber ,
NewLogicalDeviceInfo
- > DataMigrationBlockNumber ,
LogicalDeviceSize ) ;
else if ( NewLogicalDeviceInfo - > PatrolOperationInProgress )
DAC960_V2_ReportProgress ( Controller ,
" Patrol Operation " ,
LogicalDeviceNumber ,
NewLogicalDeviceInfo
- > PatrolOperationBlockNumber ,
LogicalDeviceSize ) ;
if ( LogicalDeviceInfo - > BackgroundInitializationInProgress & &
! NewLogicalDeviceInfo - > BackgroundInitializationInProgress )
DAC960_Progress ( " Logical Drive %d (/dev/rd/c%dd%d) "
" Background Initialization %s \n " ,
Controller ,
LogicalDeviceNumber ,
Controller - > ControllerNumber ,
LogicalDeviceNumber ,
( NewLogicalDeviceInfo - > LogicalDeviceControl
. LogicalDeviceInitialized
? " Completed " : " Failed " ) ) ;
memcpy ( LogicalDeviceInfo , NewLogicalDeviceInfo ,
sizeof ( DAC960_V2_LogicalDeviceInfo_T ) ) ;
}
Controller - > V2 . LogicalDriveFoundDuringScan
[ LogicalDeviceNumber ] = true ;
NewLogicalDeviceInfo - > LogicalDeviceNumber + + ;
}
else if ( CommandOpcode = = DAC960_V2_GetLogicalDeviceInfoValid )
{
int LogicalDriveNumber ;
for ( LogicalDriveNumber = 0 ;
LogicalDriveNumber < DAC960_MaxLogicalDrives ;
LogicalDriveNumber + + )
{
DAC960_V2_LogicalDeviceInfo_T * LogicalDeviceInfo =
Controller - > V2 . LogicalDeviceInformation [ LogicalDriveNumber ] ;
if ( LogicalDeviceInfo = = NULL | |
Controller - > V2 . LogicalDriveFoundDuringScan
[ LogicalDriveNumber ] )
continue ;
DAC960_Critical ( " Logical Drive %d (/dev/rd/c%dd%d) "
" No Longer Exists \n " , Controller ,
LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ) ;
Controller - > V2 . LogicalDeviceInformation
[ LogicalDriveNumber ] = NULL ;
kfree ( LogicalDeviceInfo ) ;
Controller - > LogicalDriveInitiallyAccessible
[ LogicalDriveNumber ] = false ;
DAC960_ComputeGenericDiskInfo ( Controller ) ;
}
Controller - > V2 . NeedLogicalDeviceInformation = false ;
}
else if ( CommandOpcode = = DAC960_V2_SCSI_10_Passthru )
{
DAC960_SCSI_Inquiry_UnitSerialNumber_T * InquiryUnitSerialNumber =
Controller - > V2 . InquiryUnitSerialNumber [ Controller - > V2 . PhysicalDeviceIndex - 1 ] ;
if ( CommandStatus ! = DAC960_V2_NormalCompletion ) {
memset ( InquiryUnitSerialNumber ,
0 , sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ) ;
InquiryUnitSerialNumber - > PeripheralDeviceType = 0x1F ;
} else
memcpy ( InquiryUnitSerialNumber ,
Controller - > V2 . NewInquiryUnitSerialNumber ,
sizeof ( DAC960_SCSI_Inquiry_UnitSerialNumber_T ) ) ;
Controller - > V2 . NeedDeviceSerialNumberInformation = false ;
}
if ( Controller - > V2 . HealthStatusBuffer - > NextEventSequenceNumber
- Controller - > V2 . NextEventSequenceNumber > 0 )
{
CommandMailbox - > GetEvent . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > GetEvent . DataTransferSize = sizeof ( DAC960_V2_Event_T ) ;
CommandMailbox - > GetEvent . EventSequenceNumberHigh16 =
Controller - > V2 . NextEventSequenceNumber > > 16 ;
CommandMailbox - > GetEvent . ControllerNumber = 0 ;
CommandMailbox - > GetEvent . IOCTL_Opcode =
DAC960_V2_GetEvent ;
CommandMailbox - > GetEvent . EventSequenceNumberLow16 =
Controller - > V2 . NextEventSequenceNumber & 0xFFFF ;
CommandMailbox - > GetEvent . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . EventDMA ;
CommandMailbox - > GetEvent . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > GetEvent . DataTransferSize ;
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V2 . NeedPhysicalDeviceInformation )
{
if ( Controller - > V2 . NeedDeviceSerialNumberInformation )
{
DAC960_SCSI_Inquiry_UnitSerialNumber_T * InquiryUnitSerialNumber =
Controller - > V2 . NewInquiryUnitSerialNumber ;
InquiryUnitSerialNumber - > PeripheralDeviceType = 0x1F ;
DAC960_V2_ConstructNewUnitSerialNumber ( Controller , CommandMailbox ,
Controller - > V2 . NewPhysicalDeviceInformation - > Channel ,
Controller - > V2 . NewPhysicalDeviceInformation - > TargetID ,
Controller - > V2 . NewPhysicalDeviceInformation - > LogicalUnit - 1 ) ;
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V2 . StartPhysicalDeviceInformationScan )
{
Controller - > V2 . PhysicalDeviceIndex = 0 ;
Controller - > V2 . NewPhysicalDeviceInformation - > Channel = 0 ;
Controller - > V2 . NewPhysicalDeviceInformation - > TargetID = 0 ;
Controller - > V2 . NewPhysicalDeviceInformation - > LogicalUnit = 0 ;
Controller - > V2 . StartPhysicalDeviceInformationScan = false ;
}
CommandMailbox - > PhysicalDeviceInfo . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > PhysicalDeviceInfo . DataTransferSize =
sizeof ( DAC960_V2_PhysicalDeviceInfo_T ) ;
CommandMailbox - > PhysicalDeviceInfo . PhysicalDevice . LogicalUnit =
Controller - > V2 . NewPhysicalDeviceInformation - > LogicalUnit ;
CommandMailbox - > PhysicalDeviceInfo . PhysicalDevice . TargetID =
Controller - > V2 . NewPhysicalDeviceInformation - > TargetID ;
CommandMailbox - > PhysicalDeviceInfo . PhysicalDevice . Channel =
Controller - > V2 . NewPhysicalDeviceInformation - > Channel ;
CommandMailbox - > PhysicalDeviceInfo . IOCTL_Opcode =
DAC960_V2_GetPhysicalDeviceInfoValid ;
CommandMailbox - > PhysicalDeviceInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . NewPhysicalDeviceInformationDMA ;
CommandMailbox - > PhysicalDeviceInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > PhysicalDeviceInfo . DataTransferSize ;
DAC960_QueueCommand ( Command ) ;
return ;
}
if ( Controller - > V2 . NeedLogicalDeviceInformation )
{
if ( Controller - > V2 . StartLogicalDeviceInformationScan )
{
int LogicalDriveNumber ;
for ( LogicalDriveNumber = 0 ;
LogicalDriveNumber < DAC960_MaxLogicalDrives ;
LogicalDriveNumber + + )
Controller - > V2 . LogicalDriveFoundDuringScan
[ LogicalDriveNumber ] = false ;
Controller - > V2 . NewLogicalDeviceInformation - > LogicalDeviceNumber = 0 ;
Controller - > V2 . StartLogicalDeviceInformationScan = false ;
}
CommandMailbox - > LogicalDeviceInfo . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > LogicalDeviceInfo . DataTransferSize =
sizeof ( DAC960_V2_LogicalDeviceInfo_T ) ;
CommandMailbox - > LogicalDeviceInfo . LogicalDevice . LogicalDeviceNumber =
Controller - > V2 . NewLogicalDeviceInformation - > LogicalDeviceNumber ;
CommandMailbox - > LogicalDeviceInfo . IOCTL_Opcode =
DAC960_V2_GetLogicalDeviceInfoValid ;
CommandMailbox - > LogicalDeviceInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . NewLogicalDeviceInformationDMA ;
CommandMailbox - > LogicalDeviceInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > LogicalDeviceInfo . DataTransferSize ;
DAC960_QueueCommand ( Command ) ;
return ;
}
Controller - > MonitoringTimerCount + + ;
Controller - > MonitoringTimer . expires =
jiffies + DAC960_HealthStatusMonitoringInterval ;
add_timer ( & Controller - > MonitoringTimer ) ;
}
if ( CommandType = = DAC960_ImmediateCommand )
{
complete ( Command - > Completion ) ;
Command - > Completion = NULL ;
return ;
}
if ( CommandType = = DAC960_QueuedCommand )
{
DAC960_V2_KernelCommand_T * KernelCommand = Command - > V2 . KernelCommand ;
KernelCommand - > CommandStatus = CommandStatus ;
KernelCommand - > RequestSenseLength = Command - > V2 . RequestSenseLength ;
KernelCommand - > DataTransferLength = Command - > V2 . DataTransferResidue ;
Command - > V2 . KernelCommand = NULL ;
DAC960_DeallocateCommand ( Command ) ;
KernelCommand - > CompletionFunction ( KernelCommand ) ;
return ;
}
/*
Queue a Status Monitoring Command to the Controller using the just
completed Command if one was deferred previously due to lack of a
free Command when the Monitoring Timer Function was called .
*/
if ( Controller - > MonitoringCommandDeferred )
{
Controller - > MonitoringCommandDeferred = false ;
DAC960_V2_QueueMonitoringCommand ( Command ) ;
return ;
}
/*
Deallocate the Command .
*/
DAC960_DeallocateCommand ( Command ) ;
/*
Wake up any processes waiting on a free Command .
*/
wake_up ( & Controller - > CommandWaitQueue ) ;
}
2005-05-05 16:15:58 -07:00
/*
DAC960_GEM_InterruptHandler handles hardware interrupts from DAC960 GEM Series
Controllers .
*/
static irqreturn_t DAC960_GEM_InterruptHandler ( int IRQ_Channel ,
void * DeviceIdentifier ,
struct pt_regs * InterruptRegisters )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) DeviceIdentifier ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V2_StatusMailbox_T * NextStatusMailbox ;
unsigned long flags ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_GEM_AcknowledgeInterrupt ( ControllerBaseAddress ) ;
NextStatusMailbox = Controller - > V2 . NextStatusMailbox ;
while ( NextStatusMailbox - > Fields . CommandIdentifier > 0 )
{
DAC960_V2_CommandIdentifier_T CommandIdentifier =
NextStatusMailbox - > Fields . CommandIdentifier ;
DAC960_Command_T * Command = Controller - > Commands [ CommandIdentifier - 1 ] ;
Command - > V2 . CommandStatus = NextStatusMailbox - > Fields . CommandStatus ;
Command - > V2 . RequestSenseLength =
NextStatusMailbox - > Fields . RequestSenseLength ;
Command - > V2 . DataTransferResidue =
NextStatusMailbox - > Fields . DataTransferResidue ;
NextStatusMailbox - > Words [ 0 ] = 0 ;
if ( + + NextStatusMailbox > Controller - > V2 . LastStatusMailbox )
NextStatusMailbox = Controller - > V2 . FirstStatusMailbox ;
DAC960_V2_ProcessCompletedCommand ( Command ) ;
}
Controller - > V2 . NextStatusMailbox = NextStatusMailbox ;
/*
Attempt to remove additional I / O Requests from the Controller ' s
I / O Request Queue and queue them to the Controller .
*/
DAC960_ProcessRequest ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
return IRQ_HANDLED ;
}
2005-04-16 15:20:36 -07:00
/*
DAC960_BA_InterruptHandler handles hardware interrupts from DAC960 BA Series
Controllers .
*/
static irqreturn_t DAC960_BA_InterruptHandler ( int IRQ_Channel ,
void * DeviceIdentifier ,
struct pt_regs * InterruptRegisters )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) DeviceIdentifier ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V2_StatusMailbox_T * NextStatusMailbox ;
unsigned long flags ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_BA_AcknowledgeInterrupt ( ControllerBaseAddress ) ;
NextStatusMailbox = Controller - > V2 . NextStatusMailbox ;
while ( NextStatusMailbox - > Fields . CommandIdentifier > 0 )
{
DAC960_V2_CommandIdentifier_T CommandIdentifier =
NextStatusMailbox - > Fields . CommandIdentifier ;
DAC960_Command_T * Command = Controller - > Commands [ CommandIdentifier - 1 ] ;
Command - > V2 . CommandStatus = NextStatusMailbox - > Fields . CommandStatus ;
Command - > V2 . RequestSenseLength =
NextStatusMailbox - > Fields . RequestSenseLength ;
Command - > V2 . DataTransferResidue =
NextStatusMailbox - > Fields . DataTransferResidue ;
NextStatusMailbox - > Words [ 0 ] = 0 ;
if ( + + NextStatusMailbox > Controller - > V2 . LastStatusMailbox )
NextStatusMailbox = Controller - > V2 . FirstStatusMailbox ;
DAC960_V2_ProcessCompletedCommand ( Command ) ;
}
Controller - > V2 . NextStatusMailbox = NextStatusMailbox ;
/*
Attempt to remove additional I / O Requests from the Controller ' s
I / O Request Queue and queue them to the Controller .
*/
DAC960_ProcessRequest ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
return IRQ_HANDLED ;
}
/*
DAC960_LP_InterruptHandler handles hardware interrupts from DAC960 LP Series
Controllers .
*/
static irqreturn_t DAC960_LP_InterruptHandler ( int IRQ_Channel ,
void * DeviceIdentifier ,
struct pt_regs * InterruptRegisters )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) DeviceIdentifier ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V2_StatusMailbox_T * NextStatusMailbox ;
unsigned long flags ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_LP_AcknowledgeInterrupt ( ControllerBaseAddress ) ;
NextStatusMailbox = Controller - > V2 . NextStatusMailbox ;
while ( NextStatusMailbox - > Fields . CommandIdentifier > 0 )
{
DAC960_V2_CommandIdentifier_T CommandIdentifier =
NextStatusMailbox - > Fields . CommandIdentifier ;
DAC960_Command_T * Command = Controller - > Commands [ CommandIdentifier - 1 ] ;
Command - > V2 . CommandStatus = NextStatusMailbox - > Fields . CommandStatus ;
Command - > V2 . RequestSenseLength =
NextStatusMailbox - > Fields . RequestSenseLength ;
Command - > V2 . DataTransferResidue =
NextStatusMailbox - > Fields . DataTransferResidue ;
NextStatusMailbox - > Words [ 0 ] = 0 ;
if ( + + NextStatusMailbox > Controller - > V2 . LastStatusMailbox )
NextStatusMailbox = Controller - > V2 . FirstStatusMailbox ;
DAC960_V2_ProcessCompletedCommand ( Command ) ;
}
Controller - > V2 . NextStatusMailbox = NextStatusMailbox ;
/*
Attempt to remove additional I / O Requests from the Controller ' s
I / O Request Queue and queue them to the Controller .
*/
DAC960_ProcessRequest ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
return IRQ_HANDLED ;
}
/*
DAC960_LA_InterruptHandler handles hardware interrupts from DAC960 LA Series
Controllers .
*/
static irqreturn_t DAC960_LA_InterruptHandler ( int IRQ_Channel ,
void * DeviceIdentifier ,
struct pt_regs * InterruptRegisters )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) DeviceIdentifier ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V1_StatusMailbox_T * NextStatusMailbox ;
unsigned long flags ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_LA_AcknowledgeInterrupt ( ControllerBaseAddress ) ;
NextStatusMailbox = Controller - > V1 . NextStatusMailbox ;
while ( NextStatusMailbox - > Fields . Valid )
{
DAC960_V1_CommandIdentifier_T CommandIdentifier =
NextStatusMailbox - > Fields . CommandIdentifier ;
DAC960_Command_T * Command = Controller - > Commands [ CommandIdentifier - 1 ] ;
Command - > V1 . CommandStatus = NextStatusMailbox - > Fields . CommandStatus ;
NextStatusMailbox - > Word = 0 ;
if ( + + NextStatusMailbox > Controller - > V1 . LastStatusMailbox )
NextStatusMailbox = Controller - > V1 . FirstStatusMailbox ;
DAC960_V1_ProcessCompletedCommand ( Command ) ;
}
Controller - > V1 . NextStatusMailbox = NextStatusMailbox ;
/*
Attempt to remove additional I / O Requests from the Controller ' s
I / O Request Queue and queue them to the Controller .
*/
DAC960_ProcessRequest ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
return IRQ_HANDLED ;
}
/*
DAC960_PG_InterruptHandler handles hardware interrupts from DAC960 PG Series
Controllers .
*/
static irqreturn_t DAC960_PG_InterruptHandler ( int IRQ_Channel ,
void * DeviceIdentifier ,
struct pt_regs * InterruptRegisters )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) DeviceIdentifier ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
DAC960_V1_StatusMailbox_T * NextStatusMailbox ;
unsigned long flags ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_PG_AcknowledgeInterrupt ( ControllerBaseAddress ) ;
NextStatusMailbox = Controller - > V1 . NextStatusMailbox ;
while ( NextStatusMailbox - > Fields . Valid )
{
DAC960_V1_CommandIdentifier_T CommandIdentifier =
NextStatusMailbox - > Fields . CommandIdentifier ;
DAC960_Command_T * Command = Controller - > Commands [ CommandIdentifier - 1 ] ;
Command - > V1 . CommandStatus = NextStatusMailbox - > Fields . CommandStatus ;
NextStatusMailbox - > Word = 0 ;
if ( + + NextStatusMailbox > Controller - > V1 . LastStatusMailbox )
NextStatusMailbox = Controller - > V1 . FirstStatusMailbox ;
DAC960_V1_ProcessCompletedCommand ( Command ) ;
}
Controller - > V1 . NextStatusMailbox = NextStatusMailbox ;
/*
Attempt to remove additional I / O Requests from the Controller ' s
I / O Request Queue and queue them to the Controller .
*/
DAC960_ProcessRequest ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
return IRQ_HANDLED ;
}
/*
DAC960_PD_InterruptHandler handles hardware interrupts from DAC960 PD Series
Controllers .
*/
static irqreturn_t DAC960_PD_InterruptHandler ( int IRQ_Channel ,
void * DeviceIdentifier ,
struct pt_regs * InterruptRegisters )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) DeviceIdentifier ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
unsigned long flags ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
while ( DAC960_PD_StatusAvailableP ( ControllerBaseAddress ) )
{
DAC960_V1_CommandIdentifier_T CommandIdentifier =
DAC960_PD_ReadStatusCommandIdentifier ( ControllerBaseAddress ) ;
DAC960_Command_T * Command = Controller - > Commands [ CommandIdentifier - 1 ] ;
Command - > V1 . CommandStatus =
DAC960_PD_ReadStatusRegister ( ControllerBaseAddress ) ;
DAC960_PD_AcknowledgeInterrupt ( ControllerBaseAddress ) ;
DAC960_PD_AcknowledgeStatus ( ControllerBaseAddress ) ;
DAC960_V1_ProcessCompletedCommand ( Command ) ;
}
/*
Attempt to remove additional I / O Requests from the Controller ' s
I / O Request Queue and queue them to the Controller .
*/
DAC960_ProcessRequest ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
return IRQ_HANDLED ;
}
/*
DAC960_P_InterruptHandler handles hardware interrupts from DAC960 P Series
Controllers .
Translations of DAC960_V1_Enquiry and DAC960_V1_GetDeviceState rely
on the data having been placed into DAC960_Controller_T , rather than
an arbitrary buffer .
*/
static irqreturn_t DAC960_P_InterruptHandler ( int IRQ_Channel ,
void * DeviceIdentifier ,
struct pt_regs * InterruptRegisters )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) DeviceIdentifier ;
void __iomem * ControllerBaseAddress = Controller - > BaseAddress ;
unsigned long flags ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
while ( DAC960_PD_StatusAvailableP ( ControllerBaseAddress ) )
{
DAC960_V1_CommandIdentifier_T CommandIdentifier =
DAC960_PD_ReadStatusCommandIdentifier ( ControllerBaseAddress ) ;
DAC960_Command_T * Command = Controller - > Commands [ CommandIdentifier - 1 ] ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
DAC960_V1_CommandOpcode_T CommandOpcode =
CommandMailbox - > Common . CommandOpcode ;
Command - > V1 . CommandStatus =
DAC960_PD_ReadStatusRegister ( ControllerBaseAddress ) ;
DAC960_PD_AcknowledgeInterrupt ( ControllerBaseAddress ) ;
DAC960_PD_AcknowledgeStatus ( ControllerBaseAddress ) ;
switch ( CommandOpcode )
{
case DAC960_V1_Enquiry_Old :
Command - > V1 . CommandMailbox . Common . CommandOpcode = DAC960_V1_Enquiry ;
DAC960_P_To_PD_TranslateEnquiry ( Controller - > V1 . NewEnquiry ) ;
break ;
case DAC960_V1_GetDeviceState_Old :
Command - > V1 . CommandMailbox . Common . CommandOpcode =
DAC960_V1_GetDeviceState ;
DAC960_P_To_PD_TranslateDeviceState ( Controller - > V1 . NewDeviceState ) ;
break ;
case DAC960_V1_Read_Old :
Command - > V1 . CommandMailbox . Common . CommandOpcode = DAC960_V1_Read ;
DAC960_P_To_PD_TranslateReadWriteCommand ( CommandMailbox ) ;
break ;
case DAC960_V1_Write_Old :
Command - > V1 . CommandMailbox . Common . CommandOpcode = DAC960_V1_Write ;
DAC960_P_To_PD_TranslateReadWriteCommand ( CommandMailbox ) ;
break ;
case DAC960_V1_ReadWithScatterGather_Old :
Command - > V1 . CommandMailbox . Common . CommandOpcode =
DAC960_V1_ReadWithScatterGather ;
DAC960_P_To_PD_TranslateReadWriteCommand ( CommandMailbox ) ;
break ;
case DAC960_V1_WriteWithScatterGather_Old :
Command - > V1 . CommandMailbox . Common . CommandOpcode =
DAC960_V1_WriteWithScatterGather ;
DAC960_P_To_PD_TranslateReadWriteCommand ( CommandMailbox ) ;
break ;
default :
break ;
}
DAC960_V1_ProcessCompletedCommand ( Command ) ;
}
/*
Attempt to remove additional I / O Requests from the Controller ' s
I / O Request Queue and queue them to the Controller .
*/
DAC960_ProcessRequest ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
return IRQ_HANDLED ;
}
/*
DAC960_V1_QueueMonitoringCommand queues a Monitoring Command to DAC960 V1
Firmware Controllers .
*/
static void DAC960_V1_QueueMonitoringCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
DAC960_V1_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_MonitoringCommand ;
CommandMailbox - > Type3 . CommandOpcode = DAC960_V1_Enquiry ;
CommandMailbox - > Type3 . BusAddress = Controller - > V1 . NewEnquiryDMA ;
DAC960_QueueCommand ( Command ) ;
}
/*
DAC960_V2_QueueMonitoringCommand queues a Monitoring Command to DAC960 V2
Firmware Controllers .
*/
static void DAC960_V2_QueueMonitoringCommand ( DAC960_Command_T * Command )
{
DAC960_Controller_T * Controller = Command - > Controller ;
DAC960_V2_CommandMailbox_T * CommandMailbox = & Command - > V2 . CommandMailbox ;
DAC960_V2_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_MonitoringCommand ;
CommandMailbox - > ControllerInfo . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > ControllerInfo . CommandControlBits
. DataTransferControllerToHost = true ;
CommandMailbox - > ControllerInfo . CommandControlBits
. NoAutoRequestSense = true ;
CommandMailbox - > ControllerInfo . DataTransferSize =
sizeof ( DAC960_V2_ControllerInfo_T ) ;
CommandMailbox - > ControllerInfo . ControllerNumber = 0 ;
CommandMailbox - > ControllerInfo . IOCTL_Opcode = DAC960_V2_GetControllerInfo ;
CommandMailbox - > ControllerInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . NewControllerInformationDMA ;
CommandMailbox - > ControllerInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > ControllerInfo . DataTransferSize ;
DAC960_QueueCommand ( Command ) ;
}
/*
DAC960_MonitoringTimerFunction is the timer function for monitoring
the status of DAC960 Controllers .
*/
static void DAC960_MonitoringTimerFunction ( unsigned long TimerData )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) TimerData ;
DAC960_Command_T * Command ;
unsigned long flags ;
if ( Controller - > FirmwareType = = DAC960_V1_Controller )
{
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
/*
Queue a Status Monitoring Command to Controller .
*/
Command = DAC960_AllocateCommand ( Controller ) ;
if ( Command ! = NULL )
DAC960_V1_QueueMonitoringCommand ( Command ) ;
else Controller - > MonitoringCommandDeferred = true ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
}
else
{
DAC960_V2_ControllerInfo_T * ControllerInfo =
& Controller - > V2 . ControllerInformation ;
unsigned int StatusChangeCounter =
Controller - > V2 . HealthStatusBuffer - > StatusChangeCounter ;
boolean ForceMonitoringCommand = false ;
if ( jiffies - Controller - > SecondaryMonitoringTime
> DAC960_SecondaryMonitoringInterval )
{
int LogicalDriveNumber ;
for ( LogicalDriveNumber = 0 ;
LogicalDriveNumber < DAC960_MaxLogicalDrives ;
LogicalDriveNumber + + )
{
DAC960_V2_LogicalDeviceInfo_T * LogicalDeviceInfo =
Controller - > V2 . LogicalDeviceInformation [ LogicalDriveNumber ] ;
if ( LogicalDeviceInfo = = NULL ) continue ;
if ( ! LogicalDeviceInfo - > LogicalDeviceControl
. LogicalDeviceInitialized )
{
ForceMonitoringCommand = true ;
break ;
}
}
Controller - > SecondaryMonitoringTime = jiffies ;
}
if ( StatusChangeCounter = = Controller - > V2 . StatusChangeCounter & &
Controller - > V2 . HealthStatusBuffer - > NextEventSequenceNumber
= = Controller - > V2 . NextEventSequenceNumber & &
( ControllerInfo - > BackgroundInitializationsActive +
ControllerInfo - > LogicalDeviceInitializationsActive +
ControllerInfo - > PhysicalDeviceInitializationsActive +
ControllerInfo - > ConsistencyChecksActive +
ControllerInfo - > RebuildsActive +
ControllerInfo - > OnlineExpansionsActive = = 0 | |
jiffies - Controller - > PrimaryMonitoringTime
< DAC960_MonitoringTimerInterval ) & &
! ForceMonitoringCommand )
{
Controller - > MonitoringTimer . expires =
jiffies + DAC960_HealthStatusMonitoringInterval ;
add_timer ( & Controller - > MonitoringTimer ) ;
return ;
}
Controller - > V2 . StatusChangeCounter = StatusChangeCounter ;
Controller - > PrimaryMonitoringTime = jiffies ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
/*
Queue a Status Monitoring Command to Controller .
*/
Command = DAC960_AllocateCommand ( Controller ) ;
if ( Command ! = NULL )
DAC960_V2_QueueMonitoringCommand ( Command ) ;
else Controller - > MonitoringCommandDeferred = true ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
/*
Wake up any processes waiting on a Health Status Buffer change .
*/
wake_up ( & Controller - > HealthStatusWaitQueue ) ;
}
}
/*
DAC960_CheckStatusBuffer verifies that there is room to hold ByteCount
additional bytes in the Combined Status Buffer and grows the buffer if
necessary . It returns true if there is enough room and false otherwise .
*/
static boolean DAC960_CheckStatusBuffer ( DAC960_Controller_T * Controller ,
unsigned int ByteCount )
{
unsigned char * NewStatusBuffer ;
if ( Controller - > InitialStatusLength + 1 +
Controller - > CurrentStatusLength + ByteCount + 1 < =
Controller - > CombinedStatusBufferLength )
return true ;
if ( Controller - > CombinedStatusBufferLength = = 0 )
{
unsigned int NewStatusBufferLength = DAC960_InitialStatusBufferSize ;
while ( NewStatusBufferLength < ByteCount )
NewStatusBufferLength * = 2 ;
Controller - > CombinedStatusBuffer =
( unsigned char * ) kmalloc ( NewStatusBufferLength , GFP_ATOMIC ) ;
if ( Controller - > CombinedStatusBuffer = = NULL ) return false ;
Controller - > CombinedStatusBufferLength = NewStatusBufferLength ;
return true ;
}
NewStatusBuffer = ( unsigned char * )
kmalloc ( 2 * Controller - > CombinedStatusBufferLength , GFP_ATOMIC ) ;
if ( NewStatusBuffer = = NULL )
{
DAC960_Warning ( " Unable to expand Combined Status Buffer - Truncating \n " ,
Controller ) ;
return false ;
}
memcpy ( NewStatusBuffer , Controller - > CombinedStatusBuffer ,
Controller - > CombinedStatusBufferLength ) ;
kfree ( Controller - > CombinedStatusBuffer ) ;
Controller - > CombinedStatusBuffer = NewStatusBuffer ;
Controller - > CombinedStatusBufferLength * = 2 ;
Controller - > CurrentStatusBuffer =
& NewStatusBuffer [ Controller - > InitialStatusLength + 1 ] ;
return true ;
}
/*
DAC960_Message prints Driver Messages .
*/
static void DAC960_Message ( DAC960_MessageLevel_T MessageLevel ,
unsigned char * Format ,
DAC960_Controller_T * Controller ,
. . . )
{
static unsigned char Buffer [ DAC960_LineBufferSize ] ;
static boolean BeginningOfLine = true ;
va_list Arguments ;
int Length = 0 ;
va_start ( Arguments , Controller ) ;
Length = vsprintf ( Buffer , Format , Arguments ) ;
va_end ( Arguments ) ;
if ( Controller = = NULL )
printk ( " %sDAC960#%d: %s " , DAC960_MessageLevelMap [ MessageLevel ] ,
DAC960_ControllerCount , Buffer ) ;
else if ( MessageLevel = = DAC960_AnnounceLevel | |
MessageLevel = = DAC960_InfoLevel )
{
if ( ! Controller - > ControllerInitialized )
{
if ( DAC960_CheckStatusBuffer ( Controller , Length ) )
{
strcpy ( & Controller - > CombinedStatusBuffer
[ Controller - > InitialStatusLength ] ,
Buffer ) ;
Controller - > InitialStatusLength + = Length ;
Controller - > CurrentStatusBuffer =
& Controller - > CombinedStatusBuffer
[ Controller - > InitialStatusLength + 1 ] ;
}
if ( MessageLevel = = DAC960_AnnounceLevel )
{
static int AnnouncementLines = 0 ;
if ( + + AnnouncementLines < = 2 )
printk ( " %sDAC960: %s " , DAC960_MessageLevelMap [ MessageLevel ] ,
Buffer ) ;
}
else
{
if ( BeginningOfLine )
{
if ( Buffer [ 0 ] ! = ' \n ' | | Length > 1 )
printk ( " %sDAC960#%d: %s " ,
DAC960_MessageLevelMap [ MessageLevel ] ,
Controller - > ControllerNumber , Buffer ) ;
}
else printk ( " %s " , Buffer ) ;
}
}
else if ( DAC960_CheckStatusBuffer ( Controller , Length ) )
{
strcpy ( & Controller - > CurrentStatusBuffer [
Controller - > CurrentStatusLength ] , Buffer ) ;
Controller - > CurrentStatusLength + = Length ;
}
}
else if ( MessageLevel = = DAC960_ProgressLevel )
{
strcpy ( Controller - > ProgressBuffer , Buffer ) ;
Controller - > ProgressBufferLength = Length ;
if ( Controller - > EphemeralProgressMessage )
{
if ( jiffies - Controller - > LastProgressReportTime
> = DAC960_ProgressReportingInterval )
{
printk ( " %sDAC960#%d: %s " , DAC960_MessageLevelMap [ MessageLevel ] ,
Controller - > ControllerNumber , Buffer ) ;
Controller - > LastProgressReportTime = jiffies ;
}
}
else printk ( " %sDAC960#%d: %s " , DAC960_MessageLevelMap [ MessageLevel ] ,
Controller - > ControllerNumber , Buffer ) ;
}
else if ( MessageLevel = = DAC960_UserCriticalLevel )
{
strcpy ( & Controller - > UserStatusBuffer [ Controller - > UserStatusLength ] ,
Buffer ) ;
Controller - > UserStatusLength + = Length ;
if ( Buffer [ 0 ] ! = ' \n ' | | Length > 1 )
printk ( " %sDAC960#%d: %s " , DAC960_MessageLevelMap [ MessageLevel ] ,
Controller - > ControllerNumber , Buffer ) ;
}
else
{
if ( BeginningOfLine )
printk ( " %sDAC960#%d: %s " , DAC960_MessageLevelMap [ MessageLevel ] ,
Controller - > ControllerNumber , Buffer ) ;
else printk ( " %s " , Buffer ) ;
}
BeginningOfLine = ( Buffer [ Length - 1 ] = = ' \n ' ) ;
}
/*
DAC960_ParsePhysicalDevice parses spaces followed by a Physical Device
Channel : TargetID specification from a User Command string . It updates
Channel and TargetID and returns true on success and false on failure .
*/
static boolean DAC960_ParsePhysicalDevice ( DAC960_Controller_T * Controller ,
char * UserCommandString ,
unsigned char * Channel ,
unsigned char * TargetID )
{
char * NewUserCommandString = UserCommandString ;
unsigned long XChannel , XTargetID ;
while ( * UserCommandString = = ' ' ) UserCommandString + + ;
if ( UserCommandString = = NewUserCommandString )
return false ;
XChannel = simple_strtoul ( UserCommandString , & NewUserCommandString , 10 ) ;
if ( NewUserCommandString = = UserCommandString | |
* NewUserCommandString ! = ' : ' | |
XChannel > = Controller - > Channels )
return false ;
UserCommandString = + + NewUserCommandString ;
XTargetID = simple_strtoul ( UserCommandString , & NewUserCommandString , 10 ) ;
if ( NewUserCommandString = = UserCommandString | |
* NewUserCommandString ! = ' \0 ' | |
XTargetID > = Controller - > Targets )
return false ;
* Channel = XChannel ;
* TargetID = XTargetID ;
return true ;
}
/*
DAC960_ParseLogicalDrive parses spaces followed by a Logical Drive Number
specification from a User Command string . It updates LogicalDriveNumber and
returns true on success and false on failure .
*/
static boolean DAC960_ParseLogicalDrive ( DAC960_Controller_T * Controller ,
char * UserCommandString ,
unsigned char * LogicalDriveNumber )
{
char * NewUserCommandString = UserCommandString ;
unsigned long XLogicalDriveNumber ;
while ( * UserCommandString = = ' ' ) UserCommandString + + ;
if ( UserCommandString = = NewUserCommandString )
return false ;
XLogicalDriveNumber =
simple_strtoul ( UserCommandString , & NewUserCommandString , 10 ) ;
if ( NewUserCommandString = = UserCommandString | |
* NewUserCommandString ! = ' \0 ' | |
XLogicalDriveNumber > DAC960_MaxLogicalDrives - 1 )
return false ;
* LogicalDriveNumber = XLogicalDriveNumber ;
return true ;
}
/*
DAC960_V1_SetDeviceState sets the Device State for a Physical Device for
DAC960 V1 Firmware Controllers .
*/
static void DAC960_V1_SetDeviceState ( DAC960_Controller_T * Controller ,
DAC960_Command_T * Command ,
unsigned char Channel ,
unsigned char TargetID ,
DAC960_V1_PhysicalDeviceState_T
DeviceState ,
const unsigned char * DeviceStateString )
{
DAC960_V1_CommandMailbox_T * CommandMailbox = & Command - > V1 . CommandMailbox ;
CommandMailbox - > Type3D . CommandOpcode = DAC960_V1_StartDevice ;
CommandMailbox - > Type3D . Channel = Channel ;
CommandMailbox - > Type3D . TargetID = TargetID ;
CommandMailbox - > Type3D . DeviceState = DeviceState ;
CommandMailbox - > Type3D . Modifier = 0 ;
DAC960_ExecuteCommand ( Command ) ;
switch ( Command - > V1 . CommandStatus )
{
case DAC960_V1_NormalCompletion :
DAC960_UserCritical ( " %s of Physical Device %d:%d Succeeded \n " , Controller ,
DeviceStateString , Channel , TargetID ) ;
break ;
case DAC960_V1_UnableToStartDevice :
DAC960_UserCritical ( " %s of Physical Device %d:%d Failed - "
" Unable to Start Device \n " , Controller ,
DeviceStateString , Channel , TargetID ) ;
break ;
case DAC960_V1_NoDeviceAtAddress :
DAC960_UserCritical ( " %s of Physical Device %d:%d Failed - "
" No Device at Address \n " , Controller ,
DeviceStateString , Channel , TargetID ) ;
break ;
case DAC960_V1_InvalidChannelOrTargetOrModifier :
DAC960_UserCritical ( " %s of Physical Device %d:%d Failed - "
" Invalid Channel or Target or Modifier \n " ,
Controller , DeviceStateString , Channel , TargetID ) ;
break ;
case DAC960_V1_ChannelBusy :
DAC960_UserCritical ( " %s of Physical Device %d:%d Failed - "
" Channel Busy \n " , Controller ,
DeviceStateString , Channel , TargetID ) ;
break ;
default :
DAC960_UserCritical ( " %s of Physical Device %d:%d Failed - "
" Unexpected Status %04X \n " , Controller ,
DeviceStateString , Channel , TargetID ,
Command - > V1 . CommandStatus ) ;
break ;
}
}
/*
DAC960_V1_ExecuteUserCommand executes a User Command for DAC960 V1 Firmware
Controllers .
*/
static boolean DAC960_V1_ExecuteUserCommand ( DAC960_Controller_T * Controller ,
unsigned char * UserCommand )
{
DAC960_Command_T * Command ;
DAC960_V1_CommandMailbox_T * CommandMailbox ;
unsigned long flags ;
unsigned char Channel , TargetID , LogicalDriveNumber ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
while ( ( Command = DAC960_AllocateCommand ( Controller ) ) = = NULL )
DAC960_WaitForCommand ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
Controller - > UserStatusLength = 0 ;
DAC960_V1_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox = & Command - > V1 . CommandMailbox ;
if ( strcmp ( UserCommand , " flush-cache " ) = = 0 )
{
CommandMailbox - > Type3 . CommandOpcode = DAC960_V1_Flush ;
DAC960_ExecuteCommand ( Command ) ;
DAC960_UserCritical ( " Cache Flush Completed \n " , Controller ) ;
}
else if ( strncmp ( UserCommand , " kill " , 4 ) = = 0 & &
DAC960_ParsePhysicalDevice ( Controller , & UserCommand [ 4 ] ,
& Channel , & TargetID ) )
{
DAC960_V1_DeviceState_T * DeviceState =
& Controller - > V1 . DeviceState [ Channel ] [ TargetID ] ;
if ( DeviceState - > Present & &
DeviceState - > DeviceType = = DAC960_V1_DiskType & &
DeviceState - > DeviceState ! = DAC960_V1_Device_Dead )
DAC960_V1_SetDeviceState ( Controller , Command , Channel , TargetID ,
DAC960_V1_Device_Dead , " Kill " ) ;
else DAC960_UserCritical ( " Kill of Physical Device %d:%d Illegal \n " ,
Controller , Channel , TargetID ) ;
}
else if ( strncmp ( UserCommand , " make-online " , 11 ) = = 0 & &
DAC960_ParsePhysicalDevice ( Controller , & UserCommand [ 11 ] ,
& Channel , & TargetID ) )
{
DAC960_V1_DeviceState_T * DeviceState =
& Controller - > V1 . DeviceState [ Channel ] [ TargetID ] ;
if ( DeviceState - > Present & &
DeviceState - > DeviceType = = DAC960_V1_DiskType & &
DeviceState - > DeviceState = = DAC960_V1_Device_Dead )
DAC960_V1_SetDeviceState ( Controller , Command , Channel , TargetID ,
DAC960_V1_Device_Online , " Make Online " ) ;
else DAC960_UserCritical ( " Make Online of Physical Device %d:%d Illegal \n " ,
Controller , Channel , TargetID ) ;
}
else if ( strncmp ( UserCommand , " make-standby " , 12 ) = = 0 & &
DAC960_ParsePhysicalDevice ( Controller , & UserCommand [ 12 ] ,
& Channel , & TargetID ) )
{
DAC960_V1_DeviceState_T * DeviceState =
& Controller - > V1 . DeviceState [ Channel ] [ TargetID ] ;
if ( DeviceState - > Present & &
DeviceState - > DeviceType = = DAC960_V1_DiskType & &
DeviceState - > DeviceState = = DAC960_V1_Device_Dead )
DAC960_V1_SetDeviceState ( Controller , Command , Channel , TargetID ,
DAC960_V1_Device_Standby , " Make Standby " ) ;
else DAC960_UserCritical ( " Make Standby of Physical "
" Device %d:%d Illegal \n " ,
Controller , Channel , TargetID ) ;
}
else if ( strncmp ( UserCommand , " rebuild " , 7 ) = = 0 & &
DAC960_ParsePhysicalDevice ( Controller , & UserCommand [ 7 ] ,
& Channel , & TargetID ) )
{
CommandMailbox - > Type3D . CommandOpcode = DAC960_V1_RebuildAsync ;
CommandMailbox - > Type3D . Channel = Channel ;
CommandMailbox - > Type3D . TargetID = TargetID ;
DAC960_ExecuteCommand ( Command ) ;
switch ( Command - > V1 . CommandStatus )
{
case DAC960_V1_NormalCompletion :
DAC960_UserCritical ( " Rebuild of Physical Device %d:%d Initiated \n " ,
Controller , Channel , TargetID ) ;
break ;
case DAC960_V1_AttemptToRebuildOnlineDrive :
DAC960_UserCritical ( " Rebuild of Physical Device %d:%d Failed - "
" Attempt to Rebuild Online or "
" Unresponsive Drive \n " ,
Controller , Channel , TargetID ) ;
break ;
case DAC960_V1_NewDiskFailedDuringRebuild :
DAC960_UserCritical ( " Rebuild of Physical Device %d:%d Failed - "
" New Disk Failed During Rebuild \n " ,
Controller , Channel , TargetID ) ;
break ;
case DAC960_V1_InvalidDeviceAddress :
DAC960_UserCritical ( " Rebuild of Physical Device %d:%d Failed - "
" Invalid Device Address \n " ,
Controller , Channel , TargetID ) ;
break ;
case DAC960_V1_RebuildOrCheckAlreadyInProgress :
DAC960_UserCritical ( " Rebuild of Physical Device %d:%d Failed - "
" Rebuild or Consistency Check Already "
" in Progress \n " , Controller , Channel , TargetID ) ;
break ;
default :
DAC960_UserCritical ( " Rebuild of Physical Device %d:%d Failed - "
" Unexpected Status %04X \n " , Controller ,
Channel , TargetID , Command - > V1 . CommandStatus ) ;
break ;
}
}
else if ( strncmp ( UserCommand , " check-consistency " , 17 ) = = 0 & &
DAC960_ParseLogicalDrive ( Controller , & UserCommand [ 17 ] ,
& LogicalDriveNumber ) )
{
CommandMailbox - > Type3C . CommandOpcode = DAC960_V1_CheckConsistencyAsync ;
CommandMailbox - > Type3C . LogicalDriveNumber = LogicalDriveNumber ;
CommandMailbox - > Type3C . AutoRestore = true ;
DAC960_ExecuteCommand ( Command ) ;
switch ( Command - > V1 . CommandStatus )
{
case DAC960_V1_NormalCompletion :
DAC960_UserCritical ( " Consistency Check of Logical Drive %d "
" (/dev/rd/c%dd%d) Initiated \n " ,
Controller , LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ) ;
break ;
case DAC960_V1_DependentDiskIsDead :
DAC960_UserCritical ( " Consistency Check of Logical Drive %d "
" (/dev/rd/c%dd%d) Failed - "
" Dependent Physical Device is DEAD \n " ,
Controller , LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ) ;
break ;
case DAC960_V1_InvalidOrNonredundantLogicalDrive :
DAC960_UserCritical ( " Consistency Check of Logical Drive %d "
" (/dev/rd/c%dd%d) Failed - "
" Invalid or Nonredundant Logical Drive \n " ,
Controller , LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ) ;
break ;
case DAC960_V1_RebuildOrCheckAlreadyInProgress :
DAC960_UserCritical ( " Consistency Check of Logical Drive %d "
" (/dev/rd/c%dd%d) Failed - Rebuild or "
" Consistency Check Already in Progress \n " ,
Controller , LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ) ;
break ;
default :
DAC960_UserCritical ( " Consistency Check of Logical Drive %d "
" (/dev/rd/c%dd%d) Failed - "
" Unexpected Status %04X \n " ,
Controller , LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber , Command - > V1 . CommandStatus ) ;
break ;
}
}
else if ( strcmp ( UserCommand , " cancel-rebuild " ) = = 0 | |
strcmp ( UserCommand , " cancel-consistency-check " ) = = 0 )
{
/*
the OldRebuildRateConstant is never actually used
once its value is retrieved from the controller .
*/
unsigned char * OldRebuildRateConstant ;
dma_addr_t OldRebuildRateConstantDMA ;
OldRebuildRateConstant = pci_alloc_consistent ( Controller - > PCIDevice ,
sizeof ( char ) , & OldRebuildRateConstantDMA ) ;
if ( OldRebuildRateConstant = = NULL ) {
DAC960_UserCritical ( " Cancellation of Rebuild or "
" Consistency Check Failed - "
" Out of Memory " ,
Controller ) ;
goto failure ;
}
CommandMailbox - > Type3R . CommandOpcode = DAC960_V1_RebuildControl ;
CommandMailbox - > Type3R . RebuildRateConstant = 0xFF ;
CommandMailbox - > Type3R . BusAddress = OldRebuildRateConstantDMA ;
DAC960_ExecuteCommand ( Command ) ;
switch ( Command - > V1 . CommandStatus )
{
case DAC960_V1_NormalCompletion :
DAC960_UserCritical ( " Rebuild or Consistency Check Cancelled \n " ,
Controller ) ;
break ;
default :
DAC960_UserCritical ( " Cancellation of Rebuild or "
" Consistency Check Failed - "
" Unexpected Status %04X \n " ,
Controller , Command - > V1 . CommandStatus ) ;
break ;
}
failure :
pci_free_consistent ( Controller - > PCIDevice , sizeof ( char ) ,
OldRebuildRateConstant , OldRebuildRateConstantDMA ) ;
}
else DAC960_UserCritical ( " Illegal User Command: '%s' \n " ,
Controller , UserCommand ) ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_DeallocateCommand ( Command ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
return true ;
}
/*
DAC960_V2_TranslatePhysicalDevice translates a Physical Device Channel and
TargetID into a Logical Device . It returns true on success and false
on failure .
*/
static boolean DAC960_V2_TranslatePhysicalDevice ( DAC960_Command_T * Command ,
unsigned char Channel ,
unsigned char TargetID ,
unsigned short
* LogicalDeviceNumber )
{
DAC960_V2_CommandMailbox_T SavedCommandMailbox , * CommandMailbox ;
DAC960_Controller_T * Controller = Command - > Controller ;
CommandMailbox = & Command - > V2 . CommandMailbox ;
memcpy ( & SavedCommandMailbox , CommandMailbox ,
sizeof ( DAC960_V2_CommandMailbox_T ) ) ;
CommandMailbox - > PhysicalDeviceInfo . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > PhysicalDeviceInfo . CommandControlBits
. DataTransferControllerToHost = true ;
CommandMailbox - > PhysicalDeviceInfo . CommandControlBits
. NoAutoRequestSense = true ;
CommandMailbox - > PhysicalDeviceInfo . DataTransferSize =
sizeof ( DAC960_V2_PhysicalToLogicalDevice_T ) ;
CommandMailbox - > PhysicalDeviceInfo . PhysicalDevice . TargetID = TargetID ;
CommandMailbox - > PhysicalDeviceInfo . PhysicalDevice . Channel = Channel ;
CommandMailbox - > PhysicalDeviceInfo . IOCTL_Opcode =
DAC960_V2_TranslatePhysicalToLogicalDevice ;
CommandMailbox - > Common . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . PhysicalToLogicalDeviceDMA ;
CommandMailbox - > Common . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > Common . DataTransferSize ;
DAC960_ExecuteCommand ( Command ) ;
* LogicalDeviceNumber = Controller - > V2 . PhysicalToLogicalDevice - > LogicalDeviceNumber ;
memcpy ( CommandMailbox , & SavedCommandMailbox ,
sizeof ( DAC960_V2_CommandMailbox_T ) ) ;
return ( Command - > V2 . CommandStatus = = DAC960_V2_NormalCompletion ) ;
}
/*
DAC960_V2_ExecuteUserCommand executes a User Command for DAC960 V2 Firmware
Controllers .
*/
static boolean DAC960_V2_ExecuteUserCommand ( DAC960_Controller_T * Controller ,
unsigned char * UserCommand )
{
DAC960_Command_T * Command ;
DAC960_V2_CommandMailbox_T * CommandMailbox ;
unsigned long flags ;
unsigned char Channel , TargetID , LogicalDriveNumber ;
unsigned short LogicalDeviceNumber ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
while ( ( Command = DAC960_AllocateCommand ( Controller ) ) = = NULL )
DAC960_WaitForCommand ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
Controller - > UserStatusLength = 0 ;
DAC960_V2_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox = & Command - > V2 . CommandMailbox ;
CommandMailbox - > Common . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > Common . CommandControlBits . DataTransferControllerToHost = true ;
CommandMailbox - > Common . CommandControlBits . NoAutoRequestSense = true ;
if ( strcmp ( UserCommand , " flush-cache " ) = = 0 )
{
CommandMailbox - > DeviceOperation . IOCTL_Opcode = DAC960_V2_PauseDevice ;
CommandMailbox - > DeviceOperation . OperationDevice =
DAC960_V2_RAID_Controller ;
DAC960_ExecuteCommand ( Command ) ;
DAC960_UserCritical ( " Cache Flush Completed \n " , Controller ) ;
}
else if ( strncmp ( UserCommand , " kill " , 4 ) = = 0 & &
DAC960_ParsePhysicalDevice ( Controller , & UserCommand [ 4 ] ,
& Channel , & TargetID ) & &
DAC960_V2_TranslatePhysicalDevice ( Command , Channel , TargetID ,
& LogicalDeviceNumber ) )
{
CommandMailbox - > SetDeviceState . LogicalDevice . LogicalDeviceNumber =
LogicalDeviceNumber ;
CommandMailbox - > SetDeviceState . IOCTL_Opcode =
DAC960_V2_SetDeviceState ;
CommandMailbox - > SetDeviceState . DeviceState . PhysicalDeviceState =
DAC960_V2_Device_Dead ;
DAC960_ExecuteCommand ( Command ) ;
DAC960_UserCritical ( " Kill of Physical Device %d:%d %s \n " ,
Controller , Channel , TargetID ,
( Command - > V2 . CommandStatus
= = DAC960_V2_NormalCompletion
? " Succeeded " : " Failed " ) ) ;
}
else if ( strncmp ( UserCommand , " make-online " , 11 ) = = 0 & &
DAC960_ParsePhysicalDevice ( Controller , & UserCommand [ 11 ] ,
& Channel , & TargetID ) & &
DAC960_V2_TranslatePhysicalDevice ( Command , Channel , TargetID ,
& LogicalDeviceNumber ) )
{
CommandMailbox - > SetDeviceState . LogicalDevice . LogicalDeviceNumber =
LogicalDeviceNumber ;
CommandMailbox - > SetDeviceState . IOCTL_Opcode =
DAC960_V2_SetDeviceState ;
CommandMailbox - > SetDeviceState . DeviceState . PhysicalDeviceState =
DAC960_V2_Device_Online ;
DAC960_ExecuteCommand ( Command ) ;
DAC960_UserCritical ( " Make Online of Physical Device %d:%d %s \n " ,
Controller , Channel , TargetID ,
( Command - > V2 . CommandStatus
= = DAC960_V2_NormalCompletion
? " Succeeded " : " Failed " ) ) ;
}
else if ( strncmp ( UserCommand , " make-standby " , 12 ) = = 0 & &
DAC960_ParsePhysicalDevice ( Controller , & UserCommand [ 12 ] ,
& Channel , & TargetID ) & &
DAC960_V2_TranslatePhysicalDevice ( Command , Channel , TargetID ,
& LogicalDeviceNumber ) )
{
CommandMailbox - > SetDeviceState . LogicalDevice . LogicalDeviceNumber =
LogicalDeviceNumber ;
CommandMailbox - > SetDeviceState . IOCTL_Opcode =
DAC960_V2_SetDeviceState ;
CommandMailbox - > SetDeviceState . DeviceState . PhysicalDeviceState =
DAC960_V2_Device_Standby ;
DAC960_ExecuteCommand ( Command ) ;
DAC960_UserCritical ( " Make Standby of Physical Device %d:%d %s \n " ,
Controller , Channel , TargetID ,
( Command - > V2 . CommandStatus
= = DAC960_V2_NormalCompletion
? " Succeeded " : " Failed " ) ) ;
}
else if ( strncmp ( UserCommand , " rebuild " , 7 ) = = 0 & &
DAC960_ParsePhysicalDevice ( Controller , & UserCommand [ 7 ] ,
& Channel , & TargetID ) & &
DAC960_V2_TranslatePhysicalDevice ( Command , Channel , TargetID ,
& LogicalDeviceNumber ) )
{
CommandMailbox - > LogicalDeviceInfo . LogicalDevice . LogicalDeviceNumber =
LogicalDeviceNumber ;
CommandMailbox - > LogicalDeviceInfo . IOCTL_Opcode =
DAC960_V2_RebuildDeviceStart ;
DAC960_ExecuteCommand ( Command ) ;
DAC960_UserCritical ( " Rebuild of Physical Device %d:%d %s \n " ,
Controller , Channel , TargetID ,
( Command - > V2 . CommandStatus
= = DAC960_V2_NormalCompletion
? " Initiated " : " Not Initiated " ) ) ;
}
else if ( strncmp ( UserCommand , " cancel-rebuild " , 14 ) = = 0 & &
DAC960_ParsePhysicalDevice ( Controller , & UserCommand [ 14 ] ,
& Channel , & TargetID ) & &
DAC960_V2_TranslatePhysicalDevice ( Command , Channel , TargetID ,
& LogicalDeviceNumber ) )
{
CommandMailbox - > LogicalDeviceInfo . LogicalDevice . LogicalDeviceNumber =
LogicalDeviceNumber ;
CommandMailbox - > LogicalDeviceInfo . IOCTL_Opcode =
DAC960_V2_RebuildDeviceStop ;
DAC960_ExecuteCommand ( Command ) ;
DAC960_UserCritical ( " Rebuild of Physical Device %d:%d %s \n " ,
Controller , Channel , TargetID ,
( Command - > V2 . CommandStatus
= = DAC960_V2_NormalCompletion
? " Cancelled " : " Not Cancelled " ) ) ;
}
else if ( strncmp ( UserCommand , " check-consistency " , 17 ) = = 0 & &
DAC960_ParseLogicalDrive ( Controller , & UserCommand [ 17 ] ,
& LogicalDriveNumber ) )
{
CommandMailbox - > ConsistencyCheck . LogicalDevice . LogicalDeviceNumber =
LogicalDriveNumber ;
CommandMailbox - > ConsistencyCheck . IOCTL_Opcode =
DAC960_V2_ConsistencyCheckStart ;
CommandMailbox - > ConsistencyCheck . RestoreConsistency = true ;
CommandMailbox - > ConsistencyCheck . InitializedAreaOnly = false ;
DAC960_ExecuteCommand ( Command ) ;
DAC960_UserCritical ( " Consistency Check of Logical Drive %d "
" (/dev/rd/c%dd%d) %s \n " ,
Controller , LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ,
( Command - > V2 . CommandStatus
= = DAC960_V2_NormalCompletion
? " Initiated " : " Not Initiated " ) ) ;
}
else if ( strncmp ( UserCommand , " cancel-consistency-check " , 24 ) = = 0 & &
DAC960_ParseLogicalDrive ( Controller , & UserCommand [ 24 ] ,
& LogicalDriveNumber ) )
{
CommandMailbox - > ConsistencyCheck . LogicalDevice . LogicalDeviceNumber =
LogicalDriveNumber ;
CommandMailbox - > ConsistencyCheck . IOCTL_Opcode =
DAC960_V2_ConsistencyCheckStop ;
DAC960_ExecuteCommand ( Command ) ;
DAC960_UserCritical ( " Consistency Check of Logical Drive %d "
" (/dev/rd/c%dd%d) %s \n " ,
Controller , LogicalDriveNumber ,
Controller - > ControllerNumber ,
LogicalDriveNumber ,
( Command - > V2 . CommandStatus
= = DAC960_V2_NormalCompletion
? " Cancelled " : " Not Cancelled " ) ) ;
}
else if ( strcmp ( UserCommand , " perform-discovery " ) = = 0 )
{
CommandMailbox - > Common . IOCTL_Opcode = DAC960_V2_StartDiscovery ;
DAC960_ExecuteCommand ( Command ) ;
DAC960_UserCritical ( " Discovery %s \n " , Controller ,
( Command - > V2 . CommandStatus
= = DAC960_V2_NormalCompletion
? " Initiated " : " Not Initiated " ) ) ;
if ( Command - > V2 . CommandStatus = = DAC960_V2_NormalCompletion )
{
CommandMailbox - > ControllerInfo . CommandOpcode = DAC960_V2_IOCTL ;
CommandMailbox - > ControllerInfo . CommandControlBits
. DataTransferControllerToHost = true ;
CommandMailbox - > ControllerInfo . CommandControlBits
. NoAutoRequestSense = true ;
CommandMailbox - > ControllerInfo . DataTransferSize =
sizeof ( DAC960_V2_ControllerInfo_T ) ;
CommandMailbox - > ControllerInfo . ControllerNumber = 0 ;
CommandMailbox - > ControllerInfo . IOCTL_Opcode =
DAC960_V2_GetControllerInfo ;
/*
* How does this NOT race with the queued Monitoring
* usage of this structure ?
*/
CommandMailbox - > ControllerInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer =
Controller - > V2 . NewControllerInformationDMA ;
CommandMailbox - > ControllerInfo . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > ControllerInfo . DataTransferSize ;
DAC960_ExecuteCommand ( Command ) ;
while ( Controller - > V2 . NewControllerInformation - > PhysicalScanActive )
{
DAC960_ExecuteCommand ( Command ) ;
sleep_on_timeout ( & Controller - > CommandWaitQueue , HZ ) ;
}
DAC960_UserCritical ( " Discovery Completed \n " , Controller ) ;
}
}
else if ( strcmp ( UserCommand , " suppress-enclosure-messages " ) = = 0 )
Controller - > SuppressEnclosureMessages = true ;
else DAC960_UserCritical ( " Illegal User Command: '%s' \n " ,
Controller , UserCommand ) ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_DeallocateCommand ( Command ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
return true ;
}
/*
DAC960_ProcReadStatus implements reading / proc / rd / status .
*/
static int DAC960_ProcReadStatus ( char * Page , char * * Start , off_t Offset ,
int Count , int * EOF , void * Data )
{
unsigned char * StatusMessage = " OK \n " ;
int ControllerNumber , BytesAvailable ;
for ( ControllerNumber = 0 ;
ControllerNumber < DAC960_ControllerCount ;
ControllerNumber + + )
{
DAC960_Controller_T * Controller = DAC960_Controllers [ ControllerNumber ] ;
if ( Controller = = NULL ) continue ;
if ( Controller - > MonitoringAlertMode )
{
StatusMessage = " ALERT \n " ;
break ;
}
}
BytesAvailable = strlen ( StatusMessage ) - Offset ;
if ( Count > = BytesAvailable )
{
Count = BytesAvailable ;
* EOF = true ;
}
if ( Count < = 0 ) return 0 ;
* Start = Page ;
memcpy ( Page , & StatusMessage [ Offset ] , Count ) ;
return Count ;
}
/*
DAC960_ProcReadInitialStatus implements reading / proc / rd / cN / initial_status .
*/
static int DAC960_ProcReadInitialStatus ( char * Page , char * * Start , off_t Offset ,
int Count , int * EOF , void * Data )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) Data ;
int BytesAvailable = Controller - > InitialStatusLength - Offset ;
if ( Count > = BytesAvailable )
{
Count = BytesAvailable ;
* EOF = true ;
}
if ( Count < = 0 ) return 0 ;
* Start = Page ;
memcpy ( Page , & Controller - > CombinedStatusBuffer [ Offset ] , Count ) ;
return Count ;
}
/*
DAC960_ProcReadCurrentStatus implements reading / proc / rd / cN / current_status .
*/
static int DAC960_ProcReadCurrentStatus ( char * Page , char * * Start , off_t Offset ,
int Count , int * EOF , void * Data )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) Data ;
unsigned char * StatusMessage =
" No Rebuild or Consistency Check in Progress \n " ;
int ProgressMessageLength = strlen ( StatusMessage ) ;
int BytesAvailable ;
if ( jiffies ! = Controller - > LastCurrentStatusTime )
{
Controller - > CurrentStatusLength = 0 ;
DAC960_AnnounceDriver ( Controller ) ;
DAC960_ReportControllerConfiguration ( Controller ) ;
DAC960_ReportDeviceConfiguration ( Controller ) ;
if ( Controller - > ProgressBufferLength > 0 )
ProgressMessageLength = Controller - > ProgressBufferLength ;
if ( DAC960_CheckStatusBuffer ( Controller , 2 + ProgressMessageLength ) )
{
unsigned char * CurrentStatusBuffer = Controller - > CurrentStatusBuffer ;
CurrentStatusBuffer [ Controller - > CurrentStatusLength + + ] = ' ' ;
CurrentStatusBuffer [ Controller - > CurrentStatusLength + + ] = ' ' ;
if ( Controller - > ProgressBufferLength > 0 )
strcpy ( & CurrentStatusBuffer [ Controller - > CurrentStatusLength ] ,
Controller - > ProgressBuffer ) ;
else
strcpy ( & CurrentStatusBuffer [ Controller - > CurrentStatusLength ] ,
StatusMessage ) ;
Controller - > CurrentStatusLength + = ProgressMessageLength ;
}
Controller - > LastCurrentStatusTime = jiffies ;
}
BytesAvailable = Controller - > CurrentStatusLength - Offset ;
if ( Count > = BytesAvailable )
{
Count = BytesAvailable ;
* EOF = true ;
}
if ( Count < = 0 ) return 0 ;
* Start = Page ;
memcpy ( Page , & Controller - > CurrentStatusBuffer [ Offset ] , Count ) ;
return Count ;
}
/*
DAC960_ProcReadUserCommand implements reading / proc / rd / cN / user_command .
*/
static int DAC960_ProcReadUserCommand ( char * Page , char * * Start , off_t Offset ,
int Count , int * EOF , void * Data )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) Data ;
int BytesAvailable = Controller - > UserStatusLength - Offset ;
if ( Count > = BytesAvailable )
{
Count = BytesAvailable ;
* EOF = true ;
}
if ( Count < = 0 ) return 0 ;
* Start = Page ;
memcpy ( Page , & Controller - > UserStatusBuffer [ Offset ] , Count ) ;
return Count ;
}
/*
DAC960_ProcWriteUserCommand implements writing / proc / rd / cN / user_command .
*/
static int DAC960_ProcWriteUserCommand ( struct file * file ,
const char __user * Buffer ,
unsigned long Count , void * Data )
{
DAC960_Controller_T * Controller = ( DAC960_Controller_T * ) Data ;
unsigned char CommandBuffer [ 80 ] ;
int Length ;
if ( Count > sizeof ( CommandBuffer ) - 1 ) return - EINVAL ;
if ( copy_from_user ( CommandBuffer , Buffer , Count ) ) return - EFAULT ;
CommandBuffer [ Count ] = ' \0 ' ;
Length = strlen ( CommandBuffer ) ;
if ( CommandBuffer [ Length - 1 ] = = ' \n ' )
CommandBuffer [ - - Length ] = ' \0 ' ;
if ( Controller - > FirmwareType = = DAC960_V1_Controller )
return ( DAC960_V1_ExecuteUserCommand ( Controller , CommandBuffer )
? Count : - EBUSY ) ;
else
return ( DAC960_V2_ExecuteUserCommand ( Controller , CommandBuffer )
? Count : - EBUSY ) ;
}
/*
DAC960_CreateProcEntries creates the / proc / rd / . . . entries for the
DAC960 Driver .
*/
static void DAC960_CreateProcEntries ( DAC960_Controller_T * Controller )
{
struct proc_dir_entry * StatusProcEntry ;
struct proc_dir_entry * ControllerProcEntry ;
struct proc_dir_entry * UserCommandProcEntry ;
if ( DAC960_ProcDirectoryEntry = = NULL ) {
DAC960_ProcDirectoryEntry = proc_mkdir ( " rd " , NULL ) ;
StatusProcEntry = create_proc_read_entry ( " status " , 0 ,
DAC960_ProcDirectoryEntry ,
DAC960_ProcReadStatus , NULL ) ;
}
sprintf ( Controller - > ControllerName , " c%d " , Controller - > ControllerNumber ) ;
ControllerProcEntry = proc_mkdir ( Controller - > ControllerName ,
DAC960_ProcDirectoryEntry ) ;
create_proc_read_entry ( " initial_status " , 0 , ControllerProcEntry ,
DAC960_ProcReadInitialStatus , Controller ) ;
create_proc_read_entry ( " current_status " , 0 , ControllerProcEntry ,
DAC960_ProcReadCurrentStatus , Controller ) ;
UserCommandProcEntry =
create_proc_read_entry ( " user_command " , S_IWUSR | S_IRUSR ,
ControllerProcEntry , DAC960_ProcReadUserCommand ,
Controller ) ;
UserCommandProcEntry - > write_proc = DAC960_ProcWriteUserCommand ;
Controller - > ControllerProcEntry = ControllerProcEntry ;
}
/*
DAC960_DestroyProcEntries destroys the / proc / rd / . . . entries for the
DAC960 Driver .
*/
static void DAC960_DestroyProcEntries ( DAC960_Controller_T * Controller )
{
if ( Controller - > ControllerProcEntry = = NULL )
return ;
remove_proc_entry ( " initial_status " , Controller - > ControllerProcEntry ) ;
remove_proc_entry ( " current_status " , Controller - > ControllerProcEntry ) ;
remove_proc_entry ( " user_command " , Controller - > ControllerProcEntry ) ;
remove_proc_entry ( Controller - > ControllerName , DAC960_ProcDirectoryEntry ) ;
Controller - > ControllerProcEntry = NULL ;
}
# ifdef DAC960_GAM_MINOR
/*
* DAC960_gam_ioctl is the ioctl function for performing RAID operations .
*/
static int DAC960_gam_ioctl ( struct inode * inode , struct file * file ,
unsigned int Request , unsigned long Argument )
{
int ErrorCode = 0 ;
if ( ! capable ( CAP_SYS_ADMIN ) ) return - EACCES ;
switch ( Request )
{
case DAC960_IOCTL_GET_CONTROLLER_COUNT :
return DAC960_ControllerCount ;
case DAC960_IOCTL_GET_CONTROLLER_INFO :
{
DAC960_ControllerInfo_T __user * UserSpaceControllerInfo =
( DAC960_ControllerInfo_T __user * ) Argument ;
DAC960_ControllerInfo_T ControllerInfo ;
DAC960_Controller_T * Controller ;
int ControllerNumber ;
if ( UserSpaceControllerInfo = = NULL ) return - EINVAL ;
ErrorCode = get_user ( ControllerNumber ,
& UserSpaceControllerInfo - > ControllerNumber ) ;
if ( ErrorCode ! = 0 ) return ErrorCode ;
if ( ControllerNumber < 0 | |
ControllerNumber > DAC960_ControllerCount - 1 )
return - ENXIO ;
Controller = DAC960_Controllers [ ControllerNumber ] ;
if ( Controller = = NULL ) return - ENXIO ;
memset ( & ControllerInfo , 0 , sizeof ( DAC960_ControllerInfo_T ) ) ;
ControllerInfo . ControllerNumber = ControllerNumber ;
ControllerInfo . FirmwareType = Controller - > FirmwareType ;
ControllerInfo . Channels = Controller - > Channels ;
ControllerInfo . Targets = Controller - > Targets ;
ControllerInfo . PCI_Bus = Controller - > Bus ;
ControllerInfo . PCI_Device = Controller - > Device ;
ControllerInfo . PCI_Function = Controller - > Function ;
ControllerInfo . IRQ_Channel = Controller - > IRQ_Channel ;
ControllerInfo . PCI_Address = Controller - > PCI_Address ;
strcpy ( ControllerInfo . ModelName , Controller - > ModelName ) ;
strcpy ( ControllerInfo . FirmwareVersion , Controller - > FirmwareVersion ) ;
return ( copy_to_user ( UserSpaceControllerInfo , & ControllerInfo ,
sizeof ( DAC960_ControllerInfo_T ) ) ? - EFAULT : 0 ) ;
}
case DAC960_IOCTL_V1_EXECUTE_COMMAND :
{
DAC960_V1_UserCommand_T __user * UserSpaceUserCommand =
( DAC960_V1_UserCommand_T __user * ) Argument ;
DAC960_V1_UserCommand_T UserCommand ;
DAC960_Controller_T * Controller ;
DAC960_Command_T * Command = NULL ;
DAC960_V1_CommandOpcode_T CommandOpcode ;
DAC960_V1_CommandStatus_T CommandStatus ;
DAC960_V1_DCDB_T DCDB ;
DAC960_V1_DCDB_T * DCDB_IOBUF = NULL ;
dma_addr_t DCDB_IOBUFDMA ;
unsigned long flags ;
int ControllerNumber , DataTransferLength ;
unsigned char * DataTransferBuffer = NULL ;
dma_addr_t DataTransferBufferDMA ;
if ( UserSpaceUserCommand = = NULL ) return - EINVAL ;
if ( copy_from_user ( & UserCommand , UserSpaceUserCommand ,
sizeof ( DAC960_V1_UserCommand_T ) ) ) {
ErrorCode = - EFAULT ;
goto Failure1a ;
}
ControllerNumber = UserCommand . ControllerNumber ;
if ( ControllerNumber < 0 | |
ControllerNumber > DAC960_ControllerCount - 1 )
return - ENXIO ;
Controller = DAC960_Controllers [ ControllerNumber ] ;
if ( Controller = = NULL ) return - ENXIO ;
if ( Controller - > FirmwareType ! = DAC960_V1_Controller ) return - EINVAL ;
CommandOpcode = UserCommand . CommandMailbox . Common . CommandOpcode ;
DataTransferLength = UserCommand . DataTransferLength ;
if ( CommandOpcode & 0x80 ) return - EINVAL ;
if ( CommandOpcode = = DAC960_V1_DCDB )
{
if ( copy_from_user ( & DCDB , UserCommand . DCDB ,
sizeof ( DAC960_V1_DCDB_T ) ) ) {
ErrorCode = - EFAULT ;
goto Failure1a ;
}
if ( DCDB . Channel > = DAC960_V1_MaxChannels ) return - EINVAL ;
if ( ! ( ( DataTransferLength = = 0 & &
DCDB . Direction
= = DAC960_V1_DCDB_NoDataTransfer ) | |
( DataTransferLength > 0 & &
DCDB . Direction
= = DAC960_V1_DCDB_DataTransferDeviceToSystem ) | |
( DataTransferLength < 0 & &
DCDB . Direction
= = DAC960_V1_DCDB_DataTransferSystemToDevice ) ) )
return - EINVAL ;
if ( ( ( DCDB . TransferLengthHigh4 < < 16 ) | DCDB . TransferLength )
! = abs ( DataTransferLength ) )
return - EINVAL ;
DCDB_IOBUF = pci_alloc_consistent ( Controller - > PCIDevice ,
sizeof ( DAC960_V1_DCDB_T ) , & DCDB_IOBUFDMA ) ;
if ( DCDB_IOBUF = = NULL )
return - ENOMEM ;
}
if ( DataTransferLength > 0 )
{
DataTransferBuffer = pci_alloc_consistent ( Controller - > PCIDevice ,
DataTransferLength , & DataTransferBufferDMA ) ;
if ( DataTransferBuffer = = NULL ) {
ErrorCode = - ENOMEM ;
goto Failure1 ;
}
memset ( DataTransferBuffer , 0 , DataTransferLength ) ;
}
else if ( DataTransferLength < 0 )
{
DataTransferBuffer = pci_alloc_consistent ( Controller - > PCIDevice ,
- DataTransferLength , & DataTransferBufferDMA ) ;
if ( DataTransferBuffer = = NULL ) {
ErrorCode = - ENOMEM ;
goto Failure1 ;
}
if ( copy_from_user ( DataTransferBuffer ,
UserCommand . DataTransferBuffer ,
- DataTransferLength ) ) {
ErrorCode = - EFAULT ;
goto Failure1 ;
}
}
if ( CommandOpcode = = DAC960_V1_DCDB )
{
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
while ( ( Command = DAC960_AllocateCommand ( Controller ) ) = = NULL )
DAC960_WaitForCommand ( Controller ) ;
while ( Controller - > V1 . DirectCommandActive [ DCDB . Channel ]
[ DCDB . TargetID ] )
{
spin_unlock_irq ( & Controller - > queue_lock ) ;
__wait_event ( Controller - > CommandWaitQueue ,
! Controller - > V1 . DirectCommandActive
[ DCDB . Channel ] [ DCDB . TargetID ] ) ;
spin_lock_irq ( & Controller - > queue_lock ) ;
}
Controller - > V1 . DirectCommandActive [ DCDB . Channel ]
[ DCDB . TargetID ] = true ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
DAC960_V1_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
memcpy ( & Command - > V1 . CommandMailbox , & UserCommand . CommandMailbox ,
sizeof ( DAC960_V1_CommandMailbox_T ) ) ;
Command - > V1 . CommandMailbox . Type3 . BusAddress = DCDB_IOBUFDMA ;
DCDB . BusAddress = DataTransferBufferDMA ;
memcpy ( DCDB_IOBUF , & DCDB , sizeof ( DAC960_V1_DCDB_T ) ) ;
}
else
{
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
while ( ( Command = DAC960_AllocateCommand ( Controller ) ) = = NULL )
DAC960_WaitForCommand ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
DAC960_V1_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
memcpy ( & Command - > V1 . CommandMailbox , & UserCommand . CommandMailbox ,
sizeof ( DAC960_V1_CommandMailbox_T ) ) ;
if ( DataTransferBuffer ! = NULL )
Command - > V1 . CommandMailbox . Type3 . BusAddress =
DataTransferBufferDMA ;
}
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V1 . CommandStatus ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_DeallocateCommand ( Command ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
if ( DataTransferLength > 0 )
{
if ( copy_to_user ( UserCommand . DataTransferBuffer ,
DataTransferBuffer , DataTransferLength ) ) {
ErrorCode = - EFAULT ;
goto Failure1 ;
}
}
if ( CommandOpcode = = DAC960_V1_DCDB )
{
/*
I don ' t believe Target or Channel in the DCDB_IOBUF
should be any different from the contents of DCDB .
*/
Controller - > V1 . DirectCommandActive [ DCDB . Channel ]
[ DCDB . TargetID ] = false ;
if ( copy_to_user ( UserCommand . DCDB , DCDB_IOBUF ,
sizeof ( DAC960_V1_DCDB_T ) ) ) {
ErrorCode = - EFAULT ;
goto Failure1 ;
}
}
ErrorCode = CommandStatus ;
Failure1 :
if ( DataTransferBuffer ! = NULL )
pci_free_consistent ( Controller - > PCIDevice , abs ( DataTransferLength ) ,
DataTransferBuffer , DataTransferBufferDMA ) ;
if ( DCDB_IOBUF ! = NULL )
pci_free_consistent ( Controller - > PCIDevice , sizeof ( DAC960_V1_DCDB_T ) ,
DCDB_IOBUF , DCDB_IOBUFDMA ) ;
Failure1a :
return ErrorCode ;
}
case DAC960_IOCTL_V2_EXECUTE_COMMAND :
{
DAC960_V2_UserCommand_T __user * UserSpaceUserCommand =
( DAC960_V2_UserCommand_T __user * ) Argument ;
DAC960_V2_UserCommand_T UserCommand ;
DAC960_Controller_T * Controller ;
DAC960_Command_T * Command = NULL ;
DAC960_V2_CommandMailbox_T * CommandMailbox ;
DAC960_V2_CommandStatus_T CommandStatus ;
unsigned long flags ;
int ControllerNumber , DataTransferLength ;
int DataTransferResidue , RequestSenseLength ;
unsigned char * DataTransferBuffer = NULL ;
dma_addr_t DataTransferBufferDMA ;
unsigned char * RequestSenseBuffer = NULL ;
dma_addr_t RequestSenseBufferDMA ;
if ( UserSpaceUserCommand = = NULL ) return - EINVAL ;
if ( copy_from_user ( & UserCommand , UserSpaceUserCommand ,
sizeof ( DAC960_V2_UserCommand_T ) ) ) {
ErrorCode = - EFAULT ;
goto Failure2a ;
}
ControllerNumber = UserCommand . ControllerNumber ;
if ( ControllerNumber < 0 | |
ControllerNumber > DAC960_ControllerCount - 1 )
return - ENXIO ;
Controller = DAC960_Controllers [ ControllerNumber ] ;
if ( Controller = = NULL ) return - ENXIO ;
if ( Controller - > FirmwareType ! = DAC960_V2_Controller ) return - EINVAL ;
DataTransferLength = UserCommand . DataTransferLength ;
if ( DataTransferLength > 0 )
{
DataTransferBuffer = pci_alloc_consistent ( Controller - > PCIDevice ,
DataTransferLength , & DataTransferBufferDMA ) ;
if ( DataTransferBuffer = = NULL ) return - ENOMEM ;
memset ( DataTransferBuffer , 0 , DataTransferLength ) ;
}
else if ( DataTransferLength < 0 )
{
DataTransferBuffer = pci_alloc_consistent ( Controller - > PCIDevice ,
- DataTransferLength , & DataTransferBufferDMA ) ;
if ( DataTransferBuffer = = NULL ) return - ENOMEM ;
if ( copy_from_user ( DataTransferBuffer ,
UserCommand . DataTransferBuffer ,
- DataTransferLength ) ) {
ErrorCode = - EFAULT ;
goto Failure2 ;
}
}
RequestSenseLength = UserCommand . RequestSenseLength ;
if ( RequestSenseLength > 0 )
{
RequestSenseBuffer = pci_alloc_consistent ( Controller - > PCIDevice ,
RequestSenseLength , & RequestSenseBufferDMA ) ;
if ( RequestSenseBuffer = = NULL )
{
ErrorCode = - ENOMEM ;
goto Failure2 ;
}
memset ( RequestSenseBuffer , 0 , RequestSenseLength ) ;
}
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
while ( ( Command = DAC960_AllocateCommand ( Controller ) ) = = NULL )
DAC960_WaitForCommand ( Controller ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
DAC960_V2_ClearCommand ( Command ) ;
Command - > CommandType = DAC960_ImmediateCommand ;
CommandMailbox = & Command - > V2 . CommandMailbox ;
memcpy ( CommandMailbox , & UserCommand . CommandMailbox ,
sizeof ( DAC960_V2_CommandMailbox_T ) ) ;
CommandMailbox - > Common . CommandControlBits
. AdditionalScatterGatherListMemory = false ;
CommandMailbox - > Common . CommandControlBits
. NoAutoRequestSense = true ;
CommandMailbox - > Common . DataTransferSize = 0 ;
CommandMailbox - > Common . DataTransferPageNumber = 0 ;
memset ( & CommandMailbox - > Common . DataTransferMemoryAddress , 0 ,
sizeof ( DAC960_V2_DataTransferMemoryAddress_T ) ) ;
if ( DataTransferLength ! = 0 )
{
if ( DataTransferLength > 0 )
{
CommandMailbox - > Common . CommandControlBits
. DataTransferControllerToHost = true ;
CommandMailbox - > Common . DataTransferSize = DataTransferLength ;
}
else
{
CommandMailbox - > Common . CommandControlBits
. DataTransferControllerToHost = false ;
CommandMailbox - > Common . DataTransferSize = - DataTransferLength ;
}
CommandMailbox - > Common . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentDataPointer = DataTransferBufferDMA ;
CommandMailbox - > Common . DataTransferMemoryAddress
. ScatterGatherSegments [ 0 ]
. SegmentByteCount =
CommandMailbox - > Common . DataTransferSize ;
}
if ( RequestSenseLength > 0 )
{
CommandMailbox - > Common . CommandControlBits
. NoAutoRequestSense = false ;
CommandMailbox - > Common . RequestSenseSize = RequestSenseLength ;
CommandMailbox - > Common . RequestSenseBusAddress =
RequestSenseBufferDMA ;
}
DAC960_ExecuteCommand ( Command ) ;
CommandStatus = Command - > V2 . CommandStatus ;
RequestSenseLength = Command - > V2 . RequestSenseLength ;
DataTransferResidue = Command - > V2 . DataTransferResidue ;
spin_lock_irqsave ( & Controller - > queue_lock , flags ) ;
DAC960_DeallocateCommand ( Command ) ;
spin_unlock_irqrestore ( & Controller - > queue_lock , flags ) ;
if ( RequestSenseLength > UserCommand . RequestSenseLength )
RequestSenseLength = UserCommand . RequestSenseLength ;
if ( copy_to_user ( & UserSpaceUserCommand - > DataTransferLength ,
& DataTransferResidue ,
sizeof ( DataTransferResidue ) ) ) {
ErrorCode = - EFAULT ;
goto Failure2 ;
}
if ( copy_to_user ( & UserSpaceUserCommand - > RequestSenseLength ,
& RequestSenseLength , sizeof ( RequestSenseLength ) ) ) {
ErrorCode = - EFAULT ;
goto Failure2 ;
}
if ( DataTransferLength > 0 )
{
if ( copy_to_user ( UserCommand . DataTransferBuffer ,
DataTransferBuffer , DataTransferLength ) ) {
ErrorCode = - EFAULT ;
goto Failure2 ;
}
}
if ( RequestSenseLength > 0 )
{
if ( copy_to_user ( UserCommand . RequestSenseBuffer ,
RequestSenseBuffer , RequestSenseLength ) ) {
ErrorCode = - EFAULT ;
goto Failure2 ;
}
}
ErrorCode = CommandStatus ;
Failure2 :
pci_free_consistent ( Controller - > PCIDevice , abs ( DataTransferLength ) ,
DataTransferBuffer , DataTransferBufferDMA ) ;
if ( RequestSenseBuffer ! = NULL )
pci_free_consistent ( Controller - > PCIDevice , RequestSenseLength ,
RequestSenseBuffer , RequestSenseBufferDMA ) ;
Failure2a :
return ErrorCode ;
}
case DAC960_IOCTL_V2_GET_HEALTH_STATUS :
{
DAC960_V2_GetHealthStatus_T __user * UserSpaceGetHealthStatus =
( DAC960_V2_GetHealthStatus_T __user * ) Argument ;
DAC960_V2_GetHealthStatus_T GetHealthStatus ;
DAC960_V2_HealthStatusBuffer_T HealthStatusBuffer ;
DAC960_Controller_T * Controller ;
int ControllerNumber ;
if ( UserSpaceGetHealthStatus = = NULL ) return - EINVAL ;
if ( copy_from_user ( & GetHealthStatus , UserSpaceGetHealthStatus ,
sizeof ( DAC960_V2_GetHealthStatus_T ) ) )
return - EFAULT ;
ControllerNumber = GetHealthStatus . ControllerNumber ;
if ( ControllerNumber < 0 | |
ControllerNumber > DAC960_ControllerCount - 1 )
return - ENXIO ;
Controller = DAC960_Controllers [ ControllerNumber ] ;
if ( Controller = = NULL ) return - ENXIO ;
if ( Controller - > FirmwareType ! = DAC960_V2_Controller ) return - EINVAL ;
if ( copy_from_user ( & HealthStatusBuffer ,
GetHealthStatus . HealthStatusBuffer ,
sizeof ( DAC960_V2_HealthStatusBuffer_T ) ) )
return - EFAULT ;
while ( Controller - > V2 . HealthStatusBuffer - > StatusChangeCounter
= = HealthStatusBuffer . StatusChangeCounter & &
Controller - > V2 . HealthStatusBuffer - > NextEventSequenceNumber
= = HealthStatusBuffer . NextEventSequenceNumber )
{
interruptible_sleep_on_timeout ( & Controller - > HealthStatusWaitQueue ,
DAC960_MonitoringTimerInterval ) ;
if ( signal_pending ( current ) ) return - EINTR ;
}
if ( copy_to_user ( GetHealthStatus . HealthStatusBuffer ,
Controller - > V2 . HealthStatusBuffer ,
sizeof ( DAC960_V2_HealthStatusBuffer_T ) ) )
return - EFAULT ;
return 0 ;
}
}
return - EINVAL ;
}
static struct file_operations DAC960_gam_fops = {
. owner = THIS_MODULE ,
. ioctl = DAC960_gam_ioctl
} ;
static struct miscdevice DAC960_gam_dev = {
DAC960_GAM_MINOR ,
" dac960_gam " ,
& DAC960_gam_fops
} ;
static int DAC960_gam_init ( void )
{
int ret ;
ret = misc_register ( & DAC960_gam_dev ) ;
if ( ret )
printk ( KERN_ERR " DAC960_gam: can't misc_register on minor %d \n " , DAC960_GAM_MINOR ) ;
return ret ;
}
static void DAC960_gam_cleanup ( void )
{
misc_deregister ( & DAC960_gam_dev ) ;
}
# endif /* DAC960_GAM_MINOR */
2005-05-05 16:15:58 -07:00
static struct DAC960_privdata DAC960_GEM_privdata = {
. HardwareType = DAC960_GEM_Controller ,
. FirmwareType = DAC960_V2_Controller ,
. InterruptHandler = DAC960_GEM_InterruptHandler ,
. MemoryWindowSize = DAC960_GEM_RegisterWindowSize ,
} ;
2005-04-16 15:20:36 -07:00
static struct DAC960_privdata DAC960_BA_privdata = {
. HardwareType = DAC960_BA_Controller ,
. FirmwareType = DAC960_V2_Controller ,
. InterruptHandler = DAC960_BA_InterruptHandler ,
. MemoryWindowSize = DAC960_BA_RegisterWindowSize ,
} ;
static struct DAC960_privdata DAC960_LP_privdata = {
. HardwareType = DAC960_LP_Controller ,
. FirmwareType = DAC960_LP_Controller ,
. InterruptHandler = DAC960_LP_InterruptHandler ,
. MemoryWindowSize = DAC960_LP_RegisterWindowSize ,
} ;
static struct DAC960_privdata DAC960_LA_privdata = {
. HardwareType = DAC960_LA_Controller ,
. FirmwareType = DAC960_V1_Controller ,
. InterruptHandler = DAC960_LA_InterruptHandler ,
. MemoryWindowSize = DAC960_LA_RegisterWindowSize ,
} ;
static struct DAC960_privdata DAC960_PG_privdata = {
. HardwareType = DAC960_PG_Controller ,
. FirmwareType = DAC960_V1_Controller ,
. InterruptHandler = DAC960_PG_InterruptHandler ,
. MemoryWindowSize = DAC960_PG_RegisterWindowSize ,
} ;
static struct DAC960_privdata DAC960_PD_privdata = {
. HardwareType = DAC960_PD_Controller ,
. FirmwareType = DAC960_V1_Controller ,
. InterruptHandler = DAC960_PD_InterruptHandler ,
. MemoryWindowSize = DAC960_PD_RegisterWindowSize ,
} ;
static struct DAC960_privdata DAC960_P_privdata = {
. HardwareType = DAC960_P_Controller ,
. FirmwareType = DAC960_V1_Controller ,
. InterruptHandler = DAC960_P_InterruptHandler ,
. MemoryWindowSize = DAC960_PD_RegisterWindowSize ,
} ;
static struct pci_device_id DAC960_id_table [ ] = {
2005-05-05 16:15:58 -07:00
{
. vendor = PCI_VENDOR_ID_MYLEX ,
. device = PCI_DEVICE_ID_MYLEX_DAC960_GEM ,
. subvendor = PCI_ANY_ID ,
. subdevice = PCI_ANY_ID ,
. driver_data = ( unsigned long ) & DAC960_GEM_privdata ,
} ,
2005-04-16 15:20:36 -07:00
{
. vendor = PCI_VENDOR_ID_MYLEX ,
. device = PCI_DEVICE_ID_MYLEX_DAC960_BA ,
. subvendor = PCI_ANY_ID ,
. subdevice = PCI_ANY_ID ,
. driver_data = ( unsigned long ) & DAC960_BA_privdata ,
} ,
{
. vendor = PCI_VENDOR_ID_MYLEX ,
. device = PCI_DEVICE_ID_MYLEX_DAC960_LP ,
. subvendor = PCI_ANY_ID ,
. subdevice = PCI_ANY_ID ,
. driver_data = ( unsigned long ) & DAC960_LP_privdata ,
} ,
{
. vendor = PCI_VENDOR_ID_DEC ,
. device = PCI_DEVICE_ID_DEC_21285 ,
. subvendor = PCI_VENDOR_ID_MYLEX ,
. subdevice = PCI_DEVICE_ID_MYLEX_DAC960_LA ,
. driver_data = ( unsigned long ) & DAC960_LA_privdata ,
} ,
{
. vendor = PCI_VENDOR_ID_MYLEX ,
. device = PCI_DEVICE_ID_MYLEX_DAC960_PG ,
. subvendor = PCI_ANY_ID ,
. subdevice = PCI_ANY_ID ,
. driver_data = ( unsigned long ) & DAC960_PG_privdata ,
} ,
{
. vendor = PCI_VENDOR_ID_MYLEX ,
. device = PCI_DEVICE_ID_MYLEX_DAC960_PD ,
. subvendor = PCI_ANY_ID ,
. subdevice = PCI_ANY_ID ,
. driver_data = ( unsigned long ) & DAC960_PD_privdata ,
} ,
{
. vendor = PCI_VENDOR_ID_MYLEX ,
. device = PCI_DEVICE_ID_MYLEX_DAC960_P ,
. subvendor = PCI_ANY_ID ,
. subdevice = PCI_ANY_ID ,
. driver_data = ( unsigned long ) & DAC960_P_privdata ,
} ,
{ 0 , } ,
} ;
MODULE_DEVICE_TABLE ( pci , DAC960_id_table ) ;
static struct pci_driver DAC960_pci_driver = {
. name = " DAC960 " ,
. id_table = DAC960_id_table ,
. probe = DAC960_Probe ,
. remove = DAC960_Remove ,
} ;
static int DAC960_init_module ( void )
{
int ret ;
ret = pci_module_init ( & DAC960_pci_driver ) ;
# ifdef DAC960_GAM_MINOR
if ( ! ret )
DAC960_gam_init ( ) ;
# endif
return ret ;
}
static void DAC960_cleanup_module ( void )
{
int i ;
# ifdef DAC960_GAM_MINOR
DAC960_gam_cleanup ( ) ;
# endif
for ( i = 0 ; i < DAC960_ControllerCount ; i + + ) {
DAC960_Controller_T * Controller = DAC960_Controllers [ i ] ;
if ( Controller = = NULL )
continue ;
DAC960_FinalizeController ( Controller ) ;
}
if ( DAC960_ProcDirectoryEntry ! = NULL ) {
remove_proc_entry ( " rd/status " , NULL ) ;
remove_proc_entry ( " rd " , NULL ) ;
}
DAC960_ControllerCount = 0 ;
pci_unregister_driver ( & DAC960_pci_driver ) ;
}
module_init ( DAC960_init_module ) ;
module_exit ( DAC960_cleanup_module ) ;
MODULE_LICENSE ( " GPL " ) ;