Wed Dec 26 06:45:58 2018 UTC ()
Fix 32bit build.


(mlelstv)
diff -r1.1 -r1.2 src/sys/dev/ipmi.c
diff -r1.1 -r1.2 src/sys/dev/acpi/ipmi_acpi.c

cvs diff -r1.1 -r1.2 src/sys/dev/ipmi.c (switch to unified diff)

--- src/sys/dev/ipmi.c 2018/12/25 11:56:13 1.1
+++ src/sys/dev/ipmi.c 2018/12/26 06:45:58 1.2
@@ -1,2205 +1,2206 @@ @@ -1,2205 +1,2206 @@
1/* $NetBSD: ipmi.c,v 1.1 2018/12/25 11:56:13 mlelstv Exp $ */ 1/* $NetBSD: ipmi.c,v 1.2 2018/12/26 06:45:58 mlelstv Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Manuel Bouyer. 4 * Copyright (c) 2006 Manuel Bouyer.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * 25 *
26 */ 26 */
27 27
28/* 28/*
29 * Copyright (c) 2005 Jordan Hargrave 29 * Copyright (c) 2005 Jordan Hargrave
30 * All rights reserved. 30 * All rights reserved.
31 * 31 *
32 * Redistribution and use in source and binary forms, with or without 32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions 33 * modification, are permitted provided that the following conditions
34 * are met: 34 * are met:
35 * 1. Redistributions of source code must retain the above copyright 35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer. 36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright 37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the 38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution. 39 * documentation and/or other materials provided with the distribution.
40 * 40 *
41 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 41 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
45 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 45 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE. 51 * SUCH DAMAGE.
52 */ 52 */
53 53
54#include <sys/cdefs.h> 54#include <sys/cdefs.h>
55__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.1 2018/12/25 11:56:13 mlelstv Exp $"); 55__KERNEL_RCSID(0, "$NetBSD: ipmi.c,v 1.2 2018/12/26 06:45:58 mlelstv Exp $");
56 56
57#include <sys/types.h> 57#include <sys/types.h>
58#include <sys/param.h> 58#include <sys/param.h>
59#include <sys/systm.h> 59#include <sys/systm.h>
60#include <sys/kernel.h> 60#include <sys/kernel.h>
61#include <sys/device.h> 61#include <sys/device.h>
62#include <sys/extent.h> 62#include <sys/extent.h>
63#include <sys/callout.h> 63#include <sys/callout.h>
64#include <sys/envsys.h> 64#include <sys/envsys.h>
65#include <sys/malloc.h> 65#include <sys/malloc.h>
66#include <sys/kthread.h> 66#include <sys/kthread.h>
67#include <sys/bus.h> 67#include <sys/bus.h>
68#include <sys/intr.h> 68#include <sys/intr.h>
69 69
70#include <dev/isa/isareg.h> 70#include <dev/isa/isareg.h>
71#include <dev/isa/isavar.h> 71#include <dev/isa/isavar.h>
72 72
73#include <dev/ipmivar.h> 73#include <dev/ipmivar.h>
74 74
75#include <uvm/uvm_extern.h> 75#include <uvm/uvm_extern.h>
76 76
77struct ipmi_sensor { 77struct ipmi_sensor {
78 uint8_t *i_sdr; 78 uint8_t *i_sdr;
79 int i_num; 79 int i_num;
80 int i_stype; 80 int i_stype;
81 int i_etype; 81 int i_etype;
82 char i_envdesc[64]; 82 char i_envdesc[64];
83 int i_envtype; /* envsys compatible type */ 83 int i_envtype; /* envsys compatible type */
84 int i_envnum; /* envsys index */ 84 int i_envnum; /* envsys index */
85 sysmon_envsys_lim_t i_limits, i_deflims; 85 sysmon_envsys_lim_t i_limits, i_deflims;
86 uint32_t i_props, i_defprops; 86 uint32_t i_props, i_defprops;
87 SLIST_ENTRY(ipmi_sensor) i_list; 87 SLIST_ENTRY(ipmi_sensor) i_list;
88 int32_t i_prevval; /* feed rnd source on change */ 88 int32_t i_prevval; /* feed rnd source on change */
89}; 89};
90 90
91#if 0 91#if 0
92static int ipmi_nintr; 92static int ipmi_nintr;
93#endif 93#endif
94static int ipmi_dbg = 0; 94static int ipmi_dbg = 0;
95static int ipmi_enabled = 0; 95static int ipmi_enabled = 0;
96 96
97#define SENSOR_REFRESH_RATE (hz / 2) 97#define SENSOR_REFRESH_RATE (hz / 2)
98 98
99#define IPMI_BTMSG_LEN 0 99#define IPMI_BTMSG_LEN 0
100#define IPMI_BTMSG_NFLN 1 100#define IPMI_BTMSG_NFLN 1
101#define IPMI_BTMSG_SEQ 2 101#define IPMI_BTMSG_SEQ 2
102#define IPMI_BTMSG_CMD 3 102#define IPMI_BTMSG_CMD 3
103#define IPMI_BTMSG_CCODE 4 103#define IPMI_BTMSG_CCODE 4
104#define IPMI_BTMSG_DATASND 4 104#define IPMI_BTMSG_DATASND 4
105#define IPMI_BTMSG_DATARCV 5 105#define IPMI_BTMSG_DATARCV 5
106 106
107#define IPMI_MSG_NFLN 0 107#define IPMI_MSG_NFLN 0
108#define IPMI_MSG_CMD 1 108#define IPMI_MSG_CMD 1
109#define IPMI_MSG_CCODE 2 109#define IPMI_MSG_CCODE 2
110#define IPMI_MSG_DATASND 2 110#define IPMI_MSG_DATASND 2
111#define IPMI_MSG_DATARCV 3 111#define IPMI_MSG_DATARCV 3
112 112
113#define IPMI_SENSOR_TYPE_TEMP 0x0101 113#define IPMI_SENSOR_TYPE_TEMP 0x0101
114#define IPMI_SENSOR_TYPE_VOLT 0x0102 114#define IPMI_SENSOR_TYPE_VOLT 0x0102
115#define IPMI_SENSOR_TYPE_FAN 0x0104 115#define IPMI_SENSOR_TYPE_FAN 0x0104
116#define IPMI_SENSOR_TYPE_INTRUSION 0x6F05 116#define IPMI_SENSOR_TYPE_INTRUSION 0x6F05
117#define IPMI_SENSOR_TYPE_PWRSUPPLY 0x6F08 117#define IPMI_SENSOR_TYPE_PWRSUPPLY 0x6F08
118 118
119#define IPMI_NAME_UNICODE 0x00 119#define IPMI_NAME_UNICODE 0x00
120#define IPMI_NAME_BCDPLUS 0x01 120#define IPMI_NAME_BCDPLUS 0x01
121#define IPMI_NAME_ASCII6BIT 0x02 121#define IPMI_NAME_ASCII6BIT 0x02
122#define IPMI_NAME_ASCII8BIT 0x03 122#define IPMI_NAME_ASCII8BIT 0x03
123 123
124#define IPMI_ENTITY_PWRSUPPLY 0x0A 124#define IPMI_ENTITY_PWRSUPPLY 0x0A
125 125
126#define IPMI_SENSOR_SCANNING_ENABLED (1L << 6) 126#define IPMI_SENSOR_SCANNING_ENABLED (1L << 6)
127#define IPMI_SENSOR_UNAVAILABLE (1L << 5) 127#define IPMI_SENSOR_UNAVAILABLE (1L << 5)
128#define IPMI_INVALID_SENSOR_P(x) \ 128#define IPMI_INVALID_SENSOR_P(x) \
129 (((x) & (IPMI_SENSOR_SCANNING_ENABLED|IPMI_SENSOR_UNAVAILABLE)) \ 129 (((x) & (IPMI_SENSOR_SCANNING_ENABLED|IPMI_SENSOR_UNAVAILABLE)) \
130 != IPMI_SENSOR_SCANNING_ENABLED) 130 != IPMI_SENSOR_SCANNING_ENABLED)
131 131
132#define IPMI_SDR_TYPEFULL 1 132#define IPMI_SDR_TYPEFULL 1
133#define IPMI_SDR_TYPECOMPACT 2 133#define IPMI_SDR_TYPECOMPACT 2
134 134
135#define byteof(x) ((x) >> 3) 135#define byteof(x) ((x) >> 3)
136#define bitof(x) (1L << ((x) & 0x7)) 136#define bitof(x) (1L << ((x) & 0x7))
137#define TB(b,m) (data[2+byteof(b)] & bitof(b)) 137#define TB(b,m) (data[2+byteof(b)] & bitof(b))
138 138
139#define dbg_printf(lvl, fmt...) \ 139#define dbg_printf(lvl, fmt...) \
140 if (ipmi_dbg >= lvl) \ 140 if (ipmi_dbg >= lvl) \
141 printf(fmt); 141 printf(fmt);
142#define dbg_dump(lvl, msg, len, buf) \ 142#define dbg_dump(lvl, msg, len, buf) \
143 if (len && ipmi_dbg >= lvl) \ 143 if (len && ipmi_dbg >= lvl) \
144 dumpb(msg, len, (const uint8_t *)(buf)); 144 dumpb(msg, len, (const uint8_t *)(buf));
145 145
146static long signextend(unsigned long, int); 146static long signextend(unsigned long, int);
147 147
148SLIST_HEAD(ipmi_sensors_head, ipmi_sensor); 148SLIST_HEAD(ipmi_sensors_head, ipmi_sensor);
149static struct ipmi_sensors_head ipmi_sensor_list = 149static struct ipmi_sensors_head ipmi_sensor_list =
150 SLIST_HEAD_INITIALIZER(&ipmi_sensor_list); 150 SLIST_HEAD_INITIALIZER(&ipmi_sensor_list);
151 151
152static void dumpb(const char *, int, const uint8_t *); 152static void dumpb(const char *, int, const uint8_t *);
153 153
154static int read_sensor(struct ipmi_softc *, struct ipmi_sensor *); 154static int read_sensor(struct ipmi_softc *, struct ipmi_sensor *);
155static int add_sdr_sensor(struct ipmi_softc *, uint8_t *); 155static int add_sdr_sensor(struct ipmi_softc *, uint8_t *);
156static int get_sdr_partial(struct ipmi_softc *, uint16_t, uint16_t, 156static int get_sdr_partial(struct ipmi_softc *, uint16_t, uint16_t,
157 uint8_t, uint8_t, void *, uint16_t *); 157 uint8_t, uint8_t, void *, uint16_t *);
158static int get_sdr(struct ipmi_softc *, uint16_t, uint16_t *); 158static int get_sdr(struct ipmi_softc *, uint16_t, uint16_t *);
159 159
160static char *ipmi_buf_acquire(struct ipmi_softc *, size_t); 160static char *ipmi_buf_acquire(struct ipmi_softc *, size_t);
161static void ipmi_buf_release(struct ipmi_softc *, char *); 161static void ipmi_buf_release(struct ipmi_softc *, char *);
162static int ipmi_sendcmd(struct ipmi_softc *, int, int, int, int, int, const void*); 162static int ipmi_sendcmd(struct ipmi_softc *, int, int, int, int, int, const void*);
163static int ipmi_recvcmd(struct ipmi_softc *, int, int *, void *); 163static int ipmi_recvcmd(struct ipmi_softc *, int, int *, void *);
164static void ipmi_delay(struct ipmi_softc *, int); 164static void ipmi_delay(struct ipmi_softc *, int);
165 165
166static int ipmi_watchdog_setmode(struct sysmon_wdog *); 166static int ipmi_watchdog_setmode(struct sysmon_wdog *);
167static int ipmi_watchdog_tickle(struct sysmon_wdog *); 167static int ipmi_watchdog_tickle(struct sysmon_wdog *);
168static void ipmi_dotickle(struct ipmi_softc *); 168static void ipmi_dotickle(struct ipmi_softc *);
169 169
170#if 0 170#if 0
171static int ipmi_intr(void *); 171static int ipmi_intr(void *);
172#endif 172#endif
173 173
174static int ipmi_match(device_t, cfdata_t, void *); 174static int ipmi_match(device_t, cfdata_t, void *);
175static void ipmi_attach(device_t, device_t, void *); 175static void ipmi_attach(device_t, device_t, void *);
176static int ipmi_detach(device_t, int); 176static int ipmi_detach(device_t, int);
177 177
178static long ipmi_convert(uint8_t, struct sdrtype1 *, long); 178static long ipmi_convert(uint8_t, struct sdrtype1 *, long);
179static void ipmi_sensor_name(char *, int, uint8_t, uint8_t *); 179static void ipmi_sensor_name(char *, int, uint8_t, uint8_t *);
180 180
181/* BMC Helper Functions */ 181/* BMC Helper Functions */
182static uint8_t bmc_read(struct ipmi_softc *, int); 182static uint8_t bmc_read(struct ipmi_softc *, int);
183static void bmc_write(struct ipmi_softc *, int, uint8_t); 183static void bmc_write(struct ipmi_softc *, int, uint8_t);
184static int bmc_io_wait(struct ipmi_softc *, int, uint8_t, uint8_t, const char *); 184static int bmc_io_wait(struct ipmi_softc *, int, uint8_t, uint8_t, const char *);
185static int bmc_io_wait_spin(struct ipmi_softc *, int, uint8_t, uint8_t); 185static int bmc_io_wait_spin(struct ipmi_softc *, int, uint8_t, uint8_t);
186static int bmc_io_wait_sleep(struct ipmi_softc *, int, uint8_t, uint8_t); 186static int bmc_io_wait_sleep(struct ipmi_softc *, int, uint8_t, uint8_t);
187 187
188static void *bt_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *); 188static void *bt_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *);
189static void *cmn_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *); 189static void *cmn_buildmsg(struct ipmi_softc *, int, int, int, const void *, int *);
190 190
191static int getbits(uint8_t *, int, int); 191static int getbits(uint8_t *, int, int);
192static int ipmi_sensor_type(int, int, int); 192static int ipmi_sensor_type(int, int, int);
193 193
194static void ipmi_refresh_sensors(struct ipmi_softc *); 194static void ipmi_refresh_sensors(struct ipmi_softc *);
195static int ipmi_map_regs(struct ipmi_softc *, struct ipmi_attach_args *); 195static int ipmi_map_regs(struct ipmi_softc *, struct ipmi_attach_args *);
196static void ipmi_unmap_regs(struct ipmi_softc *); 196static void ipmi_unmap_regs(struct ipmi_softc *);
197 197
198static int32_t ipmi_convert_sensor(uint8_t *, struct ipmi_sensor *); 198static int32_t ipmi_convert_sensor(uint8_t *, struct ipmi_sensor *);
199static void ipmi_set_limits(struct sysmon_envsys *, envsys_data_t *, 199static void ipmi_set_limits(struct sysmon_envsys *, envsys_data_t *,
200 sysmon_envsys_lim_t *, uint32_t *); 200 sysmon_envsys_lim_t *, uint32_t *);
201static void ipmi_get_limits(struct sysmon_envsys *, envsys_data_t *, 201static void ipmi_get_limits(struct sysmon_envsys *, envsys_data_t *,
202 sysmon_envsys_lim_t *, uint32_t *); 202 sysmon_envsys_lim_t *, uint32_t *);
203static void ipmi_get_sensor_limits(struct ipmi_softc *, struct ipmi_sensor *, 203static void ipmi_get_sensor_limits(struct ipmi_softc *, struct ipmi_sensor *,
204 sysmon_envsys_lim_t *, uint32_t *); 204 sysmon_envsys_lim_t *, uint32_t *);
205static int ipmi_sensor_status(struct ipmi_softc *, struct ipmi_sensor *, 205static int ipmi_sensor_status(struct ipmi_softc *, struct ipmi_sensor *,
206 envsys_data_t *, uint8_t *); 206 envsys_data_t *, uint8_t *);
207 207
208static int add_child_sensors(struct ipmi_softc *, uint8_t *, int, int, int, 208static int add_child_sensors(struct ipmi_softc *, uint8_t *, int, int, int,
209 int, int, int, const char *); 209 int, int, int, const char *);
210 210
211static bool ipmi_suspend(device_t, const pmf_qual_t *); 211static bool ipmi_suspend(device_t, const pmf_qual_t *);
212 212
213static int kcs_probe(struct ipmi_softc *); 213static int kcs_probe(struct ipmi_softc *);
214static int kcs_reset(struct ipmi_softc *); 214static int kcs_reset(struct ipmi_softc *);
215static int kcs_sendmsg(struct ipmi_softc *, int, const uint8_t *); 215static int kcs_sendmsg(struct ipmi_softc *, int, const uint8_t *);
216static int kcs_recvmsg(struct ipmi_softc *, int, int *len, uint8_t *); 216static int kcs_recvmsg(struct ipmi_softc *, int, int *len, uint8_t *);
217 217
218static int bt_probe(struct ipmi_softc *); 218static int bt_probe(struct ipmi_softc *);
219static int bt_reset(struct ipmi_softc *); 219static int bt_reset(struct ipmi_softc *);
220static int bt_sendmsg(struct ipmi_softc *, int, const uint8_t *); 220static int bt_sendmsg(struct ipmi_softc *, int, const uint8_t *);
221static int bt_recvmsg(struct ipmi_softc *, int, int *, uint8_t *); 221static int bt_recvmsg(struct ipmi_softc *, int, int *, uint8_t *);
222 222
223static int smic_probe(struct ipmi_softc *); 223static int smic_probe(struct ipmi_softc *);
224static int smic_reset(struct ipmi_softc *); 224static int smic_reset(struct ipmi_softc *);
225static int smic_sendmsg(struct ipmi_softc *, int, const uint8_t *); 225static int smic_sendmsg(struct ipmi_softc *, int, const uint8_t *);
226static int smic_recvmsg(struct ipmi_softc *, int, int *, uint8_t *); 226static int smic_recvmsg(struct ipmi_softc *, int, int *, uint8_t *);
227 227
228static struct ipmi_if kcs_if = { 228static struct ipmi_if kcs_if = {
229 "KCS", 229 "KCS",
230 IPMI_IF_KCS_NREGS, 230 IPMI_IF_KCS_NREGS,
231 cmn_buildmsg, 231 cmn_buildmsg,
232 kcs_sendmsg, 232 kcs_sendmsg,
233 kcs_recvmsg, 233 kcs_recvmsg,
234 kcs_reset, 234 kcs_reset,
235 kcs_probe, 235 kcs_probe,
236}; 236};
237 237
238static struct ipmi_if smic_if = { 238static struct ipmi_if smic_if = {
239 "SMIC", 239 "SMIC",
240 IPMI_IF_SMIC_NREGS, 240 IPMI_IF_SMIC_NREGS,
241 cmn_buildmsg, 241 cmn_buildmsg,
242 smic_sendmsg, 242 smic_sendmsg,
243 smic_recvmsg, 243 smic_recvmsg,
244 smic_reset, 244 smic_reset,
245 smic_probe, 245 smic_probe,
246}; 246};
247 247
248static struct ipmi_if bt_if = { 248static struct ipmi_if bt_if = {
249 "BT", 249 "BT",
250 IPMI_IF_BT_NREGS, 250 IPMI_IF_BT_NREGS,
251 bt_buildmsg, 251 bt_buildmsg,
252 bt_sendmsg, 252 bt_sendmsg,
253 bt_recvmsg, 253 bt_recvmsg,
254 bt_reset, 254 bt_reset,
255 bt_probe, 255 bt_probe,
256}; 256};
257 257
258static struct ipmi_if *ipmi_get_if(int); 258static struct ipmi_if *ipmi_get_if(int);
259 259
260static struct ipmi_if * 260static struct ipmi_if *
261ipmi_get_if(int iftype) 261ipmi_get_if(int iftype)
262{ 262{
263 switch (iftype) { 263 switch (iftype) {
264 case IPMI_IF_KCS: 264 case IPMI_IF_KCS:
265 return &kcs_if; 265 return &kcs_if;
266 case IPMI_IF_SMIC: 266 case IPMI_IF_SMIC:
267 return &smic_if; 267 return &smic_if;
268 case IPMI_IF_BT: 268 case IPMI_IF_BT:
269 return &bt_if; 269 return &bt_if;
270 default: 270 default:
271 return NULL; 271 return NULL;
272 } 272 }
273} 273}
274 274
275/* 275/*
276 * BMC Helper Functions 276 * BMC Helper Functions
277 */ 277 */
278static uint8_t 278static uint8_t
279bmc_read(struct ipmi_softc *sc, int offset) 279bmc_read(struct ipmi_softc *sc, int offset)
280{ 280{
281 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, 281 return bus_space_read_1(sc->sc_iot, sc->sc_ioh,
282 offset * sc->sc_if_iospacing); 282 offset * sc->sc_if_iospacing);
283} 283}
284 284
285static void 285static void
286bmc_write(struct ipmi_softc *sc, int offset, uint8_t val) 286bmc_write(struct ipmi_softc *sc, int offset, uint8_t val)
287{ 287{
288 bus_space_write_1(sc->sc_iot, sc->sc_ioh, 288 bus_space_write_1(sc->sc_iot, sc->sc_ioh,
289 offset * sc->sc_if_iospacing, val); 289 offset * sc->sc_if_iospacing, val);
290} 290}
291 291
292static int 292static int
293bmc_io_wait_sleep(struct ipmi_softc *sc, int offset, uint8_t mask, 293bmc_io_wait_sleep(struct ipmi_softc *sc, int offset, uint8_t mask,
294 uint8_t value) 294 uint8_t value)
295{ 295{
296 int retries; 296 int retries;
297 uint8_t v; 297 uint8_t v;
298 298
299 KASSERT(mutex_owned(&sc->sc_cmd_mtx)); 299 KASSERT(mutex_owned(&sc->sc_cmd_mtx));
300 300
301 for (retries = 0; retries < sc->sc_max_retries; retries++) { 301 for (retries = 0; retries < sc->sc_max_retries; retries++) {
302 v = bmc_read(sc, offset); 302 v = bmc_read(sc, offset);
303 if ((v & mask) == value) 303 if ((v & mask) == value)
304 return v; 304 return v;
305 mutex_enter(&sc->sc_sleep_mtx); 305 mutex_enter(&sc->sc_sleep_mtx);
306 cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_sleep_mtx, 1); 306 cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_sleep_mtx, 1);
307 mutex_exit(&sc->sc_sleep_mtx); 307 mutex_exit(&sc->sc_sleep_mtx);
308 } 308 }
309 return -1; 309 return -1;
310} 310}
311 311
312static int 312static int
313bmc_io_wait(struct ipmi_softc *sc, int offset, uint8_t mask, uint8_t value, 313bmc_io_wait(struct ipmi_softc *sc, int offset, uint8_t mask, uint8_t value,
314 const char *lbl) 314 const char *lbl)
315{ 315{
316 int v; 316 int v;
317 317
318 v = bmc_io_wait_spin(sc, offset, mask, value); 318 v = bmc_io_wait_spin(sc, offset, mask, value);
319 if (cold || v != -1) 319 if (cold || v != -1)
320 return v; 320 return v;
321 321
322 return bmc_io_wait_sleep(sc, offset, mask, value); 322 return bmc_io_wait_sleep(sc, offset, mask, value);
323} 323}
324 324
325static int 325static int
326bmc_io_wait_spin(struct ipmi_softc *sc, int offset, uint8_t mask, 326bmc_io_wait_spin(struct ipmi_softc *sc, int offset, uint8_t mask,
327 uint8_t value) 327 uint8_t value)
328{ 328{
329 uint8_t v; 329 uint8_t v;
330 int count = cold ? 15000 : 500; 330 int count = cold ? 15000 : 500;
331 /* ~us */ 331 /* ~us */
332 332
333 while (count--) { 333 while (count--) {
334 v = bmc_read(sc, offset); 334 v = bmc_read(sc, offset);
335 if ((v & mask) == value) 335 if ((v & mask) == value)
336 return v; 336 return v;
337 337
338 delay(1); 338 delay(1);
339 } 339 }
340 340
341 return -1; 341 return -1;
342 342
343} 343}
344 344
345#define NETFN_LUN(nf,ln) (((nf) << 2) | ((ln) & 0x3)) 345#define NETFN_LUN(nf,ln) (((nf) << 2) | ((ln) & 0x3))
346 346
347/* 347/*
348 * BT interface 348 * BT interface
349 */ 349 */
350#define _BT_CTRL_REG 0 350#define _BT_CTRL_REG 0
351#define BT_CLR_WR_PTR (1L << 0) 351#define BT_CLR_WR_PTR (1L << 0)
352#define BT_CLR_RD_PTR (1L << 1) 352#define BT_CLR_RD_PTR (1L << 1)
353#define BT_HOST2BMC_ATN (1L << 2) 353#define BT_HOST2BMC_ATN (1L << 2)
354#define BT_BMC2HOST_ATN (1L << 3) 354#define BT_BMC2HOST_ATN (1L << 3)
355#define BT_EVT_ATN (1L << 4) 355#define BT_EVT_ATN (1L << 4)
356#define BT_HOST_BUSY (1L << 6) 356#define BT_HOST_BUSY (1L << 6)
357#define BT_BMC_BUSY (1L << 7) 357#define BT_BMC_BUSY (1L << 7)
358 358
359#define BT_READY (BT_HOST_BUSY|BT_HOST2BMC_ATN|BT_BMC2HOST_ATN) 359#define BT_READY (BT_HOST_BUSY|BT_HOST2BMC_ATN|BT_BMC2HOST_ATN)
360 360
361#define _BT_DATAIN_REG 1 361#define _BT_DATAIN_REG 1
362#define _BT_DATAOUT_REG 1 362#define _BT_DATAOUT_REG 1
363 363
364#define _BT_INTMASK_REG 2 364#define _BT_INTMASK_REG 2
365#define BT_IM_HIRQ_PEND (1L << 1) 365#define BT_IM_HIRQ_PEND (1L << 1)
366#define BT_IM_SCI_EN (1L << 2) 366#define BT_IM_SCI_EN (1L << 2)
367#define BT_IM_SMI_EN (1L << 3) 367#define BT_IM_SMI_EN (1L << 3)
368#define BT_IM_NMI2SMI (1L << 4) 368#define BT_IM_NMI2SMI (1L << 4)
369 369
370static int bt_read(struct ipmi_softc *, int); 370static int bt_read(struct ipmi_softc *, int);
371static int bt_write(struct ipmi_softc *, int, uint8_t); 371static int bt_write(struct ipmi_softc *, int, uint8_t);
372 372
373static int 373static int
374bt_read(struct ipmi_softc *sc, int reg) 374bt_read(struct ipmi_softc *sc, int reg)
375{ 375{
376 return bmc_read(sc, reg); 376 return bmc_read(sc, reg);
377} 377}
378 378
379static int 379static int
380bt_write(struct ipmi_softc *sc, int reg, uint8_t data) 380bt_write(struct ipmi_softc *sc, int reg, uint8_t data)
381{ 381{
382 if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC_BUSY, 0, __func__) < 0) 382 if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC_BUSY, 0, __func__) < 0)
383 return -1; 383 return -1;
384 384
385 bmc_write(sc, reg, data); 385 bmc_write(sc, reg, data);
386 return 0; 386 return 0;
387} 387}
388 388
389static int 389static int
390bt_sendmsg(struct ipmi_softc *sc, int len, const uint8_t *data) 390bt_sendmsg(struct ipmi_softc *sc, int len, const uint8_t *data)
391{ 391{
392 int i; 392 int i;
393 393
394 bt_write(sc, _BT_CTRL_REG, BT_CLR_WR_PTR); 394 bt_write(sc, _BT_CTRL_REG, BT_CLR_WR_PTR);
395 for (i = 0; i < len; i++) 395 for (i = 0; i < len; i++)
396 bt_write(sc, _BT_DATAOUT_REG, data[i]); 396 bt_write(sc, _BT_DATAOUT_REG, data[i]);
397 397
398 bt_write(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN); 398 bt_write(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN);
399 if (bmc_io_wait(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN | BT_BMC_BUSY, 0, 399 if (bmc_io_wait(sc, _BT_CTRL_REG, BT_HOST2BMC_ATN | BT_BMC_BUSY, 0,
400 __func__) < 0) 400 __func__) < 0)
401 return -1; 401 return -1;
402 402
403 return 0; 403 return 0;
404} 404}
405 405
406static int 406static int
407bt_recvmsg(struct ipmi_softc *sc, int maxlen, int *rxlen, uint8_t *data) 407bt_recvmsg(struct ipmi_softc *sc, int maxlen, int *rxlen, uint8_t *data)
408{ 408{
409 uint8_t len, v, i; 409 uint8_t len, v, i;
410 410
411 if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN, BT_BMC2HOST_ATN, 411 if (bmc_io_wait(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN, BT_BMC2HOST_ATN,
412 __func__) < 0) 412 __func__) < 0)
413 return -1; 413 return -1;
414 414
415 bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY); 415 bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY);
416 bt_write(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN); 416 bt_write(sc, _BT_CTRL_REG, BT_BMC2HOST_ATN);
417 bt_write(sc, _BT_CTRL_REG, BT_CLR_RD_PTR); 417 bt_write(sc, _BT_CTRL_REG, BT_CLR_RD_PTR);
418 len = bt_read(sc, _BT_DATAIN_REG); 418 len = bt_read(sc, _BT_DATAIN_REG);
419 for (i = IPMI_BTMSG_NFLN; i <= len; i++) { 419 for (i = IPMI_BTMSG_NFLN; i <= len; i++) {
420 v = bt_read(sc, _BT_DATAIN_REG); 420 v = bt_read(sc, _BT_DATAIN_REG);
421 if (i != IPMI_BTMSG_SEQ) 421 if (i != IPMI_BTMSG_SEQ)
422 *(data++) = v; 422 *(data++) = v;
423 } 423 }
424 bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY); 424 bt_write(sc, _BT_CTRL_REG, BT_HOST_BUSY);
425 *rxlen = len - 1; 425 *rxlen = len - 1;
426 426
427 return 0; 427 return 0;
428} 428}
429 429
430static int 430static int
431bt_reset(struct ipmi_softc *sc) 431bt_reset(struct ipmi_softc *sc)
432{ 432{
433 return -1; 433 return -1;
434} 434}
435 435
436static int 436static int
437bt_probe(struct ipmi_softc *sc) 437bt_probe(struct ipmi_softc *sc)
438{ 438{
439 uint8_t rv; 439 uint8_t rv;
440 440
441 rv = bmc_read(sc, _BT_CTRL_REG); 441 rv = bmc_read(sc, _BT_CTRL_REG);
442 rv &= BT_HOST_BUSY; 442 rv &= BT_HOST_BUSY;
443 rv |= BT_CLR_WR_PTR|BT_CLR_RD_PTR|BT_BMC2HOST_ATN|BT_HOST2BMC_ATN; 443 rv |= BT_CLR_WR_PTR|BT_CLR_RD_PTR|BT_BMC2HOST_ATN|BT_HOST2BMC_ATN;
444 bmc_write(sc, _BT_CTRL_REG, rv); 444 bmc_write(sc, _BT_CTRL_REG, rv);
445 445
446 rv = bmc_read(sc, _BT_INTMASK_REG); 446 rv = bmc_read(sc, _BT_INTMASK_REG);
447 rv &= BT_IM_SCI_EN|BT_IM_SMI_EN|BT_IM_NMI2SMI; 447 rv &= BT_IM_SCI_EN|BT_IM_SMI_EN|BT_IM_NMI2SMI;
448 rv |= BT_IM_HIRQ_PEND; 448 rv |= BT_IM_HIRQ_PEND;
449 bmc_write(sc, _BT_INTMASK_REG, rv); 449 bmc_write(sc, _BT_INTMASK_REG, rv);
450 450
451#if 0 451#if 0
452 printf("%s: %2x\n", __func__, v); 452 printf("%s: %2x\n", __func__, v);
453 printf(" WR : %2x\n", v & BT_CLR_WR_PTR); 453 printf(" WR : %2x\n", v & BT_CLR_WR_PTR);
454 printf(" RD : %2x\n", v & BT_CLR_RD_PTR); 454 printf(" RD : %2x\n", v & BT_CLR_RD_PTR);
455 printf(" H2B : %2x\n", v & BT_HOST2BMC_ATN); 455 printf(" H2B : %2x\n", v & BT_HOST2BMC_ATN);
456 printf(" B2H : %2x\n", v & BT_BMC2HOST_ATN); 456 printf(" B2H : %2x\n", v & BT_BMC2HOST_ATN);
457 printf(" EVT : %2x\n", v & BT_EVT_ATN); 457 printf(" EVT : %2x\n", v & BT_EVT_ATN);
458 printf(" HBSY : %2x\n", v & BT_HOST_BUSY); 458 printf(" HBSY : %2x\n", v & BT_HOST_BUSY);
459 printf(" BBSY : %2x\n", v & BT_BMC_BUSY); 459 printf(" BBSY : %2x\n", v & BT_BMC_BUSY);
460#endif 460#endif
461 return 0; 461 return 0;
462} 462}
463 463
464/* 464/*
465 * SMIC interface 465 * SMIC interface
466 */ 466 */
467#define _SMIC_DATAIN_REG 0 467#define _SMIC_DATAIN_REG 0
468#define _SMIC_DATAOUT_REG 0 468#define _SMIC_DATAOUT_REG 0
469 469
470#define _SMIC_CTRL_REG 1 470#define _SMIC_CTRL_REG 1
471#define SMS_CC_GET_STATUS 0x40 471#define SMS_CC_GET_STATUS 0x40
472#define SMS_CC_START_TRANSFER 0x41 472#define SMS_CC_START_TRANSFER 0x41
473#define SMS_CC_NEXT_TRANSFER 0x42 473#define SMS_CC_NEXT_TRANSFER 0x42
474#define SMS_CC_END_TRANSFER 0x43 474#define SMS_CC_END_TRANSFER 0x43
475#define SMS_CC_START_RECEIVE 0x44 475#define SMS_CC_START_RECEIVE 0x44
476#define SMS_CC_NEXT_RECEIVE 0x45 476#define SMS_CC_NEXT_RECEIVE 0x45
477#define SMS_CC_END_RECEIVE 0x46 477#define SMS_CC_END_RECEIVE 0x46
478#define SMS_CC_TRANSFER_ABORT 0x47 478#define SMS_CC_TRANSFER_ABORT 0x47
479 479
480#define SMS_SC_READY 0xc0 480#define SMS_SC_READY 0xc0
481#define SMS_SC_WRITE_START 0xc1 481#define SMS_SC_WRITE_START 0xc1
482#define SMS_SC_WRITE_NEXT 0xc2 482#define SMS_SC_WRITE_NEXT 0xc2
483#define SMS_SC_WRITE_END 0xc3 483#define SMS_SC_WRITE_END 0xc3
484#define SMS_SC_READ_START 0xc4 484#define SMS_SC_READ_START 0xc4
485#define SMS_SC_READ_NEXT 0xc5 485#define SMS_SC_READ_NEXT 0xc5
486#define SMS_SC_READ_END 0xc6 486#define SMS_SC_READ_END 0xc6
487 487
488#define _SMIC_FLAG_REG 2 488#define _SMIC_FLAG_REG 2
489#define SMIC_BUSY (1L << 0) 489#define SMIC_BUSY (1L << 0)
490#define SMIC_SMS_ATN (1L << 2) 490#define SMIC_SMS_ATN (1L << 2)
491#define SMIC_EVT_ATN (1L << 3) 491#define SMIC_EVT_ATN (1L << 3)
492#define SMIC_SMI (1L << 4) 492#define SMIC_SMI (1L << 4)
493#define SMIC_TX_DATA_RDY (1L << 6) 493#define SMIC_TX_DATA_RDY (1L << 6)
494#define SMIC_RX_DATA_RDY (1L << 7) 494#define SMIC_RX_DATA_RDY (1L << 7)
495 495
496static int smic_wait(struct ipmi_softc *, uint8_t, uint8_t, const char *); 496static int smic_wait(struct ipmi_softc *, uint8_t, uint8_t, const char *);
497static int smic_write_cmd_data(struct ipmi_softc *, uint8_t, const uint8_t *); 497static int smic_write_cmd_data(struct ipmi_softc *, uint8_t, const uint8_t *);
498static int smic_read_data(struct ipmi_softc *, uint8_t *); 498static int smic_read_data(struct ipmi_softc *, uint8_t *);
499 499
500static int 500static int
501smic_wait(struct ipmi_softc *sc, uint8_t mask, uint8_t val, const char *lbl) 501smic_wait(struct ipmi_softc *sc, uint8_t mask, uint8_t val, const char *lbl)
502{ 502{
503 int v; 503 int v;
504 504
505 /* Wait for expected flag bits */ 505 /* Wait for expected flag bits */
506 v = bmc_io_wait(sc, _SMIC_FLAG_REG, mask, val, __func__); 506 v = bmc_io_wait(sc, _SMIC_FLAG_REG, mask, val, __func__);
507 if (v < 0) 507 if (v < 0)
508 return -1; 508 return -1;
509 509
510 /* Return current status */ 510 /* Return current status */
511 v = bmc_read(sc, _SMIC_CTRL_REG); 511 v = bmc_read(sc, _SMIC_CTRL_REG);
512 dbg_printf(99, "%s(%s) = %#.2x\n", __func__, lbl, v); 512 dbg_printf(99, "%s(%s) = %#.2x\n", __func__, lbl, v);
513 return v; 513 return v;
514} 514}
515 515
516static int 516static int
517smic_write_cmd_data(struct ipmi_softc *sc, uint8_t cmd, const uint8_t *data) 517smic_write_cmd_data(struct ipmi_softc *sc, uint8_t cmd, const uint8_t *data)
518{ 518{
519 int sts, v; 519 int sts, v;
520 520
521 dbg_printf(50, "%s: %#.2x %#.2x\n", __func__, cmd, data ? *data : -1); 521 dbg_printf(50, "%s: %#.2x %#.2x\n", __func__, cmd, data ? *data : -1);
522 sts = smic_wait(sc, SMIC_TX_DATA_RDY | SMIC_BUSY, SMIC_TX_DATA_RDY, 522 sts = smic_wait(sc, SMIC_TX_DATA_RDY | SMIC_BUSY, SMIC_TX_DATA_RDY,
523 "smic_write_cmd_data ready"); 523 "smic_write_cmd_data ready");
524 if (sts < 0) 524 if (sts < 0)
525 return sts; 525 return sts;
526 526
527 bmc_write(sc, _SMIC_CTRL_REG, cmd); 527 bmc_write(sc, _SMIC_CTRL_REG, cmd);
528 if (data) 528 if (data)
529 bmc_write(sc, _SMIC_DATAOUT_REG, *data); 529 bmc_write(sc, _SMIC_DATAOUT_REG, *data);
530 530
531 /* Toggle BUSY bit, then wait for busy bit to clear */ 531 /* Toggle BUSY bit, then wait for busy bit to clear */
532 v = bmc_read(sc, _SMIC_FLAG_REG); 532 v = bmc_read(sc, _SMIC_FLAG_REG);
533 bmc_write(sc, _SMIC_FLAG_REG, v | SMIC_BUSY); 533 bmc_write(sc, _SMIC_FLAG_REG, v | SMIC_BUSY);
534 534
535 return smic_wait(sc, SMIC_BUSY, 0, __func__); 535 return smic_wait(sc, SMIC_BUSY, 0, __func__);
536} 536}
537 537
538static int 538static int
539smic_read_data(struct ipmi_softc *sc, uint8_t *data) 539smic_read_data(struct ipmi_softc *sc, uint8_t *data)
540{ 540{
541 int sts; 541 int sts;
542 542
543 sts = smic_wait(sc, SMIC_RX_DATA_RDY | SMIC_BUSY, SMIC_RX_DATA_RDY, 543 sts = smic_wait(sc, SMIC_RX_DATA_RDY | SMIC_BUSY, SMIC_RX_DATA_RDY,
544 __func__); 544 __func__);
545 if (sts >= 0) { 545 if (sts >= 0) {
546 *data = bmc_read(sc, _SMIC_DATAIN_REG); 546 *data = bmc_read(sc, _SMIC_DATAIN_REG);
547 dbg_printf(50, "%s: %#.2x\n", __func__, *data); 547 dbg_printf(50, "%s: %#.2x\n", __func__, *data);
548 } 548 }
549 return sts; 549 return sts;
550} 550}
551 551
552#define ErrStat(a, ...) if (a) printf(__VA_ARGS__); 552#define ErrStat(a, ...) if (a) printf(__VA_ARGS__);
553 553
554static int 554static int
555smic_sendmsg(struct ipmi_softc *sc, int len, const uint8_t *data) 555smic_sendmsg(struct ipmi_softc *sc, int len, const uint8_t *data)
556{ 556{
557 int sts, idx; 557 int sts, idx;
558 558
559 sts = smic_write_cmd_data(sc, SMS_CC_START_TRANSFER, &data[0]); 559 sts = smic_write_cmd_data(sc, SMS_CC_START_TRANSFER, &data[0]);
560 ErrStat(sts != SMS_SC_WRITE_START, "%s: wstart", __func__); 560 ErrStat(sts != SMS_SC_WRITE_START, "%s: wstart", __func__);
561 for (idx = 1; idx < len - 1; idx++) { 561 for (idx = 1; idx < len - 1; idx++) {
562 sts = smic_write_cmd_data(sc, SMS_CC_NEXT_TRANSFER, 562 sts = smic_write_cmd_data(sc, SMS_CC_NEXT_TRANSFER,
563 &data[idx]); 563 &data[idx]);
564 ErrStat(sts != SMS_SC_WRITE_NEXT, "%s: write", __func__); 564 ErrStat(sts != SMS_SC_WRITE_NEXT, "%s: write", __func__);
565 } 565 }
566 sts = smic_write_cmd_data(sc, SMS_CC_END_TRANSFER, &data[idx]); 566 sts = smic_write_cmd_data(sc, SMS_CC_END_TRANSFER, &data[idx]);
567 if (sts != SMS_SC_WRITE_END) { 567 if (sts != SMS_SC_WRITE_END) {
568 dbg_printf(50, "%s: %d/%d = %#.2x\n", __func__, idx, len, sts); 568 dbg_printf(50, "%s: %d/%d = %#.2x\n", __func__, idx, len, sts);
569 return -1; 569 return -1;
570 } 570 }
571 571
572 return 0; 572 return 0;
573} 573}
574 574
575static int 575static int
576smic_recvmsg(struct ipmi_softc *sc, int maxlen, int *len, uint8_t *data) 576smic_recvmsg(struct ipmi_softc *sc, int maxlen, int *len, uint8_t *data)
577{ 577{
578 int sts, idx; 578 int sts, idx;
579 579
580 *len = 0; 580 *len = 0;
581 sts = smic_wait(sc, SMIC_RX_DATA_RDY, SMIC_RX_DATA_RDY, __func__); 581 sts = smic_wait(sc, SMIC_RX_DATA_RDY, SMIC_RX_DATA_RDY, __func__);
582 if (sts < 0) 582 if (sts < 0)
583 return -1; 583 return -1;
584 584
585 sts = smic_write_cmd_data(sc, SMS_CC_START_RECEIVE, NULL); 585 sts = smic_write_cmd_data(sc, SMS_CC_START_RECEIVE, NULL);
586 ErrStat(sts != SMS_SC_READ_START, "%s: rstart", __func__); 586 ErrStat(sts != SMS_SC_READ_START, "%s: rstart", __func__);
587 for (idx = 0;; ) { 587 for (idx = 0;; ) {
588 sts = smic_read_data(sc, &data[idx++]); 588 sts = smic_read_data(sc, &data[idx++]);
589 if (sts != SMS_SC_READ_START && sts != SMS_SC_READ_NEXT) 589 if (sts != SMS_SC_READ_START && sts != SMS_SC_READ_NEXT)
590 break; 590 break;
591 smic_write_cmd_data(sc, SMS_CC_NEXT_RECEIVE, NULL); 591 smic_write_cmd_data(sc, SMS_CC_NEXT_RECEIVE, NULL);
592 } 592 }
593 ErrStat(sts != SMS_SC_READ_END, "%s: rend", __func__); 593 ErrStat(sts != SMS_SC_READ_END, "%s: rend", __func__);
594 594
595 *len = idx; 595 *len = idx;
596 596
597 sts = smic_write_cmd_data(sc, SMS_CC_END_RECEIVE, NULL); 597 sts = smic_write_cmd_data(sc, SMS_CC_END_RECEIVE, NULL);
598 if (sts != SMS_SC_READY) { 598 if (sts != SMS_SC_READY) {
599 dbg_printf(50, "%s: %d/%d = %#.2x\n", 599 dbg_printf(50, "%s: %d/%d = %#.2x\n",
600 __func__, idx, maxlen, sts); 600 __func__, idx, maxlen, sts);
601 return -1; 601 return -1;
602 } 602 }
603 603
604 return 0; 604 return 0;
605} 605}
606 606
607static int 607static int
608smic_reset(struct ipmi_softc *sc) 608smic_reset(struct ipmi_softc *sc)
609{ 609{
610 return -1; 610 return -1;
611} 611}
612 612
613static int 613static int
614smic_probe(struct ipmi_softc *sc) 614smic_probe(struct ipmi_softc *sc)
615{ 615{
616 /* Flag register should not be 0xFF on a good system */ 616 /* Flag register should not be 0xFF on a good system */
617 if (bmc_read(sc, _SMIC_FLAG_REG) == 0xFF) 617 if (bmc_read(sc, _SMIC_FLAG_REG) == 0xFF)
618 return -1; 618 return -1;
619 619
620 return 0; 620 return 0;
621} 621}
622 622
623/* 623/*
624 * KCS interface 624 * KCS interface
625 */ 625 */
626#define _KCS_DATAIN_REGISTER 0 626#define _KCS_DATAIN_REGISTER 0
627#define _KCS_DATAOUT_REGISTER 0 627#define _KCS_DATAOUT_REGISTER 0
628#define KCS_READ_NEXT 0x68 628#define KCS_READ_NEXT 0x68
629 629
630#define _KCS_COMMAND_REGISTER 1 630#define _KCS_COMMAND_REGISTER 1
631#define KCS_GET_STATUS 0x60 631#define KCS_GET_STATUS 0x60
632#define KCS_WRITE_START 0x61 632#define KCS_WRITE_START 0x61
633#define KCS_WRITE_END 0x62 633#define KCS_WRITE_END 0x62
634 634
635#define _KCS_STATUS_REGISTER 1 635#define _KCS_STATUS_REGISTER 1
636#define KCS_OBF (1L << 0) 636#define KCS_OBF (1L << 0)
637#define KCS_IBF (1L << 1) 637#define KCS_IBF (1L << 1)
638#define KCS_SMS_ATN (1L << 2) 638#define KCS_SMS_ATN (1L << 2)
639#define KCS_CD (1L << 3) 639#define KCS_CD (1L << 3)
640#define KCS_OEM1 (1L << 4) 640#define KCS_OEM1 (1L << 4)
641#define KCS_OEM2 (1L << 5) 641#define KCS_OEM2 (1L << 5)
642#define KCS_STATE_MASK 0xc0 642#define KCS_STATE_MASK 0xc0
643#define KCS_IDLE_STATE 0x00 643#define KCS_IDLE_STATE 0x00
644#define KCS_READ_STATE 0x40 644#define KCS_READ_STATE 0x40
645#define KCS_WRITE_STATE 0x80 645#define KCS_WRITE_STATE 0x80
646#define KCS_ERROR_STATE 0xC0 646#define KCS_ERROR_STATE 0xC0
647 647
648static int kcs_wait(struct ipmi_softc *, uint8_t, uint8_t, const char *); 648static int kcs_wait(struct ipmi_softc *, uint8_t, uint8_t, const char *);
649static int kcs_write_cmd(struct ipmi_softc *, uint8_t); 649static int kcs_write_cmd(struct ipmi_softc *, uint8_t);
650static int kcs_write_data(struct ipmi_softc *, uint8_t); 650static int kcs_write_data(struct ipmi_softc *, uint8_t);
651static int kcs_read_data(struct ipmi_softc *, uint8_t *); 651static int kcs_read_data(struct ipmi_softc *, uint8_t *);
652 652
653static int 653static int
654kcs_wait(struct ipmi_softc *sc, uint8_t mask, uint8_t value, const char *lbl) 654kcs_wait(struct ipmi_softc *sc, uint8_t mask, uint8_t value, const char *lbl)
655{ 655{
656 int v; 656 int v;
657 657
658 v = bmc_io_wait(sc, _KCS_STATUS_REGISTER, mask, value, lbl); 658 v = bmc_io_wait(sc, _KCS_STATUS_REGISTER, mask, value, lbl);
659 if (v < 0) 659 if (v < 0)
660 return v; 660 return v;
661 661
662 /* Check if output buffer full, read dummy byte */ 662 /* Check if output buffer full, read dummy byte */
663 if ((v & (KCS_OBF | KCS_STATE_MASK)) == (KCS_OBF | KCS_WRITE_STATE)) 663 if ((v & (KCS_OBF | KCS_STATE_MASK)) == (KCS_OBF | KCS_WRITE_STATE))
664 bmc_read(sc, _KCS_DATAIN_REGISTER); 664 bmc_read(sc, _KCS_DATAIN_REGISTER);
665 665
666 /* Check for error state */ 666 /* Check for error state */
667 if ((v & KCS_STATE_MASK) == KCS_ERROR_STATE) { 667 if ((v & KCS_STATE_MASK) == KCS_ERROR_STATE) {
668 bmc_write(sc, _KCS_COMMAND_REGISTER, KCS_GET_STATUS); 668 bmc_write(sc, _KCS_COMMAND_REGISTER, KCS_GET_STATUS);
669 while (bmc_read(sc, _KCS_STATUS_REGISTER) & KCS_IBF) 669 while (bmc_read(sc, _KCS_STATUS_REGISTER) & KCS_IBF)
670 ; 670 ;
671 aprint_error_dev(sc->sc_dev, "error code: %#x\n", 671 aprint_error_dev(sc->sc_dev, "error code: %#x\n",
672 bmc_read(sc, _KCS_DATAIN_REGISTER)); 672 bmc_read(sc, _KCS_DATAIN_REGISTER));
673 } 673 }
674 674
675 return v & KCS_STATE_MASK; 675 return v & KCS_STATE_MASK;
676} 676}
677 677
678static int 678static int
679kcs_write_cmd(struct ipmi_softc *sc, uint8_t cmd) 679kcs_write_cmd(struct ipmi_softc *sc, uint8_t cmd)
680{ 680{
681 /* ASSERT: IBF and OBF are clear */ 681 /* ASSERT: IBF and OBF are clear */
682 dbg_printf(50, "%s: %#.2x\n", __func__, cmd); 682 dbg_printf(50, "%s: %#.2x\n", __func__, cmd);
683 bmc_write(sc, _KCS_COMMAND_REGISTER, cmd); 683 bmc_write(sc, _KCS_COMMAND_REGISTER, cmd);
684 684
685 return kcs_wait(sc, KCS_IBF, 0, "write_cmd"); 685 return kcs_wait(sc, KCS_IBF, 0, "write_cmd");
686} 686}
687 687
688static int 688static int
689kcs_write_data(struct ipmi_softc *sc, uint8_t data) 689kcs_write_data(struct ipmi_softc *sc, uint8_t data)
690{ 690{
691 /* ASSERT: IBF and OBF are clear */ 691 /* ASSERT: IBF and OBF are clear */
692 dbg_printf(50, "%s: %#.2x\n", __func__, data); 692 dbg_printf(50, "%s: %#.2x\n", __func__, data);
693 bmc_write(sc, _KCS_DATAOUT_REGISTER, data); 693 bmc_write(sc, _KCS_DATAOUT_REGISTER, data);
694 694
695 return kcs_wait(sc, KCS_IBF, 0, "write_data"); 695 return kcs_wait(sc, KCS_IBF, 0, "write_data");
696} 696}
697 697
698static int 698static int
699kcs_read_data(struct ipmi_softc *sc, uint8_t * data) 699kcs_read_data(struct ipmi_softc *sc, uint8_t * data)
700{ 700{
701 int sts; 701 int sts;
702 702
703 sts = kcs_wait(sc, KCS_IBF | KCS_OBF, KCS_OBF, __func__); 703 sts = kcs_wait(sc, KCS_IBF | KCS_OBF, KCS_OBF, __func__);
704 if (sts != KCS_READ_STATE) 704 if (sts != KCS_READ_STATE)
705 return sts; 705 return sts;
706 706
707 /* ASSERT: OBF is set read data, request next byte */ 707 /* ASSERT: OBF is set read data, request next byte */
708 *data = bmc_read(sc, _KCS_DATAIN_REGISTER); 708 *data = bmc_read(sc, _KCS_DATAIN_REGISTER);
709 bmc_write(sc, _KCS_DATAOUT_REGISTER, KCS_READ_NEXT); 709 bmc_write(sc, _KCS_DATAOUT_REGISTER, KCS_READ_NEXT);
710 710
711 dbg_printf(50, "%s: %#.2x\n", __func__, *data); 711 dbg_printf(50, "%s: %#.2x\n", __func__, *data);
712 712
713 return sts; 713 return sts;
714} 714}
715 715
716/* Exported KCS functions */ 716/* Exported KCS functions */
717static int 717static int
718kcs_sendmsg(struct ipmi_softc *sc, int len, const uint8_t * data) 718kcs_sendmsg(struct ipmi_softc *sc, int len, const uint8_t * data)
719{ 719{
720 int idx, sts; 720 int idx, sts;
721 721
722 /* ASSERT: IBF is clear */ 722 /* ASSERT: IBF is clear */
723 dbg_dump(50, __func__, len, data); 723 dbg_dump(50, __func__, len, data);
724 sts = kcs_write_cmd(sc, KCS_WRITE_START); 724 sts = kcs_write_cmd(sc, KCS_WRITE_START);
725 for (idx = 0; idx < len; idx++) { 725 for (idx = 0; idx < len; idx++) {
726 if (idx == len - 1) 726 if (idx == len - 1)
727 sts = kcs_write_cmd(sc, KCS_WRITE_END); 727 sts = kcs_write_cmd(sc, KCS_WRITE_END);
728 728
729 if (sts != KCS_WRITE_STATE) 729 if (sts != KCS_WRITE_STATE)
730 break; 730 break;
731 731
732 sts = kcs_write_data(sc, data[idx]); 732 sts = kcs_write_data(sc, data[idx]);
733 } 733 }
734 if (sts != KCS_READ_STATE) { 734 if (sts != KCS_READ_STATE) {
735 dbg_printf(1, "%s: %d/%d <%#.2x>\n", __func__, idx, len, sts); 735 dbg_printf(1, "%s: %d/%d <%#.2x>\n", __func__, idx, len, sts);
736 dbg_dump(1, __func__, len, data); 736 dbg_dump(1, __func__, len, data);
737 return -1; 737 return -1;
738 } 738 }
739 739
740 return 0; 740 return 0;
741} 741}
742 742
743static int 743static int
744kcs_recvmsg(struct ipmi_softc *sc, int maxlen, int *rxlen, uint8_t * data) 744kcs_recvmsg(struct ipmi_softc *sc, int maxlen, int *rxlen, uint8_t * data)
745{ 745{
746 int idx, sts; 746 int idx, sts;
747 747
748 for (idx = 0; idx < maxlen; idx++) { 748 for (idx = 0; idx < maxlen; idx++) {
749 sts = kcs_read_data(sc, &data[idx]); 749 sts = kcs_read_data(sc, &data[idx]);
750 if (sts != KCS_READ_STATE) 750 if (sts != KCS_READ_STATE)
751 break; 751 break;
752 } 752 }
753 sts = kcs_wait(sc, KCS_IBF, 0, __func__); 753 sts = kcs_wait(sc, KCS_IBF, 0, __func__);
754 *rxlen = idx; 754 *rxlen = idx;
755 if (sts != KCS_IDLE_STATE) { 755 if (sts != KCS_IDLE_STATE) {
756 dbg_printf(1, "%s: %d/%d <%#.2x>\n", 756 dbg_printf(1, "%s: %d/%d <%#.2x>\n",
757 __func__, idx, maxlen, sts); 757 __func__, idx, maxlen, sts);
758 return -1; 758 return -1;
759 } 759 }
760 760
761 dbg_dump(50, __func__, idx, data); 761 dbg_dump(50, __func__, idx, data);
762 762
763 return 0; 763 return 0;
764} 764}
765 765
766static int 766static int
767kcs_reset(struct ipmi_softc *sc) 767kcs_reset(struct ipmi_softc *sc)
768{ 768{
769 return -1; 769 return -1;
770} 770}
771 771
772static int 772static int
773kcs_probe(struct ipmi_softc *sc) 773kcs_probe(struct ipmi_softc *sc)
774{ 774{
775 uint8_t v; 775 uint8_t v;
776 776
777 v = bmc_read(sc, _KCS_STATUS_REGISTER); 777 v = bmc_read(sc, _KCS_STATUS_REGISTER);
778#if 0 778#if 0
779 printf("%s: %2x\n", __func__, v); 779 printf("%s: %2x\n", __func__, v);
780 printf(" STS: %2x\n", v & KCS_STATE_MASK); 780 printf(" STS: %2x\n", v & KCS_STATE_MASK);
781 printf(" ATN: %2x\n", v & KCS_SMS_ATN); 781 printf(" ATN: %2x\n", v & KCS_SMS_ATN);
782 printf(" C/D: %2x\n", v & KCS_CD); 782 printf(" C/D: %2x\n", v & KCS_CD);
783 printf(" IBF: %2x\n", v & KCS_IBF); 783 printf(" IBF: %2x\n", v & KCS_IBF);
784 printf(" OBF: %2x\n", v & KCS_OBF); 784 printf(" OBF: %2x\n", v & KCS_OBF);
785#else 785#else
786 __USE(v); 786 __USE(v);
787#endif 787#endif
788 return 0; 788 return 0;
789} 789}
790 790
791/* 791/*
792 * IPMI code 792 * IPMI code
793 */ 793 */
794#define READ_SMS_BUFFER 0x37 794#define READ_SMS_BUFFER 0x37
795#define WRITE_I2C 0x50 795#define WRITE_I2C 0x50
796 796
797#define GET_MESSAGE_CMD 0x33 797#define GET_MESSAGE_CMD 0x33
798#define SEND_MESSAGE_CMD 0x34 798#define SEND_MESSAGE_CMD 0x34
799 799
800#define IPMB_CHANNEL_NUMBER 0 800#define IPMB_CHANNEL_NUMBER 0
801 801
802#define PUBLIC_BUS 0 802#define PUBLIC_BUS 0
803 803
804#define MIN_I2C_PACKET_SIZE 3 804#define MIN_I2C_PACKET_SIZE 3
805#define MIN_IMB_PACKET_SIZE 7 /* one byte for cksum */ 805#define MIN_IMB_PACKET_SIZE 7 /* one byte for cksum */
806 806
807#define MIN_BTBMC_REQ_SIZE 4 807#define MIN_BTBMC_REQ_SIZE 4
808#define MIN_BTBMC_RSP_SIZE 5 808#define MIN_BTBMC_RSP_SIZE 5
809#define MIN_BMC_REQ_SIZE 2 809#define MIN_BMC_REQ_SIZE 2
810#define MIN_BMC_RSP_SIZE 3 810#define MIN_BMC_RSP_SIZE 3
811 811
812#define BMC_SA 0x20 /* BMC/ESM3 */ 812#define BMC_SA 0x20 /* BMC/ESM3 */
813#define FPC_SA 0x22 /* front panel */ 813#define FPC_SA 0x22 /* front panel */
814#define BP_SA 0xC0 /* Primary Backplane */ 814#define BP_SA 0xC0 /* Primary Backplane */
815#define BP2_SA 0xC2 /* Secondary Backplane */ 815#define BP2_SA 0xC2 /* Secondary Backplane */
816#define PBP_SA 0xC4 /* Peripheral Backplane */ 816#define PBP_SA 0xC4 /* Peripheral Backplane */
817#define DRAC_SA 0x28 /* DRAC-III */ 817#define DRAC_SA 0x28 /* DRAC-III */
818#define DRAC3_SA 0x30 /* DRAC-III */ 818#define DRAC3_SA 0x30 /* DRAC-III */
819#define BMC_LUN 0 819#define BMC_LUN 0
820#define SMS_LUN 2 820#define SMS_LUN 2
821 821
822struct ipmi_request { 822struct ipmi_request {
823 uint8_t rsSa; 823 uint8_t rsSa;
824 uint8_t rsLun; 824 uint8_t rsLun;
825 uint8_t netFn; 825 uint8_t netFn;
826 uint8_t cmd; 826 uint8_t cmd;
827 uint8_t data_len; 827 uint8_t data_len;
828 uint8_t *data; 828 uint8_t *data;
829}; 829};
830 830
831struct ipmi_response { 831struct ipmi_response {
832 uint8_t cCode; 832 uint8_t cCode;
833 uint8_t data_len; 833 uint8_t data_len;
834 uint8_t *data; 834 uint8_t *data;
835}; 835};
836 836
837struct ipmi_bmc_request { 837struct ipmi_bmc_request {
838 uint8_t bmc_nfLn; 838 uint8_t bmc_nfLn;
839 uint8_t bmc_cmd; 839 uint8_t bmc_cmd;
840 uint8_t bmc_data_len; 840 uint8_t bmc_data_len;
841 uint8_t bmc_data[1]; 841 uint8_t bmc_data[1];
842}; 842};
843 843
844struct ipmi_bmc_response { 844struct ipmi_bmc_response {
845 uint8_t bmc_nfLn; 845 uint8_t bmc_nfLn;
846 uint8_t bmc_cmd; 846 uint8_t bmc_cmd;
847 uint8_t bmc_cCode; 847 uint8_t bmc_cCode;
848 uint8_t bmc_data_len; 848 uint8_t bmc_data_len;
849 uint8_t bmc_data[1]; 849 uint8_t bmc_data[1];
850}; 850};
851 851
852 852
853CFATTACH_DECL2_NEW(ipmi, sizeof(struct ipmi_softc), 853CFATTACH_DECL2_NEW(ipmi, sizeof(struct ipmi_softc),
854 ipmi_match, ipmi_attach, ipmi_detach, NULL, NULL, NULL); 854 ipmi_match, ipmi_attach, ipmi_detach, NULL, NULL, NULL);
855 855
856static void 856static void
857dumpb(const char *lbl, int len, const uint8_t *data) 857dumpb(const char *lbl, int len, const uint8_t *data)
858{ 858{
859 int idx; 859 int idx;
860 860
861 printf("%s: ", lbl); 861 printf("%s: ", lbl);
862 for (idx = 0; idx < len; idx++) 862 for (idx = 0; idx < len; idx++)
863 printf("%.2x ", data[idx]); 863 printf("%.2x ", data[idx]);
864 864
865 printf("\n"); 865 printf("\n");
866} 866}
867 867
868/* 868/*
869 * bt_buildmsg builds an IPMI message from a nfLun, cmd, and data 869 * bt_buildmsg builds an IPMI message from a nfLun, cmd, and data
870 * This is used by BT protocol 870 * This is used by BT protocol
871 * 871 *
872 * Returns a buffer to an allocated message, txlen contains length 872 * Returns a buffer to an allocated message, txlen contains length
873 * of allocated message 873 * of allocated message
874 */ 874 */
875static void * 875static void *
876bt_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len, 876bt_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len,
877 const void *data, int *txlen) 877 const void *data, int *txlen)
878{ 878{
879 uint8_t *buf; 879 uint8_t *buf;
880 880
881 /* Block transfer needs 4 extra bytes: length/netfn/seq/cmd + data */ 881 /* Block transfer needs 4 extra bytes: length/netfn/seq/cmd + data */
882 *txlen = len + 4; 882 *txlen = len + 4;
883 buf = ipmi_buf_acquire(sc, *txlen); 883 buf = ipmi_buf_acquire(sc, *txlen);
884 if (buf == NULL) 884 if (buf == NULL)
885 return NULL; 885 return NULL;
886 886
887 buf[IPMI_BTMSG_LEN] = len + 3; 887 buf[IPMI_BTMSG_LEN] = len + 3;
888 buf[IPMI_BTMSG_NFLN] = nfLun; 888 buf[IPMI_BTMSG_NFLN] = nfLun;
889 buf[IPMI_BTMSG_SEQ] = sc->sc_btseq++; 889 buf[IPMI_BTMSG_SEQ] = sc->sc_btseq++;
890 buf[IPMI_BTMSG_CMD] = cmd; 890 buf[IPMI_BTMSG_CMD] = cmd;
891 if (len && data) 891 if (len && data)
892 memcpy(buf + IPMI_BTMSG_DATASND, data, len); 892 memcpy(buf + IPMI_BTMSG_DATASND, data, len);
893 893
894 return buf; 894 return buf;
895} 895}
896 896
897/* 897/*
898 * cmn_buildmsg builds an IPMI message from a nfLun, cmd, and data 898 * cmn_buildmsg builds an IPMI message from a nfLun, cmd, and data
899 * This is used by both SMIC and KCS protocols 899 * This is used by both SMIC and KCS protocols
900 * 900 *
901 * Returns a buffer to an allocated message, txlen contains length 901 * Returns a buffer to an allocated message, txlen contains length
902 * of allocated message 902 * of allocated message
903 */ 903 */
904static void * 904static void *
905cmn_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len, 905cmn_buildmsg(struct ipmi_softc *sc, int nfLun, int cmd, int len,
906 const void *data, int *txlen) 906 const void *data, int *txlen)
907{ 907{
908 uint8_t *buf; 908 uint8_t *buf;
909 909
910 /* Common needs two extra bytes: nfLun/cmd + data */ 910 /* Common needs two extra bytes: nfLun/cmd + data */
911 *txlen = len + 2; 911 *txlen = len + 2;
912 buf = ipmi_buf_acquire(sc, *txlen); 912 buf = ipmi_buf_acquire(sc, *txlen);
913 if (buf == NULL) 913 if (buf == NULL)
914 return NULL; 914 return NULL;
915 915
916 buf[IPMI_MSG_NFLN] = nfLun; 916 buf[IPMI_MSG_NFLN] = nfLun;
917 buf[IPMI_MSG_CMD] = cmd; 917 buf[IPMI_MSG_CMD] = cmd;
918 if (len && data) 918 if (len && data)
919 memcpy(buf + IPMI_MSG_DATASND, data, len); 919 memcpy(buf + IPMI_MSG_DATASND, data, len);
920 920
921 return buf; 921 return buf;
922} 922}
923 923
924/* 924/*
925 * ipmi_sendcmd: caller must hold sc_cmd_mtx. 925 * ipmi_sendcmd: caller must hold sc_cmd_mtx.
926 * 926 *
927 * Send an IPMI command 927 * Send an IPMI command
928 */ 928 */
929static int 929static int
930ipmi_sendcmd(struct ipmi_softc *sc, int rssa, int rslun, int netfn, int cmd, 930ipmi_sendcmd(struct ipmi_softc *sc, int rssa, int rslun, int netfn, int cmd,
931 int txlen, const void *data) 931 int txlen, const void *data)
932{ 932{
933 uint8_t *buf; 933 uint8_t *buf;
934 int rc = -1; 934 int rc = -1;
935 935
936 dbg_printf(50, "%s: rssa=%#.2x nfln=%#.2x cmd=%#.2x len=%#.2x\n", 936 dbg_printf(50, "%s: rssa=%#.2x nfln=%#.2x cmd=%#.2x len=%#.2x\n",
937 __func__, rssa, NETFN_LUN(netfn, rslun), cmd, txlen); 937 __func__, rssa, NETFN_LUN(netfn, rslun), cmd, txlen);
938 dbg_dump(10, __func__, txlen, data); 938 dbg_dump(10, __func__, txlen, data);
939 if (rssa != BMC_SA) { 939 if (rssa != BMC_SA) {
940#if 0 940#if 0
941 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(APP_NETFN, BMC_LUN), 941 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(APP_NETFN, BMC_LUN),
942 APP_SEND_MESSAGE, 7 + txlen, NULL, &txlen); 942 APP_SEND_MESSAGE, 7 + txlen, NULL, &txlen);
943 pI2C->bus = (sc->if_ver == 0x09) ? 943 pI2C->bus = (sc->if_ver == 0x09) ?
944 PUBLIC_BUS : 944 PUBLIC_BUS :
945 IPMB_CHANNEL_NUMBER; 945 IPMB_CHANNEL_NUMBER;
946 946
947 imbreq->rsSa = rssa; 947 imbreq->rsSa = rssa;
948 imbreq->nfLn = NETFN_LUN(netfn, rslun); 948 imbreq->nfLn = NETFN_LUN(netfn, rslun);
949 imbreq->cSum1 = -(imbreq->rsSa + imbreq->nfLn); 949 imbreq->cSum1 = -(imbreq->rsSa + imbreq->nfLn);
950 imbreq->rqSa = BMC_SA; 950 imbreq->rqSa = BMC_SA;
951 imbreq->seqLn = NETFN_LUN(sc->imb_seq++, SMS_LUN); 951 imbreq->seqLn = NETFN_LUN(sc->imb_seq++, SMS_LUN);
952 imbreq->cmd = cmd; 952 imbreq->cmd = cmd;
953 if (txlen) 953 if (txlen)
954 memcpy(imbreq->data, data, txlen); 954 memcpy(imbreq->data, data, txlen);
955 /* Set message checksum */ 955 /* Set message checksum */
956 imbreq->data[txlen] = cksum8(&imbreq->rqSa, txlen + 3); 956 imbreq->data[txlen] = cksum8(&imbreq->rqSa, txlen + 3);
957#endif 957#endif
958 goto done; 958 goto done;
959 } else 959 } else
960 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(netfn, rslun), cmd, 960 buf = sc->sc_if->buildmsg(sc, NETFN_LUN(netfn, rslun), cmd,
961 txlen, data, &txlen); 961 txlen, data, &txlen);
962 962
963 if (buf == NULL) { 963 if (buf == NULL) {
964 aprint_error_dev(sc->sc_dev, "sendcmd buffer busy\n"); 964 aprint_error_dev(sc->sc_dev, "sendcmd buffer busy\n");
965 goto done; 965 goto done;
966 } 966 }
967 rc = sc->sc_if->sendmsg(sc, txlen, buf); 967 rc = sc->sc_if->sendmsg(sc, txlen, buf);
968 ipmi_buf_release(sc, buf); 968 ipmi_buf_release(sc, buf);
969 969
970 ipmi_delay(sc, 50); /* give bmc chance to digest command */ 970 ipmi_delay(sc, 50); /* give bmc chance to digest command */
971 971
972done: 972done:
973 return rc; 973 return rc;
974} 974}
975 975
976static void 976static void
977ipmi_buf_release(struct ipmi_softc *sc, char *buf) 977ipmi_buf_release(struct ipmi_softc *sc, char *buf)
978{ 978{
979 KASSERT(sc->sc_buf_rsvd); 979 KASSERT(sc->sc_buf_rsvd);
980 KASSERT(sc->sc_buf == buf); 980 KASSERT(sc->sc_buf == buf);
981 sc->sc_buf_rsvd = false; 981 sc->sc_buf_rsvd = false;
982} 982}
983 983
984static char * 984static char *
985ipmi_buf_acquire(struct ipmi_softc *sc, size_t len) 985ipmi_buf_acquire(struct ipmi_softc *sc, size_t len)
986{ 986{
987 KASSERT(len <= sizeof(sc->sc_buf)); 987 KASSERT(len <= sizeof(sc->sc_buf));
988 988
989 if (sc->sc_buf_rsvd || len > sizeof(sc->sc_buf)) 989 if (sc->sc_buf_rsvd || len > sizeof(sc->sc_buf))
990 return NULL; 990 return NULL;
991 sc->sc_buf_rsvd = true; 991 sc->sc_buf_rsvd = true;
992 return sc->sc_buf; 992 return sc->sc_buf;
993} 993}
994 994
995/* 995/*
996 * ipmi_recvcmd: caller must hold sc_cmd_mtx. 996 * ipmi_recvcmd: caller must hold sc_cmd_mtx.
997 */ 997 */
998static int 998static int
999ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data) 999ipmi_recvcmd(struct ipmi_softc *sc, int maxlen, int *rxlen, void *data)
1000{ 1000{
1001 uint8_t *buf, rc = 0; 1001 uint8_t *buf, rc = 0;
1002 int rawlen; 1002 int rawlen;
1003 1003
1004 /* Need three extra bytes: netfn/cmd/ccode + data */ 1004 /* Need three extra bytes: netfn/cmd/ccode + data */
1005 buf = ipmi_buf_acquire(sc, maxlen + 3); 1005 buf = ipmi_buf_acquire(sc, maxlen + 3);
1006 if (buf == NULL) { 1006 if (buf == NULL) {
1007 aprint_error_dev(sc->sc_dev, "%s: malloc fails\n", __func__); 1007 aprint_error_dev(sc->sc_dev, "%s: malloc fails\n", __func__);
1008 return -1; 1008 return -1;
1009 } 1009 }
1010 /* Receive message from interface, copy out result data */ 1010 /* Receive message from interface, copy out result data */
1011 if (sc->sc_if->recvmsg(sc, maxlen + 3, &rawlen, buf)) { 1011 if (sc->sc_if->recvmsg(sc, maxlen + 3, &rawlen, buf)) {
1012 ipmi_buf_release(sc, buf); 1012 ipmi_buf_release(sc, buf);
1013 return -1; 1013 return -1;
1014 } 1014 }
1015 1015
1016 *rxlen = rawlen - IPMI_MSG_DATARCV; 1016 *rxlen = rawlen - IPMI_MSG_DATARCV;
1017 if (*rxlen > 0 && data) 1017 if (*rxlen > 0 && data)
1018 memcpy(data, buf + IPMI_MSG_DATARCV, *rxlen); 1018 memcpy(data, buf + IPMI_MSG_DATARCV, *rxlen);
1019 1019
1020 if ((rc = buf[IPMI_MSG_CCODE]) != 0) 1020 if ((rc = buf[IPMI_MSG_CCODE]) != 0)
1021 dbg_printf(1, "%s: nfln=%#.2x cmd=%#.2x err=%#.2x\n", __func__, 1021 dbg_printf(1, "%s: nfln=%#.2x cmd=%#.2x err=%#.2x\n", __func__,
1022 buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE]); 1022 buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], buf[IPMI_MSG_CCODE]);
1023 1023
1024 dbg_printf(50, "%s: nfln=%#.2x cmd=%#.2x err=%#.2x len=%#.2x\n", 1024 dbg_printf(50, "%s: nfln=%#.2x cmd=%#.2x err=%#.2x len=%#.2x\n",
1025 __func__, buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD], 1025 __func__, buf[IPMI_MSG_NFLN], buf[IPMI_MSG_CMD],
1026 buf[IPMI_MSG_CCODE], *rxlen); 1026 buf[IPMI_MSG_CCODE], *rxlen);
1027 dbg_dump(10, __func__, *rxlen, data); 1027 dbg_dump(10, __func__, *rxlen, data);
1028 1028
1029 ipmi_buf_release(sc, buf); 1029 ipmi_buf_release(sc, buf);
1030 1030
1031 return rc; 1031 return rc;
1032} 1032}
1033 1033
1034/* 1034/*
1035 * ipmi_delay: caller must hold sc_cmd_mtx. 1035 * ipmi_delay: caller must hold sc_cmd_mtx.
1036 */ 1036 */
1037static void 1037static void
1038ipmi_delay(struct ipmi_softc *sc, int ms) 1038ipmi_delay(struct ipmi_softc *sc, int ms)
1039{ 1039{
1040 if (cold) { 1040 if (cold) {
1041 delay(ms * 1000); 1041 delay(ms * 1000);
1042 return; 1042 return;
1043 } 1043 }
1044 mutex_enter(&sc->sc_sleep_mtx); 1044 mutex_enter(&sc->sc_sleep_mtx);
1045 cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_sleep_mtx, mstohz(ms)); 1045 cv_timedwait(&sc->sc_cmd_sleep, &sc->sc_sleep_mtx, mstohz(ms));
1046 mutex_exit(&sc->sc_sleep_mtx); 1046 mutex_exit(&sc->sc_sleep_mtx);
1047} 1047}
1048 1048
1049/* Read a partial SDR entry */ 1049/* Read a partial SDR entry */
1050static int 1050static int
1051get_sdr_partial(struct ipmi_softc *sc, uint16_t recordId, uint16_t reserveId, 1051get_sdr_partial(struct ipmi_softc *sc, uint16_t recordId, uint16_t reserveId,
1052 uint8_t offset, uint8_t length, void *buffer, uint16_t *nxtRecordId) 1052 uint8_t offset, uint8_t length, void *buffer, uint16_t *nxtRecordId)
1053{ 1053{
1054 uint8_t cmd[256 + 8]; 1054 uint8_t cmd[256 + 8];
1055 int len; 1055 int len;
1056 1056
1057 ((uint16_t *) cmd)[0] = reserveId; 1057 ((uint16_t *) cmd)[0] = reserveId;
1058 ((uint16_t *) cmd)[1] = recordId; 1058 ((uint16_t *) cmd)[1] = recordId;
1059 cmd[4] = offset; 1059 cmd[4] = offset;
1060 cmd[5] = length; 1060 cmd[5] = length;
1061 mutex_enter(&sc->sc_cmd_mtx); 1061 mutex_enter(&sc->sc_cmd_mtx);
1062 if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_GET_SDR, 6, 1062 if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_GET_SDR, 6,
1063 cmd)) { 1063 cmd)) {
1064 mutex_exit(&sc->sc_cmd_mtx); 1064 mutex_exit(&sc->sc_cmd_mtx);
1065 aprint_error_dev(sc->sc_dev, "%s: sendcmd fails\n", __func__); 1065 aprint_error_dev(sc->sc_dev, "%s: sendcmd fails\n", __func__);
1066 return -1; 1066 return -1;
1067 } 1067 }
1068 if (ipmi_recvcmd(sc, 8 + length, &len, cmd)) { 1068 if (ipmi_recvcmd(sc, 8 + length, &len, cmd)) {
1069 mutex_exit(&sc->sc_cmd_mtx); 1069 mutex_exit(&sc->sc_cmd_mtx);
1070 aprint_error_dev(sc->sc_dev, "%s: recvcmd fails\n", __func__); 1070 aprint_error_dev(sc->sc_dev, "%s: recvcmd fails\n", __func__);
1071 return -1; 1071 return -1;
1072 } 1072 }
1073 mutex_exit(&sc->sc_cmd_mtx); 1073 mutex_exit(&sc->sc_cmd_mtx);
1074 if (nxtRecordId) 1074 if (nxtRecordId)
1075 *nxtRecordId = *(uint16_t *) cmd; 1075 *nxtRecordId = *(uint16_t *) cmd;
1076 memcpy(buffer, cmd + 2, len - 2); 1076 memcpy(buffer, cmd + 2, len - 2);
1077 1077
1078 return 0; 1078 return 0;
1079} 1079}
1080 1080
1081static int maxsdrlen = 0x10; 1081static int maxsdrlen = 0x10;
1082 1082
1083/* Read an entire SDR; pass to add sensor */ 1083/* Read an entire SDR; pass to add sensor */
1084static int 1084static int
1085get_sdr(struct ipmi_softc *sc, uint16_t recid, uint16_t *nxtrec) 1085get_sdr(struct ipmi_softc *sc, uint16_t recid, uint16_t *nxtrec)
1086{ 1086{
1087 uint16_t resid = 0; 1087 uint16_t resid = 0;
1088 int len, sdrlen, offset; 1088 int len, sdrlen, offset;
1089 uint8_t *psdr; 1089 uint8_t *psdr;
1090 struct sdrhdr shdr; 1090 struct sdrhdr shdr;
1091 1091
1092 mutex_enter(&sc->sc_cmd_mtx); 1092 mutex_enter(&sc->sc_cmd_mtx);
1093 /* Reserve SDR */ 1093 /* Reserve SDR */
1094 if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_RESERVE_SDR, 1094 if (ipmi_sendcmd(sc, BMC_SA, 0, STORAGE_NETFN, STORAGE_RESERVE_SDR,
1095 0, NULL)) { 1095 0, NULL)) {
1096 mutex_exit(&sc->sc_cmd_mtx); 1096 mutex_exit(&sc->sc_cmd_mtx);
1097 aprint_error_dev(sc->sc_dev, "reserve send fails\n"); 1097 aprint_error_dev(sc->sc_dev, "reserve send fails\n");
1098 return -1; 1098 return -1;
1099 } 1099 }
1100 if (ipmi_recvcmd(sc, sizeof(resid), &len, &resid)) { 1100 if (ipmi_recvcmd(sc, sizeof(resid), &len, &resid)) {
1101 mutex_exit(&sc->sc_cmd_mtx); 1101 mutex_exit(&sc->sc_cmd_mtx);
1102 aprint_error_dev(sc->sc_dev, "reserve recv fails\n"); 1102 aprint_error_dev(sc->sc_dev, "reserve recv fails\n");
1103 return -1; 1103 return -1;
1104 } 1104 }
1105 mutex_exit(&sc->sc_cmd_mtx); 1105 mutex_exit(&sc->sc_cmd_mtx);
1106 /* Get SDR Header */ 1106 /* Get SDR Header */
1107 if (get_sdr_partial(sc, recid, resid, 0, sizeof shdr, &shdr, nxtrec)) { 1107 if (get_sdr_partial(sc, recid, resid, 0, sizeof shdr, &shdr, nxtrec)) {
1108 aprint_error_dev(sc->sc_dev, "get header fails\n"); 1108 aprint_error_dev(sc->sc_dev, "get header fails\n");
1109 return -1; 1109 return -1;
1110 } 1110 }
1111 /* Allocate space for entire SDR Length of SDR in header does not 1111 /* Allocate space for entire SDR Length of SDR in header does not
1112 * include header length */ 1112 * include header length */
1113 sdrlen = sizeof(shdr) + shdr.record_length; 1113 sdrlen = sizeof(shdr) + shdr.record_length;
1114 psdr = malloc(sdrlen, M_DEVBUF, M_WAITOK); 1114 psdr = malloc(sdrlen, M_DEVBUF, M_WAITOK);
1115 if (psdr == NULL) 1115 if (psdr == NULL)
1116 return -1; 1116 return -1;
1117 1117
1118 memcpy(psdr, &shdr, sizeof(shdr)); 1118 memcpy(psdr, &shdr, sizeof(shdr));
1119 1119
1120 /* Read SDR Data maxsdrlen bytes at a time */ 1120 /* Read SDR Data maxsdrlen bytes at a time */
1121 for (offset = sizeof(shdr); offset < sdrlen; offset += maxsdrlen) { 1121 for (offset = sizeof(shdr); offset < sdrlen; offset += maxsdrlen) {
1122 len = sdrlen - offset; 1122 len = sdrlen - offset;
1123 if (len > maxsdrlen) 1123 if (len > maxsdrlen)
1124 len = maxsdrlen; 1124 len = maxsdrlen;
1125 1125
1126 if (get_sdr_partial(sc, recid, resid, offset, len, 1126 if (get_sdr_partial(sc, recid, resid, offset, len,
1127 psdr + offset, NULL)) { 1127 psdr + offset, NULL)) {
1128 aprint_error_dev(sc->sc_dev, 1128 aprint_error_dev(sc->sc_dev,
1129 "get chunk : %d,%d fails\n", offset, len); 1129 "get chunk : %d,%d fails\n", offset, len);
1130 free(psdr, M_DEVBUF); 1130 free(psdr, M_DEVBUF);
1131 return -1; 1131 return -1;
1132 } 1132 }
1133 } 1133 }
1134 1134
1135 /* Add SDR to sensor list, if not wanted, free buffer */ 1135 /* Add SDR to sensor list, if not wanted, free buffer */
1136 if (add_sdr_sensor(sc, psdr) == 0) 1136 if (add_sdr_sensor(sc, psdr) == 0)
1137 free(psdr, M_DEVBUF); 1137 free(psdr, M_DEVBUF);
1138 1138
1139 return 0; 1139 return 0;
1140} 1140}
1141 1141
1142static int 1142static int
1143getbits(uint8_t *bytes, int bitpos, int bitlen) 1143getbits(uint8_t *bytes, int bitpos, int bitlen)
1144{ 1144{
1145 int v; 1145 int v;
1146 int mask; 1146 int mask;
1147 1147
1148 bitpos += bitlen - 1; 1148 bitpos += bitlen - 1;
1149 for (v = 0; bitlen--;) { 1149 for (v = 0; bitlen--;) {
1150 v <<= 1; 1150 v <<= 1;
1151 mask = 1L << (bitpos & 7); 1151 mask = 1L << (bitpos & 7);
1152 if (bytes[bitpos >> 3] & mask) 1152 if (bytes[bitpos >> 3] & mask)
1153 v |= 1; 1153 v |= 1;
1154 bitpos--; 1154 bitpos--;
1155 } 1155 }
1156 1156
1157 return v; 1157 return v;
1158} 1158}
1159 1159
1160/* Decode IPMI sensor name */ 1160/* Decode IPMI sensor name */
1161static void 1161static void
1162ipmi_sensor_name(char *name, int len, uint8_t typelen, uint8_t *bits) 1162ipmi_sensor_name(char *name, int len, uint8_t typelen, uint8_t *bits)
1163{ 1163{
1164 int i, slen; 1164 int i, slen;
1165 char bcdplus[] = "0123456789 -.:,_"; 1165 char bcdplus[] = "0123456789 -.:,_";
1166 1166
1167 slen = typelen & 0x1F; 1167 slen = typelen & 0x1F;
1168 switch (typelen >> 6) { 1168 switch (typelen >> 6) {
1169 case IPMI_NAME_UNICODE: 1169 case IPMI_NAME_UNICODE:
1170 //unicode 1170 //unicode
1171 break; 1171 break;
1172 1172
1173 case IPMI_NAME_BCDPLUS: 1173 case IPMI_NAME_BCDPLUS:
1174 /* Characters are encoded in 4-bit BCDPLUS */ 1174 /* Characters are encoded in 4-bit BCDPLUS */
1175 if (len < slen * 2 + 1) 1175 if (len < slen * 2 + 1)
1176 slen = (len >> 1) - 1; 1176 slen = (len >> 1) - 1;
1177 for (i = 0; i < slen; i++) { 1177 for (i = 0; i < slen; i++) {
1178 *(name++) = bcdplus[bits[i] >> 4]; 1178 *(name++) = bcdplus[bits[i] >> 4];
1179 *(name++) = bcdplus[bits[i] & 0xF]; 1179 *(name++) = bcdplus[bits[i] & 0xF];
1180 } 1180 }
1181 break; 1181 break;
1182 1182
1183 case IPMI_NAME_ASCII6BIT: 1183 case IPMI_NAME_ASCII6BIT:
1184 /* Characters are encoded in 6-bit ASCII 1184 /* Characters are encoded in 6-bit ASCII
1185 * 0x00 - 0x3F maps to 0x20 - 0x5F */ 1185 * 0x00 - 0x3F maps to 0x20 - 0x5F */
1186 /* XXX: need to calculate max len: slen = 3/4 * len */ 1186 /* XXX: need to calculate max len: slen = 3/4 * len */
1187 if (len < slen + 1) 1187 if (len < slen + 1)
1188 slen = len - 1; 1188 slen = len - 1;
1189 for (i = 0; i < slen * 8; i += 6) 1189 for (i = 0; i < slen * 8; i += 6)
1190 *(name++) = getbits(bits, i, 6) + ' '; 1190 *(name++) = getbits(bits, i, 6) + ' ';
1191 break; 1191 break;
1192 1192
1193 case IPMI_NAME_ASCII8BIT: 1193 case IPMI_NAME_ASCII8BIT:
1194 /* Characters are 8-bit ascii */ 1194 /* Characters are 8-bit ascii */
1195 if (len < slen + 1) 1195 if (len < slen + 1)
1196 slen = len - 1; 1196 slen = len - 1;
1197 while (slen--) 1197 while (slen--)
1198 *(name++) = *(bits++); 1198 *(name++) = *(bits++);
1199 break; 1199 break;
1200 } 1200 }
1201 *name = 0; 1201 *name = 0;
1202} 1202}
1203 1203
1204/* Sign extend a n-bit value */ 1204/* Sign extend a n-bit value */
1205static long 1205static long
1206signextend(unsigned long val, int bits) 1206signextend(unsigned long val, int bits)
1207{ 1207{
1208 long msk = (1L << (bits-1))-1; 1208 long msk = (1L << (bits-1))-1;
1209 1209
1210 return -(val & ~msk) | val; 1210 return -(val & ~msk) | val;
1211} 1211}
1212 1212
1213 1213
1214/* fixpoint arithmetic */ 1214/* fixpoint arithmetic */
1215#define FIX2INT(x) ((int64_t)((x) >> 32)) 1215#define FIX2INT(x) ((int64_t)((x) >> 32))
1216#define INT2FIX(x) ((int64_t)((uint64_t)(x) << 32)) 1216#define INT2FIX(x) ((int64_t)((uint64_t)(x) << 32))
1217 1217
1218#define FIX2 0x0000000200000000ll /* 2.0 */ 1218#define FIX2 0x0000000200000000ll /* 2.0 */
1219#define FIX3 0x0000000300000000ll /* 3.0 */ 1219#define FIX3 0x0000000300000000ll /* 3.0 */
1220#define FIXE 0x00000002b7e15163ll /* 2.71828182845904523536 */ 1220#define FIXE 0x00000002b7e15163ll /* 2.71828182845904523536 */
1221#define FIX10 0x0000000a00000000ll /* 10.0 */ 1221#define FIX10 0x0000000a00000000ll /* 10.0 */
1222#define FIXMONE 0xffffffff00000000ll /* -1.0 */ 1222#define FIXMONE 0xffffffff00000000ll /* -1.0 */
1223#define FIXHALF 0x0000000080000000ll /* 0.5 */ 1223#define FIXHALF 0x0000000080000000ll /* 0.5 */
1224#define FIXTHIRD 0x0000000055555555ll /* 0.33333333333333333333 */ 1224#define FIXTHIRD 0x0000000055555555ll /* 0.33333333333333333333 */
1225 1225
1226#define FIX1LOG2 0x0000000171547653ll /* 1.0/log(2) */ 1226#define FIX1LOG2 0x0000000171547653ll /* 1.0/log(2) */
1227#define FIX1LOGE 0x0000000100000000ll /* 1.0/log(2.71828182845904523536) */ 1227#define FIX1LOGE 0x0000000100000000ll /* 1.0/log(2.71828182845904523536) */
1228#define FIX1LOG10 0x000000006F2DEC55ll /* 1.0/log(10) */ 1228#define FIX1LOG10 0x000000006F2DEC55ll /* 1.0/log(10) */
1229 1229
1230#define FIX1E 0x000000005E2D58D9ll /* 1.0/2.71828182845904523536 */ 1230#define FIX1E 0x000000005E2D58D9ll /* 1.0/2.71828182845904523536 */
1231 1231
1232static int64_t fixlog_a[] = { 1232static int64_t fixlog_a[] = {
1233 0x0000000100000000ll /* 1.0/1.0 */, 1233 0x0000000100000000ll /* 1.0/1.0 */,
1234 0xffffffff80000000ll /* -1.0/2.0 */, 1234 0xffffffff80000000ll /* -1.0/2.0 */,
1235 0x0000000055555555ll /* 1.0/3.0 */, 1235 0x0000000055555555ll /* 1.0/3.0 */,
1236 0xffffffffc0000000ll /* -1.0/4.0 */, 1236 0xffffffffc0000000ll /* -1.0/4.0 */,
1237 0x0000000033333333ll /* 1.0/5.0 */, 1237 0x0000000033333333ll /* 1.0/5.0 */,
1238 0x000000002aaaaaabll /* -1.0/6.0 */, 1238 0x000000002aaaaaabll /* -1.0/6.0 */,
1239 0x0000000024924925ll /* 1.0/7.0 */, 1239 0x0000000024924925ll /* 1.0/7.0 */,
1240 0x0000000020000000ll /* -1.0/8.0 */, 1240 0x0000000020000000ll /* -1.0/8.0 */,
1241 0x000000001c71c71cll /* 1.0/9.0 */ 1241 0x000000001c71c71cll /* 1.0/9.0 */
1242}; 1242};
1243 1243
1244static int64_t fixexp_a[] = { 1244static int64_t fixexp_a[] = {
1245 0x0000000100000000ll /* 1.0/1.0 */, 1245 0x0000000100000000ll /* 1.0/1.0 */,
1246 0x0000000100000000ll /* 1.0/1.0 */, 1246 0x0000000100000000ll /* 1.0/1.0 */,
1247 0x0000000080000000ll /* 1.0/2.0 */, 1247 0x0000000080000000ll /* 1.0/2.0 */,
1248 0x000000002aaaaaabll /* 1.0/6.0 */, 1248 0x000000002aaaaaabll /* 1.0/6.0 */,
1249 0x000000000aaaaaabll /* 1.0/24.0 */, 1249 0x000000000aaaaaabll /* 1.0/24.0 */,
1250 0x0000000002222222ll /* 1.0/120.0 */,  1250 0x0000000002222222ll /* 1.0/120.0 */,
1251 0x00000000005b05b0ll /* 1.0/720.0 */, 1251 0x00000000005b05b0ll /* 1.0/720.0 */,
1252 0x00000000000d00d0ll /* 1.0/5040.0 */, 1252 0x00000000000d00d0ll /* 1.0/5040.0 */,
1253 0x000000000001a01all /* 1.0/40320.0 */ 1253 0x000000000001a01all /* 1.0/40320.0 */
1254}; 1254};
1255 1255
1256static int64_t 1256static int64_t
1257fixmul(int64_t x, int64_t y) 1257fixmul(int64_t x, int64_t y)
1258{ 1258{
1259 int64_t z; 1259 int64_t z;
1260 int64_t a,b,c,d; 1260 int64_t a,b,c,d;
1261 int neg; 1261 int neg;
1262 1262
1263 neg = 0; 1263 neg = 0;
1264 if (x < 0) { 1264 if (x < 0) {
1265 x = -x; 1265 x = -x;
1266 neg = !neg; 1266 neg = !neg;
1267 } 1267 }
1268 if (y < 0) {  1268 if (y < 0) {
1269 y = -y; 1269 y = -y;
1270 neg = !neg; 1270 neg = !neg;
1271 } 1271 }
1272 1272
1273 a = FIX2INT(x); 1273 a = FIX2INT(x);
1274 b = x - INT2FIX(a); 1274 b = x - INT2FIX(a);
1275 c = FIX2INT(y); 1275 c = FIX2INT(y);
1276 d = y - INT2FIX(c); 1276 d = y - INT2FIX(c);
1277 1277
1278 z = INT2FIX(a*c) + a * d + b * c + (b/2 * d/2 >> 30); 1278 z = INT2FIX(a*c) + a * d + b * c + (b/2 * d/2 >> 30);
1279 1279
1280 return neg ? -z : z; 1280 return neg ? -z : z;
1281} 1281}
1282 1282
1283static int64_t 1283static int64_t
1284poly(int64_t x0, int64_t x, int64_t a[], int n) 1284poly(int64_t x0, int64_t x, int64_t a[], int n)
1285{ 1285{
1286 int64_t z; 1286 int64_t z;
1287 int i; 1287 int i;
1288 1288
1289 z = fixmul(x0, a[0]); 1289 z = fixmul(x0, a[0]);
1290 for (i=1; i<n; ++i) { 1290 for (i=1; i<n; ++i) {
1291 x0 = fixmul(x0, x); 1291 x0 = fixmul(x0, x);
1292 z = fixmul(x0, a[i]) + z; 1292 z = fixmul(x0, a[i]) + z;
1293 } 1293 }
1294 return z; 1294 return z;
1295} 1295}
1296 1296
1297static int64_t 1297static int64_t
1298logx(int64_t x, int64_t y) 1298logx(int64_t x, int64_t y)
1299{ 1299{
1300 int64_t z; 1300 int64_t z;
1301 1301
1302 if (x <= INT2FIX(0)) { 1302 if (x <= INT2FIX(0)) {
1303 z = INT2FIX(-99999); 1303 z = INT2FIX(-99999);
1304 goto done; 1304 goto done;
1305 } 1305 }
1306 1306
1307 z = INT2FIX(0); 1307 z = INT2FIX(0);
1308 while (x >= FIXE) { 1308 while (x >= FIXE) {
1309 x = fixmul(x, FIX1E); 1309 x = fixmul(x, FIX1E);
1310 z += INT2FIX(1); 1310 z += INT2FIX(1);
1311 } 1311 }
1312 while (x < INT2FIX(1)) { 1312 while (x < INT2FIX(1)) {
1313 x = fixmul(x, FIXE); 1313 x = fixmul(x, FIXE);
1314 z -= INT2FIX(1); 1314 z -= INT2FIX(1);
1315 } 1315 }
1316 1316
1317 x -= INT2FIX(1); 1317 x -= INT2FIX(1);
1318 z += poly(x, x, fixlog_a, sizeof(fixlog_a)/sizeof(fixlog_a[0])); 1318 z += poly(x, x, fixlog_a, sizeof(fixlog_a)/sizeof(fixlog_a[0]));
1319 z = fixmul(z, y); 1319 z = fixmul(z, y);
1320 1320
1321done: 1321done:
1322 return z; 1322 return z;
1323} 1323}
1324 1324
1325static int64_t 1325static int64_t
1326powx(int64_t x, int64_t y) 1326powx(int64_t x, int64_t y)
1327{ 1327{
1328 int64_t k; 1328 int64_t k;
1329 1329
1330 if (x == INT2FIX(0)) 1330 if (x == INT2FIX(0))
1331 goto done; 1331 goto done;
1332 1332
1333 x = logx(x,y); 1333 x = logx(x,y);
1334 1334
1335 if (x < INT2FIX(0)) { 1335 if (x < INT2FIX(0)) {
1336 x = INT2FIX(0) - x; 1336 x = INT2FIX(0) - x;
1337 k = -FIX2INT(x); 1337 k = -FIX2INT(x);
1338 x = INT2FIX(-k) - x; 1338 x = INT2FIX(-k) - x;
1339 } else { 1339 } else {
1340 k = FIX2INT(x); 1340 k = FIX2INT(x);
1341 x = x - INT2FIX(k); 1341 x = x - INT2FIX(k);
1342 } 1342 }
1343 1343
1344 x = poly(INT2FIX(1), x, fixexp_a, sizeof(fixexp_a)/sizeof(fixexp_a[0])); 1344 x = poly(INT2FIX(1), x, fixexp_a, sizeof(fixexp_a)/sizeof(fixexp_a[0]));
1345 1345
1346 while (k < 0) { 1346 while (k < 0) {
1347 x = fixmul(x, FIX1E); 1347 x = fixmul(x, FIX1E);
1348 ++k; 1348 ++k;
1349 } 1349 }
1350 while (k > 0) { 1350 while (k > 0) {
1351 x = fixmul(x, FIXE); 1351 x = fixmul(x, FIXE);
1352 --k; 1352 --k;
1353 } 1353 }
1354 1354
1355done: 1355done:
1356 return x; 1356 return x;
1357} 1357}
1358 1358
1359/* Convert IPMI reading from sensor factors */ 1359/* Convert IPMI reading from sensor factors */
1360static long 1360static long
1361ipmi_convert(uint8_t v, struct sdrtype1 *s1, long adj) 1361ipmi_convert(uint8_t v, struct sdrtype1 *s1, long adj)
1362{ 1362{
1363 int64_t M, B; 1363 int64_t M, B;
1364 char K1, K2; 1364 char K1, K2;
1365 int64_t val, v1, v2, vs; 1365 int64_t val, v1, v2, vs;
1366 int sign = (s1->units1 >> 6) & 0x3; 1366 int sign = (s1->units1 >> 6) & 0x3;
1367 1367
1368 vs = (sign == 0x1 || sign == 0x2) ? (int8_t)v : v; 1368 vs = (sign == 0x1 || sign == 0x2) ? (int8_t)v : v;
1369 if ((vs < 0) && (sign == 0x1)) 1369 if ((vs < 0) && (sign == 0x1))
1370 vs++; 1370 vs++;
1371 1371
1372 /* Calculate linear reading variables */ 1372 /* Calculate linear reading variables */
1373 M = signextend((((short)(s1->m_tolerance & 0xC0)) << 2) + s1->m, 10); 1373 M = signextend((((short)(s1->m_tolerance & 0xC0)) << 2) + s1->m, 10);
1374 B = signextend((((short)(s1->b_accuracy & 0xC0)) << 2) + s1->b, 10); 1374 B = signextend((((short)(s1->b_accuracy & 0xC0)) << 2) + s1->b, 10);
1375 K1 = signextend(s1->rbexp & 0xF, 4); 1375 K1 = signextend(s1->rbexp & 0xF, 4);
1376 K2 = signextend(s1->rbexp >> 4, 4); 1376 K2 = signextend(s1->rbexp >> 4, 4);
1377 1377
1378 /* Calculate sensor reading: 1378 /* Calculate sensor reading:
1379 * y = L((M * v + (B * 10^K1)) * 10^(K2+adj) 1379 * y = L((M * v + (B * 10^K1)) * 10^(K2+adj)
1380 * 1380 *
1381 * This commutes out to: 1381 * This commutes out to:
1382 * y = L(M*v * 10^(K2+adj) + B * 10^(K1+K2+adj)); */ 1382 * y = L(M*v * 10^(K2+adj) + B * 10^(K1+K2+adj)); */
1383 v1 = powx(FIX10, INT2FIX(K2 + adj)); 1383 v1 = powx(FIX10, INT2FIX(K2 + adj));
1384 v2 = powx(FIX10, INT2FIX(K1 + K2 + adj)); 1384 v2 = powx(FIX10, INT2FIX(K1 + K2 + adj));
1385 val = M * vs * v1 + B * v2; 1385 val = M * vs * v1 + B * v2;
1386 1386
1387 /* Linearization function: y = f(x) 0 : y = x 1 : y = ln(x) 2 : y = 1387 /* Linearization function: y = f(x) 0 : y = x 1 : y = ln(x) 2 : y =
1388 * log10(x) 3 : y = log2(x) 4 : y = e^x 5 : y = 10^x 6 : y = 2^x 7 : y 1388 * log10(x) 3 : y = log2(x) 4 : y = e^x 5 : y = 10^x 6 : y = 2^x 7 : y
1389 * = 1/x 8 : y = x^2 9 : y = x^3 10 : y = square root(x) 11 : y = cube 1389 * = 1/x 8 : y = x^2 9 : y = x^3 10 : y = square root(x) 11 : y = cube
1390 * root(x) */ 1390 * root(x) */
1391 switch (s1->linear & 0x7f) { 1391 switch (s1->linear & 0x7f) {
1392 case 0: break; 1392 case 0: break;
1393 case 1: val = logx(val,FIX1LOGE); break; 1393 case 1: val = logx(val,FIX1LOGE); break;
1394 case 2: val = logx(val,FIX1LOG10); break; 1394 case 2: val = logx(val,FIX1LOG10); break;
1395 case 3: val = logx(val,FIX1LOG2); break; 1395 case 3: val = logx(val,FIX1LOG2); break;
1396 case 4: val = powx(FIXE,val); break; 1396 case 4: val = powx(FIXE,val); break;
1397 case 5: val = powx(FIX10,val); break; 1397 case 5: val = powx(FIX10,val); break;
1398 case 6: val = powx(FIX2,val); break; 1398 case 6: val = powx(FIX2,val); break;
1399 case 7: val = powx(val,FIXMONE); break; 1399 case 7: val = powx(val,FIXMONE); break;
1400 case 8: val = powx(val,FIX2); break; 1400 case 8: val = powx(val,FIX2); break;
1401 case 9: val = powx(val,FIX3); break; 1401 case 9: val = powx(val,FIX3); break;
1402 case 10: val = powx(val,FIXHALF); break; 1402 case 10: val = powx(val,FIXHALF); break;
1403 case 11: val = powx(val,FIXTHIRD); break; 1403 case 11: val = powx(val,FIXTHIRD); break;
1404 } 1404 }
1405 1405
1406 return FIX2INT(val); 1406 return FIX2INT(val);
1407} 1407}
1408 1408
1409static int32_t 1409static int32_t
1410ipmi_convert_sensor(uint8_t *reading, struct ipmi_sensor *psensor) 1410ipmi_convert_sensor(uint8_t *reading, struct ipmi_sensor *psensor)
1411{ 1411{
1412 struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr; 1412 struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr;
1413 int32_t val; 1413 int32_t val;
1414 1414
1415 switch (psensor->i_envtype) { 1415 switch (psensor->i_envtype) {
1416 case ENVSYS_STEMP: 1416 case ENVSYS_STEMP:
1417 val = ipmi_convert(reading[0], s1, 6) + 273150000; 1417 val = ipmi_convert(reading[0], s1, 6) + 273150000;
1418 break; 1418 break;
1419 1419
1420 case ENVSYS_SVOLTS_DC: 1420 case ENVSYS_SVOLTS_DC:
1421 val = ipmi_convert(reading[0], s1, 6); 1421 val = ipmi_convert(reading[0], s1, 6);
1422 break; 1422 break;
1423 1423
1424 case ENVSYS_SFANRPM: 1424 case ENVSYS_SFANRPM:
1425 val = ipmi_convert(reading[0], s1, 0); 1425 val = ipmi_convert(reading[0], s1, 0);
1426 if (((s1->units1>>3)&0x7) == 0x3) 1426 if (((s1->units1>>3)&0x7) == 0x3)
1427 val *= 60; /* RPS -> RPM */ 1427 val *= 60; /* RPS -> RPM */
1428 break; 1428 break;
1429 default: 1429 default:
1430 val = 0; 1430 val = 0;
1431 break; 1431 break;
1432 } 1432 }
1433 return val; 1433 return val;
1434} 1434}
1435 1435
1436static void 1436static void
1437ipmi_set_limits(struct sysmon_envsys *sme, envsys_data_t *edata, 1437ipmi_set_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
1438 sysmon_envsys_lim_t *limits, uint32_t *props) 1438 sysmon_envsys_lim_t *limits, uint32_t *props)
1439{ 1439{
1440 struct ipmi_sensor *ipmi_s; 1440 struct ipmi_sensor *ipmi_s;
1441 1441
1442 /* Find the ipmi_sensor corresponding to this edata */ 1442 /* Find the ipmi_sensor corresponding to this edata */
1443 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) { 1443 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) {
1444 if (ipmi_s->i_envnum == edata->sensor) { 1444 if (ipmi_s->i_envnum == edata->sensor) {
1445 if (limits == NULL) { 1445 if (limits == NULL) {
1446 limits = &ipmi_s->i_deflims; 1446 limits = &ipmi_s->i_deflims;
1447 props = &ipmi_s->i_defprops; 1447 props = &ipmi_s->i_defprops;
1448 } 1448 }
1449 *props |= PROP_DRIVER_LIMITS; 1449 *props |= PROP_DRIVER_LIMITS;
1450 ipmi_s->i_limits = *limits; 1450 ipmi_s->i_limits = *limits;
1451 ipmi_s->i_props = *props; 1451 ipmi_s->i_props = *props;
1452 return; 1452 return;
1453 } 1453 }
1454 } 1454 }
1455 return; 1455 return;
1456} 1456}
1457 1457
1458static void 1458static void
1459ipmi_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata, 1459ipmi_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
1460 sysmon_envsys_lim_t *limits, uint32_t *props) 1460 sysmon_envsys_lim_t *limits, uint32_t *props)
1461{ 1461{
1462 struct ipmi_sensor *ipmi_s; 1462 struct ipmi_sensor *ipmi_s;
1463 struct ipmi_softc *sc = sme->sme_cookie; 1463 struct ipmi_softc *sc = sme->sme_cookie;
1464 1464
1465 /* Find the ipmi_sensor corresponding to this edata */ 1465 /* Find the ipmi_sensor corresponding to this edata */
1466 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) { 1466 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) {
1467 if (ipmi_s->i_envnum == edata->sensor) { 1467 if (ipmi_s->i_envnum == edata->sensor) {
1468 ipmi_get_sensor_limits(sc, ipmi_s, limits, props); 1468 ipmi_get_sensor_limits(sc, ipmi_s, limits, props);
1469 ipmi_s->i_limits = *limits; 1469 ipmi_s->i_limits = *limits;
1470 ipmi_s->i_props = *props; 1470 ipmi_s->i_props = *props;
1471 if (ipmi_s->i_defprops == 0) { 1471 if (ipmi_s->i_defprops == 0) {
1472 ipmi_s->i_defprops = *props; 1472 ipmi_s->i_defprops = *props;
1473 ipmi_s->i_deflims = *limits; 1473 ipmi_s->i_deflims = *limits;
1474 } 1474 }
1475 return; 1475 return;
1476 } 1476 }
1477 } 1477 }
1478 return; 1478 return;
1479} 1479}
1480 1480
1481static void 1481static void
1482ipmi_get_sensor_limits(struct ipmi_softc *sc, struct ipmi_sensor *psensor, 1482ipmi_get_sensor_limits(struct ipmi_softc *sc, struct ipmi_sensor *psensor,
1483 sysmon_envsys_lim_t *limits, uint32_t *props) 1483 sysmon_envsys_lim_t *limits, uint32_t *props)
1484{ 1484{
1485 struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr; 1485 struct sdrtype1 *s1 = (struct sdrtype1 *)psensor->i_sdr;
1486 bool failure; 1486 bool failure;
1487 int rxlen; 1487 int rxlen;
1488 uint8_t data[32]; 1488 uint8_t data[32];
1489 uint32_t prop_critmax, prop_warnmax, prop_critmin, prop_warnmin; 1489 uint32_t prop_critmax, prop_warnmax, prop_critmin, prop_warnmin;
1490 int32_t *pcritmax, *pwarnmax, *pcritmin, *pwarnmin; 1490 int32_t *pcritmax, *pwarnmax, *pcritmin, *pwarnmin;
1491 1491
1492 *props &= ~(PROP_CRITMIN | PROP_CRITMAX | PROP_WARNMIN | PROP_WARNMAX); 1492 *props &= ~(PROP_CRITMIN | PROP_CRITMAX | PROP_WARNMIN | PROP_WARNMAX);
1493 data[0] = psensor->i_num; 1493 data[0] = psensor->i_num;
1494 mutex_enter(&sc->sc_cmd_mtx); 1494 mutex_enter(&sc->sc_cmd_mtx);
1495 failure = 1495 failure =
1496 ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, 1496 ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun,
1497 SE_NETFN, SE_GET_SENSOR_THRESHOLD, 1, data) || 1497 SE_NETFN, SE_GET_SENSOR_THRESHOLD, 1, data) ||
1498 ipmi_recvcmd(sc, sizeof(data), &rxlen, data); 1498 ipmi_recvcmd(sc, sizeof(data), &rxlen, data);
1499 mutex_exit(&sc->sc_cmd_mtx); 1499 mutex_exit(&sc->sc_cmd_mtx);
1500 if (failure) 1500 if (failure)
1501 return; 1501 return;
1502 1502
1503 dbg_printf(25, "%s: %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x\n", 1503 dbg_printf(25, "%s: %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x %#.2x\n",
1504 __func__, data[0], data[1], data[2], data[3], data[4], data[5], 1504 __func__, data[0], data[1], data[2], data[3], data[4], data[5],
1505 data[6]); 1505 data[6]);
1506 1506
1507 switch (s1->linear & 0x7f) { 1507 switch (s1->linear & 0x7f) {
1508 case 7: /* 1/x sensor, exchange upper and lower limits */ 1508 case 7: /* 1/x sensor, exchange upper and lower limits */
1509 prop_critmax = PROP_CRITMIN; 1509 prop_critmax = PROP_CRITMIN;
1510 prop_warnmax = PROP_WARNMIN; 1510 prop_warnmax = PROP_WARNMIN;
1511 prop_critmin = PROP_CRITMAX; 1511 prop_critmin = PROP_CRITMAX;
1512 prop_warnmin = PROP_WARNMAX; 1512 prop_warnmin = PROP_WARNMAX;
1513 pcritmax = &limits->sel_critmin; 1513 pcritmax = &limits->sel_critmin;
1514 pwarnmax = &limits->sel_warnmin; 1514 pwarnmax = &limits->sel_warnmin;
1515 pcritmin = &limits->sel_critmax; 1515 pcritmin = &limits->sel_critmax;
1516 pwarnmin = &limits->sel_warnmax; 1516 pwarnmin = &limits->sel_warnmax;
1517 break; 1517 break;
1518 default: 1518 default:
1519 prop_critmax = PROP_CRITMAX; 1519 prop_critmax = PROP_CRITMAX;
1520 prop_warnmax = PROP_WARNMAX; 1520 prop_warnmax = PROP_WARNMAX;
1521 prop_critmin = PROP_CRITMIN; 1521 prop_critmin = PROP_CRITMIN;
1522 prop_warnmin = PROP_WARNMIN; 1522 prop_warnmin = PROP_WARNMIN;
1523 pcritmax = &limits->sel_critmax; 1523 pcritmax = &limits->sel_critmax;
1524 pwarnmax = &limits->sel_warnmax; 1524 pwarnmax = &limits->sel_warnmax;
1525 pcritmin = &limits->sel_critmin; 1525 pcritmin = &limits->sel_critmin;
1526 pwarnmin = &limits->sel_warnmin; 1526 pwarnmin = &limits->sel_warnmin;
1527 break; 1527 break;
1528 } 1528 }
1529 1529
1530 if (data[0] & 0x20 && data[6] != 0xff) { 1530 if (data[0] & 0x20 && data[6] != 0xff) {
1531 *pcritmax = ipmi_convert_sensor(&data[6], psensor); 1531 *pcritmax = ipmi_convert_sensor(&data[6], psensor);
1532 *props |= prop_critmax; 1532 *props |= prop_critmax;
1533 } 1533 }
1534 if (data[0] & 0x10 && data[5] != 0xff) { 1534 if (data[0] & 0x10 && data[5] != 0xff) {
1535 *pcritmax = ipmi_convert_sensor(&data[5], psensor); 1535 *pcritmax = ipmi_convert_sensor(&data[5], psensor);
1536 *props |= prop_critmax; 1536 *props |= prop_critmax;
1537 } 1537 }
1538 if (data[0] & 0x08 && data[4] != 0xff) { 1538 if (data[0] & 0x08 && data[4] != 0xff) {
1539 *pwarnmax = ipmi_convert_sensor(&data[4], psensor); 1539 *pwarnmax = ipmi_convert_sensor(&data[4], psensor);
1540 *props |= prop_warnmax; 1540 *props |= prop_warnmax;
1541 } 1541 }
1542 if (data[0] & 0x04 && data[3] != 0x00) { 1542 if (data[0] & 0x04 && data[3] != 0x00) {
1543 *pcritmin = ipmi_convert_sensor(&data[3], psensor); 1543 *pcritmin = ipmi_convert_sensor(&data[3], psensor);
1544 *props |= prop_critmin; 1544 *props |= prop_critmin;
1545 } 1545 }
1546 if (data[0] & 0x02 && data[2] != 0x00) { 1546 if (data[0] & 0x02 && data[2] != 0x00) {
1547 *pcritmin = ipmi_convert_sensor(&data[2], psensor); 1547 *pcritmin = ipmi_convert_sensor(&data[2], psensor);
1548 *props |= prop_critmin; 1548 *props |= prop_critmin;
1549 } 1549 }
1550 if (data[0] & 0x01 && data[1] != 0x00) { 1550 if (data[0] & 0x01 && data[1] != 0x00) {
1551 *pwarnmin = ipmi_convert_sensor(&data[1], psensor); 1551 *pwarnmin = ipmi_convert_sensor(&data[1], psensor);
1552 *props |= prop_warnmin; 1552 *props |= prop_warnmin;
1553 } 1553 }
1554 return; 1554 return;
1555} 1555}
1556 1556
1557static int 1557static int
1558ipmi_sensor_status(struct ipmi_softc *sc, struct ipmi_sensor *psensor, 1558ipmi_sensor_status(struct ipmi_softc *sc, struct ipmi_sensor *psensor,
1559 envsys_data_t *edata, uint8_t *reading) 1559 envsys_data_t *edata, uint8_t *reading)
1560{ 1560{
1561 int etype; 1561 int etype;
1562 1562
1563 /* Get reading of sensor */ 1563 /* Get reading of sensor */
1564 edata->value_cur = ipmi_convert_sensor(reading, psensor); 1564 edata->value_cur = ipmi_convert_sensor(reading, psensor);
1565 1565
1566 /* Return Sensor Status */ 1566 /* Return Sensor Status */
1567 etype = (psensor->i_etype << 8) + psensor->i_stype; 1567 etype = (psensor->i_etype << 8) + psensor->i_stype;
1568 switch (etype) { 1568 switch (etype) {
1569 case IPMI_SENSOR_TYPE_TEMP: 1569 case IPMI_SENSOR_TYPE_TEMP:
1570 case IPMI_SENSOR_TYPE_VOLT: 1570 case IPMI_SENSOR_TYPE_VOLT:
1571 case IPMI_SENSOR_TYPE_FAN: 1571 case IPMI_SENSOR_TYPE_FAN:
1572 if (psensor->i_props & PROP_CRITMAX && 1572 if (psensor->i_props & PROP_CRITMAX &&
1573 edata->value_cur > psensor->i_limits.sel_critmax) 1573 edata->value_cur > psensor->i_limits.sel_critmax)
1574 return ENVSYS_SCRITOVER; 1574 return ENVSYS_SCRITOVER;
1575 1575
1576 if (psensor->i_props & PROP_WARNMAX && 1576 if (psensor->i_props & PROP_WARNMAX &&
1577 edata->value_cur > psensor->i_limits.sel_warnmax) 1577 edata->value_cur > psensor->i_limits.sel_warnmax)
1578 return ENVSYS_SWARNOVER; 1578 return ENVSYS_SWARNOVER;
1579 1579
1580 if (psensor->i_props & PROP_WARNMIN && 1580 if (psensor->i_props & PROP_WARNMIN &&
1581 edata->value_cur < psensor->i_limits.sel_warnmin) 1581 edata->value_cur < psensor->i_limits.sel_warnmin)
1582 return ENVSYS_SWARNUNDER; 1582 return ENVSYS_SWARNUNDER;
1583 1583
1584 if (psensor->i_props & PROP_CRITMIN && 1584 if (psensor->i_props & PROP_CRITMIN &&
1585 edata->value_cur < psensor->i_limits.sel_critmin) 1585 edata->value_cur < psensor->i_limits.sel_critmin)
1586 return ENVSYS_SCRITUNDER; 1586 return ENVSYS_SCRITUNDER;
1587 1587
1588 break; 1588 break;
1589 1589
1590 case IPMI_SENSOR_TYPE_INTRUSION: 1590 case IPMI_SENSOR_TYPE_INTRUSION:
1591 edata->value_cur = (reading[2] & 1) ? 0 : 1; 1591 edata->value_cur = (reading[2] & 1) ? 0 : 1;
1592 if (reading[2] & 0x1) 1592 if (reading[2] & 0x1)
1593 return ENVSYS_SCRITICAL; 1593 return ENVSYS_SCRITICAL;
1594 break; 1594 break;
1595 1595
1596 case IPMI_SENSOR_TYPE_PWRSUPPLY: 1596 case IPMI_SENSOR_TYPE_PWRSUPPLY:
1597 /* Reading: 1 = present+powered, 0 = otherwise */ 1597 /* Reading: 1 = present+powered, 0 = otherwise */
1598 edata->value_cur = (reading[2] & 1) ? 0 : 1; 1598 edata->value_cur = (reading[2] & 1) ? 0 : 1;
1599 if (reading[2] & 0x10) { 1599 if (reading[2] & 0x10) {
1600 /* XXX: Need envsys type for Power Supply types 1600 /* XXX: Need envsys type for Power Supply types
1601 * ok: power supply installed && powered 1601 * ok: power supply installed && powered
1602 * warn: power supply installed && !powered 1602 * warn: power supply installed && !powered
1603 * crit: power supply !installed 1603 * crit: power supply !installed
1604 */ 1604 */
1605 return ENVSYS_SCRITICAL; 1605 return ENVSYS_SCRITICAL;
1606 } 1606 }
1607 if (reading[2] & 0x08) { 1607 if (reading[2] & 0x08) {
1608 /* Power supply AC lost */ 1608 /* Power supply AC lost */
1609 return ENVSYS_SWARNOVER; 1609 return ENVSYS_SWARNOVER;
1610 } 1610 }
1611 break; 1611 break;
1612 } 1612 }
1613 1613
1614 return ENVSYS_SVALID; 1614 return ENVSYS_SVALID;
1615} 1615}
1616 1616
1617static int 1617static int
1618read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor) 1618read_sensor(struct ipmi_softc *sc, struct ipmi_sensor *psensor)
1619{ 1619{
1620 struct sdrtype1 *s1 = (struct sdrtype1 *) psensor->i_sdr; 1620 struct sdrtype1 *s1 = (struct sdrtype1 *) psensor->i_sdr;
1621 uint8_t data[8]; 1621 uint8_t data[8];
1622 int rxlen; 1622 int rxlen;
1623 envsys_data_t *edata = &sc->sc_sensor[psensor->i_envnum]; 1623 envsys_data_t *edata = &sc->sc_sensor[psensor->i_envnum];
1624 1624
1625 memset(data, 0, sizeof(data)); 1625 memset(data, 0, sizeof(data));
1626 data[0] = psensor->i_num; 1626 data[0] = psensor->i_num;
1627 1627
1628 mutex_enter(&sc->sc_cmd_mtx); 1628 mutex_enter(&sc->sc_cmd_mtx);
1629 if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, SE_NETFN, 1629 if (ipmi_sendcmd(sc, s1->owner_id, s1->owner_lun, SE_NETFN,
1630 SE_GET_SENSOR_READING, 1, data)) 1630 SE_GET_SENSOR_READING, 1, data))
1631 goto err; 1631 goto err;
1632 1632
1633 if (ipmi_recvcmd(sc, sizeof(data), &rxlen, data)) 1633 if (ipmi_recvcmd(sc, sizeof(data), &rxlen, data))
1634 goto err; 1634 goto err;
1635 mutex_exit(&sc->sc_cmd_mtx); 1635 mutex_exit(&sc->sc_cmd_mtx);
1636 1636
1637 dbg_printf(10, "m=%u, m_tolerance=%u, b=%u, b_accuracy=%u, " 1637 dbg_printf(10, "m=%u, m_tolerance=%u, b=%u, b_accuracy=%u, "
1638 "rbexp=%u, linear=%d\n", s1->m, s1->m_tolerance, s1->b, 1638 "rbexp=%u, linear=%d\n", s1->m, s1->m_tolerance, s1->b,
1639 s1->b_accuracy, s1->rbexp, s1->linear); 1639 s1->b_accuracy, s1->rbexp, s1->linear);
1640 dbg_printf(10, "values=%#.2x %#.2x %#.2x %#.2x %s\n", 1640 dbg_printf(10, "values=%#.2x %#.2x %#.2x %#.2x %s\n",
1641 data[0],data[1],data[2],data[3], edata->desc); 1641 data[0],data[1],data[2],data[3], edata->desc);
1642 if (IPMI_INVALID_SENSOR_P(data[1])) { 1642 if (IPMI_INVALID_SENSOR_P(data[1])) {
1643 /* Check if sensor is valid */ 1643 /* Check if sensor is valid */
1644 edata->state = ENVSYS_SINVALID; 1644 edata->state = ENVSYS_SINVALID;
1645 } else { 1645 } else {
1646 edata->state = ipmi_sensor_status(sc, psensor, edata, data); 1646 edata->state = ipmi_sensor_status(sc, psensor, edata, data);
1647 } 1647 }
1648 return 0; 1648 return 0;
1649err: 1649err:
1650 mutex_exit(&sc->sc_cmd_mtx); 1650 mutex_exit(&sc->sc_cmd_mtx);
1651 return -1; 1651 return -1;
1652} 1652}
1653 1653
1654static int 1654static int
1655ipmi_sensor_type(int type, int ext_type, int entity) 1655ipmi_sensor_type(int type, int ext_type, int entity)
1656{ 1656{
1657 switch (ext_type << 8L | type) { 1657 switch (ext_type << 8L | type) {
1658 case IPMI_SENSOR_TYPE_TEMP: 1658 case IPMI_SENSOR_TYPE_TEMP:
1659 return ENVSYS_STEMP; 1659 return ENVSYS_STEMP;
1660 1660
1661 case IPMI_SENSOR_TYPE_VOLT: 1661 case IPMI_SENSOR_TYPE_VOLT:
1662 return ENVSYS_SVOLTS_DC; 1662 return ENVSYS_SVOLTS_DC;
1663 1663
1664 case IPMI_SENSOR_TYPE_FAN: 1664 case IPMI_SENSOR_TYPE_FAN:
1665 return ENVSYS_SFANRPM; 1665 return ENVSYS_SFANRPM;
1666 1666
1667 case IPMI_SENSOR_TYPE_PWRSUPPLY: 1667 case IPMI_SENSOR_TYPE_PWRSUPPLY:
1668 if (entity == IPMI_ENTITY_PWRSUPPLY) 1668 if (entity == IPMI_ENTITY_PWRSUPPLY)
1669 return ENVSYS_INDICATOR; 1669 return ENVSYS_INDICATOR;
1670 break; 1670 break;
1671 1671
1672 case IPMI_SENSOR_TYPE_INTRUSION: 1672 case IPMI_SENSOR_TYPE_INTRUSION:
1673 return ENVSYS_INDICATOR; 1673 return ENVSYS_INDICATOR;
1674 } 1674 }
1675 1675
1676 return -1; 1676 return -1;
1677} 1677}
1678 1678
1679/* Add Sensor to BSD Sysctl interface */ 1679/* Add Sensor to BSD Sysctl interface */
1680static int 1680static int
1681add_sdr_sensor(struct ipmi_softc *sc, uint8_t *psdr) 1681add_sdr_sensor(struct ipmi_softc *sc, uint8_t *psdr)
1682{ 1682{
1683 int rc; 1683 int rc;
1684 struct sdrtype1 *s1 = (struct sdrtype1 *)psdr; 1684 struct sdrtype1 *s1 = (struct sdrtype1 *)psdr;
1685 struct sdrtype2 *s2 = (struct sdrtype2 *)psdr; 1685 struct sdrtype2 *s2 = (struct sdrtype2 *)psdr;
1686 char name[64]; 1686 char name[64];
1687 1687
1688 switch (s1->sdrhdr.record_type) { 1688 switch (s1->sdrhdr.record_type) {
1689 case IPMI_SDR_TYPEFULL: 1689 case IPMI_SDR_TYPEFULL:
1690 ipmi_sensor_name(name, sizeof(name), s1->typelen, s1->name); 1690 ipmi_sensor_name(name, sizeof(name), s1->typelen, s1->name);
1691 rc = add_child_sensors(sc, psdr, 1, s1->sensor_num, 1691 rc = add_child_sensors(sc, psdr, 1, s1->sensor_num,
1692 s1->sensor_type, s1->event_code, 0, s1->entity_id, name); 1692 s1->sensor_type, s1->event_code, 0, s1->entity_id, name);
1693 break; 1693 break;
1694 1694
1695 case IPMI_SDR_TYPECOMPACT: 1695 case IPMI_SDR_TYPECOMPACT:
1696 ipmi_sensor_name(name, sizeof(name), s2->typelen, s2->name); 1696 ipmi_sensor_name(name, sizeof(name), s2->typelen, s2->name);
1697 rc = add_child_sensors(sc, psdr, s2->share1 & 0xF, 1697 rc = add_child_sensors(sc, psdr, s2->share1 & 0xF,
1698 s2->sensor_num, s2->sensor_type, s2->event_code, 1698 s2->sensor_num, s2->sensor_type, s2->event_code,
1699 s2->share2 & 0x7F, s2->entity_id, name); 1699 s2->share2 & 0x7F, s2->entity_id, name);
1700 break; 1700 break;
1701 1701
1702 default: 1702 default:
1703 return 0; 1703 return 0;
1704 } 1704 }
1705 1705
1706 return rc; 1706 return rc;
1707} 1707}
1708 1708
1709static int 1709static int
1710ipmi_is_dupname(char *name) 1710ipmi_is_dupname(char *name)
1711{ 1711{
1712 struct ipmi_sensor *ipmi_s; 1712 struct ipmi_sensor *ipmi_s;
1713 1713
1714 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) { 1714 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) {
1715 if (strcmp(ipmi_s->i_envdesc, name) == 0) { 1715 if (strcmp(ipmi_s->i_envdesc, name) == 0) {
1716 return 1; 1716 return 1;
1717 } 1717 }
1718 } 1718 }
1719 return 0; 1719 return 0;
1720} 1720}
1721 1721
1722static int 1722static int
1723add_child_sensors(struct ipmi_softc *sc, uint8_t *psdr, int count, 1723add_child_sensors(struct ipmi_softc *sc, uint8_t *psdr, int count,
1724 int sensor_num, int sensor_type, int ext_type, int sensor_base, 1724 int sensor_num, int sensor_type, int ext_type, int sensor_base,
1725 int entity, const char *name) 1725 int entity, const char *name)
1726{ 1726{
1727 int typ, idx, dupcnt, c; 1727 int typ, idx, dupcnt, c;
1728 char *e; 1728 char *e;
1729 struct ipmi_sensor *psensor; 1729 struct ipmi_sensor *psensor;
1730 struct sdrtype1 *s1 = (struct sdrtype1 *)psdr; 1730 struct sdrtype1 *s1 = (struct sdrtype1 *)psdr;
1731  1731
1732 typ = ipmi_sensor_type(sensor_type, ext_type, entity); 1732 typ = ipmi_sensor_type(sensor_type, ext_type, entity);
1733 if (typ == -1) { 1733 if (typ == -1) {
1734 dbg_printf(5, "Unknown sensor type:%#.2x et:%#.2x sn:%#.2x " 1734 dbg_printf(5, "Unknown sensor type:%#.2x et:%#.2x sn:%#.2x "
1735 "name:%s\n", sensor_type, ext_type, sensor_num, name); 1735 "name:%s\n", sensor_type, ext_type, sensor_num, name);
1736 return 0; 1736 return 0;
1737 } 1737 }
1738 dupcnt = 0; 1738 dupcnt = 0;
1739 sc->sc_nsensors += count; 1739 sc->sc_nsensors += count;
1740 for (idx = 0; idx < count; idx++) { 1740 for (idx = 0; idx < count; idx++) {
1741 psensor = malloc(sizeof(struct ipmi_sensor), M_DEVBUF, 1741 psensor = malloc(sizeof(struct ipmi_sensor), M_DEVBUF,
1742 M_WAITOK); 1742 M_WAITOK);
1743 if (psensor == NULL) 1743 if (psensor == NULL)
1744 break; 1744 break;
1745 1745
1746 memset(psensor, 0, sizeof(struct ipmi_sensor)); 1746 memset(psensor, 0, sizeof(struct ipmi_sensor));
1747 1747
1748 /* Initialize BSD Sensor info */ 1748 /* Initialize BSD Sensor info */
1749 psensor->i_sdr = psdr; 1749 psensor->i_sdr = psdr;
1750 psensor->i_num = sensor_num + idx; 1750 psensor->i_num = sensor_num + idx;
1751 psensor->i_stype = sensor_type; 1751 psensor->i_stype = sensor_type;
1752 psensor->i_etype = ext_type; 1752 psensor->i_etype = ext_type;
1753 psensor->i_envtype = typ; 1753 psensor->i_envtype = typ;
1754 if (count > 1) 1754 if (count > 1)
1755 snprintf(psensor->i_envdesc, 1755 snprintf(psensor->i_envdesc,
1756 sizeof(psensor->i_envdesc), 1756 sizeof(psensor->i_envdesc),
1757 "%s - %d", name, sensor_base + idx); 1757 "%s - %d", name, sensor_base + idx);
1758 else 1758 else
1759 strlcpy(psensor->i_envdesc, name, 1759 strlcpy(psensor->i_envdesc, name,
1760 sizeof(psensor->i_envdesc)); 1760 sizeof(psensor->i_envdesc));
1761 1761
1762 /* 1762 /*
1763 * Check for duplicates. If there are duplicates, 1763 * Check for duplicates. If there are duplicates,
1764 * make sure there is space in the name (if not, 1764 * make sure there is space in the name (if not,
1765 * truncate to make space) for a count (1-99) to 1765 * truncate to make space) for a count (1-99) to
1766 * add to make the name unique. If we run the 1766 * add to make the name unique. If we run the
1767 * counter out, just accept the duplicate (@name99) 1767 * counter out, just accept the duplicate (@name99)
1768 * for now. 1768 * for now.
1769 */ 1769 */
1770 if (ipmi_is_dupname(psensor->i_envdesc)) { 1770 if (ipmi_is_dupname(psensor->i_envdesc)) {
1771 if (strlen(psensor->i_envdesc) >= 1771 if (strlen(psensor->i_envdesc) >=
1772 sizeof(psensor->i_envdesc) - 3) { 1772 sizeof(psensor->i_envdesc) - 3) {
1773 e = psensor->i_envdesc + 1773 e = psensor->i_envdesc +
1774 sizeof(psensor->i_envdesc) - 3; 1774 sizeof(psensor->i_envdesc) - 3;
1775 } else { 1775 } else {
1776 e = psensor->i_envdesc + 1776 e = psensor->i_envdesc +
1777 strlen(psensor->i_envdesc); 1777 strlen(psensor->i_envdesc);
1778 } 1778 }
1779 c = psensor->i_envdesc + 1779 c = psensor->i_envdesc +
1780 sizeof(psensor->i_envdesc) - e; 1780 sizeof(psensor->i_envdesc) - e;
1781 do { 1781 do {
1782 dupcnt++; 1782 dupcnt++;
1783 snprintf(e, c, "%d", dupcnt); 1783 snprintf(e, c, "%d", dupcnt);
1784 } while (dupcnt < 100 && 1784 } while (dupcnt < 100 &&
1785 ipmi_is_dupname(psensor->i_envdesc)); 1785 ipmi_is_dupname(psensor->i_envdesc));
1786 } 1786 }
1787 1787
1788 dbg_printf(5, "%s: %#.4x %#.2x:%d ent:%#.2x:%#.2x %s\n", 1788 dbg_printf(5, "%s: %#.4x %#.2x:%d ent:%#.2x:%#.2x %s\n",
1789 __func__, 1789 __func__,
1790 s1->sdrhdr.record_id, s1->sensor_type, 1790 s1->sdrhdr.record_id, s1->sensor_type,
1791 typ, s1->entity_id, s1->entity_instance, 1791 typ, s1->entity_id, s1->entity_instance,
1792 psensor->i_envdesc); 1792 psensor->i_envdesc);
1793 SLIST_INSERT_HEAD(&ipmi_sensor_list, psensor, i_list); 1793 SLIST_INSERT_HEAD(&ipmi_sensor_list, psensor, i_list);
1794 } 1794 }
1795 1795
1796 return 1; 1796 return 1;
1797} 1797}
1798 1798
1799#if 0 1799#if 0
1800/* Interrupt handler */ 1800/* Interrupt handler */
1801static int 1801static int
1802ipmi_intr(void *arg) 1802ipmi_intr(void *arg)
1803{ 1803{
1804 struct ipmi_softc *sc = (struct ipmi_softc *)arg; 1804 struct ipmi_softc *sc = (struct ipmi_softc *)arg;
1805 int v; 1805 int v;
1806 1806
1807 v = bmc_read(sc, _KCS_STATUS_REGISTER); 1807 v = bmc_read(sc, _KCS_STATUS_REGISTER);
1808 if (v & KCS_OBF) 1808 if (v & KCS_OBF)
1809 ++ipmi_nintr; 1809 ++ipmi_nintr;
1810 1810
1811 return 0; 1811 return 0;
1812} 1812}
1813#endif 1813#endif
1814 1814
1815/* Handle IPMI Timer - reread sensor values */ 1815/* Handle IPMI Timer - reread sensor values */
1816static void 1816static void
1817ipmi_refresh_sensors(struct ipmi_softc *sc) 1817ipmi_refresh_sensors(struct ipmi_softc *sc)
1818{ 1818{
1819 1819
1820 if (SLIST_EMPTY(&ipmi_sensor_list)) 1820 if (SLIST_EMPTY(&ipmi_sensor_list))
1821 return; 1821 return;
1822 1822
1823 sc->current_sensor = SLIST_NEXT(sc->current_sensor, i_list); 1823 sc->current_sensor = SLIST_NEXT(sc->current_sensor, i_list);
1824 if (sc->current_sensor == NULL) 1824 if (sc->current_sensor == NULL)
1825 sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list); 1825 sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list);
1826 1826
1827 if (read_sensor(sc, sc->current_sensor)) { 1827 if (read_sensor(sc, sc->current_sensor)) {
1828 dbg_printf(1, "%s: error reading\n", __func__); 1828 dbg_printf(1, "%s: error reading\n", __func__);
1829 } 1829 }
1830} 1830}
1831 1831
1832static int 1832static int
1833ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia) 1833ipmi_map_regs(struct ipmi_softc *sc, struct ipmi_attach_args *ia)
1834{ 1834{
1835 int error; 1835 int error;
1836 1836
1837 sc->sc_if = ipmi_get_if(ia->iaa_if_type); 1837 sc->sc_if = ipmi_get_if(ia->iaa_if_type);
1838 if (sc->sc_if == NULL) 1838 if (sc->sc_if == NULL)
1839 return -1; 1839 return -1;
1840 1840
1841 if (ia->iaa_if_iotype == 'i') 1841 if (ia->iaa_if_iotype == 'i')
1842 sc->sc_iot = ia->iaa_iot; 1842 sc->sc_iot = ia->iaa_iot;
1843 else 1843 else
1844 sc->sc_iot = ia->iaa_memt; 1844 sc->sc_iot = ia->iaa_memt;
1845 1845
1846 sc->sc_if_rev = ia->iaa_if_rev; 1846 sc->sc_if_rev = ia->iaa_if_rev;
1847 sc->sc_if_iospacing = ia->iaa_if_iospacing; 1847 sc->sc_if_iospacing = ia->iaa_if_iospacing;
1848 if ((error = bus_space_map(sc->sc_iot, ia->iaa_if_iobase, 1848 if ((error = bus_space_map(sc->sc_iot, ia->iaa_if_iobase,
1849 sc->sc_if->nregs * sc->sc_if_iospacing, 0, &sc->sc_ioh)) != 0) { 1849 sc->sc_if->nregs * sc->sc_if_iospacing, 0, &sc->sc_ioh)) != 0) {
1850 const char *xname = sc->sc_dev ? device_xname(sc->sc_dev) : 1850 const char *xname = sc->sc_dev ? device_xname(sc->sc_dev) :
1851 "ipmi0"; 1851 "ipmi0";
1852 aprint_error("%s: %s:bus_space_map(..., %" PRIx64 ", %x" 1852 aprint_error("%s: %s:bus_space_map(..., %" PRIx64 ", %x"
1853 ", 0, %p) type %c failed %d\n", 1853 ", 0, %p) type %c failed %d\n",
1854 xname, __func__, ia->iaa_if_iobase, 1854 xname, __func__, (uint64_t)ia->iaa_if_iobase,
1855 sc->sc_if->nregs * sc->sc_if_iospacing, &sc->sc_ioh, 1855 sc->sc_if->nregs * sc->sc_if_iospacing, &sc->sc_ioh,
1856 ia->iaa_if_iotype, error); 1856 ia->iaa_if_iotype, error);
1857 return -1; 1857 return -1;
1858 } 1858 }
1859#if 0 1859#if 0
1860 if (iaa->if_if_irq != -1) 1860 if (iaa->if_if_irq != -1)
1861 sc->ih = isa_intr_establish(-1, iaa->if_if_irq, 1861 sc->ih = isa_intr_establish(-1, iaa->if_if_irq,
1862 iaa->if_irqlvl, IPL_BIO, ipmi_intr, sc, 1862 iaa->if_irqlvl, IPL_BIO, ipmi_intr, sc,
1863 device_xname(sc->sc_dev); 1863 device_xname(sc->sc_dev);
1864#endif 1864#endif
1865 return 0; 1865 return 0;
1866} 1866}
1867 1867
1868static void 1868static void
1869ipmi_unmap_regs(struct ipmi_softc *sc) 1869ipmi_unmap_regs(struct ipmi_softc *sc)
1870{ 1870{
1871 bus_space_unmap(sc->sc_iot, sc->sc_ioh, 1871 bus_space_unmap(sc->sc_iot, sc->sc_ioh,
1872 sc->sc_if->nregs * sc->sc_if_iospacing); 1872 sc->sc_if->nregs * sc->sc_if_iospacing);
1873} 1873}
1874 1874
1875static int 1875static int
1876ipmi_match(device_t parent, cfdata_t cf, void *aux) 1876ipmi_match(device_t parent, cfdata_t cf, void *aux)
1877{ 1877{
1878 struct ipmi_softc sc; 1878 struct ipmi_softc sc;
1879 struct ipmi_attach_args *ia = aux; 1879 struct ipmi_attach_args *ia = aux;
1880 uint8_t cmd[32]; 1880 uint8_t cmd[32];
1881 int len; 1881 int len;
1882 int rv = 0; 1882 int rv = 0;
1883 1883
1884 memset(&sc, 0, sizeof(sc)); 1884 memset(&sc, 0, sizeof(sc));
1885 1885
1886 /* Map registers */ 1886 /* Map registers */
1887 if (ipmi_map_regs(&sc, ia) != 0) 1887 if (ipmi_map_regs(&sc, ia) != 0)
1888 return 0; 1888 return 0;
1889 1889
1890 sc.sc_if->probe(&sc); 1890 sc.sc_if->probe(&sc);
1891 1891
1892 mutex_init(&sc.sc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK); 1892 mutex_init(&sc.sc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
1893 cv_init(&sc.sc_cmd_sleep, "ipmimtch"); 1893 cv_init(&sc.sc_cmd_sleep, "ipmimtch");
1894 mutex_enter(&sc.sc_cmd_mtx); 1894 mutex_enter(&sc.sc_cmd_mtx);
1895 /* Identify BMC device early to detect lying bios */ 1895 /* Identify BMC device early to detect lying bios */
1896 if (ipmi_sendcmd(&sc, BMC_SA, 0, APP_NETFN, APP_GET_DEVICE_ID, 1896 if (ipmi_sendcmd(&sc, BMC_SA, 0, APP_NETFN, APP_GET_DEVICE_ID,
1897 0, NULL)) { 1897 0, NULL)) {
1898 mutex_exit(&sc.sc_cmd_mtx); 1898 mutex_exit(&sc.sc_cmd_mtx);
1899 dbg_printf(1, ": unable to send get device id " 1899 dbg_printf(1, ": unable to send get device id "
1900 "command\n"); 1900 "command\n");
1901 goto unmap; 1901 goto unmap;
1902 } 1902 }
1903 if (ipmi_recvcmd(&sc, sizeof(cmd), &len, cmd)) { 1903 if (ipmi_recvcmd(&sc, sizeof(cmd), &len, cmd)) {
1904 mutex_exit(&sc.sc_cmd_mtx); 1904 mutex_exit(&sc.sc_cmd_mtx);
1905 dbg_printf(1, ": unable to retrieve device id\n"); 1905 dbg_printf(1, ": unable to retrieve device id\n");
1906 goto unmap; 1906 goto unmap;
1907 } 1907 }
1908 mutex_exit(&sc.sc_cmd_mtx); 1908 mutex_exit(&sc.sc_cmd_mtx);
1909 1909
1910 dbg_dump(1, __func__, len, cmd); 1910 dbg_dump(1, __func__, len, cmd);
1911 rv = 1; /* GETID worked, we got IPMI */ 1911 rv = 1; /* GETID worked, we got IPMI */
1912unmap: 1912unmap:
1913 cv_destroy(&sc.sc_cmd_sleep); 1913 cv_destroy(&sc.sc_cmd_sleep);
1914 mutex_destroy(&sc.sc_cmd_mtx); 1914 mutex_destroy(&sc.sc_cmd_mtx);
1915 ipmi_unmap_regs(&sc); 1915 ipmi_unmap_regs(&sc);
1916 1916
1917 return rv; 1917 return rv;
1918} 1918}
1919 1919
1920static void 1920static void
1921ipmi_thread(void *cookie) 1921ipmi_thread(void *cookie)
1922{ 1922{
1923 device_t self = cookie; 1923 device_t self = cookie;
1924 struct ipmi_softc *sc = device_private(self); 1924 struct ipmi_softc *sc = device_private(self);
1925 struct ipmi_attach_args *ia = &sc->sc_ia; 1925 struct ipmi_attach_args *ia = &sc->sc_ia;
1926 uint16_t rec; 1926 uint16_t rec;
1927 struct ipmi_sensor *ipmi_s; 1927 struct ipmi_sensor *ipmi_s;
1928 int i; 1928 int i;
1929 1929
1930 sc->sc_thread_running = true; 1930 sc->sc_thread_running = true;
1931 1931
1932 /* setup ticker */ 1932 /* setup ticker */
1933 sc->sc_max_retries = hz * 90; /* 90 seconds max */ 1933 sc->sc_max_retries = hz * 90; /* 90 seconds max */
1934 1934
1935 /* Map registers */ 1935 /* Map registers */
1936 ipmi_map_regs(sc, ia); 1936 ipmi_map_regs(sc, ia);
1937 1937
1938 /* Scan SDRs, add sensors to list */ 1938 /* Scan SDRs, add sensors to list */
1939 for (rec = 0; rec != 0xFFFF;) 1939 for (rec = 0; rec != 0xFFFF;)
1940 if (get_sdr(sc, rec, &rec)) 1940 if (get_sdr(sc, rec, &rec))
1941 break; 1941 break;
1942 1942
1943 /* allocate and fill sensor arrays */ 1943 /* allocate and fill sensor arrays */
1944 sc->sc_sensor = 1944 sc->sc_sensor =
1945 malloc(sizeof(envsys_data_t) * sc->sc_nsensors, 1945 malloc(sizeof(envsys_data_t) * sc->sc_nsensors,
1946 M_DEVBUF, M_WAITOK | M_ZERO); 1946 M_DEVBUF, M_WAITOK | M_ZERO);
1947 if (sc->sc_sensor == NULL) { 1947 if (sc->sc_sensor == NULL) {
1948 aprint_error_dev(self, "can't allocate envsys_data_t\n"); 1948 aprint_error_dev(self, "can't allocate envsys_data_t\n");
1949 kthread_exit(0); 1949 kthread_exit(0);
1950 } 1950 }
1951 1951
1952 sc->sc_envsys = sysmon_envsys_create(); 1952 sc->sc_envsys = sysmon_envsys_create();
1953 sc->sc_envsys->sme_cookie = sc; 1953 sc->sc_envsys->sme_cookie = sc;
1954 sc->sc_envsys->sme_get_limits = ipmi_get_limits; 1954 sc->sc_envsys->sme_get_limits = ipmi_get_limits;
1955 sc->sc_envsys->sme_set_limits = ipmi_set_limits; 1955 sc->sc_envsys->sme_set_limits = ipmi_set_limits;
1956 1956
1957 i = 0; 1957 i = 0;
1958 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) { 1958 SLIST_FOREACH(ipmi_s, &ipmi_sensor_list, i_list) {
1959 ipmi_s->i_props = 0; 1959 ipmi_s->i_props = 0;
1960 ipmi_s->i_envnum = -1; 1960 ipmi_s->i_envnum = -1;
1961 sc->sc_sensor[i].units = ipmi_s->i_envtype; 1961 sc->sc_sensor[i].units = ipmi_s->i_envtype;
1962 sc->sc_sensor[i].state = ENVSYS_SINVALID; 1962 sc->sc_sensor[i].state = ENVSYS_SINVALID;
1963 sc->sc_sensor[i].flags |= ENVSYS_FHAS_ENTROPY; 1963 sc->sc_sensor[i].flags |= ENVSYS_FHAS_ENTROPY;
1964 /* 1964 /*
1965 * Monitor threshold limits in the sensors. 1965 * Monitor threshold limits in the sensors.
1966 */ 1966 */
1967 switch (sc->sc_sensor[i].units) { 1967 switch (sc->sc_sensor[i].units) {
1968 case ENVSYS_STEMP: 1968 case ENVSYS_STEMP:
1969 case ENVSYS_SVOLTS_DC: 1969 case ENVSYS_SVOLTS_DC:
1970 case ENVSYS_SFANRPM: 1970 case ENVSYS_SFANRPM:
1971 sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS; 1971 sc->sc_sensor[i].flags |= ENVSYS_FMONLIMITS;
1972 break; 1972 break;
1973 default: 1973 default:
1974 sc->sc_sensor[i].flags |= ENVSYS_FMONCRITICAL; 1974 sc->sc_sensor[i].flags |= ENVSYS_FMONCRITICAL;
1975 } 1975 }
1976 (void)strlcpy(sc->sc_sensor[i].desc, ipmi_s->i_envdesc, 1976 (void)strlcpy(sc->sc_sensor[i].desc, ipmi_s->i_envdesc,
1977 sizeof(sc->sc_sensor[i].desc)); 1977 sizeof(sc->sc_sensor[i].desc));
1978 ++i; 1978 ++i;
1979 1979
1980 if (sysmon_envsys_sensor_attach(sc->sc_envsys, 1980 if (sysmon_envsys_sensor_attach(sc->sc_envsys,
1981 &sc->sc_sensor[i-1])) 1981 &sc->sc_sensor[i-1]))
1982 continue; 1982 continue;
1983 1983
1984 /* get reference number from envsys */ 1984 /* get reference number from envsys */
1985 ipmi_s->i_envnum = sc->sc_sensor[i-1].sensor; 1985 ipmi_s->i_envnum = sc->sc_sensor[i-1].sensor;
1986 } 1986 }
1987 1987
1988 sc->sc_envsys->sme_name = device_xname(sc->sc_dev); 1988 sc->sc_envsys->sme_name = device_xname(sc->sc_dev);
1989 sc->sc_envsys->sme_flags = SME_DISABLE_REFRESH; 1989 sc->sc_envsys->sme_flags = SME_DISABLE_REFRESH;
1990 1990
1991 if (sysmon_envsys_register(sc->sc_envsys)) { 1991 if (sysmon_envsys_register(sc->sc_envsys)) {
1992 aprint_error_dev(self, "unable to register with sysmon\n"); 1992 aprint_error_dev(self, "unable to register with sysmon\n");
1993 sysmon_envsys_destroy(sc->sc_envsys); 1993 sysmon_envsys_destroy(sc->sc_envsys);
1994 } 1994 }
1995 1995
1996 /* initialize sensor list for thread */ 1996 /* initialize sensor list for thread */
1997 if (!SLIST_EMPTY(&ipmi_sensor_list)) 1997 if (!SLIST_EMPTY(&ipmi_sensor_list))
1998 sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list); 1998 sc->current_sensor = SLIST_FIRST(&ipmi_sensor_list);
1999 1999
2000 aprint_verbose_dev(self, "version %d.%d interface %s %sbase " 2000 aprint_verbose_dev(self, "version %d.%d interface %s %sbase "
2001 "0x%" PRIx64 "/%#x spacing %d\n", 2001 "0x%" PRIx64 "/%#x spacing %d\n",
2002 ia->iaa_if_rev >> 4, ia->iaa_if_rev & 0xF, sc->sc_if->name, 2002 ia->iaa_if_rev >> 4, ia->iaa_if_rev & 0xF, sc->sc_if->name,
2003 ia->iaa_if_iotype == 'i' ? "io" : "mem", ia->iaa_if_iobase, 2003 ia->iaa_if_iotype == 'i' ? "io" : "mem",
 2004 (uint64_t)ia->iaa_if_iobase,
2004 ia->iaa_if_iospacing * sc->sc_if->nregs, ia->iaa_if_iospacing); 2005 ia->iaa_if_iospacing * sc->sc_if->nregs, ia->iaa_if_iospacing);
2005 if (ia->iaa_if_irq != -1) 2006 if (ia->iaa_if_irq != -1)
2006 aprint_verbose_dev(self, " irq %d\n", ia->iaa_if_irq); 2007 aprint_verbose_dev(self, " irq %d\n", ia->iaa_if_irq);
2007 2008
2008 /* setup flag to exclude iic */ 2009 /* setup flag to exclude iic */
2009 ipmi_enabled = 1; 2010 ipmi_enabled = 1;
2010 2011
2011 /* Setup Watchdog timer */ 2012 /* Setup Watchdog timer */
2012 sc->sc_wdog.smw_name = device_xname(sc->sc_dev); 2013 sc->sc_wdog.smw_name = device_xname(sc->sc_dev);
2013 sc->sc_wdog.smw_cookie = sc; 2014 sc->sc_wdog.smw_cookie = sc;
2014 sc->sc_wdog.smw_setmode = ipmi_watchdog_setmode; 2015 sc->sc_wdog.smw_setmode = ipmi_watchdog_setmode;
2015 sc->sc_wdog.smw_tickle = ipmi_watchdog_tickle; 2016 sc->sc_wdog.smw_tickle = ipmi_watchdog_tickle;
2016 sysmon_wdog_register(&sc->sc_wdog); 2017 sysmon_wdog_register(&sc->sc_wdog);
2017 2018
2018 /* Set up a power handler so we can possibly sleep */ 2019 /* Set up a power handler so we can possibly sleep */
2019 if (!pmf_device_register(self, ipmi_suspend, NULL)) 2020 if (!pmf_device_register(self, ipmi_suspend, NULL))
2020 aprint_error_dev(self, "couldn't establish a power handler\n"); 2021 aprint_error_dev(self, "couldn't establish a power handler\n");
2021 2022
2022 mutex_enter(&sc->sc_poll_mtx); 2023 mutex_enter(&sc->sc_poll_mtx);
2023 while (sc->sc_thread_running) { 2024 while (sc->sc_thread_running) {
2024 ipmi_refresh_sensors(sc); 2025 ipmi_refresh_sensors(sc);
2025 cv_timedwait(&sc->sc_poll_cv, &sc->sc_poll_mtx, 2026 cv_timedwait(&sc->sc_poll_cv, &sc->sc_poll_mtx,
2026 SENSOR_REFRESH_RATE); 2027 SENSOR_REFRESH_RATE);
2027 if (sc->sc_tickle_due) { 2028 if (sc->sc_tickle_due) {
2028 ipmi_dotickle(sc); 2029 ipmi_dotickle(sc);
2029 sc->sc_tickle_due = false; 2030 sc->sc_tickle_due = false;
2030 } 2031 }
2031 } 2032 }
2032 mutex_exit(&sc->sc_poll_mtx); 2033 mutex_exit(&sc->sc_poll_mtx);
2033 self->dv_flags &= ~DVF_ATTACH_INPROGRESS; 2034 self->dv_flags &= ~DVF_ATTACH_INPROGRESS;
2034 kthread_exit(0); 2035 kthread_exit(0);
2035} 2036}
2036 2037
2037static void 2038static void
2038ipmi_attach(device_t parent, device_t self, void *aux) 2039ipmi_attach(device_t parent, device_t self, void *aux)
2039{ 2040{
2040 struct ipmi_softc *sc = device_private(self); 2041 struct ipmi_softc *sc = device_private(self);
2041 2042
2042 sc->sc_ia = *(struct ipmi_attach_args *)aux; 2043 sc->sc_ia = *(struct ipmi_attach_args *)aux;
2043 sc->sc_dev = self; 2044 sc->sc_dev = self;
2044 aprint_naive("\n"); 2045 aprint_naive("\n");
2045 aprint_normal("\n"); 2046 aprint_normal("\n");
2046 2047
2047 /* lock around read_sensor so that no one messes with the bmc regs */ 2048 /* lock around read_sensor so that no one messes with the bmc regs */
2048 mutex_init(&sc->sc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK); 2049 mutex_init(&sc->sc_cmd_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
2049 mutex_init(&sc->sc_sleep_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK); 2050 mutex_init(&sc->sc_sleep_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
2050 cv_init(&sc->sc_cmd_sleep, "ipmicmd"); 2051 cv_init(&sc->sc_cmd_sleep, "ipmicmd");
2051 2052
2052 mutex_init(&sc->sc_poll_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK); 2053 mutex_init(&sc->sc_poll_mtx, MUTEX_DEFAULT, IPL_SOFTCLOCK);
2053 cv_init(&sc->sc_poll_cv, "ipmipoll"); 2054 cv_init(&sc->sc_poll_cv, "ipmipoll");
2054 2055
2055 if (kthread_create(PRI_NONE, 0, NULL, ipmi_thread, self, 2056 if (kthread_create(PRI_NONE, 0, NULL, ipmi_thread, self,
2056 &sc->sc_kthread, "%s", device_xname(self)) != 0) { 2057 &sc->sc_kthread, "%s", device_xname(self)) != 0) {
2057 aprint_error_dev(self, "unable to create thread, disabled\n"); 2058 aprint_error_dev(self, "unable to create thread, disabled\n");
2058 } else 2059 } else
2059 self->dv_flags |= DVF_ATTACH_INPROGRESS; 2060 self->dv_flags |= DVF_ATTACH_INPROGRESS;
2060} 2061}
2061 2062
2062static int 2063static int
2063ipmi_detach(device_t self, int flags) 2064ipmi_detach(device_t self, int flags)
2064{ 2065{
2065 struct ipmi_sensor *i; 2066 struct ipmi_sensor *i;
2066 int rc; 2067 int rc;
2067 struct ipmi_softc *sc = device_private(self); 2068 struct ipmi_softc *sc = device_private(self);
2068 2069
2069 mutex_enter(&sc->sc_poll_mtx); 2070 mutex_enter(&sc->sc_poll_mtx);
2070 sc->sc_thread_running = false; 2071 sc->sc_thread_running = false;
2071 cv_signal(&sc->sc_poll_cv); 2072 cv_signal(&sc->sc_poll_cv);
2072 mutex_exit(&sc->sc_poll_mtx); 2073 mutex_exit(&sc->sc_poll_mtx);
2073 2074
2074 if ((rc = sysmon_wdog_unregister(&sc->sc_wdog)) != 0) { 2075 if ((rc = sysmon_wdog_unregister(&sc->sc_wdog)) != 0) {
2075 if (rc == ERESTART) 2076 if (rc == ERESTART)
2076 rc = EINTR; 2077 rc = EINTR;
2077 return rc; 2078 return rc;
2078 } 2079 }
2079 2080
2080 /* cancel any pending countdown */ 2081 /* cancel any pending countdown */
2081 sc->sc_wdog.smw_mode &= ~WDOG_MODE_MASK; 2082 sc->sc_wdog.smw_mode &= ~WDOG_MODE_MASK;
2082 sc->sc_wdog.smw_mode |= WDOG_MODE_DISARMED; 2083 sc->sc_wdog.smw_mode |= WDOG_MODE_DISARMED;
2083 sc->sc_wdog.smw_period = WDOG_PERIOD_DEFAULT; 2084 sc->sc_wdog.smw_period = WDOG_PERIOD_DEFAULT;
2084 2085
2085 if ((rc = ipmi_watchdog_setmode(&sc->sc_wdog)) != 0) 2086 if ((rc = ipmi_watchdog_setmode(&sc->sc_wdog)) != 0)
2086 return rc; 2087 return rc;
2087 2088
2088 ipmi_enabled = 0; 2089 ipmi_enabled = 0;
2089 2090
2090 if (sc->sc_envsys != NULL) { 2091 if (sc->sc_envsys != NULL) {
2091 /* _unregister also destroys */ 2092 /* _unregister also destroys */
2092 sysmon_envsys_unregister(sc->sc_envsys); 2093 sysmon_envsys_unregister(sc->sc_envsys);
2093 sc->sc_envsys = NULL; 2094 sc->sc_envsys = NULL;
2094 } 2095 }
2095 2096
2096 while ((i = SLIST_FIRST(&ipmi_sensor_list)) != NULL) { 2097 while ((i = SLIST_FIRST(&ipmi_sensor_list)) != NULL) {
2097 SLIST_REMOVE_HEAD(&ipmi_sensor_list, i_list); 2098 SLIST_REMOVE_HEAD(&ipmi_sensor_list, i_list);
2098 free(i, M_DEVBUF); 2099 free(i, M_DEVBUF);
2099 } 2100 }
2100 2101
2101 if (sc->sc_sensor != NULL) { 2102 if (sc->sc_sensor != NULL) {
2102 free(sc->sc_sensor, M_DEVBUF); 2103 free(sc->sc_sensor, M_DEVBUF);
2103 sc->sc_sensor = NULL; 2104 sc->sc_sensor = NULL;
2104 } 2105 }
2105 2106
2106 ipmi_unmap_regs(sc); 2107 ipmi_unmap_regs(sc);
2107 2108
2108 cv_destroy(&sc->sc_poll_cv); 2109 cv_destroy(&sc->sc_poll_cv);
2109 mutex_destroy(&sc->sc_poll_mtx); 2110 mutex_destroy(&sc->sc_poll_mtx);
2110 cv_destroy(&sc->sc_cmd_sleep); 2111 cv_destroy(&sc->sc_cmd_sleep);
2111 mutex_destroy(&sc->sc_sleep_mtx); 2112 mutex_destroy(&sc->sc_sleep_mtx);
2112 mutex_destroy(&sc->sc_cmd_mtx); 2113 mutex_destroy(&sc->sc_cmd_mtx);
2113 2114
2114 return 0; 2115 return 0;
2115} 2116}
2116 2117
2117static int 2118static int
2118ipmi_watchdog_setmode(struct sysmon_wdog *smwdog) 2119ipmi_watchdog_setmode(struct sysmon_wdog *smwdog)
2119{ 2120{
2120 struct ipmi_softc *sc = smwdog->smw_cookie; 2121 struct ipmi_softc *sc = smwdog->smw_cookie;
2121 struct ipmi_get_watchdog gwdog; 2122 struct ipmi_get_watchdog gwdog;
2122 struct ipmi_set_watchdog swdog; 2123 struct ipmi_set_watchdog swdog;
2123 int rc, len; 2124 int rc, len;
2124 2125
2125 if (smwdog->smw_period < 10) 2126 if (smwdog->smw_period < 10)
2126 return EINVAL; 2127 return EINVAL;
2127 if (smwdog->smw_period == WDOG_PERIOD_DEFAULT) 2128 if (smwdog->smw_period == WDOG_PERIOD_DEFAULT)
2128 sc->sc_wdog.smw_period = 10; 2129 sc->sc_wdog.smw_period = 10;
2129 else 2130 else
2130 sc->sc_wdog.smw_period = smwdog->smw_period; 2131 sc->sc_wdog.smw_period = smwdog->smw_period;
2131 2132
2132 mutex_enter(&sc->sc_cmd_mtx); 2133 mutex_enter(&sc->sc_cmd_mtx);
2133 /* see if we can properly task to the watchdog */ 2134 /* see if we can properly task to the watchdog */
2134 rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, 2135 rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
2135 APP_GET_WATCHDOG_TIMER, 0, NULL); 2136 APP_GET_WATCHDOG_TIMER, 0, NULL);
2136 rc = ipmi_recvcmd(sc, sizeof(gwdog), &len, &gwdog); 2137 rc = ipmi_recvcmd(sc, sizeof(gwdog), &len, &gwdog);
2137 mutex_exit(&sc->sc_cmd_mtx); 2138 mutex_exit(&sc->sc_cmd_mtx);
2138 if (rc) { 2139 if (rc) {
2139 aprint_error_dev(sc->sc_dev, 2140 aprint_error_dev(sc->sc_dev,
2140 "APP_GET_WATCHDOG_TIMER returned %#x\n", rc); 2141 "APP_GET_WATCHDOG_TIMER returned %#x\n", rc);
2141 return EIO; 2142 return EIO;
2142 } 2143 }
2143 2144
2144 memset(&swdog, 0, sizeof(swdog)); 2145 memset(&swdog, 0, sizeof(swdog));
2145 /* Period is 10ths/sec */ 2146 /* Period is 10ths/sec */
2146 swdog.wdog_timeout = htole16(sc->sc_wdog.smw_period * 10); 2147 swdog.wdog_timeout = htole16(sc->sc_wdog.smw_period * 10);
2147 if ((smwdog->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED) 2148 if ((smwdog->smw_mode & WDOG_MODE_MASK) == WDOG_MODE_DISARMED)
2148 swdog.wdog_action = IPMI_WDOG_ACT_DISABLED; 2149 swdog.wdog_action = IPMI_WDOG_ACT_DISABLED;
2149 else 2150 else
2150 swdog.wdog_action = IPMI_WDOG_ACT_RESET; 2151 swdog.wdog_action = IPMI_WDOG_ACT_RESET;
2151 swdog.wdog_use = IPMI_WDOG_USE_USE_OS; 2152 swdog.wdog_use = IPMI_WDOG_USE_USE_OS;
2152 2153
2153 mutex_enter(&sc->sc_cmd_mtx); 2154 mutex_enter(&sc->sc_cmd_mtx);
2154 if ((rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, 2155 if ((rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
2155 APP_SET_WATCHDOG_TIMER, sizeof(swdog), &swdog)) == 0) 2156 APP_SET_WATCHDOG_TIMER, sizeof(swdog), &swdog)) == 0)
2156 rc = ipmi_recvcmd(sc, 0, &len, NULL); 2157 rc = ipmi_recvcmd(sc, 0, &len, NULL);
2157 mutex_exit(&sc->sc_cmd_mtx); 2158 mutex_exit(&sc->sc_cmd_mtx);
2158 if (rc) { 2159 if (rc) {
2159 aprint_error_dev(sc->sc_dev, 2160 aprint_error_dev(sc->sc_dev,
2160 "APP_SET_WATCHDOG_TIMER returned %#x\n", rc); 2161 "APP_SET_WATCHDOG_TIMER returned %#x\n", rc);
2161 return EIO; 2162 return EIO;
2162 } 2163 }
2163 2164
2164 return 0; 2165 return 0;
2165} 2166}
2166 2167
2167static int 2168static int
2168ipmi_watchdog_tickle(struct sysmon_wdog *smwdog) 2169ipmi_watchdog_tickle(struct sysmon_wdog *smwdog)
2169{ 2170{
2170 struct ipmi_softc *sc = smwdog->smw_cookie; 2171 struct ipmi_softc *sc = smwdog->smw_cookie;
2171 2172
2172 mutex_enter(&sc->sc_poll_mtx); 2173 mutex_enter(&sc->sc_poll_mtx);
2173 sc->sc_tickle_due = true; 2174 sc->sc_tickle_due = true;
2174 cv_signal(&sc->sc_poll_cv); 2175 cv_signal(&sc->sc_poll_cv);
2175 mutex_exit(&sc->sc_poll_mtx); 2176 mutex_exit(&sc->sc_poll_mtx);
2176 return 0; 2177 return 0;
2177} 2178}
2178 2179
2179static void 2180static void
2180ipmi_dotickle(struct ipmi_softc *sc) 2181ipmi_dotickle(struct ipmi_softc *sc)
2181{ 2182{
2182 int rc, len; 2183 int rc, len;
2183 2184
2184 mutex_enter(&sc->sc_cmd_mtx); 2185 mutex_enter(&sc->sc_cmd_mtx);
2185 /* tickle the watchdog */ 2186 /* tickle the watchdog */
2186 if ((rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN, 2187 if ((rc = ipmi_sendcmd(sc, BMC_SA, BMC_LUN, APP_NETFN,
2187 APP_RESET_WATCHDOG, 0, NULL)) == 0) 2188 APP_RESET_WATCHDOG, 0, NULL)) == 0)
2188 rc = ipmi_recvcmd(sc, 0, &len, NULL); 2189 rc = ipmi_recvcmd(sc, 0, &len, NULL);
2189 mutex_exit(&sc->sc_cmd_mtx); 2190 mutex_exit(&sc->sc_cmd_mtx);
2190 if (rc != 0) { 2191 if (rc != 0) {
2191 aprint_error_dev(sc->sc_dev, "watchdog tickle returned %#x\n", 2192 aprint_error_dev(sc->sc_dev, "watchdog tickle returned %#x\n",
2192 rc); 2193 rc);
2193 } 2194 }
2194} 2195}
2195 2196
2196static bool 2197static bool
2197ipmi_suspend(device_t dev, const pmf_qual_t *qual) 2198ipmi_suspend(device_t dev, const pmf_qual_t *qual)
2198{ 2199{
2199 struct ipmi_softc *sc = device_private(dev); 2200 struct ipmi_softc *sc = device_private(dev);
2200 2201
2201 /* Don't allow suspend if watchdog is armed */ 2202 /* Don't allow suspend if watchdog is armed */
2202 if ((sc->sc_wdog.smw_mode & WDOG_MODE_MASK) != WDOG_MODE_DISARMED) 2203 if ((sc->sc_wdog.smw_mode & WDOG_MODE_MASK) != WDOG_MODE_DISARMED)
2203 return false; 2204 return false;
2204 return true; 2205 return true;
2205} 2206}

cvs diff -r1.1 -r1.2 src/sys/dev/acpi/ipmi_acpi.c (switch to unified diff)

--- src/sys/dev/acpi/ipmi_acpi.c 2018/12/25 11:56:14 1.1
+++ src/sys/dev/acpi/ipmi_acpi.c 2018/12/26 06:45:58 1.2
@@ -1,205 +1,213 @@ @@ -1,205 +1,213 @@
1/* $NetBSD: ipmi_acpi.c,v 1.1 2018/12/25 11:56:14 mlelstv Exp $ */ 1/* $NetBSD: ipmi_acpi.c,v 1.2 2018/12/26 06:45:58 mlelstv Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2018 The NetBSD Foundation, Inc. 4 * Copyright (c) 2018 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Michael van Elst 8 * by Michael van Elst
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: ipmi_acpi.c,v 1.1 2018/12/25 11:56:14 mlelstv Exp $"); 33__KERNEL_RCSID(0, "$NetBSD: ipmi_acpi.c,v 1.2 2018/12/26 06:45:58 mlelstv Exp $");
34 34
35#include <sys/param.h> 35#include <sys/param.h>
36#include <sys/device.h> 36#include <sys/device.h>
37#include <sys/module.h> 37#include <sys/module.h>
38#include <sys/systm.h> 38#include <sys/systm.h>
39 39
40#include <dev/acpi/acpireg.h> 40#include <dev/acpi/acpireg.h>
41#include <dev/acpi/acpivar.h> 41#include <dev/acpi/acpivar.h>
42 42
43#include <dev/ipmivar.h> 43#include <dev/ipmivar.h>
44 44
45#define _COMPONENT ACPI_RESOURCE_COMPONENT 45#define _COMPONENT ACPI_RESOURCE_COMPONENT
46ACPI_MODULE_NAME ("ipmi_acpi") 46ACPI_MODULE_NAME ("ipmi_acpi")
47 47
48typedef struct ipmi_acpi_softc { 48typedef struct ipmi_acpi_softc {
49 device_t sc_dev; 49 device_t sc_dev;
50 bool sc_init; 50 bool sc_init;
51} ipmi_acpi_softc_t; 51} ipmi_acpi_softc_t;
52 52
53static int ipmi_acpi_match(device_t, cfdata_t, void *); 53static int ipmi_acpi_match(device_t, cfdata_t, void *);
54static void ipmi_acpi_attach(device_t, device_t, void *); 54static void ipmi_acpi_attach(device_t, device_t, void *);
55static int ipmi_acpi_detach(device_t, int); 55static int ipmi_acpi_detach(device_t, int);
56 56
57CFATTACH_DECL3_NEW(ipmi_acpi, sizeof(ipmi_acpi_softc_t), 57CFATTACH_DECL3_NEW(ipmi_acpi, sizeof(ipmi_acpi_softc_t),
58 ipmi_acpi_match, ipmi_acpi_attach, ipmi_acpi_detach, NULL, NULL, NULL, 58 ipmi_acpi_match, ipmi_acpi_attach, ipmi_acpi_detach, NULL, NULL, NULL,
59 DVF_DETACH_SHUTDOWN); 59 DVF_DETACH_SHUTDOWN);
60 60
61static const char * const ipmi_ids[] = { 61static const char * const ipmi_ids[] = {
62 "IPI0001", 62 "IPI0001",
63 NULL 63 NULL
64}; 64};
65 65
66static int 66static int
67ipmi_acpi_match(device_t parent, cfdata_t match, void *opaque) 67ipmi_acpi_match(device_t parent, cfdata_t match, void *opaque)
68{ 68{
69 struct acpi_attach_args *aa = (struct acpi_attach_args *)opaque; 69 struct acpi_attach_args *aa = (struct acpi_attach_args *)opaque;
70 70
71 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE) 71 if (aa->aa_node->ad_type != ACPI_TYPE_DEVICE)
72 return 0; 72 return 0;
73 73
74 if (!acpi_match_hid(aa->aa_node->ad_devinfo, ipmi_ids)) 74 if (!acpi_match_hid(aa->aa_node->ad_devinfo, ipmi_ids))
75 return 0; 75 return 0;
76 76
77 return 1; 77 return 1;
78} 78}
79 79
80static void 80static void
81ipmi_acpi_attach(device_t parent, device_t self, void *opaque) 81ipmi_acpi_attach(device_t parent, device_t self, void *opaque)
82{ 82{
83 ipmi_acpi_softc_t *sc = device_private(self); 83 ipmi_acpi_softc_t *sc = device_private(self);
84 struct acpi_attach_args *aa = (struct acpi_attach_args *)opaque; 84 struct acpi_attach_args *aa = (struct acpi_attach_args *)opaque;
85 ACPI_STATUS rv; 85 ACPI_STATUS rv;
86 ACPI_INTEGER itype, ivers, adr; 86 ACPI_INTEGER itype, ivers, adr;
87 struct acpi_resources res; 87 struct acpi_resources res;
88 struct acpi_io *io; 88 struct acpi_io *io;
89 struct acpi_mem *mem; 89 struct acpi_mem *mem;
90#if notyet 90#if notyet
91 struct acpi_irq *irq; 91 struct acpi_irq *irq;
92#endif 92#endif
93 struct ipmi_attach_args IA, *ia = &IA; 93 struct ipmi_attach_args IA, *ia = &IA;
94 bus_addr_t reg2; 94 bus_addr_t reg2;
 95 uint16_t i2caddr;
95 96
96 sc->sc_dev = self; 97 sc->sc_dev = self;
97 98
98 aprint_naive("\n"); 99 aprint_naive("\n");
99 100
100 rv = acpi_eval_integer(aa->aa_node->ad_handle, "_IFT", &itype); 101 rv = acpi_eval_integer(aa->aa_node->ad_handle, "_IFT", &itype);
101 if (ACPI_FAILURE(rv)) { 102 if (ACPI_FAILURE(rv)) {
102 aprint_error("no _IFT\n"); 103 aprint_error("no _IFT\n");
103 return; 104 return;
104 } 105 }
105 106
106 rv = acpi_eval_integer(aa->aa_node->ad_handle, "_SRV", &ivers); 107 rv = acpi_eval_integer(aa->aa_node->ad_handle, "_SRV", &ivers);
107 if (ACPI_FAILURE(rv)) { 108 if (ACPI_FAILURE(rv)) {
108 aprint_error("no _SRV\n"); 109 aprint_error("no _SRV\n");
109 return; 110 return;
110 } 111 }
111 112
112 switch (itype) { 113 switch (itype) {
113 case IPMI_IF_KCS: 114 case IPMI_IF_KCS:
114 case IPMI_IF_SMIC: 115 case IPMI_IF_SMIC:
115 case IPMI_IF_BT: 116 case IPMI_IF_BT:
116 rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS", 117 rv = acpi_resource_parse(self, aa->aa_node->ad_handle, "_CRS",
117 &res, &acpi_resource_parse_ops_default); 118 &res, &acpi_resource_parse_ops_default);
118 if (ACPI_FAILURE(rv)) { 119 if (ACPI_FAILURE(rv)) {
119 aprint_normal("\n"); 120 aprint_normal("\n");
120 aprint_error_dev(self, "no resources\n"); 121 aprint_error_dev(self, "no resources\n");
121 return; 122 return;
122 } 123 }
123 124
124 acpi_resource_print(self, &res); 125 acpi_resource_print(self, &res);
125 126
126 io = acpi_res_io(&res, 0); 127 io = acpi_res_io(&res, 0);
127 mem = acpi_res_mem(&res, 0); 128 mem = acpi_res_mem(&res, 0);
128 if (io == NULL && mem == NULL) { 129 if (io == NULL && mem == NULL) {
129 aprint_error_dev(self, "no resources\n"); 130 aprint_error_dev(self, "no resources\n");
130 return; 131 return;
131 } 132 }
132 133
133#if notyet 134#if notyet
134 if ((irq = acpi_res_irq(&res, 0)) != NULL) { 135 if ((irq = acpi_res_irq(&res, 0)) != NULL) {
135 aprint_normal_dev(self, "IRQ %d type %d\n", 136 aprint_normal_dev(self, "IRQ %d type %d\n",
136 irq->ar_irq, irq->ar_type); 137 irq->ar_irq, irq->ar_type);
137 } else { 138 } else {
138 aprint_error_dev(self, "no interrupt\n"); 139 aprint_error_dev(self, "no interrupt\n");
139 } 140 }
140#endif 141#endif
141 ia->iaa_iot = aa->aa_iot; 142 ia->iaa_iot = aa->aa_iot;
142 ia->iaa_memt = aa->aa_memt; 143 ia->iaa_memt = aa->aa_memt;
143 144
144 ia->iaa_if_type = itype; 145 ia->iaa_if_type = itype;
145 ia->iaa_if_rev = ivers; 146 ia->iaa_if_rev = ivers;
146 ia->iaa_if_iotype = io ? 'i' : 'm'; 147 ia->iaa_if_iotype = io ? 'i' : 'm';
147 ia->iaa_if_iobase = io ? io->ar_base : mem->ar_base; 148 ia->iaa_if_iobase = io ? io->ar_base : mem->ar_base;
148 ia->iaa_if_iospacing = 1; 149 ia->iaa_if_iospacing = 1;
149 ia->iaa_if_irq = -1; 150 ia->iaa_if_irq = -1;
150 ia->iaa_if_irqlvl = 0; 151 ia->iaa_if_irqlvl = 0;
151 152
152 reg2 = 0; 153 reg2 = 0;
153 if (io) { 154 if (io) {
154 io = acpi_res_io(&res, 1); 155 io = acpi_res_io(&res, 1);
155 if (io != NULL) 156 if (io != NULL)
156 reg2 = (bus_addr_t)io->ar_base; 157 reg2 = (bus_addr_t)io->ar_base;
157 } else { 158 } else {
158 mem = acpi_res_mem(&res, 1); 159 mem = acpi_res_mem(&res, 1);
159 if (mem != NULL) 160 if (mem != NULL)
160 reg2 = mem->ar_base; 161 reg2 = mem->ar_base;
161 } 162 }
162 163
163 if (reg2 > ia->iaa_if_iobase) 164 if (reg2 > ia->iaa_if_iobase)
164 ia->iaa_if_iospacing = reg2 - ia->iaa_if_iobase; 165 ia->iaa_if_iospacing = reg2 - ia->iaa_if_iobase;
165 166
166 config_found_ia(self, "ipmibus", ia, 0); 167 config_found_ia(self, "ipmibus", ia, 0);
167 168
168 break; 169 break;
169 case IPMI_IF_SSIF: 170 case IPMI_IF_SSIF:
170 rv = acpi_eval_integer(aa->aa_node->ad_handle, "_ADR", &adr); 171 rv = acpi_eval_integer(aa->aa_node->ad_handle, "_ADR", &adr);
171 if (ACPI_FAILURE(rv)) { 172 if (ACPI_FAILURE(rv)) {
172 aprint_normal("\n"); 173 aprint_normal("\n");
173 aprint_error_dev(self, "no resources\n"); 174 aprint_error_dev(self, "no resources\n");
174 return; 175 return;
175 } 176 }
176 aprint_normal(": i2c 0x%lx\n", adr); 177 if (adr > 65535) {
 178 aprint_normal("\n");
 179 aprint_error_dev(self, "i2c address out of range\n");
 180 return;
 181 }
 182 i2caddr = adr;
 183
 184 aprint_normal(": i2c 0x%x\n", i2caddr);
177 break; 185 break;
178 default: 186 default:
179 aprint_normal("\n"); 187 aprint_normal("\n");
180 aprint_error_dev(self, "unknown interface type\n"); 188 aprint_error_dev(self, "unknown interface type\n");
181 return; 189 return;
182 } 190 }
183 191
184 sc->sc_init = true; 192 sc->sc_init = true;
185 193
186 if (!pmf_device_register(self, NULL, NULL)) 194 if (!pmf_device_register(self, NULL, NULL))
187 aprint_error_dev(self, "couldn't establish power handler\n"); 195 aprint_error_dev(self, "couldn't establish power handler\n");
188} 196}
189 197
190static int 198static int
191ipmi_acpi_detach(device_t self, int flags) 199ipmi_acpi_detach(device_t self, int flags)
192{ 200{
193 struct ipmi_acpi_softc *sc = device_private(self); 201 struct ipmi_acpi_softc *sc = device_private(self);
194 int rc; 202 int rc;
195 203
196 if (!sc->sc_init) 204 if (!sc->sc_init)
197 return 0; 205 return 0;
198 206
199 rc = config_detach_children(self, flags); 207 rc = config_detach_children(self, flags);
200 if (rc) 208 if (rc)
201 return rc; 209 return rc;
202 210
203 pmf_device_deregister(self); 211 pmf_device_deregister(self);
204 return 0; 212 return 0;
205} 213}