/*
 * This file is part of the UCB release of Plan 9. It is subject to the license
 * terms in the LICENSE file found in the top-level directory of this
 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
 * part of the UCB release of Plan 9, including this file, may be copied,
 * modified, propagated, or distributed except according to the terms contained
 * in the LICENSE file.
 *
 * Adapted from usbehcipc.c and usbuhci.c
 */

#define Clegacy 				1
#define CLbiossem 				2
#define CLossem 				3
#define CLcontrol 				4

#include <arch/x86.h>
#include <arch/pci.h>
#include <trap.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <kmalloc.h>
#include <time.h>
#include <mm.h>

static void ehci_disable_leg(struct pci_device *pcidev)
{
	int i, ptr, cap, sem;

	//ptr = (ctlr->capio->capparms >> Ceecpshift) & Ceecpmask;
	uintptr_t bar0 = pci_get_membar(pcidev, 0);
	assert(bar0);
	uintptr_t ehci_hcc_regs = vmap_pmem_nocache(bar0, pcidev->bar[0].mmio_sz);
	uint32_t hccparams = read_mmreg32(ehci_hcc_regs + 0x08);
	ptr = (hccparams >> 8) & ((1 << 8) - 1);

	for(; ptr != 0; ptr = pcidev_read8(pcidev, ptr + 1)) {
		if (ptr < 0x40 || (ptr & ~0xFC))
			break;
		cap = pcidev_read8(pcidev, ptr);
		if (cap != Clegacy)
			continue;
		sem = pcidev_read8(pcidev, ptr + CLbiossem);
		if (sem == 0)
			continue;
		pcidev_write8(pcidev, ptr + CLossem, 1);
		for (i = 0; i < 100; i++) {
			if (pcidev_read8(pcidev, ptr + CLbiossem) == 0)
				break;
			udelay(10);
		}
		if (i == 100)
			printk("PCI EHCI %x:%x:%x: bios timed out\n",
			       pcidev->bus, pcidev->dev, pcidev->func);
		/* bit 29 could be left on, in case we want to give it back */
		pcidev_write32(pcidev, ptr + CLcontrol, 0);	/* no SMIs */
		//ctlr->opio->config = 0;
		//coherence();
		printk("PCI EHCI %x:%x:%x: disabled legacy USB\n",
		       pcidev->bus, pcidev->dev, pcidev->func);
		return;
	}
	printk("PCI EHCI %x:%x:%x: couldn't find legacy capability\n",
	       pcidev->bus, pcidev->dev, pcidev->func);
}

#define XHCI_USBLEGSUP 1

static void xhci_disable_leg(struct pci_device *pcidev)
{
	uintptr_t bar0, xhci_hcc_regs, xecp;
	uint32_t hccparams, val;
	int i;

	bar0 = pci_get_membar(pcidev, 0);
	assert(bar0);
	xhci_hcc_regs = vmap_pmem_nocache(bar0, pcidev->bar[0].mmio_sz);
	hccparams = read_mmreg32(xhci_hcc_regs + 0x10);
	xecp = (hccparams >> 16) & 0xffff;

	/* xecp is the rel offset, in 32 bit words, from the base to the extended
	 * capabilities pointer. */
	for (/* xecp set */; xecp; xecp = (read_mmreg32(xecp) >> 8) & 0xff) {
		xecp = xhci_hcc_regs + (xecp << 2);
		val = read_mmreg32(xecp);

		if ((val & 0xff) != XHCI_USBLEGSUP)
			continue;
		/* bios already does not own it */
		if (!(val & (1 << 16)))
			return;
		/* take ownership.  Note we're allowed to do byte-width writes here. */
		write_mmreg8(xecp + 3, 1);
		/* book says to wait up to a second, though i regularly see it time out
		 * on my machines. */
		for (i = 0; i < 100000; i++) {
			if (!(read_mmreg32(xecp) & (1 << 16)))
				break;
			udelay(10);
		}
		if (i == 100000) {
			printk("PCI XHCI %x:%x:%x: bios timed out\n",
			       pcidev->bus, pcidev->dev, pcidev->func);
			/* Force the bios's byte clear */
			write_mmreg8(xecp + 2, 0);
		}
		/* Turn off settings in USBLEGCTLSTS.  Not sure if any of this is
		 * necessary. */
		val = read_mmreg32(xecp + 4);
		val &= ~((1 << 0) | (1 << 4) | (0x7 << 13));
		/* These are write-to-clear. */
		val |= 0x7 << 29;
		write_mmreg32(xecp + 4, val);
		printk("PCI XHCI %x:%x:%x: disabled legacy USB\n",
		       pcidev->bus, pcidev->dev, pcidev->func);
		return;
	}
	printk("PCI XHCI %x:%x:%x: couldn't find legacy capability\n",
	       pcidev->bus, pcidev->dev, pcidev->func);
}

static void uhci_disable_leg(struct pci_device *pcidev)
{
	pcidev_write16(pcidev, 0xc0, 0x2000);
	printk("PCI UHCI %x:%x:%x: disabled legacy USB\n",
	       pcidev->bus, pcidev->dev, pcidev->func);
}

void usb_disable_legacy()
{
	struct pci_device *i;

	STAILQ_FOREACH(i, &pci_devices, all_dev) {
		if ((i->class == 0x0c) && (i->subclass == 0x03)) {
			switch (i->progif) {
				case 0x00:
					uhci_disable_leg(i);
					break;
				case 0x20:
					ehci_disable_leg(i);
					break;
				case 0x30:
					xhci_disable_leg(i);
					break;
				default:
					/* TODO: ohci */
					printk("PCI USB %x:%x:%x, unknown progif 0x%x\n",
					       i->bus, i->dev, i->func, i->progif);
			}
		}
	}
}
