From owner-svn-src-all@FreeBSD.ORG Wed Oct 10 17:13:46 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id C267E65F; Wed, 10 Oct 2012 17:13:46 +0000 (UTC) (envelope-from np@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A0E118FC0A; Wed, 10 Oct 2012 17:13:46 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q9AHDkP2068146; Wed, 10 Oct 2012 17:13:46 GMT (envelope-from np@svn.freebsd.org) Received: (from np@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q9AHDkDV068141; Wed, 10 Oct 2012 17:13:46 GMT (envelope-from np@svn.freebsd.org) Message-Id: <201210101713.q9AHDkDV068141@svn.freebsd.org> From: Navdeep Parhar Date: Wed, 10 Oct 2012 17:13:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r241399 - in head/sys/dev/cxgbe: . common X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Oct 2012 17:13:46 -0000 Author: np Date: Wed Oct 10 17:13:46 2012 New Revision: 241399 URL: http://svn.freebsd.org/changeset/base/241399 Log: Add a driver ioctl to read a byte from any device on a port's i2c bus. This lets userspace read arbitrary information from the SFP+ modules etc. on this bus. Reading multiple bytes in the same transaction isn't possible right now. I'll update the driver once the chip's firmware supports this. MFC after: 3 days Modified: head/sys/dev/cxgbe/common/common.h head/sys/dev/cxgbe/common/t4_hw.c head/sys/dev/cxgbe/t4_ioctl.h head/sys/dev/cxgbe/t4_main.c Modified: head/sys/dev/cxgbe/common/common.h ============================================================================== --- head/sys/dev/cxgbe/common/common.h Wed Oct 10 16:54:14 2012 (r241398) +++ head/sys/dev/cxgbe/common/common.h Wed Oct 10 17:13:46 2012 (r241399) @@ -521,6 +521,8 @@ int t4_enable_vi(struct adapter *adap, u bool rx_en, bool tx_en); int t4_identify_port(struct adapter *adap, unsigned int mbox, unsigned int viid, unsigned int nblinks); +int t4_i2c_rd(struct adapter *adap, unsigned int mbox, unsigned int port_id, + u8 dev_addr, u8 offset, u8 *valp); int t4_mdio_rd(struct adapter *adap, unsigned int mbox, unsigned int phy_addr, unsigned int mmd, unsigned int reg, unsigned int *valp); int t4_mdio_wr(struct adapter *adap, unsigned int mbox, unsigned int phy_addr, Modified: head/sys/dev/cxgbe/common/t4_hw.c ============================================================================== --- head/sys/dev/cxgbe/common/t4_hw.c Wed Oct 10 16:54:14 2012 (r241398) +++ head/sys/dev/cxgbe/common/t4_hw.c Wed Oct 10 17:13:46 2012 (r241399) @@ -3885,6 +3885,36 @@ int t4_fwaddrspace_write(struct adapter } /** + * t4_i2c_rd - read a byte from an i2c addressable device + * @adap: the adapter + * @mbox: mailbox to use for the FW command + * @port_id: the port id + * @dev_addr: the i2c device address + * @offset: the byte offset to read from + * @valp: where to store the value + */ +int t4_i2c_rd(struct adapter *adap, unsigned int mbox, unsigned int port_id, + u8 dev_addr, u8 offset, u8 *valp) +{ + int ret; + struct fw_ldst_cmd c; + + memset(&c, 0, sizeof(c)); + c.op_to_addrspace = htonl(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST | + F_FW_CMD_READ | + V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_I2C)); + c.cycles_to_len16 = htonl(FW_LEN16(c)); + c.u.i2c.pid_pkd = V_FW_LDST_CMD_PID(port_id); + c.u.i2c.base = dev_addr; + c.u.i2c.boffset = offset; + + ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c); + if (ret == 0) + *valp = c.u.i2c.data; + return ret; +} + +/** * t4_mdio_rd - read a PHY register through MDIO * @adap: the adapter * @mbox: mailbox to use for the FW command Modified: head/sys/dev/cxgbe/t4_ioctl.h ============================================================================== --- head/sys/dev/cxgbe/t4_ioctl.h Wed Oct 10 16:54:14 2012 (r241398) +++ head/sys/dev/cxgbe/t4_ioctl.h Wed Oct 10 17:13:46 2012 (r241399) @@ -49,6 +49,7 @@ enum { T4_GET_SGE_CONTEXT, /* get SGE context for a queue */ T4_LOAD_FW, /* flash firmware */ T4_GET_MEM, /* read memory */ + T4_GET_I2C, /* read from i2c addressible device */ }; struct t4_reg { @@ -69,6 +70,14 @@ struct t4_data { uint8_t *data; }; +struct t4_i2c_data { + uint8_t port_id; + uint8_t dev_addr; + uint8_t offset; + uint8_t len; + uint8_t data[8]; +}; + /* * A hardware filter is some valid combination of these. */ @@ -224,4 +233,5 @@ struct t4_mem_range { struct t4_sge_context) #define CHELSIO_T4_LOAD_FW _IOW('f', T4_LOAD_FW, struct t4_data) #define CHELSIO_T4_GET_MEM _IOW('f', T4_GET_MEM, struct t4_mem_range) +#define CHELSIO_T4_GET_I2C _IOWR('f', T4_GET_I2C, struct t4_i2c_data) #endif Modified: head/sys/dev/cxgbe/t4_main.c ============================================================================== --- head/sys/dev/cxgbe/t4_main.c Wed Oct 10 16:54:14 2012 (r241398) +++ head/sys/dev/cxgbe/t4_main.c Wed Oct 10 17:13:46 2012 (r241399) @@ -349,6 +349,7 @@ static int set_filter_wr(struct adapter static int del_filter_wr(struct adapter *, int); static int get_sge_context(struct adapter *, struct t4_sge_context *); static int read_card_mem(struct adapter *, struct t4_mem_range *); +static int read_i2c(struct adapter *, struct t4_i2c_data *); #ifdef TCP_OFFLOAD static int toe_capability(struct port_info *, int); #endif @@ -5170,6 +5171,27 @@ proceed: return (rc); } +static int +read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd) +{ + int rc; + + ADAPTER_LOCK_ASSERT_OWNED(sc); /* for mbox */ + + if (i2cd->len == 0 || i2cd->port_id >= sc->params.nports) + return (EINVAL); + + if (i2cd->len > 1) { + /* XXX: need fw support for longer reads in one go */ + return (ENOTSUP); + } + + rc = -t4_i2c_rd(sc, sc->mbox, i2cd->port_id, i2cd->dev_addr, + i2cd->offset, &i2cd->data[0]); + + return (rc); +} + int t4_os_find_pci_capability(struct adapter *sc, int cap) { @@ -5373,6 +5395,11 @@ t4_ioctl(struct cdev *dev, unsigned long case CHELSIO_T4_GET_MEM: rc = read_card_mem(sc, (struct t4_mem_range *)data); break; + case CHELSIO_T4_GET_I2C: + ADAPTER_LOCK(sc); + rc = read_i2c(sc, (struct t4_i2c_data *)data); + ADAPTER_UNLOCK(sc); + break; default: rc = EINVAL; }