ipmi_kcs.c revision 281941
1240116Smarcel/*- 2240116Smarcel * Copyright (c) 2006 IronPort Systems Inc. <ambrisko@ironport.com> 3240116Smarcel * All rights reserved. 4240116Smarcel * 5240116Smarcel * Redistribution and use in source and binary forms, with or without 6240116Smarcel * modification, are permitted provided that the following conditions 7240116Smarcel * are met: 8240116Smarcel * 1. Redistributions of source code must retain the above copyright 9240116Smarcel * notice, this list of conditions and the following disclaimer. 10240116Smarcel * 2. Redistributions in binary form must reproduce the above copyright 11240116Smarcel * notice, this list of conditions and the following disclaimer in the 12240116Smarcel * documentation and/or other materials provided with the distribution. 13240116Smarcel * 14240116Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15240116Smarcel * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16240116Smarcel * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17240116Smarcel * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18240116Smarcel * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19240116Smarcel * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20240116Smarcel * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21240116Smarcel * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22240116Smarcel * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23240116Smarcel * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24240116Smarcel * SUCH DAMAGE. 25240116Smarcel */ 26240116Smarcel 27240116Smarcel#include <sys/cdefs.h> 28240116Smarcel__FBSDID("$FreeBSD: head/sys/dev/ipmi/ipmi_kcs.c 281941 2015-04-24 16:56:23Z jhb $"); 29240116Smarcel 30240116Smarcel#include <sys/param.h> 31240116Smarcel#include <sys/systm.h> 32240116Smarcel#include <sys/bus.h> 33240116Smarcel#include <sys/condvar.h> 34240116Smarcel#include <sys/eventhandler.h> 35240116Smarcel#include <sys/kernel.h> 36240116Smarcel#include <sys/kthread.h> 37240116Smarcel#include <sys/rman.h> 38240116Smarcel#include <sys/selinfo.h> 39240116Smarcel#include <machine/bus.h> 40240116Smarcel 41240116Smarcel#ifdef LOCAL_MODULE 42240116Smarcel#include <ipmi.h> 43240116Smarcel#include <ipmivars.h> 44240116Smarcel#else 45240116Smarcel#include <sys/ipmi.h> 46240116Smarcel#include <dev/ipmi/ipmivars.h> 47240116Smarcel#endif 48240116Smarcel 49240116Smarcelstatic void kcs_clear_obf(struct ipmi_softc *, int); 50240116Smarcelstatic void kcs_error(struct ipmi_softc *); 51240116Smarcelstatic int kcs_wait_for_ibf(struct ipmi_softc *, int); 52240116Smarcelstatic int kcs_wait_for_obf(struct ipmi_softc *, int); 53240116Smarcel 54240116Smarcelstatic int 55240116Smarcelkcs_wait_for_ibf(struct ipmi_softc *sc, int state) 56240116Smarcel{ 57240116Smarcel int status, start = ticks; 58240116Smarcel 59240116Smarcel status = INB(sc, KCS_CTL_STS); 60240116Smarcel if (state == 0) { 61240116Smarcel /* WAIT FOR IBF = 0 */ 62240116Smarcel while (ticks - start < MAX_TIMEOUT && status & KCS_STATUS_IBF) { 63240116Smarcel DELAY(100); 64240116Smarcel status = INB(sc, KCS_CTL_STS); 65240116Smarcel } 66240116Smarcel } else { 67240116Smarcel /* WAIT FOR IBF = 1 */ 68240116Smarcel while (ticks - start < MAX_TIMEOUT && 69240116Smarcel !(status & KCS_STATUS_IBF)) { 70240116Smarcel DELAY(100); 71240116Smarcel status = INB(sc, KCS_CTL_STS); 72240116Smarcel } 73240116Smarcel } 74240116Smarcel return (status); 75240116Smarcel} 76240116Smarcel 77240116Smarcelstatic int 78240116Smarcelkcs_wait_for_obf(struct ipmi_softc *sc, int state) 79240116Smarcel{ 80240116Smarcel int status, start = ticks; 81240116Smarcel 82240116Smarcel status = INB(sc, KCS_CTL_STS); 83240116Smarcel if (state == 0) { 84240116Smarcel /* WAIT FOR OBF = 0 */ 85240116Smarcel while (ticks - start < MAX_TIMEOUT && status & KCS_STATUS_OBF) { 86240116Smarcel DELAY(100); 87240116Smarcel status = INB(sc, KCS_CTL_STS); 88240116Smarcel } 89240116Smarcel } else { 90240116Smarcel /* WAIT FOR OBF = 1 */ 91240116Smarcel while (ticks - start < MAX_TIMEOUT && 92240116Smarcel !(status & KCS_STATUS_OBF)) { 93240116Smarcel DELAY(100); 94240116Smarcel status = INB(sc, KCS_CTL_STS); 95240116Smarcel } 96240116Smarcel } 97240116Smarcel return (status); 98240116Smarcel} 99240116Smarcel 100240116Smarcelstatic void 101240116Smarcelkcs_clear_obf(struct ipmi_softc *sc, int status) 102240116Smarcel{ 103240116Smarcel int data; 104240116Smarcel 105240116Smarcel /* Clear OBF */ 106240116Smarcel if (status & KCS_STATUS_OBF) { 107240116Smarcel data = INB(sc, KCS_DATA); 108240116Smarcel } 109240116Smarcel} 110240116Smarcel 111240116Smarcelstatic void 112240116Smarcelkcs_error(struct ipmi_softc *sc) 113240116Smarcel{ 114240116Smarcel int retry, status; 115240116Smarcel u_char data; 116240116Smarcel 117240116Smarcel for (retry = 0; retry < 2; retry++) { 118240116Smarcel 119240116Smarcel /* Wait for IBF = 0 */ 120240116Smarcel status = kcs_wait_for_ibf(sc, 0); 121240116Smarcel 122240116Smarcel /* ABORT */ 123240116Smarcel OUTB(sc, KCS_CTL_STS, KCS_CONTROL_GET_STATUS_ABORT); 124240116Smarcel 125240116Smarcel /* Wait for IBF = 0 */ 126240116Smarcel status = kcs_wait_for_ibf(sc, 0); 127240116Smarcel 128240116Smarcel /* Clear OBF */ 129240116Smarcel kcs_clear_obf(sc, status); 130240116Smarcel 131240116Smarcel if (status & KCS_STATUS_OBF) { 132240116Smarcel data = INB(sc, KCS_DATA); 133240116Smarcel if (data != 0) 134240116Smarcel device_printf(sc->ipmi_dev, 135240116Smarcel "KCS Error Data %02x\n", data); 136240116Smarcel } 137240116Smarcel 138240116Smarcel /* 0x00 to DATA_IN */ 139240116Smarcel OUTB(sc, KCS_DATA, 0x00); 140240116Smarcel 141240116Smarcel /* Wait for IBF = 0 */ 142240116Smarcel status = kcs_wait_for_ibf(sc, 0); 143240116Smarcel 144240116Smarcel if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) { 145240116Smarcel 146240116Smarcel /* Wait for OBF = 1 */ 147240116Smarcel status = kcs_wait_for_obf(sc, 1); 148240116Smarcel 149240116Smarcel /* Read error status */ 150240116Smarcel data = INB(sc, KCS_DATA); 151240116Smarcel if (data != 0) 152240116Smarcel device_printf(sc->ipmi_dev, "KCS error: %02x\n", 153240116Smarcel data); 154240116Smarcel 155240116Smarcel /* Write READ into Data_in */ 156240116Smarcel OUTB(sc, KCS_DATA, KCS_DATA_IN_READ); 157240116Smarcel 158240116Smarcel /* Wait for IBF = 0 */ 159240116Smarcel status = kcs_wait_for_ibf(sc, 0); 160240116Smarcel } 161240116Smarcel 162240116Smarcel /* IDLE STATE */ 163240116Smarcel if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) { 164240116Smarcel /* Wait for OBF = 1 */ 165240116Smarcel status = kcs_wait_for_obf(sc, 1); 166240116Smarcel 167240116Smarcel /* Clear OBF */ 168240116Smarcel kcs_clear_obf(sc, status); 169240116Smarcel return; 170240116Smarcel } 171240116Smarcel } 172240116Smarcel device_printf(sc->ipmi_dev, "KCS: Error retry exhausted\n"); 173240116Smarcel} 174240116Smarcel 175240116Smarcel/* 176240116Smarcel * Start to write a request. Waits for IBF to clear and then sends the 177240116Smarcel * WR_START command. 178240116Smarcel */ 179240116Smarcelstatic int 180240116Smarcelkcs_start_write(struct ipmi_softc *sc) 181240116Smarcel{ 182240116Smarcel int retry, status; 183240116Smarcel 184240116Smarcel for (retry = 0; retry < 10; retry++) { 185240116Smarcel /* Wait for IBF = 0 */ 186240116Smarcel status = kcs_wait_for_ibf(sc, 0); 187240116Smarcel if (status & KCS_STATUS_IBF) 188240116Smarcel return (0); 189240116Smarcel 190240116Smarcel /* Clear OBF */ 191240116Smarcel kcs_clear_obf(sc, status); 192240116Smarcel 193240116Smarcel /* Write start to command */ 194240116Smarcel OUTB(sc, KCS_CTL_STS, KCS_CONTROL_WRITE_START); 195240116Smarcel 196240116Smarcel /* Wait for IBF = 0 */ 197240116Smarcel status = kcs_wait_for_ibf(sc, 0); 198240116Smarcel if (status & KCS_STATUS_IBF) 199240116Smarcel return (0); 200240116Smarcel 201240116Smarcel if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_WRITE) 202240116Smarcel break; 203240116Smarcel DELAY(1000000); 204240116Smarcel } 205240116Smarcel 206240116Smarcel if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE) 207240116Smarcel /* error state */ 208240116Smarcel return (0); 209240116Smarcel 210240116Smarcel /* Clear OBF */ 211240116Smarcel kcs_clear_obf(sc, status); 212240116Smarcel 213240116Smarcel return (1); 214240116Smarcel} 215240116Smarcel 216240116Smarcel/* 217240116Smarcel * Write a byte of the request message, excluding the last byte of the 218240116Smarcel * message which requires special handling. 219240116Smarcel */ 220240116Smarcelstatic int 221240116Smarcelkcs_write_byte(struct ipmi_softc *sc, u_char data) 222240116Smarcel{ 223240116Smarcel int status; 224240116Smarcel 225240116Smarcel /* Data to Data */ 226240116Smarcel OUTB(sc, KCS_DATA, data); 227240116Smarcel 228240116Smarcel /* Wait for IBF = 0 */ 229240116Smarcel status = kcs_wait_for_ibf(sc, 0); 230240116Smarcel if (status & KCS_STATUS_IBF) 231240116Smarcel return (0); 232240116Smarcel 233240116Smarcel if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE) 234240116Smarcel return (0); 235240116Smarcel 236240116Smarcel /* Clear OBF */ 237240116Smarcel kcs_clear_obf(sc, status); 238240116Smarcel return (1); 239240116Smarcel} 240240116Smarcel 241240116Smarcel/* 242240116Smarcel * Write the last byte of a request message. 243240116Smarcel */ 244240116Smarcelstatic int 245240116Smarcelkcs_write_last_byte(struct ipmi_softc *sc, u_char data) 246240116Smarcel{ 247240116Smarcel int status; 248240116Smarcel 249240116Smarcel /* Write end to command */ 250240116Smarcel OUTB(sc, KCS_CTL_STS, KCS_CONTROL_WRITE_END); 251240116Smarcel 252240116Smarcel /* Wait for IBF = 0 */ 253240116Smarcel status = kcs_wait_for_ibf(sc, 0); 254240116Smarcel if (status & KCS_STATUS_IBF) 255240116Smarcel return (0); 256240116Smarcel 257240116Smarcel if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE) 258240116Smarcel /* error state */ 259240116Smarcel return (0); 260240116Smarcel 261240116Smarcel /* Clear OBF */ 262240116Smarcel kcs_clear_obf(sc, status); 263240116Smarcel 264240116Smarcel /* Send data byte to DATA. */ 265240116Smarcel OUTB(sc, KCS_DATA, data); 266240116Smarcel return (1); 267240116Smarcel} 268240116Smarcel 269240116Smarcel/* 270240116Smarcel * Read one byte of the reply message. 271240116Smarcel */ 272240116Smarcelstatic int 273240116Smarcelkcs_read_byte(struct ipmi_softc *sc, u_char *data) 274240116Smarcel{ 275240116Smarcel int status; 276240116Smarcel u_char dummy; 277240116Smarcel 278240116Smarcel /* Wait for IBF = 0 */ 279240116Smarcel status = kcs_wait_for_ibf(sc, 0); 280240116Smarcel 281240116Smarcel /* Read State */ 282240116Smarcel if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) { 283240116Smarcel 284240116Smarcel /* Wait for OBF = 1 */ 285240116Smarcel status = kcs_wait_for_obf(sc, 1); 286240116Smarcel if ((status & KCS_STATUS_OBF) == 0) 287240116Smarcel return (0); 288240116Smarcel 289240116Smarcel /* Read Data_out */ 290240116Smarcel *data = INB(sc, KCS_DATA); 291240116Smarcel 292240116Smarcel /* Write READ into Data_in */ 293240116Smarcel OUTB(sc, KCS_DATA, KCS_DATA_IN_READ); 294240116Smarcel return (1); 295240116Smarcel } 296240116Smarcel 297240116Smarcel /* Idle State */ 298240116Smarcel if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) { 299240116Smarcel 300240116Smarcel /* Wait for OBF = 1*/ 301240116Smarcel status = kcs_wait_for_obf(sc, 1); 302240116Smarcel if ((status & KCS_STATUS_OBF) == 0) 303240116Smarcel return (0); 304240116Smarcel 305240116Smarcel /* Read Dummy */ 306240116Smarcel dummy = INB(sc, KCS_DATA); 307240116Smarcel return (2); 308240116Smarcel } 309240116Smarcel 310240116Smarcel /* Error State */ 311240116Smarcel return (0); 312240116Smarcel} 313240116Smarcel 314240116Smarcel/* 315240116Smarcel * Send a request message and collect the reply. Returns true if we 316240116Smarcel * succeed. 317240116Smarcel */ 318240116Smarcelstatic int 319240116Smarcelkcs_polled_request(struct ipmi_softc *sc, struct ipmi_request *req) 320240116Smarcel{ 321240116Smarcel u_char *cp, data; 322240116Smarcel int i, state; 323240116Smarcel 324240116Smarcel IPMI_IO_LOCK(sc); 325240116Smarcel 326240116Smarcel /* Send the request. */ 327240116Smarcel if (!kcs_start_write(sc)) { 328240116Smarcel device_printf(sc->ipmi_dev, "KCS: Failed to start write\n"); 329240116Smarcel goto fail; 330240116Smarcel } 331240116Smarcel#ifdef KCS_DEBUG 332240116Smarcel device_printf(sc->ipmi_dev, "KCS: WRITE_START... ok\n"); 333240116Smarcel#endif 334240116Smarcel 335240116Smarcel if (!kcs_write_byte(sc, req->ir_addr)) { 336240116Smarcel device_printf(sc->ipmi_dev, "KCS: Failed to write address\n"); 337240116Smarcel goto fail; 338240116Smarcel } 339240116Smarcel#ifdef KCS_DEBUG 340240116Smarcel device_printf(sc->ipmi_dev, "KCS: Wrote address: %02x\n", req->ir_addr); 341240116Smarcel#endif 342240116Smarcel 343240116Smarcel if (req->ir_requestlen == 0) { 344240116Smarcel if (!kcs_write_last_byte(sc, req->ir_command)) { 345240116Smarcel device_printf(sc->ipmi_dev, 346240116Smarcel "KCS: Failed to write command\n"); 347240116Smarcel goto fail; 348240116Smarcel } 349240116Smarcel#ifdef KCS_DEBUG 350240116Smarcel device_printf(sc->ipmi_dev, "KCS: Wrote command: %02x\n", 351240116Smarcel req->ir_command); 352240116Smarcel#endif 353240116Smarcel } else { 354240116Smarcel if (!kcs_write_byte(sc, req->ir_command)) { 355240116Smarcel device_printf(sc->ipmi_dev, 356240116Smarcel "KCS: Failed to write command\n"); 357240116Smarcel goto fail; 358240116Smarcel } 359240116Smarcel#ifdef KCS_DEBUG 360240116Smarcel device_printf(sc->ipmi_dev, "KCS: Wrote command: %02x\n", 361240116Smarcel req->ir_command); 362240116Smarcel#endif 363240116Smarcel 364240116Smarcel cp = req->ir_request; 365240116Smarcel for (i = 0; i < req->ir_requestlen - 1; i++) { 366240116Smarcel if (!kcs_write_byte(sc, *cp++)) { 367240116Smarcel device_printf(sc->ipmi_dev, 368240116Smarcel "KCS: Failed to write data byte %d\n", 369240116Smarcel i + 1); 370240116Smarcel goto fail; 371240116Smarcel } 372240116Smarcel#ifdef KCS_DEBUG 373240116Smarcel device_printf(sc->ipmi_dev, "KCS: Wrote data: %02x\n", 374240116Smarcel cp[-1]); 375240116Smarcel#endif 376240116Smarcel } 377240116Smarcel 378240116Smarcel if (!kcs_write_last_byte(sc, *cp)) { 379240116Smarcel device_printf(sc->ipmi_dev, 380240116Smarcel "KCS: Failed to write last dta byte\n"); 381240116Smarcel goto fail; 382240116Smarcel } 383240116Smarcel#ifdef KCS_DEBUG 384240116Smarcel device_printf(sc->ipmi_dev, "KCS: Wrote last data: %02x\n", 385240116Smarcel *cp); 386240116Smarcel#endif 387240116Smarcel } 388240116Smarcel 389240116Smarcel /* Read the reply. First, read the NetFn/LUN. */ 390240116Smarcel if (kcs_read_byte(sc, &data) != 1) { 391240116Smarcel device_printf(sc->ipmi_dev, "KCS: Failed to read address\n"); 392240116Smarcel goto fail; 393 } 394#ifdef KCS_DEBUG 395 device_printf(sc->ipmi_dev, "KCS: Read address: %02x\n", data); 396#endif 397 if (data != IPMI_REPLY_ADDR(req->ir_addr)) { 398 device_printf(sc->ipmi_dev, "KCS: Reply address mismatch\n"); 399 goto fail; 400 } 401 402 /* Next we read the command. */ 403 if (kcs_read_byte(sc, &data) != 1) { 404 device_printf(sc->ipmi_dev, "KCS: Failed to read command\n"); 405 goto fail; 406 } 407#ifdef KCS_DEBUG 408 device_printf(sc->ipmi_dev, "KCS: Read command: %02x\n", data); 409#endif 410 if (data != req->ir_command) { 411 device_printf(sc->ipmi_dev, "KCS: Command mismatch\n"); 412 goto fail; 413 } 414 415 /* Next we read the completion code. */ 416 if (kcs_read_byte(sc, &req->ir_compcode) != 1) { 417 device_printf(sc->ipmi_dev, 418 "KCS: Failed to read completion code\n"); 419 goto fail; 420 } 421#ifdef KCS_DEBUG 422 device_printf(sc->ipmi_dev, "KCS: Read completion code: %02x\n", 423 req->ir_compcode); 424#endif 425 426 /* Finally, read the reply from the BMC. */ 427 i = 0; 428 for (;;) { 429 state = kcs_read_byte(sc, &data); 430 if (state == 0) { 431 device_printf(sc->ipmi_dev, 432 "KCS: Read failed on byte %d\n", i + 1); 433 goto fail; 434 } 435 if (state == 2) 436 break; 437 if (i < req->ir_replybuflen) { 438 req->ir_reply[i] = data; 439#ifdef KCS_DEBUG 440 device_printf(sc->ipmi_dev, "KCS: Read data %02x\n", 441 data); 442 } else { 443 device_printf(sc->ipmi_dev, 444 "KCS: Read short %02x byte %d\n", data, i + 1); 445#endif 446 } 447 i++; 448 } 449 IPMI_IO_UNLOCK(sc); 450 req->ir_replylen = i; 451#ifdef KCS_DEBUG 452 device_printf(sc->ipmi_dev, "KCS: READ finished (%d bytes)\n", i); 453 if (req->ir_replybuflen < i) 454#else 455 if (req->ir_replybuflen < i && req->ir_replybuflen != 0) 456#endif 457 device_printf(sc->ipmi_dev, 458 "KCS: Read short: %zd buffer, %d actual\n", 459 req->ir_replybuflen, i); 460 return (1); 461fail: 462 kcs_error(sc); 463 IPMI_IO_UNLOCK(sc); 464 return (0); 465} 466 467static void 468kcs_loop(void *arg) 469{ 470 struct ipmi_softc *sc = arg; 471 struct ipmi_request *req; 472 int i, ok; 473 474 IPMI_LOCK(sc); 475 while ((req = ipmi_dequeue_request(sc)) != NULL) { 476 IPMI_UNLOCK(sc); 477 ok = 0; 478 for (i = 0; i < 3 && !ok; i++) 479 ok = kcs_polled_request(sc, req); 480 if (ok) 481 req->ir_error = 0; 482 else 483 req->ir_error = EIO; 484 IPMI_LOCK(sc); 485 ipmi_complete_request(sc, req); 486 } 487 IPMI_UNLOCK(sc); 488 kproc_exit(0); 489} 490 491static int 492kcs_startup(struct ipmi_softc *sc) 493{ 494 495 return (kproc_create(kcs_loop, sc, &sc->ipmi_kthread, 0, 0, "%s: kcs", 496 device_get_nameunit(sc->ipmi_dev))); 497} 498 499static int 500kcs_driver_request(struct ipmi_softc *sc, struct ipmi_request *req, int timo) 501{ 502 int i, ok; 503 504 ok = 0; 505 for (i = 0; i < 3 && !ok; i++) 506 ok = kcs_polled_request(sc, req); 507 if (ok) 508 req->ir_error = 0; 509 else 510 req->ir_error = EIO; 511 return (req->ir_error); 512} 513 514int 515ipmi_kcs_attach(struct ipmi_softc *sc) 516{ 517 int status; 518 519 /* Setup function pointers. */ 520 sc->ipmi_startup = kcs_startup; 521 sc->ipmi_enqueue_request = ipmi_polled_enqueue_request; 522 sc->ipmi_driver_request = kcs_driver_request; 523 sc->ipmi_driver_requests_polled = 1; 524 525 /* See if we can talk to the controller. */ 526 status = INB(sc, KCS_CTL_STS); 527 if (status == 0xff) { 528 device_printf(sc->ipmi_dev, "couldn't find it\n"); 529 return (ENXIO); 530 } 531 532#ifdef KCS_DEBUG 533 device_printf(sc->ipmi_dev, "KCS: initial state: %02x\n", status); 534#endif 535 if (status & KCS_STATUS_OBF || 536 KCS_STATUS_STATE(status) != KCS_STATUS_STATE_IDLE) 537 kcs_error(sc); 538 539 return (0); 540} 541 542/* 543 * Determine the alignment automatically for a PCI attachment. In this case, 544 * any unused bytes will return 0x00 when read. We make use of the C/D bit 545 * in the CTL_STS register to try to start a GET_STATUS transaction. When 546 * we write the command, that bit should be set, so we should get a non-zero 547 * value back when we read CTL_STS if the offset we are testing is the CTL_STS 548 * register. 549 */ 550int 551ipmi_kcs_probe_align(struct ipmi_softc *sc) 552{ 553 int data, status; 554 555 sc->ipmi_io_spacing = 1; 556retry: 557#ifdef KCS_DEBUG 558 device_printf(sc->ipmi_dev, "Trying KCS align %d... ", sc->ipmi_io_spacing); 559#endif 560 561 /* Wait for IBF = 0 */ 562 status = INB(sc, KCS_CTL_STS); 563 while (status & KCS_STATUS_IBF) { 564 DELAY(100); 565 status = INB(sc, KCS_CTL_STS); 566 } 567 568 OUTB(sc, KCS_CTL_STS, KCS_CONTROL_GET_STATUS_ABORT); 569 570 /* Wait for IBF = 0 */ 571 status = INB(sc, KCS_CTL_STS); 572 while (status & KCS_STATUS_IBF) { 573 DELAY(100); 574 status = INB(sc, KCS_CTL_STS); 575 } 576 577 /* If we got 0x00 back, then this must not be the CTL_STS register. */ 578 if (status == 0) { 579#ifdef KCS_DEBUG 580 printf("failed\n"); 581#endif 582 sc->ipmi_io_spacing <<= 1; 583 if (sc->ipmi_io_spacing > 4) 584 return (0); 585 goto retry; 586 } 587#ifdef KCS_DEBUG 588 printf("ok\n"); 589#endif 590 591 /* Finish out the transaction. */ 592 593 /* Clear OBF */ 594 if (status & KCS_STATUS_OBF) 595 data = INB(sc, KCS_DATA); 596 597 /* 0x00 to DATA_IN */ 598 OUTB(sc, KCS_DATA, 0); 599 600 /* Wait for IBF = 0 */ 601 status = INB(sc, KCS_CTL_STS); 602 while (status & KCS_STATUS_IBF) { 603 DELAY(100); 604 status = INB(sc, KCS_CTL_STS); 605 } 606 607 if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) { 608 /* Wait for IBF = 1 */ 609 while (!(status & KCS_STATUS_OBF)) { 610 DELAY(100); 611 status = INB(sc, KCS_CTL_STS); 612 } 613 614 /* Read error status. */ 615 data = INB(sc, KCS_DATA); 616 617 /* Write dummy READ to DATA_IN. */ 618 OUTB(sc, KCS_DATA, KCS_DATA_IN_READ); 619 620 /* Wait for IBF = 0 */ 621 status = INB(sc, KCS_CTL_STS); 622 while (status & KCS_STATUS_IBF) { 623 DELAY(100); 624 status = INB(sc, KCS_CTL_STS); 625 } 626 } 627 628 if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) { 629 /* Wait for IBF = 1 */ 630 while (!(status & KCS_STATUS_OBF)) { 631 DELAY(100); 632 status = INB(sc, KCS_CTL_STS); 633 } 634 635 /* Clear OBF */ 636 if (status & KCS_STATUS_OBF) 637 data = INB(sc, KCS_DATA); 638 } else 639 device_printf(sc->ipmi_dev, "KCS probe: end state %x\n", 640 KCS_STATUS_STATE(status)); 641 642 return (1); 643} 644