[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [microblaze-uclinux] EthernetLite driver
Hi Pavel,
Sorry for that - I forgot to include the patch on the
drivers/net/Makefile. Can you try the attached new patch?
It should build, but as I said it doesn't quite work yet - close but not
quite.
Cheers,
John
Pavel Ivanchenko wrote:
Hello, John.
Thanks for you work!
I apply patch and it create
uClinux-dist/linux-2.4.x/drivers/net/xilinx_emaclite/ directory with
files and string in the menuconfig, but make no have effect with driver
sources. I try include driver as module and integrate to kernel, after
make, image size exactly coincides.
I try add next strings to uClinux-dist/linux-2.4.x/drivers/net/Makefile:
mod-subdirs += xilinx_emaclite
subdir-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite
obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite/xilinx_emaclite.o
After "make dep" there was is created ".depend" file in
/xilinx_emaclite/, but make unsuccessful. Last screen with error include.
----- Original Message ----- From: "John Williams"
<jwilliams@xxxxxxxxxxxxxx>
To: <microblaze-uclinux@xxxxxxxxxxxxxx>
Sent: Wednesday, December 07, 2005 6:24 AM
Subject: [microblaze-uclinux] EthernetLite driver
Hi folks,
Inspired by Pavel's efforts[1], I recently did a quick hack at a driver
for the Xilinx EthernetLite core. It is based on the driver for the
full ethernet MAC, with lots of trimming.
Status is that TX packets work correctly, but there's still something
broken on the RX side.
I don't have any time to keep working on it right now, so I thought I'd
throw it out there and see if someone wants to pick it up and run with
it.
To that end, find attached a patch file that creates
drivers/net/xilinx_emaclite/*, and adds the option to build it in the
MicroBlaze menuconfig.
Obviously you need to build a microblaze system with the EMACLITE - no
rocket science there, just remember to disconnect the MII data and clock
lines (EMACLITE doesn't do MII), and IIRC you have to disconnect the
TX_ER signal.
Cheers,
John
[1] Pavel, I decided to start from an existing "real" driver, rather
than the Linux Device Drivers template, because it's my experience that
there's a pretty big gap between the theoretical devices they describe,
and the workings of a real ethernet controller. LDD is great for
learning the concepts, but you can't beat a proper driver as a
template/starting point.
------------------------------------------------------------------------
Index: arch/microblaze/config.in
===================================================================
--- arch/microblaze/config.in (revision 309)
+++ arch/microblaze/config.in (working copy)
@@ -110,6 +110,7 @@
tristate 'GPIO driver' CONFIG_XILINX_GPIO
tristate 'Ethernet driver' CONFIG_XILINX_ENET
+ tristate 'Ethernet Lite driver' CONFIG_XILINX_EMACLITE
tristate 'SystemAce driver' CONFIG_XILINX_SYSACE
bool 'Kernel cmdline support (needs new bootloader)' CONFIG_MBVANILLA_CMDLINE
Index: drivers/net/xilinx_emaclite/adapter.c
===================================================================
--- drivers/net/xilinx_emaclite/adapter.c (revision 0)
+++ drivers/net/xilinx_emaclite/adapter.c (revision 0)
@@ -0,0 +1,655 @@
+/*
+ * adapter.c
+ *
+ * Xilinx Ethernet MAC Lite Adapter component to interface XEmac component
+ * to Linux
+ *
+ * Author: John Williams <john.williams@xxxxxxxxxxxxx>
+ *
+ * based on Xilinx enet driver which is by
+ *
+ * Author: MontaVista Software, Inc.
+ * source@xxxxxxxxxx
+ *
+ * 2002 (c) MontaVista, Software, Inc. This file is licensed under the terms
+ * of the GNU General Public License version 2.1. This program is licensed
+ * "as is" without any warranty of any kind, whether express or implied.
+ */
+
+/*
+ * This driver is a bit unusual in that it is composed of two logical
+ * parts where one part is the OS independent code and the other part is
+ * the OS dependent code. Xilinx provides their drivers split in this
+ * fashion. This file represents the Linux OS dependent part known as
+ * the Linux adapter. The other files in this directory are the OS
+ * independent files as provided by Xilinx with no changes made to them.
+ * The names exported by those files begin with XEmacLite_. All functions
+ * in this file that are called by Linux have names that begin with
+ * xemaclite_. The functions in this file that have Handler in their name
+ * are registered as callbacks with the underlying Xilinx OS independent
+ * layer. Any other functions are static helper functions.
+ */
+
+#include <linux/module.h>
+#include <asm/uaccess.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/mii.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/pgalloc.h>
+#include <linux/ethtool.h>
+
+#include <xbasic_types.h>
+#include "xemaclite.h"
+#include "xemaclite_i.h"
+#include "xipif_v1_23_b.h"
+
+#define DRIVER_NAME "Xilinx Eth MACLite driver"
+#define DRIVER_VERSION "1.0"
+
+MODULE_AUTHOR("John Williams <john.williams@xxxxxxxxxxxxx>");
+MODULE_DESCRIPTION(DRIVER_NAME);
+MODULE_LICENSE("GPL");
+
+/* FIXME hardcoded MAC addresses */
+#define CONFIG_XILINX_ETHERNETLITE_0_MACADDR {0x00, 0x00, 0xC0, 0xA3, 0xE5, 0x44}
+#define CONFIG_XILINX_ETHERNETLITE_1_MACADDR {0x00, 0x00, 0xC0, 0xA3, 0xE5, 0x45}
+#define CONFIG_XILINX_ETHERNETLITE_2_MACADDR {0x00, 0x00, 0xC0, 0xA3, 0xE5, 0x46}
+
+#define TX_TIMEOUT (60*HZ) /* Transmission timeout is 60 seconds. */
+
+struct ethernet_desc {
+ unsigned baseaddr;
+ unsigned irq;
+ unsigned char macaddr[6];
+};
+
+static struct ethernet_desc ether_table[] = {
+#ifdef CONFIG_XILINX_ETHERNETLITE_0_INSTANCE
+ {CONFIG_XILINX_ETHERNETLITE_0_BASEADDR,
+ CONFIG_XILINX_ETHERNETLITE_0_IRQ,
+ CONFIG_XILINX_ETHERNETLITE_0_MACADDR },
+#endif
+#ifdef CONFIG_XILINX_ETHERNETLITE_1_INSTANCE
+ {CONFIG_XILINX_ETHERNETLITE_1_BASEADDR,
+ CONFIG_XILINX_ETHERNETLITE_1_IRQ,
+ CONFIG_XILINX_ETHERNETLITE_1_MACADDR },
+#endif
+#ifdef CONFIG_XILINX_ETHERNETLITE_2_INSTANCE
+ {CONFIG_XILINX_ETHERNETLITE_2_BASEADDR,
+ CONFIG_XILINX_ETHERNETLITE_2_IRQ,
+ CONFIG_XILINX_ETHERNETLITE_2_MACADDR },
+#endif
+};
+
+static int num_ether_devices = sizeof(ether_table)/sizeof(struct ethernet_desc);
+
+#define ALIGNMENT 4
+
+/* BUFFER_ALIGN(adr) calculates the number of bytes to the next alignment. */
+#define BUFFER_ALIGN(adr) ((ALIGNMENT - ((u32) adr)) % ALIGNMENT)
+
+/* physical to virtual pointer conversion */
+#define P_TO_V(InstancePtr, p) \
+ ((p) ? \
+ ((InstancePtr)->VirtPtr + ((u32)(p) - (u32)(InstancePtr)->PhyPtr)) : \
+ 0)
+
+int bh_entry = 0;
+
+/*
+ * Our private per device data. When a net_device is allocated we will
+ * ask for enough extra space for this.
+ */
+struct net_local {
+ struct list_head rcv;
+ struct list_head xmit;
+
+ struct net_device_stats stats; /* Statistics for this device */
+ struct net_device *next_dev; /* The next device in dev_list */
+ struct net_device *dev; /* this device */
+ u32 index; /* Which interface is this */
+ XInterruptHandler Isr; /* Pointer to the XEmac ISR routine */
+ u8 mii_addr; /* The MII address of the PHY */
+ /*
+ * The underlying OS independent code needs space as well. A
+ * pointer to the following XEmacLite structure will be passed to
+ * any XEmacLite_ function that requires it. However, we treat the
+ * data as an opaque object in this file (meaning that we never
+ * reference any of the fields inside of the structure).
+ */
+ XEmacLite EmacLite;
+
+ void *desc_space;
+ dma_addr_t desc_space_handle;
+ int desc_space_size;
+
+ u8 *ddrVirtPtr;
+ u32 ddrOffset;
+ u32 ddrSize;
+
+ struct sk_buff* deferred_skb;
+};
+
+/* List of devices we're handling and a lock to give us atomic access. */
+static struct net_device *dev_list = NULL;
+static spinlock_t dev_lock = SPIN_LOCK_UNLOCKED;
+
+/* for exclusion of all program flows (processes, ISRs and BHs) possible to share data with current one */
+static spinlock_t reset_lock = SPIN_LOCK_UNLOCKED;
+
+/* Helper function to determine if a given XEmac error warrants a reset. */
+extern inline int
+status_requires_reset(XStatus s)
+{
+ return (s == XST_DMA_ERROR || s == XST_FIFO_ERROR ||
+ s == XST_RESET_ERROR || s == XST_DMA_SG_NO_LIST ||
+ s == XST_DMA_SG_LIST_EMPTY);
+}
+
+/* BH statics */
+LIST_HEAD(receivedQueue);
+static spinlock_t rcvSpin = SPIN_LOCK_UNLOCKED;
+LIST_HEAD(sentQueue);
+static spinlock_t xmitSpin = SPIN_LOCK_UNLOCKED;
+
+/* SAATODO: This function will be moved into the Xilinx code. */
+/*****************************************************************************/
+/**
+*
+* Lookup the device configuration based on the emac instance. The table
+* EmacConfigTable contains the configuration info for each device in the system.
+*
+* @param Instance is the index of the emac being looked up.
+*
+* @return
+*
+* A pointer to the configuration table entry corresponding to the given
+* device ID, or NULL if no match is found.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XEmacLite_Config *
+XEmacLite_GetConfig(int Instance)
+{
+ if (Instance < 0 || Instance >= CONFIG_XILINX_ETHERNETLITE_NUM_INSTANCES) {
+ return NULL;
+ }
+
+ return &XEmacLite_ConfigTable[Instance];
+}
+
+/*
+ * The following are notes regarding the critical sections in this
+ * driver and how they are protected.
+ *
+ * dev_list
+ * There is a spinlock protecting the device list. It isn't really
+ * necessary yet because the list is only manipulated at init and
+ * cleanup, but it's there because it is basically free and if we start
+ * doing hot add and removal of ethernet devices when the FPGA is
+ * reprogrammed while the system is up, we'll need to protect the list.
+ *
+ * XEmacLite_EnableInterrupts, XEmacLite_DisableInterrupts and XEmacLite_SetOptions are not thread safe.
+ * These functions are called from xemaclite_open(), xemaclite_close(), reset(),
+ * and xemaclite_set_multicast_list(). xemaclite_open() and xemaclite_close()
+ * should be safe because when they do start and stop, they don't have
+ * interrupts or timers enabled. The other side is that they won't be
+ * called while a timer or interrupt is being handled.
+ *
+ * XEmacLite_PhyRead and XEmacLite_PhyWrite are not thread safe.
+ * These functions are called from get_phy_status(), xemaclite_ioctl() and
+ * probe(). probe() is only called from xemaclite_init() so it is not an
+ * issue (nothing is really up and running yet). get_phy_status() is
+ * called from both poll_mii() (a timer bottom half) and xemaclite_open().
+ * These shouldn't interfere with each other because xemaclite_open() is
+ * what starts the poll_mii() timer. xemaclite_open() and xemaclite_ioctl()
+ * should be safe as well because they will be sequential. That leaves
+ * the interaction between poll_mii() and xemaclite_ioctl(). While the
+ * timer bottom half is executing, a new ioctl won't come in so that is
+ * taken care of. That leaves the one case of the poll_mii timer
+ * popping while handling an ioctl. To take care of that case, the
+ * timer is deleted when the ioctl comes in and then added back in after
+ * the ioctl is finished.
+ */
+
+typedef enum DUPLEX { UNKNOWN_DUPLEX, HALF_DUPLEX, FULL_DUPLEX } DUPLEX;
+static void
+reset(struct net_device *dev, DUPLEX duplex)
+{
+ struct net_local *lp = (struct net_local *) dev->priv;
+ u32 Options;
+ int dma_works;
+ int i;
+ XEmacLite_Config *cfg=lp->EmacLite.ConfigPtr;
+
+ /* Shouldn't really be necessary, but shouldn't hurt. */
+ netif_stop_queue(dev);
+
+ printk("reset disable\n");
+
+ XEmacLite_DisableInterrupts(&lp->EmacLite);
+ printk("reset enable\n");
+ XEmacLite_EnableInterrupts(&lp->EmacLite);
+
+ if (lp->deferred_skb) {
+ dev_kfree_skb(lp->deferred_skb);
+ lp->deferred_skb = NULL;
+ lp->stats.tx_errors++;
+ }
+
+ dev->trans_start = 0xffffffff - TX_TIMEOUT - TX_TIMEOUT; /* to exclude tx timeout */
+
+ /* We're all ready to go. Start the queue in case it was stopped. */
+ if (!bh_entry)
+ netif_wake_queue(dev);
+}
+
+/*
+ * This routine is registered with the OS as the function to call when
+ * the EMAC interrupts. It in turn, calls the Xilinx OS independent
+ */
+static void
+xemaclite_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct net_local *lp = (struct net_local *) dev->priv;
+
+ /* Call it. */
+ (*(lp->Isr)) (&lp->EmacLite);
+}
+
+static int
+xemaclite_open(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *) dev->priv;
+ int retval;
+
+ /*
+ * Just to be safe, stop the device first.
+ */
+ printk("open disable\n");
+ XEmacLite_DisableInterrupts(&lp->EmacLite);
+
+ /* Set the MAC address each time opened. */
+ XEmacLite_SetMacAddress(&lp->EmacLite, dev->dev_addr);
+
+ /* Grab the IRQ */
+ retval = request_irq(dev->irq, &xemaclite_interrupt, 0, dev->name, dev);
+ if (retval) {
+ printk(KERN_ERR
+ "%s: Could not allocate interrupt %d.\n",
+ dev->name, dev->irq);
+ return retval;
+ }
+
+ INIT_LIST_HEAD(&(lp->rcv));
+ INIT_LIST_HEAD(&(lp->xmit));
+
+ printk("open enable\n");
+ if (XEmacLite_EnableInterrupts(&lp->EmacLite) != XST_SUCCESS) {
+ printk(KERN_ERR "%s: Could not start device.\n", dev->name);
+ free_irq(dev->irq, dev);
+ return -EBUSY;
+ }
+
+ /* We're ready to go. */
+ MOD_INC_USE_COUNT;
+ netif_start_queue(dev);
+
+ return 0;
+}
+static int
+xemaclite_close(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *) dev->priv;
+ unsigned long flags;
+
+ netif_stop_queue(dev);
+ printk("close disable\n");
+ XEmacLite_DisableInterrupts(&lp->EmacLite);
+
+ free_irq(dev->irq, dev);
+
+ spin_lock_irqsave(rcvSpin, flags);
+ list_del(&(lp->rcv));
+ spin_unlock_irqrestore(rcvSpin, flags);
+ spin_lock_irqsave(xmitSpin, flags);
+ list_del(&(lp->xmit));
+ spin_unlock_irqrestore(xmitSpin, flags);
+
+ MOD_DEC_USE_COUNT;
+ return 0;
+}
+static struct net_device_stats *
+xemaclite_get_stats(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *) dev->priv;
+ return &lp->stats;
+}
+
+static int
+xemaclite_Send(struct sk_buff *orig_skb, struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *) dev->priv;
+ struct sk_buff *new_skb;
+ unsigned int len, align;
+ unsigned long flags;
+
+ len = orig_skb->len;
+
+ new_skb = orig_skb;
+
+ spin_lock_irqsave(reset_lock, flags);
+ if (XEmacLite_Send(&lp->EmacLite, (u8 *) new_skb->data, len) != XST_SUCCESS) {
+ netif_stop_queue(dev);
+ lp->deferred_skb = new_skb;
+ spin_unlock_irqrestore(reset_lock, flags);
+ return 0;
+ }
+ spin_unlock_irqrestore(reset_lock, flags);
+
+ lp->stats.tx_bytes += len;
+ dev_kfree_skb(new_skb);
+ dev->trans_start = jiffies;
+
+ return 0;
+}
+
+/* The callback function for completed frames sent. */
+static void
+SendHandler(void *CallbackRef)
+{
+ struct net_device *dev = (struct net_device *) CallbackRef;
+ struct net_local *lp = (struct net_local *) dev->priv;
+
+ if (lp->deferred_skb) {
+ if (XEmacLite_Send(&lp->EmacLite, (u8 *) lp->deferred_skb->data, lp->deferred_skb->len) != XST_SUCCESS) {
+ return;
+ } else {
+ dev_kfree_skb(lp->deferred_skb);
+ lp->deferred_skb = NULL;
+ netif_wake_queue(dev);
+ }
+ }
+ lp->stats.tx_packets++;
+}
+
+static void
+xemaclite_tx_timeout(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *) dev->priv;
+ unsigned long flags;
+
+ printk("%s: Exceeded transmit timeout of %lu ms.\n",
+ dev->name, TX_TIMEOUT * 1000UL / HZ);
+
+ lp->stats.tx_errors++;
+ spin_lock_irqsave(reset_lock, flags);
+ reset(dev, UNKNOWN_DUPLEX);
+ spin_unlock_irqrestore(reset_lock, flags);
+}
+
+/* The callback function for frames received. */
+static void
+RecvHandler(void *CallbackRef)
+{
+ struct net_device *dev = (struct net_device *) CallbackRef;
+ struct net_local *lp = (struct net_local *) dev->priv;
+ struct sk_buff *skb;
+ unsigned int align;
+ u32 len;
+ XStatus Result;
+
+ len = XEL_MAX_FRAME_SIZE;
+ if (!(skb = /*dev_ */ alloc_skb(len + ALIGNMENT, GFP_ATOMIC))) {
+ /* Couldn't get memory. */
+ lp->stats.rx_dropped++;
+ printk(KERN_ERR "%s: Could not allocate receive buffer.\n",
+ dev->name);
+ return;
+ }
+
+ /*
+ * A new skb should have the data halfword aligned, but this code is
+ * here just in case that isn't true... Calculate how many
+ * bytes we should reserve to get the data to start on a word
+ * boundary. */
+ align = BUFFER_ALIGN(skb->data);
+ if (align)
+ skb_reserve(skb, align);
+
+ skb_reserve(skb,2);
+
+ len = XEmacLite_Recv(&lp->EmacLite, (u8 *) skb->data);
+ printk("rcv 0x%08x\n",len);
+
+ if (!len) {
+
+ lp->stats.rx_errors++;
+ dev_kfree_skb(skb);
+ //printk(KERN_ERR "%s: Could not receive buffer\n",dev->name);
+ spin_lock(reset_lock);
+ //reset(dev, UNKNOWN_DUPLEX);
+ spin_unlock(reset_lock);
+
+ return;
+ }
+
+ skb_put(skb, len); /* Tell the skb how much data we got. */
+ skb->dev = dev; /* Fill out required meta-data. */
+
+
+ skb->protocol = eth_type_trans(skb, dev);
+ skb->ip_summed = CHECKSUM_NONE;
+
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes += len;
+
+ netif_rx(skb); /* Send the packet upstream. */
+}
+
+/* Take kernel cmdline option macaddr=... and set MAC address */
+static int __init xilinx_emac_hw_addr_setup(char *addrs)
+{
+ unsigned int hw_addr[6];
+ int count;
+ static int interface=0;
+
+ /* Scan the kernel param for HW MAC address */
+ count=sscanf(addrs, "%2x:%2x:%2x:%2x:%2x:%2x",hw_addr+0, hw_addr+1,
+ hw_addr+2, hw_addr+3,
+ hw_addr+4, hw_addr+5);
+ /* Did we get 6 hex digits? */
+ if(count!=6)
+ return 0;
+
+ for(count=0;count<6;count++)
+ {
+ ether_table[interface].macaddr[count] = hw_addr[count] & 0xFF;
+ }
+
+ /* Increase interface number, for next time */
+ interface++;
+ return 1;
+}
+
+
+static int
+xemaclite_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct net_local *lp = (struct net_local *) dev->priv;
+ /* mii_ioctl_data has 4 u16 fields: phy_id, reg_num, val_in & val_out */
+ struct mii_ioctl_data *data = (struct mii_ioctl_data *) &rq->ifr_data;
+
+ struct hw_addr_data *hw_addr= (struct sockaddr *) &rq->ifr_hwaddr;
+
+ XStatus ret;
+ unsigned long flags;
+
+ XStatus Result;
+
+ switch (cmd) {
+ case SIOCETHTOOL:
+ return -EIO;
+
+ case SIOCSIFHWADDR:
+ {
+ printk(KERN_INFO "%s: SIOCSIFHWADDR\n", dev->name);
+
+ /* Copy MAC address in from user space*/
+ copy_from_user(dev->dev_addr, (void *)hw_addr, IFHWADDRLEN);
+ XEmacLite_SetMacAddress(&lp->EmacLite, dev->dev_addr);
+ break;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static void
+remove_head_dev(void)
+{
+ struct net_local *lp;
+ struct net_device *dev;
+ XEmacLite_Config *cfg;
+
+ /* Pull the head off of dev_list. */
+ spin_lock(&dev_lock);
+ dev = dev_list;
+ lp = (struct net_local *) dev->priv;
+ dev_list = lp->next_dev;
+ spin_unlock(&dev_lock);
+
+ /* Put the physical address back */
+ cfg = XEmacLite_GetConfig(lp->index);
+ iounmap((void *) cfg->BaseAddress);
+ cfg->BaseAddress = cfg->PhysAddress;
+
+ if (lp->ddrVirtPtr) {
+ kfree (lp->ddrVirtPtr);
+ }
+
+ unregister_netdev(dev);
+ kfree(dev);
+}
+
+static int __init
+probe(int index)
+{
+ static const unsigned long remap_size
+ = CONFIG_XILINX_ETHERNETLITE_0_HIGHADDR -
+ CONFIG_XILINX_ETHERNETLITE_0_BASEADDR + 1;
+ struct net_device *dev;
+ struct net_local *lp;
+ XEmacLite_Config *cfg;
+ unsigned int irq;
+ u32 maddr;
+
+ if(index>=num_ether_devices)
+ return -ENODEV;
+ else
+ irq=ether_table[index].irq;
+
+ /* Find the config for our device. */
+ cfg = XEmacLite_GetConfig(index);
+ if (!cfg)
+ return -ENODEV;
+
+ dev = init_etherdev(0, sizeof (struct net_local));
+ if (!dev) {
+ printk(KERN_ERR "Could not allocate Xilinx enet device %d.\n",
+ index);
+ return -ENOMEM;
+ }
+ SET_MODULE_OWNER(dev);
+
+ ether_setup(dev);
+ dev->irq = irq;
+
+ /* Initialize our private data. */
+ lp = (struct net_local *) dev->priv;
+ memset(lp, 0, sizeof (struct net_local));
+ lp->index = index;
+ lp->dev = dev;
+
+ /* Make it the head of dev_list. */
+ spin_lock(&dev_lock);
+ lp->next_dev = dev_list;
+ dev_list = dev;
+ spin_unlock(&dev_lock);
+
+ /* Change the addresses to be virtual */
+ cfg->PhysAddress = ether_table[index].baseaddr;
+ cfg->BaseAddress = (u32) ioremap(cfg->PhysAddress, remap_size);
+
+ if (XEmacLite_Initialize(&lp->EmacLite, cfg->DeviceId) != XST_SUCCESS) {
+ printk(KERN_ERR "%s: Could not initialize device.\n",
+ dev->name);
+ remove_head_dev();
+ return -ENODEV;
+ }
+
+ /* Copy MAC address in from descriptor table */
+ XEmacLite_SetMacAddress(&lp->EmacLite, ether_table[index].macaddr);
+
+ printk(KERN_ERR "%s: using fifo mode.\n", dev->name);
+ XEmacLite_SetRecvHandler(&lp->EmacLite, dev, RecvHandler);
+ XEmacLite_SetSendHandler(&lp->EmacLite, dev, SendHandler);
+ dev->hard_start_xmit = xemaclite_Send;
+ lp->Isr = XEmacLite_InterruptHandler;
+
+ lp->mii_addr = 0;
+ printk(KERN_WARNING
+ "%s: No PHY detected. Assuming a PHY at address %d.\n",
+ dev->name, lp->mii_addr);
+
+ dev->open = xemaclite_open;
+ dev->stop = xemaclite_close;
+ dev->get_stats = xemaclite_get_stats;
+ dev->flags &= ~IFF_MULTICAST;
+ dev->do_ioctl = xemaclite_ioctl;
+ dev->tx_timeout = xemaclite_tx_timeout;
+ dev->watchdog_timeo = TX_TIMEOUT;
+
+ dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HW_CSUM;
+
+ printk(KERN_INFO
+ "%s: Xilinx EMACLite #%d at 0x%08X mapped to 0x%08X, irq=%d\n",
+ dev->name, index, cfg->PhysAddress,
+ ether_table[index].baseaddr, dev->irq);
+ return 0;
+}
+
+static int __init
+xemaclite_init(void)
+{
+ int index = 0;
+
+ while (probe(index++) == 0) ;
+ /* If we found at least one, report success. */
+ return (index > 1) ? 0 : -ENODEV;
+}
+
+static void __exit
+xemaclite_cleanup(void)
+{
+ while (dev_list)
+ remove_head_dev();
+}
+
+EXPORT_NO_SYMBOLS;
+
+module_init(xemaclite_init);
+module_exit(xemaclite_cleanup);
+
+__setup("macaddr=", xilinx_emac_hw_addr_setup);
+
Index: drivers/net/xilinx_emaclite/xemaclite.h
===================================================================
--- drivers/net/xilinx_emaclite/xemaclite.h (revision 0)
+++ drivers/net/xilinx_emaclite/xemaclite.h (revision 0)
@@ -0,0 +1,277 @@
+/* $Id: xemaclite.h,v 1.2 2004/05/24 20:48:12 meinelte Exp $ */
+/******************************************************************************
+*
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE.
+*
+* (c) Copyright 2004 Xilinx Inc.
+* All rights reserved.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemaclite.h
+*
+* The Xilinx Ethernet Lite driver component. This component supports the Xilinx
+* Lite Ethernet 10/100 MAC (EMAC Lite).
+*
+* The Xilinx Ethernet Lite 10/100 MAC supports the following features:
+* - Media Independent Interface (MII) for connection to external
+* 10/100 Mbps PHY transceivers.
+* - Independent internal transmit and receive buffers
+* - CSMA/CD compliant operations for half-duplex modes
+* - Unicast and broadcast
+* - Automatic FCS insertion
+* - Automatic pad insertion on transmit
+* - Configurable ping/pong buffer scheme for either/both transmit and receive
+* buffer areas.
+* - Interrupt driven mode available.
+*
+* The Xilinx Ethernet Lite 10/100 MAC does not support the following features:
+* - multi-frame buffering
+* only 1 transmit frame is allowed into each transmit buffer
+* only 1 receive frame is allowed into each receive buffer.
+* the hardware blocks reception until buffer is emptied
+* - Pause frame (flow control) detection in full-duplex mode
+* - Programmable interframe gap
+* - Multicast and promiscuous address filtering
+* - Internal loopback
+* - Automatic source address insertion or overwrite
+*
+* <b>Driver Description</b>
+*
+* The device driver enables higher layer software (e.g., an application) to
+* communicate to the EMAC Lite. The driver handles transmission and reception
+* of Ethernet frames, as well as configuration of the controller. It does not
+* handle protocol stack functionality such as Link Layer Control (LLC) or the
+* Address Resolution Protocol (ARP). The protocol stack that makes use of the
+* driver handles this functionality. This implies that the driver is simply a
+* pass-through mechanism between a protocol stack and the EMAC Lite.
+*
+* Since the driver is a simple pass-through mechanism between a protocol stack
+* and the EMAC Lite, no assembly or disassembly of Ethernet frames is done at
+* the driver-level. This assumes that the protocol stack passes a correctly
+* formatted Ethernet frame to the driver for transmission, and that the driver
+* does not validate the contents of an incoming frame. A single device driver
+* can support multiple EmacLite devices.
+*
+* The driver supports interrupt driven mode and the default mode of operation
+* is polled mode. If interrupts are desired, XEmacLite_InterruptEnable() must
+* be called.
+*
+* <b>Device Configuration</b>
+*
+* The device can be configured in various ways during the FPGA implementation
+* process. Configuration parameters are stored in the xemaclite_g.c file. A table
+* is defined where each entry contains configuration information for an EmacLite
+* device. This information includes such things as the base address
+* of the memory-mapped device and the number of buffers.
+*
+* <b>Interrupt Processing</b>
+*
+* After _Initialize is called, _InterruptEnable can be called to enable the interrupt
+* driven functionality. If polled operation is desired, just call _Send and check the
+* return code. If XST_FAILURE is returned, call _Send with the same data until
+* XST_SUCCESS is returned. The same idea applies to _Recv. Call _Recv until the
+* returned length is non-zero at which point the received data is in the buffer
+* provided in the function call.
+*
+* The Transmit and Receive interrupts are enabled within the _InterruptEnable
+* function and disabled in the _InterruptDisable function. The _Send and _Recv
+* functions acknowledge the EMACLite generated interrupts associated with each
+* function.
+* It is the application's responsibility to acknowledge any associated Interrupt
+* Controller interrupts if it is used in the system.
+*
+* <b>Memory Buffer Alignment</b>
+*
+* The alignment of the input/output buffers for the _Send and _Recv routine is
+* not required to be 32 bits. If the buffer is not aligned on a 32-bit boundry
+* there will be a performance impact while the driver aligns the data for
+* transmission or upon reception.
+*
+* For optimum performance, the user should provide a 32-bit aligned buffer
+* to the _Send and _Recv routines.
+*
+* <b>Asserts</b>
+*
+* Asserts are used within all Xilinx drivers to enforce constraints on argument
+* values. Asserts can be turned off on a system-wide basis by defining, at compile
+* time, the NDEBUG identifier. By default, asserts are turned on and it is
+* recommended that application developers leave asserts on during development.
+*
+* @note
+*
+* This driver requires EmacLite hardware version 1.01a and higher. It is not
+* compatible with earlier versions of the EmacLite hardware. Use version 1.00a
+* software driver for hardware version 1.00a/b.
+*
+* The RX hardware is enabled from powerup and there is no disable. It is
+* possible that frames have been received prior to the initialization
+* of the driver. If this situation is possible, call XEmacLite_mFlushReceive()
+* to empty the receive buffers after initialization.
+*
+* This driver is intended to be RTOS and processor independent. It works
+* with physical addresses only. Any needs for dynamic memory management,
+* threads or thread mutual exclusion, virtual memory, or cache control must
+* be satisfied by the layer above this driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.01a ecm 01/30/04 First release
+* </pre>
+*
+*
+******************************************************************************/
+
+#ifndef XEMACLITE_H /* prevent circular inclusions */
+#define XEMACLITE_H /* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xstatus.h"
+#include "xemaclite_l.h"
+
+/************************** Constant Definitions *****************************/
+/*
+ * Device information
+ */
+#define XEL_DEVICE_NAME "xemaclite"
+#define XEL_DEVICE_DESC "Xilinx Ethernet Lite 10/100 MAC"
+
+/**************************** Type Definitions *******************************/
+
+/**
+ * This typedef contains configuration information for a device.
+ */
+typedef struct
+{
+ Xuint16 DeviceId; /**< Unique ID of device */
+ Xuint32 BaseAddress; /**< Device base address */
+ Xuint32 PhysAddress; /* < Physical address (for Linux)> */
+ Xuint8 TxPingPong; /**< 1 if TX Pong buffer configured,0 otherwise */
+ Xuint8 RxPingPong; /**< 1 if RX Pong buffer configured,0 otherwise */
+} XEmacLite_Config;
+
+
+/*
+ * Callback when data is sent or received .
+ * @param CallBackRef is a callback reference passed in by the upper layer
+ * when setting the callback functions, and passed back to the upper
+ * layer when the callback is invoked.
+ */
+typedef void (*XEmacLite_Handler)(void *CallBackRef);
+
+/**
+ * The XEmacLite driver instance data. The user is required to allocate a
+ * variable of this type for every EmacLite device in the system. A pointer
+ * to a variable of this type is then passed to the driver API functions.
+ */
+
+typedef struct
+{
+ Xuint32 BaseAddress; /* Base address for device (IPIF) */
+ Xuint32 IsReady; /* Device is initialized and ready */
+ Xuint32 NextTxBufferToUse; /* Next TX buffer to write to */
+ Xuint32 NextRxBufferToUse; /* Next RX buffer to read from */
+ XEmacLite_Config *ConfigPtr; /* A pointer to the device configuration */
+
+ /*
+ * Callbacks
+ */
+
+ XEmacLite_Handler RecvHandler;
+ void *RecvRef;
+ XEmacLite_Handler SendHandler;
+ void *SendRef;
+
+} XEmacLite;
+
+/***************** Macros (Inline Functions) Definitions *********************/
+/****************************************************************************/
+/**
+*
+* Return the next expected Transmit Buffer's address .
+*
+* @param InstancePtr is the pointer to the instance of the driver to
+* be worked on
+*
+* @note
+* This macro returns the address of the next transmit buffer to put data into.
+* This is used to determine the destination of the next transmit data frame.
+*
+*****************************************************************************/
+#define XEmacLite_mNextTransmitAddr(InstancePtr) \
+ ((InstancePtr)->BaseAddress + (InstancePtr)->NextTxBufferToUse) + \
+ XEL_TXBUFF_OFFSET
+
+/****************************************************************************/
+/**
+*
+* Return the next expected Receive Buffer's address .
+*
+* @param InstancePtr is the pointer to the instance of the driver to
+* be worked on
+*
+* @note
+* This macro returns the address of the next receive buffer to read data from.
+* This is the expected receive buffer address if the driver is in sync.
+*
+*****************************************************************************/
+#define XEmacLite_mNextReceiveAddr(InstancePtr) \
+ ((InstancePtr)->BaseAddress + (InstancePtr)->NextRxBufferToUse)
+
+
+/************************** Variable Definitions *****************************/
+
+/************************** Function Prototypes ******************************/
+
+/*
+ * Initialization functions in xemaclite.c
+ */
+XStatus XEmacLite_Initialize(XEmacLite *InstancePtr, Xuint16 DeviceId);
+void XEmacLite_SetMacAddress(XEmacLite *InstancePtr, Xuint8 *AddressPtr);
+Xboolean XEmacLite_TxBufferAvailable(XEmacLite *InstancePtr);
+void XEmacLite_FlushReceive(XEmacLite *InstancePtr);
+
+XEmacLite_Config *XEmacLite_LookupConfig(Xuint16 DeviceId);
+
+XStatus XEmacLite_Send(XEmacLite *InstancePtr, Xuint8 *FramePtr, unsigned ByteCount);
+Xuint16 XEmacLite_Recv(XEmacLite *InstancePtr, Xuint8 *FramePtr);
+
+/*
+ * Interrupt driven functions in xemaclite_intr.c
+ */
+
+XStatus XEmacLite_EnableInterrupts(XEmacLite *InstancePtr);
+void XEmacLite_DisableInterrupts(XEmacLite *InstancePtr);
+
+void XEmacLite_InterruptHandler(void *InstancePtr);
+
+void XEmacLite_SetRecvHandler(XEmacLite *InstancePtr, void *CallBackRef,
+ XEmacLite_Handler FuncPtr);
+void XEmacLite_SetSendHandler(XEmacLite *InstancePtr, void *CallBackRef,
+ XEmacLite_Handler FuncPtr);
+
+/*
+ * Selftest function in xemaclite_selftest.c
+ */
+XStatus XEmacLite_SelfTest(XEmacLite *InstancePtr);
+
+#endif /* end of protection macro */
Index: drivers/net/xilinx_emaclite/xemaclite_g.c
===================================================================
--- drivers/net/xilinx_emaclite/xemaclite_g.c (revision 0)
+++ drivers/net/xilinx_emaclite/xemaclite_g.c (revision 0)
@@ -0,0 +1,68 @@
+/* $Id: xemaclite_g.c,v 1.3 2004/05/26 12:12:06 meinelte Exp $ */
+/******************************************************************************
+*
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE.
+*
+* (c) Copyright 2004 Xilinx Inc.
+* All rights reserved.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemaclite_g.c
+*
+* This file contains a configuration table that specifies the configuration
+* of EMACLite devices in the system.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.01a ecm 02/16/04 First release
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xemaclite.h"
+#include <linux/autoconf.h>
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Prototypes ******************************/
+
+/**
+ * This table contains configuration information for each EMACLite device
+ * in the system.
+ */
+XEmacLite_Config XEmacLite_ConfigTable[CONFIG_XILINX_ETHERNETLITE_NUM_INSTANCES] =
+{
+ {
+ 0, /* Unique ID of device */
+ CONFIG_XILINX_ETHERNETLITE_0_BASEADDR, /* Base address */
+ CONFIG_XILINX_ETHERNETLITE_0_TX_PING_PONG, /* Hardware configuration */
+ CONFIG_XILINX_ETHERNETLITE_0_RX_PING_PONG /* Hardware configuration */
+ }
+};
+
Index: drivers/net/xilinx_emaclite/xemaclite_selftest.c
===================================================================
--- drivers/net/xilinx_emaclite/xemaclite_selftest.c (revision 0)
+++ drivers/net/xilinx_emaclite/xemaclite_selftest.c (revision 0)
@@ -0,0 +1,214 @@
+/* $Id: xemaclite_selftest.c,v 1.1 2004/05/21 16:58:25 meinelte Exp $ */
+/******************************************************************************
+*
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE.
+*
+* (c) Copyright 2004 Xilinx Inc.
+* All rights reserved.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemaclite_selftest.c
+*
+* Function(s) in this file are the required functions for the EMAC Lite
+* driver sefftest for the hardware.
+* See xemaclite.h for a detailed description of the driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.01a ecm 01/31/04 First release
+* </pre>
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xstatus.h"
+#include "xemaclite_l.h"
+#include "xio.h"
+#include "xemaclite.h"
+#include "xemaclite_i.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+/**
+*
+* Performs a SelfTest on the EmacLite device as follows:
+* - Writes to the mandatory TX buffer and reads back to verify.
+* - If configured, writes to the secondary TX buffer and reads back to verify.
+* - Writes to the mandatory RX buffer and reads back to verify.
+* - If configured, writes to the secondary RX buffer and reads back to verify.
+*
+*
+* @param InstancePtr is a pointer to the XEmacLite instance to be worked on.
+*
+* @return
+*
+* - XST_SUCCESS if the device Passed the Self Test.
+* - XST_FAILURE if any of the data read backs fail.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XStatus XEmacLite_SelfTest(XEmacLite *InstancePtr)
+{
+ Xuint32 BaseAddress;
+ Xuint8 i;
+ Xuint8 TestString[4] = {0xDE, 0xAD, 0xBE, 0xEF};
+ Xuint8 ReturnString[4] = {0x0, 0x0, 0x0, 0x0};
+
+ /*
+ * Verify that each of the inputs are valid.
+ */
+
+ XASSERT_NONVOID(InstancePtr != XNULL);
+
+ /*
+ * Determine the TX buffer address
+ */
+
+ BaseAddress = InstancePtr->BaseAddress + XEL_TXBUFF_OFFSET;
+
+ /*
+ * Write the TestString to the TX buffer in EMAC Lite then
+ * back from the EMAC Lite and verify
+ */
+ XEmacLite_AlignedWrite(TestString, (Xuint32 *) BaseAddress,
+ sizeof(TestString));
+ XEmacLite_AlignedRead((Xuint32 *) BaseAddress, ReturnString,
+ sizeof(ReturnString));
+
+ for (i=0; i < 4; i++)
+ {
+
+ if (ReturnString[i] != TestString[i])
+ {
+ return XST_FAILURE;
+ }
+
+ /*
+ * Zero thge return string for the next test
+ */
+ ReturnString[i] = 0;
+ }
+
+ /*
+ * If the second buffer is configured, test it also
+ */
+
+ if (InstancePtr->ConfigPtr->TxPingPong != 0)
+ {
+ BaseAddress += XEL_BUFFER_OFFSET;
+ /*
+ * Write the TestString to the optional TX buffer in EMAC Lite then
+ * back from the EMAC Lite and verify
+ */
+ XEmacLite_AlignedWrite(TestString, (Xuint32 *) BaseAddress,
+ sizeof(TestString));
+ XEmacLite_AlignedRead((Xuint32 *) BaseAddress, ReturnString,
+ sizeof(ReturnString));
+
+ for (i=0; i < 4; i++)
+ {
+
+ if (ReturnString[i] != TestString[i])
+ {
+ return XST_FAILURE;
+ }
+
+ /*
+ * Zero thge return string for the next test
+ */
+ ReturnString[i] = 0;
+ }
+ }
+
+ /*
+ * Determine the RX buffer address
+ */
+
+ BaseAddress = InstancePtr->BaseAddress + XEL_RXBUFF_OFFSET;
+
+ /*
+ * Write the TestString to the RX buffer in EMAC Lite then
+ * back from the EMAC Lite and verify
+ */
+ XEmacLite_AlignedWrite(TestString, (Xuint32 *) (BaseAddress),
+ sizeof(TestString));
+ XEmacLite_AlignedRead((Xuint32 *) (BaseAddress), ReturnString,
+ sizeof(ReturnString));
+
+ for (i=0; i < 4; i++)
+ {
+
+ if (ReturnString[i] != TestString[i])
+ {
+ return XST_FAILURE;
+ }
+
+ /*
+ * Zero thge return string for the next test
+ */
+ ReturnString[i] = 0;
+ }
+
+ /*
+ * If the second buffer is configured, test it also
+ */
+
+ if (InstancePtr->ConfigPtr->RxPingPong != 0)
+ {
+ BaseAddress += XEL_BUFFER_OFFSET;
+ /*
+ * Write the TestString to the optional RX buffer in EMAC Lite then
+ * back from the EMAC Lite and verify
+ */
+ XEmacLite_AlignedWrite(TestString, (Xuint32 *) BaseAddress,
+ sizeof(TestString));
+ XEmacLite_AlignedRead((Xuint32 *) BaseAddress, ReturnString,
+ sizeof(ReturnString));
+
+ for (i=0; i < 4; i++)
+ {
+
+ if (ReturnString[i] != TestString[i])
+ {
+ return XST_FAILURE;
+ }
+
+ /*
+ * Zero thge return string for the next test
+ */
+ ReturnString[i] = 0;
+ }
+ }
+
+ return XST_SUCCESS;
+}
Index: drivers/net/xilinx_emaclite/xemaclite_l.c
===================================================================
--- drivers/net/xilinx_emaclite/xemaclite_l.c (revision 0)
+++ drivers/net/xilinx_emaclite/xemaclite_l.c (revision 0)
@@ -0,0 +1,507 @@
+/* $Id: xemaclite_l.c,v 1.3 2004/12/16 18:35:48 meinelte Exp $ */
+/******************************************************************************
+*
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE.
+*
+* (c) Copyright 2004 Xilinx Inc.
+* All rights reserved.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemaclite_l.c
+*
+* This file contains the minimal, polled functions to send and receive Ethernet
+* frames.
+*
+* Refer to xemaclite.h for more details.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm 06/01/02 First release
+* 1.01a ecm 03/31/04 Additional functionality and the _AlignedRead and
+* _AlignedWrite functions.
+* </pre>
+*
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xemaclite_l.h"
+#include "xemaclite_i.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+void XEmacLite_AlignedWrite(void *SrcPtr, Xuint32 *DestPtr, unsigned ByteCount);
+void XEmacLite_AlignedRead(Xuint32 *SrcPtr, void *DestPtr, unsigned ByteCount);
+
+/************************** Variable Definitions *****************************/
+
+/*****************************************************************************/
+/**
+*
+* Send an Ethernet frame. The size is the total frame size, including header.
+* This function blocks waiting for the frame to be transmitted.
+*
+* @param BaseAddress is the base address of the device
+* @param FramePtr is a pointer to frame
+* @param ByteCount is the size, in bytes, of the frame
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* This function call is blocking in nature, i.e. it will wait until the
+* frame is transmitted. This function can hang and not exit if the
+* hardware is not configured properly.
+*
+* If the ping buffer is the destination of the data, the argument should be
+* DeviceAddress + XEL_TXBUFF_OFFSET.
+* If the pong buffer is the destination of the data, the argument should be
+* DeviceAddress + XEL_TXBUFF_OFFSET + XEL_BUFFER_OFFSET.
+* The function does not take the different buffers into consideration.
+******************************************************************************/
+void XEmacLite_SendFrame(Xuint32 BaseAddress, Xuint8 *FramePtr, unsigned ByteCount)
+{
+ Xuint32 Register;
+
+ /*
+ * Write data to the EMAC Lite
+ */
+ XEmacLite_AlignedWrite(FramePtr, (Xuint32 *) (BaseAddress), ByteCount);
+
+ /*
+ * The frame is in the buffer, now send it
+ */
+ XIo_Out32(BaseAddress + XEL_TPLR_OFFSET,
+ (ByteCount & (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO)));
+
+
+ Register = XIo_In32(BaseAddress + XEL_TSR_OFFSET);
+ XIo_Out32(BaseAddress + XEL_TSR_OFFSET, (Register | XEL_TSR_XMIT_BUSY_MASK));
+
+ /*
+ * Loop on the status waiting for the transmit to be complete.
+ */
+// while (!XEmacLite_mIsTxDone(BaseAddress));
+
+}
+
+
+/*****************************************************************************/
+/**
+*
+* Receive a frame. Wait for a frame to arrive.
+*
+* @param BaseAddress is the base address of the device
+* @param FramePtr is a pointer to a buffer where the frame will
+* be stored.
+*
+* @return
+*
+* The type/length field of the frame received. When the type/length field
+* contains the type , XEL_MAX_FRAME_SIZE bytes will be copied out of the
+* buffer and it is up to the higher layers to sort out the frame.
+*
+* @note
+*
+* This function call is blocking in nature, i.e. it will wait until a
+* frame arrives.
+*
+* If the ping buffer is the source of the data, the argument should be
+* DeviceAddress + XEL_RXBUFF_OFFSET.
+* If the pong buffer is the source of the data, the argument should be
+* DeviceAddress + XEL_RXBUFF_OFFSET + XEL_BUFFER_OFFSET.
+* The function does not take the different buffers into consideration.
+******************************************************************************/
+Xuint16 XEmacLite_RecvFrame(Xuint32 BaseAddress, Xuint8 *FramePtr)
+{
+ Xuint16 LengthType;
+ Xuint16 Length;
+ Xuint32 Register;
+
+ /*
+ * Wait for a frame to arrive - this is a blocking call
+ */
+
+ while (XEmacLite_mIsRxEmpty(BaseAddress));
+
+ /*
+ * Get the length of the frame that arrived
+ */
+ LengthType = XIo_In32(BaseAddress + XEL_RPLR_OFFSET);
+ LengthType &= (XEL_RPLR_LENGTH_MASK_HI | XEL_RPLR_LENGTH_MASK_LO);
+
+ /* check if length is valid */
+
+ if (LengthType > XEL_MAX_FRAME_SIZE)
+ {
+ /* Field contain type, use max frame size and let user parse it */
+ Length = XEL_MAX_FRAME_SIZE;
+ }
+ else
+ {
+ /* Use the length in the frame, plus the header and trailer */
+ Length = LengthType + XEL_HEADER_SIZE + XEL_FCS_SIZE;
+ }
+
+ /*
+ * Read each byte from the EMAC Lite
+ */
+ XEmacLite_AlignedRead((Xuint32 *) (BaseAddress + XEL_RXBUFF_OFFSET),
+ FramePtr, Length);
+
+ /*
+ * Acknowledge the frame
+ */
+
+ Register = XIo_In32(BaseAddress + XEL_RSR_OFFSET);
+ Register &= ~XEL_RSR_RECV_DONE_MASK;
+ XIo_Out32(BaseAddress + XEL_RSR_OFFSET, Register);
+
+ return LengthType;
+}
+
+/******************************************************************************/
+/**
+*
+* This function aligns the incoming data and writes it out to a 32-bit
+* aligned destination address range.
+*
+* @param SrcPtr is a pointer to incoming data of any alignment.
+* @param DestPtr is a pointer to outgoing data of 32-bit alignment.
+* @param ByteCount is the number of bytes to write.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void XEmacLite_AlignedWrite(void *SrcPtr, Xuint32 *DestPtr, unsigned ByteCount)
+{
+ unsigned i;
+ unsigned Length = ByteCount;
+ Xuint32 AlignBuffer;
+ Xuint32 *To32Ptr;
+ Xuint32 *From32Ptr;
+ Xuint16 *To16Ptr;
+ Xuint16 *From16Ptr;
+ Xuint8 *To8Ptr;
+ Xuint8 *From8Ptr;
+
+ To32Ptr = DestPtr;
+
+ if ((((Xuint32)SrcPtr) & 0x00000003) == 0)
+ {
+
+ /*
+ * Word aligned buffer, no correction needed.
+ */
+// printk("noaligned\n");
+
+ From32Ptr = (Xuint32 *)SrcPtr;
+
+ while (Length > 3)
+ {
+ /*
+ * Output each word destination.
+ */
+
+ *To32Ptr++ = *From32Ptr++;
+
+ /*
+ * Adjust length accordingly
+ */
+
+ Length -= 4;
+ }
+
+ /*
+ * Set up to output the remaining data, zero the temp buffer first.
+ */
+
+ AlignBuffer = 0;
+ To8Ptr = (Xuint8 *) &AlignBuffer;
+ From8Ptr = (Xuint8 *) From32Ptr;
+
+ }
+ else if ((((Xuint32)SrcPtr) & 0x00000001) != 0)
+ {
+ /*
+ * Byte aligned buffer, correct.
+ */
+
+ AlignBuffer = 0;
+ To8Ptr = (Xuint8 *) &AlignBuffer;
+ From8Ptr = (Xuint8 *) SrcPtr;
+
+// printk("aligned8\n");
+
+ while (Length > 3)
+ {
+ /*
+ * Copy each byte into the temporary buffer.
+ */
+
+ for (i = 0; i < 4; i++)
+ {
+ *To8Ptr++ = *From8Ptr++;
+ }
+
+ /*
+ * Output the buffer
+ */
+
+ *To32Ptr++ = AlignBuffer;
+
+ /*.
+ * Reset the temporary buffer pointer and adjust length.
+ */
+
+ To8Ptr = (Xuint8 *) &AlignBuffer;
+ Length -= 4;
+ }
+
+ /*
+ * Set up to output the remaining data, zero the temp buffer first.
+ */
+
+ AlignBuffer = 0;
+ To8Ptr = (Xuint8 *) &AlignBuffer;
+
+ }
+ else
+ {
+ /*
+ * Half-Word aligned buffer, correct.
+ */
+
+ AlignBuffer = 0;
+ To16Ptr = (Xuint16 *) &AlignBuffer;
+ From16Ptr = (Xuint16 *)SrcPtr;
+
+// printk("aligned16\n");
+
+ while (Length > 3)
+ {
+ /*
+ * Copy each half word into the temporary buffer.
+ */
+
+ for (i = 0; i < 2; i++)
+ {
+ *To16Ptr++ = *From16Ptr++;
+ }
+
+ /*
+ * Output the buffer.
+ */
+
+ *To32Ptr++ = AlignBuffer;
+
+ /*
+ * Reset the temporary buffer pointer and adjust length.
+ */
+
+ To16Ptr = (Xuint16 *) &AlignBuffer;
+ Length -= 4;
+ }
+
+ /*
+ * Set up to output the remaining data, zero the temp buffer first.
+ */
+
+ AlignBuffer = 0;
+ To8Ptr = (Xuint8 *) &AlignBuffer;
+ From8Ptr = (Xuint8 *) From16Ptr;
+ }
+
+ /*
+ * Output the remaining data, zero the temp buffer first.
+ */
+ for (i = 0; i < Length; i++)
+ {
+ *To8Ptr++ = *From8Ptr++;
+ }
+
+ *To32Ptr++ = AlignBuffer;
+
+}
+
+/******************************************************************************/
+/**
+*
+* This function reads from a 32-bit aligned source address range and aligns
+* the writes to the provided destination pointer alignment.
+*
+* @param SrcPtr is a pointer to incoming data of 32-bit alignment.
+* @param DestPtr is a pointer to outgoing data of any alignment.
+* @param ByteCount is the number of bytes to read.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void XEmacLite_AlignedRead(Xuint32 *SrcPtr, void *DestPtr, unsigned ByteCount)
+{
+ unsigned i;
+ unsigned Length = ByteCount;
+ Xuint32 AlignBuffer;
+ Xuint32 *To32Ptr;
+ Xuint32 *From32Ptr;
+ Xuint16 *To16Ptr;
+ Xuint16 *From16Ptr;
+ Xuint8 *To8Ptr;
+ Xuint8 *From8Ptr;
+
+ From32Ptr = (Xuint32 *)SrcPtr;
+
+ if ((((Xuint32)DestPtr) & 0x00000003) == 0)
+ {
+
+ /*
+ * Word aligned buffer, no correction needed.
+ */
+
+ To32Ptr = (Xuint32 *)DestPtr;
+
+ while (Length > 3)
+ {
+ /*
+ * Output each word.
+ */
+
+ *To32Ptr++ = *From32Ptr++;
+
+ /*
+ * Adjust length accordingly.
+ */
+ Length -= 4;
+ }
+
+ /*
+ * Set up to read the remaining data.
+ */
+
+ To8Ptr = (Xuint8 *) To32Ptr;
+
+ }
+ else if ((((Xuint32)DestPtr) & 0x00000001) != 0)
+ {
+ /*
+ * Byte aligned buffer, correct.
+ */
+
+ To8Ptr = (Xuint8 *)DestPtr;
+
+ while (Length > 3)
+ {
+ /*
+ * Copy each word into the temporary buffer.
+ */
+
+ AlignBuffer = *From32Ptr++;
+ From8Ptr = (Xuint8 *) &AlignBuffer;
+
+ /*
+ * Write data to destination.
+ */
+
+ for (i = 0; i < 4; i++)
+ {
+ *To8Ptr++ = *From8Ptr++;
+ }
+
+ /*
+ * Adjust length
+ */
+
+ Length -= 4;
+ }
+
+ }
+ else
+ {
+ /*
+ * Half-Word aligned buffer, correct.
+ */
+
+ To16Ptr = (Xuint16 *)DestPtr;
+
+ while (Length > 3)
+ {
+ /*
+ * Copy each word into the temporary buffer.
+ */
+
+ AlignBuffer = *From32Ptr++;
+ From16Ptr = (Xuint16 *) &AlignBuffer;
+
+ /*
+ * Write data to destination.
+ */
+
+ for (i = 0; i < 2; i++)
+ {
+ *To16Ptr++ = *From16Ptr++;
+ }
+
+ /*
+ * Adjust length.
+ */
+
+ Length -= 4;
+ }
+
+ /*
+ * Set up to read the remaining data.
+ */
+
+ To8Ptr = (Xuint8 *) To16Ptr;
+ }
+
+ /*
+ * Read the remaining data.
+ */
+
+ AlignBuffer = *From32Ptr++;
+ From8Ptr = (Xuint8 *) &AlignBuffer;
+
+ for (i = 0; i < Length; i++)
+ {
+ *To8Ptr++ = *From8Ptr++;
+ }
+}
Index: drivers/net/xilinx_emaclite/xemaclite_intr.c
===================================================================
--- drivers/net/xilinx_emaclite/xemaclite_intr.c (revision 0)
+++ drivers/net/xilinx_emaclite/xemaclite_intr.c (revision 0)
@@ -0,0 +1,341 @@
+/* $Id: xemaclite_intr.c,v 1.2 2004/05/28 13:48:04 meinelte Exp $ */
+/******************************************************************************
+*
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE.
+*
+* (c) Copyright 2004 Xilinx Inc.
+* All rights reserved.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemaclite_intr.c
+*
+* Functions in this file are for the interrupt driven processing functionality.
+* See xemaclite.h for a detailed description of the driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.01a ecm 03/31/04 First release
+* </pre>
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xstatus.h"
+#include "xemaclite_l.h"
+#include "xemaclite_i.h"
+#include "xio.h"
+#include "xemaclite.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/************************** Function Prototypes ******************************/
+
+/************************** Variable Definitions *****************************/
+/*****************************************************************************/
+/**
+*
+* Enable the EmacLite Interrupts.
+*
+* This function must be called before other functions to send or receive data
+* in interrupt driven mode. The user should have connected the
+* interrupt handler of the driver to an interrupt source such as an interrupt
+* controller or the processor interrupt prior to this function being called.
+*
+* @param InstancePtr is a pointer to the XEmacLite instance to be worked on.
+*
+* @return
+*
+* - XST_SUCCESS if the device interrupts were enabled successfully.
+* - XST_NO_CALLBACK if the callbacks were not set.
+*
+* @note
+*
+* None
+*
+******************************************************************************/
+XStatus XEmacLite_EnableInterrupts(XEmacLite *InstancePtr)
+{
+ Xuint32 Register;
+
+ /*
+ * Verify that each of the inputs are valid.
+ */
+
+ XASSERT_NONVOID(InstancePtr != XNULL);
+ XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+ /*
+ * Verify that the handlers are in place
+ */
+
+ if ((InstancePtr->RecvHandler == (XEmacLite_Handler) StubHandler) ||
+ (InstancePtr->SendHandler == (XEmacLite_Handler) StubHandler))
+ {
+ return XST_NO_CALLBACK;
+ }
+
+
+ /* Enable TX and RX interrupts */
+
+ Register = XIo_In32(InstancePtr->BaseAddress + XEL_TSR_OFFSET);
+ Register |= XEL_TSR_XMIT_IE_MASK;
+ XIo_Out32(InstancePtr->BaseAddress + XEL_TSR_OFFSET, Register);
+ XIo_Out32(InstancePtr->BaseAddress + XEL_TSR_OFFSET +
+ XEL_BUFFER_OFFSET, Register);
+
+ Register = XIo_In32(InstancePtr->BaseAddress + XEL_RSR_OFFSET);
+ Register |= XEL_RSR_RECV_IE_MASK;
+ XIo_Out32(InstancePtr->BaseAddress + XEL_RSR_OFFSET, Register);
+ XIo_Out32(InstancePtr->BaseAddress + XEL_RSR_OFFSET +
+ XEL_BUFFER_OFFSET, Register);
+
+ /* Enable the global interrupt output. */
+
+ XIo_Out32(InstancePtr->BaseAddress + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK);
+
+ return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Disables the interrupts from the device(the higher layer software is
+* responsible for disabling interrupts at the interrupt controller).
+*
+* To start using the device again, _EnableInterrupts must be called.
+*
+* @param InstancePtr is a pointer to the XEmacLite instance to be worked on.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void XEmacLite_DisableInterrupts(XEmacLite *InstancePtr)
+{
+ Xuint32 Register;
+
+ /*
+ * Verify that each of the inputs are valid.
+ */
+
+ XASSERT_VOID(InstancePtr != XNULL);
+ XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+
+ /* Disable the global interrupt output. */
+
+ XIo_Out32(InstancePtr->BaseAddress + XEL_GIER_OFFSET, 0);
+
+ /* Disable TX and RX interrupts */
+
+ Register = XIo_In32(InstancePtr->BaseAddress + XEL_TSR_OFFSET);
+ Register &= ~XEL_TSR_XMIT_IE_MASK;
+ XIo_Out32(InstancePtr->BaseAddress + XEL_TSR_OFFSET, Register);
+ XIo_Out32(InstancePtr->BaseAddress + XEL_TSR_OFFSET +
+ XEL_BUFFER_OFFSET, Register);
+
+ Register = XIo_In32(InstancePtr->BaseAddress + XEL_RSR_OFFSET);
+ Register &= ~XEL_RSR_RECV_IE_MASK;
+ XIo_Out32(InstancePtr->BaseAddress + XEL_RSR_OFFSET, Register);
+ XIo_Out32(InstancePtr->BaseAddress + XEL_RSR_OFFSET +
+ XEL_BUFFER_OFFSET, Register);
+
+}
+
+/*****************************************************************************/
+/**
+*
+* Interrupt handler for the EMACLite driver. It performs the following
+* processing:
+*
+* - Get the interrupt status from the registers to determine the source of the
+* interrupt.
+*
+* - Call the appropriate handler based on the source of the interrupt.
+*
+* @param InstancePtr contains a pointer to the EMACLite device instance for
+* the interrupt.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+*
+******************************************************************************/
+void XEmacLite_InterruptHandler(void *InstancePtr)
+{
+
+ XEmacLite *EmacLitePtr;
+ Xuint32 Register = 0;
+
+ /*
+ * Verify that each of the inputs are valid.
+ */
+
+ XASSERT_VOID(InstancePtr != XNULL);
+
+ /*
+ * Convert the non-typed pointer to an EmacLite instance pointer
+ * such that there is access to the device.
+ */
+ EmacLitePtr = (XEmacLite *)InstancePtr;
+
+ if ((XEmacLite_mIsRxEmpty(EmacLitePtr->BaseAddress) != XTRUE) ||
+ (XEmacLite_mIsRxEmpty(EmacLitePtr->BaseAddress + XEL_BUFFER_OFFSET) != XTRUE))
+ {
+ /*
+ * Call the RX callback.
+ */
+
+ EmacLitePtr->RecvHandler(EmacLitePtr->RecvRef);
+
+ }
+ if ((XEmacLite_mIsTxDone(EmacLitePtr->BaseAddress) == XTRUE) &&
+ ((XEmacLite_mGetTxActive(EmacLitePtr->BaseAddress) & XEL_TSR_XMIT_ACTIVE_MASK) != 0))
+ {
+
+ /*
+ * Clear the Active bit
+ */
+ Register = XEmacLite_mGetTxActive(EmacLitePtr->BaseAddress);
+ Register &= ~XEL_TSR_XMIT_ACTIVE_MASK;
+ XEmacLite_mSetTxActive(EmacLitePtr->BaseAddress, Register);
+ }
+ if ((XEmacLite_mIsTxDone(EmacLitePtr->BaseAddress + XEL_BUFFER_OFFSET) ==
+ XTRUE) &&
+ ((XEmacLite_mGetTxActive(EmacLitePtr->BaseAddress + XEL_BUFFER_OFFSET)
+ & XEL_TSR_XMIT_ACTIVE_MASK) != 0))
+ {
+
+ /*
+ * Clear the Active bit
+ */
+ Register =
+ XEmacLite_mGetTxActive(EmacLitePtr->BaseAddress + XEL_BUFFER_OFFSET);
+ Register &= ~XEL_TSR_XMIT_ACTIVE_MASK;
+ XEmacLite_mSetTxActive(EmacLitePtr->BaseAddress + XEL_BUFFER_OFFSET,
+ Register);
+ }
+
+ /*
+ * If there was a TX interrupt, call the callback
+ */
+ if (Register != 0)
+ {
+
+ /*
+ * Call the TX callback.
+ */
+
+ EmacLitePtr->SendHandler(EmacLitePtr->SendRef);
+
+ }
+}
+
+/*****************************************************************************/
+/**
+*
+* Sets the callback function for handling received frames in interrupt mode.
+* The upper layer software should call this function during initialization.
+* The callback is called when a frame is received. The callback function
+* should communicate the data to a thread such that the processing is not
+* performed in an interrupt context.
+*
+* The callback is invoked by the driver within interrupt context, so it needs
+* to do its job quickly. If there are other potentially slow operations
+* within the callback, these should be done at task-level.
+*
+* @param InstancePtr is a pointer to the XEmacLite instance to be worked on.
+* @param CallBackRef is a reference pointer to be passed back to the
+* application in the callback. This helps the application correlate
+* the callback to a particular driver.
+* @param FuncPtr is the pointer to the callback function.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void XEmacLite_SetRecvHandler(XEmacLite *InstancePtr, void *CallBackRef,
+ XEmacLite_Handler FuncPtr)
+{
+ XASSERT_VOID(InstancePtr != XNULL);
+ XASSERT_VOID(FuncPtr != XNULL);
+ XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+ InstancePtr->RecvHandler = FuncPtr;
+ InstancePtr->RecvRef = CallBackRef;
+}
+
+
+/*****************************************************************************/
+/**
+*
+* Sets the callback function for handling transmitted frames in interrupt mode.
+* The upper layer software should call this function during initialization.
+* The callback is called when a frame is transmitted. The callback function
+* should communicate the data to a thread such that the processing is not
+* performed in an interrupt context.
+*
+* The callback is invoked by the driver within interrupt context, so it needs
+* to do its job quickly. If there are other potentially slow operations
+* within the callback, these should be done at task-level.
+*
+* @param InstancePtr is a pointer to the XEmacLite instance to be worked on.
+* @param CallBackRef is a reference pointer to be passed back to the
+* application in the callback. This helps the application correlate
+* the callback to a particular driver.
+* @param FuncPtr is the pointer to the callback function.
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void XEmacLite_SetSendHandler(XEmacLite *InstancePtr, void *CallBackRef,
+ XEmacLite_Handler FuncPtr)
+{
+ XASSERT_VOID(InstancePtr != XNULL);
+ XASSERT_VOID(FuncPtr != XNULL);
+ XASSERT_VOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);
+
+ InstancePtr->SendHandler = FuncPtr;
+ InstancePtr->SendRef = CallBackRef;
+}
Index: drivers/net/xilinx_emaclite/xemaclite_i.h
===================================================================
--- drivers/net/xilinx_emaclite/xemaclite_i.h (revision 0)
+++ drivers/net/xilinx_emaclite/xemaclite_i.h (revision 0)
@@ -0,0 +1,110 @@
+/* $Id: xemaclite_i.h,v 1.2 2004/05/21 19:35:08 meinelte Exp $: */
+/******************************************************************************
+*
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE.
+*
+* (c) Copyright 2004 Xilinx Inc.
+* All rights reserved.
+*
+******************************************************************************/
+/******************************************************************************/
+/**
+* @file xemaclite_i.h
+*
+* This header file contains internal identifiers, which are those shared
+* between the files of the driver. It is intended for internal use only.
+*
+* NOTES:
+*
+* None.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.01a ecm 05/21/04 First release
+* </pre>
+******************************************************************************/
+
+#ifndef XEMACLITE_I_H /* prevent circular inclusions */
+#define XEMACLITE_I_H /* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xemaclite.h"
+
+/************************** Constant Definitions ****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/****************************************************************************/
+/**
+*
+* Get the TX active location to check status. This is used to check if
+* the TX buffer is currently active. There isn't any way in the hardware
+* to implement this but the register is fully populated so the driver can
+* set the bit in the send routine and the ISR can clear the bit when
+* the handler is complete. This mimics the correct operation of the hardware
+* if it was possible to do this in hardware.
+*
+* @param BaseAddress is the base address of the device
+*
+* @return Contents of active bit in register.
+*
+* @note
+* Xuint32 XEmacLite_mGetTxActive(Xuint32 BaseAddress)
+*
+*****************************************************************************/
+#define XEmacLite_mGetTxActive(BaseAddress) \
+ (XIo_In32((BaseAddress) + XEL_TSR_OFFSET))
+
+/****************************************************************************/
+/**
+*
+* Set the TX active location to update status. This is used to set the bit
+* indicating which TX buffer is currently active. There isn't any way in the
+* hardware to implement this but the register is fully populated so the driver
+* can set the bit in the send routine and the ISR can clear the bit when
+* the handler is complete. This mimics the correct operation of the hardware
+* if it was possible to do this in hardware.
+*
+* @param BaseAddress is the base address of the device
+* @param Mask is the data to be written
+*
+* @return None
+*
+* @note
+* void XEmacLite_mSetTxActive(Xuint32 BaseAddress, Xuint32 Mask)
+*
+*****************************************************************************/
+#define XEmacLite_mSetTxActive(BaseAddress, Mask) \
+ (XIo_Out32((BaseAddress) + XEL_TSR_OFFSET, (Mask)))
+
+/************************** Variable Definitions ****************************/
+
+extern XEmacLite_Config XEmacLite_ConfigTable[];
+
+/************************** Function Prototypes ******************************/
+
+void XEmacLite_AlignedWrite(void *SrcPtr, Xuint32 *DestPtr, unsigned ByteCount);
+void XEmacLite_AlignedRead(Xuint32 *SrcPtr, void *DestPtr, unsigned ByteCount);
+
+void StubHandler(void *CallBackRef);
+
+
+#endif /* end of protection macro */
Index: drivers/net/xilinx_emaclite/xemaclite.c
===================================================================
--- drivers/net/xilinx_emaclite/xemaclite.c (revision 0)
+++ drivers/net/xilinx_emaclite/xemaclite.c (revision 0)
@@ -0,0 +1,693 @@
+/* $Id: xemaclite.c,v 1.3 2004/05/28 13:48:04 meinelte Exp $ */
+/******************************************************************************
+*
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE.
+*
+* (c) Copyright 2004 Xilinx Inc.
+* All rights reserved.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemaclite.c
+*
+* Functions in this file are the minimum required functions for the EMAC Lite
+* driver. See xemaclite.h for a detailed description of the driver.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- -------- --------------------------------------------------------
+* 1.01a ecm 01/31/04 First release
+* </pre>
+******************************************************************************/
+
+/***************************** Include Files *********************************/
+
+#include "xstatus.h"
+/*#include "xparameters.h"*/
+#include "xio.h"
+//#include "xenv.h"
+#include "xemaclite.h"
+#include "xemaclite_l.h"
+#include "xemaclite_i.h"
+
+/************************** Constant Definitions *****************************/
+
+/**************************** Type Definitions *******************************/
+
+/***************** Macros (Inline Functions) Definitions *********************/
+/****************************************************************************
+*
+* Return the length of the data in the Receive Buffer.
+*
+* @param InstancePtr is the pointer to the instance of the driver to
+* be worked on
+*
+* @note
+* This macro returns the length of the received data..
+*
+*****************************************************************************/
+#define XEmacLite_mGetReceiveDataLength(BaseAddress) \
+ ((XIo_In32((BaseAddress) + XEL_HEADER_OFFSET + XEL_RXBUFF_OFFSET) >> \
+ XEL_HEADER_SHIFT) & \
+ (XEL_RPLR_LENGTH_MASK_HI | XEL_RPLR_LENGTH_MASK_LO))
+
+/************************** Function Prototypes ******************************/
+/************************** Variable Definitions *****************************/
+/*****************************************************************************/
+/**
+*
+* Initialize a specific XEmacLite instance/driver. The initialization entails:
+* - Initialize fields of the XEmacLite instance structure.
+*
+* The driver defaults to polled mode operation.
+*
+* @param InstancePtr is a pointer to the XEmacLite instance to be worked on.
+* @param DeviceId is the unique id of the device controlled by this XEmacLite
+* instance. Passing in a device id associates the generic XEmacLite
+* instance to a specific device, as chosen by the caller or application
+* developer.
+*
+* @return
+*
+* - XST_SUCCESS if initialization was successful.
+* - XST_DEVICE_NOT_FOUND if device configuration information was not found for
+* a device with the supplied device ID.
+*
+* @note
+*
+* None
+*
+******************************************************************************/
+XStatus XEmacLite_Initialize(XEmacLite *InstancePtr, Xuint16 DeviceId)
+{
+ XEmacLite_Config *EmacLiteConfigPtr; /* Pointer to Configuration data. */
+
+ /*
+ * Verify that each of the inputs are valid.
+ */
+ XASSERT_NONVOID(InstancePtr != XNULL);
+
+ /*
+ * Zero the provided instance memory
+ */
+
+ //XENV_MEM_FILL(InstancePtr, 0, sizeof(XEmacLite));
+ memset(InstancePtr, 0, sizeof(XEmacLite));
+
+ /*
+ * Lookup the device configuration in the configuration table. Use this
+ * configuration info down below when initializing this component.
+ */
+
+ EmacLiteConfigPtr = XEmacLite_LookupConfig(DeviceId);
+ if (EmacLiteConfigPtr == XNULL)
+ {
+ return XST_DEVICE_NOT_FOUND;
+ }
+
+ /*
+ * Set some default values for instance data, don't indicate the device
+ * is ready to use until everything has been initialized successfully
+ */
+
+ InstancePtr->BaseAddress = EmacLiteConfigPtr->BaseAddress;
+ InstancePtr->ConfigPtr = EmacLiteConfigPtr;
+
+ InstancePtr->RecvHandler = (XEmacLite_Handler) StubHandler;
+ InstancePtr->SendHandler = (XEmacLite_Handler) StubHandler;
+
+
+ /*
+ * Clear the TX CSR's in case this is a restart
+ */
+
+ XIo_Out32(InstancePtr->BaseAddress + XEL_TSR_OFFSET, 0);
+ XIo_Out32(InstancePtr->BaseAddress + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0);
+
+ /*
+ * Since there were no failures, indicate the device is ready to use.
+ */
+
+ InstancePtr->IsReady = XCOMPONENT_IS_READY;
+
+ return XST_SUCCESS;
+}
+
+/*****************************************************************************/
+/**
+*
+* Send an Ethernet frame. The ByteCount is the total frame size, including
+* header.
+*
+* @param InstancePtr is a pointer to the XEmacLite instance to be worked on.
+* @param FramePtr is a pointer to frame. For optimal performance, a 32-bit
+* aligned buffer should be used but it is not required, the function
+* will align the data if necessary.
+* @param ByteCount is the size, in bytes, of the frame
+*
+* @return
+*
+* - XST_SUCCESS if data was transmitted.
+* - XST_FAILURE if buffer(s) was (were) full and no valid data was
+* transmitted.
+*
+* @note
+*
+* This function call is not blocking in nature, i.e. it will not wait until the
+* frame is transmitted.
+*
+******************************************************************************/
+XStatus XEmacLite_Send(XEmacLite *InstancePtr, Xuint8 *FramePtr, unsigned ByteCount)
+{
+ Xuint32 Register;
+ Xuint32 BaseAddress;
+
+ /*
+ * Verify that each of the inputs are valid.
+ */
+
+ XASSERT_NONVOID(InstancePtr != XNULL);
+
+ /*
+ * Determine the expected TX buffer address
+ */
+
+ BaseAddress = XEmacLite_mNextTransmitAddr(InstancePtr);
+
+ /*
+ * Check the Length, of too large, truncate
+ */
+
+ if (ByteCount > XEL_MAX_FRAME_SIZE)
+ {
+
+ ByteCount = XEL_MAX_FRAME_SIZE;
+ }
+ /*
+ * Determine if the expected buffer address is empty
+ */
+
+ Register = XIo_In32(BaseAddress + XEL_TSR_OFFSET);
+
+ /*
+ * If the expected buffer is available, fill it with the provided data
+ * Align if necessary.
+ */
+
+
+ if (((Register & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
+ ((XEmacLite_mGetTxActive(BaseAddress) & XEL_TSR_XMIT_ACTIVE_MASK) == 0))
+ {
+
+ /*
+ * Switch to next buffer if configured
+ */
+
+ if (InstancePtr->ConfigPtr->TxPingPong != 0)
+ {
+ InstancePtr->NextTxBufferToUse ^= XEL_BUFFER_OFFSET;
+ }
+
+ /*
+ * Write the frame to the buffer.
+ */
+ XEmacLite_AlignedWrite(FramePtr, (Xuint32 *) BaseAddress, ByteCount);
+
+
+ /*
+ * The frame is in the buffer, now send it
+ */
+ XIo_Out32(BaseAddress + XEL_TPLR_OFFSET, (ByteCount &
+ (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO)));
+
+ Register = XIo_In32(BaseAddress + XEL_TSR_OFFSET);
+
+ Register |= XEL_TSR_XMIT_BUSY_MASK;
+
+ if ((Register & XEL_TSR_XMIT_IE_MASK) != 0)
+ {
+ Register |= XEL_TSR_XMIT_ACTIVE_MASK;
+ }
+
+ XIo_Out32(BaseAddress + XEL_TSR_OFFSET, Register);
+
+ return XST_SUCCESS;
+ }
+
+ /*
+ * If the expected buffer was full, try the other buffer if configured
+ */
+
+ if (InstancePtr->ConfigPtr->TxPingPong != 0)
+ {
+
+ BaseAddress ^= XEL_BUFFER_OFFSET;
+
+ /*
+ * Determine if the expected buffer address is empty
+ */
+
+ Register = XIo_In32(BaseAddress + XEL_TSR_OFFSET);
+
+ /*
+ * If the next buffer is available, fill it with the provided data
+ */
+
+ if (((Register & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
+ ((XEmacLite_mGetTxActive(BaseAddress) & XEL_TSR_XMIT_ACTIVE_MASK) ==
+ 0))
+ {
+
+ /*
+ * Write the frame to the buffer.
+ */
+ XEmacLite_AlignedWrite(FramePtr, (Xuint32 *)BaseAddress, ByteCount);
+
+ /*
+ * The frame is in the buffer, now send it
+ */
+ XIo_Out32(BaseAddress + XEL_TPLR_OFFSET, (ByteCount &
+ (XEL_TPLR_LENGTH_MASK_HI | XEL_TPLR_LENGTH_MASK_LO)));
+
+ Register = XIo_In32(BaseAddress + XEL_TSR_OFFSET);
+
+ Register |= XEL_TSR_XMIT_BUSY_MASK;
+
+ if ((Register & XEL_TSR_XMIT_IE_MASK) != 0)
+ {
+ Register |= XEL_TSR_XMIT_ACTIVE_MASK;
+ }
+
+ XIo_Out32(BaseAddress + XEL_TSR_OFFSET, Register);
+
+ /*
+ * Do not switch to next buffer, there is a sync problem and
+ * the expected buffer should not change.
+ */
+
+ return XST_SUCCESS;
+ }
+ }
+
+
+ /*
+ * Buffer(s) was(were) full, return failure to allow for polling usage
+ */
+
+ return XST_FAILURE;
+}
+
+/*****************************************************************************/
+/**
+*
+* Receive a frame. Intended to be called from the interrupt context or
+* with a wrapper which waits for the receive frame to be available.
+*
+* @param InstancePtr is a pointer to the XEmacLite instance to be worked on.
+* @param FramePtr is a pointer to a buffer where the frame will
+* be stored. The buffer must be at least XEL_MAX_FRAME_SIZE bytes.
+* For optimal performance, a 32-bit aligned buffer should be used but
+* it is not required, the function will align the data if necessary.
+*
+* @return
+*
+* The type/length field of the frame received. When the type/length field
+* contains the type, XEL_MAX_FRAME_SIZE bytes will be copied out of the
+* buffer and it is up to the higher layers to sort out the frame.
+* Function returns 0 if there is no data waiting in the receive buffer or
+* the pong buffer if configured.
+*
+* @note
+*
+* This function call is not blocking in nature, i.e. it will not wait until
+* a frame arrives.
+*
+******************************************************************************/
+Xuint16 XEmacLite_Recv(XEmacLite *InstancePtr, Xuint8 *FramePtr)
+{
+ Xuint16 LengthType;
+ Xuint16 Length;
+ Xuint32 Register;
+ Xuint32 BaseAddress;
+
+ /*
+ * Verify that each of the inputs are valid.
+ */
+
+ XASSERT_NONVOID(InstancePtr != XNULL);
+
+ /*
+ * Determine the expected buffer address
+ */
+
+ BaseAddress = XEmacLite_mNextReceiveAddr(InstancePtr);
+
+ /*
+ * Verify which buffer has valid data
+ */
+
+ Register = XIo_In32(BaseAddress + XEL_RSR_OFFSET);
+
+ if ((Register & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK)
+ {
+
+ /*
+ * The driver is in sync, update the next expected buffer if configured
+ */
+
+ if (InstancePtr->ConfigPtr->RxPingPong != 0)
+ {
+ InstancePtr->NextRxBufferToUse ^= XEL_BUFFER_OFFSET;
+ }
+ }
+ else
+ {
+ /*
+ * The instance is out of sync, try other buffer if other
+ * buffer is configured, return 0 otherwise. If the instance is
+ * out of syne, do not update the 'NextRxBufferToUse' since it
+ * will ce correct on subsequent calls.
+ */
+ if (InstancePtr->ConfigPtr->RxPingPong != 0)
+ {
+ BaseAddress ^= XEL_BUFFER_OFFSET;
+ }
+ else
+ {
+ return 0; /* No data was available */
+ }
+ /*
+ * Verify that buffer has valid data
+ */
+
+ Register = XIo_In32(BaseAddress + XEL_RSR_OFFSET);
+
+ if ((Register & XEL_RSR_RECV_DONE_MASK) != XEL_RSR_RECV_DONE_MASK)
+ {
+ return 0; /* No data was available */
+ }
+ }
+
+ /*
+ * Get the length of the frame that arrived
+ */
+ LengthType = XEmacLite_mGetReceiveDataLength(BaseAddress);
+
+ /* Check if length is valid */
+
+ if (LengthType > XEL_MAX_FRAME_SIZE)
+ {
+ /* Field contains type, use max frame size and let user parse it */
+ Length = XEL_MAX_FRAME_SIZE;
+ }
+ else
+ {
+ /* Use the length in the frame, plus the header and trailer */
+ Length = LengthType + XEL_HEADER_SIZE + XEL_FCS_SIZE;
+ }
+
+ /*
+ * Read from the EMAC Lite
+ */
+ XEmacLite_AlignedRead(((Xuint32 *)(BaseAddress + XEL_RXBUFF_OFFSET)),
+ FramePtr, Length);
+
+ /*
+ * Acknowledge the frame
+ */
+
+ Register = XIo_In32(BaseAddress + XEL_RSR_OFFSET);
+
+ Register &= ~XEL_RSR_RECV_DONE_MASK;
+
+ XIo_Out32(BaseAddress + XEL_RSR_OFFSET, Register);
+
+
+ return Length;
+}
+
+/*****************************************************************************/
+/**
+*
+* Set the MAC address for this device. The address is a 48-bit value.
+*
+* @param InstancePtr is a pointer to the XEmacLite instance to be worked on.
+* @param AddressPtr is a pointer to a 6-byte MAC address.
+* the format of the MAC address is major octet to minor octet
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* TX must be idle and RX should be idle for deterministic results.
+*
+* Function will not return if hardware is absent or not functioning
+* properly.
+*
+******************************************************************************/
+void XEmacLite_SetMacAddress(XEmacLite *InstancePtr, Xuint8 *AddressPtr)
+{
+ Xuint32 BaseAddress;
+
+ /*
+ * Verify that each of the inputs are valid.
+ */
+
+ XASSERT_VOID(InstancePtr != XNULL);
+
+ BaseAddress = InstancePtr->BaseAddress + InstancePtr->NextTxBufferToUse +
+ XEL_TXBUFF_OFFSET;
+
+ /*
+ * Copy the MAC address to the Transmit buffer
+ */
+ XEmacLite_AlignedWrite(AddressPtr, (Xuint32 *)BaseAddress, XEL_MAC_ADDR_SIZE);
+
+ /*
+ * Set the length
+ */
+
+ XIo_Out32(BaseAddress + XEL_TPLR_OFFSET, XEL_MAC_ADDR_SIZE);
+
+ /*
+ * Update the MAC address in the EMAC Lite
+ */
+
+ XIo_Out32(BaseAddress + XEL_TSR_OFFSET, XEL_TSR_PROG_MAC_ADDR);
+
+
+ /*
+ * Wait for EMAC Lite to finish with the MAC address update
+ */
+
+ while ((XIo_In32(BaseAddress + XEL_TSR_OFFSET ) &
+ XEL_TSR_PROG_MAC_ADDR) != 0 );
+
+ /*
+ * Switch to next buffer if configured
+ */
+
+ if (InstancePtr->ConfigPtr->TxPingPong != 0)
+ {
+ InstancePtr->NextTxBufferToUse ^= XEL_BUFFER_OFFSET;
+ }
+
+}
+
+/*****************************************************************************/
+/**
+*
+* Lookup the device configuration based on the unique device ID. The table
+* XEmacLite_ConfigTable contains the configuration info for each device in the
+* system.
+*
+* @param DeviceId is the unique device ID of the device being looked up.
+*
+* @return
+*
+* A pointer to the configuration table entry corresponding to the given
+* device ID, or XNULL if no match is found.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+XEmacLite_Config *XEmacLite_LookupConfig(Xuint16 DeviceId)
+{
+ XEmacLite_Config *CfgPtr = XNULL;
+ int i;
+
+ for (i = 0; i < CONFIG_XILINX_ETHERNETLITE_NUM_INSTANCES; i++)
+ {
+ if (XEmacLite_ConfigTable[i].DeviceId == DeviceId)
+ {
+ CfgPtr = &XEmacLite_ConfigTable[i];
+ break;
+ }
+ }
+
+ return CfgPtr;
+}
+
+/******************************************************************************/
+/**
+*
+* This is a stub for the send and recv callbacks. The stub
+* is here in case the upper layers forget to set the handlers.
+*
+* @param CallBackRef is a pointer to the upper layer callback reference
+*
+* @return
+*
+* None.
+*
+* @note
+*
+* None.
+*
+******************************************************************************/
+void StubHandler(void *CallBackRef)
+{
+ XASSERT_VOID_ALWAYS();
+}
+
+
+/****************************************************************************/
+/**
+*
+* Determine if there is a transmit buffer available.
+*
+* @param InstancePtr is the pointer to the instance of the driver to
+* be worked on
+*
+* @return XTRUE if there is a TX buffer available for data to be written into,
+* XFALSE otherwise.
+*
+* @note
+*
+*****************************************************************************/
+Xboolean XEmacLite_TxBufferAvailable(XEmacLite *InstancePtr)
+{
+
+ Xuint32 Register;
+ Xboolean TxPingBusy;
+ Xboolean TxPongBusy;
+ /*
+ * Verify that each of the inputs are valid.
+ */
+
+ XASSERT_NONVOID(InstancePtr != XNULL);
+
+ /*
+ * Read the current buffer register and determine if the buffer is available
+ */
+
+ Register = XIo_In32(InstancePtr->BaseAddress +
+ InstancePtr->NextTxBufferToUse +
+ XEL_TXBUFF_OFFSET);
+
+ TxPingBusy = ((Register & XEL_TSR_XMIT_BUSY_MASK) == XEL_TSR_XMIT_BUSY_MASK);
+
+ /*
+ * Read the other buffer register and determine if the other buffer is available
+ */
+
+ Register = XIo_In32(InstancePtr->BaseAddress +
+ (InstancePtr->NextTxBufferToUse^ XEL_TSR_OFFSET) +
+ XEL_TXBUFF_OFFSET);
+
+ TxPongBusy = ((Register & XEL_TSR_XMIT_BUSY_MASK) == XEL_TSR_XMIT_BUSY_MASK);
+
+ return (!(TxPingBusy && TxPongBusy));
+
+}
+
+/****************************************************************************/
+/**
+*
+*
+* Flush the Receive buffers. All data will be lost.
+*
+* @param InstancePtr is the pointer to the instance of the driver to
+* be worked on
+*
+* @return None.
+*
+* @note
+*
+*****************************************************************************/
+void XEmacLite_FlushReceive(XEmacLite *InstancePtr)
+{
+
+ Xuint32 Register;
+ /*
+ * Verify that each of the inputs are valid.
+ */
+
+ XASSERT_VOID(InstancePtr != XNULL);
+
+ /*
+ * Read the current buffer register and determine if the buffer is available
+ */
+
+ Register = XIo_In32(InstancePtr->BaseAddress + XEL_RSR_OFFSET);
+
+ /*
+ * Preserve the IE bit
+ */
+ Register &= XEL_RSR_RECV_IE_MASK;
+
+ /*
+ * Write out the value to flush the RX buffer
+ */
+
+ XIo_Out32(InstancePtr->BaseAddress + XEL_RSR_OFFSET, Register);
+
+ /*
+ * If the pong buffer is available, flush it also
+ */
+
+ if (InstancePtr->ConfigPtr->RxPingPong != 0)
+ {
+ /*
+ * Read the current buffer register and determine if the buffer is
+ * available
+ */
+
+ Register = XIo_In32(InstancePtr->BaseAddress + XEL_RSR_OFFSET +
+ XEL_BUFFER_OFFSET);
+
+ /*
+ * Preserve the IE bit
+ */
+ Register &= XEL_RSR_RECV_IE_MASK;
+
+ /*
+ * Write out the value to flush the RX buffer
+ */
+
+ XIo_Out32(InstancePtr->BaseAddress + XEL_RSR_OFFSET + XEL_BUFFER_OFFSET,
+ Register);
+
+ }
+
+}
Index: drivers/net/xilinx_emaclite/xemaclite_l.h
===================================================================
--- drivers/net/xilinx_emaclite/xemaclite_l.h (revision 0)
+++ drivers/net/xilinx_emaclite/xemaclite_l.h (revision 0)
@@ -0,0 +1,182 @@
+/* $Id: xemaclite_l.h,v 1.2 2004/05/24 20:48:12 meinelte Exp $ */
+/******************************************************************************
+*
+* XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
+* AS A COURTESY TO YOU, SOLELY FOR USE IN DEVELOPING PROGRAMS AND
+* SOLUTIONS FOR XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE,
+* OR INFORMATION AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE,
+* APPLICATION OR STANDARD, XILINX IS MAKING NO REPRESENTATION
+* THAT THIS IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
+* AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
+* FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
+* WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
+* IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
+* REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
+* INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+* FOR A PARTICULAR PURPOSE.
+*
+* (c) Copyright 2004 Xilinx Inc.
+* All rights reserved.
+*
+******************************************************************************/
+/*****************************************************************************/
+/**
+*
+* @file xemaclite_l.h
+*
+* This header file contains identifiers and low-level driver functions and
+* macros that can be used to access the device.
+*
+* The Xilinx Ethernet Lite driver component. This component supports the Xilinx
+* Lite Ethernet 10/100 MAC (EMAC Lite).
+*
+* Refer to xemaclite.h for more details.
+*
+* @note
+*
+* The functions and macros in this file assume that the proper device address is
+* provided in the argument. If the ping buffer is the source or destination,
+* the argument should be DeviceAddress + XEL_(T/R)XBUFF_OFFSET. If the pong
+* buffer is the source or destination, the argument should be
+* DeviceAddress + XEL_(T/R)XBUFF_OFFSET + XEL_BUFFER_OFFSET. The driver does
+* not take the different buffers into consideration.
+* For more details on the ping/pong buffer configuration please refer to the
+* OPB Ehternet Lite Media Access Controller hardware specification.
+*
+* <pre>
+* MODIFICATION HISTORY:
+*
+* Ver Who Date Changes
+* ----- ---- -------- -----------------------------------------------
+* 1.00a ecm 06/01/02 First release
+* 1.01a ecm 03/31/04 Additional functionality and the _AlignedRead and
+* AlignedWrite functions.
+* Moved the bulk of description to xemaclite.h
+* </pre>
+*
+******************************************************************************/
+
+#ifndef XEMAC_LITE_L_H /* prevent circular inclusions */
+#define XEMAC_LITE_L_H /* by using protection macros */
+
+/***************************** Include Files *********************************/
+
+#include "xbasic_types.h"
+#include "xio.h"
+
+/************************** Constant Definitions *****************************/
+/**
+ * Register offsets for the Ethernet MAC.
+ */
+#define XEL_TXBUFF_OFFSET (0x00000000) /**< Transmit Buffer */
+#define XEL_GIER_OFFSET (XEL_TXBUFF_OFFSET + 0x07F8) /**< Offset for the GIE bit */
+#define XEL_TSR_OFFSET (XEL_TXBUFF_OFFSET + 0x07FC) /**< Tx status */
+#define XEL_TPLR_OFFSET (XEL_TXBUFF_OFFSET + 0x07F4) /**< Tx packet length */
+
+#define XEL_RXBUFF_OFFSET (0x00001000) /**< Receive Buffer */
+#define XEL_RSR_OFFSET (XEL_RXBUFF_OFFSET + 0x07FC) /**< Rx status */
+#define XEL_RPLR_OFFSET (XEL_RXBUFF_OFFSET + 0x0C) /**< Rx packet length */
+
+#define XEL_MAC_HI_OFFSET (XEL_TXBUFF_OFFSET + 0x14) /**< MAC address hi offset */
+#define XEL_MAC_LO_OFFSET (XEL_TXBUFF_OFFSET) /**< MAC address lo offset */
+
+#define XEL_BUFFER_OFFSET (0x00000800) /**< Next buffer's offset
+ same for both TX and RX*/
+
+/**
+ * Global Interrupt Enable Register (GIER)
+ */
+#define XEL_GIER_GIE_MASK 0x80000000UL /**< Global Enable */
+
+/**
+ * Transmit Status Register (TSR)
+ */
+#define XEL_TSR_XMIT_BUSY_MASK 0x00000001UL /**< Xmit complete */
+#define XEL_TSR_PROGRAM_MASK 0x00000002UL /**< Program the MAC address */
+#define XEL_TSR_XMIT_IE_MASK 0x00000008UL /**< Xmit interrupt enable bit */
+#define XEL_TSR_XMIT_ACTIVE_MASK 0x80000000UL /**< Buffer is active, SW bit only */
+
+/**
+ * define for programming the MAC address into the EMAC Lite
+ */
+
+#define XEL_TSR_PROG_MAC_ADDR (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_PROGRAM_MASK)
+
+/**
+ * Receive Status Register (RSR)
+ */
+#define XEL_RSR_RECV_DONE_MASK 0x00000001UL /**< Recv complete */
+#define XEL_RSR_RECV_IE_MASK 0x00000008UL /**< Recv interrupt enable bit */
+
+/**
+ * Transmit Packet Length Register (TPLR)
+ */
+#define XEL_TPLR_LENGTH_MASK_HI 0x0000FF00UL /**< Transmit packet length upper byte */
+#define XEL_TPLR_LENGTH_MASK_LO 0x000000FFUL /**< Transmit packet length lower byte */
+
+/**
+ * Receive Packet Length Register (RPLR)
+ */
+#define XEL_RPLR_LENGTH_MASK_HI 0x0000FF00UL /**< Receive packet length upper byte */
+#define XEL_RPLR_LENGTH_MASK_LO 0x000000FFUL /**< Receive packet length lower byte */
+
+#define XEL_HEADER_SIZE 14 /**< Size of header in bytes */
+#define XEL_MTU_SIZE 1500 /**< Max size of data in frame */
+#define XEL_FCS_SIZE 4 /**< Size of CRC */
+
+#define XEL_HEADER_OFFSET 12 /**< Offset to length field */
+#define XEL_HEADER_SHIFT 16 /**< Right shift value to align length */
+
+
+#define XEL_MAX_FRAME_SIZE (XEL_HEADER_SIZE+XEL_MTU_SIZE+XEL_FCS_SIZE)
+ /**< Maximum lenght of rx frame
+ used if length/type field
+ contains the type (> 1500) */
+
+#define XEL_MAC_ADDR_SIZE 6 /**< length of MAC address */
+
+
+/***************** Macros (Inline Functions) Definitions *********************/
+
+/****************************************************************************/
+/**
+*
+* Check to see if the transmission is complete.
+*
+* @param BaseAddress is the base address of the device
+*
+* @return XTRUE if it is done, or XFALSE if it is not.
+*
+* @note
+* Xboolean XEmacLite_mIsTxDone(Xuint32 BaseAddress)
+*
+*****************************************************************************/
+#define XEmacLite_mIsTxDone(BaseAddress) \
+ ((XIo_In32((BaseAddress) + XEL_TSR_OFFSET) & \
+ XEL_TSR_XMIT_BUSY_MASK) != XEL_TSR_XMIT_BUSY_MASK)
+
+
+/****************************************************************************/
+/**
+*
+* Check to see if the receive is empty.
+*
+* @param BaseAddress is the base address of the device
+*
+* @return XTRUE if it is empty, or XFALSE if it is not.
+*
+* @note
+* Xboolean XEmacLite_mIsRxEmpty(Xuint32 BaseAddress)
+*
+*****************************************************************************/
+#define XEmacLite_mIsRxEmpty(BaseAddress) \
+ ((XIo_In32((BaseAddress) + XEL_RSR_OFFSET) & \
+ XEL_RSR_RECV_DONE_MASK) != XEL_RSR_RECV_DONE_MASK)
+
+/************************** Function Prototypes ******************************/
+
+void XEmacLite_SendFrame(Xuint32 BaseAddress, Xuint8 *FramePtr, unsigned ByteCount);
+Xuint16 XEmacLite_RecvFrame(Xuint32 BaseAddress, Xuint8 *FramePtr);
+
+
+#endif /* end of protection macro */
Index: drivers/net/xilinx_emaclite/Makefile
===================================================================
--- drivers/net/xilinx_emaclite/Makefile (revision 0)
+++ drivers/net/xilinx_emaclite/Makefile (revision 0)
@@ -0,0 +1,20 @@
+#
+# Makefile for the Xilinx ethernet Lite driver
+#
+
+EXTRA_CFLAGS += -I$(TOPDIR)/arch/microblaze/xilinx_ocp
+
+list-multi := xilinx_emaclite.o
+
+# The Linux adapter for the Xilinx driver code.
+xilinx_emaclite-objs += adapter.o
+
+# The Xilinx OS independent code.
+xilinx_emaclite-objs += xemaclite.o xemaclite_g.o xemaclite_intr.o xemaclite_l.o
+
+obj-$(CONFIG_XILINX_EMACLITE) := xilinx_emaclite.o
+
+xilinx_emaclite.o: $(xilinx_emaclite-objs)
+ $(LD) -r -o $@ $(xilinx_emaclite-objs)
+
+include $(TOPDIR)/Rules.make
Index: drivers/net/Makefile
===================================================================
--- drivers/net/Makefile (revision 309)
+++ drivers/net/Makefile (working copy)
@@ -102,10 +102,16 @@
obj-$(CONFIG_TC35815) += tc35815.o
obj-$(CONFIG_TIGON3) += tg3.o
+# Xilinx Ethernet MAC
mod-subdirs += xilinx_enet
subdir-$(CONFIG_XILINX_ENET) += xilinx_enet
obj-$(CONFIG_XILINX_ENET) += xilinx_enet/xilinx_enet.o
+# Xilinx Ethernet MAC Lite
+mod-subdirs += xilinx_emaclite
+subdir-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite
+obj-$(CONFIG_XILINX_EMACLITE) += xilinx_emaclite/xilinx_emaclite.o
+
ifeq ($(CONFIG_E100),y)
obj-y += e100/e100.o
endif