ETRAX-FS: Correct ethernet PHY diagnostics register reads.
* Correct ethernet PHY diagnostics register reads. * Add friendly names for the speed/duplex fields. * Report duplex mismatches between MAC and PHY. git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5300 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									9d92659858
								
							
						
					
					
						commit
						c64882682d
					
				| @ -30,6 +30,12 @@ | ||||
| 
 | ||||
| #define D(x) | ||||
| 
 | ||||
| /* Advertisement control register. */ | ||||
| #define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */ | ||||
| #define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */ | ||||
| #define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */ | ||||
| #define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */ | ||||
| 
 | ||||
| /* 
 | ||||
|  * The MDIO extensions in the TDK PHY model were reversed engineered from the  | ||||
|  * linux driver (PHYID and Diagnostics reg). | ||||
| @ -78,9 +84,12 @@ static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req) | ||||
| 			int speed_100 = 0; | ||||
| 
 | ||||
| 			/* Are we advertising 100 half or 100 duplex ? */ | ||||
| 			speed_100 = !!(phy->regs[4] & 0x180); | ||||
| 			speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF); | ||||
| 			speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL); | ||||
| 
 | ||||
| 			/* Are we advertising 10 duplex or 100 duplex ? */ | ||||
| 			duplex = !!(phy->regs[4] & 0x180); | ||||
| 			duplex = !!(phy->regs[4] & ADVERTISE_100FULL); | ||||
| 			duplex |= !!(phy->regs[4] & ADVERTISE_10FULL); | ||||
| 			r = (speed_100 << 10) | (duplex << 11); | ||||
| 		} | ||||
| 		break; | ||||
| @ -322,10 +331,40 @@ struct fs_eth | ||||
| 
 | ||||
| 	/* MDIO bus.  */ | ||||
| 	struct qemu_mdio mdio_bus; | ||||
| 	unsigned int phyaddr; | ||||
| 	int duplex_mismatch; | ||||
| 
 | ||||
| 	/* PHY.	 */ | ||||
| 	struct qemu_phy phy; | ||||
| }; | ||||
| 
 | ||||
| static void eth_validate_duplex(struct fs_eth *eth) | ||||
| { | ||||
| 	struct qemu_phy *phy; | ||||
| 	unsigned int phy_duplex; | ||||
| 	unsigned int mac_duplex; | ||||
| 	int new_mm = 0; | ||||
| 
 | ||||
| 	phy = eth->mdio_bus.devs[eth->phyaddr]; | ||||
| 	phy_duplex = !!(phy->read(phy, 18) & (1 << 11)); | ||||
| 	mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128); | ||||
| 
 | ||||
| 	if (mac_duplex != phy_duplex) | ||||
| 		new_mm = 1; | ||||
| 
 | ||||
| 	if (eth->regs[RW_GEN_CTRL] & 1) { | ||||
| 		if (new_mm != eth->duplex_mismatch) { | ||||
| 			if (new_mm) | ||||
| 				printf("HW: WARNING " | ||||
| 				       "ETH duplex mismatch MAC=%d PHY=%d\n", | ||||
| 				       mac_duplex, phy_duplex); | ||||
| 			else | ||||
| 				printf("HW: ETH duplex ok.\n"); | ||||
| 		} | ||||
| 		eth->duplex_mismatch = new_mm; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static uint32_t eth_rinvalid (void *opaque, target_phys_addr_t addr) | ||||
| { | ||||
| 	struct fs_eth *eth = opaque; | ||||
| @ -418,11 +457,18 @@ eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value) | ||||
| 			/* Attach an MDIO/PHY abstraction.  */ | ||||
| 			if (value & 2) | ||||
| 				eth->mdio_bus.mdio = value & 1; | ||||
| 			if (eth->mdio_bus.mdc != (value & 4)) | ||||
| 			if (eth->mdio_bus.mdc != (value & 4)) { | ||||
| 				mdio_cycle(ð->mdio_bus); | ||||
| 				eth_validate_duplex(eth); | ||||
| 			} | ||||
| 			eth->mdio_bus.mdc = !!(value & 4); | ||||
| 			break; | ||||
| 
 | ||||
| 		case RW_REC_CTRL: | ||||
| 			eth->regs[addr] = value; | ||||
| 			eth_validate_duplex(eth); | ||||
| 			break; | ||||
| 
 | ||||
| 		default: | ||||
| 			eth->regs[addr] = value; | ||||
| 			D(printf ("%s %x %x\n", | ||||
| @ -591,8 +637,9 @@ void *etraxfs_eth_init(NICInfo *nd, CPUState *env, | ||||
| 	eth->dma_in = dma + 1; | ||||
| 
 | ||||
| 	/* Connect the phy.  */ | ||||
| 	eth->phyaddr = 1; | ||||
| 	tdk_init(ð->phy); | ||||
| 	mdio_attach(ð->mdio_bus, ð->phy, 0x1); | ||||
| 	mdio_attach(ð->mdio_bus, ð->phy, eth->phyaddr); | ||||
| 
 | ||||
| 	eth->ethregs = cpu_register_io_memory(0, eth_read, eth_write, eth); | ||||
| 	cpu_register_physical_memory (base, 0x5c, eth->ethregs); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 edgar_igl
						edgar_igl