+static int w5100_readbuf(struct w5100_priv *priv, u16 offset, u8 *buf, int len)
+{
+ u16 addr;
+ int remain = 0;
+ int ret;
+
+ offset %= W5100_RX_MEM_SIZE;
+ addr = W5100_RX_MEM_START + offset;
+
+ if (offset + len > W5100_RX_MEM_SIZE) {
+ remain = (offset + len) % W5100_RX_MEM_SIZE;
+ len = W5100_RX_MEM_SIZE - offset;
+ }
+
+ ret = w5100_readbulk(priv, addr, buf, len);
+ if (ret || !remain)
+ return ret;
+
+ return w5100_readbulk(priv, W5100_RX_MEM_START, buf + len, remain);
+}
+
+static int w5100_writebuf(struct w5100_priv *priv, u16 offset, const u8 *buf,
+ int len)
+{
+ u16 addr;
+ int ret;
+ int remain = 0;
+
+ offset %= W5100_TX_MEM_SIZE;
+ addr = W5100_TX_MEM_START + offset;
+
+ if (offset + len > W5100_TX_MEM_SIZE) {
+ remain = (offset + len) % W5100_TX_MEM_SIZE;
+ len = W5100_TX_MEM_SIZE - offset;
+ }
+
+ ret = w5100_writebulk(priv, addr, buf, len);
+ if (ret || !remain)
+ return ret;
+
+ return w5100_writebulk(priv, W5100_TX_MEM_START, buf + len, remain);
+}
+
+static int w5100_reset(struct w5100_priv *priv)
+{
+ if (priv->ops->reset)
+ return priv->ops->reset(priv->ndev);
+
+ w5100_write(priv, W5100_MR, MR_RST);
+ mdelay(5);
+ w5100_write(priv, W5100_MR, MR_PB);
+
+ return 0;
+}
+