📄 athrs26_phy.c
字号:
** athrs26_phy_is_fdx - Determines whether the phy ports associated with the* specified device are FULL or HALF duplex.** RETURNS:* 1 --> FULL* 0 --> HALF*/intathrs26_phy_is_fdx(int ethUnit){ int phyUnit; uint32_t phyBase; uint32_t phyAddr; uint16_t phyHwStatus; int ii = 200; if (ethUnit == ENET_UNIT_LAN) return TRUE; for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) { if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (athrs26_phy_is_link_alive(phyUnit)) { phyBase = ATHR_PHYBASE(phyUnit); phyAddr = ATHR_PHYADDR(phyUnit); do { phy_reg_read(phyBase, phyAddr, ATHR_PHY_SPEC_STATUS, &phyHwStatus); sysMsDelay(10); } while((!(phyHwStatus & ATHR_STATUS_RESOVLED)) && --ii); if (phyHwStatus & ATHER_STATUS_FULL_DEPLEX) return TRUE; } } return FALSE;}/******************************************************************************** athrs26_phy_speed - Determines the speed of phy ports associated with the* specified device.** RETURNS:* AG7100_PHY_SPEED_10T, AG7100_PHY_SPEED_100TX;* AG7100_PHY_SPEED_1000T;*/BOOLathrs26_phy_speed(int ethUnit){ int phyUnit; uint16_t phyHwStatus; uint32_t phyBase; uint32_t phyAddr; int ii = 200; if (ethUnit == ENET_UNIT_LAN) return _100BASET; for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) { if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } if (athrs26_phy_is_link_alive(phyUnit)) { phyBase = ATHR_PHYBASE(phyUnit); phyAddr = ATHR_PHYADDR(phyUnit); do { phy_reg_read(phyBase, phyAddr, ATHR_PHY_SPEC_STATUS, &phyHwStatus); sysMsDelay(10); }while((!(phyHwStatus & ATHR_STATUS_RESOVLED)) && --ii); phyHwStatus = ((phyHwStatus & ATHER_STATUS_LINK_MASK) >> ATHER_STATUS_LINK_SHIFT); switch(phyHwStatus) { case 0: return _10BASET; case 1: return _100BASET; case 2: return _1000BASET; default: DRV_PRINT(DRV_DEBUG_PHYERROR, ("Unkown speed read!\n")); } } } return _10BASET;}/******************************************************************************* athr_phy_is_up -- checks for significant changes in PHY state.** A "significant change" is:* dropped link (e.g. ethernet cable unplugged) OR* autonegotiation completed + link (e.g. ethernet cable plugged in)** When a PHY is plugged in, phyLinkGained is called.* When a PHY is unplugged, phyLinkLost is called.*/intathrs26_phy_is_up(int ethUnit){ int phyUnit; uint16_t phyHwStatus; athrPhyInfo_t *lastStatus; int linkCount = 0; int lostLinks = 0; int gainedLinks = 0; uint32_t phyBase; uint32_t phyAddr;#ifdef CFG_ATHRHDR_REG /* if using header to config s26, the link of MAC0 should always be up */ if (ethUnit == ENET_UNIT_LAN) return 1;#endif for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) { if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ATHR_PHYBASE(phyUnit); phyAddr = ATHR_PHYADDR(phyUnit); lastStatus = &athrPhyInfo[phyUnit]; phy_reg_read(phyBase, phyAddr, ATHR_PHY_SPEC_STATUS, &phyHwStatus); if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */ /* See if we've lost link */ if (phyHwStatus & ATHR_STATUS_LINK_PASS) { linkCount++; } else { lostLinks++; DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d down\n", ethUnit, phyUnit)); lastStatus->isPhyAlive = FALSE; } } else { /* last known link status was DEAD */ /* Check for reset complete */ phy_reg_read(phyBase, phyAddr, ATHR_PHY_STATUS, &phyHwStatus); if (!ATHR_RESET_DONE(phyHwStatus)) continue; /* Check for AutoNegotiation complete */ if (ATHR_AUTONEG_DONE(phyHwStatus)) { //printk("autoneg done\n"); gainedLinks++; linkCount++; DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d up\n", ethUnit, phyUnit)); lastStatus->isPhyAlive = TRUE; } } } return (linkCount);#if 0 if (linkCount == 0) { if (lostLinks) { /* We just lost the last link for this MAC */ phyLinkLost(ethUnit); } } else { if (gainedLinks == linkCount) { /* We just gained our first link(s) for this MAC */ phyLinkGained(ethUnit); } }#endif}#ifdef CFG_ATHRHDR_ENvoid athr_hdr_timeout(void){ printf("%s\n",__func__); eth_halt(); NetState = NETLOOP_FAIL; }void athr_hdr_handler(uchar *recv_pkt, unsigned dest, unsigned src, unsigned len){ header_receive_pkt(recv_pkt); NetState = NETLOOP_SUCCESS;}static intathrs26_header_config_reg (struct eth_device *dev, uint8_t wr_flag, uint16_t reg_addr, uint16_t cmd_len, uint8_t *val){ at_header_t at_header; reg_cmd_t reg_cmd; uchar *AthrHdrPkt; AthrHdrPkt = NetTxPacket; if(AthrHdrPkt == NULL) { printf("Null packet\n"); return; } memset(AthrHdrPkt,0,60); /*fill at_header*/ at_header.reserved0 = 0x10; //default at_header.priority = 0; at_header.type = 0x5; at_header.broadcast = 0; at_header.from_cpu = 1; at_header.reserved1 = 0x01; //default at_header.port_num = 0; AthrHdrPkt[0] = at_header.port_num; AthrHdrPkt[0] |= at_header.reserved1 << 4; AthrHdrPkt[0] |= at_header.from_cpu << 6; AthrHdrPkt[0] |= at_header.broadcast << 7; AthrHdrPkt[1] = at_header.type; AthrHdrPkt[1] |= at_header.priority << 4; AthrHdrPkt[1] |= at_header.reserved0 << 6; /*fill reg cmd*/ if(cmd_len > 4) cmd_len = 4;//only support 32bits register r/w reg_cmd.reg_addr = reg_addr&0x3FFFC; reg_cmd.cmd_len = cmd_len; reg_cmd.cmd = wr_flag; reg_cmd.reserved2 = 0x5; //default reg_cmd.seq_num = seqcnt; AthrHdrPkt[2] = reg_cmd.reg_addr & 0xff; AthrHdrPkt[3] = (reg_cmd.reg_addr & 0xff00) >> 8; AthrHdrPkt[4] = (reg_cmd.reg_addr & 0x30000) >> 16; AthrHdrPkt[4] |= reg_cmd.cmd_len << 4; AthrHdrPkt[5] = reg_cmd.cmd << 4; AthrHdrPkt[5] |= reg_cmd.reserved2 << 5; AthrHdrPkt[6] = (reg_cmd.seq_num & 0x7f) << 1; AthrHdrPkt[7] = (reg_cmd.seq_num & 0x7f80) >> 7; AthrHdrPkt[8] = (reg_cmd.seq_num & 0x7f8000) >> 15; AthrHdrPkt[9] = (reg_cmd.seq_num & 0x7f800000) >> 23; /*fill reg data*/ if(!wr_flag)//write memcpy((AthrHdrPkt + 10), val, cmd_len); /*start xmit*/ if(dev == NULL) { printf("ERROR device not found\n"); return -1; } header_xmit(dev, AthrHdrPkt ,60); return 0;}void athr_hdr_func(void) { NetSetTimeout (1 * CFG_HZ,athr_hdr_timeout ); NetSetHandler (athr_hdr_handler); if(cmd) athrs26_header_config_reg(lan_mac, cmd, cmd_read.reg_addr, cmd_read.cmd_len, cmd_read.reg_data); else athrs26_header_config_reg(lan_mac, cmd, cmd_write.reg_addr, cmd_write.cmd_len, cmd_write.reg_data);}static intathrs26_header_write_reg(uint16_t reg_addr, uint16_t cmd_len, uint8_t *reg_data){ int i = 2; cmd_write.reg_addr = reg_addr; cmd_write.cmd_len = cmd_len; cmd_write.reg_data = reg_data; cmd = 0; seqcnt++; do { if (NetLoop(ATHRHDR) >= 0) /* polls for read/write ack from PHY */ break; } while (i--); return i;}static intathrs26_header_read_reg(uint16_t reg_addr, uint16_t cmd_len, uint8_t *reg_data){ int i = 2; cmd_read.reg_addr = reg_addr; cmd_read.cmd_len = cmd_len; cmd_read.reg_data = reg_data; cmd = 1; seqcnt++; do { if (NetLoop(ATHRHDR) >= 0) /* polls for read/write ack from PHY */ break; } while (i--); if ((i==0) || (seqcnt != cmd_resp.seq) || (cmd_len != cmd_resp.len)) { return -1; } memcpy (cmd_read.reg_data, cmd_resp.data, cmd_len); return 0;}int header_receive_pkt(uchar *recv_pkt){ cmd_resp.len = recv_pkt[4] >> 4; if (cmd_resp.len > 10) goto out; cmd_resp.seq = recv_pkt[6] >> 1; cmd_resp.seq |= recv_pkt[7] << 7; cmd_resp.seq |= recv_pkt[8] << 15; cmd_resp.seq |= recv_pkt[9] << 23; if (cmd_resp.seq < seqcnt) goto out; memcpy (cmd_resp.data, (recv_pkt + 10), cmd_resp.len);out: return 0;}void athrs26_reg_dev(struct eth_device *mac){ lan_mac = mac;}#endifstatic uint32_tathrs26_reg_read(uint16_t reg_addr){#ifndef CFG_ATHRHDR_REG uint16_t reg_word_addr = reg_addr / 2, phy_val; uint32_t phy_addr; uint8_t phy_reg; /* configure register high address */ phy_addr = 0x18; phy_reg = 0x0; phy_val = (reg_word_addr >> 8) & 0x1ff; /* bit16-8 of reg address*/ phy_reg_write (0, phy_addr, phy_reg, phy_val); /* read register with low address */ phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */ phy_reg = reg_word_addr & 0x1f; /* bit 4-0 of reg address*/ phy_reg_read(0, phy_addr, phy_reg, &phy_val); return phy_val;#else uint8_t reg_data[4]; memset (reg_data, 0, 4); athrs26_header_read_reg(reg_addr, 4, reg_data); return (reg_data[0] | (reg_data[1] << 8) | (reg_data[2] << 16) | (reg_data[3] << 24));#endif}static voidathrs26_reg_write(uint16_t reg_addr, uint32_t reg_val){#ifndef CFG_ATHRHDR_REG uint16_t reg_word_addr = reg_addr / 2, phy_val; uint32_t phy_addr; uint8_t phy_reg; /* configure register high address */ phy_addr = 0x18; phy_reg = 0x0; phy_val = (reg_word_addr >> 8) & 0x1ff; /* bit16-8 of reg address*/ phy_reg_write (0, phy_addr, phy_reg, phy_val); /* read register with low address */ phy_addr = 0x10 | ((reg_word_addr >> 5) & 0x7); /* bit7-5 of reg address */ phy_reg = reg_word_addr & 0x1f; /* bit 4-0 of reg address */ phy_reg_write (0, phy_addr, phy_reg, reg_val);#else uint8_t reg_data[4]; memset (reg_data, 0, 4); reg_data[0] = (uint8_t)(0x00ff & reg_val); reg_data[1] = (uint8_t)((0xff00 & reg_val) >> 8); reg_data[2] = (uint8_t)((0xff0000 & reg_val) >> 16); reg_data[3] = (uint8_t)((0xff000000 & reg_val) >> 24); athrs26_header_write_reg (reg_addr, 4, reg_data);#endif}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -