/*
 * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com)
 * Licensed under the GPL
 */

#include "linux/list.h"
#include "linux/sched.h"
#include "linux/slab.h"
#include "linux/interrupt.h"
#include "linux/spinlock.h"
#include "linux/errno.h"
#include "asm/atomic.h"
#include "asm/semaphore.h"
#include "asm/errno.h"
#include "kern_util.h"
#include "kern.h"
#include "irq_user.h"
#include "irq_kern.h"
#include "port.h"
#include "init.h"
#include "os.h"

struct port_list {
	struct list_head list;
	atomic_t wait_count;
	int has_connection;
	struct completion done;
	int port;
	int fd;
	spinlock_t lock;
	struct list_head pending;
	struct list_head connections;
};

struct port_dev {
	struct port_list *port;
	int helper_pid;
	int telnetd_pid;
};

struct connection {
	struct list_head list;
	int fd;
	int helper_pid;
	int socket[2];
	int telnetd_pid;
	struct port_list *port;
};

static irqreturn_t pipe_interrupt(int irq, void *data)
{
	struct connection *conn = data;
	int fd;

	fd = os_rcv_fd(conn->socket[0], &conn->helper_pid);
	if(fd < 0){
		if(fd == -EAGAIN)
			return IRQ_NONE;

		printk(KERN_ERR "pipe_interrupt : os_rcv_fd returned %d\n",
		       -fd);
		os_close_file(conn->fd);
	}

	list_del(&conn->list);

	conn->fd = fd;
	list_add(&conn->list, &conn->port->connections);

	complete(&conn->port->done);
	return IRQ_HANDLED;
}

#define NO_WAITER_MSG \
    "****\n" \
    "There are currently no UML consoles waiting for port connections.\n" \
    "Either disconnect from one to make it available or activate some more\n" \
    "by enabling more consoles in the UML /etc/inittab.\n" \
    "****\n"

static int port_accept(struct port_list *port)
{
	struct connection *conn;
	int fd, socket[2], pid, ret = 0;

	fd = port_connection(port->fd, socket, &pid);
	if(fd < 0){
		if(fd != -EAGAIN)
			printk(KERN_ERR "port_accept : port_connection "
			       "returned %d\n", -fd);
		goto out;
	}

	conn = kmalloc(sizeof(*conn), GFP_ATOMIC);
	if(conn == NULL){
		printk(KERN_ERR "port_accept : failed to allocate "
		       "connection\n");
		goto out_close;
	}
	*conn = ((struct connection)
		{ .list 	= LIST_HEAD_INIT(conn->list),
		  .fd 		= fd,
		  .socket  	= { socket[0], socket[1] },
		  .telnetd_pid 	= pid,
		  .port 	= port });

	if(um_request_irq(TELNETD_IRQ, socket[0], IRQ_READ, pipe_interrupt,
			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
			  "telnetd", conn)){
		printk(KERN_ERR "port_accept : failed to get IRQ for "
		       "telnetd\n");
		goto out_free;
	}

	if(atomic_read(&port->wait_count) == 0){
		os_write_file(fd, NO_WAITER_MSG, sizeof(NO_WAITER_MSG));
		printk("No one waiting for port\n");
	}
	list_add(&conn->list, &port->pending);
	return 1;

 out_free:
	kfree(conn);
 out_close:
	os_close_file(fd);
	if(pid != -1)
		os_kill_process(pid, 1);
 out:
	return ret;
}

static DECLARE_MUTEX(ports_sem);
static LIST_HEAD(ports);

void port_work_proc(struct work_struct *unused)
{
	struct port_list *port;
	struct list_head *ele;
	unsigned long flags;

	local_irq_save(flags);
	list_for_each(ele, &ports){
		port = list_entry(ele, struct port_list, list);
		if(!port->has_connection)
			continue;
		reactivate_fd(port->fd, ACCEPT_IRQ);
		while(port_accept(port)) ;
		port->has_connection = 0;
	}
	local_irq_restore(flags);
}

DECLARE_WORK(port_work, port_work_proc);

static irqreturn_t port_interrupt(int irq, void *data)
{
	struct port_list *port = data;

	port->has_connection = 1;
	schedule_work(&port_work);
	return IRQ_HANDLED;
}

void *port_data(int port_num)
{
	struct list_head *ele;
	struct port_list *port;
	struct port_dev *dev = NULL;
	int fd;

	down(&ports_sem);
	list_for_each(ele, &ports){
		port = list_entry(ele, struct port_list, list);
		if(port->port == port_num) goto found;
	}
	port = kmalloc(sizeof(struct port_list), GFP_KERNEL);
	if(port == NULL){
		printk(KERN_ERR "Allocation of port list failed\n");
		goto out;
	}

	fd = port_listen_fd(port_num);
	if(fd < 0){
		printk(KERN_ERR "binding to port %d failed, errno = %d\n",
		       port_num, -fd);
		goto out_free;
	}
	if(um_request_irq(ACCEPT_IRQ, fd, IRQ_READ, port_interrupt,
			  IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
			  "port", port)){
		printk(KERN_ERR "Failed to get IRQ for port %d\n", port_num);
		goto out_close;
	}

	*port = ((struct port_list)
		{ .list 	 	= LIST_HEAD_INIT(port->list),
		  .wait_count		= ATOMIC_INIT(0),
		  .has_connection 	= 0,
		  .port 	 	= port_num,
		  .fd  			= fd,
		  .pending 		= LIST_HEAD_INIT(port->pending),
		  .connections 		= LIST_HEAD_INIT(port->connections) });
	spin_lock_init(&port->lock);
	init_completion(&port->done);
	list_add(&port->list, &ports);

 found:
	dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL);
	if(dev == NULL){
		printk(KERN_ERR "Allocation of port device entry failed\n");
		goto out;
	}

	*dev = ((struct port_dev) { .port  		= port,
				    .helper_pid  	= -1,
				    .telnetd_pid  	= -1 });
	goto out;

 out_free:
	kfree(port);
 out_close:
	os_close_file(fd);
 out:
	up(&ports_sem);
	return dev;
}

int port_wait(void *data)
{
	struct port_dev *dev = data;
	struct connection *conn;
	struct port_list *port = dev->port;
	int fd;

	atomic_inc(&port->wait_count);
	while(1){
		fd = -ERESTARTSYS;
		if(wait_for_completion_interruptible(&port->done))
			goto out;

		spin_lock(&port->lock);

		conn = list_entry(port->connections.next, struct connection,
				  list);
		list_del(&conn->list);
		spin_unlock(&port->lock);

		os_shutdown_socket(conn->socket[0], 1, 1);
		os_close_file(conn->socket[0]);
		os_shutdown_socket(conn->socket[1], 1, 1);
		os_close_file(conn->socket[1]);

		/* This is done here because freeing an IRQ can't be done
		 * within the IRQ handler.  So, pipe_interrupt always ups
		 * the semaphore regardless of whether it got a successful
		 * connection.  Then we loop here throwing out failed
		 * connections until a good one is found.
		 */
		free_irq(TELNETD_IRQ, conn);

		if(conn->fd >= 0) break;
		os_close_file(conn->fd);
		kfree(conn);
	}

	fd = conn->fd;
	dev->helper_pid = conn->helper_pid;
	dev->telnetd_pid = conn->telnetd_pid;
	kfree(conn);
 out:
	atomic_dec(&port->wait_count);
	return fd;
}

void port_remove_dev(void *d)
{
	struct port_dev *dev = d;

	if(dev->helper_pid != -1)
		os_kill_process(dev->helper_pid, 0);
	if(dev->telnetd_pid != -1)
		os_kill_process(dev->telnetd_pid, 1);
	dev->helper_pid = -1;
	dev->telnetd_pid = -1;
}

void port_kern_free(void *d)
{
	struct port_dev *dev = d;

	port_remove_dev(dev);
	kfree(dev);
}

static void free_port(void)
{
	struct list_head *ele;
	struct port_list *port;

	list_for_each(ele, &ports){
		port = list_entry(ele, struct port_list, list);
		free_irq_by_fd(port->fd);
		os_close_file(port->fd);
	}
}

__uml_exitcall(free_port);
