tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

SMBUS missing Send/Receive protocol?



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;


Home | Main Index | Thread Index | Old Index