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

📄 cciss.c

📁 Linux块设备驱动源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	printk(KERN_INFO "      blocks= %u block_size= %d\n",		*total_size, *block_size);	return;}static int cciss_revalidate(struct gendisk *disk){	ctlr_info_t *h = get_host(disk);	drive_info_struct *drv = get_drv(disk);	int logvol;	int FOUND=0;	unsigned int block_size;	unsigned int total_size;	ReadCapdata_struct *size_buff = NULL;	InquiryData_struct *inq_buff = NULL;	for(logvol=0; logvol < CISS_MAX_LUN; logvol++)	{		if(h->drv[logvol].LunID == drv->LunID) {			FOUND=1;			break;		}	}	if (!FOUND) return 1;	size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);        if (size_buff == NULL)        {                printk(KERN_WARNING "cciss: out of memory\n");                return 1;        }	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);        if (inq_buff == NULL)        {                printk(KERN_WARNING "cciss: out of memory\n");		kfree(size_buff);                return 1;        }	cciss_read_capacity(h->ctlr, logvol, size_buff, 1, &total_size, &block_size);	cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, inq_buff, drv);	blk_queue_hardsect_size(drv->queue, drv->block_size);	set_capacity(disk, drv->nr_blocks);	kfree(size_buff);	kfree(inq_buff);	return 0;}/* *   Wait polling for a command to complete. *   The memory mapped FIFO is polled for the completion. *   Used only at init time, interrupts from the HBA are disabled. */static unsigned long pollcomplete(int ctlr){	unsigned long done;	int i;	/* Wait (up to 20 seconds) for a command to complete */	for (i = 20 * HZ; i > 0; i--) {		done = hba[ctlr]->access.command_completed(hba[ctlr]);		if (done == FIFO_EMPTY)			schedule_timeout_uninterruptible(1);		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, /* 0: address the controller,				      1: address logical volume log_unit, 				      2: periph device address is scsi3addr */	unsigned int log_unit,	__u8	page_code,	unsigned char *scsi3addr,	int cmd_type){	CommandList_struct *c;	int i;	unsigned long complete;	ctlr_info_t *info_p= hba[ctlr];	u64bit buff_dma_handle;	int status;	if ((c = cmd_alloc(info_p, 1)) == NULL) {		printk(KERN_WARNING "cciss: unable to get memory");		return(IO_ERROR);	}	status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num,		log_unit, page_code, scsi3addr, cmd_type);	if (status != IO_OK) {		cmd_free(info_p, c, 1);		return status;	}resend_cmd1:	/*         * 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 */	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_REPORT_PHYS) ||			     (c->Request.CDB[0] == CISS_INQUIRY)) &&				((c->err_info->CommandStatus == 					CMD_DATA_OVERRUN) || 				 (c->err_info->CommandStatus == 					CMD_DATA_UNDERRUN)			 	))			{				complete = c->busaddr;			} else {				if (c->err_info->CommandStatus ==						CMD_UNSOLICITED_ABORT) {					printk(KERN_WARNING "cciss%d: "						"unsolicited abort %p\n",						ctlr, c);					if (c->retry_count < MAX_CMD_RETRIES) {						printk(KERN_WARNING						   "cciss%d: retrying %p\n",						   ctlr, c);						c->retry_count++;						/* erase the old error */						/* information */						memset(c->err_info, 0,						   sizeof(ErrorInfo_struct));						goto resend_cmd1;					} else {						printk(KERN_WARNING						   "cciss%d: retried %p too "						   "many times\n", ctlr, c);						status = IO_ERROR;						goto cleanup1;					}				}				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);				status = IO_ERROR;				goto cleanup1;			}		}                if (complete != c->busaddr) {                        printk( KERN_WARNING "cciss cciss%d: SendCmd "                      "Invalid command list address returned! (%lx)\n",                                ctlr, complete);			status = IO_ERROR;			goto cleanup1;                }        } else {                printk( KERN_WARNING                        "cciss cciss%d: SendCmd Timeout out, "                        "No command list address returned!\n",                        ctlr);		status = IO_ERROR;        }		cleanup1:		/* unlock the data buffer from DMA */	buff_dma_handle.val32.lower = c->SG[0].Addr.lower;	buff_dma_handle.val32.upper = c->SG[0].Addr.upper;	pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val,				c->SG[0].Len, PCI_DMA_BIDIRECTIONAL);	cmd_free(info_p, c, 1);	return (status);} /* * Map (physical) PCI mem into (virtual) kernel space */static void __iomem *remap_pci_mem(ulong base, ulong size){        ulong page_base        = ((ulong) base) & PAGE_MASK;        ulong page_offs        = ((ulong) base) - page_base;        void __iomem *page_remapped = ioremap(page_base, page_offs+size);        return page_remapped ? (page_remapped + page_offs) : NULL;}/*  * 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");			break;		}		/* 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 bio *bio, int status){	while (bio) {		struct bio *xbh = bio->bi_next; 		int nr_sectors = bio_sectors(bio);		bio->bi_next = NULL; 		blk_finished_io(len);		bio_endio(bio, nr_sectors << 9, status ? 0 : -EIO);		bio = xbh;	}} /* Assumes that CCISS_LOCK(h->ctlr) is held. *//* Zeros out the error record and then resends the command back *//* to the controller */static inline void resend_cciss_cmd( ctlr_info_t *h, CommandList_struct *c){	/* erase the old error information */	memset(c->err_info, 0, sizeof(ErrorInfo_struct));	/* add it to software queue and then send it to the controller */	addQ(&(h->reqQ),c);	h->Qdepth++;	if(h->Qdepth > h->maxQsinceinit)		h->maxQsinceinit = h->Qdepth;	start_io(h);}/* checks the status of the job and calls complete buffers to mark all  * buffers for the completed job.  */ static inline void complete_command( ctlr_info_t *h, CommandList_struct *cmd,		int timeout){	int status = 1;	int i;	int retry_cmd = 0;	u64bit temp64;			if (timeout)		status = 0; 	if(cmd->err_info->CommandStatus != 0) 	{ /* an error has occurred */ 		switch(cmd->err_info->CommandStatus)		{			unsigned char sense_key;			case CMD_TARGET_STATUS:				status = 0;							if( cmd->err_info->ScsiStatus == 0x02)				{					printk(KERN_WARNING "cciss: cmd %p "                                        	"has CHECK CONDITION "						" byte 2 = 0x%x\n", cmd,						cmd->err_info->SenseInfo[2]					);					/* check the sense key */					sense_key = 0xf & 						cmd->err_info->SenseInfo[2];					/* no status or recovered error */					if((sense_key == 0x0) ||					    (sense_key == 0x1))					{							status = 1;					}				} else				{					printk(KERN_WARNING "cciss: cmd %p "                                                "has SCSI Status 0x%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%d: unsolicited "					"abort %p\n", h->ctlr, cmd);				if (cmd->retry_count < MAX_CMD_RETRIES) {					retry_cmd=1;					printk(KERN_WARNING						"cciss%d: retrying %p\n",						h->ctlr, cmd);					cmd->retry_count++;				} else					printk(KERN_WARNING						"cciss%d: %p retried too "						"many times\n", h->ctlr, 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;		}	}	/* We need to return this command */	if(retry_cmd) {		resend_cciss_cmd(h,cmd);		return;	}		/* command did not need to be retried */	/* 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_page(hba[cmd->ctlr]->pdev,			temp64.val, cmd->SG[i].Len,			(cmd->Request.Type.Direction == XFER_READ) ?				PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);	}	complete_buffers(cmd->rq->bio, status);#ifdef CCISS_DEBUG	printk("Done with %p\n", cmd->rq);#endif /* CCISS_DEBUG */ 	end_that_request_last(cmd->rq);	cmd_free(h,cmd,1);}/*  * Get a request and submit it to the controller.  */static void do_cciss_request(request_queue_t *q){	ctlr_info_t *h= q->queuedata; 	CommandList_struct *c;	int start_blk, seg;	struct request *creq;	u64bit temp64;	struct scatterlist tmp_sg[MAXSGENTRIES];	drive_info_struct *drv;	int i, dir;	/* We call start_io here in case there is a command waiting on the	 * queue that has not been sent.	*/	if (blk_queue_plugged(q))		goto startio;queue:	creq = elv_next_requ

⌨️ 快捷键说明

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