Ejemplo n.º 1
0
/* ioctl callback function */
long ioctl(struct file *file,
           unsigned int ioctl_num,
           unsigned long ioctl_param)
{
    char ch;    /* current character to or from userspace */
    int size;   /* size of page being written to */
    int bytes;  /* current number of bytes being read or written */

    switch (ioctl_num) {

        case IOCTL_ALLOC:

            printk(KERN_INFO "vmm: allocating %d bytes\n", (int)ioctl_param);
            return buddy_alloc((int)ioctl_param);

        case IOCTL_FREE:

            printk(KERN_INFO "vmm: freeing idx %d\n", (int)ioctl_param);
            return buddy_free((int)ioctl_param);

        case IOCTL_SET_IDX:

            current_idx = (int)ioctl_param;
            printk(KERN_INFO "vmm: setting idx to %d\n", current_idx);
            return 0;

        case IOCTL_SET_READ_SIZE:

            read_size = (int)ioctl_param;
            printk(KERN_INFO "vmm: setting read size to %d\n", read_size);
            return 0;

        case IOCTL_WRITE:

            /* reset the number of bytes written */
            bytes = 0;

            /* get the page size */
            size = buddy_size(current_idx);

            /* keep writing until some condition breaks us out */
            while (1) {

                /* get the next byte from userspace */
                get_user(ch, (char*)ioctl_param+bytes);

                /* if it's a null terminator we are finished writing */
                if (ch == '\0') break;

                /* if we are about to write outside the page error out */
                if (bytes > size) {
                    printk(KERN_INFO "vmm: writing out of allocated area\n");
                    return -1;
                }

                /* write the byte into the pool */
                *(buddy_pool+current_idx+bytes) = ch;
                printk(KERN_INFO "wrote %c to %d\n", ch, current_idx+bytes);

                /* go to the next byte */
                bytes++;
            }

            printk(KERN_INFO "vmm: wrote %d bytes\n", bytes);

            /* return how many bytes were written */
            return bytes;

        case IOCTL_READ:

            /* return error if trying to read more than the page size */
            if (read_size > buddy_size(current_idx)) {
                printk(KERN_INFO "vmm: read bigger than allocated area\n");
                return -1;
            }

            /* reset the number of bytes read */
            bytes = 0;

            /* keep reading bytes until we've satisfied the request */
            while (bytes < read_size) {

                /* get byte out of pool and send it to user */
                put_user(*(buddy_pool+current_idx+bytes), (char*)ioctl_param+bytes);

                /* go to the next byte */
                bytes++;
            }

            printk(KERN_INFO "vmm: read %d bytes\n", bytes);

            /* return how many bytes were read */
            return bytes;

        default: printk(KERN_INFO "vmm: unknown ioctl call\n");
    }

    return 0;
}
Ejemplo n.º 2
0
/* Get the packet mode of a pty */
static int pty_get_pktmode(struct tty_struct *tty, int __user *arg)
{
	int pktmode = tty->packet;
	return put_user(pktmode, arg);
}
Ejemplo n.º 3
0
static long ar7_wdt_ioctl(struct file *file,
					unsigned int cmd, unsigned long arg)
{
	static const struct watchdog_info ident = {
		.identity = LONGNAME,
		.firmware_version = 1,
		.options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
						WDIOF_MAGICCLOSE),
	};
	int new_margin;

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user((struct watchdog_info *)arg, &ident,
				sizeof(ident)))
			return -EFAULT;
		return 0;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		if (put_user(0, (int *)arg))
			return -EFAULT;
		return 0;
	case WDIOC_KEEPALIVE:
		ar7_wdt_kick(1);
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_margin, (int *)arg))
			return -EFAULT;
		if (new_margin < 1)
			return -EINVAL;

		spin_lock(&wdt_lock);
		ar7_wdt_update_margin(new_margin);
		ar7_wdt_kick(1);
		spin_unlock(&wdt_lock);

	case WDIOC_GETTIMEOUT:
		if (put_user(margin, (int *)arg))
			return -EFAULT;
		return 0;
	default:
		return -ENOTTY;
	}
}

static const struct file_operations ar7_wdt_fops = {
	.owner		= THIS_MODULE,
	.write		= ar7_wdt_write,
	.unlocked_ioctl	= ar7_wdt_ioctl,
	.open		= ar7_wdt_open,
	.release	= ar7_wdt_release,
	.llseek		= no_llseek,
};

static struct miscdevice ar7_wdt_miscdev = {
	.minor		= WATCHDOG_MINOR,
	.name		= "watchdog",
	.fops		= &ar7_wdt_fops,
};

static int __devinit ar7_wdt_probe(struct platform_device *pdev)
{
	int rc;

	spin_lock_init(&wdt_lock);

	ar7_regs_wdt =
		platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
	if (!ar7_regs_wdt) {
		printk(KERN_ERR DRVNAME ": could not get registers resource\n");
		rc = -ENODEV;
		goto out;
	}

	if (!request_mem_region(ar7_regs_wdt->start,
				resource_size(ar7_regs_wdt), LONGNAME)) {
		printk(KERN_WARNING DRVNAME ": watchdog I/O region busy\n");
		rc = -EBUSY;
		goto out;
	}

	ar7_wdt = ioremap(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));
	if (!ar7_wdt) {
		printk(KERN_ERR DRVNAME ": could not ioremap registers\n");
		rc = -ENXIO;
		goto out_mem_region;
	}

	vbus_clk = clk_get(NULL, "vbus");
	if (IS_ERR(vbus_clk)) {
		printk(KERN_ERR DRVNAME ": could not get vbus clock\n");
		rc = PTR_ERR(vbus_clk);
		goto out_mem_region;
	}

	ar7_wdt_disable_wdt();
	ar7_wdt_prescale(prescale_value);
	ar7_wdt_update_margin(margin);

	rc = misc_register(&ar7_wdt_miscdev);
	if (rc) {
		printk(KERN_ERR DRVNAME ": unable to register misc device\n");
		goto out_alloc;
	}
	goto out;

out_alloc:
	iounmap(ar7_wdt);
out_mem_region:
	release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));
out:
	return rc;
}

static int __devexit ar7_wdt_remove(struct platform_device *pdev)
{
	misc_deregister(&ar7_wdt_miscdev);
	iounmap(ar7_wdt);
	release_mem_region(ar7_regs_wdt->start, resource_size(ar7_regs_wdt));

	return 0;
}
Ejemplo n.º 4
0
static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
		     unsigned long arg)
{

	unsigned long flags;
	struct rtc_time wtime; 

	switch (cmd) {
	case RTC_AIE_OFF:	/* Mask alarm int. enab. bit	*/
	{
		mask_rtc_irq_bit(RTC_AIE);
		return 0;
	}
	case RTC_AIE_ON:	/* Allow alarm interrupts.	*/
	{
		set_rtc_irq_bit(RTC_AIE);
		return 0;
	}
	case RTC_PIE_OFF:	/* Mask periodic int. enab. bit	*/
	{
		mask_rtc_irq_bit(RTC_PIE);
		if (rtc_status & RTC_TIMER_ON) {
			del_timer(&rtc_irq_timer);
			rtc_status &= ~RTC_TIMER_ON;
		}
		return 0;
	}
	case RTC_PIE_ON:	/* Allow periodic ints		*/
	{

		/*
		 * We don't really want Joe User enabling more
		 * than 64Hz of interrupts on a multi-user machine.
		 */
		if ((rtc_freq > 64) && (!capable(CAP_SYS_RESOURCE)))
			return -EACCES;

		if (!(rtc_status & RTC_TIMER_ON)) {
			rtc_status |= RTC_TIMER_ON;
			rtc_irq_timer.expires = jiffies + HZ/rtc_freq + 2*HZ/100;
			add_timer(&rtc_irq_timer);
		}
		set_rtc_irq_bit(RTC_PIE);
		return 0;
	}
	case RTC_UIE_OFF:	/* Mask ints from RTC updates.	*/
	{
		mask_rtc_irq_bit(RTC_UIE);
		return 0;
	}
	case RTC_UIE_ON:	/* Allow ints for RTC updates.	*/
	{
		set_rtc_irq_bit(RTC_UIE);
		return 0;
	}
	case RTC_ALM_READ:	/* Read the present alarm time */
	{
		/*
		 * This returns a struct rtc_time. Reading >= 0xc0
		 * means "don't care" or "match all". Only the tm_hour,
		 * tm_min, and tm_sec values are filled in.
		 */

		get_rtc_alm_time(&wtime);
		break; 
	}
	case RTC_ALM_SET:	/* Store a time into the alarm */
	{
		/*
		 * This expects a struct rtc_time. Writing 0xff means
		 * "don't care" or "match all". Only the tm_hour,
		 * tm_min and tm_sec are used.
		 */
		unsigned char hrs, min, sec;
		struct rtc_time alm_tm;

		if (copy_from_user(&alm_tm, (struct rtc_time*)arg,
				   sizeof(struct rtc_time)))
			return -EFAULT;

		hrs = alm_tm.tm_hour;
		min = alm_tm.tm_min;
		sec = alm_tm.tm_sec;

		if (hrs >= 24)
			hrs = 0xff;

		if (min >= 60)
			min = 0xff;

		if (sec >= 60)
			sec = 0xff;

		save_flags(flags);
		cli();
		if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ||
		    RTC_ALWAYS_BCD)
		{
			BIN_TO_BCD(sec);
			BIN_TO_BCD(min);
			BIN_TO_BCD(hrs);
		}
		CMOS_WRITE(hrs, RTC_HOURS_ALARM);
		CMOS_WRITE(min, RTC_MINUTES_ALARM);
		CMOS_WRITE(sec, RTC_SECONDS_ALARM);
		restore_flags(flags);

		return 0;
	}
	case RTC_RD_TIME:	/* Read the time/date from RTC	*/
	{
		get_rtc_time(&wtime);
		break;
	}
	case RTC_SET_TIME:	/* Set the RTC */
	{
		struct rtc_time rtc_tm;
		unsigned char mon, day, hrs, min, sec, leap_yr;
		unsigned char save_control, save_freq_select;
		unsigned int yrs;
		unsigned long flags;
			
		if (!capable(CAP_SYS_TIME))
			return -EACCES;

		if (copy_from_user(&rtc_tm, (struct rtc_time*)arg,
				   sizeof(struct rtc_time)))
			return -EFAULT;

		yrs = rtc_tm.tm_year + 1900;
		mon = rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
		day = rtc_tm.tm_mday;
		hrs = rtc_tm.tm_hour;
		min = rtc_tm.tm_min;
		sec = rtc_tm.tm_sec;

		if (yrs < 1970)
			return -EINVAL;

		leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));

		if ((mon > 12) || (day == 0))
			return -EINVAL;

		if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
			return -EINVAL;
			
		if ((hrs >= 24) || (min >= 60) || (sec >= 60))
			return -EINVAL;

		if ((yrs -= epoch) > 255)    /* They are unsigned */
			return -EINVAL;

		save_flags(flags);
		cli();
		if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY)
		    || RTC_ALWAYS_BCD) {
			if (yrs > 169) {
				restore_flags(flags);
				return -EINVAL;
			}
			if (yrs >= 100)
				yrs -= 100;

			BIN_TO_BCD(sec);
			BIN_TO_BCD(min);
			BIN_TO_BCD(hrs);
			BIN_TO_BCD(day);
			BIN_TO_BCD(mon);
			BIN_TO_BCD(yrs);
		}

		save_control = CMOS_READ(RTC_CONTROL);
		CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
		save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
		CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);

		CMOS_WRITE(yrs, RTC_YEAR);
		CMOS_WRITE(mon, RTC_MONTH);
		CMOS_WRITE(day, RTC_DAY_OF_MONTH);
		CMOS_WRITE(hrs, RTC_HOURS);
		CMOS_WRITE(min, RTC_MINUTES);
		CMOS_WRITE(sec, RTC_SECONDS);

		CMOS_WRITE(save_control, RTC_CONTROL);
		CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT);

		restore_flags(flags);
		return 0;
	}
	case RTC_IRQP_READ:	/* Read the periodic IRQ rate.	*/
	{
		return put_user(rtc_freq, (unsigned long *)arg);
	}
	case RTC_IRQP_SET:	/* Set periodic IRQ rate.	*/
	{
		int tmp = 0;
		unsigned char val;

		/* 
		 * The max we can do is 8192Hz.
		 */
		if ((arg < 2) || (arg > 8192))
			return -EINVAL;
		/*
		 * We don't really want Joe User generating more
		 * than 64Hz of interrupts on a multi-user machine.
		 */
		if ((arg > 64) && (!capable(CAP_SYS_RESOURCE)))
			return -EACCES;

		while (arg > (1<<tmp))
			tmp++;

		/*
		 * Check that the input was really a power of 2.
		 */
		if (arg != (1<<tmp))
			return -EINVAL;

		rtc_freq = arg;

		save_flags(flags);
		cli();
		val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
		val |= (16 - tmp);
		CMOS_WRITE(val, RTC_FREQ_SELECT);
		restore_flags(flags);
		return 0;
	}
#ifdef __alpha__
	case RTC_EPOCH_READ:	/* Read the epoch.	*/
	{
		return put_user (epoch, (unsigned long *)arg);
	}
	case RTC_EPOCH_SET:	/* Set the epoch.	*/
	{
		/* 
		 * There were no RTC clocks before 1900.
		 */
		if (arg < 1900)
			return -EINVAL;

		if (!capable(CAP_SYS_TIME))
			return -EACCES;

		epoch = arg;
		return 0;
	}
#endif
	default:
		return -EINVAL;
	}
	return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
}
Ejemplo n.º 5
0
static long sc1200wdt_ioctl(struct file *file, unsigned int cmd,
						unsigned long arg)
{
	int new_timeout;
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static const struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
							WDIOF_MAGICCLOSE,
		.firmware_version = 0,
		.identity = "PC87307/PC97307",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &ident, sizeof(ident)))
			return -EFAULT;
		return 0;

	case WDIOC_GETSTATUS:
		return put_user(sc1200wdt_status(), p);

	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);

	case WDIOC_SETOPTIONS:
	{
		int options, retval = -EINVAL;

		if (get_user(options, p))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD) {
			sc1200wdt_stop();
			retval = 0;
		}

		if (options & WDIOS_ENABLECARD) {
			sc1200wdt_start();
			retval = 0;
		}

		return retval;
	}
	case WDIOC_KEEPALIVE:
		sc1200wdt_write_data(WDTO, timeout);
		return 0;

	case WDIOC_SETTIMEOUT:
		if (get_user(new_timeout, p))
			return -EFAULT;
		/* the API states this is given in secs */
		new_timeout /= 60;
		if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
			return -EINVAL;
		timeout = new_timeout;
		sc1200wdt_write_data(WDTO, timeout);
		/* fall through and return the new timeout */

	case WDIOC_GETTIMEOUT:
		return put_user(timeout * 60, p);

	default:
		return -ENOTTY;
	}
}


static int sc1200wdt_release(struct inode *inode, struct file *file)
{
	if (expect_close == 42) {
		sc1200wdt_stop();
#ifdef CONFIG_DEBUG_PRINTK
		printk(KERN_INFO PFX "Watchdog disabled\n");
#else
		;
#endif
	} else {
		sc1200wdt_write_data(WDTO, timeout);
#ifdef CONFIG_DEBUG_PRINTK
		printk(KERN_CRIT PFX
			"Unexpected close!, timeout = %d min(s)\n", timeout);
#else
		;
#endif
	}
	clear_bit(0, &open_flag);
	expect_close = 0;

	return 0;
}


static ssize_t sc1200wdt_write(struct file *file, const char __user *data,
						size_t len, loff_t *ppos)
{
	if (len) {
		if (!nowayout) {
			size_t i;

			expect_close = 0;

			for (i = 0; i != len; i++) {
				char c;

				if (get_user(c, data + i))
					return -EFAULT;
				if (c == 'V')
					expect_close = 42;
			}
		}

		sc1200wdt_write_data(WDTO, timeout);
		return len;
	}

	return 0;
}


static int sc1200wdt_notify_sys(struct notifier_block *this,
					unsigned long code, void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		sc1200wdt_stop();

	return NOTIFY_DONE;
}


static struct notifier_block sc1200wdt_notifier = {
	.notifier_call =	sc1200wdt_notify_sys,
};

static const struct file_operations sc1200wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= sc1200wdt_write,
	.unlocked_ioctl = sc1200wdt_ioctl,
	.open		= sc1200wdt_open,
	.release	= sc1200wdt_release,
};

static struct miscdevice sc1200wdt_miscdev = {
	.minor		= WATCHDOG_MINOR,
	.name		= "watchdog",
	.fops		= &sc1200wdt_fops,
};


static int __init sc1200wdt_probe(void)
{
	/* The probe works by reading the PMC3 register's default value of 0x0e
	 * there is one caveat, if the device disables the parallel port or any
	 * of the UARTs we won't be able to detect it.
	 * NB. This could be done with accuracy by reading the SID registers,
	 * but we don't have access to those io regions.
	 */

	unsigned char reg;

	sc1200wdt_read_data(PMC3, &reg);
	reg &= 0x0f;		/* we don't want the UART busy bits */
	return (reg == 0x0e) ? 0 : -ENODEV;
}


#if defined CONFIG_PNP

static struct pnp_device_id scl200wdt_pnp_devices[] = {
	/* National Semiconductor PC87307/PC97307 watchdog component */
	{.id = "NSC0800", .driver_data = 0},
	{.id = ""},
Ejemplo n.º 6
0
static long sch311x_wdt_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{
	int status;
	int new_timeout;
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static const struct watchdog_info ident = {
		.options		= WDIOF_KEEPALIVEPING |
					  WDIOF_SETTIMEOUT |
					  WDIOF_MAGICCLOSE,
		.firmware_version	= 1,
		.identity		= DRV_NAME,
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &ident, sizeof(ident)))
			return -EFAULT;
		break;

	case WDIOC_GETSTATUS:
	{
		sch311x_wdt_get_status(&status);
		return put_user(status, p);
	}
	case WDIOC_GETBOOTSTATUS:
		return put_user(sch311x_wdt_data.boot_status, p);

	case WDIOC_SETOPTIONS:
	{
		int options, retval = -EINVAL;

		if (get_user(options, p))
			return -EFAULT;
		if (options & WDIOS_DISABLECARD) {
			sch311x_wdt_stop();
			retval = 0;
		}
		if (options & WDIOS_ENABLECARD) {
			sch311x_wdt_start();
			retval = 0;
		}
		return retval;
	}
	case WDIOC_KEEPALIVE:
		sch311x_wdt_keepalive();
		break;

	case WDIOC_SETTIMEOUT:
		if (get_user(new_timeout, p))
			return -EFAULT;
		if (sch311x_wdt_set_heartbeat(new_timeout))
			return -EINVAL;
		sch311x_wdt_keepalive();
		/* Fall */
	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);
	default:
		return -ENOTTY;
	}
	return 0;
}

static int sch311x_wdt_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &sch311x_wdt_is_open))
		return -EBUSY;
	/*
	 *	Activate
	 */
	sch311x_wdt_start();
	return nonseekable_open(inode, file);
}

static int sch311x_wdt_close(struct inode *inode, struct file *file)
{
	if (sch311x_wdt_expect_close == 42) {
		sch311x_wdt_stop();
	} else {
		printk(KERN_CRIT PFX
				"Unexpected close, not stopping watchdog!\n");
		sch311x_wdt_keepalive();
	}
	clear_bit(0, &sch311x_wdt_is_open);
	sch311x_wdt_expect_close = 0;
	return 0;
}

/*
 *	Kernel Interfaces
 */

static const struct file_operations sch311x_wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= sch311x_wdt_write,
	.unlocked_ioctl	= sch311x_wdt_ioctl,
	.open		= sch311x_wdt_open,
	.release	= sch311x_wdt_close,
};

static struct miscdevice sch311x_wdt_miscdev = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &sch311x_wdt_fops,
};

/*
 *	Init & exit routines
 */

static int __devinit sch311x_wdt_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	unsigned char val;
	int err;

	spin_lock_init(&sch311x_wdt_data.io_lock);

	if (!request_region(sch311x_wdt_data.runtime_reg + RESGEN, 1,
								DRV_NAME)) {
		dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
			sch311x_wdt_data.runtime_reg + RESGEN,
			sch311x_wdt_data.runtime_reg + RESGEN);
		err = -EBUSY;
		goto exit;
	}

	if (!request_region(sch311x_wdt_data.runtime_reg + GP60, 1, DRV_NAME)) {
		dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
			sch311x_wdt_data.runtime_reg + GP60,
			sch311x_wdt_data.runtime_reg + GP60);
		err = -EBUSY;
		goto exit_release_region;
	}

	if (!request_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4,
								DRV_NAME)) {
		dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n",
			sch311x_wdt_data.runtime_reg + WDT_TIME_OUT,
			sch311x_wdt_data.runtime_reg + WDT_CTRL);
		err = -EBUSY;
		goto exit_release_region2;
	}

	/* Make sure that the watchdog is not running */
	sch311x_wdt_stop();

	/* Disable keyboard and mouse interaction and interrupt */
	/* -- Watchdog timer configuration --
	 * Bit 0   Reserved
	 * Bit 1   Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr.
	 * Bit 2   Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr
	 * Bit 3   Reserved
	 * Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled,
	 *            0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15)
	 */
	outb(0, sch311x_wdt_data.runtime_reg + WDT_CFG);

	/* Check that the heartbeat value is within it's range ;
	 * if not reset to the default */
	if (sch311x_wdt_set_heartbeat(timeout)) {
		sch311x_wdt_set_heartbeat(WATCHDOG_TIMEOUT);
		dev_info(dev, "timeout value must be 1<=x<=15300, using %d\n",
			timeout);
	}

	/* Get status at boot */
	sch311x_wdt_get_status(&sch311x_wdt_data.boot_status);

	/* enable watchdog */
	/* -- Reset Generator --
	 * Bit 0   Enable Watchdog Timer Generation: 0* = Enabled, 1 = Disabled
	 * Bit 1   Thermtrip Source Select: O* = No Source, 1 = Source
	 * Bit 2   WDT2_CTL: WDT input bit
	 * Bit 3-7 Reserved
	 */
	outb(0, sch311x_wdt_data.runtime_reg + RESGEN);
	val = therm_trip ? 0x06 : 0x04;
	outb(val, sch311x_wdt_data.runtime_reg + RESGEN);

	sch311x_wdt_miscdev.parent = dev;

	err = misc_register(&sch311x_wdt_miscdev);
	if (err != 0) {
		dev_err(dev, "cannot register miscdev on minor=%d (err=%d)\n",
							WATCHDOG_MINOR, err);
		goto exit_release_region3;
	}

	dev_info(dev,
		"SMSC SCH311x WDT initialized. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

	return 0;

exit_release_region3:
	release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4);
exit_release_region2:
	release_region(sch311x_wdt_data.runtime_reg + GP60, 1);
exit_release_region:
	release_region(sch311x_wdt_data.runtime_reg + RESGEN, 1);
	sch311x_wdt_data.runtime_reg = 0;
exit:
	return err;
}

static int __devexit sch311x_wdt_remove(struct platform_device *pdev)
{
	/* Stop the timer before we leave */
	if (!nowayout)
		sch311x_wdt_stop();

	/* Deregister */
	misc_deregister(&sch311x_wdt_miscdev);
	release_region(sch311x_wdt_data.runtime_reg + WDT_TIME_OUT, 4);
	release_region(sch311x_wdt_data.runtime_reg + GP60, 1);
	release_region(sch311x_wdt_data.runtime_reg + RESGEN, 1);
	sch311x_wdt_data.runtime_reg = 0;
	return 0;
}

static void sch311x_wdt_shutdown(struct platform_device *dev)
{
	/* Turn the WDT off if we have a soft shutdown */
	sch311x_wdt_stop();
}

static struct platform_driver sch311x_wdt_driver = {
	.probe		= sch311x_wdt_probe,
	.remove		= __devexit_p(sch311x_wdt_remove),
	.shutdown	= sch311x_wdt_shutdown,
	.driver		= {
		.owner = THIS_MODULE,
		.name = DRV_NAME,
	},
};

static int __init sch311x_detect(int sio_config_port, unsigned short *addr)
{
	int err = 0, reg;
	unsigned short base_addr;
	unsigned char dev_id;

	sch311x_sio_enter(sio_config_port);

	/* Check device ID. We currently know about:
	 * SCH3112 (0x7c), SCH3114 (0x7d), and SCH3116 (0x7f). */
	reg = force_id ? force_id : sch311x_sio_inb(sio_config_port, 0x20);
	if (!(reg == 0x7c || reg == 0x7d || reg == 0x7f)) {
		err = -ENODEV;
		goto exit;
	}
	dev_id = reg == 0x7c ? 2 : reg == 0x7d ? 4 : 6;

	/* Select logical device A (runtime registers) */
	sch311x_sio_outb(sio_config_port, 0x07, 0x0a);

	/* Check if Logical Device Register is currently active */
	if ((sch311x_sio_inb(sio_config_port, 0x30) & 0x01) == 0)
		printk(KERN_INFO PFX "Seems that LDN 0x0a is not active...\n");

	/* Get the base address of the runtime registers */
	base_addr = (sch311x_sio_inb(sio_config_port, 0x60) << 8) |
			   sch311x_sio_inb(sio_config_port, 0x61);
	if (!base_addr) {
		printk(KERN_ERR PFX "Base address not set.\n");
		err = -ENODEV;
		goto exit;
	}
	*addr = base_addr;

	printk(KERN_INFO PFX "Found an SMSC SCH311%d chip at 0x%04x\n",
		dev_id, base_addr);

exit:
	sch311x_sio_exit(sio_config_port);
	return err;
}

static int __init sch311x_wdt_init(void)
{
	int err, i, found = 0;
	unsigned short addr = 0;

	for (i = 0; !found && sch311x_ioports[i]; i++)
		if (sch311x_detect(sch311x_ioports[i], &addr) == 0)
			found++;

	if (!found)
		return -ENODEV;

	sch311x_wdt_data.runtime_reg = addr;

	err = platform_driver_register(&sch311x_wdt_driver);
	if (err)
		return err;

	sch311x_wdt_pdev = platform_device_register_simple(DRV_NAME, addr,
								NULL, 0);

	if (IS_ERR(sch311x_wdt_pdev)) {
		err = PTR_ERR(sch311x_wdt_pdev);
		goto unreg_platform_driver;
	}

	return 0;

unreg_platform_driver:
	platform_driver_unregister(&sch311x_wdt_driver);
	return err;
}
Ejemplo n.º 7
0
int sock_getsockopt(struct socket *sock, int level, int optname,
		    char *optval, int *optlen)
{
	struct sock *sk = sock->sk;
	
	union
	{
  		int val;
  		struct linger ling;
		struct timeval tm;
	} v;
	
	unsigned int lv=sizeof(int),len;
  	
  	if(get_user(len,optlen))
  		return -EFAULT;
	if(len < 0)
		return -EINVAL;
		
  	switch(optname) 
  	{
		case SO_DEBUG:		
			v.val = sk->debug;
			break;
		
		case SO_DONTROUTE:
			v.val = sk->localroute;
			break;
		
		case SO_BROADCAST:
			v.val= sk->broadcast;
			break;

		case SO_SNDBUF:
			v.val=sk->sndbuf;
			break;
		
		case SO_RCVBUF:
			v.val =sk->rcvbuf;
			break;

		case SO_REUSEADDR:
			v.val = sk->reuse;
			break;

		case SO_KEEPALIVE:
			v.val = sk->keepopen;
			break;

		case SO_TYPE:
			v.val = sk->type;		  		
			break;

		case SO_ERROR:
			v.val = -sock_error(sk);
			if(v.val==0)
				v.val=xchg(&sk->err_soft,0);
			break;

		case SO_OOBINLINE:
			v.val = sk->urginline;
			break;
	
		case SO_NO_CHECK:
			v.val = sk->no_check;
			break;

		case SO_PRIORITY:
			v.val = sk->priority;
			break;
		
		case SO_LINGER:	
			lv=sizeof(v.ling);
			v.ling.l_onoff=sk->linger;
 			v.ling.l_linger=sk->lingertime/HZ;
			break;
					
		case SO_BSDCOMPAT:
			v.val = sk->bsdism;
			break;

		case SO_TIMESTAMP:
			v.val = sk->rcvtstamp;
			break;

		case SO_RCVTIMEO:
			lv=sizeof(struct timeval);
			if (sk->rcvtimeo == MAX_SCHEDULE_TIMEOUT) {
				v.tm.tv_sec = 0;
				v.tm.tv_usec = 0;
			} else {
				v.tm.tv_sec = sk->rcvtimeo/HZ;
				v.tm.tv_usec = ((sk->rcvtimeo%HZ)*1000)/HZ;
			}
			break;

		case SO_SNDTIMEO:
			lv=sizeof(struct timeval);
			if (sk->sndtimeo == MAX_SCHEDULE_TIMEOUT) {
				v.tm.tv_sec = 0;
				v.tm.tv_usec = 0;
			} else {
				v.tm.tv_sec = sk->sndtimeo/HZ;
				v.tm.tv_usec = ((sk->sndtimeo%HZ)*1000)/HZ;
			}
			break;

		case SO_RCVLOWAT:
			v.val = sk->rcvlowat;
			break;

		case SO_SNDLOWAT:
			v.val=1;
			break; 

		case SO_PASSCRED:
			v.val = sock->passcred;
			break;

		case SO_PEERCRED:
			if (len > sizeof(sk->peercred))
				len = sizeof(sk->peercred);
			if (copy_to_user(optval, &sk->peercred, len))
				return -EFAULT;
			goto lenout;

		case SO_PEERNAME:
		{
			char address[128];

			if (sock->ops->getname(sock, (struct sockaddr *)address, &lv, 2))
				return -ENOTCONN;
			if (lv < len)
				return -EINVAL;
			if(copy_to_user((void*)optval, address, len))
				return -EFAULT;
			goto lenout;
		}

		/* Dubious BSD thing... Probably nobody even uses it, but
		 * the UNIX standard wants it for whatever reason... -DaveM
		 */
		case SO_ACCEPTCONN:
			v.val = (sk->state == TCP_LISTEN);
			break;

		default:
			return(-ENOPROTOOPT);
	}
	if (len > lv)
		len = lv;
	if (copy_to_user(optval, &v, len))
		return -EFAULT;
lenout:
  	if (put_user(len, optlen))
  		return -EFAULT;
  	return 0;
}
Ejemplo n.º 8
0
asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
			  unsigned long arg4, unsigned long arg5)
{
	int error;
	int sig;

	error = security_task_prctl(option, arg2, arg3, arg4, arg5);
	if (error)
		return error;

	switch (option) {
		case PR_SET_PDEATHSIG:
			sig = arg2;
			if (sig < 0 || sig > _NSIG) {
				error = -EINVAL;
				break;
			}
			current->pdeath_signal = sig;
			break;
		case PR_GET_PDEATHSIG:
			error = put_user(current->pdeath_signal, (int __user *)arg2);
			break;
		case PR_GET_DUMPABLE:
			if (current->mm->dumpable)
				error = 1;
			break;
		case PR_SET_DUMPABLE:
			if (arg2 != 0 && arg2 != 1) {
				error = -EINVAL;
				break;
			}
			current->mm->dumpable = arg2;
			break;

		case PR_SET_UNALIGN:
			error = SET_UNALIGN_CTL(current, arg2);
			break;
		case PR_GET_UNALIGN:
			error = GET_UNALIGN_CTL(current, arg2);
			break;
		case PR_SET_FPEMU:
			error = SET_FPEMU_CTL(current, arg2);
			break;
		case PR_GET_FPEMU:
			error = GET_FPEMU_CTL(current, arg2);
			break;
		case PR_SET_FPEXC:
			error = SET_FPEXC_CTL(current, arg2);
			break;
		case PR_GET_FPEXC:
			error = GET_FPEXC_CTL(current, arg2);
			break;
		case PR_GET_TIMING:
			error = PR_TIMING_STATISTICAL;
			break;
		case PR_SET_TIMING:
			if (arg2 == PR_TIMING_STATISTICAL)
				error = 0;
			else
				error = -EINVAL;
			break;

		case PR_GET_KEEPCAPS:
			if (current->keep_capabilities)
				error = 1;
			break;
		case PR_SET_KEEPCAPS:
			if (arg2 != 0 && arg2 != 1) {
				error = -EINVAL;
				break;
			}
			current->keep_capabilities = arg2;
			break;
		default:
			error = -EINVAL;
			break;
	}
	return error;
}
Ejemplo n.º 9
0
/*
 * handle the arch-specific side of process tracing
 */
long arch_ptrace(struct task_struct *child, long request,
		 unsigned long addr, unsigned long data)
{
	unsigned long tmp;
	int ret;
	unsigned long __user *datap = (unsigned long __user *) data;

	switch (request) {
	/* read the word at location addr in the USER area. */
	case PTRACE_PEEKUSR:
		ret = -EIO;
		if ((addr & 3) || addr > sizeof(struct user) - 3)
			break;

		tmp = 0;  /* Default return condition */
		if (addr < NR_PTREGS << 2)
			tmp = get_stack_long(child,
					     ptrace_regid_to_frame[addr]);
		ret = put_user(tmp, datap);
		break;

		/* write the word at location addr in the USER area */
	case PTRACE_POKEUSR:
		ret = -EIO;
		if ((addr & 3) || addr > sizeof(struct user) - 3)
			break;

		ret = 0;
		if (addr < NR_PTREGS << 2)
			ret = put_stack_long(child, ptrace_regid_to_frame[addr],
					     data);
		break;

	case PTRACE_GETREGS:	/* Get all integer regs from the child. */
		return copy_regset_to_user(child, &user_mn10300_native_view,
					   REGSET_GENERAL,
					   0, NR_PTREGS * sizeof(long),
					   datap);

	case PTRACE_SETREGS:	/* Set all integer regs in the child. */
		return copy_regset_from_user(child, &user_mn10300_native_view,
					     REGSET_GENERAL,
					     0, NR_PTREGS * sizeof(long),
					     datap);

	case PTRACE_GETFPREGS:	/* Get the child FPU state. */
		return copy_regset_to_user(child, &user_mn10300_native_view,
					   REGSET_FPU,
					   0, sizeof(struct fpu_state_struct),
					   datap);

	case PTRACE_SETFPREGS:	/* Set the child FPU state. */
		return copy_regset_from_user(child, &user_mn10300_native_view,
					     REGSET_FPU,
					     0, sizeof(struct fpu_state_struct),
					     datap);

	default:
		ret = ptrace_request(child, request, addr, data);
		break;
	}

	return ret;
}
Ejemplo n.º 10
0
static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen)
{
	struct sock *sk = sock->sk;
	struct l2cap_options opts;
	struct l2cap_conninfo cinfo;
	int len, err = 0;
	u32 opt;

	BT_DBG("sk %p", sk);

	if (get_user(len, optlen))
		return -EFAULT;

	lock_sock(sk);

	switch (optname) {
	case L2CAP_OPTIONS:
		memset(&opts, 0, sizeof(opts));
		opts.imtu     = l2cap_pi(sk)->imtu;
		opts.omtu     = l2cap_pi(sk)->omtu;
		opts.flush_to = l2cap_pi(sk)->flush_to;
		opts.mode     = l2cap_pi(sk)->mode;
		opts.fcs      = l2cap_pi(sk)->fcs;
		opts.max_tx   = l2cap_pi(sk)->max_tx;
		opts.txwin_size = (__u16)l2cap_pi(sk)->tx_win;

		len = min_t(unsigned int, len, sizeof(opts));
		if (copy_to_user(optval, (char *) &opts, len))
			err = -EFAULT;

		break;

	case L2CAP_LM:
		switch (l2cap_pi(sk)->sec_level) {
		case BT_SECURITY_LOW:
			opt = L2CAP_LM_AUTH;
			break;
		case BT_SECURITY_MEDIUM:
			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT;
			break;
		case BT_SECURITY_HIGH:
			opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT |
							L2CAP_LM_SECURE;
			break;
		default:
			opt = 0;
			break;
		}

		if (l2cap_pi(sk)->role_switch)
			opt |= L2CAP_LM_MASTER;

		if (l2cap_pi(sk)->force_reliable)
			opt |= L2CAP_LM_RELIABLE;

		if (put_user(opt, (u32 __user *) optval))
			err = -EFAULT;
		break;

	case L2CAP_CONNINFO:
		if (sk->sk_state != BT_CONNECTED &&
					!(sk->sk_state == BT_CONNECT2 &&
						bt_sk(sk)->defer_setup)) {
			err = -ENOTCONN;
			break;
		}

		cinfo.hci_handle = l2cap_pi(sk)->conn->hcon->handle;
		memcpy(cinfo.dev_class, l2cap_pi(sk)->conn->hcon->dev_class, 3);

		len = min_t(unsigned int, len, sizeof(cinfo));
		if (copy_to_user(optval, (char *) &cinfo, len))
			err = -EFAULT;

		break;

	default:
		err = -ENOPROTOOPT;
		break;
	}

	release_sock(sk);
	return err;
}
Ejemplo n.º 11
0
static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
{
	struct sock *sk = sock->sk;
	struct bt_security sec;
	struct bt_power pwr;
	int len, err = 0;

	BT_DBG("sk %p", sk);

	if (level == SOL_L2CAP)
		return l2cap_sock_getsockopt_old(sock, optname, optval, optlen);

	if (level != SOL_BLUETOOTH)
		return -ENOPROTOOPT;

	if (get_user(len, optlen))
		return -EFAULT;

	lock_sock(sk);

	switch (optname) {
	case BT_SECURITY:
		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
				&& sk->sk_type != SOCK_RAW) {
			err = -EINVAL;
			break;
		}

		sec.level = l2cap_pi(sk)->sec_level;

		len = min_t(unsigned int, len, sizeof(sec));
		if (copy_to_user(optval, (char *) &sec, len))
			err = -EFAULT;

		break;

	case BT_DEFER_SETUP:
		if (sk->sk_state != BT_BOUND && sk->sk_state != BT_LISTEN) {
			err = -EINVAL;
			break;
		}

		if (put_user(bt_sk(sk)->defer_setup, (u32 __user *) optval))
			err = -EFAULT;

		break;

	case BT_FLUSHABLE:
		if (put_user(l2cap_pi(sk)->flushable, (u32 __user *) optval))
			err = -EFAULT;

		break;

	case BT_POWER:
		if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM
				&& sk->sk_type != SOCK_RAW) {
			err = -EINVAL;
			break;
		}

		pwr.force_active = l2cap_pi(sk)->force_active;

		len = min_t(unsigned int, len, sizeof(pwr));
		if (copy_to_user(optval, (char *) &pwr, len))
			err = -EFAULT;

		break;

	default:
		err = -ENOPROTOOPT;
		break;
	}

	release_sock(sk);
	return err;
}
static long efi_rtc_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{

	efi_status_t	status;
	unsigned long	flags;
	efi_time_t	eft;
	efi_time_cap_t	cap;
	struct rtc_time	wtime;
	struct rtc_wkalrm __user *ewp;
	unsigned char	enabled, pending;

	switch (cmd) {
		case RTC_UIE_ON:
		case RTC_UIE_OFF:
		case RTC_PIE_ON:
		case RTC_PIE_OFF:
		case RTC_AIE_ON:
		case RTC_AIE_OFF:
		case RTC_ALM_SET:
		case RTC_ALM_READ:
		case RTC_IRQP_READ:
		case RTC_IRQP_SET:
		case RTC_EPOCH_READ:
		case RTC_EPOCH_SET:
			return -EINVAL;

		case RTC_RD_TIME:
			spin_lock_irqsave(&efi_rtc_lock, flags);

			status = efi.get_time(&eft, &cap);

			spin_unlock_irqrestore(&efi_rtc_lock,flags);

			if (status != EFI_SUCCESS) {
				/* should never happen */
				printk(KERN_ERR "efitime: can't read time\n");
				return -EINVAL;
			}

			convert_from_efi_time(&eft, &wtime);

			return copy_to_user((void __user *)arg, &wtime,
					    sizeof (struct rtc_time)) ? - EFAULT : 0;

		case RTC_SET_TIME:

			if (!capable(CAP_SYS_TIME)) return -EACCES;

			if (copy_from_user(&wtime, (struct rtc_time __user *)arg,
					   sizeof(struct rtc_time)) )
				return -EFAULT;

			convert_to_efi_time(&wtime, &eft);

			spin_lock_irqsave(&efi_rtc_lock, flags);

			status = efi.set_time(&eft);

			spin_unlock_irqrestore(&efi_rtc_lock,flags);

			return status == EFI_SUCCESS ? 0 : -EINVAL;

		case RTC_WKALM_SET:

			if (!capable(CAP_SYS_TIME)) return -EACCES;

			ewp = (struct rtc_wkalrm __user *)arg;

			if (  get_user(enabled, &ewp->enabled)
			   || copy_from_user(&wtime, &ewp->time, sizeof(struct rtc_time)) )
				return -EFAULT;

			convert_to_efi_time(&wtime, &eft);

			spin_lock_irqsave(&efi_rtc_lock, flags);
			/*
			 * XXX Fixme:
			 * As of EFI 0.92 with the firmware I have on my
			 * machine this call does not seem to work quite
			 * right
			 */
			status = efi.set_wakeup_time((efi_bool_t)enabled, &eft);

			spin_unlock_irqrestore(&efi_rtc_lock,flags);

			return status == EFI_SUCCESS ? 0 : -EINVAL;

		case RTC_WKALM_RD:

			spin_lock_irqsave(&efi_rtc_lock, flags);

			status = efi.get_wakeup_time((efi_bool_t *)&enabled, (efi_bool_t *)&pending, &eft);

			spin_unlock_irqrestore(&efi_rtc_lock,flags);

			if (status != EFI_SUCCESS) return -EINVAL;

			ewp = (struct rtc_wkalrm __user *)arg;

			if (  put_user(enabled, &ewp->enabled)
			   || put_user(pending, &ewp->pending)) return -EFAULT;

			convert_from_efi_time(&eft, &wtime);

			return copy_to_user(&ewp->time, &wtime,
					    sizeof(struct rtc_time)) ? -EFAULT : 0;
	}
	return -ENOTTY;
}
Ejemplo n.º 13
0
static int genregs32_get(struct task_struct *target,
			 const struct user_regset *regset,
			 unsigned int pos, unsigned int count,
			 void *kbuf, void __user *ubuf)
{
	const struct pt_regs *regs = target->thread.kregs;
	unsigned long __user *reg_window;
	unsigned long *k = kbuf;
	unsigned long __user *u = ubuf;
	unsigned long reg;

	if (target == current)
		flush_user_windows();

	pos /= sizeof(reg);
	count /= sizeof(reg);

	if (kbuf) {
		for (; count > 0 && pos < 16; count--)
			*k++ = regs->u_regs[pos++];

		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
		reg_window -= 16;
		for (; count > 0 && pos < 32; count--) {
			if (get_user(*k++, &reg_window[pos++]))
				return -EFAULT;
		}
	} else {
		for (; count > 0 && pos < 16; count--) {
			if (put_user(regs->u_regs[pos++], u++))
				return -EFAULT;
		}

		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
		reg_window -= 16;
		for (; count > 0 && pos < 32; count--) {
			if (get_user(reg, &reg_window[pos++]) ||
			    put_user(reg, u++))
				return -EFAULT;
		}
	}
	while (count > 0) {
		switch (pos) {
		case 32: /* PSR */
			reg = regs->psr;
			break;
		case 33: /* PC */
			reg = regs->pc;
			break;
		case 34: /* NPC */
			reg = regs->npc;
			break;
		case 35: /* Y */
			reg = regs->y;
			break;
		case 36: /* WIM */
		case 37: /* TBR */
			reg = 0;
			break;
		default:
			goto finish;
		}

		if (kbuf)
			*k++ = reg;
		else if (put_user(reg, u++))
			return -EFAULT;
		pos++;
		count--;
	}
finish:
	pos *= sizeof(reg);
	count *= sizeof(reg);

	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
					38 * sizeof(reg), -1);
}
Ejemplo n.º 14
0
static int genregs32_set(struct task_struct *target,
			 const struct user_regset *regset,
			 unsigned int pos, unsigned int count,
			 const void *kbuf, const void __user *ubuf)
{
	struct pt_regs *regs = target->thread.kregs;
	unsigned long __user *reg_window;
	const unsigned long *k = kbuf;
	const unsigned long __user *u = ubuf;
	unsigned long reg;

	if (target == current)
		flush_user_windows();

	pos /= sizeof(reg);
	count /= sizeof(reg);

	if (kbuf) {
		for (; count > 0 && pos < 16; count--)
			regs->u_regs[pos++] = *k++;

		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
		reg_window -= 16;
		for (; count > 0 && pos < 32; count--) {
			if (put_user(*k++, &reg_window[pos++]))
				return -EFAULT;
		}
	} else {
		for (; count > 0 && pos < 16; count--) {
			if (get_user(reg, u++))
				return -EFAULT;
			regs->u_regs[pos++] = reg;
		}

		reg_window = (unsigned long __user *) regs->u_regs[UREG_I6];
		reg_window -= 16;
		for (; count > 0 && pos < 32; count--) {
			if (get_user(reg, u++) ||
			    put_user(reg, &reg_window[pos++]))
				return -EFAULT;
		}
	}
	while (count > 0) {
		unsigned long psr;

		if (kbuf)
			reg = *k++;
		else if (get_user(reg, u++))
			return -EFAULT;

		switch (pos) {
		case 32: /* PSR */
			psr = regs->psr;
			psr &= ~(PSR_ICC | PSR_SYSCALL);
			psr |= (reg & (PSR_ICC | PSR_SYSCALL));
			regs->psr = psr;
			break;
		case 33: /* PC */
			regs->pc = reg;
			break;
		case 34: /* NPC */
			regs->npc = reg;
			break;
		case 35: /* Y */
			regs->y = reg;
			break;
		case 36: /* WIM */
		case 37: /* TBR */
			break;
		default:
			goto finish;
		}

		pos++;
		count--;
	}
finish:
	pos *= sizeof(reg);
	count *= sizeof(reg);

	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
					 38 * sizeof(reg), -1);
}
Ejemplo n.º 15
0
static int pty_get_device_number(struct tty_struct *tty, unsigned int *value)
{
	unsigned int result = MINOR(tty->device)
		- tty->driver.minor_start + tty->driver.name_base;
	return put_user(result, value);
}
Ejemplo n.º 16
0
static int audio_ioctl(struct inode *inode, struct file *file,
		       uint cmd, ulong arg)
{
	audio_state_t *state = (audio_state_t *)file->private_data;
	audio_stream_t *os = state->output_stream;
	audio_stream_t *is = state->input_stream;
	long val;

	/* dispatch based on command */
	switch (cmd) {
	case OSS_GETVERSION:
		return put_user(SOUND_VERSION, (int *)arg);

	case SNDCTL_DSP_GETBLKSIZE:
		if (file->f_mode & FMODE_WRITE)
			return put_user(os->fragsize, (int *)arg);
		else
			return put_user(is->fragsize, (int *)arg);

	case SNDCTL_DSP_GETCAPS:
		val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;
		if (is && os)
			val |= DSP_CAP_DUPLEX;
		return put_user(val, (int *)arg);

	case SNDCTL_DSP_SETFRAGMENT:
		if (get_user(val, (long *) arg))
			return -EFAULT;
		if (file->f_mode & FMODE_READ) {
			int ret = audio_set_fragments(is, val);
			if (ret < 0)
				return ret;
			ret = put_user(ret, (int *)arg);
			if (ret)
				return ret;
		}
		if (file->f_mode & FMODE_WRITE) {
			int ret = audio_set_fragments(os, val);
			if (ret < 0)
				return ret;
			ret = put_user(ret, (int *)arg);
			if (ret)
				return ret;
		}
		return 0;

	case SNDCTL_DSP_SYNC:
		return audio_sync(file);

	case SNDCTL_DSP_SETDUPLEX:
		return 0;

	case SNDCTL_DSP_POST:
		return 0;

	case SNDCTL_DSP_GETTRIGGER:
		val = 0;
		if (file->f_mode & FMODE_READ && is->active && !is->stopped)
			val |= PCM_ENABLE_INPUT;
		if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
			val |= PCM_ENABLE_OUTPUT;
		return put_user(val, (int *)arg);

	case SNDCTL_DSP_SETTRIGGER:
		if (get_user(val, (int *)arg))
			return -EFAULT;
		if (file->f_mode & FMODE_READ) {
			if (val & PCM_ENABLE_INPUT) {
				if (!is->active) {
					if (!is->buffers && audio_setup_buf(is))
						return -ENOMEM;
					audio_prime_dma(is);
				}
				audio_check_tx_spin(state);
				if (is->stopped) {
					is->stopped = 0;
					sa1100_dma_resume(is->dma_ch);
				}
			} else {
				sa1100_dma_stop(is->dma_ch);
				is->stopped = 1;
			}
		}
		if (file->f_mode & FMODE_WRITE) {
			if (val & PCM_ENABLE_OUTPUT) {
				if (!os->active) {
					if (!os->buffers && audio_setup_buf(os))
						return -ENOMEM;
					if (os->mapped)
						audio_prime_dma(os);
				}
				if (os->stopped) {
					os->stopped = 0;
					sa1100_dma_resume(os->dma_ch);
				}
			} else {
				sa1100_dma_stop(os->dma_ch);
				os->stopped = 1;
			}
		}
		return 0;

	case SNDCTL_DSP_GETOPTR:
	case SNDCTL_DSP_GETIPTR:
	    {
		count_info inf = { 0, };
		audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
		audio_buf_t *b;
		dma_addr_t ptr;
		int bytecount, offset, flags;

		if ((s == is && !(file->f_mode & FMODE_READ)) ||
		    (s == os && !(file->f_mode & FMODE_WRITE)))
			return -EINVAL;
		if (s->active) {
			save_flags_cli(flags);
			if (sa1100_dma_get_current(s->dma_ch, (void *)&b, &ptr) == 0) {
				offset = ptr - b->dma_addr;
				inf.ptr = (b - s->buffers) * s->fragsize + offset;
			} else offset = 0;
			bytecount = s->bytecount + offset;
			s->getptrCount = s->bytecount;	/* so poll can tell if it changes */
			inf.blocks = s->fragcount;
			s->fragcount = 0;
			restore_flags(flags);
			if (bytecount < 0)
				bytecount = 0;
			inf.bytes = bytecount;
		}
		return copy_to_user((void *)arg, &inf, sizeof(inf));
	    }

	case SNDCTL_DSP_GETOSPACE:
	    {
		audio_buf_info inf = { 0, };
		int i;

		if (!(file->f_mode & FMODE_WRITE))
			return -EINVAL;
		if (!os->buffers && audio_setup_buf(os))
			return -ENOMEM;
		for (i = 0; i < os->nbfrags; i++) {
			if (atomic_read(&os->buffers[i].sem.count) > 0) {
				if (os->buffers[i].size == 0)
					inf.fragments++;
				inf.bytes += os->fragsize - os->buffers[i].size;
			}
		}
		inf.fragstotal = os->nbfrags;
		inf.fragsize = os->fragsize;
		return copy_to_user((void *)arg, &inf, sizeof(inf));
	    }

	case SNDCTL_DSP_GETISPACE:
	    {
		audio_buf_info inf = { 0, };
		int i;

		if (!(file->f_mode & FMODE_READ))
			return -EINVAL;
		if (!is->buffers && audio_setup_buf(is))
			return -ENOMEM;
		for (i = 0; i < is->nbfrags; i++) {
			if (atomic_read(&is->buffers[i].sem.count) > 0) {
				if (is->buffers[i].size == is->fragsize)
					inf.fragments++;
				inf.bytes += is->buffers[i].size;
			}
		}
		inf.fragstotal = is->nbfrags;
		inf.fragsize = is->fragsize;
		return copy_to_user((void *)arg, &inf, sizeof(inf));
	    }

	case SNDCTL_DSP_NONBLOCK:
		file->f_flags |= O_NONBLOCK;
		return 0;

	case SNDCTL_DSP_RESET:
		if (file->f_mode & FMODE_READ) {
			if (state->tx_spinning) {
				sa1100_dma_set_spin(os->dma_ch, 0, 0);
				state->tx_spinning = 0;
			}
			audio_reset_buf(is);
		}
		if (file->f_mode & FMODE_WRITE) {
			audio_reset_buf(os);
		}
		return 0;

	default:
		/*
		 * Let the client of this module handle the
		 * non generic ioctls
		 */
		return state->client_ioctl(inode, file, cmd, arg);
	}

	return 0;
}
Ejemplo n.º 17
0
int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
		unsigned long arg)
{
	struct ext3_inode_info *ei = EXT3_I(inode);
	unsigned int flags;
	unsigned short rsv_window_size;

	ext3_debug ("cmd = %u, arg = %lu\n", cmd, arg);

	switch (cmd) {
	case EXT3_IOC_GETFLAGS:
		flags = ei->i_flags & EXT3_FL_USER_VISIBLE;
		return put_user(flags, (int __user *) arg);
	case EXT3_IOC_SETFLAGS: {
		handle_t *handle = NULL;
		int err;
		struct ext3_iloc iloc;
		unsigned int oldflags;
		unsigned int jflag;

		if (IS_RDONLY(inode))
			return -EROFS;

		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
			return -EACCES;

		if (get_user(flags, (int __user *) arg))
			return -EFAULT;

		if (!S_ISDIR(inode->i_mode))
			flags &= ~EXT3_DIRSYNC_FL;

		oldflags = ei->i_flags;

		/* The JOURNAL_DATA flag is modifiable only by root */
		jflag = flags & EXT3_JOURNAL_DATA_FL;

		/*
		 * The IMMUTABLE and APPEND_ONLY flags can only be changed by
		 * the relevant capability.
		 *
		 * This test looks nicer. Thanks to Pauline Middelink
		 */
		if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) {
			if (!capable(CAP_LINUX_IMMUTABLE))
				return -EPERM;
		}

		/*
		 * The JOURNAL_DATA flag can only be changed by
		 * the relevant capability.
		 */
		if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) {
			if (!capable(CAP_SYS_RESOURCE))
				return -EPERM;
		}


		handle = ext3_journal_start(inode, 1);
		if (IS_ERR(handle))
			return PTR_ERR(handle);
		if (IS_SYNC(inode))
			handle->h_sync = 1;
		err = ext3_reserve_inode_write(handle, inode, &iloc);
		if (err)
			goto flags_err;

		flags = flags & EXT3_FL_USER_MODIFIABLE;
		flags |= oldflags & ~EXT3_FL_USER_MODIFIABLE;
		ei->i_flags = flags;

		ext3_set_inode_flags(inode);
		inode->i_ctime = CURRENT_TIME;

		err = ext3_mark_iloc_dirty(handle, inode, &iloc);
flags_err:
		ext3_journal_stop(handle);
		if (err)
			return err;

		if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL))
			err = ext3_change_inode_journal_flag(inode, jflag);
		return err;
	}
	case EXT3_IOC_GETVERSION:
	case EXT3_IOC_GETVERSION_OLD:
		return put_user(inode->i_generation, (int __user *) arg);
	case EXT3_IOC_SETVERSION:
	case EXT3_IOC_SETVERSION_OLD: {
		handle_t *handle;
		struct ext3_iloc iloc;
		__u32 generation;
		int err;

		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
			return -EPERM;
		if (IS_RDONLY(inode))
			return -EROFS;
		if (get_user(generation, (int __user *) arg))
			return -EFAULT;

		handle = ext3_journal_start(inode, 1);
		if (IS_ERR(handle))
			return PTR_ERR(handle);
		err = ext3_reserve_inode_write(handle, inode, &iloc);
		if (err == 0) {
			inode->i_ctime = CURRENT_TIME;
			inode->i_generation = generation;
			err = ext3_mark_iloc_dirty(handle, inode, &iloc);
		}
		ext3_journal_stop(handle);
		return err;
	}
#ifdef CONFIG_JBD_DEBUG
	case EXT3_IOC_WAIT_FOR_READONLY:
		/*
		 * This is racy - by the time we're woken up and running,
		 * the superblock could be released.  And the module could
		 * have been unloaded.  So sue me.
		 *
		 * Returns 1 if it slept, else zero.
		 */
		{
			struct super_block *sb = inode->i_sb;
			DECLARE_WAITQUEUE(wait, current);
			int ret = 0;

			set_current_state(TASK_INTERRUPTIBLE);
			add_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
			if (timer_pending(&EXT3_SB(sb)->turn_ro_timer)) {
				schedule();
				ret = 1;
			}
			remove_wait_queue(&EXT3_SB(sb)->ro_wait_queue, &wait);
			return ret;
		}
#endif
	case EXT3_IOC_GETRSVSZ:
		if (test_opt(inode->i_sb, RESERVATION) && S_ISREG(inode->i_mode)) {
			rsv_window_size = atomic_read(&ei->i_rsv_window.rsv_goal_size);
			return put_user(rsv_window_size, (int __user *)arg);
		}
		return -ENOTTY;
	case EXT3_IOC_SETRSVSZ:
		if (!test_opt(inode->i_sb, RESERVATION) ||!S_ISREG(inode->i_mode))
			return -ENOTTY;

		if (IS_RDONLY(inode))
			return -EROFS;

		if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER))
			return -EACCES;

		if (get_user(rsv_window_size, (int __user *)arg))
			return -EFAULT;

		if (rsv_window_size > EXT3_MAX_RESERVE_BLOCKS)
			rsv_window_size = EXT3_MAX_RESERVE_BLOCKS;
		atomic_set(&ei->i_rsv_window.rsv_goal_size, rsv_window_size);
		return 0;
	case EXT3_IOC_GROUP_EXTEND: {
		unsigned long n_blocks_count;
		struct super_block *sb = inode->i_sb;
		int err;

		if (!capable(CAP_SYS_RESOURCE))
			return -EPERM;

		if (IS_RDONLY(inode))
			return -EROFS;

		if (get_user(n_blocks_count, (__u32 __user *)arg))
			return -EFAULT;

		err = ext3_group_extend(sb, EXT3_SB(sb)->s_es, n_blocks_count);
		journal_lock_updates(EXT3_SB(sb)->s_journal);
		journal_flush(EXT3_SB(sb)->s_journal);
		journal_unlock_updates(EXT3_SB(sb)->s_journal);

		return err;
	}
	case EXT3_IOC_GROUP_ADD: {
		struct ext3_new_group_data input;
		struct super_block *sb = inode->i_sb;
		int err;

		if (!capable(CAP_SYS_RESOURCE))
			return -EPERM;

		if (IS_RDONLY(inode))
			return -EROFS;

		if (copy_from_user(&input, (struct ext3_new_group_input __user *)arg,
				sizeof(input)))
			return -EFAULT;

		err = ext3_group_add(sb, &input);
		journal_lock_updates(EXT3_SB(sb)->s_journal);
		journal_flush(EXT3_SB(sb)->s_journal);
		journal_unlock_updates(EXT3_SB(sb)->s_journal);

		return err;
	}


	default:
		return -ENOTTY;
	}
}
Ejemplo n.º 18
0
static int wdt_ioctl(struct inode *inode, struct file *file,
    unsigned int cmd, unsigned long arg)
{
    int status;
    int new_options, retval = -EINVAL;
    int new_timeout;
    union {
        struct watchdog_info __user *ident;
        int __user *i;
    } uarg;

    uarg.i = (int __user *)arg;

    switch(cmd)
    {
    default:
        return -ENOTTY;

    case WDIOC_GETSUPPORT:
        return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0;

    case WDIOC_GETSTATUS:
        wdt_get_status(&status);
        return put_user(status, uarg.i);

    case WDIOC_GETBOOTSTATUS:
        return put_user(0, uarg.i);

    case WDIOC_KEEPALIVE:
        wdt_keepalive();
        return 0;

    case WDIOC_SETOPTIONS:
        if (get_user (new_options, uarg.i))
            return -EFAULT;

        if (new_options & WDIOS_DISABLECARD) {
            wdt_stop();
            retval = 0;
        }

        if (new_options & WDIOS_ENABLECARD) {
            wdt_start();
            retval = 0;
        }

        return retval;

    case WDIOC_SETTIMEOUT:
        if (get_user(new_timeout, uarg.i))
            return -EFAULT;

        if (wdt_set_timeout(new_timeout))
            return -EINVAL;

        wdt_keepalive();
        /* Fall */

    case WDIOC_GETTIMEOUT:
        return put_user(timeout, uarg.i);

    }
}
Ejemplo n.º 19
0
static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static struct watchdog_info ident=
	{
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "SBC60xx",
	};

	switch(cmd)
	{
		default:
			return -ENOTTY;
		case WDIOC_GETSUPPORT:
			return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
		case WDIOC_GETSTATUS:
		case WDIOC_GETBOOTSTATUS:
			return put_user(0, p);
		case WDIOC_KEEPALIVE:
			wdt_keepalive();
			return 0;
		case WDIOC_SETOPTIONS:
		{
			int new_options, retval = -EINVAL;

			if(get_user(new_options, p))
				return -EFAULT;

			if(new_options & WDIOS_DISABLECARD) {
				wdt_turnoff();
				retval = 0;
			}

			if(new_options & WDIOS_ENABLECARD) {
				wdt_startup();
				retval = 0;
			}

			return retval;
		}
		case WDIOC_SETTIMEOUT:
		{
			int new_timeout;

			if(get_user(new_timeout, p))
				return -EFAULT;

			if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */
				return -EINVAL;

			timeout = new_timeout;
			wdt_keepalive();
			/* Fall through */
		}
		case WDIOC_GETTIMEOUT:
			return put_user(timeout, p);
	}
}

static const struct file_operations wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= fop_write,
	.open		= fop_open,
	.release	= fop_close,
	.ioctl		= fop_ioctl,
};

static struct miscdevice wdt_miscdev = {
	.minor = WATCHDOG_MINOR,
	.name = "watchdog",
	.fops = &wdt_fops,
};

/*
 *	Notifier for system down
 */

static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if(code==SYS_DOWN || code==SYS_HALT)
		wdt_turnoff();
	return NOTIFY_DONE;
}

/*
 *	The WDT needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 */

static struct notifier_block wdt_notifier=
{
	.notifier_call = wdt_notify_sys,
};

static void __exit sbc60xxwdt_unload(void)
{
	wdt_turnoff();

	/* Deregister */
	misc_deregister(&wdt_miscdev);

	unregister_reboot_notifier(&wdt_notifier);
	if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
		release_region(wdt_stop,1);
	release_region(wdt_start,1);
}

static int __init sbc60xxwdt_init(void)
{
	int rc = -EBUSY;

	if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */
	{
		timeout = WATCHDOG_TIMEOUT;
		printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n",
			timeout);
 	}

	if (!request_region(wdt_start, 1, "SBC 60XX WDT"))
	{
		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
			wdt_start);
		rc = -EIO;
		goto err_out;
	}

	/* We cannot reserve 0x45 - the kernel already has! */
	if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
	{
		if (!request_region(wdt_stop, 1, "SBC 60XX WDT"))
		{
			printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
				wdt_stop);
			rc = -EIO;
			goto err_out_region1;
		}
	}

	rc = register_reboot_notifier(&wdt_notifier);
	if (rc)
	{
		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
			rc);
		goto err_out_region2;
	}

	rc = misc_register(&wdt_miscdev);
	if (rc)
	{
		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
			wdt_miscdev.minor, rc);
		goto err_out_reboot;
	}

	printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

	return 0;

err_out_reboot:
	unregister_reboot_notifier(&wdt_notifier);
err_out_region2:
	if ((wdt_stop != 0x45) && (wdt_stop != wdt_start))
		release_region(wdt_stop,1);
err_out_region1:
	release_region(wdt_start,1);
err_out:
	return rc;
}
Ejemplo n.º 20
0
/**
 * ecryptfs_miscdev_read - format and send message from queue
 * @file: miscdevfs handle
 * @buf: User buffer into which to copy the next message on the daemon queue
 * @count: Amount of space available in @buf
 * @ppos: Offset in file (ignored)
 *
 * Pulls the most recent message from the daemon queue, formats it for
 * being sent via a miscdevfs handle, and copies it into @buf
 *
 * Returns the number of bytes copied into the user buffer
 */
static ssize_t
ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
		      loff_t *ppos)
{
	struct ecryptfs_daemon *daemon = file->private_data;
	struct ecryptfs_msg_ctx *msg_ctx;
	size_t packet_length_size;
	char packet_length[ECRYPTFS_MAX_PKT_LEN_SIZE];
	size_t i;
	size_t total_length;
	int rc;

	mutex_lock(&daemon->mux);
	if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
		rc = 0;
		printk(KERN_WARNING "%s: Attempt to read from zombified "
		       "daemon\n", __func__);
		goto out_unlock_daemon;
	}
	if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) {
		rc = 0;
		goto out_unlock_daemon;
	}
	/* This daemon will not go away so long as this flag is set */
	daemon->flags |= ECRYPTFS_DAEMON_IN_READ;
check_list:
	if (list_empty(&daemon->msg_ctx_out_queue)) {
		mutex_unlock(&daemon->mux);
		rc = wait_event_interruptible(
			daemon->wait, !list_empty(&daemon->msg_ctx_out_queue));
		mutex_lock(&daemon->mux);
		if (rc < 0) {
			rc = 0;
			goto out_unlock_daemon;
		}
	}
	if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
		rc = 0;
		goto out_unlock_daemon;
	}
	if (list_empty(&daemon->msg_ctx_out_queue)) {
		/* Something else jumped in since the
		 * wait_event_interruptable() and removed the
		 * message from the queue; try again */
		goto check_list;
	}
	msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
				   struct ecryptfs_msg_ctx, daemon_out_list);
	BUG_ON(!msg_ctx);
	mutex_lock(&msg_ctx->mux);
	if (msg_ctx->msg) {
		rc = ecryptfs_write_packet_length(packet_length,
						  msg_ctx->msg_size,
						  &packet_length_size);
		if (rc) {
			rc = 0;
			printk(KERN_WARNING "%s: Error writing packet length; "
			       "rc = [%d]\n", __func__, rc);
			goto out_unlock_msg_ctx;
		}
	} else {
		packet_length_size = 0;
		msg_ctx->msg_size = 0;
	}
	total_length = (PKT_TYPE_SIZE + PKT_CTR_SIZE + packet_length_size
			+ msg_ctx->msg_size);
	if (count < total_length) {
		rc = 0;
		printk(KERN_WARNING "%s: Only given user buffer of "
		       "size [%zd], but we need [%zd] to read the "
		       "pending message\n", __func__, count, total_length);
		goto out_unlock_msg_ctx;
	}
	rc = -EFAULT;
	if (put_user(msg_ctx->type, buf))
		goto out_unlock_msg_ctx;
	if (put_user(cpu_to_be32(msg_ctx->counter),
		     (__be32 __user *)(&buf[PKT_CTR_OFFSET])))
		goto out_unlock_msg_ctx;
	i = PKT_TYPE_SIZE + PKT_CTR_SIZE;
	if (msg_ctx->msg) {
		if (packet_length_size > sizeof(packet_length) || copy_to_user(&buf[i], packet_length, packet_length_size))
			goto out_unlock_msg_ctx;
		i += packet_length_size;
		if (copy_to_user(&buf[i], msg_ctx->msg, msg_ctx->msg_size))
			goto out_unlock_msg_ctx;
		i += msg_ctx->msg_size;
	}
	rc = i;
	list_del(&msg_ctx->daemon_out_list);
	kfree(msg_ctx->msg);
	msg_ctx->msg = NULL;
	/* We do not expect a reply from the userspace daemon for any
	 * message type other than ECRYPTFS_MSG_REQUEST */
	if (msg_ctx->type != ECRYPTFS_MSG_REQUEST)
		ecryptfs_msg_ctx_alloc_to_free(msg_ctx);
out_unlock_msg_ctx:
	mutex_unlock(&msg_ctx->mux);
out_unlock_daemon:
	daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ;
	mutex_unlock(&daemon->mux);
	return rc;
}
static long smschar_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct smschar_device_t *dev = file->private_data;
	void __user *up = (void __user *)arg;

	if (!dev->coredev || !dev->smsclient) {
		sms_err("no client\n");
		return -ENODEV;
	}

	switch (cmd) {
	case SMSCHAR_SET_DEVICE_MODE:
		return smscore_set_device_mode(dev->coredev, (int)arg);

	case SMSCHAR_GET_DEVICE_MODE:
		{
			if (put_user(smscore_get_device_mode(dev->coredev),
				     (int *)up))
				return -EFAULT;
			break;
		}
	case SMSCHAR_IS_DEVICE_PNP_EVENT:
		{
			sms_info("Waiting for PnP event.\n");
			wait_event_interruptible(g_pnp_event,
						 !g_pnp_status_changed);
			g_pnp_status_changed = 0;
			sms_info("PnP Event %d.\n", g_smschar_inuse);
			if (put_user(g_smschar_inuse, (int *)up))
				return -EFAULT;
			break;
		}
	case SMSCHAR_GET_BUFFER_SIZE:
		{
			if (put_user
			    (smscore_get_common_buffer_size(dev->coredev),
			     (int *)up))
				return -EFAULT;

			break;
		}

	case SMSCHAR_WAIT_GET_BUFFER:
		{
			struct smschar_buffer_t touser;
			int rc;

			rc = smschar_wait_get_buffer(dev, &touser);
			if (rc < 0)
				return rc;

			if (copy_to_user(up, &touser,
					 sizeof(struct smschar_buffer_t)))
				return -EFAULT;

			break;
		}
	case SMSCHAR_CANCEL_WAIT_BUFFER:
		{
			dev->cancel_waitq = 1;
			wake_up_interruptible(&dev->waitq);
			break;
		}
	case SMSCHAR_CANCEL_POLL:
		{
			/*obsollete*/
			break;		
		}
	case SMSCHAR_GET_FW_FILE_NAME:
		{
			if (!up)
				return -EINVAL;
			return smschar_get_fw_filename(dev,
				       (struct smschar_get_fw_filename_ioctl_t*)up);
		}
	case SMSCHAR_SEND_FW_FILE:
		{
			if (!up)
				return -EINVAL;
			return smschar_send_fw_file(dev,
					(struct smschar_send_fw_file_ioctl_t*)up);
		}

	default:
		return -ENOIOCTLCMD;
	}

	return 0;
}
Ejemplo n.º 22
0
int audio_ioctl(int dev, struct file *file, unsigned int cmd, void __user *arg)
{
	int val, count;
	unsigned long flags;
	struct dma_buffparms *dmap;
	int __user *p = arg;

	dev = dev >> 4;

	if (_IOC_TYPE(cmd) == 'C')	{
		if (audio_devs[dev]->coproc)	/* Coprocessor ioctl */
			return audio_devs[dev]->coproc->ioctl(audio_devs[dev]->coproc->devc, cmd, arg, 0);
		/* else
		        printk(KERN_DEBUG"/dev/dsp%d: No coprocessor for this device\n", dev); */
		return -ENXIO;
	}
	else switch (cmd) 
	{
		case SNDCTL_DSP_SYNC:
			if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
				return 0;
			if (audio_devs[dev]->dmap_out->fragment_size == 0)
				return 0;
			sync_output(dev);
			DMAbuf_sync(dev);
			DMAbuf_reset(dev);
			return 0;

		case SNDCTL_DSP_POST:
			if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
				return 0;
			if (audio_devs[dev]->dmap_out->fragment_size == 0)
				return 0;
			audio_devs[dev]->dmap_out->flags |= DMA_POST | DMA_DIRTY;
			sync_output(dev);
			dma_ioctl(dev, SNDCTL_DSP_POST, NULL);
			return 0;

		case SNDCTL_DSP_RESET:
			audio_devs[dev]->audio_mode = AM_NONE;
			DMAbuf_reset(dev);
			return 0;

		case SNDCTL_DSP_GETFMTS:
			val = audio_devs[dev]->format_mask | AFMT_MU_LAW;
			break;
	
		case SNDCTL_DSP_SETFMT:
			if (get_user(val, p))
				return -EFAULT;
			val = set_format(dev, val);
			break;

		case SNDCTL_DSP_GETISPACE:
			if (!(audio_devs[dev]->open_mode & OPEN_READ))
				return 0;
  			if ((audio_devs[dev]->audio_mode & AM_WRITE) && !(audio_devs[dev]->flags & DMA_DUPLEX))
  				return -EBUSY;
			return dma_ioctl(dev, cmd, arg);

		case SNDCTL_DSP_GETOSPACE:
			if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
				return -EPERM;
  			if ((audio_devs[dev]->audio_mode & AM_READ) && !(audio_devs[dev]->flags & DMA_DUPLEX))
  				return -EBUSY;
			return dma_ioctl(dev, cmd, arg);
		
		case SNDCTL_DSP_NONBLOCK:
			spin_lock(&file->f_lock);
			file->f_flags |= O_NONBLOCK;
			spin_unlock(&file->f_lock);
			return 0;

		case SNDCTL_DSP_GETCAPS:
				val = 1 | DSP_CAP_MMAP;	/* Revision level of this ioctl() */
				if (audio_devs[dev]->flags & DMA_DUPLEX &&
					audio_devs[dev]->open_mode == OPEN_READWRITE)
					val |= DSP_CAP_DUPLEX;
				if (audio_devs[dev]->coproc)
					val |= DSP_CAP_COPROC;
				if (audio_devs[dev]->d->local_qlen)	/* Device has hidden buffers */
					val |= DSP_CAP_BATCH;
				if (audio_devs[dev]->d->trigger)	/* Supports SETTRIGGER */
					val |= DSP_CAP_TRIGGER;
				break;
			
		case SOUND_PCM_WRITE_RATE:
			if (get_user(val, p))
				return -EFAULT;
			val = audio_devs[dev]->d->set_speed(dev, val);
			break;

		case SOUND_PCM_READ_RATE:
			val = audio_devs[dev]->d->set_speed(dev, 0);
			break;
			
		case SNDCTL_DSP_STEREO:
			if (get_user(val, p))
				return -EFAULT;
			if (val > 1 || val < 0)
				return -EINVAL;
			val = audio_devs[dev]->d->set_channels(dev, val + 1) - 1;
			break;

		case SOUND_PCM_WRITE_CHANNELS:
			if (get_user(val, p))
				return -EFAULT;
			val = audio_devs[dev]->d->set_channels(dev, val);
			break;

		case SOUND_PCM_READ_CHANNELS:
			val = audio_devs[dev]->d->set_channels(dev, 0);
			break;
		
		case SOUND_PCM_READ_BITS:
			val = audio_devs[dev]->d->set_bits(dev, 0);
			break;

		case SNDCTL_DSP_SETDUPLEX:
			if (audio_devs[dev]->open_mode != OPEN_READWRITE)
				return -EPERM;
			return (audio_devs[dev]->flags & DMA_DUPLEX) ? 0 : -EIO;

		case SNDCTL_DSP_PROFILE:
			if (get_user(val, p))
				return -EFAULT;
			if (audio_devs[dev]->open_mode & OPEN_WRITE)
				audio_devs[dev]->dmap_out->applic_profile = val;
			if (audio_devs[dev]->open_mode & OPEN_READ)
				audio_devs[dev]->dmap_in->applic_profile = val;
			return 0;
		
		case SNDCTL_DSP_GETODELAY:
			dmap = audio_devs[dev]->dmap_out;
			if (!(audio_devs[dev]->open_mode & OPEN_WRITE))
				return -EINVAL;
			if (!(dmap->flags & DMA_ALLOC_DONE))
			{
				val=0;
				break;
			}
		
			spin_lock_irqsave(&dmap->lock,flags);
			/* Compute number of bytes that have been played */
			count = DMAbuf_get_buffer_pointer (dev, dmap, DMODE_OUTPUT);
			if (count < dmap->fragment_size && dmap->qhead != 0)
				count += dmap->bytes_in_use;	/* Pointer wrap not handled yet */
			count += dmap->byte_counter;
		
			/* Subtract current count from the number of bytes written by app */
			count = dmap->user_counter - count;
			if (count < 0)
				count = 0;
			spin_unlock_irqrestore(&dmap->lock,flags);
			val = count;
			break;
		
		default:
			return dma_ioctl(dev, cmd, arg);
	}
	return put_user(val, p);
}
Ejemplo n.º 23
0
/*
 *  Ok, this is the main fork-routine.
 *
 * It copies the process, and if successful kick-starts
 * it and waits for it to finish using the VM if required.
 */
long do_fork(unsigned long clone_flags,
	      unsigned long stack_start,
	      struct pt_regs *regs,
	      unsigned long stack_size,
	      int __user *parent_tidptr,
	      int __user *child_tidptr)
{
	struct task_struct *p;
	int trace = 0;
	long nr;

	/*
	 * Do some preliminary argument and permissions checking before we
	 * actually start allocating stuff
	 */
	if (clone_flags & CLONE_NEWUSER) {
		if (clone_flags & CLONE_THREAD)
			return -EINVAL;
		/* hopefully this check will go away when userns support is
		 * complete
		 */
		if (!capable(CAP_SYS_ADMIN) || !capable(CAP_SETUID) ||
				!capable(CAP_SETGID))
			return -EPERM;
	}

	/*
	 * We hope to recycle these flags after 2.6.26
	 */
	if (unlikely(clone_flags & CLONE_STOPPED)) {
		static int __read_mostly count = 100;

		if (count > 0 && printk_ratelimit()) {
			char comm[TASK_COMM_LEN];

			count--;
			printk(KERN_INFO "fork(): process `%s' used deprecated "
					"clone flags 0x%lx\n",
				get_task_comm(comm, current),
				clone_flags & CLONE_STOPPED);
		}
	}

	/*
	 * When called from kernel_thread, don't do user tracing stuff.
	 */
	if (likely(user_mode(regs)))
		trace = tracehook_prepare_clone(clone_flags);

	p = copy_process(clone_flags, stack_start, regs, stack_size,
			 child_tidptr, NULL, trace);
	/*
	 * Do this prior waking up the new thread - the thread pointer
	 * might get invalid after that point, if the thread exits quickly.
	 */
	if (!IS_ERR(p)) {
		struct completion vfork;

		trace_sched_process_fork(current, p);

		nr = task_pid_vnr(p);

		if (clone_flags & CLONE_PARENT_SETTID)
			put_user(nr, parent_tidptr);

		if (clone_flags & CLONE_VFORK) {
			p->vfork_done = &vfork;
			init_completion(&vfork);
		}

		audit_finish_fork(p);
		tracehook_report_clone(regs, clone_flags, nr, p);

		/*
		 * We set PF_STARTING at creation in case tracing wants to
		 * use this to distinguish a fully live task from one that
		 * hasn't gotten to tracehook_report_clone() yet.  Now we
		 * clear it and set the child going.
		 */
		p->flags &= ~PF_STARTING;

		if (unlikely(clone_flags & CLONE_STOPPED)) {
			/*
			 * We'll start up with an immediate SIGSTOP.
			 */
			sigaddset(&p->pending.signal, SIGSTOP);
			set_tsk_thread_flag(p, TIF_SIGPENDING);
			__set_task_state(p, TASK_STOPPED);
		} else {
			wake_up_new_task(p, clone_flags);
		}

		tracehook_report_clone_complete(trace, regs,
						clone_flags, nr, p);

		if (clone_flags & CLONE_VFORK) {
			freezer_do_not_count();
			wait_for_completion(&vfork);
			freezer_count();
			tracehook_report_vfork_done(p, nr);
		}
	} else {
		nr = PTR_ERR(p);
	}
	return nr;
}
Ejemplo n.º 24
0
static long lis3df_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int rc = 0;
	Accelerometer* data = i2c_get_clientdata(this_client);

	#if debug
	pr_info("%s cmd:%d, arg:%ld\n", __func__, _IOC_NR(cmd), arg);
	#endif

	mutex_lock(&Lis3df_global_lock);
	switch(cmd){
		case ACCELEROMETER_IOCTL_SET_STATE:
			rc = arg ? lis3df_enable() : lis3df_disable();
			break;
		case ACCELEROMETER_IOCTL_GET_STATE:
			mutex_lock(&data->mutex);
			put_user(data->enabled, (unsigned long __user *) arg);
			mutex_unlock(&data->mutex);
			break;
		case ACCELEROMETER_IOCTL_GET_DEVICE_INFOR:
		{
			struct device_infor infor = {
				.name		= "Accelerometer Sensor",
				.vendor		= "ST Microelectionics",
				.maxRange	= 2,// 2G
				.resolution	= 128,// 2G / 128
				.power		= 700,// uA
			};
			rc = copy_to_user((unsigned long __user *)arg, (char *)&(infor), sizeof(struct device_infor));
			break;
		}
		case ACCELEROMETER_IOCTL_SET_DELAY:
		{
			arg = (arg >= 10) ? arg : 10;
			SleepTime = msecs_to_jiffies(--arg);// To makeure timer is exactly.
			break;
		}
		case ACCELEROMETER_IOCTL_SET_AXIS_OFFSET:
		{
			char* tmp = NULL;
			AccelerometerAxisOffset* offset = kzalloc(sizeof(AccelerometerAxisOffset), GFP_KERNEL);
			rc = copy_from_user(offset, (unsigned long __user *) arg, sizeof(AccelerometerAxisOffset));
			mutex_lock(&data->mutex);
			offset->X += data->odata.X;
			offset->Y += data->odata.Y;
			offset->Z += data->odata.Z;
			mutex_unlock(&data->mutex);
			tmp = lis3df_resetAxisOffset(offset->X, offset->Y, offset->Z);
			rc = (tmp != NULL) ? 1 : -1;
			kfree(tmp);
			kfree(offset);
			break;
		}
		case ACCELEROMETER_IOCTL_SET_AXIS_OFFSET_INIT:
		{
			char* tmp = lis3df_resetAxisOffset(0, 0, 0);
			rc = (tmp != NULL) ? 1 : -1;
			kfree(tmp);
			break;
		}
		default:
			pr_err("%s: invalid cmd %d\n", __func__, _IOC_NR(cmd));
			rc = -EINVAL;
	}
	mutex_unlock(&Lis3df_global_lock);

	return rc;
}

static struct file_operations lis3df_fops = {
	.owner = THIS_MODULE,
	.open = lis3df_open,
	.release = lis3df_release,
	.unlocked_ioctl = lis3df_ioctl
};

struct miscdevice lis3df_misc = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = "accelerometer",
	.fops = &lis3df_fops
};

// Return true if data ready to report
static bool lis3df_readData(void){
	memset(&rawData, 0, sizeof(AccelerometerData));
	rawData.Y = i2c_smbus_read_byte_data(this_client, ACCELEROMETER_REG_OUT_X);
	rawData.Y = (rawData.Y < 128) ? rawData.Y : (rawData.Y - 256);
	rawData.Y = (rawData.Y * 10000) >> 6;
	rawData.X = i2c_smbus_read_byte_data(this_client, ACCELEROMETER_REG_OUT_Y);
	rawData.X = (rawData.X < 128) ? rawData.X : (rawData.X - 256);
	rawData.X = (rawData.X * 10000) >> 6;
	rawData.Z = i2c_smbus_read_byte_data(this_client, ACCELEROMETER_REG_OUT_Z);
	rawData.Z = (rawData.Z < 128) ? rawData.Z : (rawData.Z - 256);
	rawData.Z = (rawData.Z * 10000) >> 6;
	memcpy(&(queueData[queueIndex]), &rawData, sizeof(AccelerometerData));
	queueIndex = (queueIndex < FILTER_INDEX) ? queueIndex + 1 : 0;
	ignoreCount = (ignoreCount < FILTER_INDEX) ? ignoreCount + 1 : ignoreCount;
	return (ignoreCount == FILTER_INDEX);
}

static void lis3df_reportData(Accelerometer* data){
	u8 i = 0;
	memset(&averageData, 0, sizeof(AccelerometerData));
	for( ; i < FILTER_SIZE ; ++i){
		averageData.X += queueData[i].X >> FILTER_SIZEBIT;
		averageData.Y += queueData[i].Y >> FILTER_SIZEBIT;
		averageData.Z += queueData[i].Z >> FILTER_SIZEBIT;
	}
	mutex_lock(&data->mutex);
	memcpy(&(data->sdata), &averageData, sizeof(AccelerometerData));
	mutex_unlock(&data->mutex);
	input_report_abs(data->input, ABS_X, (0 - data->sdata.X) - data->odata.X);
	input_report_abs(data->input, ABS_Y, data->sdata.Y - data->odata.Y);
	input_report_abs(data->input, ABS_Z, data->sdata.Z - data->odata.Z);
	input_sync(data->input);
}
Ejemplo n.º 25
0
static int pty_get_lock(struct tty_struct *tty, int __user *arg)
{
	int locked = test_bit(TTY_PTY_LOCK, &tty->flags);
	return put_user(locked, arg);
}
Ejemplo n.º 26
0
long arch_ptrace(struct task_struct *child, long request, long addr, long data)
{
	int ret = -EPERM;

	switch (request) {
	/* when I and D space are separate, these will need to be fixed. */
	case PTRACE_PEEKTEXT: /* read word at location addr. */
	case PTRACE_PEEKDATA: {
		unsigned long tmp;
		int copied;

		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
		ret = -EIO;
		if (copied != sizeof(tmp))
			break;
		ret = put_user(tmp,(unsigned long __user *) data);
		break;
	}

	/* read the word at location addr in the USER area. */
	case PTRACE_PEEKUSR: {
		unsigned long index, tmp;

		ret = -EIO;
		/* convert to index and check */
#ifdef CONFIG_PPC32
		index = (unsigned long) addr >> 2;
		if ((addr & 3) || (index > PT_FPSCR)
		    || (child->thread.regs == NULL))
#else
		index = (unsigned long) addr >> 3;
		if ((addr & 7) || (index > PT_FPSCR))
#endif
			break;

#ifdef CONFIG_PPC32
		CHECK_FULL_REGS(child->thread.regs);
#endif
		if (index < PT_FPR0) {
			tmp = get_reg(child, (int) index);
		} else {
			flush_fp_to_thread(child);
			tmp = ((unsigned long *)child->thread.fpr)[index - PT_FPR0];
		}
		ret = put_user(tmp,(unsigned long __user *) data);
		break;
	}

	/* If I and D space are separate, this will have to be fixed. */
	case PTRACE_POKETEXT: /* write the word at location addr. */
	case PTRACE_POKEDATA:
		ret = 0;
		if (access_process_vm(child, addr, &data, sizeof(data), 1)
				== sizeof(data))
			break;
		ret = -EIO;
		break;

	/* write the word at location addr in the USER area */
	case PTRACE_POKEUSR: {
		unsigned long index;

		ret = -EIO;
		/* convert to index and check */
#ifdef CONFIG_PPC32
		index = (unsigned long) addr >> 2;
		if ((addr & 3) || (index > PT_FPSCR)
		    || (child->thread.regs == NULL))
#else
		index = (unsigned long) addr >> 3;
		if ((addr & 7) || (index > PT_FPSCR))
#endif
			break;

#ifdef CONFIG_PPC32
		CHECK_FULL_REGS(child->thread.regs);
#endif
		if (index == PT_ORIG_R3)
			break;
		if (index < PT_FPR0) {
			ret = put_reg(child, index, data);
		} else {
			flush_fp_to_thread(child);
			((unsigned long *)child->thread.fpr)[index - PT_FPR0] = data;
			ret = 0;
		}
		break;
	}

	case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
	case PTRACE_CONT: { /* restart after signal. */
		ret = -EIO;
		if (!valid_signal(data))
			break;
		if (request == PTRACE_SYSCALL)
			set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
		else
			clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
		child->exit_code = data;
		/* make sure the single step bit is not set. */
		clear_single_step(child);
		wake_up_process(child);
		ret = 0;
		break;
	}

/*
 * make the child exit.  Best I can do is send it a sigkill.
 * perhaps it should be put in the status that it wants to
 * exit.
 */
	case PTRACE_KILL: {
		ret = 0;
		if (child->exit_state == EXIT_ZOMBIE)	/* already dead */
			break;
		child->exit_code = SIGKILL;
		/* make sure the single step bit is not set. */
		clear_single_step(child);
		wake_up_process(child);
		break;
	}

	case PTRACE_SINGLESTEP: {  /* set the trap flag. */
		ret = -EIO;
		if (!valid_signal(data))
			break;
		clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
		set_single_step(child);
		child->exit_code = data;
		/* give it a chance to run. */
		wake_up_process(child);
		ret = 0;
		break;
	}

#ifdef CONFIG_PPC64
	case PTRACE_GET_DEBUGREG: {
		ret = -EINVAL;
		/* We only support one DABR and no IABRS at the moment */
		if (addr > 0)
			break;
		ret = put_user(child->thread.dabr,
			       (unsigned long __user *)data);
		break;
	}

	case PTRACE_SET_DEBUGREG:
		ret = ptrace_set_debugreg(child, addr, data);
		break;
#endif

	case PTRACE_DETACH:
		ret = ptrace_detach(child, data);
		break;

	case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */
		int i;
		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
		unsigned long __user *tmp = (unsigned long __user *)addr;

		for (i = 0; i < 32; i++) {
			ret = put_user(*reg, tmp);
			if (ret)
				break;
			reg++;
			tmp++;
		}
		break;
	}

	case PPC_PTRACE_SETREGS: { /* Set GPRs 0 - 31. */
		int i;
		unsigned long *reg = &((unsigned long *)child->thread.regs)[0];
		unsigned long __user *tmp = (unsigned long __user *)addr;

		for (i = 0; i < 32; i++) {
			ret = get_user(*reg, tmp);
			if (ret)
				break;
			reg++;
			tmp++;
		}
		break;
	}

	case PPC_PTRACE_GETFPREGS: { /* Get FPRs 0 - 31. */
		int i;
		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
		unsigned long __user *tmp = (unsigned long __user *)addr;

		flush_fp_to_thread(child);

		for (i = 0; i < 32; i++) {
			ret = put_user(*reg, tmp);
			if (ret)
				break;
			reg++;
			tmp++;
		}
		break;
	}

	case PPC_PTRACE_SETFPREGS: { /* Get FPRs 0 - 31. */
		int i;
		unsigned long *reg = &((unsigned long *)child->thread.fpr)[0];
		unsigned long __user *tmp = (unsigned long __user *)addr;

		flush_fp_to_thread(child);

		for (i = 0; i < 32; i++) {
			ret = get_user(*reg, tmp);
			if (ret)
				break;
			reg++;
			tmp++;
		}
		break;
	}

#ifdef CONFIG_ALTIVEC
	case PTRACE_GETVRREGS:
		/* Get the child altivec register state. */
		flush_altivec_to_thread(child);
		ret = get_vrregs((unsigned long __user *)data, child);
		break;

	case PTRACE_SETVRREGS:
		/* Set the child altivec register state. */
		flush_altivec_to_thread(child);
		ret = set_vrregs(child, (unsigned long __user *)data);
		break;
#endif
#ifdef CONFIG_SPE
	case PTRACE_GETEVRREGS:
		/* Get the child spe register state. */
		if (child->thread.regs->msr & MSR_SPE)
			giveup_spe(child);
		ret = get_evrregs((unsigned long __user *)data, child);
		break;

	case PTRACE_SETEVRREGS:
		/* Set the child spe register state. */
		/* this is to clear the MSR_SPE bit to force a reload
		 * of register state from memory */
		if (child->thread.regs->msr & MSR_SPE)
			giveup_spe(child);
		ret = set_evrregs(child, (unsigned long __user *)data);
		break;
#endif

	default:
		ret = ptrace_request(child, request, addr, data);
		break;
	}

	return ret;
}
Ejemplo n.º 27
0
int cp_compat_stat(struct kstat *stat, struct compat_stat __user *statbuf)
{
	int err;

	if (stat->size > MAX_NON_LFS || !old_valid_dev(stat->dev) ||
	    !old_valid_dev(stat->rdev))
		return -EOVERFLOW;

	err  = put_user(old_encode_dev(stat->dev), &statbuf->st_dev);
	err |= put_user(stat->ino, &statbuf->st_ino);
	err |= put_user(stat->mode, &statbuf->st_mode);
	err |= put_user(stat->nlink, &statbuf->st_nlink);
	err |= put_user(high2lowuid(stat->uid), &statbuf->st_uid);
	err |= put_user(high2lowgid(stat->gid), &statbuf->st_gid);
	err |= put_user(old_encode_dev(stat->rdev), &statbuf->st_rdev);
	err |= put_user(stat->size, &statbuf->st_size);
	err |= put_user(stat->atime.tv_sec, &statbuf->st_atime);
	err |= put_user(0, &statbuf->__unused1);
	err |= put_user(stat->mtime.tv_sec, &statbuf->st_mtime);
	err |= put_user(0, &statbuf->__unused2);
	err |= put_user(stat->ctime.tv_sec, &statbuf->st_ctime);
	err |= put_user(0, &statbuf->__unused3);
	err |= put_user(stat->blksize, &statbuf->st_blksize);
	err |= put_user(stat->blocks, &statbuf->st_blocks);
	err |= put_user(0, &statbuf->__unused4[0]);
	err |= put_user(0, &statbuf->__unused4[1]);

	return err;
}
Ejemplo n.º 28
0
static long emd_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int ret = 0;
    unsigned int sim_mode=0, boot_mode=0;
    int value;
    emd_dev_client_t *client=(emd_dev_client_t *)file->private_data;
    switch (cmd) {
    case CCCI_IOC_GET_MD_STATE:
        EMD_MSG_INF("chr", "Get md state ioctl called by %s\n", current->comm);
        if(arg!=0)
        {
            value = get_curr_emd_state();
            value+='0'; // Make number to charactor
            ret = put_user((unsigned int)value, (unsigned int __user *)arg);
        }else{
            EMD_MSG_INF("chr", "Get md state ioctl: arg is null\n");
        }
        break;
    case CCCI_IOC_DO_START_MD:
        EMD_MSG_INF("chr", "Start md ioctl called by %s\n", current->comm);
        if(copy_from_user(&boot_mode, (void __user *)arg, sizeof(unsigned int))) {
            EMD_MSG_INF("chr", "CCCI_IOC_DO_START_MD: copy_from_user fail!\n");
            ret = -EFAULT;
        } else {
            ret = emd_power_on(boot_mode);
            EMD_MSG_INF("chr", "CCCI_IOC_DO_START_MD,%d\n",boot_mode);
            ret = let_ext_md_go();
        }
        break;
    case CCCI_IOC_ENTER_MD_DL_MODE:        
        EMD_MSG_INF("chr", "Enter md download md ioctl called by %s\n", current->comm);
        ret = enter_md_download_mode();
        break;
    case CCCI_IOC_MD_RESET:
        EMD_MSG_INF("chr", "Reset on md ioctl called by %s\n", current->comm);
        ret = emd_request_reset();
        break;
    
    case CCCI_IOC_POWER_ON_MD:
        EMD_MSG_INF("chr", "Power on md ioctl called by %s\n", current->comm);
        if(copy_from_user(&boot_mode, (void __user *)arg, sizeof(unsigned int))) {
            EMD_MSG_INF("chr", "CCCI_IOC_POWER_ON_MD: copy_from_user fail!\n");
            ret = -EFAULT;
        } else {
            ret = emd_power_on(boot_mode);
            EMD_MSG_INF("chr", "CCCI_IOC_POWER_ON_MD(%x): %d\n", boot_mode, ret);  
        }
        break;
    case CCCI_IOC_ENTER_DEEP_FLIGHT:
        EMD_MSG_INF("chr", "Enter MD flight mode ioctl called by %s\n", current->comm);
        ret = emd_send_enter_flight_mode();
        break;

    case CCCI_IOC_LEAVE_DEEP_FLIGHT:
        EMD_MSG_INF("chr","Leave MD flight mode ioctl called by %s\n", current->comm);
        ret = emd_send_leave_flight_mode();
        break;
    case CCCI_IOC_GET_MD_ASSERTLOG:
        emd_aseert_log_wait_timeout=0;
        EMD_MSG_INF("chr","CCCI_IOC_GET_MD_ASSERTLOG ioctl called by %s, sub_dev=%d\n", current->comm,client->sub_dev_id);
        if(wait_event_interruptible(emd_aseert_log_wait, emd_aseert_log_wait_timeout) == -ERESTARTSYS)
            ret = -EINTR;
        else {
            EMD_MSG_INF("chr","sub_dev=%d call CCCI_IOC_GET_MD_ASSERTLOG is exit\n", client->sub_dev_id);
            emd_aseert_log_wait_timeout = 0;
        }
        break;
    case CCCI_IOC_GET_MD_ASSERTLOG_STATUS:
        EMD_MSG_INF("chr","CCCI_IOC_GET_MD_ASSERTLOG_STATUS ioctl called by %s, sub_dev=%d\n", current->comm,client->sub_dev_id);
        value = cm_get_assertlog_status();
        if (copy_to_user((int *)arg, &value, sizeof(int)))
        {                 
          return -EACCES;
        }           
        EMD_MSG_INF("chr", "CCCI_IOC_GET_MD_ASSERTLOG_STATUS %d\n", value);
        break;
        
    case CCCI_IOC_SIM_SWITCH:
        if(copy_from_user(&sim_mode, (void __user *)arg, sizeof(unsigned int))) {
            EMD_MSG_INF("chr", "IOC_SIM_SWITCH: copy_from_user fail!\n");
            ret = -EFAULT;
        } else {
            ret = switch_sim_mode(0,(char*)&sim_mode,sizeof(unsigned int));//switch_sim_mode(sim_mode);
            EMD_MSG_INF("chr", "IOC_SIM_SWITCH(%x): %d\n", sim_mode, ret);
        }
        break;        
    case CCCI_IOC_SIM_SWITCH_TYPE:
        value = get_sim_switch_type();
        ret = put_user(value, (unsigned int __user *)arg);
        break;
    case CCCI_IOC_STORE_SIM_MODE:
        EMD_MSG_INF("chr","store sim mode ioctl called by %s!\n",  current->comm);
        if(copy_from_user(&sim_mode, (void __user *)arg, sizeof(unsigned int))) {
            EMD_MSG_INF("chr","store sim mode fail: copy_from_user fail!\n");
            ret = -EFAULT;
        }
        else 
        {
            EMD_MSG_INF("chr","storing sim mode(%d) in kernel space!\n", sim_mode);
            exec_ccci_kern_func_by_md_id(0, ID_STORE_SIM_SWITCH_MODE, (char *)&sim_mode, sizeof(unsigned int));
        }
        break;
    
    case CCCI_IOC_GET_SIM_MODE:
        EMD_MSG_INF("chr", "get sim mode ioctl called by %s\n", current->comm);
        exec_ccci_kern_func_by_md_id(0, ID_GET_SIM_SWITCH_MODE, (char *)&sim_mode, sizeof(unsigned int));
        ret = put_user(sim_mode, (unsigned int __user *)arg);
        break;

    default:
        ret = -EMD_ERR_UN_DEF_CMD;
        EMD_MSG_INF("chr","undefined ioctl called by %s\n", current->comm);
        break;
    }

    return ret;
}
Ejemplo n.º 29
0
/*int scull_ioctl(struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg)*/
int scull_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{

	int err = 0, tmp;
	int retval = 0;
    
	/*
	 * extract the type and number bitfields, and don't decode
	 * wrong cmds: return ENOTTY (inappropriate ioctl) before access_ok()
	 */
	if (_IOC_TYPE(cmd) != SCULL_IOC_MAGIC) return -ENOTTY;
	if (_IOC_NR(cmd) > SCULL_IOC_MAXNR) return -ENOTTY;

	/*
	 * the direction is a bitmask, and VERIFY_WRITE catches R/W
	 * transfers. `Type' is user-oriented, while
	 * access_ok is kernel-oriented, so the concept of "read" and
	 * "write" is reversed
	 */
	if (_IOC_DIR(cmd) & _IOC_READ)
		err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
	else if (_IOC_DIR(cmd) & _IOC_WRITE)
		err =  !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
	if (err) return -EFAULT;

	switch(cmd) {

	  case SCULL_IOCRESET:
		scull_quantum = SCULL_QUANTUM;
		scull_qset = SCULL_QSET;
		break;
        
	  case SCULL_IOCSQUANTUM: /* Set: arg points to the value */
		if (! capable (CAP_SYS_ADMIN))
			return -EPERM;
		retval = __get_user(scull_quantum, (int __user *)arg);
		break;

	  case SCULL_IOCTQUANTUM: /* Tell: arg is the value */
		if (! capable (CAP_SYS_ADMIN))
			return -EPERM;
		scull_quantum = arg;
		break;

	  case SCULL_IOCGQUANTUM: /* Get: arg is pointer to result */
		retval = __put_user(scull_quantum, (int __user *)arg);
		break;

	  case SCULL_IOCQQUANTUM: /* Query: return it (it's positive) */
		return scull_quantum;

	  case SCULL_IOCXQUANTUM: /* eXchange: use arg as pointer */
		if (! capable (CAP_SYS_ADMIN))
			return -EPERM;
		tmp = scull_quantum;
		retval = __get_user(scull_quantum, (int __user *)arg);
		if (retval == 0)
			retval = __put_user(tmp, (int __user *)arg);
		break;

	  case SCULL_IOCHQUANTUM: /* sHift: like Tell + Query */
		if (! capable (CAP_SYS_ADMIN))
			return -EPERM;
		tmp = scull_quantum;
		scull_quantum = arg;
		return tmp;
        
	  case SCULL_IOCSQSET:
		if (! capable (CAP_SYS_ADMIN))
			return -EPERM;
		retval = __get_user(scull_qset, (int __user *)arg);
		break;

	  case SCULL_IOCTQSET:
		if (! capable (CAP_SYS_ADMIN))
			return -EPERM;
		scull_qset = arg;
		break;

	  case SCULL_IOCGQSET:
		retval = __put_user(scull_qset, (int __user *)arg);
		break;

	  case SCULL_IOCQQSET:
		return scull_qset;

	  case SCULL_IOCXQSET:
		if (! capable (CAP_SYS_ADMIN))
			return -EPERM;
		tmp = scull_qset;
		retval = __get_user(scull_qset, (int __user *)arg);
		if (retval == 0)
			retval = put_user(tmp, (int __user *)arg);
		break;

	  case SCULL_IOCHQSET:
		if (! capable (CAP_SYS_ADMIN))
			return -EPERM;
		tmp = scull_qset;
		scull_qset = arg;
		return tmp;

        /*
         * The following two change the buffer size for scullpipe.
         * The scullpipe device uses this same ioctl method, just to
         * write less code. Actually, it's the same driver, isn't it?
         */

	  case SCULL_P_IOCTSIZE:
		scull_p_buffer = arg;
		break;

	  case SCULL_P_IOCQSIZE:
		return scull_p_buffer;


	  default:  /* redundant, as cmd was checked against MAXNR */
		return -ENOTTY;
	}
	return retval;

}
Ejemplo n.º 30
0
static long schw_dev_ioctl(struct file *filp, unsigned int cmd,
               unsigned long arg)
{
       int ret = -ENOTTY;
       fcry_pt fcr = NULL;
       int id = -1;
       size_t glen = -1;

       dprintk("Enter !\n");
       fcr = filp->private_data;
       if (fcr == NULL) {
               derr("file private null!\n");
               return -1;
       }
       switch (cmd) {
               case SCHW_GET_SLOT:
                       dprintk("SCHW_GET_SLOT: \n");
                       schw_slot_enqueue(fcr);
                       id = fcr->slot->slot_id;
                       if (put_user(id, (int __user *) arg))
                               return -EFAULT;

                       ret = 0;
                       break;

               case SCHW_SECURE_LEN:
                       if(copy_from_user((void*)&glen, (void __user *)arg,
                                               (unsigned long)sizeof(glen)))
                               return -EFAULT;
                       dprintk("SCHW_SECURE_LEN: \n");
                       fcr->bpt_len = glen;
                       fcr->bpt = kmalloc(glen, GFP_KERNEL);
                       if (!fcr->bpt)
                               return -ENOMEM;
                       memset(fcr->bpt, 0, glen);
                       put_user(1, (int *)arg);
                       ret = 0;
                       break;

               case SCHW_SECURE_STORE:
                       dprintk("SCHW_SECURE_STORE: \n");

                       ret = 0;
                       break;

               case SCHW_SECURE_PULL:
                       dprintk("SCHW_SECURE_PULL: \n");

                       ret = 0;
                       break;

               case SCHW_SET_SLOT:
                       dprintk("SCHW_SET_SLOT: \n");
                       if(copy_from_user((void*)(&fcr->resh_id),(void __user *)arg,
                                               (unsigned long)sizeof(fcr->resh_id)))
                               return -EFAULT;
                       ret = 0;
                       break;

               case SCHW_SECURE_CLEAR:
                       ret = 0;
                       break;
       }
       dprintk("Exit ret%d.....!\n",ret);
       return ret;
}