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

📄 cciss.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 4 页
字号:
			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))				return -EFAULT;		}		if ((c = cmd_alloc(NULL)) == NULL)		{			if(buff!=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 = (__u64) virt_to_bus(buff);			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);		/* Copy the error information out */ 		iocommand.error_info = *(c->err_info);		if ( copy_to_user((void *) arg, &iocommand, sizeof( IOCTL_Command_struct) ) )		{			cmd_free(NULL, c);			if (buff != NULL) 				kfree(buff);			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))			{			             cmd_free(NULL, c);			             kfree(buff);			}                }		cmd_free(NULL, c);                if (buff != NULL)                	kfree(buff);                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 "cpqarray: 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; i>=0; i--) {                int minor = start+i;                kdev_t devi = MKDEV(MAJOR_NR + ctlr, minor);                struct super_block *sb = get_super(devi);                sync_dev(devi);                if (sb) invalidate_inodes(sb);                invalidate_buffers(devi);                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 interupts 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;        int i;        /* Wait (up to 2 seconds) for a command to complete */        for (i = 200000; i > 0; i--) {                done = hba[ctlr]->access.command_completed(hba[ctlr]);                if (done == FIFO_EMPTY) {                        udelay(10);     /* a short fixed delay */                } 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,	unsigned int log_unit,	__u8	page_code ){	CommandList_struct *c;	int i;	unsigned long complete;	ctlr_info_t *info_p= hba[ctlr];	u64bit temp64;	c = cmd_alloc(info_p);	if (c == NULL)	{		printk(KERN_WARNING "cciss: unable to get memory");		return(IO_ERROR);	}	// Fill in Command Header 	c->Header.ReplyQueue = 0;  // unused in simple mode	if( buff != NULL) 	// 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.Tag.lower = c->busaddr;  // use the kernel address the cmd block for tag	// Fill in Request block 		switch(cmd)	{		case  CISS_INQUIRY:			/* If the logical unit number is 0 then, this is going				to controller so It's a physical command				mode = 0 target = 0.				So we have nothing to write. 				Otherwise 				mode = 1  target = LUNID			*/			if(use_unit_num != 0)			{				c->Header.LUN.LogDev.VolId=                                	hba[ctlr]->drv[log_unit].LunID;                        	c->Header.LUN.LogDev.Mode = 1;			}			/* are we trying to read a vital product page */			if(page_code != 0)			{				c->Request.CDB[1] = 0x01;				c->Request.CDB[2] = page_code;			}			c->Request.CDBLen = 6;			c->Request.Type.Type =  TYPE_CMD; // It is a command. 			c->Request.Type.Attribute = ATTR_SIMPLE;  			c->Request.Type.Direction = XFER_READ; // Read 			c->Request.Timeout = 0; // Don't time out 			c->Request.CDB[0] =  CISS_INQUIRY;			c->Request.CDB[4] = size  & 0xFF;  		break;		case CISS_REPORT_LOG:                        /* Talking to controller so It's a physical command                                mode = 00 target = 0.                                So we have nothing to write.                        */                        c->Request.CDBLen = 12;                        c->Request.Type.Type =  TYPE_CMD; // It is a command.                        c->Request.Type.Attribute = ATTR_SIMPLE;                         c->Request.Type.Direction = XFER_READ; // Read                        c->Request.Timeout = 0; // Don't time out                        c->Request.CDB[0] = CISS_REPORT_LOG;                        c->Request.CDB[6] = (size >> 24) & 0xFF;  //MSB                        c->Request.CDB[7] = (size >> 16) & 0xFF;                        c->Request.CDB[8] = (size >> 8) & 0xFF;                        c->Request.CDB[9] = size & 0xFF;                break;		case CCISS_READ_CAPACITY:			c->Header.LUN.LogDev.VolId= 				hba[ctlr]->drv[log_unit].LunID;			c->Header.LUN.LogDev.Mode = 1;			c->Request.CDBLen = 10;                        c->Request.Type.Type =  TYPE_CMD; // It is a command.                        c->Request.Type.Attribute = ATTR_SIMPLE;                         c->Request.Type.Direction = XFER_READ; // Read                        c->Request.Timeout = 0; // Don't time out                        c->Request.CDB[0] = CCISS_READ_CAPACITY;		break;		default:			printk(KERN_WARNING				"cciss:  Unknown Command 0x%c sent attempted\n",				  cmd);			cmd_free(info_p, c);			return(IO_ERROR);	};	// Fill in the scatter gather information	if (size > 0 ) 	{		temp64.val = (__u64) virt_to_bus(buff);		c->SG[0].Addr.lower = temp64.val32.lower;		c->SG[0].Addr.upper = temp64.val32.upper;		c->SG[0].Len = size;		c->SG[0].Ext = 0;  // we are not chaining	}	/*         * 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");

⌨️ 快捷键说明

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