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

📄 cpqarray.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 4 页
字号:
			if(hba[i]->cmd_pool_bits == NULL || hba[i]->cmd_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);			free_irq(hba[i]->intr, hba[i]);			unregister_blkdev(MAJOR_NR+i, hba[i]->devname);			num_cntlrs_reg--;                	printk( KERN_ERR "cpqarray: out of memory");			/* If num_cntlrs_reg == 0, no controllers worked. 			 *	init_module will fail, so clean up global 			 *	memory that clean_module would do.			*/					if (num_cntlrs_reg == 0) 			{				kfree(ida);				kfree(ida_sizes);				kfree(ida_hardsizes);				kfree(ida_blocksizes);			}                	return(num_cntlrs_reg);			}		memset(hba[i]->cmd_pool, 0, NR_CMDS * sizeof(cmdlist_t));		memset(hba[i]->cmd_pool_bits, 0, ((NR_CMDS+31)/32)*sizeof(__u32));		printk(KERN_INFO "cpqarray: Finding drives on %s", 			hba[i]->devname);		getgeometry(i);		start_fwbk(i); 		hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);		ida_procinit(i);		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 			request_fns[i]);				blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR + i), 0);		blksize_size[MAJOR_NR+i] = ida_blocksizes + (i*256);		hardsect_size[MAJOR_NR+i] = ida_hardsizes + (i*256);		read_ahead[MAJOR_NR+i] = READ_AHEAD;		ida_gendisk[i].major = MAJOR_NR + i;		ida_gendisk[i].major_name = "ida";		ida_gendisk[i].minor_shift = NWD_SHIFT;		ida_gendisk[i].max_p = 16;		ida_gendisk[i].part = ida + (i*256);		ida_gendisk[i].sizes = ida_sizes + (i*256);		ida_gendisk[i].nr_real = 0; 			/* Get on the disk list */		ida_gendisk[i].next = gendisk_head;		gendisk_head = &ida_gendisk[i];		init_timer(&hba[i]->timer);		hba[i]->timer.expires = jiffies + IDA_TIMER;		hba[i]->timer.data = (unsigned long)hba[i];		hba[i]->timer.function = ida_timer;		add_timer(&hba[i]->timer);		ida_geninit(i);		for(j=0; j<NWD; j++)				register_disk(&ida_gendisk[i], 				MKDEV(MAJOR_NR+i,j<<4),				16, &ida_fops, hba[i]->drv[j].nr_blks);	}	/* done ! */	return(num_cntlrs_reg);}/* * Find the controller and initialize it *  Cannot use the class code to search, because older array controllers use *    0x018000 and new ones use 0x010400.  So I might as well search for each *    each device IDs, being there are only going to be three of them.  */static int cpqarray_pci_detect(void){	struct pci_dev *pdev;#define IDA_BOARD_TYPES 3	static int ida_vendor_id[IDA_BOARD_TYPES] = { PCI_VENDOR_ID_DEC, 		PCI_VENDOR_ID_NCR, PCI_VENDOR_ID_COMPAQ };	static int ida_device_id[IDA_BOARD_TYPES] = { PCI_DEVICE_ID_COMPAQ_42XX,		PCI_DEVICE_ID_NCR_53C1510, PCI_DEVICE_ID_COMPAQ_SMART2P };	int brdtype;		/* search for all PCI board types that could be for this driver */	for(brdtype=0; brdtype<IDA_BOARD_TYPES; brdtype++)	{		pdev = pci_find_device(ida_vendor_id[brdtype],				       ida_device_id[brdtype], NULL);		while (pdev) {			printk(KERN_DEBUG "cpqarray: Device %x has been found at %x %x\n",				ida_vendor_id[brdtype],				pdev->bus->number, pdev->devfn);			if (nr_ctlr == 8) {				printk(KERN_WARNING "cpqarray: This driver"				" supports a maximum of 8 controllers.\n");				break;			}			/* if it is a PCI_DEVICE_ID_NCR_53C1510, make sure it's 				the Compaq version of the chip */ 			if (ida_device_id[brdtype] == PCI_DEVICE_ID_NCR_53C1510)			{					unsigned short subvendor=pdev->subsystem_vendor;				if(subvendor !=  PCI_VENDOR_ID_COMPAQ)				{					printk(KERN_DEBUG 						"cpqarray: not a Compaq integrated array controller\n");					continue;				}			}			hba[nr_ctlr] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);			if(hba[nr_ctlr]==NULL)			{				printk(KERN_ERR "cpqarray: out of memory.\n");				continue;			}			memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));			if (cpqarray_pci_init(hba[nr_ctlr], pdev) != 0)			{				kfree(hba[nr_ctlr]);				continue;			}			sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);			hba[nr_ctlr]->ctlr = nr_ctlr;			nr_ctlr++;			pdev = pci_find_device(ida_vendor_id[brdtype],					       ida_device_id[brdtype], pdev);		}	}	return nr_ctlr;}/* * Find the IO address of the controller, its IRQ and so forth.  Fill * in some basic stuff into the ctlr_info_t structure. */static int cpqarray_pci_init(ctlr_info_t *c, struct pci_dev *pdev){	ushort vendor_id, device_id, command;	unchar cache_line_size, latency_timer;	unchar irq, revision;	unsigned long addr[6];	__u32 board_id;	int i;	c->pci_dev = pdev;	vendor_id = pdev->vendor;	device_id = pdev->device;	irq = pdev->irq;	for(i=0; i<6; i++)		addr[i] = pci_resource_start(pdev, i);	if (pci_enable_device(pdev))		return -1;	pci_read_config_word(pdev, PCI_COMMAND, &command);	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision);	pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &cache_line_size);	pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_timer);	pci_read_config_dword(pdev, 0x2c, &board_id);DBGINFO(	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] = %lx\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););	c->intr = irq;	c->ioaddr = addr[0];	c->paddr = 0;	for(i=0; i<6; i++)		if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) {			c->paddr = pci_resource_start (pdev, i);			break;		}	if (!c->paddr)		return -1;	c->vaddr = remap_pci_mem(c->paddr, 128);	if (!c->vaddr)		return -1;	c->board_id = board_id;	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 "cpqarray: Sorry, I don't know how"			" to access the SMART Array controller %08lx\n", 				(unsigned long)board_id);		return -1;	}	return 0;}/* * Map (physical) PCI mem into (virtual) kernel space */static void *remap_pci_mem(ulong base, ulong size){        ulong page_base        = ((ulong) base) & PAGE_MASK;        ulong page_offs        = ((ulong) base) - page_base;        void *page_remapped    = ioremap(page_base, page_offs+size);        return (page_remapped ? (page_remapped + page_offs) : NULL);}#ifndef MODULE#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)/* * Config string is a comma seperated set of i/o addresses of EISA cards. */static int cpqarray_setup(char *str){	int i, ints[9];	(void)get_options(str, ARRAY_SIZE(ints), ints);	for(i=0; i<ints[0] && i<8; i++)		eisa[i] = ints[i+1];	return 1;}__setup("smart2=", cpqarray_setup);#else/* * Copy the contents of the ints[] array passed to us by init. */void cpqarray_setup(char *str, int *ints){	int i;	for(i=0; i<ints[0] && i<8; i++)		eisa[i] = ints[i+1];}#endif#endif/* * Find an EISA controller's signature.  Set up an hba if we find it. */static int cpqarray_eisa_detect(void){	int i=0, j;	__u32 board_id;	int intr;	while(i<8 && eisa[i]) {		if (nr_ctlr == 8) {			printk(KERN_WARNING "cpqarray: This driver supports"				" a maximum of 8 controllers.\n");			break;		}		board_id = inl(eisa[i]+0xC80);		for(j=0; j < NR_PRODUCTS; j++)			if (board_id == products[j].board_id) 				break;		if (j == NR_PRODUCTS) {			printk(KERN_WARNING "cpqarray: Sorry, I don't know how"				" to access the SMART Array controller %08lx\n",				 (unsigned long)board_id);			continue;		}		hba[nr_ctlr] = (ctlr_info_t *) kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);		if(hba[nr_ctlr]==NULL)		{			printk(KERN_ERR "cpqarray: out of memory.\n");			continue;		}		memset(hba[nr_ctlr], 0, sizeof(ctlr_info_t));		hba[nr_ctlr]->ioaddr = eisa[i];		/*		 * Read the config register to find our interrupt		 */		intr = inb(eisa[i]+0xCC0) >> 4;		if (intr & 1) intr = 11;		else if (intr & 2) intr = 10;		else if (intr & 4) intr = 14;		else if (intr & 8) intr = 15;				hba[nr_ctlr]->intr = intr;		sprintf(hba[nr_ctlr]->devname, "ida%d", nr_ctlr);		hba[nr_ctlr]->product_name = products[j].product_name;		hba[nr_ctlr]->access = *(products[j].access);		hba[nr_ctlr]->ctlr = nr_ctlr;		hba[nr_ctlr]->board_id = board_id;		hba[nr_ctlr]->pci_dev = NULL; /* not PCI */DBGINFO(	printk("i = %d, j = %d\n", i, j);	printk("irq = %x\n", intr);	printk("product name = %s\n", products[j].product_name);	printk("board_id = %x\n", board_id););		nr_ctlr++;		i++;	}	return nr_ctlr;}/* * Open.  Make sure the device is really there. */static int ida_open(struct inode *inode, struct file *filep){	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;	DBGINFO(printk("ida_open %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );	if (ctlr > MAX_CTLR || hba[ctlr] == NULL)		return -ENXIO;	if (!suser() && ida_sizes[(ctlr << CTLR_SHIFT) +						MINOR(inode->i_rdev)] == 0)		return -ENXIO;	/*	 * Root is allowed to open raw volume zero even if its not configured	 * so array config can still work.  I don't think I really like this,	 * but I'm already using way to many device nodes to claim another one	 * for "raw controller".	 */	if (suser()		&& ida_sizes[(ctlr << CTLR_SHIFT) + MINOR(inode->i_rdev)] == 0 		&& MINOR(inode->i_rdev) != 0)		return -ENXIO;	hba[ctlr]->drv[dsk].usage_count++;	hba[ctlr]->usage_count++;	MOD_INC_USE_COUNT;	return 0;}/* * Close.  Sync first. */static int ida_release(struct inode *inode, struct file *filep){	int ctlr = MAJOR(inode->i_rdev) - MAJOR_NR;	int dsk  = MINOR(inode->i_rdev) >> NWD_SHIFT;	DBGINFO(printk("ida_release %x (%x:%x)\n", inode->i_rdev, ctlr, dsk) );	hba[ctlr]->drv[dsk].usage_count--;	hba[ctlr]->usage_count--;	MOD_DEC_USE_COUNT;	return 0;}/* * Enqueuing and dequeuing functions for cmdlists. */static inline void addQ(cmdlist_t **Qptr, cmdlist_t *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 cmdlist_t *removeQ(cmdlist_t **Qptr, cmdlist_t *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;}/* * Get a request and submit it to the controller. * This routine needs to grab all the requests it possibly can from the * req Q and submit them.  Interrupts are off (and need to be off) when you * are in here (either via the dummy do_ida_request functions or by being * called from the interrupt handler */static void do_ida_request(int ctlr){	ctlr_info_t *h = hba[ctlr];	cmdlist_t *c;	int seg, sect;	char *lastdataend;	struct list_head * queue_head;	struct buffer_head *bh;	struct request *creq;	queue_head = &blk_dev[MAJOR_NR+ctlr].request_queue.queue_head;	if (list_empty(queue_head))	{		start_io(h);		return;	}	creq = blkdev_entry_next_request(queue_head);	if (creq->rq_status == RQ_INACTIVE)	{	                start_io(h);                return;        }	if (ctlr != MAJOR(creq->rq_dev)-MAJOR_NR ||		ctlr > nr_ctlr || h == NULL) 	{		printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",				ctlr, creq->rq_dev, creq);		complete_buffers(creq->bh, 0);		start_io(h);                return;	}	if ((c = cmd_alloc(h)) == NULL)	{                start_io(h);                return;        }	bh = creq->bh;	c->ctlr = ctlr;	c->hdr.unit = MINOR(creq->rq_dev) >> NWD_SHIFT;

⌨️ 快捷键说明

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