i did notice some odd dmesg output, however:
eth%d: enabling 64 bit PCI.
eth%d: enabling optical transceiver
eth1: ns83820.c v0.13: DP83820 00:40:f4:29:ea:d7 pciaddr=0xe1000000
irq=12 rev 0x103
eth1: link now 1000F mbps, full duplex and up.
eth1: link now 1000F mbps, full duplex and up.
[now keeping in mind i know nothing of linux device drivers...]
this is only a 32bit pci box so why would it enable 64bit pci?
are references to dev->net_dev.name valid before
register_netdev(&dev->net_dev) in ns83820_init_one()?
is/why phy_intr() called 2wice?
thanks for the patch!
rob.
On Tue, 2001-12-04 at 10:35, Michael Clark wrote:
> Hi,
> 
> This patch adds Netgear GA621 support to the ns83820 driver
> by adding code to configure the optical transceiver on
> these boards. People currently using Netgear driver (gam)
> may like to test this.
> 
> I decided to add support for GA621 to the ns83820 driver after
> suffering an oops with the netgear supplied driver whose code
> is rather convoluted on not very Linux like (appears to be a
> port of a NDIS driver) ie. it won't probably ever make it into
> the kernel without a lot of rework.
> 
> It would be good if someone could test this on copper
> cards to make sure it still works okay.
> 
> ~mc
> 
> ----
> 
> --- linux/drivers/net/ns83820.c.orig	Tue Dec  4 20:27:10 2001
> +++ linux/drivers/net/ns83820.c	Tue Dec  4 23:33:34 2001
> @@ -43,10 +43,12 @@
>   *			       otherwise fragments get lost
>   *			     - fix >> 32 bugs
>   *			0.12 - add statistics counters
>   *			     - add allmulti/promisc support
>   *	20011009	0.13 - hotplug support, other smaller pci api cleanups
> + *	20011204	0.13a - optical transceiver support added
> + *			        by Michael Clark <michael@metaparadigm.com>
>   *
>   * Driver Overview
>   * ===============
>   *
>   * This driver was originally written for the National Semiconductor
> @@ -63,10 +65,11 @@
>   *
>   *	Cameo		SOHO-GA2000T	SOHO-GA2500T
>   *	D-Link		DGE-500T
>   *	PureData	PDP8023Z-TG
>   *	SMC		SMC9452TX	SMC9462TX
> + *	Netgear		GA621
>   *
>   * Special thanks to SMC for providing hardware to test this driver on.
>   *
>   * Reports of success or failure would be greatly appreciated.
>   */
> @@ -210,10 +213,11 @@
>  #define CFG_SPDSTS	0x60000000
>  #define CFG_SPDSTS1	0x40000000
>  #define CFG_SPDSTS0	0x20000000
>  #define CFG_DUPSTS	0x10000000
>  #define CFG_TBI_EN	0x01000000
> +#define CFG_AUTO_1000	0x00200000
>  #define CFG_MODE_1000	0x00400000
>  #define CFG_PINT_CTL	0x001c0000
>  #define CFG_PINT_DUPSTS	0x00100000
>  #define CFG_PINT_LNKSTS	0x00080000
>  #define CFG_PINT_SPDSTS	0x00040000
> @@ -314,10 +318,44 @@
>  #define VRCR		0xbc
>  #define VTCR		0xc0
>  #define VDR		0xc4
>  #define CCSR		0xcc
>  
> +#define TBICR		0xe0
> +#define TBISR		0xe4
> +#define TANAR		0xe8
> +#define TANLPAR		0xec
> +#define TANER		0xf0
> +#define TESR		0xf4
> +
> +/* TBICR bit definitions */
> +
> +#define MR_AN_ENABLE 		0x00001000
> +#define MR_RESTART_AN 		0x00000200
> +
> +/* TBISR bit definitions */
> +
> +#define MR_LINK_STATUS 		0x00000020
> +#define MR_AN_COMPLETE 		0x00000004
> +
> +/* TANAR, TANALPAR bit definitions */
> +
> +#define PS2 			0x00000100
> +#define PS1 			0x00000080
> +#define HALF_DUP 		0x00000040
> +#define FULL_DUP 		0x00000020
> +
> +/* GPIOR bit definitions */
> +
> +#define GP5_OE			0x00000200
> +#define GP4_OE			0x00000100
> +#define GP3_OE			0x00000080
> +#define GP2_OE			0x00000040
> +#define GP1_OE			0x00000020
> +#define GP3_OUT			0x00000004
> +#define GP1_OUT			0x00000001
> +
>  #define __kick_rx(dev)	writel(CR_RXE, dev->base + CR)
>  
>  #define kick_rx(dev) do { \
>  	dprintk("kick_rx: maybe kicking\n"); \
>  	if (test_and_clear_bit(0, &dev->rx_info.idle)) { \
> @@ -543,28 +581,82 @@
>  	build_rx_desc(dev, dev->rx_info.descs + (DESC_SIZE * i), 0, 0, CMDSTS_OWN, 0);
>  }
>  
>  static void phy_intr(struct ns83820 *dev)
>  {
> -	static char *speeds[] = { "10", "100", "1000", "1000(?)" };
> +	static char *speeds[] = { "10", "100", "1000", "1000(?)", "1000F" };
>  	u32 cfg, new_cfg;
> +	u32 tbisr, tanar, tanlpar;
> +	int speed, fullduplex = 0;
>  
> -	new_cfg = dev->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS);
>  	cfg = readl(dev->base + CFG) ^ SPDSTS_POLARITY;
>  
> -	if (cfg & CFG_SPDSTS1)
> -		new_cfg |= CFG_MODE_1000 | CFG_SB;
> -	else
> -		new_cfg &= ~CFG_MODE_1000 | CFG_SB;
> +	if (dev->CFG_cache & CFG_TBI_EN) {
>  
> -	if ((cfg & CFG_LNKSTS) && ((new_cfg ^ dev->CFG_cache) & CFG_MODE_1000)) {
> -		writel(new_cfg, dev->base + CFG);
> -		dev->CFG_cache = new_cfg;
> -	}
> +		/* we have an optical transceiver */
> +		tbisr = readl(dev->base + TBISR);
> +		tanar = readl(dev->base + TANAR);
> +		tanlpar = readl(dev->base + TANLPAR);
> +		dprintk("phy_intr: tbisr=%08x, tanar=%08x, tanlpar=%08x\n",
> +			tbisr, tanar, tanlpar);
> +
> +		if (!tanlpar && !tbisr) {
> +			dprintk("%s: waiting for autoneg to complete\n",
> +				dev->net_dev.name);
> +			return;
> +		}
> +
> +		if ( (fullduplex = (tanlpar & FULL_DUP)
> +		      && (tanar & FULL_DUP)) ) {
>  
> -	dev->CFG_cache &= ~CFG_SPDSTS;
> -	dev->CFG_cache |= cfg & CFG_SPDSTS;
> +			/* both of us are full duplex */
> +			writel(readl(dev->base + TXCFG)
> +			       | TXCFG_CSI | TXCFG_HBI | TXCFG_ATP,
> +			       dev->base + TXCFG);
> +			writel(readl(dev->base + RXCFG) | RXCFG_RX_FD,
> +			       dev->base + RXCFG);
> +			/* Light up full duplex LED */
> +			writel(readl(dev->base + GPIOR) | GP1_OUT,
> +			       dev->base + GPIOR);
> +
> +		} else if(((tanlpar & HALF_DUP) && (tanar & HALF_DUP))
> +			|| ((tanlpar & FULL_DUP) && (tanar & HALF_DUP))
> +			|| ((tanlpar & HALF_DUP) && (tanar & FULL_DUP))) {
> +
> +			/* one or both of us are half duplex */
> +			writel((readl(dev->base + TXCFG)
> +				& ~(TXCFG_CSI | TXCFG_HBI)) | TXCFG_ATP,
> +			       dev->base + TXCFG);
> +			writel(readl(dev->base + RXCFG) & ~RXCFG_RX_FD,
> +			       dev->base + RXCFG);
> +			/* Turn off full duplex LED */
> +			writel(readl(dev->base + GPIOR) & ~GP1_OUT,
> +			       dev->base + GPIOR);
> +		}
> +
> +		speed = 4; /* 1000F */
> +
> +	} else {
> +		/* we have a copper transceiver */
> +		new_cfg = dev->CFG_cache & ~(CFG_SB | CFG_MODE_1000 | CFG_SPDSTS);
> +
> +		if (cfg & CFG_SPDSTS1)
> +			new_cfg |= CFG_MODE_1000 | CFG_SB;
> +		else
> +			new_cfg &= ~CFG_MODE_1000 | CFG_SB;
> +
> +		if ((cfg & CFG_LNKSTS) && ((new_cfg ^ dev->CFG_cache) & CFG_MODE_1000)) {
> +			writel(new_cfg, dev->base + CFG);
> +			dev->CFG_cache = new_cfg;
> +		}
> +
> +		dev->CFG_cache &= ~CFG_SPDSTS;
> +		dev->CFG_cache |= cfg & CFG_SPDSTS;
> +
> +		speed = ((cfg / CFG_SPDSTS0) & 3);
> +		fullduplex = (cfg & CFG_DUPSTS);
> +	}
>  
>  	if (cfg & CFG_LNKSTS) {
>  		netif_start_queue(&dev->net_dev);
>  		netif_wake_queue(&dev->net_dev);
>  	} else {
> @@ -572,12 +664,12 @@
>  	}
>  
>  	if (cfg & CFG_LNKSTS)
>  		printk(KERN_INFO "%s: link now %s mbps, %s duplex and up.\n",
>  			dev->net_dev.name,
> -			speeds[((cfg / CFG_SPDSTS0) & 3)],
> -			(cfg & CFG_DUPSTS) ? "full" : "half");
> +			speeds[speed],
> +			fullduplex ? "full" : "half");
>  	else
>  		printk(KERN_INFO "%s: link now down.\n", dev->net_dev.name);
>  }
>  
>  static int ns83820_setup_rx(struct ns83820 *dev)
> @@ -1341,10 +1433,27 @@
>  	dev->CFG_cache |= CFG_BEM;
>  #else
>  #error This driver only works for big or little endian!!!
>  #endif
>  
> +	/* setup optical transceiver if we have one */
> +	if(dev->CFG_cache & CFG_TBI_EN) {
> +		printk("%s: enabling optical transceiver\n",
> +		       dev->net_dev.name);
> +		writel(readl(dev->base + GPIOR) | 0x3e8, dev->base + GPIOR);
> +
> +		/* setup auto negotiation feature advertisement */
> +		writel(readl(dev->base + TANAR) | HALF_DUP | FULL_DUP,
> +		       dev->base + TANAR);
> +
> +		/* start auto negotiation */
> +		writel(MR_AN_ENABLE | MR_RESTART_AN, dev->base + TBICR);
> +		writel(MR_AN_ENABLE, dev->base + TBICR);
> +
> +		dev->CFG_cache |= CFG_MODE_1000;
> +	}
> +
>  	writel(dev->CFG_cache, dev->base + CFG);
>  	dprintk("CFG: %08x\n", dev->CFG_cache);
>  
>  	if (readl(dev->base + SRR))
>  		writel(readl(dev->base+0x20c) | 0xfe00, dev->base + 0x20c);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/