]> git.zerfleddert.de Git - rsbs2/blobdiff - bmc/chassis.c
implement powercycle via IPMI
[rsbs2] / bmc / chassis.c
index 5bdad1f511431f04fd996a42f3146cb5cb5eb334..2259d8605eed30ce49c067f789573d5b7453aa0b 100644 (file)
 #include <avr/io.h>
+#include <avr/interrupt.h>
 #include <stdio.h>
 
+#include "config.h"
 #include "chassis.h"
 
-#define DEBUG
+#ifdef __AVR_ATmega16__
+#define CHASSISPORT B
+#define POWER_PIN 0
+#define RESET_PIN 1
+#define ACTIVE_LOW
+#else
+#error "Please add chassis power/reset-PIN information for this chip"
+#endif
+
+#define __CPORT(port) PORT##port
+#define _CPORT(port) __CPORT(port)
+#define CPORT _CPORT(CHASSISPORT)
+
+#define __CDDR(port) DDR##port
+#define _CDDR(port) __CDDR(port)
+#define CDDR _CDDR(CHASSISPORT)
+
+static volatile int power_cnt = 0;
+static volatile int reset_cnt = 0;
+static volatile int power_cycle = 0;
+
+static void chassis_set_pins(uint8_t pins, uint8_t state);
 
 void chassis_init()
 {
-       DDRB = 0xff;
-       PORTB = 0xff;
+       chassis_set_pins((1<<POWER_PIN) | (1<<RESET_PIN), 0);
+       CDDR |= ((1<<POWER_PIN) | (1<<RESET_PIN));
+
+       /* About 1ms */
+       OCR0 = ((F_CPU/64)/1000) - 1;
+
+       TCCR0 = ((1<<WGM01) | (1<<CS01) | (1<<CS00)); /* CTC, Prescaler 64 */
+       TIMSK |= (1<<OCIE0);
+
+}
+
+static void chassis_set_pins(uint8_t pins, uint8_t state)
+{
+#ifdef ACTIVE_LOW
+       state = !state;
+#endif
+
+       if(state) {
+               CPORT |= pins;
+       } else {
+               CPORT &= ~pins;
+       }
+}
+
+static void chassis_power(int msec)
+{
+       uint8_t old_SREG = SREG;
+
+       chassis_set_pins((1<<POWER_PIN), 1);
+
+       cli();
+       if (!power_cnt)
+               power_cnt = msec;
+       SREG = old_SREG;
+}
+
+static void chassis_reset(int msec)
+{
+       uint8_t old_SREG = SREG;
+
+       chassis_set_pins((1<<RESET_PIN), 1);
+
+       cli();
+       if (!reset_cnt)
+               reset_cnt = msec;
+       SREG = old_SREG;
 }
 
 void chassis_control(unsigned char action)
 {
+       uint8_t old_SREG = SREG;
+
 #ifdef DEBUG
        printf("Chassis control 0x%02x\n", action);
 #endif
 
        switch(action) {
                case CHASSIS_ACTION_POWER_DOWN:
-                       PORTB=0xff;
+                       chassis_power(POWERDOWN_TIME_MS);
                        break;
 
                case CHASSIS_ACTION_POWER_UP:
-                       PORTB=0x00;
+                       chassis_power(POWERUP_TIME_MS);
                        break;
 
                case CHASSIS_ACTION_HARD_RESET:
-                       PORTB=0x55;
+                       chassis_reset(RESET_TIME_MS);
                        break;
 
+               case CHASSIS_ACTION_POWER_CYCLE:
+                       cli();
+                       power_cycle = POWER_CYCLE_PAUSE_MS;
+                       SREG = old_SREG;
+                       chassis_power(POWERDOWN_TIME_MS);
+
                default:
+#ifdef DEBUG
                        printf("Unimplemented chassis action 0x%02x\n", action);
+#endif
                        break;
        }
 }
+
+ISR(TIMER0_COMP_vect)
+{
+       if (power_cnt) {
+               power_cnt--;
+
+               if (!power_cnt)
+                       chassis_set_pins((1<<POWER_PIN), 0);
+       } else if (power_cycle) {
+               power_cycle--;
+
+               if (!power_cycle) {
+                       chassis_set_pins((1<<POWER_PIN), 1);
+                       power_cnt = POWERUP_TIME_MS;
+               }
+       }
+       if (reset_cnt) {
+               reset_cnt--;
+
+               if (!reset_cnt)
+                       chassis_set_pins((1<<RESET_PIN), 0);
+       }
+}
Impressum, Datenschutz