2 * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 /* $FreeBSD: src/sys/dev/ipmi/ipmi_kcs.c,v 1.3 2008/08/28 02:11:04 jhb */
30 * Copyright 2013, Joyent, Inc. All rights reserved.
31 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
34 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/condvar.h>
38 #include <sys/cmn_err.h>
40 #include <sys/sunddi.h>
45 static void kcs_clear_obf(struct ipmi_softc
*, int);
46 static void kcs_error(struct ipmi_softc
*);
47 static int kcs_wait_for_ibf(struct ipmi_softc
*, int);
48 static int kcs_wait_for_obf(struct ipmi_softc
*, int);
50 #define RETRY_USECS 100
51 static clock_t timeout_usecs
;
54 kcs_wait_for_ibf(struct ipmi_softc
*sc
, int state
)
59 status
= INB(sc
, KCS_CTL_STS
);
61 /* WAIT FOR IBF = 0 */
62 for (i
= 0; i
< timeout_usecs
&& status
& KCS_STATUS_IBF
;
64 drv_usecwait(RETRY_USECS
);
65 status
= INB(sc
, KCS_CTL_STS
);
68 /* WAIT FOR IBF = 1 */
69 for (i
= 0; i
< timeout_usecs
&& !(status
& KCS_STATUS_IBF
);
71 drv_usecwait(RETRY_USECS
);
72 status
= INB(sc
, KCS_CTL_STS
);
79 kcs_wait_for_obf(struct ipmi_softc
*sc
, int state
)
84 status
= INB(sc
, KCS_CTL_STS
);
86 /* WAIT FOR OBF = 0 */
87 for (i
= 0; i
< timeout_usecs
&& status
& KCS_STATUS_OBF
;
89 drv_usecwait(RETRY_USECS
);
90 status
= INB(sc
, KCS_CTL_STS
);
93 /* WAIT FOR OBF = 1 */
94 for (i
= 0; i
< timeout_usecs
&& !(status
& KCS_STATUS_OBF
);
96 drv_usecwait(RETRY_USECS
);
97 status
= INB(sc
, KCS_CTL_STS
);
104 kcs_clear_obf(struct ipmi_softc
*sc
, int status
)
107 if (status
& KCS_STATUS_OBF
) {
108 (void) INB(sc
, KCS_DATA
);
113 kcs_error(struct ipmi_softc
*sc
)
118 for (retry
= 0; retry
< 2; retry
++) {
120 /* Wait for IBF = 0 */
121 status
= kcs_wait_for_ibf(sc
, 0);
124 OUTB(sc
, KCS_CTL_STS
, KCS_CONTROL_GET_STATUS_ABORT
);
126 /* Wait for IBF = 0 */
127 status
= kcs_wait_for_ibf(sc
, 0);
130 kcs_clear_obf(sc
, status
);
132 if (status
& KCS_STATUS_OBF
) {
133 data
= INB(sc
, KCS_DATA
);
136 "KCS Error Data %02x", data
);
139 /* 0x00 to DATA_IN */
140 OUTB(sc
, KCS_DATA
, 0x00);
142 /* Wait for IBF = 0 */
143 status
= kcs_wait_for_ibf(sc
, 0);
145 if (KCS_STATUS_STATE(status
) == KCS_STATUS_STATE_READ
) {
147 /* Wait for OBF = 1 */
148 status
= kcs_wait_for_obf(sc
, 1);
150 /* Read error status */
151 data
= INB(sc
, KCS_DATA
);
153 cmn_err(CE_WARN
, "KCS error: %02x", data
);
155 /* Write READ into Data_in */
156 OUTB(sc
, KCS_DATA
, KCS_DATA_IN_READ
);
158 /* Wait for IBF = 0 */
159 status
= kcs_wait_for_ibf(sc
, 0);
163 if (KCS_STATUS_STATE(status
) == KCS_STATUS_STATE_IDLE
) {
164 /* Wait for OBF = 1 */
165 status
= kcs_wait_for_obf(sc
, 1);
168 kcs_clear_obf(sc
, status
);
172 cmn_err(CE_WARN
, "KCS: Error retry exhausted");
176 * Start to write a request. Waits for IBF to clear and then sends the
180 kcs_start_write(struct ipmi_softc
*sc
)
184 for (retry
= 0; retry
< 10; retry
++) {
185 /* Wait for IBF = 0 */
186 status
= kcs_wait_for_ibf(sc
, 0);
189 kcs_clear_obf(sc
, status
);
191 /* Write start to command */
192 OUTB(sc
, KCS_CTL_STS
, KCS_CONTROL_WRITE_START
);
194 /* Wait for IBF = 0 */
195 status
= kcs_wait_for_ibf(sc
, 0);
196 if (KCS_STATUS_STATE(status
) == KCS_STATUS_STATE_WRITE
)
201 if (KCS_STATUS_STATE(status
) != KCS_STATUS_STATE_WRITE
)
206 kcs_clear_obf(sc
, status
);
212 * Write a byte of the request message, excluding the last byte of the
213 * message which requires special handling.
216 kcs_write_byte(struct ipmi_softc
*sc
, uchar_t data
)
221 OUTB(sc
, KCS_DATA
, data
);
223 /* Wait for IBF = 0 */
224 status
= kcs_wait_for_ibf(sc
, 0);
226 if (KCS_STATUS_STATE(status
) != KCS_STATUS_STATE_WRITE
)
230 kcs_clear_obf(sc
, status
);
235 * Write the last byte of a request message.
238 kcs_write_last_byte(struct ipmi_softc
*sc
, uchar_t data
)
242 /* Write end to command */
243 OUTB(sc
, KCS_CTL_STS
, KCS_CONTROL_WRITE_END
);
245 /* Wait for IBF = 0 */
246 status
= kcs_wait_for_ibf(sc
, 0);
248 if (KCS_STATUS_STATE(status
) != KCS_STATUS_STATE_WRITE
)
253 kcs_clear_obf(sc
, status
);
255 /* Send data byte to DATA. */
256 OUTB(sc
, KCS_DATA
, data
);
261 * Read one byte of the reply message.
264 kcs_read_byte(struct ipmi_softc
*sc
, uchar_t
*data
)
268 /* Wait for IBF = 0 */
269 status
= kcs_wait_for_ibf(sc
, 0);
272 if (KCS_STATUS_STATE(status
) == KCS_STATUS_STATE_READ
) {
274 /* Wait for OBF = 1 */
275 status
= kcs_wait_for_obf(sc
, 1);
278 *data
= INB(sc
, KCS_DATA
);
280 /* Write READ into Data_in */
281 OUTB(sc
, KCS_DATA
, KCS_DATA_IN_READ
);
286 if (KCS_STATUS_STATE(status
) == KCS_STATUS_STATE_IDLE
) {
288 /* Wait for OBF = 1 */
289 status
= kcs_wait_for_obf(sc
, 1);
292 (void) INB(sc
, KCS_DATA
);
301 * Send a request message and collect the reply. Returns true if we
305 kcs_polled_request(struct ipmi_softc
*sc
, struct ipmi_request
*req
)
310 /* Send the request. */
311 if (!kcs_start_write(sc
)) {
312 cmn_err(CE_WARN
, "KCS: Failed to start write");
316 cmn_err(CE_NOTE
, "KCS: WRITE_START... ok");
319 if (!kcs_write_byte(sc
, req
->ir_addr
)) {
320 cmn_err(CE_WARN
, "KCS: Failed to write address");
324 cmn_err(CE_NOTE
, "KCS: Wrote address: %02x", req
->ir_addr
);
327 if (req
->ir_requestlen
== 0) {
328 if (!kcs_write_last_byte(sc
, req
->ir_command
)) {
330 "KCS: Failed to write command");
334 cmn_err(CE_NOTE
, "KCS: Wrote command: %02x",
338 if (!kcs_write_byte(sc
, req
->ir_command
)) {
340 "KCS: Failed to write command");
344 cmn_err(CE_NOTE
, "KCS: Wrote command: %02x",
348 cp
= req
->ir_request
;
349 for (i
= 0; i
< req
->ir_requestlen
- 1; i
++) {
350 if (!kcs_write_byte(sc
, *cp
++)) {
352 "KCS: Failed to write data byte %d",
357 cmn_err(CE_NOTE
, "KCS: Wrote data: %02x",
362 if (!kcs_write_last_byte(sc
, *cp
)) {
364 "KCS: Failed to write last dta byte");
368 cmn_err(CE_NOTE
, "KCS: Wrote last data: %02x",
373 /* Read the reply. First, read the NetFn/LUN. */
374 if (kcs_read_byte(sc
, &data
) != 1) {
375 cmn_err(CE_WARN
, "KCS: Failed to read address");
379 cmn_err(CE_NOTE
, "KCS: Read address: %02x", data
);
381 if (data
!= IPMI_REPLY_ADDR(req
->ir_addr
)) {
382 cmn_err(CE_WARN
, "KCS: Reply address mismatch");
386 /* Next we read the command. */
387 if (kcs_read_byte(sc
, &data
) != 1) {
388 cmn_err(CE_WARN
, "KCS: Failed to read command");
392 cmn_err(CE_NOTE
, "KCS: Read command: %02x", data
);
394 if (data
!= req
->ir_command
) {
395 cmn_err(CE_WARN
, "KCS: Command mismatch");
399 /* Next we read the completion code. */
400 if (kcs_read_byte(sc
, &req
->ir_compcode
) != 1) {
401 cmn_err(CE_WARN
, "KCS: Failed to read completion code");
405 cmn_err(CE_NOTE
, "KCS: Read completion code: %02x",
409 /* Finally, read the reply from the BMC. */
412 state
= kcs_read_byte(sc
, &data
);
415 "KCS: Read failed on byte %d", i
+ 1);
420 if (i
< req
->ir_replybuflen
) {
421 req
->ir_reply
[i
] = data
;
423 cmn_err(CE_NOTE
, "KCS: Read data %02x",
427 "KCS: Read short %02x byte %d", data
, i
+ 1);
432 req
->ir_replylen
= i
;
434 cmn_err(CE_NOTE
, "KCS: READ finished (%d bytes)", i
);
435 if (req
->ir_replybuflen
< i
)
437 if (req
->ir_replybuflen
< i
&& req
->ir_replybuflen
!= 0)
439 cmn_err(CE_WARN
, "KCS: Read short: %d buffer, %d actual",
440 (int)(req
->ir_replybuflen
), i
);
450 struct ipmi_softc
*sc
= arg
;
451 struct ipmi_request
*req
;
455 while ((req
= ipmi_dequeue_request(sc
)) != NULL
) {
458 for (i
= 0; i
< 3 && !ok
; i
++)
459 ok
= kcs_polled_request(sc
, req
);
465 ipmi_complete_request(sc
, req
);
471 kcs_startup(struct ipmi_softc
*sc
)
473 sc
->ipmi_kthread
= taskq_create_proc("ipmi_kcs", 1, minclsyspri
, 1, 1,
474 curzone
->zone_zsched
, TASKQ_PREPOPULATE
);
476 if (taskq_dispatch(sc
->ipmi_kthread
, kcs_loop
, (void *) sc
,
477 TQ_SLEEP
) == (uintptr_t)NULL
) {
478 taskq_destroy(sc
->ipmi_kthread
);
486 ipmi_kcs_attach(struct ipmi_softc
*sc
)
490 /* Setup function pointers. */
491 sc
->ipmi_startup
= kcs_startup
;
492 sc
->ipmi_enqueue_request
= ipmi_polled_enqueue_request
;
494 /* See if we can talk to the controller. */
495 status
= INB(sc
, KCS_CTL_STS
);
496 if (status
== 0xff) {
497 cmn_err(CE_CONT
, "!KCS couldn't find it");
501 timeout_usecs
= drv_hztousec(MAX_TIMEOUT
);
504 cmn_err(CE_NOTE
, "KCS: initial state: %02x", status
);
506 if (status
& KCS_STATUS_OBF
||
507 KCS_STATUS_STATE(status
) != KCS_STATUS_STATE_IDLE
)