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

📄 cciss.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 4 页
字号:
#endif /* CCISS_DEBUG */	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);				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);                        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);                return (IO_ERROR);        }	cmd_free(info_p, c);        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; 		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;		if (timeout)		status = 0; 	if(cmd->err_info->CommandStatus != 0) 	{ /* an error has occured */ 		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->bh, status);}/*  * Get a request and submit it to the controller.  * Currently we do one request at a time.  Ideally we would like to send * everything to the controller on the first call, but there is a danger * of holding the io_request_lock for to long.   */static void do_cciss_request(int ctlr){	ctlr_info_t *h= hba[ctlr];	CommandList_struct *c;	int log_unit, start_blk, seg, sect;	char *lastdataend;	struct buffer_head *bh;	struct list_head *queue_head;	struct request *creq;	u64bit temp64;	queue_head = &blk_dev[MAJOR_NR+ctlr].request_queue.queue_head;		if (list_empty(queue_head))	{		/* nothing to do... */		start_io(h);		return;	}	creq =	blkdev_entry_next_request(queue_head); 	if ((creq == NULL) || (creq->rq_status == RQ_INACTIVE))	{		/* nothing to do... restart processing and return */ 		start_io(h);		return;	}	if ((ctlr != (MAJOR(creq->rq_dev)-MAJOR_NR)) || (ctlr > nr_ctlr)		|| (h == NULL))	{#ifdef CCISS_DEBUG		printk(KERN_WARNING "cciss: doreq cmd of %d, %x at %p\n",			ctlr, creq->rq_dev, creq);#endif /* CCISS_DEBUG */		complete_buffers(creq->bh, 0);		start_io(h); 		return;	}	if (( c = cmd_alloc(h)) == NULL)	{		start_io(h);		return;	}	c->cmd_type = CMD_RWREQ;      	bh = c->bh = creq->bh;		/* fill in the request */ 	log_unit = MINOR(creq->rq_dev) >> NWD_SHIFT; 	c->Header.ReplyQueue = 0;  // unused in simple mode	c->Header.Tag.lower = c->busaddr;  // use the physical address the cmd block for tag	c->Header.LUN.LogDev.VolId= hba[ctlr]->drv[log_unit].LunID;	c->Header.LUN.LogDev.Mode = 1;	c->Request.CDBLen = 10; // 12 byte commands not in FW yet;	c->Request.Type.Type =  TYPE_CMD; // It is a command. 	c->Request.Type.Attribute = ATTR_SIMPLE; 	c->Request.Type.Direction = 		(creq->cmd == READ) ? XFER_READ: XFER_WRITE; 	c->Request.Timeout = 0; // Don't time out		c->Request.CDB[0] = (creq->cmd == READ) ? CCISS_READ : CCISS_WRITE;	start_blk = hba[ctlr]->hd[MINOR(creq->rq_dev)].start_sect + creq->sector;	if (bh == NULL)		panic("cciss: bh== NULL?");#ifdef CCISS_DEBUG	printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n",(int) creq->sector,		(int) creq->nr_sectors);	#endif /* CCISS_DEBUG */	seg = 0; 	lastdataend = NULL;	sect = 0;	while(bh)	{		sect += bh->b_size/512;		if (bh->b_size % 512)		{			printk(KERN_CRIT "cciss:  Oh Man.  %d+%d, size=%d\n", 				(int) creq->sector, sect, (int) bh->b_size);			panic("b_size 512 != 0\n");		}		if (bh->b_data == lastdataend)		{  // tack it on to the last segment 			c->SG[seg-1].Len +=bh->b_size;			lastdataend += bh->b_size;		} else		{			c->SG[seg].Len = bh->b_size;			temp64.val = (__u64) virt_to_bus(bh->b_data);			c->SG[seg].Addr.lower = temp64.val32.lower;			c->SG[seg].Addr.upper = temp64.val32.upper;			c->SG[0].Ext = 0;  // we are not chaining			lastdataend = bh->b_data + bh->b_size;			if( ++seg == MAXSGENTRIES)			{				break; 			}		}		bh = bh->b_reqnext;	}	/* track how many SG entries we are using */ 	if( seg > h->maxSG)		h->maxSG = seg; 	/* adjusting the remaining request, if any */ 	creq-> sector+= sect;	creq->nr_sectors -= sect; #ifdef CCISS_DEBUG	printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n", sect, seg);#endif /* CCISS_DEBUG */	c->Header.SGList = c->Header.SGTotal = seg;	c->Request.CDB[1]= 0;	c->Request.CDB[2]= (start_blk >> 24) & 0xff;	//MSB	c->Request.CDB[3]= (start_blk >> 16) & 0xff;	c->Request.CDB[4]= (start_blk >>  8) & 0xff;	c->Request.CDB[5]= start_blk & 0xff;	c->Request.CDB[6]= 0; // (sect >> 24) & 0xff; MSB	// c->Request.CDB[7]= (sect >> 16) & 0xff; 	c->Request.CDB[7]= (sect >>  8) & 0xff; 	c->Request.CDB[8]= sect & 0xff; 	c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;	/* check to see if we going to complete the entire request */ 	/* if so, mark this request as Done and ready the next one */ 	if (creq->nr_sectors)	{#ifdef CCISS_DEBUG		printk(KERN_DEBUG "cciss: More to do on the same request %p %ld\n", 			creq, creq->nr_sectors);#endif /* CCISS_DEBUG */		creq->bh = bh->b_reqnext;		bh->b_reqnext = NULL;	} else	{#ifdef CCISS_DEBUG		printk("cciss: Done with %p, queueing %p\n", creq);#endif /* CCISS_DEBUG */					blkdev_dequeue_request(creq);		end_that_request_last(creq);	}	addQ(&(h->reqQ),c);	h->Qdepth++;	if(h->Qdepth > h->maxQsinceinit)		h->maxQsinceinit = h->Qdepth; 	start_io(h);}static void do_cciss_intr(int irq, void *dev_id, struct pt_regs *regs){	ctlr_info_t *h = dev_id;	CommandList_struct *c;	unsigned long flags;	__u32 a, a1;	/* Is this interrupt for us? */	if ( h->access.intr_pending(h) == 0)		return;	/*	 * If there are completed commands in the completion queue,	 * we had better do something about it.	 */	spin_lock_irqsave(&io_request_lock, flags);	while( h->access.intr_pending(h))	{		while((a = h->access.command_completed(h)) != FIFO_EMPTY) 		{			a1 = a;			a &= ~3;			if ((c = h->cmpQ) == NULL)			{  				printk(KERN_WARNING "cpqarray: Completion of %08lx ignored\n", (unsigned long)a1);				continue;				} 			while(c->busaddr != a) {				c = c->next;				if (c == h->cmpQ) 					break;			}			/*			 * If we've found the command, take it off the			 * completion Q and free it			 */			 if (c->busaddr == a) {				removeQ(&h->cmpQ, c);				if (c->cmd_type == CMD_RWREQ) {					complete_command(c, 0);					cmd_free(h, c);				} else if (c->cmd_type == CMD_IOCTL_PEND) {					c->cmd_type = CMD_IOCTL_DONE;				}				continue;			}		}	}	/*	 * See if we can queue up some more IO	 */	do_cciss_request(h->ctlr);	spin_unlock_irqrestore(&io_request_lock, flags);}/*  *  We cannot read the structure directly, for portablity we must use  *   the io functions. *   This is for debug only.  */#ifdef CCISS_DEBUGstatic void print_cfg_table( CfgTable_struct *tb){	int i;	char temp_name[17];	printk("Controller Configuration information\n");	printk("------------------------------------\n");	for(i=0;i<4;i++)		temp_name[i] = readb(&(tb->Signature[i]));	temp_name[4]='\0';	printk("   Signature = %s\n", temp_name); 	printk("   Spec Number = %d\n", readl(&(tb->SpecValence)));	printk("   Transport methods supported = 0x%x\n", 				readl(&(tb-> TransportSupport)));	printk("   Transport methods active = 0x%x\n", 				readl(&(tb->TransportActive)));	printk("   Requested transport Method = 0x%x\n", 			readl(&(tb->HostWrite.TransportRequest)));	printk("   Coalese Interrupt Delay = 0x%x\n", 			readl(&(tb->HostWrite.CoalIntDelay)));	printk("   Coalese Interrupt Count = 0x%x\n", 			readl(&(tb->HostWrite.CoalIntCount)));	printk("   Max outstanding commands = 0x%d\n", 			readl(&(tb->CmdsOutMax)));	printk("   Bus Types = 0x%x\n", readl(&(tb-> BusTypes)));	for(i=0;i<16;i++)		temp_name[i] = readb(&(tb->ServerName[i]));	temp_name[16] = '\0';	printk("   Server Name = %s\n", temp_name);	printk("   Heartbeat Counter = 0x%x\n\n\n", 			readl(&(tb->HeartBeat)));}#endif /* CCISS_DEBUG */static int cciss_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn){	ushort vendor_id, device_id, command;	unchar cache_line_size, latency_timer;	unchar irq, revision;	uint addr[6];	__u32 board_id;	struct pci_dev *pdev;	int i;	pdev = pci_find_slot(bus, device_fn);	vendor_id = pdev->vendor;	device_id = pdev->device;	irq = pdev->irq;	for(i=0; i<6; i++)

⌨️ 快捷键说明

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