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