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

📄 megaraid.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
						    FROMTO_DEVICE);				mbox->numsgelements = 0;				break;			case DCMD_CHANGE_LDNO:			case DCMD_CHANGE_LOOPID:				*(mboxdata + 3) = data[2];				*(mboxdata + 4) = data[3];				set_mbox_xfer_addr (megaCfg, pScb, mbox,						    TO_DEVICE);				mbox->numsgelements = 0;				break;			default:				set_mbox_xfer_addr (megaCfg, pScb, mbox,						    FROMTO_DEVICE);				mbox->numsgelements = 0;				break;			}	/*switch */			break;		default:			set_mbox_xfer_addr (megaCfg, pScb, mbox, FROMTO_DEVICE);			mbox->numsgelements = 0;			break;		}	} else {		mbox->numsgelements = mega_build_sglist (megaCfg, pScb,							 (u32 *) & mbox->							 xferaddr,							 (u32 *) & seg);		/* Handling some of the fw special commands */		switch (data[0]) {		case 6:	/* START_DEV */			mbox->xferaddr = *((u32 *) & data[i + 6]);			break;		default:			break;		}		for (i = 0; i < (SCpnt->request_bufflen - 6); i++) {			data[i] = data[i + 6];		}	}	return (pScb);}static void mega_build_kernel_sg (char *barea, ulong xfersize, mega_scb * pScb, mega_ioctl_mbox * mbox){	ulong i, buffer_area, len, end, end_page, x, idx = 0;	buffer_area = (ulong) barea;	i = buffer_area;	end = buffer_area + xfersize;	end_page = (end) & ~(PAGE_SIZE - 1);	do {		len = PAGE_SIZE - (i % PAGE_SIZE);		x = pScb->sgList[idx].address =		    virt_to_bus ((volatile void *) i);		pScb->sgList[idx].length = len;		i += len;		idx++;	} while (i < end_page);	if ((end - i) < 0) {		printk ("megaraid:Error in user address\n");	}	if (end - i) {		pScb->sgList[idx].address = virt_to_bus ((volatile void *) i);		pScb->sgList[idx].length = end - i;		idx++;	}	mbox->xferaddr = virt_to_bus (pScb->sgList);	mbox->numsgelements = idx;}#endif#if DEBUGstatic unsigned int cum_time = 0;static unsigned int cum_time_cnt = 0;static void showMbox (mega_scb * pScb){	mega_mailbox *mbox;	if (pScb == NULL)		return;	mbox = (mega_mailbox *) pScb->mboxData;	printk ("%u cmd:%x id:%x #scts:%x lba:%x addr:%x logdrv:%x #sg:%x\n",		pScb->SCpnt->pid,		mbox->cmd, mbox->cmdid, mbox->numsectors,		mbox->lba, mbox->xferaddr, mbox->logdrv, mbox->numsgelements);}#endif/*-------------------------------------------------------------------- * Interrupt service routine *--------------------------------------------------------------------*/static void megaraid_isr (int irq, void *devp, struct pt_regs *regs){	IO_LOCK_T;	mega_host_config * megaCfg;	u_char byte, idx, sIdx, tmpBox[MAILBOX_SIZE];	u32 dword = 0;	mega_mailbox *mbox;	mega_scb *pScb;	u_char qCnt, qStatus;	u_char completed[MAX_FIRMWARE_STATUS];	Scsi_Cmnd *SCpnt;	megaCfg = (mega_host_config *) devp;	mbox = (mega_mailbox *) tmpBox;	if (megaCfg->host->irq == irq) {		if (megaCfg->flag & IN_ISR) {			TRACE (("ISR called reentrantly!!\n"));			printk ("ISR called reentrantly!!\n");		}		megaCfg->flag |= IN_ISR;		if (mega_busyWaitMbox (megaCfg)) {			printk (KERN_WARNING "Error: mailbox busy in isr!\n");		}		/* Check if a valid interrupt is pending */		if (megaCfg->flag & BOARD_QUARTZ) {			dword = RDOUTDOOR (megaCfg);			if (dword != 0x10001234) {				/* Spurious interrupt */				megaCfg->flag &= ~IN_ISR;				return;			}		} else {			byte = READ_PORT (megaCfg->host->io_port, INTR_PORT);			if ((byte & VALID_INTR_BYTE) == 0) {				/* Spurious interrupt */				megaCfg->flag &= ~IN_ISR;				return;			}			WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);		}		for (idx = 0; idx < MAX_FIRMWARE_STATUS; idx++)			completed[idx] = 0;		IO_LOCK;		megaCfg->nInterrupts++;		qCnt = 0xff;		while ((qCnt = megaCfg->mbox->numstatus) == 0xFF) ;		qStatus = 0xff;		while ((qStatus = megaCfg->mbox->status) == 0xFF) ;		/* Get list of completed requests */		for (idx = 0; idx < qCnt; idx++) {			while ((sIdx = megaCfg->mbox->completed[idx]) == 0xFF) {				printk ("p");			}			completed[idx] = sIdx;			sIdx = 0xFF;		}		if (megaCfg->flag & BOARD_QUARTZ) {			WROUTDOOR (megaCfg, dword);			/* Acknowledge interrupt */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)			/* In this case mbox contains physical address */#if 0			WRINDOOR (megaCfg, megaCfg->adjdmahandle64 | 0x2);#else			WRINDOOR (megaCfg, 0x2);#endif#else#if 0			WRINDOOR (megaCfg, virt_to_bus (megaCfg->mbox) | 0x2);#else			WRINDOOR (megaCfg, 0x2);#endif#endif#if 0			while (RDINDOOR (megaCfg) & 0x02) ;#endif		} else {			CLEAR_INTR (megaCfg->host->io_port);		}#if DEBUG		if (qCnt >= MAX_FIRMWARE_STATUS) {			printk ("megaraid_isr: cmplt=%d ", qCnt);		}#endif		for (idx = 0; idx < qCnt; idx++) {			sIdx = completed[idx];			if ((sIdx > 0) && (sIdx <= MAX_COMMANDS)) {				pScb = &megaCfg->scbList[sIdx - 1];				/* ASSERT(pScb->state == SCB_ISSUED); */#if DEBUG				if (((jiffies) - pScb->isrcount) > maxCmdTime) {					maxCmdTime = (jiffies) - pScb->isrcount;					printk					    ("megaraid_isr : cmd time = %u\n",					     maxCmdTime);				}#endif				/*				 * Assuming that the scsi command, for which 				 * an abort request was received earlier, has 				 * completed.				 */				if (pScb->state == SCB_ABORTED) {					SCpnt = pScb->SCpnt;				}				if (pScb->state == SCB_RESET) {					SCpnt = pScb->SCpnt;					mega_freeSCB (megaCfg, pScb);					SCpnt->result = (DID_RESET << 16);					if (megaCfg->qCompletedH == NULL) {						megaCfg->qCompletedH =						    megaCfg->qCompletedT =						    SCpnt;					} else {						megaCfg->qCompletedT->						    host_scribble =						    (unsigned char *) SCpnt;						megaCfg->qCompletedT = SCpnt;					}					megaCfg->qCompletedT->host_scribble =					    (unsigned char *) NULL;					megaCfg->qCcnt++;					continue;				}				/* We don't want the ISR routine to touch M_RD_IOCTL_CMD_NEW commands, so				 * don't mark them as complete, instead we pop their semaphore so				 * that the queue routine can finish them off				 */				if (pScb->SCpnt->cmnd[0] == M_RD_IOCTL_CMD_NEW) {					/* save the status byte for the queue routine to use */					pScb->SCpnt->result = qStatus;					up (&pScb->ioctl_sem);				} else {					/* Mark command as completed */					mega_cmd_done (megaCfg, pScb, qStatus);				}			} else {				printk				    ("megaraid: wrong cmd id completed from firmware:id=%x\n",				     sIdx);			}		}		mega_rundoneq (megaCfg);		megaCfg->flag &= ~IN_ISR;		/* Loop through any pending requests */		mega_runpendq (megaCfg);		IO_UNLOCK;	}}/*==================================================*//* Wait until the controller's mailbox is available *//*==================================================*/static int mega_busyWaitMbox (mega_host_config * megaCfg){	mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;	long counter;	for (counter = 0; counter < 10000; counter++) {		if (!mbox->busy) {			return 0;		}		udelay (100);		barrier ();	}	return -1;		/* give up after 1 second */}/*===================================================== * Post a command to the card * * Arguments: *   mega_host_config *megaCfg - Controller structure *   u_char *mboxData - Mailbox area, 16 bytes *   mega_scb *pScb   - SCB posting (or NULL if N/A) *   int intr         - if 1, interrupt, 0 is blocking * Return Value: (added on 7/26 for 40ld/64bit) *   -1: the command was not actually issued out *   other cases: *     intr==0, return ScsiStatus, i.e. mbox->status *     intr==1, return 0 *===================================================== */static int megaIssueCmd (mega_host_config * megaCfg, u_char * mboxData, 		mega_scb * pScb, int intr){	volatile mega_mailbox *mbox = (mega_mailbox *) megaCfg->mbox;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	volatile mega_mailbox64 *mbox64 = (mega_mailbox64 *) megaCfg->mbox64;#endif	u_char byte;#ifdef __LP64__	u64 phys_mbox;#else	u32 phys_mbox;#endif	u8 retval = -1;	mboxData[0x1] = (pScb ? pScb->idx + 1 : 0xFE);	/* Set cmdid */	mboxData[0xF] = 1;	/* Set busy */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	/* In this case mbox contains physical address */	phys_mbox = megaCfg->adjdmahandle64;#else	phys_mbox = virt_to_bus (megaCfg->mbox);#endif#if DEBUG	ShowMbox (pScb);#endif	/* Wait until mailbox is free */	if (mega_busyWaitMbox (megaCfg)) {		printk ("Blocked mailbox......!!\n");		udelay (1000);#if DEBUG		showMbox (pLastScb);#endif		/* Abort command */		if (pScb == NULL) {			TRACE (("NULL pScb in megaIssue\n"));			printk ("NULL pScb in megaIssue\n");		}		mega_cmd_done (megaCfg, pScb, 0x08);		return -1;	}	pLastScb = pScb;	/* Copy mailbox data into host structure */	megaCfg->mbox64->xferSegment_lo = 0;	megaCfg->mbox64->xferSegment_hi = 0;	memcpy ((char *) mbox, mboxData, 16);#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	switch (mboxData[0]) {	case MEGA_MBOXCMD_LREAD64:	case MEGA_MBOXCMD_LWRITE64:		mbox64->xferSegment_lo = mbox->xferaddr;		mbox64->xferSegment_hi = 0;		mbox->xferaddr = 0xFFFFFFFF;		break;	}#endif	/* Kick IO */	if (intr) {		/* Issue interrupt (non-blocking) command */		if (megaCfg->flag & BOARD_QUARTZ) {			mbox->mraid_poll = 0;			mbox->mraid_ack = 0;			WRINDOOR (megaCfg, phys_mbox | 0x1);		} else {			ENABLE_INTR (megaCfg->host->io_port);			ISSUE_COMMAND (megaCfg->host->io_port);		}		pScb->state = SCB_ISSUED;		retval = 0;	} else {		/* Issue non-ISR (blocking) command */		disable_irq (megaCfg->host->irq);		if (megaCfg->flag & BOARD_QUARTZ) {			mbox->mraid_poll = 0;			mbox->mraid_ack = 0;			mbox->numstatus = 0xFF;			mbox->status = 0xFF;			WRINDOOR (megaCfg, phys_mbox | 0x1);			while (mbox->numstatus == 0xFF) ;			while (mbox->status == 0xFF) ;			while (mbox->mraid_poll != 0x77) ;			mbox->mraid_poll = 0;			mbox->mraid_ack = 0x77;			/* while ((cmdDone = RDOUTDOOR (megaCfg)) != 0x10001234);			   WROUTDOOR (megaCfg, cmdDone); */			if (pScb) {				mega_cmd_done (megaCfg, pScb, mbox->status);			}			WRINDOOR (megaCfg, phys_mbox | 0x2);			while (RDINDOOR (megaCfg) & 0x2) ;		} else {			DISABLE_INTR (megaCfg->host->io_port);			ISSUE_COMMAND (megaCfg->host->io_port);			while (!			       ((byte =				 READ_PORT (megaCfg->host->io_port,					    INTR_PORT)) & INTR_VALID)) ;			WRITE_PORT (megaCfg->host->io_port, INTR_PORT, byte);			ENABLE_INTR (megaCfg->host->io_port);			CLEAR_INTR (megaCfg->host->io_port);			if (pScb) {				mega_cmd_done (megaCfg, pScb, mbox->status);			} else {				TRACE (("Error: NULL pScb!\n"));			}		}		enable_irq (megaCfg->host->irq);		retval = mbox->status;	}#if DEBUG	while (mega_busyWaitMbox (megaCfg)) {		printk(KERN_ERR "Blocked mailbox on exit......!\n");		udelay (1000);	}#endif	return retval;}/*------------------------------------------------------------------- * Copies data to SGLIST *-------------------------------------------------------------------*//* Note:	For 64 bit cards, we need a minimum of one SG element for read/write*/static intmega_build_sglist (mega_host_config * megaCfg, mega_scb * scb,		   u32 * buffer, u32 * length){	struct scatterlist *sgList;	int idx;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)	int sgcnt;#endif	mega_mailbox *mbox = NULL;	mbox = (mega_mailbox *) scb->mboxData;	/* Scatter-gather not used */	if (scb->SCpnt->use_sg == 0) {#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)		scb->dma_h_bulkdata = pci_map_single (megaCfg->dev,				      scb->SCpnt->request_buffer,				      scb->SCpnt->request_bufflen,				      scb->dma_direction);		/* We need to handle special commands like READ64, WRITE64		   as they need a minimum of 1 SG irrespective of actually SG		 */		

⌨️ 快捷键说明

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