/* Simplistic PCI support.

   Copyright (C) 2011 Richard Henderson

   This file is part of QEMU PALcode.

   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.

   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 text
   of the GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; see the file COPYING.  If not see
   <http://www.gnu.org/licenses/>.  */

/* We don't bother supporting PCI bridges, because the device model we're
   currently using for QEMU doesn't build any.

   We don't bother to build real datastructures in memory, because it's
   fairly quick under emulation simply to access configuration space again.
   This helps when running kernels under the emulator that might have
   re-organized the BARs out from under us.  */

#include "protos.h"
#include "pci.h"
#include "pci_regs.h"
#include SYSTEM_H


#define PCI_SLOT_MAX		32
#define PCI_FUNC_MAX		8
#define PCI_REGION_ROM		6
#define PCI_REGIONS_MAX		7


void
pci_config_maskw(int bdf, int addr, uint16_t off, uint16_t on)
{
  uint16_t val = pci_config_readw(bdf, addr);
  val = (val & ~off) | on;
  pci_config_writew(bdf, addr, val);
}

int
pci_next(int bdf, int *pmax)
{
  int max;

  if (PCI_FUNC(bdf) == 1)
    {
      /* If the last device was not a multi-function device, skip to next.  */
      if ((pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0)
        bdf += 7;
    }

  max = *pmax;
  while (1)
    {
      uint16_t vendor;

      /* ??? Support multiple PCI busses here at some point.  */
      if (bdf >= max)
	return -1;

      /* Check if there is a device present at the location.  */
      vendor = pci_config_readw(bdf, PCI_VENDOR_ID);
      if (vendor != 0x0000 && vendor != 0xffff)
	return bdf;

      bdf += (PCI_FUNC(bdf) == 0 ? 8 : 1);
    }
}

static void
pci_setup_device(int bdf, uint32_t *p_io_base, uint32_t *p_mem_base)
{
  int vendor_id, device_id, class_id, region;

  vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
  device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
  class_id = pci_config_readw(bdf, PCI_CLASS_DEVICE);

  printf("PCI: %02x:%02x:%x class %04x id %04x:%04x\r\n",
	 PCI_BUS(bdf), PCI_SLOT(bdf), PCI_FUNC(bdf),
         class_id, vendor_id, device_id);

  for (region = 0; region < PCI_REGION_ROM; region++)
    {
      int ofs = PCI_BASE_ADDRESS_0 + region * 4;
      uint32_t old, mask, val, size, align;
      uint32_t *p_base;

      old = pci_config_readl(bdf, ofs);
      if (old & PCI_BASE_ADDRESS_SPACE_IO)
	{
	  mask = PCI_BASE_ADDRESS_IO_MASK;
	  p_base = p_io_base;
	}
      else
	{
	  mask = PCI_BASE_ADDRESS_MEM_MASK;
	  p_base = p_mem_base;
	}

      pci_config_writel(bdf, ofs, -1);
      val = pci_config_readl(bdf, ofs);
      pci_config_writel(bdf, ofs, old);

      align = size = ~(val & mask) + 1;
      if (val != 0)
	{
	  uint32_t addr = *p_base;
	  addr = (addr + align - 1) & ~(align - 1);
	  *p_base = addr + size;
	  pci_config_writel(bdf, ofs, addr);

	  printf("PCI:   region %d: %08x\r\n", region, addr);

	  if ((old & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
              == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64))
	    {
	      pci_config_writel(bdf, ofs + 4, 0);
	      region++;
	    }
	}
    }

  pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);

  /* Map the interrupt and program the IRQ into the line register.
     Some operating systems rely on the Console providing this information
     in order to avoid having mapping tables for every possible system
     variation.  */

  const uint8_t pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
  const uint8_t slot = PCI_SLOT(bdf);
  const uint8_t irq = MAP_PCI_INTERRUPT(slot, pin, class_id);

  pci_config_writeb(bdf, PCI_INTERRUPT_LINE, irq);
}

void
pci_setup(void)
{
  uint32_t io_base = 0xc000;
  uint32_t mem_base = 256 * 1024 * 1024;
  int bdf, max;

  foreachpci (bdf, max)
    pci_setup_device(bdf, &io_base, &mem_base);
}
