cciss.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,278 行 · 第 1/5 页

C
2,278
字号
		switch(c->err_info->CommandStatus)		{			case CMD_TARGET_STATUS:				printk(KERN_WARNING "cciss: cmd %p has "					" completed with errors\n", c);				if( c->err_info->ScsiStatus)                		{                    			printk(KERN_WARNING "cciss: cmd %p "					"has SCSI Status = %x\n",                        			c,  						c->err_info->ScsiStatus);                		}			break;			case CMD_DATA_UNDERRUN:			case CMD_DATA_OVERRUN:			/* expected for inquire and report lun commands */			break;			case CMD_INVALID:				printk(KERN_WARNING "cciss: Cmd %p is "					"reported invalid\n", c);				return_status = IO_ERROR;			break;			case CMD_PROTOCOL_ERR:                                printk(KERN_WARNING "cciss: cmd %p has "					"protocol error \n", c);                                return_status = IO_ERROR;                        break;case CMD_HARDWARE_ERR:                                printk(KERN_WARNING "cciss: cmd %p had "                                         " hardware error\n", c);                                return_status = IO_ERROR;                        break;			case CMD_CONNECTION_LOST:				printk(KERN_WARNING "cciss: cmd %p had "					"connection lost\n", c);				return_status = IO_ERROR;			break;			case CMD_ABORTED:				printk(KERN_WARNING "cciss: cmd %p was "					"aborted\n", c);				return_status = IO_ERROR;			break;			case CMD_ABORT_FAILED:				printk(KERN_WARNING "cciss: cmd %p reports "					"abort failed\n", c);				return_status = IO_ERROR;			break;			case 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));					return_status = IO_OK;					INIT_COMPLETION(wait);					goto resend_cmd2;				}				return_status = IO_ERROR;			break;			default:				printk(KERN_WARNING "cciss: cmd %p returned "					"unknown status %x\n", c, 						c->err_info->CommandStatus); 				return_status = IO_ERROR;		}	}		/* unlock the buffers from DMA */	pci_unmap_single( h->pdev, (dma_addr_t) buff_dma_handle.val,			size, PCI_DMA_BIDIRECTIONAL);	cmd_free(h, c, 0);        return(return_status);}static void cciss_geometry_inquiry(int ctlr, int logvol,			int withirq, unsigned int total_size,			unsigned int block_size, InquiryData_struct *inq_buff,			drive_info_struct *drv){	int return_code;	memset(inq_buff, 0, sizeof(InquiryData_struct));	if (withirq)		return_code = sendcmd_withirq(CISS_INQUIRY, ctlr,			inq_buff, sizeof(*inq_buff), 1, logvol ,0xC1, TYPE_CMD);	else		return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff,			sizeof(*inq_buff), 1, logvol ,0xC1, NULL, TYPE_CMD);	if (return_code == IO_OK) {		if(inq_buff->data_byte[8] == 0xFF) {			printk(KERN_WARNING				"cciss: reading geometry failed, volume "				"does not support reading geometry\n");			drv->block_size = block_size;			drv->nr_blocks = total_size;			drv->heads = 255;			drv->sectors = 32; // Sectors per track			drv->cylinders = total_size / 255 / 32;		} else {			unsigned int t;			drv->block_size = block_size;			drv->nr_blocks = total_size;			drv->heads = inq_buff->data_byte[6];			drv->sectors = inq_buff->data_byte[7];			drv->cylinders = (inq_buff->data_byte[4] & 0xff) << 8;			drv->cylinders += inq_buff->data_byte[5];			drv->raid_level = inq_buff->data_byte[8];			t = drv->heads * drv->sectors;			if (t > 1) {				drv->cylinders = total_size/t;			}		}	} else { /* Get geometry failed */		printk(KERN_WARNING "cciss: reading geometry failed, "			"continuing with default geometry\n");		drv->block_size = block_size;		drv->nr_blocks = total_size;		drv->heads = 255;		drv->sectors = 32; // Sectors per track		drv->cylinders = total_size / 255 / 32;	}	printk(KERN_INFO "      heads= %d, sectors= %d, cylinders= %d\n\n",		drv->heads, drv->sectors, drv->cylinders);}static voidcciss_read_capacity(int ctlr, int logvol, ReadCapdata_struct *buf,		int withirq, unsigned int *total_size, unsigned int *block_size){	int return_code;	memset(buf, 0, sizeof(*buf));	if (withirq)		return_code = sendcmd_withirq(CCISS_READ_CAPACITY,			ctlr, buf, sizeof(*buf), 1, logvol, 0, TYPE_CMD);	else		return_code = sendcmd(CCISS_READ_CAPACITY,			ctlr, buf, sizeof(*buf), 1, logvol, 0, NULL, TYPE_CMD);	if (return_code == IO_OK) {		*total_size = be32_to_cpu(*((__be32 *) &buf->total_size[0]))+1;		*block_size = be32_to_cpu(*((__be32 *) &buf->block_size[0]));	} else { /* read capacity command failed */		printk(KERN_WARNING "cciss: read capacity failed\n");		*total_size = 0;		*block_size = BLOCK_SIZE;	}	printk(KERN_INFO "      blocks= %u block_size= %d\n",		*total_size, *block_size);	return;}static int register_new_disk(ctlr_info_t *h){        struct gendisk *disk;	int ctlr = h->ctlr;        int i;	int num_luns;	int logvol;	int new_lun_found = 0;	int new_lun_index = 0;	int free_index_found = 0;	int free_index = 0;	ReportLunData_struct *ld_buff = NULL;	ReadCapdata_struct *size_buff = NULL;	InquiryData_struct *inq_buff = NULL;	int return_code;	int listlength = 0;	__u32 lunid = 0;	unsigned int block_size;	unsigned int total_size;        if (!capable(CAP_SYS_RAWIO))                return -EPERM;	/* if we have no space in our disk array left to add anything */	if(  h->num_luns >= CISS_MAX_LUN)		return -EINVAL;		ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);	if (ld_buff == NULL)		goto mem_msg;	memset(ld_buff, 0, sizeof(ReportLunData_struct));	size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);        if (size_buff == NULL)		goto mem_msg;	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);        if (inq_buff == NULL)		goto mem_msg;		return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, 			sizeof(ReportLunData_struct), 0, 0, 0, TYPE_CMD);	if( return_code == IO_OK)	{				// printk("LUN Data\n--------------------------\n");		listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[0])) << 24;		listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[1])) << 16;		listlength |= (0xff & (unsigned int)(ld_buff->LUNListLength[2])) << 8;			listlength |= 0xff & (unsigned int)(ld_buff->LUNListLength[3]);	} else /* reading number of logical volumes failed */	{		printk(KERN_WARNING "cciss: report logical volume"			" command failed\n");		listlength = 0;		goto free_err;	}	num_luns = listlength / 8; // 8 bytes pre entry	if (num_luns > CISS_MAX_LUN)	{		num_luns = CISS_MAX_LUN;	}#ifdef CCISS_DEBUG	printk(KERN_DEBUG "Length = %x %x %x %x = %d\n", ld_buff->LUNListLength[0],		ld_buff->LUNListLength[1], ld_buff->LUNListLength[2],		ld_buff->LUNListLength[3],  num_luns);#endif 	for(i=0; i<  num_luns; i++)	{		int j;		int lunID_found = 0;	  	lunid = (0xff & (unsigned int)(ld_buff->LUN[i][3])) << 24;        	lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][2])) << 16;        	lunid |= (0xff & (unsigned int)(ld_buff->LUN[i][1])) << 8;        	lunid |= 0xff & (unsigned int)(ld_buff->LUN[i][0]);		 		/* check to see if this is a new lun */ 		for(j=0; j <= h->highest_lun; j++)		{#ifdef CCISS_DEBUG			printk("Checking %d %x against %x\n", j,h->drv[j].LunID,						lunid);#endif /* CCISS_DEBUG */			if (h->drv[j].LunID == lunid)			{				lunID_found = 1;				break;			}					}		if( lunID_found == 1)			continue;		else		{	/* It is the new lun we have been looking for */#ifdef CCISS_DEBUG			printk("new lun found at %d\n", i);#endif /* CCISS_DEBUG */			new_lun_index = i;			new_lun_found = 1;			break;			}	 }	 if (!new_lun_found)	 {		printk(KERN_WARNING "cciss:  New Logical Volume not found\n");		goto free_err;	 }	 /* Now find the free index 	*/	for(i=0; i <CISS_MAX_LUN; i++)	{#ifdef CCISS_DEBUG		printk("Checking Index %d\n", i);#endif /* CCISS_DEBUG */		if(h->drv[i].LunID == 0)		{#ifdef CCISS_DEBUG			printk("free index found at %d\n", i);#endif /* CCISS_DEBUG */			free_index_found = 1;			free_index = i;			break;		}	}	if (!free_index_found)	{		printk(KERN_WARNING "cciss: unable to find free slot for disk\n");		goto free_err;         }	logvol = free_index;	h->drv[logvol].LunID = lunid;		/* there could be gaps in lun numbers, track hightest */	if(h->highest_lun < lunid)		h->highest_lun = logvol;	cciss_read_capacity(ctlr, logvol, size_buff, 1,		&total_size, &block_size);	cciss_geometry_inquiry(ctlr, logvol, 1, total_size, block_size,			inq_buff, &h->drv[logvol]);	h->drv[logvol].usage_count = 0;	++h->num_luns;	/* setup partitions per disk */        disk = h->gendisk[logvol];	set_capacity(disk, h->drv[logvol].nr_blocks);	add_disk(disk);freeret:	kfree(ld_buff);	kfree(size_buff);	kfree(inq_buff);	return (logvol);mem_msg:	printk(KERN_ERR "cciss: out of memory\n");free_err:	logvol = -1;	goto freeret;}/* *   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) {			set_current_state(TASK_UNINTERRUPTIBLE);			schedule_timeout(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",

⌨️ 快捷键说明

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