summaryrefslogtreecommitdiff
path: root/polux/linux-2.6.10
diff options
context:
space:
mode:
authorNĂ©lio Laranjeiro2012-02-23 11:05:55 +0100
committerYacine Belkadi2012-06-11 13:39:53 +0200
commitb7fe8fa73e3b880b97893e1faba67308547e2597 (patch)
tree315f5108bd189caf042c361f5fd880efd7b2fbeb /polux/linux-2.6.10
parent9549a1be60381f2b31d64d4f9ee3d041e61fbc3d (diff)
polux/linux/drv/net: copied ks8001 to synop3504, refs #2967
Diffstat (limited to 'polux/linux-2.6.10')
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/KS8001.c2275
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/KS8001_dma.c694
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/KS8001_dma.h73
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw.h13
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw_spc2XXc.h90
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw_vi1888.h75
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/KS8001_mii.h349
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/KS8001_reg.h192
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/KS8001_regdef.h526
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/KS8001_sys.h13
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/Kconfig20
-rw-r--r--polux/linux-2.6.10/drivers/net/synop3504/Makefile3
12 files changed, 4323 insertions, 0 deletions
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/KS8001.c b/polux/linux-2.6.10/drivers/net/synop3504/KS8001.c
new file mode 100644
index 0000000000..72c960edd0
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/KS8001.c
@@ -0,0 +1,2275 @@
+/**
+ *
+ * (C) Copyright 2007 SPiDCOM Technologies
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#undef CONFIG_PROC_FS
+
+#define DRV_NAME "KS8001"
+#define DRV_VERSION "2.1"
+#define DRV_RELDATE "April 10, 2009"
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+#include <linux/proc_fs.h>
+#include <asm/cacheflush.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/dma-mapping.h>
+#include <linux/kthread.h>
+
+MODULE_AUTHOR ("SPiDCOM Technologies");
+MODULE_DESCRIPTION ("Synopsys" DRV_NAME "ethernet driver");
+MODULE_LICENSE ("GPL");
+MODULE_VERSION (DRV_VERSION);
+
+//These identify the driver base version and may not be removed
+static char version[] __devinitdata = DRV_NAME " 10/100 Ethernet driver v" DRV_VERSION " (" DRV_RELDATE ")\n";
+
+static int debug = 0;
+
+/** Synopsys device definitions and functions */
+#include "KS8001_reg.h"
+#include "KS8001_regdef.h"
+#include "KS8001_hw.h"
+#include "KS8001_dma.h"
+#include "KS8001_mii.h"
+
+#define TXDESCS 32
+#define RXDESCS 128
+
+#define MAC_OFFSET 0x0000
+#define DMA_OFFSET 0x1000
+
+#define MSEC_PER_JIFFY (1000/HZ) //aligned on HZ, which corresponds to 10ms
+#define AUTONEG_STEP (100) //in ms
+#define RESET_STEP (100) //in ms
+#define AUTONEG_TIMEOUT (10) //in s
+#define TIMEOUT (2*HZ)
+
+//IOCTL are triplicated in linux/KS8001.c, linux-tools/safe-return.c and app/mib-interface.h
+#define SIOCGLINKSTATUS (SIOCDEVPRIVATE+0)
+#define SIOCGSETLINKSPEED (SIOCDEVPRIVATE+1)
+#define SIOCGGETLINKSETUPSPEED (SIOCDEVPRIVATE+2)
+#define SIOCGGETLINKCURRENTSPEED (SIOCDEVPRIVATE+3)
+#define SIOCGSETLINKMODE (SIOCDEVPRIVATE+4)
+#define SIOCGGETLINKSETUPMODE (SIOCDEVPRIVATE+5)
+#define SIOCGGETLINKCURRENTMODE (SIOCDEVPRIVATE+6)
+
+#define ETH_MODE_AUTO 0
+#define ETH_MODE_FD 1
+#define ETH_MODE_HD 2
+
+#ifdef CONFIG_SLAVE
+# define NVRAM_ADDRESS (0x08010000)
+#else
+# define NVRAM_ADDRESS (0x08020000)
+#endif
+
+#define NVRAM_ETH_OFFSET (0x14C)
+
+struct SynopsysMacReg {
+ uint32_t GmacConfig;
+ uint32_t GmacFrameFilter;
+ uint32_t GmacFlowControl;
+ uint32_t GmacGmiiAddr;
+};
+
+/** Driver private data */
+typedef struct PrivateStruct {
+ Synopsys synopsys;
+ struct syeth_dma_rb *rx;
+ struct syeth_dma_rb *tx;
+ int minor;
+ struct net_device_stats stats;
+ struct timer_list timer;
+ struct mii_if_info mii_if;
+ enum phy_chipset_id OUI_model;
+ uint32_t phy_id;
+ uint32_t phy_oui;
+ uint32_t phy_model;
+ uint32_t phy_rev;
+ struct SynopsysMacReg macreg;
+} Private;
+
+static uint32_t phy_modes = ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL;
+static int eth_duplex_mode = 0;
+static int eth_speed = 0;
+static int init_finish = 0;
+
+/**
+ * Function : mdly
+ * Purpose : delay for thread.
+ * Parameters : msec->value of the delay in ms
+ * Return value : void.
+ */
+static inline void mdly (unsigned int msec)
+{
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout((msec + MSEC_PER_JIFFY - 1) / MSEC_PER_JIFFY);
+}//mdly
+
+/**
+ * Function : ks8001_receive
+ * Purpose : Receives the packet and give to the upper layers.
+ * Parameters : dev->network device
+ * budget->maximum packets count
+ * Return value : void.
+ */
+static void ks8001_receive (struct net_device *dev, int *budget)
+{
+ Private *pr = NULL;
+ Synopsys *tc = NULL;
+ struct sk_buff *skb = NULL;
+ int count = 0;
+
+ pr = (Private *)dev->priv;
+ tc = &pr->synopsys;
+
+ if(*budget == 0)
+ return;
+
+ do
+ {
+ skb = syeth_dma_rx_rb_get(pr->rx);
+ if(skb == NULL)
+ break;
+ skb->dev = dev;
+ skb->protocol = eth_type_trans(skb, dev);
+ dev->last_rx = jiffies;
+ // with NAPI buffer have to be processed immediatelly
+ netif_receive_skb(skb);
+ (*budget)--;
+ count++;
+ } while(skb && *budget);
+}//ks8001_receive
+
+/**
+ * Function : ks8001_poll
+ * Purpose : This will call by netif framework for poll the device.
+ * Parameters : dev->network device structure
+ * budget->maximum count of packets to receive
+ * Return value : error code.
+ */
+static int ks8001_poll (struct net_device *dev, int *budget)
+{
+ Private *pr = NULL;
+ Synopsys *tc = NULL;
+ u32 status;
+ int tbudget, ibudget;
+
+ pr = (Private *)dev->priv;
+ tc = &pr->synopsys;
+
+ tbudget = *budget;
+ //we have to receive no more packet then the current budget and the device quota
+ if(tbudget > dev->quota)
+ {
+ tbudget = dev->quota;
+ }
+ ibudget = tbudget;
+
+ do
+ {
+ //Get and cleanup IRQ status as soon as possible
+ status = SynopsysReadDmaReg(tc, DmaStatus);
+ SynopsysWriteDmaReg(tc, DmaStatus, status);
+
+ status &= DmaIntMask;
+
+ if(status == 0)
+ break;
+
+ if(status & DmaIntBusError)
+ {
+ //DMA error occured
+ printk(DRV_NAME ": %s: poll: DMA error occured - fatal\n", dev->name);
+ }
+
+ if(status & DmaIntTxNoBuffer)
+ {
+ syeth_dma_tx_rb_complete(pr->tx);
+ }
+
+ if(status & (DmaIntTxCompleted | DmaIntTxNoBuffer))
+ {
+ if(netif_queue_stopped(dev))
+ {
+ netif_wake_queue(dev);
+ debugp (DRV_NAME ": %s: TX normal: Wake Up send queue\n", dev->name);
+ }
+ }
+
+ if(status & DmaIntTxUnderflow)
+ {
+ //Abnormal transmitter interrupt
+ printk(DRV_NAME ": %s: interupt: Abnormal Tx Interrupt Seen\n", dev->name);
+ //Remove old buffers from TX descriptors
+ syeth_dma_tx_rb_complete(pr->tx);
+ netif_start_queue(dev);
+ }
+
+ if(status & (DmaIntRxCompleted | DmaIntRxNoBuffer))
+ {
+ ks8001_receive(dev, &tbudget);
+ }
+
+ if(status & DmaIntRxNoBuffer)
+ {
+ //Abnormal receiver interrupt
+ debugp(DRV_NAME ": %s: interupt: Abnormal Rx Interrupt Seen\n", dev->name);
+ pr->stats.rx_over_errors++;
+ SynopsysWriteDmaReg(tc, DmaRxPollDemand, 0);
+ }
+
+ if(status & DmaIntRxStopped)
+ {
+ //Receiver went to stopped state
+ printk(DRV_NAME ": %s: interupt: Rx Stopped Interrupt Seen\n", dev->name);
+ }
+
+ if(status & DmaIntTxStopped)
+ {
+ //Transmitter went to stopped state
+ printk(DRV_NAME ": %s: interupt: Tx Stopped Interrupt Seen\n", dev->name);
+ netif_stop_queue(dev);
+ syeth_dma_tx_rb_reset(pr->tx);
+ }
+
+ } while(tbudget > 0);
+
+ *budget -= ibudget - tbudget;
+ dev->quota -= ibudget - tbudget;
+ if(status == 0)
+ {
+ netif_rx_complete(dev);
+ //Enable Interrupts
+ SynopsysWriteDmaReg(tc, DmaInterrupt, DmaIntEnable);
+ return 0;
+ }
+ return 1;
+}//ks8001_poll
+
+/**
+ * Function : int_handler
+ * Purpose : This will call the particular handler according to
+ * the interrupt.
+ * Parameters : int_num->interrupt number
+ * dev_id->device address
+ * Return value : error code.
+ */
+static irqreturn_t int_handler (int int_num, void *dev_id,
+ struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *)dev_id;
+ Private *pr = NULL;
+ Synopsys *tc = NULL;
+
+ pr = (Private *)dev->priv;
+ if (pr == NULL)
+ return IRQ_NONE;
+
+ tc = &pr->synopsys;
+ if (tc == NULL)
+ return IRQ_NONE;
+
+ //Clear interrupts
+ SynopsysWriteDmaReg(tc, DmaInterrupt, 0);
+ if(netif_rx_schedule_prep(dev))
+ {
+ __netif_rx_schedule(dev);
+ }
+ else
+ {
+ printk(DRV_NAME ": %s: interrupt: driver bug! interrupt while in poll\n", dev->name);
+ }
+ return IRQ_HANDLED;
+}//int_handler
+
+/**
+ * Function : ks8001_init_mac_register
+ * Purpose : Set default options of synopsys MAC IP.
+ * Parameters : dev->network device structure
+ * Return value : error code.
+ */
+static void ks8001_init_mac_register (struct net_device *dev)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+ uint32_t data;
+ int fdx;
+
+ switch (pr->OUI_model)
+ {
+ case ICS_1893BF:
+ case ICS_1893CF:
+ data = SynopsysMiiRead(tc, MII_QPDSR, AUTOMATIC_PHY_RESOLUTION);
+ fdx = data & QPDSR_FULLDPLX;
+ break;
+
+ case MICREL_KS8721:
+ //using PHYCTRL instead of BMCR
+ data = SynopsysMiiRead(tc, MII_PHYCTRL, AUTOMATIC_PHY_RESOLUTION);
+ fdx = (data & PHYCTRL_OP_MODE)==PHYCTRL_OM_10FULL || (data & PHYCTRL_OP_MODE)==PHYCTRL_OM_100FULL;
+ break;
+
+ default:
+ case REALTEK_RTL8201CP:
+ case ICPLUS_IP101A:
+ case JVA_1893BF:
+ //BMCR duplex status after autonegotiation is not standard : works on RTL8201CP
+ data = SynopsysMiiRead(tc, MII_BMCR, AUTOMATIC_PHY_RESOLUTION);
+ fdx = data & BMCR_FULLDPLX;
+ break;
+
+ case ICPLUS_IP175C:
+ case ICPLUS_IP175D:
+ // MII speed and mode returned... because 5 Port possibless
+ data = SynopsysMiiRead(tc, MII_BMCR, 5);
+ fdx = data & BMCR_FULLDPLX;
+ break;
+ }
+
+ if(fdx)
+ {
+ SynopsysWriteMacReg(tc, GmacConfig, GmacConfigInitFdx110);
+ SynopsysWriteMacReg(tc, GmacFrameFilter, GmacFrameFilterInitFdx);
+ SynopsysWriteMacReg(tc, GmacFlowControl, GmacFlowControlInitFdx);
+ SynopsysWriteMacReg(tc, GmacGmiiAddr, GmacGmiiAddrInitFdx);
+ }
+ else
+ {
+ SynopsysWriteMacReg(tc, GmacConfig, GmacConfigInitHdx110);
+ SynopsysWriteMacReg(tc, GmacFrameFilter, GmacFrameFilterInitHdx);
+ SynopsysWriteMacReg(tc, GmacFlowControl, GmacFlowControlInitHdx);
+ SynopsysWriteMacReg(tc, GmacGmiiAddr, GmacGmiiAddrInitHdx);
+ }
+}//ks8001_init_mac_register
+
+/**
+ * Function : ks8001_save_mac_register
+ * Purpose : Save options of the synopsys MAC IP.
+ * Parameters : dev->network device structure
+ * Return value : error code.
+ */
+static int ks8001_save_mac_register (struct net_device *dev)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+
+ pr->macreg.GmacConfig = SynopsysReadMacReg(tc, GmacConfig);
+ pr->macreg.GmacFrameFilter = SynopsysReadMacReg(tc, GmacFrameFilter);
+ pr->macreg.GmacFlowControl = SynopsysReadMacReg(tc, GmacFlowControl);
+ pr->macreg.GmacGmiiAddr = SynopsysReadMacReg(tc, GmacGmiiAddr);
+}//ks8001_save_mac_register
+
+/**
+ * Function : ks8001_restore_mac_register
+ * Purpose : Restore options of the synopsys MAC IP.
+ * Parameters : dev->network device structure
+ * Return value : error code.
+ */
+static int ks8001_restore_mac_register (struct net_device *dev)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+
+ SynopsysWriteMacReg(tc, GmacConfig, pr->macreg.GmacConfig);
+ SynopsysWriteMacReg(tc, GmacFrameFilter, pr->macreg.GmacFrameFilter);
+ SynopsysWriteMacReg(tc, GmacFlowControl, pr->macreg.GmacFlowControl);
+ SynopsysWriteMacReg(tc, GmacGmiiAddr, pr->macreg.GmacGmiiAddr);
+}//ks8001_restore_mac_register
+
+/**
+ * Function : ks8001_an_complete
+ * Purpose : Set the correct duplex mode to the hardware after AN.
+ * Parameters : dev->network device structure
+ * Return value : error code.
+ */
+static void ks8001_an_complete (struct net_device *dev)
+{
+ Private* pr = (Private*)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+ uint32_t data;
+ uint32_t control;
+ int s100_used = 0;
+ int fd_used = 0;
+
+ //Check the duplex mode (result of the Autonegotiation)
+ switch (pr->OUI_model)
+ {
+ case ICS_1893BF:
+ case ICS_1893CF:
+ data = SynopsysMiiRead(tc, MII_QPDSR, AUTOMATIC_PHY_RESOLUTION);
+ s100_used = data & QPDSR_SPEED100;
+ fd_used = data & QPDSR_FULLDPLX;
+ break;
+
+ case MICREL_KS8721:
+ //using PHYCTRL instead of BMCR
+ data = SynopsysMiiRead(tc, MII_PHYCTRL, AUTOMATIC_PHY_RESOLUTION);
+ s100_used = (data & PHYCTRL_OP_MODE)==PHYCTRL_OM_100HALF || (data & PHYCTRL_OP_MODE)==PHYCTRL_OM_100FULL;
+ fd_used = (data & PHYCTRL_OP_MODE)==PHYCTRL_OM_10FULL || (data & PHYCTRL_OP_MODE)==PHYCTRL_OM_100FULL;
+ break;
+
+ default:
+ case REALTEK_RTL8201CP:
+ case ICPLUS_IP101A:
+ case JVA_1893BF:
+ //BMCR duplex status after autonegotiation is not standard : works on RTL8201CP
+ data = SynopsysMiiRead(tc, MII_BMCR, AUTOMATIC_PHY_RESOLUTION);
+ s100_used = data & BMCR_SPEED100;
+ fd_used = data & BMCR_FULLDPLX;
+ break;
+
+ case ICPLUS_IP175C:
+ case ICPLUS_IP175D:
+ // MII speed and mode returned... because 5 Port possibless
+ data = SynopsysMiiRead(tc, MII_BMCR, 5);
+ s100_used = data & BMCR_SPEED100;
+ fd_used = data & BMCR_FULLDPLX;
+ break;
+ }
+
+ //Store the duplex mode in hardware
+ ks8001_hw_set_speed(pr->minor, ((s100_used|fd_used) & 0x0008));
+
+ switch (pr->OUI_model)
+ {
+ case ICPLUS_IP175C:
+ case ICPLUS_IP175D:
+ // Do Nothing.
+ break;
+
+ default:
+ case REALTEK_RTL8201CP:
+ case ICPLUS_IP101A:
+ case JVA_1893BF:
+ // Nothing to do.
+ break;
+
+ case MICREL_KS8721:
+ case ICS_1893BF:
+ case ICS_1893CF:
+ // Set the correct duplex mode to the hardware after AN.
+ control = SynopsysMiiRead(tc, MII_BMCR, AUTOMATIC_PHY_RESOLUTION);
+ if(s100_used)
+ control |= BMCR_SPEED100;
+ else
+ control &= ~BMCR_SPEED100;
+ if(fd_used)
+ control |= BMCR_FULLDPLX;
+ else
+ control &= ~BMCR_FULLDPLX;
+ SynopsysMiiWrite(tc, MII_BMCR, control, AUTOMATIC_PHY_RESOLUTION);
+ debugp(DRV_NAME": %s: Store Speed and Duplex given by AutoNegotiation (10%sMbit/s %s-Duplex)\n", dev->name,
+ s100_used ? "0" : "", fd_used ? "Full" : "Half");
+ break;
+ }
+}//ks8001_an_complete
+
+static void ks8001_reset_phy (struct net_device *dev)
+{
+ Private* pr = (Private*)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+
+ switch (pr->OUI_model)
+ {
+ default:
+ case ICS_1893BF:
+ case ICS_1893CF:
+ case MICREL_KS8721:
+ case REALTEK_RTL8201CP:
+ case ICPLUS_IP101A:
+ case JVA_1893BF:
+ {
+ SynopsysMiiWrite(tc, MII_BMCR, BMCR_RESET, AUTOMATIC_PHY_RESOLUTION);
+ while(SynopsysMiiRead(tc, MII_BMCR, AUTOMATIC_PHY_RESOLUTION) & BMCR_RESET);
+ }
+ break;
+
+ case ICPLUS_IP175C:
+ SynopsysMiiWrite(tc, 0, 0x175C, 30);
+ mdly(RESET_STEP);
+ break;
+
+ case ICPLUS_IP175D:
+ // Reset the Switch
+ SynopsysMiiWrite(tc, 2, 0x175D, 20);
+ mdly(RESET_STEP);
+
+ // Reset Vlan Table. PHY22 MII0, MSB.
+ SynopsysMiiWrite(tc, 0, 0x8000, 22);
+
+ // TPID Vlan. PHY22 MII3, MSB.
+ SynopsysMiiWrite(tc, 3, 0x8100, 22);
+ break;
+ }
+}
+
+__u32 get_regdump_len (struct net_device *dev)
+{
+ Private* pr = (Private*)dev->priv;
+ int size = 0;
+
+ switch (pr->OUI_model)
+ {
+ default:
+ case ICS_1893BF:
+ case ICS_1893CF:
+ case MICREL_KS8721:
+ case REALTEK_RTL8201CP:
+ case ICPLUS_IP101A:
+ case JVA_1893BF:
+ size = (2 * REGDUMP_KS8001_OUI_Size); // OUI_model copied.
+ break;
+
+ case ICPLUS_IP175C:
+ size = (2 * (REGDUMP_ICPLUS_IP175C_SIZE));
+ break;
+
+ case ICPLUS_IP175D:
+ size = (2 * REGDUMP_ICPLUS_IP175D_SIZE);
+ break;
+ }
+
+ return size;
+}
+
+int fill_regdump (struct net_device *dev, struct ethtool_regs *reg)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+ u16 *temp = (u16*) reg->data;
+ int mii;
+
+ *temp++ = pr->OUI_model >> 16; // 0
+ *temp++ = pr->OUI_model & 0xffff; // 1
+
+ switch (pr->OUI_model)
+ {
+ default :
+ break;
+
+ case ICPLUS_IP175C:
+ // index from 2 to 6
+ *temp++ = SynopsysMiiRead(tc, MII_BMSR, 0); // 2
+ *temp++ = SynopsysMiiRead(tc, MII_BMSR, 1); // 3
+ *temp++ = SynopsysMiiRead(tc, MII_BMSR, 2); // 4
+ *temp++ = SynopsysMiiRead(tc, MII_BMSR, 3); // 5
+ *temp++ = SynopsysMiiRead(tc, MII_BMSR, 4); // 6
+
+ for (mii = REGDUMP_ICPLUS_IP175C_PHY29_Begin; mii <= REGDUMP_ICPLUS_IP175C_PHY29_End; mii++)
+ {
+ *temp++ = SynopsysMiiRead(tc, mii, 29);
+ }
+
+ for (mii = REGDUMP_ICPLUS_IP175C_PHY30_Begin; mii <= REGDUMP_ICPLUS_IP175C_PHY30_End; mii++)
+ {
+ *temp++ = SynopsysMiiRead(tc, mii, 30);
+ }
+
+ for (mii = REGDUMP_ICPLUS_IP175C_PHY31_Begin; mii <= REGDUMP_ICPLUS_IP175C_PHY31_End; mii++)
+ {
+ *temp++ = SynopsysMiiRead(tc, mii, 31);
+ }
+ break;
+
+ case ICPLUS_IP175D:
+ // index from 2 to 6
+ *temp++ = SynopsysMiiRead(tc, MII_BMSR, 0); // 2
+ *temp++ = SynopsysMiiRead(tc, MII_BMSR, 1); // 3
+ *temp++ = SynopsysMiiRead(tc, MII_BMSR, 2); // 4
+ *temp++ = SynopsysMiiRead(tc, MII_BMSR, 3); // 5
+ *temp++ = SynopsysMiiRead(tc, MII_BMSR, 4); // 6
+
+ for (mii = REGDUMP_ICPLUS_IP175D_PHY20_Begin; mii <= REGDUMP_ICPLUS_IP175D_PHY20_End; mii++)
+ {
+ if (mii == 1 || mii == 23)
+ continue;
+
+ // index from 7 to 29
+ *temp++ = SynopsysMiiRead(tc, mii, 20);
+ }
+
+ for (mii = REGDUMP_ICPLUS_IP175D_PHY21_Begin; mii <= REGDUMP_ICPLUS_IP175D_PHY21_End; mii++)
+ {
+ if (mii == 11 || mii == 13)
+ continue;
+
+ // index from 30 to 53
+ *temp++ = SynopsysMiiRead(tc, mii, 21);
+ }
+
+ for (mii = REGDUMP_ICPLUS_IP175D_PHY22_Begin; mii <= REGDUMP_ICPLUS_IP175D_PHY22_End; mii++)
+ {
+ // index from 54 to 83
+ *temp++ = SynopsysMiiRead(tc, mii, 22);
+ }
+
+ for (mii = REGDUMP_ICPLUS_IP175D_PHY23_Begin; mii <= REGDUMP_ICPLUS_IP175D_PHY23_End; mii++)
+ {
+ // index from 84 to 115
+ *temp++ = SynopsysMiiRead(tc, mii, 23);
+ }
+
+ for (mii = REGDUMP_ICPLUS_IP175D_PHY24_Begin; mii <= REGDUMP_ICPLUS_IP175D_PHY24_End; mii++)
+ {
+ // index from 116 to 119
+ *temp++ = SynopsysMiiRead(tc, mii, 24);
+ }
+
+ for (mii = REGDUMP_ICPLUS_IP175D_PHY25_Begin; mii <= REGDUMP_ICPLUS_IP175D_PHY25_End; mii++)
+ {
+ // index from 120 to 143
+ *temp++ = SynopsysMiiRead(tc, mii, 25);
+ }
+
+ for (mii = REGDUMP_ICPLUS_IP175D_PHY26_Begin; mii <= REGDUMP_ICPLUS_IP175D_PHY26_End; mii++)
+ {
+ // index from 144 to 167
+ *temp++ = SynopsysMiiRead(tc, mii, 26);
+ }
+ break;
+ }
+
+ return 0;
+}
+
+int ks8001_read_vlan_table (struct net_device *dev, struct ethtool_vlanparam *ecmd)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+ u16 reg;
+ int port;
+
+ switch (pr->OUI_model)
+ {
+ case ICPLUS_IP175D:
+ // Read VLAN_MODE[5:0] field in PHY22, MII0.
+ reg = SynopsysMiiRead(tc, 0, 22);
+
+ for (port = 0; port < MAX_VLAN_SUPPORTED; port++)
+ {
+ if(reg & (1 << port))
+ {
+ ecmd->vlan_table[port].state = VLAN_ON;
+ }
+ else
+ {
+ ecmd->vlan_table[port].state = VLAN_OFF;
+ }
+
+ ecmd->vlan_table[port].vlan = SynopsysMiiRead(tc, port + 4, 22);
+ }
+ break;
+
+ default :
+ // Feature not supported
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+int ks8001_write_vlan_table (struct net_device *dev, struct ethtool_vlanparam *ecmd)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+
+ switch (pr->OUI_model)
+ {
+ case ICPLUS_IP175D:
+ // ***************************************************
+ // All the fixed number are the registers.
+ // Because that cannot be changed, no define have been created.
+ // See Datasheet IP175DLF-DS-R02 : February 22, 2008
+ // ***************************************************
+#if 0
+ {
+ u16 vlan_mode = 0, vlan_valid = 0;
+ u16 vlan_member[PORT_MAX_NB];
+ u16 vlan_add_tag[PORT_MAX_NB];
+ u16 vlan_remove_tag[PORT_MAX_NB];
+ int port = 0, i = 0;
+
+ memset (vlan_member, PORT_MAX_NB, '\0');
+ memset (vlan_add_tag, PORT_MAX_NB, '\0');
+ memset (vlan_remove_tag, PORT_MAX_NB, '\0');
+
+ for (port = 0; port < PORT_MAX_NB; port++)
+ {
+ if(VLAN_ON == ecmd->vlan_table[port].state)
+ {
+ vlan_mode |= (1 << port); /* VLAN_MODE */
+ vlan_mode |= (1 << (6 + port)); /* VLAN_CLS */
+
+ /* VLAN_INFO */
+ SynopsysMiiWrite(tc, 4 + port, ecmd->vlan_table[port].vlan, 22);
+ vlan_valid |= (1 << port); /* VLAN_VALID */
+ /* VLAN FID + VID */
+ SynopsysMiiWrite(tc, 14 + port, (port << 12) | (ecmd->vlan_table[port].vlan & 0x0fff), 22);
+ /* VLAN MEMBER */
+ vlan_member[port] = (1 << port) | (1 << IP175D_VLAN_TABLE_COMMON_PHY);
+ vlan_add_tag[port] = (1 << IP175D_VLAN_TABLE_COMMON_PHY);
+ vlan_remove_tag[port] |= (1 << port);
+ }
+ }
+ /* set vlan member, add and remove tag */
+ for(i = 0; i < PORT_MAX_NB / 2; i++)
+ {
+ SynopsysMiiWrite(tc, i, vlan_member[i * 2] | (vlan_member[i * 2 + 1] << 8) , 23);
+ SynopsysMiiWrite(tc, i + 8, vlan_add_tag[i * 2] | (vlan_add_tag[i * 2 + 1] << 8) , 23);
+ SynopsysMiiWrite(tc, i + 16, vlan_remove_tag[i * 2] | (vlan_remove_tag[i * 2 + 1] << 8) , 23);
+ }
+ /* set vlan valid */
+ SynopsysMiiWrite(tc, 10, vlan_valid, 22);
+ /* set vlan mode */
+ SynopsysMiiWrite(tc, 0, vlan_mode | (1 << 12), 22);
+ }
+#endif
+//#if 0
+ {
+ u8 add_tag_reg[IP175D_VLAN_TABLE_SIZE];
+ u8 remove_tag_reg[IP175D_VLAN_TABLE_SIZE];
+ u8 vlan_member_reg[IP175D_VLAN_TABLE_SIZE];
+ u16 vlan_valid = 0;
+ u16 vlan_prio_mode = 0; /* all vid */
+ int i, j;
+
+ memset(add_tag_reg, 0, sizeof(add_tag_reg));
+ memset(remove_tag_reg, 0, sizeof(remove_tag_reg));
+ memset(vlan_member_reg, 0, sizeof(vlan_member_reg));
+
+ // entry from 0 to 4 are reserved for port-based or tag-based.
+ for (i=0; i < MAX_VLAN_SUPPORTED; i++)
+ {
+ // Write VLAN_INFO_x
+ SynopsysMiiWrite(tc, 4+i, ecmd->vlan_table[i].vlan, 22);
+
+ // Write the VID_x
+ SynopsysMiiWrite(tc, 14+i, ecmd->vlan_table[i].vlan, 22);
+
+ vlan_valid |= (ecmd->vlan_table[i].state != VLAN_OFF) ? (1 << i) : 0;
+ }
+
+ // entry 5, is connected to spc200c. special entry. always in tag mode.
+ vlan_valid |= (1 << IP175D_VLAN_TABLE_COMMON_PHY);
+ vlan_member_reg[IP175D_VLAN_TABLE_COMMON_PHY] = 0x3F; // Maybe this line is not usefull.
+ SynopsysMiiWrite(tc, 9, 0, 22); // PVID_5 = 0
+
+ // entry 6. // JLe : is it usefull ?????
+ vlan_valid |= (1 << IP175D_VLAN_TABLE_NO_TAG_LINE);
+ vlan_member_reg[IP175D_VLAN_TABLE_NO_TAG_LINE] |= ( 1 << IP175D_VLAN_TABLE_COMMON_PHY );
+ SynopsysMiiWrite(tc, 20, 0, 22); // Write the VID_6 (= PVID_5)
+
+ for (i=0; i < MAX_VLAN_SUPPORTED; i++)
+ {
+ if (ecmd->vlan_table[i].state != VLAN_OFF)
+ {
+ add_tag_reg[i] |= (1 << IP175D_VLAN_TABLE_COMMON_PHY); // Add tag from outside to spc200c.
+ remove_tag_reg[i] = 0x1F; // Remove tag from spc200c to outside and from other port also.
+ vlan_member_reg[i] |= (1 << IP175D_VLAN_TABLE_COMMON_PHY) | (1 << i);
+
+ for (j=i+1; j < MAX_VLAN_SUPPORTED; j++)
+ {
+ // The same VID can forward the packet between them.
+ if ((ecmd->vlan_table[i].vlan == ecmd->vlan_table[j].vlan) &&
+ (ecmd->vlan_table[j].state != VLAN_OFF)
+ )
+ {
+ vlan_member_reg[i] |= (1 << j);
+ vlan_member_reg[j] |= (1 << i);
+ }
+ }
+ }
+ else
+ {
+ // The no-VID can forward the packet between them.
+ vlan_member_reg[IP175D_VLAN_TABLE_NO_TAG_LINE] |= ( 1 << i );
+ }
+ }
+
+ for (i=0; i < MAX_VLAN_SUPPORTED; i++)
+ {
+ if (ecmd->vlan_table[i].state == VLAN_OFF)
+ {
+ // The no-VID have the same forward rules.
+ vlan_member_reg[i] = vlan_member_reg[IP175D_VLAN_TABLE_NO_TAG_LINE];
+ }
+ }
+
+ for (i=0; i < IP175D_VLAN_TABLE_SIZE; i+=2)
+ {
+ u16 reg;
+
+ reg = ((vlan_member_reg[i+1] << 8) & 0xFF00) + (vlan_member_reg[i+0] & 0x00FF);
+ SynopsysMiiWrite(tc, 0 + (i/2), reg, 23); // VLAN_MEMBER
+
+ reg = ((add_tag_reg[i+1] << 8) & 0xFF00) + (add_tag_reg[i+0] & 0x00FF);
+ SynopsysMiiWrite(tc, 8 + (i/2), reg, 23); // ADD_TAG
+
+ reg = ((remove_tag_reg[i+1] << 8) & 0xFF00) + (remove_tag_reg[i+0] & 0x00FF);
+ SynopsysMiiWrite(tc, 16 + (i/2), reg, 23); // REMOVE_TAG
+ }
+
+ // Global register
+ // Write VLAN_MODE + VLAN_CLS
+ SynopsysMiiWrite(tc, 0, 0x1000 | (vlan_valid & 0x3F), 22);
+ // Write the VLAN_VALID
+ SynopsysMiiWrite(tc, 10, vlan_valid, 22);
+ }
+//#endif
+ break;
+
+ default :
+ // Feature not supported
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+/**
+ * Function : ks8001_enable_autonegotiation
+ * Purpose : activate the autonegotiation.
+ * Parameters : dev->network device structure
+ * Return value : void.
+ */
+static void ks8001_enable_autonegotiation (struct net_device *dev)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+ volatile int data;
+
+ switch (pr->OUI_model)
+ {
+ case ICS_1893BF:
+ case ICS_1893CF:
+ case MICREL_KS8721:
+ case REALTEK_RTL8201CP:
+ case ICPLUS_IP101A:
+ case JVA_1893BF:
+ //Ensure that phy is autonegotiation capable
+ if(SynopsysMiiRead(tc, MII_BMSR, AUTOMATIC_PHY_RESOLUTION) & BMSR_ANEGCAPABLE)
+ {
+ //Disable auto negotiation
+ data = SynopsysMiiRead(tc, MII_BMCR, AUTOMATIC_PHY_RESOLUTION);
+ data &= ~BMCR_ANENABLE;
+ SynopsysMiiWrite(tc, MII_BMCR, data, AUTOMATIC_PHY_RESOLUTION);
+
+ //Set auto-neogtiation advertisement register - all techs
+ data = SynopsysMiiRead(tc, MII_ADVERTISE, AUTOMATIC_PHY_RESOLUTION);
+ data |= phy_modes;
+ SynopsysMiiWrite(tc, MII_ADVERTISE, data, AUTOMATIC_PHY_RESOLUTION);
+
+ //Kick auto negotiation
+ data = SynopsysMiiRead(tc, MII_BMCR, AUTOMATIC_PHY_RESOLUTION);
+ data |= BMCR_ANENABLE;
+ SynopsysMiiWrite(tc, MII_BMCR, data, AUTOMATIC_PHY_RESOLUTION);
+ }
+
+ break;
+
+ case ICPLUS_IP175C:
+ case ICPLUS_IP175D:
+ // TODO
+ break;
+
+ default:
+ break;
+ }
+
+}//ks8001_enable_autonegotiation
+
+/**
+ * Function : ks8001_autonegotiate
+ * Purpose : Start the autonegotiation procedure.
+ * Parameters : dev->network device structure
+ * Return value : error code.
+ */
+static int ks8001_autonegotiate (struct net_device *dev, int wait)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+ int result = 0;
+
+ switch (pr->OUI_model)
+ {
+ case ICS_1893BF:
+ case ICS_1893CF:
+ case MICREL_KS8721:
+ case REALTEK_RTL8201CP:
+ case ICPLUS_IP101A:
+ case JVA_1893BF:
+ //Ensure that phy is autonegotiation capable
+ if(SynopsysMiiRead(tc, MII_BMSR, AUTOMATIC_PHY_RESOLUTION) & BMSR_ANEGCAPABLE)
+ {
+ debugp(DRV_NAME ": starting autonegotiation for %s\n", dev->name);
+
+ //Kick auto negotiation
+ result = mii_nway_restart(&pr->mii_if);
+ if(wait)
+ {
+ int timeout = AUTONEG_TIMEOUT * 1000 / AUTONEG_STEP;
+ volatile uint32_t data;
+
+ switch (pr->OUI_model)
+ {
+ case ICS_1893BF:
+ case ICS_1893CF:
+ do
+ {
+ mdly(AUTONEG_STEP);
+ data = SynopsysMiiRead(tc, MII_QPDSR, AUTOMATIC_PHY_RESOLUTION);
+ } while((!(data & QPDSR_ANEGCOMPLETE) || !(data & QPDSR_LSTATUS)) && timeout--);
+ break;
+
+ default:
+ do
+ {
+ mdly(AUTONEG_STEP);
+ data = SynopsysMiiRead(tc, MII_BMSR, AUTOMATIC_PHY_RESOLUTION);
+ } while(!(data & BMSR_ANEGCOMPLETE) && timeout--);
+ break;
+ }
+
+ if(timeout <= 0)
+ {
+ printk(DRV_NAME ": autonegotiation timed out after %d s for %s\n", AUTONEG_TIMEOUT, dev->name);
+ return -1;
+ }
+ else
+ {
+ debugp(DRV_NAME ": autonegotiation complete after %d ms for %s\n", AUTONEG_TIMEOUT * 1000 - timeout * AUTONEG_STEP, dev->name);
+ }
+ }
+ //Set duplex mode anyway
+ ks8001_an_complete(dev);
+ }
+ else
+ {
+ result = -ENOSYS;
+ }
+ break;
+
+ case ICPLUS_IP175C:
+ case ICPLUS_IP175D:
+ // TODO
+ result = -ENOSYS;
+ break;
+
+ default:
+ result = -ENOSYS;
+ break;
+ }
+
+ return result;
+}//ks8001_autonegotiate
+
+/**
+ * Function : ks8001_setup_ethernet_address
+ * Purpose : Change the MAC address.
+ * Parameters : dev->network device structure
+ * Return value : void.
+ */
+static void ks8001_setup_ethernet_address (struct net_device *dev)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+ uint32_t data;
+ uint32_t data2;
+
+ //Setup MAC address
+ data = (dev->dev_addr[5] << 8) | dev->dev_addr[4];
+ SynopsysWriteMacReg(tc, GmacAddr0High, data);
+ data = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | dev->dev_addr[0];
+ SynopsysWriteMacReg(tc, GmacAddr0Low, data);
+
+
+ data = SynopsysReadMacReg (tc, GmacAddr0High);
+ data2 = SynopsysReadMacReg (tc, GmacAddr0Low);
+ debugp(DRV_NAME ": hardware ethernet addr =%02X:%02X:%02X:%02X:%02X:%02X\n",(data2) & 0xFF, (data2>>8) & 0xFF,
+ (data2>>16) & 0xFF, (data2>>24) & 0xFF,
+ (data) & 0xFF, (data>>8) & 0xFF);
+}//ks8001_setup_ethernet_address
+
+/**
+ * Function : ks8001_on_link_up
+ * Purpose : Called when driver found link up event.
+ * Parameters : dev->network device structure
+ * Return value : error code.
+ */
+static int ks8001_on_link_up (struct net_device *dev)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+ int speed_100 = 0;
+ uint32_t data;
+
+ //Set init register values
+ SynopsysWriteDmaReg(tc, DmaBusMode, DmaBusModeInit);
+ SynopsysWriteDmaReg(tc, DmaRxBaseAddr, pr->rx->phys);
+ SynopsysWriteDmaReg(tc, DmaTxBaseAddr, pr->tx->phys);
+
+ //Select DMA speed
+ switch (pr->OUI_model)
+ {
+ case ICS_1893BF:
+ case ICS_1893CF:
+ data = SynopsysMiiRead(tc, MII_QPDSR, AUTOMATIC_PHY_RESOLUTION);
+ speed_100 = data & QPDSR_SPEED100;
+ break;
+
+ case MICREL_KS8721:
+ //using PHYCTRL instead of BMCR
+ data = SynopsysMiiRead(tc, MII_PHYCTRL, AUTOMATIC_PHY_RESOLUTION);
+ speed_100 = (data & PHYCTRL_OP_MODE)==PHYCTRL_OM_100HALF || (data & PHYCTRL_OP_MODE)==PHYCTRL_OM_100FULL;
+ break;
+
+ case REALTEK_RTL8201CP:
+ case ICPLUS_IP101A:
+ case JVA_1893BF:
+ //BMCR duplex status after autonegotiation is not standard : works on RTL8201CP
+ data = SynopsysMiiRead(tc, MII_BMCR, AUTOMATIC_PHY_RESOLUTION);
+ speed_100 = data & BMCR_SPEED100;
+ break;
+
+ case ICPLUS_IP175C:
+ case ICPLUS_IP175D:
+ // MII speed and mode returned... because 5 Port possibles
+ data = SynopsysMiiRead(tc, MII_BMCR, 5);
+ speed_100 = data & BMCR_SPEED100;
+ break;
+
+ default:
+ break;
+ }
+
+ if(speed_100)
+ SynopsysWriteDmaReg(tc, DmaControl, DmaControlInit100);
+ else
+ SynopsysWriteDmaReg(tc, DmaControl, DmaControlInit10);
+
+ //Disable interrupts
+ SynopsysWriteDmaReg(tc, DmaInterrupt, DmaIntDisable);
+
+ debugp(DRV_NAME ": %s: autoned - DMA Tuned\n", dev->name);
+
+ //Write MAC Address
+ ks8001_setup_ethernet_address(dev);
+
+ //Restore Mac configuration
+ ks8001_restore_mac_register(dev);
+
+ //Start DMAs
+ SynopsysWriteDmaReg(tc, DmaStatus, 0xFFFFFFFF);
+ SynopsysWriteDmaReg(tc, DmaInterrupt, DmaIntEnable);
+ SynopsysSetDmaReg(tc, DmaControl, DmaRxStart);
+
+ return 0;
+}//ks8001_on_link_up
+
+/**
+ * Function : ks8001_on_link_down
+ * Purpose : Called when driver found link down event.
+ * Parameters : dev->network device structure
+ * Return value : void.
+ */
+static void ks8001_on_link_down (struct net_device *dev)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+
+ //Save Mac configuration
+ ks8001_save_mac_register(dev);
+
+ //Stop RX and TX
+ SynopsysClearDmaReg(tc, DmaControl, DmaTxStart);
+ SynopsysClearDmaReg(tc, DmaControl, DmaRxStart);
+
+ //Reset DMA engine
+ while(SynopsysReadDmaReg(tc, DmaBusMode) & DmaResetOn);
+ SynopsysWriteDmaReg(tc, DmaBusMode, DmaResetOn);
+ while(SynopsysReadDmaReg(tc, DmaBusMode) & DmaResetOn);
+ SynopsysWriteDmaReg(tc, DmaInterrupt, DmaIntDisable);
+
+ //Reset descriptors
+ syeth_dma_tx_rb_reset(pr->tx);
+ syeth_dma_rx_rb_reset(pr->rx);
+}//ks8001_on_link_down
+
+/**
+ * Function : ks8001_scan_link
+ * Purpose : check the link status.
+ * parameters : dev->device address
+ * return value : value of the link status.
+ */
+static int ks8001_scan_link (struct net_device *dev)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+ int i;
+ int status = 0;
+
+ SynopsysMiiRead(tc, MII_BMSR, AUTOMATIC_PHY_RESOLUTION); //TODO:Dummy Read
+
+ switch (pr->OUI_model)
+ {
+ case ICS_1893BF:
+ case ICS_1893CF:
+ return SynopsysMiiRead (tc, MII_QPDSR, AUTOMATIC_PHY_RESOLUTION) & QPDSR_LSTATUS;
+
+ case MICREL_KS8721:
+ case REALTEK_RTL8201CP:
+ case ICPLUS_IP101A:
+ case JVA_1893BF:
+ return SynopsysMiiRead (tc, MII_BMSR, AUTOMATIC_PHY_RESOLUTION) & BMSR_LSTATUS;
+
+ case ICPLUS_IP175C:
+ case ICPLUS_IP175D:
+ return 1;
+#if 0
+ for (i=0; i<IP175D_VLAN_TABLE_COMMON_PHY && status == 0; i++)
+ {
+ status |= (SynopsysMiiRead (tc, MII_BMSR, i) & BMSR_LSTATUS);
+ }
+ return status;
+#endif
+
+ default:
+ // No links up
+ return 0;
+ }
+
+ return 0;
+}//ks8001_scan_link
+
+/**
+ * Function : ks8001_timer
+ * Purpose : Poll the link status to check connexion/unconnexion
+ * and restart autonegociation.
+ * parameters : data->device address
+ * return value : void.
+ */
+static void ks8001_timer (unsigned long data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ Private *pr = (Private*)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+
+ if(!ks8001_scan_link(dev))
+ {
+ if(netif_carrier_ok(dev))
+ {
+ //OK. LINK DOWN.
+ // debugp(DRV_NAME ": %s: " "Link DOWN\n", dev->name);
+ printk(DRV_NAME ": %s: " "Link DOWN\n", dev->name);
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+ ks8001_on_link_down(dev);
+ }
+ else
+ {
+#ifdef SYNOP_ETH_DEBUG_LINK
+ debugp(DRV_NAME ": %s: Link still down\n", dev->name);
+#endif
+ }
+ }
+ else
+ {
+ if(!netif_carrier_ok(dev))
+ {
+ //OK. link UP.
+ // debugp(DRV_NAME ": %s: Link UP\n", dev->name);
+ printk(DRV_NAME ": %s: Link UP\n", dev->name);
+ //Check if it is the first time the link goes up
+ if(!init_finish)
+ {
+ //save the current value for promiscuous mode multicast....
+ pr->macreg.GmacFrameFilter = SynopsysReadMacReg(tc, GmacFrameFilter);
+ ks8001_an_complete(dev);
+ ks8001_on_link_up(dev);
+ netif_carrier_on(dev);
+ netif_wake_queue(dev);
+ //set default config into hardware
+ ks8001_init_mac_register(dev);
+ //store the config saved before for promiscuous mode multicast....
+ SynopsysWriteMacReg(tc, GmacFrameFilter, pr->macreg.GmacFrameFilter);
+ init_finish = 1;
+ }
+ else
+ {
+ ks8001_an_complete(dev);
+ ks8001_on_link_up(dev);
+ netif_carrier_on(dev);
+ netif_wake_queue(dev);
+ }
+ }
+ else
+ {
+#ifdef SYNOP_ETH_DEBUG_LINK
+ debugp(DRV_NAME ": %s: Link still up\n", dev->name);
+#endif
+ //save the current value for promiscuous mode multicast....
+ pr->macreg.GmacFrameFilter = SynopsysReadMacReg(tc, GmacFrameFilter);
+ }
+ }
+ mod_timer(&pr->timer, jiffies + TIMEOUT);
+}//ks8001_timer
+
+/**
+ * Function : ks8001_stop
+ * Purpose : Stop the device.
+ * Parameters : device address
+ * Return value : error code.
+ */
+static int ks8001_stop (struct net_device *dev)
+{
+ Private *pr = NULL;
+ Synopsys *tc = NULL;
+
+ if(dev == NULL)
+ return -1;
+ pr = (Private *)dev->priv;
+ tc = &pr->synopsys;
+
+ debugp(DRV_NAME ": %s: stop\n", dev->name);
+
+ //Stop timer thread
+ del_timer_sync(&pr->timer);
+
+ //Disable transmitter
+ netif_stop_queue(dev);
+ netif_carrier_off(dev);
+
+ //Device stopped
+ SynopsysWriteDmaReg(tc, DmaInterrupt, DmaIntDisable);
+ SynopsysClearDmaReg(tc, DmaControl, DmaRxStart);
+ SynopsysClearDmaReg(tc, DmaControl, DmaTxStart);
+
+ //Reset DMA engine
+ while(SynopsysReadDmaReg(tc, DmaBusMode) & DmaResetOn);
+ SynopsysWriteDmaReg(tc, DmaBusMode, DmaResetOn);
+ while(SynopsysReadDmaReg(tc, DmaBusMode) & DmaResetOn);
+ SynopsysWriteDmaReg(tc, DmaInterrupt, DmaIntDisable);
+
+ //Disconnect from IRQ
+ free_irq(dev->irq, dev);
+
+ //Delete DMA descriptors
+ syeth_dma_rx_rb_free(pr->rx);
+ pr->rx = NULL;
+ syeth_dma_tx_rb_free(pr->tx);
+ pr->tx = NULL;
+ return 0;
+}//ks8001_Stop
+
+/**
+ * Function : ks8001_hard_start_xmit
+ * Purpose : Transmit the packet to the destination.
+ * Parameters : skb->includes all the headers and data
+ * dev->device address
+ * Return value : error code.
+ */
+static int ks8001_hard_start_xmit (struct sk_buff *skb,
+ struct net_device *dev)
+{
+ Private *pr = NULL;
+ Synopsys *tc = NULL;
+ int r = 0;
+
+ //Check pointers
+ if(dev == NULL)
+ return -EBUSY;
+ pr = (Private *)dev->priv;
+ if(pr == NULL)
+ return -EBUSY;
+ tc = &pr->synopsys;
+ if(tc == NULL)
+ return -EBUSY;
+ if(skb == NULL)
+ return 1;
+
+ debugp (DRV_NAME ": hard_start_xmit(%s)\n", dev->name);
+
+ //TODO:Check if the link is down
+
+ //Transmit the packet to hardware
+ r = syeth_dma_tx_rb_put (pr->tx, skb);
+ if(r < 0)
+ {
+ //should never been occured because of descriptor expiration have to be detected during the previous pass
+ netif_stop_queue(dev);
+ printk(DRV_NAME ": %s: No more free tx descriptors\n", dev->name);
+ return 1;
+ }
+ if(r > 0)
+ {
+ //no more space in TX desc buffer Transmition will be respawned when interupt or poll will came on
+ netif_stop_queue(dev);
+ debugp (DRV_NAME ": %s: No more space on device om d=%d. Stop queue\n", dev->name, r - 1);
+ }
+
+ SynopsysSetDmaReg(tc, DmaControl, DmaTxStart);
+ SynopsysWriteDmaReg(tc, DmaTxPollDemand, 0);
+
+ dev->trans_start = jiffies;
+
+ return 0;
+}//ks8001_hard_start_xmit
+
+/**
+ * Function : ks8001_set_multicast
+ * Purpose : This will control promiscuous mode.
+ * Parameters : dev->device address
+ * Return value : void.
+ */
+static void ks8001_set_multicast (struct net_device *dev)
+{
+ Private *pr = NULL;
+ Synopsys *tc = NULL;
+ uint32_t value;
+
+ pr = (Private *)dev->priv;
+ if(pr == NULL)
+ return;
+
+ tc = &pr->synopsys;
+ if(tc == NULL)
+ return;
+
+ value = SynopsysReadMacReg(tc, GmacFrameFilter);
+
+ //Set promiscuous mode if it's asked for.
+ if(dev->flags & IFF_PROMISC)
+ {
+ if(!(value & GmacPromiscuousModeOn))
+ {
+ value |= GmacPromiscuousModeOn;
+ SynopsysWriteMacReg(tc, GmacFrameFilter, value);
+ return;
+ }
+ }
+ else
+ {
+ if(value & GmacPromiscuousModeOn)
+ {
+ value &= ~GmacPromiscuousModeOn;
+ SynopsysWriteMacReg(tc, GmacFrameFilter, value);
+ return;
+ }
+ }
+
+ //Hardware cannot filter multicast addresses
+ //Just block or unblock all addresses
+ if(dev->flags & IFF_ALLMULTI || dev->mc_count > 0)
+ value |= GmacMulticastFilterOff;
+ else
+ value &= ~GmacMulticastFilterOff;
+
+ SynopsysWriteMacReg(tc, GmacFrameFilter, value);
+}//ks8001_set_multicast
+
+/**
+ * Function : ks8001_ethtool_ioctl
+ * Purpose : This will control the device for ethtool.
+ * Parameters : dev->device address
+ * useraddr->user data address
+ * Return value : error code.
+ */
+#ifndef MODULE
+static int ks8001_ethtool_ioctl (struct net_device *dev, void *useraddr)
+{
+ uint32_t ethcmd;
+ Private *pr = (Private *)dev->priv;
+
+ //dev_ioctl() in ../../net/core/dev.c has already checked
+ //capable(CAP_NET_ADMIN), so don't bother with that here.
+
+ if(get_user(ethcmd, (uint32_t *) useraddr))
+ return -EFAULT;
+
+ debugp(DRV_NAME ": %s: ethtool(cmd=%08x)\n", dev->name, ethcmd);
+ switch(ethcmd)
+ {
+ case ETHTOOL_GDRVINFO:
+ {
+ struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };
+ strcpy(info.driver, DRV_NAME);
+ strcpy(info.version, DRV_VERSION);
+ info.regdump_len = get_regdump_len (dev);
+ if(copy_to_user(useraddr, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+
+ //Get settings
+ case ETHTOOL_GSET:
+ {
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+ mii_ethtool_gset(&pr->mii_if, &ecmd);
+ if(copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+ return -EFAULT;
+ return 0;
+ }
+
+ //Set settings
+ case ETHTOOL_SSET:
+ {
+ int r;
+ struct ethtool_cmd ecmd;
+
+ if(copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+ return -EFAULT;
+ r = mii_ethtool_sset(&pr->mii_if, &ecmd);
+ return r;
+ }
+
+ //Restart autonegotiation
+ case ETHTOOL_NWAY_RST:
+ {
+ return ks8001_autonegotiate(dev, 1);
+ }
+ //Get link status
+ case ETHTOOL_GLINK:
+ {
+ struct ethtool_value edata = { ETHTOOL_GLINK };
+ edata.data = mii_link_ok(&pr->mii_if);
+ if(copy_to_user(useraddr, &edata, sizeof(edata)))
+ return -EFAULT;
+ return 0;
+ }
+
+ case ETHTOOL_GREGS:
+ {
+ char buffer[512];
+ int len = get_regdump_len (dev);
+
+ if(copy_from_user(buffer, useraddr, sizeof(u32)*3))
+ return -EFAULT;
+
+ fill_regdump (dev, (struct ethtool_regs*) buffer);
+
+ if(copy_to_user(useraddr, &buffer, sizeof(struct ethtool_regs) + len))
+ return -EFAULT;
+
+ return 0;
+ }
+ case ETHTOOL_RVLAN_TABLE:
+ {
+ struct ethtool_vlanparam ecmd;
+
+ if (ks8001_read_vlan_table (dev, &ecmd))
+ return -EFAULT;
+
+ if(copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+ return -EFAULT;
+
+ return 0;
+ }
+ case ETHTOOL_SVLAN_TABLE:
+ {
+ struct ethtool_vlanparam ecmd;
+
+ if(copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+ return -EFAULT;
+
+ if (ks8001_write_vlan_table (dev, &ecmd))
+ return -EFAULT;
+
+ return 0;
+ }
+
+ default:
+ break;
+ }
+ return -EOPNOTSUPP;
+}//ks8001_ethtool_ioctl
+#endif
+
+/**
+ * Function : ks8001_do_ioctl
+ * Purpose : This will control the device.
+ * Parameters : dev->device address
+ * cmd->command to execute
+ * Return value : error code.
+ */
+static int ks8001_do_ioctl (struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ Private *pr = NULL;
+ Synopsys *tc = NULL;
+ uint16_t reg;
+
+ if(ifr == NULL)
+ return -1;
+ if(dev == NULL)
+ return -1;
+ pr = (Private *)dev->priv;
+ if(pr == NULL)
+ return -1;
+ tc = &pr->synopsys;
+ if(tc == NULL)
+ return -1;
+
+ debugp(DRV_NAME ": %s: do_ioctl(cmd=%08x)\n", dev->name, cmd);
+
+ switch(cmd)
+ {
+ case SIOCGLINKSTATUS:
+ ifr->ifr_data = (void *)ks8001_scan_link(dev);
+ break;
+
+ case SIOCGSETLINKSPEED:
+ eth_speed = (int) ifr->ifr_data;
+ switch(eth_duplex_mode)
+ {
+ case 0:
+ phy_modes = (!eth_speed) ? ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL : (eth_speed == 10) ?
+ ADVERTISE_10HALF | ADVERTISE_10FULL : ADVERTISE_100HALF | ADVERTISE_100FULL;
+ break;
+ case 1:
+ phy_modes = (!eth_speed) ? ADVERTISE_10FULL | ADVERTISE_100FULL : (eth_speed == 10) ? ADVERTISE_10FULL : ADVERTISE_100FULL;
+ break;
+ case 2:
+ phy_modes = (!eth_speed) ? ADVERTISE_10HALF | ADVERTISE_100HALF : (eth_speed == 10) ? ADVERTISE_10HALF : ADVERTISE_100HALF;
+ }
+ ks8001_enable_autonegotiation (dev);
+ ks8001_autonegotiate (dev, 1);
+ break;
+
+ case SIOCGGETLINKSETUPSPEED:
+ ifr->ifr_data = (void *)eth_speed;
+ break;
+ case SIOCGGETLINKCURRENTSPEED:
+ reg = SynopsysMiiRead(tc, MII_QPDSR, AUTOMATIC_PHY_RESOLUTION);
+ if(reg & QPDSR_SPEED100)
+ ifr->ifr_data = (void *)100;
+ else
+ ifr->ifr_data = (void *)10;
+ break;
+ case SIOCGSETLINKMODE:
+ eth_duplex_mode = (int) ifr->ifr_data;
+ switch(eth_duplex_mode)
+ {
+ case 0:
+ phy_modes = (!eth_speed) ? ADVERTISE_10HALF | ADVERTISE_10FULL | ADVERTISE_100HALF | ADVERTISE_100FULL : (eth_speed == 10) ?
+ ADVERTISE_10HALF | ADVERTISE_10FULL : ADVERTISE_100HALF | ADVERTISE_100FULL;
+ break;
+ case 1:
+ phy_modes = (!eth_speed) ? ADVERTISE_10FULL | ADVERTISE_100FULL : (eth_speed == 10) ? ADVERTISE_10FULL : ADVERTISE_100FULL;
+ break;
+ case 2:
+ phy_modes = (!eth_speed) ? ADVERTISE_10HALF | ADVERTISE_100HALF : (eth_speed == 10) ? ADVERTISE_10HALF : ADVERTISE_100HALF;
+ }
+ ks8001_enable_autonegotiation (dev);
+ ks8001_autonegotiate (dev, 1);
+ break;
+
+ case SIOCGGETLINKSETUPMODE:
+ ifr->ifr_data = (void *)eth_duplex_mode;
+ break;
+
+ case SIOCGGETLINKCURRENTMODE:
+ reg = SynopsysMiiRead(tc, MII_QPDSR, AUTOMATIC_PHY_RESOLUTION);
+ if(reg & QPDSR_FULLDPLX)
+ ifr->ifr_data = (void *)ETH_MODE_FD;
+ else
+ ifr->ifr_data = (void *)ETH_MODE_HD;
+ break;
+
+#ifndef MODULE
+ case SIOCETHTOOL: //EthTool Interface
+ return ks8001_ethtool_ioctl(dev, (void *)ifr->ifr_data);
+#endif
+
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}//ks8001_do_ioctl
+
+/**
+ * Function : ks8001_get_stats
+ * Purpose : Read the packet status from the device.
+ * Parameters : dev->device address
+ * Return value : return the device stats.
+ */
+static struct net_device_stats *ks8001_get_stats (struct net_device *dev)
+{
+ Private *pr = NULL;
+ Synopsys *tc = NULL;
+
+ if(dev == NULL)
+ return NULL;
+
+ debugp(DRV_NAME ": Synopsys::get_stats(%s)\n", dev->name);
+
+ pr = (Private *)dev->priv;
+ if(pr == NULL)
+ return NULL;
+
+ tc = &pr->synopsys;
+ if(tc == NULL)
+ return NULL;
+
+ return &pr->stats;
+}//ks8001_get_stats
+
+/**
+ * Function : ks8001_change_mtu
+ * Purpose : Change the MTU.
+ * Parameters : dev->device address
+ * new_mtu->the new mtu value
+ * Return value : error code.
+ */
+static int ks8001_change_mtu (struct net_device *dev, int new_mtu)
+{
+ if(new_mtu < 64 || new_mtu > 1508)
+ return -EINVAL;
+ else
+ {
+ //should reset the port first, no?
+ dev->mtu = new_mtu;
+ return 0;
+ }
+}//ks8001_change_mtu
+
+/**
+ * Function : ks8001_set_mac_address
+ * Purpose : Change the MAC address.
+ * Parameters : dev->device address
+ * p->mac addr source
+ * Return value : error code.
+ */
+static int ks8001_set_mac_address (struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ ks8001_setup_ethernet_address(dev);
+
+ return 0;
+}//ks8001_set_mac_address
+
+/**
+ * Function : mdio_read
+ * Purpose : read a MII register.
+ * Parameters : dev->device address
+ * phy->phy addr (not used for us)
+ * reg->register to read
+ * Return value : value read.
+ */
+static int mdio_read (struct net_device *dev, int phy, int reg)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+
+ return SynopsysMiiRead(tc, reg, (s16) phy);
+}//mdio_read
+
+/**
+ * Function : mdio_write
+ * Purpose : write a MII register.
+ * Parameters : dev->device address
+ * phy->phy addr (not used for us)
+ * reg->register to write
+ * value->value to write
+ * Return value : void.
+ */
+static void mdio_write (struct net_device *dev, int phy, int reg, int value)
+{
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+
+ SynopsysMiiWrite(tc, reg, value, (s16) phy);
+}//mdio_write
+
+/**
+ * Function : ks8001_open
+ * Purpose : This will initialize the device.
+ * parameters : device address
+ * return value : error code.
+ */
+static int ks8001_open (struct net_device *dev)
+{
+ bool is_phy_is_known = false;
+ Private *pr = NULL;
+ Synopsys *tc = NULL;
+
+ //Check pointers
+ if(dev == NULL)
+ return -1;
+ pr = (Private *)dev->priv;
+ if(pr == NULL)
+ return -1;
+ tc = &pr->synopsys;
+ if(tc == NULL)
+ return -1;
+
+ debugp(DRV_NAME ": %s: open\n", dev->name);
+
+ //Call platform dependent hook
+ ks8001_hw_prepare(pr->minor); //TODO:normally during the init procedure is enough
+
+ //Check PHY ID
+ pr->phy_id = SynopsysMiiRead(tc, MII_PHYSID1, AUTOMATIC_PHY_RESOLUTION) << 16 | SynopsysMiiRead(tc, MII_PHYSID2, AUTOMATIC_PHY_RESOLUTION);
+ pr->phy_oui = (pr->phy_id >> 10) & 0x00ffffff;
+ pr->phy_model = (pr->phy_id >> 4) & 0x0000003f;
+ pr->phy_rev = (pr->phy_id >> 0) & 0x0000000f;
+
+ pr->OUI_model = (pr->phy_oui << OFFSET_OUI) + (pr->phy_model << OFFSET_MODEL);
+
+ switch (pr->OUI_model)
+ {
+ case ICS_1893BF:
+ printk(DRV_NAME": PHY for %s is ICS 1893BF rev %u\n",dev->name ,pr->phy_rev);
+ break;
+
+ case ICS_1893CF:
+ printk(DRV_NAME": PHY for %s is ICS ICS1893CF rev %u\n",dev->name ,pr->phy_rev);
+ break;
+
+ case MICREL_KS8721:
+ printk(DRV_NAME": PHY for %s is Micrel KS8721B/BT rev %u\n",dev->name,pr->phy_rev);
+ break;
+
+ case REALTEK_RTL8201CP:
+ printk(DRV_NAME": PHY for %s is Realtek RTL8201CP rev %u\n",dev->name,pr->phy_rev);
+ break;
+
+ case ICPLUS_IP101A:
+ printk(DRV_NAME": PHY for %s is IC+ IP101A rev %u\n",dev->name,pr->phy_rev);
+ break;
+
+ case ICPLUS_IP175C:
+ {
+ int ID2;
+
+ is_phy_is_known = true;
+ // Try to read the Second ID number : available only in the IP175D
+ ID2 = SynopsysMiiRead(tc, 0, 20);
+
+ // phy from 0 to 4, are real phy.
+ // phy 5 is the between the ethernet switch and spc200c
+ pr->mii_if.phy_id = 5;
+
+ if ((ID2 == 0x175D) || (ID2 == 0x0c40))
+ {
+ printk(DRV_NAME": PHY for %s is IC+ IP175D rev %u\n",dev->name,pr->phy_rev);
+ pr->OUI_model = ICPLUS_IP175D; // Dirty patch against the hardware.
+ }
+ else
+ {
+ printk(DRV_NAME": PHY for %s is IC+ IP175C rev %u\n",dev->name,pr->phy_rev);
+ }
+ }
+ break;
+
+ case ICPLUS_IP175D:
+ printk(DRV_NAME": WARNING : PHY software conflit detected\n");
+ break;
+
+ case JVA_1893BF:
+ printk(DRV_NAME": PHY for %s is ICS_NO rev %u\n",dev->name,pr->phy_rev);
+ break;
+
+ default:
+ printk(DRV_NAME": PHY ID for %s id is 0x%8.8x on phy N°%d\n",dev->name,pr->phy_id, tc->phyAddr);
+ }
+
+ debugp(DRV_NAME ": %s: open: MII status=0x%08X control=0x%08X\n", dev->name, SynopsysMiiRead(tc, MII_BMCR, AUTOMATIC_PHY_RESOLUTION), SynopsysMiiRead(tc, MII_BMSR, AUTOMATIC_PHY_RESOLUTION));
+
+ //Reset PHY
+ ks8001_reset_phy(dev);
+
+ //Set MAC address
+ ks8001_setup_ethernet_address(dev);
+
+ //Activate multicast management
+ ks8001_set_multicast(dev);
+
+ //Activate auto-negotiation
+ ks8001_enable_autonegotiation(dev);
+
+ //Does not use Gmac interupts. For switch it on change 'Clear' to 'Set'
+ SynopsysClearConfigReg(tc, GmacIntMask, 0x03);
+
+ //Initialize dma
+#ifdef CONFIG_MMU
+ pr->rx = syeth_dma_rx_rb_alloc(RXDESCS, dev->mtu, &pr->stats);
+#else
+ pr->rx = syeth_dma_rx_rb_static_alloc(&pr->stats);
+#endif
+ if(NULL == pr->rx)
+ {
+ debugp(DRV_NAME ": %s: open: cannot init RX DMA\n", dev->name);
+ return -ENODEV;
+ }
+ debugp(DRV_NAME ": %s: open: RX DMA initialized: 0x%p=>0x%08X\n", dev->name, pr->rx->d.rx, pr->rx->phys);
+
+#ifdef CONFIG_MMU
+ pr->tx = syeth_dma_tx_rb_alloc(TXDESCS, &pr->stats);
+#else
+ pr->tx = syeth_dma_tx_rb_static_alloc(&pr->stats);
+#endif
+ if(NULL == pr->tx)
+ {
+ debugp(DRV_NAME ": %s: open: cannot init TX DMA\n", dev->name);
+ return -ENODEV;
+ }
+ debugp(DRV_NAME ": %s: open: TX DMA initialized: 0x%p=>0x%08X\n", dev->name, pr->tx->d.tx, pr->tx->phys);
+
+ //Reset DMA engine
+ while(SynopsysReadDmaReg(tc, DmaBusMode) & DmaResetOn);
+ SynopsysWriteDmaReg(tc, DmaBusMode, DmaResetOn);
+ while(SynopsysReadDmaReg(tc, DmaBusMode) & DmaResetOn);
+ SynopsysWriteDmaReg(tc, DmaInterrupt, DmaIntDisable);
+
+ //start autonegotiation
+ ks8001_an_complete(dev); //store default config in hardware
+ netif_stop_queue(dev); //considere link as off
+ netif_carrier_off(dev);
+ ks8001_on_link_down(dev);
+ ks8001_autonegotiate(dev, 0);
+
+ //Request irq
+ debugp(DRV_NAME ": %s: open: request interrupt %d\n", dev->name, dev->irq);
+ if(request_irq(dev->irq, int_handler, SA_INTERRUPT, dev->name, dev) != 0)
+ {
+ debugp(DRV_NAME ": Synopsys::open(%s) - interrupt %d request fail\n", dev->name, dev->irq);
+ return -ENODEV;
+ }
+
+ //Autonegotiation polling will be started in timer thread immediately
+ pr->timer.expires = jiffies;
+ add_timer(&pr->timer);
+
+ return 0;
+}//ks8001_open
+
+/**
+ * Function : ks8001_try_init
+ * Purpose : probe device at specified location or find the device.
+ * Parameters : dev->device address
+ * Return value : error code.
+ */
+static int ks8001_try_init (struct net_device *dev)
+{
+ u32 configBase, macBase, dmaBase;
+ int i;
+ Private *pr = (Private *)dev->priv;
+ u32 data;
+
+ //Save base addresses of Synopsys board registers
+ configBase = dev->base_addr;
+ macBase = configBase + MAC_OFFSET; // MAC address offset
+ dmaBase = configBase + DMA_OFFSET; // DMA address offset
+
+ //Try to find valid PHY address
+ for(i = 1; i < 32; i++)
+ {
+ SynopsysInit(&pr->synopsys, configBase, macBase, dmaBase, i);
+ data = SynopsysMiiRead(&pr->synopsys, MII_BMSR, AUTOMATIC_PHY_RESOLUTION);
+ if((data != 0xFFFF) && (data != 0x0))
+ {
+ return 0;
+ }
+ }
+ return -1;
+}//ks8001_try_init
+
+
+/**
+ * Function : ks8001_init
+ * Purpose : Register the device with the network subsystem.
+ * Parameters : dev->device address
+ * Return value : error code.
+ */
+static int ks8001_init (struct net_device *dev)
+{
+ int rc;
+ Private *pr = NULL;
+
+ if(dev == NULL)
+ return -ENODEV;
+
+ pr = (Private *)dev->priv;
+
+ // try Mem space access
+ dev->base_addr = ks8001_hw_device.base_addr;
+ dev->irq = ks8001_hw_device.irq;
+ pr->minor = ks8001_hw_device.minor;
+ debugp(DRV_NAME ": eth%d: addr=%08lx, irq=%d\n", pr->minor, dev->base_addr, dev->irq);
+
+ // Init Synopsys internal data.
+ // Search for Phy address.
+ // Try it without reset first to check does U-Boot already sets up
+ // Ethernet controller and MAC address.
+ ks8001_hw_prepare(pr->minor);
+ rc = ks8001_try_init(dev);
+ ks8001_hw_unreset(pr->minor);
+ if(rc == -1)
+ rc = ks8001_try_init(dev);
+ if(rc == -1)
+ {
+ SynopsysInit(&pr->synopsys, dev->base_addr,
+ dev->base_addr + MAC_OFFSET,
+ dev->base_addr + DMA_OFFSET, ks8001_hw_device.phy_addr);
+ printk(DRV_NAME ": eth%d: Could not find valid PHY address. Try use default one: %d\n", ks8001_hw_device.minor, ks8001_hw_device.phy_addr);
+ }
+
+ //Initialisation functions
+ dev->open = &ks8001_open;
+ dev->hard_start_xmit = &ks8001_hard_start_xmit;
+ dev->stop = &ks8001_stop;
+ dev->do_ioctl = &ks8001_do_ioctl;
+ dev->set_multicast_list = &ks8001_set_multicast;
+ dev->get_stats = &ks8001_get_stats;
+ dev->set_mac_address = &ks8001_set_mac_address;
+ dev->change_mtu = &ks8001_change_mtu;
+ //TODO:// dev->weight = 32;
+ dev->weight = 16;
+ dev->poll = &ks8001_poll;
+ if(debug)
+ dev->flags |= IFF_DEBUG;
+
+ //Set MAC Address
+ if(*((unsigned int *) NVRAM_ADDRESS) == 0x0000FEED && *((unsigned int *) (NVRAM_ADDRESS + 4)) == 0xDEADBEEF)
+ {
+ debugp(DRV_NAME ": NVRAM detected\n");
+ memcpy(dev->dev_addr, (char *) NVRAM_ADDRESS + NVRAM_ETH_OFFSET, 6);
+ }
+ else
+ {
+ debugp(DRV_NAME ": NVRAM not detected\n");
+ memset(dev->dev_addr, 0, sizeof (dev->dev_addr));
+ }
+
+ //Initialise timer thread
+ init_timer(&pr->timer);
+ pr->timer.data = (unsigned long) dev;
+ pr->timer.function = ks8001_timer;
+
+ //Init MII information sturcture
+ pr->mii_if.dev = dev;
+ pr->mii_if.mdio_read = mdio_read;
+ pr->mii_if.mdio_write = mdio_write;
+ pr->mii_if.phy_id = pr->synopsys.phyAddr;
+
+ return 0;
+}//ks8001_init
+
+#ifdef CONFIG_PROC_FS
+static int ks8001_readproc_stats (char *buf, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ // struct net_device *dev = (struct net_device *) data;
+ // uint32_t reg;
+ char *p;
+
+ p = buf;
+ p += sprintf (p, "TBD\n");
+ /*
+ * DISPLAY_DRVSTAT("Events Dropped Counter (Rx Overruns)",0x058);
+ * DISPLAY_DRVSTAT("FCS/Alignment Errors Counter",0x05C);
+ * DISPLAY_DRVSTAT("Runt Packets Counter",0x060);
+ * DISPLAY_DRVSTAT("Oversize Packets Counter",0x064);
+ * DISPLAY_DRVSTAT("Fragment Packets Counter",0x068);
+ * DISPLAY_DRVSTAT("Jabber Counter",0x06C);
+ * DISPLAY_DRVSTAT("Transmit Underruns Counter",0x070);
+ * DISPLAY_DRVSTAT("Late Collisions Counter",0x074);
+ * DISPLAY_DRVSTAT("Carrier Loss Counter",0x078);
+ * DISPLAY_DRVSTAT("Collisions Counter: 1 or More Back-to-Back",0x07C);
+ * DISPLAY_DRVSTAT("Collisions Counter: 2 or More Back-to-Back",0x080);
+ * DISPLAY_DRVSTAT("Collisions Counter: 3 or More Back-to-Back",0x084);
+ * DISPLAY_DRVSTAT("Collisions Counter: 4 or More Back-to-Back",0x088);
+ * DISPLAY_DRVSTAT("Collisions Counter: 5 or More Back-to-Back",0x08C);
+ * DISPLAY_DRVSTAT("Collisions Counter: 6 or More Back-to-Back",0x090);
+ * DISPLAY_DRVSTAT("Collisions Counter: 7 or More Back-to-Back",0x094);
+ * DISPLAY_DRVSTAT("Collisions Counter: 8 or More Back-to-Back",0x098);
+ * DISPLAY_DRVSTAT("Collisions Counter: 9 or More Back-to-Back",0x09C);
+ * DISPLAY_DRVSTAT("Collisions Counter: 10 or More Back-to-Back",0x0A0);
+ * DISPLAY_DRVSTAT("Collisions Counter: 11 or More Back-to-Back",0x0A4);
+ * DISPLAY_DRVSTAT("Collisions Counter: 12 or More Back-to-Back",0x0A8);
+ * DISPLAY_DRVSTAT("Collisions Counter: 13 or More Back-to-Back",0x0AC);
+ * DISPLAY_DRVSTAT("Collisions Counter: 14 or More Back-to-Back",0x0B0);
+ * DISPLAY_DRVSTAT("Collisions Counter: 15 or More Back-to-Back",0x0B4);
+ */
+ *eof = 1;
+ return p - buf + 1;
+}
+
+static int ks8001_readproc_internals (char *buf, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ // struct net_device *dev = (struct net_device *) data;
+ // struct net_priv *priv = dev->priv;
+ char *p;
+
+ p = buf;
+
+ p += sprintf (p, "TBD\n");
+ /*
+ * DISPLAY_INTRN(dma_isr);
+ * DISPLAY_INTRN(dma_poll_rx);
+ * DISPLAY_INTRN(dma_poll_tx);
+ * DISPLAY_INTRN(int_ahb_err);
+ * DISPLAY_INTRN(mac_lcarr);
+ * DISPLAY_INTRN(mac_rx_or);
+ * DISPLAY_INTRN(rx_status_ok);
+ * DISPLAY_INTRN(rx_status_err);
+ * if (priv->drvstats.rx_status_err)
+ * {
+ * DISPLAY_INTRN(viol_4b_5b);
+ * DISPLAY_INTRN(drib_nib);
+ * DISPLAY_INTRN(crc_err);
+ * DISPLAY_INTRN(bad_pre);
+ * DISPLAY_INTRN(long_ev);
+ * DISPLAY_INTRN(bad_packet);
+ * DISPLAY_INTRN(late_carr_ev);
+ * DISPLAY_INTRN(reserved);
+ * }
+ * DISPLAY_INTRN(rx_eof_err);
+ * DISPLAY_INTRN(rx_alloc_err);
+ * DISPLAY_INTRN(tx_status_err);
+ * DISPLAY_INTRN(tx_qfull_err);
+ * DISPLAY_INTRN(tx_skb_err);
+ * DISPLAY_INTRN(tx_bmd_valid_err);
+ * p += sprintf(p,"tx_queue_stopped = %d\n",priv->tx_queue_stopped);
+ */
+ *eof = 1;
+ return p - buf + 1;
+}
+
+#define DISPLAY_PHYREG_DIRTY(tc, phy , mii) SynopsysMiiRead(tc, mii, phy); p += sprintf(p,"PHY%d MR%-2d 0x%4.4x\n",phy,mii,reg)
+
+static int ks8001_readproc_regs_mii (char *buf, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ int phy_begin, phy_end, phy_addr;
+ struct net_device *dev = (struct net_device *)data;
+ Private *pr = (Private *)dev->priv;
+ Synopsys *tc = &pr->synopsys;
+ int reg;
+ char *p;
+
+ p = buf;
+
+ switch (pr->OUI_model)
+ {
+ case ICPLUS_IP175C:
+ case ICPLUS_IP175D:
+ phy_begin = 0;
+ phy_end = 5;
+ break;
+
+ default:
+ phy_begin = AUTOMATIC_PHY_RESOLUTION;
+ phy_end = AUTOMATIC_PHY_RESOLUTION;
+ break;
+ }
+
+ for (phy_addr = phy_begin; (phy_addr <= phy_end); phy_addr++)
+ {
+ reg = DISPLAY_PHYREG_DIRTY(tc, phy_addr, MII_BMCR);
+ reg = DISPLAY_PHYREG_DIRTY(tc, phy_addr, MII_BMSR);
+ reg = DISPLAY_PHYREG_DIRTY(tc, phy_addr, MII_PHYSID1);
+ reg = DISPLAY_PHYREG_DIRTY(tc, phy_addr, MII_PHYSID2);
+ reg = DISPLAY_PHYREG_DIRTY(tc, phy_addr, MII_ADVERTISE);
+ reg = DISPLAY_PHYREG_DIRTY(tc, phy_addr, MII_LPA);
+ reg = DISPLAY_PHYREG_DIRTY(tc, phy_addr, MII_EXPANSION);
+ reg = DISPLAY_PHYREG_DIRTY(tc, phy_addr, MII_TPISTATUS);
+ p += sprintf(p,"\n");
+ }
+
+ *eof = 1;
+ return p-buf+1;
+}
+
+static int ks8001_writeproc_regs_mii (struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ unsigned int reg;
+ int value;
+ int phy;
+
+ if (sscanf(buffer,"PHY%d MII%u %i",&phy, &reg,&value)==3)
+ {
+ mdio_write(dev,phy,reg,value);
+ printk ("wrote PHY%d MII%d 0x%-4x\n", phy, reg ,value);
+ }
+
+ return count;
+}
+
+static int ks8001_readproc_phy_model (char *buf, char **start, off_t offset,
+ int count, int *eof, void *data)
+{
+ struct net_device *dev = (struct net_device *)data;
+ Private *pr = (Private *)dev->priv;
+ char *p;
+
+ p = buf;
+
+ switch (pr->OUI_model)
+ {
+ case ICPLUS_IP175C:
+ p += sprintf(p, "ICPLUS IP175C\n");
+ break;
+
+ case ICPLUS_IP175D:
+ p += sprintf(p, "ICPLUS IP175D\n");
+ break;
+
+ case ICS_1893BF:
+ p += sprintf(p, "ICS 1893BF\n");
+ break;
+
+ case ICS_1893CF:
+ p += sprintf(p, "ICS 1893CF\n");
+ break;
+
+ case MICREL_KS8721:
+ p += sprintf(p, "MICREL KS8721\n");
+ break;
+
+ case REALTEK_RTL8201CP:
+ p += sprintf(p, "REALTEK RTL8201CP\n");
+ break;
+
+ case ICPLUS_IP101A:
+ p += sprintf(p, "ICPLUS IP101A\n");
+ break;
+
+ case JVA_1893BF:
+ p += sprintf(p, "JVA 1893BF\n");
+ break;
+
+ default:
+ p += sprintf(p, "Unknown Chipset %08x\n", pr->OUI_model);
+ break;
+ }
+
+ *eof = 1;
+ return p-buf+1;
+}
+
+#endif
+
+static struct net_device *_device;
+
+/**
+ * Function : ks8001_eth_init
+ * Purpose : Initialize the module.
+ * parameters : void
+ * return value : error code.
+ */
+static int ks8001_eth_init (void)
+{
+ int result;
+ Private *pr;
+ struct net_device *dev;
+
+ printk("%s", version);
+
+ dev = alloc_etherdev(sizeof (Private));
+ if(NULL == dev)
+ {
+ result = -ENOMEM;
+ }
+ pr = (Private *)dev->priv;
+ dev->init = ks8001_init;
+ SET_MODULE_OWNER(dev);
+
+ //Register net device
+ result = register_netdev(dev);
+ if(result < 0)
+ {
+ printk(KERN_ERR "KS8001: eth%d: Could not register device\n", pr->minor);
+ kfree(dev->priv);
+ free_netdev(dev);
+ }
+ else
+ {
+ _device = dev;
+ }
+
+
+#ifdef CONFIG_PROC_FS
+ {
+ struct proc_dir_entry *eth_dir;
+ struct proc_dir_entry *regs_dir;
+ struct proc_dir_entry *entry;
+ struct proc_dir_entry *internals_dir;
+
+ eth_dir = proc_mkdir("eth", proc_net);
+ create_proc_read_entry("stats", 0, eth_dir, ks8001_readproc_stats, dev);
+ create_proc_read_entry("phy_model", 0, eth_dir, ks8001_readproc_phy_model, dev);
+ internals_dir = proc_mkdir("internals", eth_dir);
+ create_proc_read_entry("stats", 0, internals_dir, ks8001_readproc_internals, dev);
+ regs_dir = proc_mkdir("regs", eth_dir);
+ entry = create_proc_entry("mii", 0, regs_dir);
+ entry->read_proc = ks8001_readproc_regs_mii;
+ entry->write_proc = ks8001_writeproc_regs_mii;
+ entry->data = (int *) dev;
+ }
+#endif
+ return result;
+}// ks8001_eth_init
+
+/**
+ * Function : ks8001_eth_exit
+ * Purpose : Unregister the device.
+ * Parameters : void
+ * Return value : void.
+ */
+static void ks8001_eth_exit (void)
+{
+ Private *pr = _device->priv;
+ int minor = pr->minor;
+
+ if(_device)
+ {
+ //Freeing private field of the net device struture
+ if(pr)
+ kfree(pr);
+
+ //Freeing network device
+ free_netdev(_device);
+
+ //Unregister net device
+ unregister_netdev(_device);
+ }
+
+ //cleanup Hardware part
+ ks8001_hw_cleanup(minor);
+
+}//ks8001_eth_exit
+
+module_init(ks8001_eth_init);
+module_exit(ks8001_eth_exit);
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/KS8001_dma.c b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_dma.c
new file mode 100644
index 0000000000..9da1ac2a73
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_dma.c
@@ -0,0 +1,694 @@
+#include "KS8001_dma.h"
+#include "KS8001_reg.h"
+
+#include <asm/types.h>
+#include <asm/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/netdevice.h>
+
+/* Size of each temporary Rx buffer.*/
+#define PKT_BUF_SZ 1536
+
+/* print debug message on bad packet receiving or transmitting */
+#define SYNOP_ETH_DEBUG_BAD
+
+/* try to pre-synchronize descriptors */
+/* #define USE_PRESYNC */
+
+/* count of check the current RX descriptor again if owned by DMA */
+#define MAX_CHECK_RX 1
+
+/* RX descriptor error mask */
+#define RX_ERROR_MASK 0x400078DF
+
+#ifndef CONFIG_MMU
+/* Necessary because DMA allocation is not correct (to be fixed) */
+#undef GFP_DMA
+#define GFP_DMA 0
+#endif /* CONFIG_MMU */
+
+extern uint32_t DMA_zone_base;
+
+struct syeth_dma_rx_t
+{
+ union {
+ struct {
+ int err_mac : 1; /**< [ 0: 0] Rx MAC Address/Payload Checksum Errort */
+ int err_crc : 1; /**< [ 1: 1] CRC error */
+ int err_drib : 1; /**< [ 2: 2] Dribble error */
+ int err_recv : 1; /**< [ 3: 3] Receive error */
+ int watchdog : 1; /**< [ 4: 4] Watchdog event occured */
+ int type : 1; /**< [ 5: 5] Ethernet-type */
+ int err_coll : 1; /**< [ 6: 6] Late collision */
+ int err_ipc : 1; /**< [ 7: 7] IPC checksumm error */
+ int last : 1; /**< [ 8: 8] last frame descriptor */
+ int first : 1; /**< [ 9: 9] first frame descriptor */
+ int vlan : 1; /**< [10:10] VLAN tag */
+ int err_over : 1; /**< [11:11] overflow error */
+ int err_length: 1; /**< [12:12] length/type error */
+ int err_sfail : 1; /**< [13:13] source address fail */
+ int err_desc : 1; /**< [14:14] Descriptor error */
+ int err : 1; /**< [15:15] error summary */
+ uint length : 14; /**< [29:16] frame length */
+ int err_dfail : 1; /**< [30:30] if set - destination address fail */
+ int dma_own : 1; /**< [31:31] if set - owned by DMA */
+ }bf;
+ unsigned int val;
+ }status;
+
+ union {
+ struct {
+ uint length1 : 11; /**< [10: 0] Buffer1 length */
+ uint length2 : 11; /**< [21:11] Buffer2 length */
+ int _reserved2 : 2; /**< [23:22] */
+ int addr2en : 1; /**< [24:24] Addr2 is the next descr address */
+ int eor : 1; /**< [25:25] End of ring */
+ int _reserved1 : 5; /**< [30:26] */
+ int int_dis : 1; /**< [31:31] Disable Int on Completion */
+ }bf;
+ unsigned int val;
+ }state;
+ unsigned int addr1;
+ unsigned int addr2;
+};
+
+struct syeth_dma_tx_t
+{
+ union {
+ struct {
+ int deffered : 1; /**< [ 0: 0] Deffered bit */
+ int err_under : 1; /**< [ 1: 1] Underflow error */
+ int exc_deff : 1; /**< [ 2: 2] excessive defferal */
+ int coll_cnt : 4; /**< [ 6: 3] Collision count*/
+ int vlan : 1; /**< [ 7: 7] VLAN tag */
+ int err_ecoll : 1; /**< [ 8: 8] Excessive collision */
+ int err_lcoll : 1; /**< [ 9: 9] Late collision */
+ int err_nocar : 1; /**< [10:10] No carrier */
+ int err_clost : 1; /**< [11:11] Carrier lost */
+ int err_plcs : 1; /**< [12:12] Payload/Checksumm error */
+ int flushed : 1; /**< [13:13] Frame flushed */
+ int err_jabt : 1; /**< [14:14] Jabber Timeout */
+ int err : 1; /**< [15:15] error summary */
+ int err_ip : 1; /**< [16:16] IP header error */
+ int _reserved : 14; /**< [30:17] */
+ int dma_own : 1; /**< [31:31] if set - owned by DMA */
+ }bf;
+ unsigned int val;
+ }status;
+
+ union {
+ struct {
+ uint length1 : 11; /**< [10: 0] Buffer1 length */
+ uint length2 : 11; /**< [21:11] Buffer2 length */
+ int _reserved : 1; /**< [22:22] */
+ int no_pad : 1; /**< [23:23] Disable padding */
+ int addr2en : 1; /**< [24:24] Addr2 is the next descr address */
+ int eor : 1; /**< [25:25] End of ring */
+ int no_crc : 1; /**< [26:26] Disable CRC */
+ int cs_ctrl : 2; /**< [28:27] Checksumm insertion control */
+ int first : 1; /**< [29:29] First frame segment */
+ int last : 1; /**< [30:30] Last frame segment */
+ int int_oncomp: 1; /**< [31:31] Enable Int on Completion */
+ }bf;
+ unsigned int val;
+ }state;
+ unsigned int addr1;
+ unsigned int addr2;
+};
+
+struct syeth_dma_tx_ex_t
+{
+ union {
+ struct {
+ int deffered : 1; /**< [ 0: 0] Deffered bit */
+ int err_under : 1; /**< [ 1: 1] Underflow error */
+ int exc_deff : 1; /**< [ 2: 2] excessive defferal */
+ int coll_cnt : 4; /**< [ 6: 3] Collision count*/
+ int vlan : 1; /**< [ 7: 7] VLAN tag */
+ int err_ecoll : 1; /**< [ 8: 8] Excessive collision */
+ int err_lcoll : 1; /**< [ 9: 9] Late collision */
+ int err_nocar : 1; /**< [10:10] No carrier */
+ int err_clost : 1; /**< [11:11] Carrier lost */
+ int err_plcs : 1; /**< [12:12] Payload/Checksumm error */
+ int flushed : 1; /**< [13:13] Frame flushed */
+ int err_jabt : 1; /**< [14:14] Jabber Timeout */
+ int err : 1; /**< [15:15] error summary */
+ int err_ip : 1; /**< [16:16] IP header error */
+ int _reserved2 : 3; /**< [19:17] */
+ int addr2en : 1; /**< [20:20] Addr2 is the next descr address */
+ int eor : 1; /**< [21:21] End of ring */
+ int cs_ctrl : 2; /**< [23:22] Checksumm insertion control */
+ int _reserved1 : 14; /**< [25:24] */
+ int no_pad : 1; /**< [26:26] Disable padding */
+ int no_crc : 1; /**< [27:27] Disable CRC */
+ int first : 1; /**< [28:28] First frame segment */
+ int last : 1; /**< [29:29] Last frame segment */
+ int int_oncomp: 1; /**< [30:30] Enable Int on Completion */
+ int dma_own : 1; /**< [31:31] if set - owned by DMA */
+ }bf;
+ unsigned int val;
+ }status;
+
+ union {
+ struct {
+ int length1 : 13; /**< [12: 0] Buffer1 length */
+ int _reserved1 : 3; /**< [15:13] */
+ int length2 : 13; /**< [28:16] Buffer1 length */
+ int _reserved2 : 3; /**< [31:29] */
+ }bf;
+ unsigned int val;
+ }state;
+ unsigned int addr1;
+ unsigned int addr2;
+};
+
+static const unsigned char __hexdigits[] = "0123456789ABCDEF";
+static void sprintf_hex(unsigned char * str, const unsigned char * ptr,
+ int len, unsigned char delim)
+{
+ int i, j=0;
+ for(i=0; i<len; i++){
+ if(i)str[j++]=delim;
+ str[j++]=__hexdigits[ptr[i]>>4];
+ str[j++]=__hexdigits[ptr[i]&0x0F];
+ }
+ str[j] = 0;
+}
+
+static void __print_packet(const char * prefix, int descr, int len, struct sk_buff * skb)
+{
+ struct ethhdr * h;
+ unsigned char src[20], dst[20], body[50];
+ int l;
+
+ h = (struct ethhdr *)skb->data;
+ l = len - 14 > 16 ? 16 : len - 14;
+ sprintf_hex(src, &h->h_source[0], 6, ':');
+ sprintf_hex(dst, &h->h_dest[0], 6, ':');
+ sprintf_hex(body, ((unsigned char *)skb->data)+14, l, ' ');
+
+ printk("%08lX %s: d=%-3d len=%-4d proto=0x%04X src=%s dst=%s\n"
+ " body=%s\n",
+ jiffies, prefix, descr, len, be16_to_cpu(h->h_proto),
+ src, dst, body);
+}
+
+#ifdef SYNOP_ETH_DEBUG
+#define print_packet __print_packet
+#else
+#define print_packet(...)
+#endif
+
+#ifdef CONFIG_MMU
+struct syeth_dma_rb * syeth_dma_rx_rb_alloc (int dcount, int mtu,
+ struct net_device_stats * st)
+{
+ struct syeth_dma_rb * rb;
+ int i;
+
+ rb = kmalloc (sizeof (*rb) + (dcount*sizeof(void*)), GFP_ATOMIC);
+ if(NULL == rb) return NULL;
+
+ /* dma descriptors */
+ rb->cur = 0;
+ rb->dcount = dcount;
+ if (mtu > ETH_DATA_LEN)
+ /* MTU + ethernet header + FCS + optional VLAN tag */
+ rb->skblength = mtu + ETH_HLEN + 8;
+ else
+ rb->skblength = PKT_BUF_SZ;
+
+ rb->dsize = dcount * 16;
+ rb->stats = st;
+
+ rb->d.rx = dma_alloc_coherent(NULL, rb->dsize, &rb->phys, GFP_ATOMIC);
+ if(rb->d.rx == NULL){
+ kfree(rb);
+ return NULL;
+ }
+
+ memset(rb->d.rx, 0, rb->dsize);
+ memset(rb->sk, 0, dcount * sizeof(struct sk_buff*));
+
+ /* sk_buff array */
+ for(i=0; i<dcount; i++){
+ struct syeth_dma_rx_t * d = rb->d.rx + i;
+ struct sk_buff * skb = dev_alloc_skb(rb->skblength);
+ if (skb == NULL) {
+ printk(KERN_ERR "KS8001: DMA: RX: "
+ "Could not allocate skb. Stop!!!\n");
+ syeth_dma_rx_rb_free (rb);
+ return NULL;
+ }
+ rb->sk[i] = skb;
+ d->addr1 = dma_map_single(NULL, skb->data, rb->skblength,
+ DMA_FROM_DEVICE);
+ d->state.bf.length1 = rb->skblength;
+
+ d->status.bf.dma_own = 1;
+ }
+ /* set EndOfRing bit */
+ (rb->d.rx+(dcount-1))->state.bf.eor = 1;
+
+ return rb;
+}
+#else
+struct syeth_dma_rb * syeth_dma_rx_rb_static_alloc (struct net_device_stats * st)
+{
+ struct syeth_dma_rb * rb;
+ int i;
+
+ rb = (struct syeth_dma_rb*)ETH_DMA_RX_BASE;
+
+ /* dma descriptors */
+ rb->cur = 0;
+ rb->dcount = ETH_RX_RING_SIZE;
+ rb->skblength = PKT_BUF_SZ;
+ rb->dsize = ETH_RX_DMAREG_SIZE;
+ rb->stats = st;
+ rb->d.rx = (struct syeth_dma_rx_t*)ETH_RX_DMAREG_BASE;
+ rb->phys = virt_to_phys(rb->d.rx);
+
+ memset(rb->d.rx, 0, rb->dsize);
+ memset(rb->sk, 0, ETH_RX_RING_SIZE*sizeof(void*));
+
+ /* sk_buff array */
+ for(i=0; i<ETH_RX_RING_SIZE; i++){
+ struct syeth_dma_rx_t * d = rb->d.rx + i;
+ struct sk_buff * skb = dev_alloc_skb(rb->skblength);
+ if (skb == NULL) {
+ printk(KERN_ERR "KS8001: DMA: RX: "
+ "Could not allocate skb. Stop!!!\n");
+ syeth_dma_rx_rb_free (rb);
+ return NULL;
+ }
+ rb->sk[i] = skb;
+ consistent_sync(skb->data, rb->skblength, DMA_FROM_DEVICE);
+ d->addr1 = virt_to_dma(NULL, (unsigned long)skb->data);
+ d->state.bf.length1 = rb->skblength;
+
+ d->status.bf.dma_own = 1;
+ }
+ /* set EndOfRing bit */
+ (rb->d.rx+(ETH_RX_RING_SIZE-1))->state.bf.eor = 1;
+
+ return rb;
+}
+#endif
+
+void syeth_dma_rx_rb_reset (struct syeth_dma_rb * rb)
+{
+ int i;
+ volatile struct syeth_dma_rx_t * d = rb->d.rx;
+#if defined USE_PRESYNC && defined CONFIG_MMU
+ dma_sync_single_for_cpu(NULL, rb->phys,
+ rb->dsize, DMA_FROM_DEVICE);
+#endif
+ for(i=0; i<rb->dcount; i++){
+ d->status.val = 0;
+ d->status.bf.dma_own = 1;
+ d++;
+ }
+#if defined USE_PRESYNC && defined CONFIG_MMU
+ dma_sync_single_for_cpu(NULL, rb->phys,
+ rb->dsize, DMA_TO_DEVICE);
+#endif
+ rb->cur = 0;
+}
+
+void syeth_dma_rx_rb_free (struct syeth_dma_rb * rb)
+{
+ int i;
+ for(i=0; i<rb->dcount; i++){
+ if(rb->sk[i]){
+ dev_kfree_skb_any(rb->sk[i]);
+ }
+ }
+#ifdef CONFIG_MMU
+ dma_free_coherent(NULL, rb->dcount * sizeof(struct syeth_dma_rx_t),
+ rb->d.rx, rb->phys);
+ kfree(rb);
+#endif
+}
+
+struct sk_buff * syeth_dma_rx_rb_get (struct syeth_dma_rb * rb)
+{
+ struct sk_buff *retskb = NULL;
+ struct sk_buff *nskb;
+ volatile struct syeth_dma_rx_t * d = rb->d.rx + rb->cur;
+ int trycnt = MAX_CHECK_RX;
+
+ while(retskb == NULL) {
+
+#if defined USE_PRESYNC && defined CONFIG_MMU
+ dma_sync_single_for_cpu(NULL, rb->phys,
+ rb->dsize, DMA_FROM_DEVICE);
+#endif
+ if(d->status.bf.dma_own){
+ if(--trycnt){
+ udelay(50);
+ continue;
+ }
+ break;
+ }
+#ifdef CONFIG_KS8001_RMII
+ /* Dribble error is not affected on RMII */
+ if(d->status.bf.err_drib)
+ d->status.bf.err_drib = 0;
+#endif
+ if((d->status.val&RX_ERROR_MASK) || /* some error occured. skip this descriptor */
+ 0==d->status.bf.first || /* packetizing is not supported now */
+ 0==d->status.bf.last ||
+ 4>=d->status.bf.length /* Zero-length is not supported */
+ ){
+ rb->stats->rx_errors++;
+ rb->stats->collisions +=
+ (d->status.bf.err_over|
+ d->status.bf.err_length);
+
+ rb->stats->rx_crc_errors +=
+ d->status.bf.err_crc;
+
+ rb->stats->rx_frame_errors +=
+ d->status.bf.err_drib;
+
+ rb->stats->rx_length_errors +=
+ d->status.bf.err_length;
+#ifdef SYNOP_ETH_DEBUG_BAD
+ {
+ char prefix[64];
+ sprintf(prefix, "RX BAD: %s%s%s%s%s%s%s%s%s",
+ d->status.bf.err_mac ? "EMAC " :"",
+ d->status.bf.err_recv ? "ERECV " :"",
+ d->status.bf.err_crc ? "ECRC " :"",
+ d->status.bf.err_drib ? "EDRIB " :"",
+ d->status.bf.watchdog ? "EWD " :"",
+ d->status.bf.err_length ? "ELEN " :"",
+ 4>=d->status.bf.length ? "ZLEN " :"",
+ 0==d->status.bf.first ? "NOFIRST ":"",
+ 0==d->status.bf.last ? "NOLAST " :""
+ );
+ __print_packet(prefix, rb->cur,
+ d->status.bf.length-4,
+ rb->sk[rb->cur]);
+ }
+#endif
+ goto d_skip;
+ }
+
+ retskb = rb->sk[rb->cur];
+ BUG_ON(retskb == NULL);
+
+ nskb = dev_alloc_skb(rb->skblength);
+ if(nskb){
+ int len = d->status.bf.length-4;
+ skb_put(retskb, len);
+
+ print_packet("RECV", rb->cur, len, retskb);
+#ifdef CONFIG_MMU
+ dma_unmap_single(NULL, d->addr1, d->state.bf.length1,
+ DMA_FROM_DEVICE);
+#endif
+ rb->sk[rb->cur] = nskb;
+ d->state.bf.length1 = rb->skblength;
+#ifdef CONFIG_MMU
+ d->addr1 = dma_map_single(NULL, nskb->data,
+ rb->skblength,
+ DMA_FROM_DEVICE);
+#else
+ consistent_sync(nskb->data, rb->skblength, DMA_FROM_DEVICE);
+ d->addr1 = virt_to_dma(NULL,nskb->data);
+#endif
+
+ if(rb->stats){
+ rb->stats->rx_packets++;
+ rb->stats->rx_bytes += len;
+ }
+
+ }else{
+ retskb = NULL;
+ if(rb->stats){
+ rb->stats->rx_dropped++;
+ }
+ }
+ d_skip:
+ d->status.val = 0;
+ d->status.bf.dma_own = 1;
+#if defined USE_PRESYNC && defined CONFIG_MMU
+ dma_sync_single_for_cpu(NULL, rb->phys, rb->dsize,
+ DMA_TO_DEVICE);
+#endif
+ rb->cur = d->state.bf.eor ? 0 : rb->cur + 1;
+ d = rb->d.rx + rb->cur;
+ }
+ return retskb;
+}
+
+struct sk_buff * syeth_dma_rx_rb_scan (struct syeth_dma_rb * rb)
+{
+ volatile struct syeth_dma_rx_t * d;
+ struct sk_buff * rscb = NULL;
+ u32 i = rb->cur;
+
+#if defined USE_PRESYNC && defined CONFIG_MMU
+ dma_sync_single_for_cpu(NULL, rb->phys, rb->dsize, DMA_FROM_DEVICE);
+#endif
+ do{
+ d = rb->d.rx + i;
+ if(0==d->status.bf.dma_own){
+ debugp(KERN_INFO "KS8001: DMA: RX: "
+ "Resynced (%d==>%d)\n", rb->cur, i);
+ rb->cur = i;
+ rscb = syeth_dma_rx_rb_get(rb);
+ break;
+ }
+ if(d->state.bf.eor){
+ i = 0;
+ }else{
+ i ++;
+ }
+ }while(i != rb->cur);
+
+ return rscb;
+}
+
+#ifdef CONFIG_MMU
+struct syeth_dma_rb * syeth_dma_tx_rb_alloc (int dcount,
+ struct net_device_stats * st)
+{
+ struct syeth_dma_rb *rb;
+
+ rb = kmalloc (sizeof (*rb) + (dcount*sizeof(void*)), GFP_ATOMIC);
+ if(NULL == rb) return NULL;
+
+ /* dma descriptors */
+ rb->cur = 0;
+ rb->dcount = dcount;
+ rb->dsize = dcount * 16;
+ rb->stats = st;
+ rb->skblength = 0;
+
+ rb->d.tx = dma_alloc_coherent(NULL, rb->dsize, &rb->phys, GFP_ATOMIC);
+ if(rb->d.tx == NULL){
+ kfree(rb);
+ return NULL;
+ }
+
+ memset(rb->d.tx, 0, rb->dsize);
+ memset(rb->sk, 0, dcount * sizeof(void*));
+
+ /* set EndOfRing bit */
+ (rb->d.tx+(dcount-1))->state.bf.eor = 1;
+ return rb;
+}
+#else
+struct syeth_dma_rb * syeth_dma_tx_rb_static_alloc (struct net_device_stats * st)
+{
+ struct syeth_dma_rb *rb;
+
+ rb = (struct syeth_dma_rb*)ETH_DMA_TX_BASE;
+
+ /* dma descriptors */
+ rb->cur = 0;
+ rb->dcount = ETH_TX_RING_SIZE;
+ rb->dsize = ETH_RX_DMAREG_SIZE;
+ rb->stats = st;
+ rb->skblength = 0;
+ rb->d.tx = (struct syeth_dma_tx_t*)ETH_TX_DMAREG_BASE;
+ rb->phys = virt_to_phys(rb->d.tx);
+
+ memset(rb->d.tx, 0, rb->dsize);
+ memset(rb->sk, 0, ETH_TX_RING_SIZE*sizeof(void*));
+
+ /* set EndOfRing bit */
+ (rb->d.tx+(ETH_TX_RING_SIZE-1))->state.bf.eor = 1;
+ return rb;
+}
+#endif
+
+static void syeth_dma_tx_skb_complete(struct syeth_dma_rb * rb, int i)
+{
+ struct syeth_dma_tx_t * d = rb->d.tx + i;
+ struct sk_buff * old = rb->sk[i];
+ /* last transmitted frame found.
+ * cleanup */
+ if(d->status.bf.dma_own || d->status.bf.err){
+ rb->stats->tx_errors++;
+
+ rb->stats->tx_aborted_errors +=
+ d->status.bf.err_lcoll+
+ d->status.bf.err_ecoll;
+
+ rb->stats->tx_carrier_errors +=
+ d->status.bf.err_clost+
+ d->status.bf.err_nocar;
+#ifdef SYNOP_ETH_DEBUG_BAD
+ if(d->status.bf.err){
+ char prefix[64];
+ sprintf(prefix, "TX BAD: %s%s%s%s%s%s%s%s",
+ d->status.bf.err_ip ? "EIPH " :"",
+ d->status.bf.flushed ? "FLUSH " :"",
+ d->status.bf.err_plcs ? "EPLCS " :"",
+ d->status.bf.err_clost ? "ECLOST ":"",
+ d->status.bf.err_nocar ? "ENOCAR ":"",
+ d->status.bf.err_ecoll ? "EECOLL ":"",
+ d->status.bf.err_lcoll ? "ELCOLL ":"",
+ d->status.bf.exc_deff ? "EEDEF " :""
+ );
+ __print_packet(prefix, rb->cur, d->state.bf.length1, old);
+ }
+#endif
+ }else{
+ rb->stats->tx_bytes += d->state.bf.length1;
+ rb->stats->tx_packets++;
+ }
+ rb->stats->collisions += d->status.bf.coll_cnt;
+#ifdef CONFIG_MMU
+ dma_unmap_single(NULL, d->addr1, d->state.bf.length1,
+ DMA_TO_DEVICE);
+#endif
+ dev_kfree_skb_any(old);
+ rb->sk[i] = NULL;
+}
+
+void syeth_dma_tx_rb_reset (struct syeth_dma_rb * rb)
+{
+ int i;
+ memset(rb->d.tx, 0, rb->dsize);
+ /* set EndOfRing bit */
+ (rb->d.tx+(rb->dcount-1))->state.bf.eor = 1;
+ rb->cur = 0;
+
+ /* delete all sk_bufs */
+ for(i=0; i<rb->dcount; i++){
+ if(rb->sk[i]){
+ dev_kfree_skb_any(rb->sk[i]);
+ rb->sk[i] = NULL;
+ }
+ }
+}
+void syeth_dma_tx_rb_free (struct syeth_dma_rb * rb)
+{
+ syeth_dma_tx_rb_reset(rb);
+#ifdef CONFIG_MMU
+ dma_free_coherent(NULL, rb->dsize, rb->d.tx, rb->phys);
+ kfree(rb);
+#endif
+}
+
+int syeth_dma_tx_rb_put (struct syeth_dma_rb * rb, struct sk_buff * skb)
+{
+ volatile struct syeth_dma_tx_t * d = rb->d.tx + rb->cur;
+ int eor;
+
+#if defined USE_PRESYNC && defined CONFIG_MMU
+ dma_sync_single_for_cpu(NULL, rb->phys, rb->dsize, DMA_FROM_DEVICE);
+#endif
+
+ if(d->status.bf.dma_own){
+ printk(KERN_ERR "KS8001: TX DESCRIPTOR %d is owned by DMA.\n", rb->cur);
+ return -1;
+ }
+
+ if(rb->sk[rb->cur]){
+ syeth_dma_tx_skb_complete(rb, rb->cur);
+ }
+
+ rb->sk[rb->cur] = skb;
+ eor = d->state.bf.eor;
+ d->state.val = 0;
+ d->status.val = 0;
+#ifdef CONFIG_MMU
+ d->addr1 = dma_map_single(NULL, skb->data, skb->len,
+ DMA_TO_DEVICE);
+#else
+ consistent_sync(skb->data, skb->len, DMA_TO_DEVICE);
+ d->addr1 = virt_to_dma(NULL, (unsigned long)skb->data);
+#endif
+ d->addr2 = 0;
+ d->state.bf.eor = eor;
+ d->state.bf.first = 1;
+ d->state.bf.last = 1;
+ d->state.bf.int_oncomp = 1;
+ d->state.bf.length1 = skb->len;
+
+ d->status.val = 0;
+ d->status.bf.dma_own = 1;
+
+#if defined USE_PRESYNC && defined CONFIG_MMU
+ dma_sync_single_for_cpu(NULL, rb->phys, rb->dsize, DMA_TO_DEVICE);
+#endif
+
+ print_packet("SEND", rb->cur, skb->len, skb);
+
+ rb->cur = eor ? 0 : rb->cur + 1;
+
+ /* check next and next+1 descriptor for Host ownership */
+ d = rb->d.tx + rb->cur;
+ if(d->status.bf.dma_own){
+ return rb->cur+1;
+ }else{
+ int n = rb->cur + 1;
+ if(n == rb->dcount) n = 0;
+ d = rb->d.tx + n;
+ if(d->status.bf.dma_own){
+ return n+1;
+ }
+ }
+ return 0;
+}
+
+int syeth_dma_tx_rb_complete(struct syeth_dma_rb * rb)
+{
+ int cnt = 0;
+ struct syeth_dma_tx_t * d = rb->d.tx + rb->skblength;
+ while ( rb->skblength != rb->cur
+ && 0==d->status.bf.dma_own
+ && rb->sk[rb->skblength] ) {
+ syeth_dma_tx_skb_complete(rb, rb->skblength);
+ rb->skblength = (d->state.bf.eor) ? 0 : rb->skblength + 1;
+ d = rb->d.tx + rb->skblength;
+ cnt++;
+ }
+ return cnt;
+}
+
+int syeth_dma_tx_rb_complete_next(struct syeth_dma_rb * rb)
+{
+ int i, cnt = 0;
+ struct syeth_dma_tx_t * d;
+ i = rb->cur;
+
+ do{
+ d = rb->d.tx + i;
+ if(d->status.bf.dma_own){
+ break;
+ }
+ if(rb->sk[i]){
+ syeth_dma_tx_skb_complete(rb, i);
+ cnt++;
+ }
+ i = (d->state.bf.eor) ? 0 : i+1;
+ }while(i != rb->cur);
+ return cnt;
+}
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/KS8001_dma.h b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_dma.h
new file mode 100644
index 0000000000..1d0416ab60
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_dma.h
@@ -0,0 +1,73 @@
+#ifndef KS8001_DMA_H
+#define KS8001_DMA_H
+
+#include <asm/types.h>
+#include <linux/skbuff.h>
+
+/*************************************************************/
+struct syeth_dma_rx_t;
+struct syeth_dma_tx_t;
+
+struct syeth_dma_rb
+{
+ union{
+ struct syeth_dma_rx_t * rx; /* rx descriptors array */
+ struct syeth_dma_tx_t * tx; /* tx descriptors array */
+ }d;
+ dma_addr_t phys; /* phys. address of 1-st descr. */
+ int dcount; /* descriptor count */
+ int dsize; /* full size of desc buffer */
+ int skblength; /* use it as previous index in TX */
+ int cur; /* current descriptor */
+ struct net_device_stats * stats; /* device statistics pointer */
+ struct sk_buff * sk[]; /* skbufs for descriptors */
+};
+
+/*************************************************************/
+
+/** Allocate RX ringbuffer */
+#ifdef CONFIG_MMU
+struct syeth_dma_rb * syeth_dma_rx_rb_alloc (int dcount, int dlength,
+ struct net_device_stats * st);
+#else
+struct syeth_dma_rb * syeth_dma_rx_rb_static_alloc (struct net_device_stats * st);
+#endif
+
+/** Reset RX ringbuffer. Cleanup all completed descriptors */
+
+void syeth_dma_rx_rb_reset (struct syeth_dma_rb *);
+
+/** Reset and delete RX ringbuffer. */
+void syeth_dma_rx_rb_free (struct syeth_dma_rb *);
+
+/** Get next completed skbuf. */
+struct sk_buff * syeth_dma_rx_rb_get (struct syeth_dma_rb *);
+
+/** Scan ringbuffer for completed skbuf. */
+struct sk_buff * syeth_dma_rx_rb_scan (struct syeth_dma_rb *);
+
+/*************************************************************/
+
+/** Allocate TX ringbuffer */
+#ifdef CONFIG_MMU
+struct syeth_dma_rb * syeth_dma_tx_rb_alloc (int dcount,
+ struct net_device_stats * st);
+#else
+struct syeth_dma_rb * syeth_dma_tx_rb_static_alloc (struct net_device_stats * st);
+#endif
+
+/** Reset TX ringbuffer. Cancel all uncompleted descriptors */
+void syeth_dma_tx_rb_reset (struct syeth_dma_rb *);
+
+/** Reset and delete TX ringbuffer. */
+void syeth_dma_tx_rb_free (struct syeth_dma_rb *);
+
+/* Put skbuf to TX ringbuffer. Cleanup old skbuf if it possible */
+int syeth_dma_tx_rb_put (struct syeth_dma_rb *,
+ struct sk_buff *);
+/* Cleanup all completed skbuf in TX ringbuffer */
+int syeth_dma_tx_rb_complete (struct syeth_dma_rb *);
+
+/*************************************************************/
+
+#endif
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw.h b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw.h
new file mode 100644
index 0000000000..a640d2f2a9
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw.h
@@ -0,0 +1,13 @@
+#ifndef KS8001_hw_h
+#define KS8001_hw_h
+struct ks8001_device_table
+{
+ int minor;
+ unsigned int base_addr;
+ unsigned char irq;
+ int phy_addr;
+};
+//#include "KS8001_hw_vi1888.h"
+#include "KS8001_hw_spc2XXc.h"
+#endif
+
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw_spc2XXc.h b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw_spc2XXc.h
new file mode 100644
index 0000000000..cbcec4aa83
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw_spc2XXc.h
@@ -0,0 +1,90 @@
+#ifndef KS8001_hw_spc2XXc_H
+#define KS8001_hw_spc2XXc_H
+
+#if defined(CONFIG_ARCH_SPC200C) || defined(CONFIG_ARCH_MSE500)
+
+/* Use mega-super-pouper newest version of FPGA */
+#define KS8001_USE_PIO1
+
+/* Base address and IRQ definitions */
+# define clk_get(X,NAME) ((void*)1) /* to prevent IS_ERR() check failed */
+# define clk_enable(X)
+# define clk_disable(X)
+# define clk_put(X)
+
+# define PIO_ETH_RESET (1<<7)
+# define PIO_ETH_SPEED (1<<5)
+
+# define FPGA_ETH_RMII (1<<2)
+# define FPGA_ETH_100 (1<<3)
+
+#ifdef KS8001_USE_PIO1
+#define KS8001_ETH_PIO CSP_PIO1
+#else
+#define KS8001_ETH_PIO CSP_PIO
+#endif
+
+static __inline__ void ks8001_hw_prepare(uint minor)
+{
+ volatile unsigned int * selreg = ((volatile unsigned int *)CSP_CM_FPGA_VA_BASE) + 8;
+ unsigned int data = (*selreg) | (SEL_KEY<<16);
+#ifdef CONFIG_KS8001_RMII
+ data |= FPGA_ETH_RMII;
+#else
+ data &= ~FPGA_ETH_RMII;
+#endif
+ *selreg = data;
+ printk("KS8001: eth%d: configured as %sMII\n", minor,
+ ((*selreg)&FPGA_ETH_RMII) ? "R" : ""
+ );
+}
+
+static __inline__ void ks8001_hw_unreset(uint minor)
+{
+ int i;
+ CSP_PIO_SET_ECR(KS8001_ETH_PIO, PIO_PIO);
+ CSP_PIO_SET_PER(KS8001_ETH_PIO, PIO_ETH_RESET);
+ CSP_PIO_SET_OER(KS8001_ETH_PIO, PIO_ETH_RESET);
+ CSP_PIO_SET_CODR(KS8001_ETH_PIO,PIO_ETH_RESET);
+ for(i=0;i<0x1000;i++);
+ CSP_PIO_SET_SODR(KS8001_ETH_PIO,PIO_ETH_RESET);
+}
+
+
+static __inline__ void ks8001_hw_set_speed(uint minor, uint is_100)
+{
+ volatile unsigned int * selreg = ((volatile unsigned int *)CSP_CM_FPGA_VA_BASE) + 8;
+ unsigned int data = *selreg;
+ /* enable PIO */
+#ifndef KS8001_USE_PIO1
+ CSP_PIO_SET_ECR(KS8001_ETH_PIO,PIO_PIO);
+ CSP_PIO_SET_PER(KS8001_ETH_PIO, PIO_ETH_SPEED);
+ CSP_PIO_SET_OER(KS8001_ETH_PIO, PIO_ETH_SPEED);
+#endif
+ if(is_100){
+#ifndef KS8001_USE_PIO1
+ CSP_PIO_SET_CODR(KS8001_ETH_PIO,PIO_ETH_SPEED);
+ CSP_PIO_SET_SODR(KS8001_ETH_PIO,PIO_ETH_SPEED);
+#endif
+ data |= FPGA_ETH_100;
+ }else{
+#ifndef KS8001_USE_PIO1
+ CSP_PIO_SET_SODR(KS8001_ETH_PIO,PIO_ETH_SPEED);
+ CSP_PIO_SET_CODR(KS8001_ETH_PIO,PIO_ETH_SPEED);
+#endif
+ data &= ~FPGA_ETH_100;
+ }
+ data |= (SEL_KEY<<16);
+ *selreg = data;
+ *selreg;
+ debugp("KS8001: spc2XXc set speed: selr=0x%08X\n", *selreg);
+}
+static __inline__ void ks8001_hw_cleanup(int minor)
+{
+ /* Nothing to do */
+}
+
+static struct ks8001_device_table ks8001_hw_device = {0, EXT_AHBM0_AHB_ETHVIRT_BASE, 1, 2 };
+#endif /* CONFIG_ARCH_SPC200C && CONFIG_ARCH_MSE500 */
+
+#endif
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw_vi1888.h b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw_vi1888.h
new file mode 100644
index 0000000000..346ed7a393
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_hw_vi1888.h
@@ -0,0 +1,75 @@
+#ifndef KS8001_VI1888_H
+#define KS8001_VI1888_H
+
+#ifdef CONFIG_ARCH_VI1888_EVB
+
+#include <asm/arch/constants.h>
+#include <linux/clk.h>
+
+/* Base address and IRQ definitions */
+static const char * const _clk_names[] = {
+ "AHB_ETH_1_CLK",
+ "AHB_ETH_2_CLK"
+};
+static struct clk * __clk[2] = {NULL, NULL};
+
+static __inline__ void ks8001_hw_prepare(uint minor)
+{
+ if(__clk[minor] == NULL){
+ struct clk * eth_clk;
+ eth_clk = clk_get(0, _clk_names[minor]);
+ if (!IS_ERR(eth_clk)){
+ clk_enable(eth_clk);
+ __clk[minor] = eth_clk;
+ }
+ }
+}
+
+static __inline__ void ks8001_hw_unreset(uint minor)
+{
+ volatile u32 dummy;
+ int mask = minor ? reset_ETH_2 : reset_ETH_1;
+ VI1888_SYSCTRL_MRST = VI1888_SYSCTRL_MRST | ~mask;
+ dummy = VI1888_SYSCTRL_MRST;
+ dummy = VI1888_SYSCTRL_MRST;
+ dummy = VI1888_SYSCTRL_MRST;
+ dummy = VI1888_SYSCTRL_MRST;
+ dummy = VI1888_SYSCTRL_MRST;
+ VI1888_SYSCTRL_MRST = VI1888_SYSCTRL_MRST & mask;
+ dummy = VI1888_SYSCTRL_MRST;
+ dummy = VI1888_SYSCTRL_MRST;
+ dummy = VI1888_SYSCTRL_MRST;
+ dummy = VI1888_SYSCTRL_MRST;
+ dummy = VI1888_SYSCTRL_MRST;
+ dummy = VI1888_SYSCTRL_MRST;
+ dummy = VI1888_SYSCTRL_MRST;
+}
+
+static __inline__ void ks8001_hw_set_speed(uint minor, uint is_100)
+{
+ if(is_100)
+ VI1888_SYSCTRL_CONFIG |= (1 << (2 * minor));
+ else
+ VI1888_SYSCTRL_CONFIG &= ~(1 << (2 * minor));
+}
+
+static __inline__ void ks8001_hw_cleanup(int minor)
+{
+ if(__clk[minor]){
+ struct clk * eth_clk = __clk[minor];
+ clk_disable(eth_clk);
+ clk_put(eth_clk);
+ __clk[minor] = NULL;
+ }
+}
+
+#define KS8001_HW_DEVICE_COUNT 2
+#ifdef KS8001_NEED_HW_DEVICE_TABLE
+static struct ks8001_device_table ks8001_hw_devices[] = {
+ {0, IO_ADDRESS(VI1888_Eth_1_BASE), VI1888_IRQ_EC_1, 0, {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF7}},
+ {1, IO_ADDRESS(VI1888_Eth_2_BASE), VI1888_IRQ_EC_2, 0, {0x00, 0x55, 0x7B, 0xB5, 0x7D, 0xF8}},
+};
+#endif
+#endif /*CONFIG_ARCH_VI1888_EVB */
+
+#endif
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/KS8001_mii.h b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_mii.h
new file mode 100644
index 0000000000..9397481301
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_mii.h
@@ -0,0 +1,349 @@
+#ifndef KS8001_mii_h
+#define KS8001_mii_h
+
+#define OFFSET_OUI 10
+#define OFFSET_MODEL 4
+
+/****** Organizationally Unique Identifier *****/
+#define OUI_ICS (0x00057D)
+#define OUI_MICREL (0x000885)
+#define OUI_JVA (0x00BEEF)
+#define OUI_REALTEK (0x000020)
+#define OUI_ICPLUS (0x0090C3)
+
+/********* Manufacture’s Model Number **********/
+
+#define MODEL_1893BF (0x04)
+#define MODEL_1893CF (0x05)
+#define MODEL_IP101A (0x05)
+#define MODEL_IP175C (0x18)
+#define MODEL_IP175D (0x19) // The REAL ID is the same as IP175C ... big shit. So we robe in ID.
+#define MODEL_KS8721 (0x21)
+#define MODEL_RTL8201CP (0x20)
+
+/********* Supported PHY ***********************/
+// Revision Number ignored
+enum phy_chipset_id {
+ // ICS list
+ ICS_1893BF = ((OUI_ICS << OFFSET_OUI) + (MODEL_1893BF << OFFSET_MODEL)),
+ ICS_1893CF = ((OUI_ICS << OFFSET_OUI) + (MODEL_1893CF << OFFSET_MODEL)),
+
+ // MICREL List
+ MICREL_KS8721 = ((OUI_MICREL << OFFSET_OUI) + (MODEL_KS8721 << OFFSET_MODEL)),
+
+ // REALTEK List
+ REALTEK_RTL8201CP = ((OUI_REALTEK << OFFSET_OUI) + (MODEL_RTL8201CP << OFFSET_MODEL)),
+
+ // IC+ list.
+ ICPLUS_IP101A = ((OUI_ICPLUS << OFFSET_OUI) + (MODEL_IP101A << OFFSET_MODEL)),
+ ICPLUS_IP175C = ((OUI_ICPLUS << OFFSET_OUI) + (MODEL_IP175C << OFFSET_MODEL)),
+ ICPLUS_IP175D = ((OUI_ICPLUS << OFFSET_OUI) + (MODEL_IP175D << OFFSET_MODEL)),
+
+ // JVA List
+ JVA_1893BF = ((OUI_JVA << OFFSET_OUI) + (MODEL_1893BF << OFFSET_MODEL))
+};
+
+/******************* ICS *********************/
+//specific regs
+#define MII_NEXTPAGE (0x07) //Autonegotiation Next Page
+#define MII_NEXTPAGELPA (0x08) //Autonegotiation Next Page Link Partner
+#define MII_EXCR (0x10) //Extended Control
+#define MII_QPDSR (0x11) //Quick Poll Detailed Status Register
+#define MII_EXCR2 (0x13) //Extended Control 2
+//QPDSR reg
+#define QPDSR_SPEED100 (0x8000)
+#define QPDSR_FULLDPLX (0x4000)
+#define QPDSR_AN_PMB2 (0x2000)
+#define QPDSR_AN_PMB1 (0x1000)
+#define QPDSR_AN_PMB0 (0x0800)
+#define QPDSR_100TX_LOST (0x0400)
+#define QPDSR_PLL_FAIL (0x0200)
+#define QPDSR_FALSE_CARRIER (0x0100)
+#define QPDSR_INV_SYM (0x0080)
+#define QPDSR_HALT_SYM (0x0040)
+#define QPDSR_PREM_END (0x0020)
+#define QPDSR_ANEGCOMPLETE (0x0010)
+#define QPDSR_100TX_DTCT (0x0008)
+#define QPDSR_JABBER_DTCT (0x0004)
+#define QPDSR_REM_FAULT (0x0002)
+#define QPDSR_LSTATUS (0x0001)
+
+
+/***************** MICREL *******************/
+//specific reg
+#define MII_PHYCTRL (0x1F)
+//PHYCTRL reg
+#define PHYCTRL_PAIRSWP_DIS (0x2000)
+#define PHYCTRL_ENERGY (0x1000)
+#define PHYCTRL_FORCE_LINK (0x0800)
+#define PHYCTRL_POW_SAVE (0x0400)
+#define PHYCTRL_INTR_HIGH (0x0200)
+#define PHYCTRL_EN_JABBER (0x0100)
+#define PHYCTRL_ANEGCOMPLETE (0x0080)
+#define PHYCTRL_EN_PAUSE (0x0040)
+#define PHYCTRL_PHY_ISOL (0x0020)
+#define PHYCTRL_OP_MODE (0x001C)
+#define PHYCTRL_EN_SQE_TEST (0x0002)
+#define PHYCTRL_DIS_DATA_SCR (0x0001)
+//PHYCTRL_OP_MODE values
+#define PHYCTRL_OM_ANEG (0x0 << 2)
+#define PHYCTRL_OM_10HALF (0x1 << 2)
+#define PHYCTRL_OM_100HALF (0x2 << 2)
+#define PHYCTRL_OM_DEFAULT (0x3 << 2)
+#define PHYCTRL_OM_RESERVED (0x4 << 2)
+#define PHYCTRL_OM_10FULL (0x5 << 2)
+#define PHYCTRL_OM_100FULL (0x6 << 2)
+#define PHYCTRL_OM_PHY_ISOL (0x7 << 2)
+
+/***************** ICPLUS_IP175D *******************/
+#define IP175D_VLAN_TABLE_SIZE 16
+#define IP175D_VLAN_TABLE_COMMON_PHY 5
+#define IP175D_VLAN_TABLE_NO_TAG_LINE 6
+
+/***************** ETHTOOL Section *******************/
+#define KS8001__OUI1 0
+#define KS8001__OUI2 1
+
+/***************** specific reg ICPLUS_IP175C *******************/
+enum {
+ ICPLUS_IP175C__BMSR_PHY0 = 2,
+ ICPLUS_IP175C__BMSR_PHY1,
+ ICPLUS_IP175C__BMSR_PHY2,
+ ICPLUS_IP175C__BMSR_PHY3,
+ ICPLUS_IP175C__BMSR_PHY4,
+
+ ICPLUS_IP175C__PHY29_MII18 = 7,
+ ICPLUS_IP175C__PHY29_MII19,
+ ICPLUS_IP175C__PHY29_MII20,
+ ICPLUS_IP175C__PHY29_MII21,
+ ICPLUS_IP175C__PHY29_MII22,
+ ICPLUS_IP175C__PHY29_MII23,
+ ICPLUS_IP175C__PHY29_MII24,
+ ICPLUS_IP175C__PHY29_MII25,
+ ICPLUS_IP175C__PHY29_MII26,
+ ICPLUS_IP175C__PHY29_MII27,
+ ICPLUS_IP175C__PHY29_MII28,
+ ICPLUS_IP175C__PHY29_MII29,
+ ICPLUS_IP175C__PHY29_MII30,
+ ICPLUS_IP175C__PHY29_MII31,
+
+ ICPLUS_IP175C__PHY30_MII0 = 31,
+ ICPLUS_IP175C__PHY30_MII1,
+ ICPLUS_IP175C__PHY30_MII2,
+ ICPLUS_IP175C__PHY30_MII3,
+ ICPLUS_IP175C__PHY30_MII4,
+ ICPLUS_IP175C__PHY30_MII5,
+ ICPLUS_IP175C__PHY30_MII6,
+ ICPLUS_IP175C__PHY30_MII7,
+ ICPLUS_IP175C__PHY30_MII8,
+ ICPLUS_IP175C__PHY30_MII9,
+ ICPLUS_IP175C__PHY30_MII10,
+ ICPLUS_IP175C__PHY30_MII11,
+ ICPLUS_IP175C__PHY30_MII12,
+ ICPLUS_IP175C__PHY30_MII13,
+ ICPLUS_IP175C__PHY30_MII14,
+ ICPLUS_IP175C__PHY30_MII15,
+ ICPLUS_IP175C__PHY30_MII16,
+ ICPLUS_IP175C__PHY30_MII17,
+ ICPLUS_IP175C__PHY30_MII18,
+ ICPLUS_IP175C__PHY30_MII19,
+ ICPLUS_IP175C__PHY30_MII20,
+ ICPLUS_IP175C__PHY30_MII21,
+ ICPLUS_IP175C__PHY30_MII22,
+ ICPLUS_IP175C__PHY30_MII23,
+ ICPLUS_IP175C__PHY30_MII24,
+ ICPLUS_IP175C__PHY30_MII25,
+ ICPLUS_IP175C__PHY30_MII26,
+ ICPLUS_IP175C__PHY30_MII27,
+ ICPLUS_IP175C__PHY30_MII28,
+ ICPLUS_IP175C__PHY30_MII29,
+ ICPLUS_IP175C__PHY30_MII30,
+ ICPLUS_IP175C__PHY30_MII31,
+
+ ICPLUS_IP175C__PHY31_MII0 = 63,
+ ICPLUS_IP175C__PHY31_MII1,
+ ICPLUS_IP175C__PHY31_MII2,
+ ICPLUS_IP175C__PHY31_MII3,
+ ICPLUS_IP175C__PHY31_MII4,
+ ICPLUS_IP175C__PHY31_MII5,
+ ICPLUS_IP175C__PHY31_MII6,
+};
+
+/***************** specific reg ICPLUS_IP175D *******************/
+enum {
+ ICPLUS_IP175D__BMSR_PHY0 = 2,
+ ICPLUS_IP175D__BMSR_PHY1,
+ ICPLUS_IP175D__BMSR_PHY2,
+ ICPLUS_IP175D__BMSR_PHY3,
+ ICPLUS_IP175D__BMSR_PHY4,
+
+ ICPLUS_IP175D__PHY20_MII0 = 7,
+ ICPLUS_IP175D__PHY20_MII2,
+ ICPLUS_IP175D__PHY20_MII3,
+ ICPLUS_IP175D__PHY20_MII4,
+ ICPLUS_IP175D__PHY20_MII5,
+ ICPLUS_IP175D__PHY20_MII6,
+ ICPLUS_IP175D__PHY20_MII7,
+ ICPLUS_IP175D__PHY20_MII8,
+ ICPLUS_IP175D__PHY20_MII9,
+ ICPLUS_IP175D__PHY20_MII10,
+ ICPLUS_IP175D__PHY20_MII11,
+ ICPLUS_IP175D__PHY20_MII12,
+ ICPLUS_IP175D__PHY20_MII13,
+ ICPLUS_IP175D__PHY20_MII14,
+ ICPLUS_IP175D__PHY20_MII15,
+ ICPLUS_IP175D__PHY20_MII16,
+ ICPLUS_IP175D__PHY20_MII17,
+ ICPLUS_IP175D__PHY20_MII18,
+ ICPLUS_IP175D__PHY20_MII19,
+ ICPLUS_IP175D__PHY20_MII20,
+ ICPLUS_IP175D__PHY20_MII21,
+ ICPLUS_IP175D__PHY20_MII22,
+ ICPLUS_IP175D__PHY20_MII24,
+
+ ICPLUS_IP175D__PHY21_MII0 = 30,
+ ICPLUS_IP175D__PHY21_MII1,
+ ICPLUS_IP175D__PHY21_MII2,
+ ICPLUS_IP175D__PHY21_MII3,
+ ICPLUS_IP175D__PHY21_MII4,
+ ICPLUS_IP175D__PHY21_MII5,
+ ICPLUS_IP175D__PHY21_MII6,
+ ICPLUS_IP175D__PHY21_MII7,
+ ICPLUS_IP175D__PHY21_MII8,
+ ICPLUS_IP175D__PHY21_MII9,
+ ICPLUS_IP175D__PHY21_MII10,
+ ICPLUS_IP175D__PHY21_MII12,
+ ICPLUS_IP175D__PHY21_MII14,
+ ICPLUS_IP175D__PHY21_MII15,
+ ICPLUS_IP175D__PHY21_MII16,
+ ICPLUS_IP175D__PHY21_MII17,
+ ICPLUS_IP175D__PHY21_MII18,
+ ICPLUS_IP175D__PHY21_MII19,
+ ICPLUS_IP175D__PHY21_MII20,
+ ICPLUS_IP175D__PHY21_MII21,
+ ICPLUS_IP175D__PHY21_MII22,
+ ICPLUS_IP175D__PHY21_MII23,
+ ICPLUS_IP175D__PHY21_MII24,
+ ICPLUS_IP175D__PHY21_MII25,
+
+ ICPLUS_IP175D__PHY22_MII0 = 54,
+ ICPLUS_IP175D__PHY22_MII1,
+ ICPLUS_IP175D__PHY22_MII2,
+ ICPLUS_IP175D__PHY22_MII3,
+ ICPLUS_IP175D__PHY22_MII4,
+ ICPLUS_IP175D__PHY22_MII5,
+ ICPLUS_IP175D__PHY22_MII6,
+ ICPLUS_IP175D__PHY22_MII7,
+ ICPLUS_IP175D__PHY22_MII8,
+ ICPLUS_IP175D__PHY22_MII9,
+ ICPLUS_IP175D__PHY22_MII10,
+ ICPLUS_IP175D__PHY22_MII11,
+ ICPLUS_IP175D__PHY22_MII12,
+ ICPLUS_IP175D__PHY22_MII13,
+ ICPLUS_IP175D__PHY22_MII14,
+ ICPLUS_IP175D__PHY22_MII15,
+ ICPLUS_IP175D__PHY22_MII16,
+ ICPLUS_IP175D__PHY22_MII17,
+ ICPLUS_IP175D__PHY22_MII18,
+ ICPLUS_IP175D__PHY22_MII19,
+ ICPLUS_IP175D__PHY22_MII20,
+ ICPLUS_IP175D__PHY22_MII21,
+ ICPLUS_IP175D__PHY22_MII22,
+ ICPLUS_IP175D__PHY22_MII23,
+ ICPLUS_IP175D__PHY22_MII24,
+ ICPLUS_IP175D__PHY22_MII25,
+ ICPLUS_IP175D__PHY22_MII26,
+ ICPLUS_IP175D__PHY22_MII27,
+ ICPLUS_IP175D__PHY22_MII28,
+ ICPLUS_IP175D__PHY22_MII29,
+
+ ICPLUS_IP175D__PHY23_MII0 = 84,
+ ICPLUS_IP175D__PHY23_MII1,
+ ICPLUS_IP175D__PHY23_MII2,
+ ICPLUS_IP175D__PHY23_MII3,
+ ICPLUS_IP175D__PHY23_MII4,
+ ICPLUS_IP175D__PHY23_MII5,
+ ICPLUS_IP175D__PHY23_MII6,
+ ICPLUS_IP175D__PHY23_MII7,
+ ICPLUS_IP175D__PHY23_MII8,
+ ICPLUS_IP175D__PHY23_MII9,
+ ICPLUS_IP175D__PHY23_MII10,
+ ICPLUS_IP175D__PHY23_MII11,
+ ICPLUS_IP175D__PHY23_MII12,
+ ICPLUS_IP175D__PHY23_MII13,
+ ICPLUS_IP175D__PHY23_MII14,
+ ICPLUS_IP175D__PHY23_MII15,
+ ICPLUS_IP175D__PHY23_MII16,
+ ICPLUS_IP175D__PHY23_MII17,
+ ICPLUS_IP175D__PHY23_MII18,
+ ICPLUS_IP175D__PHY23_MII19,
+ ICPLUS_IP175D__PHY23_MII20,
+ ICPLUS_IP175D__PHY23_MII21,
+ ICPLUS_IP175D__PHY23_MII22,
+ ICPLUS_IP175D__PHY23_MII23,
+ ICPLUS_IP175D__PHY23_MII24,
+ ICPLUS_IP175D__PHY23_MII25,
+ ICPLUS_IP175D__PHY23_MII26,
+ ICPLUS_IP175D__PHY23_MII27,
+ ICPLUS_IP175D__PHY23_MII28,
+ ICPLUS_IP175D__PHY23_MII29,
+ ICPLUS_IP175D__PHY23_MII30,
+ ICPLUS_IP175D__PHY23_MII31,
+
+ ICPLUS_IP175D__PHY24_MII0 = 116,
+ ICPLUS_IP175D__PHY24_MII1,
+ ICPLUS_IP175D__PHY24_MII2,
+ ICPLUS_IP175D__PHY24_MII3,
+
+ ICPLUS_IP175D__PHY25_MII0 = 120,
+ ICPLUS_IP175D__PHY25_MII1,
+ ICPLUS_IP175D__PHY25_MII2,
+ ICPLUS_IP175D__PHY25_MII3,
+ ICPLUS_IP175D__PHY25_MII4,
+ ICPLUS_IP175D__PHY25_MII5,
+ ICPLUS_IP175D__PHY25_MII6,
+ ICPLUS_IP175D__PHY25_MII7,
+ ICPLUS_IP175D__PHY25_MII8,
+ ICPLUS_IP175D__PHY25_MII9,
+ ICPLUS_IP175D__PHY25_MII10,
+ ICPLUS_IP175D__PHY25_MII11,
+ ICPLUS_IP175D__PHY25_MII12,
+ ICPLUS_IP175D__PHY25_MII13,
+ ICPLUS_IP175D__PHY25_MII14,
+ ICPLUS_IP175D__PHY25_MII15,
+ ICPLUS_IP175D__PHY25_MII16,
+ ICPLUS_IP175D__PHY25_MII17,
+ ICPLUS_IP175D__PHY25_MII18,
+ ICPLUS_IP175D__PHY25_MII19,
+ ICPLUS_IP175D__PHY25_MII20,
+ ICPLUS_IP175D__PHY25_MII21,
+ ICPLUS_IP175D__PHY25_MII22,
+ ICPLUS_IP175D__PHY25_MII23,
+
+ ICPLUS_IP175D__PHY26_MII0 = 144,
+ ICPLUS_IP175D__PHY26_MII1,
+ ICPLUS_IP175D__PHY26_MII2,
+ ICPLUS_IP175D__PHY26_MII3,
+ ICPLUS_IP175D__PHY26_MII4,
+ ICPLUS_IP175D__PHY26_MII5,
+ ICPLUS_IP175D__PHY26_MII6,
+ ICPLUS_IP175D__PHY26_MII7,
+ ICPLUS_IP175D__PHY26_MII8,
+ ICPLUS_IP175D__PHY26_MII9,
+ ICPLUS_IP175D__PHY26_MII10,
+ ICPLUS_IP175D__PHY26_MII11,
+ ICPLUS_IP175D__PHY26_MII12,
+ ICPLUS_IP175D__PHY26_MII13,
+ ICPLUS_IP175D__PHY26_MII14,
+ ICPLUS_IP175D__PHY26_MII15,
+ ICPLUS_IP175D__PHY26_MII16,
+ ICPLUS_IP175D__PHY26_MII17,
+ ICPLUS_IP175D__PHY26_MII18,
+ ICPLUS_IP175D__PHY26_MII19,
+ ICPLUS_IP175D__PHY26_MII20,
+ ICPLUS_IP175D__PHY26_MII21,
+ ICPLUS_IP175D__PHY26_MII22,
+ ICPLUS_IP175D__PHY26_MII23
+};
+
+#endif /* KS8001_mii_h */
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/KS8001_reg.h b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_reg.h
new file mode 100644
index 0000000000..11b77e823b
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_reg.h
@@ -0,0 +1,192 @@
+#include <asm/io.h>
+
+#ifndef __KS8001_REG_H__
+#define __KS8001_REG_H__
+
+#ifdef SYNOP_ETH_DEBUG
+#define debugp printk
+#else
+#define debugp(x, ...)
+#endif
+
+#include "KS8001_sys.h" /* System-dependent definitions */
+
+typedef struct SynopsysStruct /* Synopsys device data */
+{
+ u32 configBase; /* base address of Config registers */
+ u32 macBase; /* base address of MAC registers */
+ u32 dmaBase; /* base address of DMA registers */
+ u32 phyAddr; /* PHY device address on MII interface */
+} Synopsys;
+
+static void __inline__ SynopsysInit
+(
+ Synopsys *Dev, /* Device structure, must be allocated by caller */
+ u32 ConfigBase, /* Base address of Configuration registers */
+ u32 MacBase, /* Base address of MAC registers */
+ u32 DmaBase, /* Base address of DMA registers */
+ u32 PhyAddr /* PHY device address */
+){
+ Dev->configBase = ConfigBase;
+ Dev->macBase = MacBase;
+ Dev->dmaBase = DmaBase;
+ Dev->phyAddr = PhyAddr;
+}
+
+
+#include "KS8001_regdef.h"
+#define AUTOMATIC_PHY_RESOLUTION -1
+
+static u32 __inline__ SynopsysReadConfigReg( Synopsys *Dev, u32 Reg )
+{
+ u32 data;
+ data=__raw_readl(Dev->configBase+Reg);
+ //TR( KERN_DEBUG "SynopsysReadConfigReg(%02x)=%08x\n", Reg, data );
+ return data;
+}
+
+static void __inline__ SynopsysWriteConfigReg( Synopsys *Dev, u32 Reg, u32 Data )
+{
+ //TR( KERN_DEBUG "SynopsysWriteConfigReg(%02x,%08x)\n", Reg, Data );
+ __raw_writel(Data,Dev->configBase+Reg);
+}
+
+static void __inline__ SynopsysSetConfigReg( Synopsys *Dev, u32 Reg, u32 Data )
+{
+ u32 data;
+ data=__raw_readl(Dev->configBase+Reg);
+ data |= Data;
+ //TR( KERN_DEBUG "SynopsysSetConfigReg(%02x,%08x)=%08x\n", Reg, Data, data );
+ __raw_writel(data,Dev->configBase+Reg);
+}
+
+static void __inline__ SynopsysClearConfigReg( Synopsys *Dev, u32 Reg, u32 Data )
+{
+ u32 data;
+ data=__raw_readl(Dev->configBase+Reg);
+ data &= ~Data;
+ //TR( KERN_DEBUG "SynopsysClearConfigReg(%02x,%08x)=%08x\n", Reg, Data, data );
+ __raw_writel(data,Dev->configBase+Reg);
+}
+
+static u32 __inline__ SynopsysReadMacReg( Synopsys *Dev, u32 Reg )
+{
+ u32 data;
+ data=__raw_readl(Dev->macBase+Reg);
+ //TR( KERN_DEBUG "SynopsysReadMacReg(%02x)=%08x\n", Reg, data );
+ return data;
+}
+
+static void __inline__ SynopsysWriteMacReg( Synopsys *Dev, u32 Reg, u32 Data )
+{
+ //TR( KERN_DEBUG "SynopsysWriteMacReg(%02x,%08x)\n", Reg, Data );
+ __raw_writel(Data,Dev->macBase+Reg);
+}
+
+static void __inline__ SynopsysSetMacReg( Synopsys *Dev, u32 Reg, u32 Data )
+{
+ u32 data;
+ data=__raw_readl(Dev->macBase+Reg);
+ data |= Data;
+ //TR( KERN_DEBUG "SynopsysSetMacReg(%02x,%08x)=%08x\n", Reg, Data, data );
+ __raw_writel(data,Dev->macBase+Reg);
+}
+
+static void __inline__ SynopsysClearMacReg( Synopsys *Dev, u32 Reg, u32 Data )
+{
+ u32 data;
+ data=__raw_readl(Dev->macBase+Reg);
+ data &= ~Data;
+ //TR( KERN_DEBUG "SynopsysClearMacReg(%02x,%08x)=%08x\n", Reg, Data, data );
+ __raw_writel(data,Dev->macBase+Reg);
+}
+
+static u32 __inline__ SynopsysReadDmaReg( Synopsys *Dev, u32 Reg )
+{
+ u32 data;
+ data=__raw_readl(Dev->dmaBase+Reg);
+ //TR( KERN_DEBUG "SynopsysReadDmaReg(%02x)=%08x\n", Reg, data );
+ return data;
+}
+
+static void __inline__ SynopsysWriteDmaReg( Synopsys *Dev, u32 Reg, u32 Data )
+{
+ //TR( KERN_DEBUG "SynopsysWriteDmaReg(%02x,%08x)\n", Reg, Data );
+ __raw_writel(Data,Dev->dmaBase+Reg);
+}
+
+static void __inline__ SynopsysSetDmaReg( Synopsys *Dev, u32 Reg, u32 Data )
+{
+ u32 data;
+ data=__raw_readl(Dev->dmaBase+Reg);
+ data |= Data;
+ //TR( KERN_DEBUG "SynopsysSetDmaReg(%02x,%08x)=%08x\n", Reg, Data, data );
+ __raw_writel(data,Dev->dmaBase+Reg);
+}
+
+static void __inline__ SynopsysClearDmaReg( Synopsys *Dev, u32 Reg, u32 Data )
+{
+ u32 data;
+ data=__raw_readl(Dev->dmaBase+Reg);
+ data &= ~Data;
+ //TR( KERN_DEBUG "SynopsysClearDmaReg(%02x,%08x)=%08x\n", Reg, Data, data );
+ __raw_writel(data,Dev->dmaBase+Reg);
+}
+
+static u16 __inline__ SynopsysMiiReadPhy (Synopsys * Dev, u32 phyAddr, u8 Reg)
+{
+ u32 addr;
+ u16 data;
+
+ addr = ((phyAddr << GmiiDevShift) & GmiiDevMask) |
+ ((Reg << GmiiRegShift) & GmiiRegMask);
+
+ // Enable the phy clock and set the busy bit.
+ SynopsysWriteMacReg (Dev, GmacGmiiAddr, (addr | GmiiAppClk4 | GmiiBusy));
+
+ // Wait for busy bit to clear
+ while ((SynopsysReadMacReg (Dev, GmacGmiiAddr) & GmiiBusy) == GmiiBusy);
+
+ // Read the phy device data
+ data = SynopsysReadMacReg (Dev, GmacGmiiData) & 0xFFFF;
+
+ return data;
+}
+
+static u16 __inline__ SynopsysMiiRead (Synopsys * Dev, u8 Reg, s8 PhyAddr_forced)
+{
+ // If PhyAddr_forced is negative, use the PhyAddr detected
+ if (PhyAddr_forced < 0)
+ return SynopsysMiiReadPhy (Dev, Dev->phyAddr, Reg);
+ else
+ return SynopsysMiiReadPhy (Dev, PhyAddr_forced, Reg);
+}
+
+static void __inline__ SynopsysMiiWritePhy (Synopsys * Dev, u32 phyAddr, u8 Reg, u16 Data)
+{
+ u32 addr;
+
+ SynopsysWriteMacReg (Dev, GmacGmiiData, Data);
+ addr = ((phyAddr << GmiiDevShift) & GmiiDevMask) |
+ ((Reg << GmiiRegShift) & GmiiRegMask) | GmiiWrite;
+
+ // Enable the phy clock and set the busy bit.
+ SynopsysWriteMacReg (Dev, GmacGmiiAddr, (addr | GmiiAppClk4 | GmiiBusy));
+
+ // Wait for busy bit to clear
+ while ((SynopsysReadMacReg (Dev, GmacGmiiAddr) & GmiiBusy) == GmiiBusy);
+
+}
+
+static void __inline__ SynopsysMiiWrite (Synopsys * Dev, u8 Reg, u16 Data, s8 PhyAddr_forced)
+{
+ // If PhyAddr_forced is negative, use the PhyAddr detected
+ if (PhyAddr_forced <= 0)
+ SynopsysMiiWritePhy (Dev, Dev->phyAddr, Reg, Data);
+ else
+ SynopsysMiiWritePhy (Dev, PhyAddr_forced, Reg, Data);
+}
+
+#endif /* __KS8001_REG_H__ */
+
+
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/KS8001_regdef.h b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_regdef.h
new file mode 100644
index 0000000000..510e97362c
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_regdef.h
@@ -0,0 +1,526 @@
+#ifndef __KS8001_REGDEF_H__
+#define __KS8001_REGDEF_H__
+
+enum GmacRegisters /* GMAC registers, base address is BAR+GmacRegistersBase */
+{
+ GmacConfig = 0x00, /* config */
+ GmacFrameFilter = 0x04, /* frame filter */
+ GmacHashHigh = 0x08, /* multi-cast hash table high */
+ GmacHashLow = 0x0C, /* multi-cast hash table low */
+ GmacGmiiAddr = 0x10, /* GMII address */
+ GmacGmiiData = 0x14, /* GMII data */
+ GmacFlowControl = 0x18, /* Flow control */
+ GmacVlan = 0x1C, /* VLAN tag */
+ GmacVersion = 0x20, /* Version of Gmac */
+ GmacIntStatus = 0x38, /* Gmac interupt status */
+ GmacIntMask = 0x3C, /* Gmac interupt status */
+ GmacAddr0High = 0x40, /* address0 high */
+ GmacAddr0Low = 0x44, /* address0 low */
+ GmacAddr1High = 0x48, /* address1 high */
+ GmacAddr1Low = 0x4C, /* address1 low */
+ GmacAddr2High = 0x50, /* address2 high */
+ GmacAddr2Low = 0x54, /* address2 low */
+ GmacAddr3High = 0x58, /* address3 high */
+ GmacAddr3Low = 0x5C, /* address3 low */
+ GmacAddr4High = 0x60, /* address4 high */
+ GmacAddr4Low = 0x64, /* address4 low */
+ GmacAddr5High = 0x68, /* address5 high */
+ GmacAddr5Low = 0x6C, /* address5 low */
+ GmacAddr6High = 0x70, /* address6 high */
+ GmacAddr6Low = 0x74, /* address6 low */
+ GmacAddr7High = 0x78, /* address7 high */
+ GmacAddr7Low = 0x7C, /* address7 low */
+ GmacAddr8High = 0x80, /* address8 high */
+ GmacAddr8Low = 0x84, /* address8 low */
+ GmacAddr9High = 0x88, /* address9 high */
+ GmacAddr9Low = 0x8C, /* address9 low */
+ GmacAddr10High = 0x90, /* address10 high */
+ GmacAddr10Low = 0x94, /* address10 low */
+ GmacAddr11High = 0x98, /* address11 high */
+ GmacAddr11Low = 0x9C, /* address11 low */
+ GmacAddr12High = 0xA0, /* address12 high */
+ GmacAddr12Low = 0xA4, /* address12 low */
+ GmacAddr13High = 0xA8, /* address13 high */
+ GmacAddr13Low = 0xAC, /* address13 low */
+ GmacAddr14High = 0xB0, /* address14 high */
+ GmacAddr14Low = 0xB4, /* address14 low */
+ GmacAddr15High = 0xB8, /* address15 high */
+ GmacAddr15Low = 0xBC, /* address15 low */
+ /* AN registers */
+ GmacANControl = 0xC0, /* AN Control */
+ GmacANStatus = 0xC4, /* AN Status */
+ GmacANAdwert = 0xC8, /* AN Advertisement */
+ GmacANLPA = 0xCC, /* AN Link Partner Abilitye */
+ GmacANExpansion = 0xD0, /* AN Expansion */
+};
+
+enum DmaRegisters /* DMA engine registers, base address is BAR+DmaRegistersBase */
+{
+ DmaBusMode = 0x00, /* CSR0 - Bus Mode */
+ DmaTxPollDemand = 0x04, /* CSR1 - Transmit Poll Demand */
+ DmaRxPollDemand = 0x08, /* CSR2 - Receive Poll Demand */
+ DmaRxBaseAddr = 0x0C, /* CSR3 - Receive list base address */
+ DmaTxBaseAddr = 0x10, /* CSR4 - Transmit list base address */
+ DmaStatus = 0x14, /* CSR5 - Dma status */
+ DmaControl = 0x18, /* CSR6 - Dma control */
+ DmaInterrupt = 0x1C, /* CSR7 - Interrupt enable */
+ DmaMissedFr = 0x20, /* CSR8 - Missed Frame Counter */
+ DmaTxCurrDesc = 0x48, /* CSR20 - Current host transmit buffer address */
+ DmaRxCurrDesc = 0x4C, /* CSR20 - Current host transmit buffer address */
+ DmaTxCurrBuff = 0x50, /* CSR21 - Current host receive buffer address */
+ DmaRxCurrBuff = 0x54, /* CSR21 - Current host receive buffer address */
+
+ //DmaTxCurrAddr = 0x50, /* CSR20 - Current host transmit buffer address */
+ //DmaRxCurrAddr = 0x54, /* CSR21 - Current host receive buffer address */
+};
+
+/**********************************************************
+ * GMAC Network interface registers
+ **********************************************************/
+
+enum GmacConfigReg /* GMAC Config register layout */
+{ /* Bit description R/W Reset value */
+ GmacWatchdogDisable = 0x00800000, /* Disable watchdog timer RW */
+ GmacWatchdogEnable = 0, /* Enable watchdog timer 0 */
+
+ GmacJabberDisable = 0x00400000, /* Disable jabber timer RW */
+ GmacJabberEnable = 0, /* Enable jabber timer 0 */
+
+ GmacFrameBurstEnable = 0x00200000, /* Enable frame bursting RW */
+ GmacFrameBurstDisable = 0, /* Disable frame bursting 0 */
+
+ GmacJumboFrameEnable = 0x00100000, /* Enable jumbo frame RW */
+ GmacJumboFrameDisable = 0, /* Disable jumbo frame 0 */
+
+// CHANGE: Added on 07/28 SNPS
+ GmacInterFrameGap7 = 0x000E0000, /* IFG Config7 - 40 bit times RW 000 */
+ GmacInterFrameGap6 = 0x000C0000, /* IFG Config6 - 48 bit times */
+ GmacInterFrameGap5 = 0x000A0000, /* IFG Config5 - 56 bit times */
+ GmacInterFrameGap4 = 0x00080000, /* IFG Config4 - 64 bit times */
+ GmacInterFrameGap3 = 0x00040000, /* IFG Config3 - 72 bit times */
+ GmacInterFrameGap2 = 0x00020000, /* IFG Config2 - 80 bit times */
+ GmacInterFrameGap1 = 0x00010000, /* IFG Config1 - 88 bit times */
+ GmacInterFrameGap0 = 000, /* IFG Config0 - 96 bit times */
+
+ GmacSelectMii = 0x00008000, /* Select MII mode RW */
+ GmacSelectGmii = 0, /* Select GMII mode 0 */
+
+// CHANGE: Commented as Endian mode is not register configurable
+// GmacBigEndian = 0x00004000, /* Big endian mode RW */
+// GmacLittleEndian = 0, /* Little endian 0 */
+
+ GmacDisableRxOwn = 0x00002000, /* Disable receive own packets RW */
+ GmacEnableRxOwn = 0, /* Enable receive own packets 0 */
+
+ GmacLoopbackOn = 0x00001000, /* Loopback mode RW */
+ GmacLoopbackOff = 0, /* Normal mode 0 */
+
+ GmacFullDuplex = 0x00000800, /* Full duplex mode RW */
+ GmacHalfDuplex = 0, /* Half duplex mode 0 */
+
+ GmacRetryDisable = 0x00000200, /* Disable retransmission RW */
+ GmacRetryEnable = 0, /* Enable retransmission 0 */
+
+// CHANGE: Commented as Pad / CRC strip is one single bit
+// GmacPadStripEnable = 0x00000100, /* Pad stripping enable RW */
+// GmacPadStripDisable = 0, /* Pad stripping disable 0 */
+
+// CHANGE: 07/28 renamed GmacCrcStrip* GmacPadCrcStrip*
+ GmacPadCrcStripEnable = 0x00000080, /* Pad / Crc stripping enable RW */
+ GmacPadCrcStripDisable = 0, /* Pad / Crc stripping disable 0 */
+
+ GmacBackoffLimit3 = 0x00000060, /* Back-off limit RW */
+ GmacBackoffLimit2 = 0x00000040, /* */
+ GmacBackoffLimit1 = 0x00000020, /* */
+ GmacBackoffLimit0 = 00, /* 00 */
+
+ GmacDeferralCheckEnable = 0x00000010, /* Deferral check enable RW */
+ GmacDeferralCheckDisable = 0, /* Deferral check disable 0 */
+
+ GmacTxEnable = 0x00000008, /* Transmitter enable RW */
+ GmacTxDisable = 0, /* Transmitter disable 0 */
+
+ GmacRxEnable = 0x00000004, /* Receiver enable RW */
+ GmacRxDisable = 0, /* Receiver disable 0 */
+};
+
+enum GmacFrameFilterReg /* GMAC frame filter register layout */
+{
+ GmacFilterOff = 0x80000000, /* Receive all incoming packets RW */
+ GmacFilterOn = 0, /* Receive filtered packets only 0 */
+
+// CHANGE: Added on 07/28 SNPS
+ GmacSrcAddrFilterEnable = 0x00000200, /* Source Address Filter enable RW */
+ GmacSrcAddrFilterDisable = 0, /* 0 */
+
+// CHANGE: Added on 07/28 SNPS
+ GmacSrcInvAddrFilterEn = 0x00000100, /* Inverse Source Address Filter enable RW */
+ GmacSrcInvAddrFilterDis = 0, /* 0 */
+
+// CHANGE: Changed the control frame config (07/28)
+ GmacPassControl3 = 0x000000C0, /* Forwards control frames that pass AF RW */
+ GmacPassControl2 = 0x00000080, /* Forwards all control frames */
+ GmacPassControl1 = 0x00000040, /* Does not pass control frames */
+ GmacPassControl0 = 00, /* Does not pass control frames 00 */
+
+ GmacBroadcastDisable = 0x00000020, /* Disable reception of broadcast frames RW */
+ GmacBroadcastEnable = 0, /* Enable broadcast frames 0 */
+
+ GmacMulticastFilterOff = 0x00000010, /* Pass all multicast packets RW */
+ GmacMulticastFilterOn = 0, /* Pass filtered multicast packets 0 */
+
+// CHANGE: Changed to Dest Addr Filter Inverse (07/28)
+ GmacDestAddrFilterInv = 0x00000008, /* Inverse filtering for DA RW */
+ GmacDestAddrFilterNor = 0, /* Normal filtering for DA 0 */
+
+// CHANGE: Changed to Multicast Hash filter (07/28)
+ GmacMcastHashFilterOn = 0x00000004, /* perfom multicast hash filtering RW */
+ GmacMcastHashFilterOff = 0, /* perfect filtering only 0 */
+
+// CHANGE: Changed to Unicast Hash filter (07/28)
+ GmacUcastHashFilterOn = 0x00000002, /* Unicast Hash filtering only RW */
+ GmacUcastHashFilterOff = 0, /* perfect filtering only 0 */
+
+ GmacPromiscuousModeOn = 0x00000001, /* Receive all valid packets RW */
+ GmacPromiscuousModeOff = 0, /* Receive filtered packets only 0 */
+};
+
+enum GmacGmiiAddrReg /* GMII address register layout */
+{
+ GmiiDevMask = 0x0000F800, /* GMII device address */
+ GmiiDevShift = 11,
+
+ GmiiRegMask = 0x000007C0, /* GMII register */
+ GmiiRegShift = 6,
+
+// CHANGED: 3-bit config instead of older 2-bit (07/28)
+ GmiiAppClk5 = 0x00000014, /* Application Clock Range 250-300 MHz */
+ GmiiAppClk4 = 0x00000010, /* 150-250 MHz */
+ GmiiAppClk3 = 0x0000000C, /* 35-60 MHz */
+ GmiiAppClk2 = 0x00000008, /* 20-35 MHz */
+ GmiiAppClk1 = 0x00000004, /* 100-150 MHz */
+ GmiiAppClk0 = 00, /* 60-100 MHz */
+
+ GmiiWrite = 0x00000002, /* Write to register */
+ GmiiRead = 0, /* Read from register */
+
+ GmiiBusy = 0x00000001, /* GMII interface is busy */
+};
+
+enum GmacGmiiDataReg /* GMII address register layout */
+{
+ GmiiDataMask = 0x0000FFFF, /* GMII Data */
+};
+
+enum GmacFlowControlReg /* GMAC flow control register layout */
+{ /* Bit description R/W Reset value */
+ GmacPauseTimeMask = 0xFFFF0000, /* PAUSE TIME field in the control frame RW 0000 */
+ GmacPauseTimeShift = 16,
+
+// CHANGED: Added on (07/28)
+ GmacPauseLowThresh3 = 0x00000030, /* threshold for pause tmr 256 slot time RW 00 */
+ GmacPauseLowThresh2 = 0x00000020, /* 144 slot time */
+ GmacPauseLowThresh1 = 0x00000010, /* 28 slot time */
+ GmacPauseLowThresh0 = 00, /* 4 slot time */
+
+ GmacUnicastPauseFrameOn = 0x00000008, /* Detect pause frame with unicast addr. RW */
+ GmacUnicastPauseFrameOff = 0, /* Detect only pause frame with multicast addr. 0 */
+
+ GmacRxFlowControlEnable = 0x00000004, /* Enable Rx flow control RW */
+ GmacRxFlowControlDisable = 0, /* Disable Rx flow control 0 */
+
+ GmacTxFlowControlEnable = 0x00000002, /* Enable Tx flow control RW */
+ GmacTxFlowControlDisable = 0, /* Disable flow control 0 */
+
+ GmacSendPauseFrame = 0x00000001, /* send pause frame RW 0 */
+};
+
+enum GmacAN {
+ GmacANCLoopback = (1<<14),
+ GmacANCEnable = (1<<12),
+ GmacANCRestart = (1<<9),
+ GmacANSComplete = (1<<5),
+ GmacANSLink = (1<<2),
+ GmacANAHalfDuplex = (1<<6),
+ GmacANAFullDuplex = (1<<5),
+};
+
+
+/**********************************************************
+ * DMA Engine registers
+ **********************************************************/
+
+enum DmaBusModeReg /* DMA bus mode register */
+{ /* Bit description R/W Reset value */
+// CHANGED: Commented as not applicable (07/28)
+// DmaBigEndianDesc = 0x00100000, /* Big endian data buffer descriptors RW */
+// DmaLittleEndianDesc = 0, /* Little endian data descriptors 0 */
+
+// CHANGED: Added on 07/28
+ DmaFixedBurstEnable = 0x00010000, /* Fixed Burst SINGLE, INCR4, INCR8 or INCR16 */
+ DmaFixedBurstDisable = 0, /* SINGLE, INCR 0 */
+
+ DmaBurstLength32 = 0x00002000, /* Dma burst length = 32 RW */
+ DmaBurstLength16 = 0x00001000, /* Dma burst length = 16 */
+ DmaBurstLength8 = 0x00000800, /* Dma burst length = 8 */
+ DmaBurstLength4 = 0x00000400, /* Dma burst length = 4 */
+ DmaBurstLength2 = 0x00000200, /* Dma burst length = 2 */
+ DmaBurstLength1 = 0x00000100, /* Dma burst length = 1 */
+ DmaBurstLength0 = 0x00000000, /* Dma burst length = 0 0 */
+
+// CHANGED: Commented as not applicable (07/28)
+// DmaBigEndianData = 0x00000080, /* Big endian data buffers RW */
+// DmaLittleEndianData = 0, /* Little endian data buffers 0 */
+
+ DmaDescriptorSkip16 = 0x00000040, /* number of dwords to skip RW */
+ DmaDescriptorSkip8 = 0x00000020, /* between two unchained descriptors */
+ DmaDescriptorSkip4 = 0x00000010, /* */
+ DmaDescriptorSkip2 = 0x00000008, /* */
+ DmaDescriptorSkip1 = 0x00000004, /* */
+ DmaDescriptorSkip0 = 0, /* 0 */
+
+ DmaResetOn = 0x00000001, /* Reset DMA engine RW */
+ DmaResetOff = 0, /* 0 */
+};
+
+enum DmaStatusReg /* DMA Status register */
+{ /* Bit description R/W Reset value */
+// CHANGED: Added on 07/28
+ DmaLineIntfIntr = 0x04000000, /* Line interface interrupt R 0 */
+// CHANGED: Added on 07/28
+ DmaErrorBit2 = 0x02000000, /* err. 0-data buffer, 1-desc. access R 0 */
+ DmaErrorBit1 = 0x01000000, /* err. 0-write trnsf, 1-read transfr R 0 */
+ DmaErrorBit0 = 0x00800000, /* err. 0-Rx DMA, 1-Tx DMA R 0 */
+
+ DmaTxState = 0x00700000, /* Transmit process state R 000 */
+ DmaTxStopped = 0x00000000, /* Stopped */
+ DmaTxFetching = 0x00100000, /* Running - fetching the descriptor */
+ DmaTxWaiting = 0x00200000, /* Running - waiting for end of transmission */
+ DmaTxReading = 0x00300000, /* Running - reading the data from memory */
+ DmaTxSuspended = 0x00600000, /* Suspended */
+ DmaTxClosing = 0x00700000, /* Running - closing descriptor */
+
+ DmaRxState = 0x000E0000, /* Receive process state R 000 */
+ DmaRxStopped = 0x00000000, /* Stopped */
+ DmaRxFetching = 0x00020000, /* Running - fetching the descriptor */
+// CHANGED: Commented as not applicable (07/28)
+// DmaRxChecking = 0x00040000, /* Running - checking for end of packet */
+ DmaRxWaiting = 0x00060000, /* Running - waiting for packet */
+ DmaRxSuspended = 0x00080000, /* Suspended */
+ DmaRxClosing = 0x000A0000, /* Running - closing descriptor */
+// CHANGED: Commented as not applicable (07/28)
+// DmaRxFlushing = 0x000C0000, /* Running - flushing the current frame */
+ DmaRxQueuing = 0x000E0000, /* Running - queuing the recieve frame into host memory */
+
+ DmaIntNormal = 0x00010000, /* Normal interrupt summary RW 0 */
+ DmaIntAbnormal = 0x00008000, /* Abnormal interrupt summary RW 0 */
+
+ DmaIntEarlyRx = 0x00004000, /* Early receive interrupt (Normal) RW 0 */
+ DmaIntBusError = 0x00002000, /* Fatal bus error (Abnormal) RW 0 */
+ DmaIntEarlyTx = 0x00000400, /* Early transmit interrupt (Abnormal) RW 0 */
+ DmaIntRxWdogTO = 0x00000200, /* Receive Watchdog Timeout (Abnormal) RW 0 */
+ DmaIntRxStopped = 0x00000100, /* Receive process stopped (Abnormal) RW 0 */
+ DmaIntRxNoBuffer = 0x00000080, /* Receive buffer unavailable (Abnormal) RW 0 */
+ DmaIntRxCompleted = 0x00000040, /* Completion of frame reception (Normal) RW 0 */
+ DmaIntTxUnderflow = 0x00000020, /* Transmit underflow (Abnormal) RW 0 */
+// CHANGED: Added on 07/28
+ DmaIntRcvOverflow = 0x00000010, /* Receive Buffer overflow interrupt RW 0 */
+ DmaIntTxJabberTO = 0x00000008, /* Transmit Jabber Timeout (Abnormal) RW 0 */
+ DmaIntTxNoBuffer = 0x00000004, /* Transmit buffer unavailable (Normal) RW 0 */
+ DmaIntTxStopped = 0x00000002, /* Transmit process stopped (Abnormal) RW 0 */
+ DmaIntTxCompleted = 0x00000001, /* Transmit completed (Normal) RW 0 */
+};
+
+enum DmaControlReg /* DMA control register */
+{ /* Bit description R/W Reset value */
+ DmaStoreAndForward = 0x00200000, /* Store and forward RW 0 */
+ DmaTxStart = 0x00002000, /* Start/Stop transmission RW 0 */
+// CHANGED: Added on 07/28
+ DmaFwdErrorFrames = 0x00000080, /* Forward error frames RW 0 */
+ DmaFwdUnderSzFrames = 0x00000040, /* Forward undersize frames RW 0 */
+ DmaTxSecondFrame = 0x00000004, /* Operate on second frame RW 0 */
+ DmaRxStart = 0x00000002, /* Start/Stop reception RW 0 */
+};
+
+enum DmaInterruptReg /* DMA interrupt enable register */
+{ /* Bit description R/W Reset value */
+ DmaIeNormal = DmaIntNormal , /* Normal interrupt enable RW 0 */
+ DmaIeAbnormal = DmaIntAbnormal , /* Abnormal interrupt enable RW 0 */
+
+ DmaIeEarlyRx = DmaIntEarlyRx , /* Early receive interrupt enable RW 0 */
+ DmaIeBusError = DmaIntBusError , /* Fatal bus error enable RW 0 */
+ DmaIeEarlyTx = DmaIntEarlyTx , /* Early transmit interrupt enable RW 0 */
+ DmaIeRxWdogTO = DmaIntRxWdogTO , /* Receive Watchdog Timeout enable RW 0 */
+ DmaIeRxStopped = DmaIntRxStopped , /* Receive process stopped enable RW 0 */
+ DmaIeRxNoBuffer = DmaIntRxNoBuffer , /* Receive buffer unavailable enable RW 0 */
+ DmaIeRxCompleted = DmaIntRxCompleted, /* Completion of frame reception enable RW 0 */
+ DmaIeTxUnderflow = DmaIntTxUnderflow, /* Transmit underflow enable RW 0 */
+// CHANGED: Added on 07/28
+ DmaIeRxOverflow = DmaIntRcvOverflow, /* Receive Buffer overflow interrupt RW 0 */
+ DmaIeTxJabberTO = DmaIntTxJabberTO , /* Transmit Jabber Timeout enable RW 0 */
+ DmaIeTxNoBuffer = DmaIntTxNoBuffer , /* Transmit buffer unavailable enable RW 0 */
+ DmaIeTxStopped = DmaIntTxStopped , /* Transmit process stopped enable RW 0 */
+ DmaIeTxCompleted = DmaIntTxCompleted, /* Transmit completed enable RW 0 */
+};
+
+/**********************************************************
+ * DMA Engine descriptors
+ **********************************************************/
+
+enum DmaDescriptorStatus /* status word of DMA descriptor */
+{
+ DescOwnByDma = 0x80000000, /* Descriptor is owned by DMA engine */
+// CHANGED: Added on 07/29
+ DescDAFilterFail = 0x40000000, /* Rx - DA Filter Fail for the received frame E */
+ DescFrameLengthMask = 0x3FFF0000, /* Receive descriptor frame length */
+ DescFrameLengthShift = 16,
+
+ DescError = 0x00008000, /* Error summary bit - OR of the following bits: v */
+
+ DescRxTruncated = 0x00004000, /* Rx - no more descriptors for receive frame E */
+// CHANGED: Added on 07/29
+ DescSAFilterFail = 0x00002000, /* Rx - SA Filter Fail for the received frame E */
+/* added by reyaz */
+ DescRxLengthError = 0x00001000, /* Rx - frame size not matching with length field E */
+ DescRxDamaged = 0x00000800, /* Rx - frame was damaged due to buffer overflow E */
+// CHANGED: Added on 07/29
+ DescRxVLANTag = 0x00000400, /* Rx - received frame is a VLAN frame I */
+ DescRxFirst = 0x00000200, /* Rx - first descriptor of the frame I */
+ DescRxLast = 0x00000100, /* Rx - last descriptor of the frame I */
+ DescRxLongFrame = 0x00000080, /* Rx - frame is longer than 1518 bytes E */
+ DescRxCollision = 0x00000040, /* Rx - late collision occurred during reception E */
+ DescRxFrameEther = 0x00000020, /* Rx - Frame type - Ethernet, otherwise 802.3 */
+ DescRxWatchdog = 0x00000010, /* Rx - watchdog timer expired during reception E */
+ DescRxMiiError = 0x00000008, /* Rx - error reported by MII interface E */
+ DescRxDribbling = 0x00000004, /* Rx - frame contains noninteger multiple of 8 bits */
+ DescRxCrc = 0x00000002, /* Rx - CRC error E */
+
+ DescTxTimeout = 0x00004000, /* Tx - Transmit jabber timeout E */
+// CHANGED: Added on 07/29
+ DescTxFrameFlushed = 0x00002000, /* Tx - DMA/MTL flushed the frame due to SW flush I */
+ DescTxLostCarrier = 0x00000800, /* Tx - carrier lost during tramsmission E */
+ DescTxNoCarrier = 0x00000400, /* Tx - no carrier signal from the tranceiver E */
+ DescTxLateCollision = 0x00000200, /* Tx - transmission aborted due to collision E */
+ DescTxExcCollisions = 0x00000100, /* Tx - transmission aborted after 16 collisions E */
+ DescTxVLANFrame = 0x00000080, /* Tx - VLAN-type frame */
+ DescTxCollMask = 0x00000078, /* Tx - Collision count */
+ DescTxCollShift = 3,
+ DescTxExcDeferral = 0x00000004, /* Tx - excessive deferral E */
+ DescTxUnderflow = 0x00000002, /* Tx - late data arrival from the memory E */
+ DescTxDeferred = 0x00000001, /* Tx - frame transmision deferred */
+};
+
+enum DmaDescriptorLength /* length word of DMA descriptor */
+{
+ DescTxIntEnable = 0x80000000, /* Tx - interrupt on completion */
+ DescTxLast = 0x40000000, /* Tx - Last segment of the frame */
+ DescTxFirst = 0x20000000, /* Tx - First segment of the frame */
+ DescTxDisableCrc = 0x04000000, /* Tx - Add CRC disabled (first segment only) */
+
+ DescEndOfRing = 0x02000000, /* End of descriptors ring */
+ DescChain = 0x01000000, /* Second buffer address is chain address */
+ DescTxDisablePadd = 0x00800000, /* disable padding, added by - reyaz */
+
+ DescSize2Mask = 0x003FF800, /* Buffer 2 size */
+ DescSize2Shift = 11,
+ DescSize1Mask = 0x000007FF, /* Buffer 1 size */
+ DescSize1Shift = 0,
+};
+
+/**********************************************************
+ * Initial register values
+ **********************************************************/
+
+enum InitialRegisters
+{
+ GmacConfigInitFdx1000 /* Full-duplex mode with perfect filter on */
+ = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable
+// CHANGED: Removed Endian configuration, added single bit config for PAD/CRC strip,
+ | GmacSelectGmii | GmacEnableRxOwn | GmacLoopbackOff
+ | GmacFullDuplex | GmacRetryEnable | GmacPadCrcStripDisable
+ | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable,
+
+ GmacConfigInitFdx110 /* Full-duplex mode with perfect filter on */
+ = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable
+// CHANGED: Removed Endian configuration, added single bit config for PAD/CRC strip,
+ | GmacSelectMii | GmacEnableRxOwn | GmacLoopbackOff
+ //| GmacSelectMii | GmacLoopbackOff
+ | GmacFullDuplex | GmacRetryEnable | GmacPadCrcStripDisable
+ | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable,
+
+ GmacFrameFilterInitFdx /* Full-duplex mode */
+// CHANGED: Pass control config, dest addr filter normal, added source address filter, multicast & unicast
+// Hash filter.
+ = GmacFilterOn | GmacPassControl0 | GmacBroadcastEnable | GmacSrcAddrFilterDisable
+/* = GmacFilterOff | GmacPassControlOff | GmacBroadcastEnable */
+ | GmacMulticastFilterOn | GmacDestAddrFilterNor | GmacMcastHashFilterOff
+ | GmacPromiscuousModeOff | GmacUcastHashFilterOff,
+
+ GmacFlowControlInitFdx /* Full-duplex mode */
+ = GmacUnicastPauseFrameOff | GmacRxFlowControlEnable | GmacTxFlowControlEnable,
+ //= GmacUnicastPauseFrameOff | GmacRxFlowControlDisable | GmacTxFlowControlDisable,
+
+ GmacGmiiAddrInitFdx /* Full-duplex mode */
+ = GmiiAppClk3,
+
+ GmacConfigInitHdx1000 /* Half-duplex mode with perfect filter on */
+ = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable
+// CHANGED: Removed Endian configuration, added single bit config for PAD/CRC strip,
+ /*| GmacSelectMii | GmacLittleEndian | GmacDisableRxOwn | GmacLoopbackOff*/
+ | GmacSelectGmii | GmacDisableRxOwn | GmacLoopbackOff
+ | GmacHalfDuplex | GmacRetryEnable | GmacPadCrcStripDisable
+ | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable,
+
+ GmacConfigInitHdx110 /* Half-duplex mode with perfect filter on */
+ = GmacWatchdogEnable | GmacJabberEnable | GmacFrameBurstEnable | GmacJumboFrameDisable
+// CHANGED: Removed Endian configuration, added single bit config for PAD/CRC strip,
+ | GmacSelectMii | GmacLoopbackOff
+ | GmacHalfDuplex | GmacRetryEnable | GmacPadCrcStripDisable
+ | GmacBackoffLimit0 | GmacDeferralCheckDisable | GmacTxEnable | GmacRxEnable,
+
+ GmacFrameFilterInitHdx /* Half-duplex mode */
+ = GmacFilterOn | GmacPassControl0 | GmacBroadcastEnable | GmacSrcAddrFilterDisable
+ | GmacMulticastFilterOn | GmacDestAddrFilterNor | GmacMcastHashFilterOff
+ | GmacUcastHashFilterOff| GmacPromiscuousModeOff,
+
+ GmacFlowControlInitHdx /* Half-duplex mode */
+ = GmacUnicastPauseFrameOff | GmacRxFlowControlDisable | GmacTxFlowControlDisable,
+
+ GmacGmiiAddrInitHdx /* Half-duplex mode */
+ = GmiiAppClk3,
+
+ DmaBusModeInit /* Little-endian mode */
+// CHANGED: Removed Endian configuration
+ //= DmaFixedBurstEnable | DmaBurstLength8 | DmaDescriptorSkip2 | DmaResetOff,
+
+ //= DmaFixedBurstEnable | DmaResetOff,
+ = DmaFixedBurstEnable | DmaBurstLength8 | DmaResetOff,
+
+ DmaControlInit1000 /* 1000 Mb/s mode */
+ = DmaStoreAndForward | DmaTxSecondFrame ,
+
+ DmaControlInit100 /* 100 Mb/s mode */
+ = DmaStoreAndForward,
+
+ DmaControlInit10 /* 10 Mb/s mode */
+ = DmaStoreAndForward,
+
+ /* Interrupt groups */
+ DmaIntErrorMask = DmaIntBusError, /* Error */
+ DmaIntRxAbnMask = DmaIntRxNoBuffer, /* receiver abnormal interrupt */
+ DmaIntRxNormMask = DmaIntRxCompleted, /* receiver normal interrupt */
+ DmaIntRxStoppedMask = DmaIntRxStopped, /* receiver stopped */
+ DmaIntTxAbnMask = DmaIntTxUnderflow, /* transmitter abnormal interrupt */
+ DmaIntTxNormMask = DmaIntTxCompleted|DmaIntTxNoBuffer, /* transmitter normal interrupt */
+ DmaIntTxStoppedMask = DmaIntTxStopped, /* receiver stopped */
+ DmaIntMask = DmaIntErrorMask
+ | DmaIntRxAbnMask | DmaIntRxNormMask | DmaIntRxStoppedMask
+ | DmaIntTxAbnMask | DmaIntTxNormMask | DmaIntTxStoppedMask,
+
+ DmaIntEnable = DmaIeNormal | DmaIeAbnormal | DmaIntErrorMask
+ | DmaIntRxAbnMask | DmaIntRxNormMask | DmaIntRxStoppedMask
+ | DmaIntTxAbnMask | DmaIntTxNormMask | DmaIntTxStoppedMask,
+ DmaIntDisable = 0,
+};
+
+#endif /* __KS8001_REGDEF_H__ */
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/KS8001_sys.h b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_sys.h
new file mode 100644
index 0000000000..8b6a05c4f2
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/KS8001_sys.h
@@ -0,0 +1,13 @@
+
+#ifndef TIPSTER_SYS_INCLUDED
+#define TIPSTER_SYS_INCLUDED
+
+#include <asm/types.h>
+#include <asm/delay.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#define SynopsysSysDelay( usec ) udelay( usec )
+
+#endif /* TIPSTER_SYS_INCLUDED */
+
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/Kconfig b/polux/linux-2.6.10/drivers/net/synop3504/Kconfig
new file mode 100644
index 0000000000..016998fae4
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/Kconfig
@@ -0,0 +1,20 @@
+
+config KS8001
+ tristate "KS8001 support"
+ depends on (ARM || MIPS) && NET_ETHERNET
+ select CRC32
+ select MII
+ ---help---
+ Support for KS8001 chipset.
+
+ To compile this driver as a module, choose M here and read
+ <file:Documentation/networking/net-modules.txt>. The module will be
+ called KS8001.
+
+config KS8001_NAPI
+ depends on KS8001
+ bool "KS8001 NAPI support by default"
+
+config KS8001_RMII
+ depends on KS8001
+ bool "KS8001 controller is configured as RMII"
diff --git a/polux/linux-2.6.10/drivers/net/synop3504/Makefile b/polux/linux-2.6.10/drivers/net/synop3504/Makefile
new file mode 100644
index 0000000000..f556098541
--- /dev/null
+++ b/polux/linux-2.6.10/drivers/net/synop3504/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_KS8001) += KS8001_dma.o KS8001.o
+CFLAGS_KS8001.o := -O2 #-DSYNOP_ETH_DEBUG
+CFLAGS_KS8001_dma.o := -O2 #-DSYNOP_ETH_DEBUG