Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci - use mii(4) layer to control KSZ8841 builtin PHY.



details:   https://anonhg.NetBSD.org/src/rev/89a416488449
branches:  trunk
changeset: 967003:89a416488449
user:      nisimura <nisimura%NetBSD.org@localhost>
date:      Tue Nov 26 08:37:05 2019 +0000

description:
- use mii(4) layer to control KSZ8841 builtin PHY.
- handle PAUSE flow control properly according to ifconfig(8) mediaopt
  selection.
- some style knits; use aprint(9) and modernise callout(9).

diffstat:

 sys/dev/pci/files.pci |    4 +-
 sys/dev/pci/if_kse.c  |  482 ++++++++++++++++++++++++++++++-------------------
 2 files changed, 293 insertions(+), 193 deletions(-)

diffs (truncated from 886 to 300 lines):

diff -r fc100a225af1 -r 89a416488449 sys/dev/pci/files.pci
--- a/sys/dev/pci/files.pci     Tue Nov 26 08:21:03 2019 +0000
+++ b/sys/dev/pci/files.pci     Tue Nov 26 08:37:05 2019 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.pci,v 1.416 2019/11/20 09:37:45 hikaru Exp $
+#      $NetBSD: files.pci,v 1.417 2019/11/26 08:37:05 nisimura Exp $
 #
 # Config file and device description for machine-independent PCI code.
 # Included by ports that need it.  Requires that the SCSI files be
@@ -965,7 +965,7 @@
 file    dev/pci/if_nfe.c                nfe
 
 # MICREL Etherent
-device kse: ether, ifnet, arp
+device kse: ether, ifnet, arp, mii
 attach kse at pci
 file   dev/pci/if_kse.c                kse
 
diff -r fc100a225af1 -r 89a416488449 sys/dev/pci/if_kse.c
--- a/sys/dev/pci/if_kse.c      Tue Nov 26 08:21:03 2019 +0000
+++ b/sys/dev/pci/if_kse.c      Tue Nov 26 08:37:05 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_kse.c,v 1.41 2019/11/07 22:00:37 nisimura Exp $     */
+/*     $NetBSD: if_kse.c,v 1.42 2019/11/26 08:37:05 nisimura Exp $     */
 
 /*-
  * Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -30,11 +30,11 @@
  */
 
 /*
- * Micrel 8841/8842 10/100 ethernet driver
+ * Micrel 8841/8842 10/100 PCI ethernet driver
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_kse.c,v 1.41 2019/11/07 22:00:37 nisimura Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_kse.c,v 1.42 2019/11/26 08:37:05 nisimura Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -55,6 +55,8 @@
 #include <net/if_media.h>
 #include <net/if_dl.h>
 #include <net/if_ether.h>
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
 #include <net/bpf.h>
 
 #include <dev/pci/pcivar.h>
@@ -68,9 +70,9 @@
 #define CSR_WRITE_4(sc, off, val) \
            bus_space_write_4(sc->sc_st, sc->sc_sh, off, val)
 #define CSR_READ_2(sc, off) \
-           bus_space_read_2(sc->sc_st, sc->sc_sh, off)
+           bus_space_read_2((sc)->sc_st, (sc)->sc_sh, (off))
 #define CSR_WRITE_2(sc, off, val) \
-           bus_space_write_2(sc->sc_st, sc->sc_sh, off, val)
+           bus_space_write_2((sc)->sc_st, (sc)->sc_sh, (off), (val))
 
 #define MDTXC  0x000   /* DMA transmit control */
 #define MDRXC  0x004   /* DMA receive control */
@@ -86,8 +88,7 @@
 #define MARM   0x202   /* MAC address middle */
 #define MARH   0x204   /* MAC address high */
 #define GRR    0x216   /* global reset */
-#define CIDR   0x400   /* chip ID and enable */
-#define CGCR   0x40a   /* chip global control */
+#define SIDER  0x400   /* switch ID and function enable */
 #define IACR   0x4a0   /* indirect access control */
 #define IADR1  0x4a2   /* indirect access data 66:63 */
 #define IADR2  0x4a4   /* indirect access data 47:32 */
@@ -98,24 +99,27 @@
 #define P1SR   0x514   /* port 1 status */
 #define P2CR4  0x532   /* port 2 control 4 */
 #define P2SR   0x534   /* port 2 status */
-#define PxCR_STARTNEG  (1U << 9)       /* restart auto negotiation */
-#define PxCR_AUTOEN    (1U << 7)       /* auto negotiation enable */
-#define PxCR_SPD100    (1U << 6)       /* force speed 100 */
-#define PxCR_USEFDX    (1U << 5)       /* force full duplex */
-#define PxCR_USEFC     (1U << 4)       /* advertise pause flow control */
-#define PxSR_ACOMP     (1U << 6)       /* auto negotiation completed */
-#define PxSR_SPD100    (1U << 10)      /* speed is 100Mbps */
-#define PxSR_FDX       (1U << 9)       /* full duplex */
-#define PxSR_LINKUP    (1U << 5)       /* link is good */
-#define PxSR_RXFLOW    (1U << 12)      /* receive flow control active */
-#define PxSR_TXFLOW    (1U << 11)      /* transmit flow control active */
+#define  PxCR_STARTNEG (1U<<9)         /* restart auto negotiation */
+#define  PxCR_AUTOEN   (1U<<7)         /* auto negotiation enable */
+#define  PxCR_SPD100   (1U<<6)         /* force speed 100 */
+#define  PxCR_USEFDX   (1U<<5)         /* force full duplex */
+#define  PxCR_USEFC    (1U<<4)         /* advertise pause flow control */
+#define  PxSR_ACOMP    (1U<<6)         /* auto negotiation completed */
+#define  PxSR_SPD100   (1U<<10)        /* speed is 100Mbps */
+#define  PxSR_FDX      (1U<<9)         /* full duplex */
+#define  PxSR_LINKUP   (1U<<5)         /* link is good */
+#define  PxSR_RXFLOW   (1U<<12)        /* receive flow control active */
+#define  PxSR_TXFLOW   (1U<<11)        /* transmit flow control active */
+#define P1VIDCR        0x504   /* port 1 vtag */
+#define P2VIDCR        0x524   /* port 2 vtag */
+#define P3VIDCR        0x544   /* 8842 host vtag */
 
 #define TXC_BS_MSK     0x3f000000      /* burst size */
 #define TXC_BS_SFT     (24)            /* 1,2,4,8,16,32 or 0 for unlimited */
 #define TXC_UCG                (1U<<18)        /* generate UDP checksum */
 #define TXC_TCG                (1U<<17)        /* generate TCP checksum */
 #define TXC_ICG                (1U<<16)        /* generate IP checksum */
-#define TXC_FCE                (1U<<9)         /* enable flowcontrol */
+#define TXC_FCE                (1U<<9)         /* generate PAUSE to moderate Rx lvl */
 #define TXC_EP         (1U<<2)         /* enable automatic padding */
 #define TXC_AC         (1U<<1)         /* add CRC to frame */
 #define TXC_TEN                (1)             /* enable DMA to run */
@@ -126,7 +130,7 @@
 #define RXC_UCC                (1U<<18)        /* run UDP checksum */
 #define RXC_TCC                (1U<<17)        /* run TDP checksum */
 #define RXC_ICC                (1U<<16)        /* run IP checksum */
-#define RXC_FCE                (1U<<9)         /* enable flowcontrol */
+#define RXC_FCE                (1U<<9)         /* accept PAUSE to throttle Tx */
 #define RXC_RB         (1U<<6)         /* receive broadcast frame */
 #define RXC_RM         (1U<<5)         /* receive multicast frame */
 #define RXC_RU         (1U<<4)         /* receive unicast frame */
@@ -218,14 +222,17 @@
        device_t sc_dev;                /* generic device information */
        bus_space_tag_t sc_st;          /* bus space tag */
        bus_space_handle_t sc_sh;       /* bus space handle */
+       bus_size_t sc_memsize;          /* csr map size */
        bus_dma_tag_t sc_dmat;          /* bus DMA tag */
+       pci_chipset_tag_t sc_pc;        /* PCI chipset tag */
        struct ethercom sc_ethercom;    /* Ethernet common data */
        void *sc_ih;                    /* interrupt cookie */
 
-       struct ifmedia sc_media;        /* ifmedia information */
-       int sc_linkstatus;              /* last P1SR register value */
+       struct mii_data sc_mii;         /* mii 8841 */
+       struct ifmedia sc_media;        /* ifmedia 8842 */
+       int sc_flowflags;               /* 802.3x PAUSE flow control */
 
-       callout_t  sc_callout;          /* MII tick callout */
+       callout_t  sc_tick_ch;          /* MII tick callout */
        callout_t  sc_stat_ch;          /* statistics counter callout */
 
        bus_dmamap_t sc_cddmamap;       /* control data DMA map */
@@ -329,10 +336,13 @@
 static void rxintr(struct kse_softc *);
 static void txreap(struct kse_softc *);
 static void lnkchg(struct kse_softc *);
-static int ksephy_change(struct ifnet *);
-static void ksephy_status(struct ifnet *, struct ifmediareq *);
-static void nopifm_status(struct ifnet *, struct ifmediareq *);
+static int kse_ifmedia_upd(struct ifnet *);
+static void kse_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+static void nopifmedia_sts(struct ifnet *, struct ifmediareq *);
 static void phy_tick(void *);
+int kse_mii_readreg(device_t, int, int, uint16_t *);
+int kse_mii_writereg(device_t, int, int, uint16_t);
+void kse_mii_statchg(struct ifnet *);
 #ifdef KSE_EVENT_COUNTERS
 static void stat_tick(void *);
 static void zerostats(struct kse_softc *);
@@ -360,90 +370,77 @@
        pci_chipset_tag_t pc = pa->pa_pc;
        pci_intr_handle_t ih;
        const char *intrstr;
-       struct ifnet *ifp;
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       struct mii_data * const mii = &sc->sc_mii;
        struct ifmedia *ifm;
        uint8_t enaddr[ETHER_ADDR_LEN];
        bus_dma_segment_t seg;
        int i, error, nseg;
-       pcireg_t pmode;
-       int pmreg;
        char intrbuf[PCI_INTRSTR_LEN];
 
+       aprint_normal(": Micrel KSZ%04x Ethernet (rev. 0x%02x)\n",
+           PCI_PRODUCT(pa->pa_id), PCI_REVISION(pa->pa_class));
+
        if (pci_mapreg_map(pa, 0x10,
            PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT,
-           0, &sc->sc_st, &sc->sc_sh, NULL, NULL) != 0) {
-               printf(": unable to map device registers\n");
+           0, &sc->sc_st, &sc->sc_sh, NULL, &sc->sc_memsize) != 0) {
+               aprint_error_dev(self, "unable to map device registers\n");
                return;
        }
 
-       sc->sc_dev = self;
-       sc->sc_dmat = pa->pa_dmat;
-
        /* Make sure bus mastering is enabled. */
        pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
            pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) |
            PCI_COMMAND_MASTER_ENABLE);
 
-       /* Get it out of power save mode, if needed. */
-       if (pci_get_capability(pc, pa->pa_tag, PCI_CAP_PWRMGMT, &pmreg, 0)) {
-               pmode = pci_conf_read(pc, pa->pa_tag, pmreg + PCI_PMCSR) &
-                   PCI_PMCSR_STATE_MASK;
-               if (pmode == PCI_PMCSR_STATE_D3) {
-                       /*
-                        * The card has lost all configuration data in
-                        * this state, so punt.
-                        */
-                       printf("%s: unable to wake from power state D3\n",
-                           device_xname(sc->sc_dev));
-                       return;
-               }
-               if (pmode != PCI_PMCSR_STATE_D0) {
-                       printf("%s: waking up from power date D%d\n",
-                           device_xname(sc->sc_dev), pmode);
-                       pci_conf_write(pc, pa->pa_tag, pmreg + PCI_PMCSR,
-                           PCI_PMCSR_STATE_D0);
-               }
+       /* Power up chip if necessary. */
+       if ((error = pci_activate(pc, pa->pa_tag, self, NULL))
+           && error != EOPNOTSUPP) {
+               aprint_error_dev(self, "cannot activate %d\n", error);
+               return;
        }
 
-       sc->sc_chip = PCI_PRODUCT(pa->pa_id);
-       printf(": Micrel KSZ%04x Ethernet (rev. 0x%02x)\n",
-           sc->sc_chip, PCI_REVISION(pa->pa_class));
-
-       /*
-        * Read the Ethernet address from the EEPROM.
-        */
-       i = CSR_READ_2(sc, MARL);
-       enaddr[5] = i; enaddr[4] = i >> 8;
-       i = CSR_READ_2(sc, MARM);
-       enaddr[3] = i; enaddr[2] = i >> 8;
-       i = CSR_READ_2(sc, MARH);
-       enaddr[1] = i; enaddr[0] = i >> 8;
-       printf("%s: Ethernet address %s\n",
-               device_xname(sc->sc_dev), ether_sprintf(enaddr));
-
-       /*
-        * Enable chip function.
-        */
-       CSR_WRITE_2(sc, CIDR, 1);
-
-       /*
-        * Map and establish our interrupt.
-        */
+       /* Map and establish our interrupt. */
        if (pci_intr_map(pa, &ih)) {
-               aprint_error_dev(sc->sc_dev, "unable to map interrupt\n");
+               aprint_error_dev(self, "unable to map interrupt\n");
                return;
        }
        intrstr = pci_intr_string(pc, ih, intrbuf, sizeof(intrbuf));
        sc->sc_ih = pci_intr_establish_xname(pc, ih, IPL_NET, kse_intr, sc,
            device_xname(self));
        if (sc->sc_ih == NULL) {
-               aprint_error_dev(sc->sc_dev, "unable to establish interrupt");
+               aprint_error_dev(self, "unable to establish interrupt");
                if (intrstr != NULL)
                        aprint_error(" at %s", intrstr);
                aprint_error("\n");
                return;
        }
-       aprint_normal_dev(sc->sc_dev, "interrupting at %s\n", intrstr);
+       aprint_normal_dev(self, "interrupting at %s\n", intrstr);
+
+       sc->sc_dev = self;
+       sc->sc_dmat = pa->pa_dmat;
+       sc->sc_pc = pa->pa_pc;
+       sc->sc_chip = PCI_PRODUCT(pa->pa_id);
+
+       /*
+        * Read the Ethernet address from the EEPROM.
+        */
+       i = CSR_READ_2(sc, MARL);
+       enaddr[5] = i;
+       enaddr[4] = i >> 8;
+       i = CSR_READ_2(sc, MARM);
+       enaddr[3] = i;
+       enaddr[2] = i >> 8;
+       i = CSR_READ_2(sc, MARH);
+       enaddr[1] = i;
+       enaddr[0] = i >> 8;
+       aprint_normal_dev(self,
+           "Ethernet address %s\n", ether_sprintf(enaddr));
+
+       /*
+        * Enable chip function.
+        */
+       CSR_WRITE_2(sc, SIDER, 1);
 
        /*
         * Allocate the control data structures, and create and load the
@@ -452,7 +449,7 @@
        error = bus_dmamem_alloc(sc->sc_dmat,
            sizeof(struct kse_control_data), PAGE_SIZE, 0, &seg, 1, &nseg, 0);
        if (error != 0) {
-               aprint_error_dev(sc->sc_dev,
+               aprint_error_dev(self,
                    "unable to allocate control data, error = %d\n", error);
                goto fail_0;
        }



Home | Main Index | Thread Index | Old Index