aachba.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:33k
- /*
- * Adaptec AAC series RAID controller driver
- * (c) Copyright 2001 Red Hat Inc. <alan@redhat.com>
- *
- * based on the old aacraid driver that is..
- * Adaptec aacraid device driver for Linux.
- * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
- *
- * 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, 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
- #include <linux/config.h>
- #include <linux/kernel.h>
- #include <linux/init.h>
- #include <linux/types.h>
- #include <linux/sched.h>
- #include <linux/pci.h>
- #include <linux/spinlock.h>
- #include <linux/slab.h>
- #include <linux/completion.h>
- #include <asm/semaphore.h>
- #include <asm/uaccess.h>
- #define MAJOR_NR SCSI_DISK0_MAJOR /* For DEVICE_NR() */
- #include <linux/blk.h>
- #include "scsi.h"
- #include "hosts.h"
- #include "sd.h"
- #include "aacraid.h"
- /* SCSI Commands */
- #define SS_TEST 0x00 /* Test unit ready */
- #define SS_REZERO 0x01 /* Rezero unit */
- #define SS_REQSEN 0x03 /* Request Sense */
- #define SS_REASGN 0x07 /* Reassign blocks */
- #define SS_READ 0x08 /* Read 6 */
- #define SS_WRITE 0x0A /* Write 6 */
- #define SS_INQUIR 0x12 /* inquiry */
- #define SS_ST_SP 0x1B /* Start/Stop unit */
- #define SS_LOCK 0x1E /* prevent/allow medium removal */
- #define SS_RESERV 0x16 /* Reserve */
- #define SS_RELES 0x17 /* Release */
- #define SS_MODESEN 0x1A /* Mode Sense 6 */
- #define SS_RDCAP 0x25 /* Read Capacity */
- #define SM_READ 0x28 /* Read 10 */
- #define SM_WRITE 0x2A /* Write 10 */
- #define SS_SEEK 0x2B /* Seek */
- /* values for inqd_pdt: Peripheral device type in plain English */
- #define INQD_PDT_DA 0x00 /* Direct-access (DISK) device */
- #define INQD_PDT_PROC 0x03 /* Processor device */
- #define INQD_PDT_CHNGR 0x08 /* Changer (jukebox, scsi2) */
- #define INQD_PDT_COMM 0x09 /* Communication device (scsi2) */
- #define INQD_PDT_NOLUN2 0x1f /* Unknown Device (scsi2) */
- #define INQD_PDT_NOLUN 0x7f /* Logical Unit Not Present */
- #define INQD_PDT_DMASK 0x1F /* Peripheral Device Type Mask */
- #define INQD_PDT_QMASK 0xE0 /* Peripheral Device Qualifer Mask */
- #define TARGET_LUN_TO_CONTAINER(target, lun) (((lun) << 4) | target)
- #define CONTAINER_TO_TARGET(cont) ((cont) & 0xf)
- #define CONTAINER_TO_LUN(cont) ((cont) >> 4)
- #define MAX_FIB_DATA (sizeof(struct hw_fib) - sizeof(FIB_HEADER))
- #define MAX_DRIVER_SG_SEGMENT_COUNT 17
- /*
- * Sense keys
- */
- #define SENKEY_NO_SENSE 0x00
- #define SENKEY_UNDEFINED 0x01
- #define SENKEY_NOT_READY 0x02
- #define SENKEY_MEDIUM_ERR 0x03
- #define SENKEY_HW_ERR 0x04
- #define SENKEY_ILLEGAL 0x05
- #define SENKEY_ATTENTION 0x06
- #define SENKEY_PROTECTED 0x07
- #define SENKEY_BLANK 0x08
- #define SENKEY_V_UNIQUE 0x09
- #define SENKEY_CPY_ABORT 0x0A
- #define SENKEY_ABORT 0x0B
- #define SENKEY_EQUAL 0x0C
- #define SENKEY_VOL_OVERFLOW 0x0D
- #define SENKEY_MISCOMP 0x0E
- #define SENKEY_RESERVED 0x0F
- /*
- * Sense codes
- */
-
- #define SENCODE_NO_SENSE 0x00
- #define SENCODE_END_OF_DATA 0x00
- #define SENCODE_BECOMING_READY 0x04
- #define SENCODE_INIT_CMD_REQUIRED 0x04
- #define SENCODE_PARAM_LIST_LENGTH_ERROR 0x1A
- #define SENCODE_INVALID_COMMAND 0x20
- #define SENCODE_LBA_OUT_OF_RANGE 0x21
- #define SENCODE_INVALID_CDB_FIELD 0x24
- #define SENCODE_LUN_NOT_SUPPORTED 0x25
- #define SENCODE_INVALID_PARAM_FIELD 0x26
- #define SENCODE_PARAM_NOT_SUPPORTED 0x26
- #define SENCODE_PARAM_VALUE_INVALID 0x26
- #define SENCODE_RESET_OCCURRED 0x29
- #define SENCODE_LUN_NOT_SELF_CONFIGURED_YET 0x3E
- #define SENCODE_INQUIRY_DATA_CHANGED 0x3F
- #define SENCODE_SAVING_PARAMS_NOT_SUPPORTED 0x39
- #define SENCODE_DIAGNOSTIC_FAILURE 0x40
- #define SENCODE_INTERNAL_TARGET_FAILURE 0x44
- #define SENCODE_INVALID_MESSAGE_ERROR 0x49
- #define SENCODE_LUN_FAILED_SELF_CONFIG 0x4c
- #define SENCODE_OVERLAPPED_COMMAND 0x4E
- /*
- * Additional sense codes
- */
-
- #define ASENCODE_NO_SENSE 0x00
- #define ASENCODE_END_OF_DATA 0x05
- #define ASENCODE_BECOMING_READY 0x01
- #define ASENCODE_INIT_CMD_REQUIRED 0x02
- #define ASENCODE_PARAM_LIST_LENGTH_ERROR 0x00
- #define ASENCODE_INVALID_COMMAND 0x00
- #define ASENCODE_LBA_OUT_OF_RANGE 0x00
- #define ASENCODE_INVALID_CDB_FIELD 0x00
- #define ASENCODE_LUN_NOT_SUPPORTED 0x00
- #define ASENCODE_INVALID_PARAM_FIELD 0x00
- #define ASENCODE_PARAM_NOT_SUPPORTED 0x01
- #define ASENCODE_PARAM_VALUE_INVALID 0x02
- #define ASENCODE_RESET_OCCURRED 0x00
- #define ASENCODE_LUN_NOT_SELF_CONFIGURED_YET 0x00
- #define ASENCODE_INQUIRY_DATA_CHANGED 0x03
- #define ASENCODE_SAVING_PARAMS_NOT_SUPPORTED 0x00
- #define ASENCODE_DIAGNOSTIC_FAILURE 0x80
- #define ASENCODE_INTERNAL_TARGET_FAILURE 0x00
- #define ASENCODE_INVALID_MESSAGE_ERROR 0x00
- #define ASENCODE_LUN_FAILED_SELF_CONFIG 0x00
- #define ASENCODE_OVERLAPPED_COMMAND 0x00
- #define BYTE0(x) (unsigned char)(x)
- #define BYTE1(x) (unsigned char)((x) >> 8)
- #define BYTE2(x) (unsigned char)((x) >> 16)
- #define BYTE3(x) (unsigned char)((x) >> 24)
- /*------------------------------------------------------------------------------
- * S T R U C T S / T Y P E D E F S
- *----------------------------------------------------------------------------*/
- /* SCSI inquiry data */
- struct inquiry_data {
- u8 inqd_pdt; /* Peripheral qualifier | Peripheral Device Type */
- u8 inqd_dtq; /* RMB | Device Type Qualifier */
- u8 inqd_ver; /* ISO version | ECMA version | ANSI-approved version */
- u8 inqd_rdf; /* AENC | TrmIOP | Response data format */
- u8 inqd_len; /* Additional length (n-4) */
- u8 inqd_pad1[2];/* Reserved - must be zero */
- u8 inqd_pad2; /* RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */
- u8 inqd_vid[8]; /* Vendor ID */
- u8 inqd_pid[16];/* Product ID */
- u8 inqd_prl[4]; /* Product Revision Level */
- };
- struct sense_data {
- u8 error_code; /* 70h (current errors), 71h(deferred errors) */
- u8 valid:1; /* A valid bit of one indicates that the information */
- /* field contains valid information as defined in the
- * SCSI-2 Standard.
- */
- u8 segment_number; /* Only used for COPY, COMPARE, or COPY AND VERIFY Commands */
- u8 sense_key:4; /* Sense Key */
- u8 reserved:1;
- u8 ILI:1; /* Incorrect Length Indicator */
- u8 EOM:1; /* End Of Medium - reserved for random access devices */
- u8 filemark:1; /* Filemark - reserved for random access devices */
- u8 information[4]; /* for direct-access devices, contains the unsigned
- * logical block address or residue associated with
- * the sense key
- */
- u8 add_sense_len; /* number of additional sense bytes to follow this field */
- u8 cmnd_info[4]; /* not used */
- u8 ASC; /* Additional Sense Code */
- u8 ASCQ; /* Additional Sense Code Qualifier */
- u8 FRUC; /* Field Replaceable Unit Code - not used */
- u8 bit_ptr:3; /* indicates which byte of the CDB or parameter data
- * was in error
- */
- u8 BPV:1; /* bit pointer valid (BPV): 1- indicates that
- * the bit_ptr field has valid value
- */
- u8 reserved2:2;
- u8 CD:1; /* command data bit: 1- illegal parameter in CDB.
- * 0- illegal parameter in data.
- */
- u8 SKSV:1;
- u8 field_ptr[2]; /* byte of the CDB or parameter data in error */
- };
- /*
- * M O D U L E G L O B A L S
- */
-
- static struct fsa_scsi_hba *fsa_dev[MAXIMUM_NUM_ADAPTERS]; /* SCSI Device Instance Pointers */
- static struct sense_data sense_data[MAXIMUM_NUM_CONTAINERS];
- static void get_sd_devname(int disknum, char *buffer);
- /**
- * aac_get_containers - list containers
- * @common: adapter to probe
- *
- * Make a list of all containers on this controller
- */
- int aac_get_containers(struct aac_dev *dev)
- {
- struct fsa_scsi_hba *fsa_dev_ptr;
- int index, status = 0;
- struct aac_query_mount *dinfo;
- struct aac_mount *dresp;
- struct fib * fibptr;
- unsigned instance;
- fsa_dev_ptr = &(dev->fsa_dev);
- instance = dev->scsi_host_ptr->unique_id;
- if (!(fibptr = fib_alloc(dev)))
- return -ENOMEM;
- for (index = 0; index < MAXIMUM_NUM_CONTAINERS; index++) {
- fib_init(fibptr);
- dinfo = (struct aac_query_mount *) fib_data(fibptr);
- dinfo->command = cpu_to_le32(VM_NameServe);
- dinfo->count = cpu_to_le32(index);
- dinfo->type = cpu_to_le32(FT_FILESYS);
- status = fib_send(ContainerCommand,
- fibptr,
- sizeof (struct aac_query_mount),
- FsaNormal,
- 1, 1,
- NULL, NULL);
- if (status < 0 ) {
- printk(KERN_WARNING "ProbeContainers: SendFIB failed.n");
- break;
- }
- dresp = (struct aac_mount *)fib_data(fibptr);
- if ((le32_to_cpu(dresp->status) == ST_OK) &&
- (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
- fsa_dev_ptr->valid[index] = 1;
- fsa_dev_ptr->type[index] = le32_to_cpu(dresp->mnt[0].vol);
- fsa_dev_ptr->size[index] = le32_to_cpu(dresp->mnt[0].capacity);
- if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
- fsa_dev_ptr->ro[index] = 1;
- }
- fib_complete(fibptr);
- /*
- * If there are no more containers, then stop asking.
- */
- if ((index + 1) >= le32_to_cpu(dresp->count))
- break;
- }
- fib_free(fibptr);
- fsa_dev[instance] = fsa_dev_ptr;
- return status;
- }
- /**
- * probe_container - query a logical volume
- * @dev: device to query
- * @cid: container identifier
- *
- * Queries the controller about the given volume. The volume information
- * is updated in the struct fsa_scsi_hba structure rather than returned.
- */
-
- static int probe_container(struct aac_dev *dev, int cid)
- {
- struct fsa_scsi_hba *fsa_dev_ptr;
- int status;
- struct aac_query_mount *dinfo;
- struct aac_mount *dresp;
- struct fib * fibptr;
- unsigned instance;
- fsa_dev_ptr = &(dev->fsa_dev);
- instance = dev->scsi_host_ptr->unique_id;
- if (!(fibptr = fib_alloc(dev)))
- return -ENOMEM;
- fib_init(fibptr);
- dinfo = (struct aac_query_mount *)fib_data(fibptr);
- dinfo->command = cpu_to_le32(VM_NameServe);
- dinfo->count = cpu_to_le32(cid);
- dinfo->type = cpu_to_le32(FT_FILESYS);
- status = fib_send(ContainerCommand,
- fibptr,
- sizeof(struct aac_query_mount),
- FsaNormal,
- 1, 1,
- NULL, NULL);
- if (status < 0) {
- printk(KERN_WARNING "aacraid: probe_containers query failed.n");
- goto error;
- }
- dresp = (struct aac_mount *) fib_data(fibptr);
- if ((le32_to_cpu(dresp->status) == ST_OK) &&
- (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
- fsa_dev_ptr->valid[cid] = 1;
- fsa_dev_ptr->type[cid] = le32_to_cpu(dresp->mnt[0].vol);
- fsa_dev_ptr->size[cid] = le32_to_cpu(dresp->mnt[0].capacity);
- if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
- fsa_dev_ptr->ro[cid] = 1;
- }
- error:
- fib_complete(fibptr);
- fib_free(fibptr);
- return status;
- }
- /* Local Structure to set SCSI inquiry data strings */
- struct scsi_inq {
- char vid[8]; /* Vendor ID */
- char pid[16]; /* Product ID */
- char prl[4]; /* Product Revision Level */
- };
- /**
- * InqStrCopy - string merge
- * @a: string to copy from
- * @b: string to copy to
- *
- * Copy a String from one location to another
- * without copying