/*
 *   NVRAM WakeUp
 *   Copyright (C) 2001-2005, Sergei Haller.
 *   Copyright (C) 2002 Bernhard "Bero" Rosenkraenzer <bero@arklinux.org>
 *
 *   $Id: nvram-wakeup-mb.c 870 2008-09-06 20:48:34Z tiber $
 *
 *   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
 *
 */

#define CVSREV_nvram_wakeup_mb_c \
     "$Id: nvram-wakeup-mb.c 870 2008-09-06 20:48:34Z tiber $"

#include <stdio.h>
#include <string.h>
#include <syslog.h>

#include "nvram-wakeup.h"

/*
 *  If you can't find your motherboard here, try at the MB tracker
 *    http://sourceforge.net/tracker/index.php?group_id=35022&atid=412959
 *  or the latest SVN revision of this file
 *    http://nvram-wakeup.svn.sourceforge.net/viewvc/nvram-wakeup/trunk/nvram-wakeup/boards/boards.yaml
 *  or
 *    read README.mb.
 */

typedef void (*info_writer)(struct biosinfo *b);
     
struct mainboard {
     info_writer infowriter;

     char *iw_name;     /* the function name of the infowriter */

     char *vendor;
     char *type;
     char *version;

     char *biosvendor;
     char *biosversion;
     char *biosrelease;
};


/*
 *  look into nvram-wakeup.conf(5) for the documentation of the options
 */
 
/* 
 *  By far the most common way of storing the timing information is having
 *  it in subsequent bytes in the day-hour-min-sec order. #define this
 *  here to save code later on
 */
 
#define TIMEREGS(b, base) b->addr_day  = base;  \
                          b->addr_hour = base+1;\
                          b->addr_min  = base+2;\
                          b->addr_sec  = base+3

/* 
 *  Virtually every board keeps the low and high bytes of the checksum in
 *  subsequent bytes - save some more code
 */
 
#define CHECKSUM(b, base) b->addr_chk_h = base;\
                          b->addr_chk_l = base+1

#define   BCD(b) b->nr_mon      = 5;\
                 b->nr_day      = 6;\
                 b->nr_hour     = 6;\
                 b->nr_min      = 7;\
                 b->nr_sec      = 7;\
                 b->nr_rtc_mon  = 5;\
                 b->nr_rtc_day  = 6;\
                 b->nr_wdays    = 7;\
                 b->bcd         = ON

#define NOBCD(b) b->nr_mon      = 4;\
                 b->nr_day      = 5;\
                 b->nr_hour     = 5;\
                 b->nr_min      = 6;\
                 b->nr_sec      = 6;\
                 b->nr_rtc_day  = 6;\
                 b->nr_rtc_mon  = 5;\
                 b->nr_wdays    = 7

#include "infowriters.c.inc"

#define IW(x) x, #x

/*
 * Definitions of the mainboards below are in the format
 *
 *             { infowriter,        iwname,             boardvendor, boardtype, boardversion, biosvendor, biosversion, biosrelease }
 *
 * Where NULL means "Don't care" and "" is a real empty field.
 */
#include "boards.c.inc"


int set_biosinfo_defaults(struct biosinfo *b) {
     if (b) {
          memset(b, 0, sizeof(struct biosinfo));
          b->nr_stat = 1;
          b->addr_stat = -1;
          NOBCD(b);
          return 1;
     }
     else return 0;
}

int get_bios_info_by_dmi(struct biosinfo *b) {

     int i;

     /* Set defaults... */
     if (!set_biosinfo_defaults(b))
          return 0;

     if (!__dmi_probe())
          return -1;

     /* Check if we know the mainboard... */
     for(i=0; boards[i].infowriter; i++) {
          if (boards[i].vendor      && (!board_vendor()  || strcmp(boards[i].vendor,      board_vendor() )))
               continue;
          if (boards[i].type        && (!board_type()    || strcmp(boards[i].type,        board_type()   )))
               continue;
          if (boards[i].version     && (!board_version() || strcmp(boards[i].version,     board_version())))
               continue;
          if (boards[i].biosvendor  && (!bios_vendor()   || strcmp(boards[i].biosvendor,  bios_vendor()  )))
               continue;
          if (boards[i].biosversion && (!bios_version()  || strcmp(boards[i].biosversion, bios_version() )))
               continue;
          if (boards[i].biosrelease && (!bios_release()  || strcmp(boards[i].biosrelease, bios_release() )))
               continue;

          /* This is our board... */
          nvprintf(LOG_DEBUG, "Using infowriter \"%s\" (automatically detected)\n", boards[i].iw_name);
          boards[i].infowriter(b);
          return 1;
     }
     return 0;
}



int get_bios_info_by_iw(struct biosinfo *b, const char * iw_name) {

     int i;

     /* Set defaults... */
     if (!set_biosinfo_defaults(b))
          return 0;

     /* Check if we know that infowriter... */
     for(i=0; boards[i].infowriter; i++) {
          if ( strcmp( boards[i].iw_name, iw_name ) )
               continue;

          /* This is our board... */
          nvprintf(LOG_DEBUG, "Using infowriter \"%s\" (manually choosen)\n", boards[i].iw_name);
          boards[i].infowriter(b);
          return 1;
     }
     return 0;
}


