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