]> git.zerfleddert.de Git - rsbs2/blob - bmc/chassis.c
implement powercycle via IPMI
[rsbs2] / bmc / chassis.c
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <stdio.h>
4
5 #include "config.h"
6 #include "chassis.h"
7
8 #ifdef __AVR_ATmega16__
9 #define CHASSISPORT B
10 #define POWER_PIN 0
11 #define RESET_PIN 1
12 #define ACTIVE_LOW
13 #else
14 #error "Please add chassis power/reset-PIN information for this chip"
15 #endif
16
17 #define __CPORT(port) PORT##port
18 #define _CPORT(port) __CPORT(port)
19 #define CPORT _CPORT(CHASSISPORT)
20
21 #define __CDDR(port) DDR##port
22 #define _CDDR(port) __CDDR(port)
23 #define CDDR _CDDR(CHASSISPORT)
24
25 static volatile int power_cnt = 0;
26 static volatile int reset_cnt = 0;
27 static volatile int power_cycle = 0;
28
29 static void chassis_set_pins(uint8_t pins, uint8_t state);
30
31 void chassis_init()
32 {
33 chassis_set_pins((1<<POWER_PIN) | (1<<RESET_PIN), 0);
34 CDDR |= ((1<<POWER_PIN) | (1<<RESET_PIN));
35
36 /* About 1ms */
37 OCR0 = ((F_CPU/64)/1000) - 1;
38
39 TCCR0 = ((1<<WGM01) | (1<<CS01) | (1<<CS00)); /* CTC, Prescaler 64 */
40 TIMSK |= (1<<OCIE0);
41
42 }
43
44 static void chassis_set_pins(uint8_t pins, uint8_t state)
45 {
46 #ifdef ACTIVE_LOW
47 state = !state;
48 #endif
49
50 if(state) {
51 CPORT |= pins;
52 } else {
53 CPORT &= ~pins;
54 }
55 }
56
57 static void chassis_power(int msec)
58 {
59 uint8_t old_SREG = SREG;
60
61 chassis_set_pins((1<<POWER_PIN), 1);
62
63 cli();
64 if (!power_cnt)
65 power_cnt = msec;
66 SREG = old_SREG;
67 }
68
69 static void chassis_reset(int msec)
70 {
71 uint8_t old_SREG = SREG;
72
73 chassis_set_pins((1<<RESET_PIN), 1);
74
75 cli();
76 if (!reset_cnt)
77 reset_cnt = msec;
78 SREG = old_SREG;
79 }
80
81 void chassis_control(unsigned char action)
82 {
83 uint8_t old_SREG = SREG;
84
85 #ifdef DEBUG
86 printf("Chassis control 0x%02x\n", action);
87 #endif
88
89 switch(action) {
90 case CHASSIS_ACTION_POWER_DOWN:
91 chassis_power(POWERDOWN_TIME_MS);
92 break;
93
94 case CHASSIS_ACTION_POWER_UP:
95 chassis_power(POWERUP_TIME_MS);
96 break;
97
98 case CHASSIS_ACTION_HARD_RESET:
99 chassis_reset(RESET_TIME_MS);
100 break;
101
102 case CHASSIS_ACTION_POWER_CYCLE:
103 cli();
104 power_cycle = POWER_CYCLE_PAUSE_MS;
105 SREG = old_SREG;
106 chassis_power(POWERDOWN_TIME_MS);
107
108 default:
109 #ifdef DEBUG
110 printf("Unimplemented chassis action 0x%02x\n", action);
111 #endif
112 break;
113 }
114 }
115
116 ISR(TIMER0_COMP_vect)
117 {
118 if (power_cnt) {
119 power_cnt--;
120
121 if (!power_cnt)
122 chassis_set_pins((1<<POWER_PIN), 0);
123 } else if (power_cycle) {
124 power_cycle--;
125
126 if (!power_cycle) {
127 chassis_set_pins((1<<POWER_PIN), 1);
128 power_cnt = POWERUP_TIME_MS;
129 }
130 }
131 if (reset_cnt) {
132 reset_cnt--;
133
134 if (!reset_cnt)
135 chassis_set_pins((1<<RESET_PIN), 0);
136 }
137 }
Impressum, Datenschutz