/*
 * Copyright (C) 2002  Emmanuel VARAGNAT <hddtemp@guzu.net>
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

// Include file generated by ./configure
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

// Gettext includes
#if ENABLE_NLS
#include <libintl.h>
#define _(String) gettext (String)
#else
#define _(String) (String)
#endif

// Standard includes
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/hdreg.h>

// Application specific includes
#include "atacmds.h"
#include "hddtemp.h"

int ata_enable_smart(int device) {
  unsigned char cmd[4] = { WIN_SMART, 0, SMART_ENABLE, 0 };

  return ioctl(device, HDIO_DRIVE_CMD, cmd);
}

int ata_get_smart_values(int device, unsigned char* buff) {
  unsigned char  cmd[516] = { WIN_SMART, 0, SMART_READ_VALUES, 1 };
  int            ret;

  ret = ioctl(device, HDIO_DRIVE_CMD, cmd);
  if(ret)
    return ret;
  memcpy(buff, cmd+4, 512);
  return 0;
}

unsigned char* ata_search_temperature(const unsigned char* smart_data, int attribute_id) {
  int i, n;

  n = 3;
  i = 0;
  while((debug || *(smart_data + n) != attribute_id) && i < 30) {
    if(debug && *(smart_data + n))
      printf(_("field(%d)\t = %d\t(0x%02x)\n"),
	     (int)*(smart_data + n),
	     (int)*(smart_data + n + 3),
	     *(smart_data + n + 3));

    n += 12;
    i++;
  }

  if(i >= 30)
    return NULL;
  else
    return (unsigned char*)(smart_data + n);
}

enum e_powermode ata_get_powermode(int device) {
#ifndef WIN_CHECKPOWERMODE1
#define WIN_CHECKPOWERMODE1 0xE5
#endif
#ifndef WIN_CHECKPOWERMODE2
#define WIN_CHECKPOWERMODE2 0x98
#endif
  unsigned char args[4] = { WIN_CHECKPOWERMODE1, 0, 0, 0 };
  enum e_powermode state = PWM_UNKNOWN;

  /*
    After ioctl:
      args[0] = status;
      args[1] = error;
      args[2] = nsector_reg;
  */

  if (ioctl(device, HDIO_DRIVE_CMD, &args)
      && (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */
      && ioctl(device, HDIO_DRIVE_CMD, &args))
    {
       if (errno != EIO || args[0] != 0 || args[1] != 0)
         state = PWM_UNKNOWN;
       else
         state = PWM_SLEEPING;
    } else {
       state = ( (args[2] == 0xFF) ? PWM_ACTIVE : PWM_STANDBY );
    }

  return state;
}

int ata_get_packet (int device) {
  unsigned short buf[256];
  if (!ioctl(device, HDIO_GET_IDENTITY, buf) && (buf[0] & 0x8000))
    return 1;	 
  else	  
    return 0;
}
