/*
 * sound/uart6850.c
 *
 *
 * Copyright (C) by Hannu Savolainen 1993-1997
 *
 * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
 * Version 2 (June 1991). See the "COPYING" file distributed with this software
 * for more info.
 * Extended by Alan Cox for Red Hat Software. Now a loadable MIDI driver.
 * 28/4/97 - (C) Copyright Alan Cox. Released under the GPL version 2.
 *
 * Alan Cox:		Updated for new modular code. Removed snd_* irq handling. Now
 *			uses native linux resources
 * Christoph Hellwig:	Adapted to module_init/module_exit
 * Jeff Garzik:		Made it work again, in theory
 *			FIXME: If the request_irq() succeeds, the probe succeeds. Ug.
 *
 *	Status: Testing required (no shit -jgarzik)
 *
 *
 */

#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/spinlock.h>
/* Mon Nov 22 22:38:35 MET 1993 marco@driq.home.usn.nl:
 *      added 6850 support, used with COVOX SoundMaster II and custom cards.
 */

#include "sound_config.h"

static int uart6850_base = 0x330;

static int *uart6850_osp;

#define	DATAPORT   (uart6850_base)
#define	COMDPORT   (uart6850_base+1)
#define	STATPORT   (uart6850_base+1)

static int uart6850_status(void)
{
	return inb(STATPORT);
}

#define input_avail()		(uart6850_status()&INPUT_AVAIL)
#define output_ready()		(uart6850_status()&OUTPUT_READY)

static void uart6850_cmd(unsigned char cmd)
{
	outb(cmd, COMDPORT);
}

static int uart6850_read(void)
{
	return inb(DATAPORT);
}

static void uart6850_write(unsigned char byte)
{
	outb(byte, DATAPORT);
}

#define	OUTPUT_READY	0x02	/* Mask for data ready Bit */
#define	INPUT_AVAIL	0x01	/* Mask for Data Send Ready Bit */

#define	UART_RESET	0x95
#define	UART_MODE_ON	0x03

static int uart6850_opened;
static int uart6850_irq;
static int uart6850_detected;
static int my_dev;
static DEFINE_SPINLOCK(lock);

static void (*midi_input_intr) (int dev, unsigned char data);
static void poll_uart6850(unsigned long dummy);


static struct timer_list uart6850_timer =
		TIMER_INITIALIZER(poll_uart6850, 0, 0);

static void uart6850_input_loop(void)
{
	int count = 10;

	while (count)
	{
		/*
		 * Not timed out
		 */
		if (input_avail())
		{
			unsigned char c = uart6850_read();
			count = 100;
			if (uart6850_opened & OPEN_READ)
				midi_input_intr(my_dev, c);
		}
		else
		{
			while (!input_avail() && count)
				count--;
		}
	}
}

static irqreturn_t m6850intr(int irq, void *dev_id, struct pt_regs *dummy)
{
	if (input_avail())
		uart6850_input_loop();
	return IRQ_HANDLED;
}

/*
 *	It looks like there is no input interrupts in the UART mode. Let's try
 *	polling.
 */

static void poll_uart6850(unsigned long dummy)
{
	unsigned long flags;

	if (!(uart6850_opened & OPEN_READ))
		return;		/* Device has been closed */

	spin_lock_irqsave(&lock,flags);
	if (input_avail())
		uart6850_input_loop();

	uart6850_timer.expires = 1 + jiffies;
	add_timer(&uart6850_timer);
	
	/*
	 *	Come back later
	 */

	spin_unlock_irqrestore(&lock,flags);
}

static int uart6850_open(int dev, int mode,
	      void            (*input) (int dev, unsigned char data),
	      void            (*output) (int dev)
)
{
	if (uart6850_opened)
	{
/*		  printk("Midi6850: Midi busy\n");*/
		  return -EBUSY;
	};

	uart6850_cmd(UART_RESET);
	uart6850_input_loop();
	midi_input_intr = input;
	uart6850_opened = mode;
	poll_uart6850(0);	/*
				 * Enable input polling
				 */

	return 0;
}

static void uart6850_close(int dev)
{
	uart6850_cmd(UART_MODE_ON);
	del_timer(&uart6850_timer);
	uart6850_opened = 0;
}

static int uart6850_out(int dev, unsigned char midi_byte)
{
	int timeout;
	unsigned long flags;

	/*
	 * Test for input since pending input seems to block the output.
	 */

	spin_lock_irqsave(&lock,flags);

	if (input_avail())
		uart6850_input_loop();

	spin_unlock_irqrestore(&lock,flags);

	/*
	 * Sometimes it takes about 13000 loops before the output becomes ready
	 * (After reset). Normally it takes just about 10 loops.
	 */

	for (timeout = 30000; timeout > 0 && !output_ready(); timeout--);	/*
										 * Wait
										 */
	if (!output_ready())
	{
		printk(KERN_WARNING "Midi6850: Timeout\n");
		return 0;
	}
	uart6850_write(midi_byte);
	return 1;
}

static inline int uart6850_command(int dev, unsigned char *midi_byte)
{
	return 1;
}

static inline int uart6850_start_read(int dev)
{
	return 0;
}

static inline int uart6850_end_read(int dev)
{
	return 0;
}

static inline void uart6850_kick(int dev)
{
}

static inline int uart6850_buffer_status(int dev)
{
	return 0;		/*
				 * No data in buffers
				 */
}

#define MIDI_SYNTH_NAME	"6850 UART Midi"
#define MIDI_SYNTH_CAPS	SYNTH_CAP_INPUT
#include "midi_synth.h"

static struct midi_operations uart6850_operations =
{
	.owner		= THIS_MODULE,
	.info		= {"6850 UART", 0, 0, SNDCARD_UART6850},
	.converter	= &std_midi_synth,
	.in_info	= {0},
	.open		= uart6850_open,
	.close		= uart6850_close,
	.outputc	= uart6850_out,
	.start_read	= uart6850_start_read,
	.end_read	= uart6850_end_read,
	.kick		= uart6850_kick,
	.command	= uart6850_command,
	.buffer_status	= uart6850_buffer_status
};


static void __init attach_uart6850(struct address_info *hw_config)
{
	int ok, timeout;
	unsigned long   flags;

	if (!uart6850_detected)
		return;

	if ((my_dev = sound_alloc_mididev()) == -1)
	{
		printk(KERN_INFO "uart6850: Too many midi devices detected\n");
		return;
	}
	uart6850_base = hw_config->io_base;
	uart6850_osp = hw_config->osp;
	uart6850_irq = hw_config->irq;

	spin_lock_irqsave(&lock,flags);

	for (timeout = 30000; timeout > 0 && !output_ready(); timeout--);	/*
										 * Wait
										 */
	uart6850_cmd(UART_MODE_ON);
	ok = 1;
	spin_unlock_irqrestore(&lock,flags);

	conf_printf("6850 Midi Interface", hw_config);

	std_midi_synth.midi_dev = my_dev;
	hw_config->slots[4] = my_dev;
	midi_devs[my_dev] = &uart6850_operations;
	sequencer_init();
}

static inline int reset_uart6850(void)
{
	uart6850_read();
	return 1;		/*
				 * OK
				 */
}

static int __init probe_uart6850(struct address_info *hw_config)
{
	int ok;

	uart6850_osp = hw_config->osp;
	uart6850_base = hw_config->io_base;
	uart6850_irq = hw_config->irq;

	if (request_irq(uart6850_irq, m6850intr, 0, "MIDI6850", NULL) < 0)
		return 0;

	ok = reset_uart6850();
	uart6850_detected = ok;
	return ok;
}

static void __exit unload_uart6850(struct address_info *hw_config)
{
	free_irq(hw_config->irq, NULL);
	sound_unload_mididev(hw_config->slots[4]);
}

static struct address_info cfg_mpu;

static int __initdata io = -1;
static int __initdata irq = -1;

module_param(io, int, 0);
module_param(irq, int, 0);

static int __init init_uart6850(void)
{
	cfg_mpu.io_base = io;
	cfg_mpu.irq = irq;

	if (cfg_mpu.io_base == -1 || cfg_mpu.irq == -1) {
		printk(KERN_INFO "uart6850: irq and io must be set.\n");
		return -EINVAL;
	}

	if (probe_uart6850(&cfg_mpu))
		return -ENODEV;
	attach_uart6850(&cfg_mpu);

	return 0;
}

static void __exit cleanup_uart6850(void)
{
	unload_uart6850(&cfg_mpu);
}

module_init(init_uart6850);
module_exit(cleanup_uart6850);

#ifndef MODULE
static int __init setup_uart6850(char *str)
{
	/* io, irq */
	int ints[3];
	
	str = get_options(str, ARRAY_SIZE(ints), ints);
	
	io = ints[1];
	irq = ints[2];

	return 1;
}
__setup("uart6850=", setup_uart6850);
#endif
MODULE_LICENSE("GPL");
