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

📄 megaraid.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				target = 0;			}		}	}	else {		if( islogical ) {			/* this is the logical channel */			channel = cmd->device->channel;			}		else {			/* physical channel */			channel = cmd->device->channel - NVIRT_CHAN;				target = cmd->device->id;		}	}	if(islogical) {		/* have just LUN 0 for each target on virtual channels */		if (cmd->device->lun) {			cmd->result = (DID_BAD_TARGET << 16);			cmd->scsi_done(cmd);			return NULL;		}		ldrv_num = mega_get_ldrv_num(adapter, cmd, channel);		max_ldrv_num = (adapter->flag & BOARD_40LD) ?			MAX_LOGICAL_DRIVES_40LD : MAX_LOGICAL_DRIVES_8LD;		/*		 * max_ldrv_num increases by 0x80 if some logical drive was		 * deleted.		 */		if(adapter->read_ldidmap)			max_ldrv_num += 0x80;		if(ldrv_num > max_ldrv_num ) {			cmd->result = (DID_BAD_TARGET << 16);			cmd->scsi_done(cmd);			return NULL;		}	}	else {		if( cmd->device->lun > 7) {			/*			 * Do not support lun >7 for physically accessed			 * devices			 */			cmd->result = (DID_BAD_TARGET << 16);			cmd->scsi_done(cmd);			return NULL;		}	}	/*	 *	 * Logical drive commands	 *	 */	if(islogical) {		switch (cmd->cmnd[0]) {		case TEST_UNIT_READY:#if MEGA_HAVE_CLUSTERING			/*			 * Do we support clustering and is the support enabled			 * If no, return success always			 */			if( !adapter->has_cluster ) {				cmd->result = (DID_OK << 16);				cmd->scsi_done(cmd);				return NULL;			}			if(!(scb = mega_allocate_scb(adapter, cmd))) {				*busy = 1;				return NULL;			}			scb->raw_mbox[0] = MEGA_CLUSTER_CMD;			scb->raw_mbox[2] = MEGA_RESERVATION_STATUS;			scb->raw_mbox[3] = ldrv_num;			scb->dma_direction = PCI_DMA_NONE;			return scb;#else			cmd->result = (DID_OK << 16);			cmd->scsi_done(cmd);			return NULL;#endif		case MODE_SENSE: {			char *buf;			struct scatterlist *sg;			sg = scsi_sglist(cmd);			buf = kmap_atomic(sg_page(sg), KM_IRQ0) + sg->offset;			memset(buf, 0, cmd->cmnd[4]);			kunmap_atomic(buf - sg->offset, KM_IRQ0);			cmd->result = (DID_OK << 16);			cmd->scsi_done(cmd);			return NULL;		}		case READ_CAPACITY:		case INQUIRY:			if(!(adapter->flag & (1L << cmd->device->channel))) {				printk(KERN_NOTICE					"scsi%d: scanning scsi channel %d ",						adapter->host->host_no,						cmd->device->channel);				printk("for logical drives.\n");				adapter->flag |= (1L << cmd->device->channel);			}			/* Allocate a SCB and initialize passthru */			if(!(scb = mega_allocate_scb(adapter, cmd))) {				*busy = 1;				return NULL;			}			pthru = scb->pthru;			mbox = (mbox_t *)scb->raw_mbox;			memset(mbox, 0, sizeof(scb->raw_mbox));			memset(pthru, 0, sizeof(mega_passthru));			pthru->timeout = 0;			pthru->ars = 1;			pthru->reqsenselen = 14;			pthru->islogical = 1;			pthru->logdrv = ldrv_num;			pthru->cdblen = cmd->cmd_len;			memcpy(pthru->cdb, cmd->cmnd, cmd->cmd_len);			if( adapter->has_64bit_addr ) {				mbox->m_out.cmd = MEGA_MBOXCMD_PASSTHRU64;			}			else {				mbox->m_out.cmd = MEGA_MBOXCMD_PASSTHRU;			}			scb->dma_direction = PCI_DMA_FROMDEVICE;			pthru->numsgelements = mega_build_sglist(adapter, scb,				&pthru->dataxferaddr, &pthru->dataxferlen);			mbox->m_out.xferaddr = scb->pthru_dma_addr;			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 = mega_allocate_scb(adapter, cmd))) {				*busy = 1;				return NULL;			}			mbox = (mbox_t *)scb->raw_mbox;			memset(mbox, 0, sizeof(scb->raw_mbox));			mbox->m_out.logdrv = ldrv_num;			/*			 * A little hack: 2nd bit is zero for all scsi read			 * commands and is set for all scsi write commands			 */			if( adapter->has_64bit_addr ) {				mbox->m_out.cmd = (*cmd->cmnd & 0x02) ?					MEGA_MBOXCMD_LWRITE64:					MEGA_MBOXCMD_LREAD64 ;			}			else {				mbox->m_out.cmd = (*cmd->cmnd & 0x02) ?					MEGA_MBOXCMD_LWRITE:					MEGA_MBOXCMD_LREAD ;			}			/*			 * 6-byte READ(0x08) or WRITE(0x0A) cdb			 */			if( cmd->cmd_len == 6 ) {				mbox->m_out.numsectors = (u32) cmd->cmnd[4];				mbox->m_out.lba =					((u32)cmd->cmnd[1] << 16) |					((u32)cmd->cmnd[2] << 8) |					(u32)cmd->cmnd[3];				mbox->m_out.lba &= 0x1FFFFF;#if MEGA_HAVE_STATS				/*				 * Take modulo 0x80, since the logical drive				 * number increases by 0x80 when a logical				 * drive was deleted				 */				if (*cmd->cmnd == READ_6) {					adapter->nreads[ldrv_num%0x80]++;					adapter->nreadblocks[ldrv_num%0x80] +=						mbox->m_out.numsectors;				} else {					adapter->nwrites[ldrv_num%0x80]++;					adapter->nwriteblocks[ldrv_num%0x80] +=						mbox->m_out.numsectors;				}#endif			}			/*			 * 10-byte READ(0x28) or WRITE(0x2A) cdb			 */			if( cmd->cmd_len == 10 ) {				mbox->m_out.numsectors =					(u32)cmd->cmnd[8] |					((u32)cmd->cmnd[7] << 8);				mbox->m_out.lba =					((u32)cmd->cmnd[2] << 24) |					((u32)cmd->cmnd[3] << 16) |					((u32)cmd->cmnd[4] << 8) |					(u32)cmd->cmnd[5];#if MEGA_HAVE_STATS				if (*cmd->cmnd == READ_10) {					adapter->nreads[ldrv_num%0x80]++;					adapter->nreadblocks[ldrv_num%0x80] +=						mbox->m_out.numsectors;				} else {					adapter->nwrites[ldrv_num%0x80]++;					adapter->nwriteblocks[ldrv_num%0x80] +=						mbox->m_out.numsectors;				}#endif			}			/*			 * 12-byte READ(0xA8) or WRITE(0xAA) cdb			 */			if( cmd->cmd_len == 12 ) {				mbox->m_out.lba =					((u32)cmd->cmnd[2] << 24) |					((u32)cmd->cmnd[3] << 16) |					((u32)cmd->cmnd[4] << 8) |					(u32)cmd->cmnd[5];				mbox->m_out.numsectors =					((u32)cmd->cmnd[6] << 24) |					((u32)cmd->cmnd[7] << 16) |					((u32)cmd->cmnd[8] << 8) |					(u32)cmd->cmnd[9];#if MEGA_HAVE_STATS				if (*cmd->cmnd == READ_12) {					adapter->nreads[ldrv_num%0x80]++;					adapter->nreadblocks[ldrv_num%0x80] +=						mbox->m_out.numsectors;				} else {					adapter->nwrites[ldrv_num%0x80]++;					adapter->nwriteblocks[ldrv_num%0x80] +=						mbox->m_out.numsectors;				}#endif			}			/*			 * If it is a read command			 */			if( (*cmd->cmnd & 0x0F) == 0x08 ) {				scb->dma_direction = PCI_DMA_FROMDEVICE;			}			else {				scb->dma_direction = PCI_DMA_TODEVICE;			}			/* Calculate Scatter-Gather info */			mbox->m_out.numsgelements = mega_build_sglist(adapter, scb,					(u32 *)&mbox->m_out.xferaddr, (u32 *)&seg);			return scb;#if MEGA_HAVE_CLUSTERING		case RESERVE:	/* Fall through */		case RELEASE:			/*			 * Do we support clustering and is the support enabled			 */			if( ! adapter->has_cluster ) {				cmd->result = (DID_BAD_TARGET << 16);				cmd->scsi_done(cmd);				return NULL;			}			/* Allocate a SCB and initialize mailbox */			if(!(scb = mega_allocate_scb(adapter, cmd))) {				*busy = 1;				return NULL;			}			scb->raw_mbox[0] = MEGA_CLUSTER_CMD;			scb->raw_mbox[2] = ( *cmd->cmnd == RESERVE ) ?				MEGA_RESERVE_LD : MEGA_RELEASE_LD;			scb->raw_mbox[3] = ldrv_num;			scb->dma_direction = PCI_DMA_NONE;			return scb;#endif		default:			cmd->result = (DID_BAD_TARGET << 16);			cmd->scsi_done(cmd);			return NULL;		}	}	/*	 * Passthru drive commands	 */	else {		/* Allocate a SCB and initialize passthru */		if(!(scb = mega_allocate_scb(adapter, cmd))) {			*busy = 1;			return NULL;		}		mbox = (mbox_t *)scb->raw_mbox;		memset(mbox, 0, sizeof(scb->raw_mbox));		if( adapter->support_ext_cdb ) {			epthru = mega_prepare_extpassthru(adapter, scb, cmd,					channel, target);			mbox->m_out.cmd = MEGA_MBOXCMD_EXTPTHRU;			mbox->m_out.xferaddr = scb->epthru_dma_addr;		}		else {			pthru = mega_prepare_passthru(adapter, scb, cmd,					channel, target);			/* Initialize mailbox */			if( adapter->has_64bit_addr ) {				mbox->m_out.cmd = MEGA_MBOXCMD_PASSTHRU64;			}			else {				mbox->m_out.cmd = MEGA_MBOXCMD_PASSTHRU;			}			mbox->m_out.xferaddr = scb->pthru_dma_addr;		}		return scb;	}	return NULL;}/** * mega_prepare_passthru() * @adapter - pointer to our soft state * @scb - our scsi control block * @cmd - scsi command from the mid-layer * @channel - actual channel on the controller * @target - actual id on the controller. * * prepare a command for the scsi physical devices. */static mega_passthru *mega_prepare_passthru(adapter_t *adapter, scb_t *scb, Scsi_Cmnd *cmd,		int channel, int target){	mega_passthru *pthru;	pthru = scb->pthru;	memset(pthru, 0, sizeof (mega_passthru));	/* 0=6sec/1=60sec/2=10min/3=3hrs */	pthru->timeout = 2;	pthru->ars = 1;	pthru->reqsenselen = 14;	pthru->islogical = 0;	pthru->channel = (adapter->flag & BOARD_40LD) ? 0 : channel;	pthru->target = (adapter->flag & BOARD_40LD) ?		(channel << 4) | target : target;	pthru->cdblen = cmd->cmd_len;	pthru->logdrv = cmd->device->lun;	memcpy(pthru->cdb, cmd->cmnd, cmd->cmd_len);	/* Not sure about the direction */	scb->dma_direction = PCI_DMA_BIDIRECTIONAL;	/* Special Code for Handling READ_CAPA/ INQ using bounce buffers */	switch (cmd->cmnd[0]) {	case INQUIRY:	case READ_CAPACITY:		if(!(adapter->flag & (1L << cmd->device->channel))) {			printk(KERN_NOTICE				"scsi%d: scanning scsi channel %d [P%d] ",					adapter->host->host_no,					cmd->device->channel, channel);			printk("for physical devices.\n");			adapter->flag |= (1L << cmd->device->channel);		}		/* Fall through */	default:		pthru->numsgelements = mega_build_sglist(adapter, scb,				&pthru->dataxferaddr, &pthru->dataxferlen);		break;	}	return pthru;}/** * mega_prepare_extpassthru() * @adapter - pointer to our soft state * @scb - our scsi control block * @cmd - scsi command from the mid-layer * @channel - actual channel on the controller * @target - actual id on the controller. * * prepare a command for the scsi physical devices. This rountine prepares * commands for devices which can take extended CDBs (>10 bytes) */static mega_ext_passthru *mega_prepare_extpassthru(adapter_t *adapter, scb_t *scb, Scsi_Cmnd *cmd,		int channel, int target){	mega_ext_passthru	*epthru;	epthru = scb->epthru;	memset(epthru, 0, sizeof(mega_ext_passthru));	/* 0=6sec/1=60sec/2=10min/3=3hrs */	epthru->timeout = 2;	epthru->ars = 1;	epthru->reqsenselen = 14;	epthru->islogical = 0;	epthru->channel = (adapter->flag & BOARD_40LD) ? 0 : channel;	epthru->target = (adapter->flag & BOARD_40LD) ?		(channel << 4) | target : target;	epthru->cdblen = cmd->cmd_len;	epthru->logdrv = cmd->device->lun;	memcpy(epthru->cdb, cmd->cmnd, cmd->cmd_len);	/* Not sure about the direction */	scb->dma_direction = PCI_DMA_BIDIRECTIONAL;	switch(cmd->cmnd[0]) {	case INQUIRY:	case READ_CAPACITY:		if(!(adapter->flag & (1L << cmd->device->channel))) {			printk(KERN_NOTICE				"scsi%d: scanning scsi channel %d [P%d] ",					adapter->host->host_no,					cmd->device->channel, channel);			printk("for physical devices.\n");			adapter->flag |= (1L << cmd->device->channel);		}		/* Fall through */	default:		epthru->numsgelements = mega_build_sglist(adapter, scb,				&epthru->dataxferaddr, &epthru->dataxferlen);		break;	}	return epthru;}static void__mega_runpendq(adapter_t *adapter){	scb_t *scb;	struct list_head *pos, *next;	/* Issue any pending commands to the card */	list_for_each_safe(pos, next, &adapter->pending_list) {		scb = list_entry(pos, scb_t, list);		if( !(scb->state & SCB_ISSUED) ) {			if( issue_scb(adapter, scb) != 0 )				return;		}	}	return;}/** * issue_scb() * @adapter - pointer to our soft state * @scb - scsi control block * * Post a command to the card if the mailbox is available, otherwise return * busy. We also take the scb from the pending list if the mailbox is * available. */static intissue_scb(adapter_t *adapter, scb_t *scb){	volatile mbox64_t	*mbox64 = adapter->mbox64;	volatile mbox_t		*mbox = adapter->mbox;	unsigned int	i = 0;	if(unlikely(mbox->m_in.busy)) {		do {			udelay(1);			i++;		} while( mbox->m_in.busy && (i < max_mbox_busy_wait) );		if(mbox->m_in.busy) return -1;	}	/* Copy mailbox data into host structure */	memcpy((char *)&mbox->m_out, (char *)scb->raw_mbox, 			sizeof(struct mbox_out));	mbox->m_out.cmdid = scb->idx;	/* Set cmdid */	mbox->m_in.busy = 1;		/* Set busy */	/*	 * Increment the pending queue counter	 */	atomic_inc(&adapter->pend_cmds);

⌨️ 快捷键说明

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