/*
 * (C) Copyright 2002 Wolfgang Grandegger, wg@denx.de.
 *
 * This driver for AMD PCnet network controllers is derived from the
 * Linux driver pcnet32.c written 1996-1999 by Thomas Bogendoerfer.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <malloc.h>
#include <net.h>
#include <asm/io.h>
#include <pci.h>

#if 0
#define	PCNET_DEBUG_LEVEL	0 /* 0=off, 1=init, 2=rx/tx */
#endif

#if PCNET_DEBUG_LEVEL > 0
#define	PCNET_DEBUG1(fmt,args...)	printf (fmt ,##args)
#if PCNET_DEBUG_LEVEL > 1
#define	PCNET_DEBUG2(fmt,args...)	printf (fmt ,##args)
#else
#define PCNET_DEBUG2(fmt,args...)
#endif
#else
#define PCNET_DEBUG1(fmt,args...)
#define PCNET_DEBUG2(fmt,args...)
#endif

#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \
    && defined(CONFIG_PCNET)

#if !defined(CONF_PCNET_79C973) && defined(CONF_PCNET_79C975)
#error "Macro for PCnet chip version is not defined!"
#endif

/*
 * Set the number of Tx and Rx buffers, using Log_2(# buffers).
 * Reasonable default values are 4 Tx buffers, and 16 Rx buffers.
 * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4).
 */
#define PCNET_LOG_TX_BUFFERS	0
#define PCNET_LOG_RX_BUFFERS	2

#define TX_RING_SIZE		(1 << (PCNET_LOG_TX_BUFFERS))
#define TX_RING_LEN_BITS	((PCNET_LOG_TX_BUFFERS) << 12)

#define RX_RING_SIZE		(1 << (PCNET_LOG_RX_BUFFERS))
#define RX_RING_LEN_BITS	((PCNET_LOG_RX_BUFFERS) << 4)

#define PKT_BUF_SZ		1544

/* The PCNET Rx and Tx ring descriptors. */
struct pcnet_rx_head {
    u32 base;
    s16 buf_length;
    s16 status;
    u32 msg_length;
    u32 reserved;
};

struct pcnet_tx_head {
    u32 base;
    s16 length;
    s16 status;
    u32 misc;
    u32 reserved;
};

/* The PCNET 32-Bit initialization block, described in databook. */
struct pcnet_init_block {
    u16 mode;
    u16 tlen_rlen;
    u8	phys_addr[6];
    u16 reserved;
    u32 filter[2];
    /* Receive and transmit ring base, along with extra bits. */
    u32 rx_ring;
    u32 tx_ring;
    u32 reserved2;
};

typedef struct pcnet_priv {
    struct pcnet_rx_head    rx_ring[RX_RING_SIZE];
    struct pcnet_tx_head    tx_ring[TX_RING_SIZE];
    struct pcnet_init_block init_block;
    /* Receive Buffer space */
    unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4];
    int cur_rx;
    int cur_tx;
} pcnet_priv_t;

static pcnet_priv_t *lp;

/* Offsets from base I/O address for WIO mode */
#define PCNET_RDP		0x10
#define PCNET_RAP		0x12
#define PCNET_RESET		0x14
#define PCNET_BDP		0x16

static u16 pcnet_read_csr (struct eth_device *dev, int index)
{
    outw (index, dev->iobase+PCNET_RAP);
    return inw (dev->iobase+PCNET_RDP);
}

static void pcnet_write_csr (struct eth_device *dev, int index, u16 val)
{
    outw (index, dev->iobase+PCNET_RAP);
    outw (val, dev->iobase+PCNET_RDP);
}

static u16 pcnet_read_bcr (struct eth_device *dev, int index)
{
    outw (index, dev->iobase+PCNET_RAP);
    return inw (dev->iobase+PCNET_BDP);
}

static void pcnet_write_bcr (struct eth_device *dev, int index, u16 val)
{
    outw (index, dev->iobase+PCNET_RAP);
    outw (val, dev->iobase+PCNET_BDP);
}

static void pcnet_reset (struct eth_device *dev)
{
    inw (dev->iobase+PCNET_RESET);
}

static int pcnet_check (struct eth_device *dev)
{
    outw (88, dev->iobase+PCNET_RAP);
    return (inw (dev->iobase+PCNET_RAP) == 88);
}

static int  pcnet_init( struct eth_device* dev, bd_t *bis);
static int  pcnet_send (struct eth_device* dev, volatile void *packet,
			int length);
static int  pcnet_recv (struct eth_device* dev);
static void pcnet_halt (struct eth_device* dev);
static int  pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_num);

#define PCI_TO_MEM(d,a) pci_phys_to_mem((pci_dev_t)d->priv, (u_long)(a))
#define PCI_TO_MEM_LE(d,a) (u32)(cpu_to_le32(PCI_TO_MEM(d,a)))

static struct pci_device_id supported[] = {
	{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE },
	{ }
};


int pcnet_initialize(bd_t *bis)
{
    pci_dev_t devbusfn;
    struct eth_device* dev;
    u16 command, status;
    int dev_nr = 0;

    PCNET_DEBUG1("\npcnet_initialize...\n");

    for (dev_nr = 0; ; dev_nr++) {

	/*
	 * Find the PCnet PCI device(s).
	 */
	if ((devbusfn = pci_find_devices(supported, dev_nr)) < 0) {
	    break;
	}

	/*
	 * Allocate and pre-fill the device structure.
	 */
	dev = (struct eth_device*) malloc(sizeof *dev);
	dev->priv = (void *)devbusfn;
	sprintf(dev->name, "pcnet#%d", dev_nr);

	/*
	 * Setup the PCI device.
	 */
	pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, (unsigned int *)&dev->iobase);
	dev->iobase &= ~0xf;

	PCNET_DEBUG1("%s: devbusfn=0x%x iobase=0x%x: ",
	       dev->name, devbusfn, dev->iobase);

	command = PCI_COMMAND_IO | PCI_COMMAND_MASTER;
	pci_write_config_word(devbusfn, PCI_COMMAND, command);
	pci_read_config_word(devbusfn, PCI_COMMAND, &status);
	if ((status & command) != command) {
	    printf("%s: Couldn't enable IO access or Bus Mastering\n",
		   dev->name);
	    free(dev);
	    continue;
	}

	pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40);

	/*
	 * Probe the PCnet chip.
	 */
	if (pcnet_probe(dev, bis, dev_nr) < 0) {
	    free(dev);
	    continue;
	}

	/*
	 * Setup device structure and register the driver.
	 */
	dev->init   = pcnet_init;
	dev->halt   = pcnet_halt;
	dev->send   = pcnet_send;
	dev->recv   = pcnet_recv;

	eth_register(dev);
    }

    udelay(10 * 1000);

    return dev_nr;
}

static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_nr)
{
    int chip_version;
    char *chipname;
#ifdef PCNET_HAS_PROM
    int i;
#endif

    /* Reset the PCnet controller */
    pcnet_reset(dev);

    /* Check if register access is working */
    if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) {
	printf("%s: CSR register access check failed\n", dev->name);
	return -1;
    }

    /* Identify the chip */
    chip_version = pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev,89) << 16);
    if ((chip_version & 0xfff) != 0x003)
       return -1;
    chip_version = (chip_version >> 12) & 0xffff;
    switch (chip_version) {
#ifdef CONFIG_PCNET_79C973
    case 0x2625:
	chipname = "PCnet/FAST III 79C973"; /* PCI */
	break;
#endif
#ifdef CONFIG_PCNET_79C975
    case 0x2627:
	chipname = "PCnet/FAST III 79C975"; /* PCI */
	break;
#endif
    default:
	printf("%s: PCnet version %#x not supported\n",
	       dev->name, chip_version);
	return -1;
    }

    PCNET_DEBUG1("AMD %s\n", chipname);

#ifdef PCNET_HAS_PROM
    /*
     * In most chips, after a chip reset, the ethernet address is read from
     * the station address PROM at the base address and programmed into the
     * "Physical Address Registers" CSR12-14.
     */
    for (i = 0; i < 3; i++) {
	unsigned int val;
	val = pcnet_read_csr(dev, i+12) & 0x0ffff;
	/* There may be endianness issues here. */
	dev->enetaddr[2*i  ] =  val       & 0x0ff;
	dev->enetaddr[2*i+1] = (val >> 8) & 0x0ff;
    }
#endif /* PCNET_HAS_PROM */

    return 0;
}

static int pcnet_init(struct eth_device* dev, bd_t *bis)
{
    int i, val;
    u32 addr;

    PCNET_DEBUG1("%s: pcnet_init...\n", dev->name);

    /* Switch pcnet to 32bit mode */
    pcnet_write_bcr (dev, 20, 2);

#ifdef CONFIG_PN62
    /* Setup LED registers */
    val = pcnet_read_bcr (dev, 2) | 0x1000;
    pcnet_write_bcr (dev, 2, val);    /* enable LEDPE */
    pcnet_write_bcr (dev, 4, 0x5080); /* 100MBit */
    pcnet_write_bcr (dev, 5, 0x40c0); /* LNKSE */
    pcnet_write_bcr (dev, 6, 0x4090); /* TX Activity */
    pcnet_write_bcr (dev, 7, 0x4084); /* RX Activity */
#endif

    /* Set/reset autoselect bit */
    val = pcnet_read_bcr (dev, 2) & ~2;
    val |= 2;
    pcnet_write_bcr (dev, 2, val);

    /* Enable auto negotiate, setup, disable fd */
    val = pcnet_read_bcr(dev, 32) & ~0x98;
    val |= 0x20;
    pcnet_write_bcr(dev, 32, val);

    /*
     * We only maintain one structure because the drivers will never
     * be used concurrently. In 32bit mode the RX and TX ring entries
     * must be aligned on 16-byte boundaries.
     */
    if (lp == NULL) {
	addr = (u32)malloc(sizeof(pcnet_priv_t) + 0x10);
	addr = (addr + 0xf) & ~0xf;
	lp = (pcnet_priv_t *)addr;
    }

    lp->init_block.mode = cpu_to_le16(0x0000);
    lp->init_block.filter[0] = 0x00000000;
    lp->init_block.filter[1] = 0x00000000;

    /*
     * Initialize the Rx ring.
     */
    lp->cur_rx = 0;
    for (i = 0; i < RX_RING_SIZE; i++) {
	lp->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]);
	lp->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ);
	lp->rx_ring[i].status = cpu_to_le16(0x8000);
	PCNET_DEBUG1("Rx%d: base=0x%x buf_length=0x%hx status=0x%hx\n",
	       i, lp->rx_ring[i].base, lp->rx_ring[i].buf_length,
	       lp->rx_ring[i].status);
    }

    /*
     * Initialize the Tx ring. The Tx buffer address is filled in as
     * needed, but we do need to clear the upper ownership bit.
     */
    lp->cur_tx = 0;
    for (i = 0; i < TX_RING_SIZE; i++) {
	lp->tx_ring[i].base = 0;
	lp->tx_ring[i].status = 0;
    }

    /*
     * Setup Init Block.
     */
    PCNET_DEBUG1("Init block at 0x%p: MAC", &lp->init_block);

    for (i = 0; i < 6; i++) {
	lp->init_block.phys_addr[i] = dev->enetaddr[i];
	PCNET_DEBUG1(" %02x", lp->init_block.phys_addr[i]);
    }

    lp->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS |
					   RX_RING_LEN_BITS);
    lp->init_block.rx_ring = PCI_TO_MEM_LE(dev, lp->rx_ring);
    lp->init_block.tx_ring = PCI_TO_MEM_LE(dev, lp->tx_ring);

    PCNET_DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n",
	   lp->init_block.tlen_rlen,
	   lp->init_block.rx_ring, lp->init_block.tx_ring);

    /*
     * Tell the controller where the Init Block is located.
     */
    addr = PCI_TO_MEM(dev, &lp->init_block);
    pcnet_write_csr(dev, 1, addr & 0xffff);
    pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff);

    pcnet_write_csr (dev, 4, 0x0915);
    pcnet_write_csr (dev, 0, 0x0001); /* start */

    /* Wait for Init Done bit */
    for (i = 10000; i > 0; i--) {
	if (pcnet_read_csr (dev, 0) & 0x0100)
	    break;
	udelay(10);
    }
    if (i <= 0) {
	printf("%s: TIMEOUT: controller init failed\n", dev->name);
	pcnet_reset (dev);
	return 0;
    }

    /*
     * Finally start network controller operation.
     */
    pcnet_write_csr (dev, 0, 0x0002);

    return 1;
}

static int pcnet_send(struct eth_device* dev, volatile void *packet, int pkt_len)
{
    int i, status;
    struct pcnet_tx_head *entry = &lp->tx_ring[lp->cur_tx];

    PCNET_DEBUG2("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len, packet);

    /* Wait for completion by testing the OWN bit */
    for (i = 1000; i > 0; i--) {
	status = le16_to_cpu(entry->status);
	if ((status & 0x8000) == 0)
	    break;
	udelay(100);
	PCNET_DEBUG2(".");
    }
    if (i <= 0) {
	printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n",
	       dev->name, lp->cur_tx, status);
	pkt_len = 0;
	goto failure;
    }

    /*
     * Setup Tx ring. Caution: the write order is important here,
     * set the status with the "ownership" bits last.
     */
    status = 0x8300;
    entry->length = le16_to_cpu(-pkt_len);
    entry->misc   = 0x00000000;
    entry->base   = PCI_TO_MEM_LE(dev, packet);
    entry->status = le16_to_cpu(status);

    /* Trigger an immediate send poll. */
    pcnet_write_csr (dev, 0, 0x0008);

 failure:
    if (++lp->cur_tx >= TX_RING_SIZE)
	lp->cur_tx = 0;

    PCNET_DEBUG2("done\n");
    return pkt_len;
}

static int pcnet_recv(struct eth_device* dev)
{
    struct pcnet_rx_head *entry;
    int pkt_len = 0;
    u16 status;

    while (1) {
	entry = &lp->rx_ring[lp->cur_rx];
	/*
	 * If we own the next entry, it's a new packet. Send it up.
	 */
	if (((status = le16_to_cpu(entry->status)) & 0x8000) != 0) {
	    break;
	}
	status >>= 8;

	if (status != 0x03) {	/* There was an error. */

	    printf("%s: Rx%d", dev->name, lp->cur_rx);
	    PCNET_DEBUG1(" (status=0x%x)", status);
	    if (status & 0x20) printf(" Frame");
	    if (status & 0x10) printf(" Overflow");
	    if (status & 0x08) printf(" CRC");
	    if (status & 0x04) printf(" Fifo");
	    printf(" Error\n");
	    entry->status &= le16_to_cpu(0x03ff);

	} else {

	    pkt_len = (le32_to_cpu(entry->msg_length) & 0xfff) - 4;
	    if (pkt_len < 60) {
		printf("%s: Rx%d: invalid packet length %d\n",
		       dev->name, lp->cur_rx, pkt_len);
	    } else {
		NetReceive(lp->rx_buf[lp->cur_rx], pkt_len);
		PCNET_DEBUG2("Rx%d: %d bytes from 0x%p\n",
		       lp->cur_rx, pkt_len, lp->rx_buf[lp->cur_rx]);
	    }
	}
	entry->status |= cpu_to_le16(0x8000);

	if (++lp->cur_rx >= RX_RING_SIZE)
	    lp->cur_rx = 0;
    }
    return pkt_len;
}

static void pcnet_halt(struct eth_device* dev)
{
    int i;

    PCNET_DEBUG1("%s: pcnet_halt...\n", dev->name);

    /* Reset the PCnet controller */
    pcnet_reset (dev);

    /* Wait for Stop bit */
    for (i = 1000; i > 0; i--) {
	if (pcnet_read_csr (dev, 0) & 0x4)
	    break;
	udelay(10);
    }
    if (i <= 0) {
	printf("%s: TIMEOUT: controller reset failed\n", dev->name);
    }
}

#endif
