Index: if_wm.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_wm.c,v
retrieving revision 1.16
diff -c -r1.16 if_wm.c
*** if_wm.c	2002/08/07 04:53:18	1.16
--- if_wm.c	2002/08/07 23:42:13
***************
*** 303,308 ****
--- 303,309 ----
  
  /* sc_flags */
  #define	WM_F_HAS_MII		0x01	/* has MII */
+ #define	WM_F_EEPROM_HANDSHAKE	0x02	/* requires EEPROM handshake */
  
  #ifdef WM_EVENT_COUNTERS
  #define	WM_EVCNT_INCR(ev)	(ev)->ev_count++
***************
*** 474,479 ****
--- 475,504 ----
  	  "Intel i82544GC (LOM) 1000BASE-T Ethernet",
  	  WM_T_82544,		WMP_F_1000T },
  
+ 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82540EM,
+ 	  "Intel i82540EM 1000BASE-T Ethernet",
+ 	  WM_T_82540,		WMP_F_1000T },
+ 
+ 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82545EM_COPPER,
+ 	  "Intel i82545EM 1000BASE-T Ethernet",
+ 	  WM_T_82545,		WMP_F_1000T },
+ 
+ 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82546EB_COPPER,
+ 	  "Intel i82546EB 1000BASE-T Ethernet",
+ 	  WM_T_82546,		WMP_F_1000T },
+ 
+ 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82545EM_FIBER,
+ 	  "Intel i82545EM 1000BASE-X Ethernet",
+ 	  WM_T_82545,		WMP_F_1000X },
+ 
+ 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82546EB_FIBER,
+ 	  "Intel i82546EB 1000BASE-X Ethernet",
+ 	  WM_T_82546,		WMP_F_1000X },
+ 
+ 	{ PCI_VENDOR_INTEL,	PCI_PRODUCT_INTEL_82540EM_LOM,
+ 	  "Intel i82540EM (LOM) 1000BASE-T Ethernet",
+ 	  WM_T_82540,		WMP_F_1000T },
+ 
  	{ 0,			0,
  	  NULL,
  	  0,			0 },
***************
*** 572,577 ****
--- 597,608 ----
  	}
  
  	/*
+ 	 * Some chips require a handshake to access the EEPROM.
+ 	 */
+ 	if (sc->sc_type >= WM_T_82540)
+ 		sc->sc_flags |= WM_F_EEPROM_HANDSHAKE;
+ 
+ 	/*
  	 * Map the device.
  	 */
  	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, WM_PCI_MMBA);
***************
*** 718,723 ****
--- 749,763 ----
  	enaddr[4] = myea[2] & 0xff;
  	enaddr[5] = myea[2] >> 8;
  
+ 	/*
+ 	 * Toggle the LSB of the MAC address on the second port
+ 	 * of the i82546.
+ 	 */
+ 	if (sc->sc_type == WM_T_82546) {
+ 		if ((CSR_READ(sc, WMREG_STATUS) >> STATUS_FUNCID_SHIFT) & 1)
+ 			enaddr[5] ^= 1;
+ 	}
+ 
  	printf("%s: Ethernet address %s\n", sc->sc_dev.dv_xname,
  	    ether_sprintf(enaddr));
  
***************
*** 2136,2153 ****
  wm_read_eeprom(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
  {
  	uint32_t reg;
! 	int i, x;
  
  	for (i = 0; i < wordcnt; i++) {
! 		/* Send CHIP SELECT for one clock tick. */
! 		CSR_WRITE(sc, WMREG_EECD, EECD_CS);
  		delay(2);
  
  		/* Shift in the READ command. */
  		for (x = 3; x > 0; x--) {
- 			reg = EECD_CS;
  			if (UWIRE_OPC_READ & (1 << (x - 1)))
  				reg |= EECD_DI;
  			CSR_WRITE(sc, WMREG_EECD, reg);
  			delay(2);
  			CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
--- 2176,2229 ----
  wm_read_eeprom(struct wm_softc *sc, int word, int wordcnt, uint16_t *data)
  {
  	uint32_t reg;
! 	int i, x, addrbits = 6;
! 
  
  	for (i = 0; i < wordcnt; i++) {
! 		if (sc->sc_flags & WM_F_EEPROM_HANDSHAKE) {
! 			reg = CSR_READ(sc, WMREG_EECD);
! 
! 			/* Get number of address bits. */
! 			if (reg & EECD_EE_SIZE)
! 				addrbits = 8;
! 
! 			/* Request EEPROM access. */
! 			reg |= EECD_EE_REQ;
! 			CSR_WRITE(sc, WMREG_EECD, reg);
! 
! 			/* ..and wait for it to be granted. */
! 			for (i = 0; i < 100; i++) {
! 				reg = CSR_READ(sc, WMREG_EECD);
! 				if (reg & EECD_EE_GNT)
! 					break;
! 				delay(5);
! 			}
! 			if ((reg & EECD_EE_GNT) == 0) {
! 				printf("%s: could not acquire EEPROM GNT\n",
! 				    sc->sc_dev.dv_xname);
! 				*data = 0xffff;
! 				reg &= ~EECD_EE_REQ;
! 				CSR_WRITE(sc, WMREG_EECD, reg);
! 				continue;
! 			}
! 		} else
! 			reg = 0;
! 
! 		/* Clear SK and DI. */
! 		reg &= ~(EECD_SK | EECD_DI);
! 		CSR_WRITE(sc, WMREG_EECD, reg);
! 
! 		/* Set CHIP SELECT. */
! 		reg |= EECD_CS;
! 		CSR_WRITE(sc, WMREG_EECD, reg);
  		delay(2);
  
  		/* Shift in the READ command. */
  		for (x = 3; x > 0; x--) {
  			if (UWIRE_OPC_READ & (1 << (x - 1)))
  				reg |= EECD_DI;
+ 			else
+ 				reg &= ~EECD_DI;
  			CSR_WRITE(sc, WMREG_EECD, reg);
  			delay(2);
  			CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
***************
*** 2157,2166 ****
  		}
  
  		/* Shift in address. */
! 		for (x = 6; x > 0; x--) {
! 			reg = EECD_CS; 
  			if ((word + i) & (1 << (x - 1)))
  				reg |= EECD_DI;
  			CSR_WRITE(sc, WMREG_EECD, reg);
  			delay(2);
  			CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
--- 2233,2243 ----
  		}
  
  		/* Shift in address. */
! 		for (x = addrbits; x > 0; x--) {
  			if ((word + i) & (1 << (x - 1)))
  				reg |= EECD_DI;
+ 			else
+ 				reg &= ~EECD_DI;
  			CSR_WRITE(sc, WMREG_EECD, reg);
  			delay(2);
  			CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
***************
*** 2170,2176 ****
  		}
  
  		/* Shift out the data. */
! 		reg = EECD_CS;
  		data[i] = 0;
  		for (x = 16; x > 0; x--) {
  			CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
--- 2247,2253 ----
  		}
  
  		/* Shift out the data. */
! 		reg &= ~EECD_DI;
  		data[i] = 0;
  		for (x = 16; x > 0; x--) {
  			CSR_WRITE(sc, WMREG_EECD, reg | EECD_SK);
***************
*** 2182,2188 ****
  		}
  
  		/* Clear CHIP SELECT. */
! 		CSR_WRITE(sc, WMREG_EECD, 0);
  	}
  }
  
--- 2259,2273 ----
  		}
  
  		/* Clear CHIP SELECT. */
! 		reg &= ~EECD_CS;
! 		CSR_WRITE(sc, WMREG_EECD, reg);
! 		delay(2);
! 
! 		if (sc->sc_flags & WM_F_EEPROM_HANDSHAKE) {
! 			/* Release the EEPROM. */
! 			reg &= ~EECD_EE_REQ;
! 			CSR_WRITE(sc, WMREG_EECD, reg);
! 		}
  	}
  }
  
Index: if_wmreg.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/if_wmreg.h,v
retrieving revision 1.2
diff -c -r1.2 if_wmreg.h
*** if_wmreg.h	2002/07/14 00:56:22	1.2
--- if_wmreg.h	2002/08/07 23:42:14
***************
*** 201,206 ****
--- 201,208 ----
  #define	STATUS_LU	(1U << 1)	/* link up */
  #define	STATUS_TCKOK	(1U << 2)	/* Tx clock running */
  #define	STATUS_RBCOK	(1U << 3)	/* Rx clock running */
+ #define	STATUS_FUNCID_SHIFT 2		/* 82546 function ID */
+ #define	STATUS_FUNCID_MASK  3		/* ... */
  #define	STATUS_TXOFF	(1U << 4)	/* Tx paused */
  #define	STATUS_TBIMODE	(1U << 5)	/* fiber mode (Livengood) */
  #define	STATUS_SPEED(x)	((x) << 6)	/* speed indication */
***************
*** 225,230 ****
--- 227,237 ----
  #define	EECD_FWE(x)	((x) << 4)	/* flash write enable control */
  #define	EECD_FWE_DISABLED EECD_FWE(1)
  #define	EECD_FWE_ENABLED  EECD_FWE(2)
+ #define	EECD_EE_REQ	(1U << 6)	/* (shared) EEPROM request */
+ #define	EECD_EE_GNT	(1U << 7)	/* (shared) EEPROM grant */
+ #define	EECD_EE_PRES	(1U << 8)	/* EEPROM present */
+ #define	EECD_EE_SIZE	(1U << 9)	/* EEPROM size
+ 					   (0 = 64 word, 1 = 256 word) */
  
  #define	UWIRE_OPC_ERASE	0x04		/* MicroWire "erase" opcode */
  #define	UWIRE_OPC_WRITE	0x05		/* MicroWire "write" opcode */
