/* * Copyright (c) 2004, 2005 Zultys Technologies * Eugene Surovegin or */ #include #include #include #include "internal.h" /* Ethtool get_regs complex data. * we want to get not just EMAC registers, but also MAL, ZMII, RGMII, TAH * when available. * * Returned BLOB consists of the ibm_emac_ethtool_regs_hdr, * MAL registers, EMAC registers and optional ZMII, RGMII, TAH registers. * Each register component is preceded with emac_ethtool_regs_subhdr. * Order of the optional headers follows their relative bit posititions * in emac_ethtool_regs_hdr.components */ #define EMAC_ETHTOOL_REGS_ZMII 0x00000001 #define EMAC_ETHTOOL_REGS_RGMII 0x00000002 #define EMAC_ETHTOOL_REGS_TAH 0x00000004 #define EMAC_VERSION 3 #define EMAC4_VERSION 4 #define EMAC4SYNC_VERSION 5 struct emac_ethtool_regs_hdr { u32 components; }; struct emac_ethtool_regs_subhdr { u32 version; u32 index; }; struct emac_regs { /* Common registers across all EMAC implementations. */ u32 mr0; /* Special */ u32 mr1; /* Reset */ u32 tmr0; /* Special */ u32 tmr1; /* Special */ u32 rmr; /* Reset */ u32 isr; /* Always */ u32 iser; /* Reset */ u32 iahr; /* Reset, R, T */ u32 ialr; /* Reset, R, T */ u32 vtpid; /* Reset, R, T */ u32 vtci; /* Reset, R, T */ u32 ptr; /* Reset, T */ union { /* Registers unique to EMAC4 implementations */ struct { u32 iaht1; /* Reset, R */ u32 iaht2; /* Reset, R */ u32 iaht3; /* Reset, R */ u32 iaht4; /* Reset, R */ u32 gaht1; /* Reset, R */ u32 gaht2; /* Reset, R */ u32 gaht3; /* Reset, R */ u32 gaht4; /* Reset, R */ } emac4; /* Registers unique to EMAC4SYNC implementations */ struct { u32 mahr; /* Reset, R, T */ u32 malr; /* Reset, R, T */ u32 mmahr; /* Reset, R, T */ u32 mmalr; /* Reset, R, T */ u32 rsvd0[4]; } emac4sync; } u0; /* Common registers across all EMAC implementations. */ u32 lsah; u32 lsal; u32 ipgvr; /* Reset, T */ u32 stacr; /* Special */ u32 trtr; /* Special */ u32 rwmr; /* Reset */ u32 octx; u32 ocrx; union { /* Registers unique to EMAC4 implementations */ struct { u32 ipcr; } emac4; /* Registers unique to EMAC4SYNC implementations */ struct { u32 rsvd1; u32 revid; u32 rsvd2[2]; u32 iaht1; /* Reset, R */ u32 iaht2; /* Reset, R */ u32 iaht3; /* Reset, R */ u32 iaht4; /* Reset, R */ u32 iaht5; /* Reset, R */ u32 iaht6; /* Reset, R */ u32 iaht7; /* Reset, R */ u32 iaht8; /* Reset, R */ u32 gaht1; /* Reset, R */ u32 gaht2; /* Reset, R */ u32 gaht3; /* Reset, R */ u32 gaht4; /* Reset, R */ u32 gaht5; /* Reset, R */ u32 gaht6; /* Reset, R */ u32 gaht7; /* Reset, R */ u32 gaht8; /* Reset, R */ u32 tpc; /* Reset, T */ } emac4sync; } u1; }; struct mal_regs { u32 tx_count; u32 rx_count; u32 cfg; u32 esr; u32 ier; u32 tx_casr; u32 tx_carr; u32 tx_eobisr; u32 tx_deir; u32 rx_casr; u32 rx_carr; u32 rx_eobisr; u32 rx_deir; u32 tx_ctpr[32]; u32 rx_ctpr[32]; u32 rcbs[32]; }; struct zmii_regs { u32 fer; u32 ssr; u32 smiisr; }; struct rgmii_regs { u32 fer; u32 ssr; }; struct tah_regs { u32 revid; u32 pad[3]; u32 mr; u32 ssr0; u32 ssr1; u32 ssr2; u32 ssr3; u32 ssr4; u32 ssr5; u32 tsr; }; static void *print_emac_regs(void *buf) { struct emac_ethtool_regs_subhdr *hdr = buf; struct emac_regs *p = (struct emac_regs *)(hdr + 1); void *res = p + 1; if (!((hdr->version == EMAC_VERSION) || (hdr->version == EMAC4_VERSION) || (hdr->version == EMAC4SYNC_VERSION))) { printf("This driver version doesn't support information\n" " output for EMAC area, please update it or use older\n" " ethtool version\n"); return res; } printf("EMAC%d Registers\n", hdr->index); printf("-----------------\n"); printf("MR0 = 0x%08x MR1 = 0x%08x RMR = 0x%08x\n" "ISR = 0x%08x ISER = 0x%08x\n" "TMR0 = 0x%08x TMR1 = 0x%08x\n" "TRTR = 0x%08x RWMR = 0x%08x\n" "IAR = %04x%08x\n" "LSA = %04x%08x\n" "VTPID = 0x%04x VTCI = 0x%04x\n" "IPGVR = 0x%04x STACR = 0x%08x\n" "OCTX = 0x%08x OCRX = 0x%08x\n", p->mr0, p->mr1, p->rmr, p->isr, p->iser, p->tmr0, p->tmr1, p->trtr, p->rwmr, p->iahr, p->ialr, p->lsah, p->lsal, p->vtpid, p->vtci, p->ipgvr, p->stacr, p->octx, p->ocrx); if (hdr->version == EMAC4SYNC_VERSION) { printf("MAHR = 0x%08x MALR = 0x%08x MMAHR = 0x%08x\n" "MMALR = 0x%08x REVID = 0x%08x\n", p->u0.emac4sync.mahr, p->u0.emac4sync.malr, p->u0.emac4sync.mmahr, p->u0.emac4sync.mmalr, p->u1.emac4sync.revid); printf("IAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", p->u1.emac4sync.iaht1, p->u1.emac4sync.iaht2, p->u1.emac4sync.iaht3, p->u1.emac4sync.iaht4); printf(" 0x%04x 0x%04x 0x%04x 0x%04x\n", p->u1.emac4sync.iaht5, p->u1.emac4sync.iaht6, p->u1.emac4sync.iaht7, p->u1.emac4sync.iaht8); printf("GAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", p->u1.emac4sync.gaht1, p->u1.emac4sync.gaht2, p->u1.emac4sync.gaht3, p->u1.emac4sync.gaht4); printf(" 0x%04x 0x%04x 0x%04x 0x%04x\n\n", p->u1.emac4sync.gaht5, p->u1.emac4sync.gaht6, p->u1.emac4sync.gaht7, p->u1.emac4sync.gaht8); } else if (hdr->version == EMAC4_VERSION) { printf("IAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", p->u0.emac4.iaht1, p->u0.emac4.iaht2, p->u0.emac4.iaht3, p->u0.emac4.iaht4); printf("GAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", p->u0.emac4.gaht1, p->u0.emac4.gaht2, p->u0.emac4.gaht3, p->u0.emac4.gaht4); printf(" IPCR = 0x%08x\n\n", p->u1.emac4.ipcr); } else if (hdr->version == EMAC_VERSION) { printf("IAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", p->u0.emac4.iaht1, p->u0.emac4.iaht2, p->u0.emac4.iaht3, p->u0.emac4.iaht4); printf("GAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n", p->u0.emac4.gaht1, p->u0.emac4.gaht2, p->u0.emac4.gaht3, p->u0.emac4.gaht4); } return res; } static void *print_mal_regs(void *buf) { struct emac_ethtool_regs_subhdr *hdr = buf; struct mal_regs *p = (struct mal_regs *)(hdr + 1); int i; printf("MAL%d Registers\n", hdr->index); printf("-----------------\n"); printf("CFG = 0x%08x ESR = 0x%08x IER = 0x%08x\n" "TX|CASR = 0x%08x CARR = 0x%08x EOBISR = 0x%08x DEIR = 0x%08x\n" "RX|CASR = 0x%08x CARR = 0x%08x EOBISR = 0x%08x DEIR = 0x%08x\n", p->cfg, p->esr, p->ier, p->tx_casr, p->tx_carr, p->tx_eobisr, p->tx_deir, p->rx_casr, p->rx_carr, p->rx_eobisr, p->rx_deir); printf("TX|"); for (i = 0; i < p->tx_count; ++i) { if (i && !(i % 4)) printf("\n "); printf("CTP%d = 0x%08x ", i, p->tx_ctpr[i]); } printf("\nRX|"); for (i = 0; i < p->rx_count; ++i) { if (i && !(i % 4)) printf("\n "); printf("CTP%d = 0x%08x ", i, p->rx_ctpr[i]); } printf("\n "); for (i = 0; i < p->rx_count; ++i) { u32 r = p->rcbs[i]; if (i && !(i % 3)) printf("\n "); printf("RCBS%d = 0x%08x (%d) ", i, r, r * 16); } printf("\n\n"); return p + 1; } static void *print_zmii_regs(void *buf) { struct emac_ethtool_regs_subhdr *hdr = buf; struct zmii_regs *p = (struct zmii_regs *)(hdr + 1); printf("ZMII%d Registers\n", hdr->index); printf("-----------------\n"); printf("FER = %08x SSR = %08x\n" "SMIISR = %08x\n\n", p->fer, p->ssr, p->smiisr); return p + 1; } static void *print_rgmii_regs(void *buf) { struct emac_ethtool_regs_subhdr *hdr = buf; struct rgmii_regs *p = (struct rgmii_regs *)(hdr + 1); printf("RGMII%d Registers\n", hdr->index); printf("-----------------\n"); printf("FER = %08x SSR = %08x\n\n", p->fer, p->ssr); return p + 1; } static void *print_tah_regs(void *buf) { struct emac_ethtool_regs_subhdr *hdr = buf; struct tah_regs *p = (struct tah_regs *)(hdr + 1); printf("TAH%d Registers\n", hdr->index); printf("-----------------\n"); printf("REVID = %08x MR = %08x TSR = %08x\n" "SSR0 = %08x SSR1 = %08x SSR2 = %08x\n" "SSR3 = %08x SSR4 = %08x SSR5 = %08x\n\n", p->revid, p->mr, p->tsr, p->ssr0, p->ssr1, p->ssr2, p->ssr3, p->ssr4, p->ssr5); return p + 1; } int ibm_emac_dump_regs(struct ethtool_drvinfo *info maybe_unused, struct ethtool_regs *regs) { struct emac_ethtool_regs_hdr *hdr = (struct emac_ethtool_regs_hdr *)regs->data; void *buf = hdr + 1; buf = print_mal_regs(buf); buf = print_emac_regs(buf); if (hdr->components & EMAC_ETHTOOL_REGS_ZMII) buf = print_zmii_regs(buf); if (hdr->components & EMAC_ETHTOOL_REGS_RGMII) buf = print_rgmii_regs(buf); if (hdr->components & EMAC_ETHTOOL_REGS_TAH) print_tah_regs(buf); return 0; }