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 + -
显示快捷键?