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

📄 cciss.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	case BLKRASET:	case BLKRAGET:	case BLKPG:	case BLKELVGET:	case BLKELVSET:		return( blk_ioctl(inode->i_rdev, cmd, arg));	case CCISS_GETPCIINFO:	{		cciss_pci_info_struct pciinfo;		if (!arg) return -EINVAL;		pciinfo.bus = hba[ctlr]->pdev->bus->number;		pciinfo.dev_fn = hba[ctlr]->pdev->devfn;		pciinfo.board_id = hba[ctlr]->board_id;		if (copy_to_user((void *) arg, &pciinfo,  sizeof( cciss_pci_info_struct )))			return  -EFAULT;		return(0);	}		case CCISS_GETINTINFO:	{		cciss_coalint_struct intinfo;		ctlr_info_t *c = hba[ctlr];		if (!arg) return -EINVAL;		intinfo.delay = readl(&c->cfgtable->HostWrite.CoalIntDelay);		intinfo.count = readl(&c->cfgtable->HostWrite.CoalIntCount);		if (copy_to_user((void *) arg, &intinfo, sizeof( cciss_coalint_struct )))			return -EFAULT;                return(0);        }	case CCISS_SETINTINFO:        {                cciss_coalint_struct intinfo;                ctlr_info_t *c = hba[ctlr];		unsigned long flags;		int i;		if (!arg) return -EINVAL;			if (!capable(CAP_SYS_ADMIN)) return -EPERM;		if (copy_from_user(&intinfo, (void *) arg, sizeof( cciss_coalint_struct)))			return -EFAULT;		if ( (intinfo.delay == 0 ) && (intinfo.count == 0))		{//			printk("cciss_ioctl: delay and count cannot be 0\n");			return( -EINVAL);		}		spin_lock_irqsave(&io_request_lock, flags);		/* Can only safely update if no commands outstanding */ 		if (c->commands_outstanding > 0 )		{//			printk("cciss_ioctl: cannot change coalasing "//				"%d commands outstanding on controller\n", //					c->commands_outstanding);			spin_unlock_irqrestore(&io_request_lock, flags);			return(-EINVAL);		}		/* Update the field, and then ring the doorbell */ 		writel( intinfo.delay, 			&(c->cfgtable->HostWrite.CoalIntDelay));		writel( intinfo.count,                         &(c->cfgtable->HostWrite.CoalIntCount));		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);		}			spin_unlock_irqrestore(&io_request_lock, flags);		if (i >= MAX_CONFIG_WAIT)			return( -EFAULT);                return(0);        }	case CCISS_GETNODENAME:        {                NodeName_type NodeName;                ctlr_info_t *c = hba[ctlr];		int i; 		if (!arg) return -EINVAL;		for(i=0;i<16;i++)			NodeName[i] = readb(&c->cfgtable->ServerName[i]);                if (copy_to_user((void *) arg, NodeName, sizeof( NodeName_type)))                	return  -EFAULT;                return(0);        }	case CCISS_SETNODENAME:	{		NodeName_type NodeName;		ctlr_info_t *c = hba[ctlr];		unsigned long flags;		int i;		if (!arg) return -EINVAL;		if (!capable(CAP_SYS_ADMIN)) return -EPERM;				if (copy_from_user(NodeName, (void *) arg, sizeof( NodeName_type)))			return -EFAULT;		spin_lock_irqsave(&io_request_lock, flags);			/* Update the field, and then ring the doorbell */ 		for(i=0;i<16;i++)			writeb( NodeName[i], &c->cfgtable->ServerName[i]);					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);		}			spin_unlock_irqrestore(&io_request_lock, flags);		if (i >= MAX_CONFIG_WAIT)			return( -EFAULT);                return(0);        }	case CCISS_GETHEARTBEAT:        {                Heartbeat_type heartbeat;                ctlr_info_t *c = hba[ctlr];		if (!arg) return -EINVAL;                heartbeat = readl(&c->cfgtable->HeartBeat);                if (copy_to_user((void *) arg, &heartbeat, sizeof( Heartbeat_type)))                	return -EFAULT;                return(0);        }	case CCISS_GETBUSTYPES:        {                BusTypes_type BusTypes;                ctlr_info_t *c = hba[ctlr];		if (!arg) return -EINVAL;                BusTypes = readl(&c->cfgtable->BusTypes);                if (copy_to_user((void *) arg, &BusTypes, sizeof( BusTypes_type) ))                	return  -EFAULT;                return(0);        }	case CCISS_GETFIRMVER:        {		FirmwareVer_type firmware;		if (!arg) return -EINVAL;		memcpy(firmware, hba[ctlr]->firm_ver, 4);                if (copy_to_user((void *) arg, firmware, sizeof( FirmwareVer_type)))                	return -EFAULT;                return(0);        }        case CCISS_GETDRIVVER:        {		DriverVer_type DriverVer = DRIVER_VERSION;                if (!arg) return -EINVAL;                if (copy_to_user((void *) arg, &DriverVer, sizeof( DriverVer_type) ))                	return -EFAULT;                return(0);        }	case CCISS_REVALIDVOLS:                return( revalidate_allvol(inode->i_rdev));		case CCISS_PASSTHRU:	{		IOCTL_Command_struct iocommand;		ctlr_info_t *h = hba[ctlr];		CommandList_struct *c;		char 	*buff = NULL;		u64bit	temp64;		unsigned long flags;		if (!arg) return -EINVAL;			if (!capable(CAP_SYS_RAWIO)) return -EPERM;		if (copy_from_user(&iocommand, (void *) arg, sizeof( IOCTL_Command_struct) ))			return -EFAULT;		if((iocommand.buf_size < 1) && 				(iocommand.Request.Type.Direction != XFER_NONE))		{				return -EINVAL;		} 		/* Check kmalloc limits */		if(iocommand.buf_size > 128000)			return -EINVAL;		if(iocommand.buf_size > 0)		{			buff =  kmalloc(iocommand.buf_size, GFP_KERNEL);			if( buff == NULL) 				return -EFAULT;		}		if (iocommand.Request.Type.Direction == XFER_WRITE)		{			/* Copy the data into the buffer we created */ 			if (copy_from_user(buff, iocommand.buf, iocommand.buf_size))			{				kfree(buff);				return -EFAULT;			}		}		if ((c = cmd_alloc(h , 0)) == NULL)		{			kfree(buff);			return -ENOMEM;		}			// Fill in the command type 		c->cmd_type = CMD_IOCTL_PEND;			// Fill in Command Header 		c->Header.ReplyQueue = 0;  // unused in simple mode		if( iocommand.buf_size > 0) 	// buffer to fill 		{			c->Header.SGList = 1;			c->Header.SGTotal= 1;		} else	// no buffers to fill  		{			c->Header.SGList = 0;                	c->Header.SGTotal= 0;		}		c->Header.LUN = iocommand.LUN_info;		c->Header.Tag.lower = c->busaddr;  // use the kernel address the cmd block for tag				// Fill in Request block 		c->Request = iocommand.Request; 			// Fill in the scatter gather information		if (iocommand.buf_size > 0 ) 		{			temp64.val = pci_map_single( h->pdev, buff,                                        iocommand.buf_size,                                 PCI_DMA_BIDIRECTIONAL);				c->SG[0].Addr.lower = temp64.val32.lower;			c->SG[0].Addr.upper = temp64.val32.upper;			c->SG[0].Len = iocommand.buf_size;			c->SG[0].Ext = 0;  // we are not chaining		}		/* Put the request on the tail of the request queue */		spin_lock_irqsave(&io_request_lock, flags);		addQ(&h->reqQ, c);		h->Qdepth++;		start_io(h);		spin_unlock_irqrestore(&io_request_lock, flags);		/* Wait for completion */		while(c->cmd_type != CMD_IOCTL_DONE)			schedule_timeout(1);		/* unlock the buffers from DMA */		temp64.val32.lower = c->SG[0].Addr.lower;                temp64.val32.upper = c->SG[0].Addr.upper;                pci_unmap_single( h->pdev, (dma_addr_t) temp64.val,                	iocommand.buf_size, PCI_DMA_BIDIRECTIONAL);		/* Copy the error information out */ 		iocommand.error_info = *(c->err_info);		if ( copy_to_user((void *) arg, &iocommand, sizeof( IOCTL_Command_struct) ) )		{			kfree(buff);			cmd_free(h, c, 0);			return( -EFAULT);			} 			if (iocommand.Request.Type.Direction == XFER_READ)                {                        /* Copy the data out of the buffer we created */                        if (copy_to_user(iocommand.buf, buff, iocommand.buf_size))			{                        	kfree(buff);				cmd_free(h, c, 0);				return -EFAULT;			}                }                kfree(buff);		cmd_free(h, c, 0);                return(0);	} 	default:		return -EBADRQC;	}	}/* Borrowed and adapted from sd.c */static int revalidate_logvol(kdev_t dev, int maxusage){        int ctlr, target;        struct gendisk *gdev;        unsigned long flags;        int max_p;        int start;        int i;        target = MINOR(dev) >> NWD_SHIFT;        ctlr = MAJOR(dev) - MAJOR_NR;        gdev = &(hba[ctlr]->gendisk);        spin_lock_irqsave(&io_request_lock, flags);        if (hba[ctlr]->drv[target].usage_count > maxusage) {                spin_unlock_irqrestore(&io_request_lock, flags);                printk(KERN_WARNING "cciss: Device busy for "                        "revalidation (usage=%d)\n",                        hba[ctlr]->drv[target].usage_count);                return -EBUSY;        }        hba[ctlr]->drv[target].usage_count++;        spin_unlock_irqrestore(&io_request_lock, flags);        max_p = gdev->max_p;        start = target << gdev->minor_shift;        for(i=max_p-1; i>=0; i--) {                int minor = start+i;                invalidate_device(MKDEV(MAJOR_NR + ctlr, minor), 1);                gdev->part[minor].start_sect = 0;                gdev->part[minor].nr_sects = 0;                /* reset the blocksize so we can read the partition table */                blksize_size[MAJOR_NR+ctlr][minor] = 1024;        }	/* setup partitions per disk */	grok_partitions(gdev, target, MAX_PART, 			hba[ctlr]->drv[target].nr_blocks);        hba[ctlr]->drv[target].usage_count--;        return 0;}static int frevalidate_logvol(kdev_t dev){#ifdef CCISS_DEBUG	printk(KERN_DEBUG "cciss: frevalidate has been called\n");#endif /* CCISS_DEBUG */ 	return revalidate_logvol(dev, 0);}/* * revalidate_allvol is for online array config utilities.  After a * utility reconfigures the drives in the array, it can use this function * (through an ioctl) to make the driver zap any previous disk structs for * that controller and get new ones. * * Right now I'm using the getgeometry() function to do this, but this * function should probably be finer grained and allow you to revalidate one * particualar logical volume (instead of all of them on a particular * controller). */static int revalidate_allvol(kdev_t dev){	int ctlr, i;	unsigned long flags;	ctlr = MAJOR(dev) - MAJOR_NR;        if (MINOR(dev) != 0)                return -ENXIO;        spin_lock_irqsave(&io_request_lock, flags);        if (hba[ctlr]->usage_count > 1) {                spin_unlock_irqrestore(&io_request_lock, flags);                printk(KERN_WARNING "cciss: Device busy for volume"                        " revalidation (usage=%d)\n", hba[ctlr]->usage_count);                return -EBUSY;        }        spin_unlock_irqrestore(&io_request_lock, flags);        hba[ctlr]->usage_count++;        /*         * Set the partition and block size structures for all volumes         * on this controller to zero.  We will reread all of this data         */	memset(hba[ctlr]->hd,         0, sizeof(struct hd_struct) * 256);        memset(hba[ctlr]->sizes,      0, sizeof(int) * 256);        memset(hba[ctlr]->blocksizes, 0, sizeof(int) * 256);        memset(hba[ctlr]->hardsizes,  0, sizeof(int) * 256);        memset(hba[ctlr]->drv,        0, sizeof(drive_info_struct)						* CISS_MAX_LUN);        hba[ctlr]->gendisk.nr_real = 0;        /*         * Tell the array controller not to give us any interrupts while         * we check the new geometry.  Then turn interrupts back on when         * we're done.         */        hba[ctlr]->access.set_intr_mask(hba[ctlr], CCISS_INTR_OFF);        cciss_getgeometry(ctlr);        hba[ctlr]->access.set_intr_mask(hba[ctlr], CCISS_INTR_ON);        cciss_geninit(ctlr);        for(i=0; i<NWD; i++)                if (hba[ctlr]->sizes[ i<<NWD_SHIFT ])                        revalidate_logvol(dev+(i<<NWD_SHIFT), 2);        hba[ctlr]->usage_count--;        return 0;}/* *   Wait polling for a command to complete. *   The memory mapped FIFO is polled for the completion. *   Used only at init time, interrupts disabled. */static unsigned long pollcomplete(int ctlr){        unsigned long done;

⌨️ 快捷键说明

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