Exemple #1
0
static int pn544_probe(struct i2c_client *client,
		const struct i2c_device_id *id)
{
    int ret;
    struct pn544_dev *pn544_dev = NULL;
    pn544_client = client;

    dprintk(PN544_DRV_NAME ": pn544_probe() start\n");

    pn544_dev = kzalloc(sizeof(*pn544_dev), GFP_KERNEL);
    if (pn544_dev == NULL) {
        dev_err(&client->dev,
                "failed to allocate memory for module data\n");
        ret = -ENOMEM;
        goto err_exit;
    }

    pn544_parse_dt(&client->dev, pn544_dev);

    pn544_dev->client   = client;
    dprintk(PN544_DRV_NAME ":IRQ : %d\nVEN : %d\nFIRM : %d\n",
            pn544_dev->irq_gpio, pn544_dev->ven_gpio, pn544_dev->firm_gpio);

    ret = gpio_request(pn544_dev->irq_gpio, "nfc_int");
    if (ret) {
        dprintk(PN544_DRV_NAME ":pn544_probe() : nfc_int request failed!\n");
        goto err_int;
    }
    ret = gpio_request(pn544_dev->ven_gpio, "nfc_ven");
    if (ret) {
        dprintk(PN544_DRV_NAME ":pn544_probe() : nfc_ven request failed!\n");
        goto err_ven;
    }
    ret = gpio_request(pn544_dev->firm_gpio, "nfc_firm");
    if (ret) {
        dprintk(PN544_DRV_NAME ":pn544_probe() : nfc_firm request failed!\n");
        goto err_firm;
    }

    pn544_gpio_enable(pn544_dev);

    ret = gpio_direction_output(pn544_dev->ven_gpio,1);
    ret = gpio_direction_output(pn544_dev->firm_gpio,0);
    ret = gpio_direction_input(pn544_dev->irq_gpio);

	/* init mutex and queues */
    init_waitqueue_head(&pn544_dev->read_wq);
    mutex_init(&pn544_dev->read_mutex);
#ifdef CONFIG_LGE_NFC_PRESTANDBY
    mutex_init(&mode_mutex);
#endif
    spin_lock_init(&pn544_dev->irq_enabled_lock);

    pn544_dev->pn544_device.minor = MISC_DYNAMIC_MINOR;
    pn544_dev->pn544_device.name = PN544_DRV_NAME;
    pn544_dev->pn544_device.fops = &pn544_dev_fops;

    ret = misc_register(&pn544_dev->pn544_device);
    if (ret) {
        pr_err("%s : misc_register failed\n", __FILE__);
        goto err_misc_register;
    }

	/* request irq.  the irq is set whenever the chip has data available
	 * for reading.  it is cleared when all data has been read.
	 */
    pr_info("%s : requesting IRQ %d\n", __func__, client->irq);
    pn544_dev->irq_enabled = true;
    ret = request_irq(pn544_gpio_to_irq(pn544_dev), pn544_dev_irq_handler,
              IRQF_TRIGGER_HIGH, client->name, pn544_dev);
    if (ret) {
        dev_err(&client->dev, "request_irq failed\n");
        goto err_request_irq_failed;
    }
#if !defined(LGE_NFC_HW_QCT_MSM8660)&&!defined(CONFIG_LGE_NFC_HW_QCT_MSM8255)
    enable_irq_wake(pn544_get_irq_pin(pn544_dev));
#endif
    pn544_disable_irq(pn544_dev);
    i2c_set_clientdata(client, pn544_dev);
    dprintk(PN544_DRV_NAME ": pn544_probe() end\n");
/*             
  
                                  
                                    
                                   
  
                                  
 */
#ifdef CONFIG_LGE_NFC_PRESTANDBY
    if (pn544_validate_boot_mode()) {
        dprintk("%s : get in the standbyset\n", __func__);
#ifdef CONFIG_LGE_NFC_MULTICORE_FASTBOOT
        {
            struct task_struct *th;
            th = kthread_create(pn544_factory_standby_set_thread, NULL, "pn544_factory_standby");
            if (IS_ERR(th)) {
                ret = PTR_ERR(th);
                goto err_request_irq_failed;
            }
            wake_up_process(th);
        }
#else
        pn544_factory_standby_set();
#endif
/*              */
    }
#endif
    return 0;

err_request_irq_failed:
    misc_deregister(&pn544_dev->pn544_device);

err_misc_register:
    mutex_destroy(&pn544_dev->read_mutex);
#ifdef CONFIG_LGE_NFC_PRESTANDBY
    mutex_destroy(&mode_mutex);
#endif
    gpio_free(pn544_dev->firm_gpio);

err_firm:
    gpio_free(pn544_dev->ven_gpio);

err_ven:
    gpio_free(pn544_dev->irq_gpio);

err_int:
    kfree(pn544_dev);

err_exit:
    pr_err(PN544_DRV_NAME ": pn544_dev is null\n");
    pr_err(PN544_DRV_NAME ": pn544_probe() end with error!\n");

	return ret;
}
Exemple #2
0
static int __init init_ugidctl(void)
{
	dev_t dev;
	int rc;

	rc = find_syscalls();
	if (rc)
		return rc;

	dprintk("found sys_setuid() 0x%p", ugidctl_sys_setuid);
	dprintk("found sys_setgid() 0x%p", ugidctl_sys_setgid);
	dprintk("found sys_setgroups() 0x%p\n", ugidctl_sys_setgroups);

	rc = -ENOMEM;

	uid_cache = KMEM_CACHE(ugidctl_uid_node, 0);
	if (!uid_cache) {
		printk(KERN_ERR "%s: cannot allocate uid cache\n", MOD_NAME);
		goto out;
	}

	gid_cache = KMEM_CACHE(ugidctl_gid_node, 0);
	if (!gid_cache) {
		printk(KERN_ERR "%s: cannot allocate gid cache\n", MOD_NAME);
		goto out_uid_cache;
	}

	rc = alloc_chrdev_region(&dev, 0, 1, DEV_NAME);
	if (rc) {
		printk(KERN_ERR "%s: failed to register chrdev region\n", MOD_NAME);
		goto out_gid_cache;
	}

	ugidctl_major = MAJOR(dev);
	ugidctl_class = class_create(THIS_MODULE, DEV_NAME);

	if (IS_ERR(ugidctl_class)) {
		printk(KERN_ERR "%s: failed to register with sysfs\n", MOD_NAME);
		rc = PTR_ERR(ugidctl_class);
		goto out_region;
	}

	cdev_init(&ugidctl_cdev, &ugidctl_fops);

	rc = cdev_add(&ugidctl_cdev, dev, 1);
	if (rc) {
		printk(KERN_ERR "%s: failed to add char device\n", MOD_NAME);
		goto out_class;
	}

	device_create(ugidctl_class, NULL, dev, NULL, DEV_NAME);

	// printk(KERN_INFO "%s: v" MOD_VERSION " loaded\n", MOD_NAME);

	return 0;

out_class:
	class_destroy(ugidctl_class);
out_region:
	unregister_chrdev_region(dev, 1);
out_gid_cache:
	kmem_cache_destroy(gid_cache);
out_uid_cache:
	kmem_cache_destroy(uid_cache);
out:
	return rc;
}
static int sep0611_overlay_resume(struct platform_device *pdev)
{
	dprintk("go to %s\n", __func__);
	return 0;
}
/*
 * if you use these, you must assure that the frequency table is valid
 * all the time between get_attr and put_attr!
 */
void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
				      unsigned int cpu)
{
	dprintk("setting show_table for cpu %u to %p\n", cpu, table);
	show_table[cpu] = table;
}
/**ltl
 * 功能: 获取目标频点在频点列表中对应数组下标
 * 参数: policy	-> 调频率策略对象
 *		table	-> 频率列表
 *		target_freq-> 目标频点
 *		relation	-> 关系,值可以是:CPUFREQ_RELATION_H、CPUFREQ_RELATION_L
 *		index	-> [out] 目标频点在频点列表的下标
 * 返回值: 
 * 说明: 这个函数会根据target_freq和relation的值返回不同值:
 *		1. 当target_freq值为0,relation=CPUFREQ_RELATION_H,则index=0
 *						   relation=CPUFREQ_RELATION_L,则index=table最后一个元素的下标。
 *		2. 当target_freq值属性频点列表,返回此频点的下标
 */
int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
				   struct cpufreq_frequency_table *table,
				   unsigned int target_freq,
				   unsigned int relation,
				   unsigned int *index)
{
	struct cpufreq_frequency_table optimal = {
		.index = ~0,
		.frequency = 0,
	};
	struct cpufreq_frequency_table suboptimal = {
		.index = ~0,
		.frequency = 0,
	};
	unsigned int i;

	dprintk("request for target %u kHz (relation: %u) for cpu %u\n", target_freq, relation, policy->cpu);

	switch (relation) {
	case CPUFREQ_RELATION_H:
		suboptimal.frequency = ~0;
		break;
	case CPUFREQ_RELATION_L:
		optimal.frequency = ~0;
		break;
	}

	if (!cpu_online(policy->cpu))
		return -EINVAL;

	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
		unsigned int freq = table[i].frequency;
		if (freq == CPUFREQ_ENTRY_INVALID)
			continue;
		if ((freq < policy->min) || (freq > policy->max))
			continue;
		switch(relation) {
		case CPUFREQ_RELATION_H:
			if (freq <= target_freq) {
				if (freq >= optimal.frequency) {
					optimal.frequency = freq;
					optimal.index = i;
				}
			} else {
				if (freq <= suboptimal.frequency) {
					suboptimal.frequency = freq;
					suboptimal.index = i;
				}
			}
			break;
		case CPUFREQ_RELATION_L:
			if (freq >= target_freq) {
				if (freq <= optimal.frequency) {
					optimal.frequency = freq;
					optimal.index = i;
				}
			} else {
				if (freq >= suboptimal.frequency) {
					suboptimal.frequency = freq;
					suboptimal.index = i;
				}
			}
			break;
		}
	}
	if (optimal.index > i) {
		if (suboptimal.index > i)
			return -EINVAL;
		*index = suboptimal.index;
	} else
		*index = optimal.index;

	dprintk("target is %u (%u kHz, %u)\n", *index, table[*index].frequency,
		table[*index].index);

	return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);

static struct cpufreq_frequency_table *show_table[NR_CPUS];
/**
 * show_scaling_governor - show the current policy for the specified CPU
 */
static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf)
{
	unsigned int i = 0;
	unsigned int cpu = policy->cpu;
	ssize_t count = 0;
	struct cpufreq_frequency_table *table;

	if (!show_table[cpu])
		return -ENODEV;

	table = show_table[cpu];

	for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
		if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
			continue;
		count += sprintf(&buf[count], "%d ", table[i].frequency);
	}
	count += sprintf(&buf[count], "\n");

	return count;

}

struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
	.attr = { .name = "scaling_available_frequencies", .mode = 0444, .owner=THIS_MODULE },
	.show = show_available_freqs,
};
Exemple #6
0
int pohmelfs_data_lock(struct pohmelfs_inode *pi, u64 start, u32 size, int type)
{
	struct pohmelfs_sb *psb = POHMELFS_SB(pi->vfs_inode.i_sb);
	struct pohmelfs_mcache *m;
	int err = -ENOMEM;
	struct iattr iattr;
	struct inode *inode = &pi->vfs_inode;

	dprintk("%s: %p: ino: %llu, start: %llu, size: %u, "
			"type: %d, locked as: %d, owned: %d.\n",
			__func__, &pi->vfs_inode, pi->ino,
			start, size, type, pi->lock_type,
			!!test_bit(NETFS_INODE_OWNED, &pi->state));

	if (!pohmelfs_need_lock(pi, type))
		return 0;

	m = pohmelfs_mcache_alloc(psb, start, size, NULL);
	if (IS_ERR(m))
		return PTR_ERR(m);

	err = pohmelfs_send_lock_trans(pi, m->gen, start, size,
			type | POHMELFS_LOCK_GRAB);
	if (err)
		goto err_out_put;

	err = wait_for_completion_timeout(&m->complete, psb->mcache_timeout);
	if (err)
		err = m->err;
	else
		err = -ETIMEDOUT;

	if (err) {
		printk("%s: %p: ino: %llu, mgen: %llu, start: %llu, size: %u, err: %d.\n",
			__func__, &pi->vfs_inode, pi->ino, m->gen, start, size, err);
	}

	if (err && (err != -ENOENT))
		goto err_out_put;

	if (!err) {
		netfs_convert_inode_info(&m->info);

		iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_SIZE | ATTR_ATIME;
		iattr.ia_mode = m->info.mode;
		iattr.ia_uid = m->info.uid;
		iattr.ia_gid = m->info.gid;
		iattr.ia_size = m->info.size;
		iattr.ia_atime = CURRENT_TIME;

		dprintk("%s: %p: ino: %llu, mgen: %llu, start: %llu, isize: %llu -> %llu.\n",
			__func__, &pi->vfs_inode, pi->ino, m->gen, start, inode->i_size, m->info.size);

		err = pohmelfs_setattr_raw(inode, &iattr);
		if (!err) {
			struct dentry *dentry = d_find_alias(inode);
			if (dentry) {
				fsnotify_change(dentry, iattr.ia_valid);
				dput(dentry);
			}
		}
	}

	pi->lock_type = type;
	set_bit(NETFS_INODE_OWNED, &pi->state);

	pohmelfs_mcache_put(psb, m);

	return 0;

err_out_put:
	pohmelfs_mcache_put(psb, m);
	return err;
}
Exemple #7
0
/*
 *	This function is exported.
 */
int
v4l_compat_translate_ioctl(struct inode         *inode,
			   struct file		*file,
			   int			cmd,
			   void			*arg,
			   v4l2_kioctl          drv)
{
	struct v4l2_capability  *cap2 = NULL;
	struct v4l2_format	*fmt2 = NULL;
	enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;

	struct v4l2_framebuffer fbuf2;
	struct v4l2_input	input2;
	struct v4l2_tuner	tun2;
	struct v4l2_standard	std2;
	struct v4l2_frequency   freq2;
	struct v4l2_audio	aud2;
	struct v4l2_queryctrl	qctrl2;
	struct v4l2_buffer	buf2;
	v4l2_std_id    		sid;
	int i, err = 0;

	switch (cmd) {
	case VIDIOCGCAP:	/* capability */
	{
		struct video_capability *cap = arg;

		cap2 = kmalloc(sizeof(*cap2),GFP_KERNEL);
		memset(cap, 0, sizeof(*cap));
		memset(cap2, 0, sizeof(*cap2));
		memset(&fbuf2, 0, sizeof(fbuf2));

		err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
		if (err < 0) {
			dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);
			break;
		}
		if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
			err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
			if (err < 0) {
				dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);
				memset(&fbuf2, 0, sizeof(fbuf2));
			}
			err = 0;
		}

		memcpy(cap->name, cap2->card, 
		       min(sizeof(cap->name), sizeof(cap2->card)));
		cap->name[sizeof(cap->name) - 1] = 0;
		if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
			cap->type |= VID_TYPE_CAPTURE;
		if (cap2->capabilities & V4L2_CAP_TUNER)
			cap->type |= VID_TYPE_TUNER;
		if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
			cap->type |= VID_TYPE_TELETEXT;
		if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
			cap->type |= VID_TYPE_OVERLAY;
		if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
			cap->type |= VID_TYPE_CLIPPING;

		cap->channels  = count_inputs(inode,file,drv);
		check_size(inode,file,drv,
			   &cap->maxwidth,&cap->maxheight);
		cap->audios    =  0; /* FIXME */
		cap->minwidth  = 48; /* FIXME */
		cap->minheight = 32; /* FIXME */
		break;
	}
	case VIDIOCGFBUF: /*  get frame buffer  */
	{
		struct video_buffer	*buffer = arg;

		err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
		if (err < 0) {
			dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
			break;
		}
		buffer->base   = fbuf2.base;
		buffer->height = fbuf2.fmt.height;
		buffer->width  = fbuf2.fmt.width;

		switch (fbuf2.fmt.pixelformat) {
		case V4L2_PIX_FMT_RGB332:
			buffer->depth = 8;
				break;
		case V4L2_PIX_FMT_RGB555:
			buffer->depth = 15;
			break;
		case V4L2_PIX_FMT_RGB565:
			buffer->depth = 16;
			break;
		case V4L2_PIX_FMT_BGR24:
			buffer->depth = 24;
			break;
		case V4L2_PIX_FMT_BGR32:
			buffer->depth = 32;
			break;
		default:
			buffer->depth = 0;
		}
		if (0 != fbuf2.fmt.bytesperline)
			buffer->bytesperline = fbuf2.fmt.bytesperline;
		else {
			buffer->bytesperline = 
				(buffer->width * buffer->depth + 7) & 7;
			buffer->bytesperline >>= 3;
		}
		break;
	}
	case VIDIOCSFBUF: /*  set frame buffer  */
	{
		struct video_buffer	*buffer = arg;

		memset(&fbuf2, 0, sizeof(fbuf2));
		fbuf2.base       = buffer->base;
		fbuf2.fmt.height = buffer->height;
		fbuf2.fmt.width  = buffer->width;
		switch (buffer->depth) {
		case 8:
			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
			break;
		case 15:
			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
			break;
		case 16:
			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
			break;
		case 24:
			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
			break;
		case 32:
			fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
			break;
		}
		fbuf2.fmt.bytesperline = buffer->bytesperline;
		err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
		if (err < 0)
			dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err);
		break;
	}
	case VIDIOCGWIN: /*  get window or capture dimensions  */
	{
		struct video_window	*win = arg;

		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
		memset(win,0,sizeof(*win));
		memset(fmt2,0,sizeof(*fmt2));

		fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
		if (err < 0)
			dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);
		if (err == 0) {
			win->x         = fmt2->fmt.win.w.left;
			win->y         = fmt2->fmt.win.w.top;
			win->width     = fmt2->fmt.win.w.width;
			win->height    = fmt2->fmt.win.w.height;
			win->chromakey = fmt2->fmt.win.chromakey;
			win->clips     = NULL;
			win->clipcount = 0;
			break;
		}

		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
		if (err < 0) {
			dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);
			break;
		}
		win->x         = 0;
		win->y         = 0;
		win->width     = fmt2->fmt.pix.width;
		win->height    = fmt2->fmt.pix.height;
		win->chromakey = 0;
		win->clips     = NULL;
		win->clipcount = 0;
		break;
	}
	case VIDIOCSWIN: /*  set window and/or capture dimensions  */
	{
		struct video_window	*win = arg;
		int err1,err2;

		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
		memset(fmt2,0,sizeof(*fmt2));
		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
		err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
		if (err1 < 0)
			dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);
		if (err1 == 0) {
			fmt2->fmt.pix.width  = win->width;
			fmt2->fmt.pix.height = win->height;
			fmt2->fmt.pix.field  = V4L2_FIELD_ANY;
			fmt2->fmt.pix.bytesperline = 0;
			err = drv(inode, file, VIDIOC_S_FMT, fmt2);
			if (err < 0)
				dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
					err);
			win->width  = fmt2->fmt.pix.width;
			win->height = fmt2->fmt.pix.height;
		}

		memset(fmt2,0,sizeof(*fmt2));
		fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
		fmt2->fmt.win.w.left    = win->x;
		fmt2->fmt.win.w.top     = win->y;
		fmt2->fmt.win.w.width   = win->width;
		fmt2->fmt.win.w.height  = win->height;
		fmt2->fmt.win.chromakey = win->chromakey;
		fmt2->fmt.win.clips     = (void __user *)win->clips;
		fmt2->fmt.win.clipcount = win->clipcount;
		err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);
		if (err2 < 0)
			dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);

		if (err1 != 0 && err2 != 0)
			err = err1;
		break;
	}
	case VIDIOCCAPTURE: /*  turn on/off preview  */
	{
		int *on = arg;

		if (0 == *on) {
			/* dirty hack time.  But v4l1 has no STREAMOFF
			 * equivalent in the API, and this one at
			 * least comes close ... */
			drv(inode, file, VIDIOC_STREAMOFF, &captype);
		}
		err = drv(inode, file, VIDIOC_OVERLAY, arg);
		if (err < 0)
			dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n",err);
		break;
	}
	case VIDIOCGCHAN: /*  get input information  */
	{
		struct video_channel	*chan = arg;

		memset(&input2,0,sizeof(input2));
		input2.index = chan->channel;
		err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
		if (err < 0) {
			dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
				"channel=%d err=%d\n",chan->channel,err);
			break;
		}
		chan->channel = input2.index;
		memcpy(chan->name, input2.name,
		       min(sizeof(chan->name), sizeof(input2.name)));
		chan->name[sizeof(chan->name) - 1] = 0;
		chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
		chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
		switch (input2.type) {
		case V4L2_INPUT_TYPE_TUNER:
			chan->type = VIDEO_TYPE_TV;
			break;
		default:
		case V4L2_INPUT_TYPE_CAMERA:
			chan->type = VIDEO_TYPE_CAMERA;
			break;
		}
		chan->norm = 0;
		err = drv(inode, file, VIDIOC_G_STD, &sid);
		if (err < 0)
			dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err);
		if (err == 0) {
			if (sid & V4L2_STD_PAL)
				chan->norm = VIDEO_MODE_PAL;
			if (sid & V4L2_STD_NTSC)
				chan->norm = VIDEO_MODE_NTSC;
			if (sid & V4L2_STD_SECAM)
				chan->norm = VIDEO_MODE_SECAM;
		}
		break;
	}
	case VIDIOCSCHAN: /*  set input  */
	{
		struct video_channel *chan = arg;

		sid = 0;
		err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
		if (err < 0)
			dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err);
		switch (chan->norm) {
		case VIDEO_MODE_PAL:
			sid = V4L2_STD_PAL;
			break;
		case VIDEO_MODE_NTSC:
			sid = V4L2_STD_NTSC;
			break;
		case VIDEO_MODE_SECAM:
			sid = V4L2_STD_SECAM;
			break;
		}
		if (0 != sid) {
			err = drv(inode, file, VIDIOC_S_STD, &sid);
			if (err < 0)
				dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err);
		}
		break;
	}
	case VIDIOCGPICT: /*  get tone controls & partial capture format  */
	{
		struct video_picture	*pict = arg;

		pict->brightness = get_v4l_control(inode, file,
						   V4L2_CID_BRIGHTNESS,drv);
		pict->hue = get_v4l_control(inode, file,
					    V4L2_CID_HUE, drv);
		pict->contrast = get_v4l_control(inode, file,
						 V4L2_CID_CONTRAST, drv);
		pict->colour = get_v4l_control(inode, file,
					       V4L2_CID_SATURATION, drv);
		pict->whiteness = get_v4l_control(inode, file,
						  V4L2_CID_WHITENESS, drv);

		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
		memset(fmt2,0,sizeof(*fmt2));
		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
		if (err < 0) {
			dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
			break;
		}
#if 0 /* FIXME */
		pict->depth   = fmt2->fmt.pix.depth;
#endif
		pict->palette = pixelformat_to_palette(
			fmt2->fmt.pix.pixelformat);
		break;
	}
	case VIDIOCSPICT: /*  set tone controls & partial capture format  */
	{
		struct video_picture	*pict = arg;

		set_v4l_control(inode, file,
				V4L2_CID_BRIGHTNESS, pict->brightness, drv);
		set_v4l_control(inode, file,
				V4L2_CID_HUE, pict->hue, drv);
		set_v4l_control(inode, file,
				V4L2_CID_CONTRAST, pict->contrast, drv);
		set_v4l_control(inode, file,
				V4L2_CID_SATURATION, pict->colour, drv);
		set_v4l_control(inode, file,
				V4L2_CID_WHITENESS, pict->whiteness, drv);

		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
		memset(fmt2,0,sizeof(*fmt2));
		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
		if (err < 0)
			dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
		if (fmt2->fmt.pix.pixelformat != 
		    palette_to_pixelformat(pict->palette)) {
			fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
				pict->palette);
			err = drv(inode, file, VIDIOC_S_FMT, fmt2);
			if (err < 0)
				dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err);
		}

		err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
		if (err < 0)
			dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
		if (fbuf2.fmt.pixelformat !=
		    palette_to_pixelformat(pict->palette)) {
			fbuf2.fmt.pixelformat = palette_to_pixelformat(
				pict->palette);
			err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
			if (err < 0)
				dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err);
			err = 0; /* likely fails for non-root */
		}
		break;
	}
	case VIDIOCGTUNER: /*  get tuner information  */
	{
		struct video_tuner	*tun = arg;

		memset(&tun2,0,sizeof(tun2));
		err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
		if (err < 0) {
			dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err);
			break;
		}
		memcpy(tun->name, tun2.name,
		       min(sizeof(tun->name), sizeof(tun2.name)));
		tun->name[sizeof(tun->name) - 1] = 0;
		tun->rangelow = tun2.rangelow;
		tun->rangehigh = tun2.rangehigh;
		tun->flags = 0;
		tun->mode = VIDEO_MODE_AUTO;

		for (i = 0; i < 64; i++) {
			memset(&std2,0,sizeof(std2));
			std2.index = i;
			if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
				break;
			if (std2.id & V4L2_STD_PAL)
				tun->flags |= VIDEO_TUNER_PAL;
			if (std2.id & V4L2_STD_NTSC)
				tun->flags |= VIDEO_TUNER_NTSC;
			if (std2.id & V4L2_STD_SECAM)
				tun->flags |= VIDEO_TUNER_SECAM;
		}

		err = drv(inode, file, VIDIOC_G_STD, &sid);
		if (err < 0)
			dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err);
		if (err == 0) {
			if (sid & V4L2_STD_PAL)
				tun->mode = VIDEO_MODE_PAL;
			if (sid & V4L2_STD_NTSC)
				tun->mode = VIDEO_MODE_NTSC;
			if (sid & V4L2_STD_SECAM)
				tun->mode = VIDEO_MODE_SECAM;
		}

		if (tun2.capability & V4L2_TUNER_CAP_LOW)
			tun->flags |= VIDEO_TUNER_LOW;
		if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
			tun->flags |= VIDEO_TUNER_STEREO_ON;
		tun->signal = tun2.signal;
		break;
	}
	case VIDIOCSTUNER: /*  select a tuner input  */
	{
#if 0 /* FIXME */
		err = drv(inode, file, VIDIOC_S_INPUT, &i);
		if (err < 0)
			dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
#else
		err = 0;
#endif
		break;
	}
	case VIDIOCGFREQ: /*  get frequency  */
	{
		int *freq = arg;

		freq2.tuner = 0;
		err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
		if (err < 0)
			dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err);
		if (0 == err)
			*freq = freq2.frequency;
		break;
	}
	case VIDIOCSFREQ: /*  set frequency  */
	{
		int *freq = arg;

		freq2.tuner = 0;
		drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
		freq2.frequency = *freq;
		err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
		if (err < 0)
			dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err);
		break;
	}
	case VIDIOCGAUDIO: /*  get audio properties/controls  */
	{
		struct video_audio	*aud = arg;

		err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
		if (err < 0) {
			dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err);
			break;
		}
		memcpy(aud->name, aud2.name,
		       min(sizeof(aud->name), sizeof(aud2.name)));
		aud->name[sizeof(aud->name) - 1] = 0;
		aud->audio = aud2.index;
		aud->flags = 0;
		i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
		if (i >= 0) {
			aud->volume = i;
			aud->flags |= VIDEO_AUDIO_VOLUME;
		}
		i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
		if (i >= 0) {
			aud->bass = i;
			aud->flags |= VIDEO_AUDIO_BASS;
		}
		i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
		if (i >= 0) {
			aud->treble = i;
			aud->flags |= VIDEO_AUDIO_TREBLE;
		}
		i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
		if (i >= 0) {
			aud->balance = i;
			aud->flags |= VIDEO_AUDIO_BALANCE;
		}
		i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
		if (i >= 0) {
			if (i)
				aud->flags |= VIDEO_AUDIO_MUTE;
			aud->flags |= VIDEO_AUDIO_MUTABLE;
		}
		aud->step = 1;
		qctrl2.id = V4L2_CID_AUDIO_VOLUME;
		if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
		    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
			aud->step = qctrl2.step;
		aud->mode = 0;
		err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
		if (err < 0) {
			dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
			err = 0;
			break;
		}
		if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
			aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
		else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
			aud->mode = VIDEO_SOUND_STEREO;
		else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
			aud->mode = VIDEO_SOUND_MONO;
		break;
	}
	case VIDIOCSAUDIO: /*  set audio controls  */
	{
		struct video_audio	*aud = arg;

		memset(&aud2,0,sizeof(aud2));
		memset(&tun2,0,sizeof(tun2));
		
		aud2.index = aud->audio;
		err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
		if (err < 0) {
			dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err);
			break;
		}

		set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, 
				aud->volume, drv);
		set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
				aud->bass, drv);
		set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
				aud->treble, drv);
		set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
				aud->balance, drv);
		set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
				!!(aud->flags & VIDEO_AUDIO_MUTE), drv);

		err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
		if (err < 0)
			dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n",err);
		if (err == 0) {
			switch (aud->mode) {
			default:
			case VIDEO_SOUND_MONO:
			case VIDEO_SOUND_LANG1:
				tun2.audmode = V4L2_TUNER_MODE_MONO;
				break;
			case VIDEO_SOUND_STEREO:
				tun2.audmode = V4L2_TUNER_MODE_STEREO;
				break;
			case VIDEO_SOUND_LANG2:
				tun2.audmode = V4L2_TUNER_MODE_LANG2;
				break;
			}
			err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
			if (err < 0)
				dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err);
		}
		err = 0;
		break;
	}
#if 0
	case VIDIOCGMBUF:
		/* v4l2 drivers must implement that themself.  The
		   mmap() differences can't be translated fully
		   transparent, thus there is no point to try that */
#endif
	case VIDIOCMCAPTURE: /*  capture a frame  */
	{
		struct video_mmap	*mm = arg;

		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
		memset(&buf2,0,sizeof(buf2));
		memset(fmt2,0,sizeof(*fmt2));
		
		fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
		if (err < 0) {
			dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
			break;
		}
		if (mm->width   != fmt2->fmt.pix.width  || 
		    mm->height  != fmt2->fmt.pix.height ||
		    palette_to_pixelformat(mm->format) != 
		    fmt2->fmt.pix.pixelformat)
		{/* New capture format...  */
			fmt2->fmt.pix.width = mm->width;
			fmt2->fmt.pix.height = mm->height;
			fmt2->fmt.pix.pixelformat =
				palette_to_pixelformat(mm->format);
			fmt2->fmt.pix.field = V4L2_FIELD_ANY;
			fmt2->fmt.pix.bytesperline = 0;
			err = drv(inode, file, VIDIOC_S_FMT, fmt2);
			if (err < 0) {
				dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err);
				break;
			}
		}
		buf2.index = mm->frame;
		buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
		if (err < 0) {
			dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err);
			break;
		}
		err = drv(inode, file, VIDIOC_QBUF, &buf2);
		if (err < 0) {
			dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err);
			break;
		}
		err = drv(inode, file, VIDIOC_STREAMON, &captype);
		if (err < 0)
			dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err);
		break;
	}
	case VIDIOCSYNC: /*  wait for a frame  */
	{
		int			*i = arg;

		buf2.index = *i;
		buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
		err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
		if (err < 0) {
			/*  No such buffer */
			dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
			break;
		}
		if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) {
			/* Buffer is not mapped  */
			err = -EINVAL;
			break;
		}

		/* make sure capture actually runs so we don't block forever */
		err = drv(inode, file, VIDIOC_STREAMON, &captype);
		if (err < 0) {
			dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err);
			break;
		}

		/*  Loop as long as the buffer is queued, but not done  */
		while ((buf2.flags &
			(V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
		       == V4L2_BUF_FLAG_QUEUED)
		{
			err = poll_one(file);
			if (err < 0 ||	/* error or sleep was interrupted  */
			    err == 0)	/* timeout? Shouldn't occur.  */
				break;
			err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
			if (err < 0)
				dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
		}
		if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */
			break;
		do {
			err = drv(inode, file, VIDIOC_DQBUF, &buf2);
			if (err < 0)
				dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err);
		} while (err == 0 && buf2.index != *i);
		break;
	}

	case VIDIOCGVBIFMT: /* query VBI data capture format */
	{
		struct vbi_format      *fmt = arg;
		
		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
		memset(fmt2, 0, sizeof(*fmt2));
		fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
		
		err = drv(inode, file, VIDIOC_G_FMT, fmt2);
		if (err < 0) {
			dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
			break;
		}
		memset(fmt, 0, sizeof(*fmt));
		fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
		fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
		fmt->sample_format    = VIDEO_PALETTE_RAW;
		fmt->start[0]         = fmt2->fmt.vbi.start[0];
		fmt->count[0]         = fmt2->fmt.vbi.count[0];
		fmt->start[1]         = fmt2->fmt.vbi.start[1];
		fmt->count[1]         = fmt2->fmt.vbi.count[1];
		fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
                break;
	}
	case VIDIOCSVBIFMT:
	{
		struct vbi_format      *fmt = arg;
		
		fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL);
		memset(fmt2, 0, sizeof(*fmt2));

		fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
		fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
		fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
		fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
		fmt2->fmt.vbi.start[0]         = fmt->start[0]; 
		fmt2->fmt.vbi.count[0]         = fmt->count[0]; 
		fmt2->fmt.vbi.start[1]         = fmt->start[1]; 
		fmt2->fmt.vbi.count[1]         = fmt->count[1]; 
		fmt2->fmt.vbi.flags            = fmt->flags;
		err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
		if (err < 0) {
			dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
			break;
		}

		if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
		    fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
		    VIDEO_PALETTE_RAW              != fmt->sample_format    ||
		    fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
		    fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
		    fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
		    fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
		    fmt2->fmt.vbi.flags            != fmt->flags) {
			err = -EINVAL;
			break;
		}
		err = drv(inode, file, VIDIOC_S_FMT, fmt2);
		if (err < 0)
			dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
		break;
	}
	
	default:
		err = -ENOIOCTLCMD;
		break;
	}

	if (cap2)
		kfree(cap2);
	if (fmt2)
		kfree(fmt2);
	return err;
}
static int si21_writeregs(struct si21xx_state *state, u8 reg1,
							u8 *data, int len)
{
	int ret;
	u8 buf[60];
	struct i2c_msg msg = {
				.addr = state->config->demod_address,
				.flags = 0,
				.buf = buf,
				.len = len + 1
	};

	msg.buf[0] =  reg1;
	memcpy(msg.buf + 1, data, len);

	ret = i2c_transfer(state->i2c, &msg, 1);

	if (ret != 1)
		dprintk("%s: writereg error (reg1 == 0x%02x, data == 0x%02x, "
			"ret == %i)\n", __func__, reg1, data[0], ret);

	return (ret != 1) ? -EREMOTEIO : 0;
}

static int si21_writereg(struct si21xx_state *state, u8 reg, u8 data)
{
	int ret;
	u8 buf[] = { reg, data };
	struct i2c_msg msg = {
				.addr = state->config->demod_address,
				.flags = 0,
				.buf = buf,
				.len = 2
	};

	ret = i2c_transfer(state->i2c, &msg, 1);

	if (ret != 1)
		dprintk("%s: writereg error (reg == 0x%02x, data == 0x%02x, "
			"ret == %i)\n", __func__, reg, data, ret);

	return (ret != 1) ? -EREMOTEIO : 0;
}

static int si21_write(struct dvb_frontend *fe, const u8 buf[], int len)
{
	struct si21xx_state *state = fe->demodulator_priv;

	if (len != 2)
		return -EINVAL;

	return si21_writereg(state, buf[0], buf[1]);
}

static u8 si21_readreg(struct si21xx_state *state, u8 reg)
{
	int ret;
	u8 b0[] = { reg };
	u8 b1[] = { 0 };
	struct i2c_msg msg[] = {
		{
			.addr = state->config->demod_address,
			.flags = 0,
			.buf = b0,
			.len = 1
		}, {
			.addr = state->config->demod_address,
Exemple #9
0
static int tda7432_command(struct i2c_client *client,
			   unsigned int cmd, void *arg)
{
	struct tda7432 *t = client->data;
	d2printk("tda7432: In tda7432_command\n");

	switch (cmd) {
	/* --- v4l ioctls --- */
	/* take care: bttv does userspace copying, we'll get a
	   kernel pointer here... */
	
	/* Query card - scale from TDA7432 settings to V4L settings */
	case VIDIOCGAUDIO:
	{
		struct video_audio *va = arg;
		dprintk("tda7432: VIDIOCGAUDIO\n");

		va->flags |= VIDEO_AUDIO_VOLUME |
			VIDEO_AUDIO_BASS |
			VIDEO_AUDIO_TREBLE |
			VIDEO_AUDIO_MUTABLE;
		if (t->muted)
			va->flags |= VIDEO_AUDIO_MUTE;
		va->mode |= VIDEO_SOUND_STEREO;
		/* Master volume control
		 * V4L volume is min 0, max 65535
		 * TDA7432 Volume: 
		 * Min (-79dB) is 0x6f
		 * Max (+20dB) is 0x07 (630)
		 * Max (0dB) is 0x20 (829)
		 * (Mask out bit 7 of vol - it's for the loudness setting)
		 */
		if(!maxvol){  /* max +20db */
			va->volume = ( 0x6f - (t->volume & 0x7F) ) * 630;
		} else {     /* max 0db   */
			va->volume = (int )(( 0x6f - (t->volume & 0x7F) ) * 829.557);
		}
		
		/* Balance depends on L,R attenuation
		 * V4L balance is 0 to 65535, middle is 32768
		 * TDA7432 attenuation: min (0dB) is 0, max (-37.5dB) is 0x1f
		 * to scale up to V4L numbers, mult by 1057
		 * attenuation exists for lf, lr, rf, rr
		 * we use only lf and rf (front channels)
		 */
		
		if ( (t->lf) < (t->rf) )
			/* right is attenuated, balance shifted left */
			va->balance = (32768 - 1057*(t->rf));
		else
			/* left is attenuated, balance shifted right */
			va->balance = (32768 + 1057*(t->lf));
		
		/* Bass/treble 4 bits each */	
		va->bass=t->bass;
		if(va->bass >= 0x8)
			va->bass = ~(va->bass - 0x8) & 0xf;
		va->bass = (va->bass << 12)+(va->bass << 8)+(va->bass << 4)+(va->bass);
		va->treble=t->treble;
		if(va->treble >= 0x8)
			va->treble = ~(va->treble - 0x8) & 0xf;
		va->treble = (va->treble << 12)+(va->treble << 8)+(va->treble << 4)+(va->treble);
								
		break; /* VIDIOCGAUDIO case */
	}

	/* Set card - scale from V4L settings to TDA7432 settings */
	case VIDIOCSAUDIO:
	{
		struct video_audio *va = arg;
		dprintk("tda7432: VIDEOCSAUDIO\n");

		if(va->flags & VIDEO_AUDIO_VOLUME){
				
			if(!maxvol){ /* max +20db */
				t->volume = 0x6f - ( (va->volume)/630 );
			} else {    /* max 0db   */
				t->volume = 0x6f - ((int) (va->volume)/829.557 );
			}
		
		if (loudness)		/* Turn on the loudness bit */
			t->volume |= TDA7432_LD_ON;
		
			tda7432_write(client,TDA7432_VL, t->volume);
		}
		
		if(va->flags & VIDEO_AUDIO_BASS)
		{
			t->bass = va->bass >> 12;
			if(t->bass>= 0x8)
					t->bass = (~t->bass & 0xf) + 0x8 ;
		}
		if(va->flags & VIDEO_AUDIO_TREBLE)
		{
			t->treble= va->treble >> 12;
			if(t->treble>= 0x8)
					t->treble = (~t->treble & 0xf) + 0x8 ;
		}
		if(va->flags & (VIDEO_AUDIO_TREBLE| VIDEO_AUDIO_BASS))
			tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble );
		
		if(va->flags & VIDEO_AUDIO_BALANCE)	{
		if (va->balance < 32768) 
		{
			/* shifted to left, attenuate right */
			t->rr = (32768 - va->balance)/1057;
			t->rf = t->rr;
			t->lr = TDA7432_ATTEN_0DB;
			t->lf = TDA7432_ATTEN_0DB;	
		}
		else if(va->balance > 32769)
		{
			/* shifted to right, attenuate left */
			t->lf = (va->balance - 32768)/1057;
			t->lr = t->lf;
			t->rr = TDA7432_ATTEN_0DB;
			t->rf = TDA7432_ATTEN_0DB;		
		}
		else 
		{
			/* centered */		
			t->rr = TDA7432_ATTEN_0DB;
			t->rf = TDA7432_ATTEN_0DB;
			t->lf = TDA7432_ATTEN_0DB;
			t->lr = TDA7432_ATTEN_0DB;
		}
		}
					
	 	t->muted=(va->flags & VIDEO_AUDIO_MUTE);	
		if (t->muted)
		{
			/* Mute & update balance*/	
			tda7432_write(client,TDA7432_LF, t->lf | TDA7432_MUTE);
			tda7432_write(client,TDA7432_LR, t->lr | TDA7432_MUTE);
			tda7432_write(client,TDA7432_RF, t->rf | TDA7432_MUTE);
			tda7432_write(client,TDA7432_RR, t->rr | TDA7432_MUTE);
		} else {
			tda7432_write(client,TDA7432_LF, t->lf);
			tda7432_write(client,TDA7432_LR, t->lr);
			tda7432_write(client,TDA7432_RF, t->rf);
			tda7432_write(client,TDA7432_RR, t->rr);
		}
							
		break;

	} /* end of VIDEOCSAUDIO case */
static int
nfs_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, struct qstr *name,
		struct nfs_fh *fhandle, struct nfs_fattr *fattr)
{
	struct nfs_diropargs	arg = {
		.fh		= NFS_FH(dir),
		.name		= name->name,
		.len		= name->len
	};
	struct nfs_diropok	res = {
		.fh		= fhandle,
		.fattr		= fattr
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_LOOKUP],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
	};
	int			status;

	dprintk("NFS call  lookup %s\n", name->name);
	nfs_fattr_init(fattr);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	dprintk("NFS reply lookup: %d\n", status);
	return status;
}

static int nfs_proc_readlink(struct inode *inode, struct page *page,
		unsigned int pgbase, unsigned int pglen)
{
	struct nfs_readlinkargs	args = {
		.fh		= NFS_FH(inode),
		.pgbase		= pgbase,
		.pglen		= pglen,
		.pages		= &page
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_READLINK],
		.rpc_argp	= &args,
	};
	int			status;

	dprintk("NFS call  readlink\n");
	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
	dprintk("NFS reply readlink: %d\n", status);
	return status;
}

struct nfs_createdata {
	struct nfs_createargs arg;
	struct nfs_diropok res;
	struct nfs_fh fhandle;
	struct nfs_fattr fattr;
};

static struct nfs_createdata *nfs_alloc_createdata(struct inode *dir,
		struct dentry *dentry, struct iattr *sattr)
{
	struct nfs_createdata *data;

	data = kmalloc(sizeof(*data), GFP_KERNEL);

	if (data != NULL) {
		data->arg.fh = NFS_FH(dir);
		data->arg.name = dentry->d_name.name;
		data->arg.len = dentry->d_name.len;
		data->arg.sattr = sattr;
		nfs_fattr_init(&data->fattr);
		data->fhandle.size = 0;
		data->res.fh = &data->fhandle;
		data->res.fattr = &data->fattr;
	}
	return data;
};

static void nfs_free_createdata(const struct nfs_createdata *data)
{
	kfree(data);
}
static int
nfs_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
{
	struct nfs_linkargs	arg = {
		.fromfh		= NFS_FH(inode),
		.tofh		= NFS_FH(dir),
		.toname		= name->name,
		.tolen		= name->len
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_LINK],
		.rpc_argp	= &arg,
	};
	int			status;

	dprintk("NFS call  link %s\n", name->name);
	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
	nfs_mark_for_revalidate(inode);
	nfs_mark_for_revalidate(dir);
	dprintk("NFS reply link: %d\n", status);
	return status;
}

static int
nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
		 unsigned int len, struct iattr *sattr)
{
	struct nfs_fh *fh;
	struct nfs_fattr *fattr;
	struct nfs_symlinkargs	arg = {
		.fromfh		= NFS_FH(dir),
		.fromname	= dentry->d_name.name,
		.fromlen	= dentry->d_name.len,
		.pages		= &page,
		.pathlen	= len,
		.sattr		= sattr
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_SYMLINK],
		.rpc_argp	= &arg,
	};
	int status = -ENAMETOOLONG;

	dprintk("NFS call  symlink %s\n", dentry->d_name.name);

	if (len > NFS2_MAXPATHLEN)
		goto out;

	fh = nfs_alloc_fhandle();
	fattr = nfs_alloc_fattr();
	status = -ENOMEM;
	if (fh == NULL || fattr == NULL)
		goto out_free;

	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_mark_for_revalidate(dir);

	/*
	 * V2 SYMLINK requests don't return any attributes.  Setting the
	 * filehandle size to zero indicates to nfs_instantiate that it
	 * should fill in the data with a LOOKUP call on the wire.
	 */
	if (status == 0)
		status = nfs_instantiate(dentry, fh, fattr);

out_free:
	nfs_free_fattr(fattr);
	nfs_free_fhandle(fh);
out:
	dprintk("NFS reply symlink: %d\n", status);
	return status;
}

static int
nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
{
	struct nfs_createdata *data;
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_MKDIR],
	};
	int status = -ENOMEM;

	dprintk("NFS call  mkdir %s\n", dentry->d_name.name);
	data = nfs_alloc_createdata(dir, dentry, sattr);
	if (data == NULL)
		goto out;
	msg.rpc_argp = &data->arg;
	msg.rpc_resp = &data->res;

	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_mark_for_revalidate(dir);
	if (status == 0)
		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr);
	nfs_free_createdata(data);
out:
	dprintk("NFS reply mkdir: %d\n", status);
	return status;
}

static int
nfs_proc_rmdir(struct inode *dir, struct qstr *name)
{
	struct nfs_diropargs	arg = {
		.fh		= NFS_FH(dir),
		.name		= name->name,
		.len		= name->len
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_RMDIR],
		.rpc_argp	= &arg,
	};
	int			status;

	dprintk("NFS call  rmdir %s\n", name->name);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_mark_for_revalidate(dir);
	dprintk("NFS reply rmdir: %d\n", status);
	return status;
}

/*
 * The READDIR implementation is somewhat hackish - we pass a temporary
 * buffer to the encode function, which installs it in the receive
 * the receive iovec. The decode function just parses the reply to make
 * sure it is syntactically correct; the entries itself are decoded
 * from nfs_readdir by calling the decode_entry function directly.
 */
static int
nfs_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
		 u64 cookie, struct page **pages, unsigned int count, int plus)
{
	struct inode		*dir = dentry->d_inode;
	struct nfs_readdirargs	arg = {
		.fh		= NFS_FH(dir),
		.cookie		= cookie,
		.count		= count,
		.pages		= pages,
	};
	struct rpc_message	msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_READDIR],
		.rpc_argp	= &arg,
		.rpc_cred	= cred,
	};
	int			status;

	dprintk("NFS call  readdir %d\n", (unsigned int)cookie);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);

	nfs_invalidate_atime(dir);

	dprintk("NFS reply readdir: %d\n", status);
	return status;
}

static int
nfs_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
			struct nfs_fsstat *stat)
{
	struct nfs2_fsstat fsinfo;
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_STATFS],
		.rpc_argp	= fhandle,
		.rpc_resp	= &fsinfo,
	};
	int	status;

	dprintk("NFS call  statfs\n");
	nfs_fattr_init(stat->fattr);
	status = rpc_call_sync(server->client, &msg, 0);
	dprintk("NFS reply statfs: %d\n", status);
	if (status)
		goto out;
	stat->tbytes = (u64)fsinfo.blocks * fsinfo.bsize;
	stat->fbytes = (u64)fsinfo.bfree  * fsinfo.bsize;
	stat->abytes = (u64)fsinfo.bavail * fsinfo.bsize;
	stat->tfiles = 0;
	stat->ffiles = 0;
	stat->afiles = 0;
out:
	return status;
}

static int
nfs_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
			struct nfs_fsinfo *info)
{
	struct nfs2_fsstat fsinfo;
	struct rpc_message msg = {
		.rpc_proc	= &nfs_procedures[NFSPROC_STATFS],
		.rpc_argp	= fhandle,
		.rpc_resp	= &fsinfo,
	};
	int	status;

	dprintk("NFS call  fsinfo\n");
	nfs_fattr_init(info->fattr);
	status = rpc_call_sync(server->client, &msg, 0);
	dprintk("NFS reply fsinfo: %d\n", status);
	if (status)
		goto out;
	info->rtmax  = NFS_MAXDATA;
	info->rtpref = fsinfo.tsize;
	info->rtmult = fsinfo.bsize;
	info->wtmax  = NFS_MAXDATA;
	info->wtpref = fsinfo.tsize;
	info->wtmult = fsinfo.bsize;
	info->dtpref = fsinfo.tsize;
	info->maxfilesize = 0x7FFFFFFF;
	info->lease_time = 0;
out:
	return status;
}

static int
nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle,
		  struct nfs_pathconf *info)
{
	info->max_link = 0;
	info->max_namelen = NFS2_MAXNAMLEN;
	return 0;
}

static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data)
{
	nfs_invalidate_atime(data->inode);
	if (task->tk_status >= 0) {
		nfs_refresh_inode(data->inode, data->res.fattr);
		/* Emulate the eof flag, which isn't normally needed in NFSv2
		 * as it is guaranteed to always return the file attributes
		 */
		if (data->args.offset + data->args.count >= data->res.fattr->size)
			data->res.eof = 1;
	}
	return 0;
}

static void nfs_proc_read_setup(struct nfs_read_data *data, struct rpc_message *msg)
{
	msg->rpc_proc = &nfs_procedures[NFSPROC_READ];
}

static void nfs_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_data *data)
{
	rpc_call_start(task);
}
Exemple #12
0
static int
nfs3_proc_link(struct inode *inode, struct inode *dir, struct qstr *name)
{
	struct nfs3_linkargs	arg = {
		.fromfh		= NFS_FH(inode),
		.tofh		= NFS_FH(dir),
		.toname		= name->name,
		.tolen		= name->len
	};
	struct nfs3_linkres	res;
	struct rpc_message msg = {
		.rpc_proc	= &nfs3_procedures[NFS3PROC_LINK],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
	};
	int status = -ENOMEM;

	dprintk("NFS call  link %s\n", name->name);
	res.fattr = nfs_alloc_fattr();
	res.dir_attr = nfs_alloc_fattr();
	if (res.fattr == NULL || res.dir_attr == NULL)
		goto out;

	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
	nfs_post_op_update_inode(dir, res.dir_attr);
	nfs_post_op_update_inode(inode, res.fattr);
out:
	nfs_free_fattr(res.dir_attr);
	nfs_free_fattr(res.fattr);
	dprintk("NFS reply link: %d\n", status);
	return status;
}

static int
nfs3_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page,
		  unsigned int len, struct iattr *sattr)
{
	struct nfs3_createdata *data;
	int status = -ENOMEM;

	if (len > NFS3_MAXPATHLEN)
		return -ENAMETOOLONG;

	dprintk("NFS call  symlink %pd\n", dentry);

	data = nfs3_alloc_createdata();
	if (data == NULL)
		goto out;
	data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_SYMLINK];
	data->arg.symlink.fromfh = NFS_FH(dir);
	data->arg.symlink.fromname = dentry->d_name.name;
	data->arg.symlink.fromlen = dentry->d_name.len;
	data->arg.symlink.pages = &page;
	data->arg.symlink.pathlen = len;
	data->arg.symlink.sattr = sattr;

	status = nfs3_do_create(dir, dentry, data);

	nfs3_free_createdata(data);
out:
	dprintk("NFS reply symlink: %d\n", status);
	return status;
}

static int
nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr)
{
	struct posix_acl *default_acl, *acl;
	struct nfs3_createdata *data;
	int status = -ENOMEM;

	dprintk("NFS call  mkdir %pd\n", dentry);

	data = nfs3_alloc_createdata();
	if (data == NULL)
		goto out;

	status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
	if (status)
		goto out;

	data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKDIR];
	data->arg.mkdir.fh = NFS_FH(dir);
	data->arg.mkdir.name = dentry->d_name.name;
	data->arg.mkdir.len = dentry->d_name.len;
	data->arg.mkdir.sattr = sattr;

	status = nfs3_do_create(dir, dentry, data);
	if (status != 0)
		goto out_release_acls;

	status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);

out_release_acls:
	posix_acl_release(acl);
	posix_acl_release(default_acl);
out:
	nfs3_free_createdata(data);
	dprintk("NFS reply mkdir: %d\n", status);
	return status;
}

static int
nfs3_proc_rmdir(struct inode *dir, struct qstr *name)
{
	struct nfs_fattr	*dir_attr;
	struct nfs3_diropargs	arg = {
		.fh		= NFS_FH(dir),
		.name		= name->name,
		.len		= name->len
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs3_procedures[NFS3PROC_RMDIR],
		.rpc_argp	= &arg,
	};
	int status = -ENOMEM;

	dprintk("NFS call  rmdir %s\n", name->name);
	dir_attr = nfs_alloc_fattr();
	if (dir_attr == NULL)
		goto out;

	msg.rpc_resp = dir_attr;
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_post_op_update_inode(dir, dir_attr);
	nfs_free_fattr(dir_attr);
out:
	dprintk("NFS reply rmdir: %d\n", status);
	return status;
}

/*
 * The READDIR implementation is somewhat hackish - we pass the user buffer
 * to the encode function, which installs it in the receive iovec.
 * The decode function itself doesn't perform any decoding, it just makes
 * sure the reply is syntactically correct.
 *
 * Also note that this implementation handles both plain readdir and
 * readdirplus.
 */
static int
nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
		  u64 cookie, struct page **pages, unsigned int count, int plus)
{
	struct inode		*dir = dentry->d_inode;
	__be32			*verf = NFS_I(dir)->cookieverf;
	struct nfs3_readdirargs	arg = {
		.fh		= NFS_FH(dir),
		.cookie		= cookie,
		.verf		= {verf[0], verf[1]},
		.plus		= plus,
		.count		= count,
		.pages		= pages
	};
	struct nfs3_readdirres	res = {
		.verf		= verf,
		.plus		= plus
	};
	struct rpc_message	msg = {
		.rpc_proc	= &nfs3_procedures[NFS3PROC_READDIR],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
		.rpc_cred	= cred
	};
	int status = -ENOMEM;

	if (plus)
		msg.rpc_proc = &nfs3_procedures[NFS3PROC_READDIRPLUS];

	dprintk("NFS call  readdir%s %d\n",
			plus? "plus" : "", (unsigned int) cookie);

	res.dir_attr = nfs_alloc_fattr();
	if (res.dir_attr == NULL)
		goto out;

	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);

	nfs_invalidate_atime(dir);
	nfs_refresh_inode(dir, res.dir_attr);

	nfs_free_fattr(res.dir_attr);
out:
	dprintk("NFS reply readdir%s: %d\n",
			plus? "plus" : "", status);
	return status;
}

static int
nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
		dev_t rdev)
{
	struct posix_acl *default_acl, *acl;
	struct nfs3_createdata *data;
	int status = -ENOMEM;

	dprintk("NFS call  mknod %pd %u:%u\n", dentry,
			MAJOR(rdev), MINOR(rdev));

	data = nfs3_alloc_createdata();
	if (data == NULL)
		goto out;

	status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
	if (status)
		goto out;

	data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_MKNOD];
	data->arg.mknod.fh = NFS_FH(dir);
	data->arg.mknod.name = dentry->d_name.name;
	data->arg.mknod.len = dentry->d_name.len;
	data->arg.mknod.sattr = sattr;
	data->arg.mknod.rdev = rdev;

	switch (sattr->ia_mode & S_IFMT) {
	case S_IFBLK:
		data->arg.mknod.type = NF3BLK;
		break;
	case S_IFCHR:
		data->arg.mknod.type = NF3CHR;
		break;
	case S_IFIFO:
		data->arg.mknod.type = NF3FIFO;
		break;
	case S_IFSOCK:
		data->arg.mknod.type = NF3SOCK;
		break;
	default:
		status = -EINVAL;
		goto out;
	}

	status = nfs3_do_create(dir, dentry, data);
	if (status != 0)
		goto out_release_acls;

	status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);

out_release_acls:
	posix_acl_release(acl);
	posix_acl_release(default_acl);
out:
	nfs3_free_createdata(data);
	dprintk("NFS reply mknod: %d\n", status);
	return status;
}

static int
nfs3_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle,
		 struct nfs_fsstat *stat)
{
	struct rpc_message msg = {
		.rpc_proc	= &nfs3_procedures[NFS3PROC_FSSTAT],
		.rpc_argp	= fhandle,
		.rpc_resp	= stat,
	};
	int	status;

	dprintk("NFS call  fsstat\n");
	nfs_fattr_init(stat->fattr);
	status = rpc_call_sync(server->client, &msg, 0);
	dprintk("NFS reply fsstat: %d\n", status);
	return status;
}

static int
do_proc_fsinfo(struct rpc_clnt *client, struct nfs_fh *fhandle,
		 struct nfs_fsinfo *info)
{
	struct rpc_message msg = {
		.rpc_proc	= &nfs3_procedures[NFS3PROC_FSINFO],
		.rpc_argp	= fhandle,
		.rpc_resp	= info,
	};
	int	status;

	dprintk("NFS call  fsinfo\n");
	nfs_fattr_init(info->fattr);
	status = rpc_call_sync(client, &msg, 0);
	dprintk("NFS reply fsinfo: %d\n", status);
	return status;
}

/*
 * Bare-bones access to fsinfo: this is for nfs_get_root/nfs_get_sb via
 * nfs_create_server
 */
static int
nfs3_proc_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle,
		   struct nfs_fsinfo *info)
{
	int	status;

	status = do_proc_fsinfo(server->client, fhandle, info);
	if (status && server->nfs_client->cl_rpcclient != server->client)
		status = do_proc_fsinfo(server->nfs_client->cl_rpcclient, fhandle, info);
	return status;
}
Exemple #13
0
/*
 * Create a regular file.
 */
static int
nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
		 int flags)
{
	struct posix_acl *default_acl, *acl;
	struct nfs3_createdata *data;
	int status = -ENOMEM;

	dprintk("NFS call  create %pd\n", dentry);

	data = nfs3_alloc_createdata();
	if (data == NULL)
		goto out;

	data->msg.rpc_proc = &nfs3_procedures[NFS3PROC_CREATE];
	data->arg.create.fh = NFS_FH(dir);
	data->arg.create.name = dentry->d_name.name;
	data->arg.create.len = dentry->d_name.len;
	data->arg.create.sattr = sattr;

	data->arg.create.createmode = NFS3_CREATE_UNCHECKED;
	if (flags & O_EXCL) {
		data->arg.create.createmode  = NFS3_CREATE_EXCLUSIVE;
		data->arg.create.verifier[0] = cpu_to_be32(jiffies);
		data->arg.create.verifier[1] = cpu_to_be32(current->pid);
	}

	status = posix_acl_create(dir, &sattr->ia_mode, &default_acl, &acl);
	if (status)
		goto out;

	for (;;) {
		status = nfs3_do_create(dir, dentry, data);

		if (status != -ENOTSUPP)
			break;
		/* If the server doesn't support the exclusive creation
		 * semantics, try again with simple 'guarded' mode. */
		switch (data->arg.create.createmode) {
			case NFS3_CREATE_EXCLUSIVE:
				data->arg.create.createmode = NFS3_CREATE_GUARDED;
				break;

			case NFS3_CREATE_GUARDED:
				data->arg.create.createmode = NFS3_CREATE_UNCHECKED;
				break;

			case NFS3_CREATE_UNCHECKED:
				goto out;
		}
		nfs_fattr_init(data->res.dir_attr);
		nfs_fattr_init(data->res.fattr);
	}

	if (status != 0)
		goto out_release_acls;

	/* When we created the file with exclusive semantics, make
	 * sure we set the attributes afterwards. */
	if (data->arg.create.createmode == NFS3_CREATE_EXCLUSIVE) {
		dprintk("NFS call  setattr (post-create)\n");

		if (!(sattr->ia_valid & ATTR_ATIME_SET))
			sattr->ia_valid |= ATTR_ATIME;
		if (!(sattr->ia_valid & ATTR_MTIME_SET))
			sattr->ia_valid |= ATTR_MTIME;

		/* Note: we could use a guarded setattr here, but I'm
		 * not sure this buys us anything (and I'd have
		 * to revamp the NFSv3 XDR code) */
		status = nfs3_proc_setattr(dentry, data->res.fattr, sattr);
		nfs_post_op_update_inode(dentry->d_inode, data->res.fattr);
		dprintk("NFS reply setattr (post-create): %d\n", status);
		if (status != 0)
			goto out_release_acls;
	}

	status = nfs3_proc_setacls(dentry->d_inode, acl, default_acl);

out_release_acls:
	posix_acl_release(acl);
	posix_acl_release(default_acl);
out:
	nfs3_free_createdata(data);
	dprintk("NFS reply create: %d\n", status);
	return status;
}
Exemple #14
0
static int
nfs3_proc_lookup(struct inode *dir, struct qstr *name,
		 struct nfs_fh *fhandle, struct nfs_fattr *fattr,
		 struct nfs4_label *label)
{
	struct nfs3_diropargs	arg = {
		.fh		= NFS_FH(dir),
		.name		= name->name,
		.len		= name->len
	};
	struct nfs3_diropres	res = {
		.fh		= fhandle,
		.fattr		= fattr
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs3_procedures[NFS3PROC_LOOKUP],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
	};
	int			status;

	dprintk("NFS call  lookup %s\n", name->name);
	res.dir_attr = nfs_alloc_fattr();
	if (res.dir_attr == NULL)
		return -ENOMEM;

	nfs_fattr_init(fattr);
	status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	nfs_refresh_inode(dir, res.dir_attr);
	if (status >= 0 && !(fattr->valid & NFS_ATTR_FATTR)) {
		msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR];
		msg.rpc_argp = fhandle;
		msg.rpc_resp = fattr;
		status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0);
	}
	nfs_free_fattr(res.dir_attr);
	dprintk("NFS reply lookup: %d\n", status);
	return status;
}

static int nfs3_proc_access(struct inode *inode, struct nfs_access_entry *entry)
{
	struct nfs3_accessargs	arg = {
		.fh		= NFS_FH(inode),
	};
	struct nfs3_accessres	res;
	struct rpc_message msg = {
		.rpc_proc	= &nfs3_procedures[NFS3PROC_ACCESS],
		.rpc_argp	= &arg,
		.rpc_resp	= &res,
		.rpc_cred	= entry->cred,
	};
	int mode = entry->mask;
	int status = -ENOMEM;

	dprintk("NFS call  access\n");

	if (mode & MAY_READ)
		arg.access |= NFS3_ACCESS_READ;
	if (S_ISDIR(inode->i_mode)) {
		if (mode & MAY_WRITE)
			arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE;
		if (mode & MAY_EXEC)
			arg.access |= NFS3_ACCESS_LOOKUP;
	} else {
		if (mode & MAY_WRITE)
			arg.access |= NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND;
		if (mode & MAY_EXEC)
			arg.access |= NFS3_ACCESS_EXECUTE;
	}

	res.fattr = nfs_alloc_fattr();
	if (res.fattr == NULL)
		goto out;

	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
	nfs_refresh_inode(inode, res.fattr);
	if (status == 0) {
		entry->mask = 0;
		if (res.access & NFS3_ACCESS_READ)
			entry->mask |= MAY_READ;
		if (res.access & (NFS3_ACCESS_MODIFY | NFS3_ACCESS_EXTEND | NFS3_ACCESS_DELETE))
			entry->mask |= MAY_WRITE;
		if (res.access & (NFS3_ACCESS_LOOKUP|NFS3_ACCESS_EXECUTE))
			entry->mask |= MAY_EXEC;
	}
	nfs_free_fattr(res.fattr);
out:
	dprintk("NFS reply access: %d\n", status);
	return status;
}

static int nfs3_proc_readlink(struct inode *inode, struct page *page,
		unsigned int pgbase, unsigned int pglen)
{
	struct nfs_fattr	*fattr;
	struct nfs3_readlinkargs args = {
		.fh		= NFS_FH(inode),
		.pgbase		= pgbase,
		.pglen		= pglen,
		.pages		= &page
	};
	struct rpc_message msg = {
		.rpc_proc	= &nfs3_procedures[NFS3PROC_READLINK],
		.rpc_argp	= &args,
	};
	int status = -ENOMEM;

	dprintk("NFS call  readlink\n");
	fattr = nfs_alloc_fattr();
	if (fattr == NULL)
		goto out;
	msg.rpc_resp = fattr;

	status = rpc_call_sync(NFS_CLIENT(inode), &msg, 0);
	nfs_refresh_inode(inode, fattr);
	nfs_free_fattr(fattr);
out:
	dprintk("NFS reply readlink: %d\n", status);
	return status;
}

struct nfs3_createdata {
	struct rpc_message msg;
	union {
		struct nfs3_createargs create;
		struct nfs3_mkdirargs mkdir;
		struct nfs3_symlinkargs symlink;
		struct nfs3_mknodargs mknod;
	} arg;
	struct nfs3_diropres res;
	struct nfs_fh fh;
	struct nfs_fattr fattr;
	struct nfs_fattr dir_attr;
};

static struct nfs3_createdata *nfs3_alloc_createdata(void)
{
	struct nfs3_createdata *data;

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (data != NULL) {
		data->msg.rpc_argp = &data->arg;
		data->msg.rpc_resp = &data->res;
		data->res.fh = &data->fh;
		data->res.fattr = &data->fattr;
		data->res.dir_attr = &data->dir_attr;
		nfs_fattr_init(data->res.fattr);
		nfs_fattr_init(data->res.dir_attr);
	}
	return data;
}

static int nfs3_do_create(struct inode *dir, struct dentry *dentry, struct nfs3_createdata *data)
{
	int status;

	status = rpc_call_sync(NFS_CLIENT(dir), &data->msg, 0);
	nfs_post_op_update_inode(dir, data->res.dir_attr);
	if (status == 0)
		status = nfs_instantiate(dentry, data->res.fh, data->res.fattr, NULL);
	return status;
}

static void nfs3_free_createdata(struct nfs3_createdata *data)
{
	kfree(data);
}
Exemple #15
0
ssize_t videobuf_read_one(struct videobuf_queue *q,
			  char __user *data, size_t count, loff_t *ppos,
			  int nonblocking)
{
	enum v4l2_field field;
	unsigned long flags = 0;
	unsigned size = 0, nbufs = 1;
	int retval;

	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);

	videobuf_queue_lock(q);

	q->ops->buf_setup(q, &nbufs, &size);

	if (NULL == q->read_buf  &&
	    count >= size        &&
	    !nonblocking) {
		retval = videobuf_read_zerocopy(q, data, count, ppos);
		if (retval >= 0  ||  retval == -EIO)
			/* ok, all done */
			goto done;
		/* fallback to kernel bounce buffer on failures */
	}

	if (NULL == q->read_buf) {
		/* need to capture a new frame */
		retval = -ENOMEM;
		q->read_buf = videobuf_alloc_vb(q);

		dprintk(1, "video alloc=0x%p\n", q->read_buf);
		if (NULL == q->read_buf)
			goto done;
		q->read_buf->memory = V4L2_MEMORY_USERPTR;
		q->read_buf->bsize = count; /* preferred size */
		field = videobuf_next_field(q);
		retval = q->ops->buf_prepare(q, q->read_buf, field);

		if (0 != retval) {
			kfree(q->read_buf);
			q->read_buf = NULL;
			goto done;
		}

		spin_lock_irqsave(q->irqlock, flags);
		q->ops->buf_queue(q, q->read_buf);
		spin_unlock_irqrestore(q->irqlock, flags);

		q->read_off = 0;
	}

	/* wait until capture is done */
	retval = videobuf_waiton(q, q->read_buf, nonblocking, 1);
	if (0 != retval)
		goto done;

	CALL(q, sync, q, q->read_buf);

	if (VIDEOBUF_ERROR == q->read_buf->state) {
		/* catch I/O errors */
		q->ops->buf_release(q, q->read_buf);
		kfree(q->read_buf);
		q->read_buf = NULL;
		retval = -EIO;
		goto done;
	}

	/* Copy to userspace */
	retval = __videobuf_copy_to_user(q, q->read_buf, data, count, nonblocking);
	if (retval < 0)
		goto done;

	q->read_off += retval;
	if (q->read_off == q->read_buf->size) {
		/* all data copied, cleanup */
		q->ops->buf_release(q, q->read_buf);
		kfree(q->read_buf);
		q->read_buf = NULL;
	}

done:
	videobuf_queue_unlock(q);
	return retval;
}
Exemple #16
0
/*
 * Process the RPC request.
 */
int
svc_process(struct svc_serv *serv, struct svc_rqst *rqstp)
{
	struct svc_program	*progp;
	struct svc_version	*versp = NULL;	/* compiler food */
	struct svc_procedure	*procp = NULL;
	struct svc_buf *	argp = &rqstp->rq_argbuf;
	struct svc_buf *	resp = &rqstp->rq_resbuf;
	kxdrproc_t		xdr;
	u32			*bufp, *statp;
	u32			dir, prog, vers, proc,
				auth_stat, rpc_stat;

	rpc_stat = rpc_success;
	bufp = argp->buf;

	if (argp->len < 5)
		goto err_short_len;

	dir  = ntohl(*bufp++);
	vers = ntohl(*bufp++);

	/* First words of reply: */
	svc_putlong(resp, xdr_one);		/* REPLY */
	svc_putlong(resp, xdr_zero);		/* ACCEPT */

	if (dir != 0)		/* direction != CALL */
		goto err_bad_dir;
	if (vers != 2)		/* RPC version number */
		goto err_bad_rpc;

	rqstp->rq_prog = prog = ntohl(*bufp++);	/* program number */
	rqstp->rq_vers = vers = ntohl(*bufp++);	/* version number */
	rqstp->rq_proc = proc = ntohl(*bufp++);	/* procedure number */

	argp->buf += 5;
	argp->len -= 5;

	/* Used by nfsd to only allow the NULL procedure for amd. */
	if (rqstp->rq_auth && !rqstp->rq_client && proc) {
		auth_stat = rpc_autherr_badcred;
		goto err_bad_auth;
	}

	/*
	 * Decode auth data, and add verifier to reply buffer.
	 * We do this before anything else in order to get a decent
	 * auth verifier.
	 */
	svc_authenticate(rqstp, &rpc_stat, &auth_stat);

	if (rpc_stat != rpc_success)
		goto err_garbage;

	if (auth_stat != rpc_auth_ok)
		goto err_bad_auth;

	progp = serv->sv_program;
	if (prog != progp->pg_prog)
		goto err_bad_prog;

	versp = progp->pg_vers[vers];
	if (!versp || vers >= progp->pg_nvers)
		goto err_bad_vers;

	procp = versp->vs_proc + proc;
	if (proc >= versp->vs_nproc || !procp->pc_func)
		goto err_bad_proc;
	rqstp->rq_server   = serv;
	rqstp->rq_procinfo = procp;

	/* Syntactic check complete */
	serv->sv_stats->rpccnt++;

	/* Build the reply header. */
	statp = resp->buf;
	svc_putlong(resp, rpc_success);		/* RPC_SUCCESS */

	/* Bump per-procedure stats counter */
	procp->pc_count++;

	/* Initialize storage for argp and resp */
	memset(rqstp->rq_argp, 0, procp->pc_argsize);
	memset(rqstp->rq_resp, 0, procp->pc_ressize);

	/* Call the function that processes the request. */
	if (!versp->vs_dispatch) {
		/* Decode arguments */
		xdr = procp->pc_decode;
		if (xdr && !xdr(rqstp, rqstp->rq_argbuf.buf, rqstp->rq_argp))
			goto err_garbage;

		*statp = procp->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp);

		/* Encode reply */
		if (*statp == rpc_success && (xdr = procp->pc_encode)
		 && !xdr(rqstp, rqstp->rq_resbuf.buf, rqstp->rq_resp)) {
			dprintk("svc: failed to encode reply\n");
			/* serv->sv_stats->rpcsystemerr++; */
			*statp = rpc_system_err;
		}
	} else {
		dprintk("svc: calling dispatcher\n");
		if (!versp->vs_dispatch(rqstp, statp))
			goto dropit;
	}

	/* Check RPC status result */
	if (*statp != rpc_success)
		resp->len = statp + 1 - resp->base;

	/* Release reply info */
	if (procp->pc_release)
		procp->pc_release(rqstp, NULL, rqstp->rq_resp);

	if (procp->pc_encode == NULL)
		goto dropit;
sendit:
	return svc_send(rqstp);

dropit:
	dprintk("svc: svc_process dropit\n");
	svc_drop(rqstp);
	return 0;

err_short_len:
#ifdef RPC_PARANOIA
	printk("svc: short len %d, dropping request\n", argp->len);
#endif
	goto dropit;			/* drop request */

err_bad_dir:
#ifdef RPC_PARANOIA
	printk("svc: bad direction %d, dropping request\n", dir);
#endif
	serv->sv_stats->rpcbadfmt++;
	goto dropit;			/* drop request */

err_bad_rpc:
	serv->sv_stats->rpcbadfmt++;
	resp->buf[-1] = xdr_one;	/* REJECT */
	svc_putlong(resp, xdr_zero);	/* RPC_MISMATCH */
	svc_putlong(resp, xdr_two);	/* Only RPCv2 supported */
	svc_putlong(resp, xdr_two);
	goto sendit;

err_bad_auth:
	dprintk("svc: authentication failed (%d)\n", ntohl(auth_stat));
	serv->sv_stats->rpcbadauth++;
	resp->buf[-1] = xdr_one;	/* REJECT */
	svc_putlong(resp, xdr_one);	/* AUTH_ERROR */
	svc_putlong(resp, auth_stat);	/* status */
	goto sendit;

err_bad_prog:
#ifdef RPC_PARANOIA
	printk("svc: unknown program %d (me %d)\n", prog, progp->pg_prog);
#endif
	serv->sv_stats->rpcbadfmt++;
	svc_putlong(resp, rpc_prog_unavail);
	goto sendit;

err_bad_vers:
#ifdef RPC_PARANOIA
	printk("svc: unknown version (%d)\n", vers);
#endif
	serv->sv_stats->rpcbadfmt++;
	svc_putlong(resp, rpc_prog_mismatch);
	svc_putlong(resp, htonl(progp->pg_lovers));
	svc_putlong(resp, htonl(progp->pg_hivers));
	goto sendit;

err_bad_proc:
#ifdef RPC_PARANOIA
	printk("svc: unknown procedure (%d)\n", proc);
#endif
	serv->sv_stats->rpcbadfmt++;
	svc_putlong(resp, rpc_proc_unavail);
	goto sendit;

err_garbage:
#ifdef RPC_PARANOIA
	printk("svc: failed to decode args\n");
#endif
	serv->sv_stats->rpcbadfmt++;
	svc_putlong(resp, rpc_garbage_args);
	goto sendit;
}
Exemple #17
0
int mantis_dvb_init(struct mantis_pci *mantis)
{
	struct mantis_hwconfig *config = mantis->hwconfig;
	int result = -1;

	dprintk(MANTIS_DEBUG, 1, "dvb_register_adapter");

	result = dvb_register_adapter(&mantis->dvb_adapter,
				      "Mantis DVB adapter",
				      THIS_MODULE,
				      &mantis->pdev->dev,
				      adapter_nr);

	if (result < 0) {

		dprintk(MANTIS_ERROR, 1, "Error registering adapter");
		return -ENODEV;
	}

	mantis->dvb_adapter.priv	= mantis;
	mantis->demux.dmx.capabilities	= DMX_TS_FILTERING	|
					 DMX_SECTION_FILTERING	|
					 DMX_MEMORY_BASED_FILTERING;

	mantis->demux.priv		= mantis;
	mantis->demux.filternum		= 256;
	mantis->demux.feednum		= 256;
	mantis->demux.start_feed	= mantis_dvb_start_feed;
	mantis->demux.stop_feed		= mantis_dvb_stop_feed;
	mantis->demux.write_to_decoder	= NULL;

	dprintk(MANTIS_DEBUG, 1, "dvb_dmx_init");
	result = dvb_dmx_init(&mantis->demux);
	if (result < 0) {
		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);

		goto err0;
	}

	mantis->dmxdev.filternum	= 256;
	mantis->dmxdev.demux		= &mantis->demux.dmx;
	mantis->dmxdev.capabilities	= 0;
	dprintk(MANTIS_DEBUG, 1, "dvb_dmxdev_init");

	result = dvb_dmxdev_init(&mantis->dmxdev, &mantis->dvb_adapter);
	if (result < 0) {

		dprintk(MANTIS_ERROR, 1, "dvb_dmxdev_init failed, ERROR=%d", result);
		goto err1;
	}

	mantis->fe_hw.source		= DMX_FRONTEND_0;
	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_hw);
	if (result < 0) {

		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
		goto err2;
	}

	mantis->fe_mem.source		= DMX_MEMORY_FE;
	result = mantis->demux.dmx.add_frontend(&mantis->demux.dmx, &mantis->fe_mem);
	if (result < 0) {
		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
		goto err3;
	}

	result = mantis->demux.dmx.connect_frontend(&mantis->demux.dmx, &mantis->fe_hw);
	if (result < 0) {
		dprintk(MANTIS_ERROR, 1, "dvb_dmx_init failed, ERROR=%d", result);
		goto err4;
	}

	dvb_net_init(&mantis->dvb_adapter, &mantis->dvbnet, &mantis->demux.dmx);
	tasklet_init(&mantis->tasklet, mantis_dma_xfer, (unsigned long) mantis);
	tasklet_disable(&mantis->tasklet);
	if (mantis->hwconfig) {
		result = config->frontend_init(mantis, mantis->fe);
		if (result < 0) {
			dprintk(MANTIS_ERROR, 1, "!!! NO Frontends found !!!");
			goto err5;
		} else {
			if (mantis->fe == NULL) {
				result = -ENOMEM;
				dprintk(MANTIS_ERROR, 1, "FE <NULL>");
				goto err5;
			}
			result = dvb_register_frontend(&mantis->dvb_adapter, mantis->fe);
			if (result) {
				dprintk(MANTIS_ERROR, 1, "ERROR: Frontend registration failed");

				if (mantis->fe->ops.release)
					mantis->fe->ops.release(mantis->fe);

				mantis->fe = NULL;
				goto err5;
			}
		}
	}

	return 0;

	/* Error conditions ..	*/
err5:
	tasklet_kill(&mantis->tasklet);
	dvb_net_release(&mantis->dvbnet);
	if (mantis->fe) {
		dvb_unregister_frontend(mantis->fe);
		dvb_frontend_detach(mantis->fe);
	}
err4:
	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);

err3:
	mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_hw);

err2:
	dvb_dmxdev_release(&mantis->dmxdev);

err1:
	dvb_dmx_release(&mantis->demux);

err0:
	dvb_unregister_adapter(&mantis->dvb_adapter);

	return result;
}
Exemple #18
0
static s32 detect_a2_a2m_eiaj(struct cx88_core *core, s16 x[], u32 N)
{
	s32 carrier, stereo, dual, noise;
	s32 carrier_freq, stereo_freq, dual_freq;
	s32 ret;

	switch (core->tvaudio) {
	case WW_BG:
	case WW_DK:
		carrier_freq = FREQ_A2_CARRIER;
		stereo_freq = FREQ_A2_STEREO;
		dual_freq = FREQ_A2_DUAL;
		break;
	case WW_M:
		carrier_freq = FREQ_A2M_CARRIER;
		stereo_freq = FREQ_A2M_STEREO;
		dual_freq = FREQ_A2M_DUAL;
		break;
	case WW_EIAJ:
		carrier_freq = FREQ_EIAJ_CARRIER;
		stereo_freq = FREQ_EIAJ_STEREO;
		dual_freq = FREQ_EIAJ_DUAL;
		break;
	default:
		printk(KERN_WARNING "%s/0: unsupported audio mode %d for %s\n",
		       core->name, core->tvaudio, __func__);
		return UNSET;
	}

	carrier = freq_magnitude(x, N, carrier_freq);
	stereo  = freq_magnitude(x, N, stereo_freq);
	dual    = freq_magnitude(x, N, dual_freq);
	noise   = noise_magnitude(x, N, FREQ_NOISE_START, FREQ_NOISE_END);

	dprintk(1, "detect a2/a2m/eiaj: carrier=%d, stereo=%d, dual=%d, "
		   "noise=%d\n", carrier, stereo, dual, noise);

	if (stereo > dual)
		ret = V4L2_TUNER_SUB_STEREO;
	else
		ret = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2;

	if (core->tvaudio == WW_EIAJ) {
		/* EIAJ checks may need adjustments */
		if ((carrier > max(stereo, dual)*2) &&
		    (carrier < max(stereo, dual)*6) &&
		    (carrier > 20 && carrier < 200) &&
		    (max(stereo, dual) > min(stereo, dual))) {
			/* For EIAJ the carrier is always present,
			   so we probably don't need noise detection */
			return ret;
		}
	} else {
		if ((carrier > max(stereo, dual)*2) &&
		    (carrier < max(stereo, dual)*8) &&
		    (carrier > 20 && carrier < 200) &&
		    (noise < 10) &&
		    (max(stereo, dual) > min(stereo, dual)*2)) {
			return ret;
		}
	}
	return V4L2_TUNER_SUB_MONO;
}
Exemple #19
0
static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
{
	dprintk("nfs: %s: prematurely hit end of receive buffer. "
		"Remaining buffer length is %tu words.\n",
		func, xdr->end - xdr->p);
}
Exemple #20
0
static void
rtl8169_hw_start(struct net_device *dev)
{
    struct rtl8169_private *tp = dev->priv;
    void *ioaddr = tp->mmio_addr;
    u32 i;

    /* Soft reset the chip. */
    RTL_W8(ChipCmd, CmdReset);

    /* Check that the chip has finished the reset. */
    for (i = 1000; i > 0; i--) {
        if ((RTL_R8(ChipCmd) & CmdReset) == 0)
            break;
        else
            udelay(10);
    }

    RTL_W8(Cfg9346, Cfg9346_Unlock);
    RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
    RTL_W8(EarlyTxThres, EarlyTxThld);

    // For gigabit rtl8169
    RTL_W16(RxMaxSize, RxPacketMaxSize);

    // Set Rx Config register
    i = rtl8169_rx_config | (RTL_R32(RxConfig) & rtl_chip_info[tp->chipset].
                             RxConfigMask);
    RTL_W32(RxConfig, i);

    /* Set DMA burst size and Interframe Gap Time */
    RTL_W32(TxConfig,
            (TX_DMA_BURST << TxDMAShift) | (InterFrameGap <<
                                            TxInterFrameGapShift));
    tp->cp_cmd |= RTL_R16(CPlusCmd);
    RTL_W16(CPlusCmd, tp->cp_cmd);

    if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
        dprintk(KERN_INFO PFX "Set MAC Reg C+CR Offset 0xE0: bit-3 and bit-14 MUST be 1\n");
        tp->cp_cmd |= (1 << 14) | PCIMulRW;
        RTL_W16(CPlusCmd, tp->cp_cmd);
    }

    tp->cur_rx = 0;

    RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_32BIT_MASK));
    RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32));
    RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_32BIT_MASK));
    RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32));
    RTL_W8(Cfg9346, Cfg9346_Lock);
    udelay(10);

    RTL_W32(RxMissed, 0);

    rtl8169_set_rx_mode(dev);

    /* no early-rx interrupts */
    RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);

    /* Enable all known interrupts by setting the interrupt mask. */
    RTL_W16(IntrMask, rtl8169_intr_mask);

    netif_start_queue(dev);

}
Exemple #21
0
static U32 PDrvCryptoUpdateDESWithDMA(PUBLIC_CRYPTO_DES_DES3_CONTEXT * pDesCtx,
                        U8 * pSrc, U8 * pDest, U32 nbBlocks, U32 dmaUse)
{
   /*
    * Note: The DMA only sees physical addresses !
    */

   U32 bufIn_phys = virt_to_phys(pSrc);
   U32 bufOut_phys = virt_to_phys(pDest);

   U32 dma_ch0 = OMAP3430_SMC_DMA_CH_0;
   U32 dma_ch1 = OMAP3430_SMC_DMA_CH_1;
   SCX_DMA_CHANNEL_PARAM ch0_parameters;
   SCX_DMA_CHANNEL_PARAM ch1_parameters;
   U32 nLength = nbBlocks * DES_BLOCK_SIZE;
   U32 returnCode;

   dprintk(KERN_INFO "PDrvCryptoUpdateDESWithDMA: Use=%u, Len=%u, In=0x%08x, Out=0x%08x\n",
               (unsigned int)dmaUse, (unsigned int)nLength, (unsigned int)bufIn_phys, (unsigned int)bufOut_phys);

	if (nLength == 0) {
       /* No need of setting the dma and crypto-processor */
      dprintk(KERN_INFO "PDrvCryptoUpdateDESWithDMA: Nothing to process\n");
      return PUBLIC_CRYPTO_OPERATION_SUCCESS;
   }

	if ((bufIn_phys == 0) || (bufOut_phys == 0)) {
       dprintk(KERN_ERR "PDrvCryptoUpdateDESWithDMA: bufIn_phys/bufOut_phys NULL\n");
       return PUBLIC_CRYPTO_ERR_BAD_PARAMETERS;
   }

   /* Makes sure buffers are 4-bytes aligned */
	if (!IS_4_BYTES_ALIGNED((int)bufIn_phys) || !IS_4_BYTES_ALIGNED((int)bufOut_phys)) {
      dprintk(KERN_ERR "PDrvCryptoUpdateDESWithDMA: bufIn_phys/Out not 4 bytes aligned\n");
      return PUBLIC_CRYPTO_ERR_ALIGNMENT;
   }

   /*
    * Only one segment of the sg list to proceed --> no need of scatter gather algo
    */

   /* Makes sure that if the dma channels that will need to be used are currently active,
   one can reprogram it (them)  */
   scxPublicDMADisableChannel(dma_ch0);
   scxPublicDMADisableChannel(dma_ch1);

	if (dmaUse == PUBLIC_CRYPTO_DMA_USE_IRQ) {
      /* Reset DMA int (DMA CTRL) - The DMA int (INT CTRL) is reset by the OS */
      scxPublicDMADisableL3IRQ();
      scxPublicDMAClearL3IRQ();
   }

   /* DMA used for Input and Output */
   OUTREG32(&g_pDESReg_t->DES_MASK,
            INREG32(&g_pDESReg_t->DES_MASK)
            | DES_MASK_DMA_REQ_OUT_EN_BIT
            | DES_MASK_DMA_REQ_IN_EN_BIT);

   /* DMA1: Mem -> DES */
   ch0_parameters.data_type =   DMA_CSDP_Srce_Endian_little
      | DMA_CSDP_Srce_Endian_Lock_off
      | DMA_CSDP_Dest_Endian_little
      | DMA_CSDP_Dest_Endian_Lock_off
      | DMA_CSDP_Write_Mode_none_posted
      | DMA_CSDP_Dest_Burst_off
      | DMA_CSDP_Dest_packed_off
      | DMA_CSDP_WR_Add_Trslt
      | DMA_CSDP_Src_Burst_off
      | DMA_CSDP_Src_packed_off
      | DMA_CSDP_RD_Add_Trslt
      | DMA_CSDP_Data_32b;
   ch0_parameters.elem_count = DMA_CEN_Elts_per_Frame_DES;

   ch0_parameters.frame_count = nbBlocks;

   ch0_parameters.src_amode = 1; /* post increment */
   ch0_parameters.src_start = bufIn_phys;
   ch0_parameters.src_ei = DMA_CSEI_Default;
   ch0_parameters.src_fi = DMA_CSFI_Default;

   ch0_parameters.dst_amode = 0; /* const */
   ch0_parameters.dst_start = DES1_REGS_HW_ADDR + 0x24;
   ch0_parameters.dst_ei = DMA_CDEI_Default;
   ch0_parameters.dst_fi = DMA_CDFI_Default; /* source frame index */

   ch0_parameters.trigger = DMA_CCR_Mask_Channel(DMA_CCR_Channel_Mem2DES);
   ch0_parameters.sync_mode = 0x2; /* FS =1, BS=0 => An entire frame is
                                      transferred once a DMA request is made */
   ch0_parameters.src_or_dst_synch = 0; /* Transfert is triggered by the Dest */

   dprintk(KERN_INFO "PDrvCryptoUpdateDESWithDMA: scxPublicDMASetParams(ch0)\n");
   scxPublicDMASetParams(dma_ch0, &ch0_parameters);

   dprintk(KERN_INFO "PDrvCryptoUpdateDESWithDMA: Start DMA channel %d\n", (unsigned int)dma_ch0);

   scxPublicDMAStart(dma_ch0, OMAP_DMA_DROP_IRQ);

   /* DMA2: DES -> Mem */
   ch1_parameters.data_type =   DMA_CSDP_Srce_Endian_little
      | DMA_CSDP_Srce_Endian_Lock_off
      | DMA_CSDP_Dest_Endian_little
      | DMA_CSDP_Dest_Endian_Lock_off
      | DMA_CSDP_Write_Mode_none_posted
      | DMA_CSDP_Dest_Burst_off
      | DMA_CSDP_Dest_packed_off
      | DMA_CSDP_WR_Add_Trslt
      | DMA_CSDP_Src_Burst_off
      | DMA_CSDP_Src_packed_off
      | DMA_CSDP_RD_Add_Trslt
      | DMA_CSDP_Data_32b;
   ch1_parameters.elem_count = DMA_CEN_Elts_per_Frame_DES;
   ch1_parameters.frame_count = nbBlocks;

   ch1_parameters.src_amode = 0; /* const */
   ch1_parameters.src_start = DES1_REGS_HW_ADDR + 0x24;
   ch1_parameters.src_ei = DMA_CSEI_Default;
   ch1_parameters.src_fi = DMA_CSFI_Default;

   ch1_parameters.dst_amode = 1; /* post increment */
   ch1_parameters.dst_start =  bufOut_phys;
   ch1_parameters.dst_ei = DMA_CDEI_Default;
   ch1_parameters.dst_fi = DMA_CDFI_Default; /* source frame index */

   ch1_parameters.trigger = DMA_CCR_Mask_Channel(DMA_CCR_Channel_DES2Mem);
   ch1_parameters.sync_mode = 0x2; /* FS =1, BS=0 => An entire frame is
              transferred once a DMA request is made */
   ch1_parameters.src_or_dst_synch = 1; /* Transfert is triggered by the Src */

   dprintk(KERN_INFO "PDrvCryptoUpdateDESWithDMA: scxPublicDMASetParams(ch1)\n");
   scxPublicDMASetParams(dma_ch1, &ch1_parameters);

	if (dmaUse == PUBLIC_CRYPTO_DMA_USE_IRQ) {
      scxPublicDMAEnableL3IRQ();
   }

   dprintk(KERN_INFO "PDrvCryptoUpdateDESWithDMA: Start DMA channel %d\n", (unsigned int)dma_ch1);
   scxPublicDMAStart(dma_ch1, OMAP_DMA_DROP_IRQ|OMAP_DMA_BLOCK_IRQ);

   /*
    * The input data may be in the cache only,
    * and the DMA is only working with physical addresses.
    * So flush the cache to have data coherency.
    */
   v7_dma_flush_range((u32)pSrc, (u32)(pSrc + nLength));

   /* Start operation */
   OUTREG32(&g_pDESReg_t->DES_MASK,
            INREG32(&g_pDESReg_t->DES_MASK)|DES_MASK_START_BIT);

	if (dmaUse == PUBLIC_CRYPTO_DMA_USE_IRQ) {
      /* Suspends the process until the DMA IRQ occurs */
      dprintk(KERN_INFO "PDrvCryptoUpdateDESWithDMA: Waiting for IRQ\n");
      returnCode = scxPublicDMAWait();
	} else {
      dprintk(KERN_INFO "PDrvCryptoUpdateDESWithDMA: Polling DMA\n");
      returnCode = scxPublicDMAPoll(dma_ch1);
   }

	if (returnCode != PUBLIC_CRYPTO_OPERATION_SUCCESS) {
      dprintk(KERN_ERR "PDrvCryptoUpdateDESWithDMA: Timeout\n");
      /* Do not exit function but clear properly the operation */
   }

	if (dmaUse == PUBLIC_CRYPTO_DMA_USE_IRQ) {
      /* Acknoledge DMA interrupt */
      scxPublicDMADisableL3IRQ();
   }

   scxPublicDMAClearChannel(dma_ch1);

   /*
    * The dma transfert is complete
    */

   /* Stop clocks */
   OUTREG32(&g_pDESReg_t->DES_MASK,
            INREG32(&g_pDESReg_t->DES_MASK)
            &(~DES_MASK_START_BIT) );

   /* Unset DMA synchronisation requests */
   OUTREG32(&g_pDESReg_t->DES_MASK,
            INREG32(&g_pDESReg_t->DES_MASK)
            & (~DES_MASK_DMA_REQ_OUT_EN_BIT)
            & (~DES_MASK_DMA_REQ_IN_EN_BIT));

	if (returnCode != PUBLIC_CRYPTO_OPERATION_SUCCESS) {
      dprintk(KERN_INFO "PDrvCryptoUpdateDESWithDMA: Error [0x%08x]\n", (unsigned int)returnCode);
      return returnCode;
   }

   /*
    * The output data are in the physical memory.
    * So invalidate the cache to have data coherency.
    */
   v7_dma_inv_range((u32)pDest, (u32)(pDest + nLength));

   dprintk(KERN_INFO "PDrvCryptoUpdateDESWithDMA: Success\n");

   return PUBLIC_CRYPTO_OPERATION_SUCCESS;
}
Exemple #22
0
static void rtl8169_hw_phy_config(struct net_device *dev)
{
    struct rtl8169_private *tp = dev->priv;
    void *ioaddr = tp->mmio_addr;
    struct {
        u16 regs[5]; /* Beware of bit-sign propagation */
    } phy_magic[5] = { {
            {   0x0000,	//w 4 15 12 0
                0x00a1,	//w 3 15 0 00a1
                0x0008,	//w 2 15 0 0008
                0x1020,	//w 1 15 0 1020
                0x1000
            }
        },{	//w 0 15 0 1000
            {   0x7000,	//w 4 15 12 7
                0xff41,	//w 3 15 0 ff41
                0xde60,	//w 2 15 0 de60
                0x0140,	//w 1 15 0 0140
                0x0077
            }
        },{	//w 0 15 0 0077
            {   0xa000,	//w 4 15 12 a
                0xdf01,	//w 3 15 0 df01
                0xdf20,	//w 2 15 0 df20
                0xff95,	//w 1 15 0 ff95
                0xfa00
            }
        },{	//w 0 15 0 fa00
            {   0xb000,	//w 4 15 12 b
                0xff41,	//w 3 15 0 ff41
                0xde20,	//w 2 15 0 de20
                0x0140,	//w 1 15 0 0140
                0x00bb
            }
        },{	//w 0 15 0 00bb
            {   0xf000,	//w 4 15 12 f
                0xdf01,	//w 3 15 0 df01
                0xdf20,	//w 2 15 0 df20
                0xff95,	//w 1 15 0 ff95
                0xbf00
            }	//w 0 15 0 bf00
        }
    }, *p = phy_magic;
    int i;

    rtl8169_print_mac_version(tp);
    rtl8169_print_phy_version(tp);

    if (tp->mac_version <= RTL_GIGA_MAC_VER_B)
        return;
    if (tp->phy_version >= RTL_GIGA_PHY_VER_F)
        return;

    dprintk("MAC version != 0 && PHY version == 0 or 1\n");
    dprintk("Do final_reg2.cfg\n");

    /* Shazam ! */

    // phy config for RTL8169s mac_version C chip
    mdio_write(ioaddr, 31, 0x0001);			//w 31 2 0 1
    mdio_write(ioaddr, 21, 0x1000);			//w 21 15 0 1000
    mdio_write(ioaddr, 24, 0x65c7);			//w 24 15 0 65c7
    rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0);	//w 4 11 11 0

    for (i = 0; i < ARRAY_SIZE(phy_magic); i++, p++) {
        int val, pos = 4;

        val = (mdio_read(ioaddr, pos) & 0x0fff) | (p->regs[0] & 0xffff);
        mdio_write(ioaddr, pos, val);
        while (--pos >= 0)
            mdio_write(ioaddr, pos, p->regs[4 - pos] & 0xffff);
        rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 1); //w 4 11 11 1
        rtl8169_write_gmii_reg_bit(ioaddr, 4, 11, 0); //w 4 11 11 0
    }
    mdio_write(ioaddr, 31, 0x0000); //w 31 2 0 0
}
void cpufreq_frequency_table_put_attr(unsigned int cpu)
{
	dprintk("clearing show_table for cpu %u\n", cpu);
	show_table[cpu] = NULL;
}
Exemple #24
0
static int __devinit
rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
{
    struct net_device *dev = NULL;
    struct rtl8169_private *tp = NULL;
    void *ioaddr = NULL;
    static int board_idx = -1;
    static int printed_version = 0;
    int i, rc;
    int option = -1, Cap10_100 = 0, Cap1000 = 0;

    assert(pdev != NULL);
    assert(ent != NULL);

    board_idx++;

    if (!printed_version) {
        printk(KERN_INFO RTL8169_DRIVER_NAME " loaded\n");
        printed_version = 1;
    }

    rc = rtl8169_init_board(pdev, &dev, &ioaddr);
    if (rc)
        return rc;

    tp = dev->priv;
    assert(ioaddr != NULL);
    assert(dev != NULL);
    assert(tp != NULL);

    // Get MAC address.  FIXME: read EEPROM
    for (i = 0; i < MAC_ADDR_LEN; i++)
        dev->dev_addr[i] = RTL_R8(MAC0 + i);

    dev->open = rtl8169_open;
    dev->hard_start_xmit = rtl8169_start_xmit;
    dev->get_stats = rtl8169_get_stats;
    dev->ethtool_ops = &rtl8169_ethtool_ops;
    dev->stop = rtl8169_close;
    dev->tx_timeout = rtl8169_tx_timeout;
    dev->set_multicast_list = rtl8169_set_rx_mode;
    dev->watchdog_timeo = RTL8169_TX_TIMEOUT;
    dev->irq = pdev->irq;
    dev->base_addr = (unsigned long) ioaddr;
//      dev->do_ioctl           = mii_ioctl;

    tp = dev->priv;		// private data //
    tp->pci_dev = pdev;
    tp->mmio_addr = ioaddr;

    spin_lock_init(&tp->lock);

    rc = register_netdev(dev);
    if (rc) {
        iounmap(ioaddr);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
        free_netdev(dev);
        return rc;
    }

    printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n", dev->name,
           rtl_chip_info[tp->chipset].name);

    pci_set_drvdata(pdev, dev);

    printk(KERN_INFO "%s: %s at 0x%lx, "
           "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
           "IRQ %d\n",
           dev->name,
           rtl_chip_info[ent->driver_data].name,
           dev->base_addr,
           dev->dev_addr[0], dev->dev_addr[1],
           dev->dev_addr[2], dev->dev_addr[3],
           dev->dev_addr[4], dev->dev_addr[5], dev->irq);

    rtl8169_hw_phy_config(dev);

    dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
    RTL_W8(0x82, 0x01);

    if (tp->mac_version < RTL_GIGA_MAC_VER_E) {
        dprintk("Set PCI Latency=0x40\n");
        pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x40);
    }

    if (tp->mac_version == RTL_GIGA_MAC_VER_D) {
        dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n");
        RTL_W8(0x82, 0x01);
        dprintk("Set PHY Reg 0x0bh = 0x00h\n");
        mdio_write(ioaddr, 0x0b, 0x0000); //w 0x0b 15 0 0
    }

    // if TBI is not endbled
    if (!(RTL_R8(PHYstatus) & TBI_Enable)) {
        int val = mdio_read(ioaddr, PHY_AUTO_NEGO_REG);

        option = (board_idx >= MAX_UNITS) ? 0 : media[board_idx];
        // Force RTL8169 in 10/100/1000 Full/Half mode.
        if (option > 0) {
            printk(KERN_INFO "%s: Force-mode Enabled.\n",
                   dev->name);
            Cap10_100 = 0, Cap1000 = 0;
            switch (option) {
            case _10_Half:
                Cap10_100 = PHY_Cap_10_Half_Or_Less;
                Cap1000 = PHY_Cap_Null;
                break;
            case _10_Full:
                Cap10_100 = PHY_Cap_10_Full_Or_Less;
                Cap1000 = PHY_Cap_Null;
                break;
            case _100_Half:
                Cap10_100 = PHY_Cap_100_Half_Or_Less;
                Cap1000 = PHY_Cap_Null;
                break;
            case _100_Full:
                Cap10_100 = PHY_Cap_100_Full_Or_Less;
                Cap1000 = PHY_Cap_Null;
                break;
            case _1000_Full:
                Cap10_100 = PHY_Cap_100_Full_Or_Less;
                Cap1000 = PHY_Cap_1000_Full;
                break;
            default:
                break;
            }
            mdio_write(ioaddr, PHY_AUTO_NEGO_REG, Cap10_100 | (val & 0x1F));	//leave PHY_AUTO_NEGO_REG bit4:0 unchanged
            mdio_write(ioaddr, PHY_1000_CTRL_REG, Cap1000);
        } else {
            printk(KERN_INFO "%s: Auto-negotiation Enabled.\n",
                   dev->name);

            // enable 10/100 Full/Half Mode, leave PHY_AUTO_NEGO_REG bit4:0 unchanged
            mdio_write(ioaddr, PHY_AUTO_NEGO_REG,
                       PHY_Cap_100_Full_Or_Less | (val & 0x1f));

            // enable 1000 Full Mode
            mdio_write(ioaddr, PHY_1000_CTRL_REG,
                       PHY_Cap_1000_Full);

        }

        // Enable auto-negotiation and restart auto-nigotiation
        mdio_write(ioaddr, PHY_CTRL_REG,
                   PHY_Enable_Auto_Nego | PHY_Restart_Auto_Nego);
        udelay(100);

        // wait for auto-negotiation process
        for (i = 10000; i > 0; i--) {
            //check if auto-negotiation complete
            if (mdio_read(ioaddr, PHY_STAT_REG) &
                    PHY_Auto_Neco_Comp) {
                udelay(100);
                option = RTL_R8(PHYstatus);
                if (option & _1000bpsF) {
                    printk(KERN_INFO
                           "%s: 1000Mbps Full-duplex operation.\n",
                           dev->name);
                } else {
                    printk(KERN_INFO
                           "%s: %sMbps %s-duplex operation.\n",
                           dev->name,
                           (option & _100bps) ? "100" :
                           "10",
                           (option & FullDup) ? "Full" :
                           "Half");
                }
                break;
            } else {
                udelay(100);
            }
        }		// end for-loop to wait for auto-negotiation process

    } else {
        udelay(100);
        printk(KERN_INFO
               "%s: 1000Mbps Full-duplex operation, TBI Link %s!\n",
               dev->name,
               (RTL_R32(TBICSR) & TBILinkOK) ? "OK" : "Failed");

    }

    return 0;
}
Exemple #25
0
/*
 * There is no protocol support for leases, so we have no way to implement
 * them correctly in the face of opens by other clients.
 */
int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
{
	dprintk("NFS: setlease(%pD2, arg=%ld)\n", file, arg);
	return -EINVAL;
}
Exemple #26
0
ssize_t videobuf_read_stream(struct videobuf_queue *q,
			     char __user *data, size_t count, loff_t *ppos,
			     int vbihack, int nonblocking)
{
	int rc, retval;
	unsigned long flags = 0;

	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);

	dprintk(2, "%s\n", __func__);
	videobuf_queue_lock(q);
	retval = -EBUSY;
	if (q->streaming)
		goto done;
	if (!q->reading) {
		retval = __videobuf_read_start(q);
		if (retval < 0)
			goto done;
	}

	retval = 0;
	while (count > 0) {
		/* get / wait for data */
		if (NULL == q->read_buf) {
			q->read_buf = list_entry(q->stream.next,
						 struct videobuf_buffer,
						 stream);
			list_del(&q->read_buf->stream);
			q->read_off = 0;
		}
		rc = videobuf_waiton(q, q->read_buf, nonblocking, 1);
		if (rc < 0) {
			if (0 == retval)
				retval = rc;
			break;
		}

		if (q->read_buf->state == VIDEOBUF_DONE) {
			rc = __videobuf_copy_stream(q, q->read_buf, data + retval, count,
					retval, vbihack, nonblocking);
			if (rc < 0) {
				retval = rc;
				break;
			}
			retval      += rc;
			count       -= rc;
			q->read_off += rc;
		} else {
			/* some error */
			q->read_off = q->read_buf->size;
			if (0 == retval)
				retval = -EIO;
		}

		/* requeue buffer when done with copying */
		if (q->read_off == q->read_buf->size) {
			list_add_tail(&q->read_buf->stream,
				      &q->stream);
			spin_lock_irqsave(q->irqlock, flags);
			q->ops->buf_queue(q, q->read_buf);
			spin_unlock_irqrestore(q->irqlock, flags);
			q->read_buf = NULL;
		}
		if (retval < 0)
			break;
	}
static int dvb_register(struct cx23885_tsport *port)
{
	struct cx23885_dev *dev = port->dev;
	struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
	struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
	int mfe_shared = 0; /* bus not shared by default */
	int ret;

	/* Get the first frontend */
	fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
	if (!fe0)
		return -EINVAL;

	/* init struct videobuf_dvb */
	fe0->dvb.name = dev->name;

	/* multi-frontend gate control is undefined or defaults to fe0 */
	port->frontends.gate = 0;

	/* Sets the gate control callback to be used by i2c command calls */
	port->gate_ctrl = cx23885_dvb_gate_ctrl;

	/* init frontend */
	switch (dev->board) {
	case CX23885_BOARD_HAUPPAUGE_HVR1250:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
						&hauppauge_generic_config,
						&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(mt2131_attach, fe0->dvb.frontend,
				   &i2c_bus->i2c_adap,
				   &hauppauge_generic_tunerconfig, 0);
		}
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1270:
	case CX23885_BOARD_HAUPPAUGE_HVR1275:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
					       &hauppauge_lgdt3305_config,
					       &i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(tda18271_attach, fe0->dvb.frontend,
				   0x60, &dev->i2c_bus[1].i2c_adap,
				   &hauppauge_hvr127x_config);
		}
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1255:
	case CX23885_BOARD_HAUPPAUGE_HVR1255_22111:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
					       &hcw_s5h1411_config,
					       &i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(tda18271_attach, fe0->dvb.frontend,
				   0x60, &dev->i2c_bus[1].i2c_adap,
				   &hauppauge_tda18271_config);
		}

		tda18271_attach(&dev->ts1.analog_fe,
			0x60, &dev->i2c_bus[1].i2c_adap,
			&hauppauge_tda18271_config);

		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1800:
		i2c_bus = &dev->i2c_bus[0];
		switch (alt_tuner) {
		case 1:
			fe0->dvb.frontend =
				dvb_attach(s5h1409_attach,
					   &hauppauge_ezqam_config,
					   &i2c_bus->i2c_adap);
			if (fe0->dvb.frontend != NULL) {
				dvb_attach(tda829x_attach, fe0->dvb.frontend,
					   &dev->i2c_bus[1].i2c_adap, 0x42,
					   &tda829x_no_probe);
				dvb_attach(tda18271_attach, fe0->dvb.frontend,
					   0x60, &dev->i2c_bus[1].i2c_adap,
					   &hauppauge_tda18271_config);
			}
			break;
		case 0:
		default:
			fe0->dvb.frontend =
				dvb_attach(s5h1409_attach,
					   &hauppauge_generic_config,
					   &i2c_bus->i2c_adap);
			if (fe0->dvb.frontend != NULL)
				dvb_attach(mt2131_attach, fe0->dvb.frontend,
					   &i2c_bus->i2c_adap,
					   &hauppauge_generic_tunerconfig, 0);
			break;
		}
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
						&hauppauge_hvr1800lp_config,
						&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(mt2131_attach, fe0->dvb.frontend,
				   &i2c_bus->i2c_adap,
				   &hauppauge_generic_tunerconfig, 0);
		}
		break;
	case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
						&fusionhdtv_5_express,
						&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
				   &i2c_bus->i2c_adap, 0x61,
				   TUNER_LG_TDVS_H06XF);
		}
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
		i2c_bus = &dev->i2c_bus[1];
		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
						&hauppauge_hvr1500q_config,
						&dev->i2c_bus[0].i2c_adap);
		if (fe0->dvb.frontend != NULL)
			dvb_attach(xc5000_attach, fe0->dvb.frontend,
				   &i2c_bus->i2c_adap,
				   &hauppauge_hvr1500q_tunerconfig);
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1500:
		i2c_bus = &dev->i2c_bus[1];
		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
						&hauppauge_hvr1500_config,
						&dev->i2c_bus[0].i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			struct dvb_frontend *fe;
			struct xc2028_config cfg = {
				.i2c_adap  = &i2c_bus->i2c_adap,
				.i2c_addr  = 0x61,
			};
			static struct xc2028_ctrl ctl = {
				.fname       = XC2028_DEFAULT_FIRMWARE,
				.max_len     = 64,
				.demod       = XC3028_FE_OREN538,
			};

			fe = dvb_attach(xc2028_attach,
					fe0->dvb.frontend, &cfg);
			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
				fe->ops.tuner_ops.set_config(fe, &ctl);
		}
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1200:
	case CX23885_BOARD_HAUPPAUGE_HVR1700:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(tda10048_attach,
			&hauppauge_hvr1200_config,
			&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(tda829x_attach, fe0->dvb.frontend,
				&dev->i2c_bus[1].i2c_adap, 0x42,
				&tda829x_no_probe);
			dvb_attach(tda18271_attach, fe0->dvb.frontend,
				0x60, &dev->i2c_bus[1].i2c_adap,
				&hauppauge_hvr1200_tuner_config);
		}
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1210:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(tda10048_attach,
			&hauppauge_hvr1210_config,
			&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(tda18271_attach, fe0->dvb.frontend,
				0x60, &dev->i2c_bus[1].i2c_adap,
				&hauppauge_hvr1210_tuner_config);
		}
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1400:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(dib7000p_attach,
			&i2c_bus->i2c_adap,
			0x12, &hauppauge_hvr1400_dib7000_config);
		if (fe0->dvb.frontend != NULL) {
			struct dvb_frontend *fe;
			struct xc2028_config cfg = {
				.i2c_adap  = &dev->i2c_bus[1].i2c_adap,
				.i2c_addr  = 0x64,
			};
			static struct xc2028_ctrl ctl = {
				.fname   = XC3028L_DEFAULT_FIRMWARE,
				.max_len = 64,
				.demod   = XC3028_FE_DIBCOM52,
				/* This is true for all demods with
					v36 firmware? */
				.type    = XC2028_D2633,
			};

			fe = dvb_attach(xc2028_attach,
					fe0->dvb.frontend, &cfg);
			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
				fe->ops.tuner_ops.set_config(fe, &ctl);
		}
		break;
	case CX23885_BOARD_DVICO_FUSIONHDTV_7_DUAL_EXP:
		i2c_bus = &dev->i2c_bus[port->nr - 1];

		fe0->dvb.frontend = dvb_attach(s5h1409_attach,
						&dvico_s5h1409_config,
						&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend == NULL)
			fe0->dvb.frontend = dvb_attach(s5h1411_attach,
							&dvico_s5h1411_config,
							&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL)
			dvb_attach(xc5000_attach, fe0->dvb.frontend,
				   &i2c_bus->i2c_adap,
				   &dvico_xc5000_tunerconfig);
		break;
	case CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP: {
		i2c_bus = &dev->i2c_bus[port->nr - 1];

		fe0->dvb.frontend = dvb_attach(zl10353_attach,
					       &dvico_fusionhdtv_xc3028,
					       &i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			struct dvb_frontend      *fe;
			struct xc2028_config	  cfg = {
				.i2c_adap  = &i2c_bus->i2c_adap,
				.i2c_addr  = 0x61,
			};
			static struct xc2028_ctrl ctl = {
				.fname       = XC2028_DEFAULT_FIRMWARE,
				.max_len     = 64,
				.demod       = XC3028_FE_ZARLINK456,
			};

			fe = dvb_attach(xc2028_attach, fe0->dvb.frontend,
					&cfg);
			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
				fe->ops.tuner_ops.set_config(fe, &ctl);
		}
		break;
	}
	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
		i2c_bus = &dev->i2c_bus[0];

		fe0->dvb.frontend = dvb_attach(zl10353_attach,
			&dvico_fusionhdtv_xc3028,
			&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			struct dvb_frontend      *fe;
			struct xc2028_config	  cfg = {
				.i2c_adap  = &dev->i2c_bus[1].i2c_adap,
				.i2c_addr  = 0x61,
			};
			static struct xc2028_ctrl ctl = {
				.fname       = XC2028_DEFAULT_FIRMWARE,
				.max_len     = 64,
				.demod       = XC3028_FE_ZARLINK456,
			};

			fe = dvb_attach(xc2028_attach, fe0->dvb.frontend,
				&cfg);
			if (fe != NULL && fe->ops.tuner_ops.set_config != NULL)
				fe->ops.tuner_ops.set_config(fe, &ctl);
		}
		break;
	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
		i2c_bus = &dev->i2c_bus[0];

		fe0->dvb.frontend = dvb_attach(zl10353_attach,
					       &dvico_fusionhdtv_xc3028,
					       &i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			struct dvb_frontend	*fe;
			struct xc4000_config	cfg = {
				.i2c_address	  = 0x61,
				.default_pm	  = 0,
				.dvb_amplitude	  = 134,
				.set_smoothedcvbs = 1,
				.if_khz		  = 4560
			};

			fe = dvb_attach(xc4000_attach, fe0->dvb.frontend,
					&dev->i2c_bus[1].i2c_adap, &cfg);
			if (!fe) {
				printk(KERN_ERR "%s/2: xc4000 attach failed\n",
				       dev->name);
				goto frontend_detach;
			}
		}
		break;
	case CX23885_BOARD_TBS_6920:
		i2c_bus = &dev->i2c_bus[1];

		fe0->dvb.frontend = dvb_attach(cx24116_attach,
					&tbs_cx24116_config,
					&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL)
			fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;

		break;
	case CX23885_BOARD_TEVII_S470:
		i2c_bus = &dev->i2c_bus[1];

		fe0->dvb.frontend = dvb_attach(ds3000_attach,
					&tevii_ds3000_config,
					&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(ts2020_attach, fe0->dvb.frontend,
				&tevii_ts2020_config, &i2c_bus->i2c_adap);
			fe0->dvb.frontend->ops.set_voltage = f300_set_voltage;
		}

		break;
	case CX23885_BOARD_DVBWORLD_2005:
		i2c_bus = &dev->i2c_bus[1];

		fe0->dvb.frontend = dvb_attach(cx24116_attach,
			&dvbworld_cx24116_config,
			&i2c_bus->i2c_adap);
		break;
	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
		i2c_bus = &dev->i2c_bus[0];
		switch (port->nr) {
		/* port B */
		case 1:
			fe0->dvb.frontend = dvb_attach(stv0900_attach,
							&netup_stv0900_config,
							&i2c_bus->i2c_adap, 0);
			if (fe0->dvb.frontend != NULL) {
				if (dvb_attach(stv6110_attach,
						fe0->dvb.frontend,
						&netup_stv6110_tunerconfig_a,
						&i2c_bus->i2c_adap)) {
					if (!dvb_attach(lnbh24_attach,
							fe0->dvb.frontend,
							&i2c_bus->i2c_adap,
							LNBH24_PCL | LNBH24_TTX,
							LNBH24_TEN, 0x09))
						printk(KERN_ERR
							"No LNBH24 found!\n");

				}
			}
			break;
		/* port C */
		case 2:
			fe0->dvb.frontend = dvb_attach(stv0900_attach,
							&netup_stv0900_config,
							&i2c_bus->i2c_adap, 1);
			if (fe0->dvb.frontend != NULL) {
				if (dvb_attach(stv6110_attach,
						fe0->dvb.frontend,
						&netup_stv6110_tunerconfig_b,
						&i2c_bus->i2c_adap)) {
					if (!dvb_attach(lnbh24_attach,
							fe0->dvb.frontend,
							&i2c_bus->i2c_adap,
							LNBH24_PCL | LNBH24_TTX,
							LNBH24_TEN, 0x0a))
						printk(KERN_ERR
							"No LNBH24 found!\n");

				}
			}
			break;
		}
		break;
	case CX23885_BOARD_MYGICA_X8506:
		i2c_bus = &dev->i2c_bus[0];
		i2c_bus2 = &dev->i2c_bus[1];
		fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
			&mygica_x8506_lgs8gl5_config,
			&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(xc5000_attach,
				fe0->dvb.frontend,
				&i2c_bus2->i2c_adap,
				&mygica_x8506_xc5000_config);
		}
		break;
	case CX23885_BOARD_MAGICPRO_PROHDTVE2:
		i2c_bus = &dev->i2c_bus[0];
		i2c_bus2 = &dev->i2c_bus[1];
		fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
			&magicpro_prohdtve2_lgs8g75_config,
			&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(xc5000_attach,
				fe0->dvb.frontend,
				&i2c_bus2->i2c_adap,
				&magicpro_prohdtve2_xc5000_config);
		}
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1850:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
			&hcw_s5h1411_config,
			&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL)
			dvb_attach(tda18271_attach, fe0->dvb.frontend,
				0x60, &dev->i2c_bus[0].i2c_adap,
				&hauppauge_tda18271_config);

		tda18271_attach(&dev->ts1.analog_fe,
			0x60, &dev->i2c_bus[1].i2c_adap,
			&hauppauge_tda18271_config);

		break;
	case CX23885_BOARD_HAUPPAUGE_HVR1290:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(s5h1411_attach,
			&hcw_s5h1411_config,
			&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL)
			dvb_attach(tda18271_attach, fe0->dvb.frontend,
				0x60, &dev->i2c_bus[0].i2c_adap,
				&hauppauge_tda18271_config);
		break;
	case CX23885_BOARD_MYGICA_X8558PRO:
		switch (port->nr) {
		/* port B */
		case 1:
			i2c_bus = &dev->i2c_bus[0];
			fe0->dvb.frontend = dvb_attach(atbm8830_attach,
				&mygica_x8558pro_atbm8830_cfg1,
				&i2c_bus->i2c_adap);
			if (fe0->dvb.frontend != NULL) {
				dvb_attach(max2165_attach,
					fe0->dvb.frontend,
					&i2c_bus->i2c_adap,
					&mygic_x8558pro_max2165_cfg1);
			}
			break;
		/* port C */
		case 2:
			i2c_bus = &dev->i2c_bus[1];
			fe0->dvb.frontend = dvb_attach(atbm8830_attach,
				&mygica_x8558pro_atbm8830_cfg2,
				&i2c_bus->i2c_adap);
			if (fe0->dvb.frontend != NULL) {
				dvb_attach(max2165_attach,
					fe0->dvb.frontend,
					&i2c_bus->i2c_adap,
					&mygic_x8558pro_max2165_cfg2);
			}
			break;
		}
		break;
	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
		i2c_bus = &dev->i2c_bus[0];
		mfe_shared = 1;/* MFE */
		port->frontends.gate = 0;/* not clear for me yet */
		/* ports B, C */
		/* MFE frontend 1 DVB-T */
		fe0->dvb.frontend = dvb_attach(stv0367ter_attach,
					&netup_stv0367_config[port->nr - 1],
					&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			if (NULL == dvb_attach(xc5000_attach,
					fe0->dvb.frontend,
					&i2c_bus->i2c_adap,
					&netup_xc5000_config[port->nr - 1]))
				goto frontend_detach;
			/* load xc5000 firmware */
			fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend);
		}
		/* MFE frontend 2 */
		fe1 = videobuf_dvb_get_frontend(&port->frontends, 2);
		if (fe1 == NULL)
			goto frontend_detach;
		/* DVB-C init */
		fe1->dvb.frontend = dvb_attach(stv0367cab_attach,
					&netup_stv0367_config[port->nr - 1],
					&i2c_bus->i2c_adap);
		if (fe1->dvb.frontend != NULL) {
			fe1->dvb.frontend->id = 1;
			if (NULL == dvb_attach(xc5000_attach,
					fe1->dvb.frontend,
					&i2c_bus->i2c_adap,
					&netup_xc5000_config[port->nr - 1]))
				goto frontend_detach;
		}
		break;
	case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
		i2c_bus = &dev->i2c_bus[0];
		i2c_bus2 = &dev->i2c_bus[1];

		switch (port->nr) {
		/* port b */
		case 1:
			fe0->dvb.frontend = dvb_attach(drxk_attach,
					&terratec_drxk_config[0],
					&i2c_bus->i2c_adap);
			if (fe0->dvb.frontend != NULL) {
				if (!dvb_attach(mt2063_attach,
						fe0->dvb.frontend,
						&terratec_mt2063_config[0],
						&i2c_bus2->i2c_adap))
					goto frontend_detach;
			}
			break;
		/* port c */
		case 2:
			fe0->dvb.frontend = dvb_attach(drxk_attach,
					&terratec_drxk_config[1],
					&i2c_bus->i2c_adap);
			if (fe0->dvb.frontend != NULL) {
				if (!dvb_attach(mt2063_attach,
						fe0->dvb.frontend,
						&terratec_mt2063_config[1],
						&i2c_bus2->i2c_adap))
					goto frontend_detach;
			}
			break;
		}
		break;
	case CX23885_BOARD_TEVII_S471:
		i2c_bus = &dev->i2c_bus[1];

		fe0->dvb.frontend = dvb_attach(ds3000_attach,
					&tevii_ds3000_config,
					&i2c_bus->i2c_adap);
		break;
	case CX23885_BOARD_PROF_8000:
		i2c_bus = &dev->i2c_bus[0];

		fe0->dvb.frontend = dvb_attach(stv090x_attach,
						&prof_8000_stv090x_config,
						&i2c_bus->i2c_adap,
						STV090x_DEMODULATOR_0);
		if (fe0->dvb.frontend != NULL) {
			if (!dvb_attach(stb6100_attach,
					fe0->dvb.frontend,
					&prof_8000_stb6100_config,
					&i2c_bus->i2c_adap))
				goto frontend_detach;

			fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage;
		}
		break;
	case CX23885_BOARD_HAUPPAUGE_HVR4400:
		i2c_bus = &dev->i2c_bus[0];
		fe0->dvb.frontend = dvb_attach(tda10071_attach,
						&hauppauge_tda10071_config,
						&i2c_bus->i2c_adap);
		if (fe0->dvb.frontend != NULL) {
			dvb_attach(a8293_attach, fe0->dvb.frontend,
				   &i2c_bus->i2c_adap,
				   &hauppauge_a8293_config);
		}
		break;
	default:
		printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
			" isn't supported yet\n",
		       dev->name);
		break;
	}

	if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) {
		printk(KERN_ERR "%s: frontend initialization failed\n",
		       dev->name);
		goto frontend_detach;
	}

	/* define general-purpose callback pointer */
	fe0->dvb.frontend->callback = cx23885_tuner_callback;
	if (fe1)
		fe1->dvb.frontend->callback = cx23885_tuner_callback;
#if 0
	/* Ensure all frontends negotiate bus access */
	fe0->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl;
	if (fe1)
		fe1->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl;
#endif

	/* Put the analog decoder in standby to keep it quiet */
	call_all(dev, core, s_power, 0);

	if (fe0->dvb.frontend->ops.analog_ops.standby)
		fe0->dvb.frontend->ops.analog_ops.standby(fe0->dvb.frontend);

	/* register everything */
	ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
					&dev->pci->dev, adapter_nr, mfe_shared);
	if (ret)
		goto frontend_detach;

	/* init CI & MAC */
	switch (dev->board) {
	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI: {
		static struct netup_card_info cinfo;

		netup_get_card_info(&dev->i2c_bus[0].i2c_adap, &cinfo);
		memcpy(port->frontends.adapter.proposed_mac,
				cinfo.port[port->nr - 1].mac, 6);
		printk(KERN_INFO "NetUP Dual DVB-S2 CI card port%d MAC=%pM\n",
			port->nr, port->frontends.adapter.proposed_mac);

		netup_ci_init(port);
		break;
		}
	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
		struct altera_ci_config netup_ci_cfg = {
			.dev = dev,/* magic number to identify*/
			.adapter = &port->frontends.adapter,/* for CI */
			.demux = &fe0->dvb.demux,/* for hw pid filter */
			.fpga_rw = netup_altera_fpga_rw,
		};

		altera_ci_init(&netup_ci_cfg, port->nr);
		break;
		}
	case CX23885_BOARD_TEVII_S470: {
		u8 eeprom[256]; /* 24C02 i2c eeprom */

		if (port->nr != 1)
			break;

		/* Read entire EEPROM */
		dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
		tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom, sizeof(eeprom));
		printk(KERN_INFO "TeVii S470 MAC= %pM\n", eeprom + 0xa0);
		memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
		break;
		}
	}

	return ret;

frontend_detach:
	port->gate_ctrl = NULL;
	videobuf_dvb_dealloc_frontends(&port->frontends);
	return -EINVAL;
}

int cx23885_dvb_register(struct cx23885_tsport *port)
{

	struct videobuf_dvb_frontend *fe0;
	struct cx23885_dev *dev = port->dev;
	int err, i;

	/* Here we need to allocate the correct number of frontends,
	 * as reflected in the cards struct. The reality is that currently
	 * no cx23885 boards support this - yet. But, if we don't modify this
	 * code then the second frontend would never be allocated (later)
	 * and fail with error before the attach in dvb_register().
	 * Without these changes we risk an OOPS later. The changes here
	 * are for safety, and should provide a good foundation for the
	 * future addition of any multi-frontend cx23885 based boards.
	 */
	printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
		port->num_frontends);

	for (i = 1; i <= port->num_frontends; i++) {
		if (videobuf_dvb_alloc_frontend(
			&port->frontends, i) == NULL) {
			printk(KERN_ERR "%s() failed to alloc\n", __func__);
			return -ENOMEM;
		}

		fe0 = videobuf_dvb_get_frontend(&port->frontends, i);
		if (!fe0)
			err = -EINVAL;

		dprintk(1, "%s\n", __func__);
		dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n",
			dev->board,
			dev->name,
			dev->pci_bus,
			dev->pci_slot);

		err = -ENODEV;

		/* dvb stuff */
		/* We have to init the queue for each frontend on a port. */
		printk(KERN_INFO "%s: cx23885 based dvb card\n", dev->name);
		videobuf_queue_sg_init(&fe0->dvb.dvbq, &dvb_qops,
			    &dev->pci->dev, &port->slock,
			    V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP,
			    sizeof(struct cx23885_buffer), port, NULL);
	}
	err = dvb_register(port);
	if (err != 0)
		printk(KERN_ERR "%s() dvb_register failed err = %d\n",
			__func__, err);

	return err;
}

int cx23885_dvb_unregister(struct cx23885_tsport *port)
{
	struct videobuf_dvb_frontend *fe0;

	/* FIXME: in an error condition where the we have
	 * an expected number of frontends (attach problem)
	 * then this might not clean up correctly, if 1
	 * is invalid.
	 * This comment only applies to future boards IF they
	 * implement MFE support.
	 */
	fe0 = videobuf_dvb_get_frontend(&port->frontends, 1);
	if (fe0 && fe0->dvb.frontend)
		videobuf_dvb_unregister_bus(&port->frontends);

	switch (port->dev->board) {
	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
		netup_ci_exit(port);
		break;
	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
		altera_ci_release(port->dev, port->nr);
		break;
	}

	port->gate_ctrl = NULL;

	return 0;
}
Exemple #28
0
int videobuf_qbuf(struct videobuf_queue *q, struct v4l2_buffer *b)
{
	struct videobuf_buffer *buf;
	enum v4l2_field field;
	unsigned long flags = 0;
	int retval;

	MAGIC_CHECK(q->int_ops->magic, MAGIC_QTYPE_OPS);

	if (b->memory == V4L2_MEMORY_MMAP)
		down_read(&current->mm->mmap_sem);

	videobuf_queue_lock(q);
	retval = -EBUSY;
	if (q->reading) {
		dprintk(1, "qbuf: Reading running...\n");
		goto done;
	}
	retval = -EINVAL;
	if (b->type != q->type) {
		dprintk(1, "qbuf: Wrong type.\n");
		goto done;
	}
	if (b->index >= VIDEO_MAX_FRAME) {
		dprintk(1, "qbuf: index out of range.\n");
		goto done;
	}
	buf = q->bufs[b->index];
	if (NULL == buf) {
		dprintk(1, "qbuf: buffer is null.\n");
		goto done;
	}
	MAGIC_CHECK(buf->magic, MAGIC_BUFFER);
	if (buf->memory != b->memory) {
		dprintk(1, "qbuf: memory type is wrong.\n");
		goto done;
	}
	if (buf->state != VIDEOBUF_NEEDS_INIT && buf->state != VIDEOBUF_IDLE) {
		dprintk(1, "qbuf: buffer is already queued or active.\n");
		goto done;
	}

	switch (b->memory) {
	case V4L2_MEMORY_MMAP:
		if (0 == buf->baddr) {
			dprintk(1, "qbuf: mmap requested but buffer addr is zero!\n");
			goto done;
		}
		if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT
		    || q->type == V4L2_BUF_TYPE_VBI_OUTPUT
		    || q->type == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
		    || q->type == V4L2_BUF_TYPE_SDR_OUTPUT) {
			buf->size = b->bytesused;
			buf->field = b->field;
			buf->ts = b->timestamp;
		}
		break;
	case V4L2_MEMORY_USERPTR:
		if (b->length < buf->bsize) {
			dprintk(1, "qbuf: buffer length is not enough\n");
			goto done;
		}
		if (VIDEOBUF_NEEDS_INIT != buf->state &&
		    buf->baddr != b->m.userptr)
			q->ops->buf_release(q, buf);
		buf->baddr = b->m.userptr;
		break;
	case V4L2_MEMORY_OVERLAY:
		buf->boff = b->m.offset;
		break;
	default:
		dprintk(1, "qbuf: wrong memory type\n");
		goto done;
	}

	dprintk(1, "qbuf: requesting next field\n");
	field = videobuf_next_field(q);
	retval = q->ops->buf_prepare(q, buf, field);
	if (0 != retval) {
		dprintk(1, "qbuf: buffer_prepare returned %d\n", retval);
		goto done;
	}

	list_add_tail(&buf->stream, &q->stream);
	if (q->streaming) {
		spin_lock_irqsave(q->irqlock, flags);
		q->ops->buf_queue(q, buf);
		spin_unlock_irqrestore(q->irqlock, flags);
	}
	dprintk(1, "qbuf: succeeded\n");
	retval = 0;
	wake_up_interruptible_sync(&q->wait);

done:
	videobuf_queue_unlock(q);

	if (b->memory == V4L2_MEMORY_MMAP)
		up_read(&current->mm->mmap_sem);

	return retval;
}
static void __exit sep0611_overlay_exit(void)
{
	dprintk("sep0611_overlay driver exit\n");
	platform_driver_unregister(&sep0611_overlay_driver);
	//platform_device_unregister(&sep0611_overlay_device);
}
Exemple #30
0
static long pn544_dev_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	struct pn544_dev *pn544_dev = filp->private_data;

	switch (cmd) {
	case PN544_SET_PWR:
		if (arg == 2) {
			/*
			power on with firmware download (requires hw reset)
			*/
			dprintk(PN544_DRV_NAME ":%s power on with firmware\n", __func__);

			gpio_set_value(pn544_dev->ven_gpio, 1);
			gpio_set_value(pn544_dev->firm_gpio, 1);
			msleep(10);
			gpio_set_value(pn544_dev->ven_gpio, 0);
			msleep(10);
			gpio_set_value(pn544_dev->ven_gpio, 1);
			msleep(10);
		} else if (arg == 1) {
			/* power on */
			dprintk(PN544_DRV_NAME ":%s power on\n", __func__);

			gpio_set_value(pn544_dev->firm_gpio, 0);
			gpio_set_value(pn544_dev->ven_gpio, 1);
			msleep(10);
#ifdef CONFIG_LGE_NFC_SET_IRQ_WAKEUP
            if (sIrqState == false) {
                irq_set_irq_wake(pn544_dev->client->irq,1);
                sIrqState = true;
                dprintk(PN544_DRV_NAME ":%s enable IRQ\n", __func__);
            }
            else {
                pr_err("%s IRQ is already enabled!\n", __func__);
            }
#endif
		} else  if (arg == 0) {
			/* power off */
			dprintk(PN544_DRV_NAME ":%s power off\n", __func__);
			gpio_set_value(pn544_dev->firm_gpio, 0);
			gpio_set_value(pn544_dev->ven_gpio, 0);
			msleep(10);
#ifdef CONFIG_LGE_NFC_SET_IRQ_WAKEUP
            if (sIrqState == true) {
                irq_set_irq_wake(pn544_dev->client->irq,0);
                sIrqState = false;
                dprintk(PN544_DRV_NAME ":%s disable IRQ\n", __func__);
            }
            else {
                pr_err("%s IRQ is already disabled!\n", __func__);
            }
#endif
#ifdef LGE_NFC_READ_IRQ_MODIFY
		} else if (arg == 3) {//DY_TEST
			dprintk("%s Read Cancle\n", __func__);
            cancle_read = true;
            do_reading = 1;
        	wake_up(&pn544_dev->read_wq);
#endif
		} else {
				pr_err("%s bad arg %ld\n", __func__, arg);
			return -EINVAL;
		}
		break;
	case PN544_INTERRUPT_CMD:
		{
			/*
			pn544_disable_irq = level;
			*/
			dprintk(PN544_DRV_NAME ":ioctl: pn544_interrupt enable level:%ld\n", arg);
			break;
		}
	case PN544_READ_POLLING_CMD:
		{
			stReadIntFlag = arg;
			dprintk(PN544_DRV_NAME ":ioctl: pn544_polling flag set:%ld\n", arg);
			break;
		}
	case PN544_HW_REVISION:
		{
			return pn544_get_hw_revision();
		}
	default:
		pr_err("%s bad ioctl %d\n", __func__, cmd);
		return -EINVAL;
	}

	return 0;
}