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

📄 cciss.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
        int i;        /* Wait (up to 2 seconds) for a command to complete */        for (i = 200000; i > 0; i--) {                done = hba[ctlr]->access.command_completed(hba[ctlr]);                if (done == FIFO_EMPTY) {                        udelay(10);     /* a short fixed delay */                } else                        return (done);        }        /* Invalid address to tell caller we ran out of time */        return 1;}/* * Send a command to the controller, and wait for it to complete.   * Only used at init time.  */static int sendcmd(	__u8	cmd,	int	ctlr,	void	*buff,	size_t	size,	unsigned int use_unit_num,	unsigned int log_unit,	__u8	page_code ){	CommandList_struct *c;	int i;	unsigned long complete;	ctlr_info_t *info_p= hba[ctlr];	u64bit buff_dma_handle;	c = cmd_alloc(info_p, 1);	if (c == NULL)	{		printk(KERN_WARNING "cciss: unable to get memory");		return(IO_ERROR);	}	// Fill in Command Header 	c->Header.ReplyQueue = 0;  // unused in simple mode	if( buff != NULL) 	// buffer to fill 	{		c->Header.SGList = 1;		c->Header.SGTotal= 1;	} else	// no buffers to fill  	{		c->Header.SGList = 0;                c->Header.SGTotal= 0;	}	c->Header.Tag.lower = c->busaddr;  // use the kernel address the cmd block for tag	// Fill in Request block 		switch(cmd)	{		case  CISS_INQUIRY:			/* If the logical unit number is 0 then, this is going				to controller so It's a physical command				mode = 0 target = 0.				So we have nothing to write. 				Otherwise 				mode = 1  target = LUNID			*/			if(use_unit_num != 0)			{				c->Header.LUN.LogDev.VolId=                                	hba[ctlr]->drv[log_unit].LunID;                        	c->Header.LUN.LogDev.Mode = 1;			}			/* are we trying to read a vital product page */			if(page_code != 0)			{				c->Request.CDB[1] = 0x01;				c->Request.CDB[2] = page_code;			}			c->Request.CDBLen = 6;			c->Request.Type.Type =  TYPE_CMD; // It is a command. 			c->Request.Type.Attribute = ATTR_SIMPLE;  			c->Request.Type.Direction = XFER_READ; // Read 			c->Request.Timeout = 0; // Don't time out 			c->Request.CDB[0] =  CISS_INQUIRY;			c->Request.CDB[4] = size  & 0xFF;  		break;		case CISS_REPORT_LOG:                        /* Talking to controller so It's a physical command                                mode = 00 target = 0.                                So we have nothing to write.                        */                        c->Request.CDBLen = 12;                        c->Request.Type.Type =  TYPE_CMD; // It is a command.                        c->Request.Type.Attribute = ATTR_SIMPLE;                         c->Request.Type.Direction = XFER_READ; // Read                        c->Request.Timeout = 0; // Don't time out                        c->Request.CDB[0] = CISS_REPORT_LOG;                        c->Request.CDB[6] = (size >> 24) & 0xFF;  //MSB                        c->Request.CDB[7] = (size >> 16) & 0xFF;                        c->Request.CDB[8] = (size >> 8) & 0xFF;                        c->Request.CDB[9] = size & 0xFF;                break;		case CCISS_READ_CAPACITY:			c->Header.LUN.LogDev.VolId= 				hba[ctlr]->drv[log_unit].LunID;			c->Header.LUN.LogDev.Mode = 1;			c->Request.CDBLen = 10;                        c->Request.Type.Type =  TYPE_CMD; // It is a command.                        c->Request.Type.Attribute = ATTR_SIMPLE;                         c->Request.Type.Direction = XFER_READ; // Read                        c->Request.Timeout = 0; // Don't time out                        c->Request.CDB[0] = CCISS_READ_CAPACITY;		break;		default:			printk(KERN_WARNING				"cciss:  Unknown Command 0x%c sent attempted\n",				  cmd);			cmd_free(info_p, c, 1);			return(IO_ERROR);	};	// Fill in the scatter gather information	if (size > 0 ) 	{		buff_dma_handle.val = (__u64) pci_map_single( info_p->pdev, 			buff, size, PCI_DMA_BIDIRECTIONAL);		c->SG[0].Addr.lower = buff_dma_handle.val32.lower;		c->SG[0].Addr.upper = buff_dma_handle.val32.upper;		c->SG[0].Len = size;		c->SG[0].Ext = 0;  // we are not chaining	}	/*         * Disable interrupt         */#ifdef CCISS_DEBUG	printk(KERN_DEBUG "cciss: turning intr off\n");#endif /* CCISS_DEBUG */         info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF);		/* Make sure there is room in the command FIFO */        /* Actually it should be completely empty at this time. */        for (i = 200000; i > 0; i--) 	{		/* if fifo isn't full go */                if (!(info_p->access.fifo_full(info_p))) 		{			                        break;                }                udelay(10);                printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full,"                        " waiting!\n", ctlr);        }        /*         * Send the cmd         */        info_p->access.submit_command(info_p, c);        complete = pollcomplete(ctlr);#ifdef CCISS_DEBUG	printk(KERN_DEBUG "cciss: command completed\n");#endif /* CCISS_DEBUG */	/* unlock the data buffer from DMA */	pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,                                size, PCI_DMA_BIDIRECTIONAL);	if (complete != 1) {		if ( (complete & CISS_ERROR_BIT)		     && (complete & ~CISS_ERROR_BIT) == c->busaddr)		     {			/* if data overrun or underun on Report command 				ignore it 			*/			if (((c->Request.CDB[0] == CISS_REPORT_LOG) ||			     (c->Request.CDB[0] == CISS_INQUIRY)) &&				((c->err_info->CommandStatus == 					CMD_DATA_OVERRUN) || 				 (c->err_info->CommandStatus == 					CMD_DATA_UNDERRUN)			 	))			{				complete = c->busaddr;			} else			{				printk(KERN_WARNING "ciss ciss%d: sendcmd"				" Error %x \n", ctlr, 					c->err_info->CommandStatus); 				printk(KERN_WARNING "ciss ciss%d: sendcmd"				" offensive info\n"				"  size %x\n   num %x   value %x\n", ctlr,				  c->err_info->MoreErrInfo.Invalid_Cmd.offense_size,				  c->err_info->MoreErrInfo.Invalid_Cmd.offense_num,				  c->err_info->MoreErrInfo.Invalid_Cmd.offense_value);				cmd_free(info_p,c, 1);				return(IO_ERROR);			}		}                if (complete != c->busaddr) {                        printk( KERN_WARNING "cciss cciss%d: SendCmd "                      "Invalid command list address returned! (%lx)\n",                                ctlr, complete);                        cmd_free(info_p, c, 1);                        return (IO_ERROR);                }        } else {                printk( KERN_WARNING                        "cciss cciss%d: SendCmd Timeout out, "                        "No command list address returned!\n",                        ctlr);                cmd_free(info_p, c, 1);                return (IO_ERROR);        }	cmd_free(info_p, c, 1);        return (IO_OK);} /* * Map (physical) PCI mem into (virtual) kernel space */static ulong remap_pci_mem(ulong base, ulong size){        ulong page_base        = ((ulong) base) & PAGE_MASK;        ulong page_offs        = ((ulong) base) - page_base;        ulong page_remapped    = (ulong) ioremap(page_base, page_offs+size);        return (ulong) (page_remapped ? (page_remapped + page_offs) : 0UL);}/* * Enqueuing and dequeuing functions for cmdlists. */static inline void addQ(CommandList_struct **Qptr, CommandList_struct *c){        if (*Qptr == NULL) {                *Qptr = c;                c->next = c->prev = c;        } else {                c->prev = (*Qptr)->prev;                c->next = (*Qptr);                (*Qptr)->prev->next = c;                (*Qptr)->prev = c;        }}static inline CommandList_struct *removeQ(CommandList_struct **Qptr, 						CommandList_struct *c){        if (c && c->next != c) {                if (*Qptr == c) *Qptr = c->next;                c->prev->next = c->next;                c->next->prev = c->prev;        } else {                *Qptr = NULL;        }        return c;}/*  * Takes jobs of the Q and sends them to the hardware, then puts it on  * the Q to wait for completion.  */ static void start_io( ctlr_info_t *h){	CommandList_struct *c;		while(( c = h->reqQ) != NULL )	{		/* can't do anything if fifo is full */		if ((h->access.fifo_full(h)))		{			printk(KERN_WARNING "cciss: fifo full \n");			return;		}		/* Get the frist entry from the Request Q */ 		removeQ(&(h->reqQ), c);		h->Qdepth--;			/* Tell the controller execute command */ 		h->access.submit_command(h, c);				/* Put job onto the completed Q */ 		addQ (&(h->cmpQ), c); 	}}static inline void complete_buffers( struct buffer_head *bh, int status){	struct buffer_head *xbh;		while(bh)	{		xbh = bh->b_reqnext; 		bh->b_reqnext = NULL; 		blk_finished_io(bh->b_size >> 9);		bh->b_end_io(bh, status);		bh = xbh;	}} /* checks the status of the job and calls complete buffers to mark all  * buffers for the completed job.  */ static inline void complete_command( CommandList_struct *cmd, int timeout){	int status = 1;	int i;	u64bit temp64;			if (timeout)		status = 0; 	/* unmap the DMA mapping for all the scatter gather elements */	for(i=0; i<cmd->Header.SGList; i++)	{		temp64.val32.lower = cmd->SG[i].Addr.lower;		temp64.val32.upper = cmd->SG[i].Addr.upper;		pci_unmap_single(hba[cmd->ctlr]->pdev,			temp64.val, cmd->SG[i].Len, 			(cmd->Request.Type.Direction == XFER_READ) ? 				PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);	}	if(cmd->err_info->CommandStatus != 0) 	{ /* an error has occurred */ 		switch(cmd->err_info->CommandStatus)		{			case CMD_TARGET_STATUS:				printk(KERN_WARNING "cciss: cmd %p has "					" completed with errors\n", cmd);				if( cmd->err_info->ScsiStatus)                		{                    			printk(KERN_WARNING "cciss: cmd %p "					"has SCSI Status = %x\n",                        			cmd,  						cmd->err_info->ScsiStatus);                		}			break;			case CMD_DATA_UNDERRUN:				printk(KERN_WARNING "cciss: cmd %p has"					" completed with data underrun "					"reported\n", cmd);			break;			case CMD_DATA_OVERRUN:				printk(KERN_WARNING "cciss: cmd %p has"					" completed with data overrun "					"reported\n", cmd);			break;			case CMD_INVALID:				printk(KERN_WARNING "cciss: cmd %p is "					"reported invalid\n", cmd);				status = 0;			break;			case CMD_PROTOCOL_ERR:                                printk(KERN_WARNING "cciss: cmd %p has "					"protocol error \n", cmd);                                status = 0;                        break;			case CMD_HARDWARE_ERR:                                printk(KERN_WARNING "cciss: cmd %p had "                                         " hardware error\n", cmd);                                status = 0;                        break;			case CMD_CONNECTION_LOST:				printk(KERN_WARNING "cciss: cmd %p had "					"connection lost\n", cmd);				status=0;			break;			case CMD_ABORTED:				printk(KERN_WARNING "cciss: cmd %p was "					"aborted\n", cmd);				status=0;			break;			case CMD_ABORT_FAILED:				printk(KERN_WARNING "cciss: cmd %p reports "					"abort failed\n", cmd);				status=0;			break;			case CMD_UNSOLICITED_ABORT:				printk(KERN_WARNING "cciss: cmd %p aborted "					"do to an unsolicited abort\n", cmd);				status=0;			break;			case CMD_TIMEOUT:				printk(KERN_WARNING "cciss: cmd %p timedout\n",					cmd);				status=0;			break;			default:				printk(KERN_WARNING "cciss: cmd %p returned "					"unknown status %x\n", cmd, 						cmd->err_info->CommandStatus); 				status=0;		}	}	complete_buffers(cmd->rq->bh, status);#ifdef CCISS_DEBUG	printk("Done with %p\n", cmd->rq);#endif /* CCISS_DEBUG */ 	end_that_request_last(cmd->rq);}static inline int cpq_new_segment(request_queue_t *q, struct request *rq,                                  int max_segments){        if (rq->nr_segments < MAXSGENTRIES) {                rq->nr_segments++;                return 1;        }        return 0;}static int cpq_back_merge_fn(request_queue_t *q, struct request *rq,                             struct buffer_head *bh, int max_segments){        if (rq->bhtail->b_data + rq->bhtail->b_size == bh->b_data)                return 1;        return cpq_new_segment(q, rq, max_segments);}

⌨️ 快捷键说明

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