* r8169.c: Etherboot device driver for the RealTek RTL-8169 Gigabit
* Written 2003 by Timothy Legge <tlegge@rogers.com>
*
-* This program is free software; you can redistribute it and/or modify
-* it under the terms of the GNU General Public License as published by
-* the Free Software Foundation; either version 2 of the License, or
-* (at your option) any later version.
-*
-* This program is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-* GNU General Public License for more details.
-*
-* You should have received a copy of the GNU General Public License
-* along with this program; if not, write to the Free Software
-* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * SPDX-License-Identifier: GPL-2.0+
*
* Portions of this code based on:
* r8169.c: A RealTek RTL-8169 Gigabit Ethernet driver
#define ETH_ALEN MAC_ADDR_LEN
#define ETH_ZLEN 60
+#define bus_to_phys(a) pci_mem_to_phys((pci_dev_t)dev->priv, (pci_addr_t)a)
+#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, (phys_addr_t)a)
+
enum RTL8169_registers {
MAC0 = 0, /* Ethernet hardware address. */
MAR0 = 8, /* Multicast filter. */
{"RTL-8169sc/8110sc", 0x18, 0xff7e1880,},
{"RTL-8168b/8111sb", 0x30, 0xff7e1880,},
{"RTL-8168b/8111sb", 0x38, 0xff7e1880,},
+ {"RTL-8168d/8111d", 0x28, 0xff7e1880,},
+ {"RTL-8168evl/8111evl", 0x2e, 0xff7e1880,},
{"RTL-8101e", 0x34, 0xff7e1880,},
{"RTL-8100e", 0x32, 0xff7e1880,},
};
static struct pci_device_id supported[] = {
{PCI_VENDOR_ID_REALTEK, 0x8167},
+ {PCI_VENDOR_ID_REALTEK, 0x8168},
{PCI_VENDOR_ID_REALTEK, 0x8169},
{}
};
return 0;
}
+/*
+ * Cache maintenance functions. These are simple wrappers around the more
+ * general purpose flush_cache() and invalidate_dcache_range() functions.
+ */
+
+static void rtl_inval_rx_desc(struct RxDesc *desc)
+{
+ unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
+ unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN);
+
+ invalidate_dcache_range(start, end);
+}
+
+static void rtl_flush_rx_desc(struct RxDesc *desc)
+{
+ flush_cache((unsigned long)desc, sizeof(*desc));
+}
+
+static void rtl_inval_tx_desc(struct TxDesc *desc)
+{
+ unsigned long start = (unsigned long)desc & ~(ARCH_DMA_MINALIGN - 1);
+ unsigned long end = ALIGN(start + sizeof(*desc), ARCH_DMA_MINALIGN);
+
+ invalidate_dcache_range(start, end);
+}
+
+static void rtl_flush_tx_desc(struct TxDesc *desc)
+{
+ flush_cache((unsigned long)desc, sizeof(*desc));
+}
+
+static void rtl_inval_buffer(void *buf, size_t size)
+{
+ unsigned long start = (unsigned long)buf & ~(ARCH_DMA_MINALIGN - 1);
+ unsigned long end = ALIGN(start + size, ARCH_DMA_MINALIGN);
+
+ invalidate_dcache_range(start, end);
+}
+
+static void rtl_flush_buffer(void *buf, size_t size)
+{
+ flush_cache((unsigned long)buf, size);
+}
+
/**************************************************************************
RECV - Receive a frame
***************************************************************************/
ioaddr = dev->iobase;
cur_rx = tpc->cur_rx;
+
+ rtl_inval_rx_desc(&tpc->RxDescArray[cur_rx]);
+
if ((le32_to_cpu(tpc->RxDescArray[cur_rx].status) & OWNbit) == 0) {
if (!(le32_to_cpu(tpc->RxDescArray[cur_rx].status) & RxRES)) {
unsigned char rxdata[RX_BUF_LEN];
length = (int) (le32_to_cpu(tpc->RxDescArray[cur_rx].
status) & 0x00001FFF) - 4;
+ rtl_inval_buffer(tpc->RxBufferRing[cur_rx], length);
memcpy(rxdata, tpc->RxBufferRing[cur_rx], length);
NetReceive(rxdata, length);
tpc->RxDescArray[cur_rx].status =
cpu_to_le32(OWNbit + RX_BUF_SIZE);
tpc->RxDescArray[cur_rx].buf_addr =
- cpu_to_le32((unsigned long)tpc->RxBufferRing[cur_rx]);
+ cpu_to_le32(bus_to_phys(tpc->RxBufferRing[cur_rx]));
+ rtl_flush_rx_desc(&tpc->RxDescArray[cur_rx]);
} else {
puts("Error Rx");
}
/**************************************************************************
SEND - Transmit a frame
***************************************************************************/
-static int rtl_send(struct eth_device *dev, volatile void *packet, int length)
+static int rtl_send(struct eth_device *dev, void *packet, int length)
{
/* send the packet to destination */
/* point to the current txb incase multiple tx_rings are used */
ptxb = tpc->Tx_skbuff[entry * MAX_ETH_FRAME_SIZE];
memcpy(ptxb, (char *)packet, (int)length);
+ rtl_flush_buffer(ptxb, length);
while (len < ETH_ZLEN)
ptxb[len++] = '\0';
tpc->TxDescArray[entry].buf_Haddr = 0;
- tpc->TxDescArray[entry].buf_addr = cpu_to_le32((unsigned long)ptxb);
+ tpc->TxDescArray[entry].buf_addr = cpu_to_le32(bus_to_phys(ptxb));
if (entry != (NUM_TX_DESC - 1)) {
tpc->TxDescArray[entry].status =
cpu_to_le32((OWNbit | FSbit | LSbit) |
cpu_to_le32((OWNbit | EORbit | FSbit | LSbit) |
((len > ETH_ZLEN) ? len : ETH_ZLEN));
}
+ rtl_flush_tx_desc(&tpc->TxDescArray[entry]);
RTL_W8(TxPoll, 0x40); /* set polling bit */
tpc->cur_tx++;
to = currticks() + TX_TIMEOUT;
- while ((le32_to_cpu(tpc->TxDescArray[entry].status) & OWNbit)
+ do {
+ rtl_inval_tx_desc(&tpc->TxDescArray[entry]);
+ } while ((le32_to_cpu(tpc->TxDescArray[entry].status) & OWNbit)
&& (currticks() < to)); /* wait */
if (currticks() >= to) {
#ifdef DEBUG_RTL8169_TX
- puts ("tx timeout/error\n");
- printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);
+ puts("tx timeout/error\n");
+ printf("%s elapsed time : %lu\n", __func__, currticks()-stime);
#endif
ret = 0;
} else {
tpc->cur_rx = 0;
- RTL_W32(TxDescStartAddrLow, (unsigned long)tpc->TxDescArray);
+ RTL_W32(TxDescStartAddrLow, bus_to_phys(tpc->TxDescArray));
RTL_W32(TxDescStartAddrHigh, (unsigned long)0);
- RTL_W32(RxDescStartAddrLow, (unsigned long)tpc->RxDescArray);
+ RTL_W32(RxDescStartAddrLow, bus_to_phys(tpc->RxDescArray));
RTL_W32(RxDescStartAddrHigh, (unsigned long)0);
/* RTL-8169sc/8110sc or later version */
RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000);
#ifdef DEBUG_RTL8169
- printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);
+ printf("%s elapsed time : %lu\n", __func__, currticks()-stime);
#endif
}
tpc->RxBufferRing[i] = &rxb[i * RX_BUF_SIZE];
tpc->RxDescArray[i].buf_addr =
- cpu_to_le32((unsigned long)tpc->RxBufferRing[i]);
+ cpu_to_le32(bus_to_phys(tpc->RxBufferRing[i]));
+ rtl_flush_rx_desc(&tpc->RxDescArray[i]);
}
#ifdef DEBUG_RTL8169
- printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);
+ printf("%s elapsed time : %lu\n", __func__, currticks()-stime);
#endif
}
txb[5] = dev->enetaddr[5];
#ifdef DEBUG_RTL8169
- printf ("%s elapsed time : %d\n", __FUNCTION__, currticks()-stime);
+ printf("%s elapsed time : %lu\n", __func__, currticks()-stime);
#endif
return 0;
}
static int rtl_init(struct eth_device *dev, bd_t *bis)
{
static int board_idx = -1;
- static int printed_version = 0;
int i, rc;
int option = -1, Cap10_100 = 0, Cap1000 = 0;
board_idx++;
- printed_version = 1;
-
/* point to private storage */
tpc = &tpx;
/* Get MAC address. FIXME: read EEPROM */
for (i = 0; i < MAC_ADDR_LEN; i++)
- bis->bi_enetaddr[i] = dev->enetaddr[i] = RTL_R8(MAC0 + i);
+ dev->enetaddr[i] = RTL_R8(MAC0 + i);
#ifdef DEBUG_RTL8169
printf("chipset = %d\n", tpc->chipset);
int idx=0;
while(1){
+ unsigned int region;
+ u16 device;
+
/* Find RTL8169 */
if ((devno = pci_find_devices(supported, idx++)) < 0)
break;
- pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase);
+ pci_read_config_word(devno, PCI_DEVICE_ID, &device);
+ switch (device) {
+ case 0x8168:
+ region = 2;
+ break;
+
+ default:
+ region = 1;
+ break;
+ }
+
+ pci_read_config_dword(devno, PCI_BASE_ADDRESS_0 + (region * 4), &iobase);
iobase &= ~0xf;
debug ("rtl8169: REALTEK RTL8169 @0x%x\n", iobase);
dev = (struct eth_device *)malloc(sizeof *dev);
+ if (!dev) {
+ printf("Can not allocate memory of rtl8169\n");
+ break;
+ }
+ memset(dev, 0, sizeof(*dev));
sprintf (dev->name, "RTL8169#%d", card_number);
dev->priv = (void *) devno;