diff options
author | Jonathan Matthew <jmatthew@cvs.openbsd.org> | 2019-05-24 05:59:14 +0000 |
---|---|---|
committer | Jonathan Matthew <jmatthew@cvs.openbsd.org> | 2019-05-24 05:59:14 +0000 |
commit | c579c3cd8d067dac63e98694dd5f9aca6b03caaf (patch) | |
tree | 4dc9cb73b0e3743fb7694d43a02844512bdab939 | |
parent | 9d79681eb99e704f399232aa0210df92073e2cb0 (diff) |
implement support for SIOCGIFSFFPAGE
i2c reads are implemented as a port register read that returns up to 32
bytes from a page.
ok dlg@
-rw-r--r-- | sys/dev/pci/if_mcx.c | 78 |
1 files changed, 77 insertions, 1 deletions
diff --git a/sys/dev/pci/if_mcx.c b/sys/dev/pci/if_mcx.c index 6c4b9cba68e..3f9b6da91d5 100644 --- a/sys/dev/pci/if_mcx.c +++ b/sys/dev/pci/if_mcx.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mcx.c,v 1.9 2019/05/23 06:51:36 jmatthew Exp $ */ +/* $OpenBSD: if_mcx.c,v 1.10 2019/05/24 05:59:13 jmatthew Exp $ */ /* * Copyright (c) 2017 David Gwynne <dlg@openbsd.org> @@ -124,11 +124,13 @@ #define MCX_REG_OP_WRITE 0 #define MCX_REG_OP_READ 1 +#define MCX_REG_PMLP 0x5002 #define MCX_REG_PMTU 0x5003 #define MCX_REG_PTYS 0x5004 #define MCX_REG_PAOS 0x5006 #define MCX_REG_PFCC 0x5007 #define MCX_REG_PPCNT 0x5008 +#define MCX_REG_MCIA 0x9014 #define MCX_ETHER_CAP_SGMII (1 << 0) #define MCX_ETHER_CAP_1000_KX (1 << 1) @@ -412,6 +414,34 @@ struct mcx_reg_pfcc { uint8_t rp_reserved6[12]; } __packed __aligned(4); +#define MCX_PMLP_MODULE_NUM_MASK 0xff +struct mcx_reg_pmlp { + uint8_t rp_rxtx; + uint8_t rp_local_port; + uint8_t rp_reserved0; + uint8_t rp_width; + uint32_t rp_lane0_mapping; + uint32_t rp_lane1_mapping; + uint32_t rp_lane2_mapping; + uint32_t rp_lane3_mapping; + uint8_t rp_reserved1[44]; +} __packed __aligned(4); + +#define MCX_MCIA_EEPROM_BYTES 32 +struct mcx_reg_mcia { + uint8_t rm_l; + uint8_t rm_module; + uint8_t rm_reserved0; + uint8_t rm_status; + uint8_t rm_i2c_addr; + uint8_t rm_page_num; + uint16_t rm_dev_addr; + uint16_t rm_reserved1; + uint16_t rm_size; + uint32_t rm_reserved2; + uint8_t rm_data[48]; +} __packed __aligned(4); + struct mcx_cmd_query_issi_in { uint16_t cmd_opcode; uint8_t cmd_reserved0[4]; @@ -1967,6 +1997,7 @@ static void mcx_start(struct ifqueue *); static void mcx_watchdog(struct ifnet *); static void mcx_media_status(struct ifnet *, struct ifmediareq *); static int mcx_media_change(struct ifnet *); +static int mcx_get_sffpage(struct ifnet *, struct if_sffpage *); static inline uint32_t mcx_rd(struct mcx_softc *, bus_size_t); @@ -5674,6 +5705,10 @@ mcx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); break; + case SIOCGIFSFFPAGE: + error = mcx_get_sffpage(ifp, (struct if_sffpage *)data); + break; + case SIOCGIFRXR: error = mcx_rxrinfo(sc, (struct if_rxrinfo *)ifr->ifr_data); break; @@ -5694,6 +5729,47 @@ mcx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) } static int +mcx_get_sffpage(struct ifnet *ifp, struct if_sffpage *sff) +{ + struct mcx_softc *sc = (struct mcx_softc *)ifp->if_softc; + struct mcx_reg_mcia mcia; + struct mcx_reg_pmlp pmlp; + int offset, error; + + /* get module number */ + memset(&pmlp, 0, sizeof(pmlp)); + pmlp.rp_local_port = 1; + error = mcx_read_hca_reg(sc, MCX_REG_PMLP, &pmlp, sizeof(pmlp)); + if (error != 0) { + printf("%s: unable to get eeprom module number\n", + DEVNAME(sc)); + return error; + } + + for (offset = 0; offset < 256; offset += MCX_MCIA_EEPROM_BYTES) { + memset(&mcia, 0, sizeof(mcia)); + mcia.rm_l = 0; + mcia.rm_module = betoh32(pmlp.rp_lane0_mapping) & + MCX_PMLP_MODULE_NUM_MASK; + mcia.rm_i2c_addr = sff->sff_addr / 2; /* apparently */ + mcia.rm_page_num = sff->sff_page; + mcia.rm_dev_addr = htobe16(offset); + mcia.rm_size = htobe16(MCX_MCIA_EEPROM_BYTES); + + error = mcx_read_hca_reg(sc, MCX_REG_MCIA, &mcia, sizeof(mcia)); + if (error != 0) { + printf("%s: unable to read eeprom at %x\n", + DEVNAME(sc), offset); + return error; + } + + memcpy(sff->sff_data + offset, mcia.rm_data, MCX_MCIA_EEPROM_BYTES); + } + + return 0; +} + +static int mcx_rxrinfo(struct mcx_softc *sc, struct if_rxrinfo *ifri) { struct if_rxring_info ifr; |