/*
 * Basic EISA bus support for the SGI Indigo-2.
 *
 * (C) 2002 Pascal Dameme <netinet@freesurf.fr>
 *      and Marc Zyngier <mzyngier@freesurf.fr>
 *
 * This code is released under both the GPL version 2 and BSD
 * licenses.  Either license may be used.
 *
 * This code offers a very basic support for this EISA bus present in
 * the SGI Indigo-2. It currently only supports PIO (forget about DMA
 * for the time being). This is enough for a low-end ethernet card,
 * but forget about your favorite SCSI card...
 *
 * TODO :
 * - Fix bugs...
 * - Add ISA support
 * - Add DMA (yeah, right...).
 * - Fix more bugs.
 */

#include <linux/eisa.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/kernel_stat.h>
#include <linux/signal.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/processor.h>
#include <asm/sgi/ioc.h>
#include <asm/sgi/mc.h>
#include <asm/sgi/ip22.h>

/* I2 has four EISA slots. */
#define IP22_EISA_MAX_SLOTS	  4
#define EISA_MAX_IRQ             16

#define EIU_MODE_REG     0x0001ffc0
#define EIU_STAT_REG     0x0001ffc4
#define EIU_PREMPT_REG   0x0001ffc8
#define EIU_QUIET_REG    0x0001ffcc
#define EIU_INTRPT_ACK   0x00010004

static char __init *decode_eisa_sig(unsigned long addr)
{
        static char sig_str[EISA_SIG_LEN];
	u8 sig[4];
        u16 rev;
	int i;

	for (i = 0; i < 4; i++) {
		sig[i] = inb (addr + i);

		if (!i && (sig[0] & 0x80))
			return NULL;
	}

	sig_str[0] = ((sig[0] >> 2) & 0x1f) + ('A' - 1);
	sig_str[1] = (((sig[0] & 3) << 3) | (sig[1] >> 5)) + ('A' - 1);
	sig_str[2] = (sig[1] & 0x1f) + ('A' - 1);
	rev = (sig[2] << 8) | sig[3];
	sprintf(sig_str + 3, "%04X", rev);

	return sig_str;
}

static irqreturn_t ip22_eisa_intr(int irq, void *dev_id)
{
	u8 eisa_irq;
	u8 dma1, dma2;

	eisa_irq = inb(EIU_INTRPT_ACK);
	dma1 = inb(EISA_DMA1_STATUS);
	dma2 = inb(EISA_DMA2_STATUS);

	if (eisa_irq < EISA_MAX_IRQ) {
		do_IRQ(eisa_irq);
		return IRQ_HANDLED;
	}

	/* Oops, Bad Stuff Happened... */
	printk(KERN_ERR "eisa_irq %d out of bound\n", eisa_irq);

	outb(0x20, EISA_INT2_CTRL);
	outb(0x20, EISA_INT1_CTRL);

	return IRQ_NONE;
}

static void enable_eisa1_irq(unsigned int irq)
{
	u8 mask;

	mask = inb(EISA_INT1_MASK);
	mask &= ~((u8) (1 << irq));
	outb(mask, EISA_INT1_MASK);
}

static unsigned int startup_eisa1_irq(unsigned int irq)
{
	u8 edge;

	/* Only use edge interrupts for EISA */

	edge = inb(EISA_INT1_EDGE_LEVEL);
	edge &= ~((u8) (1 << irq));
	outb(edge, EISA_INT1_EDGE_LEVEL);

	enable_eisa1_irq(irq);
	return 0;
}

static void disable_eisa1_irq(unsigned int irq)
{
	u8 mask;

	mask = inb(EISA_INT1_MASK);
	mask |= ((u8) (1 << irq));
	outb(mask, EISA_INT1_MASK);
}

static void mask_and_ack_eisa1_irq(unsigned int irq)
{
	disable_eisa1_irq(irq);

	outb(0x20, EISA_INT1_CTRL);
}

static void end_eisa1_irq(unsigned int irq)
{
	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
		enable_eisa1_irq(irq);
}

static struct irq_chip ip22_eisa1_irq_type = {
	.typename	= "IP22 EISA",
	.startup	= startup_eisa1_irq,
	.ack		= mask_and_ack_eisa1_irq,
	.mask		= disable_eisa1_irq,
	.mask_ack	= mask_and_ack_eisa1_irq,
	.unmask		= enable_eisa1_irq,
	.end		= end_eisa1_irq,
};

static void enable_eisa2_irq(unsigned int irq)
{
	u8 mask;

	mask = inb(EISA_INT2_MASK);
	mask &= ~((u8) (1 << (irq - 8)));
	outb(mask, EISA_INT2_MASK);
}

static unsigned int startup_eisa2_irq(unsigned int irq)
{
	u8 edge;

	/* Only use edge interrupts for EISA */

	edge = inb(EISA_INT2_EDGE_LEVEL);
	edge &= ~((u8) (1 << (irq - 8)));
	outb(edge, EISA_INT2_EDGE_LEVEL);

	enable_eisa2_irq(irq);
	return 0;
}

static void disable_eisa2_irq(unsigned int irq)
{
	u8 mask;

	mask = inb(EISA_INT2_MASK);
	mask |= ((u8) (1 << (irq - 8)));
	outb(mask, EISA_INT2_MASK);
}

static void mask_and_ack_eisa2_irq(unsigned int irq)
{
	disable_eisa2_irq(irq);

	outb(0x20, EISA_INT2_CTRL);
}

static void end_eisa2_irq(unsigned int irq)
{
	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
		enable_eisa2_irq(irq);
}

static struct irq_chip ip22_eisa2_irq_type = {
	.typename	= "IP22 EISA",
	.startup	= startup_eisa2_irq,
	.ack		= mask_and_ack_eisa2_irq,
	.mask		= disable_eisa2_irq,
	.mask_ack	= mask_and_ack_eisa2_irq,
	.unmask		= enable_eisa2_irq,
	.end		= end_eisa2_irq,
};

static struct irqaction eisa_action = {
	.handler	= ip22_eisa_intr,
	.name		= "EISA",
};

static struct irqaction cascade_action = {
	.handler	= no_action,
	.name		= "EISA cascade",
};

int __init ip22_eisa_init(void)
{
	int i, c;
	char *str;

	if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
		printk(KERN_INFO "EISA: bus not present.\n");
		return 1;
	}

	printk(KERN_INFO "EISA: Probing bus...\n");
	for (c = 0, i = 1; i <= IP22_EISA_MAX_SLOTS; i++) {
		if ((str = decode_eisa_sig(0x1000 * i + EISA_VENDOR_ID_OFFSET))) {
			printk(KERN_INFO "EISA: slot %d : %s detected.\n",
			       i, str);
			c++;
		}
	}
	printk(KERN_INFO "EISA: Detected %d card%s.\n", c, c < 2 ? "" : "s");
#ifdef CONFIG_ISA
	printk(KERN_INFO "ISA support compiled in.\n");
#endif

	/* Warning : BlackMagicAhead(tm).
	   Please wave your favorite dead chicken over the busses */

	/* First say hello to the EIU */
	outl(0x0000FFFF, EIU_PREMPT_REG);
	outl(1, EIU_QUIET_REG);
	outl(0x40f3c07F, EIU_MODE_REG);

	/* Now be nice to the EISA chipset */
	outb(1, EISA_EXT_NMI_RESET_CTRL);
	udelay(50);	/* Wait long enough for the dust to settle */
	outb(0, EISA_EXT_NMI_RESET_CTRL);
	outb(0x11, EISA_INT1_CTRL);
	outb(0x11, EISA_INT2_CTRL);
	outb(0, EISA_INT1_MASK);
	outb(8, EISA_INT2_MASK);
	outb(4, EISA_INT1_MASK);
	outb(2, EISA_INT2_MASK);
	outb(1, EISA_INT1_MASK);
	outb(1, EISA_INT2_MASK);
	outb(0xfb, EISA_INT1_MASK);
	outb(0xff, EISA_INT2_MASK);
	outb(0, EISA_DMA2_WRITE_SINGLE);

	for (i = SGINT_EISA; i < (SGINT_EISA + EISA_MAX_IRQ); i++) {
		if (i < (SGINT_EISA + 8))
			set_irq_chip(i, &ip22_eisa1_irq_type);
		else
			set_irq_chip(i, &ip22_eisa2_irq_type);
	}

	/* Cannot use request_irq because of kmalloc not being ready at such
	 * an early stage. Yes, I've been bitten... */
	setup_irq(SGI_EISA_IRQ, &eisa_action);
	setup_irq(SGINT_EISA + 2, &cascade_action);

	EISA_bus = 1;
	return 0;
}
