/*
 * 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 <linux/string.h>
#include <linux/slab.h>

#include <asm/rtas.h>
#include "rpaphp.h"

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);

	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);	

	/* 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);
	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;
	
	rc = rtas_get_power_level(slot->power_domain, &level);
	if (rc < 0) {
		err("failed to get power-level for slot(%s), rc=0x%x\n",
			slot->location, rc);
		return 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;

	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;
}
