netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2.6.11.1] net/8139cp.c - get and set eeprom II
@ 2005-03-24 15:02 Jyri Reitel
  2005-03-25  4:06 ` Jeff Garzik
  0 siblings, 1 reply; 2+ messages in thread
From: Jyri Reitel @ 2005-03-24 15:02 UTC (permalink / raw)
  To: netdev; +Cc: jgarzik, mroos

[-- Attachment #1: Type: text/plain, Size: 7140 bytes --]

Hi. My next patch where removed the pci table modification because most people don't want (need) this.
Also indentification should be ok now?

When answering please add jyri.reitel@mail.ee to the cc line, because i'm not the member of the mainling list

Signed-off-by: Jüri Reitel <jyri.reitel@mail.ee>

--- linux-2.6.11.1/drivers/net/8139cp.c.orig	Thu Mar 24 10:08:32 2005
+++ linux-2.6.11.1/drivers/net/8139cp.c	Thu Mar 24 16:37:42 2005
@@ -110,6 +110,11 @@ MODULE_PARM_DESC (multicast_filter_limit
 #define TRUE (!FALSE)
 #endif
 
+#define RTL8139_EEPROM_SIZE 128
+static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data);
+static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data);
+static int get_eeprom_len(struct net_device *dev);
+
 #define CP_DEF_MSG_ENABLE	(NETIF_MSG_DRV		| \
 				 NETIF_MSG_PROBE 	| \
 				 NETIF_MSG_LINK)
@@ -400,6 +405,15 @@ static struct pci_device_id cp_pci_tbl[]
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
 	{ PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322,
 	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+
+	/* 
+	* comment out this when the eeprom is corrupted or not preprogrammed
+	* and you want this driver to be loaded, thus allowing to program 
+	* the eeprom with ethtool
+	* It would be good idea not to compile 8139too driver then
+	{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8129,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
+	*/
 	{ },
 };
 MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
@@ -1543,6 +1557,9 @@ static struct ethtool_ops cp_ethtool_ops
 	.set_wol		= cp_set_wol,
 	.get_strings		= cp_get_strings,
 	.get_ethtool_stats	= cp_get_ethtool_stats,
+	.get_eeprom		= get_eeprom,
+	.set_eeprom		= set_eeprom,
+	.get_eeprom_len		= get_eeprom_len,
 };
 
 static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
@@ -1566,8 +1583,8 @@ static int cp_ioctl (struct net_device *
 #define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */
 #define EE_CS			0x08	/* EEPROM chip select. */
 #define EE_DATA_WRITE	0x02	/* EEPROM chip data in. */
-#define EE_WRITE_0		0x00
-#define EE_WRITE_1		0x02
+#define EE_WRITE_0		(0x00 | EE_ENB)
+#define EE_WRITE_1		(0x02 | EE_ENB)
 #define EE_DATA_READ	0x01	/* EEPROM chip data out. */
 #define EE_ENB			(0x80 | EE_CS)
 
@@ -1582,7 +1599,7 @@ static int cp_ioctl (struct net_device *
 #define EE_READ_CMD		(6)
 #define EE_ERASE_CMD	(7)
 
-static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
+static int read_eeprom(void __iomem *ioaddr, int location, int addr_len)
 {
 	int i;
 	unsigned retval = 0;
@@ -1608,8 +1625,7 @@ static int read_eeprom (void __iomem *io
 		writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
 		eeprom_delay ();
 		retval =
-		    (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
-				     0);
+		    (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 : 0);
 		writeb (EE_ENB, ee_addr);
 		eeprom_delay ();
 	}
@@ -1619,6 +1635,130 @@ static int read_eeprom (void __iomem *io
 	eeprom_delay ();
 
 	return retval;
+}
+
+/* This executes a generic EEPROM command, typically a write or write enable.
+   It returns the data output from the EEPROM, and thus may also be used for
+   reads. */
+static int do_eeprom_cmd(void __iomem *ioaddr, int cmd, int cmd_len)
+{
+	unsigned retval = 0;
+	void __iomem *ee_addr = ioaddr + Cfg9346;
+
+	writeb(EE_ENB | EE_SHIFT_CLK, ee_addr);
+
+	/* Shift the command bits out. */
+	do {
+		short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
+		writeb(dataval, ee_addr);
+		eeprom_delay();
+		writeb(dataval | EE_SHIFT_CLK, ee_addr);
+		eeprom_delay();
+		retval = (retval << 1) | ((readb(ee_addr) & EE_DATA_READ) ? 1 : 0);
+	} while (--cmd_len >= 0);
+	writeb(EE_ENB, ee_addr);
+
+	/* Terminate the EEPROM access. */
+	writeb(EE_ENB & ~EE_CS, ee_addr);
+	writeb(~EE_CS, ee_addr);
+	return retval;
+}
+
+
+static void write_eeprom(void __iomem *ioaddr, int index, u16 value, int ee_addr_size)
+{
+	int i;
+	/* Enable programming modes. */
+	do_eeprom_cmd(ioaddr, (0x4f << (ee_addr_size - 4)), 3 + ee_addr_size);
+	/* Do the actual write. */
+	do_eeprom_cmd(ioaddr,
+		(((EE_WRITE_CMD << ee_addr_size) | index) << 16) | value,
+		3 + ee_addr_size + 16
+	);
+	/* Poll for write finished. */
+	writeb(EE_ENB, ioaddr + Cfg9346);
+	for (i = 0; i < 10000; i++)			/* Typical 2000 ticks */
+		if (readb(ioaddr + Cfg9346) & EE_DATA_READ)
+			break;
+	/* Disable programming. */
+	do_eeprom_cmd(ioaddr, (0x40 << (ee_addr_size - 4)), 3 + ee_addr_size);
+}
+
+
+static int get_eeprom_len(struct net_device *dev)
+{
+	return RTL8139_EEPROM_SIZE;
+}
+
+static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
+{
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned int addr_len;
+	u16 eep_data_word = 0;
+	u32 i;
+
+	eeprom->magic = PCI_VENDOR_ID_REALTEK | (PCI_DEVICE_ID_REALTEK_8139 << 16);
+	spin_lock_irq(&cp->lock);
+
+	addr_len = (read_eeprom(cp->regs, 0, 8) == 0x8129)? 8 : 6;
+
+	/* reading word by word from the eeprom */
+
+	if (eeprom->offset & 1) {
+		/* offset is odd */
+		eep_data_word = le16_to_cpu(read_eeprom(cp->regs, eeprom->offset >> 1, addr_len));
+	}
+	for (i = eeprom->offset; i < (eeprom->offset + eeprom->len); i++) {
+		if (i & 1) {
+			/* copy odd byte */
+			data[i - eeprom->offset] = (u8)(eep_data_word >> 8);
+		} else {
+			/* reading even byte so lets fech next word from eeprom */
+			eep_data_word = le16_to_cpu(read_eeprom(cp->regs, i >> 1, addr_len));
+			data[i - eeprom->offset] = (u8)eep_data_word;
+		}
+	}
+	spin_unlock_irq(&cp->lock);
+	return 0;
+}
+
+static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
+{
+	struct cp_private *cp = netdev_priv(dev);
+	unsigned int addr_len;
+	u16 eep_data_word = 0;
+	u32 i;
+	/*
+	if(eeprom->magic != (PCI_VENDOR_ID_REALTEK | (PCI_DEVICE_ID_REALTEK_8139 << 16))) {
+		return -ENODEV;
+	}
+	*/
+	spin_lock_irq(&cp->lock);
+
+	addr_len = (read_eeprom(cp->regs, 0, 8) == 0x8129)? 8 : 6;
+
+	if (eeprom->offset & 1) {
+		/* offset is odd, so read the word to later replace MSB byte */
+		eep_data_word = le16_to_cpu(read_eeprom(cp->regs, eeprom->offset >> 1, addr_len));
+	}
+	for (i = eeprom->offset; i < (eeprom->offset + eeprom->len); i++) {
+		if (i & 1) {
+			/* copy odd byte, to the word data to be stored to the eeprom */
+			eep_data_word |= (u16)data[i - eeprom->offset] << 8;
+			write_eeprom(cp->regs, i >> 1, eep_data_word, addr_len);
+		} else {
+			/* reading even byte so lets fech next word from eeprom */
+			eep_data_word = (u16)data[i - eeprom->offset];
+			if (i + 1 == (eeprom->offset + eeprom->len)) {
+				/* when writing last byte that is LSB, i.e. must get the MSB from eeprom */
+				eep_data_word |= le16_to_cpu(read_eeprom(cp->regs, i >> 1, addr_len)) & 0xFF00;
+				write_eeprom(cp->regs, i >> 1, eep_data_word, addr_len);
+			}
+		}
+	}
+
+	spin_unlock_irq(&cp->lock);
+	return 0;
 }
 
 /* Put the board into D3cold state and wait for WakeUp signal */

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH 2.6.11.1] net/8139cp.c - get and set eeprom II
  2005-03-24 15:02 [PATCH 2.6.11.1] net/8139cp.c - get and set eeprom II Jyri Reitel
@ 2005-03-25  4:06 ` Jeff Garzik
  0 siblings, 0 replies; 2+ messages in thread
From: Jeff Garzik @ 2005-03-25  4:06 UTC (permalink / raw)
  To: Jyri Reitel; +Cc: netdev, mroos, Francois Romieu

Jyri Reitel wrote:
> Hi. My next patch where removed the pci table modification because most people don't want (need) this.
> Also indentification should be ok now?
> 
> When answering please add jyri.reitel@mail.ee to the cc line, because i'm not the member of the mainling list
> 
> Signed-off-by: Jüri Reitel <jyri.reitel@mail.ee>
> 
> --- linux-2.6.11.1/drivers/net/8139cp.c.orig	Thu Mar 24 10:08:32 2005
> +++ linux-2.6.11.1/drivers/net/8139cp.c	Thu Mar 24 16:37:42 2005
> @@ -110,6 +110,11 @@ MODULE_PARM_DESC (multicast_filter_limit
>  #define TRUE (!FALSE)
>  #endif
>  
> +#define RTL8139_EEPROM_SIZE 128
> +static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data);
> +static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data);
> +static int get_eeprom_len(struct net_device *dev);
> +
>  #define CP_DEF_MSG_ENABLE	(NETIF_MSG_DRV		| \
>  				 NETIF_MSG_PROBE 	| \
>  				 NETIF_MSG_LINK)
> @@ -400,6 +405,15 @@ static struct pci_device_id cp_pci_tbl[]
>  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
>  	{ PCI_VENDOR_ID_TTTECH, PCI_DEVICE_ID_TTTECH_MC322,
>  	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
> +
> +	/* 
> +	* comment out this when the eeprom is corrupted or not preprogrammed
> +	* and you want this driver to be loaded, thus allowing to program 
> +	* the eeprom with ethtool
> +	* It would be good idea not to compile 8139too driver then
> +	{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8129,
> +	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
> +	*/

Please remove this.

Overall, it would be better to start a "librealtek" for common code like 
this.  There are bits which are the same between 8139too <-> 8139cp <-> 
r8169.


>  MODULE_DEVICE_TABLE(pci, cp_pci_tbl);
> @@ -1543,6 +1557,9 @@ static struct ethtool_ops cp_ethtool_ops
>  	.set_wol		= cp_set_wol,
>  	.get_strings		= cp_get_strings,
>  	.get_ethtool_stats	= cp_get_ethtool_stats,
> +	.get_eeprom		= get_eeprom,
> +	.set_eeprom		= set_eeprom,
> +	.get_eeprom_len		= get_eeprom_len,
>  };
>  
>  static int cp_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
> @@ -1566,8 +1583,8 @@ static int cp_ioctl (struct net_device *
>  #define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */
>  #define EE_CS			0x08	/* EEPROM chip select. */
>  #define EE_DATA_WRITE	0x02	/* EEPROM chip data in. */
> -#define EE_WRITE_0		0x00
> -#define EE_WRITE_1		0x02
> +#define EE_WRITE_0		(0x00 | EE_ENB)
> +#define EE_WRITE_1		(0x02 | EE_ENB)
>  #define EE_DATA_READ	0x01	/* EEPROM chip data out. */
>  #define EE_ENB			(0x80 | EE_CS)
>  
> @@ -1582,7 +1599,7 @@ static int cp_ioctl (struct net_device *
>  #define EE_READ_CMD		(6)
>  #define EE_ERASE_CMD	(7)
>  
> -static int read_eeprom (void __iomem *ioaddr, int location, int addr_len)
> +static int read_eeprom(void __iomem *ioaddr, int location, int addr_len)
>  {
>  	int i;
>  	unsigned retval = 0;
> @@ -1608,8 +1625,7 @@ static int read_eeprom (void __iomem *io
>  		writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
>  		eeprom_delay ();
>  		retval =
> -		    (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
> -				     0);
> +		    (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 : 0);
>  		writeb (EE_ENB, ee_addr);
>  		eeprom_delay ();
>  	}
> @@ -1619,6 +1635,130 @@ static int read_eeprom (void __iomem *io
>  	eeprom_delay ();
>  
>  	return retval;
> +}
> +
> +/* This executes a generic EEPROM command, typically a write or write enable.
> +   It returns the data output from the EEPROM, and thus may also be used for
> +   reads. */
> +static int do_eeprom_cmd(void __iomem *ioaddr, int cmd, int cmd_len)
> +{
> +	unsigned retval = 0;
> +	void __iomem *ee_addr = ioaddr + Cfg9346;
> +
> +	writeb(EE_ENB | EE_SHIFT_CLK, ee_addr);
> +
> +	/* Shift the command bits out. */
> +	do {
> +		short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0;
> +		writeb(dataval, ee_addr);
> +		eeprom_delay();
> +		writeb(dataval | EE_SHIFT_CLK, ee_addr);
> +		eeprom_delay();
> +		retval = (retval << 1) | ((readb(ee_addr) & EE_DATA_READ) ? 1 : 0);
> +	} while (--cmd_len >= 0);

add a blank line here


> +	writeb(EE_ENB, ee_addr);
> +
> +	/* Terminate the EEPROM access. */
> +	writeb(EE_ENB & ~EE_CS, ee_addr);
> +	writeb(~EE_CS, ee_addr);
> +	return retval;
> +}
> +
> +
> +static void write_eeprom(void __iomem *ioaddr, int index, u16 value, int ee_addr_size)
> +{
> +	int i;
> +	/* Enable programming modes. */
> +	do_eeprom_cmd(ioaddr, (0x4f << (ee_addr_size - 4)), 3 + ee_addr_size);
> +	/* Do the actual write. */
> +	do_eeprom_cmd(ioaddr,
> +		(((EE_WRITE_CMD << ee_addr_size) | index) << 16) | value,
> +		3 + ee_addr_size + 16
> +	);

style:  don't put the ");" by itself on a line.  Nowhere else in the 
driver is this done.


> +	/* Poll for write finished. */
> +	writeb(EE_ENB, ioaddr + Cfg9346);
> +	for (i = 0; i < 10000; i++)			/* Typical 2000 ticks */
> +		if (readb(ioaddr + Cfg9346) & EE_DATA_READ)
> +			break;

I'm worried about doing this under spin_lock_irq(), but I guess it's ok.


> +	/* Disable programming. */
> +	do_eeprom_cmd(ioaddr, (0x40 << (ee_addr_size - 4)), 3 + ee_addr_size);
> +}
> +
> +
> +static int get_eeprom_len(struct net_device *dev)
> +{
> +	return RTL8139_EEPROM_SIZE;
> +}
> +
> +static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
> +{
> +	struct cp_private *cp = netdev_priv(dev);
> +	unsigned int addr_len;
> +	u16 eep_data_word = 0;
> +	u32 i;
> +
> +	eeprom->magic = PCI_VENDOR_ID_REALTEK | (PCI_DEVICE_ID_REALTEK_8139 << 16);

add blank line here

> +	spin_lock_irq(&cp->lock);
> +
> +	addr_len = (read_eeprom(cp->regs, 0, 8) == 0x8129)? 8 : 6;
> +
> +	/* reading word by word from the eeprom */
> +
> +	if (eeprom->offset & 1) {
> +		/* offset is odd */
> +		eep_data_word = le16_to_cpu(read_eeprom(cp->regs, eeprom->offset >> 1, addr_len));
> +	}

don't add braces {} for just one C statement


> +	for (i = eeprom->offset; i < (eeprom->offset + eeprom->len); i++) {
> +		if (i & 1) {
> +			/* copy odd byte */
> +			data[i - eeprom->offset] = (u8)(eep_data_word >> 8);

ditto


> +		} else {
> +			/* reading even byte so lets fech next word from eeprom */
> +			eep_data_word = le16_to_cpu(read_eeprom(cp->regs, i >> 1, addr_len));
> +			data[i - eeprom->offset] = (u8)eep_data_word;
> +		}
> +	}
> +	spin_unlock_irq(&cp->lock);
> +	return 0;
> +}
> +
> +static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *data)
> +{
> +	struct cp_private *cp = netdev_priv(dev);
> +	unsigned int addr_len;
> +	u16 eep_data_word = 0;
> +	u32 i;
> +	/*
> +	if(eeprom->magic != (PCI_VENDOR_ID_REALTEK | (PCI_DEVICE_ID_REALTEK_8139 << 16))) {
> +		return -ENODEV;
> +	}

ditto


> +	*/
> +	spin_lock_irq(&cp->lock);
> +
> +	addr_len = (read_eeprom(cp->regs, 0, 8) == 0x8129)? 8 : 6;
> +
> +	if (eeprom->offset & 1) {
> +		/* offset is odd, so read the word to later replace MSB byte */
> +		eep_data_word = le16_to_cpu(read_eeprom(cp->regs, eeprom->offset >> 1, addr_len));
> +	}
> +	for (i = eeprom->offset; i < (eeprom->offset + eeprom->len); i++) {
> +		if (i & 1) {
> +			/* copy odd byte, to the word data to be stored to the eeprom */
> +			eep_data_word |= (u16)data[i - eeprom->offset] << 8;
> +			write_eeprom(cp->regs, i >> 1, eep_data_word, addr_len);
> +		} else {
> +			/* reading even byte so lets fech next word from eeprom */
> +			eep_data_word = (u16)data[i - eeprom->offset];
> +			if (i + 1 == (eeprom->offset + eeprom->len)) {
> +				/* when writing last byte that is LSB, i.e. must get the MSB from eeprom */
> +				eep_data_word |= le16_to_cpu(read_eeprom(cp->regs, i >> 1, addr_len)) & 0xFF00;
> +				write_eeprom(cp->regs, i >> 1, eep_data_word, addr_len);
> +			}
> +		}
> +	}
> +
> +	spin_unlock_irq(&cp->lock);
> +	return 0;
>  }
>  
>  /* Put the board into D3cold state and wait for WakeUp signal */

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2005-03-25  4:06 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-24 15:02 [PATCH 2.6.11.1] net/8139cp.c - get and set eeprom II Jyri Reitel
2005-03-25  4:06 ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).