/*
 * Copyright 2012 Google Inc.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <assert.h>
#include <usb/usb.h>

#include "base/cleanup.h"
#include "base/xalloc.h"
#include "drivers/bus/usb/usb.h"

ListNode generic_usb_drivers;
ListNode usb_host_controllers;

void usb_generic_create(UsbDev *dev)
{
	// Allocate a structure to keep track of this device.
	GenericUsbDevice *gdev = xmalloc(sizeof(*gdev));
	gdev->dev = dev;

	// Check if any generic USB driver wants to claim it.
	GenericUsbDriver *driver;
	list_for_each(driver, generic_usb_drivers, list_node) {
		gdev->driver = driver;
		// If so, attach our info and return.
		if (driver->probe && driver->probe(gdev)) {
			dev->data = gdev;
			return;
		}
	}

	// Nobody wanted it so free resources and return.
	free(gdev);
}

void usb_generic_remove(UsbDev *dev)
{
	// If this device was never claimed, ignore it.
	if (!dev->data)
		return;

	// If the driver for this device has a "remove" function, call it.
	GenericUsbDevice *gdev = dev->data;
	assert(gdev->driver);
	if (gdev->driver->remove)
		gdev->driver->remove(gdev);

	// Free our bookeeping data structure and return.
	free(gdev);
	dev->data = NULL;
}

UsbHostController *new_usb_hc(UsbHcType type, uintptr_t bar)
{
	UsbHostController *hc = xzalloc(sizeof(*hc));
	hc->type = type;
	hc->bar = (void *)bar;
	return hc;
}

void set_usb_init_callback(UsbHostController *hc, UsbHcCallback *callback)
{
	hc->init_callback = callback;
}

static int dc_usb_shutdown(DcEvent *event)
{
	printf("Shutting down all USB controllers.\n");
	usb_exit();
	return 0;
}

void dc_usb_initialize(void)
{
	static const char *const hc_types[] = {
		[UsbUhci] = "UHCI",
		[UsbOhci] = "OHCI",
		[UsbEhci] = "EHCI",
		[UsbXhci] = "XHCI",
		[UsbDwc2] = "DWC2"
	};
	static int need_init = 1;
	static CleanupEvent cleanup = {
		.event = { .trigger = &dc_usb_shutdown },
		.types = CleanupOnHandoff | CleanupOnLegacy,
	};

	if (need_init) {
		usb_initialize();
		need_init = 0;
		cleanup_add(&cleanup);

		UsbHostController *hc;
		list_for_each(hc, usb_host_controllers, list_node) {
			printf("Initializing %s USB controller at %p.\n",
			       hc_types[hc->type], hc->bar);
			usb_add_mmio_hc(hc->type, hc->bar);
			if (hc->init_callback)
				hc->init_callback(hc);
		}
	}
}
