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

📄 aachba.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			    : sizeof(dev->fsa_dev[cid].sense_data));			scsicmd->scsi_done(scsicmd);			return 0;	}}static int query_disk(struct aac_dev *dev, void __user *arg){	struct aac_query_disk qd;	struct fsa_dev_info *fsa_dev_ptr;	fsa_dev_ptr = dev->fsa_dev;	if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))		return -EFAULT;	if (qd.cnum == -1)		qd.cnum = ID_LUN_TO_CONTAINER(qd.id, qd.lun);	else if ((qd.bus == -1) && (qd.id == -1) && (qd.lun == -1)) 	{		if (qd.cnum < 0 || qd.cnum >= dev->maximum_num_containers)			return -EINVAL;		qd.instance = dev->scsi_host_ptr->host_no;		qd.bus = 0;		qd.id = CONTAINER_TO_ID(qd.cnum);		qd.lun = CONTAINER_TO_LUN(qd.cnum);	}	else return -EINVAL;	qd.valid = fsa_dev_ptr[qd.cnum].valid;	qd.locked = fsa_dev_ptr[qd.cnum].locked;	qd.deleted = fsa_dev_ptr[qd.cnum].deleted;	if (fsa_dev_ptr[qd.cnum].devname[0] == '\0')		qd.unmapped = 1;	else		qd.unmapped = 0;	strlcpy(qd.name, fsa_dev_ptr[qd.cnum].devname,	  min(sizeof(qd.name), sizeof(fsa_dev_ptr[qd.cnum].devname) + 1));	if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk)))		return -EFAULT;	return 0;}static int force_delete_disk(struct aac_dev *dev, void __user *arg){	struct aac_delete_disk dd;	struct fsa_dev_info *fsa_dev_ptr;	fsa_dev_ptr = dev->fsa_dev;	if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))		return -EFAULT;	if (dd.cnum >= dev->maximum_num_containers)		return -EINVAL;	/*	 *	Mark this container as being deleted.	 */	fsa_dev_ptr[dd.cnum].deleted = 1;	/*	 *	Mark the container as no longer valid	 */	fsa_dev_ptr[dd.cnum].valid = 0;	return 0;}static int delete_disk(struct aac_dev *dev, void __user *arg){	struct aac_delete_disk dd;	struct fsa_dev_info *fsa_dev_ptr;	fsa_dev_ptr = dev->fsa_dev;	if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))		return -EFAULT;	if (dd.cnum >= dev->maximum_num_containers)		return -EINVAL;	/*	 *	If the container is locked, it can not be deleted by the API.	 */	if (fsa_dev_ptr[dd.cnum].locked)		return -EBUSY;	else {		/*		 *	Mark the container as no longer being valid.		 */		fsa_dev_ptr[dd.cnum].valid = 0;		fsa_dev_ptr[dd.cnum].devname[0] = '\0';		return 0;	}}int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg){	switch (cmd) {	case FSACTL_QUERY_DISK:		return query_disk(dev, arg);	case FSACTL_DELETE_DISK:		return delete_disk(dev, arg);	case FSACTL_FORCE_DELETE_DISK:		return force_delete_disk(dev, arg);	case FSACTL_GET_CONTAINERS:		return aac_get_containers(dev);	default:		return -ENOTTY;	}}/** * * aac_srb_callback * @context: the context set in the fib - here it is scsi cmd * @fibptr: pointer to the fib * * Handles the completion of a scsi command to a non dasd device * */static void aac_srb_callback(void *context, struct fib * fibptr){	struct aac_dev *dev;	struct aac_srb_reply *srbreply;	struct scsi_cmnd *scsicmd;	scsicmd = (struct scsi_cmnd *) context;	dev = (struct aac_dev *)scsicmd->device->host->hostdata;	if (fibptr == NULL)		BUG();	srbreply = (struct aac_srb_reply *) fib_data(fibptr);	scsicmd->sense_buffer[0] = '\0';  /* Initialize sense valid flag to false */	/*	 *	Calculate resid for sg 	 */	 	scsicmd->resid = scsicmd->request_bufflen - 		le32_to_cpu(srbreply->data_xfer_length);	if(scsicmd->use_sg)		pci_unmap_sg(dev->pdev, 			(struct scatterlist *)scsicmd->buffer,			scsicmd->use_sg,			scsicmd->sc_data_direction);	else if(scsicmd->request_bufflen)		pci_unmap_single(dev->pdev, scsicmd->SCp.dma_handle, scsicmd->request_bufflen,			scsicmd->sc_data_direction);	/*	 * First check the fib status	 */	if (le32_to_cpu(srbreply->status) != ST_OK){		int len;		printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", le32_to_cpu(srbreply->status));		len = (le32_to_cpu(srbreply->sense_data_size) > 				sizeof(scsicmd->sense_buffer)) ?				sizeof(scsicmd->sense_buffer) : 				le32_to_cpu(srbreply->sense_data_size);		scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;		memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);	}	/*	 * Next check the srb status	 */	switch( (le32_to_cpu(srbreply->srb_status))&0x3f){	case SRB_STATUS_ERROR_RECOVERY:	case SRB_STATUS_PENDING:	case SRB_STATUS_SUCCESS:		if(scsicmd->cmnd[0] == INQUIRY ){			u8 b;			u8 b1;			/* We can't expose disk devices because we can't tell whether they			 * are the raw container drives or stand alone drives.  If they have			 * the removable bit set then we should expose them though.			 */			b = (*(u8*)scsicmd->buffer)&0x1f;			b1 = ((u8*)scsicmd->buffer)[1];			if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER 					|| (b==TYPE_DISK && (b1&0x80)) ){				scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;			/*			 * We will allow disk devices if in RAID/SCSI mode and			 * the channel is 2			 */			} else if ((dev->raid_scsi_mode) &&					(scmd_channel(scsicmd) == 2)) {				scsicmd->result = DID_OK << 16 | 						COMMAND_COMPLETE << 8;			} else {				scsicmd->result = DID_NO_CONNECT << 16 | 						COMMAND_COMPLETE << 8;			}		} else {			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;		}		break;	case SRB_STATUS_DATA_OVERRUN:		switch(scsicmd->cmnd[0]){		case  READ_6:		case  WRITE_6:		case  READ_10:		case  WRITE_10:		case  READ_12:		case  WRITE_12:		case  READ_16:		case  WRITE_16:			if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) {				printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");			} else {				printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n");			}			scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;			break;		case INQUIRY: {			u8 b;			u8 b1;			/* We can't expose disk devices because we can't tell whether they			* are the raw container drives or stand alone drives			*/			b = (*(u8*)scsicmd->buffer)&0x0f;			b1 = ((u8*)scsicmd->buffer)[1];			if( b==TYPE_TAPE || b==TYPE_WORM || b==TYPE_ROM || b==TYPE_MOD|| b==TYPE_MEDIUM_CHANGER					|| (b==TYPE_DISK && (b1&0x80)) ){				scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;			/*			 * We will allow disk devices if in RAID/SCSI mode and			 * the channel is 2			 */			} else if ((dev->raid_scsi_mode) &&					(scmd_channel(scsicmd) == 2)) {				scsicmd->result = DID_OK << 16 | 						COMMAND_COMPLETE << 8;			} else {				scsicmd->result = DID_NO_CONNECT << 16 | 						COMMAND_COMPLETE << 8;			}			break;		}		default:			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;			break;		}		break;	case SRB_STATUS_ABORTED:		scsicmd->result = DID_ABORT << 16 | ABORT << 8;		break;	case SRB_STATUS_ABORT_FAILED:		// Not sure about this one - but assuming the hba was trying to abort for some reason		scsicmd->result = DID_ERROR << 16 | ABORT << 8;		break;	case SRB_STATUS_PARITY_ERROR:		scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8;		break;	case SRB_STATUS_NO_DEVICE:	case SRB_STATUS_INVALID_PATH_ID:	case SRB_STATUS_INVALID_TARGET_ID:	case SRB_STATUS_INVALID_LUN:	case SRB_STATUS_SELECTION_TIMEOUT:		scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;		break;	case SRB_STATUS_COMMAND_TIMEOUT:	case SRB_STATUS_TIMEOUT:		scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8;		break;	case SRB_STATUS_BUSY:		scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;		break;	case SRB_STATUS_BUS_RESET:		scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8;		break;	case SRB_STATUS_MESSAGE_REJECTED:		scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8;		break;	case SRB_STATUS_REQUEST_FLUSHED:	case SRB_STATUS_ERROR:	case SRB_STATUS_INVALID_REQUEST:	case SRB_STATUS_REQUEST_SENSE_FAILED:	case SRB_STATUS_NO_HBA:	case SRB_STATUS_UNEXPECTED_BUS_FREE:	case SRB_STATUS_PHASE_SEQUENCE_FAILURE:	case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:	case SRB_STATUS_DELAYED_RETRY:	case SRB_STATUS_BAD_FUNCTION:	case SRB_STATUS_NOT_STARTED:	case SRB_STATUS_NOT_IN_USE:	case SRB_STATUS_FORCE_ABORT:	case SRB_STATUS_DOMAIN_VALIDATION_FAIL:	default:#ifdef AAC_DETAILED_STATUS_INFO		printk("aacraid: SRB ERROR(%u) %s scsi cmd 0x%x - scsi status 0x%x\n",			le32_to_cpu(srbreply->srb_status) & 0x3F,			aac_get_status_string(				le32_to_cpu(srbreply->srb_status) & 0x3F), 			scsicmd->cmnd[0], 			le32_to_cpu(srbreply->scsi_status));#endif		scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;		break;	}	if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){  // Check Condition		int len;		scsicmd->result |= SAM_STAT_CHECK_CONDITION;		len = (le32_to_cpu(srbreply->sense_data_size) > 				sizeof(scsicmd->sense_buffer)) ?				sizeof(scsicmd->sense_buffer) :				le32_to_cpu(srbreply->sense_data_size);#ifdef AAC_DETAILED_STATUS_INFO		printk(KERN_WARNING "aac_srb_callback: check condition, status = %d len=%d\n",					le32_to_cpu(srbreply->status), len);#endif		memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);			}	/*	 * OR in the scsi status (already shifted up a bit)	 */	scsicmd->result |= le32_to_cpu(srbreply->scsi_status);	fib_complete(fibptr);	fib_free(fibptr);	scsicmd->scsi_done(scsicmd);}/** * * aac_send_scb_fib * @scsicmd: the scsi command block * * This routine will form a FIB and fill in the aac_srb from the  * scsicmd passed in. */static int aac_send_srb_fib(struct scsi_cmnd* scsicmd){	struct fib* cmd_fibcontext;	struct aac_dev* dev;	int status;	struct aac_srb *srbcmd;	u16 fibsize;	u32 flag;	u32 timeout;	dev = (struct aac_dev *)scsicmd->device->host->hostdata;	if (scsicmd->device->id >= dev->maximum_num_physicals || 			scsicmd->device->lun > 7) {		scsicmd->result = DID_NO_CONNECT << 16;		scsicmd->scsi_done(scsicmd);		return 0;	}	dev = (struct aac_dev *)scsicmd->device->host->hostdata;	switch(scsicmd->sc_data_direction){	case DMA_TO_DEVICE:		flag = SRB_DataOut;		break;	case DMA_BIDIRECTIONAL:		flag = SRB_DataIn | SRB_DataOut;		break;	case DMA_FROM_DEVICE:		flag = SRB_DataIn;		break;	case DMA_NONE:	default:	/* shuts up some versions of gcc */		flag = SRB_NoDataXfer;		break;	}	/*	 *	Allocate and initialize a Fib then setup a BlockWrite command	 */	if (!(cmd_fibcontext = fib_alloc(dev))) {		return -1;	}	fib_init(cmd_fibcontext);	srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);	srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scsicmd->device->channel));	srbcmd->id   = cpu_to_le32(scsicmd->device->id);	srbcmd->lun      = cpu_to_le32(scsicmd->device->lun);	srbcmd->flags    = cpu_to_le32(flag);	timeout = scsicmd->timeout_per_command/HZ;	if(timeout == 0){		timeout = 1;	}	srbcmd->timeout  = cpu_to_le32(timeout);  // timeout in seconds	srbcmd->retry_limit = 0; /* Obsolete parameter */	srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len);		if( dev->dac_support == 1 ) {		aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg);		srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);		memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));		memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len);		/*		 *	Build Scatter/Gather list		 */		fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +			((le32_to_cpu(srbcmd->sg.count) & 0xff) * 			 sizeof (struct sgentry64));		BUG_ON (fibsize > (dev->max_fib_size -					sizeof(struct aac_fibhdr)));		/*		 *	Now send the Fib to the adapter		 */		status = fib_send(ScsiPortCommand64, cmd_fibcontext, 				fibsize, FsaNormal, 0, 1,				  (fib_callback) aac_srb_callback, 				  (void *) scsicmd);	} else {		aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg);		srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);		memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));		memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len);		/*		 *	Build Scatter/Gather list		 */		fibsize = sizeof (struct aac_srb) + 			(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * 			 sizeof (struct sgentry));		BUG_ON (fibsize > (dev->max_fib_size -					sizeof(struct aac_fibhdr)));		/*		 *	Now send the Fib to the adapte

⌨️ 快捷键说明

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