Re: [PATCH,RFC] ep93xx_eth: conversion to phylib framework

2008-02-24 Thread Herbert Valerio Riedel
hello *

On Wed, 2007-11-21 at 11:54 -0600, Andy Fleming wrote:
> On Nov 16, 2007, at 03:38, Herbert Valerio Riedel wrote:
> 
> > Currently, the ep93xx_eth driver doesn't care about the PHY state,
> > but it should, in order to tell the MAC when full duplex operation is
> > required; failure to do so causes degraded performance on full duplex
> > links. This patch implements proper PHY handling via the phylib  
> > framework:
> >
> >  - clean up ep93xx_mdio_{read,write} to conform to ep93xx manual
> >  - convert ep93xx_eth driver to phylib framework
> >  - set full duplex bit in configuration of MAC when FDX link detected
> >  - convert to use print_mac()
> 
> Looks good to me.  My only comment is that we might want to have  
> support for checking preamble suppression support in the PHY Lib,  
> itself.
> 
> Acked-by: Andy Fleming <[EMAIL PROTECTED]>

...as nothing happend for some months now just wondering, what I should
do next, to get this patch merged upstream :-)

cheers,
hvr

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH,RFC] ep93xx_eth: conversion to phylib framework

2007-11-16 Thread Herbert Valerio Riedel
Currently, the ep93xx_eth driver doesn't care about the PHY state,
but it should, in order to tell the MAC when full duplex operation is
required; failure to do so causes degraded performance on full duplex
links. This patch implements proper PHY handling via the phylib framework:

 - clean up ep93xx_mdio_{read,write} to conform to ep93xx manual
 - convert ep93xx_eth driver to phylib framework
 - set full duplex bit in configuration of MAC when FDX link detected
 - convert to use print_mac()

Signed-off-by: Herbert Valerio Riedel <[EMAIL PROTECTED]>
Cc: Lennert Buytenhek <[EMAIL PROTECTED]>
Cc: Andy Fleming <[EMAIL PROTECTED]>
---
If you need me to split this patch, please let me know into 
what parts

 drivers/net/arm/Kconfig  |1 +
 drivers/net/arm/ep93xx_eth.c |  354 +-
 2 files changed, 282 insertions(+), 73 deletions(-)

diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
index f9cc2b6..5860175 100644
--- a/drivers/net/arm/Kconfig
+++ b/drivers/net/arm/Kconfig
@@ -44,6 +44,7 @@ config EP93XX_ETH
tristate "EP93xx Ethernet support"
depends on ARM && ARCH_EP93XX
select MII
+   select PHYLIB
help
  This is a driver for the ethernet hardware included in EP93xx CPUs.
  Say Y if you are building a kernel for EP93xx based devices.
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
index 91a6590..6b9ac41 100644
--- a/drivers/net/arm/ep93xx_eth.c
+++ b/drivers/net/arm/ep93xx_eth.c
@@ -2,6 +2,7 @@
  * EP93xx ethernet network device driver
  * Copyright (C) 2006 Lennert Buytenhek <[EMAIL PROTECTED]>
  * Dedicated to Marija Kulikova.
+ * Copyright (C) 2007 Herbert Valerio Riedel <[EMAIL PROTECTED]>
  *
  * 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
@@ -14,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -37,6 +39,8 @@
 #define  REG_RXCTL_DEFAULT 0x00073800
 #define REG_TXCTL  0x0004
 #define  REG_TXCTL_ENABLE  0x0001
+#define REG_TESTCTL0x0008
+#define  REG_TESTCTL_MFDX  0x0040
 #define REG_MIICMD 0x0010
 #define  REG_MIICMD_READ   0x8000
 #define  REG_MIICMD_WRITE  0x4000
@@ -45,6 +49,9 @@
 #define  REG_MIISTS_BUSY   0x0001
 #define REG_SELFCTL0x0020
 #define  REG_SELFCTL_RESET 0x0001
+#define  REG_SELFCTL_MDCDIV_MSK 0x7e00
+#define  REG_SELFCTL_MDCDIV_OFS 9
+#define  REG_SELFCTL_PSPRS 0x0100
 #define REG_INTEN  0x0024
 #define  REG_INTEN_TX  0x0008
 #define  REG_INTEN_RX  0x0007
@@ -174,8 +181,14 @@ struct ep93xx_priv
 
struct net_device_stats stats;
 
-   struct mii_if_info  mii;
u8  mdc_divisor;
+   int phy_supports_mfps:1;
+
+   struct mii_bus  mii_bus;
+   struct phy_device   *phy_dev;
+   int speed;
+   int duplex;
+   int link;
 };
 
 #define rdb(ep, off)   __raw_readb((ep)->base_addr + (off))
@@ -185,8 +198,6 @@ struct ep93xx_priv
 #define wrw(ep, off, val)  __raw_writew((val), (ep)->base_addr + (off))
 #define wrl(ep, off, val)  __raw_writel((val), (ep)->base_addr + (off))
 
-static int ep93xx_mdio_read(struct net_device *dev, int phy_id, int reg);
-
 static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
 {
struct ep93xx_priv *ep = netdev_priv(dev);
@@ -542,12 +553,6 @@ static int ep93xx_start_hw(struct net_device *dev)
return 1;
}
 
-   wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9));
-
-   /* Does the PHY support preamble suppress?  */
-   if ((ep93xx_mdio_read(dev, ep->mii.phy_id, MII_BMSR) & 0x0040) != 0)
-   wrl(ep, REG_SELFCTL, ((ep->mdc_divisor - 1) << 9) | (1 << 8));
-
/* Receive descriptor ring.  */
addr = ep->descs_dma_addr + offsetof(struct ep93xx_descs, rdesc);
wrl(ep, REG_RXDQBADD, addr);
@@ -631,12 +636,11 @@ static int ep93xx_open(struct net_device *dev)
return -ENOMEM;
 
if (is_zero_ether_addr(dev->dev_addr)) {
+   DECLARE_MAC_BUF(mac_buf);
+
random_ether_addr(dev->dev_addr);
-   printk(KERN_INFO "%s: generated random MAC address "
-   "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x.\n", dev->name,
-   dev->dev_addr[0], dev->dev_addr[1],
-   dev->dev_addr[2], dev->dev_addr[3],
-   dev->dev_addr[4], dev->dev_addr[5]);
+   dev_info(&dev->dev, "generated random MAC address %s\n",
+pri

[PATCH netdev-2.6#upstream] net: au1000_eth: netdev_priv() conversion

2006-06-11 Thread Herbert Valerio Riedel
convert driver to use netdev_priv(net_device*) instead of accessing ->priv
directly; where applicable, declare the resulting local pointer to be 'const'

Signed-off-by: Herbert Valerio Riedel <[EMAIL PROTECTED]>
---

 drivers/net/au1000_eth.c |   51 +++---
 1 files changed, 25 insertions(+), 26 deletions(-)

505c73271046495d4948bf7b5adc7c4e3b88835d
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 038d5fc..558aae3 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -199,7 +199,7 @@ #endif
  */
 static int mdio_read(struct net_device *dev, int phy_addr, int reg)
 {
-   struct au1000_private *aup = (struct au1000_private *) dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
volatile u32 *const mii_control_reg = &aup->mac->mii_control;
volatile u32 *const mii_data_reg = &aup->mac->mii_data;
u32 timedout = 20;
@@ -233,7 +233,7 @@ static int mdio_read(struct net_device *
 
 static void mdio_write(struct net_device *dev, int phy_addr, int reg, u16 
value)
 {
-   struct au1000_private *aup = (struct au1000_private *) dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
volatile u32 *const mii_control_reg = &aup->mac->mii_control;
volatile u32 *const mii_data_reg = &aup->mac->mii_data;
u32 timedout = 20;
@@ -288,7 +288,7 @@ static int mdiobus_reset(struct mii_bus 
 
 static int mii_probe (struct net_device *dev)
 {
-   struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
struct phy_device *phydev = NULL;
 
 #if defined(AU1XXX_PHY_STATIC_CONFIG)
@@ -419,7 +419,7 @@ void ReleaseDB(struct au1000_private *au
 
 static void enable_rx_tx(struct net_device *dev)
 {
-   struct au1000_private *aup = (struct au1000_private *) dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
 
if (au1000_debug > 4)
printk(KERN_INFO "%s: enable_rx_tx\n", dev->name);
@@ -430,7 +430,7 @@ static void enable_rx_tx(struct net_devi
 
 static void hard_stop(struct net_device *dev)
 {
-   struct au1000_private *aup = (struct au1000_private *) dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
 
if (au1000_debug > 4)
printk(KERN_INFO "%s: hard stop\n", dev->name);
@@ -442,7 +442,7 @@ static void hard_stop(struct net_device 
 static void enable_mac(struct net_device *dev, int force_reset)
 {
unsigned long flags;
-   struct au1000_private *aup = (struct au1000_private *) dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
 
spin_lock_irqsave(&aup->lock, flags);
 
@@ -461,7 +461,7 @@ static void enable_mac(struct net_device
 
 static void reset_mac_unlocked(struct net_device *dev)
 {
-   struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
int i;
 
hard_stop(dev);
@@ -487,7 +487,7 @@ static void reset_mac_unlocked(struct ne
 
 static void reset_mac(struct net_device *dev)
 {
-   struct au1000_private *const aup = (struct au1000_private *) dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
unsigned long flags;
 
if (au1000_debug > 4)
@@ -576,7 +576,7 @@ static int __init au1000_init_module(voi
 
 static int au1000_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-   struct au1000_private *aup = (struct au1000_private *)dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
 
if (aup->phy_dev)
return phy_ethtool_gset(aup->phy_dev, cmd);
@@ -586,7 +586,7 @@ static int au1000_get_settings(struct ne
 
 static int au1000_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
-   struct au1000_private *aup = (struct au1000_private *)dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
 
if (!capable(CAP_NET_ADMIN))
return -EPERM;
@@ -600,7 +600,7 @@ static int au1000_set_settings(struct ne
 static void
 au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-   struct au1000_private *aup = (struct au1000_private *)dev->priv;
+   struct au1000_private *const aup = netdev_priv(dev);
 
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
@@ -657,7 +657,7 @@ static struct net_device * au1000_probe(
printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
dev->name, base, irq);
 
-   aup = dev->priv;
+   aup = netdev_priv(dev);
 
/* Allocate the data buffers */
/* Snooping works fine with eth on all au1xxx */
@@ -822,7 +822,7 @@ err_out:
  */
 st

[PATCH netdev-2.6#upstream] net: au1000_eth: PHY framework conversion

2006-06-01 Thread Herbert Valerio Riedel
convert au1000_eth driver to use PHY framework and garbage collected
functions and identifiers that became unused/obsolete in the process

Signed-off-by: Herbert Valerio Riedel <[EMAIL PROTECTED]>

---

this is a resend of
http://marc.theaimsgroup.com/?l=linux-netdev&m=114746547301867&w=2
rebased&handmerged to netdev-2.6#upstream (i.e. on top of sergei's
probe code cleanup patch)

 drivers/net/Kconfig  |1 
 drivers/net/au1000_eth.c | 1602 +++---
 drivers/net/au1000_eth.h |  134 
 3 files changed, 378 insertions(+), 1359 deletions(-)

616e5a012a927d401befcbed37b77c3ea42da5a5
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index f499a3b..520765d 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -447,6 +447,7 @@ config MIPS_GT96100ETH
 config MIPS_AU1X00_ENET
bool "MIPS AU1000 Ethernet support"
depends on NET_ETHERNET && SOC_AU1X00
+   select PHYLIB
select CRC32
help
  If you have an Alchemy Semi AU1X00 based system
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index e1fe960..038d5fc 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -9,6 +9,9 @@
  * Update: 2004 Bjoern Riemer, [EMAIL PROTECTED] 
  * or [EMAIL PROTECTED]: fixed the link beat detection with 
  * ioctls (SIOCGMIIPHY)
+ * Copyright 2006 Herbert Valerio Riedel <[EMAIL PROTECTED]>
+ *  converted to use linux-2.6.x's PHY framework
+ *
  * Author: MontaVista Software, Inc.
  * [EMAIL PROTECTED] or [EMAIL PROTECTED]
  *
@@ -53,6 +56,7 @@ #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -88,17 +92,15 @@ static int au1000_tx(struct sk_buff *, s
 static int au1000_rx(struct net_device *);
 static irqreturn_t au1000_interrupt(int, void *, struct pt_regs *);
 static void au1000_tx_timeout(struct net_device *);
-static int au1000_set_config(struct net_device *dev, struct ifmap *map);
 static void set_rx_mode(struct net_device *);
 static struct net_device_stats *au1000_get_stats(struct net_device *);
-static void au1000_timer(unsigned long);
 static int au1000_ioctl(struct net_device *, struct ifreq *, int);
 static int mdio_read(struct net_device *, int, int);
 static void mdio_write(struct net_device *, int, int, u16);
-static void dump_mii(struct net_device *dev, int phy_id);
+static void au1000_adjust_link(struct net_device *);
+static void enable_mac(struct net_device *, int);
 
 // externs
-extern  void ack_rise_edge_irq(unsigned int);
 extern int get_ethernet_addr(char *ethernet_addr);
 extern void str2eaddr(unsigned char *ea, unsigned char *str);
 extern char * __init prom_getcmdline(void);
@@ -126,705 +128,83 @@ static unsigned char au1000_mac_addr[6] 
0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00
 };
 
-#define nibswap(x) x) >> 4) & 0x0f) | (((x) << 4) & 0xf0))
-#define RUN_AT(x) (jiffies + (x))
-
-// For reading/writing 32-bit words from/to DMA memory
-#define cpu_to_dma32 cpu_to_be32
-#define dma32_to_cpu be32_to_cpu
-
 struct au1000_private *au_macs[NUM_ETH_INTERFACES];
 
-/* FIXME 
- * All of the PHY code really should be detached from the MAC 
- * code.
+/*
+ * board-specific configurations
+ *
+ * PHY detection algorithm
+ *
+ * If AU1XXX_PHY_STATIC_CONFIG is undefined, the PHY setup is
+ * autodetected:
+ *
+ * mii_probe() first searches the current MAC's MII bus for a PHY,
+ * selecting the first (or last, if AU1XXX_PHY_SEARCH_HIGHEST_ADDR is
+ * defined) PHY address not already claimed by another netdev.
+ *
+ * If nothing was found that way when searching for the 2nd ethernet
+ * controller's PHY and AU1XXX_PHY1_SEARCH_ON_MAC0 is defined, then
+ * the first MII bus is searched as well for an unclaimed PHY; this is
+ * needed in case of a dual-PHY accessible only through the MAC0's MII
+ * bus.
+ *
+ * Finally, if no PHY is found, then the corresponding ethernet
+ * controller is not registered to the network subsystem.
  */
 
-/* Default advertise */
-#define GENMII_DEFAULT_ADVERTISE \
-   ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
-   ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
-   ADVERTISED_Autoneg
-
-#define GENMII_DEFAULT_FEATURES \
-   SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
-   SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
-   SUPPORTED_Autoneg
-
-int bcm_5201_init(struct net_device *dev, int phy_addr)
-{
-   s16 data;
-   
-   /* Stop auto-negotiation */
-   data = mdio_read(dev, phy_addr, MII_CONTROL);
-   mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
-   /* Set advertisement to 10/100 and Half/Full duplex
-* (full capabilities) */
-   data = mdio_read(dev, phy_addr, MII_ANADV);
-   data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
-   mdio_write(dev, phy_addr, MII_ANADV, da

[PATCH] phy: new SMSC LAN83C185 PHY driver

2006-05-23 Thread Herbert Valerio Riedel
new SMSC LAN83C185 10BaseT/100BaseTX PHY driver for the PHY subsystem

Signed-off-by: Herbert Valerio Riedel <[EMAIL PROTECTED]>

---
just a resend of 
http://marc.theaimsgroup.com/?l=linux-netdev&m=114703725817039&w=2

 drivers/net/phy/Kconfig  |6 +++
 drivers/net/phy/Makefile |1 
 drivers/net/phy/smsc.c   |  101 ++
 3 files changed, 108 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/phy/smsc.c

549b2b826ddca6a15b39f88cdc9f45e9131eaac0
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index fa39b94..cda3e53 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -45,5 +45,11 @@ config CICADA_PHY
---help---
  Currently supports the cis8204
 
+config SMSC_PHY
+   tristate "Drivers for SMSC PHYs"
+   depends on PHYLIB
+   ---help---
+ Currently supports the LAN83C185 PHY
+
 endmenu
 
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index e4116a5..d961413 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_DAVICOM_PHY)   += davicom.o
 obj-$(CONFIG_CICADA_PHY)   += cicada.o
 obj-$(CONFIG_LXT_PHY)  += lxt.o
 obj-$(CONFIG_QSEMI_PHY)+= qsemi.o
+obj-$(CONFIG_SMSC_PHY) += smsc.o
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
new file mode 100644
index 000..25e31fb
--- /dev/null
+++ b/drivers/net/phy/smsc.c
@@ -0,0 +1,101 @@
+/*
+ * drivers/net/phy/smsc.c
+ *
+ * Driver for SMSC PHYs
+ *
+ * Author: Herbert Valerio Riedel
+ *
+ * Copyright (c) 2006 Herbert Valerio Riedel <[EMAIL PROTECTED]>
+ *
+ * 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.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
+#define MII_LAN83C185_IM  30 /* Interrupt Mask */
+
+#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
+#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
+#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */
+#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */
+#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */
+#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */
+#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */
+
+#define MII_LAN83C185_ISF_INT_ALL (0x0e)
+
+#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \
+   (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4)
+
+
+static int lan83c185_config_intr(struct phy_device *phydev)
+{
+   int rc = phy_write (phydev, MII_LAN83C185_IM,
+   ((PHY_INTERRUPT_ENABLED == phydev->interrupts)
+   ? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS
+   : 0));
+
+   return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_ack_interrupt(struct phy_device *phydev)
+{
+   int rc = phy_read (phydev, MII_LAN83C185_ISF);
+
+   return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_config_init(struct phy_device *phydev)
+{
+   return lan83c185_ack_interrupt (phydev);
+}
+
+
+static struct phy_driver lan83c185_driver = {
+   .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
+   .phy_id_mask= 0xfff0,
+   .name   = "SMSC LAN83C185",
+
+   .features   = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+   | SUPPORTED_Asym_Pause),
+   .flags  = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+
+   /* basic functions */
+   .config_aneg= genphy_config_aneg,
+   .read_status= genphy_read_status,
+   .config_init= lan83c185_config_init,
+
+   /* IRQ related */
+   .ack_interrupt  = lan83c185_ack_interrupt,
+   .config_intr= lan83c185_config_intr,
+
+   .driver = { .owner = THIS_MODULE, }
+};
+
+static int __init smsc_init(void)
+{
+   return phy_driver_register (&lan83c185_driver);
+}
+
+static void __exit smsc_exit(void)
+{
+   phy_driver_unregister (&lan83c185_driver);
+}
+
+MODULE_DESCRIPTION("SMSC PHY driver");
+MODULE_AUTHOR("Herbert Valerio Riedel");
+MODULE_LICENSE("GPL");
+
+module_init(smsc_init);
+module_exit(smsc_exit);
-- 
1.3.2

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] [RFC] net: au1000_eth: PHY framework conversion

2006-05-12 Thread Herbert Valerio Riedel
convert au1000_eth driver to use PHY framework

Signed-off-by: Herbert Valerio Riedel <[EMAIL PROTECTED]>
---

 drivers/net/Kconfig  |1 
 drivers/net/au1000_eth.c | 1602 +++---
 drivers/net/au1000_eth.h |  134 
 3 files changed, 380 insertions(+), 1357 deletions(-)

Index: b/drivers/net/Kconfig
===
--- a/drivers/net/Kconfig   2006-05-12 21:18:36.0 +0200
+++ b/drivers/net/Kconfig   2006-05-12 21:37:42.0 +0200
@@ -455,6 +455,7 @@
 config MIPS_AU1X00_ENET
bool "MIPS AU1000 Ethernet support"
depends on NET_ETHERNET && SOC_AU1X00
+   select PHYLIB
select CRC32
help
  If you have an Alchemy Semi AU1X00 based system
Index: b/drivers/net/au1000_eth.c
===
--- a/drivers/net/au1000_eth.c  2006-05-12 21:18:36.0 +0200
+++ b/drivers/net/au1000_eth.c  2006-05-12 22:05:25.0 +0200
@@ -9,6 +9,9 @@
  * Update: 2004 Bjoern Riemer, [EMAIL PROTECTED] 
  * or [EMAIL PROTECTED]: fixed the link beat detection with 
  * ioctls (SIOCGMIIPHY)
+ * Copyright 2006 Herbert Valerio Riedel <[EMAIL PROTECTED]>
+ *  converted to use linux-2.6.x's PHY framework
+ *
  * Author: MontaVista Software, Inc.
  * [EMAIL PROTECTED] or [EMAIL PROTECTED]
  *
@@ -53,6 +56,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -88,17 +92,15 @@
 static int au1000_rx(struct net_device *);
 static irqreturn_t au1000_interrupt(int, void *, struct pt_regs *);
 static void au1000_tx_timeout(struct net_device *);
-static int au1000_set_config(struct net_device *dev, struct ifmap *map);
 static void set_rx_mode(struct net_device *);
 static struct net_device_stats *au1000_get_stats(struct net_device *);
-static void au1000_timer(unsigned long);
 static int au1000_ioctl(struct net_device *, struct ifreq *, int);
 static int mdio_read(struct net_device *, int, int);
 static void mdio_write(struct net_device *, int, int, u16);
-static void dump_mii(struct net_device *dev, int phy_id);
+static void au1000_adjust_link(struct net_device *);
+static void enable_mac(struct net_device *, int);
 
 // externs
-extern  void ack_rise_edge_irq(unsigned int);
 extern int get_ethernet_addr(char *ethernet_addr);
 extern void str2eaddr(unsigned char *ea, unsigned char *str);
 extern char * __init prom_getcmdline(void);
@@ -126,705 +128,83 @@
0x00, 0x50, 0xc2, 0x0c, 0x30, 0x00
 };
 
-#define nibswap(x) x) >> 4) & 0x0f) | (((x) << 4) & 0xf0))
-#define RUN_AT(x) (jiffies + (x))
-
-// For reading/writing 32-bit words from/to DMA memory
-#define cpu_to_dma32 cpu_to_be32
-#define dma32_to_cpu be32_to_cpu
-
 struct au1000_private *au_macs[NUM_ETH_INTERFACES];
 
-/* FIXME 
- * All of the PHY code really should be detached from the MAC 
- * code.
+/*
+ * board-specific configurations
+ *
+ * PHY detection algorithm
+ *
+ * If AU1XXX_PHY_STATIC_CONFIG is undefined, the PHY setup is
+ * autodetected:
+ *
+ * mii_probe() first searches the current MAC's MII bus for a PHY,
+ * selecting the first (or last, if AU1XXX_PHY_SEARCH_HIGHEST_ADDR is
+ * defined) PHY address not already claimed by another netdev.
+ *
+ * If nothing was found that way when searching for the 2nd ethernet
+ * controller's PHY and AU1XXX_PHY1_SEARCH_ON_MAC0 is defined, then
+ * the first MII bus is searched as well for an unclaimed PHY; this is
+ * needed in case of a dual-PHY accessible only through the MAC0's MII
+ * bus.
+ *
+ * Finally, if no PHY is found, then the corresponding ethernet
+ * controller is not registered to the network subsystem.
  */
 
-/* Default advertise */
-#define GENMII_DEFAULT_ADVERTISE \
-   ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
-   ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
-   ADVERTISED_Autoneg
-
-#define GENMII_DEFAULT_FEATURES \
-   SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
-   SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
-   SUPPORTED_Autoneg
-
-int bcm_5201_init(struct net_device *dev, int phy_addr)
-{
-   s16 data;
-   
-   /* Stop auto-negotiation */
-   data = mdio_read(dev, phy_addr, MII_CONTROL);
-   mdio_write(dev, phy_addr, MII_CONTROL, data & ~MII_CNTL_AUTO);
-
-   /* Set advertisement to 10/100 and Half/Full duplex
-* (full capabilities) */
-   data = mdio_read(dev, phy_addr, MII_ANADV);
-   data |= MII_NWAY_TX | MII_NWAY_TX_FDX | MII_NWAY_T_FDX | MII_NWAY_T;
-   mdio_write(dev, phy_addr, MII_ANADV, data);
-   
-   /* Restart auto-negotiation */
-   data = mdio_read(dev, phy_addr, MII_CONTROL);
-   data |= MII_CNTL_RST_AUTO | MII_CNTL_AUTO;
-   mdio_write(dev, phy_addr, MII_CONTROL, data);
-
-   if (au1000_debug > 4) 
-   dump_mii(dev,

[PATCH] phy: mdiobus_register(): initialize all phy_map entries

2006-05-10 Thread Herbert Valerio Riedel

make sure phy_map entries whose PHY address is masked are initialized
to NULL, given that other code (such as mdiobus_unregister for
instance) assumes that non-NULL phy_map entries are allocated
phy_devices

Signed-off-by: Herbert Valerio Riedel <[EMAIL PROTECTED]>
---

 drivers/net/phy/mdio_bus.c |4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

Index: b/drivers/net/phy/mdio_bus.c
===
--- a/drivers/net/phy/mdio_bus.c2006-05-10 17:02:12.0 +0200
+++ b/drivers/net/phy/mdio_bus.c2006-05-10 17:05:27.0 +0200
@@ -60,8 +60,10 @@
for (i = 0; i < PHY_MAX_ADDR; i++) {
struct phy_device *phydev;
 
-   if (bus->phy_mask & (1 << i))
+   if (bus->phy_mask & (1 << i)) {
+   bus->phy_map[i] = NULL;
continue;
+   }
 
phydev = get_phy_device(bus, i);
 
-- 
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] phy: new SMSC LAN83C185 PHY driver

2006-05-07 Thread Herbert Valerio Riedel
new SMSC LAN83C185 10BaseT/100BaseTX PHY driver for the PHY subsystem

Signed-off-by: Herbert Valerio Riedel <[EMAIL PROTECTED]>


---

2nd attempt

 drivers/net/phy/Kconfig  |6 +++
 drivers/net/phy/Makefile |1 
 drivers/net/phy/smsc.c   |  101 ++
 3 files changed, 108 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/phy/smsc.c

fcd93884d904a36293d80af6841fde4dc3b8eca8
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index fa39b94..cda3e53 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -45,5 +45,11 @@ config CICADA_PHY
---help---
  Currently supports the cis8204
 
+config SMSC_PHY
+   tristate "Drivers for SMSC PHYs"
+   depends on PHYLIB
+   ---help---
+ Currently supports the LAN83C185 PHY
+
 endmenu
 
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index e4116a5..d961413 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_DAVICOM_PHY)   += davicom.o
 obj-$(CONFIG_CICADA_PHY)   += cicada.o
 obj-$(CONFIG_LXT_PHY)  += lxt.o
 obj-$(CONFIG_QSEMI_PHY)+= qsemi.o
+obj-$(CONFIG_SMSC_PHY) += smsc.o
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
new file mode 100644
index 000..25e31fb
--- /dev/null
+++ b/drivers/net/phy/smsc.c
@@ -0,0 +1,101 @@
+/*
+ * drivers/net/phy/smsc.c
+ *
+ * Driver for SMSC PHYs
+ *
+ * Author: Herbert Valerio Riedel
+ *
+ * Copyright (c) 2006 Herbert Valerio Riedel <[EMAIL PROTECTED]>
+ *
+ * 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.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
+#define MII_LAN83C185_IM  30 /* Interrupt Mask */
+
+#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
+#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
+#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */
+#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */
+#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */
+#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */
+#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */
+
+#define MII_LAN83C185_ISF_INT_ALL (0x0e)
+
+#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \
+   (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4)
+
+
+static int lan83c185_config_intr(struct phy_device *phydev)
+{
+   int rc = phy_write (phydev, MII_LAN83C185_IM,
+   ((PHY_INTERRUPT_ENABLED == phydev->interrupts)
+   ? MII_LAN83C185_ISF_INT_PHYLIB_EVENTS
+   : 0));
+
+   return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_ack_interrupt(struct phy_device *phydev)
+{
+   int rc = phy_read (phydev, MII_LAN83C185_ISF);
+
+   return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_config_init(struct phy_device *phydev)
+{
+   return lan83c185_ack_interrupt (phydev);
+}
+
+
+static struct phy_driver lan83c185_driver = {
+   .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
+   .phy_id_mask= 0xfff0,
+   .name   = "SMSC LAN83C185",
+
+   .features   = (PHY_BASIC_FEATURES | SUPPORTED_Pause
+   | SUPPORTED_Asym_Pause),
+   .flags  = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+
+   /* basic functions */
+   .config_aneg= genphy_config_aneg,
+   .read_status= genphy_read_status,
+   .config_init= lan83c185_config_init,
+
+   /* IRQ related */
+   .ack_interrupt  = lan83c185_ack_interrupt,
+   .config_intr= lan83c185_config_intr,
+
+   .driver = { .owner = THIS_MODULE, }
+};
+
+static int __init smsc_init(void)
+{
+   return phy_driver_register (&lan83c185_driver);
+}
+
+static void __exit smsc_exit(void)
+{
+   phy_driver_unregister (&lan83c185_driver);
+}
+
+MODULE_DESCRIPTION("SMSC PHY driver");
+MODULE_AUTHOR("Herbert Valerio Riedel");
+MODULE_LICENSE("GPL");
+
+module_init(smsc_init);
+module_exit(smsc_exit);
-- 
1.2.6

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] phy: new SMSC LAN83C185 PHY driver

2006-05-07 Thread Herbert Valerio Riedel
new SMSC LAN83C185 10BaseT/100BaseTX PHY driver for the PHY subsystem

Signed-off-by: Herbert Valerio Riedel <[EMAIL PROTECTED]>


---

 drivers/net/phy/Kconfig  |6 ++
 drivers/net/phy/Makefile |1 
 drivers/net/phy/smsc.c   |  134 ++
 3 files changed, 141 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/phy/smsc.c

15ab98f0ecaf1fb161d0832a118c93976531af66
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index fa39b94..cda3e53 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -45,5 +45,11 @@ config CICADA_PHY
---help---
  Currently supports the cis8204
 
+config SMSC_PHY
+   tristate "Drivers for SMSC PHYs"
+   depends on PHYLIB
+   ---help---
+ Currently supports the LAN83C185 PHY
+
 endmenu
 
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index e4116a5..d961413 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_DAVICOM_PHY)   += davicom.o
 obj-$(CONFIG_CICADA_PHY)   += cicada.o
 obj-$(CONFIG_LXT_PHY)  += lxt.o
 obj-$(CONFIG_QSEMI_PHY)+= qsemi.o
+obj-$(CONFIG_SMSC_PHY) += smsc.o
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
new file mode 100644
index 000..b96eb52
--- /dev/null
+++ b/drivers/net/phy/smsc.c
@@ -0,0 +1,134 @@
+/*
+ * drivers/net/phy/smsc.c
+ *
+ * Driver for SMSC PHYs
+ *
+ * Author: Herbert Valerio Riedel
+ *
+ * Copyright (c) 2006 Herbert Valerio Riedel <[EMAIL PROTECTED]>
+ *
+ * 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.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define MII_LAN83C185_ISF 29 /* Interrupt Source Flags */
+#define MII_LAN83C185_IM  30 /* Interrupt Mask */
+
+#define MII_LAN83C185_ISF_INT1 (1<<1) /* Auto-Negotiation Page Received */
+#define MII_LAN83C185_ISF_INT2 (1<<2) /* Parallel Detection Fault */
+#define MII_LAN83C185_ISF_INT3 (1<<3) /* Auto-Negotiation LP Ack */
+#define MII_LAN83C185_ISF_INT4 (1<<4) /* Link Down */
+#define MII_LAN83C185_ISF_INT5 (1<<5) /* Remote Fault Detected */
+#define MII_LAN83C185_ISF_INT6 (1<<6) /* Auto-Negotiation complete */
+#define MII_LAN83C185_ISF_INT7 (1<<7) /* ENERGYON */
+
+#define MII_LAN83C185_ISF_INT_ALL (0x0e)
+
+#define MII_LAN83C185_ISF_INT_PHYLIB_EVENTS \
+   (MII_LAN83C185_ISF_INT6 | MII_LAN83C185_ISF_INT4)
+
+/* prototypes */
+static int lan83c185_config_init(struct phy_device *);
+static int lan83c185_config_intr(struct phy_device *);
+static int lan83c185_ack_interrupt(struct phy_device *);
+
+
+static int lan83c185_config_init(struct phy_device *phydev)
+{
+   pr_debug ("%s: config_init\n", phydev->attached_dev->name);
+
+   return lan83c185_ack_interrupt (phydev);
+}
+
+static int lan83c185_config_intr(struct phy_device *phydev)
+{
+   int rc = phy_write (phydev, MII_LAN83C185_IM,
+   ((PHY_INTERRUPT_ENABLED == phydev->interrupts) 
+?  MII_LAN83C185_ISF_INT_PHYLIB_EVENTS 
+: 0));
+
+   pr_debug ("%s: config_intr %x (rc=%.4x)\n",
+ phydev->attached_dev->name, phydev->interrupts, rc);
+
+   return rc < 0 ? rc : 0;
+}
+
+static int lan83c185_ack_interrupt(struct phy_device *phydev)
+{
+   int rc = phy_read (phydev, MII_LAN83C185_ISF);
+
+   pr_debug ("%s: ack_interrupt (masked ISF=%.4x, raw ISF: %.4x)\n", 
+ phydev->attached_dev->name, 
+ rc & MII_LAN83C185_ISF_INT_PHYLIB_EVENTS, rc);
+
+   return rc < 0 ? rc : 0;
+}
+
+static struct phy_driver lan83c185_driver = {
+   .phy_id = 0x0007c0a0, /* OUI=0x00800f, Model#=0x0a */
+   .phy_id_mask= 0xfff0,
+   .name   = "SMSC LAN83C185",
+   
+   .features   = (PHY_BASIC_FEATURES | SUPPORTED_Pause 
+  | SUPPORTED_Asym_Pause),
+   .flags  = PHY_HAS_INTERRUPT | PHY_HAS_MAGICANEG,
+
+   /* basic functions */
+   .config_aneg= genphy_config_aneg,
+   .read_status= genphy_read_status,
+   .config_init= lan83c185_config_init,
+
+   /* IRQ related */
+   .ack_interrupt  = lan83c185_ack_interrupt,
+.config_intr= lan83c185_config_intr,
+   
+   .driver = { .owner = THIS_MODULE, }
+};
+
+static int __init smsc_init(void)
+{
+int rc;
+
+if ((rc = phy_driver_register (&lan83c185_driver)))
+goto err_register_lan83c185_driver;
+
+return 0;
+   
+   /* phy_driver_unregister (&la

Re: RFC: au1000_etc.c phylib rewrite

2006-05-03 Thread Herbert Valerio Riedel
hello *

On Tue, 2006-05-02 at 11:20 -0500, Mark Schank wrote:
> At 08:23 AM 5/2/06 +0200, Herbert Valerio Riedel wrote:
> >On Mon, 2006-05-01 at 15:09 -0500, Mark Schank wrote:
> > > The Cogent CSB655 used the Broadcom Dual Phy.  They eventually redesigned
> > > the board and switched to two single Broadcom phys, but they continued to
> > > control both phys through MAC0, which is the actual purpose of the 
> > dual-phy
> > > hack.  I am a user of the CSB655, so I sort of care.
> > >
> > > Will the new PHY framework allow a second PHY for a second MAC (MAC1) be
> > > controlled from the first MAC's (MAC0) mdio interface?
> >
> >should'nt be a problem (as opposed to the bosporus case... see below)...
> >I assume the phy-addresses on which the boarcom dual phy is configured
> >are the same for all Cogent CSB655 boards?
> 
> Dual PHY configuration:
>  MAC0 - phy addr 4
>  MAC1 - phy addr 3
> Single PHY configuration:
>  MAC0 - phy addr 1
>  MAC1 - phy addr 0

while at it, does anyone happen to know what the phy-addr/MAC assignment
on the XXS1500 is?

> >does this need to be autodetected dynamically at runtime, or can we rely
> >on a compile time Kconfig-conditional to set a static phy-addr<->eth%
> >d-phy mapping for this board-specific case? Or de we really need such a
> >complex mii_probe() function to detect weird scenarios? :)
> 
> The compile time Kconfig-conditional should be okay.  The driver need to 
> handle the fact that the MAC1's phy is controlled by MAC0's mdio 
> interface.  This means that MAC0 controller can not be disabled when the 
> associated eth% device is down, otherwise you lose the ability to control 
> MAC1's phy.

...or at least, the MAC associated with the particular MII bus should be
brought up if necessary before any mdio access (that's what I'm
implementing right now)

but one thing that seems strange to me; CONFIG_BCM5222_DUAL_PHY doesn't
seem to be defined anywhere; shouldn't that be at least defined in some
Kconfig file, especially if the XXS1550 board is supposed to make use of
it? 

btw, is the CSB655 supported at all in the 2.6 linux-mips branch, I
couldn't find any mention of it in Kconfig files either?

> >using static phy addr mappings would also allow for setting
> >board-specific phy-irq assignments, which would then be handled by the
> >phylib facilities, instead of polling the status of phy with a timer;
> >(and in case we don't have any board-specific compile time setting, we
> >can still fall back to search the phy-addresses for a PHY at runtime as
> >the generic case)
> 
> Will the phylib facilities handle the case where two phys share a single IRQ?

afaics from the source, it doesn't handle the case of multiplexed phy
notification irqs; although the interrupt is requested with the SA_SHIRQ
flag, the first phy-interrupt-handler to be called already returns
IRQ_HANDLED... doesn't feel right in some way ;-)

> >while at it, what about that CONFIG_MIPS_BOSPORUS special case? why
> >doesn't the 2nd MAC see any PHY? how is the 2nd MAC connected to the
> >physical world?
> 
> I don't have first hand knowledge of this board, but I have worked with 
> Kendin switches before.  They have a special port that allows direct 
> connection of a MAC into the switch port without the use of a phy.  The 
> MAC's MII is directly connected to the switch ports MII.  So instead of this:
>  MAC <-> PHY <->PHY <-> Switch_Port
> You have this:
>  MAC <-> Switch_Port
> 
> So the MAC talks to the physical world via the switch.

thx; in the meantime, I've happened to find the board schematics and the
switch data-sheet in order to understand the situation better

regards,
hvr


signature.asc
Description: This is a digitally signed message part


[PATCH] au1000_eth.c: use ether_crc() from

2006-05-01 Thread Herbert Valerio Riedel
since the au1000 driver already selects the CRC32 routines, simply replace
the internal ether_crc() implementation with the semantically equivalent
one from 

Signed-off-by: Herbert Valerio Riedel <[EMAIL PROTECTED]>


---

 drivers/net/au1000_eth.c |   18 +-
 1 files changed, 1 insertions(+), 17 deletions(-)

9360df5368de8fc7dcaacf9b7ca446af94c4
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 29adebb..0823cb8 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -52,6 +52,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -2070,23 +2071,6 @@ static void au1000_tx_timeout(struct net
netif_wake_queue(dev);
 }
 
-
-static unsigned const ethernet_polynomial = 0x04c11db7U;
-static inline u32 ether_crc(int length, unsigned char *data)
-{
-int crc = -1;
-
-while(--length >= 0) {
-   unsigned char current_octet = *data++;
-   int bit;
-   for (bit = 0; bit < 8; bit++, current_octet >>= 1)
-   crc = (crc << 1) ^
-   ((crc < 0) ^ (current_octet & 1) ? 
-ethernet_polynomial : 0);
-}
-return crc;
-}
-
 static void set_rx_mode(struct net_device *dev)
 {
struct au1000_private *aup = (struct au1000_private *) dev->priv;
-- 
1.2.6

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html