aachba.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,204 行 · 第 1/5 页

C
2,204
字号
			set_sense((u8 *) &dev->fsa_dev[cid].sense_data,				ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,				ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);			memcpy(scsicmd->sense_buffer, &dev->fsa_dev[cid].sense_data,			  (sizeof(dev->fsa_dev[cid].sense_data) > sizeof(scsicmd->sense_buffer))			    ? sizeof(scsicmd->sense_buffer)			    : 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 = qd.id;	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;	scsicmd->SCp.phase = AAC_OWNER_MIDLEVEL;	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:		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: {			scsicmd->result = DID_OK << 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);	aac_fib_complete(fibptr);	aac_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 (scmd_id(scsicmd) >= dev->maximum_num_physicals ||			scsicmd->device->lun > 7) {		scsicmd->result = DID_NO_CONNECT << 16;		scsicmd->scsi_done(scsicmd);		return 0;	}	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 = aac_fib_alloc(dev))) {		return -1;	}	aac_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(scmd_channel(scsicmd)));	srbcmd->id   = cpu_to_le32(scmd_id(scsicmd));	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 = aac_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 adapter		 */		status = aac_fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, FsaNormal, 0, 1,				  (fib_callback) aac_srb_callback, (void *) scsicmd);	}	/*	 *	Check that the command queued to the controller	 */	if (status == -EINPROGRESS) {		scsicmd->SCp.phase = AAC_OWNER_FIRMWARE;		return 0;	}	printk(KERN_WARNING "aac_srb: aac_fib_send failed with status: %d\n", status);	aac_fib_complete(cmd_fibcontext);	aac_fib_free(cmd_fibcontext);	return -1;}static unsigned long aac_build_sg(struct scsi_cmnd* scsicmd, struct sgmap* psg){	struct aac_dev *dev;	unsigned long byte_count = 0;	dev = (struct aac_dev *)scsicmd->device->host->hostdata;	// Get rid of old data	psg->count = 0;	psg->sg[0].addr = 0;	psg->sg[0].count = 0;  	if (scsicmd->use_sg) {		struct scatterlist *sg;		int i;		int sg_count;		sg = (struct scatterlist *) scsicmd->request_buffer;		sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,			scsicmd->sc_data_direction);		psg->count = cpu_to_le32(sg_count);		for (i = 0; i < sg_count; i++) {			psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));			psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));			byte_count += sg_dma_len(s

⌨️ 快捷键说明

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