⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aachba.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *	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/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 <linux/blkdev.h>#include <asm/semaphore.h>#include <asm/uaccess.h>#include <scsi/scsi.h>#include <scsi/scsi_cmnd.h>#include <scsi/scsi_device.h>#include <scsi/scsi_host.h>#include "aacraid.h"/* 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 *//* *	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 */};/* *              M O D U L E   G L O B A L S */ static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* sgmap);static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg);static unsigned long aac_build_sgraw(struct scsi_cmnd* scsicmd, struct sgmapraw* psg);static int aac_send_srb_fib(struct scsi_cmnd* scsicmd);#ifdef AAC_DETAILED_STATUS_INFOstatic char *aac_get_status_string(u32 status);#endif/* *	Non dasd selection is handled entirely in aachba now */	 static int nondasd = -1;static int dacmode = -1;static int commit = -1;module_param(nondasd, int, 0);MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");module_param(dacmode, int, 0);MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0=off, 1=on");module_param(commit, int, 0);MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");int numacb = -1;module_param(numacb, int, S_IRUGO|S_IWUSR);MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid\nvalues are 512 and down. Default is to use suggestion from Firmware.");int acbsize = -1;module_param(acbsize, int, S_IRUGO|S_IWUSR);MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512,\n2048, 4096 and 8192. Default is to use suggestion from Firmware.");/** *	aac_get_config_status	-	check the adapter configuration *	@common: adapter to query * *	Query config status, and commit the configuration if needed. */int aac_get_config_status(struct aac_dev *dev){	int status = 0;	struct fib * fibptr;	if (!(fibptr = fib_alloc(dev)))		return -ENOMEM;	fib_init(fibptr);	{		struct aac_get_config_status *dinfo;		dinfo = (struct aac_get_config_status *) fib_data(fibptr);		dinfo->command = cpu_to_le32(VM_ContainerConfig);		dinfo->type = cpu_to_le32(CT_GET_CONFIG_STATUS);		dinfo->count = cpu_to_le32(sizeof(((struct aac_get_config_status_resp *)NULL)->data));	}	status = fib_send(ContainerCommand,			    fibptr,			    sizeof (struct aac_get_config_status),			    FsaNormal,			    1, 1,			    NULL, NULL);	if (status < 0 ) {		printk(KERN_WARNING "aac_get_config_status: SendFIB failed.\n");	} else {		struct aac_get_config_status_resp *reply		  = (struct aac_get_config_status_resp *) fib_data(fibptr);		dprintk((KERN_WARNING		  "aac_get_config_status: response=%d status=%d action=%d\n",		  le32_to_cpu(reply->response),		  le32_to_cpu(reply->status),		  le32_to_cpu(reply->data.action)));		if ((le32_to_cpu(reply->response) != ST_OK) ||		     (le32_to_cpu(reply->status) != CT_OK) ||		     (le32_to_cpu(reply->data.action) > CFACT_PAUSE)) {			printk(KERN_WARNING "aac_get_config_status: Will not issue the Commit Configuration\n");			status = -EINVAL;		}	}	fib_complete(fibptr);	/* Send a CT_COMMIT_CONFIG to enable discovery of devices */	if (status >= 0) {		if (commit == 1) {			struct aac_commit_config * dinfo;			fib_init(fibptr);			dinfo = (struct aac_commit_config *) fib_data(fibptr);				dinfo->command = cpu_to_le32(VM_ContainerConfig);			dinfo->type = cpu_to_le32(CT_COMMIT_CONFIG);				status = fib_send(ContainerCommand,				    fibptr,				    sizeof (struct aac_commit_config),				    FsaNormal,				    1, 1,				    NULL, NULL);			fib_complete(fibptr);		} else if (commit == 0) {			printk(KERN_WARNING			  "aac_get_config_status: Foreign device configurations are being ignored\n");		}	}	fib_free(fibptr);	return status;}/** *	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_dev_info *fsa_dev_ptr;	u32 index; 	int status = 0;	struct fib * fibptr;	unsigned instance;	struct aac_get_container_count *dinfo;	struct aac_get_container_count_resp *dresp;	int maximum_num_containers = MAXIMUM_NUM_CONTAINERS;	instance = dev->scsi_host_ptr->unique_id;	if (!(fibptr = fib_alloc(dev)))		return -ENOMEM;	fib_init(fibptr);	dinfo = (struct aac_get_container_count *) fib_data(fibptr);	dinfo->command = cpu_to_le32(VM_ContainerConfig);	dinfo->type = cpu_to_le32(CT_GET_CONTAINER_COUNT);	status = fib_send(ContainerCommand,		    fibptr,		    sizeof (struct aac_get_container_count),		    FsaNormal,		    1, 1,		    NULL, NULL);	if (status >= 0) {		dresp = (struct aac_get_container_count_resp *)fib_data(fibptr);		maximum_num_containers = le32_to_cpu(dresp->ContainerSwitchEntries);		fib_complete(fibptr);	}	if (maximum_num_containers < MAXIMUM_NUM_CONTAINERS)		maximum_num_containers = MAXIMUM_NUM_CONTAINERS;	fsa_dev_ptr = (struct fsa_dev_info *) kmalloc(	  sizeof(*fsa_dev_ptr) * maximum_num_containers, GFP_KERNEL);	if (!fsa_dev_ptr) {		fib_free(fibptr);		return -ENOMEM;	}	memset(fsa_dev_ptr, 0, sizeof(*fsa_dev_ptr) * maximum_num_containers);	dev->fsa_dev = fsa_dev_ptr;	dev->maximum_num_containers = maximum_num_containers;	for (index = 0; index < dev->maximum_num_containers; index++) {		struct aac_query_mount *dinfo;		struct aac_mount *dresp;		fsa_dev_ptr[index].devname[0] = '\0';		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 "aac_get_containers: 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)) {			dinfo->command = cpu_to_le32(VM_NameServe64);			dinfo->count = cpu_to_le32(index);			dinfo->type = cpu_to_le32(FT_FILESYS);			if (fib_send(ContainerCommand,				    fibptr,				    sizeof(struct aac_query_mount),				    FsaNormal,				    1, 1,				    NULL, NULL) < 0)				continue;		} else			dresp->mnt[0].capacityhigh = 0;		dprintk ((KERN_DEBUG		  "VM_NameServe cid=%d status=%d vol=%d state=%d cap=%llu\n",		  (int)index, (int)le32_to_cpu(dresp->status),		  (int)le32_to_cpu(dresp->mnt[0].vol),		  (int)le32_to_cpu(dresp->mnt[0].state),		  ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +		    (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32)));		if ((le32_to_cpu(dresp->status) == ST_OK) &&		    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE) &&		    (le32_to_cpu(dresp->mnt[0].state) != FSCS_HIDDEN)) {			fsa_dev_ptr[index].valid = 1;			fsa_dev_ptr[index].type = le32_to_cpu(dresp->mnt[0].vol);			fsa_dev_ptr[index].size			  = ((u64)le32_to_cpu(dresp->mnt[0].capacity)) +			    (((u64)le32_to_cpu(dresp->mnt[0].capacityhigh)) << 32);			if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)				    fsa_dev_ptr[index].ro = 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);	return status;}static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len){	void *buf;	unsigned int transfer_len;	struct scatterlist *sg = scsicmd->request_buffer;	if (scsicmd->use_sg) {		buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;		transfer_len = min(sg->length, len + offset);	} else {		buf = scsicmd->request_buffer;		transfer_len = min(scsicmd->request_bufflen, len + offset);	}	memcpy(buf + offset, data, transfer_len - offset);	if (scsicmd->use_sg) 		kunmap_atomic(buf - sg->offset, KM_IRQ0);}static void get_container_name_callback(void *context, struct fib * fibptr){	struct aac_get_name_resp * get_name_reply;	struct scsi_cmnd * scsicmd;	scsicmd = (struct scsi_cmnd *) context;	dprintk((KERN_DEBUG "get_container_name_callback[cpu %d]: t = %ld.\n", smp_processor_id(), jiffies));	if (fibptr == NULL)		BUG();	get_name_reply = (struct aac_get_name_resp *) fib_data(fibptr);	/* Failure is irrelevant, using default value instead */	if ((le32_to_cpu(get_name_reply->status) == CT_OK)	 && (get_name_reply->data[0] != '\0')) {		char *sp = get_name_reply->data;		sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0';		while (*sp == ' ')			++sp;		if (*sp) {			char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)];			int count = sizeof(d);			char *dp = d;			do {				*dp++ = (*sp) ? *sp++ : ' ';			} while (--count > 0);			aac_internal_transfer(scsicmd, d, 			  offsetof(struct inquiry_data, inqd_pid), sizeof(d));		}	}	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;	fib_complete(fibptr);	fib_free(fibptr);	scsicmd->scsi_done(scsicmd);}/** *	aac_get_container_name	-	get container name, none blocking. */static int aac_get_container_name(struct scsi_cmnd * scsicmd, int cid){	int status;	struct aac_get_name *dinfo;	struct fib * cmd_fibcontext;	struct aac_dev * dev;	dev = (struct aac_dev *)scsicmd->device->host->hostdata;	if (!(cmd_fibcontext = fib_alloc(dev)))		return -ENOMEM;	fib_init(cmd_fibcontext);	dinfo = (struct aac_get_name *) fib_data(cmd_fibcontext);	dinfo->command = cpu_to_le32(VM_ContainerConfig);	dinfo->type = cpu_to_le32(CT_READ_NAME);	dinfo->cid = cpu_to_le32(cid);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -