linux_iface.c

来自「6440linuxDriver的源代码」· C语言 代码 · 共 641 行 · 第 1/2 页

C
641
字号
	if (inout == 1) {		/* User write is not supported. */		return (-ENOSYS);	}	len = sprintf(pBuffer,"Marvell %s Driver , Version %s\n",		      mv_product_name, mv_version_linux);	#ifdef RAID_DRIVER	if (mv_proc_ld_info(pSHost) == -1) {		len = sprintf(pBuffer,			      "Driver is busy, please try later.\n");		goto out;	} else {		for (i = 0; i < MAX_LD_SUPPORTED_PERFORMANCE; i++) {			if (ldinfo[i].Status != LD_STATUS_INVALID) {				if (ldinfo[i].Status == LD_STATUS_OFFLINE				        && ldinfo[i].BGAStatus == LD_BGA_STATE_RUNNING) {					ldinfo[i].BGAStatus = LD_BGA_STATE_AUTOPAUSED;				}				if (ldinfo[i].Status == LD_STATUS_MISSING) {					ldinfo[i].Status = LD_STATUS_OFFLINE;				}			} else {				break;			}		}	}		len += sprintf(pBuffer+len,"Index RAID\tStatus  \t\tBGA Status\n");	for (i = 0 ; i < LDINFO_NUM ; i++) {		if (ldinfo[i].Size.value == 0) {			if (i == 0) {				len += sprintf(pBuffer+len,"NO Logical Disk\n");			}			break;		}		len += sprintf(pBuffer+len,			"%-5d %s\t%s",			ldinfo[i].ID,			mv_ld_raid_mode(ldinfo[i].RaidMode),			mv_ld_status(ldinfo[i].Status)			);		tmplen = 24 -strlen(mv_ld_status(ldinfo[i].Status));		while (j < tmplen) {			len += sprintf(pBuffer+len, "%s", " ");			j++;		}		j = 0;		len += sprintf(pBuffer+len, "%s", mv_ld_bga_status(ldinfo[i].BGAStatus));		if (ldinfo[i].BGAStatus != LD_BGA_STATE_NONE) {			ret = mv_ld_get_status(pSHost,ldinfo[i].ID,&ld_status);			if (ret == 0) {				if (ld_status.Status != LD_STATUS_INVALID) {					if (ld_status.Status == LD_STATUS_MISSING)						ld_status.Status = LD_STATUS_OFFLINE;					ld_status.BgaState = ldinfo[i].BGAStatus;				}				len += mv_ld_show_status(pBuffer+len,&ld_status);				ret = -1;			}		}		tmp = NULL;		tmplen = 0;		len += sprintf(pBuffer+len,"\n");	}out:#endif			datalen = len - offset;	if (datalen < 0) {		datalen = 0;		*ppStart = pBuffer + len;	} else {		*ppStart = pBuffer + offset;	}	return datalen;} /* *Character Device Interface. */#ifdef RAID_DRIVERstatic int mv_open(struct inode *inode, struct file *file){	unsigned int minor_number;	int retval = -ENODEV;	unsigned long flags = 0;		spin_lock_irqsave(&inode->i_lock, flags);	minor_number = MINOR(inode->i_rdev);	if (minor_number >= __mv_get_adapter_count()) {		printk("MV : No such device.\n");		goto out;	}	retval = 0;out:	spin_unlock_irqrestore(&inode->i_lock, flags);	return retval;}static dev_t _mv_major;int mv_register_chdev(struct hba_extension *hba){	int ret = 0;	dev_t num;	/*	 * look for already-allocated major number first, if not found or	 * fail to register, try allocate one .	 *	 */	if (_mv_major)		ret = register_chrdev_region(MKDEV(_mv_major,						   hba->desc->hba_desc->id),					     1,					     MV_DEVFS_NAME);	if (ret || !_mv_major) {		ret = alloc_chrdev_region(&num,					  hba->desc->hba_desc->id,					  1,					  MV_DEVFS_NAME);		if (ret)			return ret;		else			_mv_major = MAJOR(num);	}	memset(&hba->cdev, 0, sizeof(struct cdev));	cdev_init(&hba->cdev, &mv_fops);	hba->cdev.owner = THIS_MODULE;	hba->desc->hba_desc->dev_no = num;	MV_DBG(DMSG_KERN, "registered chrdev (%d, %d).\n",	       MAJOR(num), MINOR(num));	ret = cdev_add(&hba->cdev, num, 1);	return ret;}void mv_unregister_chdev(struct hba_extension *hba){	cdev_del(&hba->cdev);	unregister_chrdev_region(hba->desc->hba_desc->dev_no, 1);}#ifdef HAVE_UNLOCKED_IOCTLstatic long mv_ioctl(struct file *file, unsigned int cmd, unsigned long arg)#elsestatic int mv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 		    unsigned long arg)#endif /* HAVE_UNLOCKED_IOCTL */ {	struct hba_extension	*hba;	PMV_Request    req = NULL;	int error = 0;	int ret   = 0;	int sptdwb_size = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);	int console_id  = VIRTUAL_DEVICE_ID;	unsigned long flags;	PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER psptdwb = NULL;	int mv_device_count;#ifdef HAVE_UNLOCKED_IOCTL	hba = container_of(file->f_dentry->d_inode->i_cdev,			   struct hba_extension, cdev);#else	hba = container_of(inode->i_cdev,			   struct hba_extension, cdev);#endif /* HAVE_UNLOCKED_IOCTL */ 	mv_device_count =  __mv_get_adapter_count();		if (cmd == 1) {		if (copy_to_user((void *)arg,				(void *)&console_id,				sizeof(int)) != 0 ) {			MV_DBG(DMSG_IOCTL, 				"Marvell : Get VIRTUAL_DEVICE_ID Error.\n");			return -EIO;		}		return 0;	}	if (cmd == 2) {		if (copy_to_user((void *)arg,				(void *)&mv_device_count,				sizeof(unsigned int)) != 0) {			MV_DBG(DMSG_IOCTL, 				"Marvell : Get Device Number Error.\n");			return -EIO;		}		return 0;	}	psptdwb = kmalloc(sptdwb_size, GFP_ATOMIC);		if ( NULL == psptdwb ) 		return -ENOMEM;	error = copy_from_user(psptdwb, (void *)arg, sptdwb_size);	if (error) {		ret = -EIO;		goto clean_psp;	}	if (psptdwb->sptd.DataTransferLength) {		if (psptdwb->sptd.DataTransferLength > IOCTL_BUF_LEN) {			MV_DBG(DMSG_IOCTL, "__MV__ not enough buf space.\n");			ret = -ENOMEM;			goto clean_psp;		}					psptdwb->sptd.DataBuffer = ioctl_buf;		memset(ioctl_buf, 0, psptdwb->sptd.DataTransferLength);				error = copy_from_user( psptdwb->sptd.DataBuffer,					((PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)arg)->sptd.DataBuffer,					psptdwb->sptd.DataTransferLength);		if (error) {			ret = -EIO;			goto clean_pspbuf;		}	} else {		psptdwb->sptd.DataBuffer = NULL;	}		/*Translate request to MV_REQUEST*/	req = res_get_req_from_pool(hba->req_pool);	if (NULL == req) {		ret = -ENOMEM;		goto clean_pspbuf;	}	req->Cmd_Initiator = hba;	req->Org_Req = req;	req->Scsi_Status = psptdwb->sptd.ScsiStatus;	req->Device_Id = psptdwb->sptd.TargetId;	req->Cmd_Flag = 0;	req->Req_Type = REQ_TYPE_INTERNAL;	if (psptdwb->sptd.DataTransferLength == 0) {		req->Cmd_Flag |= CMD_FLAG_NON_DATA;	} else {		if (SCSI_IS_READ(psptdwb->sptd.Cdb[0]))			req->Cmd_Flag |= CMD_FLAG_DATA_IN;		if (SCSI_IS_READ(psptdwb->sptd.Cdb[0]) || SCSI_IS_WRITE(psptdwb->sptd.Cdb[0]))			req->Cmd_Flag |= CMD_FLAG_DMA;	}	req->Data_Transfer_Length = psptdwb->sptd.DataTransferLength;	req->Data_Buffer = psptdwb->sptd.DataBuffer;	req->Sense_Info_Buffer = psptdwb->Sense_Buffer;	SGTable_Init(&req->SG_Table, 0);		memcpy(req->Cdb, psptdwb->sptd.Cdb, MAX_CDB_SIZE);	memset(req->Context, 0, sizeof(MV_PVOID)*MAX_POSSIBLE_MODULE_NUMBER);	req->LBA.value = 0;    	req->Sector_Count = 0; 	req->Completion = ioctlcallback;	spin_lock_irqsave(&hba->irq_lock, flags);    	hba->Io_Count++;#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)	atomic_set(&hba->hba_sync, 1);#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */	hba->desc->ops->module_sendrequest(hba->desc->extension, req);	spin_unlock_irqrestore(&hba->irq_lock, flags);#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11)	if (!__hba_wait_for_atomic_timeout(&hba->hba_sync, 					    HBA_REQ_TIMER_IOCTL*HZ)) {#else	if (!wait_for_completion_timeout(&hba->cmpl, 					  HBA_REQ_TIMER_IOCTL*HZ)) {#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 11) */		MV_DBG(DMSG_HBA, "__MV__ ioctl req timed out.\n");	        ret = -EIO;	        goto clean_pspbuf;	}	if (psptdwb->sptd.DataTransferLength) {		error = copy_to_user(((PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER)arg)->sptd.DataBuffer,				     psptdwb->sptd.DataBuffer,				     psptdwb->sptd.DataTransferLength);		if (error) {			ret = -EIO;			goto clean_pspbuf;		}	}	error = copy_to_user((void*)arg, psptdwb, sptdwb_size);		if (error) {		ret = -EIO;		goto clean_pspbuf;	}	if (req->Scsi_Status)		ret = req->Scsi_Status;clean_pspbuf:/* use static buf instead.*/clean_psp:	kfree(psptdwb);	return ret;}#else  /* RAID_DRIVER */inline int mv_register_chdev(struct hba_extension *hba) {return 0;}inline void mv_unregister_chdev(struct hba_extension *hba) {}#endif /* RAID_DRIVER */

⌨️ 快捷键说明

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