#include #include #include #include #include #include #include #include "zap.h" extern int mdio_read(long ioaddr, int phy_id, int mii_reg_num); extern void mdio_write(int ioaddr, int phy_id, int location, int value); struct zap_phy { long ioaddr; int phy_id; int devad; int irq_fd; char aux_buf[16]; }; static bool phy_read(void *private, u32 addr, u32 *val) { struct zap_phy *phy = private; int v; v = mdio_read(phy->ioaddr, phy->phy_id | phy->devad, addr); *val = v >= 0 ? v : 0; return v >= 0; } static void phy_write(void *private, u32 addr, u32 val) { struct zap_phy *phy = private; mdio_write(phy->ioaddr, phy->phy_id | phy->devad, addr, val); } static void phy_c45_key(struct zap_private *priv, void *private, int key) { struct zap_phy *phy = private; int val; switch (key) { case 'r': val = mdio_read(phy->ioaddr, phy->phy_id | 7, 0); if (val < 0) return; mdio_write(phy->ioaddr, phy->phy_id | 7, 0, val | 0x200); break; case 'p': zap_prompt_input(priv, 'p', "PHY devad"); break; } } static void phy_c45_print_unit(void *private) { struct zap_phy *phy = private; const char *dev = ""; switch (phy->devad) { case 1: dev = " PMA/PMD"; break; case 2: dev = " WIS"; break; case 3: dev = " PCS"; break; case 4: dev = " PHYXS"; break; case 5: dev = " DTEXS"; break; case 7: dev = " AN"; break; } printw("PHY #%u.%-2u%s", (phy->phy_id >> 5) & 31, phy->devad, dev); clrtoeol(); } static void phy_c45_update_aux(void *private) { struct zap_phy *phy = private; char new[16]; int len; if (phy->irq_fd == -1) return; lseek(phy->irq_fd, 0, SEEK_SET); len = read(phy->irq_fd, new, sizeof(new)); if (len < 0 || len >= sizeof(new)) return; len -= 1; if (!memcmp(phy->aux_buf, new, len)) return; memcpy(phy->aux_buf, new, len); mvprintw(1, 41, "IRQ "); mvaddnstr(1, 45, new, len); clrtoeol(); } static void phy_c45_input(void *private, char mode, const char *buf) { struct zap_phy *phy = private; unsigned long unit; errno = 0; unit = strtoul(buf, NULL, 0); if (unit == ULONG_MAX && errno == ERANGE) return; if (unit > 31) return; phy->devad = unit; } static const struct zap phy_c45_zap = { .val_width = 4, .max_addr = 0xffff, .read = phy_read, .write = phy_write, .key = phy_c45_key, .print_header = phy_c45_print_unit, .update_aux = phy_c45_update_aux, .input = phy_c45_input, }; static void phy_print_c22_unit(void *private) { struct zap_phy *phy = private; printw("PHY #%u", phy->phy_id); } static const struct zap phy_c22_zap = { .val_width = 4, .max_addr = 0x1f, .read = phy_read, .write = phy_write, .print_header = phy_print_c22_unit, }; void phy_zap(long ioaddr, int phy_id, unsigned long start) { const struct zap *z; struct zap_phy phy = { .ioaddr = ioaddr, .irq_fd = -1, }; if (phy_id & 0x8000) { phy.phy_id = phy_id & ~31; phy.devad = phy_id & 31; if (phy_id == 0x8000) phy.irq_fd = open("/sys/class/gpio/gpio82/value", O_RDONLY); else if (phy_id == 0x8000 + 8 * 32) phy.irq_fd = open("/sys/class/gpio/gpio81/value", O_RDONLY); z = &phy_c45_zap; } else { phy.phy_id = phy_id; phy.devad = 0; z = &phy_c22_zap; } if (start >= z->max_addr) start = z->max_addr; zap(z, start, &phy); }