FreeBSD/sys/dev/ipmi/ipmi_kcs.c
/*
 * Determine the alignment automatically for a PCI attachment.  In this case,
 * any unused bytes will return 0x00 when read.  We make use of the C/D bit
 * in the CTL_STS register to try to start a GET_STATUS transaction.  When
 * we write the command, that bit should be set, so we should get a non-zero
 * value back when we read CTL_STS if the offset we are testing is the CTL_STS
 * register.
 */
Determine the alignment automatically for a PCI attachment.  In this case,
any unused bytes will return 0x00 when read.  We make use of the C/D bit
in the CTL_STS register to try to start a GET_STATUS transaction.  When
we write the command, that bit should be set, so we should get a non-zero
value back when we read CTL_STS if the offset we are testing is the CTL_STS
register.
Determine the alignment automatically for a PCI attachment . In this case any unused bytes will return 0x00 when read . We make use of the C / D bit in the CTL_STS register to try to start a GET_STATUS transaction . When we write the command that bit should be set so we should get a non - zero value back when we read CTL_STS if the offset we are testing is the CTL_STS register .
int
ipmi_kcs_probe_align(struct ipmi_softc *sc)
{
	int data, status;
	sc->ipmi_io_spacing = 1;
retry:
#ifdef KCS_DEBUG
	device_printf(sc->ipmi_dev, "Trying KCS align %d... ", sc->ipmi_io_spacing);
#endif
	status = INB(sc, KCS_CTL_STS);
	while (status & KCS_STATUS_IBF) {
		DELAY(100);
		status = INB(sc, KCS_CTL_STS);
	}
	OUTB(sc, KCS_CTL_STS, KCS_CONTROL_GET_STATUS_ABORT);
	status = INB(sc, KCS_CTL_STS);
	while (status & KCS_STATUS_IBF) {
		DELAY(100);
		status = INB(sc, KCS_CTL_STS);
	}
	if (status == 0) {
#ifdef KCS_DEBUG
		printf("failed\n");
#endif
		sc->ipmi_io_spacing <<= 1;
		if (sc->ipmi_io_spacing > 4)
			return (0);
		goto retry;
	}
#ifdef KCS_DEBUG
	printf("ok\n");
#endif
	if (status & KCS_STATUS_OBF)
		data = INB(sc, KCS_DATA);
	OUTB(sc, KCS_DATA, 0);
	status = INB(sc, KCS_CTL_STS);
	while (status & KCS_STATUS_IBF) {
		DELAY(100);
		status = INB(sc, KCS_CTL_STS);
	}
	if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_READ) {
		while (!(status & KCS_STATUS_OBF)) {
			DELAY(100);
			status = INB(sc, KCS_CTL_STS);
		}
		data = INB(sc, KCS_DATA);
		OUTB(sc, KCS_DATA, KCS_DATA_IN_READ);
		status = INB(sc, KCS_CTL_STS);
		while (status & KCS_STATUS_IBF) {
			DELAY(100);
			status = INB(sc, KCS_CTL_STS);
		}
	}
	if (KCS_STATUS_STATE(status) == KCS_STATUS_STATE_IDLE) {
		while (!(status & KCS_STATUS_OBF)) {
			DELAY(100);
			status = INB(sc, KCS_CTL_STS);
		}
		if (status & KCS_STATUS_OBF)
			data = INB(sc, KCS_DATA);
	} else
		device_printf(sc->ipmi_dev, "KCS probe: end state %x\n",
		    KCS_STATUS_STATE(status));
	return (1);
}
int ipmi_kcs_probe_align ( struct ipmi_softc * sc ) { int data , status ; sc -> ipmi_io_spacing = 1 ; retry : #ifdef KCS_DEBUG device_printf ( sc -> ipmi_dev , " " , sc -> ipmi_io_spacing ) ; #endif status = INB ( sc , KCS_CTL_STS ) ; while ( status & KCS_STATUS_IBF ) { DELAY ( 100 ) ; status = INB ( sc , KCS_CTL_STS ) ; } OUTB ( sc , KCS_CTL_STS , KCS_CONTROL_GET_STATUS_ABORT ) ; status = INB ( sc , KCS_CTL_STS ) ; while ( status & KCS_STATUS_IBF ) { DELAY ( 100 ) ; status = INB ( sc , KCS_CTL_STS ) ; } if ( status == 0 ) { #ifdef KCS_DEBUG printf ( " \n " ) ; #endif sc -> ipmi_io_spacing <<= 1 ; if ( sc -> ipmi_io_spacing > 4 ) return ( 0 ) ; goto retry ; } #ifdef KCS_DEBUG printf ( " \n " ) ; #endif if ( status & KCS_STATUS_OBF ) data = INB ( sc , KCS_DATA ) ; OUTB ( sc , KCS_DATA , 0 ) ; status = INB ( sc , KCS_CTL_STS ) ; while ( status & KCS_STATUS_IBF ) { DELAY ( 100 ) ; status = INB ( sc , KCS_CTL_STS ) ; } if ( KCS_STATUS_STATE ( status ) == KCS_STATUS_STATE_READ ) { while ( ! ( status & KCS_STATUS_OBF ) ) { DELAY ( 100 ) ; status = INB ( sc , KCS_CTL_STS ) ; } data = INB ( sc , KCS_DATA ) ; OUTB ( sc , KCS_DATA , KCS_DATA_IN_READ ) ; status = INB ( sc , KCS_CTL_STS ) ; while ( status & KCS_STATUS_IBF ) { DELAY ( 100 ) ; status = INB ( sc , KCS_CTL_STS ) ; } } if ( KCS_STATUS_STATE ( status ) == KCS_STATUS_STATE_IDLE ) { while ( ! ( status & KCS_STATUS_OBF ) ) { DELAY ( 100 ) ; status = INB ( sc , KCS_CTL_STS ) ; } if ( status & KCS_STATUS_OBF ) data = INB ( sc , KCS_DATA ) ; } else device_printf ( sc -> ipmi_dev , " \n " , KCS_STATUS_STATE ( status ) ) ; return ( 1 ) ; }
Determine the alignment automatically for a PCI attachment.
Determine the alignment automatically for a PCI attachment .
/* Wait for IBF = 0 */ /* Wait for IBF = 0 */ /* If we got 0x00 back, then this must not be the CTL_STS register. */ /* Finish out the transaction. */ /* Clear OBF */ /* 0x00 to DATA_IN */ /* Wait for IBF = 0 */ /* Wait for IBF = 1 */ /* Read error status. */ /* Write dummy READ to DATA_IN. */ /* Wait for IBF = 0 */ /* Wait for IBF = 1 */ /* Clear OBF */