/*
 * RPA Virtual I/O device functions 
 * Copyright (C) 2004 Linda Xie <lxie@us.ibm.com>
 *
 * All rights reserved.
 *
 * 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, GOOD TITLE or
 * NON INFRINGEMENT.  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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * Send feedback to <lxie@us.ibm.com>
 *
 */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/sysfs.h>
#include <linux/pci.h>
#include <asm/rtas.h>
#include "rpaphp.h"

static ssize_t removable_read_file (struct hotplug_slot *php_slot, char *buf)
{
	u8 value;
	int retval = -ENOENT;
	struct slot *slot = (struct slot *)php_slot->private;

	if (!slot)
		return retval;

	value = slot->removable;
	retval = sprintf (buf, "%d\n", value);
	return retval;
}

static struct hotplug_slot_attribute hotplug_slot_attr_removable = {
	.attr = {.name = "phy_removable", .mode = S_IFREG | S_IRUGO},
	.show = removable_read_file,
};

static void rpaphp_sysfs_add_attr_removable (struct hotplug_slot *slot)
{
	sysfs_create_file(&slot->kobj, &hotplug_slot_attr_removable.attr);
}

static void rpaphp_sysfs_remove_attr_removable (struct hotplug_slot *slot)
{
	sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_removable.attr);
}

static ssize_t location_read_file (struct hotplug_slot *php_slot, char *buf)
{
        char *value;
        int retval = -ENOENT;
	struct slot *slot = (struct slot *)php_slot->private;

	if (!slot)
		return retval;

        value = slot->location;
        retval = sprintf (buf, "%s\n", value);
        return retval;
}

static struct hotplug_slot_attribute hotplug_slot_attr_location = {
	.attr = {.name = "phy_location", .mode = S_IFREG | S_IRUGO},
	.show = location_read_file,
};

static void rpaphp_sysfs_add_attr_location (struct hotplug_slot *slot)
{
	sysfs_create_file(&slot->kobj, &hotplug_slot_attr_location.attr);
}

static void rpaphp_sysfs_remove_attr_location (struct hotplug_slot *slot)
{
	sysfs_remove_file(&slot->kobj, &hotplug_slot_attr_location.attr);
}

/* free up the memory used by a slot */
static void rpaphp_release_slot(struct hotplug_slot *hotplug_slot)
{
	struct slot *slot = (struct slot *) hotplug_slot->private;

	dealloc_slot_struct(slot);
}

void dealloc_slot_struct(struct slot *slot)
{
	kfree(slot->hotplug_slot->info);
	kfree(slot->hotplug_slot->name);
	kfree(slot->hotplug_slot);
	kfree(slot);
	return;
}

struct slot *alloc_slot_struct(struct device_node *dn, int drc_index, char *drc_name,
		  int power_domain)
{
	struct slot *slot;
	
	slot = kmalloc(sizeof (struct slot), GFP_KERNEL);
	if (!slot)
		goto error_nomem;
	memset(slot, 0, sizeof (struct slot));
	slot->hotplug_slot = kmalloc(sizeof (struct hotplug_slot), GFP_KERNEL);
	if (!slot->hotplug_slot)
		goto error_slot;	
	memset(slot->hotplug_slot, 0, sizeof (struct hotplug_slot));
	slot->hotplug_slot->info = kmalloc(sizeof (struct hotplug_slot_info),
					   GFP_KERNEL);
	if (!slot->hotplug_slot->info)
		goto error_hpslot;
	memset(slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info));
	slot->hotplug_slot->name = kmalloc(BUS_ID_SIZE + 1, GFP_KERNEL);
	if (!slot->hotplug_slot->name)
		goto error_info;	
	slot->location = kmalloc(strlen(drc_name) + 1, GFP_KERNEL);
	if (!slot->location)
		goto error_name;
	slot->name = slot->hotplug_slot->name;
	slot->dn = dn;
	slot->index = drc_index;
	strcpy(slot->location, drc_name);
	slot->power_domain = power_domain;
	slot->hotplug_slot->private = slot;
	slot->hotplug_slot->ops = &rpaphp_hotplug_slot_ops;
	slot->hotplug_slot->release = &rpaphp_release_slot;
	
	return (slot);

error_name:
	kfree(slot->hotplug_slot->name);
error_info:
	kfree(slot->hotplug_slot->info);
error_hpslot:
	kfree(slot->hotplug_slot);
error_slot:
	kfree(slot);
error_nomem:
	return NULL;
}

static int is_registered(struct slot *slot)
{
	struct slot             *tmp_slot;

	list_for_each_entry(tmp_slot, &rpaphp_slot_head, rpaphp_slot_list) {
		if (!strcmp(tmp_slot->name, slot->name))
			return 1;
	}	
	return 0;
}

int deregister_slot(struct slot *slot)
{
	int retval = 0;
	struct hotplug_slot *php_slot = slot->hotplug_slot;

	 dbg("%s - Entry: deregistering slot=%s\n",
		__FUNCTION__, slot->name);

	list_del(&slot->rpaphp_slot_list);
	
	/* remove "phy_location" file */
	rpaphp_sysfs_remove_attr_location(php_slot);

	/* remove "phy_removable" file */
	rpaphp_sysfs_remove_attr_removable(php_slot);

	retval = pci_hp_deregister(php_slot);
	if (retval)
		err("Problem unregistering a slot %s\n", slot->name);
	else
		num_slots--;

	dbg("%s - Exit: rc[%d]\n", __FUNCTION__, retval);
	return retval;
}

int register_slot(struct slot *slot)
{
	int retval;

	dbg("%s registering slot:path[%s] index[%x], name[%s] pdomain[%x] type[%d]\n", 
		__FUNCTION__, slot->dn->full_name, slot->index, slot->name, 
		slot->power_domain, slot->type);
	/* should not try to register the same slot twice */
	if (is_registered(slot)) { /* should't be here */
		err("register_slot: slot[%s] is already registered\n", slot->name);
		rpaphp_release_slot(slot->hotplug_slot);
		return -EAGAIN;
	}	
	retval = pci_hp_register(slot->hotplug_slot);
	if (retval) {
		err("pci_hp_register failed with error %d\n", retval);
		rpaphp_release_slot(slot->hotplug_slot);
		return retval;
	}
	
	/* create "phy_locatoin" file */
	rpaphp_sysfs_add_attr_location(slot->hotplug_slot);	

	/* create "phy_removable" file */
	rpaphp_sysfs_add_attr_removable(slot->hotplug_slot);	

	/* add slot to our internal list */
	dbg("%s adding slot[%s] to rpaphp_slot_list\n",
	    __FUNCTION__, slot->name);

	list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);

	if (slot->dev_type == VIO_DEV)
		info("Slot [%s](VIO location=%s) registered\n",
		     slot->name, slot->location);
	else
		info("Slot [%s](PCI location=%s) registered\n",
		     slot->name, slot->location);
	num_slots++;
	return 0;
}

int rpaphp_get_power_status(struct slot *slot, u8 * value)
{
	int rc = 0, level;
	
	if (slot->type == HOTPLUG) {
		rc = rtas_get_power_level(slot->power_domain, &level);
		if (!rc) {
			dbg("%s the power level of slot %s(pwd-domain:0x%x) is %d\n",
				__FUNCTION__, slot->name, slot->power_domain, level);
			*value = level;
		} else
			err("failed to get power-level for slot(%s), rc=0x%x\n",
				slot->location, rc);
	} else {
		dbg("%s report POWER_ON for EMBEDDED or PHB slot %s\n",
			__FUNCTION__, slot->location);
		*value = (u8) POWER_ON;
	}

	return rc;
}

int rpaphp_set_attention_status(struct slot *slot, u8 status)
{
	int rc;

	/* status: LED_OFF or LED_ON */
	rc = rtas_set_indicator(DR_INDICATOR, slot->index, status);
	if (rc < 0)
		err("slot(name=%s location=%s index=0x%x) set attention-status(%d) failed! rc=0x%x\n",
		    slot->name, slot->location, slot->index, status, rc);

	return rc;
}
