7243 lines · 259.6 KB · C
RawDownload
/*   Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers   Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>  Portions Copyright 2002 by Mylex (An IBM Business Unit)   This program is free software; you may redistribute and/or modify it under  the terms of the GNU General Public License Version 2 as published by the  Free Software Foundation.   This program is distributed in the hope that it will be useful, but  WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License  for complete details. */  #define DAC960_DriverVersion			"2.5.49"#define DAC960_DriverDate			"21 Aug 2007"  #include <linux/module.h>#include <linux/types.h>#include <linux/miscdevice.h>#include <linux/blkdev.h>#include <linux/bio.h>#include <linux/completion.h>#include <linux/delay.h>#include <linux/genhd.h>#include <linux/hdreg.h>#include <linux/blkpg.h>#include <linux/dma-mapping.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/mutex.h>#include <linux/proc_fs.h>#include <linux/seq_file.h>#include <linux/reboot.h>#include <linux/spinlock.h>#include <linux/timer.h>#include <linux/pci.h>#include <linux/init.h>#include <linux/jiffies.h>#include <linux/random.h>#include <linux/scatterlist.h>#include <asm/io.h>#include <asm/uaccess.h>#include "DAC960.h" #define DAC960_GAM_MINOR	252  static DEFINE_MUTEX(DAC960_mutex);static DAC960_Controller_T *DAC960_Controllers[DAC960_MaxControllers];static int DAC960_ControllerCount;static struct proc_dir_entry *DAC960_ProcDirectoryEntry; static long disk_size(DAC960_Controller_T *p, int drive_nr){	if (p->FirmwareType == DAC960_V1_Controller) {		if (drive_nr >= p->LogicalDriveCount)			return 0;		return p->V1.LogicalDriveInformation[drive_nr].			LogicalDriveSize;	} else {		DAC960_V2_LogicalDeviceInfo_T *i =			p->V2.LogicalDeviceInformation[drive_nr];		if (i == NULL)			return 0;		return i->ConfigurableDeviceSize;	}} static int DAC960_open(struct block_device *bdev, fmode_t mode){	struct gendisk *disk = bdev->bd_disk;	DAC960_Controller_T *p = disk->queue->queuedata;	int drive_nr = (long)disk->private_data;	int ret = -ENXIO; 	mutex_lock(&DAC960_mutex);	if (p->FirmwareType == DAC960_V1_Controller) {		if (p->V1.LogicalDriveInformation[drive_nr].		    LogicalDriveState == DAC960_V1_LogicalDrive_Offline)			goto out;	} else {		DAC960_V2_LogicalDeviceInfo_T *i =			p->V2.LogicalDeviceInformation[drive_nr];		if (!i || i->LogicalDeviceState == DAC960_V2_LogicalDevice_Offline)			goto out;	} 	check_disk_change(bdev); 	if (!get_capacity(p->disks[drive_nr]))		goto out;	ret = 0;out:	mutex_unlock(&DAC960_mutex);	return ret;} static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo){	struct gendisk *disk = bdev->bd_disk;	DAC960_Controller_T *p = disk->queue->queuedata;	int drive_nr = (long)disk->private_data; 	if (p->FirmwareType == DAC960_V1_Controller) {		geo->heads = p->V1.GeometryTranslationHeads;		geo->sectors = p->V1.GeometryTranslationSectors;		geo->cylinders = p->V1.LogicalDriveInformation[drive_nr].			LogicalDriveSize / (geo->heads * geo->sectors);	} else {		DAC960_V2_LogicalDeviceInfo_T *i =			p->V2.LogicalDeviceInformation[drive_nr];		switch (i->DriveGeometry) {		case DAC960_V2_Geometry_128_32:			geo->heads = 128;			geo->sectors = 32;			break;		case DAC960_V2_Geometry_255_63:			geo->heads = 255;			geo->sectors = 63;			break;		default:			DAC960_Error("Illegal Logical Device Geometry %d\n",					p, i->DriveGeometry);			return -EINVAL;		} 		geo->cylinders = i->ConfigurableDeviceSize /			(geo->heads * geo->sectors);	}		return 0;} static unsigned int DAC960_check_events(struct gendisk *disk,					unsigned int clearing){	DAC960_Controller_T *p = disk->queue->queuedata;	int drive_nr = (long)disk->private_data; 	if (!p->LogicalDriveInitiallyAccessible[drive_nr])		return DISK_EVENT_MEDIA_CHANGE;	return 0;} static int DAC960_revalidate_disk(struct gendisk *disk){	DAC960_Controller_T *p = disk->queue->queuedata;	int unit = (long)disk->private_data; 	set_capacity(disk, disk_size(p, unit));	return 0;} static const struct block_device_operations DAC960_BlockDeviceOperations = {	.owner			= THIS_MODULE,	.open			= DAC960_open,	.getgeo			= DAC960_getgeo,	.check_events		= DAC960_check_events,	.revalidate_disk	= DAC960_revalidate_disk,};  /*  DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name,  Copyright Notice, and Electronic Mail Address.*/ static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller){  DAC960_Announce("***** DAC960 RAID Driver Version "		  DAC960_DriverVersion " of "		  DAC960_DriverDate " *****\n", Controller);  DAC960_Announce("Copyright 1998-2001 by Leonard N. Zubkoff "		  "<lnz@dandelion.com>\n", Controller);}  /*  DAC960_Failure prints a standardized error message, and then returns false.*/ static bool DAC960_Failure(DAC960_Controller_T *Controller,			      unsigned char *ErrorMessage){  DAC960_Error("While configuring DAC960 PCI RAID Controller at\n",	       Controller);  if (Controller->IO_Address == 0)    DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "		 "PCI Address 0x%X\n", Controller,		 Controller->Bus, Controller->Device,		 Controller->Function, Controller->PCI_Address);  else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "		    "0x%X PCI Address 0x%X\n", Controller,		    Controller->Bus, Controller->Device,		    Controller->Function, Controller->IO_Address,		    Controller->PCI_Address);  DAC960_Error("%s FAILED - DETACHING\n", Controller, ErrorMessage);  return false;} /*  init_dma_loaf() and slice_dma_loaf() are helper functions for  aggregating the dma-mapped memory for a well-known collection of  data structures that are of different lengths.   These routines don't guarantee any alignment.  The caller must  include any space needed for alignment in the sizes of the structures  that are passed in. */ static bool init_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf,								 size_t len){	void *cpu_addr;	dma_addr_t dma_handle; 	cpu_addr = pci_alloc_consistent(dev, len, &dma_handle);	if (cpu_addr == NULL)		return false;		loaf->cpu_free = loaf->cpu_base = cpu_addr;	loaf->dma_free =loaf->dma_base = dma_handle;	loaf->length = len;	memset(cpu_addr, 0, len);	return true;} static void *slice_dma_loaf(struct dma_loaf *loaf, size_t len,					dma_addr_t *dma_handle){	void *cpu_end = loaf->cpu_free + len;	void *cpu_addr = loaf->cpu_free; 	BUG_ON(cpu_end > loaf->cpu_base + loaf->length);	*dma_handle = loaf->dma_free;	loaf->cpu_free = cpu_end;	loaf->dma_free += len;	return cpu_addr;} static void free_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf_handle){	if (loaf_handle->cpu_base != NULL)		pci_free_consistent(dev, loaf_handle->length,			loaf_handle->cpu_base, loaf_handle->dma_base);}  /*  DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary  data structures for Controller.  It returns true on success and false on  failure.*/ static bool DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller){  int CommandAllocationLength, CommandAllocationGroupSize;  int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount;  void *AllocationPointer = NULL;  void *ScatterGatherCPU = NULL;  dma_addr_t ScatterGatherDMA;  struct pci_pool *ScatterGatherPool;  void *RequestSenseCPU = NULL;  dma_addr_t RequestSenseDMA;  struct pci_pool *RequestSensePool = NULL;   if (Controller->FirmwareType == DAC960_V1_Controller)    {      CommandAllocationLength = offsetof(DAC960_Command_T, V1.EndMarker);      CommandAllocationGroupSize = DAC960_V1_CommandAllocationGroupSize;      ScatterGatherPool = pci_pool_create("DAC960_V1_ScatterGather",		Controller->PCIDevice,	DAC960_V1_ScatterGatherLimit * sizeof(DAC960_V1_ScatterGatherSegment_T),	sizeof(DAC960_V1_ScatterGatherSegment_T), 0);      if (ScatterGatherPool == NULL)	    return DAC960_Failure(Controller,			"AUXILIARY STRUCTURE CREATION (SG)");      Controller->ScatterGatherPool = ScatterGatherPool;    }  else    {      CommandAllocationLength = offsetof(DAC960_Command_T, V2.EndMarker);      CommandAllocationGroupSize = DAC960_V2_CommandAllocationGroupSize;      ScatterGatherPool = pci_pool_create("DAC960_V2_ScatterGather",		Controller->PCIDevice,	DAC960_V2_ScatterGatherLimit * sizeof(DAC960_V2_ScatterGatherSegment_T),	sizeof(DAC960_V2_ScatterGatherSegment_T), 0);      if (ScatterGatherPool == NULL)	    return DAC960_Failure(Controller,			"AUXILIARY STRUCTURE CREATION (SG)");      RequestSensePool = pci_pool_create("DAC960_V2_RequestSense",		Controller->PCIDevice, sizeof(DAC960_SCSI_RequestSense_T),		sizeof(int), 0);      if (RequestSensePool == NULL) {	    pci_pool_destroy(ScatterGatherPool);	    return DAC960_Failure(Controller,			"AUXILIARY STRUCTURE CREATION (SG)");      }      Controller->ScatterGatherPool = ScatterGatherPool;      Controller->V2.RequestSensePool = RequestSensePool;    }  Controller->CommandAllocationGroupSize = CommandAllocationGroupSize;  Controller->FreeCommands = NULL;  for (CommandIdentifier = 1;       CommandIdentifier <= Controller->DriverQueueDepth;       CommandIdentifier++)    {      DAC960_Command_T *Command;      if (--CommandsRemaining <= 0)	{	  CommandsRemaining =		Controller->DriverQueueDepth - CommandIdentifier + 1;	  if (CommandsRemaining > CommandAllocationGroupSize)		CommandsRemaining = CommandAllocationGroupSize;	  CommandGroupByteCount =		CommandsRemaining * CommandAllocationLength;	  AllocationPointer = kzalloc(CommandGroupByteCount, GFP_ATOMIC);	  if (AllocationPointer == NULL)		return DAC960_Failure(Controller,					"AUXILIARY STRUCTURE CREATION");	 }      Command = (DAC960_Command_T *) AllocationPointer;      AllocationPointer += CommandAllocationLength;      Command->CommandIdentifier = CommandIdentifier;      Command->Controller = Controller;      Command->Next = Controller->FreeCommands;      Controller->FreeCommands = Command;      Controller->Commands[CommandIdentifier-1] = Command;      ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, GFP_ATOMIC,							&ScatterGatherDMA);      if (ScatterGatherCPU == NULL)	  return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION");       if (RequestSensePool != NULL) {  	  RequestSenseCPU = pci_pool_alloc(RequestSensePool, GFP_ATOMIC,						&RequestSenseDMA);  	  if (RequestSenseCPU == NULL) {                pci_pool_free(ScatterGatherPool, ScatterGatherCPU,                                ScatterGatherDMA);    		return DAC960_Failure(Controller,					"AUXILIARY STRUCTURE CREATION");	  }        }     if (Controller->FirmwareType == DAC960_V1_Controller) {        Command->cmd_sglist = Command->V1.ScatterList;	Command->V1.ScatterGatherList =		(DAC960_V1_ScatterGatherSegment_T *)ScatterGatherCPU;	Command->V1.ScatterGatherListDMA = ScatterGatherDMA;	sg_init_table(Command->cmd_sglist, DAC960_V1_ScatterGatherLimit);      } else {        Command->cmd_sglist = Command->V2.ScatterList;	Command->V2.ScatterGatherList =		(DAC960_V2_ScatterGatherSegment_T *)ScatterGatherCPU;	Command->V2.ScatterGatherListDMA = ScatterGatherDMA;	Command->V2.RequestSense =				(DAC960_SCSI_RequestSense_T *)RequestSenseCPU;	Command->V2.RequestSenseDMA = RequestSenseDMA;	sg_init_table(Command->cmd_sglist, DAC960_V2_ScatterGatherLimit);      }    }  return true;}  /*  DAC960_DestroyAuxiliaryStructures deallocates the auxiliary data  structures for Controller.*/ static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller){  int i;  struct pci_pool *ScatterGatherPool = Controller->ScatterGatherPool;  struct pci_pool *RequestSensePool = NULL;  void *ScatterGatherCPU;  dma_addr_t ScatterGatherDMA;  void *RequestSenseCPU;  dma_addr_t RequestSenseDMA;  DAC960_Command_T *CommandGroup = NULL;     if (Controller->FirmwareType == DAC960_V2_Controller)        RequestSensePool = Controller->V2.RequestSensePool;   Controller->FreeCommands = NULL;  for (i = 0; i < Controller->DriverQueueDepth; i++)    {      DAC960_Command_T *Command = Controller->Commands[i];       if (Command == NULL)	  continue;       if (Controller->FirmwareType == DAC960_V1_Controller) {	  ScatterGatherCPU = (void *)Command->V1.ScatterGatherList;	  ScatterGatherDMA = Command->V1.ScatterGatherListDMA;	  RequestSenseCPU = NULL;	  RequestSenseDMA = (dma_addr_t)0;      } else {          ScatterGatherCPU = (void *)Command->V2.ScatterGatherList;	  ScatterGatherDMA = Command->V2.ScatterGatherListDMA;	  RequestSenseCPU = (void *)Command->V2.RequestSense;	  RequestSenseDMA = Command->V2.RequestSenseDMA;      }      if (ScatterGatherCPU != NULL)          pci_pool_free(ScatterGatherPool, ScatterGatherCPU, ScatterGatherDMA);      if (RequestSenseCPU != NULL)          pci_pool_free(RequestSensePool, RequestSenseCPU, RequestSenseDMA);       if ((Command->CommandIdentifier	   % Controller->CommandAllocationGroupSize) == 1) {	   /*	    * We can't free the group of commands until all of the	    * request sense and scatter gather dma structures are free.            * Remember the beginning of the group, but don't free it	    * until we've reached the beginning of the next group.	    */	   kfree(CommandGroup);	   CommandGroup = Command;      }      Controller->Commands[i] = NULL;    }  kfree(CommandGroup);   if (Controller->CombinedStatusBuffer != NULL)    {      kfree(Controller->CombinedStatusBuffer);      Controller->CombinedStatusBuffer = NULL;      Controller->CurrentStatusBuffer = NULL;    }   if (ScatterGatherPool != NULL)  	pci_pool_destroy(ScatterGatherPool);  if (Controller->FirmwareType == DAC960_V1_Controller)  	return;   if (RequestSensePool != NULL)	pci_pool_destroy(RequestSensePool);   for (i = 0; i < DAC960_MaxLogicalDrives; i++) {	kfree(Controller->V2.LogicalDeviceInformation[i]);	Controller->V2.LogicalDeviceInformation[i] = NULL;  }   for (i = 0; i < DAC960_V2_MaxPhysicalDevices; i++)    {      kfree(Controller->V2.PhysicalDeviceInformation[i]);      Controller->V2.PhysicalDeviceInformation[i] = NULL;      kfree(Controller->V2.InquiryUnitSerialNumber[i]);      Controller->V2.InquiryUnitSerialNumber[i] = NULL;    }}  /*  DAC960_V1_ClearCommand clears critical fields of Command for DAC960 V1  Firmware Controllers.*/ static inline void DAC960_V1_ClearCommand(DAC960_Command_T *Command){  DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;  memset(CommandMailbox, 0, sizeof(DAC960_V1_CommandMailbox_T));  Command->V1.CommandStatus = 0;}  /*  DAC960_V2_ClearCommand clears critical fields of Command for DAC960 V2  Firmware Controllers.*/ static inline void DAC960_V2_ClearCommand(DAC960_Command_T *Command){  DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;  memset(CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T));  Command->V2.CommandStatus = 0;}  /*  DAC960_AllocateCommand allocates a Command structure from Controller's  free list.  During driver initialization, a special initialization command  has been placed on the free list to guarantee that command allocation can  never fail.*/ static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T						       *Controller){  DAC960_Command_T *Command = Controller->FreeCommands;  if (Command == NULL) return NULL;

Lines 1–500 of 7243.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t