49
49
#define IPMI_CMD_GET_SENSOR_READING 0x2d
50
50
#define IPMI_CMD_SET_SENSOR_TYPE 0x2e
51
51
#define IPMI_CMD_GET_SENSOR_TYPE 0x2f
52
+ #define IPMI_CMD_SET_SENSOR_READING 0x30
52
53
53
54
/* #define IPMI_NETFN_APP 0x06 In ipmi.h */
54
55
@@ -1747,6 +1748,227 @@ static void get_sensor_type(IPMIBmcSim *ibs,
1747
1748
rsp_buffer_push (rsp , sens -> evt_reading_type_code );
1748
1749
}
1749
1750
1751
+ /*
1752
+ * bytes parameter
1753
+ * 1 sensor number
1754
+ * 2 operation (see below for bits meaning)
1755
+ * 3 sensor reading
1756
+ * 4:5 assertion states (optional)
1757
+ * 6:7 deassertion states (optional)
1758
+ * 8:10 event data 1,2,3 (optional)
1759
+ */
1760
+ static void set_sensor_reading (IPMIBmcSim * ibs ,
1761
+ uint8_t * cmd , unsigned int cmd_len ,
1762
+ RspBuffer * rsp )
1763
+ {
1764
+ IPMISensor * sens ;
1765
+ uint8_t evd1 = 0 ;
1766
+ uint8_t evd2 = 0 ;
1767
+ uint8_t evd3 = 0 ;
1768
+ uint8_t new_reading = 0 ;
1769
+ uint16_t new_assert_states = 0 ;
1770
+ uint16_t new_deassert_states = 0 ;
1771
+ bool change_reading = false;
1772
+ bool change_assert = false;
1773
+ bool change_deassert = false;
1774
+ enum {
1775
+ SENSOR_GEN_EVENT_NONE ,
1776
+ SENSOR_GEN_EVENT_DATA ,
1777
+ SENSOR_GEN_EVENT_BMC ,
1778
+ } do_gen_event = SENSOR_GEN_EVENT_NONE ;
1779
+
1780
+ if ((cmd [2 ] >= MAX_SENSORS ) ||
1781
+ !IPMI_SENSOR_GET_PRESENT (ibs -> sensors + cmd [2 ])) {
1782
+ rsp_buffer_set_error (rsp , IPMI_CC_REQ_ENTRY_NOT_PRESENT );
1783
+ return ;
1784
+ }
1785
+
1786
+ sens = ibs -> sensors + cmd [2 ];
1787
+
1788
+ /* [1:0] Sensor Reading operation */
1789
+ switch ((cmd [3 ]) & 0x3 ) {
1790
+ case 0 : /* Do not change */
1791
+ break ;
1792
+ case 1 : /* write given value to sensor reading byte */
1793
+ new_reading = cmd [4 ];
1794
+ if (sens -> reading != new_reading ) {
1795
+ change_reading = true;
1796
+ }
1797
+ break ;
1798
+ case 2 :
1799
+ case 3 :
1800
+ rsp_buffer_set_error (rsp , IPMI_CC_INVALID_DATA_FIELD );
1801
+ return ;
1802
+ }
1803
+
1804
+ /* [3:2] Deassertion bits operation */
1805
+ switch ((cmd [3 ] >> 2 ) & 0x3 ) {
1806
+ case 0 : /* Do not change */
1807
+ break ;
1808
+ case 1 : /* write given value */
1809
+ if (cmd_len > 7 ) {
1810
+ new_deassert_states = cmd [7 ];
1811
+ change_deassert = true;
1812
+ }
1813
+ if (cmd_len > 8 ) {
1814
+ new_deassert_states |= (cmd [8 ] << 8 );
1815
+ }
1816
+ break ;
1817
+
1818
+ case 2 : /* mask on */
1819
+ if (cmd_len > 7 ) {
1820
+ new_deassert_states = (sens -> deassert_states | cmd [7 ]);
1821
+ change_deassert = true;
1822
+ }
1823
+ if (cmd_len > 8 ) {
1824
+ new_deassert_states |= (sens -> deassert_states | (cmd [8 ] << 8 ));
1825
+ }
1826
+ break ;
1827
+
1828
+ case 3 : /* mask off */
1829
+ if (cmd_len > 7 ) {
1830
+ new_deassert_states = (sens -> deassert_states & cmd [7 ]);
1831
+ change_deassert = true;
1832
+ }
1833
+ if (cmd_len > 8 ) {
1834
+ new_deassert_states |= (sens -> deassert_states & (cmd [8 ] << 8 ));
1835
+ }
1836
+ break ;
1837
+ }
1838
+
1839
+ if (change_deassert && (new_deassert_states == sens -> deassert_states )) {
1840
+ change_deassert = false;
1841
+ }
1842
+
1843
+ /* [5:4] Assertion bits operation */
1844
+ switch ((cmd [3 ] >> 4 ) & 0x3 ) {
1845
+ case 0 : /* Do not change */
1846
+ break ;
1847
+ case 1 : /* write given value */
1848
+ if (cmd_len > 5 ) {
1849
+ new_assert_states = cmd [5 ];
1850
+ change_assert = true;
1851
+ }
1852
+ if (cmd_len > 6 ) {
1853
+ new_assert_states |= (cmd [6 ] << 8 );
1854
+ }
1855
+ break ;
1856
+
1857
+ case 2 : /* mask on */
1858
+ if (cmd_len > 5 ) {
1859
+ new_assert_states = (sens -> assert_states | cmd [5 ]);
1860
+ change_assert = true;
1861
+ }
1862
+ if (cmd_len > 6 ) {
1863
+ new_assert_states |= (sens -> assert_states | (cmd [6 ] << 8 ));
1864
+ }
1865
+ break ;
1866
+
1867
+ case 3 : /* mask off */
1868
+ if (cmd_len > 5 ) {
1869
+ new_assert_states = (sens -> assert_states & cmd [5 ]);
1870
+ change_assert = true;
1871
+ }
1872
+ if (cmd_len > 6 ) {
1873
+ new_assert_states |= (sens -> assert_states & (cmd [6 ] << 8 ));
1874
+ }
1875
+ break ;
1876
+ }
1877
+
1878
+ if (change_assert && (new_assert_states == sens -> assert_states )) {
1879
+ change_assert = false;
1880
+ }
1881
+
1882
+ if (cmd_len > 9 ) {
1883
+ evd1 = cmd [9 ];
1884
+ }
1885
+ if (cmd_len > 10 ) {
1886
+ evd2 = cmd [10 ];
1887
+ }
1888
+ if (cmd_len > 11 ) {
1889
+ evd3 = cmd [11 ];
1890
+ }
1891
+
1892
+ /* [7:6] Event Data Bytes operation */
1893
+ switch ((cmd [3 ] >> 6 ) & 0x3 ) {
1894
+ case 0 : /*
1895
+ * Don’t use Event Data bytes from this command. BMC will
1896
+ * generate it's own Event Data bytes based on its sensor
1897
+ * implementation.
1898
+ */
1899
+ evd1 = evd2 = evd3 = 0x0 ;
1900
+ do_gen_event = SENSOR_GEN_EVENT_BMC ;
1901
+ break ;
1902
+ case 1 : /*
1903
+ * Write given values to event data bytes including bits
1904
+ * [3:0] Event Data 1.
1905
+ */
1906
+ do_gen_event = SENSOR_GEN_EVENT_DATA ;
1907
+ break ;
1908
+ case 2 : /*
1909
+ * Write given values to event data bytes excluding bits
1910
+ * [3:0] Event Data 1.
1911
+ */
1912
+ evd1 &= 0xf0 ;
1913
+ do_gen_event = SENSOR_GEN_EVENT_DATA ;
1914
+ break ;
1915
+ case 3 :
1916
+ rsp_buffer_set_error (rsp , IPMI_CC_INVALID_DATA_FIELD );
1917
+ return ;
1918
+ }
1919
+
1920
+ /*
1921
+ * Event Data Bytes operation and parameter are inconsistent. The
1922
+ * Specs are not clear on that topic but generating an error seems
1923
+ * correct.
1924
+ */
1925
+ if (do_gen_event == SENSOR_GEN_EVENT_DATA && cmd_len < 10 ) {
1926
+ rsp_buffer_set_error (rsp , IPMI_CC_INVALID_DATA_FIELD );
1927
+ return ;
1928
+ }
1929
+
1930
+ /* commit values */
1931
+ if (change_reading ) {
1932
+ sens -> reading = new_reading ;
1933
+ }
1934
+
1935
+ if (change_assert ) {
1936
+ sens -> assert_states = new_assert_states ;
1937
+ }
1938
+
1939
+ if (change_deassert ) {
1940
+ sens -> deassert_states = new_deassert_states ;
1941
+ }
1942
+
1943
+ /* TODO: handle threshold sensor */
1944
+ if (!IPMI_SENSOR_IS_DISCRETE (sens )) {
1945
+ return ;
1946
+ }
1947
+
1948
+ switch (do_gen_event ) {
1949
+ case SENSOR_GEN_EVENT_DATA : {
1950
+ unsigned int bit = evd1 & 0xf ;
1951
+ uint16_t mask = (1 << bit );
1952
+
1953
+ if (sens -> assert_states & mask & sens -> assert_enable ) {
1954
+ gen_event (ibs , cmd [2 ], 0 , evd1 , evd2 , evd3 );
1955
+ }
1956
+
1957
+ if (sens -> deassert_states & mask & sens -> deassert_enable ) {
1958
+ gen_event (ibs , cmd [2 ], 1 , evd1 , evd2 , evd3 );
1959
+ }
1960
+ break ;
1961
+ }
1962
+ case SENSOR_GEN_EVENT_BMC :
1963
+ /*
1964
+ * TODO: generate event and event data bytes depending on the
1965
+ * sensor
1966
+ */
1967
+ break ;
1968
+ case SENSOR_GEN_EVENT_NONE :
1969
+ break ;
1970
+ }
1971
+ }
1750
1972
1751
1973
static const IPMICmdHandler chassis_cmds [] = {
1752
1974
[IPMI_CMD_GET_CHASSIS_CAPABILITIES ] = { chassis_capabilities },
@@ -1768,6 +1990,7 @@ static const IPMICmdHandler sensor_event_cmds[] = {
1768
1990
[IPMI_CMD_GET_SENSOR_READING ] = { get_sensor_reading , 3 },
1769
1991
[IPMI_CMD_SET_SENSOR_TYPE ] = { set_sensor_type , 5 },
1770
1992
[IPMI_CMD_GET_SENSOR_TYPE ] = { get_sensor_type , 3 },
1993
+ [IPMI_CMD_SET_SENSOR_READING ] = { set_sensor_reading , 5 },
1771
1994
};
1772
1995
static const IPMINetfn sensor_event_netfn = {
1773
1996
.cmd_nums = ARRAY_SIZE (sensor_event_cmds ),
0 commit comments