📄 dac960.c
字号:
/* Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers 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 Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for complete details. The author respectfully requests that any modifications to this software be sent directly to him for evaluation and testing.*/#define DAC960_DriverVersion "2.4.9"#define DAC960_DriverDate "7 September 2000"#include <linux/version.h>#include <linux/module.h>#include <linux/types.h>#include <linux/blk.h>#include <linux/blkdev.h>#include <linux/delay.h>#include <linux/hdreg.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/locks.h>#include <linux/mm.h>#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 <asm/uaccess.h>#include "DAC960.h"/* DAC960_ControllerCount is the number of DAC960 Controllers detected.*/static int DAC960_ControllerCount;/* DAC960_ActiveControllerCount is the number of active DAC960 Controllers detected.*/static int DAC960_ActiveControllerCount;/* DAC960_Controllers is an array of pointers to the DAC960 Controller structures.*/static DAC960_Controller_T *DAC960_Controllers[DAC960_MaxControllers];/* DAC960_BlockDeviceOperations is the Block Device Operations structure for DAC960 Logical Disk Devices.*/static BlockDeviceOperations_T DAC960_BlockDeviceOperations = { open: DAC960_Open, release: DAC960_Release, ioctl: DAC960_IOCTL };/* DAC960_ProcDirectoryEntry is the DAC960 /proc/rd directory entry.*/static PROC_DirectoryEntry_T *DAC960_ProcDirectoryEntry;/* DAC960_NotifierBlock is the Notifier Block structure for DAC960 Driver.*/static NotifierBlock_T DAC960_NotifierBlock = { DAC960_Finalize, NULL, 0 };/* DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name, Copyright Notice, and Electronic Mail Address.*/static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller){ DAC960_Announce("***** DAC960 RAID Driver Version " DAC960_DriverVersion " of " DAC960_DriverDate " *****\n", Controller); DAC960_Announce("Copyright 1998-2000 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", Controller);}/* DAC960_Failure prints a standardized error message, and then returns false.*/static boolean DAC960_Failure(DAC960_Controller_T *Controller, unsigned char *ErrorMessage){ DAC960_Error("While configuring DAC960 PCI RAID Controller at\n", Controller); if (Controller->IO_Address == 0) DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A " "PCI Address 0x%X\n", Controller, Controller->Bus, Controller->Device, Controller->Function, Controller->PCI_Address); else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " "0x%X PCI Address 0x%X\n", Controller, Controller->Bus, Controller->Device, Controller->Function, Controller->IO_Address, Controller->PCI_Address); DAC960_Error("%s FAILED - DETACHING\n", Controller, ErrorMessage); return false;}/* DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary data structures for Controller. It returns true on success and false on failure.*/static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller){ int CommandAllocationLength, CommandAllocationGroupSize; int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount; void *AllocationPointer = NULL; 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;}/* DAC960_AllocateCommand allocates a Command structure from Controller's free list.*/static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T *Controller){ DAC960_Command_T *Command = Controller->FreeCommands; if (Command == NULL) return NULL; Controller->FreeCommands = Command->Next; Command->Next = NULL; return Command;}/* DAC960_DeallocateCommand deallocates Command, returning it to Controller's free list.*/static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command){ DAC960_Controller_T *Controller = Command->Controller; Command->Next = Controller->FreeCommands; Controller->FreeCommands = Command;}/* DAC960_WaitForCommand waits for a wake_up on Controller's Command Wait Queue.*/static void DAC960_WaitForCommand(DAC960_Controller_T *Controller){ spin_unlock_irq(&io_request_lock); __wait_event(Controller->CommandWaitQueue, Controller->FreeCommands); spin_lock_irq(&io_request_lock);}/* DAC960_BA_QueueCommand queues Command for DAC960 BA Series Controllers.*/static void DAC960_BA_QueueCommand(DAC960_Command_T *Command){ DAC960_Controller_T *Controller = Command->Controller; void *ControllerBaseAddress = Controller->BaseAddress; DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox; DAC960_V2_CommandMailbox_T *NextCommandMailbox = Controller->V2.NextCommandMailbox; CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier; DAC960_BA_WriteCommandMailbox(NextCommandMailbox, CommandMailbox); if (Controller->V2.PreviousCommandMailbox1->Words[0] == 0 || Controller->V2.PreviousCommandMailbox2->Words[0] == 0) DAC960_BA_MemoryMailboxNewCommand(ControllerBaseAddress); Controller->V2.PreviousCommandMailbox2 = Controller->V2.PreviousCommandMailbox1; Controller->V2.PreviousCommandMailbox1 = NextCommandMailbox; if (++NextCommandMailbox > Controller->V2.LastCommandMailbox) NextCommandMailbox = Controller->V2.FirstCommandMailbox; Controller->V2.NextCommandMailbox = NextCommandMailbox;}/* DAC960_LP_QueueCommand queues Command for DAC960 LP Series Controllers.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -