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

📄 megaraid.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
					megaCfg->nWriteBlocks[(int) lun] +=					    mbox->numsectors;				}			}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)			if (*SCpnt->cmnd == READ_6 || *SCpnt->cmnd == READ_10					|| *SCpnt->cmnd == READ_12) {				pScb->dma_direction = PCI_DMA_FROMDEVICE;			} else {	/*WRITE_6 or WRITE_10 */				pScb->dma_direction = PCI_DMA_TODEVICE;			}#endif			/* Calculate Scatter-Gather info */			mbox->numsgelements = mega_build_sglist (megaCfg, pScb,								 (u32 *)&mbox->xferaddr, (u32 *)&seg);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)			pScb->iDataSize = seg;			if (mbox->numsgelements) {				pScb->dma_type = M_RD_SGLIST_ONLY;				TRACE1 (("M_RD_SGLIST_ONLY Enabled \n"));			} else {				pScb->dma_type = M_RD_BULK_DATA_ONLY;				TRACE1 (("M_RD_BULK_DATA_ONLY Enabled \n"));			}#endif			return pScb;		default:			SCpnt->result = (DID_BAD_TARGET << 16);			callDone (SCpnt);			return NULL;		}	}	/*-----------------------------------------------------	 *	 *               Passthru drive commands	 *	 *-----------------------------------------------------*/	else {		/* Allocate a SCB and initialize passthru */		if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {			SCpnt->result = (DID_ERROR << 16);			callDone (SCpnt);			return NULL;		}		mbox = (mega_mailbox *) pScb->mboxData;		memset (mbox, 0, sizeof (pScb->mboxData));		if ( megaCfg->support_ext_cdb && SCpnt->cmd_len > 10 ) {			epthru = mega_prepare_extpassthru(megaCfg, pScb, SCpnt);			mbox->cmd = MEGA_MBOXCMD_EXTPASSTHRU;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)			mbox->xferaddr = pScb->dma_ext_passthruhandle64;			if(epthru->numsgelements) {				pScb->dma_type = M_RD_PTHRU_WITH_SGLIST;			} else {				pScb->dma_type = M_RD_EPTHRU_WITH_BULK_DATA;			}#else			mbox->xferaddr = virt_to_bus(epthru);#endif		}		else {			pthru = mega_prepare_passthru(megaCfg, pScb, SCpnt);			/* Initialize mailbox */			mbox->cmd = MEGA_MBOXCMD_PASSTHRU;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)			mbox->xferaddr = pScb->dma_passthruhandle64;			if (pthru->numsgelements) {				pScb->dma_type = M_RD_PTHRU_WITH_SGLIST;			} else {				pScb->dma_type = M_RD_PTHRU_WITH_BULK_DATA;			}#else			mbox->xferaddr = virt_to_bus(pthru);#endif		}		return pScb;	}	return NULL;}static intmega_get_lun(mega_host_config *this_hba, Scsi_Cmnd *sc){	int		tgt;	int		lun;	int		virt_chan;	tgt = sc->target;		if ( tgt > 7 ) tgt--;	/* we do not get inquires for tgt 7 */	virt_chan = sc->channel - this_hba->productInfo.SCSIChanPresent;	lun = (virt_chan * 15) + tgt;	/*	 * If "delete logical drive" feature is enabled on this controller.	 * Do only if at least one delete logical drive operation was done.	 *	 * Also, after logical drive deletion, instead of logical drive number,	 * the value returned should be 0x80+logical drive id.	 *	 * These is valid only for IO commands.	 */	 if( this_hba->support_random_del && this_hba->read_ldidmap ) {		switch(sc->cmnd[0]) {		case READ_6:	/* fall through */		case WRITE_6:	/* fall through */		case READ_10:	/* fall through */		case WRITE_10:			lun += 0x80;		}	 }	 return lun;}static mega_passthru *mega_prepare_passthru(mega_host_config *megacfg, mega_scb *scb, Scsi_Cmnd *sc){	mega_passthru *pthru;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	pthru = scb->pthru;#else	pthru = &scb->pthru;#endif	memset (pthru, 0, sizeof (mega_passthru));	/* set adapter timeout value to 10 min. for tape drive	*/	/* 0=6sec/1=60sec/2=10min/3=3hrs 			*/	pthru->timeout = 2;	pthru->ars = 1;	pthru->reqsenselen = 14;	pthru->islogical = 0;	pthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : sc->channel;	pthru->target = (megacfg->flag & BOARD_40LD) ?	    (sc->channel << 4) | sc->target : sc->target;	pthru->cdblen = sc->cmd_len;	pthru->logdrv = sc->lun;	memcpy (pthru->cdb, sc->cmnd, sc->cmd_len);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	/* Not sure about the direction */	scb->dma_direction = PCI_DMA_BIDIRECTIONAL;	/* Special Code for Handling READ_CAPA/ INQ using bounce buffers */	switch (sc->cmnd[0]) {	case INQUIRY:	case READ_CAPACITY:		pthru->numsgelements = 0;		pthru->dataxferaddr = scb->dma_bounce_buffer;		pthru->dataxferlen = sc->request_bufflen;		break;	default:		pthru->numsgelements =			mega_build_sglist(				megacfg, scb, (u32 *)&pthru->dataxferaddr,				(u32 *)&pthru->dataxferlen			);		break;	}#else	pthru->numsgelements =		mega_build_sglist(			megacfg, scb, (u32 *)&pthru->dataxferaddr,			(u32 *)&pthru->dataxferlen		);#endif	return pthru;}static mega_ext_passthru *mega_prepare_extpassthru(mega_host_config *megacfg, mega_scb *scb, Scsi_Cmnd *sc){	mega_ext_passthru *epthru;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	epthru = scb->epthru;#else	epthru = &scb->epthru;#endif	memset(epthru, 0, sizeof(mega_ext_passthru));	/* set adapter timeout value to 10 min. for tape drive	*/	/* 0=6sec/1=60sec/2=10min/3=3hrs 			*/	epthru->timeout = 2;	epthru->ars = 1;	epthru->reqsenselen = 14;	epthru->islogical = 0;	epthru->channel = (megacfg->flag & BOARD_40LD) ? 0 : sc->channel;	epthru->target = (megacfg->flag & BOARD_40LD) ?	    (sc->channel << 4) | sc->target : sc->target;	epthru->cdblen = sc->cmd_len;	epthru->logdrv = sc->lun;	memcpy(epthru->cdb, sc->cmnd, sc->cmd_len);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	/* Not sure about the direction */	scb->dma_direction = PCI_DMA_BIDIRECTIONAL;	/* Special Code for Handling READ_CAPA/ INQ using bounce buffers */	switch (sc->cmnd[0]) {	case INQUIRY:	case READ_CAPACITY:		epthru->numsgelements = 0;		epthru->dataxferaddr = scb->dma_bounce_buffer;		epthru->dataxferlen = sc->request_bufflen;		break;	default:		epthru->numsgelements =			mega_build_sglist(				megacfg, scb, (u32 *)&epthru->dataxferaddr,				(u32 *)&epthru->dataxferlen			);		break;	}#else	epthru->numsgelements =		mega_build_sglist(			megacfg, scb, (u32 *)&epthru->dataxferaddr,			(u32 *)&epthru->dataxferlen		);#endif	return epthru;}/* Handle Driver Level IOCTLs * Return value of 0 indicates this function could not handle , so continue * processing*/static int mega_driver_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt){	unsigned char *data = (unsigned char *) SCpnt->request_buffer;	mega_driver_info driver_info;	/* If this is not our command dont do anything */	if (SCpnt->cmnd[0] != M_RD_DRIVER_IOCTL_INTERFACE)		return 0;	switch (SCpnt->cmnd[1]) {	case GET_DRIVER_INFO:		if (SCpnt->request_bufflen < sizeof (driver_info)) {			SCpnt->result = DID_BAD_TARGET << 16;			callDone (SCpnt);			return 1;		}		driver_info.size = sizeof (driver_info) - sizeof (int);		driver_info.version = MEGARAID_IOCTL_VERSION;		memcpy (data, &driver_info, sizeof (driver_info));		break;	default:		SCpnt->result = DID_BAD_TARGET << 16;	}	callDone (SCpnt);	return 1;}static void inline set_mbox_xfer_addr (mega_host_config * megaCfg, mega_scb * pScb,		    mega_ioctl_mbox * mbox, u32 direction){#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	switch (direction) {	case TO_DEVICE:		pScb->dma_direction = PCI_DMA_TODEVICE;		break;	case FROM_DEVICE:		pScb->dma_direction = PCI_DMA_FROMDEVICE;		break;	case FROMTO_DEVICE:		pScb->dma_direction = PCI_DMA_BIDIRECTIONAL;		break;	}	pScb->dma_h_bulkdata	    = pci_map_single (megaCfg->dev,			      pScb->buff_ptr,			      pScb->iDataSize, pScb->dma_direction);	mbox->xferaddr = pScb->dma_h_bulkdata;	pScb->dma_type = M_RD_BULK_DATA_ONLY;	TRACE1 (("M_RD_BULK_DATA_ONLY Enabled \n"));#else	mbox->xferaddr = virt_to_bus (pScb->buff_ptr);#endif}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)/*-------------------------------------------------------------------- * build RAID commands for controller, passed down through ioctl() *--------------------------------------------------------------------*/static mega_scb *mega_ioctl (mega_host_config * megaCfg, Scsi_Cmnd * SCpnt){	mega_scb *pScb;	mega_ioctl_mbox *mbox;	mega_mailbox *mailbox;	mega_passthru *pthru;	u8 *mboxdata;	long seg, i = 0;	unsigned char *data = (unsigned char *) SCpnt->request_buffer;	if ((pScb = mega_allocateSCB (megaCfg, SCpnt)) == NULL) {		SCpnt->result = (DID_ERROR << 16);		callDone (SCpnt);		return NULL;	}	pthru = &pScb->pthru;	mboxdata = (u8 *) & pScb->mboxData;	mbox = (mega_ioctl_mbox *) & pScb->mboxData;	mailbox = (mega_mailbox *) & pScb->mboxData;	memset (mailbox, 0, sizeof (pScb->mboxData));	if (data[0] == 0x03) {	/* passthrough command */		unsigned char cdblen = data[2];		memset (pthru, 0, sizeof (mega_passthru));		pthru->islogical = (data[cdblen + 3] & 0x80) ? 1 : 0;		pthru->timeout = data[cdblen + 3] & 0x07;		pthru->reqsenselen = 14;		pthru->ars = (data[cdblen + 3] & 0x08) ? 1 : 0;		pthru->logdrv = data[cdblen + 4];		pthru->channel = data[cdblen + 5];		pthru->target = data[cdblen + 6];		pthru->cdblen = cdblen;		memcpy (pthru->cdb, &data[3], cdblen);		mailbox->cmd = MEGA_MBOXCMD_PASSTHRU;		pthru->numsgelements = mega_build_sglist (megaCfg, pScb,							  (u32 *) & pthru->							  dataxferaddr,							  (u32 *) & pthru->							  dataxferlen);		mailbox->xferaddr = virt_to_bus (pthru);		for (i = 0; i < (SCpnt->request_bufflen - cdblen - 7); i++) {			data[i] = data[i + cdblen + 7];		}		return pScb;	}	/* else normal (nonpassthru) command */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,0,24)	/*0x020024 */	/*	 *usage of the function copy from user is used in case of data more than	 *4KB.This is used only with adapters which supports more than 8 logical	 * drives.This feature is disabled on kernels earlier or same as 2.0.36	 * as the uaccess.h file is not available with those kernels.	 */	if (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {		/* use external data area for large xfers  */		/* If cmnd[0] is set to M_RD_IOCTL_CMD_NEW then *		 *   cmnd[4..7] = external user buffer     *		 *   cmnd[8..11] = length of buffer        *		 *                                         */      	char *user_area = (char *)*((u32*)&SCpnt->cmnd[4]);		u32 xfer_size = *((u32 *) & SCpnt->cmnd[8]);		switch (data[0]) {		case FW_FIRE_WRITE:		case FW_FIRE_FLASH:			if ((ulong) user_area & (PAGE_SIZE - 1)) {				printk				    ("megaraid:user address not aligned on 4K boundary.Error.\n");				SCpnt->result = (DID_ERROR << 16);				callDone (SCpnt);				return NULL;			}			break;		default:			break;		}		if (!(pScb->buff_ptr = kmalloc (xfer_size, GFP_KERNEL))) {			printk			    ("megaraid: Insufficient mem for M_RD_IOCTL_CMD_NEW.\n");			SCpnt->result = (DID_ERROR << 16);			callDone (SCpnt);			return NULL;		}		copy_from_user (pScb->buff_ptr, user_area, xfer_size);		pScb->iDataSize = xfer_size;		switch (data[0]) {		case DCMD_FC_CMD:			switch (data[1]) {			case DCMD_FC_READ_NVRAM_CONFIG:			case DCMD_GET_DISK_CONFIG:				{					if ((ulong) pScb->					    buff_ptr & (PAGE_SIZE - 1)) {						printk						    ("megaraid:user address not sufficient Error.\n");						SCpnt->result =						    (DID_ERROR << 16);						callDone (SCpnt);						return NULL;					}					/*building SG list */					mega_build_kernel_sg (pScb->buff_ptr,							      xfer_size,							      pScb, mbox);					break;				}			default:				break;			}	/*switch (data[1]) */			break;		}	}#endif	mbox->cmd = data[0];	mbox->channel = data[1];	mbox->param = data[2];	mbox->pad[0] = data[3];	mbox->logdrv = data[4];	if (SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {		switch (data[0]) {		case FW_FIRE_WRITE:			mbox->cmd = FW_FIRE_WRITE;			mbox->channel = data[1];	/* Current Block Number */			set_mbox_xfer_addr (megaCfg, pScb, mbox, TO_DEVICE);			mbox->numsgelements = 0;			break;		case FW_FIRE_FLASH:			mbox->cmd = FW_FIRE_FLASH;			mbox->channel = data[1] | 0x80;	/* Origin */			set_mbox_xfer_addr (megaCfg, pScb, mbox, TO_DEVICE);			mbox->numsgelements = 0;			break;		case DCMD_FC_CMD:			*(mboxdata + 0) = data[0];	/*mailbox byte 0: DCMD_FC_CMD */			*(mboxdata + 2) = data[1];	/*sub command */			switch (data[1]) {			case DCMD_FC_READ_NVRAM_CONFIG:			case DCMD_FC_READ_NVRAM_CONFIG_64:				/* number of elements in SG list */				*(mboxdata + 3) = mbox->numsgelements;				if (megaCfg->flag & BOARD_64BIT)					*(mboxdata + 2) =					    DCMD_FC_READ_NVRAM_CONFIG_64;				break;			case DCMD_WRITE_CONFIG:			case DCMD_WRITE_CONFIG_64:				if (megaCfg->flag & BOARD_64BIT)					*(mboxdata + 2) = DCMD_WRITE_CONFIG_64;				set_mbox_xfer_addr (megaCfg, pScb, mbox,						    TO_DEVICE);				mbox->numsgelements = 0;				break;			case DCMD_GET_DISK_CONFIG:			case DCMD_GET_DISK_CONFIG_64:				if (megaCfg->flag & BOARD_64BIT)					*(mboxdata + 2) =					    DCMD_GET_DISK_CONFIG_64;				*(mboxdata + 3) = data[2];	/*number of elements in SG list */				/*nr of elements in SG list */				*(mboxdata + 4) = mbox->numsgelements;				break;			case DCMD_DELETE_LOGDRV:			case DCMD_DELETE_DRIVEGROUP:			case NC_SUBOP_ENQUIRY3:				*(mboxdata + 3) = data[2];				set_mbox_xfer_addr (megaCfg, pScb, mbox,

⌨️ 快捷键说明

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