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

📄 cciss.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 4 页
字号:
		addr[i] = pdev->resource[i].start;	if (pci_enable_device(pdev))		return( -1);		(void) pci_read_config_word(pdev, PCI_COMMAND,&command);	(void) pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);	(void) pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE,						&cache_line_size);	(void) pci_read_config_byte(pdev, PCI_LATENCY_TIMER,						&latency_timer);	(void) pci_read_config_dword(pdev, PCI_SUBSYSTEM_VENDOR_ID, 						&board_id);#ifdef CCISS_DEBUG	printk("vendor_id = %x\n", vendor_id);	printk("device_id = %x\n", device_id);	printk("command = %x\n", command);	for(i=0; i<6; i++)		printk("addr[%d] = %x\n", i, addr[i]);	printk("revision = %x\n", revision);	printk("irq = %x\n", irq);	printk("cache_line_size = %x\n", cache_line_size);	printk("latency_timer = %x\n", latency_timer);	printk("board_id = %x\n", board_id);#endif /* CCISS_DEBUG */ 	c->intr = irq;	/*	 * Memory base addr is first addr , the second points to the config         *   table	 */	c->paddr = pci_resource_start(pdev, 0);	c->vaddr = remap_pci_mem(c->paddr, 128);	c->cfgtable = (CfgTable_struct *) remap_pci_mem(addr[1], 						sizeof(CfgTable_struct));	c->board_id = board_id;#ifdef CCISS_DEBUG	print_cfg_table(c->cfgtable); #endif /* CCISS_DEBUG */	for(i=0; i<NR_PRODUCTS; i++) {		if (board_id == products[i].board_id) {			c->product_name = products[i].product_name;			c->access = *(products[i].access);			break;		}	}	if (i == NR_PRODUCTS) {		printk(KERN_WARNING "cciss: Sorry, I don't know how"			" to access the Smart Array controller %08lx\n", 				(unsigned long)board_id);		return -1;	}#ifdef CCISS_DEBUG	printk("Trying to put board into Simple mode\n");#endif /* CCISS_DEBUG */ 	c->max_commands = readl(&(c->cfgtable->CmdsOutMax));	/* Update the field, and then ring the doorbell */ 	writel( CFGTBL_Trans_Simple, 		&(c->cfgtable->HostWrite.TransportRequest));	writel( CFGTBL_ChangeReq, c->vaddr + SA5_DOORBELL);	for(i=0;i<MAX_CONFIG_WAIT;i++)	{		if (!(readl(c->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))			break;		/* delay and try again */		udelay(1000);	}	#ifdef CCISS_DEBUG	printk(KERN_DEBUG "I counter got to %d %x\n", i, readl(c->vaddr + SA5_DOORBELL));#endif /* CCISS_DEBUG */#ifdef CCISS_DEBUG	print_cfg_table(c->cfgtable);	#endif /* CCISS_DEBUG */ 	if (!(readl(&(c->cfgtable->TransportActive)) & CFGTBL_Trans_Simple))	{		printk(KERN_WARNING "cciss: unable to get board into"					" simple mode\n");		return -1;	}	return 0;}/*  * Scans PCI space for any controllers that this driver can control.  */static int cciss_pci_detect(void){	int index;	unchar bus=0, dev_fn=0;			for(index=0; ; index++) {			if (pcibios_find_device(PCI_VENDOR_ID_COMPAQ,			 	PCI_DEVICE_ID_COMPAQ_CISS, 					index, &bus, &dev_fn))				break;			printk(KERN_DEBUG "cciss: Device %x has been found at %x %x\n",				PCI_DEVICE_ID_COMPAQ_CISS, bus, dev_fn);			if (index == 1000000) break;			if (nr_ctlr == 8) {				printk(KERN_WARNING "cciss: This driver"				" supports a maximum of 8 controllers.\n");				break;			}			hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);			if(hba[nr_ctlr]==NULL)			{				printk(KERN_ERR "cciss: out of memory.\n");				continue;			}			memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));			if (cciss_pci_init(hba[nr_ctlr], bus, dev_fn) != 0)			{				kfree(hba[nr_ctlr]);				continue;			}			sprintf(hba[nr_ctlr]->devname, "cciss%d", nr_ctlr);			hba[nr_ctlr]->ctlr = nr_ctlr;			hba[nr_ctlr]->pci_bus = bus;			hba[nr_ctlr]->pci_dev_fn = dev_fn;			nr_ctlr++;		}	return nr_ctlr;}/*  * Gets information about the local volumes attached to the controller.  */ static void cciss_getgeometry(int cntl_num){	ReportLunData_struct *ld_buff;	ReadCapdata_struct *size_buff;	InquiryData_struct *inq_buff;	int return_code;	int i;	int listlength = 0;	int lunid = 0;	int block_size;	int total_size; 	ld_buff = kmalloc(sizeof(ReportLunData_struct), GFP_KERNEL);	if (ld_buff == NULL)	{		printk(KERN_ERR "cciss: out of memory\n");		return;	}	memset(ld_buff, 0, sizeof(ReportLunData_struct));	size_buff = kmalloc(sizeof( ReadCapdata_struct), GFP_KERNEL);        if (size_buff == NULL)        {                printk(KERN_ERR "cciss: out of memory\n");		kfree(ld_buff);                return;        }	inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);        if (inq_buff == NULL)        {                printk(KERN_ERR "cciss: out of memory\n");                kfree(ld_buff);		kfree(size_buff);                return;        }	/* Get the firmware version */ 	return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff, 		sizeof(InquiryData_struct), 0, 0 ,0 );	if (return_code == IO_OK)	{		hba[cntl_num]->firm_ver[0] = inq_buff->data_byte[32];		hba[cntl_num]->firm_ver[1] = inq_buff->data_byte[33];		hba[cntl_num]->firm_ver[2] = inq_buff->data_byte[34];		hba[cntl_num]->firm_ver[3] = inq_buff->data_byte[35];	} else /* send command failed */	{		printk(KERN_WARNING "cciss: unable to determine firmware"			" version of controller\n");	}	/* Get the number of logical volumes */ 	return_code = sendcmd(CISS_REPORT_LOG, cntl_num, ld_buff, 			sizeof(ReportLunData_struct), 0, 0, 0 );	if( return_code == IO_OK)	{#ifdef CCISS_DEBUG		printk("LUN Data\n--------------------------\n");#endif /* CCISS_DEBUG */ 		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;	}	hba[cntl_num]->num_luns = listlength / 8; // 8 bytes pre entry	if (hba[cntl_num]->num_luns > CISS_MAX_LUN)	{		printk(KERN_ERR "ciss:  only %d number of logical volumes supported\n",			CISS_MAX_LUN);		hba[cntl_num]->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],  hba[cntl_num]->num_luns);#endif /* CCISS_DEBUG */	for(i=0; i<  hba[cntl_num]->num_luns ; i++)	{	  	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]);		hba[cntl_num]->drv[i].LunID = lunid;#ifdef CCISS_DEBUG	  	printk(KERN_DEBUG "LUN[%d]:  %x %x %x %x = %x\n", i, 		ld_buff->LUN[i][0], ld_buff->LUN[i][1],ld_buff->LUN[i][2], 		ld_buff->LUN[i][3], hba[cntl_num]->drv[i].LunID);#endif /* CCISS_DEBUG */	  	memset(size_buff, 0, sizeof(ReadCapdata_struct));	  	return_code = sendcmd(CCISS_READ_CAPACITY, cntl_num, size_buff, 				sizeof( ReadCapdata_struct), 1, i, 0 );	  	if (return_code == IO_OK)		{			total_size = (0xff & 				(unsigned int)(size_buff->total_size[0])) << 24;			total_size |= (0xff & 				(unsigned int)(size_buff->total_size[1])) << 16;			total_size |= (0xff & 				(unsigned int)(size_buff->total_size[2])) << 8;			total_size |= (0xff & (unsigned int)				(size_buff->total_size[3])); 			total_size++; // command returns highest block address			block_size = (0xff & 				(unsigned int)(size_buff->block_size[0])) << 24;                	block_size |= (0xff & 				(unsigned int)(size_buff->block_size[1])) << 16;                	block_size |= (0xff & 				(unsigned int)(size_buff->block_size[2])) << 8;                	block_size |= (0xff & 				(unsigned int)(size_buff->block_size[3]));		} else /* read capacity command failed */ 		{			printk(KERN_WARNING "cciss: read capacity failed\n");			total_size = block_size = 0; 		}			printk("      blocks= %d block_size= %d\n", total_size,					block_size);		/* Execute the command to read the disk geometry */		memset(inq_buff, 0, sizeof(InquiryData_struct));		return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,                	sizeof(InquiryData_struct), 1, i ,0xC1 );	  	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");                           hba[cntl_num]->drv[i].block_size = block_size;                           hba[cntl_num]->drv[i].nr_blocks = total_size;                           hba[cntl_num]->drv[i].heads = 255;                           hba[cntl_num]->drv[i].sectors = 32; // Sectors per track                           hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32;                	} else			{		 	   hba[cntl_num]->drv[i].block_size = block_size;                           hba[cntl_num]->drv[i].nr_blocks = total_size;                           hba[cntl_num]->drv[i].heads = 					inq_buff->data_byte[6];                            hba[cntl_num]->drv[i].sectors = 					inq_buff->data_byte[7]; 			   hba[cntl_num]->drv[i].cylinders = 					(inq_buff->data_byte[4] & 0xff) << 8;			   hba[cntl_num]->drv[i].cylinders +=                                         inq_buff->data_byte[5];			}		}		else /* Get geometry failed */		{			printk(KERN_WARNING "cciss: reading geometry failed, continuing with default geometry\n"); 			hba[cntl_num]->drv[i].block_size = block_size;			hba[cntl_num]->drv[i].nr_blocks = total_size;			hba[cntl_num]->drv[i].heads = 255;			hba[cntl_num]->drv[i].sectors = 32; // Sectors per track 			hba[cntl_num]->drv[i].cylinders = total_size / 255 / 32;		}		printk(KERN_INFO "      heads= %d, sectors= %d, cylinders= %d\n\n",			hba[cntl_num]->drv[i].heads, 			hba[cntl_num]->drv[i].sectors,			hba[cntl_num]->drv[i].cylinders);	}	kfree(ld_buff);	kfree(size_buff);}	/* *  This is it.  Find all the controllers and register them.  I really hate *  stealing all these major device numbers. *  returns the number of block devices registered. */int __init cciss_init(void){	int num_cntlrs_reg = 0;	int i,j;	void (*request_fns[MAX_CTLR])(request_queue_t *) = {                do_cciss_request0, do_cciss_request1,                do_cciss_request2, do_cciss_request3,                do_cciss_request4, do_cciss_request5,                do_cciss_request6, do_cciss_request7,        };	/* detect controllers */	cciss_pci_detect();	if (nr_ctlr == 0)		return(num_cntlrs_reg);	printk(KERN_INFO DRIVER_NAME "\n");	printk(KERN_INFO "Found %d controller(s)\n", nr_ctlr);	for(i=0;i<nr_ctlr;i++)	{		if( register_blkdev(MAJOR_NR+i, hba[i]->devname, &cciss_fops))		{			printk(KERN_ERR "cciss:  Unable to get major number "				"%d for %s\n", MAJOR_NR+i, hba[i]->devname);			continue;		}		/* make sure the board interrupts are off */		hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);		if( request_irq(hba[i]->intr, do_cciss_intr, SA_INTERRUPT|SA_SHIRQ, hba[i]->devname, hba[i]))		{			printk(KERN_ERR "ciss: Unable to get irq %d for %s\n",				hba[i]->intr, hba[i]->devname);			unregister_blkdev( MAJOR_NR+i, hba[i]->devname);			continue;		}		num_cntlrs_reg++;		hba[i]->cmd_pool_bits = (__u32*)kmalloc(                                ((NR_CMDS+31)/32)*sizeof(__u32), GFP_KERNEL);		hba[i]->cmd_pool = (CommandList_struct *)kmalloc(                                NR_CMDS * sizeof(CommandList_struct), 					GFP_KERNEL);		hba[i]->errinfo_pool = (ErrorInfo_struct *)kmalloc(                                NR_CMDS * sizeof( ErrorInfo_struct), 					GFP_KERNEL);		if((hba[i]->cmd_pool_bits == NULL) 			|| (hba[i]->cmd_pool == NULL)			|| (hba[i]->errinfo_pool == NULL))                {                        nr_ctlr = i;			if(hba[i]->cmd_pool_bits)                                kfree(hba[i]->cmd_pool_bits);                        if(hba[i]->cmd_pool)                                kfree(hba[i]->cmd_pool);			if(hba[i]->errinfo_pool)				kfree(hba[i]->errinfo_pool);                        free_irq(hba[i]->intr, hba[i]);                        unregister_blkdev(MAJOR_NR+i, hba[i]->devname);                        num_cntlrs_reg--;                        printk( KERN_ERR "cciss: out of memory");			return(num_cntlrs_reg);		}		/* command and error info recs zeroed out before 			they are used */                memset(hba[i]->cmd_pool_bits, 0, 			((NR_CMDS+31)/32)*sizeof(__u32));#ifdef CCISS_DEBUG			printk(KERN_DEBUG "Scanning for drives on controller cciss%d\n",i);#endif /* CCISS_DEBUG */		cciss_getgeometry(i);		/* Turn the interrupts on so we can service requests */		hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);		cciss_procinit(i);				blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR+i),				request_fns[i]);		blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR+i), 0);		/* fill in the other Kernel structs */		blksize_size[MAJOR_NR+i] = hba[i]->blocksizes;                hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes;                read_ahead[MAJOR_NR+i] = READ_AHEAD;		/* Fill in the gendisk data */ 			hba[i]->gendisk.major = MAJOR_NR + i;		hba[i]->gendisk.major_name = "cciss";		hba[i]->gendisk.minor_shift = NWD_SHIFT;		hba[i]->gendisk.max_p = MAX_PART;		hba[i]->gendisk.part = hba[i]->hd;		hba[i]->gendisk.sizes = hba[i]->sizes;		hba[i]->gendisk.nr_real = hba[i]->num_luns;		/* Get on the disk list */ 		hba[i]->gendisk.next = gendisk_head;		gendisk_head = &(hba[i]->gendisk); 		cciss_geninit(i);		for(j=0; j<NWD; j++)			register_disk(&(hba[i]->gendisk),				MKDEV(MAJOR_NR+i, j <<4), 				MAX_PART, &cciss_fops, 				hba[i]->drv[j].nr_blocks);	}	return(nr_ctlr);}EXPORT_NO_SYMBOLS;/* This is a bit of a hack... */static int __init init_cciss_module(void){	if (cciss_init() == 0) /* all the block dev numbers already used */		return -EIO;	  /* or no controllers were found */	return 0;}static void __exit cleanup_cciss_module(void){	int i;	struct gendisk *g;	for(i=0; i<nr_ctlr; i++)	{		/* Turn board interrupts off */ 		hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_OFF);		free_irq(hba[i]->intr, hba[i]);		iounmap((void*)hba[i]->vaddr);		unregister_blkdev(MAJOR_NR+i, hba[i]->devname);		remove_proc_entry(hba[i]->devname, proc_cciss);			/* remove it from the disk list */ 		if (gendisk_head == &(hba[i]->gendisk))		{			gendisk_head = hba[i]->gendisk.next;		} else 		{			for(g=gendisk_head; g ; g=g->next)			{				if(g->next == &(hba[i]->gendisk))				{					g->next = hba[i]->gendisk.next;				}			}		}		remove_proc_entry("driver/cciss", &proc_root);		kfree(hba[i]->cmd_pool);		kfree(hba[i]->errinfo_pool);                kfree(hba[i]->cmd_pool_bits);		kfree(hba[i]);	}}module_init(init_cciss_module);module_exit(cleanup_cciss_module);

⌨️ 快捷键说明

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