📄 dac960.c
字号:
/* 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.47"#define DAC960_DriverDate "14 November 2002"#include <linux/module.h>#include <linux/types.h>#include <linux/miscdevice.h>#include <linux/blkdev.h>#include <linux/bio.h>#include <linux/completion.h>#include <linux/delay.h>#include <linux/genhd.h>#include <linux/hdreg.h>#include <linux/blkpg.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/proc_fs.h>#include <linux/reboot.h>#include <linux/spinlock.h>#include <linux/timer.h>#include <linux/pci.h>#include <linux/init.h>#include <asm/io.h>#include <asm/uaccess.h>#include "DAC960.h"#define DAC960_GAM_MINOR 252static DAC960_Controller_T *DAC960_Controllers[DAC960_MaxControllers];static int DAC960_ControllerCount;static struct proc_dir_entry *DAC960_ProcDirectoryEntry;static long disk_size(DAC960_Controller_T *p, int drive_nr){ if (p->FirmwareType == DAC960_V1_Controller) { if (drive_nr >= p->LogicalDriveCount) return 0; return p->V1.LogicalDriveInformation[drive_nr]. LogicalDriveSize; } else { DAC960_V2_LogicalDeviceInfo_T *i = p->V2.LogicalDeviceInformation[drive_nr]; if (i == NULL) return 0; return i->ConfigurableDeviceSize; }}static int DAC960_open(struct inode *inode, struct file *file){ struct gendisk *disk = inode->i_bdev->bd_disk; DAC960_Controller_T *p = disk->queue->queuedata; int drive_nr = (long)disk->private_data; if (p->FirmwareType == DAC960_V1_Controller) { if (p->V1.LogicalDriveInformation[drive_nr]. LogicalDriveState == DAC960_V1_LogicalDrive_Offline) return -ENXIO; } else { DAC960_V2_LogicalDeviceInfo_T *i = p->V2.LogicalDeviceInformation[drive_nr]; if (!i || i->LogicalDeviceState == DAC960_V2_LogicalDevice_Offline) return -ENXIO; } check_disk_change(inode->i_bdev); if (!get_capacity(p->disks[drive_nr])) return -ENXIO; return 0;}static int DAC960_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg){ struct gendisk *disk = inode->i_bdev->bd_disk; DAC960_Controller_T *p = disk->queue->queuedata; int drive_nr = (long)disk->private_data; struct hd_geometry g; struct hd_geometry __user *loc = (struct hd_geometry __user *)arg; if (cmd != HDIO_GETGEO || !loc) return -EINVAL; if (p->FirmwareType == DAC960_V1_Controller) { g.heads = p->V1.GeometryTranslationHeads; g.sectors = p->V1.GeometryTranslationSectors; g.cylinders = p->V1.LogicalDriveInformation[drive_nr]. LogicalDriveSize / (g.heads * g.sectors); } else { DAC960_V2_LogicalDeviceInfo_T *i = p->V2.LogicalDeviceInformation[drive_nr]; switch (i->DriveGeometry) { case DAC960_V2_Geometry_128_32: g.heads = 128; g.sectors = 32; break; case DAC960_V2_Geometry_255_63: g.heads = 255; g.sectors = 63; break; default: DAC960_Error("Illegal Logical Device Geometry %d\n", p, i->DriveGeometry); return -EINVAL; } g.cylinders = i->ConfigurableDeviceSize / (g.heads * g.sectors); } g.start = get_start_sect(inode->i_bdev); return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; }static int DAC960_media_changed(struct gendisk *disk){ DAC960_Controller_T *p = disk->queue->queuedata; int drive_nr = (long)disk->private_data; if (!p->LogicalDriveInitiallyAccessible[drive_nr]) return 1; return 0;}static int DAC960_revalidate_disk(struct gendisk *disk){ DAC960_Controller_T *p = disk->queue->queuedata; int unit = (long)disk->private_data; set_capacity(disk, disk_size(p, unit)); return 0;}static struct block_device_operations DAC960_BlockDeviceOperations = { .owner = THIS_MODULE, .open = DAC960_open, .ioctl = DAC960_ioctl, .media_changed = DAC960_media_changed, .revalidate_disk = DAC960_revalidate_disk,};/* DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name, Copyright Notice, and Electronic Mail Address.*/static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller){ DAC960_Announce("***** DAC960 RAID Driver Version " DAC960_DriverVersion " of " DAC960_DriverDate " *****\n", Controller); DAC960_Announce("Copyright 1998-2001 by Leonard N. Zubkoff " "<lnz@dandelion.com>\n", Controller);}/* DAC960_Failure prints a standardized error message, and then returns false.*/static boolean DAC960_Failure(DAC960_Controller_T *Controller, unsigned char *ErrorMessage){ DAC960_Error("While configuring DAC960 PCI RAID Controller at\n", Controller); if (Controller->IO_Address == 0) DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A " "PCI Address 0x%X\n", Controller, Controller->Bus, Controller->Device, Controller->Function, Controller->PCI_Address); else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address " "0x%X PCI Address 0x%X\n", Controller, Controller->Bus, Controller->Device, Controller->Function, Controller->IO_Address, Controller->PCI_Address); DAC960_Error("%s FAILED - DETACHING\n", Controller, ErrorMessage); return false;}/* init_dma_loaf() and slice_dma_loaf() are helper functions for aggregating the dma-mapped memory for a well-known collection of data structures that are of different lengths. These routines don't guarantee any alignment. The caller must include any space needed for alignment in the sizes of the structures that are passed in. */static boolean init_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf, size_t len){ void *cpu_addr; dma_addr_t dma_handle; cpu_addr = pci_alloc_consistent(dev, len, &dma_handle); if (cpu_addr == NULL) return false; loaf->cpu_free = loaf->cpu_base = cpu_addr; loaf->dma_free =loaf->dma_base = dma_handle; loaf->length = len; memset(cpu_addr, 0, len); return true;}static void *slice_dma_loaf(struct dma_loaf *loaf, size_t len, dma_addr_t *dma_handle){ void *cpu_end = loaf->cpu_free + len; void *cpu_addr = loaf->cpu_free; if (cpu_end > loaf->cpu_base + loaf->length) BUG(); *dma_handle = loaf->dma_free; loaf->cpu_free = cpu_end; loaf->dma_free += len; return cpu_addr;}static void free_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf_handle){ if (loaf_handle->cpu_base != NULL) pci_free_consistent(dev, loaf_handle->length, loaf_handle->cpu_base, loaf_handle->dma_base);}/* DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary data structures for Controller. It returns true on success and false on failure.*/static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller){ int CommandAllocationLength, CommandAllocationGroupSize; int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount; void *AllocationPointer = NULL; void *ScatterGatherCPU = NULL; dma_addr_t ScatterGatherDMA; struct pci_pool *ScatterGatherPool; void *RequestSenseCPU = NULL; dma_addr_t RequestSenseDMA; struct pci_pool *RequestSensePool = NULL; if (Controller->FirmwareType == DAC960_V1_Controller) { CommandAllocationLength = offsetof(DAC960_Command_T, V1.EndMarker); CommandAllocationGroupSize = DAC960_V1_CommandAllocationGroupSize; ScatterGatherPool = pci_pool_create("DAC960_V1_ScatterGather", Controller->PCIDevice, DAC960_V1_ScatterGatherLimit * sizeof(DAC960_V1_ScatterGatherSegment_T), sizeof(DAC960_V1_ScatterGatherSegment_T), 0); if (ScatterGatherPool == NULL) return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION (SG)"); Controller->ScatterGatherPool = ScatterGatherPool; } else { CommandAllocationLength = offsetof(DAC960_Command_T, V2.EndMarker); CommandAllocationGroupSize = DAC960_V2_CommandAllocationGroupSize; ScatterGatherPool = pci_pool_create("DAC960_V2_ScatterGather", Controller->PCIDevice, DAC960_V2_ScatterGatherLimit * sizeof(DAC960_V2_ScatterGatherSegment_T), sizeof(DAC960_V2_ScatterGatherSegment_T), 0); if (ScatterGatherPool == NULL) return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION (SG)"); RequestSensePool = pci_pool_create("DAC960_V2_RequestSense", Controller->PCIDevice, sizeof(DAC960_SCSI_RequestSense_T), sizeof(int), 0); if (RequestSensePool == NULL) { pci_pool_destroy(ScatterGatherPool); return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION (SG)"); } Controller->ScatterGatherPool = ScatterGatherPool; Controller->V2.RequestSensePool = RequestSensePool; } Controller->CommandAllocationGroupSize = CommandAllocationGroupSize; Controller->FreeCommands = NULL; for (CommandIdentifier = 1; CommandIdentifier <= Controller->DriverQueueDepth; CommandIdentifier++) { DAC960_Command_T *Command; if (--CommandsRemaining <= 0) { CommandsRemaining = Controller->DriverQueueDepth - CommandIdentifier + 1; if (CommandsRemaining > CommandAllocationGroupSize) CommandsRemaining = CommandAllocationGroupSize; CommandGroupByteCount = CommandsRemaining * CommandAllocationLength; AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC); if (AllocationPointer == NULL) return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); memset(AllocationPointer, 0, CommandGroupByteCount); } Command = (DAC960_Command_T *) AllocationPointer; AllocationPointer += CommandAllocationLength; Command->CommandIdentifier = CommandIdentifier; Command->Controller = Controller; Command->Next = Controller->FreeCommands; Controller->FreeCommands = Command; Controller->Commands[CommandIdentifier-1] = Command; ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, SLAB_ATOMIC, &ScatterGatherDMA); if (ScatterGatherCPU == NULL) return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); if (RequestSensePool != NULL) { RequestSenseCPU = pci_pool_alloc(RequestSensePool, SLAB_ATOMIC, &RequestSenseDMA); if (RequestSenseCPU == NULL) { pci_pool_free(ScatterGatherPool, ScatterGatherCPU, ScatterGatherDMA); return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION"); } } if (Controller->FirmwareType == DAC960_V1_Controller) { Command->cmd_sglist = Command->V1.ScatterList;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -