diff options
Diffstat (limited to 'drivers/block/DAC960.c')
-rw-r--r-- | drivers/block/DAC960.c | 5751 |
1 files changed, 4248 insertions, 1503 deletions
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index 41ec3e2f5..749b0d3da 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c @@ -1,8 +1,8 @@ /* - Linux Driver for Mylex DAC960 and DAC1100 PCI RAID Controllers + Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers - Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com> + Copyright 1998-2000 by Leonard N. Zubkoff <lnz@dandelion.com> 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 @@ -19,9 +19,8 @@ */ -#define DAC960_DriverVersion "2.3.5" -#define DAC960_DriverDate "23 January 2000" - +#define DAC960_DriverVersion "2.4.7" +#define DAC960_DriverDate "1 August 2000" #include <linux/version.h> @@ -38,11 +37,11 @@ #include <linux/malloc.h> #include <linux/proc_fs.h> #include <linux/reboot.h> +#include <linux/spinlock.h> #include <linux/timer.h> #include <linux/pci.h> #include <asm/io.h> #include <asm/segment.h> -#include <linux/spinlock.h> #include <asm/uaccess.h> #include "DAC960.h" @@ -56,7 +55,7 @@ static int /* - DAC960_ActiveControllerCount is the number of Active DAC960 Controllers + DAC960_ActiveControllerCount is the number of active DAC960 Controllers detected. */ @@ -74,23 +73,23 @@ static DAC960_Controller_T /* - DAC960_FileOperations is the File Operations structure for DAC960 Logical - Disk Devices. - Leonard, no offence, but _where_ did this C dialect come from? + DAC960_BlockDeviceOperations is the Block Device Operations structure for + DAC960 Logical Disk Devices. */ -static struct block_device_operations DAC960_FileOperations = { - open: DAC960_Open, - release: DAC960_Release, - ioctl: DAC960_IOCTL, -}; +static BlockDeviceOperations_T + DAC960_BlockDeviceOperations = + { open: DAC960_Open, + release: DAC960_Release, + ioctl: DAC960_IOCTL }; + /* - DAC960_ProcDirectoryEntry is the DAC960 /proc/driver/rd directory entry. + DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry. */ -static PROC_DirectoryEntry_T * - DAC960_ProcDirectoryEntry = NULL; +static PROC_DirectoryEntry_T + *DAC960_ProcDirectoryEntry; /* @@ -121,7 +120,7 @@ static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller) */ static boolean DAC960_Failure(DAC960_Controller_T *Controller, - char *ErrorMessage) + unsigned char *ErrorMessage) { DAC960_Error("While configuring DAC960 PCI RAID Controller at\n", Controller); @@ -141,17 +140,128 @@ static boolean DAC960_Failure(DAC960_Controller_T *Controller, /* - DAC960_ClearCommand clears critical fields of Command. + DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary + data structures for Controller. It returns true on success and false on + failure. */ -static inline void DAC960_ClearCommand(DAC960_Command_T *Command) +static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - CommandMailbox->Words[0] = 0; - CommandMailbox->Words[1] = 0; - CommandMailbox->Words[2] = 0; - CommandMailbox->Words[3] = 0; - Command->CommandStatus = 0; + int CommandAllocationLength, CommandAllocationGroupSize; + int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount; + void *AllocationPointer = NULL; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + CommandAllocationLength = offsetof(DAC960_Command_T, V1.EndMarker); + CommandAllocationGroupSize = DAC960_V1_CommandAllocationGroupSize; + } + else + { + CommandAllocationLength = offsetof(DAC960_Command_T, V2.EndMarker); + CommandAllocationGroupSize = DAC960_V2_CommandAllocationGroupSize; + } + 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; + } + return true; +} + + +/* + DAC960_DestroyAuxiliaryStructures deallocates the auxiliary data + structures for Controller. +*/ + +static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller) +{ + int i; + Controller->FreeCommands = NULL; + for (i = 0; i < Controller->DriverQueueDepth; i++) + { + DAC960_Command_T *Command = Controller->Commands[i]; + if (Command != NULL && + (Command->CommandIdentifier + % Controller->CommandAllocationGroupSize) == 1) + kfree(Command); + Controller->Commands[i] = NULL; + } + if (Controller->CombinedStatusBuffer != NULL) + { + kfree(Controller->CombinedStatusBuffer); + Controller->CombinedStatusBuffer = NULL; + Controller->CurrentStatusBuffer = NULL; + } + if (Controller->FirmwareType == DAC960_V1_Controller) return; + 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; } @@ -202,66 +312,181 @@ static void DAC960_WaitForCommand(DAC960_Controller_T *Controller) /* - DAC960_QueueCommand queues Command. + DAC960_BA_QueueCommand queues Command for DAC960 BA Series Controllers. */ -static void DAC960_QueueCommand(DAC960_Command_T *Command) +static void DAC960_BA_QueueCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; void *ControllerBaseAddress = Controller->BaseAddress; - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - DAC960_CommandMailbox_T *NextCommandMailbox; - CommandMailbox->Common.CommandIdentifier = Command - Controller->Commands; - switch (Controller->ControllerType) - { - case DAC960_V5_Controller: - NextCommandMailbox = Controller->NextCommandMailbox; - DAC960_V5_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); - if (Controller->PreviousCommandMailbox1->Words[0] == 0 || - Controller->PreviousCommandMailbox2->Words[0] == 0) - { - if (Controller->DualModeMemoryMailboxInterface) - DAC960_V5_MemoryMailboxNewCommand(ControllerBaseAddress); - else DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress); - } - Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1; - Controller->PreviousCommandMailbox1 = NextCommandMailbox; - if (++NextCommandMailbox > Controller->LastCommandMailbox) - NextCommandMailbox = Controller->FirstCommandMailbox; - Controller->NextCommandMailbox = NextCommandMailbox; - break; - case DAC960_V4_Controller: - NextCommandMailbox = Controller->NextCommandMailbox; - DAC960_V4_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); - if (Controller->PreviousCommandMailbox1->Words[0] == 0 || - Controller->PreviousCommandMailbox2->Words[0] == 0) - { - if (Controller->DualModeMemoryMailboxInterface) - DAC960_V4_MemoryMailboxNewCommand(ControllerBaseAddress); - else DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress); - } - Controller->PreviousCommandMailbox2 = Controller->PreviousCommandMailbox1; - Controller->PreviousCommandMailbox1 = NextCommandMailbox; - if (++NextCommandMailbox > Controller->LastCommandMailbox) - NextCommandMailbox = Controller->FirstCommandMailbox; - Controller->NextCommandMailbox = NextCommandMailbox; - break; - case DAC960_V3_Controller: - while (DAC960_V3_MailboxFullP(ControllerBaseAddress)) - udelay(1); - DAC960_V3_WriteCommandMailbox(ControllerBaseAddress, CommandMailbox); - DAC960_V3_NewCommand(ControllerBaseAddress); - break; - } + 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_ExecuteCommand executes Command and waits for completion. It - returns true on success and false on failure. + DAC960_LP_QueueCommand queues Command for DAC960 LP Series Controllers. */ -static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command) +static void DAC960_LP_QueueCommand(DAC960_Command_T *Command) +{ + DAC960_Controller_T *Controller = Command->Controller; + void *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 *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 *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 *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 *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 *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_ExecuteCommand executes Command and waits for completion. +*/ + +static void DAC960_ExecuteCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; DECLARE_MUTEX_LOCKED(Semaphore); @@ -270,227 +495,386 @@ static boolean DAC960_ExecuteCommand(DAC960_Command_T *Command) DAC960_AcquireControllerLock(Controller, &ProcessorFlags); DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (!in_interrupt()) - down(&Semaphore); - return Command->CommandStatus == DAC960_NormalCompletion; + if (in_interrupt()) return; + down(&Semaphore); } /* - DAC960_ExecuteType3 executes a DAC960 Type 3 Command and waits for - completion. It returns true on success and false on failure. + 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_ExecuteType3(DAC960_Controller_T *Controller, - DAC960_CommandOpcode_T CommandOpcode, - void *DataPointer) +static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller, + DAC960_V1_CommandOpcode_T CommandOpcode, + void *DataPointer) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - boolean Result; - DAC960_ClearCommand(Command); + 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 = Virtual_to_Bus(DataPointer); - Result = DAC960_ExecuteCommand(Command); + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); - return Result; + return (CommandStatus == DAC960_V1_NormalCompletion); } /* - DAC960_ExecuteType3D executes a DAC960 Type 3D Command and waits for - completion. It returns true on success and false on failure. + DAC960_V1_ExecuteType3D executes a DAC960 V1 Firmware Controller Type 3D + Command and waits for completion. It returns true on success and false + on failure. */ -static boolean DAC960_ExecuteType3D(DAC960_Controller_T *Controller, - DAC960_CommandOpcode_T CommandOpcode, - unsigned char Channel, - unsigned char TargetID, - void *DataPointer) +static boolean DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller, + DAC960_V1_CommandOpcode_T CommandOpcode, + unsigned char Channel, + unsigned char TargetID, + void *DataPointer) { DAC960_Command_T *Command = DAC960_AllocateCommand(Controller); - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - boolean Result; - DAC960_ClearCommand(Command); + 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 = Virtual_to_Bus(DataPointer); - Result = DAC960_ExecuteCommand(Command); + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V1.CommandStatus; DAC960_DeallocateCommand(Command); - return Result; + return (CommandStatus == DAC960_V1_NormalCompletion); } /* - 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. + 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. */ -static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller, - unsigned char ErrorStatus, - unsigned char Parameter0, - unsigned char Parameter1) +static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, + void *DataPointer, + unsigned int DataByteCount) { - switch (ErrorStatus) - { - case 0x00: - DAC960_Notice("Physical Drive %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 Drive %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_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 = DataByteCount; + CommandMailbox->Common.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + 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_EnableMemoryMailboxInterface enables the Memory Mailbox Interface. + 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. */ -static boolean DAC960_EnableMemoryMailboxInterface(DAC960_Controller_T - *Controller) +static boolean DAC960_V2_ControllerInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode, + void *DataPointer, + unsigned int DataByteCount) +{ + 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 = DataByteCount; + CommandMailbox->ControllerInfo.ControllerNumber = 0; + CommandMailbox->ControllerInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->ControllerInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + 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. +*/ + +static boolean DAC960_V2_LogicalDeviceInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T + IOCTL_Opcode, + unsigned short + LogicalDeviceNumber, + void *DataPointer, + unsigned int DataByteCount) +{ + 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 = DataByteCount; + CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber = + LogicalDeviceNumber; + CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + 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 Physical + Device Information Reading IOCTL Command and waits for completion. It + returns true on success and false on failure. +*/ + +static boolean DAC960_V2_PhysicalDeviceInfo(DAC960_Controller_T *Controller, + DAC960_V2_IOCTL_Opcode_T + IOCTL_Opcode, + unsigned char Channel, + unsigned char TargetID, + unsigned char LogicalUnit, + void *DataPointer, + unsigned int DataByteCount) +{ + 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 = DataByteCount; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = LogicalUnit; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = TargetID; + CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = Channel; + CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode; + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(DataPointer); + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->PhysicalDeviceInfo.DataTransferSize; + 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. +*/ + +static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T + *Controller) { void *ControllerBaseAddress = Controller->BaseAddress; - DAC960_CommandMailbox_T *CommandMailboxesMemory; - DAC960_StatusMailbox_T *StatusMailboxesMemory; - DAC960_CommandMailbox_T CommandMailbox; - DAC960_CommandStatus_T CommandStatus; + DAC960_V1_CommandMailbox_T *CommandMailboxesMemory; + DAC960_V1_StatusMailbox_T *StatusMailboxesMemory; + DAC960_V1_CommandMailbox_T CommandMailbox; + DAC960_V1_CommandStatus_T CommandStatus; + unsigned long MemoryMailboxPagesAddress; + unsigned long MemoryMailboxPagesOrder; + unsigned long MemoryMailboxPagesSize; void *SavedMemoryMailboxesAddress = NULL; short NextCommandMailboxIndex = 0; short NextStatusMailboxIndex = 0; int TimeoutCounter = 1000000, i; - if (Controller->ControllerType == DAC960_V5_Controller) - DAC960_V5_RestoreMemoryMailboxInfo(Controller, + MemoryMailboxPagesOrder = 0; + MemoryMailboxPagesSize = + DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T) + + DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T); + while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder) + MemoryMailboxPagesOrder++; + if (Controller->HardwareType == DAC960_LA_Controller) + DAC960_LA_RestoreMemoryMailboxInfo(Controller, &SavedMemoryMailboxesAddress, &NextCommandMailboxIndex, &NextStatusMailboxIndex); - else DAC960_V4_RestoreMemoryMailboxInfo(Controller, + else DAC960_PG_RestoreMemoryMailboxInfo(Controller, &SavedMemoryMailboxesAddress, &NextCommandMailboxIndex, &NextStatusMailboxIndex); if (SavedMemoryMailboxesAddress == NULL) - CommandMailboxesMemory = - (DAC960_CommandMailbox_T *) __get_free_pages(GFP_KERNEL, 1); + { + MemoryMailboxPagesAddress = + __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder); + Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress; + CommandMailboxesMemory = + (DAC960_V1_CommandMailbox_T *) MemoryMailboxPagesAddress; + } else CommandMailboxesMemory = SavedMemoryMailboxesAddress; - memset(CommandMailboxesMemory, 0, PAGE_SIZE << 1); - Controller->FirstCommandMailbox = CommandMailboxesMemory; - CommandMailboxesMemory += DAC960_CommandMailboxCount - 1; - Controller->LastCommandMailbox = CommandMailboxesMemory; - Controller->NextCommandMailbox = - &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + if (CommandMailboxesMemory == NULL) return false; + Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder; + memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize); + Controller->V1.FirstCommandMailbox = CommandMailboxesMemory; + CommandMailboxesMemory += DAC960_V1_CommandMailboxCount - 1; + Controller->V1.LastCommandMailbox = CommandMailboxesMemory; + Controller->V1.NextCommandMailbox = + &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; if (--NextCommandMailboxIndex < 0) - NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1; - Controller->PreviousCommandMailbox1 = - &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1; + Controller->V1.PreviousCommandMailbox1 = + &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; if (--NextCommandMailboxIndex < 0) - NextCommandMailboxIndex = DAC960_CommandMailboxCount - 1; - Controller->PreviousCommandMailbox2 = - &Controller->FirstCommandMailbox[NextCommandMailboxIndex]; + NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1; + Controller->V1.PreviousCommandMailbox2 = + &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex]; StatusMailboxesMemory = - (DAC960_StatusMailbox_T *) (CommandMailboxesMemory + 1); - Controller->FirstStatusMailbox = StatusMailboxesMemory; - StatusMailboxesMemory += DAC960_StatusMailboxCount - 1; - Controller->LastStatusMailbox = StatusMailboxesMemory; - Controller->NextStatusMailbox = - &Controller->FirstStatusMailbox[NextStatusMailboxIndex]; + (DAC960_V1_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->V1.FirstStatusMailbox = StatusMailboxesMemory; + StatusMailboxesMemory += DAC960_V1_StatusMailboxCount - 1; + Controller->V1.LastStatusMailbox = StatusMailboxesMemory; + Controller->V1.NextStatusMailbox = + &Controller->V1.FirstStatusMailbox[NextStatusMailboxIndex]; if (SavedMemoryMailboxesAddress != NULL) return true; /* Enable the Memory Mailbox Interface. */ - Controller->DualModeMemoryMailboxInterface = true; + Controller->V1.DualModeMemoryMailboxInterface = true; CommandMailbox.TypeX.CommandOpcode = 0x2B; CommandMailbox.TypeX.CommandIdentifier = 0; CommandMailbox.TypeX.CommandOpcode2 = 0x14; CommandMailbox.TypeX.CommandMailboxesBusAddress = - Virtual_to_Bus(Controller->FirstCommandMailbox); + Virtual_to_Bus(Controller->V1.FirstCommandMailbox); CommandMailbox.TypeX.StatusMailboxesBusAddress = - Virtual_to_Bus(Controller->FirstStatusMailbox); + Virtual_to_Bus(Controller->V1.FirstStatusMailbox); for (i = 0; i < 2; i++) - switch (Controller->ControllerType) + switch (Controller->HardwareType) { - case DAC960_V5_Controller: + case DAC960_LA_Controller: while (--TimeoutCounter >= 0) { - if (!DAC960_V5_HardwareMailboxFullP(ControllerBaseAddress)) + if (!DAC960_LA_HardwareMailboxFullP(ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - DAC960_V5_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); - DAC960_V5_HardwareMailboxNewCommand(ControllerBaseAddress); + DAC960_LA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_LA_HardwareMailboxNewCommand(ControllerBaseAddress); while (--TimeoutCounter >= 0) { - if (DAC960_V5_HardwareMailboxStatusAvailableP( + if (DAC960_LA_HardwareMailboxStatusAvailableP( ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - CommandStatus = DAC960_V5_ReadStatusRegister(ControllerBaseAddress); - DAC960_V5_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); - DAC960_V5_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); - if (CommandStatus == DAC960_NormalCompletion) return true; - Controller->DualModeMemoryMailboxInterface = 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_V4_Controller: + case DAC960_PG_Controller: while (--TimeoutCounter >= 0) { - if (!DAC960_V4_HardwareMailboxFullP(ControllerBaseAddress)) + if (!DAC960_PG_HardwareMailboxFullP(ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - DAC960_V4_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); - DAC960_V4_HardwareMailboxNewCommand(ControllerBaseAddress); + DAC960_PG_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + DAC960_PG_HardwareMailboxNewCommand(ControllerBaseAddress); while (--TimeoutCounter >= 0) { - if (DAC960_V4_HardwareMailboxStatusAvailableP( + if (DAC960_PG_HardwareMailboxStatusAvailableP( ControllerBaseAddress)) break; udelay(10); } if (TimeoutCounter < 0) return false; - CommandStatus = DAC960_V4_ReadStatusRegister(ControllerBaseAddress); - DAC960_V4_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress); - DAC960_V4_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress); - if (CommandStatus == DAC960_NormalCompletion) return true; - Controller->DualModeMemoryMailboxInterface = 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: @@ -501,287 +885,165 @@ static boolean DAC960_EnableMemoryMailboxInterface(DAC960_Controller_T /* - DAC960_DetectControllers detects DAC960 PCI RAID Controllers by interrogating - the PCI Configuration Space for Controller Type. + DAC960_V2_EnableMemoryMailboxInterface enables the Memory Mailbox Interface + for DAC960 V2 Firmware Controllers. */ -static void DAC960_DetectControllers(DAC960_ControllerType_T ControllerType) +static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T + *Controller) { - unsigned short VendorID = 0, DeviceID = 0; - unsigned int MemoryWindowSize = 0; - PCI_Device_T *PCI_Device = NULL; - switch (ControllerType) + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V2_CommandMailbox_T *CommandMailboxesMemory; + DAC960_V2_StatusMailbox_T *StatusMailboxesMemory; + DAC960_V2_CommandMailbox_T CommandMailbox; + DAC960_V2_CommandStatus_T CommandStatus = 0; + unsigned long MemoryMailboxPagesAddress; + unsigned long MemoryMailboxPagesOrder; + unsigned long MemoryMailboxPagesSize; + MemoryMailboxPagesOrder = 0; + MemoryMailboxPagesSize = + DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T) + + DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T) + + sizeof(DAC960_V2_HealthStatusBuffer_T); + while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder) + MemoryMailboxPagesOrder++; + MemoryMailboxPagesAddress = + __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder); + Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress; + CommandMailboxesMemory = + (DAC960_V2_CommandMailbox_T *) MemoryMailboxPagesAddress; + if (CommandMailboxesMemory == NULL) return false; + Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder; + memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize); + Controller->V2.FirstCommandMailbox = CommandMailboxesMemory; + 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; + StatusMailboxesMemory = + (DAC960_V2_StatusMailbox_T *) (CommandMailboxesMemory + 1); + Controller->V2.FirstStatusMailbox = StatusMailboxesMemory; + StatusMailboxesMemory += DAC960_V2_StatusMailboxCount - 1; + Controller->V2.LastStatusMailbox = StatusMailboxesMemory; + Controller->V2.NextStatusMailbox = Controller->V2.FirstStatusMailbox; + Controller->V2.HealthStatusBuffer = + (DAC960_V2_HealthStatusBuffer_T *) (StatusMailboxesMemory + 1); + /* Enable the Memory Mailbox Interface. */ + 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 = + Virtual_to_Bus(Controller->V2.HealthStatusBuffer); + CommandMailbox.SetMemoryMailbox.FirstCommandMailboxBusAddress = + Virtual_to_Bus(Controller->V2.FirstCommandMailbox); + CommandMailbox.SetMemoryMailbox.FirstStatusMailboxBusAddress = + Virtual_to_Bus(Controller->V2.FirstStatusMailbox); + switch (Controller->HardwareType) { - case DAC960_V5_Controller: - VendorID = PCI_VENDOR_ID_DEC; - DeviceID = PCI_DEVICE_ID_DEC_21285; - MemoryWindowSize = DAC960_V5_RegisterWindowSize; + case DAC960_BA_Controller: + while (DAC960_BA_HardwareMailboxFullP(ControllerBaseAddress)) + udelay(1); + DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + 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_V4_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V4; - MemoryWindowSize = DAC960_V4_RegisterWindowSize; + case DAC960_LP_Controller: + while (DAC960_LP_HardwareMailboxFullP(ControllerBaseAddress)) + udelay(1); + DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox); + 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; - case DAC960_V3_Controller: - VendorID = PCI_VENDOR_ID_MYLEX; - DeviceID = PCI_DEVICE_ID_MYLEX_DAC960P_V3; - MemoryWindowSize = DAC960_V3_RegisterWindowSize; + default: break; } - while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL) - { - DAC960_Controller_T *Controller = (DAC960_Controller_T *) - kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC); - DAC960_IO_Address_T IO_Address = 0; - DAC960_PCI_Address_T PCI_Address = 0; - unsigned char Bus = PCI_Device->bus->number; - unsigned char DeviceFunction = PCI_Device->devfn; - unsigned char Device = DeviceFunction >> 3; - unsigned char Function = DeviceFunction & 0x7; - unsigned int IRQ_Channel = PCI_Device->irq; - unsigned long BaseAddress0 = pci_resource_start (PCI_Device, 0); - unsigned long BaseAddress1 = pci_resource_start (PCI_Device, 1); - unsigned short SubsystemVendorID, SubsystemDeviceID; - int CommandIdentifier; - unsigned char ErrorStatus, Parameter0, Parameter1; - void *BaseAddress; - - - if (pci_enable_device(PCI_Device)) - goto Ignore; - - SubsystemVendorID = PCI_Device->subsystem_vendor; - SubsystemDeviceID = PCI_Device->subsystem_device; - switch (ControllerType) - { - case DAC960_V5_Controller: - if (!(SubsystemVendorID == PCI_VENDOR_ID_MYLEX && - SubsystemDeviceID == PCI_DEVICE_ID_MYLEX_DAC960P_V5)) - goto Ignore; - PCI_Address = BaseAddress0; - break; - case DAC960_V4_Controller: - PCI_Address = BaseAddress0; - break; - case DAC960_V3_Controller: - IO_Address = BaseAddress0; - PCI_Address = BaseAddress1; - break; - } - if (DAC960_ControllerCount == DAC960_MaxControllers) - { - DAC960_Error("More than %d DAC960 Controllers detected - " - "ignoring from Controller at\n", - NULL, DAC960_MaxControllers); - goto Ignore; - } - if (Controller == NULL) - { - DAC960_Error("Unable to allocate Controller structure for " - "Controller at\n", NULL); - goto Ignore; - } - memset(Controller, 0, sizeof(DAC960_Controller_T)); - init_waitqueue_head(&Controller->CommandWaitQueue); - Controller->ControllerNumber = DAC960_ControllerCount; - DAC960_Controllers[DAC960_ControllerCount++] = Controller; - DAC960_AnnounceDriver(Controller); - Controller->ControllerType = ControllerType; - Controller->IO_Address = IO_Address; - Controller->PCI_Address = PCI_Address; - Controller->Bus = Bus; - Controller->Device = Device; - Controller->Function = Function; - sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); - /* - Map the Controller Register Window. - */ - if (MemoryWindowSize < PAGE_SIZE) - MemoryWindowSize = PAGE_SIZE; - Controller->MemoryMappedAddress = - ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize); - Controller->BaseAddress = - Controller->MemoryMappedAddress + (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 (ControllerType) - { - case DAC960_V5_Controller: - DAC960_V5_DisableInterrupts(BaseAddress); - DAC960_V5_AcknowledgeHardwareMailboxStatus(BaseAddress); - udelay(1000); - while (DAC960_V5_InitializationInProgressP(BaseAddress)) - { - if (DAC960_V5_ReadErrorStatus(BaseAddress, &ErrorStatus, - &Parameter0, &Parameter1) && - DAC960_ReportErrorStatus(Controller, ErrorStatus, - Parameter0, Parameter1)) - goto Failure; - udelay(10); - } - if (!DAC960_EnableMemoryMailboxInterface(Controller)) - { - DAC960_Error("Unable to Enable Memory Mailbox Interface " - "for Controller at\n", Controller); - goto Failure; - } - DAC960_V5_EnableInterrupts(BaseAddress); - break; - case DAC960_V4_Controller: - DAC960_V4_DisableInterrupts(BaseAddress); - DAC960_V4_AcknowledgeHardwareMailboxStatus(BaseAddress); - udelay(1000); - while (DAC960_V4_InitializationInProgressP(BaseAddress)) - { - if (DAC960_V4_ReadErrorStatus(BaseAddress, &ErrorStatus, - &Parameter0, &Parameter1) && - DAC960_ReportErrorStatus(Controller, ErrorStatus, - Parameter0, Parameter1)) - goto Failure; - udelay(10); - } - if (!DAC960_EnableMemoryMailboxInterface(Controller)) - { - DAC960_Error("Unable to Enable Memory Mailbox Interface " - "for Controller at\n", Controller); - goto Failure; - } - DAC960_V4_EnableInterrupts(BaseAddress); - break; - case DAC960_V3_Controller: - request_region(Controller->IO_Address, 0x80, - Controller->FullModelName); - DAC960_V3_DisableInterrupts(BaseAddress); - DAC960_V3_AcknowledgeStatus(BaseAddress); - udelay(1000); - while (DAC960_V3_InitializationInProgressP(BaseAddress)) - { - if (DAC960_V3_ReadErrorStatus(BaseAddress, &ErrorStatus, - &Parameter0, &Parameter1) && - DAC960_ReportErrorStatus(Controller, ErrorStatus, - Parameter0, Parameter1)) - goto Failure; - udelay(10); - } - DAC960_V3_EnableInterrupts(BaseAddress); - break; - } - /* - Acquire shared access to the IRQ Channel. - */ - if (IRQ_Channel == 0) - { - DAC960_Error("IRQ Channel %d illegal for Controller at\n", - Controller, IRQ_Channel); - goto Failure; - } - strcpy(Controller->FullModelName, "DAC960"); - if (request_irq(IRQ_Channel, DAC960_InterruptHandler, - SA_SHIRQ, Controller->FullModelName, Controller) < 0) - { - DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n", - Controller, IRQ_Channel); - goto Failure; - } - Controller->IRQ_Channel = IRQ_Channel; - DAC960_ActiveControllerCount++; - for (CommandIdentifier = 0; - CommandIdentifier < DAC960_MaxChannels; - CommandIdentifier++) - { - Controller->Commands[CommandIdentifier].Controller = Controller; - Controller->Commands[CommandIdentifier].Next = - Controller->FreeCommands; - Controller->FreeCommands = &Controller->Commands[CommandIdentifier]; - } - continue; - Failure: - if (IO_Address == 0) - DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A " - "PCI Address 0x%X\n", Controller, - Bus, Device, Function, PCI_Address); - else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " - "0x%X PCI Address 0x%X\n", Controller, - Bus, Device, Function, IO_Address, PCI_Address); - if (Controller == NULL) break; - if (Controller->MemoryMappedAddress != NULL) - iounmap(Controller->MemoryMappedAddress); - DAC960_Controllers[Controller->ControllerNumber] = NULL; - if (Controller->IRQ_Channel > 0) - free_irq(IRQ_Channel, Controller); - Ignore: - kfree(Controller); - } + return (CommandStatus == DAC960_V2_NormalCompletion); } /* - DAC960_ReadControllerConfiguration reads the Configuration Information - from Controller and initializes the Controller structure. + DAC960_V1_ReadControllerConfiguration reads the Configuration Information + from DAC960 V1 Firmware Controllers and initializes the Controller structure. */ -static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T - *Controller) +static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T + *Controller) { - DAC960_Enquiry2_T Enquiry2; - DAC960_Config2_T Config2; + DAC960_V1_Enquiry2_T Enquiry2; + DAC960_V1_Config2_T Config2; int LogicalDriveNumber, Channel, TargetID; - if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry, - &Controller->Enquiry[0])) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry, + &Controller->V1.Enquiry)) return DAC960_Failure(Controller, "ENQUIRY"); - if (!DAC960_ExecuteType3(Controller, DAC960_Enquiry2, &Enquiry2)) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, &Enquiry2)) return DAC960_Failure(Controller, "ENQUIRY2"); - if (!DAC960_ExecuteType3(Controller, DAC960_ReadConfig2, &Config2)) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, &Config2)) return DAC960_Failure(Controller, "READ CONFIG2"); - if (!DAC960_ExecuteType3(Controller, DAC960_GetLogicalDriveInformation, - &Controller->LogicalDriveInformation[0])) + if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_GetLogicalDriveInformation, + &Controller->V1.LogicalDriveInformation)) return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION"); for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++) - for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) - if (!DAC960_ExecuteType3D(Controller, DAC960_GetDeviceState, - Channel, TargetID, - &Controller->DeviceState[0][Channel][TargetID])) + for (TargetID = 0; TargetID < Enquiry2.MaxTargets; TargetID++) + if (!DAC960_V1_ExecuteType3D(Controller, DAC960_V1_GetDeviceState, + Channel, TargetID, + &Controller->V1.DeviceState + [Channel][TargetID])) return DAC960_Failure(Controller, "GET DEVICE STATE"); /* Initialize the Controller Model Name and Full Model Name fields. */ switch (Enquiry2.HardwareID.SubModel) { - case DAC960_P_PD_PU: - if (Enquiry2.SCSICapability.BusSpeed == DAC960_Ultra) + 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_PL: + case DAC960_V1_PL: strcpy(Controller->ModelName, "DAC960PL"); break; - case DAC960_PG: + case DAC960_V1_PG: strcpy(Controller->ModelName, "DAC960PG"); break; - case DAC960_PJ: + case DAC960_V1_PJ: strcpy(Controller->ModelName, "DAC960PJ"); break; - case DAC960_PR: + case DAC960_V1_PR: strcpy(Controller->ModelName, "DAC960PR"); break; - case DAC960_PT: + case DAC960_V1_PT: strcpy(Controller->ModelName, "DAC960PT"); break; - case DAC960_PTL0: + case DAC960_V1_PTL0: strcpy(Controller->ModelName, "DAC960PTL0"); break; - case DAC960_PRL: + case DAC960_V1_PRL: strcpy(Controller->ModelName, "DAC960PRL"); break; - case DAC960_PTL1: + case DAC960_V1_PTL1: strcpy(Controller->ModelName, "DAC960PTL1"); break; - case DAC1164_P: + case DAC960_V1_1164P: strcpy(Controller->ModelName, "DAC1164P"); break; default: @@ -813,61 +1075,197 @@ static boolean DAC960_ReadControllerConfiguration(DAC960_Controller_T return false; } /* - Initialize the Controller Channels, Memory Size, and SAF-TE Enclosure - Management Enabled fields. + 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->SAFTE_EnclosureManagementEnabled = - Enquiry2.FaultManagementType == DAC960_SAFTE; + Controller->V1.SAFTE_EnclosureManagementEnabled = + (Enquiry2.FaultManagementType == DAC960_V1_SAFTE); /* Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive - Count, Maximum Blocks per Command, and Maximum Scatter/Gather Segments. - The Driver Queue Depth must be at most one less than the Controller Queue - Depth to allow for an automatic drive rebuild operation. + 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->Enquiry[0].MaxCommands; + Controller->ControllerQueueDepth = Controller->V1.Enquiry.MaxCommands; Controller->DriverQueueDepth = Controller->ControllerQueueDepth - 1; - Controller->LogicalDriveCount = Controller->Enquiry[0].NumberOfLogicalDrives; + if (Controller->DriverQueueDepth > DAC960_MaxDriverQueueDepth) + Controller->DriverQueueDepth = DAC960_MaxDriverQueueDepth; + Controller->LogicalDriveCount = + Controller->V1.Enquiry.NumberOfLogicalDrives; Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand; - Controller->MaxScatterGatherSegments = Enquiry2.MaxScatterGatherEntries; + 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->StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor - >> (10 - DAC960_BlockSizeBits); - Controller->SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor - >> (10 - DAC960_BlockSizeBits); + 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_Geometry_128_32: - Controller->GeometryTranslationHeads = 128; - Controller->GeometryTranslationSectors = 32; + case DAC960_V1_Geometry_128_32: + Controller->V1.GeometryTranslationHeads = 128; + Controller->V1.GeometryTranslationSectors = 32; break; - case DAC960_Geometry_255_63: - Controller->GeometryTranslationHeads = 255; - Controller->GeometryTranslationSectors = 63; + case DAC960_V1_Geometry_255_63: + Controller->V1.GeometryTranslationHeads = 255; + Controller->V1.GeometryTranslationSectors = 63; break; default: return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY"); } /* - Initialize the Logical Drive Initial State. + Initialize the Logical Drive Initially Accessible flag. */ for (LogicalDriveNumber = 0; LogicalDriveNumber < Controller->LogicalDriveCount; LogicalDriveNumber++) - Controller->LogicalDriveInitialState[LogicalDriveNumber] = - Controller->LogicalDriveInformation[0] - [LogicalDriveNumber].LogicalDriveState; - Controller->LastRebuildStatus = DAC960_NoRebuildOrCheckInProgress; + if (Controller->V1.LogicalDriveInformation + [LogicalDriveNumber].LogicalDriveState != + DAC960_V1_LogicalDrive_Offline) + Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true; + Controller->V1.LastRebuildStatus = DAC960_V1_NoRebuildOrCheckInProgress; return true; } /* - DAC960_ReportControllerConfiguration reports the Configuration Information of - Controller. + 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; + if (!DAC960_V2_ControllerInfo(Controller, DAC960_V2_GetControllerInfo, + ControllerInfo, + sizeof(DAC960_V2_ControllerInfo_T))) + return DAC960_Failure(Controller, "GET CONTROLLER INFO"); + if (!DAC960_V2_GeneralInfo(Controller, DAC960_V2_GetHealthStatus, + Controller->V2.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T))) + 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_LogicalDeviceInfo(Controller, + DAC960_V2_GetLogicalDeviceInfoValid, + LogicalDeviceNumber, + NewLogicalDeviceInfo, + sizeof(DAC960_V2_LogicalDeviceInfo_T))) + break; + LogicalDeviceNumber = NewLogicalDeviceInfo->LogicalDeviceNumber; + if (LogicalDeviceNumber > DAC960_MaxLogicalDrives) + panic("DAC960: Logical Drive Number %d not supported\n", + LogicalDeviceNumber); + if (NewLogicalDeviceInfo->DeviceBlockSizeInBytes != DAC960_BlockSize) + panic("DAC960: Logical Drive Block Size %d not supported\n", + NewLogicalDeviceInfo->DeviceBlockSizeInBytes); + 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 @@ -893,54 +1291,60 @@ static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T Controller, Controller->ControllerQueueDepth, Controller->MaxBlocksPerCommand); DAC960_Info(" Driver Queue Depth: %d, " - "Maximum Scatter/Gather Segments: %d\n", + "Scatter/Gather Limit: %d of %d Segments\n", Controller, Controller->DriverQueueDepth, - Controller->MaxScatterGatherSegments); - DAC960_Info(" Stripe Size: %dKB, Segment Size: %dKB, " - "BIOS Geometry: %d/%d\n", Controller, - Controller->StripeSize, - Controller->SegmentSize, - Controller->GeometryTranslationHeads, - Controller->GeometryTranslationSectors); - if (Controller->SAFTE_EnclosureManagementEnabled) - DAC960_Info(" SAF-TE Enclosure Management Enabled\n", Controller); + 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_ReadDeviceConfiguration reads the Device Configuration Information by - requesting the SCSI Inquiry and SCSI Inquiry Unit Serial Number information - for each device connected to Controller. + 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_ReadDeviceConfiguration(DAC960_Controller_T *Controller) +static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T + *Controller) { - DAC960_DCDB_T DCDBs[DAC960_MaxChannels], *DCDB; - Semaphore_T Semaphores[DAC960_MaxChannels], *Semaphore; + DAC960_V1_DCDB_T DCDBs[DAC960_V1_MaxChannels], *DCDB; + Semaphore_T Semaphores[DAC960_V1_MaxChannels], *Semaphore; unsigned long ProcessorFlags; int Channel, TargetID; - for (TargetID = 0; TargetID < DAC960_MaxTargets; TargetID++) + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { for (Channel = 0; Channel < Controller->Channels; Channel++) { - DAC960_Command_T *Command = &Controller->Commands[Channel]; + DAC960_Command_T *Command = Controller->Commands[Channel]; DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->InquiryStandardData[Channel][TargetID]; + &Controller->V1.InquiryStandardData[Channel][TargetID]; InquiryStandardData->PeripheralDeviceType = 0x1F; Semaphore = &Semaphores[Channel]; init_MUTEX_LOCKED(Semaphore); DCDB = &DCDBs[Channel]; - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; Command->Semaphore = Semaphore; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB; - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; + Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); DCDB->Channel = Channel; DCDB->TargetID = TargetID; - DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem; + DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; DCDB->EarlyStatus = false; - DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds; + DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds; DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); @@ -960,13 +1364,14 @@ static boolean DAC960_ReadDeviceConfiguration(DAC960_Controller_T *Controller) } for (Channel = 0; Channel < Controller->Channels; Channel++) { - DAC960_Command_T *Command = &Controller->Commands[Channel]; + DAC960_Command_T *Command = Controller->Commands[Channel]; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->InquiryUnitSerialNumber[Channel][TargetID]; + &Controller->V1.InquiryUnitSerialNumber[Channel][TargetID]; InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; Semaphore = &Semaphores[Channel]; down(Semaphore); - if (Command->CommandStatus != DAC960_NormalCompletion) continue; + if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) + continue; Command->Semaphore = Semaphore; DCDB = &DCDBs[Channel]; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); @@ -984,107 +1389,215 @@ static boolean DAC960_ReadDeviceConfiguration(DAC960_Controller_T *Controller) down(Semaphore); } } - return true; + 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 *InquiryUnitSerialNumber; + DAC960_Command_T *Command; + DAC960_V2_CommandMailbox_T *CommandMailbox; + if (!DAC960_V2_PhysicalDeviceInfo(Controller, + DAC960_V2_GetPhysicalDeviceInfoValid, + Channel, + TargetID, + LogicalUnit, + NewPhysicalDeviceInfo, + sizeof(DAC960_V2_PhysicalDeviceInfo_T))) + break; + Channel = NewPhysicalDeviceInfo->Channel; + TargetID = NewPhysicalDeviceInfo->TargetID; + LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit; + 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) + return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION"); + Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex] = + InquiryUnitSerialNumber; + memset(InquiryUnitSerialNumber, 0, + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T)); + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + Command = DAC960_AllocateCommand(Controller); + CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_ImmediateCommand; + 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 = + Virtual_to_Bus(InquiryUnitSerialNumber); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + DAC960_ExecuteCommand(Command); + DAC960_DeallocateCommand(Command); + 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_ReportDeviceConfiguration reports the Device Configuration Information - of Controller. + DAC960_V1_ReportDeviceConfiguration reports the Device Configuration + Information for DAC960 V1 Firmware Controllers. */ -static boolean DAC960_ReportDeviceConfiguration(DAC960_Controller_T *Controller) +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 < DAC960_MaxTargets; TargetID++) + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->InquiryStandardData[Channel][TargetID]; + &Controller->V1.InquiryStandardData[Channel][TargetID]; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->InquiryUnitSerialNumber[Channel][TargetID]; - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; - DAC960_ErrorTable_T *ErrorTable = - &Controller->ErrorTable[Controller->ErrorTableIndex]; - DAC960_ErrorTableEntry_T *ErrorEntry = - &ErrorTable->ErrorTableEntries[Channel][TargetID]; + &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)]; - int i; if (InquiryStandardData->PeripheralDeviceType == 0x1F) continue; - for (i = 0; i < sizeof(Vendor)-1; i++) - { - unsigned char VendorCharacter = - InquiryStandardData->VendorIdentification[i]; - Vendor[i] = (VendorCharacter >= ' ' && VendorCharacter <= '~' - ? VendorCharacter : ' '); - } - Vendor[sizeof(Vendor)-1] = '\0'; - for (i = 0; i < sizeof(Model)-1; i++) - { - unsigned char ModelCharacter = - InquiryStandardData->ProductIdentification[i]; - Model[i] = (ModelCharacter >= ' ' && ModelCharacter <= '~' - ? ModelCharacter : ' '); - } - Model[sizeof(Model)-1] = '\0'; - for (i = 0; i < sizeof(Revision)-1; i++) - { - unsigned char RevisionCharacter = - InquiryStandardData->ProductRevisionLevel[i]; - Revision[i] = (RevisionCharacter >= ' ' && RevisionCharacter <= '~' - ? RevisionCharacter : ' '); - } - Revision[sizeof(Revision)-1] = '\0'; + 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) { - int 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_Info(" Serial Number: %s\n", - Controller, SerialNumber); - } - if (DeviceState->Present && DeviceState->DeviceType == DAC960_DiskType) - { - if (Controller->DeviceResetCount[Channel][TargetID] > 0) + if (Controller->V1.DeviceResetCount[Channel][TargetID] > 0) DAC960_Info(" Disk Status: %s, %d blocks, %d resets\n", Controller, - (DeviceState->DeviceState == DAC960_Device_Dead + (DeviceState->DeviceState == DAC960_V1_Device_Dead ? "Dead" - : DeviceState->DeviceState == DAC960_Device_WriteOnly - ? "Write-Only" - : DeviceState->DeviceState == DAC960_Device_Online - ? "Online" : "Standby"), + : DeviceState->DeviceState + == DAC960_V1_Device_WriteOnly + ? "Write-Only" + : DeviceState->DeviceState + == DAC960_V1_Device_Online + ? "Online" : "Standby"), DeviceState->DiskSize, - Controller->DeviceResetCount[Channel][TargetID]); + Controller->V1.DeviceResetCount[Channel][TargetID]); else DAC960_Info(" Disk Status: %s, %d blocks\n", Controller, - (DeviceState->DeviceState == DAC960_Device_Dead + (DeviceState->DeviceState == DAC960_V1_Device_Dead ? "Dead" - : DeviceState->DeviceState == DAC960_Device_WriteOnly - ? "Write-Only" - : DeviceState->DeviceState == DAC960_Device_Online - ? "Online" : "Standby"), + : DeviceState->DeviceState + == DAC960_V1_Device_WriteOnly + ? "Write-Only" + : DeviceState->DeviceState + == DAC960_V1_Device_Online + ? "Online" : "Standby"), DeviceState->DiskSize); } if (ErrorEntry->ParityErrorCount > 0 || @@ -1103,17 +1616,16 @@ static boolean DAC960_ReportDeviceConfiguration(DAC960_Controller_T *Controller) LogicalDriveNumber < Controller->LogicalDriveCount; LogicalDriveNumber++) { - DAC960_LogicalDriveInformation_T *LogicalDriveInformation = - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex][LogicalDriveNumber]; + DAC960_V1_LogicalDriveInformation_T *LogicalDriveInformation = + &Controller->V1.LogicalDriveInformation[LogicalDriveNumber]; DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks, %s\n", Controller, Controller->ControllerNumber, LogicalDriveNumber, LogicalDriveInformation->RAIDLevel, - (LogicalDriveInformation->LogicalDriveState == - DAC960_LogicalDrive_Online + (LogicalDriveInformation->LogicalDriveState + == DAC960_V1_LogicalDrive_Online ? "Online" - : LogicalDriveInformation->LogicalDriveState == - DAC960_LogicalDrive_Critical + : LogicalDriveInformation->LogicalDriveState + == DAC960_V1_LogicalDrive_Critical ? "Critical" : "Offline"), LogicalDriveInformation->LogicalDriveSize, (LogicalDriveInformation->WriteBack @@ -1123,69 +1635,256 @@ static boolean DAC960_ReportDeviceConfiguration(DAC960_Controller_T *Controller) } -static inline int DAC_new_segment(request_queue_t *q, struct request *req, - int __max_segments) -{ - int max_segments; - DAC960_Controller_T * Controller = q->queuedata; - - max_segments = Controller->MaxSegmentsPerRequest[MINOR(req->rq_dev)]; - if (__max_segments < max_segments) - max_segments = __max_segments; +/* + DAC960_V2_ReportDeviceConfiguration reports the Device Configuration + Information for DAC960 V2 Firmware Controllers. +*/ - if (req->nr_segments < max_segments) { - req->nr_segments++; - q->elevator.nr_segments++; - return 1; +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 == 16 + ? 2 : 1))); + 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, %d blocks\n", Controller, + (PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Online + ? "Online" + : PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_WriteOnly + ? "Write-Only" + : PhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Dead + ? "Dead" : "Standby"), + PhysicalDeviceInfo + ->ConfigurableDeviceSizeIn512ByteBlocksOrMB); + 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; } - return 0; -} + DAC960_Info(" /dev/rd/c%dd%d: RAID-%d, %s, %d blocks\n", + Controller, Controller->ControllerNumber, LogicalDriveNumber, + LogicalDeviceInfo->RAIDLevel, + (LogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Online + ? "Online" + : LogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Critical + ? "Critical" : "Offline"), + LogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB); + 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); -static int DAC_back_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int __max_segments) -{ - if (req->bhtail->b_data + req->bhtail->b_size == bh->b_data) - return 1; - return DAC_new_segment(q, req, __max_segments); + } + return true; } -static int DAC_front_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int __max_segments) + +/* + DAC960_BackMergeFunction is the Back Merge Function for the DAC960 driver. +*/ + +static int DAC960_BackMergeFunction(RequestQueue_T *RequestQueue, + IO_Request_T *Request, + BufferHeader_T *BufferHeader, + int MaxSegments) { - if (bh->b_data + bh->b_size == req->bh->b_data) - return 1; - return DAC_new_segment(q, req, __max_segments); + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; + if (Request->bhtail->b_data + Request->bhtail->b_size == BufferHeader->b_data) + return true; + if (Request->nr_segments < MaxSegments && + Request->nr_segments < Controller->DriverScatterGatherLimit) + { + Request->nr_segments++; + RequestQueue->elevator.nr_segments++; + return true; + } + return false; } -static int DAC_merge_requests_fn(request_queue_t *q, - struct request *req, - struct request *next, - int __max_segments) + +/* + DAC960_FrontMergeFunction is the Front Merge Function for the DAC960 driver. +*/ + +static int DAC960_FrontMergeFunction(RequestQueue_T *RequestQueue, + IO_Request_T *Request, + BufferHeader_T *BufferHeader, + int MaxSegments) { - int max_segments; - DAC960_Controller_T * Controller = q->queuedata; - int total_segments = req->nr_segments + next->nr_segments; - int same_segment; + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; + if (BufferHeader->b_data + BufferHeader->b_size == Request->bh->b_data) + return true; + if (Request->nr_segments < MaxSegments && + Request->nr_segments < Controller->DriverScatterGatherLimit) + { + Request->nr_segments++; + RequestQueue->elevator.nr_segments++; + return true; + } + return false; +} - max_segments = Controller->MaxSegmentsPerRequest[MINOR(req->rq_dev)]; - if (__max_segments < max_segments) - max_segments = __max_segments; - same_segment = 0; - if (req->bhtail->b_data + req->bhtail->b_size == next->bh->b_data) - { - total_segments--; - same_segment = 1; - } - - if (total_segments > max_segments) - return 0; +/* + DAC960_MergeRequestsFunction is the Merge Requests Function for the + DAC960 driver. +*/ - q->elevator.nr_segments -= same_segment; - req->nr_segments = total_segments; - return 1; +static int DAC960_MergeRequestsFunction(RequestQueue_T *RequestQueue, + IO_Request_T *Request, + IO_Request_T *NextRequest, + int MaxSegments) +{ + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; + int TotalSegments = Request->nr_segments + NextRequest->nr_segments; + int SameSegment = 0; + if (Request->bhtail->b_data + Request->bhtail->b_size + == NextRequest->bh->b_data) + { + TotalSegments--; + SameSegment = 1; + } + if (TotalSegments > MaxSegments || + TotalSegments > Controller->DriverScatterGatherLimit) + return false; + RequestQueue->elevator.nr_segments -= SameSegment; + Request->nr_segments = TotalSegments; + return true; } + /* DAC960_RegisterBlockDevice registers the Block Device structures associated with Controller. @@ -1193,47 +1892,40 @@ static int DAC_merge_requests_fn(request_queue_t *q, static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) { - request_queue_t * q; - - static void (*RequestFunctions[DAC960_MaxControllers])(request_queue_t *) = - { DAC960_RequestFunction0, DAC960_RequestFunction1, - DAC960_RequestFunction2, DAC960_RequestFunction3, - DAC960_RequestFunction4, DAC960_RequestFunction5, - DAC960_RequestFunction6, DAC960_RequestFunction7 }; int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber; GenericDiskInfo_T *GenericDiskInfo; + RequestQueue_T *RequestQueue; int MinorNumber; /* Register the Block Device Major Number for this DAC960 Controller. */ - if (devfs_register_blkdev(MajorNumber, "dac960", &DAC960_FileOperations) < 0) + if (devfs_register_blkdev(MajorNumber, "dac960", + &DAC960_BlockDeviceOperations) < 0) { DAC960_Error("UNABLE TO ACQUIRE MAJOR NUMBER %d - DETACHING\n", Controller, MajorNumber); return false; } /* - Initialize the I/O Request Function. + Initialize the I/O Request Queue. */ - q = BLK_DEFAULT_QUEUE(MajorNumber); - blk_init_queue(q, RequestFunctions[Controller->ControllerNumber]); - blk_queue_headactive(q, 0); - q->back_merge_fn = DAC_back_merge_fn; - q->front_merge_fn = DAC_front_merge_fn; - q->merge_requests_fn = DAC_merge_requests_fn; - q->queuedata = (void *) Controller; - + RequestQueue = BLK_DEFAULT_QUEUE(MajorNumber); + blk_init_queue(RequestQueue, DAC960_RequestFunction); + blk_queue_headactive(RequestQueue, 0); + RequestQueue->back_merge_fn = DAC960_BackMergeFunction; + RequestQueue->front_merge_fn = DAC960_FrontMergeFunction; + RequestQueue->merge_requests_fn = DAC960_MergeRequestsFunction; + RequestQueue->queuedata = Controller; + Controller->RequestQueue = RequestQueue; /* Initialize the Disk Partitions array, Partition Sizes array, Block Sizes - array, Max Sectors per Request array, and Max Segments per Request array. + array, and Max Sectors per Request array. */ for (MinorNumber = 0; MinorNumber < DAC960_MinorCount; MinorNumber++) { Controller->BlockSizes[MinorNumber] = BLOCK_SIZE; Controller->MaxSectorsPerRequest[MinorNumber] = Controller->MaxBlocksPerCommand; - Controller->MaxSegmentsPerRequest[MinorNumber] = - Controller->MaxScatterGatherSegments; } Controller->GenericDiskInfo.part = Controller->DiskPartitions; Controller->GenericDiskInfo.sizes = Controller->PartitionSizes; @@ -1247,13 +1939,12 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller) Complete initialization of the Generic Disk Information structure. */ Controller->GenericDiskInfo.major = MajorNumber; - Controller->GenericDiskInfo.major_name = "dac960"; + Controller->GenericDiskInfo.major_name = "rd"; Controller->GenericDiskInfo.minor_shift = DAC960_MaxPartitionsBits; Controller->GenericDiskInfo.max_p = DAC960_MaxPartitions; Controller->GenericDiskInfo.nr_real = Controller->LogicalDriveCount; - Controller->GenericDiskInfo.real_devices = Controller; Controller->GenericDiskInfo.next = NULL; - Controller->GenericDiskInfo.fops = &DAC960_FileOperations; + Controller->GenericDiskInfo.fops = &DAC960_BlockDeviceOperations; /* Install the Generic Disk Information structure at the end of the list. */ @@ -1284,7 +1975,7 @@ static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller) */ devfs_unregister_blkdev(MajorNumber, "dac960"); /* - Remove the I/O Request Function. + Remove the I/O Request Queue. */ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MajorNumber)); /* @@ -1313,6 +2004,463 @@ static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller) /* + DAC960_RegisterDisk registers the DAC960 Logical Disk Device for Logical + Drive Number if it exists. +*/ + +static void DAC960_RegisterDisk(DAC960_Controller_T *Controller, + int LogicalDriveNumber) +{ + if (Controller->FirmwareType == DAC960_V1_Controller) + { + if (LogicalDriveNumber > Controller->LogicalDriveCount - 1) return; + register_disk(&Controller->GenericDiskInfo, + DAC960_KernelDevice(Controller->ControllerNumber, + LogicalDriveNumber, 0), + DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, + Controller->V1.LogicalDriveInformation + [LogicalDriveNumber].LogicalDriveSize); + } + else + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + if (LogicalDeviceInfo == NULL) return; + register_disk(&Controller->GenericDiskInfo, + DAC960_KernelDevice(Controller->ControllerNumber, + LogicalDriveNumber, 0), + DAC960_MaxPartitions, &DAC960_BlockDeviceOperations, + LogicalDeviceInfo + ->ConfigurableDeviceSizeIn512ByteBlocksOrMB); + } +} + + +/* + 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_DetectControllers detects Mylex DAC960/AcceleRAID/eXtremeRAID + PCI RAID Controllers by interrogating the PCI Configuration Space for + Controller Type. +*/ + +static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType) +{ + void (*InterruptHandler)(int, void *, Registers_T *) = NULL; + DAC960_FirmwareType_T FirmwareType = 0; + unsigned short VendorID = 0, DeviceID = 0; + unsigned int MemoryWindowSize = 0; + PCI_Device_T *PCI_Device = NULL; + switch (HardwareType) + { + case DAC960_BA_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_BA; + FirmwareType = DAC960_V2_Controller; + InterruptHandler = DAC960_BA_InterruptHandler; + MemoryWindowSize = DAC960_BA_RegisterWindowSize; + break; + case DAC960_LP_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_LP; + FirmwareType = DAC960_LP_Controller; + InterruptHandler = DAC960_LP_InterruptHandler; + MemoryWindowSize = DAC960_LP_RegisterWindowSize; + break; + case DAC960_LA_Controller: + VendorID = PCI_VENDOR_ID_DEC; + DeviceID = PCI_DEVICE_ID_DEC_21285; + FirmwareType = DAC960_V1_Controller; + InterruptHandler = DAC960_LA_InterruptHandler; + MemoryWindowSize = DAC960_LA_RegisterWindowSize; + break; + case DAC960_PG_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PG; + FirmwareType = DAC960_V1_Controller; + InterruptHandler = DAC960_PG_InterruptHandler; + MemoryWindowSize = DAC960_PG_RegisterWindowSize; + break; + case DAC960_PD_Controller: + VendorID = PCI_VENDOR_ID_MYLEX; + DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PD; + FirmwareType = DAC960_V1_Controller; + InterruptHandler = DAC960_PD_InterruptHandler; + MemoryWindowSize = DAC960_PD_RegisterWindowSize; + break; + } + while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL) + { + DAC960_Controller_T *Controller = NULL; + DAC960_IO_Address_T IO_Address = 0; + DAC960_PCI_Address_T PCI_Address = 0; + unsigned char Bus = PCI_Device->bus->number; + unsigned char DeviceFunction = PCI_Device->devfn; + unsigned char Device = DeviceFunction >> 3; + unsigned char Function = DeviceFunction & 0x7; + unsigned char ErrorStatus, Parameter0, Parameter1; + unsigned int IRQ_Channel = PCI_Device->irq; + void *BaseAddress; + if (pci_enable_device(PCI_Device) != 0) continue; + switch (HardwareType) + { + case DAC960_BA_Controller: + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_LP_Controller: + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_LA_Controller: + if (!(PCI_Device->subsystem_vendor == PCI_VENDOR_ID_MYLEX && + PCI_Device->subsystem_device == PCI_DEVICE_ID_MYLEX_DAC960_LA)) + continue; + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_PG_Controller: + PCI_Address = pci_resource_start(PCI_Device, 0); + break; + case DAC960_PD_Controller: + IO_Address = pci_resource_start(PCI_Device, 0); + PCI_Address = pci_resource_start(PCI_Device, 1); + break; + } + if (DAC960_ControllerCount == DAC960_MaxControllers) + { + DAC960_Error("More than %d DAC960 Controllers detected - " + "ignoring from Controller at\n", + NULL, DAC960_MaxControllers); + goto Failure; + } + 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); + goto Failure; + } + memset(Controller, 0, sizeof(DAC960_Controller_T)); + Controller->ControllerNumber = DAC960_ControllerCount; + init_waitqueue_head(&Controller->CommandWaitQueue); + init_waitqueue_head(&Controller->HealthStatusWaitQueue); + DAC960_Controllers[DAC960_ControllerCount++] = Controller; + DAC960_AnnounceDriver(Controller); + Controller->FirmwareType = FirmwareType; + Controller->HardwareType = HardwareType; + Controller->IO_Address = IO_Address; + Controller->PCI_Address = PCI_Address; + Controller->Bus = Bus; + Controller->Device = Device; + Controller->Function = Function; + sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber); + /* + Map the Controller Register Window. + */ + if (MemoryWindowSize < PAGE_SIZE) + MemoryWindowSize = PAGE_SIZE; + Controller->MemoryMappedAddress = + ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize); + Controller->BaseAddress = + Controller->MemoryMappedAddress + (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 (HardwareType) + { + case DAC960_BA_Controller: + DAC960_BA_DisableInterrupts(Controller->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(Controller->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(Controller->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(Controller->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(Controller->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(Controller->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(Controller->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(Controller->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: + request_region(Controller->IO_Address, 0x80, + Controller->FullModelName); + 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); + } + DAC960_PD_EnableInterrupts(Controller->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; + } + /* + Acquire shared access to the IRQ Channel. + */ + if (IRQ_Channel == 0) + { + DAC960_Error("IRQ Channel %d illegal for Controller at\n", + Controller, IRQ_Channel); + goto Failure; + } + strcpy(Controller->FullModelName, "DAC960"); + 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, IRQ_Channel); + goto Failure; + } + Controller->IRQ_Channel = IRQ_Channel; + DAC960_ActiveControllerCount++; + Controller->InitialCommand.CommandIdentifier = 1; + Controller->InitialCommand.Controller = Controller; + Controller->Commands[0] = &Controller->InitialCommand; + Controller->FreeCommands = &Controller->InitialCommand; + Controller->ControllerDetectionSuccessful = true; + continue; + Failure: + if (IO_Address == 0) + DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A " + "PCI Address 0x%X\n", Controller, + Bus, Device, Function, PCI_Address); + else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " + "0x%X PCI Address 0x%X\n", Controller, + Bus, Device, Function, IO_Address, PCI_Address); + if (Controller == NULL) break; + if (Controller->MemoryMappedAddress != NULL) + iounmap(Controller->MemoryMappedAddress); + if (Controller->IRQ_Channel > 0) + free_irq(IRQ_Channel, Controller); + } +} + + +/* + DAC960_SortControllers sorts the Controllers by PCI Bus and Device Number. +*/ + +static void DAC960_SortControllers(void) +{ + int ControllerNumber, LastInterchange, Bound, j; + LastInterchange = DAC960_ControllerCount-1; + while (LastInterchange > 0) + { + Bound = LastInterchange; + LastInterchange = 0; + for (j = 0; j < Bound; j++) + { + DAC960_Controller_T *Controller1 = DAC960_Controllers[j]; + DAC960_Controller_T *Controller2 = DAC960_Controllers[j+1]; + if (Controller1->Bus > Controller2->Bus || + (Controller1->Bus == Controller2->Bus && + (Controller1->Device > Controller2->Device))) + { + Controller2->ControllerNumber = j; + DAC960_Controllers[j] = Controller2; + Controller1->ControllerNumber = j+1; + DAC960_Controllers[j+1] = Controller1; + LastInterchange = j; + } + } + } + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + if (!Controller->ControllerDetectionSuccessful) + { + DAC960_Controllers[ControllerNumber] = NULL; + kfree(Controller); + } + } +} + + +/* DAC960_InitializeController initializes Controller. */ @@ -1320,25 +2468,12 @@ static void 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 Command structures. - */ - DAC960_Command_T *Commands = Controller->Commands; - int CommandIdentifier; - Controller->FreeCommands = NULL; - for (CommandIdentifier = 0; - CommandIdentifier < Controller->DriverQueueDepth; - CommandIdentifier++) - { - Commands[CommandIdentifier].Controller = Controller; - Commands[CommandIdentifier].Next = Controller->FreeCommands; - Controller->FreeCommands = &Commands[CommandIdentifier]; - } - /* Initialize the Monitoring Timer. */ init_timer(&Controller->MonitoringTimer); @@ -1348,7 +2483,6 @@ static void DAC960_InitializeController(DAC960_Controller_T *Controller) Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction; add_timer(&Controller->MonitoringTimer); Controller->ControllerInitialized = true; - DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); } else DAC960_FinalizeController(Controller); } @@ -1363,28 +2497,46 @@ static void DAC960_FinalizeController(DAC960_Controller_T *Controller) if (Controller->ControllerInitialized) { del_timer(&Controller->MonitoringTimer); - DAC960_Notice("Flushing Cache...", Controller); - DAC960_ExecuteType3(Controller, DAC960_Flush, NULL); - DAC960_Notice("done\n", Controller); - switch (Controller->ControllerType) - { - case DAC960_V5_Controller: - if (!Controller->DualModeMemoryMailboxInterface) - DAC960_V5_SaveMemoryMailboxInfo(Controller); - break; - case DAC960_V4_Controller: - if (!Controller->DualModeMemoryMailboxInterface) - DAC960_V4_SaveMemoryMailboxInfo(Controller); - break; - case DAC960_V3_Controller: - break; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + DAC960_Notice("Flushing Cache...", Controller); + DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, NULL); + DAC960_Notice("done\n", Controller); + switch (Controller->HardwareType) + { + case DAC960_LA_Controller: + if (Controller->V1.DualModeMemoryMailboxInterface) + free_pages(Controller->MemoryMailboxPagesAddress, + Controller->MemoryMailboxPagesOrder); + else DAC960_LA_SaveMemoryMailboxInfo(Controller); + break; + case DAC960_PG_Controller: + if (Controller->V1.DualModeMemoryMailboxInterface) + free_pages(Controller->MemoryMailboxPagesAddress, + Controller->MemoryMailboxPagesOrder); + else DAC960_PG_SaveMemoryMailboxInfo(Controller); + break; + case DAC960_PD_Controller: + release_region(Controller->IO_Address, 0x80); + break; + default: + break; + } + } + else + { + DAC960_Notice("Flushing Cache...", Controller); + DAC960_V2_DeviceOperation(Controller, DAC960_V2_PauseDevice, + DAC960_V2_RAID_Controller); + DAC960_Notice("done\n", Controller); + free_pages(Controller->MemoryMailboxPagesAddress, + Controller->MemoryMailboxPagesOrder); } } free_irq(Controller->IRQ_Channel, Controller); iounmap(Controller->MemoryMappedAddress); - if (Controller->IO_Address > 0) - release_region(Controller->IO_Address, 0x80); DAC960_UnregisterBlockDevice(Controller); + DAC960_DestroyAuxiliaryStructures(Controller); DAC960_Controllers[Controller->ControllerNumber] = NULL; kfree(Controller); } @@ -1397,15 +2549,26 @@ static void DAC960_FinalizeController(DAC960_Controller_T *Controller) void DAC960_Initialize(void) { int ControllerNumber; - DAC960_DetectControllers(DAC960_V5_Controller); - DAC960_DetectControllers(DAC960_V4_Controller); - DAC960_DetectControllers(DAC960_V3_Controller); + DAC960_DetectControllers(DAC960_BA_Controller); + DAC960_DetectControllers(DAC960_LP_Controller); + DAC960_DetectControllers(DAC960_LA_Controller); + DAC960_DetectControllers(DAC960_PG_Controller); + DAC960_DetectControllers(DAC960_PD_Controller); + DAC960_SortControllers(); if (DAC960_ActiveControllerCount == 0) return; for (ControllerNumber = 0; ControllerNumber < DAC960_ControllerCount; ControllerNumber++) - if (DAC960_Controllers[ControllerNumber] != NULL) - DAC960_InitializeController(DAC960_Controllers[ControllerNumber]); + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + int LogicalDriveNumber; + if (Controller == NULL) continue; + DAC960_InitializeController(Controller); + for (LogicalDriveNumber = 0; + LogicalDriveNumber < DAC960_MaxLogicalDrives; + LogicalDriveNumber++) + DAC960_RegisterDisk(Controller, LogicalDriveNumber); + } DAC960_CreateProcEntries(); register_reboot_notifier(&DAC960_NotifierBlock); } @@ -1435,69 +2598,38 @@ static int DAC960_Finalize(NotifierBlock_T *NotifierBlock, /* - 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. + DAC960_V1_QueueReadWriteCommand prepares and queues a Read/Write Command for + DAC960 V1 Firmware Controllers. */ -static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, - boolean WaitForCommand) +static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *Command) { - struct list_head * queue_head; - IO_Request_T *Request; - DAC960_Command_T *Command; - char *RequestBuffer; - - queue_head = &blk_dev[DAC960_MAJOR + Controller->ControllerNumber].request_queue.queue_head; - while (true) - { - if (list_empty(queue_head)) return false; - Request = blkdev_entry_next_request(queue_head); - if (Request->rq_status == RQ_INACTIVE) return false; - Command = DAC960_AllocateCommand(Controller); - if (Command != NULL) break; - if (!WaitForCommand) return false; - DAC960_WaitForCommand(Controller); - } - DAC960_ClearCommand(Command); - if (Request->cmd == READ) - Command->CommandType = DAC960_ReadCommand; - else Command->CommandType = DAC960_WriteCommand; - Command->Semaphore = Request->sem; - Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev); - Command->BlockNumber = - Request->sector - + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect; - Command->BlockCount = Request->nr_sectors; - Command->SegmentCount = Request->nr_segments; - Command->BufferHeader = Request->bh; - RequestBuffer = Request->buffer; - blkdev_dequeue_request(Request); - blkdev_release_request(Request); + DAC960_Controller_T *Controller = Command->Controller; + DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox; + DAC960_V1_ClearCommand(Command); if (Command->SegmentCount == 1) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; if (Command->CommandType == DAC960_ReadCommand) - CommandMailbox->Type5.CommandOpcode = DAC960_Read; - else CommandMailbox->Type5.CommandOpcode = DAC960_Write; + 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 = Virtual_to_Bus(RequestBuffer); + CommandMailbox->Type5.BusAddress = Virtual_to_Bus(Command->RequestBuffer); } else { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - DAC960_ScatterGatherSegment_T - *ScatterGatherList = Command->ScatterGatherList; + DAC960_V1_ScatterGatherSegment_T + *ScatterGatherList = Command->V1.ScatterGatherList; BufferHeader_T *BufferHeader = Command->BufferHeader; char *LastDataEndPointer = NULL; int SegmentNumber = 0; if (Command->CommandType == DAC960_ReadCommand) - CommandMailbox->Type5.CommandOpcode = DAC960_ReadWithOldScatterGather; + CommandMailbox->Type5.CommandOpcode = + DAC960_V1_ReadWithOldScatterGather; else - CommandMailbox->Type5.CommandOpcode = DAC960_WriteWithOldScatterGather; + CommandMailbox->Type5.CommandOpcode = + DAC960_V1_WriteWithOldScatterGather; CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber; CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber; @@ -1518,7 +2650,7 @@ static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, ScatterGatherList[SegmentNumber].SegmentByteCount = BufferHeader->b_size; LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size; - if (SegmentNumber++ > Controller->MaxScatterGatherSegments) + if (SegmentNumber++ > Controller->DriverScatterGatherLimit) panic("DAC960: Scatter/Gather Segment Overflow\n"); } BufferHeader = BufferHeader->b_reqnext; @@ -1527,167 +2659,163 @@ static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, panic("DAC960: SegmentNumber != SegmentCount\n"); } DAC960_QueueCommand(Command); - return true; -} - - -/* - DAC960_ProcessRequests attempts to remove as many I/O Requests as possible - from Controller's I/O Request Queue and queue them to the Controller. -*/ - -static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller) -{ - int Counter = 0; - while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ; -} - - -/* - DAC960_RequestFunction0 is the I/O Request Function for DAC960 Controller 0. -*/ - -static void DAC960_RequestFunction0(request_queue_t * q) -{ - DAC960_Controller_T *Controller = DAC960_Controllers[0]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); -} - - -/* - DAC960_RequestFunction1 is the I/O Request Function for DAC960 Controller 1. -*/ - -static void DAC960_RequestFunction1(request_queue_t * q) -{ - DAC960_Controller_T *Controller = DAC960_Controllers[1]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); -} - - -/* - DAC960_RequestFunction2 is the I/O Request Function for DAC960 Controller 2. -*/ - -static void DAC960_RequestFunction2(request_queue_t * q) -{ - DAC960_Controller_T *Controller = DAC960_Controllers[2]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); } /* - DAC960_RequestFunction3 is the I/O Request Function for DAC960 Controller 3. + DAC960_V2_QueueReadWriteCommand prepares and queues a Read/Write Command for + DAC960 V2 Firmware Controllers. */ -static void DAC960_RequestFunction3(request_queue_t * q) +static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *Command) { - DAC960_Controller_T *Controller = DAC960_Controllers[3]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + DAC960_Controller_T *Controller = Command->Controller; + DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; + DAC960_V2_ClearCommand(Command); + CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10; + CommandMailbox->SCSI_10.CommandControlBits.DataTransferControllerToHost = + (Command->CommandType == DAC960_ReadCommand); + CommandMailbox->SCSI_10.DataTransferSize = + Command->BlockCount << DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.RequestSenseBusAddress = + Virtual_to_Bus(&Command->V2.RequestSense); + 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->CommandType == DAC960_ReadCommand ? 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 = + Virtual_to_Bus(Command->RequestBuffer); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + } + else + { + DAC960_V2_ScatterGatherSegment_T + *ScatterGatherList = Command->V2.ScatterGatherList; + BufferHeader_T *BufferHeader = Command->BufferHeader; + char *LastDataEndPointer = NULL; + int SegmentNumber = 0; + if (Command->SegmentCount > 2) + { + CommandMailbox->SCSI_10.CommandControlBits + .AdditionalScatterGatherListMemory = true; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ExtendedScatterGather.ScatterGatherList0Length = + Command->SegmentCount; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ExtendedScatterGather.ScatterGatherList0Address = + Virtual_to_Bus(ScatterGatherList); + } + else + ScatterGatherList = + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments; + while (BufferHeader != NULL) + { + if (BufferHeader->b_data == LastDataEndPointer) + { + ScatterGatherList[SegmentNumber-1].SegmentByteCount += + BufferHeader->b_size; + LastDataEndPointer += BufferHeader->b_size; + } + else + { + ScatterGatherList[SegmentNumber].SegmentDataPointer = + Virtual_to_Bus(BufferHeader->b_data); + ScatterGatherList[SegmentNumber].SegmentByteCount = + BufferHeader->b_size; + LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size; + if (SegmentNumber++ > Controller->DriverScatterGatherLimit) + panic("DAC960: Scatter/Gather Segment Overflow\n"); + } + BufferHeader = BufferHeader->b_reqnext; + } + if (SegmentNumber != Command->SegmentCount) + panic("DAC960: SegmentNumber != SegmentCount\n"); + } + DAC960_QueueCommand(Command); } /* - DAC960_RequestFunction4 is the I/O Request Function for DAC960 Controller 4. + 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_RequestFunction4(request_queue_t * q) +static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller, + boolean WaitForCommand) { - DAC960_Controller_T *Controller = DAC960_Controllers[4]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + RequestQueue_T *RequestQueue = Controller->RequestQueue; + ListHead_T *RequestQueueHead; + IO_Request_T *Request; + DAC960_Command_T *Command; + if (RequestQueue == NULL) return false; + RequestQueueHead = &RequestQueue->queue_head; + while (true) + { + if (list_empty(RequestQueueHead)) return false; + Request = blkdev_entry_next_request(RequestQueueHead); + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) break; + if (!WaitForCommand) return false; + DAC960_WaitForCommand(Controller); + } + if (Request->cmd == READ) + Command->CommandType = DAC960_ReadCommand; + else Command->CommandType = DAC960_WriteCommand; + Command->Semaphore = Request->sem; + Command->LogicalDriveNumber = DAC960_LogicalDriveNumber(Request->rq_dev); + Command->BlockNumber = + Request->sector + + Controller->GenericDiskInfo.part[MINOR(Request->rq_dev)].start_sect; + Command->BlockCount = Request->nr_sectors; + Command->SegmentCount = Request->nr_segments; + Command->BufferHeader = Request->bh; + Command->RequestBuffer = Request->buffer; + blkdev_dequeue_request(Request); + blkdev_release_request(Request); + DAC960_QueueReadWriteCommand(Command); + return true; } /* - DAC960_RequestFunction5 is the I/O Request Function for DAC960 Controller 5. + DAC960_ProcessRequests attempts to remove as many I/O Requests as possible + from Controller's I/O Request Queue and queue them to the Controller. */ -static void DAC960_RequestFunction5(request_queue_t * q) +static inline void DAC960_ProcessRequests(DAC960_Controller_T *Controller) { - DAC960_Controller_T *Controller = DAC960_Controllers[5]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + int Counter = 0; + while (DAC960_ProcessRequest(Controller, Counter++ == 0)) ; } /* - DAC960_RequestFunction6 is the I/O Request Function for DAC960 Controller 6. + DAC960_RequestFunction is the I/O Request Function for DAC960 Controllers. */ -static void DAC960_RequestFunction6(request_queue_t * q) +static void DAC960_RequestFunction(RequestQueue_T *RequestQueue) { - DAC960_Controller_T *Controller = DAC960_Controllers[6]; + DAC960_Controller_T *Controller = + (DAC960_Controller_T *) RequestQueue->queuedata; ProcessorFlags_T ProcessorFlags; /* Acquire exclusive access to Controller. @@ -1705,37 +2833,26 @@ static void DAC960_RequestFunction6(request_queue_t * q) /* - DAC960_RequestFunction7 is the I/O Request Function for DAC960 Controller 7. + DAC960_ProcessCompletedBuffer performs completion processing for an + individual Buffer. */ -static void DAC960_RequestFunction7(request_queue_t * q) +static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader, + boolean SuccessfulIO) { - DAC960_Controller_T *Controller = DAC960_Controllers[7]; - ProcessorFlags_T ProcessorFlags; - /* - Acquire exclusive access to Controller. - */ - DAC960_AcquireControllerLockRF(Controller, &ProcessorFlags); - /* - Process I/O Requests for Controller. - */ - DAC960_ProcessRequests(Controller); - /* - Release exclusive access to Controller. - */ - DAC960_ReleaseControllerLockRF(Controller, &ProcessorFlags); + BufferHeader->b_end_io(BufferHeader, SuccessfulIO); } /* - DAC960_ReadWriteError prints an appropriate error message for Command when - an error occurs on a Read or Write operation. + DAC960_V1_ReadWriteError prints an appropriate error message for Command + when an error occurs on a Read or Write operation. */ -static void DAC960_ReadWriteError(DAC960_Command_T *Command) +static void DAC960_V1_ReadWriteError(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; - char *CommandName = "UNKNOWN"; + unsigned char *CommandName = "UNKNOWN"; switch (Command->CommandType) { case DAC960_ReadCommand: @@ -1751,26 +2868,26 @@ static void DAC960_ReadWriteError(DAC960_Command_T *Command) case DAC960_QueuedCommand: break; } - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_IrrecoverableDataError: + case DAC960_V1_IrrecoverableDataError: DAC960_Error("Irrecoverable Data Error on %s:\n", Controller, CommandName); break; - case DAC960_LogicalDriveNonexistentOrOffline: + case DAC960_V1_LogicalDriveNonexistentOrOffline: DAC960_Error("Logical Drive Nonexistent or Offline on %s:\n", Controller, CommandName); break; - case DAC960_AccessBeyondEndOfLogicalDrive: + case DAC960_V1_AccessBeyondEndOfLogicalDrive: DAC960_Error("Attempt to Access Beyond End of Logical Drive " "on %s:\n", Controller, CommandName); break; - case DAC960_BadDataEncountered: + 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->CommandStatus, CommandName); + Controller, Command->V1.CommandStatus, CommandName); break; } DAC960_Error(" /dev/rd/c%dd%d: absolute blocks %d..%d\n", @@ -1788,33 +2905,22 @@ static void DAC960_ReadWriteError(DAC960_Command_T *Command) /* - DAC960_ProcessCompletedBuffer performs completion processing for an - individual Buffer. -*/ - -static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader, - boolean SuccessfulIO) -{ - BufferHeader->b_end_io(BufferHeader, SuccessfulIO); -} - - -/* - DAC960_ProcessCompletedCommand performs completion processing for Command. + DAC960_V1_ProcessCompletedCommand performs completion processing for Command + for DAC960 V1 Firmware Controllers. */ -static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) +static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command) { DAC960_Controller_T *Controller = Command->Controller; DAC960_CommandType_T CommandType = Command->CommandType; - DAC960_CommandOpcode_T CommandOpcode = - Command->CommandMailbox.Common.CommandOpcode; - DAC960_CommandStatus_T CommandStatus = Command->CommandStatus; + DAC960_V1_CommandOpcode_T CommandOpcode = + Command->V1.CommandMailbox.Common.CommandOpcode; + DAC960_V1_CommandStatus_T CommandStatus = Command->V1.CommandStatus; BufferHeader_T *BufferHeader = Command->BufferHeader; if (CommandType == DAC960_ReadCommand || CommandType == DAC960_WriteCommand) { - if (CommandStatus == DAC960_NormalCompletion) + if (CommandStatus == DAC960_V1_NormalCompletion) { /* Perform completion processing for all buffers in this I/O Request. @@ -1836,21 +2942,22 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) } add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); } - else if ((CommandStatus == DAC960_IrrecoverableDataError || - CommandStatus == DAC960_BadDataEncountered) && + else if ((CommandStatus == DAC960_V1_IrrecoverableDataError || + CommandStatus == DAC960_V1_BadDataEncountered) && BufferHeader != NULL && BufferHeader->b_reqnext != NULL) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + DAC960_V1_CommandMailbox_T *CommandMailbox = + &Command->V1.CommandMailbox; if (CommandType == DAC960_ReadCommand) { Command->CommandType = DAC960_ReadRetryCommand; - CommandMailbox->Type5.CommandOpcode = DAC960_Read; + CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read; } else { Command->CommandType = DAC960_WriteRetryCommand; - CommandMailbox->Type5.CommandOpcode = DAC960_Write; + CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write; } Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits; CommandMailbox->Type5.LD.TransferLength = Command->BlockCount; @@ -1861,8 +2968,8 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) } else { - if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline) - DAC960_ReadWriteError(Command); + if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline) + DAC960_V1_ReadWriteError(Command); /* Perform completion processing for all buffers in this I/O Request. */ @@ -1891,17 +2998,18 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) /* Perform completion processing for this single buffer. */ - if (CommandStatus == DAC960_NormalCompletion) + if (CommandStatus == DAC960_V1_NormalCompletion) DAC960_ProcessCompletedBuffer(BufferHeader, true); else { - if (CommandStatus != DAC960_LogicalDriveNonexistentOrOffline) - DAC960_ReadWriteError(Command); + if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline) + DAC960_V1_ReadWriteError(Command); DAC960_ProcessCompletedBuffer(BufferHeader, false); } if (NextBufferHeader != NULL) { - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; + DAC960_V1_CommandMailbox_T *CommandMailbox = + &Command->V1.CommandMailbox; Command->BlockNumber += BufferHeader->b_size >> DAC960_BlockSizeBits; Command->BlockCount = @@ -1916,30 +3024,43 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) } } else if (CommandType == DAC960_MonitoringCommand || - CommandOpcode == DAC960_Enquiry || - CommandOpcode == DAC960_GetRebuildProgress) + CommandOpcode == DAC960_V1_Enquiry || + CommandOpcode == DAC960_V1_GetRebuildProgress) { if (CommandType != DAC960_MonitoringCommand) { - if (CommandOpcode == DAC960_Enquiry) - memcpy(&Controller->Enquiry[Controller->EnquiryIndex ^ 1], - Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress), - sizeof(DAC960_Enquiry_T)); - else if (CommandOpcode == DAC960_GetRebuildProgress) - memcpy(&Controller->RebuildProgress, - Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress), - sizeof(DAC960_RebuildProgress_T)); - } - if (CommandOpcode == DAC960_Enquiry) - { - DAC960_Enquiry_T *OldEnquiry = - &Controller->Enquiry[Controller->EnquiryIndex]; - DAC960_Enquiry_T *NewEnquiry = - &Controller->Enquiry[Controller->EnquiryIndex ^= 1]; + if (CommandOpcode == DAC960_V1_Enquiry) + memcpy(&Controller->V1.NewEnquiry, + Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress), + sizeof(DAC960_V1_Enquiry_T)); + else if (CommandOpcode == DAC960_V1_GetRebuildProgress) + memcpy(&Controller->V1.RebuildProgress, + Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress), + sizeof(DAC960_V1_RebuildProgress_T)); + } + if (CommandOpcode == DAC960_V1_Enquiry && + Controller->ControllerInitialized) + { + 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; + while (LogicalDriveNumber < NewEnquiry->NumberOfLogicalDrives) + { + DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " + "Now Exists\n", Controller, + LogicalDriveNumber, + Controller->ControllerNumber, + LogicalDriveNumber); + LogicalDriveNumber++; + } + Controller->LogicalDriveCount = LogicalDriveNumber; + } if (NewEnquiry->StatusFlags.DeferredWriteError != OldEnquiry->StatusFlags.DeferredWriteError) DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller, @@ -1959,72 +3080,86 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) (jiffies - Controller->SecondaryMonitoringTime >= DAC960_SecondaryMonitoringInterval)) { - Controller->NeedLogicalDriveInformation = true; - Controller->NewEventLogSequenceNumber = + Controller->V1.NeedLogicalDriveInformation = true; + Controller->V1.NewEventLogSequenceNumber = NewEnquiry->EventLogSequenceNumber; - Controller->NeedErrorTableInformation = true; - Controller->NeedDeviceStateInformation = true; - Controller->DeviceStateChannel = 0; - Controller->DeviceStateTargetID = -1; + Controller->V1.NeedErrorTableInformation = true; + Controller->V1.NeedDeviceStateInformation = true; + Controller->V1.DeviceStateChannel = 0; + Controller->V1.DeviceStateTargetID = -1; Controller->SecondaryMonitoringTime = jiffies; } - if (NewEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress || - NewEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress || - OldEnquiry->RebuildFlag == DAC960_StandbyRebuildInProgress || - OldEnquiry->RebuildFlag == DAC960_BackgroundRebuildInProgress) - Controller->NeedRebuildProgress = true; - if (OldEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress) + 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_NoStandbyRebuildOrCheckInProgress: + case DAC960_V1_NoStandbyRebuildOrCheckInProgress: DAC960_Progress("Consistency Check Completed Successfully\n", Controller); break; - case DAC960_StandbyRebuildInProgress: - case DAC960_BackgroundRebuildInProgress: + case DAC960_V1_StandbyRebuildInProgress: + case DAC960_V1_BackgroundRebuildInProgress: break; - case DAC960_BackgroundCheckInProgress: - Controller->NeedConsistencyCheckProgress = true; + case DAC960_V1_BackgroundCheckInProgress: + Controller->V1.NeedConsistencyCheckProgress = true; break; - case DAC960_StandbyRebuildCompletedWithError: + case DAC960_V1_StandbyRebuildCompletedWithError: DAC960_Progress("Consistency Check Completed with Error\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckFailed_DriveFailed: + case DAC960_V1_BackgroundRebuildOrCheckFailed_DriveFailed: DAC960_Progress("Consistency Check Failed - " - "Physical Drive Failed\n", Controller); + "Physical Device Failed\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckFailed_LogicalDriveFailed: + case DAC960_V1_BackgroundRebuildOrCheckFailed_LogicalDriveFailed: DAC960_Progress("Consistency Check Failed - " "Logical Drive Failed\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckFailed_OtherCauses: + case DAC960_V1_BackgroundRebuildOrCheckFailed_OtherCauses: DAC960_Progress("Consistency Check Failed - Other Causes\n", Controller); break; - case DAC960_BackgroundRebuildOrCheckSuccessfullyTerminated: + case DAC960_V1_BackgroundRebuildOrCheckSuccessfullyTerminated: DAC960_Progress("Consistency Check Successfully Terminated\n", Controller); break; } - else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress) - Controller->NeedConsistencyCheckProgress = true; + else if (NewEnquiry->RebuildFlag + == DAC960_V1_BackgroundCheckInProgress) + Controller->V1.NeedConsistencyCheckProgress = true; + Controller->MonitoringAlertMode = + (NewEnquiry->CriticalLogicalDriveCount > 0 || + NewEnquiry->OfflineLogicalDriveCount > 0 || + NewEnquiry->DeadDriveCount > 0); if (CommandType != DAC960_MonitoringCommand && - Controller->RebuildFlagPending) + Controller->V1.RebuildFlagPending) { - DAC960_Enquiry_T *Enquiry = (DAC960_Enquiry_T *) - Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress); - Enquiry->RebuildFlag = Controller->PendingRebuildFlag; - Controller->RebuildFlagPending = false; + DAC960_V1_Enquiry_T *Enquiry = (DAC960_V1_Enquiry_T *) + Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress); + Enquiry->RebuildFlag = Controller->V1.PendingRebuildFlag; + Controller->V1.RebuildFlagPending = false; } else if (CommandType == DAC960_MonitoringCommand && - NewEnquiry->RebuildFlag > DAC960_BackgroundCheckInProgress) + NewEnquiry->RebuildFlag > + DAC960_V1_BackgroundCheckInProgress) { - Controller->PendingRebuildFlag = NewEnquiry->RebuildFlag; - Controller->RebuildFlagPending = true; + 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_PerformEventLogOperation) + else if (CommandOpcode == DAC960_V1_PerformEventLogOperation) { static char *DAC960_EventMessages[] = @@ -2041,37 +3176,39 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) "killed because of selection timeout", "killed due to SCSI phase sequence error", "killed due to unknown status" }; - DAC960_EventLogEntry_T *EventLogEntry = &Controller->EventLogEntry; + DAC960_V1_EventLogEntry_T *EventLogEntry = + &Controller->V1.EventLogEntry; if (EventLogEntry->SequenceNumber == - Controller->OldEventLogSequenceNumber) + Controller->V1.OldEventLogSequenceNumber) { unsigned char SenseKey = EventLogEntry->SenseKey; unsigned char AdditionalSenseCode = EventLogEntry->AdditionalSenseCode; unsigned char AdditionalSenseCodeQualifier = EventLogEntry->AdditionalSenseCodeQualifier; - if (SenseKey == 9 && + if (SenseKey == DAC960_SenseKey_VendorSpecific && AdditionalSenseCode == 0x80 && AdditionalSenseCodeQualifier < sizeof(DAC960_EventMessages) / sizeof(char *)) - DAC960_Critical("Physical Drive %d:%d %s\n", Controller, + DAC960_Critical("Physical Device %d:%d %s\n", Controller, EventLogEntry->Channel, EventLogEntry->TargetID, DAC960_EventMessages[ AdditionalSenseCodeQualifier]); - else if (SenseKey == 6 && AdditionalSenseCode == 0x29) + else if (SenseKey == DAC960_SenseKey_UnitAttention && + AdditionalSenseCode == 0x29) { if (Controller->MonitoringTimerCount > 0) - Controller->DeviceResetCount[EventLogEntry->Channel] - [EventLogEntry->TargetID]++; + Controller->V1.DeviceResetCount[EventLogEntry->Channel] + [EventLogEntry->TargetID]++; } - else if (!(SenseKey == 0 || - (SenseKey == 2 && + else if (!(SenseKey == DAC960_SenseKey_NoSense || + (SenseKey == DAC960_SenseKey_NotReady && AdditionalSenseCode == 0x04 && (AdditionalSenseCodeQualifier == 0x01 || AdditionalSenseCodeQualifier == 0x02)))) { - DAC960_Critical("Physical Drive %d:%d Error Log: " + DAC960_Critical("Physical Device %d:%d Error Log: " "Sense Key = %d, ASC = %02X, ASCQ = %02X\n", Controller, EventLogEntry->Channel, @@ -2079,7 +3216,7 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) SenseKey, AdditionalSenseCode, AdditionalSenseCodeQualifier); - DAC960_Critical("Physical Drive %d:%d Error Log: " + DAC960_Critical("Physical Device %d:%d Error Log: " "Information = %02X%02X%02X%02X " "%02X%02X%02X%02X\n", Controller, @@ -2095,21 +3232,19 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) EventLogEntry->CommandSpecificInformation[3]); } } - Controller->OldEventLogSequenceNumber++; + Controller->V1.OldEventLogSequenceNumber++; } - else if (CommandOpcode == DAC960_GetErrorTable) + else if (CommandOpcode == DAC960_V1_GetErrorTable) { - DAC960_ErrorTable_T *OldErrorTable = - &Controller->ErrorTable[Controller->ErrorTableIndex]; - DAC960_ErrorTable_T *NewErrorTable = - &Controller->ErrorTable[Controller->ErrorTableIndex ^= 1]; + 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 < DAC960_MaxTargets; TargetID++) + for (TargetID = 0; TargetID < Controller->Targets; TargetID++) { - DAC960_ErrorTableEntry_T *NewErrorEntry = + DAC960_V1_ErrorTableEntry_T *NewErrorEntry = &NewErrorTable->ErrorTableEntries[Channel][TargetID]; - DAC960_ErrorTableEntry_T *OldErrorEntry = + DAC960_V1_ErrorTableEntry_T *OldErrorEntry = &OldErrorTable->ErrorTableEntries[Channel][TargetID]; if ((NewErrorEntry->ParityErrorCount != OldErrorEntry->ParityErrorCount) || @@ -2119,7 +3254,7 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) OldErrorEntry->HardErrorCount) || (NewErrorEntry->MiscErrorCount != OldErrorEntry->MiscErrorCount)) - DAC960_Critical("Physical Drive %d:%d Errors: " + DAC960_Critical("Physical Device %d:%d Errors: " "Parity = %d, Soft = %d, " "Hard = %d, Misc = %d\n", Controller, Channel, TargetID, @@ -2128,51 +3263,49 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) NewErrorEntry->HardErrorCount, NewErrorEntry->MiscErrorCount); } + memcpy(&Controller->V1.ErrorTable, &Controller->V1.NewErrorTable, + sizeof(DAC960_V1_ErrorTable_T)); } - else if (CommandOpcode == DAC960_GetDeviceState) + else if (CommandOpcode == DAC960_V1_GetDeviceState) { - DAC960_DeviceState_T *OldDeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; - DAC960_DeviceState_T *NewDeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex ^ 1] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; + 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 Drive %d:%d is now %s\n", Controller, - Controller->DeviceStateChannel, - Controller->DeviceStateTargetID, - (NewDeviceState->DeviceState == DAC960_Device_Dead + 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_Device_WriteOnly + == DAC960_V1_Device_WriteOnly ? "WRITE-ONLY" : NewDeviceState->DeviceState - == DAC960_Device_Online + == DAC960_V1_Device_Online ? "ONLINE" : "STANDBY")); - if (OldDeviceState->DeviceState == DAC960_Device_Dead && - NewDeviceState->DeviceState != DAC960_Device_Dead) + if (OldDeviceState->DeviceState == DAC960_V1_Device_Dead && + NewDeviceState->DeviceState != DAC960_V1_Device_Dead) { - Controller->NeedDeviceInquiryInformation = true; - Controller->NeedDeviceSerialNumberInformation = true; + Controller->V1.NeedDeviceInquiryInformation = true; + Controller->V1.NeedDeviceSerialNumberInformation = true; } + memcpy(OldDeviceState, NewDeviceState, + sizeof(DAC960_V1_DeviceState_T)); } - else if (CommandOpcode == DAC960_GetLogicalDriveInformation) + else if (CommandOpcode == DAC960_V1_GetLogicalDriveInformation) { int LogicalDriveNumber; for (LogicalDriveNumber = 0; LogicalDriveNumber < Controller->LogicalDriveCount; LogicalDriveNumber++) { - DAC960_LogicalDriveInformation_T *OldLogicalDriveInformation = - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex] - [LogicalDriveNumber]; - DAC960_LogicalDriveInformation_T *NewLogicalDriveInformation = - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex ^ 1] - [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) " @@ -2181,11 +3314,11 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) Controller->ControllerNumber, LogicalDriveNumber, (NewLogicalDriveInformation->LogicalDriveState - == DAC960_LogicalDrive_Online + == DAC960_V1_LogicalDrive_Online ? "ONLINE" : NewLogicalDriveInformation->LogicalDriveState - == DAC960_LogicalDrive_Critical - ? "CRITICAL" : "OFFLINE")); + == DAC960_V1_LogicalDrive_Critical + ? "CRITICAL" : "OFFLINE")); if (NewLogicalDriveInformation->WriteBack != OldLogicalDriveInformation->WriteBack) DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) " @@ -2196,22 +3329,24 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) (NewLogicalDriveInformation->WriteBack ? "WRITE BACK" : "WRITE THRU")); } - Controller->LogicalDriveInformationIndex ^= 1; + memcpy(&Controller->V1.LogicalDriveInformation, + &Controller->V1.NewLogicalDriveInformation, + sizeof(DAC960_V1_LogicalDriveInformationArray_T)); } - else if (CommandOpcode == DAC960_GetRebuildProgress) + else if (CommandOpcode == DAC960_V1_GetRebuildProgress) { unsigned int LogicalDriveNumber = - Controller->RebuildProgress.LogicalDriveNumber; + Controller->V1.RebuildProgress.LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->RebuildProgress.LogicalDriveSize; + Controller->V1.RebuildProgress.LogicalDriveSize; unsigned int BlocksCompleted = - LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks; - if (CommandStatus == DAC960_NoRebuildOrCheckInProgress && - Controller->LastRebuildStatus == DAC960_NormalCompletion) - CommandStatus = DAC960_RebuildSuccessful; + LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks; + if (CommandStatus == DAC960_V1_NoRebuildOrCheckInProgress && + Controller->V1.LastRebuildStatus == DAC960_V1_NormalCompletion) + CommandStatus = DAC960_V1_RebuildSuccessful; switch (CommandStatus) { - case DAC960_NormalCompletion: + case DAC960_V1_NormalCompletion: Controller->EphemeralProgressMessage = true; DAC960_Progress("Rebuild in Progress: " "Logical Drive %d (/dev/rd/c%dd%d) " @@ -2223,51 +3358,51 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) / (LogicalDriveSize >> 7)); Controller->EphemeralProgressMessage = false; break; - case DAC960_RebuildFailed_LogicalDriveFailure: + case DAC960_V1_RebuildFailed_LogicalDriveFailure: DAC960_Progress("Rebuild Failed due to " "Logical Drive Failure\n", Controller); break; - case DAC960_RebuildFailed_BadBlocksOnOther: + case DAC960_V1_RebuildFailed_BadBlocksOnOther: DAC960_Progress("Rebuild Failed due to " "Bad Blocks on Other Drives\n", Controller); break; - case DAC960_RebuildFailed_NewDriveFailed: + case DAC960_V1_RebuildFailed_NewDriveFailed: DAC960_Progress("Rebuild Failed due to " "Failure of Drive Being Rebuilt\n", Controller); break; - case DAC960_NoRebuildOrCheckInProgress: + case DAC960_V1_NoRebuildOrCheckInProgress: break; - case DAC960_RebuildSuccessful: + case DAC960_V1_RebuildSuccessful: DAC960_Progress("Rebuild Completed Successfully\n", Controller); break; - case DAC960_RebuildSuccessfullyTerminated: + case DAC960_V1_RebuildSuccessfullyTerminated: DAC960_Progress("Rebuild Successfully Terminated\n", Controller); break; } - Controller->LastRebuildStatus = CommandStatus; + Controller->V1.LastRebuildStatus = CommandStatus; if (CommandType != DAC960_MonitoringCommand && - Controller->RebuildStatusPending) + Controller->V1.RebuildStatusPending) { - Command->CommandStatus = Controller->PendingRebuildStatus; - Controller->RebuildStatusPending = false; + Command->V1.CommandStatus = Controller->V1.PendingRebuildStatus; + Controller->V1.RebuildStatusPending = false; } else if (CommandType == DAC960_MonitoringCommand && - CommandStatus != DAC960_NormalCompletion && - CommandStatus != DAC960_NoRebuildOrCheckInProgress) + CommandStatus != DAC960_V1_NormalCompletion && + CommandStatus != DAC960_V1_NoRebuildOrCheckInProgress) { - Controller->PendingRebuildStatus = CommandStatus; - Controller->RebuildStatusPending = true; + Controller->V1.PendingRebuildStatus = CommandStatus; + Controller->V1.RebuildStatusPending = true; } } - else if (CommandOpcode == DAC960_RebuildStat) + else if (CommandOpcode == DAC960_V1_RebuildStat) { unsigned int LogicalDriveNumber = - Controller->RebuildProgress.LogicalDriveNumber; + Controller->V1.RebuildProgress.LogicalDriveNumber; unsigned int LogicalDriveSize = - Controller->RebuildProgress.LogicalDriveSize; + Controller->V1.RebuildProgress.LogicalDriveSize; unsigned int BlocksCompleted = - LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks; - if (CommandStatus == DAC960_NormalCompletion) + LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks; + if (CommandStatus == DAC960_V1_NormalCompletion) { Controller->EphemeralProgressMessage = true; DAC960_Progress("Consistency Check in Progress: " @@ -2284,62 +3419,60 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) } if (CommandType == DAC960_MonitoringCommand) { - if (Controller->NewEventLogSequenceNumber - - Controller->OldEventLogSequenceNumber > 0) - { - Command->CommandMailbox.Type3E.CommandOpcode = - DAC960_PerformEventLogOperation; - Command->CommandMailbox.Type3E.OperationType = - DAC960_GetEventLogEntry; - Command->CommandMailbox.Type3E.OperationQualifier = 1; - Command->CommandMailbox.Type3E.SequenceNumber = - Controller->OldEventLogSequenceNumber; - Command->CommandMailbox.Type3E.BusAddress = - Virtual_to_Bus(&Controller->EventLogEntry); + 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 = + Virtual_to_Bus(&Controller->V1.EventLogEntry); DAC960_QueueCommand(Command); return; } - if (Controller->NeedErrorTableInformation) + if (Controller->V1.NeedErrorTableInformation) { - Controller->NeedErrorTableInformation = false; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_GetErrorTable; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus( - &Controller->ErrorTable[Controller->ErrorTableIndex ^ 1]); + Controller->V1.NeedErrorTableInformation = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetErrorTable; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.NewErrorTable); DAC960_QueueCommand(Command); return; } - if (Controller->NeedRebuildProgress && - Controller->Enquiry[Controller->EnquiryIndex] - .CriticalLogicalDriveCount < - Controller->Enquiry[Controller->EnquiryIndex ^ 1] - .CriticalLogicalDriveCount) - { - Controller->NeedRebuildProgress = false; - Command->CommandMailbox.Type3.CommandOpcode = - DAC960_GetRebuildProgress; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus(&Controller->RebuildProgress); + if (Controller->V1.NeedRebuildProgress && + Controller->V1.RebuildProgressFirst) + { + Controller->V1.NeedRebuildProgress = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetRebuildProgress; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.RebuildProgress); DAC960_QueueCommand(Command); return; } - if (Controller->NeedDeviceStateInformation) + if (Controller->V1.NeedDeviceStateInformation) { - if (Controller->NeedDeviceInquiryInformation) + if (Controller->V1.NeedDeviceInquiryInformation) { - DAC960_DCDB_T *DCDB = &Controller->MonitoringDCDB; + DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB; DAC960_SCSI_Inquiry_T *InquiryStandardData = - &Controller->InquiryStandardData - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; + &Controller->V1.InquiryStandardData + [Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; InquiryStandardData->PeripheralDeviceType = 0x1F; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB; - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); - DCDB->Channel = Controller->DeviceStateChannel; - DCDB->TargetID = Controller->DeviceStateTargetID; - DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem; + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DCDB); + DCDB->Channel = Controller->V1.DeviceStateChannel; + DCDB->TargetID = Controller->V1.DeviceStateTargetID; + DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; DCDB->EarlyStatus = false; - DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds; + DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds; DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T); @@ -2354,24 +3487,25 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T); DCDB->CDB[5] = 0; /* Control */ DAC960_QueueCommand(Command); - Controller->NeedDeviceInquiryInformation = false; + Controller->V1.NeedDeviceInquiryInformation = false; return; } - if (Controller->NeedDeviceSerialNumberInformation) + if (Controller->V1.NeedDeviceSerialNumberInformation) { - DAC960_DCDB_T *DCDB = &Controller->MonitoringDCDB; + DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB; DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber = - &Controller->InquiryUnitSerialNumber - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; + &Controller->V1.InquiryUnitSerialNumber + [Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_DCDB; - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); - DCDB->Channel = Controller->DeviceStateChannel; - DCDB->TargetID = Controller->DeviceStateTargetID; - DCDB->Direction = DAC960_DCDB_DataTransferDeviceToSystem; + Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DCDB); + DCDB->Channel = Controller->V1.DeviceStateChannel; + DCDB->TargetID = Controller->V1.DeviceStateTargetID; + DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem; DCDB->EarlyStatus = false; - DCDB->Timeout = DAC960_DCDB_Timeout_10_seconds; + DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds; DCDB->NoAutomaticRequestSense = false; DCDB->DisconnectPermitted = true; DCDB->TransferLength = @@ -2387,74 +3521,68 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); DCDB->CDB[5] = 0; /* Control */ DAC960_QueueCommand(Command); - Controller->NeedDeviceSerialNumberInformation = false; + Controller->V1.NeedDeviceSerialNumberInformation = false; return; } - if (++Controller->DeviceStateTargetID == DAC960_MaxTargets) + if (++Controller->V1.DeviceStateTargetID == Controller->Targets) { - Controller->DeviceStateChannel++; - Controller->DeviceStateTargetID = 0; + Controller->V1.DeviceStateChannel++; + Controller->V1.DeviceStateTargetID = 0; } - while (Controller->DeviceStateChannel < Controller->Channels) + while (Controller->V1.DeviceStateChannel < Controller->Channels) { - DAC960_DeviceState_T *OldDeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]; + DAC960_V1_DeviceState_T *OldDeviceState = + &Controller->V1.DeviceState[Controller->V1.DeviceStateChannel] + [Controller->V1.DeviceStateTargetID]; if (OldDeviceState->Present && - OldDeviceState->DeviceType == DAC960_DiskType) + OldDeviceState->DeviceType == DAC960_V1_DiskType) { - Command->CommandMailbox.Type3D.CommandOpcode = - DAC960_GetDeviceState; - Command->CommandMailbox.Type3D.Channel = - Controller->DeviceStateChannel; - Command->CommandMailbox.Type3D.TargetID = - Controller->DeviceStateTargetID; - Command->CommandMailbox.Type3D.BusAddress = - Virtual_to_Bus(&Controller->DeviceState - [Controller->DeviceStateIndex ^ 1] - [Controller->DeviceStateChannel] - [Controller->DeviceStateTargetID]); + 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 = + Virtual_to_Bus(&Controller->V1.NewDeviceState); DAC960_QueueCommand(Command); return; } - if (++Controller->DeviceStateTargetID == DAC960_MaxTargets) + if (++Controller->V1.DeviceStateTargetID == Controller->Targets) { - Controller->DeviceStateChannel++; - Controller->DeviceStateTargetID = 0; + Controller->V1.DeviceStateChannel++; + Controller->V1.DeviceStateTargetID = 0; } } - Controller->NeedDeviceStateInformation = false; - Controller->DeviceStateIndex ^= 1; - } - if (Controller->NeedLogicalDriveInformation) - { - Controller->NeedLogicalDriveInformation = false; - Command->CommandMailbox.Type3.CommandOpcode = - DAC960_GetLogicalDriveInformation; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus( - &Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex ^ 1]); + 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 = + Virtual_to_Bus(&Controller->V1.NewLogicalDriveInformation); DAC960_QueueCommand(Command); return; } - if (Controller->NeedRebuildProgress) + if (Controller->V1.NeedRebuildProgress) { - Controller->NeedRebuildProgress = false; - Command->CommandMailbox.Type3.CommandOpcode = - DAC960_GetRebuildProgress; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus(&Controller->RebuildProgress); + Controller->V1.NeedRebuildProgress = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_GetRebuildProgress; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.RebuildProgress); DAC960_QueueCommand(Command); return; } - if (Controller->NeedConsistencyCheckProgress) + if (Controller->V1.NeedConsistencyCheckProgress) { - Controller->NeedConsistencyCheckProgress = false; - Command->CommandMailbox.Type3.CommandOpcode = DAC960_RebuildStat; - Command->CommandMailbox.Type3.BusAddress = - Virtual_to_Bus(&Controller->RebuildProgress); + Controller->V1.NeedConsistencyCheckProgress = false; + Command->V1.CommandMailbox.Type3.CommandOpcode = + DAC960_V1_RebuildStat; + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&Controller->V1.RebuildProgress); DAC960_QueueCommand(Command); return; } @@ -2471,12 +3599,835 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) } if (CommandType == DAC960_QueuedCommand) { - DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand; - KernelCommand->CommandStatus = Command->CommandStatus; - Command->KernelCommand = NULL; - if (CommandOpcode == DAC960_DCDB) - Controller->DirectCommandActive[KernelCommand->DCDB->Channel] - [KernelCommand->DCDB->TargetID] = false; + 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 %d..%d\n", + Controller, Controller->ControllerNumber, + Command->LogicalDriveNumber, Command->BlockNumber, + Command->BlockNumber + Command->BlockCount - 1); + if (DAC960_PartitionNumber(Command->BufferHeader->b_rdev) > 0) + DAC960_Error(" /dev/rd/c%dd%dp%d: relative blocks %d..%d\n", + Controller, Controller->ControllerNumber, + Command->LogicalDriveNumber, + DAC960_PartitionNumber(Command->BufferHeader->b_rdev), + Command->BufferHeader->b_rsector, + Command->BufferHeader->b_rsector + 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 Gone" }, + { 0x000F, "P Unconfigured" }, + { 0x0010, "P Expand Capacity Started" }, + { 0x0011, "P Expand Capacity Completed" }, + { 0x0012, "P Expand Capacity Failed" }, + { 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" }, + /* 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, "L Initialization Started" }, + { 0x0091, "L Initialization Completed" }, + { 0x0092, "L Initialization Cancelled" }, + { 0x0093, "L Initialization Failed" }, + { 0x0094, "L Found" }, + { 0x0095, "L Gone" }, + { 0x0096, "L Expand Capacity Started" }, + { 0x0097, "L Expand Capacity Completed" }, + { 0x0098, "L 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" }, + /* 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 Failed" }, + { 0x0147, "E Temperature Sensor %d Critical" }, + { 0x0148, "E Temperature Sensor %d OK" }, + { 0x0149, "E Temperature Sensor %d Not Present" }, + { 0x014A, "E Unit %d Access Critical" }, + { 0x014B, "E Unit %d Access OK" }, + { 0x014C, "E 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 Mirror Race Recovery In Progress" }, + { 0x0196, "C Mirror Race on Critical Drive" }, + { 0x019E, "C Memory Soft ECC Error" }, + { 0x019F, "C Memory Hard ECC Error" }, + { 0x01A2, "C Battery Backup Unit Failed" }, + { 0, "" } }; + int EventListIndex = 0, EventCode; + unsigned char EventType, *EventMessage; + 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 = %d, 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': + 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; + BufferHeader_T *BufferHeader = Command->BufferHeader; + if (CommandType == DAC960_ReadCommand || + CommandType == DAC960_WriteCommand) + { + if (CommandStatus == DAC960_V2_NormalCompletion) + { + /* + Perform completion processing for all buffers in this I/O Request. + */ + while (BufferHeader != NULL) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + DAC960_ProcessCompletedBuffer(BufferHeader, true); + BufferHeader = NextBufferHeader; + } + /* + Wake up requestor for swap file paging requests. + */ + if (Command->Semaphore != NULL) + { + up(Command->Semaphore); + Command->Semaphore = NULL; + } + add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber); + } + else if (Command->V2.RequestSense.SenseKey + == DAC960_SenseKey_MediumError && + BufferHeader != NULL && + BufferHeader->b_reqnext != NULL) + { + if (CommandType == DAC960_ReadCommand) + Command->CommandType = DAC960_ReadRetryCommand; + else Command->CommandType = DAC960_WriteRetryCommand; + Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.CommandControlBits + .AdditionalScatterGatherListMemory = false; + CommandMailbox->SCSI_10.DataTransferSize = + Command->BlockCount << DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0].SegmentDataPointer = + Virtual_to_Bus(BufferHeader->b_data); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0].SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8; + CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount; + DAC960_QueueCommand(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. + */ + while (BufferHeader != NULL) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + DAC960_ProcessCompletedBuffer(BufferHeader, false); + BufferHeader = NextBufferHeader; + } + /* + Wake up requestor for swap file paging requests. + */ + if (Command->Semaphore != NULL) + { + up(Command->Semaphore); + Command->Semaphore = NULL; + } + } + } + else if (CommandType == DAC960_ReadRetryCommand || + CommandType == DAC960_WriteRetryCommand) + { + BufferHeader_T *NextBufferHeader = BufferHeader->b_reqnext; + BufferHeader->b_reqnext = NULL; + /* + Perform completion processing for this single buffer. + */ + if (CommandStatus == DAC960_V2_NormalCompletion) + DAC960_ProcessCompletedBuffer(BufferHeader, true); + else + { + if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady) + DAC960_V2_ReadWriteError(Command); + DAC960_ProcessCompletedBuffer(BufferHeader, false); + } + if (NextBufferHeader != NULL) + { + Command->BlockNumber += + BufferHeader->b_size >> DAC960_BlockSizeBits; + Command->BlockCount = + NextBufferHeader->b_size >> DAC960_BlockSizeBits; + Command->BufferHeader = NextBufferHeader; + CommandMailbox->SCSI_10.DataTransferSize = + Command->BlockCount << DAC960_BlockSizeBits; + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentDataPointer = + Virtual_to_Bus(NextBufferHeader->b_data); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + 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; + DAC960_QueueCommand(Command); + return; + } + } + else if (CommandType == DAC960_MonitoringCommand) + { + 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.NewLogicalDeviceInformation.LogicalDeviceNumber = 0; + Controller->V2.NeedPhysicalDeviceInformation = true; + Controller->V2.PhysicalDeviceIndex = 0; + Controller->V2.NewPhysicalDeviceInformation.Channel = 0; + Controller->V2.NewPhysicalDeviceInformation.TargetID = 0; + Controller->V2.NewPhysicalDeviceInformation.LogicalUnit = 0; + 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; + if (PhysicalDeviceInfo == NULL || + (NewPhysicalDeviceInfo->Channel != + PhysicalDeviceInfo->Channel) || + (NewPhysicalDeviceInfo->TargetID != + PhysicalDeviceInfo->TargetID) || + (NewPhysicalDeviceInfo->LogicalUnit != + PhysicalDeviceInfo->LogicalUnit)) + { + unsigned int DeviceIndex; + 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) + { + 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) + { + for (DeviceIndex = PhysicalDeviceIndex; + DeviceIndex < DAC960_V2_MaxPhysicalDevices - 1; + DeviceIndex++) + { + Controller->V2.PhysicalDeviceInformation[DeviceIndex+1] = + Controller->V2.PhysicalDeviceInformation[DeviceIndex]; + Controller->V2.InquiryUnitSerialNumber[DeviceIndex+1] = + Controller->V2.InquiryUnitSerialNumber[DeviceIndex]; + Controller->V2.PhysicalDeviceInformation + [PhysicalDeviceIndex] = + PhysicalDeviceInfo; + Controller->V2.InquiryUnitSerialNumber + [PhysicalDeviceIndex] = + InquiryUnitSerialNumber; + } + 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; + 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_Unconfigured + ? "UNCONFIGURED" + : NewPhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_Online + ? "ONLINE" + : NewPhysicalDeviceInfo->PhysicalDeviceState + == DAC960_V2_Device_WriteOnly + ? "WRITE-ONLY" + : NewPhysicalDeviceInfo + ->PhysicalDeviceState + == DAC960_V2_Device_Dead + ? "DEAD" : "STANDBY")); + 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 && + 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) + 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)); + } + if (LogicalDeviceInfo != NULL) + { + unsigned long LogicalDeviceSize = + NewLogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB; + 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, + "BackgroundInitialization", + 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); + memcpy(LogicalDeviceInfo, NewLogicalDeviceInfo, + sizeof(DAC960_V2_LogicalDeviceInfo_T)); + } + NewLogicalDeviceInfo->LogicalDeviceNumber++; + } + else if (CommandOpcode == DAC960_V2_GetLogicalDeviceInfoValid) + Controller->V2.NeedLogicalDeviceInformation = 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 = + Virtual_to_Bus(&Controller->V2.Event); + 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.InquiryUnitSerialNumber + [Controller->V2.PhysicalDeviceIndex - 1]; + InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F; + CommandMailbox->SCSI_10.CommandOpcode = + DAC960_V2_SCSI_10_Passthru; + CommandMailbox->SCSI_10.DataTransferSize = + sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T); + CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = + Controller->V2.NewPhysicalDeviceInformation.LogicalUnit - 1; + CommandMailbox->SCSI_10.PhysicalDevice.TargetID = + Controller->V2.NewPhysicalDeviceInformation.TargetID; + CommandMailbox->SCSI_10.PhysicalDevice.Channel = + Controller->V2.NewPhysicalDeviceInformation.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 = + Virtual_to_Bus(InquiryUnitSerialNumber); + CommandMailbox->SCSI_10.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->SCSI_10.DataTransferSize; + DAC960_QueueCommand(Command); + Controller->V2.NeedDeviceSerialNumberInformation = false; + return; + } + 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 = + Virtual_to_Bus(&Controller->V2.NewPhysicalDeviceInformation); + CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->PhysicalDeviceInfo.DataTransferSize; + DAC960_QueueCommand(Command); + return; + } + if (Controller->V2.NeedLogicalDeviceInformation) + { + 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 = + Virtual_to_Bus(&Controller->V2.NewLogicalDeviceInformation); + 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) + { + up(Command->Semaphore); + Command->Semaphore = 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; @@ -2489,7 +4440,7 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) if (Controller->MonitoringCommandDeferred) { Controller->MonitoringCommandDeferred = false; - DAC960_QueueMonitoringCommand(Command); + DAC960_V2_QueueMonitoringCommand(Command); return; } /* @@ -2504,16 +4455,17 @@ static void DAC960_ProcessCompletedCommand(DAC960_Command_T *Command) /* - DAC960_InterruptHandler handles hardware interrupts from DAC960 Controllers. + DAC960_BA_InterruptHandler handles hardware interrupts from DAC960 BA Series + Controllers. */ -static void DAC960_InterruptHandler(int IRQ_Channel, - void *DeviceIdentifier, - Registers_T *InterruptRegisters) +static void DAC960_BA_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; void *ControllerBaseAddress = Controller->BaseAddress; - DAC960_StatusMailbox_T *NextStatusMailbox; + DAC960_V2_StatusMailbox_T *NextStatusMailbox; ProcessorFlags_T ProcessorFlags; /* Acquire exclusive access to Controller. @@ -2522,54 +4474,24 @@ static void DAC960_InterruptHandler(int IRQ_Channel, /* Process Hardware Interrupts for Controller. */ - switch (Controller->ControllerType) - { - case DAC960_V5_Controller: - DAC960_V5_AcknowledgeInterrupt(ControllerBaseAddress); - NextStatusMailbox = Controller->NextStatusMailbox; - while (NextStatusMailbox->Fields.Valid) - { - DAC960_CommandIdentifier_T CommandIdentifier = - NextStatusMailbox->Fields.CommandIdentifier; - DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; - Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus; - NextStatusMailbox->Word = 0; - if (++NextStatusMailbox > Controller->LastStatusMailbox) - NextStatusMailbox = Controller->FirstStatusMailbox; - DAC960_ProcessCompletedCommand(Command); - } - Controller->NextStatusMailbox = NextStatusMailbox; - break; - case DAC960_V4_Controller: - DAC960_V4_AcknowledgeInterrupt(ControllerBaseAddress); - NextStatusMailbox = Controller->NextStatusMailbox; - while (NextStatusMailbox->Fields.Valid) - { - DAC960_CommandIdentifier_T CommandIdentifier = - NextStatusMailbox->Fields.CommandIdentifier; - DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; - Command->CommandStatus = NextStatusMailbox->Fields.CommandStatus; - NextStatusMailbox->Word = 0; - if (++NextStatusMailbox > Controller->LastStatusMailbox) - NextStatusMailbox = Controller->FirstStatusMailbox; - DAC960_ProcessCompletedCommand(Command); - } - Controller->NextStatusMailbox = NextStatusMailbox; - break; - case DAC960_V3_Controller: - while (DAC960_V3_StatusAvailableP(ControllerBaseAddress)) - { - DAC960_CommandIdentifier_T CommandIdentifier = - DAC960_V3_ReadStatusCommandIdentifier(ControllerBaseAddress); - DAC960_Command_T *Command = &Controller->Commands[CommandIdentifier]; - Command->CommandStatus = - DAC960_V3_ReadStatusRegister(ControllerBaseAddress); - DAC960_V3_AcknowledgeInterrupt(ControllerBaseAddress); - DAC960_V3_AcknowledgeStatus(ControllerBaseAddress); - DAC960_ProcessCompletedCommand(Command); - } - break; + 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. @@ -2583,47 +4505,311 @@ static void DAC960_InterruptHandler(int IRQ_Channel, /* - DAC960_QueueMonitoringCommand queues a Monitoring Command to Controller. + DAC960_LP_InterruptHandler handles hardware interrupts from DAC960 LP Series + Controllers. */ -static void DAC960_QueueMonitoringCommand(DAC960_Command_T *Command) +static void DAC960_LP_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) { - DAC960_Controller_T *Controller = Command->Controller; - DAC960_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - DAC960_ClearCommand(Command); - Command->CommandType = DAC960_MonitoringCommand; - CommandMailbox->Type3.CommandOpcode = DAC960_Enquiry; - CommandMailbox->Type3.BusAddress = - Virtual_to_Bus(&Controller->Enquiry[Controller->EnquiryIndex ^ 1]); - DAC960_QueueCommand(Command); + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V2_StatusMailbox_T *NextStatusMailbox; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + 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. + */ + while (DAC960_ProcessRequest(Controller, false)) ; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); } /* - DAC960_MonitoringTimerFunction is the timer function for monitoring - the status of DAC960 Controllers. + DAC960_LA_InterruptHandler handles hardware interrupts from DAC960 LA Series + Controllers. */ -static void DAC960_MonitoringTimerFunction(unsigned long TimerData) +static void DAC960_LA_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) { - DAC960_Controller_T *Controller = (DAC960_Controller_T *) TimerData; - DAC960_Command_T *Command; + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_StatusMailbox_T *NextStatusMailbox; ProcessorFlags_T ProcessorFlags; /* Acquire exclusive access to Controller. */ - DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); /* - Queue a Status Monitoring Command to Controller. + Process Hardware Interrupts for Controller. */ - Command = DAC960_AllocateCommand(Controller); - if (Command != NULL) - DAC960_QueueMonitoringCommand(Command); - else Controller->MonitoringCommandDeferred = true; + 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. + */ + while (DAC960_ProcessRequest(Controller, false)) ; /* Release exclusive access to Controller. */ - DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); +} + + +/* + DAC960_PG_InterruptHandler handles hardware interrupts from DAC960 PG Series + Controllers. +*/ + +static void DAC960_PG_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + DAC960_V1_StatusMailbox_T *NextStatusMailbox; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + 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. + */ + while (DAC960_ProcessRequest(Controller, false)) ; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); +} + + +/* + DAC960_PD_InterruptHandler handles hardware interrupts from DAC960 PD Series + Controllers. +*/ + +static void DAC960_PD_InterruptHandler(int IRQ_Channel, + void *DeviceIdentifier, + Registers_T *InterruptRegisters) +{ + DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier; + void *ControllerBaseAddress = Controller->BaseAddress; + ProcessorFlags_T ProcessorFlags; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLockIH(Controller, &ProcessorFlags); + /* + Process Hardware Interrupts for Controller. + */ + 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. + */ + while (DAC960_ProcessRequest(Controller, false)) ; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLockIH(Controller, &ProcessorFlags); +} + + +/* + 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 = Virtual_to_Bus(&Controller->V1.NewEnquiry); + 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 = + Virtual_to_Bus(&Controller->V2.NewControllerInformation); + 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; + ProcessorFlags_T ProcessorFlags; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + /* + Queue a Status Monitoring Command to Controller. + */ + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) + DAC960_V1_QueueMonitoringCommand(Command); + else Controller->MonitoringCommandDeferred = true; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + } + else + { + DAC960_V2_ControllerInfo_T *ControllerInfo = + &Controller->V2.ControllerInformation; + unsigned int StatusChangeCounter = + Controller->V2.HealthStatusBuffer->StatusChangeCounter; + 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)) + { + Controller->MonitoringTimer.expires = + jiffies + DAC960_HealthStatusMonitoringInterval; + add_timer(&Controller->MonitoringTimer); + return; + } + Controller->V2.StatusChangeCounter = StatusChangeCounter; + Controller->PrimaryMonitoringTime = jiffies; + /* + Acquire exclusive access to Controller. + */ + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + /* + Queue a Status Monitoring Command to Controller. + */ + Command = DAC960_AllocateCommand(Controller); + if (Command != NULL) + DAC960_V2_QueueMonitoringCommand(Command); + else Controller->MonitoringCommandDeferred = true; + /* + Release exclusive access to Controller. + */ + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + /* + Wake up any processes waiting on a Health Status Buffer change. + */ + wake_up(&Controller->HealthStatusWaitQueue); + } } @@ -2642,20 +4828,29 @@ static int DAC960_Open(Inode_T *Inode, File_T *File) if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL || - LogicalDriveNumber > Controller->LogicalDriveCount - 1) - return -ENXIO; - if (Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex] - [LogicalDriveNumber].LogicalDriveState - == DAC960_LogicalDrive_Offline) - return -ENXIO; - if (Controller->LogicalDriveInitialState[LogicalDriveNumber] - == DAC960_LogicalDrive_Offline) + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + if (LogicalDriveNumber > Controller->LogicalDriveCount - 1) + return -ENXIO; + if (Controller->V1.LogicalDriveInformation + [LogicalDriveNumber].LogicalDriveState + == DAC960_V1_LogicalDrive_Offline) + return -ENXIO; + } + else + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + if (LogicalDeviceInfo == NULL || + LogicalDeviceInfo->LogicalDeviceState + == DAC960_V2_LogicalDevice_Offline) + return -ENXIO; + } + if (!Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber]) { - Controller->LogicalDriveInitialState[LogicalDriveNumber] = - DAC960_LogicalDrive_Online; - DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); + Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true; + DAC960_RegisterDisk(Controller, LogicalDriveNumber); } if (Controller->GenericDiskInfo.sizes[MINOR(Inode->i_rdev)] == 0) return -ENXIO; @@ -2710,25 +4905,51 @@ static int DAC960_IOCTL(Inode_T *Inode, File_T *File, if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL || - LogicalDriveNumber > Controller->LogicalDriveCount - 1) - return -ENXIO; + if (Controller == NULL) return -ENXIO; switch (Request) { case HDIO_GETGEO: /* Get BIOS Disk Geometry. */ UserGeometry = (DiskGeometry_T *) Argument; if (UserGeometry == NULL) return -EINVAL; - Geometry.heads = Controller->GeometryTranslationHeads; - Geometry.sectors = Controller->GeometryTranslationSectors; - Geometry.cylinders = - Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex] - [LogicalDriveNumber].LogicalDriveSize - / (Controller->GeometryTranslationHeads * - Controller->GeometryTranslationSectors); - Geometry.start = Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)] - .start_sect; + if (Controller->FirmwareType == DAC960_V1_Controller) + { + if (LogicalDriveNumber > Controller->LogicalDriveCount - 1) + return -ENXIO; + Geometry.heads = Controller->V1.GeometryTranslationHeads; + Geometry.sectors = Controller->V1.GeometryTranslationSectors; + Geometry.cylinders = + Controller->V1.LogicalDriveInformation[LogicalDriveNumber] + .LogicalDriveSize + / (Geometry.heads * Geometry.sectors); + } + else + { + DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo = + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber]; + if (LogicalDeviceInfo == NULL) + return -EINVAL; + switch(LogicalDeviceInfo->DriveGeometry) + { + case DAC960_V2_Geometry_128_32: + Geometry.heads = 128; + Geometry.sectors = 32; + break; + case DAC960_V2_Geometry_255_63: + Geometry.heads = 255; + Geometry.sectors = 63; + break; + default: + DAC960_Error("Illegal Logical Device Geometry %d\n", + Controller, LogicalDeviceInfo->DriveGeometry); + return -EINVAL; + } + Geometry.cylinders = + LogicalDeviceInfo->ConfigurableDeviceSizeIn512ByteBlocksOrMB + / (Geometry.heads * Geometry.sectors); + } + Geometry.start = + Controller->GenericDiskInfo.part[MINOR(Inode->i_rdev)].start_sect; return copy_to_user(UserGeometry, &Geometry, sizeof(DiskGeometry_T)); case BLKGETSIZE: /* Get Device Size. */ @@ -2789,13 +5010,20 @@ static int DAC960_IOCTL(Inode_T *Inode, File_T *File, */ set_blocksize(Device, BLOCK_SIZE); } - /* - * Leonard, I'll tie you, draw around you a pentagram - * and read this file. Aloud. - */ - grok_partitions( - &Controller->GenericDiskInfo, LogicalDriveNumber, DAC960_MaxPartitions, - Controller->LogicalDriveInformation[Controller->LogicalDriveInformationIndex][LogicalDriveNumber].LogicalDriveSize); + if (Controller->FirmwareType == DAC960_V1_Controller) + grok_partitions(&Controller->GenericDiskInfo, + LogicalDriveNumber, + DAC960_MaxPartitions, + Controller->V1.LogicalDriveInformation + [LogicalDriveNumber] + .LogicalDriveSize); + else + grok_partitions( + &Controller->GenericDiskInfo, + LogicalDriveNumber, + DAC960_MaxPartitions, + Controller->V2.LogicalDeviceInformation[LogicalDriveNumber] + ->ConfigurableDeviceSizeIn512ByteBlocksOrMB); return 0; } return -EINVAL; @@ -2830,59 +5058,63 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File, ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + 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.Channels = Controller->Channels; 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)); } - case DAC960_IOCTL_EXECUTE_COMMAND: + case DAC960_IOCTL_V1_EXECUTE_COMMAND: { - DAC960_UserCommand_T *UserSpaceUserCommand = - (DAC960_UserCommand_T *) Argument; - DAC960_UserCommand_T UserCommand; + DAC960_V1_UserCommand_T *UserSpaceUserCommand = + (DAC960_V1_UserCommand_T *) Argument; + DAC960_V1_UserCommand_T UserCommand; DAC960_Controller_T *Controller; DAC960_Command_T *Command = NULL; - DAC960_CommandOpcode_T CommandOpcode; - DAC960_CommandStatus_T CommandStatus; - DAC960_DCDB_T DCDB; + DAC960_V1_CommandOpcode_T CommandOpcode; + DAC960_V1_CommandStatus_T CommandStatus; + DAC960_V1_DCDB_T DCDB; ProcessorFlags_T ProcessorFlags; int ControllerNumber, DataTransferLength; unsigned char *DataTransferBuffer = NULL; if (UserSpaceUserCommand == NULL) return -EINVAL; ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand, - sizeof(DAC960_UserCommand_T)); - if (ErrorCode != 0) goto Failure; + sizeof(DAC960_V1_UserCommand_T)); + if (ErrorCode != 0) goto Failure1; ControllerNumber = UserCommand.ControllerNumber; if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + 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_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { ErrorCode = - copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_DCDB_T)); - if (ErrorCode != 0) goto Failure; + copy_from_user(&DCDB, UserCommand.DCDB, sizeof(DAC960_V1_DCDB_T)); + if (ErrorCode != 0) goto Failure1; if (!((DataTransferLength == 0 && - DCDB.Direction == DAC960_DCDB_NoDataTransfer) || + DCDB.Direction + == DAC960_V1_DCDB_NoDataTransfer) || (DataTransferLength > 0 && - DCDB.Direction == DAC960_DCDB_DataTransferDeviceToSystem) || + DCDB.Direction + == DAC960_V1_DCDB_DataTransferDeviceToSystem) || (DataTransferLength < 0 && - DCDB.Direction == DAC960_DCDB_DataTransferSystemToDevice))) + DCDB.Direction + == DAC960_V1_DCDB_DataTransferSystemToDevice))) return -EINVAL; if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength) != abs(DataTransferLength)) @@ -2901,23 +5133,24 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File, ErrorCode = copy_from_user(DataTransferBuffer, UserCommand.DataTransferBuffer, -DataTransferLength); - if (ErrorCode != 0) goto Failure; + if (ErrorCode != 0) goto Failure1; } - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - while (Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] || + while (Controller->V1.DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] || (Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); - Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] = true; + Controller->V1.DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] = true; DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; - memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(&DCDB); + memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(&DCDB); DCDB.BusAddress = Virtual_to_Bus(DataTransferBuffer); } else @@ -2926,38 +5159,211 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File, while ((Command = DAC960_AllocateCommand(Controller)) == NULL) DAC960_WaitForCommand(Controller); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; - memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); + memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); if (DataTransferBuffer != NULL) - Command->CommandMailbox.Type3.BusAddress = + Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DataTransferBuffer); } DAC960_ExecuteCommand(Command); - CommandStatus = Command->CommandStatus; + CommandStatus = Command->V1.CommandStatus; DAC960_AcquireControllerLock(Controller, &ProcessorFlags); DAC960_DeallocateCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); - if (CommandStatus == DAC960_NormalCompletion && - DataTransferLength > 0) + if (DataTransferLength > 0) { ErrorCode = copy_to_user(UserCommand.DataTransferBuffer, DataTransferBuffer, DataTransferLength); - if (ErrorCode != 0) goto Failure; + if (ErrorCode != 0) goto Failure1; } - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { - Controller->DirectCommandActive[DCDB.Channel] - [DCDB.TargetID] = false; + Controller->V1.DirectCommandActive[DCDB.Channel] + [DCDB.TargetID] = false; ErrorCode = - copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_DCDB_T)); - if (ErrorCode != 0) goto Failure; + copy_to_user(UserCommand.DCDB, &DCDB, sizeof(DAC960_V1_DCDB_T)); + if (ErrorCode != 0) goto Failure1; + } + ErrorCode = CommandStatus; + Failure1: + if (DataTransferBuffer != NULL) + kfree(DataTransferBuffer); + return ErrorCode; + } + case DAC960_IOCTL_V2_EXECUTE_COMMAND: + { + DAC960_V2_UserCommand_T *UserSpaceUserCommand = + (DAC960_V2_UserCommand_T *) 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; + ProcessorFlags_T ProcessorFlags; + int ControllerNumber, DataTransferLength; + int DataTransferResidue, RequestSenseLength; + unsigned char *DataTransferBuffer = NULL; + unsigned char *RequestSenseBuffer = NULL; + if (UserSpaceUserCommand == NULL) return -EINVAL; + ErrorCode = copy_from_user(&UserCommand, UserSpaceUserCommand, + sizeof(DAC960_V2_UserCommand_T)); + if (ErrorCode != 0) goto Failure2; + 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 = kmalloc(DataTransferLength, GFP_KERNEL); + if (DataTransferBuffer == NULL) return -ENOMEM; + memset(DataTransferBuffer, 0, DataTransferLength); + } + else if (DataTransferLength < 0) + { + DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL); + if (DataTransferBuffer == NULL) return -ENOMEM; + ErrorCode = copy_from_user(DataTransferBuffer, + UserCommand.DataTransferBuffer, + -DataTransferLength); + if (ErrorCode != 0) goto Failure2; + } + RequestSenseLength = UserCommand.RequestSenseLength; + if (RequestSenseLength > 0) + { + RequestSenseBuffer = kmalloc(RequestSenseLength, GFP_KERNEL); + if (RequestSenseBuffer == NULL) + { + ErrorCode = -ENOMEM; + goto Failure2; + } + memset(RequestSenseBuffer, 0, RequestSenseLength); + } + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while ((Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + 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 = + Virtual_to_Bus(DataTransferBuffer); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + } + if (RequestSenseLength > 0) + { + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = false; + CommandMailbox->Common.RequestSenseSize = RequestSenseLength; + CommandMailbox->Common.RequestSenseBusAddress = + Virtual_to_Bus(RequestSenseBuffer); + } + DAC960_ExecuteCommand(Command); + CommandStatus = Command->V2.CommandStatus; + RequestSenseLength = Command->V2.RequestSenseLength; + DataTransferResidue = Command->V2.DataTransferResidue; + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_DeallocateCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + if (RequestSenseLength > UserCommand.RequestSenseLength) + RequestSenseLength = UserCommand.RequestSenseLength; + ErrorCode = copy_to_user(&UserSpaceUserCommand->DataTransferLength, + &DataTransferResidue, + sizeof(DataTransferResidue)); + if (ErrorCode != 0) goto Failure2; + ErrorCode = copy_to_user(&UserSpaceUserCommand->RequestSenseLength, + &RequestSenseLength, + sizeof(RequestSenseLength)); + if (ErrorCode != 0) goto Failure2; + if (DataTransferLength > 0) + { + ErrorCode = copy_to_user(UserCommand.DataTransferBuffer, + DataTransferBuffer, DataTransferLength); + if (ErrorCode != 0) goto Failure2; + } + if (RequestSenseLength > 0) + { + ErrorCode = copy_to_user(UserCommand.RequestSenseBuffer, + RequestSenseBuffer, RequestSenseLength); + if (ErrorCode != 0) goto Failure2; } ErrorCode = CommandStatus; - Failure: + Failure2: if (DataTransferBuffer != NULL) kfree(DataTransferBuffer); + if (RequestSenseBuffer != NULL) + kfree(RequestSenseBuffer); + return ErrorCode; + } + case DAC960_IOCTL_V2_GET_HEALTH_STATUS: + { + DAC960_V2_GetHealthStatus_T *UserSpaceGetHealthStatus = + (DAC960_V2_GetHealthStatus_T *) Argument; + DAC960_V2_GetHealthStatus_T GetHealthStatus; + DAC960_V2_HealthStatusBuffer_T HealthStatusBuffer; + DAC960_Controller_T *Controller; + int ControllerNumber; + if (UserSpaceGetHealthStatus == NULL) return -EINVAL; + ErrorCode = copy_from_user(&GetHealthStatus, UserSpaceGetHealthStatus, + sizeof(DAC960_V2_GetHealthStatus_T)); + if (ErrorCode != 0) return ErrorCode; + 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; + ErrorCode = copy_from_user(&HealthStatusBuffer, + GetHealthStatus.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T)); + if (ErrorCode != 0) return ErrorCode; + 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; + } + ErrorCode = copy_to_user(GetHealthStatus.HealthStatusBuffer, + Controller->V2.HealthStatusBuffer, + sizeof(DAC960_V2_HealthStatusBuffer_T)); return ErrorCode; } } @@ -2987,28 +5393,29 @@ int DAC960_KernelIOCTL(unsigned int Request, void *Argument) ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + 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->Channels = Controller->Channels; ControllerInfo->PCI_Address = Controller->PCI_Address; strcpy(ControllerInfo->ModelName, Controller->ModelName); strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion); return 0; } - case DAC960_IOCTL_EXECUTE_COMMAND: + case DAC960_IOCTL_V1_EXECUTE_COMMAND: { - DAC960_KernelCommand_T *KernelCommand = - (DAC960_KernelCommand_T *) Argument; + DAC960_V1_KernelCommand_T *KernelCommand = + (DAC960_V1_KernelCommand_T *) Argument; DAC960_Controller_T *Controller; DAC960_Command_T *Command = NULL; - DAC960_CommandOpcode_T CommandOpcode; - DAC960_DCDB_T *DCDB = NULL; + DAC960_V1_CommandOpcode_T CommandOpcode; + DAC960_V1_DCDB_T *DCDB = NULL; ProcessorFlags_T ProcessorFlags; int ControllerNumber, DataTransferLength; unsigned char *DataTransferBuffer = NULL; @@ -3018,21 +5425,23 @@ int DAC960_KernelIOCTL(unsigned int Request, void *Argument) ControllerNumber > DAC960_ControllerCount - 1) return -ENXIO; Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) - return -ENXIO; + if (Controller == NULL) return -ENXIO; + if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL; CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode; DataTransferLength = KernelCommand->DataTransferLength; DataTransferBuffer = KernelCommand->DataTransferBuffer; if (CommandOpcode & 0x80) return -EINVAL; - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { DCDB = KernelCommand->DCDB; if (!((DataTransferLength == 0 && - DCDB->Direction == DAC960_DCDB_NoDataTransfer) || + DCDB->Direction == DAC960_V1_DCDB_NoDataTransfer) || (DataTransferLength > 0 && - DCDB->Direction == DAC960_DCDB_DataTransferDeviceToSystem) || + DCDB->Direction + == DAC960_V1_DCDB_DataTransferDeviceToSystem) || (DataTransferLength < 0 && - DCDB->Direction == DAC960_DCDB_DataTransferSystemToDevice))) + DCDB->Direction + == DAC960_V1_DCDB_DataTransferSystemToDevice))) return -EINVAL; if (((DCDB->TransferLengthHigh4 << 16) | DCDB->TransferLength) != abs(DataTransferLength)) @@ -3042,25 +5451,26 @@ int DAC960_KernelIOCTL(unsigned int Request, void *Argument) return -EINVAL; if (DataTransferLength > 0) memset(DataTransferBuffer, 0, DataTransferLength); - if (CommandOpcode == DAC960_DCDB) + if (CommandOpcode == DAC960_V1_DCDB) { DAC960_AcquireControllerLock(Controller, &ProcessorFlags); - if (!Controller->DirectCommandActive[DCDB->Channel] - [DCDB->TargetID]) + if (!Controller->V1.DirectCommandActive[DCDB->Channel] + [DCDB->TargetID]) Command = DAC960_AllocateCommand(Controller); if (Command == NULL) { DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); return -EBUSY; } - else Controller->DirectCommandActive[DCDB->Channel] - [DCDB->TargetID] = true; - DAC960_ClearCommand(Command); + else Controller->V1.DirectCommandActive[DCDB->Channel] + [DCDB->TargetID] = true; + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_QueuedCommand; - memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); - Command->CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB); - Command->KernelCommand = KernelCommand; + memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); + Command->V1.CommandMailbox.Type3.BusAddress = + Virtual_to_Bus(DCDB); + Command->V1.KernelCommand = KernelCommand; DCDB->BusAddress = Virtual_to_Bus(DataTransferBuffer); DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); @@ -3074,44 +5484,153 @@ int DAC960_KernelIOCTL(unsigned int Request, void *Argument) DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); return -EBUSY; } - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_QueuedCommand; - memcpy(&Command->CommandMailbox, &KernelCommand->CommandMailbox, - sizeof(DAC960_CommandMailbox_T)); + memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox, + sizeof(DAC960_V1_CommandMailbox_T)); if (DataTransferBuffer != NULL) - Command->CommandMailbox.Type3.BusAddress = + Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DataTransferBuffer); - Command->KernelCommand = KernelCommand; + Command->V1.KernelCommand = KernelCommand; DAC960_QueueCommand(Command); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); } return 0; } + case DAC960_IOCTL_V2_EXECUTE_COMMAND: + { + DAC960_V2_KernelCommand_T *KernelCommand = + (DAC960_V2_KernelCommand_T *) Argument; + DAC960_Controller_T *Controller; + DAC960_Command_T *Command = NULL; + DAC960_V2_CommandMailbox_T *CommandMailbox; + ProcessorFlags_T ProcessorFlags; + int ControllerNumber, DataTransferLength, RequestSenseLength; + unsigned char *DataTransferBuffer = NULL; + unsigned char *RequestSenseBuffer = NULL; + if (KernelCommand == NULL) return -EINVAL; + ControllerNumber = KernelCommand->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 = KernelCommand->DataTransferLength; + RequestSenseLength = KernelCommand->RequestSenseLength; + DataTransferBuffer = KernelCommand->DataTransferBuffer; + RequestSenseBuffer = KernelCommand->RequestSenseBuffer; + if (DataTransferLength != 0 && DataTransferBuffer == NULL) + return -EINVAL; + if (RequestSenseLength < 0) + return -EINVAL; + if (RequestSenseLength > 0 && RequestSenseBuffer == NULL) + return -EINVAL; + if (DataTransferLength > 0) + memset(DataTransferBuffer, 0, DataTransferLength); + if (RequestSenseLength > 0) + memset(RequestSenseBuffer, 0, RequestSenseLength); + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + Command = DAC960_AllocateCommand(Controller); + if (Command == NULL) + { + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + return -EBUSY; + } + DAC960_V2_ClearCommand(Command); + Command->CommandType = DAC960_QueuedCommand; + CommandMailbox = &Command->V2.CommandMailbox; + memcpy(CommandMailbox, &KernelCommand->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 = + Virtual_to_Bus(DataTransferBuffer); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + } + if (RequestSenseLength > 0) + { + CommandMailbox->Common.CommandControlBits + .NoAutoRequestSense = false; + CommandMailbox->Common.RequestSenseBusAddress = + Virtual_to_Bus(RequestSenseBuffer); + } + Command->V2.KernelCommand = KernelCommand; + DAC960_QueueCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + return 0; + } } return -EINVAL; } /* - DAC960_GenericDiskInit is the Generic Disk Information Initialization - Function for the DAC960 Driver. + 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 void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo) +static boolean DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller, + unsigned int ByteCount) { - DAC960_Controller_T *Controller = - (DAC960_Controller_T *) GenericDiskInfo->real_devices; - DAC960_LogicalDriveInformation_T *LogicalDriveInformation = - Controller->LogicalDriveInformation - [Controller->LogicalDriveInformationIndex]; - int LogicalDriveNumber; - for (LogicalDriveNumber = 0; - LogicalDriveNumber < Controller->LogicalDriveCount; - LogicalDriveNumber++) - register_disk(GenericDiskInfo, MKDEV(GenericDiskInfo->major, - LogicalDriveNumber*DAC960_MaxPartitions), - DAC960_MaxPartitions, &DAC960_FileOperations, - LogicalDriveInformation[LogicalDriveNumber].LogicalDriveSize); + 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; } @@ -3120,11 +5639,11 @@ static void DAC960_InitializeGenericDiskInfo(GenericDiskInfo_T *GenericDiskInfo) */ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, - char *Format, + unsigned char *Format, DAC960_Controller_T *Controller, ...) { - static char Buffer[DAC960_LineBufferSize]; + static unsigned char Buffer[DAC960_LineBufferSize]; static boolean BeginningOfLine = true; va_list Arguments; int Length = 0; @@ -3139,9 +5658,16 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, { if (!Controller->ControllerInitialized) { - strcpy(&Controller->InitialStatusBuffer[ - Controller->InitialStatusLength], Buffer); - Controller->InitialStatusLength += Length; + 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; @@ -3161,7 +5687,7 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, else printk("%s", Buffer); } } - else + else if (DAC960_CheckStatusBuffer(Controller, Length)) { strcpy(&Controller->CurrentStatusBuffer[ Controller->CurrentStatusLength], Buffer); @@ -3170,8 +5696,8 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, } else if (MessageLevel == DAC960_ProgressLevel) { - strcpy(Controller->RebuildProgressBuffer, Buffer); - Controller->RebuildProgressLength = Length; + strcpy(Controller->ProgressBuffer, Buffer); + Controller->ProgressBufferLength = Length; if (Controller->EphemeralProgressMessage) { if (jiffies - Controller->LastProgressReportTime @@ -3206,15 +5732,15 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel, /* - DAC960_ParsePhysicalDrive parses spaces followed by a Physical Drive + 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 returns false otherwise. + Channel and TargetID and returns true on success and false on failure. */ -static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller, - char *UserCommandString, - unsigned char *Channel, - unsigned char *TargetID) +static boolean DAC960_ParsePhysicalDevice(DAC960_Controller_T *Controller, + char *UserCommandString, + unsigned char *Channel, + unsigned char *TargetID) { char *NewUserCommandString = UserCommandString; unsigned long XChannel, XTargetID; @@ -3230,7 +5756,7 @@ static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller, XTargetID = simple_strtoul(UserCommandString, &NewUserCommandString, 10); if (NewUserCommandString == UserCommandString || *NewUserCommandString != '\0' || - XTargetID >= DAC960_MaxTargets) + XTargetID >= Controller->Targets) return false; *Channel = XChannel; *TargetID = XTargetID; @@ -3241,7 +5767,7 @@ static boolean DAC960_ParsePhysicalDrive(DAC960_Controller_T *Controller, /* 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 returns false otherwise. + returns true on success and false on failure. */ static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller, @@ -3257,7 +5783,7 @@ static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller, simple_strtoul(UserCommandString, &NewUserCommandString, 10); if (NewUserCommandString == UserCommandString || *NewUserCommandString != '\0' || - XLogicalDriveNumber >= Controller->LogicalDriveCount) + XLogicalDriveNumber > DAC960_MaxLogicalDrives - 1) return false; *LogicalDriveNumber = XLogicalDriveNumber; return true; @@ -3265,68 +5791,71 @@ static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller, /* - DAC960_SetDeviceState sets the Device State for a Physical Drive. + DAC960_V1_SetDeviceState sets the Device State for a Physical Device for + DAC960 V1 Firmware Controllers. */ -static void DAC960_SetDeviceState(DAC960_Controller_T *Controller, - DAC960_Command_T *Command, - unsigned char Channel, - unsigned char TargetID, - DAC960_PhysicalDeviceState_T DeviceState, - const char *DeviceStateString) +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_CommandMailbox_T *CommandMailbox = &Command->CommandMailbox; - CommandMailbox->Type3D.CommandOpcode = DAC960_StartDevice; + 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->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: - DAC960_UserCritical("%s of Physical Drive %d:%d Succeeded\n", Controller, + case DAC960_V1_NormalCompletion: + DAC960_UserCritical("%s of Physical Device %d:%d Succeeded\n", Controller, DeviceStateString, Channel, TargetID); break; - case DAC960_UnableToStartDevice: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + 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_NoDeviceAtAddress: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + 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_InvalidChannelOrTargetOrModifier: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + 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_ChannelBusy: - DAC960_UserCritical("%s of Physical Drive %d:%d Failed - " + 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 Drive %d:%d Failed - " + DAC960_UserCritical("%s of Physical Device %d:%d Failed - " "Unexpected Status %04X\n", Controller, DeviceStateString, Channel, TargetID, - Command->CommandStatus); + Command->V1.CommandStatus); break; } } /* - DAC960_ExecuteUserCommand executes a User Command. + DAC960_V1_ExecuteUserCommand executes a User Command for DAC960 V1 Firmware + Controllers. */ -static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, - char *UserCommand) +static boolean DAC960_V1_ExecuteUserCommand(DAC960_Controller_T *Controller, + unsigned char *UserCommand) { DAC960_Command_T *Command; - DAC960_CommandMailbox_T *CommandMailbox; + DAC960_V1_CommandMailbox_T *CommandMailbox; ProcessorFlags_T ProcessorFlags; unsigned char Channel, TargetID, LogicalDriveNumber; DAC960_AcquireControllerLock(Controller, &ProcessorFlags); @@ -3334,100 +5863,98 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, DAC960_WaitForCommand(Controller); DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); Controller->UserStatusLength = 0; - DAC960_ClearCommand(Command); + DAC960_V1_ClearCommand(Command); Command->CommandType = DAC960_ImmediateCommand; - CommandMailbox = &Command->CommandMailbox; + CommandMailbox = &Command->V1.CommandMailbox; if (strcmp(UserCommand, "flush-cache") == 0) { - CommandMailbox->Type3.CommandOpcode = DAC960_Flush; + CommandMailbox->Type3.CommandOpcode = DAC960_V1_Flush; DAC960_ExecuteCommand(Command); DAC960_UserCritical("Cache Flush Completed\n", Controller); } else if (strncmp(UserCommand, "kill", 4) == 0 && - DAC960_ParsePhysicalDrive(Controller, &UserCommand[4], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[4], + &Channel, &TargetID)) { - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; if (DeviceState->Present && - DeviceState->DeviceType == DAC960_DiskType && - DeviceState->DeviceState != DAC960_Device_Dead) - DAC960_SetDeviceState(Controller, Command, Channel, TargetID, - DAC960_Device_Dead, "Kill"); - else DAC960_UserCritical("Kill of Physical Drive %d:%d Illegal\n", + 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_ParsePhysicalDrive(Controller, &UserCommand[11], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[11], + &Channel, &TargetID)) { - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; if (DeviceState->Present && - DeviceState->DeviceType == DAC960_DiskType && - DeviceState->DeviceState == DAC960_Device_Dead) - DAC960_SetDeviceState(Controller, Command, Channel, TargetID, - DAC960_Device_Online, "Make Online"); - else DAC960_UserCritical("Make Online of Physical Drive %d:%d Illegal\n", + 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_ParsePhysicalDrive(Controller, &UserCommand[12], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[12], + &Channel, &TargetID)) { - DAC960_DeviceState_T *DeviceState = - &Controller->DeviceState[Controller->DeviceStateIndex] - [Channel][TargetID]; + DAC960_V1_DeviceState_T *DeviceState = + &Controller->V1.DeviceState[Channel][TargetID]; if (DeviceState->Present && - DeviceState->DeviceType == DAC960_DiskType && - DeviceState->DeviceState == DAC960_Device_Dead) - DAC960_SetDeviceState(Controller, Command, Channel, TargetID, - DAC960_Device_Standby, "Make Standby"); - else DAC960_UserCritical("Make Standby of Physical Drive %d:%d Illegal\n", + 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_ParsePhysicalDrive(Controller, &UserCommand[7], - &Channel, &TargetID)) + DAC960_ParsePhysicalDevice(Controller, &UserCommand[7], + &Channel, &TargetID)) { - CommandMailbox->Type3D.CommandOpcode = DAC960_RebuildAsync; + CommandMailbox->Type3D.CommandOpcode = DAC960_V1_RebuildAsync; CommandMailbox->Type3D.Channel = Channel; CommandMailbox->Type3D.TargetID = TargetID; DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Initiated\n", + case DAC960_V1_NormalCompletion: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Initiated\n", Controller, Channel, TargetID); break; - case DAC960_AttemptToRebuildOnlineDrive: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + 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_NewDiskFailedDuringRebuild: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + 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_InvalidDeviceAddress: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + case DAC960_V1_InvalidDeviceAddress: + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "Invalid Device Address\n", Controller, Channel, TargetID); break; - case DAC960_RebuildOrCheckAlreadyInProgress: - DAC960_UserCritical("Rebuild of Physical Drive %d:%d Failed - " + 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 Drive %d:%d Failed - " + DAC960_UserCritical("Rebuild of Physical Device %d:%d Failed - " "Unexpected Status %04X\n", Controller, - Channel, TargetID, Command->CommandStatus); + Channel, TargetID, Command->V1.CommandStatus); break; } } @@ -3435,28 +5962,28 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, DAC960_ParseLogicalDrive(Controller, &UserCommand[17], &LogicalDriveNumber)) { - CommandMailbox->Type3C.CommandOpcode = DAC960_CheckConsistencyAsync; + CommandMailbox->Type3C.CommandOpcode = DAC960_V1_CheckConsistencyAsync; CommandMailbox->Type3C.LogicalDriveNumber = LogicalDriveNumber; CommandMailbox->Type3C.AutoRestore = true; DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: + 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_DependentDiskIsDead: + case DAC960_V1_DependentDiskIsDead: DAC960_UserCritical("Consistency Check of Logical Drive %d " "(/dev/rd/c%dd%d) Failed - " - "Dependent Physical Drive is DEAD\n", + "Dependent Physical Device is DEAD\n", Controller, LogicalDriveNumber, Controller->ControllerNumber, LogicalDriveNumber); break; - case DAC960_InvalidOrNonredundantLogicalDrive: + case DAC960_V1_InvalidOrNonredundantLogicalDrive: DAC960_UserCritical("Consistency Check of Logical Drive %d " "(/dev/rd/c%dd%d) Failed - " "Invalid or Nonredundant Logical Drive\n", @@ -3464,7 +5991,7 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, Controller->ControllerNumber, LogicalDriveNumber); break; - case DAC960_RebuildOrCheckAlreadyInProgress: + 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", @@ -3478,7 +6005,7 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, "Unexpected Status %04X\n", Controller, LogicalDriveNumber, Controller->ControllerNumber, - LogicalDriveNumber, Command->CommandStatus); + LogicalDriveNumber, Command->V1.CommandStatus); break; } } @@ -3486,14 +6013,14 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, strcmp(UserCommand, "cancel-consistency-check") == 0) { unsigned char OldRebuildRateConstant; - CommandMailbox->Type3R.CommandOpcode = DAC960_RebuildControl; + CommandMailbox->Type3R.CommandOpcode = DAC960_V1_RebuildControl; CommandMailbox->Type3R.RebuildRateConstant = 0xFF; CommandMailbox->Type3R.BusAddress = Virtual_to_Bus(&OldRebuildRateConstant); DAC960_ExecuteCommand(Command); - switch (Command->CommandStatus) + switch (Command->V1.CommandStatus) { - case DAC960_NormalCompletion: + case DAC960_V1_NormalCompletion: DAC960_UserCritical("Rebuild or Consistency Check Cancelled\n", Controller); break; @@ -3501,7 +6028,7 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, DAC960_UserCritical("Cancellation of Rebuild or " "Consistency Check Failed - " "Unexpected Status %04X\n", - Controller, Command->CommandStatus); + Controller, Command->V1.CommandStatus); break; } } @@ -3515,25 +6042,235 @@ static boolean DAC960_ExecuteUserCommand(DAC960_Controller_T *Controller, /* + 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_V2_PhysicalToLogicalDevice_T PhysicalToLogicalDevice; + 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 = + Virtual_to_Bus(&PhysicalToLogicalDevice); + CommandMailbox->Common.DataTransferMemoryAddress + .ScatterGatherSegments[0] + .SegmentByteCount = + CommandMailbox->Common.DataTransferSize; + DAC960_ExecuteCommand(Command); + memcpy(CommandMailbox, &SavedCommandMailbox, + sizeof(DAC960_V2_CommandMailbox_T)); + *LogicalDeviceNumber = PhysicalToLogicalDevice.LogicalDeviceNumber; + 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; + ProcessorFlags_T ProcessorFlags; + unsigned char Channel, TargetID, LogicalDriveNumber; + unsigned short LogicalDeviceNumber; + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + while ((Command = DAC960_AllocateCommand(Controller)) == NULL) + DAC960_WaitForCommand(Controller); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + 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 DAC960_UserCritical("Illegal User Command: '%s'\n", + Controller, UserCommand); + DAC960_AcquireControllerLock(Controller, &ProcessorFlags); + DAC960_DeallocateCommand(Command); + DAC960_ReleaseControllerLock(Controller, &ProcessorFlags); + 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) { - char *StatusMessage = "OK\n"; + unsigned char *StatusMessage = "OK\n"; int ControllerNumber, BytesAvailable; for (ControllerNumber = 0; ControllerNumber < DAC960_ControllerCount; ControllerNumber++) { DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - DAC960_Enquiry_T *Enquiry; if (Controller == NULL) continue; - Enquiry = &Controller->Enquiry[Controller->EnquiryIndex]; - if (Enquiry->CriticalLogicalDriveCount > 0 || - Enquiry->OfflineLogicalDriveCount > 0 || - Enquiry->DeadDriveCount > 0) + if (Controller->MonitoringAlertMode) { StatusMessage = "ALERT\n"; break; @@ -3568,7 +6305,7 @@ static int DAC960_ProcReadInitialStatus(char *Page, char **Start, off_t Offset, } if (Count <= 0) return 0; *Start = Page; - memcpy(Page, &Controller->InitialStatusBuffer[Offset], Count); + memcpy(Page, &Controller->CombinedStatusBuffer[Offset], Count); return Count; } @@ -3581,6 +6318,9 @@ 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) { @@ -3588,22 +6328,20 @@ static int DAC960_ProcReadCurrentStatus(char *Page, char **Start, off_t Offset, DAC960_AnnounceDriver(Controller); DAC960_ReportControllerConfiguration(Controller); DAC960_ReportDeviceConfiguration(Controller); - Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; - Controller->CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' '; - if (Controller->RebuildProgressLength > 0) - { - strcpy(&Controller->CurrentStatusBuffer - [Controller->CurrentStatusLength], - Controller->RebuildProgressBuffer); - Controller->CurrentStatusLength += Controller->RebuildProgressLength; - } - else + if (Controller->ProgressBufferLength > 0) + ProgressMessageLength = Controller->ProgressBufferLength; + if (DAC960_CheckStatusBuffer(Controller, 2 + ProgressMessageLength)) { - char *StatusMessage = "No Rebuild or Consistency Check in Progress\n"; - strcpy(&Controller->CurrentStatusBuffer - [Controller->CurrentStatusLength], - StatusMessage); - Controller->CurrentStatusLength += strlen(StatusMessage); + 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; } @@ -3649,7 +6387,7 @@ static int DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer, unsigned long Count, void *Data) { DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data; - char CommandBuffer[80]; + unsigned char CommandBuffer[80]; int Length; if (Count > sizeof(CommandBuffer)-1) return -EINVAL; copy_from_user(CommandBuffer, Buffer, Count); @@ -3657,21 +6395,25 @@ static int DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer, Length = strlen(CommandBuffer); if (CommandBuffer[Length-1] == '\n') CommandBuffer[--Length] = '\0'; - return (DAC960_ExecuteUserCommand(Controller, CommandBuffer) - ? Count : -EBUSY); + 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/driver/rd/... entries - for the DAC960 Driver. + DAC960_CreateProcEntries creates the /proc/rd/... entries for the + DAC960 Driver. */ static void DAC960_CreateProcEntries(void) { - static PROC_DirectoryEntry_T *StatusProcEntry; + PROC_DirectoryEntry_T *StatusProcEntry; int ControllerNumber; - DAC960_ProcDirectoryEntry = proc_mkdir("driver/rd", NULL); + DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL); StatusProcEntry = create_proc_read_entry("status", 0, DAC960_ProcDirectoryEntry, DAC960_ProcReadStatus, NULL); @@ -3684,29 +6426,42 @@ static void DAC960_CreateProcEntries(void) PROC_DirectoryEntry_T *UserCommandProcEntry; if (Controller == NULL) continue; ControllerProcEntry = proc_mkdir(Controller->ControllerName, - DAC960_ProcDirectoryEntry); - create_proc_read_entry("initial_status",0,ControllerProcEntry, + DAC960_ProcDirectoryEntry); + create_proc_read_entry("initial_status", 0, ControllerProcEntry, DAC960_ProcReadInitialStatus, Controller); - create_proc_read_entry("current_status",0,ControllerProcEntry, + 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); + 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. + DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the + DAC960 Driver. */ static void DAC960_DestroyProcEntries(void) { - /* FIXME */ - remove_proc_entry("driver/rd", NULL); + int ControllerNumber; + for (ControllerNumber = 0; + ControllerNumber < DAC960_ControllerCount; + ControllerNumber++) + { + DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; + if (Controller == NULL) continue; + 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); + } + remove_proc_entry("rd/status", NULL); + remove_proc_entry("rd", NULL); } @@ -3719,18 +6474,8 @@ static void DAC960_DestroyProcEntries(void) int init_module(void) { - int ControllerNumber; DAC960_Initialize(); - if (DAC960_ActiveControllerCount == 0) return -1; - for (ControllerNumber = 0; - ControllerNumber < DAC960_ControllerCount; - ControllerNumber++) - { - DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber]; - if (Controller == NULL) continue; - DAC960_InitializeGenericDiskInfo(&Controller->GenericDiskInfo); - } - return 0; + return (DAC960_ActiveControllerCount > 0 ? 0 : -1); } |