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

📄 aachba.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
}/** * * 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 - 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 = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?				sizeof(scsicmd->sense_buffer):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) &&					(scsicmd->device->channel == 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:			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) &&					(scsicmd->device->channel == 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 = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?				sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;#ifdef AAC_DETAILED_STATUS_INFO		dprintk((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);	aac_io_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;	if( scsicmd->device->id > 15 || 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-jiffies)/HZ;	if(timeout == 0){		timeout = 1;	}	srbcmd->timeout  = cpu_to_le32(timeout);  // timeout in seconds	srbcmd->retry_limit =cpu_to_le32(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) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64));		/*		 *	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) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));		/*		 *	Now send the Fib to the adapter		 */		status = 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){		return 0;	}	printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status);	fib_complete(cmd_fibcontext);	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 = cpu_to_le32(0);	psg->sg[0].addr = cpu_to_le32(0);	psg->sg[0].count = cpu_to_le32(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);		byte_count = 0;		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(sg);			sg++;		}		/* hba wants the size to be exact */		if(byte_count > scsicmd->request_bufflen){			psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);			byte_count = scsicmd->request_bufflen;		}		/* Check for command underflow */		if(scsicmd->underflow && (byte_count < scsicmd->underflow)){			printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",					byte_count, scsicmd->underflow);		}	}	else if(scsicmd->request_bufflen) {		dma_addr_t addr; 		addr = pci_map_single(dev->pdev,				scsicmd->request_buffer,				scsicmd->request_bufflen,				scsicmd->sc_data_direction);		psg->count = cpu_to_le32(1);		psg->sg[0].addr = cpu_to_le32(addr);		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  		scsicmd->SCp.dma_handle = addr;		byte_count = scsicmd->request_bufflen;	}	return byte_count;}static unsigned long aac_build_sg64(struct scsi_cmnd* scsicmd, struct sgmap64* psg){	struct aac_dev *dev;	unsigned long byte_count = 0;	u64 le_addr;	dev = (struct aac_dev *)scsicmd->device->host->hostdata;	// Get rid of old data	psg->count = cpu_to_le32(0);	psg->sg[0].addr[0] = cpu_to_le32(0);	psg->sg[0].addr[1] = cpu_to_le32(0);	psg->sg[0].count = cpu_to_le32(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);		byte_count = 0;		for (i = 0; i < sg_count; i++) {			le_addr = cpu_to_le64(sg_dma_address(sg));			psg->sg[i].addr[1] = (u32)(le_addr>>32);			psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);			psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));			byte_count += sg_dma_len(sg);			sg++;		}		/* hba wants the size to be exact */		if(byte_count > scsicmd->request_bufflen){			psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);			byte_count = scsicmd->request_bufflen;		}		/* Check for command underflow */		if(scsicmd->underflow && (byte_count < scsicmd->underflow)){			printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",					byte_count, scsicmd->underflow);		}	}	else if(scsicmd->request_bufflen) {		dma_addr_t addr; 		addr = pci_map_single(dev->pdev,				scsicmd->request_buffer,				scsicmd->request_bufflen,				scsicmd->sc_data_direction);		psg->count = cpu_to_le32(1);		le_addr = cpu_to_le64(addr);		psg->sg[0].addr[1] = (u32)(le_addr>>32);		psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff);		psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  		scsicmd->SCp.dma_handle = addr;		byte_count = scsicmd->request_bufflen;	}	return byte_count;}#ifdef AAC_DETAILED_STATUS_INFOstruct aac_srb_status_info {	u32	status;	char	*str;};static struct aac_srb_status_info srb_status_info[] = {	{ SRB_STATUS_PENDING,		"Pending Status"},	{ SRB_STATUS_SUCCESS,		"Success"},	{ SRB_STATUS_ABORTED,		"Aborted Command"},	{ SRB_STATUS_ABORT_FAILED,	"Abort Failed"},	{ SRB_STATUS_ERROR,		"Error Event"}, 	{ SRB_STATUS_BUSY,		"Device Busy"},	{ SRB_STATUS_INVALID_REQUEST,	"Invalid Request"},	{ SRB_STATUS_INVALID_PATH_ID,	"Invalid Path ID"},	{ SRB_STATUS_NO_DEVICE,		"No Device"},	{ SRB_STATUS_TIMEOUT,		"Timeout"},	{ SRB_STATUS_SELECTION_TIMEOUT,	"Selection Timeout"},	{ SRB_STATUS_COMMAND_TIMEOUT,	"Command Timeout"},	{ SRB_STATUS_MESSAGE_REJECTED,	"Message Rejected"},	{ SRB_STATUS_BUS_RESET,		"Bus Reset"},	{ SRB_STATUS_PARITY_ERROR,	"Parity Error"},	{ SRB_STATUS_REQUEST_SENSE_FAILED,"Request Sense Failed"},	{ SRB_STATUS_NO_HBA,		"No HBA"},	{ SRB_STATUS_DATA_OVERRUN,	"Data Overrun/Data Underrun"},	{ SRB_STATUS_UNEXPECTED_BUS_FREE,"Unexpected Bus Free"},	{ SRB_STATUS_PHASE_SEQUENCE_FAILURE,"Phase Error"},	{ SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"},	{ SRB_STATUS_REQUEST_FLUSHED,	"Request Flushed"},	{ SRB_STATUS_DELAYED_RETRY,	"Delayed Retry"},	{ SRB_STATUS_INVALID_LUN,	"Invalid LUN"}, 	{ SRB_STATUS_INVALID_TARGET_ID,	"Invalid TARGET ID"},	{ SRB_STATUS_BAD_FUNCTION,	"Bad Function"},	{ SRB_STATUS_ERROR_RECOVERY,	"Error Recovery"},	{ SRB_STATUS_NOT_STARTED,	"Not Started"},	{ SRB_STATUS_NOT_IN_USE,	"Not In Use"},    	{ SRB_STATUS_FORCE_ABORT,	"Force Abort"},	{ SRB_STATUS_DOMAIN_VALIDATION_FAIL,"Domain Validation Failure"},	{ 0xff,				"Unknown Error"}};char *aac_get_status_string(u32 status){	int i;	for(i=0; i < (sizeof(srb_status_info)/sizeof(struct aac_srb_status_info)); i++ ){		if(srb_status_info[i].status == status){			return srb_status_info[i].str;		}	}	return "Bad Status Code";}#endif

⌨️ 快捷键说明

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