/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2008 Arastra, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <console/console.h>
#include <arch/smp/mpspec.h>
#include <arch/ioapic.h>
#include <device/pci.h>
#include <string.h>
#include <stdint.h>

static void *smp_write_config_table(void *v)
{
	struct mp_config_table *mc;
	int bus_isa;
	u8 bus_pea0 = 0;
	u8 bus_pea1 = 0;
	u8 bus_aioc;
	device_t dev;

	mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);

	mptable_init(mc, LOCAL_APIC_ADDR);

	smp_write_processors(mc);

	/* AIOC bridge */
	dev = dev_find_slot(0, PCI_DEVFN(0x04,0));
	if (dev) {
		bus_aioc = pci_read_config8(dev, PCI_SECONDARY_BUS);
	}
	else {
		printk(BIOS_DEBUG, "ERROR - could not find PCI 0:04.0\n");
		bus_aioc = 0;
	}
	/* PCIe A0 */
	dev = dev_find_slot(0, PCI_DEVFN(0x02,0));
	if (dev) {
		bus_pea0 = pci_read_config8(dev, PCI_SECONDARY_BUS);
	}
	else {
		printk(BIOS_DEBUG, "ERROR - could not find PCI 0:02.0\n");
		bus_pea0 = 0;
	}
	/* PCIe A1 */
	dev = dev_find_slot(0, PCI_DEVFN(0x03,0));
	if (dev) {
		bus_pea1 = pci_read_config8(dev, PCI_SECONDARY_BUS);
	}
	else {
		printk(BIOS_DEBUG, "ERROR - could not find PCI 0:03.0\n");
		bus_pea1 = 0;
	}

	mptable_write_buses(mc, NULL, &bus_isa);

	/* IOAPIC handling */
	smp_write_ioapic(mc, 0x8, 0x20, VIO_APIC_VADDR);

	mptable_add_isa_interrupts(mc, bus_isa, 0x8, 0);

	/* Standard local interrupt assignments */
	mptable_lintsrc(mc, bus_isa);

	/* IMCH/IICH PCI devices */
	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
			 0, (0x01<<2)|0, 0x8, 0x10); /* DMA controller */
	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
			 0, (0x02<<2)|0, 0x8, 0x10); /* PCIe port A bridge */
	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
			 0, (0x03<<2)|0, 0x8, 0x10); /* PCIe port A1 bridge */
	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
			 0, (0x04<<2)|0, 0x8, 0x10); /* AIOC PCI bridge */
	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
			 0, (0x1d<<2)|0, 0x8, 0x10); /* UHCI/EHCI */
	smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
			 0, (0x1f<<2)|1, 0x8, 0x11); /* SATA/SMBus */

	if (bus_pea0) {
		/* PCIe slot 0 */
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_pea0, (0<<2)|0, 0x8, 0x10);
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_pea0, (0<<2)|1, 0x8, 0x11);
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_pea0, (0<<2)|2, 0x8, 0x12);
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_pea0, (0<<2)|3, 0x8, 0x13);
	}

	if (bus_pea1) {
		/* PCIe slots 1-4 */
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_pea1, (0<<2)|0, 0x8, 0x10);
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_pea1, (0<<2)|1, 0x8, 0x11);
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_pea1, (0<<2)|2, 0x8, 0x12);
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_pea1, (0<<2)|3, 0x8, 0x13);
	}

	if (bus_aioc) {
		/* AIOC PCI devices */
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_aioc, (0<<2)|0, 0x8, 0x10); /* GbE0 */
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_aioc, (1<<2)|0, 0x8, 0x11); /* GbE1 */
		smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
				 bus_aioc, (2<<2)|0, 0x8, 0x12); /* GbE2 */
	}

	/* There is no extension information... */

	/* Compute the checksums */
	return mptable_finalize(mc);
}

unsigned long write_smp_table(unsigned long addr)
{
	void *v;
	v = smp_write_floating_table(addr, 0);
	return (unsigned long)smp_write_config_table(v);
}
