+static int rtmdio_map_sds_register(int page, int regnum, int *sds_page, int *sds_regnum)
+{
+ /*
+ * For the SerDes PHY simulate a register mapping like common RealTek PHYs do. Always
+ * keep the common registers 0x00-0x0f in place and map the SerDes registers into the
+ * upper vendor specific registers 0x10-0x17 according to the page select register
+ * (0x1f). That gives a register mapping as follows:
+ *
+ * +-----------------------+-----------------------+---------------+-----------------+
+ * | reg 0x00-0x0f | reg 0x10-0x17 | reg 0x18-0x1e | reg 0x1f |
+ * +-----------------------+-----------------------+---------------+-----------------+
+ * | SerDes fiber page (2) | real SerDes registers | zero | SerDes page |
+ * | registers 0x00-0x0f | in packages of 8 | | select register |
+ * +-----------------------+-----------------------+---------------+-----------------+
+ */
+
+ if (regnum < 16) {
+ *sds_page = 2;
+ *sds_regnum = regnum;
+ } else if (regnum < 24) {
+ *sds_page = page / 4;
+ *sds_regnum = 8 * (page % 4) + (regnum - 16);
+ } else
+ return 0;
+
+ return 1;
+}
+
+static int rtmdio_read_sds_phy(struct rtmdio_bus_priv *priv, int sds, int page, int regnum)
+{
+ int ret, sds_page, sds_regnum;
+
+ ret = rtmdio_map_sds_register(page, regnum, &sds_page, &sds_regnum);
+ if (ret)
+ ret = priv->read_sds_phy(sds, sds_page, sds_regnum);
+ pr_debug("rd_SDS(sds=%d, pag=%d, reg=%d) = %d\n", sds, page, regnum, ret);
+
+ return ret;
+}
+
+static int rtmdio_write_sds_phy(struct rtmdio_bus_priv *priv, int sds, int page, int regnum, u16 val)
+{
+ int ret, sds_page, sds_regnum;
+
+ ret = rtmdio_map_sds_register(page, regnum, &sds_page, &sds_regnum);
+ if (ret)
+ ret = priv->write_sds_phy(sds, sds_page, sds_regnum, val);
+ pr_debug("wr_SDS(sds=%d, pag=%d, reg=%d, val=%d) err = %d\n", sds, page, regnum, val, ret);
+
+ return ret;
+}
+