Logo Search packages:      
Sourcecode: ibmasm-utils version File versions  Download package

ibmsphalt.c

/*
 * 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.
 *
 * Copyright (C) IBM Corporation, 2004
 *
 * Author: Max Asböck <amax@us.ibm.com> 
 *
 */

// ibmsphalt.c
// Register for event notification with RSA service processor driver.
// If a poweroff event is received issue the /sbin/halt command to
// shutdown the OS before the service processor powers down the system.

#include <libibmasm.h>
#include <syslog.h>

#define N_IGNORE 13
static unsigned char *ignore[N_IGNORE] = {
      "\x5\x2\x1",
      "\x5\x2\x2",
      "\x5\x2\x3",
      // ignore all events but 5.2.4, i.e. poweroff event
      "\x5\x2\x5",
      "\x5\x2\x6",
      "\x5\x2\x7",
      "\x5\x2\x8",
      "\x5\x2\x9",
      "\x5\x2\xa",
      "\x5\x2\xb",
      "\x5\x2\xc",
      "\x5\x2\xd",
      "\x5\x2\xe",
};

#define BUF_LENGTH 1
static char buffer[BUF_LENGTH * 1024];

// to allow the OS to be shutdown before the service processor powers
// the system off, attempt to set the poweroff delay to at least 
// 45 seconds.
void set_poweroff_delay(int handle)
{
      int ret;
      int delay;

      // set the bytes in the poweroff delay command
      buffer[0] = 0x02; // type = read
      buffer[1] = 0x03; // command length
      buffer[2] = 0x00; // data length LSB
      buffer[3] = 0x00; // data length MSB
      buffer[4] = 0x00; // status
      buffer[5] = 0x00; // reserved
      buffer[6] = 0x06; // 1st command byte - command  6.2.1
      buffer[7] = 0x02; // 2nd cmd byte
      buffer[8] = 0x01; // 3rd cmd byte
      buffer[9] = 0x00;

      ret = SystemDataIO(handle, buffer, 0);

      if ( (ret != RC_SUCCESS)
            || (buffer[0] != 4)     // type != command response
            || (buffer[1] != 3)     // command length != 3
            || (buffer[4] != 0)     // status != 0
            || (buffer[6] != 6)     // command 6.2.1
            || (buffer[7] != 2)
            || (buffer[8] != 1) )
            return;

      delay = buffer[9] + buffer[10] << 8;
      if (delay >= 45)
            return;

      // set the poweroff delay to 45 seconds
      buffer[0]  = 0x00;      // type = write
      buffer[1]  = 0x03;      // command length
      buffer[2]  = 0x02;      // data length LSB
      buffer[3]  = 0x00;      // data length MSB
      buffer[4]  = 0x00;      // status
      buffer[5]  = 0x00;      // reserved
      buffer[6]  = 0x06;      // 1st command byte - command  6.2.1
      buffer[7]  = 0x02;      // 2nd cmd byte
      buffer[8]  = 0x01;      // 3rd cmd byte
      buffer[9]  = 0x2D;      // 1st data byte 45
      buffer[10] = 0x00;      // 2nd data byte

      SystemDataIO(handle, buffer, 0);
}

// to be able to receive the poweroff event from the service processor
// we have to enable it by writing 1 in the event's data bit.
static int enable_poweroff_event(int handle)
{
      int ret;

      // enable the 5.2.4 event
      buffer[0]  = 0x00;      // type = write
      buffer[1]  = 0x03;      // command length
      buffer[2]  = 0x01;      // data length LSB
      buffer[3]  = 0x00;      // data length MSB
      buffer[4]  = 0x00;      // status
      buffer[5]  = 0x00;      // reserved
      buffer[6]  = 0x05;      // 1st command byte - event 5.2.1
      buffer[7]  = 0x02;      // 2nd command byte
      buffer[8]  = 0x04;      // 3rd command byte
      buffer[9]  = 0x01;      // 1st data byte
      buffer[10] = 0x00;      // 2nd data byte

      ret = SystemDataIO(handle, buffer, 0);
      if ( (ret != RC_SUCCESS) || (buffer[4] != 0) )
            return 0;

      return 1;
}

int main()
{
      int ret;
      int handle;

      ret = OpenSPDriver(&handle, BUF_LENGTH, 0);
      if (ret != RC_SUCCESS)
            return 1;

      set_poweroff_delay(handle);

      if (!enable_poweroff_event(handle))
            return 2;

      // wait for a poweroff event
      while (1) {
            memset(buffer, 0, 10);
            ret = RegisterForEvents(handle, buffer, N_IGNORE, ignore, 0);
            if (ret != RC_SUCCESS)
                  break;

            // make sure we received a valid poweroff event
            if (   (buffer[0] == 5) // type = event
                && (buffer[1] == 3) // length = 3
                && (buffer[4] == 0) // status = 0
                && (buffer[6] == 5) // command = 5.2.4, i.e poweroff
                && (buffer[7] == 2)
                && (buffer[8] == 4) ) {
                  syslog(LOG_CRIT, "Received Power Off notification "
                        "from RSA adapter - Halting system\n");
                  system("/sbin/halt");
            }
      }
      CloseSPDriver(handle, 0);
      return 0;
}

Generated by  Doxygen 1.6.0   Back to index