Exemplo n.º 1
0
int ptrace_set_bpt(struct task_struct *child)
{
        unsigned long pc,next;
	unsigned short insn;
	pc = get_reg(child,PT_PC);
	next = insn_length((unsigned char *)pc) + pc;
	insn = get_fs_word(pc);
	if (insn == 0x5470) {
	        /* rts */ 
	        unsigned long sp;
		sp = get_reg(child,PT_USP);
		next = get_fs_long(sp);
	} else if ((insn & 0xfb00) != 0x5800) {
	        /* jmp / jsr */
	        int regs;
		const short reg_tbl[]={PT_ER0,PT_ER1,PT_ER2,PT_ER3,
                                       PT_ER4,PT_ER5,PT_ER6,PT_USP};
	        switch(insn & 0xfb00) {
		        case 0x5900:
			       regs = (insn & 0x0070) >> 8;
                               next = get_reg(child,reg_tbl[regs]);
			       break;
		        case 0x5a00:
			       next = get_fs_long(pc+2) & 0x00ffffff;
			       break;
		        case 0x5b00:
			       /* unneccessary? */
			       next = *(unsigned long *)(insn & 0xff);
                               break;
		}
	} else if (((insn & 0xf000) == 0x4000) || ((insn &0xff00) == 0x5500)) { 
Exemplo n.º 2
0
/* 向文件发送一个命令,如获取文件信息的命令,
 * 将文件的信息拷贝到arg所指向的内存,如关于文件的flag和版本等信息
 */
int ext2_ioctl (struct inode * inode, struct file * filp, unsigned int cmd,
		unsigned long arg)
{

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

	switch (cmd) {
	case EXT2_IOC_GETFLAGS:
		put_fs_long (inode->u.ext2_i.i_flags, (long *) arg);
		return 0;
	case EXT2_IOC_SETFLAGS:
		if ((current->euid != inode->i_uid) && !suser())
			return -EPERM;
		if (IS_RDONLY(inode))
			return -EROFS;
		inode->u.ext2_i.i_flags = get_fs_long ((long *) arg);
		inode->i_ctime = CURRENT_TIME;
		inode->i_dirt = 1;
		return 0;
	case EXT2_IOC_GETVERSION:
		put_fs_long (inode->u.ext2_i.i_version, (long *) arg);
		return 0;
	case EXT2_IOC_SETVERSION:
		if ((current->euid != inode->i_uid) && !suser())
			return -EPERM;
		if (IS_RDONLY(inode))
			return -EROFS;
		inode->u.ext2_i.i_version = get_fs_long ((long *) arg);
		inode->i_ctime = CURRENT_TIME;
		inode->i_dirt = 1;
		return 0;
	default:
		return -EINVAL;
	}
}
Exemplo n.º 3
0
/*
 * gets the current name or the name of the connected socket.
 */
static int
unix_proto_getname(struct socket *sock, struct sockaddr *usockaddr,
		   int *usockaddr_len, int peer)
{
	struct unix_proto_data *upd;
	int len;

	PRINTK("unix_proto_getname: socket 0x%x for %s\n", sock,
	       peer ? "peer" : "self");
	if (peer) {
		if (sock->state != SS_CONNECTED) {
			PRINTK("unix_proto_getname: socket not connected\n");
			return -EINVAL;
		}
		upd = UN_DATA(sock->conn);
	}
	else
		upd = UN_DATA(sock);
	verify_area(usockaddr_len, sizeof(*usockaddr_len));
	if ((len = get_fs_long(usockaddr_len)) <= 0)
		return -EINVAL;
	if (len > upd->sockaddr_len)
		len = upd->sockaddr_len;
	if (len) {
		verify_area(usockaddr, len);
		memcpy_tofs(usockaddr, &upd->sockaddr_un, len);
	}
	put_fs_long(len, usockaddr_len);
	return 0;
}
Exemplo n.º 4
0
int sys_stime(long * tptr)
{
	if (!suser())
		return -EPERM;
	startup_time = get_fs_long((unsigned long *)tptr) - jiffies/HZ;
	return 0;
}
Exemplo n.º 5
0
static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
{
	int block;

	switch (cmd) {
		case FIBMAP:
			if (filp->f_inode->i_op == NULL)
				return -EBADF;
		    	if (filp->f_inode->i_op->bmap == NULL)
				return -EINVAL;
			verify_area((void *) arg,4);
			block = get_fs_long((long *) arg);
			block = filp->f_inode->i_op->bmap(filp->f_inode,block);
			put_fs_long(block,(long *) arg);
			return 0;
		case FIGETBSZ:
			if (filp->f_inode->i_sb == NULL)
				return -EBADF;
			verify_area((void *) arg,4);
			put_fs_long(filp->f_inode->i_sb->s_blocksize,
			    (long *) arg);
			return 0;
		case FIONREAD:
			verify_area((void *) arg,4);
			put_fs_long(filp->f_inode->i_size - filp->f_pos,
			    (long *) arg);
			return 0;
		default:
			return -EINVAL;
	}
}
Exemplo n.º 6
0
/*
 * The first time we set the timezone, we will warp the clock so that
 * it is ticking GMT time instead of local time.  Presumably, 
 * if someone is setting the timezone then we are running in an
 * environment where the programs understand about timezones.
 * This should be done at boot time in the /etc/rc script, as
 * soon as possible, so that the clock can be set right.  Otherwise,
 * various programs will get confused when the clock gets warped.
 */
asmlinkage int sys_settimeofday(struct timeval *tv, struct timezone *tz)
{
	static int	firsttime = 1;

	//if (!suser())
	//	return -EPERM;

	if (tz) {
		sys_tz.tz_minuteswest = get_fs_long((unsigned long *) tz);
		sys_tz.tz_dsttime = get_fs_long(((unsigned long *) tz)+1);
		if (firsttime) {
			firsttime = 0;
			if (!tv)
				warp_clock();
		}
	}
	if (tv) {
		int sec, usec;

		sec = get_fs_long((unsigned long *)tv);
		usec = get_fs_long(((unsigned long *)tv)+1);
	
		cli();
		/* This is revolting. We need to set the xtime.tv_usec
		 * correctly. However, the value in this location is
		 * is value at the last tick.
		 * Discover what correction gettimeofday
		 * would have done, and then undo it!
		 */
		usec -= do_gettimeoffset();

		if (usec < 0)
		{
			usec += 1000000;
			sec--;
		}
		xtime.tv_sec = sec;
		xtime.tv_usec = usec;
		time_status = TIME_BAD;
		time_maxerror = 0x70000000;
		time_esterror = 0x70000000;
		sti();
	}
	return 0;
}
Exemplo n.º 7
0
asmlinkage int sys_stime(long *tptr) {

	//if (!suser())
	//	return -EPERM;

	cli();
	xtime.tv_sec = get_fs_long((unsigned long *) tptr);
	xtime.tv_usec = 0;
	time_status = TIME_BAD;
	time_maxerror = 0x70000000;
	time_esterror = 0x70000000;
	sti();
	return 0;
}
Exemplo n.º 8
0
static int ioctl_probe(int dev, void *buffer)
{
	int temp;
	unsigned int len,slen;
	const char * string;
	
	if ((temp = scsi_hosts[dev].present) && buffer) {
		len = get_fs_long ((int *) buffer);
		string = scsi_hosts[dev].info();
		slen = strlen(string);
		if (len > slen)
			len = slen + 1;
		verify_area(VERIFY_WRITE, buffer, len);
		memcpy_tofs (buffer, string, len);
	}
	return temp;
}
Exemplo n.º 9
0
static int ioctl_probe(struct Scsi_Host * host, void *buffer)
{
	int temp;
	unsigned int len,slen;
	const char * string;
	
	if ((temp = host->hostt->present) && buffer) {
		len = get_fs_long ((unsigned long *) buffer);
		string = host->hostt->info();
		slen = strlen(string);
		if (len > slen)
			len = slen + 1;
		verify_area(VERIFY_WRITE, buffer, len);
		memcpy_tofs (buffer, string, len);
	}
	return temp;
}
Exemplo n.º 10
0
loff_t sys_lseek(unsigned int fd, loff_t * p_offset, unsigned int origin)
{
    register struct file *file;
    register struct file_operations *fop;
    loff_t offset, tmp;

    offset = (loff_t) get_fs_long(p_offset);
    if (fd >= NR_OPEN || !(file = current->files.fd[fd])
	|| !(file->f_inode))
	return -EBADF;
    if (origin > 2)
	return -EINVAL;
    fop = file->f_op;
    if (fop && fop->lseek)
	return fop->lseek(file->f_inode, file, offset, origin);

    /* this is the default handler if no lseek handler is present */
    /* Note: We already determined above that origin is in range. */
    if (origin == 2) {
	if (!file->f_inode)
	    return -EINVAL;
	tmp = file->f_inode->i_size + offset;
    } else {
	tmp = (!origin) ? offset : file->f_pos + offset;
    }

    if (tmp < 0)
	return -EINVAL;
    if (tmp != file->f_pos) {
	file->f_pos = tmp;

#ifdef BLOAT_FS
	file->f_reada = 0;
	file->f_version = ++event;
#endif

    }

    memcpy_tofs(p_offset, &tmp, 4);

    return 0;
}
Exemplo n.º 11
0
int dac0800_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
	long	speed;
	int	rc = 0;

	switch (cmd) {
	case SNDCTL_DSP_SPEED:
		rc = verify_area(VERIFY_READ, (void *) arg, sizeof(speed));
		if (rc == 0) {
			speed = get_fs_long((unsigned long *) arg);
			dac0800_setclk(speed);
		}
		break;
	default:
		rc = -EINVAL;
		break;
	}

	return(rc);
}
Exemplo n.º 12
0
static int
net_ioctl(unsigned int cmd, unsigned long arg)
{
  int er;
  switch(cmd) {
	case DDIOCSDBG:
		er=verify_area(VERIFY_READ, (void *)arg, sizeof(long));
		if(er)
			return er;
		net_debug = get_fs_long((long *)arg);
		if (net_debug != 0 && net_debug != 1) {
			net_debug = 0;
			return(-EINVAL);
		}
		return(0);
	default:
		return(-EINVAL);
  }
  /*NOTREACHED*/
  return(0);
}
Exemplo n.º 13
0
static int
ip_proto_getname(struct socket *sock, struct sockaddr *uaddr,
		 int *uaddr_len, int peer)
{
  struct sockaddr_in sin;
  volatile struct sock *sk;
  int len;
  verify_area(uaddr_len, sizeof (len));
  len = get_fs_long(uaddr_len);
  /* check this error. */
  if (len < sizeof (sin)) return (-EINVAL);
  verify_area (uaddr, len);
  sin.sin_family=AF_INET;
  sk = sock->data;
  if (sk == NULL)
    {
       printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
       return (0);
    }
  if (peer)
    {
      if (sk->state != TCP_ESTABLISHED)
	return (-ENOTCONN);
      sin.sin_port = sk->dummy_th.dest;
      sin.sin_addr.s_addr = sk->daddr;
      }
  else
    {
      sin.sin_port = sk->dummy_th.source;
      sin.sin_addr.s_addr = sk->saddr;
    }
  len = sizeof (sin);
  memcpy_tofs(uaddr, &sin, sizeof (sin));
  put_fs_long (len, uaddr_len);
  return (0);
}
Exemplo n.º 14
0
static int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
	struct sock *sk=(struct sock *)sock->data;
	int err, pid;

	switch(cmd) 
	{
		case FIOSETOWN:
		case SIOCSPGRP:
			err=verify_area(VERIFY_READ,(int *)arg,sizeof(long));
			if(err)
				return err;
			pid = get_fs_long((int *) arg);
			/* see inet_fcntl */
			if (current->pid != pid && current->pgrp != -pid && !suser())
				return -EPERM;
			sk->proc = pid;
			return(0);
		case FIOGETOWN:
		case SIOCGPGRP:
			err=verify_area(VERIFY_WRITE,(void *) arg, sizeof(long));
			if(err)
				return err;
			put_fs_long(sk->proc,(int *)arg);
			return(0);			
		case SIOCGSTAMP:
			if(sk->stamp.tv_sec==0)
				return -ENOENT;
			err=verify_area(VERIFY_WRITE,(void *)arg,sizeof(struct timeval));
			if(err)
				return err;
			memcpy_tofs((void *)arg,&sk->stamp,sizeof(struct timeval));
			return 0;
		case SIOCADDRT: case SIOCADDRTOLD:
		case SIOCDELRT: case SIOCDELRTOLD:
			return(ip_rt_ioctl(cmd,(void *) arg));
		case SIOCDARP:
		case SIOCGARP:
		case SIOCSARP:
			return(arp_ioctl(cmd,(void *) arg));
#ifdef CONFIG_INET_RARP			
		case SIOCDRARP:
		case SIOCGRARP:
		case SIOCSRARP:
			return(rarp_ioctl(cmd,(void *) arg));
#endif
		case SIOCGIFCONF:
		case SIOCGIFFLAGS:
		case SIOCSIFFLAGS:
		case SIOCGIFADDR:
		case SIOCSIFADDR:

/* begin multicast support change */
		case SIOCADDMULTI:
		case SIOCDELMULTI:
/* end multicast support change */
		
		case SIOCGIFDSTADDR:
		case SIOCSIFDSTADDR:
		case SIOCGIFBRDADDR:
		case SIOCSIFBRDADDR:
		case SIOCGIFNETMASK:
		case SIOCSIFNETMASK:
		case SIOCGIFMETRIC:
		case SIOCSIFMETRIC:
		case SIOCGIFMEM:
		case SIOCSIFMEM:
		case SIOCGIFMTU:
		case SIOCSIFMTU:
		case SIOCSIFLINK:
		case SIOCGIFHWADDR:
		case SIOCSIFHWADDR:
		case OLD_SIOCGIFHWADDR:
		case SIOCSIFMAP:
		case SIOCGIFMAP:
		case SIOCSIFSLAVE:
		case SIOCGIFSLAVE:
			return(dev_ioctl(cmd,(void *) arg));

		default:
			if ((cmd >= SIOCDEVPRIVATE) &&
			   (cmd <= (SIOCDEVPRIVATE + 15)))
				return(dev_ioctl(cmd,(void *) arg));

			if (sk->prot->ioctl==NULL) 
				return(-EINVAL);
			return(sk->prot->ioctl(sk, cmd, arg));
	}
	/*NOTREACHED*/
	return(0);
}
Exemplo n.º 15
0
static int gbatxt_ioctl(struct tty_struct *tty, struct file * file,
                        unsigned int cmd, unsigned long arg)
{
    struct gbatxt_serial * info = (struct gbatxt_serial *)tty->driver_data;
    unsigned int val;
    int retval, error;
    int dtr, rts;

    if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
            (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
            (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
        if (tty->flags & (1 << TTY_IO_ERROR))
            return -EIO;
    }

    switch (cmd) {
    case TCSBRK:	/* SVID version: non-zero arg --> no break */
        retval = tty_check_change(tty);
        if (retval)
            return retval;
        tty_wait_until_sent(tty, 0);
        if (!arg)
            send_break(info, HZ/4);	/* 1/4 second */
        return 0;
    case TCSBRKP:	/* support for POSIX tcsendbreak() */
        retval = tty_check_change(tty);
        if (retval)
            return retval;
        tty_wait_until_sent(tty, 0);
        send_break(info, arg ? arg*(HZ/10) : HZ/4);
        return 0;
    case TIOCGSOFTCAR:
        error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
        if (error)
            return error;
        put_fs_long(C_CLOCAL(tty) ? 1 : 0,
                    (unsigned long *) arg);
        return 0;
    case TIOCSSOFTCAR:
        arg = get_fs_long((unsigned long *) arg);
        tty->termios->c_cflag =
            ((tty->termios->c_cflag & ~CLOCAL) |
             (arg ? CLOCAL : 0));
        return 0;
    case TIOCGSERIAL:
        error = verify_area(VERIFY_WRITE, (void *) arg,
                            sizeof(struct serial_struct));
        if (error)
            return error;
        return get_serial_info(info,
                               (struct serial_struct *) arg);
    case TIOCSSERIAL:
        return set_serial_info(info,
                               (struct serial_struct *) arg);
    case TIOCSERGETLSR: /* Get line status register */
        error = verify_area(VERIFY_WRITE, (void *) arg,
                            sizeof(unsigned int));
        if (error)
            return error;
        else
            return get_lsr_info(info, (unsigned int *) arg);

    case TIOCSERGSTRUCT:
        error = verify_area(VERIFY_WRITE, (void *) arg,
                            sizeof(struct gbatxt_serial));
        if (error)
            return error;
        memcpy_tofs((struct gbatxt_serial *) arg,
                    info, sizeof(struct gbatxt_serial));
        return 0;

    case TIOCMGET:
        if ((error = verify_area(VERIFY_WRITE, (void *) arg,
                                 sizeof(unsigned int))))
            return(error);
        val = gbatxt_getsignals(info);
        put_user(val, (unsigned int *) arg);
        break;

    case TIOCMBIS:
        if ((error = verify_area(VERIFY_WRITE, (void *) arg,
                                 sizeof(unsigned int))))
            return(error);
        val = get_user((unsigned int *) arg);
        rts = (val & TIOCM_RTS) ? 1 : -1;
        dtr = (val & TIOCM_DTR) ? 1 : -1;
        gbatxt_setsignals(info, dtr, rts);
        break;

    case TIOCMBIC:
        if ((error = verify_area(VERIFY_WRITE, (void *) arg,
                                 sizeof(unsigned int))))
            return(error);
        val = get_user((unsigned int *) arg);
        rts = (val & TIOCM_RTS) ? 0 : -1;
        dtr = (val & TIOCM_DTR) ? 0 : -1;
        gbatxt_setsignals(info, dtr, rts);
        break;

    case TIOCMSET:
        if ((error = verify_area(VERIFY_WRITE, (void *) arg,
                                 sizeof(unsigned int))))
            return(error);
        val = get_user((unsigned int *) arg);
        rts = (val & TIOCM_RTS) ? 1 : 0;
        dtr = (val & TIOCM_DTR) ? 1 : 0;
        gbatxt_setsignals(info, dtr, rts);
        break;

    default:
        return -ENOIOCTLCMD;
    }
    return 0;
}
Exemplo n.º 16
0
asmlinkage int
sys_ipc (uint call, int first, int second, int third, void* ptr, long fifth)
{
	int version;
	
	version = call >> 16;
	call &= 0xffff;

	if (call <= SEMCTL)
		switch (call) {
		case SEMOP:
			return sys_semop (first, (struct sembuf *)ptr, second);
		case SEMGET:
			return sys_semget (first, second, third);
		case SEMCTL: {
			union semun fourth;
			int err;
			if (!ptr)
				return -EINVAL;
			if ((err = verify_area (VERIFY_READ, ptr, sizeof(long))))
				return err;
			fourth.__pad = (void *) get_fs_long(ptr);
			return sys_semctl (first, second, third, fourth);
			}
		default:
			return -EINVAL;
		}
	if (call <= MSGCTL) 
		switch (call) {
		case MSGSND:
			return sys_msgsnd (first, (struct msgbuf *) ptr, 
					   second, third);
		case MSGRCV:
			switch (version) {
			case 0: {
				struct ipc_kludge tmp;
				int err;
				if (!ptr)
					return -EINVAL;
				if ((err = verify_area (VERIFY_READ, ptr, sizeof(tmp))))
					return err;
				memcpy_fromfs (&tmp,(struct ipc_kludge *) ptr,
					       sizeof (tmp));
				return sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
				}
			case 1: default:
				return sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
			}
		case MSGGET:
			return sys_msgget ((key_t) first, second);
		case MSGCTL:
			return sys_msgctl (first, second, (struct msqid_ds *) ptr);
		default:
			return -EINVAL;
		}
	if (call <= SHMCTL) 
		switch (call) {
		case SHMAT:
			switch (version) {
			case 0: default: {
				ulong raddr;
				int err;
				if ((err = verify_area(VERIFY_WRITE, (ulong*) third, sizeof(ulong))))
					return err;
				err = sys_shmat (first, (char *) ptr, second, &raddr);
				if (err)
					return err;
				put_fs_long (raddr, (ulong *) third);
				return 0;
				}
			case 1:	/* iBCS2 emulator entry point */
				if (get_fs() != get_ds())
					return -EINVAL;
				return sys_shmat (first, (char *) ptr, second, (ulong *) third);
			}
		case SHMDT: 
			return sys_shmdt ((char *)ptr);
		case SHMGET:
			return sys_shmget (first, second, third);
		case SHMCTL:
			return sys_shmctl (first, second, (struct shmid_ds *) ptr);
		default:
			return -EINVAL;
		}
	return -EINVAL;
	
}
Exemplo n.º 17
0
/*
 * System call vectors. Since I (RIB) want to rewrite sockets as streams,
 * we have this level of indirection. Not a lot of overhead, since more of
 * the work is done via read/write/select directly.
 */
asmlinkage int
sys_socketcall(int call, unsigned long *args)
{
  int er;
  switch(call) {
	case SYS_SOCKET:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_socket(get_fs_long(args+0),
				   get_fs_long(args+1),
				   get_fs_long(args+2)));
	case SYS_BIND:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_bind(get_fs_long(args+0),
				 (struct sockaddr *)get_fs_long(args+1),
				 get_fs_long(args+2)));
	case SYS_CONNECT:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_connect(get_fs_long(args+0),
				    (struct sockaddr *)get_fs_long(args+1),
				    get_fs_long(args+2)));
	case SYS_LISTEN:
		er=verify_area(VERIFY_READ, args, 2 * sizeof(long));
		if(er)
			return er;
		return(sock_listen(get_fs_long(args+0),
				   get_fs_long(args+1)));
	case SYS_ACCEPT:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_accept(get_fs_long(args+0),
				   (struct sockaddr *)get_fs_long(args+1),
				   (int *)get_fs_long(args+2)));
	case SYS_GETSOCKNAME:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_getsockname(get_fs_long(args+0),
					(struct sockaddr *)get_fs_long(args+1),
					(int *)get_fs_long(args+2)));
	case SYS_GETPEERNAME:
		er=verify_area(VERIFY_READ, args, 3 * sizeof(long));
		if(er)
			return er;
		return(sock_getpeername(get_fs_long(args+0),
					(struct sockaddr *)get_fs_long(args+1),
					(int *)get_fs_long(args+2)));
	case SYS_SOCKETPAIR:
		er=verify_area(VERIFY_READ, args, 4 * sizeof(long));
		if(er)
			return er;
		return(sock_socketpair(get_fs_long(args+0),
				       get_fs_long(args+1),
				       get_fs_long(args+2),
				       (unsigned long *)get_fs_long(args+3)));
	case SYS_SEND:
		er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));
		if(er)
			return er;
		return(sock_send(get_fs_long(args+0),
				 (void *)get_fs_long(args+1),
				 get_fs_long(args+2),
				 get_fs_long(args+3)));
	case SYS_SENDTO:
		er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));
		if(er)
			return er;
		return(sock_sendto(get_fs_long(args+0),
				   (void *)get_fs_long(args+1),
				   get_fs_long(args+2),
				   get_fs_long(args+3),
				   (struct sockaddr *)get_fs_long(args+4),
				   get_fs_long(args+5)));
	case SYS_RECV:
		er=verify_area(VERIFY_READ, args, 4 * sizeof(unsigned long));
		if(er)
			return er;
		return(sock_recv(get_fs_long(args+0),
				 (void *)get_fs_long(args+1),
				 get_fs_long(args+2),
				 get_fs_long(args+3)));
	case SYS_RECVFROM:
		er=verify_area(VERIFY_READ, args, 6 * sizeof(unsigned long));
		if(er)
			return er;
		return(sock_recvfrom(get_fs_long(args+0),
				     (void *)get_fs_long(args+1),
				     get_fs_long(args+2),
				     get_fs_long(args+3),
				     (struct sockaddr *)get_fs_long(args+4),
				     (int *)get_fs_long(args+5)));
	case SYS_SHUTDOWN:
		er=verify_area(VERIFY_READ, args, 2* sizeof(unsigned long));
		if(er)
			return er;
		return(sock_shutdown(get_fs_long(args+0),
				     get_fs_long(args+1)));
	case SYS_SETSOCKOPT:
		er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));
		if(er)
			return er;
		return(sock_setsockopt(get_fs_long(args+0),
				       get_fs_long(args+1),
				       get_fs_long(args+2),
				       (char *)get_fs_long(args+3),
				       get_fs_long(args+4)));
	case SYS_GETSOCKOPT:
		er=verify_area(VERIFY_READ, args, 5*sizeof(unsigned long));
		if(er)
			return er;
		return(sock_getsockopt(get_fs_long(args+0),
				       get_fs_long(args+1),
				       get_fs_long(args+2),
				       (char *)get_fs_long(args+3),
				       (int *)get_fs_long(args+4)));
	default:
		return(-EINVAL);
  }
}
Exemplo n.º 18
0
int tty_ioctl(struct inode * inode, struct file * file,
	unsigned int cmd, unsigned long arg)
{
	struct tty_struct * tty;
	struct tty_struct * other_tty;
	struct tty_struct * termios_tty;
	pid_t pgrp;
	int dev;
	int termios_dev;
	int retval;

	if (MAJOR(file->f_rdev) != TTY_MAJOR) {
		printk("tty_ioctl: tty pseudo-major != TTY_MAJOR\n");
		return -EINVAL;
	}
	dev = MINOR(file->f_rdev);
	tty = TTY_TABLE(dev);
	if (!tty)
		return -EINVAL;
	if (IS_A_PTY(dev))
		other_tty = tty_table[PTY_OTHER(dev)];
	else
		other_tty = NULL;
	if (IS_A_PTY_MASTER(dev)) {
		termios_tty = other_tty;
		termios_dev = PTY_OTHER(dev);
	} else {
		termios_tty = tty;
		termios_dev = dev;
	}
	switch (cmd) {
		case TCGETS:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (struct termios));
			if (retval)
				return retval;
			memcpy_tofs((struct termios *) arg,
				    termios_tty->termios,
				    sizeof (struct termios));
			return 0;
		case TCSETSF:
		case TCSETSW:
		case TCSETS:
			retval = check_change(termios_tty, termios_dev);
			if (retval)
				return retval;
			if (cmd == TCSETSF || cmd == TCSETSW) {
				if (cmd == TCSETSF)
					flush_input(termios_tty);
				wait_until_sent(termios_tty, 0);
			}
			return set_termios(termios_tty, (struct termios *) arg,
					   termios_dev);
		case TCGETA:
			return get_termio(termios_tty,(struct termio *) arg);
		case TCSETAF:
		case TCSETAW:
		case TCSETA:
			retval = check_change(termios_tty, termios_dev);
			if (retval)
				return retval;
			if (cmd == TCSETAF || cmd == TCSETAW) {
				if (cmd == TCSETAF)
					flush_input(termios_tty);
				wait_until_sent(termios_tty, 0);
			}
			return set_termio(termios_tty, (struct termio *) arg,
					  termios_dev);
		case TCXONC:
			retval = check_change(tty, dev);
			if (retval)
				return retval;
			switch (arg) {
			case TCOOFF:
				stop_tty(tty);
				break;
			case TCOON:
				start_tty(tty);
				break;
			case TCIOFF:
				if (STOP_CHAR(tty) != __DISABLED_CHAR)
					put_tty_queue(STOP_CHAR(tty),
						      &tty->write_q);
				break;
			case TCION:
				if (START_CHAR(tty) != __DISABLED_CHAR)
					put_tty_queue(START_CHAR(tty),
						      &tty->write_q);
				break;
			default:
				return -EINVAL;
			}
			return 0;
		case TCFLSH:
			retval = check_change(tty, dev);
			if (retval)
				return retval;
			switch (arg) {
			case TCIFLUSH:
				flush_input(tty);
				break;
			case TCIOFLUSH:
				flush_input(tty);
				/* fall through */
			case TCOFLUSH:
				flush_output(tty);
				break;
			default:
				return -EINVAL;
			}
			return 0;
		case TIOCEXCL:
			set_bit(TTY_EXCLUSIVE, &tty->flags);
			return 0;
		case TIOCNXCL:
			clear_bit(TTY_EXCLUSIVE, &tty->flags);
			return 0;
		case TIOCSCTTY:
			if (current->leader &&
			    (current->session == tty->session))
				return 0;
			/*
			 * The process must be a session leader and
			 * not have a controlling tty already.
			 */
			if (!current->leader || (current->tty >= 0))
				return -EPERM;
			if (tty->session > 0) {
				/*
				 * This tty is already the controlling
				 * tty for another session group!
				 */
				if ((arg == 1) && suser()) {
					/*
					 * Steal it away
					 */
					struct task_struct *p;

					for_each_task(p)
						if (p->tty == dev)
							p->tty = -1;
				} else
					return -EPERM;
			}
			current->tty = dev;
			tty->session = current->session;
			tty->pgrp = current->pgrp;
			return 0;
		case TIOCGPGRP:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (pid_t));
			if (retval)
				return retval;
			if (current->tty != termios_dev)
				return -ENOTTY;
			put_fs_long(termios_tty->pgrp, (pid_t *) arg);
			return 0;
		case TIOCSPGRP:
			retval = check_change(termios_tty, termios_dev);
			if (retval)
				return retval;
			if ((current->tty < 0) ||
			    (current->tty != termios_dev) ||
			    (termios_tty->session != current->session))
				return -ENOTTY;
			pgrp = get_fs_long((pid_t *) arg);
			if (pgrp < 0)
				return -EINVAL;
			if (session_of_pgrp(pgrp) != current->session)
				return -EPERM;
			termios_tty->pgrp = pgrp;
			return 0;
		case TIOCOUTQ:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (unsigned long));
			if (retval)
				return retval;
			put_fs_long(CHARS(&tty->write_q),
				    (unsigned long *) arg);
			return 0;
		case TIOCINQ:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (unsigned long));
			if (retval)
				return retval;
			if (L_ICANON(tty))
				put_fs_long(inq_canon(tty),
					(unsigned long *) arg);
			else
				put_fs_long(CHARS(&tty->secondary),
					(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			if ((current->tty != dev) && !suser())
				return -EPERM;
			retval = verify_area(VERIFY_READ, (void *) arg, 1);
			if (retval)
				return retval;
			put_tty_queue(get_fs_byte((char *) arg), &tty->read_q);
			TTY_READ_FLUSH(tty);
			return 0;
		case TIOCGWINSZ:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (struct winsize));
			if (retval)
				return retval;
			memcpy_tofs((struct winsize *) arg, &tty->winsize,
				    sizeof (struct winsize));
			return 0;
		case TIOCSWINSZ:
			if (IS_A_PTY_MASTER(dev))
				set_window_size(other_tty,(struct winsize *) arg);
			return set_window_size(tty,(struct winsize *) arg);
		case TIOCLINUX:
			switch (get_fs_byte((char *)arg))
			{
				case 0: 
					return do_screendump(arg);
				case 1: 
					return do_get_ps_info(arg);
#ifdef CONFIG_SELECTION
				case 2:
					return set_selection(arg);
				case 3:
					return paste_selection(tty);
				case 4:
					unblank_screen();
					return 0;
#endif /* CONFIG_SELECTION */
				default: 
					return -EINVAL;
			}
		case TIOCCONS:
			if (IS_A_CONSOLE(dev)) {
				if (!suser())
					return -EPERM;
				redirect = NULL;
				return 0;
			}
			if (redirect)
				return -EBUSY;
			if (!suser())
				return -EPERM;
			if (IS_A_PTY_MASTER(dev))
				redirect = other_tty;
			else if (IS_A_PTY_SLAVE(dev))
				redirect = tty;
			else
				return -ENOTTY;
			return 0;
		case FIONBIO:
			arg = get_fs_long((unsigned long *) arg);
			if (arg)
				file->f_flags |= O_NONBLOCK;
			else
				file->f_flags &= ~O_NONBLOCK;
			return 0;
		case TIOCNOTTY:
			if (current->tty != dev)
				return -ENOTTY;
			if (current->leader)
				disassociate_ctty(0);
			current->tty = -1;
			return 0;
		case TIOCGETD:
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (unsigned long));
			if (retval)
				return retval;
			put_fs_long(tty->disc, (unsigned long *) arg);
			return 0;
		case TIOCSETD:
			retval = check_change(tty, dev);
			if (retval)
				return retval;
			arg = get_fs_long((unsigned long *) arg);
			return tty_set_ldisc(tty, arg);
		case TIOCGLCKTRMIOS:
			arg = get_fs_long((unsigned long *) arg);
			retval = verify_area(VERIFY_WRITE, (void *) arg,
					     sizeof (struct termios));
			if (retval)
				return retval;
			memcpy_tofs((struct termios *) arg,
				    &termios_locked[termios_dev],
				    sizeof (struct termios));
			return 0;
		case TIOCSLCKTRMIOS:
			if (!suser())
				return -EPERM;
			arg = get_fs_long((unsigned long *) arg);
			memcpy_fromfs(&termios_locked[termios_dev],
				      (struct termios *) arg,
				      sizeof (struct termios));
			return 0;
		case TIOCPKT:
			if (!IS_A_PTY_MASTER(dev))
				return -ENOTTY;
			retval = verify_area(VERIFY_READ, (void *) arg,
					     sizeof (unsigned long));
			if (retval)
				return retval;
			if (get_fs_long(arg)) {
				if (!tty->packet) {
					tty->packet = 1;
					tty->link->ctrl_status = 0;
				}
			} else
				tty->packet = 0;
			return 0;
		case TCSBRK: case TCSBRKP:
			retval = check_change(tty, dev);
			if (retval)
				return retval;
			wait_until_sent(tty, 0);
			if (!tty->ioctl)
				return 0;
			tty->ioctl(tty, file, cmd, arg);
			return 0;
		default:
			if (tty->ioctl) {
				retval = (tty->ioctl)(tty, file, cmd, arg);
				if (retval != -EINVAL)
					return retval;
			}
			if (ldiscs[tty->disc].ioctl) {
				retval = (ldiscs[tty->disc].ioctl)
					(tty, file, cmd, arg);
				return retval;
			}
			return -EINVAL;
	}
Exemplo n.º 19
0
static int
ip_proto_setsockopt(struct socket *sock, int level, int optname,
		    char *optval, int optlen)
{
    volatile struct sock *sk;
    int val;
    /* This should really pass things on to the other levels. */
    if (level != SOL_SOCKET) return (-EOPNOTSUPP);
    sk = sock->data;
   if (sk == NULL)
     {
	printk ("Warning: sock->data = NULL: %d\n" ,__LINE__);
	return (0);
     }
    verify_area (optval, sizeof (int));
    val = get_fs_long ((unsigned long *)optval);
    switch (optname)
      {
	case SO_TYPE:
	case SO_ERROR:
	default:
	  return (-ENOPROTOOPT);

	case SO_DEBUG: /* not implemented. */
	case SO_DONTROUTE:
	case SO_BROADCAST:
	case SO_SNDBUF:
	case SO_RCVBUF:
	  return (0);

	case SO_REUSEADDR:
	  if (val)
	    sk->reuse = 1;
	  else 
	    sk->reuse = 1;
	  return (0);

	case SO_KEEPALIVE:
	  if (val)
	    sk->keepopen = 1;
	  else
	    sk->keepopen = 0;
	  return (0);

	 case SO_OOBINLINE:
	  if (val)
	    sk->urginline = 1;
	  else
	    sk->urginline = 0;
	  return (0);

	 case SO_NO_CHECK:
	  if (val)
	    sk->no_check = 1;
	  else
	    sk->no_check = 0;
	  return (0);

	 case SO_PRIORITY:
	  if (val >= 0 && val < DEV_NUMBUFFS)
	    {
	       sk->priority = val;
	    }
	  else
	    {
	       return (-EINVAL);
	    }
	  return (0);

      }
}
Exemplo n.º 20
0
/*
 * We can actually return ERESTARTSYS insetad of EINTR, but I'd
 * like to be certain this leads to no problems. So I return
 * EINTR just for safety.
 */
int sys_select( unsigned long *buffer )
{
/* Perform the select(nd, in, out, ex, tv) system call. */
	int i;
	fd_set res_in, in = 0, *inp;
	fd_set res_out, out = 0, *outp;
	fd_set res_ex, ex = 0, *exp;
	fd_set mask;
	struct timeval *tvp;
	unsigned long timeout;

	mask = get_fs_long(buffer++);
	if (mask >= 32)
		mask = ~0;
	else
		mask = ~((~0) << mask);
	inp = (fd_set *) get_fs_long(buffer++);
	outp = (fd_set *) get_fs_long(buffer++);
	exp = (fd_set *) get_fs_long(buffer++);
	tvp = (struct timeval *) get_fs_long(buffer);

	if (inp)
		in = mask & get_fs_long(inp);
	if (outp)
		out = mask & get_fs_long(outp);
	if (exp)
		ex = mask & get_fs_long(exp);
	timeout = 0xffffffff;
	if (tvp) {
		timeout = get_fs_long((unsigned long *)&tvp->tv_usec)/(1000000/HZ);
		timeout += get_fs_long((unsigned long *)&tvp->tv_sec) * HZ;
		timeout += jiffies;
	}
	current->timeout = timeout;
	i = do_select(in, out, ex, &res_in, &res_out, &res_ex);
	if (current->timeout > jiffies)
		timeout = current->timeout - jiffies;
	else
		timeout = 0;
	current->timeout = 0;
	if (tvp) {
		verify_area(tvp, sizeof(*tvp));
		put_fs_long(timeout/HZ, (unsigned long *) &tvp->tv_sec);
		timeout %= HZ;
		timeout *= (1000000/HZ);
		put_fs_long(timeout, (unsigned long *) &tvp->tv_usec);
	}
	if (i < 0)
		return i;
	if (!i && (current->signal & ~current->blocked))
		return -EINTR;
	if (inp) {
		verify_area(inp, 4);
		put_fs_long(res_in,inp);
	}
	if (outp) {
		verify_area(outp,4);
		put_fs_long(res_out,outp);
	}
	if (exp) {
		verify_area(exp,4);
		put_fs_long(res_ex,exp);
	}
	return i;
}
Exemplo n.º 21
0
static int rs_ioctl(struct tty_struct *tty, struct file * file,
		    unsigned int cmd, unsigned long arg)
{
	int error;
	struct LEON_serial * info = (struct LEON_serial *)tty->driver_data;
	int retval;

	if (serial_paranoia_check(info, tty->device, "rs_ioctl"))
		return -ENODEV;

	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
		if (tty->flags & (1 << TTY_IO_ERROR))
		    return -EIO;
	}
	
	switch (cmd) {
		case TCSBRK:	/* SVID version: non-zero arg --> no break */
			retval = tty_check_change(tty);
			if (retval)
				return retval;
			tty_wait_until_sent(tty, 0);
			if (!arg)
				send_break(info, HZ/4);	/* 1/4 second */
			return 0;
		case TCSBRKP:	/* support for POSIX tcsendbreak() */
			retval = tty_check_change(tty);
			if (retval)
				return retval;
			tty_wait_until_sent(tty, 0);
			send_break(info, arg ? arg*(HZ/10) : HZ/4);
			return 0;
		case TIOCGSOFTCAR:
			error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
			if (error)
				return error;
			put_fs_long(C_CLOCAL(tty) ? 1 : 0,
				    (unsigned long *) arg);
			return 0;
		case TIOCSSOFTCAR:
			arg = get_fs_long((unsigned long *) arg);
			tty->termios->c_cflag =
				((tty->termios->c_cflag & ~CLOCAL) |
				 (arg ? CLOCAL : 0));
			return 0;
		case TIOCGSERIAL:
			error = verify_area(VERIFY_WRITE, (void *) arg,
						sizeof(struct serial_struct));
			if (error)
				return error;
			return get_serial_info(info,
					       (struct serial_struct *) arg);
		case TIOCSSERIAL:
			return set_serial_info(info,
					       (struct serial_struct *) arg);
		case TIOCSERGETLSR: /* Get line status register */
			error = verify_area(VERIFY_WRITE, (void *) arg,
				sizeof(unsigned int));
			if (error)
				return error;
			else
			    return get_lsr_info(info, (unsigned int *) arg);

		case TIOCSERGSTRUCT:
			error = verify_area(VERIFY_WRITE, (void *) arg,
						sizeof(struct LEON_serial));
			if (error)
				return error;
			memcpy_tofs((struct LEON_serial *) arg,
				    info, sizeof(struct LEON_serial));
			return 0;
			
		default:
			return -ENOIOCTLCMD;
		}
	return 0;
}
Exemplo n.º 22
0
int sys_mmap(unsigned long *buffer)
{
	unsigned long base, addr;
	unsigned long len, limit, off;
	int prot, flags, mask, fd, error;
	struct file *file;

	addr = (unsigned long)	get_fs_long(buffer);	/* user address space*/
	len = (size_t)		get_fs_long(buffer+1);	/* nbytes of mapping */
	prot = (int)		get_fs_long(buffer+2);	/* protection */
	flags = (int)		get_fs_long(buffer+3);	/* mapping type */
	fd = (int) 		get_fs_long(buffer+4);	/* object to map */
	off = (unsigned long)	get_fs_long(buffer+5);	/* offset in object */

	if (fd >= NR_OPEN || fd < 0 || !(file = current->filp[fd]))
		return -EBADF;
	if (addr > TASK_SIZE || len > TASK_SIZE || addr > TASK_SIZE-len)
		return -EINVAL;

	/*
	 * do simple checking here so the lower-level routines won't have
	 * to. we assume access permissions have been handled by the open
	 * of the memory object, so we don't do any here.
	 */

	switch (flags & MAP_TYPE) {
	case MAP_SHARED:
		if ((prot & PROT_WRITE) && !(file->f_mode & 2))
			return -EINVAL;
		/* fall through */
	case MAP_PRIVATE:
		if (!(file->f_mode & 1))
			return -EINVAL;
		break;

	default:
		return -EINVAL;
	}

	/*
	 * obtain the address to map to. we verify (or select) it and ensure
	 * that it represents a valid section of the address space. we assume
	 * that if PROT_EXEC is specified this should be in the code segment.
	 */
	if (prot & PROT_EXEC) {
		base = get_base(current->ldt[1]);	/* cs */
		limit = get_limit(0x0f);		/* cs limit */
	} else {
		base = get_base(current->ldt[2]);	/* ds */
		limit = get_limit(0x17);		/* ds limit */
	}

	if (flags & MAP_FIXED) {
		/*
		 * if MAP_FIXED is specified, we have to map exactly at this
		 * address. it must be page aligned and not ambiguous.
		 */
		if ((addr & 0xfff) || addr > 0x7fffffff || addr == 0 ||
		    (off & 0xfff))
			return -EINVAL;
		if (addr + len > limit)
			return -ENOMEM;
	} else {
		/*
		 * we're given a hint as to where to put the address.
		 * that we still need to search for a range of pages which
		 * are not mapped and which won't impact the stack or data
		 * segment.
		 * in linux, we only have a code segment and data segment.
		 * since data grows up and stack grows down, we're sort of
		 * stuck. placing above the data will break malloc, below
		 * the stack will cause stack overflow. because of this
		 * we don't allow nonspecified mappings...
		 */
		return -ENOMEM;
	}

	/*
	 * determine the object being mapped and call the appropriate
	 * specific mapper. the address has already been validated, but
	 * not unmapped
	 */
	if (!file->f_op || !file->f_op->mmap)
		return -ENODEV;
	mask = 0;
	if (prot & (PROT_READ | PROT_EXEC))
		mask |= PAGE_READONLY;
	if (prot & PROT_WRITE)
		mask |= PAGE_RW;
	if (!mask)
		return -EINVAL;
	if ((flags & MAP_TYPE) == MAP_PRIVATE) {
		mask |= PAGE_COW;
		mask &= ~PAGE_RW;
	}
	error = file->f_op->mmap(file->f_inode, file, base + addr, len, mask, off);
	if (error)
		return error;
	return addr;
}
Exemplo n.º 23
0
static int ioctl_command(Scsi_Device *dev, void *buffer)
{
	char * buf;
	char cmd[12];
	char * cmd_in;
	Scsi_Cmnd * SCpnt;
	unsigned char opcode;
	int inlen, outlen, cmdlen;
	int needed;
	int result;

	if (!buffer)
		return -EINVAL;
	
	inlen = get_fs_long((unsigned long *) buffer);
	outlen = get_fs_long( ((unsigned long *) buffer) + 1);

	cmd_in = (char *) ( ((int *)buffer) + 2);
	opcode = get_fs_byte(cmd_in); 

	needed = (inlen > outlen ? inlen : outlen);
	if(needed){
	  needed = (needed + 511) & ~511;
	  if (needed > MAX_BUF) needed = MAX_BUF;
	  buf = (char *) scsi_malloc(needed);
	  if (!buf) return -ENOMEM;
	} else
	  buf = NULL;

	memcpy_fromfs ((void *) cmd,  cmd_in,  cmdlen = COMMAND_SIZE (opcode));
	memcpy_fromfs ((void *) buf,  (void *) (cmd_in + cmdlen), inlen > MAX_BUF ? MAX_BUF : inlen);

	cmd[1] = ( cmd[1] & 0x1f ) | (dev->lun << 5);

#ifndef DEBUG_NO_CMD
	
	SCpnt = allocate_device(NULL, dev->index, 1);

	scsi_do_cmd(SCpnt,  cmd,  buf, needed,  scsi_ioctl_done,  MAX_TIMEOUT, 
			MAX_RETRIES);

	if (SCpnt->request.dev != 0xfffe){
	  SCpnt->request.waiting = current;
	  current->state = TASK_UNINTERRUPTIBLE;
	  while (SCpnt->request.dev != 0xfffe) schedule();
	};


	/* If there was an error condition, pass the info back to the user. */
	if(SCpnt->result) {
	  result = verify_area(VERIFY_WRITE, cmd_in, sizeof(SCpnt->sense_buffer));
	  if (result)
	    return result;
	  memcpy_tofs((void *) cmd_in,  SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer));
	} else {

	  result = verify_area(VERIFY_WRITE, cmd_in, (outlen > MAX_BUF) ? MAX_BUF  : outlen);
	  if (result)
	    return result;
	  memcpy_tofs ((void *) cmd_in,  buf,  (outlen > MAX_BUF) ? MAX_BUF  : outlen);
	};
	result = SCpnt->result;
	SCpnt->request.dev = -1;  /* Mark as not busy */
	if (buf) scsi_free(buf, needed);
	wake_up(&scsi_devices[SCpnt->index].device_wait);
	return result;
#else
	{
	int i;
	printk("scsi_ioctl : device %d.  command = ", dev->id);
	for (i = 0; i < 12; ++i)
		printk("%02x ", cmd[i]);
	printk("\nbuffer =");
	for (i = 0; i < 20; ++i)
		printk("%02x ", buf[i]);
	printk("\n");
	printk("inlen = %d, outlen = %d, cmdlen = %d\n",
		inlen, outlen, cmdlen);
	printk("buffer = %d, cmd_in = %d\n", buffer, cmd_in);
	}
	return 0;
#endif
}
Exemplo n.º 24
0
int tty_ioctl(int dev, int cmd, int arg)
{
	struct tty_struct * tty;
	if (MAJOR(dev) == 5) {
		dev=current->tty;
		if (dev<0)
			panic("tty_ioctl: dev<0");
	} else
		dev=MINOR(dev);
	tty = dev + tty_table;
	switch (cmd) {
		case TCGETS:
			return get_termios(tty,(struct termios *) arg);
		case TCSETSF:
			flush(&tty->read_q); /* fallthrough */
		case TCSETSW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETS:
			return set_termios(tty,(struct termios *) arg);
		case TCGETA:
			return get_termio(tty,(struct termio *) arg);
		case TCSETAF:
			flush(&tty->read_q); /* fallthrough */
		case TCSETAW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETA:
			return set_termio(tty,(struct termio *) arg);
		case TCSBRK:
			if (!arg) {
				wait_until_sent(tty);
				send_break(tty);
			}
			return 0;
		case TCXONC:
			return -EINVAL; /* not implemented */
		case TCFLSH:
			if (arg==0)
				flush(&tty->read_q);
			else if (arg==1)
				flush(&tty->write_q);
			else if (arg==2) {
				flush(&tty->read_q);
				flush(&tty->write_q);
			} else
				return -EINVAL;
			return 0;
		case TIOCEXCL:
			return -EINVAL; /* not implemented */
		case TIOCNXCL:
			return -EINVAL; /* not implemented */
		case TIOCSCTTY:
			return -EINVAL; /* set controlling term NI */
		case TIOCGPGRP:
			verify_area((void *) arg,4);
			put_fs_long(tty->pgrp,(unsigned long *) arg);
			return 0;
		case TIOCSPGRP:
			tty->pgrp=get_fs_long((unsigned long *) arg);
			return 0;
		case TIOCOUTQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			return -EINVAL; /* not implemented */
		case TIOCGWINSZ:
			return -EINVAL; /* not implemented */
		case TIOCSWINSZ:
			return -EINVAL; /* not implemented */
		case TIOCMGET:
			return -EINVAL; /* not implemented */
		case TIOCMBIS:
			return -EINVAL; /* not implemented */
		case TIOCMBIC:
			return -EINVAL; /* not implemented */
		case TIOCMSET:
			return -EINVAL; /* not implemented */
		case TIOCGSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCSSOFTCAR:
			return -EINVAL; /* not implemented */
		default:
			return -EINVAL;
	}
}
Exemplo n.º 25
0
static int
math_emulate(struct trapframe * info)
{
	unsigned short code;
	temp_real tmp;
	char * address;
	u_long oldeip;

	/* ever used fp? */
	if ((((struct pcb *)curproc->p_addr)->pcb_flags & FP_SOFTFP) == 0) {
		((struct pcb *)curproc->p_addr)->pcb_flags |= FP_SOFTFP;
		I387.cwd = 0x037f;
		I387.swd = 0x0000;
		I387.twd = 0x0000;
	}

	if (I387.cwd & I387.swd & 0x3f)
		I387.swd |= 0x8000;
	else
		I387.swd &= 0x7fff;
	oldeip = info->tf_eip;
/* 0x001f means user code space */
	if ((u_short)info->tf_cs != 0x001F) {
		printf("math_emulate: %04x:%08lx\n", (u_short)info->tf_cs,
			oldeip);
		panic("?Math emulation needed in kernel?");
	}
	code = get_fs_word((unsigned short *) oldeip);
	bswapw(code);
	code &= 0x7ff;
	I387.fip = oldeip;
	*(unsigned short *) &I387.fcs = (u_short) info->tf_cs;
	*(1+(unsigned short *) &I387.fcs) = code;
	info->tf_eip += 2;
	switch (code) {
		case 0x1d0: /* fnop */
			return(0);
		case 0x1d1: case 0x1d2: case 0x1d3:  /* fst to 32-bit mem */
		case 0x1d4: case 0x1d5: case 0x1d6: case 0x1d7:
			math_abort(info,SIGILL);
		case 0x1e0: /* fchs */
			ST(0).exponent ^= 0x8000;
			return(0);
		case 0x1e1: /* fabs */
			ST(0).exponent &= 0x7fff;
			return(0);
		case 0x1e2: case 0x1e3:
			math_abort(info,SIGILL);
		case 0x1e4: /* ftst */
			ftst(PST(0));
			return(0);
		case 0x1e5: /* fxam */
			printf("fxam not implemented\n");
			math_abort(info,SIGILL);
		case 0x1e6: case 0x1e7: /* fldenv */
			math_abort(info,SIGILL);
		case 0x1e8: /* fld1 */
			fpush();
			ST(0) = CONST1;
			return(0);
		case 0x1e9: /* fld2t */
			fpush();
			ST(0) = CONSTL2T;
			return(0);
		case 0x1ea: /* fld2e */
			fpush();
			ST(0) = CONSTL2E;
			return(0);
		case 0x1eb: /* fldpi */
			fpush();
			ST(0) = CONSTPI;
			return(0);
		case 0x1ec: /* fldlg2 */
			fpush();
			ST(0) = CONSTLG2;
			return(0);
		case 0x1ed: /* fldln2 */
			fpush();
			ST(0) = CONSTLN2;
			return(0);
		case 0x1ee: /* fldz */
			fpush();
			ST(0) = CONSTZ;
			return(0);
		case 0x1ef:
			math_abort(info,SIGILL);
		case 0x1f0: /* f2xm1 */
		case 0x1f1: /* fyl2x */
		case 0x1f2: /* fptan */
		case 0x1f3: /* fpatan */
		case 0x1f4: /* fxtract */
		case 0x1f5: /* fprem1 */
		case 0x1f6: /* fdecstp */
		case 0x1f7: /* fincstp */
		case 0x1f8: /* fprem */
		case 0x1f9: /* fyl2xp1 */
		case 0x1fa: /* fsqrt */
		case 0x1fb: /* fsincos */
		case 0x1fe: /* fsin */
		case 0x1ff: /* fcos */
			uprintf(
			 "math_emulate: instruction %04x not implemented\n",
			  code + 0xd800);
			math_abort(info,SIGILL);
		case 0x1fc: /* frndint */
			frndint(PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 0x1fd: /* fscale */
			/* incomplete and totally inadequate -wfj */
			Fscale(PST(0), PST(1), &tmp);
			real_to_real(&tmp,&ST(0));
			return(0);			/* 19 Sep 92*/
		case 0x2e9: /* ????? */
/* if this should be a fucomp ST(0),ST(1) , it must be a 0x3e9  ATS */
			fucom(PST(1),PST(0));
			fpop(); fpop();
			return(0);
		case 0x3d0: case 0x3d1: /* fist ?? */
			return(0);
		case 0x3e2: /* fclex */
			I387.swd &= 0x7f00;
			return(0);
		case 0x3e3: /* fninit */
			I387.cwd = 0x037f;
			I387.swd = 0x0000;
			I387.twd = 0x0000;
			return(0);
		case 0x3e4:
			return(0);
		case 0x6d9: /* fcompp */
			fcom(PST(1),PST(0));
			fpop(); fpop();
			return(0);
		case 0x7e0: /* fstsw ax */
			*(short *) &info->tf_eax = I387.swd;
			return(0);
	}
	switch (code >> 3) {
		case 0x18: /* fadd */
			fadd(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 0x19: /* fmul */
			fmul(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 0x1a: /* fcom */
			fcom(PST(code & 7),PST(0));
			return(0);
		case 0x1b: /* fcomp */
			fcom(PST(code & 7),PST(0));
			fpop();
			return(0);
		case 0x1c: /* fsubr */
			real_to_real(&ST(code & 7),&tmp);
			tmp.exponent ^= 0x8000;
			fadd(PST(0),&tmp,&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 0x1d: /* fsub */
			ST(0).exponent ^= 0x8000;
			fadd(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 0x1e: /* fdivr */
			fdiv(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 0x1f: /* fdiv */
			fdiv(PST(code & 7),PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 0x38: /* fld */
			fpush();
			ST(0) = ST((code & 7)+1);  /* why plus 1 ????? ATS */
			return(0);
		case 0x39: /* fxch */
			fxchg(&ST(0),&ST(code & 7));
			return(0);
		case 0x3b: /*  ??? ??? wrong ???? ATS */
			ST(code & 7) = ST(0);
			fpop();
			return(0);
		case 0x98: /* fadd */
			fadd(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return(0);
		case 0x99: /* fmul */
			fmul(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return(0);
		case 0x9a: /* ???? , my manual don't list a direction bit
for fcom , ??? ATS */
			fcom(PST(code & 7),PST(0));
			return(0);
		case 0x9b: /* same as above , ATS */
			fcom(PST(code & 7),PST(0));
			fpop();
			return(0);
		case 0x9c: /* fsubr */
			ST(code & 7).exponent ^= 0x8000;
			fadd(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return(0);
		case 0x9d: /* fsub */
			real_to_real(&ST(0),&tmp);
			tmp.exponent ^= 0x8000;
			fadd(PST(code & 7),&tmp,&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return(0);
		case 0x9e: /* fdivr */
			fdiv(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return(0);
		case 0x9f: /* fdiv */
			fdiv(PST(code & 7),PST(0),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return(0);
		case 0xb8: /* ffree */
			printf("ffree not implemented\n");
			math_abort(info,SIGILL);
		case 0xb9: /* fstp ???? where is the pop ? ATS */
			fxchg(&ST(0),&ST(code & 7));
			return(0);
		case 0xba: /* fst */
			ST(code & 7) = ST(0);
			return(0);
		case 0xbb: /* ????? encoding of fstp to mem ? ATS */
			ST(code & 7) = ST(0);
			fpop();
			return(0);
		case 0xbc: /* fucom */
			fucom(PST(code & 7),PST(0));
			return(0);
		case 0xbd: /* fucomp */
			fucom(PST(code & 7),PST(0));
			fpop();
			return(0);
		case 0xd8: /* faddp */
			fadd(PST(code & 7),PST(0),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return(0);
		case 0xd9: /* fmulp */
			fmul(PST(code & 7),PST(0),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return(0);
		case 0xda: /* ??? encoding of ficom with 16 bit mem ? ATS */
			fcom(PST(code & 7),PST(0));
			fpop();
			return(0);
		case 0xdc: /* fsubrp */
			ST(code & 7).exponent ^= 0x8000;
			fadd(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return(0);
		case 0xdd: /* fsubp */
			real_to_real(&ST(0),&tmp);
			tmp.exponent ^= 0x8000;
			fadd(PST(code & 7),&tmp,&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return(0);
		case 0xde: /* fdivrp */
			fdiv(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return(0);
		case 0xdf: /* fdivp */
			fdiv(PST(code & 7),PST(0),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return(0);
		case 0xf8: /* fild 16-bit mem ???? ATS */
			printf("ffree not implemented\n");
			math_abort(info,SIGILL);
			fpop();
			return(0);
		case 0xf9: /*  ????? ATS */
			fxchg(&ST(0),&ST(code & 7));
			return(0);
		case 0xfa: /* fist 16-bit mem ? ATS */
		case 0xfb: /* fistp 16-bit mem ? ATS */
			ST(code & 7) = ST(0);
			fpop();
			return(0);
	}
	switch ((code>>3) & 0xe7) {
		case 0x22:
			put_short_real(PST(0),info,code);
			return(0);
		case 0x23:
			put_short_real(PST(0),info,code);
			fpop();
			return(0);
		case 0x24:
			address = ea(info,code);
			for (code = 0 ; code < 7 ; code++) {
				((long *) & I387)[code] =
				   get_fs_long((unsigned long *) address);
				address += 4;
			}
			return(0);
		case 0x25:
			address = ea(info,code);
			*(unsigned short *) &I387.cwd =
				get_fs_word((unsigned short *) address);
			return(0);
		case 0x26:
			address = ea(info,code);
			/*verify_area(address,28);*/
			for (code = 0 ; code < 7 ; code++) {
				put_fs_long( ((long *) & I387)[code],
					(unsigned long *) address);
				address += 4;
			}
			return(0);
		case 0x27:
			address = ea(info,code);
			/*verify_area(address,2);*/
			put_fs_word(I387.cwd,(short *) address);
			return(0);
		case 0x62:
			put_long_int(PST(0),info,code);
			return(0);
		case 0x63:
			put_long_int(PST(0),info,code);
			fpop();
			return(0);
		case 0x65:
			fpush();
			get_temp_real(&tmp,info,code);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 0x67:
			put_temp_real(PST(0),info,code);
			fpop();
			return(0);
		case 0xa2:
			put_long_real(PST(0),info,code);
			return(0);
		case 0xa3:
			put_long_real(PST(0),info,code);
			fpop();
			return(0);
		case 0xa4:
			address = ea(info,code);
			for (code = 0 ; code < 27 ; code++) {
				((long *) & I387)[code] =
				   get_fs_long((unsigned long *) address);
				address += 4;
			}
			return(0);
		case 0xa6:
			address = ea(info,code);
			/*verify_area(address,108);*/
			for (code = 0 ; code < 27 ; code++) {
				put_fs_long( ((long *) & I387)[code],
					(unsigned long *) address);
				address += 4;
			}
			I387.cwd = 0x037f;
			I387.swd = 0x0000;
			I387.twd = 0x0000;
			return(0);
		case 0xa7:
			address = ea(info,code);
			/*verify_area(address,2);*/
			put_fs_word(I387.swd,(short *) address);
			return(0);
		case 0xe2:
			put_short_int(PST(0),info,code);
			return(0);
		case 0xe3:
			put_short_int(PST(0),info,code);
			fpop();
			return(0);
		case 0xe4:
			fpush();
			get_BCD(&tmp,info,code);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 0xe5:
			fpush();
			get_longlong_int(&tmp,info,code);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 0xe6:
			put_BCD(PST(0),info,code);
			fpop();
			return(0);
		case 0xe7:
			put_longlong_int(PST(0),info,code);
			fpop();
			return(0);
	}
	switch (code >> 9) {
		case 0:
			get_short_real(&tmp,info,code);
			break;
		case 1:
			get_long_int(&tmp,info,code);
			break;
		case 2:
			get_long_real(&tmp,info,code);
			break;
		case 4:
			get_short_int(&tmp,info,code);
	}
	switch ((code>>3) & 0x27) {
		case 0:
			fadd(&tmp,PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 1:
			fmul(&tmp,PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 2:
			fcom(&tmp,PST(0));
			return(0);
		case 3:
			fcom(&tmp,PST(0));
			fpop();
			return(0);
		case 4:
			tmp.exponent ^= 0x8000;
			fadd(&tmp,PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 5:
			ST(0).exponent ^= 0x8000;
			fadd(&tmp,PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 6:
			fdiv(PST(0),&tmp,&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
		case 7:
			fdiv(&tmp,PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return(0);
	}
	if ((code & 0x138) == 0x100) {
			fpush();
			real_to_real(&tmp,&ST(0));
			return(0);
	}
	printf("Unknown math-insns: %04x:%08x %04x\n",(u_short)info->tf_cs,
		info->tf_eip,code);
	math_abort(info,SIGFPE);
}
Exemplo n.º 26
0
static int
timer_ioctl (int dev,
	     unsigned int cmd, caddr_t arg)
{
  switch (cmd)
    {
    case SNDCTL_TMR_SOURCE:
      return snd_ioctl_return ((int *) arg, TMR_INTERNAL);
      break;

    case SNDCTL_TMR_START:
      tmr_reset ();
      tmr_running = 1;
      return 0;
      break;

    case SNDCTL_TMR_STOP:
      tmr_running = 0;
      return 0;
      break;

    case SNDCTL_TMR_CONTINUE:
      tmr_running = 1;
      return 0;
      break;

    case SNDCTL_TMR_TIMEBASE:
      {
	int             val = get_fs_long ((long *) arg);

	if (val)
	  {
	    if (val < 1)
	      val = 1;
	    if (val > 1000)
	      val = 1000;
	    curr_timebase = val;
	  }

	return snd_ioctl_return ((int *) arg, curr_timebase);
      }
      break;

    case SNDCTL_TMR_TEMPO:
      {
	int             val = get_fs_long ((long *) arg);

	if (val)
	  {
	    if (val < 8)
	      val = 8;
	    if (val > 250)
	      val = 250;
	    tmr_offs = tmr_ctr;
	    ticks_offs += tmr2ticks (tmr_ctr);
	    tmr_ctr = 0;
	    curr_tempo = val;
	    reprogram_timer ();
	  }

	return snd_ioctl_return ((int *) arg, curr_tempo);
      }
      break;

    case SNDCTL_SEQ_CTRLRATE:
      if (get_fs_long ((long *) arg) != 0)	/* Can't change */
	return -(EINVAL);

      return snd_ioctl_return ((int *) arg, ((curr_tempo * curr_timebase) + 30) / 60);
      break;

    case SNDCTL_TMR_METRONOME:
      /* NOP */
      break;

    default:;
    }

  return -(EINVAL);
}
Exemplo n.º 27
0
static void do_emu(struct info * info)
{
	unsigned short code;
	temp_real tmp;
	char * address;

	if (I387.cwd & I387.swd & 0x3f)
		I387.swd |= 0x8000;
	else
		I387.swd &= 0x7fff;
	ORIG_EIP = EIP;
/* 0x0007 means user code space */
	if (CS != 0x000F) {
		printk("math_emulate: %04x:%08x\n\r",CS,EIP);
		panic("Math emulation needed in kernel");
	}
	code = get_fs_word((unsigned short *) EIP);
	bswapw(code);
	code &= 0x7ff;
	I387.fip = EIP;
	*(unsigned short *) &I387.fcs = CS;
	*(1+(unsigned short *) &I387.fcs) = code;
	EIP += 2;
	switch (code) {
		case 0x1d0: /* fnop */
			return;
		case 0x1d1: case 0x1d2: case 0x1d3:
		case 0x1d4: case 0x1d5: case 0x1d6: case 0x1d7:
			math_abort(info,1<<(SIGILL-1));
		case 0x1e0:
			ST(0).exponent ^= 0x8000;
			return;
		case 0x1e1:
			ST(0).exponent &= 0x7fff;
			return;
		case 0x1e2: case 0x1e3:
			math_abort(info,1<<(SIGILL-1));
		case 0x1e4:
			ftst(PST(0));
			return;
		case 0x1e5:
			printk("fxam not implemented\n\r");
			math_abort(info,1<<(SIGILL-1));
		case 0x1e6: case 0x1e7:
			math_abort(info,1<<(SIGILL-1));
		case 0x1e8:
			fpush();
			ST(0) = CONST1;
			return;
		case 0x1e9:
			fpush();
			ST(0) = CONSTL2T;
			return;
		case 0x1ea:
			fpush();
			ST(0) = CONSTL2E;
			return;
		case 0x1eb:
			fpush();
			ST(0) = CONSTPI;
			return;
		case 0x1ec:
			fpush();
			ST(0) = CONSTLG2;
			return;
		case 0x1ed:
			fpush();
			ST(0) = CONSTLN2;
			return;
		case 0x1ee:
			fpush();
			ST(0) = CONSTZ;
			return;
		case 0x1ef:
			math_abort(info,1<<(SIGILL-1));
		case 0x1f0: case 0x1f1: case 0x1f2: case 0x1f3:
		case 0x1f4: case 0x1f5: case 0x1f6: case 0x1f7:
		case 0x1f8: case 0x1f9: case 0x1fa: case 0x1fb:
		case 0x1fc: case 0x1fd: case 0x1fe: case 0x1ff:
			printk("%04x fxxx not implemented\n\r",code + 0xc800);
			math_abort(info,1<<(SIGILL-1));
		case 0x2e9:
			fucom(PST(1),PST(0));
			fpop(); fpop();
			return;
		case 0x3d0: case 0x3d1:
			return;
		case 0x3e2:
			I387.swd &= 0x7f00;
			return;
		case 0x3e3:
			I387.cwd = 0x037f;
			I387.swd = 0x0000;
			I387.twd = 0x0000;
			return;
		case 0x3e4:
			return;
		case 0x6d9:
			fcom(PST(1),PST(0));
			fpop(); fpop();
			return;
		case 0x7e0:
			*(short *) &EAX = I387.swd;
			return;
	}
	switch (code >> 3) {
		case 0x18:
			fadd(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 0x19:
			fmul(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 0x1a:
			fcom(PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 0x1b:
			fcom(PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(0));
			fpop();
			return;
		case 0x1c:
			real_to_real(&ST(code & 7),&tmp);
			tmp.exponent ^= 0x8000;
			fadd(PST(0),&tmp,&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 0x1d:
			ST(0).exponent ^= 0x8000;
			fadd(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 0x1e:
			fdiv(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 0x1f:
			fdiv(PST(code & 7),PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 0x38:
			fpush();
			ST(0) = ST((code & 7)+1);
			return;
		case 0x39:
			fxchg(&ST(0),&ST(code & 7));
			return;
		case 0x3b:
			ST(code & 7) = ST(0);
			fpop();
			return;
		case 0x98:
			fadd(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return;
		case 0x99:
			fmul(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return;
		case 0x9a:
			fcom(PST(code & 7),PST(0));
			return;
		case 0x9b:
			fcom(PST(code & 7),PST(0));
			fpop();
			return;			
		case 0x9c:
			ST(code & 7).exponent ^= 0x8000;
			fadd(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return;
		case 0x9d:
			real_to_real(&ST(0),&tmp);
			tmp.exponent ^= 0x8000;
			fadd(PST(code & 7),&tmp,&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return;
		case 0x9e:
			fdiv(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return;
		case 0x9f:
			fdiv(PST(code & 7),PST(0),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			return;
		case 0xb8:
			printk("ffree not implemented\n\r");
			math_abort(info,1<<(SIGILL-1));
		case 0xb9:
			fxchg(&ST(0),&ST(code & 7));
			return;
		case 0xba:
			ST(code & 7) = ST(0);
			return;
		case 0xbb:
			ST(code & 7) = ST(0);
			fpop();
			return;
		case 0xbc:
			fucom(PST(code & 7),PST(0));
			return;
		case 0xbd:
			fucom(PST(code & 7),PST(0));
			fpop();
			return;
		case 0xd8:
			fadd(PST(code & 7),PST(0),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return;
		case 0xd9:
			fmul(PST(code & 7),PST(0),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return;
		case 0xda:
			fcom(PST(code & 7),PST(0));
			fpop();
			return;
		case 0xdc:
			ST(code & 7).exponent ^= 0x8000;
			fadd(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return;
		case 0xdd:
			real_to_real(&ST(0),&tmp);
			tmp.exponent ^= 0x8000;
			fadd(PST(code & 7),&tmp,&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return;
		case 0xde:
			fdiv(PST(0),PST(code & 7),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return;
		case 0xdf:
			fdiv(PST(code & 7),PST(0),&tmp);
			real_to_real(&tmp,&ST(code & 7));
			fpop();
			return;
		case 0xf8:
			printk("ffree not implemented\n\r");
			math_abort(info,1<<(SIGILL-1));
			fpop();
			return;
		case 0xf9:
			fxchg(&ST(0),&ST(code & 7));
			return;
		case 0xfa:
		case 0xfb:
			ST(code & 7) = ST(0);
			fpop();
			return;
	}
	switch ((code>>3) & 0xe7) {
		case 0x22:
			put_short_real(PST(0),info,code);
			return;
		case 0x23:
			put_short_real(PST(0),info,code);
			fpop();
			return;
		case 0x24:
			address = ea(info,code);
			for (code = 0 ; code < 7 ; code++) {
				((long *) & I387)[code] =
				   get_fs_long((unsigned long *) address);
				address += 4;
			}
			return;
		case 0x25:
			address = ea(info,code);
			*(unsigned short *) &I387.cwd =
				get_fs_word((unsigned short *) address);
			return;
		case 0x26:
			address = ea(info,code);
			verify_area(address,28);
			for (code = 0 ; code < 7 ; code++) {
				put_fs_long( ((long *) & I387)[code],
					(unsigned long *) address);
				address += 4;
			}
			return;
		case 0x27:
			address = ea(info,code);
			verify_area(address,2);
			put_fs_word(I387.cwd,(short *) address);
			return;
		case 0x62:
			put_long_int(PST(0),info,code);
			return;
		case 0x63:
			put_long_int(PST(0),info,code);
			fpop();
			return;
		case 0x65:
			fpush();
			get_temp_real(&tmp,info,code);
			real_to_real(&tmp,&ST(0));
			return;
		case 0x67:
			put_temp_real(PST(0),info,code);
			fpop();
			return;
		case 0xa2:
			put_long_real(PST(0),info,code);
			return;
		case 0xa3:
			put_long_real(PST(0),info,code);
			fpop();
			return;
		case 0xa4:
			address = ea(info,code);
			for (code = 0 ; code < 27 ; code++) {
				((long *) & I387)[code] =
				   get_fs_long((unsigned long *) address);
				address += 4;
			}
			return;
		case 0xa6:
			address = ea(info,code);
			verify_area(address,108);
			for (code = 0 ; code < 27 ; code++) {
				put_fs_long( ((long *) & I387)[code],
					(unsigned long *) address);
				address += 4;
			}
			I387.cwd = 0x037f;
			I387.swd = 0x0000;
			I387.twd = 0x0000;
			return;
		case 0xa7:
			address = ea(info,code);
			verify_area(address,2);
			put_fs_word(I387.swd,(short *) address);
			return;
		case 0xe2:
			put_short_int(PST(0),info,code);
			return;
		case 0xe3:
			put_short_int(PST(0),info,code);
			fpop();
			return;
		case 0xe4:
			fpush();
			get_BCD(&tmp,info,code);
			real_to_real(&tmp,&ST(0));
			return;
		case 0xe5:
			fpush();
			get_longlong_int(&tmp,info,code);
			real_to_real(&tmp,&ST(0));
			return;
		case 0xe6:
			put_BCD(PST(0),info,code);
			fpop();
			return;
		case 0xe7:
			put_longlong_int(PST(0),info,code);
			fpop();
			return;
	}
	switch (code >> 9) {
		case 0:
			get_short_real(&tmp,info,code);
			break;
		case 1:
			get_long_int(&tmp,info,code);
			break;
		case 2:
			get_long_real(&tmp,info,code);
			break;
		case 4:
			get_short_int(&tmp,info,code);
	}
	switch ((code>>3) & 0x27) {
		case 0:
			fadd(&tmp,PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 1:
			fmul(&tmp,PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 2:
			fcom(&tmp,PST(0));
			return;
		case 3:
			fcom(&tmp,PST(0));
			fpop();
			return;
		case 4:
			tmp.exponent ^= 0x8000;
			fadd(&tmp,PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 5:
			ST(0).exponent ^= 0x8000;
			fadd(&tmp,PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 6:
			fdiv(PST(0),&tmp,&tmp);
			real_to_real(&tmp,&ST(0));
			return;
		case 7:
			fdiv(&tmp,PST(0),&tmp);
			real_to_real(&tmp,&ST(0));
			return;
	}
	if ((code & 0x138) == 0x100) {
			fpush();
			real_to_real(&tmp,&ST(0));
			return;
	}
	printk("Unknown math-insns: %04x:%08x %04x\n\r",CS,EIP,code);
	math_abort(info,1<<(SIGFPE-1));
}
Exemplo n.º 28
0
int sys_semctl (int semid, int semnum, int cmd, void *arg)
{
	int i, id, val = 0;
	struct semid_ds *sma, *buf = NULL, tbuf;
	struct ipc_perm *ipcp;
	struct sem *curr;
	struct sem_undo *un;
	ushort nsems, *array = NULL;
	ushort sem_io[SEMMSL];
	
	if (semid < 0 || semnum < 0 || cmd < 0)
		return -EINVAL;

	switch (cmd) {
	case IPC_INFO: 
	case SEM_INFO: 
	{
		struct seminfo seminfo, *tmp;
		if (!arg || ! (tmp = (struct seminfo *) get_fs_long((int *)arg)))
			return -EFAULT;
		seminfo.semmni = SEMMNI;
		seminfo.semmns = SEMMNS;
		seminfo.semmsl = SEMMSL;
		seminfo.semopm = SEMOPM;
		seminfo.semvmx = SEMVMX;
		seminfo.semmnu = SEMMNU; 
		seminfo.semmap = SEMMAP; 
		seminfo.semume = SEMUME;
		seminfo.semusz = SEMUSZ;
		seminfo.semaem = SEMAEM;
		if (cmd == SEM_INFO) {
			seminfo.semusz = used_semids;
			seminfo.semaem = used_sems;
		}
		i= verify_area(VERIFY_WRITE, tmp, sizeof(struct seminfo));
		if (i)
			return i;
		memcpy_tofs (tmp, &seminfo, sizeof(struct seminfo));
		return max_semid;
	}

	case SEM_STAT:
		if (!arg || ! (buf = (struct semid_ds *) get_fs_long((int *) arg)))
			return -EFAULT;
		i = verify_area (VERIFY_WRITE, buf, sizeof (*sma));
		if (i)
			return i;
		if (semid > max_semid)
			return -EINVAL;
		sma = semary[semid];
		if (sma == IPC_UNUSED || sma == IPC_NOID)
			return -EINVAL;
		if (ipcperms (&sma->sem_perm, S_IRUGO))
			return -EACCES;
		id = semid + sma->sem_perm.seq * SEMMNI; 
		memcpy_tofs (buf, sma, sizeof(*sma));
		return id;
	}

	id = semid % SEMMNI;
	sma = semary [id];
	if (sma == IPC_UNUSED || sma == IPC_NOID)
		return -EINVAL;
	ipcp = &sma->sem_perm;
	nsems = sma->sem_nsems;
	if (ipcp->seq != semid / SEMMNI)
		return -EIDRM;
	if (semnum >= nsems)
		return -EINVAL;
	curr = &sma->sem_base[semnum];

	switch (cmd) {
	case GETVAL:
	case GETPID:
	case GETNCNT:
	case GETZCNT:
	case GETALL:
		if (ipcperms (ipcp, S_IRUGO))
			return -EACCES;
		switch (cmd) {
		case GETVAL : return curr->semval; 
		case GETPID : return curr->sempid;
		case GETNCNT: return curr->semncnt;
		case GETZCNT: return curr->semzcnt;
		case GETALL:
			if (!arg || ! (array = (ushort *) get_fs_long((int *) arg)))
				return -EFAULT;
			i = verify_area (VERIFY_WRITE, array, nsems*sizeof(short));
			if (i)
				return i;
		}
		break;
	case SETVAL: 
		if (!arg)
			return -EFAULT;
		if ((val = (int) get_fs_long ((int *) arg))  > SEMVMX || val < 0) 
			return -ERANGE;
		break;
	case IPC_RMID:
		if (suser() || current->euid == ipcp->cuid || 
		    current->euid == ipcp->uid) {
			freeary (id); 
			return 0;
		}
		return -EPERM;
	case SETALL: /* arg is a pointer to an array of ushort */
		if (!arg || ! (array = (ushort *) get_fs_long ((int *) arg)) )
			return -EFAULT;
		if ((i = verify_area (VERIFY_READ, array, sizeof tbuf)))
			return i;
		memcpy_fromfs (sem_io, array, nsems*sizeof(ushort));
		for (i=0; i< nsems; i++)
			if (sem_io[i] > SEMVMX)
				return -ERANGE;
		break;
	case IPC_STAT:
		if (!arg || !(buf = (struct semid_ds *) get_fs_long((int *) arg))) 
			return -EFAULT;
		if ((i = verify_area (VERIFY_WRITE, buf, sizeof(*sma))))
			return i;
		break;
	case IPC_SET:
		if (!arg || !(buf = (struct semid_ds *) get_fs_long((int *) arg))) 
			return -EFAULT;
		if ((i = verify_area (VERIFY_READ, buf, sizeof tbuf)))
			return i;
		memcpy_fromfs (&tbuf, buf, sizeof tbuf);
		break;
	}
	
	if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)
		return -EIDRM;
	if (ipcp->seq != semid / SEMMNI)
		return -EIDRM;
	
	switch (cmd) {
	case GETALL:
		if (ipcperms (ipcp, S_IRUGO))
			return -EACCES;
		for (i=0; i< sma->sem_nsems; i++)
			sem_io[i] = sma->sem_base[i].semval;
		memcpy_tofs (array, sem_io, nsems*sizeof(ushort));
		break;
	case SETVAL:
		if (ipcperms (ipcp, S_IWUGO))
			return -EACCES;
		for (un = sma->undo; un; un = un->id_next)
			if (semnum == un->sem_num)
				un->semadj = 0;
		sma->sem_ctime = CURRENT_TIME;
		curr->semval = val;
		if (sma->eventn)
			wake_up (&sma->eventn);
		if (sma->eventz)
			wake_up (&sma->eventz);
		break;
	case IPC_SET:
		if (suser() || current->euid == ipcp->cuid || 
		    current->euid == ipcp->uid) {
			ipcp->uid = tbuf.sem_perm.uid;
			ipcp->gid = tbuf.sem_perm.gid;
			ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
				| (tbuf.sem_perm.mode & S_IRWXUGO);
			sma->sem_ctime = CURRENT_TIME;
			return 0;
		}
		return -EPERM;
	case IPC_STAT:
		if (ipcperms (ipcp, S_IRUGO))
			return -EACCES;
		memcpy_tofs (buf, sma, sizeof (*sma));
		break;
	case SETALL:
		if (ipcperms (ipcp, S_IWUGO))
			return -EACCES;
		for (i=0; i<nsems; i++) 
			sma->sem_base[i].semval = sem_io[i];
		for (un = sma->undo; un; un = un->id_next)
			un->semadj = 0;
		if (sma->eventn)
			wake_up (&sma->eventn);
		if (sma->eventz)
			wake_up (&sma->eventz);
		sma->sem_ctime = CURRENT_TIME;
		break;
	default:
		return -EINVAL;
	}
	return 0;
}
Exemplo n.º 29
0
int tty_ioctl(struct inode * inode, struct file * file,
	unsigned int cmd, unsigned int arg)
{
	struct tty_struct * tty;
	struct tty_struct * other_tty;
	int pgrp;
	int dev;

	if (MAJOR(file->f_rdev) != 4) {
		printk("tty_ioctl: tty pseudo-major != 4\n");
		return -EINVAL;
	}
	dev = MINOR(file->f_rdev);
	tty = TTY_TABLE(dev);
	if (!tty)
		return -EINVAL;

	if (IS_A_PTY(dev))
		other_tty = tty_table[PTY_OTHER(dev)];
	else
		other_tty = NULL;
		
	switch (cmd) {
		case TCGETS:
			return get_termios(tty,(struct termios *) arg);
		case TCSETSF:
			flush_input(tty);
		/* fallthrough */
		case TCSETSW:
			wait_until_sent(tty);
		/* fallthrough */
		case TCSETS:
			return set_termios(tty,(struct termios *) arg, dev);
		case TCGETA:
			return get_termio(tty,(struct termio *) arg);
		case TCSETAF:
			flush_input(tty);
		/* fallthrough */
		case TCSETAW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETA:
			return set_termio(tty,(struct termio *) arg, dev);
		case TCXONC:
			switch (arg) {
			case TCOOFF:
				tty->stopped = 1;
				TTY_WRITE_FLUSH(tty);
				return 0;
			case TCOON:
				tty->stopped = 0;
				TTY_WRITE_FLUSH(tty);
				return 0;
			case TCIOFF:
				if (STOP_CHAR(tty))
					put_tty_queue(STOP_CHAR(tty),
						      &tty->write_q);
				return 0;
			case TCION:
				if (START_CHAR(tty))
					put_tty_queue(START_CHAR(tty),
						      &tty->write_q);
				return 0;
			}
			return -EINVAL; /* not implemented */
		case TCFLSH:
			if (arg==0)
				flush_input(tty);
			else if (arg==1)
				flush_output(tty);
			else if (arg==2) {
				flush_input(tty);
				flush_output(tty);
			} else
				return -EINVAL;
			return 0;
		case TIOCEXCL:
			return -EINVAL; /* not implemented */
		case TIOCNXCL:
			return -EINVAL; /* not implemented */
		case TIOCSCTTY:
			return -EINVAL; /* set controlling term NI */
		case TIOCGPGRP:
			verify_area((void *) arg,4);
			put_fs_long(tty->pgrp,(unsigned long *) arg);
			return 0;
		case TIOCSPGRP:
			if ((current->tty < 0) ||
			    (current->tty != dev) ||
			    (tty->session != current->session))
				return -ENOTTY;
			pgrp=get_fs_long((unsigned long *) arg);
			if (pgrp < 0)
				return -EINVAL;
			if (session_of_pgrp(pgrp) != current->session)
				return -EPERM;
			tty->pgrp = pgrp;			
			return 0;
		case TIOCOUTQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(&tty->write_q),
				    (unsigned long *) arg);
			return 0;
		case TIOCINQ:
			verify_area((void *) arg,4);
			if (L_CANON(tty) && !tty->secondary.data)
				put_fs_long(0, (unsigned long *) arg);
			else
				put_fs_long(CHARS(&tty->secondary),
					(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			return -EINVAL; /* not implemented */
		case TIOCGWINSZ:
			return get_window_size(tty,(struct winsize *) arg);
		case TIOCSWINSZ:
			if (IS_A_PTY_MASTER(dev))
				set_window_size(other_tty,(struct winsize *) arg);
			return set_window_size(tty,(struct winsize *) arg);
		case TIOCGSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCSSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCLINUX:
			switch (get_fs_byte((char *)arg))
			{
				case 0: 
					return do_screendump(arg);
				case 1: 
					return do_get_ps_info(arg);
				default: 
					return -EINVAL;
			}
		case TIOCCONS:
			if (!IS_A_PTY(dev))
				return -EINVAL;
			if (redirect)
				return -EBUSY;
			if (!suser())
				return -EPERM;
			if (IS_A_PTY_MASTER(dev))
				redirect = other_tty;
			else
				redirect = tty;
			return 0;
		case FIONBIO:
			if (arg)
				file->f_flags |= O_NONBLOCK;
			else
				file->f_flags &= ~O_NONBLOCK;
			return 0;
		case TIOCNOTTY:
			if (MINOR(file->f_rdev) != current->tty)
				return -EINVAL;
			current->tty = -1;
			if (current->leader) {
				if (tty->pgrp > 0)
					kill_pg(tty->pgrp, SIGHUP, 0);
				tty->pgrp = -1;
				tty->session = 0;
			}
			return 0;

	       case TIOCPKT:
			{
			   int on;
			   if (!IS_A_PTY_MASTER(dev))
			     return (-EINVAL);
			   verify_area ((unsigned long *)arg, sizeof (int));
			   on=get_fs_long ((unsigned long *)arg);
			   if (on )
			     tty->packet = 1;
			   else
			     tty->packet = 0;
			   return (0);
			}

		default:
			if (tty->ioctl)
				return (tty->ioctl)(tty, file, cmd, arg);
			else
				return -EINVAL;
	}
}
Exemplo n.º 30
0
int tty_ioctl(int dev, int cmd, int arg)
{
	struct tty_struct * tty;
	struct tty_struct * other_tty;
	int pgrp;

	if (MAJOR(dev) == 5) {
		dev = current->tty;
		if (dev<0)
			return -EINVAL;
	} else
		dev=MINOR(dev);
	tty = tty_table + (dev ? ((dev < 64)? dev-1:dev) : fg_console);

	if (IS_A_PTY(dev))
		other_tty = tty_table + PTY_OTHER(dev);
	else
		other_tty = NULL;
		
	if (!(tty->write_q && tty->read_q && tty->secondary && tty->write))
		return -EINVAL;
	switch (cmd) {
		case TCGETS:
			return get_termios(tty,(struct termios *) arg);
		case TCSETSF:
			flush(tty->read_q);
			flush(tty->secondary);
			if (other_tty)
				flush(other_tty->write_q);
		/* fallthrough */
		case TCSETSW:
			wait_until_sent(tty);
		/* fallthrough */
		case TCSETS:
			return set_termios(tty,(struct termios *) arg, dev);
		case TCGETA:
			return get_termio(tty,(struct termio *) arg);
		case TCSETAF:
			flush(tty->read_q);
			flush(tty->secondary);
			if (other_tty)
				flush(other_tty->write_q);
		/* fallthrough */
		case TCSETAW:
			wait_until_sent(tty); /* fallthrough */
		case TCSETA:
			return set_termio(tty,(struct termio *) arg, dev);
		case TCSBRK:
			if (!arg) {
				wait_until_sent(tty);
				send_break(tty);
			}
			return 0;
		case TCXONC:
			switch (arg) {
			case TCOOFF:
				tty->stopped = 1;
				tty->write(tty);
				return 0;
			case TCOON:
				tty->stopped = 0;
				tty->write(tty);
				return 0;
			case TCIOFF:
				if (STOP_CHAR(tty))
					PUTCH(STOP_CHAR(tty),tty->write_q);
				return 0;
			case TCION:
				if (START_CHAR(tty))
					PUTCH(START_CHAR(tty),tty->write_q);
				return 0;
			}
			return -EINVAL; /* not implemented */
		case TCFLSH:
			if (arg==0) {
				flush(tty->read_q);
				flush(tty->secondary);
				if (other_tty)
					flush(other_tty->write_q);
			} else if (arg==1)
				flush(tty->write_q);
			else if (arg==2) {
				flush(tty->read_q);
				flush(tty->secondary);
				flush(tty->write_q);
				if (other_tty)
					flush(other_tty->write_q);
			} else
				return -EINVAL;
			return 0;
		case TIOCEXCL:
			return -EINVAL; /* not implemented */
		case TIOCNXCL:
			return -EINVAL; /* not implemented */
		case TIOCSCTTY:
			return -EINVAL; /* set controlling term NI */
		case TIOCGPGRP:
			verify_area((void *) arg,4);
			put_fs_long(tty->pgrp,(unsigned long *) arg);
			return 0;
		case TIOCSPGRP:
			if ((current->tty < 0) ||
			    (current->tty != dev) ||
			    (tty->session != current->session))
				return -ENOTTY;
			pgrp=get_fs_long((unsigned long *) arg);
			if (pgrp < 0)
				return -EINVAL;
			if (session_of_pgrp(pgrp) != current->session)
				return -EPERM;
			tty->pgrp = pgrp;			
			return 0;
		case TIOCOUTQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(tty->write_q),(unsigned long *) arg);
			return 0;
		case TIOCINQ:
			verify_area((void *) arg,4);
			put_fs_long(CHARS(tty->secondary),
				(unsigned long *) arg);
			return 0;
		case TIOCSTI:
			return -EINVAL; /* not implemented */
		case TIOCGWINSZ:
			return get_window_size(tty,(struct winsize *) arg);
		case TIOCSWINSZ:
			if (other_tty)
				set_window_size(other_tty,(struct winsize *) arg);
			return set_window_size(tty,(struct winsize *) arg);
		case TIOCMGET:
			return -EINVAL; /* not implemented */
		case TIOCMBIS:
			return -EINVAL; /* not implemented */
		case TIOCMBIC:
			return -EINVAL; /* not implemented */
		case TIOCMSET:
			return -EINVAL; /* not implemented */
		case TIOCGSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCSSOFTCAR:
			return -EINVAL; /* not implemented */
		case TIOCLINUX:
			switch (get_fs_byte((char *)arg))
			{
				case 0: 
					return do_screendump(arg);
				case 1: 
					return do_get_ps_info(arg);
				default: 
					return -EINVAL;
			}
		default:
			return -EINVAL;
	}
}