/* * Start to write a request. Waits for IBF to clear and then sends the * WR_START command. */ static int kcs_start_write(struct ipmi_softc *sc) { int retry, status; for (retry = 0; retry < 10; retry++) { /* Wait for IBF = 0 */ status = kcs_wait_for_ibf(sc, 0); /* Clear OBF */ kcs_clear_obf(sc, status); /* Write start to command */ OUTB(sc, KCS_CTL_STS, KCS_CONTROL_WRITE_START); /* Wait for IBF = 0 */ status = kcs_wait_for_ibf(sc, 0); if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_WRITE) break; DELAY(1000000); } if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE) /* error state */ return (0); /* Clear OBF */ kcs_clear_obf(sc, status); return (1); }
/* * Write a byte of the request message, excluding the last byte of the * message which requires special handling. */ static int kcs_write_byte(struct ipmi_softc *sc, u_char data) { int status; /* Data to Data */ OUTB(sc, KCS_DATA, data); /* Wait for IBF = 0 */ status = kcs_wait_for_ibf(sc, 0); if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE) return (0); /* Clear OBF */ kcs_clear_obf(sc, status); return (1); }
/* * Write the last byte of a request message. */ static int kcs_write_last_byte(struct ipmi_softc *sc, u_char data) { int status; /* Write end to command */ OUTB(sc, KCS_CTL_STS, KCS_CONTROL_WRITE_END); /* Wait for IBF = 0 */ status = kcs_wait_for_ibf(sc, 0); if (KCS_STATUS_STATE(status) != KCS_STATUS_STATE_WRITE) /* error state */ return (0); /* Clear OBF */ kcs_clear_obf(sc, status); /* Send data byte to DATA. */ OUTB(sc, KCS_DATA, data); return (1); }
static void kcs_error(struct ipmi_softc *sc) { int retry, status; u_char data; for (retry = 0; retry < 2; retry++) { /* Wait for IBF = 0 */ status = kcs_wait_for_ibf(sc, 0); /* ABORT */ OUTB(sc, KCS_CTL_STS, KCS_CONTROL_GET_STATUS_ABORT); /* Wait for IBF = 0 */ status = kcs_wait_for_ibf(sc, 0); /* Clear OBF */ kcs_clear_obf(sc, status); if (status & KCS_STATUS_OBF) { data = INB(sc, KCS_DATA); if (data != 0) device_printf(sc->ipmi_dev, "KCS Error Data %02x\n", data); } /* 0x00 to DATA_IN */ OUTB(sc, KCS_DATA, 0x00); /* Wait for IBF = 0 */ status = kcs_wait_for_ibf(sc, 0); if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) { /* Wait for OBF = 1 */ status = kcs_wait_for_obf(sc, 1); /* Read error status */ data = INB(sc, KCS_DATA); if (data != 0) device_printf(sc->ipmi_dev, "KCS error: %02x\n", data); /* Write READ into Data_in */ OUTB(sc, KCS_DATA, KCS_DATA_IN_READ); /* Wait for IBF = 0 */ status = kcs_wait_for_ibf(sc, 0); } /* IDLE STATE */ if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) { /* Wait for OBF = 1 */ status = kcs_wait_for_obf(sc, 1); /* Clear OBF */ kcs_clear_obf(sc, status); return; } } device_printf(sc->ipmi_dev, "KCS: Error retry exhausted\n"); }