1 /* 2 * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 13 * 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 24 * SUCH DAMAGE. 25 */ 26 27 /* $FreeBSD: src/sys/dev/ipmi/ipmi_kcs.c,v 1.3 2008/08/28 02:11:04 jhb */ 28 29 /* 30 * Copyright 2013, Joyent, Inc. All rights reserved. 31 * Copyright 2013 Nexenta Systems, Inc. All rights reserved. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/disp.h> 36 #include <sys/systm.h> 37 #include <sys/condvar.h> 38 #include <sys/cmn_err.h> 39 #include <sys/ddi.h> 40 #include <sys/sunddi.h> 41 42 #include <sys/ipmi.h> 43 #include "ipmivars.h" 44 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); 49 50 #define RETRY_USECS 100 51 static clock_t timeout_usecs; 52 53 static int 54 kcs_wait_for_ibf(struct ipmi_softc *sc, int state) 55 { 56 int status; 57 clock_t i; 58 59 status = INB(sc, KCS_CTL_STS); 60 if (state == 0) { 61 /* WAIT FOR IBF = 0 */ 62 for (i = 0; i < timeout_usecs && status & KCS_STATUS_IBF; 63 i += RETRY_USECS) { 64 drv_usecwait(RETRY_USECS); 65 status = INB(sc, KCS_CTL_STS); 66 } 67 } else { 68 /* WAIT FOR IBF = 1 */ 69 for (i = 0; i < timeout_usecs && !(status & KCS_STATUS_IBF); 70 i += RETRY_USECS) { 71 drv_usecwait(RETRY_USECS); 72 status = INB(sc, KCS_CTL_STS); 73 } 74 } 75 return (status); 76 } 77 78 static int 79 kcs_wait_for_obf(struct ipmi_softc *sc, int state) 80 { 81 int status; 82 clock_t i; 83 84 status = INB(sc, KCS_CTL_STS); 85 if (state == 0) { 86 /* WAIT FOR OBF = 0 */ 87 for (i = 0; i < timeout_usecs && status & KCS_STATUS_OBF; 88 i += RETRY_USECS) { 89 drv_usecwait(RETRY_USECS); 90 status = INB(sc, KCS_CTL_STS); 91 } 92 } else { 93 /* WAIT FOR OBF = 1 */ 94 for (i = 0; i < timeout_usecs && !(status & KCS_STATUS_OBF); 95 i += RETRY_USECS) { 96 drv_usecwait(RETRY_USECS); 97 status = INB(sc, KCS_CTL_STS); 98 } 99 } 100 return (status); 101 } 102 103 static void 104 kcs_clear_obf(struct ipmi_softc *sc, int status) 105 { 106 /* Clear OBF */ 107 if (status & KCS_STATUS_OBF) { 108 (void) INB(sc, KCS_DATA); 109 } 110 } 111 112 static void 113 kcs_error(struct ipmi_softc *sc) 114 { 115 int retry, status; 116 uchar_t data; 117 118 for (retry = 0; retry < 2; retry++) { 119 120 /* Wait for IBF = 0 */ 121 status = kcs_wait_for_ibf(sc, 0); 122 123 /* ABORT */ 124 OUTB(sc, KCS_CTL_STS, KCS_CONTROL_GET_STATUS_ABORT); 125 126 /* Wait for IBF = 0 */ 127 status = kcs_wait_for_ibf(sc, 0); 128 129 /* Clear OBF */ 130 kcs_clear_obf(sc, status); 131 132 if (status & KCS_STATUS_OBF) { 133 data = INB(sc, KCS_DATA); 134 if (data != 0) 135 cmn_err(CE_WARN, 136 "KCS Error Data %02x", data); 137 } 138 139 /* 0x00 to DATA_IN */ 140 OUTB(sc, KCS_DATA, 0x00); 141 142 /* Wait for IBF = 0 */ 143 status = kcs_wait_for_ibf(sc, 0); 144 145 if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) { 146 147 /* Wait for OBF = 1 */ 148 status = kcs_wait_for_obf(sc, 1); 149 150 /* Read error status */ 151 data = INB(sc, KCS_DATA); 152 if (data != 0) 153 cmn_err(CE_WARN, "KCS error: %02x", data); 154 155 /* Write READ into Data_in */ 156 OUTB(sc, KCS_DATA, KCS_DATA_IN_READ); 157 158 /* Wait for IBF = 0 */ 159 status = kcs_wait_for_ibf(sc, 0); 160 } 161 162 /* IDLE STATE */ 163 if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) { 164 /* Wait for OBF = 1 */ 165 status = kcs_wait_for_obf(sc, 1); 166 167 /* Clear OBF */ 168 kcs_clear_obf(sc, status); 169 return; 170 } 171 } 172 cmn_err(CE_WARN, "KCS: Error retry exhausted"); 173 } 174 175 /* 176 * Start to write a request. Waits for IBF to clear and then sends the 177 * WR_START command. 178 */ 179 static int 180 kcs_start_write(struct ipmi_softc *sc) 181 { 182 int retry, status; 183 184 for (retry = 0; retry < 10; retry++) { 185 /* Wait for IBF = 0 */ 186 status = kcs_wait_for_ibf(sc, 0); 187 188 /* Clear OBF */ 189 kcs_clear_obf(sc, status); 190 191 /* Write start to command */ 192 OUTB(sc, KCS_CTL_STS, KCS_CONTROL_WRITE_START); 193 194 /* Wait for IBF = 0 */ 195 status = kcs_wait_for_ibf(sc, 0); 196 if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_WRITE) 197 break; 198 delay(drv_usectohz(1000000)); 199 } 200 201 if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE) 202 /* error state */ 203 return (0); 204 205 /* Clear OBF */ 206 kcs_clear_obf(sc, status); 207 208 return (1); 209 } 210 211 /* 212 * Write a byte of the request message, excluding the last byte of the 213 * message which requires special handling. 214 */ 215 static int 216 kcs_write_byte(struct ipmi_softc *sc, uchar_t data) 217 { 218 int status; 219 220 /* Data to Data */ 221 OUTB(sc, KCS_DATA, data); 222 223 /* Wait for IBF = 0 */ 224 status = kcs_wait_for_ibf(sc, 0); 225 226 if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE) 227 return (0); 228 229 /* Clear OBF */ 230 kcs_clear_obf(sc, status); 231 return (1); 232 } 233 234 /* 235 * Write the last byte of a request message. 236 */ 237 static int 238 kcs_write_last_byte(struct ipmi_softc *sc, uchar_t data) 239 { 240 int status; 241 242 /* Write end to command */ 243 OUTB(sc, KCS_CTL_STS, KCS_CONTROL_WRITE_END); 244 245 /* Wait for IBF = 0 */ 246 status = kcs_wait_for_ibf(sc, 0); 247 248 if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE) 249 /* error state */ 250 return (0); 251 252 /* Clear OBF */ 253 kcs_clear_obf(sc, status); 254 255 /* Send data byte to DATA. */ 256 OUTB(sc, KCS_DATA, data); 257 return (1); 258 } 259 260 /* 261 * Read one byte of the reply message. 262 */ 263 static int 264 kcs_read_byte(struct ipmi_softc *sc, uchar_t *data) 265 { 266 int status; 267 268 /* Wait for IBF = 0 */ 269 status = kcs_wait_for_ibf(sc, 0); 270 271 /* Read State */ 272 if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) { 273 274 /* Wait for OBF = 1 */ 275 status = kcs_wait_for_obf(sc, 1); 276 277 /* Read Data_out */ 278 *data = INB(sc, KCS_DATA); 279 280 /* Write READ into Data_in */ 281 OUTB(sc, KCS_DATA, KCS_DATA_IN_READ); 282 return (1); 283 } 284 285 /* Idle State */ 286 if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) { 287 288 /* Wait for OBF = 1 */ 289 status = kcs_wait_for_obf(sc, 1); 290 291 /* Read Dummy */ 292 (void) INB(sc, KCS_DATA); 293 return (2); 294 } 295 296 /* Error State */ 297 return (0); 298 } 299 300 /* 301 * Send a request message and collect the reply. Returns true if we 302 * succeed. 303 */ 304 static int 305 kcs_polled_request(struct ipmi_softc *sc, struct ipmi_request *req) 306 { 307 uchar_t *cp, data; 308 int i, state; 309 310 /* Send the request. */ 311 if (!kcs_start_write(sc)) { 312 cmn_err(CE_WARN, "KCS: Failed to start write"); 313 goto fail; 314 } 315 #ifdef KCS_DEBUG 316 cmn_err(CE_NOTE, "KCS: WRITE_START... ok"); 317 #endif 318 319 if (!kcs_write_byte(sc, req->ir_addr)) { 320 cmn_err(CE_WARN, "KCS: Failed to write address"); 321 goto fail; 322 } 323 #ifdef KCS_DEBUG 324 cmn_err(CE_NOTE, "KCS: Wrote address: %02x", req->ir_addr); 325 #endif 326 327 if (req->ir_requestlen == 0) { 328 if (!kcs_write_last_byte(sc, req->ir_command)) { 329 cmn_err(CE_WARN, 330 "KCS: Failed to write command"); 331 goto fail; 332 } 333 #ifdef KCS_DEBUG 334 cmn_err(CE_NOTE, "KCS: Wrote command: %02x", 335 req->ir_command); 336 #endif 337 } else { 338 if (!kcs_write_byte(sc, req->ir_command)) { 339 cmn_err(CE_WARN, 340 "KCS: Failed to write command"); 341 goto fail; 342 } 343 #ifdef KCS_DEBUG 344 cmn_err(CE_NOTE, "KCS: Wrote command: %02x", 345 req->ir_command); 346 #endif 347 348 cp = req->ir_request; 349 for (i = 0; i < req->ir_requestlen - 1; i++) { 350 if (!kcs_write_byte(sc, *cp++)) { 351 cmn_err(CE_WARN, 352 "KCS: Failed to write data byte %d", 353 i + 1); 354 goto fail; 355 } 356 #ifdef KCS_DEBUG 357 cmn_err(CE_NOTE, "KCS: Wrote data: %02x", 358 cp[-1]); 359 #endif 360 } 361 362 if (!kcs_write_last_byte(sc, *cp)) { 363 cmn_err(CE_WARN, 364 "KCS: Failed to write last dta byte"); 365 goto fail; 366 } 367 #ifdef KCS_DEBUG 368 cmn_err(CE_NOTE, "KCS: Wrote last data: %02x", 369 *cp); 370 #endif 371 } 372 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"); 376 goto fail; 377 } 378 #ifdef KCS_DEBUG 379 cmn_err(CE_NOTE, "KCS: Read address: %02x", data); 380 #endif 381 if (data != IPMI_REPLY_ADDR(req->ir_addr)) { 382 cmn_err(CE_WARN, "KCS: Reply address mismatch"); 383 goto fail; 384 } 385 386 /* Next we read the command. */ 387 if (kcs_read_byte(sc, &data) != 1) { 388 cmn_err(CE_WARN, "KCS: Failed to read command"); 389 goto fail; 390 } 391 #ifdef KCS_DEBUG 392 cmn_err(CE_NOTE, "KCS: Read command: %02x", data); 393 #endif 394 if (data != req->ir_command) { 395 cmn_err(CE_WARN, "KCS: Command mismatch"); 396 goto fail; 397 } 398 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"); 402 goto fail; 403 } 404 #ifdef KCS_DEBUG 405 cmn_err(CE_NOTE, "KCS: Read completion code: %02x", 406 req->ir_compcode); 407 #endif 408 409 /* Finally, read the reply from the BMC. */ 410 i = 0; 411 for (;;) { 412 state = kcs_read_byte(sc, &data); 413 if (state == 0) { 414 cmn_err(CE_WARN, 415 "KCS: Read failed on byte %d", i + 1); 416 goto fail; 417 } 418 if (state == 2) 419 break; 420 if (i < req->ir_replybuflen) { 421 req->ir_reply[i] = data; 422 #ifdef KCS_DEBUG 423 cmn_err(CE_NOTE, "KCS: Read data %02x", 424 data); 425 } else { 426 cmn_err(CE_WARN, 427 "KCS: Read short %02x byte %d", data, i + 1); 428 #endif 429 } 430 i++; 431 } 432 req->ir_replylen = i; 433 #ifdef KCS_DEBUG 434 cmn_err(CE_NOTE, "KCS: READ finished (%d bytes)", i); 435 if (req->ir_replybuflen < i) 436 #else 437 if (req->ir_replybuflen < i && req->ir_replybuflen != 0) 438 #endif 439 cmn_err(CE_WARN, "KCS: Read short: %d buffer, %d actual", 440 (int)(req->ir_replybuflen), i); 441 return (1); 442 fail: 443 kcs_error(sc); 444 return (0); 445 } 446 447 static void 448 kcs_loop(void *arg) 449 { 450 struct ipmi_softc *sc = arg; 451 struct ipmi_request *req; 452 int i, ok; 453 454 IPMI_LOCK(sc); 455 while ((req = ipmi_dequeue_request(sc)) != NULL) { 456 IPMI_UNLOCK(sc); 457 ok = 0; 458 for (i = 0; i < 3 && !ok; i++) 459 ok = kcs_polled_request(sc, req); 460 if (ok) 461 req->ir_error = 0; 462 else 463 req->ir_error = EIO; 464 IPMI_LOCK(sc); 465 ipmi_complete_request(sc, req); 466 } 467 IPMI_UNLOCK(sc); 468 } 469 470 static int 471 kcs_startup(struct ipmi_softc *sc) 472 { 473 sc->ipmi_kthread = taskq_create_proc("ipmi_kcs", 1, minclsyspri, 1, 1, 474 curzone->zone_zsched, TASKQ_PREPOPULATE); 475 476 if (taskq_dispatch(sc->ipmi_kthread, kcs_loop, (void *) sc, 477 TQ_SLEEP) == NULL) { 478 taskq_destroy(sc->ipmi_kthread); 479 return (1); 480 } 481 482 return (0); 483 } 484 485 int 486 ipmi_kcs_attach(struct ipmi_softc *sc) 487 { 488 int status; 489 490 /* Setup function pointers. */ 491 sc->ipmi_startup = kcs_startup; 492 sc->ipmi_enqueue_request = ipmi_polled_enqueue_request; 493 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"); 498 return (ENXIO); 499 } 500 501 timeout_usecs = drv_hztousec(MAX_TIMEOUT); 502 503 #ifdef KCS_DEBUG 504 cmn_err(CE_NOTE, "KCS: initial state: %02x", status); 505 #endif 506 if (status & KCS_STATUS_OBF || 507 KCS_STATUS_STATE(status) != KCS_STATUS_STATE_IDLE) 508 kcs_error(sc); 509 510 return (0); 511 } 512