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

📄 megaraid_mbox.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
 * convert the command issued by mid-layer to format understood by megaraid * firmware. We also complete certain command without sending them to firmware */static scb_t *megaraid_mbox_build_cmd(adapter_t *adapter, struct scsi_cmnd *scp, int *busy){	mraid_device_t		*rdev = ADAP2RAIDDEV(adapter);	int			channel;	int			target;	int			islogical;	mbox_ccb_t		*ccb;	mraid_passthru_t	*pthru;	mbox64_t		*mbox64;	mbox_t			*mbox;	scb_t			*scb;	char			skip[] = "skipping";	char			scan[] = "scanning";	char			*ss;	/*	 * Get the appropriate device map for the device this command is	 * intended for	 */	MRAID_GET_DEVICE_MAP(adapter, scp, channel, target, islogical);	/*	 * Logical drive commands	 */	if (islogical) {		switch (scp->cmnd[0]) {		case TEST_UNIT_READY:			/*			 * Do we support clustering and is the support enabled			 * If no, return success always			 */			if (!adapter->ha) {				scp->result = (DID_OK << 16);				return NULL;			}			if (!(scb = megaraid_alloc_scb(adapter, scp))) {				scp->result = (DID_ERROR << 16);				*busy = 1;				return NULL;			}			scb->dma_direction	= scp->sc_data_direction;			scb->dev_channel	= 0xFF;			scb->dev_target		= target;			ccb			= (mbox_ccb_t *)scb->ccb;			/*			 * The command id will be provided by the command			 * issuance routine			 */			ccb->raw_mbox[0]	= CLUSTER_CMD;			ccb->raw_mbox[2]	= RESERVATION_STATUS;			ccb->raw_mbox[3]	= target;			return scb;		case MODE_SENSE:			if (scp->use_sg) {				struct scatterlist	*sgl;				caddr_t			vaddr;				sgl = (struct scatterlist *)scp->request_buffer;				if (sgl->page) {					vaddr = (caddr_t)						(page_address((&sgl[0])->page)						+ (&sgl[0])->offset);					memset(vaddr, 0, scp->cmnd[4]);				}				else {					con_log(CL_ANN, (KERN_WARNING					"megaraid mailbox: invalid sg:%d\n",					__LINE__));				}			}			else {				memset(scp->request_buffer, 0, scp->cmnd[4]);			}			scp->result = (DID_OK << 16);			return NULL;		case INQUIRY:			/*			 * Display the channel scan for logical drives			 * Do not display scan for a channel if already done.			 */			if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {				con_log(CL_ANN, (KERN_INFO					"scsi[%d]: scanning scsi channel %d",					adapter->host->host_no,					SCP2CHANNEL(scp)));				con_log(CL_ANN, (					" [virtual] for logical drives\n"));				rdev->last_disp |= (1L << SCP2CHANNEL(scp));			}			/* Fall through */		case READ_CAPACITY:			/*			 * Do not allow LUN > 0 for logical drives and			 * requests for more than 40 logical drives			 */			if (SCP2LUN(scp)) {				scp->result = (DID_BAD_TARGET << 16);				return NULL;			}			if ((target % 0x80) >= MAX_LOGICAL_DRIVES_40LD) {				scp->result = (DID_BAD_TARGET << 16);				return NULL;			}			/* Allocate a SCB and initialize passthru */			if (!(scb = megaraid_alloc_scb(adapter, scp))) {				scp->result = (DID_ERROR << 16);				*busy = 1;				return NULL;			}			ccb			= (mbox_ccb_t *)scb->ccb;			scb->dev_channel	= 0xFF;			scb->dev_target		= target;			pthru			= ccb->pthru;			mbox			= ccb->mbox;			mbox64			= ccb->mbox64;			pthru->timeout		= 0;			pthru->ars		= 1;			pthru->reqsenselen	= 14;			pthru->islogical	= 1;			pthru->logdrv		= target;			pthru->cdblen		= scp->cmd_len;			memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);			mbox->cmd		= MBOXCMD_PASSTHRU64;			scb->dma_direction	= scp->sc_data_direction;			pthru->dataxferlen	= scp->request_bufflen;			pthru->dataxferaddr	= ccb->sgl_dma_h;			pthru->numsge		= megaraid_mbox_mksgl(adapter,							scb);			mbox->xferaddr		= 0xFFFFFFFF;			mbox64->xferaddr_lo	= (uint32_t )ccb->pthru_dma_h;			mbox64->xferaddr_hi	= 0;			return scb;		case READ_6:		case WRITE_6:		case READ_10:		case WRITE_10:		case READ_12:		case WRITE_12:			/*			 * Allocate a SCB and initialize mailbox			 */			if (!(scb = megaraid_alloc_scb(adapter, scp))) {				scp->result = (DID_ERROR << 16);				*busy = 1;				return NULL;			}			ccb			= (mbox_ccb_t *)scb->ccb;			scb->dev_channel	= 0xFF;			scb->dev_target		= target;			mbox			= ccb->mbox;			mbox64			= ccb->mbox64;			mbox->logdrv		= target;			/*			 * A little HACK: 2nd bit is zero for all scsi read			 * commands and is set for all scsi write commands			 */			mbox->cmd = (scp->cmnd[0] & 0x02) ?  MBOXCMD_LWRITE64:					MBOXCMD_LREAD64 ;			/*			 * 6-byte READ(0x08) or WRITE(0x0A) cdb			 */			if (scp->cmd_len == 6) {				mbox->numsectors = (uint32_t)scp->cmnd[4];				mbox->lba =					((uint32_t)scp->cmnd[1] << 16)	|					((uint32_t)scp->cmnd[2] << 8)	|					(uint32_t)scp->cmnd[3];				mbox->lba &= 0x1FFFFF;			}			/*			 * 10-byte READ(0x28) or WRITE(0x2A) cdb			 */			else if (scp->cmd_len == 10) {				mbox->numsectors =					(uint32_t)scp->cmnd[8] |					((uint32_t)scp->cmnd[7] << 8);				mbox->lba =					((uint32_t)scp->cmnd[2] << 24) |					((uint32_t)scp->cmnd[3] << 16) |					((uint32_t)scp->cmnd[4] << 8) |					(uint32_t)scp->cmnd[5];			}			/*			 * 12-byte READ(0xA8) or WRITE(0xAA) cdb			 */			else if (scp->cmd_len == 12) {				mbox->lba =					((uint32_t)scp->cmnd[2] << 24) |					((uint32_t)scp->cmnd[3] << 16) |					((uint32_t)scp->cmnd[4] << 8) |					(uint32_t)scp->cmnd[5];				mbox->numsectors =					((uint32_t)scp->cmnd[6] << 24) |					((uint32_t)scp->cmnd[7] << 16) |					((uint32_t)scp->cmnd[8] << 8) |					(uint32_t)scp->cmnd[9];			}			else {				con_log(CL_ANN, (KERN_WARNING					"megaraid: unsupported CDB length\n"));				megaraid_dealloc_scb(adapter, scb);				scp->result = (DID_ERROR << 16);				return NULL;			}			scb->dma_direction = scp->sc_data_direction;			// Calculate Scatter-Gather info			mbox64->xferaddr_lo	= (uint32_t )ccb->sgl_dma_h;			mbox->numsge		= megaraid_mbox_mksgl(adapter,							scb);			mbox->xferaddr		= 0xFFFFFFFF;			mbox64->xferaddr_hi	= 0;			return scb;		case RESERVE:		case RELEASE:			/*			 * Do we support clustering and is the support enabled			 */			if (!adapter->ha) {				scp->result = (DID_BAD_TARGET << 16);				return NULL;			}			/*			 * Allocate a SCB and initialize mailbox			 */			if (!(scb = megaraid_alloc_scb(adapter, scp))) {				scp->result = (DID_ERROR << 16);				*busy = 1;				return NULL;			}			ccb			= (mbox_ccb_t *)scb->ccb;			scb->dev_channel	= 0xFF;			scb->dev_target		= target;			ccb->raw_mbox[0]	= CLUSTER_CMD;			ccb->raw_mbox[2]	=  (scp->cmnd[0] == RESERVE) ?						RESERVE_LD : RELEASE_LD;			ccb->raw_mbox[3]	= target;			scb->dma_direction	= scp->sc_data_direction;			return scb;		default:			scp->result = (DID_BAD_TARGET << 16);			return NULL;		}	}	else { // Passthru device commands		// Do not allow access to target id > 15 or LUN > 7		if (target > 15 || SCP2LUN(scp) > 7) {			scp->result = (DID_BAD_TARGET << 16);			return NULL;		}		// if fast load option was set and scan for last device is		// over, reset the fast_load flag so that during a possible		// next scan, devices can be made available		if (rdev->fast_load && (target == 15) &&			(SCP2CHANNEL(scp) == adapter->max_channel -1)) {			con_log(CL_ANN, (KERN_INFO			"megaraid[%d]: physical device scan re-enabled\n",				adapter->host->host_no));			rdev->fast_load = 0;		}		/*		 * Display the channel scan for physical devices		 */		if (!(rdev->last_disp & (1L << SCP2CHANNEL(scp)))) {			ss = rdev->fast_load ? skip : scan;			con_log(CL_ANN, (KERN_INFO				"scsi[%d]: %s scsi channel %d [Phy %d]",				adapter->host->host_no, ss, SCP2CHANNEL(scp),				channel));			con_log(CL_ANN, (				" for non-raid devices\n"));			rdev->last_disp |= (1L << SCP2CHANNEL(scp));		}		// disable channel sweep if fast load option given		if (rdev->fast_load) {			scp->result = (DID_BAD_TARGET << 16);			return NULL;		}		// Allocate a SCB and initialize passthru		if (!(scb = megaraid_alloc_scb(adapter, scp))) {			scp->result = (DID_ERROR << 16);			*busy = 1;			return NULL;		}		ccb			= (mbox_ccb_t *)scb->ccb;		scb->dev_channel	= channel;		scb->dev_target		= target;		scb->dma_direction	= scp->sc_data_direction;		mbox			= ccb->mbox;		mbox64			= ccb->mbox64;		// Does this firmware support extended CDBs		if (adapter->max_cdb_sz == 16) {			mbox->cmd		= MBOXCMD_EXTPTHRU;			megaraid_mbox_prepare_epthru(adapter, scb, scp);			mbox64->xferaddr_lo	= (uint32_t)ccb->epthru_dma_h;			mbox64->xferaddr_hi	= 0;			mbox->xferaddr		= 0xFFFFFFFF;		}		else {			mbox->cmd = MBOXCMD_PASSTHRU64;			megaraid_mbox_prepare_pthru(adapter, scb, scp);			mbox64->xferaddr_lo	= (uint32_t)ccb->pthru_dma_h;			mbox64->xferaddr_hi	= 0;			mbox->xferaddr		= 0xFFFFFFFF;		}		return scb;	}	// NOT REACHED}/** * megaraid_mbox_runpendq - execute commands queued in the pending queue * @adapter	: controller's soft state * @scb		: SCB to be queued in the pending list * * scan the pending list for commands which are not yet issued and try to * post to the controller. The SCB can be a null pointer, which would indicate * no SCB to be queue, just try to execute the ones in the pending list. * * NOTE: We do not actually traverse the pending list. The SCBs are plucked * out from the head of the pending list. If it is successfully issued, the * next SCB is at the head now. */static voidmegaraid_mbox_runpendq(adapter_t *adapter, scb_t *scb_q){	scb_t			*scb;	unsigned long		flags;	spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);	if (scb_q) {		scb_q->state = SCB_PENDQ;		list_add_tail(&scb_q->list, &adapter->pend_list);	}	// if the adapter in not in quiescent mode, post the commands to FW	if (adapter->quiescent) {		spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);		return;	}	while (!list_empty(&adapter->pend_list)) {		assert_spin_locked(PENDING_LIST_LOCK(adapter));		scb = list_entry(adapter->pend_list.next, scb_t, list);		// remove the scb from the pending list and try to		// issue. If we are unable to issue it, put back in		// the pending list and return		list_del_init(&scb->list);		spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);		// if mailbox was busy, return SCB back to pending		// list. Make sure to add at the head, since that's		// where it would have been removed from		scb->state = SCB_ISSUED;		if (mbox_post_cmd(adapter, scb) != 0) {			spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);			scb->state = SCB_PENDQ;			list_add(&scb->list, &adapter->pend_list);			spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter),				flags);			return;		}		spin_lock_irqsave(PENDING_LIST_LOCK(adapter), flags);	}	spin_unlock_irqrestore(PENDING_LIST_LOCK(adapter), flags);	return;}/** * megaraid_mbox_prepare_pthru - prepare a command for physical devices * @adapter	- pointer to controller's soft state * @scb		- scsi control block * @scp		- scsi command from the mid-layer * * prepare a command for the scsi physical devices */static voidmegaraid_mbox_prepare_pthru(adapter_t *adapter, scb_t *scb,		struct scsi_cmnd *scp){	mbox_ccb_t		*ccb;	mraid_passthru_t	*pthru;	uint8_t			channel;	uint8_t			target;	ccb	= (mbox_ccb_t *)scb->ccb;	pthru	= ccb->pthru;	channel	= scb->dev_channel;	target	= scb->dev_target;	// 0=6sec, 1=60sec, 2=10min, 3=3hrs, 4=NO timeout	pthru->timeout		= 4;		pthru->ars		= 1;	pthru->islogical	= 0;	pthru->channel		= 0;	pthru->target		= (channel << 4) | target;	pthru->logdrv		= SCP2LUN(scp);	pthru->reqsenselen	= 14;	pthru->cdblen		= scp->cmd_len;	memcpy(pthru->cdb, scp->cmnd, scp->cmd_len);	if (scp->request_bufflen) {		pthru->dataxferlen	= scp->request_bufflen;		pthru->dataxferaddr	= ccb->sgl_dma_h;		pthru->numsge		= megaraid_mbox_mksgl(adapter, scb);	}	else {		pthru->dataxferaddr	= 0;		pthru->dataxferlen	= 0;		pthru->numsge		= 0;	}	return;}/** * megaraid_mbox_prepare_epthru - prepare a command for physical devices * @adapter	- pointer to controller's soft state * @scb		- scsi control block * @scp		- scsi command from the mid-layer * * prepare a command for the scsi physical devices. This rountine prepares * commands for devices which can take extended CDBs (>10 bytes) */static voidmegaraid_mbox_prepare_epthru(adapter_t *adapter, scb_t *scb,		struct scsi_cmnd *scp){	mbox_ccb_t		*ccb;	mraid_epassthru_t	*epthru;	uint8_t			channel;	uint8_t			target;	ccb	= (mbox_ccb_t *)scb->ccb;	epthru	= ccb->epthru;	channel	= scb->dev_channel;	target	= scb->dev_target;	// 0=6sec, 1=60sec, 2=10min, 3=3hrs, 4=NO timeout	epthru->timeout		= 4;		epthru->ars		= 1;	epthru->islogical	= 0;	epthru->channel		= 0;	epthru->target		= (channel << 4) | target;	epthru->logdrv		= SCP2LUN(scp);	epthru->reqsenselen	= 14;	epthru->cdblen		= scp->cmd_len;

⌨️ 快捷键说明

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