/* 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; }
/* 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); }
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; }
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; }
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 &= 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 = ""},
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; }
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; }
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; }
/* * 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; }
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; }
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; }
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++, ®_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, ®_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); }
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++, ®_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, ®_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); }
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); }
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; }
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; } }
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); } }
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; }
/** * 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; }
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); }
/* * 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; }
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); }
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); }
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; }
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; }
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; }
/*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; }
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; }