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

📄 mf.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* The HV appears to return no more than 256 bytes of command line */	if (off >= 256)		return 0;	if ((off + count) > 256)		count = 256 - off;	dma_addr = dma_map_single(iSeries_vio_dev, page, off + count,			DMA_FROM_DEVICE);	if (dma_mapping_error(dma_addr))		return -ENOMEM;	memset(page, 0, off + count);	memset(&vsp_cmd, 0, sizeof(vsp_cmd));	vsp_cmd.cmd = 33;	vsp_cmd.sub_data.kern.token = dma_addr;	vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;	vsp_cmd.sub_data.kern.side = (u64)data;	vsp_cmd.sub_data.kern.length = off + count;	mb();	rc = signal_vsp_instruction(&vsp_cmd);	dma_unmap_single(iSeries_vio_dev, dma_addr, off + count,			DMA_FROM_DEVICE);	if (rc)		return rc;	if (vsp_cmd.result_code != 0)		return -ENOMEM;	p = page;	len = 0;	while (len < (off + count)) {		if ((*p == '\0') || (*p == '\n')) {			if (*p == '\0')				*p = '\n';			p++;			len++;			*eof = 1;			break;		}		p++;		len++;	}	if (len < off) {		*eof = 1;		len = 0;	}	return len;}#if 0static int mf_getVmlinuxChunk(char *buffer, int *size, int offset, u64 side){	struct vsp_cmd_data vsp_cmd;	int rc;	int len = *size;	dma_addr_t dma_addr;	dma_addr = dma_map_single(iSeries_vio_dev, buffer, len,			DMA_FROM_DEVICE);	memset(buffer, 0, len);	memset(&vsp_cmd, 0, sizeof(vsp_cmd));	vsp_cmd.cmd = 32;	vsp_cmd.sub_data.kern.token = dma_addr;	vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;	vsp_cmd.sub_data.kern.side = side;	vsp_cmd.sub_data.kern.offset = offset;	vsp_cmd.sub_data.kern.length = len;	mb();	rc = signal_vsp_instruction(&vsp_cmd);	if (rc == 0) {		if (vsp_cmd.result_code == 0)			*size = vsp_cmd.sub_data.length_out;		else			rc = -ENOMEM;	}	dma_unmap_single(iSeries_vio_dev, dma_addr, len, DMA_FROM_DEVICE);	return rc;}static int proc_mf_dump_vmlinux(char *page, char **start, off_t off,		int count, int *eof, void *data){	int sizeToGet = count;	if (!capable(CAP_SYS_ADMIN))		return -EACCES;	if (mf_getVmlinuxChunk(page, &sizeToGet, off, (u64)data) == 0) {		if (sizeToGet != 0) {			*start = page + off;			return sizeToGet;		}		*eof = 1;		return 0;	}	*eof = 1;	return 0;}#endifstatic int proc_mf_dump_side(char *page, char **start, off_t off,		int count, int *eof, void *data){	int len;	char mf_current_side = ' ';	struct vsp_cmd_data vsp_cmd;	memset(&vsp_cmd, 0, sizeof(vsp_cmd));	vsp_cmd.cmd = 2;	vsp_cmd.sub_data.ipl_type = 0;	mb();	if (signal_vsp_instruction(&vsp_cmd) == 0) {		if (vsp_cmd.result_code == 0) {			switch (vsp_cmd.sub_data.ipl_type) {			case 0:	mf_current_side = 'A';				break;			case 1:	mf_current_side = 'B';				break;			case 2:	mf_current_side = 'C';				break;			default:	mf_current_side = 'D';				break;			}		}	}	len = sprintf(page, "%c\n", mf_current_side);	if (len <= (off + count))		*eof = 1;	*start = page + off;	len -= off;	if (len > count)		len = count;	if (len < 0)		len = 0;	return len;}static int proc_mf_change_side(struct file *file, const char __user *buffer,		unsigned long count, void *data){	char side;	u64 newSide;	struct vsp_cmd_data vsp_cmd;	if (!capable(CAP_SYS_ADMIN))		return -EACCES;	if (count == 0)		return 0;	if (get_user(side, buffer))		return -EFAULT;	switch (side) {	case 'A':	newSide = 0;			break;	case 'B':	newSide = 1;			break;	case 'C':	newSide = 2;			break;	case 'D':	newSide = 3;			break;	default:		printk(KERN_ERR "mf_proc.c: proc_mf_change_side: invalid side\n");		return -EINVAL;	}	memset(&vsp_cmd, 0, sizeof(vsp_cmd));	vsp_cmd.sub_data.ipl_type = newSide;	vsp_cmd.cmd = 10;	(void)signal_vsp_instruction(&vsp_cmd);	return count;}#if 0static void mf_getSrcHistory(char *buffer, int size){	struct IplTypeReturnStuff return_stuff;	struct pending_event *ev = new_pending_event();	int rc = 0;	char *pages[4];	pages[0] = kmalloc(4096, GFP_ATOMIC);	pages[1] = kmalloc(4096, GFP_ATOMIC);	pages[2] = kmalloc(4096, GFP_ATOMIC);	pages[3] = kmalloc(4096, GFP_ATOMIC);	if ((ev == NULL) || (pages[0] == NULL) || (pages[1] == NULL)			 || (pages[2] == NULL) || (pages[3] == NULL))		return -ENOMEM;	return_stuff.xType = 0;	return_stuff.xRc = 0;	return_stuff.xDone = 0;	ev->event.hp_lp_event.xSubtype = 6;	ev->event.hp_lp_event.x.xSubtypeData =		subtype_data('M', 'F', 'V', 'I');	ev->event.data.vsp_cmd.xEvent = &return_stuff;	ev->event.data.vsp_cmd.cmd = 4;	ev->event.data.vsp_cmd.lp_index = HvLpConfig_getLpIndex();	ev->event.data.vsp_cmd.result_code = 0xFF;	ev->event.data.vsp_cmd.reserved = 0;	ev->event.data.vsp_cmd.sub_data.page[0] = ISERIES_HV_ADDR(pages[0]);	ev->event.data.vsp_cmd.sub_data.page[1] = ISERIES_HV_ADDR(pages[1]);	ev->event.data.vsp_cmd.sub_data.page[2] = ISERIES_HV_ADDR(pages[2]);	ev->event.data.vsp_cmd.sub_data.page[3] = ISERIES_HV_ADDR(pages[3]);	mb();	if (signal_event(ev) != 0)		return; 	while (return_stuff.xDone != 1) 		udelay(10); 	if (return_stuff.xRc == 0) 		memcpy(buffer, pages[0], size);	kfree(pages[0]);	kfree(pages[1]);	kfree(pages[2]);	kfree(pages[3]);}#endifstatic int proc_mf_dump_src(char *page, char **start, off_t off,		int count, int *eof, void *data){#if 0	int len;	mf_getSrcHistory(page, count);	len = count;	len -= off;	if (len < count) {		*eof = 1;		if (len <= 0)			return 0;	} else		len = count;	*start = page + off;	return len;#else	return 0;#endif}static int proc_mf_change_src(struct file *file, const char __user *buffer,		unsigned long count, void *data){	char stkbuf[10];	if (!capable(CAP_SYS_ADMIN))		return -EACCES;	if ((count < 4) && (count != 1)) {		printk(KERN_ERR "mf_proc: invalid src\n");		return -EINVAL;	}	if (count > (sizeof(stkbuf) - 1))		count = sizeof(stkbuf) - 1;	if (copy_from_user(stkbuf, buffer, count))		return -EFAULT;	if ((count == 1) && (*stkbuf == '\0'))		mf_clear_src();	else		mf_display_src(*(u32 *)stkbuf);	return count;}static int proc_mf_change_cmdline(struct file *file, const char __user *buffer,		unsigned long count, void *data){	struct vsp_cmd_data vsp_cmd;	dma_addr_t dma_addr;	char *page;	int ret = -EACCES;	if (!capable(CAP_SYS_ADMIN))		goto out;	dma_addr = 0;	page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,			GFP_ATOMIC);	ret = -ENOMEM;	if (page == NULL)		goto out;	ret = -EFAULT;	if (copy_from_user(page, buffer, count))		goto out_free;	memset(&vsp_cmd, 0, sizeof(vsp_cmd));	vsp_cmd.cmd = 31;	vsp_cmd.sub_data.kern.token = dma_addr;	vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;	vsp_cmd.sub_data.kern.side = (u64)data;	vsp_cmd.sub_data.kern.length = count;	mb();	(void)signal_vsp_instruction(&vsp_cmd);	ret = count;out_free:	dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);out:	return ret;}static ssize_t proc_mf_change_vmlinux(struct file *file,				      const char __user *buf,				      size_t count, loff_t *ppos){	struct proc_dir_entry *dp = PDE(file->f_dentry->d_inode);	ssize_t rc;	dma_addr_t dma_addr;	char *page;	struct vsp_cmd_data vsp_cmd;	rc = -EACCES;	if (!capable(CAP_SYS_ADMIN))		goto out;	dma_addr = 0;	page = dma_alloc_coherent(iSeries_vio_dev, count, &dma_addr,			GFP_ATOMIC);	rc = -ENOMEM;	if (page == NULL) {		printk(KERN_ERR "mf.c: couldn't allocate memory to set vmlinux chunk\n");		goto out;	}	rc = -EFAULT;	if (copy_from_user(page, buf, count))		goto out_free;	memset(&vsp_cmd, 0, sizeof(vsp_cmd));	vsp_cmd.cmd = 30;	vsp_cmd.sub_data.kern.token = dma_addr;	vsp_cmd.sub_data.kern.address_type = HvLpDma_AddressType_TceIndex;	vsp_cmd.sub_data.kern.side = (u64)dp->data;	vsp_cmd.sub_data.kern.offset = *ppos;	vsp_cmd.sub_data.kern.length = count;	mb();	rc = signal_vsp_instruction(&vsp_cmd);	if (rc)		goto out_free;	rc = -ENOMEM;	if (vsp_cmd.result_code != 0)		goto out_free;	*ppos += count;	rc = count;out_free:	dma_free_coherent(iSeries_vio_dev, count, page, dma_addr);out:	return rc;}static struct file_operations proc_vmlinux_operations = {	.write		= proc_mf_change_vmlinux,};static int __init mf_proc_init(void){	struct proc_dir_entry *mf_proc_root;	struct proc_dir_entry *ent;	struct proc_dir_entry *mf;	char name[2];	int i;	mf_proc_root = proc_mkdir("iSeries/mf", NULL);	if (!mf_proc_root)		return 1;	name[1] = '\0';	for (i = 0; i < 4; i++) {		name[0] = 'A' + i;		mf = proc_mkdir(name, mf_proc_root);		if (!mf)			return 1;		ent = create_proc_entry("cmdline", S_IFREG|S_IRUSR|S_IWUSR, mf);		if (!ent)			return 1;		ent->nlink = 1;		ent->data = (void *)(long)i;		ent->read_proc = proc_mf_dump_cmdline;		ent->write_proc = proc_mf_change_cmdline;		if (i == 3)	/* no vmlinux entry for 'D' */			continue;		ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf);		if (!ent)			return 1;		ent->nlink = 1;		ent->data = (void *)(long)i;		ent->proc_fops = &proc_vmlinux_operations;	}	ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);	if (!ent)		return 1;	ent->nlink = 1;	ent->data = (void *)0;	ent->read_proc = proc_mf_dump_side;	ent->write_proc = proc_mf_change_side;	ent = create_proc_entry("src", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root);	if (!ent)		return 1;	ent->nlink = 1;	ent->data = (void *)0;	ent->read_proc = proc_mf_dump_src;	ent->write_proc = proc_mf_change_src;	return 0;}__initcall(mf_proc_init);#endif /* CONFIG_PROC_FS */

⌨️ 快捷键说明

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