static int
intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error, i;

	if (count > SMBBLOCKTRANS_MAX || count == 0)
		return (SMB_EINVAL);

	INTSMB_LOCK(sc);
	error = intsmb_free(sc);
	if (error) {
		INTSMB_UNLOCK(sc);
		return (error);
	}

	/* Reset internal array index. */
	bus_read_1(sc->io_res, PIIX4_SMBHSTCNT);

	bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB);
	bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
	for (i = 0; i < count; i++)
		bus_write_1(sc->io_res, PIIX4_SMBBLKDAT, buf[i]);
	bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, count);
	intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0);
	error = intsmb_stop(sc);
	INTSMB_UNLOCK(sc);
	return (error);
}
static int
intsmb_recvb(device_t dev, u_char slave, char *byte)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error;

	INTSMB_LOCK(sc);
	error = intsmb_free(sc);
	if (error) {
		INTSMB_UNLOCK(sc);
		return (error);
	}
	bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB);
	intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0);
	error = intsmb_stop(sc);
	if (error == 0) {
#ifdef RECV_IS_IN_CMD
		/*
		 * Linux SMBus stuff also troubles
		 * Because Intel's datasheet does not make clear.
		 */
		*byte = bus_read_1(sc->io_res, PIIX4_SMBHSTCMD);
#else
		*byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
#endif
	}
	INTSMB_UNLOCK(sc);
	return (error);
}
/*
 * Data sheet claims that it implements all function, but also claims
 * that it implements 7 function and not mention PCALL. So I don't know
 * whether it will work.
 */
static int
intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata)
{
#ifdef PROCCALL_TEST
	struct intsmb_softc *sc = device_get_softc(dev);
	int error;

	INTSMB_LOCK(sc);
	error = intsmb_free(sc);
	if (error) {
		INTSMB_UNLOCK(sc);
		return (error);
	}
	bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB);
	bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
	bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, sdata & 0xff);
	bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (sdata & 0xff) >> 8);
	intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0);
	error = intsmb_stop(sc);
	if (error == 0) {
		*rdata = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
		*rdata |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8;
	}
	INTSMB_UNLOCK(sc);
	return (error);
#else
	return (SMB_ENOTSUPP);
#endif
}
static int
intsmb_quick(device_t dev, u_char slave, int how)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error;
	u_char data;

	data = slave;

	/* Quick command is part of Address, I think. */
	switch(how) {
	case SMB_QWRITE:
		data &= ~LSB;
		break;
	case SMB_QREAD:
		data |= LSB;
		break;
	default:
		return (SMB_EINVAL);
	}

	INTSMB_LOCK(sc);
	error = intsmb_free(sc);
	if (error) {
		INTSMB_UNLOCK(sc);
		return (error);
	}
	bus_write_1(sc->io_res, PIIX4_SMBHSTADD, data);
	intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_QUICK, 0);
	error = intsmb_stop(sc);
	INTSMB_UNLOCK(sc);
	return (error);
}
Exemple #5
0
static int
intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error, i;
	u_char data, nread;

	INTSMB_LOCK(sc);
	error = intsmb_free(sc);
	if (error) {
		INTSMB_UNLOCK(sc);
		return (error);
	}

	/* Reset internal array index. */
	bus_read_1(sc->io_res, PIIX4_SMBHSTCNT);

	bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB);
	bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
	intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0);
	error = intsmb_stop(sc);
	if (error == 0) {
		nread = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
		if (nread != 0 && nread <= SMBBLOCKTRANS_MAX) {
			*count = nread;
			for (i = 0; i < nread; i++)
				data = bus_read_1(sc->io_res, PIIX4_SMBBLKDAT);
		} else
			error = SMB_EBUSERR;
	}
	INTSMB_UNLOCK(sc);
	return (error);
}
static int
intsmb_sendb(device_t dev, u_char slave, char byte)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error;

	INTSMB_LOCK(sc);
	error = intsmb_free(sc);
	if (error) {
		INTSMB_UNLOCK(sc);
		return (error);
	}
	bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB);
	bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, byte);
	intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0);
	error = intsmb_stop(sc);
	INTSMB_UNLOCK(sc);
	return (error);
}
static void
intsmb_rawintr(void *arg)
{
	struct intsmb_softc *sc = arg;

	INTSMB_LOCK(sc);
	intsmb_intr(sc);
	intsmb_slvintr(sc);
	INTSMB_UNLOCK(sc);
}
static int
intsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error;

	INTSMB_LOCK(sc);
	error = intsmb_free(sc);
	if (error) {
		INTSMB_UNLOCK(sc);
		return (error);
	}
	bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB);
	bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
	intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0);
	error = intsmb_stop(sc);
	if (error == 0)
		*byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
	INTSMB_UNLOCK(sc);
	return (error);
}
static int
intsmb_writew(device_t dev, u_char slave, char cmd, short word)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error;

	INTSMB_LOCK(sc);
	error = intsmb_free(sc);
	if (error) {
		INTSMB_UNLOCK(sc);
		return (error);
	}
	bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB);
	bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
	bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, word & 0xff);
	bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (word >> 8) & 0xff);
	intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0);
	error = intsmb_stop(sc);
	INTSMB_UNLOCK(sc);
	return (error);
}
static int
intsmb_readw(device_t dev, u_char slave, char cmd, short *word)
{
	struct intsmb_softc *sc = device_get_softc(dev);
	int error;

	INTSMB_LOCK(sc);
	error = intsmb_free(sc);
	if (error) {
		INTSMB_UNLOCK(sc);
		return (error);
	}
	bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB);
	bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
	intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0);
	error = intsmb_stop(sc);
	if (error == 0) {
		*word = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
		*word |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8;
	}
	INTSMB_UNLOCK(sc);
	return (error);
}