asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count) { char *p, *q, *r; char buffer[256]; int len; /* Again, we cheat :)) */ switch (cmd) { case SI_SYSNAME: r = "SunOS"; break; case SI_HOSTNAME: r = buffer + 256; for (p = system_utsname.nodename, q = buffer; q < r && *p && *p != '.'; *q++ = *p++); *q = 0; r = buffer; break; case SI_RELEASE: r = "5.6"; break; case SI_MACHINE: r = machine(); break; case SI_ARCHITECTURE: r = "sparc"; break; case SI_HW_PROVIDER: r = "Sun_Microsystems"; break; case SI_HW_SERIAL: r = serial(buffer); break; case SI_PLATFORM: r = platform(buffer); break; case SI_SRPC_DOMAIN: r = ""; break; case SI_VERSION: r = "Generic"; break; default: return -EINVAL; } len = strlen(r) + 1; if (count < len) { copy_to_user_ret((char *)A(buf), r, count - 1, -EFAULT); __put_user_ret(0, (char *)A(buf) + count - 1, -EFAULT); } else copy_to_user_ret((char *)A(buf), r, len, -EFAULT); return len; }
static ssize_t kbd_read (struct file *f, char *buffer, size_t count, loff_t *ppos) { struct wait_queue wait = { current, NULL }; char *end, *p; /* Return EWOULDBLOCK, because this is what the X server expects */ if (kbd_head == kbd_tail){ if (f->f_flags & O_NONBLOCK) return -EWOULDBLOCK; add_wait_queue (&kbd_wait, &wait); while (kbd_head == kbd_tail && !signal_pending(current)) { current->state = TASK_INTERRUPTIBLE; schedule (); } current->state = TASK_RUNNING; remove_wait_queue (&kbd_wait, &wait); } /* There is data in the keyboard, fill the user buffer */ end = buffer+count; p = buffer; for (; p < end && kbd_head != kbd_tail;){ #ifdef CONFIG_SPARC32_COMPAT if (current->tss.flags & SPARC_FLAG_32BIT) { copy_to_user_ret((Firm_event *)p, &kbd_queue [kbd_tail], sizeof(Firm_event)-sizeof(struct timeval), -EFAULT); p += sizeof(Firm_event)-sizeof(struct timeval); __put_user_ret(kbd_queue[kbd_tail].time.tv_sec, (u32 *)p, -EFAULT); p += sizeof(u32); __put_user_ret(kbd_queue[kbd_tail].time.tv_usec, (u32 *)p, -EFAULT); p += sizeof(u32); } else #endif { copy_to_user_ret((Firm_event *)p, &kbd_queue [kbd_tail], sizeof(Firm_event), -EFAULT); p += sizeof (Firm_event); } #ifdef KBD_DEBUG printk ("[%s]", kbd_queue [kbd_tail].value == VKEY_UP ? "UP" : "DOWN"); #endif kbd_tail++; kbd_tail %= KBD_QSIZE; } return p-buffer; }
ci_noinline int ioctl_resource_alloc (ci_private_char_t *priv, ulong arg) { int rc; ci_resource_alloc_t local; copy_from_user_ret(&local, (caddr_t) arg, sizeof(local), -EFAULT); rc = efch_resource_alloc(&priv->rt, &local); if( rc < 0 ) return rc; copy_to_user_ret((caddr_t) arg, &local, sizeof(local), -EFAULT); return rc; }
ci_noinline int ioctl_resource_op (ci_private_char_t *priv, ulong arg) { ci_resource_op_t local; int rc, copy_out = 0; copy_from_user_ret(&local, (caddr_t) arg, sizeof(local), -EFAULT); rc = efch_resource_op(&priv->rt, &local, ©_out); if( copy_out ) copy_to_user_ret((caddr_t) arg, &local, sizeof(local), -EFAULT); return rc; }
ci_noinline int ioctl_license_challenge (ci_private_char_t *priv, ulong arg) { struct ci_license_challenge_op_s local; int rc, copy_out = 0; copy_from_user_ret(&local, (caddr_t) arg, sizeof(local), -EFAULT); rc = efch_license_challenge(&priv->rt, &local, ©_out); if( copy_out ) copy_to_user_ret((caddr_t) arg, &local, sizeof(local), -EFAULT); return rc; }
static ssize_t state_read(struct file *filp, char *dest, size_t count, loff_t *ppos) { struct state_dev *dev = filp->private_data; if (count > STATE_BLOCK_SIZE || count <= 0) count = STATE_BLOCK_SIZE; if (hijack_force_pause_player) { hijack_force_pause_player = 0; dev->read_buffer[0x0c] &= ~0x02; } copy_to_user_ret(dest, dev->read_buffer, count, -EFAULT); return count; }
static long read_ecp(unsigned minor, char *c, unsigned long cnt) { unsigned long remaining; long rc; /* Turn ECP mode from forward to reverse if needed. */ if (! instances[minor].direction) { unsigned short pins = get_pins(minor); /* Event 38: Turn the bus around */ instances[minor].direction = 0x20; pins &= ~BPP_PP_nAutoFd; set_pins(pins, minor); /* Event 39: Set pins for reverse mode. */ snooze(TIME_PSetup, minor); set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); /* Wait for event 40: Peripheral ready to be strobed */ rc = wait_for(0, BPP_GP_PError, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; } remaining = cnt; while (remaining > 0) { /* If there is a run length for a repeated byte, repeat */ /* that byte a few times. */ if (instances[minor].run_length && !instances[minor].run_flag) { char buffer[128]; unsigned idx; unsigned repeat = remaining < instances[minor].run_length ? remaining : instances[minor].run_length; for (idx = 0 ; idx < repeat ; idx += 1) buffer[idx] = instances[minor].repeat_byte; copy_to_user_ret(c, buffer, repeat, -EFAULT); remaining -= repeat; c += repeat; instances[minor].run_length -= repeat; } if (remaining == 0) break; /* Wait for Event 43: Data active on the bus. */ rc = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); if (rc == -1) break; if (rc & BPP_GP_Busy) { /* OK, this is data. read it in. */ unsigned char byte = bpp_inb(base_addrs[minor]); put_user_ret(byte, c, -EFAULT); c += 1; remaining -= 1; if (instances[minor].run_flag) { instances[minor].repeat_byte = byte; instances[minor].run_flag = 0; } } else { unsigned char byte = bpp_inb(base_addrs[minor]); if (byte & 0x80) { printk("bpp%d: " "Ignoring ECP channel %u from device.\n", minor, byte & 0x7f); } else { instances[minor].run_length = byte; instances[minor].run_flag = 1; } } /* Event 44: I got it. */ set_pins(BPP_PP_nStrobe|BPP_PP_nAutoFd|BPP_PP_nSelectIn, minor); /* Wait for event 45: peripheral handshake */ rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); if (rc == -1) return -ETIMEDOUT; /* Event 46: Finish handshake */ set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); } return cnt - remaining; }
static int kbd_ioctl (struct inode *i, struct file *f, unsigned int cmd, unsigned long arg) { unsigned char c; unsigned char leds = 0; int value; switch (cmd){ case KIOCTYPE: /* return keyboard type */ put_user_ret(sunkbd_type, (int *) arg, -EFAULT); break; case KIOCGTRANS: put_user_ret(TR_UNTRANS_EVENT, (int *) arg, -EFAULT); break; case KIOCTRANS: get_user_ret(value, (int *) arg, -EFAULT); if (value != TR_UNTRANS_EVENT) return -EINVAL; break; case KIOCLAYOUT: put_user_ret(sunkbd_layout, (int *) arg, -EFAULT); break; case KIOCSDIRECT: #ifndef CODING_NEW_DRIVER get_user_ret(value, (int *) arg, -EFAULT); if(value) kbd_redirected = fg_console + 1; else kbd_redirected = 0; kbd_table [fg_console].kbdmode = kbd_redirected ? VC_RAW : VC_XLATE; #endif break; case KIOCCMD: get_user_ret(value, (int *) arg, -EFAULT); c = (unsigned char) value; switch (c) { case SKBDCMD_CLICK: case SKBDCMD_NOCLICK: send_cmd(c); return 0; case SKBDCMD_BELLON: kd_mksound(1,0); return 0; case SKBDCMD_BELLOFF: kd_mksound(0,0); return 0; default: return -EINVAL; } case KIOCSLED: get_user_ret(c, (unsigned char *) arg, -EFAULT); if (c & LED_SCRLCK) leds |= (1 << VC_SCROLLOCK); if (c & LED_NLOCK) leds |= (1 << VC_NUMLOCK); if (c & LED_CLOCK) leds |= (1 << VC_CAPSLOCK); compose_led_on = !!(c & LED_CMPOSE); sun_setledstate(kbd_table + fg_console, leds); break; case KIOCGLED: put_user_ret(vcleds_to_sunkbd(getleds()), (unsigned char *) arg, -EFAULT); break; case KIOCGRATE: { struct kbd_rate rate; rate.delay = kbd_delay_ticks; if (kbd_rate_ticks) rate.rate = HZ / kbd_rate_ticks; else rate.rate = 0; copy_to_user_ret((struct kbd_rate *)arg, &rate, sizeof(struct kbd_rate), -EFAULT); return 0; } case KIOCSRATE: { struct kbd_rate rate; if (verify_area(VERIFY_READ, (void *)arg, sizeof(struct kbd_rate))) return -EFAULT; copy_from_user(&rate, (struct kbd_rate *)arg, sizeof(struct kbd_rate)); if (rate.rate > 50) return -EINVAL; if (rate.rate == 0) kbd_rate_ticks = 0; else kbd_rate_ticks = HZ / rate.rate; kbd_delay_ticks = rate.delay; return 0; } case FIONREAD: /* return number of bytes in kbd queue */ { int count; count = kbd_head - kbd_tail; put_user_ret((count < 0) ? KBD_QSIZE - count : count, (int *) arg, -EFAULT); return 0; } default: printk ("Unknown Keyboard ioctl: %8.8x\n", cmd); return -EINVAL; } return 0; }
static ssize_t sun_mouse_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { struct wait_queue wait = { current, NULL }; if (queue_empty ()){ if (file->f_flags & O_NONBLOCK) return -EWOULDBLOCK; add_wait_queue (&sunmouse.proc_list, &wait); while (queue_empty () && !signal_pending(current)) { current->state = TASK_INTERRUPTIBLE; schedule (); } current->state = TASK_RUNNING; remove_wait_queue (&sunmouse.proc_list, &wait); } if (gen_events){ char *p = buffer, *end = buffer+count; while (p < end && !queue_empty ()){ #ifdef CONFIG_SPARC32_COMPAT if (current->tss.flags & SPARC_FLAG_32BIT) { Firm_event *q = get_from_queue(); if ((end - p) < ((sizeof(Firm_event) - sizeof(struct timeval) + (sizeof(u32) * 2)))) break; copy_to_user_ret((Firm_event *)p, q, sizeof(Firm_event)-sizeof(struct timeval), -EFAULT); p += sizeof(Firm_event)-sizeof(struct timeval); __put_user_ret(q->time.tv_sec, (u32 *)p, -EFAULT); p += sizeof(u32); __put_user_ret(q->time.tv_usec, (u32 *)p, -EFAULT); p += sizeof(u32); } else #endif { if ((end - p) < sizeof(Firm_event)) break; copy_to_user_ret((Firm_event *)p, get_from_queue(), sizeof(Firm_event), -EFAULT); p += sizeof (Firm_event); } } sunmouse.ready = !queue_empty (); file->f_dentry->d_inode->i_atime = CURRENT_TIME; return p-buffer; } else { int c, limit = 3; if (count < limit) limit = count; for (c = 0; c < limit; c++) { put_user(sunmouse.queue.stream[sunmouse.tail], buffer); buffer++; sunmouse.tail = (sunmouse.tail + 1) % STREAM_SIZE; } while (c < count) { if (c >= 5) break; put_user(0, buffer); buffer++; c++; } sunmouse.ready = !queue_empty(); file->f_dentry->d_inode->i_atime = CURRENT_TIME; return c; } /* Only called if nothing was sent */ if (signal_pending(current)) return -ERESTARTSYS; return 0; }