If I get the SMBUS specs right there exist 5 command types on the SMBUS:
- Quick (send address and a r/w bit)
- Send/Receive (send address and r/w a byte)
- Write/Read (send address, command byte and r/w a byte)
- Write/Read Word
- Write/Read BLOCK
Now I'm trying to communicate with the Hawk ISMP on an IBM eServer x335.
This device uses a request/response communication where we first send
a stream of bytes to the device and then read back a stream of bytes.
This has to be done with the Send/Receive protocol.
The SMBUS controller on this machine is piixpm and it looks like this
controllers driver at least has no support for the Send/Receive protocol.
Taking the comments from i2c/i2c_io.h and the implementation
from i2c/i2c_exec.c it looks like
- Send is: iic_exec() with I2C_OP_WRITE_WITH_STOP, cmdlen = 0, len = 1
- Receive is: iic_exec() with I2C_OP_READ_WITH_STOP, cmdlen = 0, len = 1
The piixpm doesn't make a difference between the "cmdlen = 0, len = 1" and
the "cmdlen = 1, len = 1" case. Both end up as PIIX_SMB_HC_CMD_BDATA, the
Write/Read protocol.
Send seems to work as "cmdlen = 1, len = 0", but this is not used by
iic_smbus_send_byte() which uses "cmdlen = 0, len = 1".
So the final question: Does this change to pci/piixpm.c look ok?
Looks like alipm.c and ichsmb.c have the same problem ...
--
Juergen Hannken-Illjes - hannken%eis.cs.tu-bs.de@localhost - TU Braunschweig
(Germany)
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/piixpm.c,v
retrieving revision 1.33
diff -p -u -8 -r1.33 piixpm.c
--- piixpm.c 27 Jul 2010 05:29:05 -0000 1.33
+++ piixpm.c 10 Feb 2011 10:41:35 -0000
@@ -311,17 +311,18 @@ piixpm_i2c_exec(void *cookie, i2c_op_t o
}
DPRINTF(("%s: exec: st 0x%d\n", device_xname(sc->sc_dev), st & 0xff));
if (st & PIIX_SMB_HS_BUSY)
return (1);
if (cold || sc->sc_poll)
flags |= I2C_F_POLL;
- if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 2)
+ if (!I2C_OP_STOP_P(op) || cmdlen > 1 || len > 2 ||
+ (cmdlen == 0 && len > 1))
return (1);
/* Setup transfer */
sc->sc_i2c_xfer.op = op;
sc->sc_i2c_xfer.buf = buf;
sc->sc_i2c_xfer.len = len;
sc->sc_i2c_xfer.flags = flags;
sc->sc_i2c_xfer.error = 0;
@@ -335,27 +336,30 @@ piixpm_i2c_exec(void *cookie, i2c_op_t o
if (cmdlen > 0)
/* Set command byte */
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
PIIX_SMB_HCMD, b[0]);
if (I2C_OP_WRITE_P(op)) {
/* Write data */
b = buf;
- if (len > 0)
+ if (cmdlen == 0 && len == 1)
+ bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
+ PIIX_SMB_HCMD, b[0]);
+ else if (len > 0)
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
PIIX_SMB_HD0, b[0]);
if (len > 1)
bus_space_write_1(sc->sc_smb_iot, sc->sc_smb_ioh,
PIIX_SMB_HD1, b[1]);
}
/* Set SMBus command */
- if (len == 0) {
- if (cmdlen == 0)
+ if (cmdlen == 0) {
+ if (len == 0)
ctl = PIIX_SMB_HC_CMD_QUICK;
else
ctl = PIIX_SMB_HC_CMD_BYTE;
} else if (len == 1)
ctl = PIIX_SMB_HC_CMD_BDATA;
else if (len == 2)
ctl = PIIX_SMB_HC_CMD_WDATA;
!DSPAM:4d53c1d72271759813121!