/*
 * IEEE 1284.3 Parallel port daisy chain and multiplexor code
 * 
 * Copyright (C) 1999, 2000  Tim Waugh <tim@cyberelk.demon.co.uk>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 *
 * ??-12-1998: Initial implementation.
 * 31-01-1999: Make port-cloning transparent.
 * 13-02-1999: Move DeviceID technique from parport_probe.
 * 13-03-1999: Get DeviceID from non-IEEE 1284.3 devices too.
 * 22-02-2000: Count devices that are actually detected.
 *
 * Any part of this program may be used in documents licensed under
 * the GNU Free Documentation License, Version 1.1 or any later version
 * published by the Free Software Foundation.
 */

#include <linux/module.h>
#include <linux/parport.h>
#include <linux/delay.h>
#include <linux/sched.h>

#include <asm/current.h>
#include <asm/uaccess.h>

#undef DEBUG

#ifdef DEBUG
#define DPRINTK(stuff...) printk (stuff)
#else
#define DPRINTK(stuff...)
#endif

static struct daisydev {
	struct daisydev *next;
	struct parport *port;
	int daisy;
	int devnum;
} *topology = NULL;
static DEFINE_SPINLOCK(topology_lock);

static int numdevs = 0;

/* Forward-declaration of lower-level functions. */
static int mux_present (struct parport *port);
static int num_mux_ports (struct parport *port);
static int select_port (struct parport *port);
static int assign_addrs (struct parport *port);

/* Add a device to the discovered topology. */
static void add_dev (int devnum, struct parport *port, int daisy)
{
	struct daisydev *newdev, **p;
	newdev = kmalloc (sizeof (struct daisydev), GFP_KERNEL);
	if (newdev) {
		newdev->port = port;
		newdev->daisy = daisy;
		newdev->devnum = devnum;
		spin_lock(&topology_lock);
		for (p = &topology; *p && (*p)->devnum<devnum; p = &(*p)->next)
			;
		newdev->next = *p;
		*p = newdev;
		spin_unlock(&topology_lock);
	}
}

/* Clone a parport (actually, make an alias). */
static struct parport *clone_parport (struct parport *real, int muxport)
{
	struct parport *extra = parport_register_port (real->base,
						       real->irq,
						       real->dma,
						       real->ops);
	if (extra) {
		extra->portnum = real->portnum;
		extra->physport = real;
		extra->muxport = muxport;
		real->slaves[muxport-1] = extra;
	}

	return extra;
}

/* Discover the IEEE1284.3 topology on a port -- muxes and daisy chains.
 * Return value is number of devices actually detected. */
int parport_daisy_init (struct parport *port)
{
	int detected = 0;
	char *deviceid;
	static const char *th[] = { /*0*/"th", "st", "nd", "rd", "th" };
	int num_ports;
	int i;
	int last_try = 0;

again:
	/* Because this is called before any other devices exist,
	 * we don't have to claim exclusive access.  */

	/* If mux present on normal port, need to create new
	 * parports for each extra port. */
	if (port->muxport < 0 && mux_present (port) &&
	    /* don't be fooled: a mux must have 2 or 4 ports. */
	    ((num_ports = num_mux_ports (port)) == 2 || num_ports == 4)) {
		/* Leave original as port zero. */
		port->muxport = 0;
		printk (KERN_INFO
			"%s: 1st (default) port of %d-way multiplexor\n",
			port->name, num_ports);
		for (i = 1; i < num_ports; i++) {
			/* Clone the port. */
			struct parport *extra = clone_parport (port, i);
			if (!extra) {
				if (signal_pending (current))
					break;

				schedule ();
				continue;
			}

			printk (KERN_INFO
				"%s: %d%s port of %d-way multiplexor on %s\n",
				extra->name, i + 1, th[i + 1], num_ports,
				port->name);

			/* Analyse that port too.  We won't recurse
			   forever because of the 'port->muxport < 0'
			   test above. */
			parport_daisy_init(extra);
		}
	}

	if (port->muxport >= 0)
		select_port (port);

	parport_daisy_deselect_all (port);
	detected += assign_addrs (port);

	/* Count the potential legacy device at the end. */
	add_dev (numdevs++, port, -1);

	/* Find out the legacy device's IEEE 1284 device ID. */
	deviceid = kmalloc (1024, GFP_KERNEL);
	if (deviceid) {
		if (parport_device_id (numdevs - 1, deviceid, 1024) > 2)
			detected++;

		kfree (deviceid);
	}

	if (!detected && !last_try) {
		/* No devices were detected.  Perhaps they are in some
                   funny state; let's try to reset them and see if
                   they wake up. */
		parport_daisy_fini (port);
		parport_write_control (port, PARPORT_CONTROL_SELECT);
		udelay (50);
		parport_write_control (port,
				       PARPORT_CONTROL_SELECT |
				       PARPORT_CONTROL_INIT);
		udelay (50);
		last_try = 1;
		goto again;
	}

	return detected;
}

/* Forget about devices on a physical port. */
void parport_daisy_fini (struct parport *port)
{
	struct daisydev **p;

	spin_lock(&topology_lock);
	p = &topology;
	while (*p) {
		struct daisydev *dev = *p;
		if (dev->port != port) {
			p = &dev->next;
			continue;
		}
		*p = dev->next;
		kfree(dev);
	}

	/* Gaps in the numbering could be handled better.  How should
           someone enumerate through all IEEE1284.3 devices in the
           topology?. */
	if (!topology) numdevs = 0;
	spin_unlock(&topology_lock);
	return;
}

/**
 *	parport_open - find a device by canonical device number
 *	@devnum: canonical device number
 *	@name: name to associate with the device
 *	@pf: preemption callback
 *	@kf: kick callback
 *	@irqf: interrupt handler
 *	@flags: registration flags
 *	@handle: driver data
 *
 *	This function is similar to parport_register_device(), except
 *	that it locates a device by its number rather than by the port
 *	it is attached to.
 *
 *	All parameters except for @devnum are the same as for
 *	parport_register_device().  The return value is the same as
 *	for parport_register_device().
 **/

struct pardevice *parport_open (int devnum, const char *name,
				int (*pf) (void *), void (*kf) (void *),
				void (*irqf) (int, void *, struct pt_regs *),
				int flags, void *handle)
{
	struct daisydev *p = topology;
	struct parport *port;
	struct pardevice *dev;
	int daisy;

	spin_lock(&topology_lock);
	while (p && p->devnum != devnum)
		p = p->next;

	if (!p) {
		spin_unlock(&topology_lock);
		return NULL;
	}

	daisy = p->daisy;
	port = parport_get_port(p->port);
	spin_unlock(&topology_lock);

	dev = parport_register_device (port, name, pf, kf,
				       irqf, flags, handle);
	parport_put_port(port);
	if (!dev)
		return NULL;

	dev->daisy = daisy;

	/* Check that there really is a device to select. */
	if (daisy >= 0) {
		int selected;
		parport_claim_or_block (dev);
		selected = port->daisy;
		parport_release (dev);

		if (selected != daisy) {
			/* No corresponding device. */
			parport_unregister_device (dev);
			return NULL;
		}
	}

	return dev;
}

/**
 *	parport_close - close a device opened with parport_open()
 *	@dev: device to close
 *
 *	This is to parport_open() as parport_unregister_device() is to
 *	parport_register_device().
 **/

void parport_close (struct pardevice *dev)
{
	parport_unregister_device (dev);
}

/**
 *	parport_device_num - convert device coordinates
 *	@parport: parallel port number
 *	@mux: multiplexor port number (-1 for no multiplexor)
 *	@daisy: daisy chain address (-1 for no daisy chain address)
 *
 *	This tries to locate a device on the given parallel port,
 *	multiplexor port and daisy chain address, and returns its
 *	device number or %-ENXIO if no device with those coordinates
 *	exists.
 **/

int parport_device_num (int parport, int mux, int daisy)
{
	int res = -ENXIO;
	struct daisydev *dev;

	spin_lock(&topology_lock);
	dev = topology;
	while (dev && dev->port->portnum != parport &&
	       dev->port->muxport != mux && dev->daisy != daisy)
		dev = dev->next;
	if (dev)
		res = dev->devnum;
	spin_unlock(&topology_lock);

	return res;
}

/* Send a daisy-chain-style CPP command packet. */
static int cpp_daisy (struct parport *port, int cmd)
{
	unsigned char s;

	parport_data_forward (port);
	parport_write_data (port, 0xaa); udelay (2);
	parport_write_data (port, 0x55); udelay (2);
	parport_write_data (port, 0x00); udelay (2);
	parport_write_data (port, 0xff); udelay (2);
	s = parport_read_status (port) & (PARPORT_STATUS_BUSY
					  | PARPORT_STATUS_PAPEROUT
					  | PARPORT_STATUS_SELECT
					  | PARPORT_STATUS_ERROR);
	if (s != (PARPORT_STATUS_BUSY
		  | PARPORT_STATUS_PAPEROUT
		  | PARPORT_STATUS_SELECT
		  | PARPORT_STATUS_ERROR)) {
		DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff(%02x)\n",
			 port->name, s);
		return -ENXIO;
	}

	parport_write_data (port, 0x87); udelay (2);
	s = parport_read_status (port) & (PARPORT_STATUS_BUSY
					  | PARPORT_STATUS_PAPEROUT
					  | PARPORT_STATUS_SELECT
					  | PARPORT_STATUS_ERROR);
	if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
		DPRINTK (KERN_DEBUG "%s: cpp_daisy: aa5500ff87(%02x)\n",
			 port->name, s);
		return -ENXIO;
	}

	parport_write_data (port, 0x78); udelay (2);
	parport_write_data (port, cmd); udelay (2);
	parport_frob_control (port,
			      PARPORT_CONTROL_STROBE,
			      PARPORT_CONTROL_STROBE);
	udelay (1);
	s = parport_read_status (port);
	parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
	udelay (1);
	parport_write_data (port, 0xff); udelay (2);

	return s;
}

/* Send a mux-style CPP command packet. */
static int cpp_mux (struct parport *port, int cmd)
{
	unsigned char s;
	int rc;

	parport_data_forward (port);
	parport_write_data (port, 0xaa); udelay (2);
	parport_write_data (port, 0x55); udelay (2);
	parport_write_data (port, 0xf0); udelay (2);
	parport_write_data (port, 0x0f); udelay (2);
	parport_write_data (port, 0x52); udelay (2);
	parport_write_data (port, 0xad); udelay (2);
	parport_write_data (port, cmd); udelay (2);

	s = parport_read_status (port);
	if (!(s & PARPORT_STATUS_ACK)) {
		DPRINTK (KERN_DEBUG "%s: cpp_mux: aa55f00f52ad%02x(%02x)\n",
			 port->name, cmd, s);
		return -EIO;
	}

	rc = (((s & PARPORT_STATUS_SELECT   ? 1 : 0) << 0) |
	      ((s & PARPORT_STATUS_PAPEROUT ? 1 : 0) << 1) |
	      ((s & PARPORT_STATUS_BUSY     ? 0 : 1) << 2) |
	      ((s & PARPORT_STATUS_ERROR    ? 0 : 1) << 3));

	return rc;
}

void parport_daisy_deselect_all (struct parport *port)
{
	cpp_daisy (port, 0x30);
}

int parport_daisy_select (struct parport *port, int daisy, int mode)
{
	switch (mode)
	{
		// For these modes we should switch to EPP mode:
		case IEEE1284_MODE_EPP:
		case IEEE1284_MODE_EPPSL:
		case IEEE1284_MODE_EPPSWE:
			return !(cpp_daisy (port, 0x20 + daisy) &
				 PARPORT_STATUS_ERROR);

		// For these modes we should switch to ECP mode:
		case IEEE1284_MODE_ECP:
		case IEEE1284_MODE_ECPRLE:
		case IEEE1284_MODE_ECPSWE: 
			return !(cpp_daisy (port, 0xd0 + daisy) &
				 PARPORT_STATUS_ERROR);

		// Nothing was told for BECP in Daisy chain specification.
		// May be it's wise to use ECP?
		case IEEE1284_MODE_BECP:
		// Others use compat mode
		case IEEE1284_MODE_NIBBLE:
		case IEEE1284_MODE_BYTE:
		case IEEE1284_MODE_COMPAT:
		default:
			return !(cpp_daisy (port, 0xe0 + daisy) &
				 PARPORT_STATUS_ERROR);
	}
}

static int mux_present (struct parport *port)
{
	return cpp_mux (port, 0x51) == 3;
}

static int num_mux_ports (struct parport *port)
{
	return cpp_mux (port, 0x58);
}

static int select_port (struct parport *port)
{
	int muxport = port->muxport;
	return cpp_mux (port, 0x60 + muxport) == muxport;
}

static int assign_addrs (struct parport *port)
{
	unsigned char s;
	unsigned char daisy;
	int thisdev = numdevs;
	int detected;
	char *deviceid;

	parport_data_forward (port);
	parport_write_data (port, 0xaa); udelay (2);
	parport_write_data (port, 0x55); udelay (2);
	parport_write_data (port, 0x00); udelay (2);
	parport_write_data (port, 0xff); udelay (2);
	s = parport_read_status (port) & (PARPORT_STATUS_BUSY
					  | PARPORT_STATUS_PAPEROUT
					  | PARPORT_STATUS_SELECT
					  | PARPORT_STATUS_ERROR);
	if (s != (PARPORT_STATUS_BUSY
		  | PARPORT_STATUS_PAPEROUT
		  | PARPORT_STATUS_SELECT
		  | PARPORT_STATUS_ERROR)) {
		DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff(%02x)\n",
			 port->name, s);
		return 0;
	}

	parport_write_data (port, 0x87); udelay (2);
	s = parport_read_status (port) & (PARPORT_STATUS_BUSY
					  | PARPORT_STATUS_PAPEROUT
					  | PARPORT_STATUS_SELECT
					  | PARPORT_STATUS_ERROR);
	if (s != (PARPORT_STATUS_SELECT | PARPORT_STATUS_ERROR)) {
		DPRINTK (KERN_DEBUG "%s: assign_addrs: aa5500ff87(%02x)\n",
			 port->name, s);
		return 0;
	}

	parport_write_data (port, 0x78); udelay (2);
	s = parport_read_status (port);

	for (daisy = 0;
	     (s & (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT))
		     == (PARPORT_STATUS_PAPEROUT|PARPORT_STATUS_SELECT)
		     && daisy < 4;
	     ++daisy) {
		parport_write_data (port, daisy);
		udelay (2);
		parport_frob_control (port,
				      PARPORT_CONTROL_STROBE,
				      PARPORT_CONTROL_STROBE);
		udelay (1);
		parport_frob_control (port, PARPORT_CONTROL_STROBE, 0);
		udelay (1);

		add_dev (numdevs++, port, daisy);

		/* See if this device thought it was the last in the
		 * chain. */
		if (!(s & PARPORT_STATUS_BUSY))
			break;

		/* We are seeing pass through status now. We see
		   last_dev from next device or if last_dev does not
		   work status lines from some non-daisy chain
		   device. */
		s = parport_read_status (port);
	}

	parport_write_data (port, 0xff); udelay (2);
	detected = numdevs - thisdev;
	DPRINTK (KERN_DEBUG "%s: Found %d daisy-chained devices\n", port->name,
		 detected);

	/* Ask the new devices to introduce themselves. */
	deviceid = kmalloc (1024, GFP_KERNEL);
	if (!deviceid) return 0;

	for (daisy = 0; thisdev < numdevs; thisdev++, daisy++)
		parport_device_id (thisdev, deviceid, 1024);

	kfree (deviceid);
	return detected;
}
