📄 aachba.c
字号:
/* * 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 \0 */static void inqstrcpy(char *a, char *b){ while(*a != (char)0) *b++ = *a++;}static char *container_types[] = { "None", "Volume", "Mirror", "Stripe", "RAID5", "SSRW", "SSRO", "Morph", "Legacy", "RAID4", "RAID10", "RAID00", "V-MIRRORS", "PSEUDO R4", "RAID50", "Unknown"};/* Function: setinqstr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -