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

📄 cpqarray.c

📁 Linux块设备驱动源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	hba[i]->timer.data = (unsigned long)hba[i];	hba[i]->timer.function = ida_timer;	add_timer(&hba[i]->timer);	/* Enable IRQ now that spinlock and rate limit timer are set up */	hba[i]->access.set_intr_mask(hba[i], FIFO_NOT_EMPTY);	for(j=0; j<NWD; j++) {		struct gendisk *disk = ida_gendisk[i][j];		drv_info_t *drv = &hba[i]->drv[j];		sprintf(disk->disk_name, "ida/c%dd%d", i, j);		disk->major = COMPAQ_SMART2_MAJOR + i;		disk->first_minor = j<<NWD_SHIFT;		disk->fops = &ida_fops;		if (j && !drv->nr_blks)			continue;		blk_queue_hardsect_size(hba[i]->queue, drv->blk_size);		set_capacity(disk, drv->nr_blks);		disk->queue = hba[i]->queue;		disk->private_data = drv;		add_disk(disk);	}	/* done ! */	return(i);Enomem1:	nr_ctlr = i; 	kfree(hba[i]->cmd_pool_bits);	if (hba[i]->cmd_pool)		pci_free_consistent(hba[i]->pci_dev, NR_CMDS*sizeof(cmdlist_t), 				    hba[i]->cmd_pool, hba[i]->cmd_pool_dhandle);Enomem2:	while (j--) {		put_disk(ida_gendisk[i][j]);		ida_gendisk[i][j] = NULL;	}	free_irq(hba[i]->intr, hba[i]);Enomem3:	unregister_blkdev(COMPAQ_SMART2_MAJOR+i, hba[i]->devname);Enomem4:	if (pdev)		pci_set_drvdata(pdev, NULL);	release_io_mem(hba[i]);	free_hba(i);	printk( KERN_ERR "cpqarray: out of memory");	return -1;}static int __init cpqarray_init_one( struct pci_dev *pdev,	const struct pci_device_id *ent){	int i;	printk(KERN_DEBUG "cpqarray: Device 0x%x has been found at"			" bus %d dev %d func %d\n",			pdev->device, pdev->bus->number, PCI_SLOT(pdev->devfn),			PCI_FUNC(pdev->devfn));	i = alloc_cpqarray_hba();	if( i < 0 )		return (-1);	memset(hba[i], 0, sizeof(ctlr_info_t));	sprintf(hba[i]->devname, "ida%d", i);	hba[i]->ctlr = i;	/* Initialize the pdev driver private data */	pci_set_drvdata(pdev, hba[i]);	if (cpqarray_pci_init(hba[i], pdev) != 0) {		pci_set_drvdata(pdev, NULL);		release_io_mem(hba[i]);		free_hba(i);		return -1;	}	return (cpqarray_register_ctlr(i, pdev));}static struct pci_driver cpqarray_pci_driver = {	.name = "cpqarray",	.probe = cpqarray_init_one,	.remove = __devexit_p(cpqarray_remove_one_pci),	.id_table = cpqarray_pci_device_id,};/* *  This is it.  Find all the controllers and register them. *  returns the number of block devices registered. */static int __init cpqarray_init(void){	int num_cntlrs_reg = 0;	int i;	int rc = 0;	/* detect controllers */	printk(DRIVER_NAME "\n");	rc = pci_register_driver(&cpqarray_pci_driver);	if (rc)		return rc;	cpqarray_eisa_detect();		for (i=0; i < MAX_CTLR; i++) {		if (hba[i] != NULL)			num_cntlrs_reg++;	}	return(num_cntlrs_reg);}/* Function to find the first free pointer into our hba[] array *//* Returns -1 if no free entries are left.  */static int alloc_cpqarray_hba(void){	int i;	for(i=0; i< MAX_CTLR; i++) {		if (hba[i] == NULL) {			hba[i] = kmalloc(sizeof(ctlr_info_t), GFP_KERNEL);			if(hba[i]==NULL) {				printk(KERN_ERR "cpqarray: out of memory.\n");				return (-1);			}			return (i);		}	}	printk(KERN_WARNING "cpqarray: This driver supports a maximum"		" of 8 controllers.\n");	return(-1);}static void free_hba(int i){	kfree(hba[i]);	hba[i]=NULL;}/* * 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;	if (pci_enable_device(pdev)) {		printk(KERN_ERR "cpqarray: Unable to Enable PCI device\n");		return -1;	}	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_set_dma_mask(pdev, CPQARRAY_DMA_MASK) != 0)	{		printk(KERN_ERR "cpqarray: Unable to set DMA mask\n");		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);	/* check to see if controller has been disabled */	if(!(command & 0x02)) {		printk(KERN_WARNING			"cpqarray: controller appears to be disabled\n");		return(-1);	}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;	for(i=0; i<6; i++) {		if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO)		{ /* IO space */			c->io_mem_addr = addr[i];			c->io_mem_length = pci_resource_end(pdev, i)				- pci_resource_start(pdev, i) + 1;			if(!request_region( c->io_mem_addr, c->io_mem_length,				"cpqarray"))			{				printk( KERN_WARNING "cpqarray I/O memory range already in use addr %lx length = %ld\n", c->io_mem_addr, c->io_mem_length);				c->io_mem_addr = 0;				c->io_mem_length = 0;			}			break;		}	}	c->paddr = 0;	for(i=0; i<6; i++)		if (!(pci_resource_flags(pdev, i) &				PCI_BASE_ADDRESS_SPACE_IO)) {			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 __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);}#ifndef MODULE/* * Config string is a comma separated 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);#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;	int ctlr;	int num_ctlr = 0;	while(i<8 && eisa[i]) {		ctlr = alloc_cpqarray_hba();		if(ctlr == -1)			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;		}		memset(hba[ctlr], 0, sizeof(ctlr_info_t));		hba[ctlr]->io_mem_addr = eisa[i];		hba[ctlr]->io_mem_length = 0x7FF;		if(!request_region(hba[ctlr]->io_mem_addr,				hba[ctlr]->io_mem_length,				"cpqarray"))		{			printk(KERN_WARNING "cpqarray: I/O range already in "					"use addr = %lx length = %ld\n",					hba[ctlr]->io_mem_addr,					hba[ctlr]->io_mem_length);			free_hba(ctlr);			continue;		}		/*		 * 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[ctlr]->intr = intr;		sprintf(hba[ctlr]->devname, "ida%d", nr_ctlr);		hba[ctlr]->product_name = products[j].product_name;		hba[ctlr]->access = *(products[j].access);		hba[ctlr]->ctlr = ctlr;		hba[ctlr]->board_id = board_id;		hba[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););		num_ctlr++;		i++;		if (cpqarray_register_ctlr(ctlr, NULL) == -1)			printk(KERN_WARNING				"cpqarray: Can't register EISA controller %d\n",				ctlr);	}	return num_ctlr;}/* * Open.  Make sure the device is really there. */static int ida_open(struct inode *inode, struct file *filep){	drv_info_t *drv = get_drv(inode->i_bdev->bd_disk);	ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);	DBGINFO(printk("ida_open %s\n", inode->i_bdev->bd_disk->disk_name));	/*	 * Root is allowed to open raw volume zero even if it's 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 (!drv->nr_blks) {		if (!capable(CAP_SYS_RAWIO))			return -ENXIO;		if (!capable(CAP_SYS_ADMIN) && drv != host->drv)			return -ENXIO;	}	host->usage_count++;	return 0;}/* * Close.  Sync first. */static int ida_release(struct inode *inode, struct file *filep){	ctlr_info_t *host = get_host(inode->i_bdev->bd_disk);	host->usage_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(request_queue_t *q){	ctlr_info_t *h = q->queuedata;	cmdlist_t *c;	struct request *creq;	struct scatterlist tmp_sg[SG_MAX];	int i, dir, seg;	if (blk_queue_plugged(q))		goto startio;queue_next:	creq = elv_next_request(q);	if (!creq)		goto startio;	if (creq->nr_phys_segments > SG_MAX)		BUG();	if ((c = cmd_alloc(h,1)) == NULL)		goto startio;	blkdev_dequeue_request(creq);	c->ctlr = h->ctlr;	c->hdr.unit = (drv_info_t *)(creq->rq_disk->private_data) - h->drv;	c->hdr.size = sizeof(rblk_t) >> 2;	c->size += sizeof(rblk_t);	c->req.hdr.blk = creq->sector;	c->rq = creq;DBGPX(	printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors););	seg = blk_rq_map_sg(q, creq, tmp_sg);

⌨️ 快捷键说明

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