ips.c
来自「linux 内核源代码」· C语言 代码 · 共 1,758 行 · 第 1/5 页
C
1,758 行
/*****************************************************************************//* ips.c -- driver for the Adaptec / IBM ServeRAID controller *//* *//* Written By: Keith Mitchell, IBM Corporation *//* Jack Hammer, Adaptec, Inc. *//* David Jeffery, Adaptec, Inc. *//* *//* Copyright (C) 2000 IBM Corporation *//* Copyright (C) 2002,2003 Adaptec, Inc. *//* *//* This program is free software; you can redistribute it and/or modify *//* it under the terms of the GNU General Public License as published by *//* the Free Software Foundation; either version 2 of the License, or *//* (at your option) any later version. *//* *//* 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 more details. *//* *//* NO WARRANTY *//* THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR *//* CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT *//* LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, *//* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is *//* solely responsible for determining the appropriateness of using and *//* distributing the Program and assumes all risks associated with its *//* exercise of rights under this Agreement, including but not limited to *//* the risks and costs of program errors, damage to or loss of data, *//* programs or equipment, and unavailability or interruption of operations. *//* *//* DISCLAIMER OF LIABILITY *//* NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY *//* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL *//* DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND *//* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR *//* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE *//* USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED *//* HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES *//* *//* You should have received a copy of the GNU General Public License *//* along with this program; if not, write to the Free Software *//* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *//* *//* Bugs/Comments/Suggestions about this driver should be mailed to: *//* ipslinux@adaptec.com *//* *//* For system support issues, contact your local IBM Customer support. *//* Directions to find IBM Customer Support for each country can be found at: *//* http://www.ibm.com/planetwide/ *//* *//*****************************************************************************//*****************************************************************************//* Change Log *//* *//* 0.99.02 - Breakup commands that are bigger than 8 * the stripe size *//* 0.99.03 - Make interrupt routine handle all completed request on the *//* adapter not just the first one *//* - Make sure passthru commands get woken up if we run out of *//* SCBs *//* - Send all of the commands on the queue at once rather than *//* one at a time since the card will support it. *//* 0.99.04 - Fix race condition in the passthru mechanism -- this required *//* the interface to the utilities to change *//* - Fix error recovery code *//* 0.99.05 - Fix an oops when we get certain passthru commands *//* 1.00.00 - Initial Public Release *//* Functionally equivalent to 0.99.05 *//* 3.60.00 - Bump max commands to 128 for use with firmware 3.60 *//* - Change version to 3.60 to coincide with release numbering. *//* 3.60.01 - Remove bogus error check in passthru routine *//* 3.60.02 - Make DCDB direction based on lookup table *//* - Only allow one DCDB command to a SCSI ID at a time *//* 4.00.00 - Add support for ServeRAID 4 *//* 4.00.01 - Add support for First Failure Data Capture *//* 4.00.02 - Fix problem with PT DCDB with no buffer *//* 4.00.03 - Add alternative passthru interface *//* - Add ability to flash BIOS *//* 4.00.04 - Rename structures/constants to be prefixed with IPS_ *//* 4.00.05 - Remove wish_block from init routine *//* - Use linux/spinlock.h instead of asm/spinlock.h for kernels *//* 2.3.18 and later *//* - Sync with other changes from the 2.3 kernels *//* 4.00.06 - Fix timeout with initial FFDC command *//* 4.00.06a - Port to 2.4 (trivial) -- Christoph Hellwig <hch@infradead.org> *//* 4.10.00 - Add support for ServeRAID 4M/4L *//* 4.10.13 - Fix for dynamic unload and proc file system *//* 4.20.03 - Rename version to coincide with new release schedules *//* Performance fixes *//* Fix truncation of /proc files with cat *//* Merge in changes through kernel 2.4.0test1ac21 *//* 4.20.13 - Fix some failure cases / reset code *//* - Hook into the reboot_notifier to flush the controller cache *//* 4.50.01 - Fix problem when there is a hole in logical drive numbering *//* 4.70.09 - Use a Common ( Large Buffer ) for Flashing from the JCRM CD *//* - Add IPSSEND Flash Support *//* - Set Sense Data for Unknown SCSI Command *//* - Use Slot Number from NVRAM Page 5 *//* - Restore caller's DCDB Structure *//* 4.70.12 - Corrective actions for bad controller ( during initialization )*//* 4.70.13 - Don't Send CDB's if we already know the device is not present *//* - Don't release HA Lock in ips_next() until SC taken off queue *//* - Unregister SCSI device in ips_release() *//* 4.70.15 - Fix Breakup for very large ( non-SG ) requests in ips_done() *//* 4.71.00 - Change all memory allocations to not use GFP_DMA flag *//* Code Clean-Up for 2.4.x kernel *//* 4.72.00 - Allow for a Scatter-Gather Element to exceed MAX_XFER Size *//* 4.72.01 - I/O Mapped Memory release ( so "insmod ips" does not Fail ) *//* - Don't Issue Internal FFDC Command if there are Active Commands *//* - Close Window for getting too many IOCTL's active *//* 4.80.00 - Make ia64 Safe *//* 4.80.04 - Eliminate calls to strtok() if 2.4.x or greater *//* - Adjustments to Device Queue Depth *//* 4.80.14 - Take all semaphores off stack *//* - Clean Up New_IOCTL path *//* 4.80.20 - Set max_sectors in Scsi_Host structure ( if >= 2.4.7 kernel ) *//* - 5 second delay needed after resetting an i960 adapter *//* 4.80.26 - Clean up potential code problems ( Arjan's recommendations ) *//* 4.90.01 - Version Matching for FirmWare, BIOS, and Driver *//* 4.90.05 - Use New PCI Architecture to facilitate Hot Plug Development *//* 4.90.08 - Increase Delays in Flashing ( Trombone Only - 4H ) *//* 4.90.08 - Data Corruption if First Scatter Gather Element is > 64K *//* 4.90.11 - Don't actually RESET unless it's physically required *//* - Remove unused compile options *//* 5.00.01 - Sarasota ( 5i ) adapters must always be scanned first *//* - Get rid on IOCTL_NEW_COMMAND code *//* - Add Extended DCDB Commands for Tape Support in 5I *//* 5.10.12 - use pci_dma interfaces, update for 2.5 kernel changes *//* 5.10.15 - remove unused code (sem, macros, etc.) *//* 5.30.00 - use __devexit_p() *//* 6.00.00 - Add 6x Adapters and Battery Flash *//* 6.10.00 - Remove 1G Addressing Limitations *//* 6.11.xx - Get VersionInfo buffer off the stack ! DDTS 60401 *//* 6.11.xx - Make Logical Drive Info structure safe for DMA DDTS 60639 *//* 7.10.18 - Add highmem_io flag in SCSI Templete for 2.4 kernels *//* - Fix path/name for scsi_hosts.h include for 2.6 kernels *//* - Fix sort order of 7k *//* - Remove 3 unused "inline" functions *//* 7.12.xx - Use STATIC functions whereever possible *//* - Clean up deprecated MODULE_PARM calls *//* 7.12.05 - Remove Version Matching per IBM request *//*****************************************************************************//* * Conditional Compilation directives for this driver: * * IPS_DEBUG - Turn on debugging info * * Parameters: * * debug:<number> - Set debug level to <number> * NOTE: only works when IPS_DEBUG compile directive is used. * 1 - Normal debug messages * 2 - Verbose debug messages * 11 - Method trace (non interrupt) * 12 - Method trace (includes interrupt) * * noi2o - Don't use I2O Queues (ServeRAID 4 only) * nommap - Don't use memory mapped I/O * ioctlsize - Initial size of the IOCTL buffer */#include <asm/io.h>#include <asm/byteorder.h>#include <asm/page.h>#include <linux/stddef.h>#include <linux/version.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/kernel.h>#include <linux/ioport.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/pci.h>#include <linux/proc_fs.h>#include <linux/reboot.h>#include <linux/interrupt.h>#include <linux/blkdev.h>#include <linux/types.h>#include <linux/dma-mapping.h>#include <scsi/sg.h>#include "scsi.h"#include <scsi/scsi_host.h>#include "ips.h"#include <linux/module.h>#include <linux/stat.h>#include <linux/spinlock.h>#include <linux/init.h>#include <linux/smp.h>#ifdef MODULEstatic char *ips = NULL;module_param(ips, charp, 0);#endif/* * DRIVER_VER */#define IPS_VERSION_HIGH IPS_VER_MAJOR_STRING "." IPS_VER_MINOR_STRING#define IPS_VERSION_LOW "." IPS_VER_BUILD_STRING " "#if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__)#warning "This driver has only been tested on the x86/ia64/x86_64 platforms"#endif#define IPS_DMA_DIR(scb) ((!scb->scsi_cmd || ips_is_passthru(scb->scsi_cmd) || \ DMA_NONE == scb->scsi_cmd->sc_data_direction) ? \ PCI_DMA_BIDIRECTIONAL : \ scb->scsi_cmd->sc_data_direction)#ifdef IPS_DEBUG#define METHOD_TRACE(s, i) if (ips_debug >= (i+10)) printk(KERN_NOTICE s "\n");#define DEBUG(i, s) if (ips_debug >= i) printk(KERN_NOTICE s "\n");#define DEBUG_VAR(i, s, v...) if (ips_debug >= i) printk(KERN_NOTICE s "\n", v);#else#define METHOD_TRACE(s, i)#define DEBUG(i, s)#define DEBUG_VAR(i, s, v...)#endif/* * Function prototypes */static int ips_detect(struct scsi_host_template *);static int ips_release(struct Scsi_Host *);static int ips_eh_abort(struct scsi_cmnd *);static int ips_eh_reset(struct scsi_cmnd *);static int ips_queue(struct scsi_cmnd *, void (*)(struct scsi_cmnd *));static const char *ips_info(struct Scsi_Host *);static irqreturn_t do_ipsintr(int, void *);static int ips_hainit(ips_ha_t *);static int ips_map_status(ips_ha_t *, ips_scb_t *, ips_stat_t *);static int ips_send_wait(ips_ha_t *, ips_scb_t *, int, int);static int ips_send_cmd(ips_ha_t *, ips_scb_t *);static int ips_online(ips_ha_t *, ips_scb_t *);static int ips_inquiry(ips_ha_t *, ips_scb_t *);static int ips_rdcap(ips_ha_t *, ips_scb_t *);static int ips_msense(ips_ha_t *, ips_scb_t *);static int ips_reqsen(ips_ha_t *, ips_scb_t *);static int ips_deallocatescbs(ips_ha_t *, int);static int ips_allocatescbs(ips_ha_t *);static int ips_reset_copperhead(ips_ha_t *);static int ips_reset_copperhead_memio(ips_ha_t *);static int ips_reset_morpheus(ips_ha_t *);static int ips_issue_copperhead(ips_ha_t *, ips_scb_t *);static int ips_issue_copperhead_memio(ips_ha_t *, ips_scb_t *);static int ips_issue_i2o(ips_ha_t *, ips_scb_t *);static int ips_issue_i2o_memio(ips_ha_t *, ips_scb_t *);static int ips_isintr_copperhead(ips_ha_t *);static int ips_isintr_copperhead_memio(ips_ha_t *);static int ips_isintr_morpheus(ips_ha_t *);static int ips_wait(ips_ha_t *, int, int);static int ips_write_driver_status(ips_ha_t *, int);static int ips_read_adapter_status(ips_ha_t *, int);static int ips_read_subsystem_parameters(ips_ha_t *, int);static int ips_read_config(ips_ha_t *, int);static int ips_clear_adapter(ips_ha_t *, int);static int ips_readwrite_page5(ips_ha_t *, int, int);static int ips_init_copperhead(ips_ha_t *);static int ips_init_copperhead_memio(ips_ha_t *);static int ips_init_morpheus(ips_ha_t *);static int ips_isinit_copperhead(ips_ha_t *);static int ips_isinit_copperhead_memio(ips_ha_t *);static int ips_isinit_morpheus(ips_ha_t *);static int ips_erase_bios(ips_ha_t *);static int ips_program_bios(ips_ha_t *, char *, uint32_t, uint32_t);static int ips_verify_bios(ips_ha_t *, char *, uint32_t, uint32_t);static int ips_erase_bios_memio(ips_ha_t *);static int ips_program_bios_memio(ips_ha_t *, char *, uint32_t, uint32_t);static int ips_verify_bios_memio(ips_ha_t *, char *, uint32_t, uint32_t);static int ips_flash_copperhead(ips_ha_t *, ips_passthru_t *, ips_scb_t *);static int ips_flash_bios(ips_ha_t *, ips_passthru_t *, ips_scb_t *);static int ips_flash_firmware(ips_ha_t *, ips_passthru_t *, ips_scb_t *);static void ips_free_flash_copperhead(ips_ha_t * ha);static void ips_get_bios_version(ips_ha_t *, int);static void ips_identify_controller(ips_ha_t *);static void ips_chkstatus(ips_ha_t *, IPS_STATUS *);static void ips_enable_int_copperhead(ips_ha_t *);static void ips_enable_int_copperhead_memio(ips_ha_t *);static void ips_enable_int_morpheus(ips_ha_t *);static int ips_intr_copperhead(ips_ha_t *);static int ips_intr_morpheus(ips_ha_t *);static void ips_next(ips_ha_t *, int);static void ipsintr_blocking(ips_ha_t *, struct ips_scb *);static void ipsintr_done(ips_ha_t *, struct ips_scb *);static void ips_done(ips_ha_t *, ips_scb_t *);static void ips_free(ips_ha_t *);static void ips_init_scb(ips_ha_t *, ips_scb_t *);static void ips_freescb(ips_ha_t *, ips_scb_t *);static void ips_setup_funclist(ips_ha_t *);static void ips_statinit(ips_ha_t *);static void ips_statinit_memio(ips_ha_t *);static void ips_fix_ffdc_time(ips_ha_t *, ips_scb_t *, time_t);static void ips_ffdc_reset(ips_ha_t *, int);static void ips_ffdc_time(ips_ha_t *);static uint32_t ips_statupd_copperhead(ips_ha_t *);static uint32_t ips_statupd_copperhead_memio(ips_ha_t *);static uint32_t ips_statupd_morpheus(ips_ha_t *);static ips_scb_t *ips_getscb(ips_ha_t *);static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);static void ips_putq_wait_tail(ips_wait_queue_t *, struct scsi_cmnd *);static void ips_putq_copp_tail(ips_copp_queue_t *, ips_copp_wait_item_t *);static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);static struct scsi_cmnd *ips_removeq_wait_head(ips_wait_queue_t *);static struct scsi_cmnd *ips_removeq_wait(ips_wait_queue_t *, struct scsi_cmnd *);static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *, ips_copp_wait_item_t *);static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);static int ips_is_passthru(struct scsi_cmnd *);static int ips_make_passthru(ips_ha_t *, struct scsi_cmnd *, ips_scb_t *, int);static int ips_usrcmd(ips_ha_t *, ips_passthru_t *, ips_scb_t *);static void ips_cleanup_passthru(ips_ha_t *, ips_scb_t *);static void ips_scmd_buf_write(struct scsi_cmnd * scmd, void *data, unsigned int count);static void ips_scmd_buf_read(struct scsi_cmnd * scmd, void *data, unsigned int count);static int ips_proc_info(struct Scsi_Host *, char *, char **, off_t, int, int);static int ips_host_info(ips_ha_t *, char *, off_t, int);static void copy_mem_info(IPS_INFOSTR *, char *, int);static int copy_info(IPS_INFOSTR *, char *, ...);static int ips_abort_init(ips_ha_t * ha, int index);static int ips_init_phase2(int index);static int ips_init_phase1(struct pci_dev *pci_dev, int *indexPtr);static int ips_register_scsi(int index);static int ips_poll_for_flush_complete(ips_ha_t * ha);static void ips_flush_and_reset(ips_ha_t *ha);/* * global variables */static const char ips_name[] = "ips";static struct Scsi_Host *ips_sh[IPS_MAX_ADAPTERS]; /* Array of host controller structures */static ips_ha_t *ips_ha[IPS_MAX_ADAPTERS]; /* Array of HA structures */static unsigned int ips_next_controller;static unsigned int ips_num_controllers;static unsigned int ips_released_controllers;static int ips_hotplug;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?