/*
 * array-info - Array Controllers Informations
 * Copyright (C) 2002  Benoit Gaussen (ben@trez42.net)
 *
 * $Log: ida_info.c,v $
 * Revision 1.2  2007/02/03 10:04:05  pere
 * Convert the cciss and ida plugin to the new shared library framework.  Some code cleanup.
 *
 * Revision 1.1  2002/07/29 16:50:19  trez42
 * Add plugin support
 * Change directory structure
 *
 * Revision 1.4  2002/07/25 16:51:14  trez42
 * CVS Fixes
 *
 *
 * 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 "array_info.h"
#include "array_plugin.h"
#include "ida_info.h"
#include "compaq_info.h"

static ida_ctrl_data_t ida_ctrl_data;

#include "xmalloc.ic"

static int
ida_sense_ldrv(ida_ctrl_data_t * ctrl_data, u_int8_t ldrv)
{
	ida_ioctl_t *ida_io_ldrv, *ida_io_sense;
	id_log_drv_t *ldrv_info;
	sense_log_drv_stat_t *ldrv_status;

	if ((ida_io_ldrv = ida_bmic_cmd(ctrl_data, ID_LOG_DRV)) == NULL) {
		printf
		    ("Error while getting IDA logical drive %d informations...\n",
		     ldrv);
		return -1;
	}

	if ((ida_io_sense =
	     ida_bmic_cmd(ctrl_data, SENSE_LOG_DRV_STAT)) == NULL) {
		printf("Error while getting IDA logical drive %d status...\n",
		       ldrv);
		return -1;
	}

	ldrv_info = &ida_io_ldrv->c.id_log_drv;
	ldrv_status = &ida_io_sense->c.sense_log_drv_stat;

	ctrl_data->ctrl.ldrvs[ldrv].log_drive = ldrv;
	ctrl_data->ctrl.ldrvs[ldrv].nr_blks = ldrv_info->nr_blks;
	ctrl_data->ctrl.ldrvs[ldrv].blk_size = ldrv_info->blk_size;
	ctrl_data->ctrl.ldrvs[ldrv].fault_tol = ldrv_info->fault_tol;
	ctrl_data->ctrl.ldrvs[ldrv].status = ldrv_status->status;
	ctrl_data->ctrl.ldrvs[ldrv].blks_to_recover =
	    ldrv_status->blks_to_recover;

	free(ida_io_ldrv);
	free(ida_io_sense);
	return 0;
}

static int
ida_ctrl_req(driver_data_ptr_t data)
{
	ida_ioctl_t *ida_io;
	id_ctlr_t *ctrl_info;
	ida_ctrl_data_t *ctrl_data = (ida_ctrl_data_t *) data;

	if ((ida_io = ida_bmic_cmd(ctrl_data, ID_CTLR)) == NULL) {
		printf("Error while getting IDA controller informations...\n");
		return -1;
	}

	ctrl_info = &ida_io->c.id_ctlr;

	ctrl_data->ctrl.board_id = ctrl_info->board_id;
	memcpy(ctrl_data->ctrl.firm_rev, ctrl_info->firm_rev, 4);
	memcpy(ctrl_data->ctrl.rom_rev, ctrl_info->rom_rev, 4);
	ctrl_data->ctrl.nr_ldrvs = ctrl_info->nr_drvs;

	if (ctrl_data->query_flags == QUERY_ALL_LDRV) {
		int i;

		ctrl_data->ctrl.ldrvs =
		    xmalloc(sizeof (compaq_log_drive_t) *
			    ctrl_data->ctrl.nr_ldrvs);

		for (i = 0; i < ctrl_data->ctrl.nr_ldrvs; i++)
			ida_sense_ldrv(ctrl_data, i);
	} else {
		ctrl_data->ctrl.ldrvs = xmalloc(sizeof (compaq_log_drive_t));
		ida_sense_ldrv(ctrl_data, ctrl_data->log_drive);
	}

	return 0;
}

static driver_data_ptr_t
ida_ctrl_open(array_data_t * array_data)
{
	ida_ctrl_data.fd = array_data->fd;
	ida_ctrl_data.log_drive = array_data->device_major.minor / 16;
	ida_ctrl_data.query_flags = array_data->query_flags;

	return &ida_ctrl_data;
}

static int
ida_ctrl_close(driver_data_ptr_t data)
{
	ida_ctrl_data_t *ctrl_data = (ida_ctrl_data_t *) data;
	return 0;
}

static char *
ida_description()
{
	static char description[35];

	snprintf(description, 35, "Compaq IDA driver plugin v%d.%d.%d",
		 IDA_INFO_VERSION >> 16 & 0xff,
		 IDA_INFO_VERSION >> 8 & 0xff, IDA_INFO_VERSION & 0xff);
	return description;
}

static void
ida_ctrl_free(driver_data_ptr_t data)
{
	ida_ctrl_data_t *ctrl_data = (ida_ctrl_data_t *) data;
	if (ctrl_data->ctrl.ldrvs) {
		free(ctrl_data->ctrl.ldrvs);
		ctrl_data->ctrl.ldrvs = NULL;
	}
}

static array_infos_t *
ida_ctrl_infos(driver_data_ptr_t data, array_plugin_callbacks_t * callbacks)
{
	ida_ctrl_data_t *ctrl_data = (ida_ctrl_data_t *) data;
	compaq_ctrl_t *ctrl = &(ctrl_data->ctrl);
	return compaq_ctrl_infos(ctrl, callbacks, ctrl_data->query_flags,
				 ctrl_data->log_drive);
}

static device_major_t ida_device_majors[] = {
	{BLOCK_DEVICE, COMPAQ_SMART2_MAJOR, -1},
	{BLOCK_DEVICE, COMPAQ_SMART2_MAJOR1, -1},
	{BLOCK_DEVICE, COMPAQ_SMART2_MAJOR2, -1},
	{BLOCK_DEVICE, COMPAQ_SMART2_MAJOR3, -1},
	{BLOCK_DEVICE, COMPAQ_SMART2_MAJOR4, -1},
	{BLOCK_DEVICE, COMPAQ_SMART2_MAJOR5, -1},
	{BLOCK_DEVICE, COMPAQ_SMART2_MAJOR6, -1},
	{BLOCK_DEVICE, COMPAQ_SMART2_MAJOR7, -1},
	{0, 0, 0},
};

array_plugin_t array_plugin = {
	.device_majors = ida_device_majors,
	.plugin_version = IDA_INFO_VERSION,
	.array_info_version = ARRAY_INFO_VERSION,
	.plugin_description = ida_description,
	.ctrl_open = ida_ctrl_open,
	.ctrl_close = ida_ctrl_close,
	.ctrl_req = ida_ctrl_req,
	.ctrl_infos = ida_ctrl_infos,
	.ctrl_free = ida_ctrl_free,
};
